xref: /original-bsd/sys/netiso/tp_iso.c (revision b4971bb3)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)tp_iso.c	7.16 (Berkeley) 05/25/93
8  */
9 
10 /***********************************************************
11 		Copyright IBM Corporation 1987
12 
13                       All Rights Reserved
14 
15 Permission to use, copy, modify, and distribute this software and its
16 documentation for any purpose and without fee is hereby granted,
17 provided that the above copyright notice appear in all copies and that
18 both that copyright notice and this permission notice appear in
19 supporting documentation, and that the name of IBM not be
20 used in advertising or publicity pertaining to distribution of the
21 software without specific, written prior permission.
22 
23 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29 SOFTWARE.
30 
31 ******************************************************************/
32 
33 /*
34  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
35  */
36 /*
37  * ARGO TP
38  * $Header: /var/src/sys/netiso/RCS/tp_iso.c,v 5.1 89/02/09 16:20:51 hagens Exp $
39  * $Source: /var/src/sys/netiso/RCS/tp_iso.c,v $
40  *
41  * Here is where you find the iso-dependent code.  We've tried
42  * keep all net-level and (primarily) address-family-dependent stuff
43  * out of the tp source, and everthing here is reached indirectly
44  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
45  * (see tp_pcb.c).
46  * The routines here are:
47  * 		iso_getsufx: gets transport suffix out of an isopcb structure.
48  * 		iso_putsufx: put transport suffix into an isopcb structure.
49  *		iso_putnetaddr: put a whole net addr into an isopcb.
50  *		iso_getnetaddr: get a whole net addr from an isopcb.
51  *		iso_cmpnetaddr: compare a whole net addr from an isopcb.
52  *		iso_recycle_suffix: clear suffix for reuse in isopcb
53  * 		tpclnp_ctlinput: handle ER CNLPdu : icmp-like stuff
54  * 		tpclnp_mtu: figure out what size tpdu to use
55  *		tpclnp_input: take a pkt from clnp, strip off its clnp header,
56  *				give to tp
57  *		tpclnp_output_dg: package a pkt for clnp given 2 addresses & some data
58  *		tpclnp_output: package a pkt for clnp given an isopcb & some data
59  */
60 
61 #ifdef ISO
62 
63 #include <sys/param.h>
64 #include <sys/socket.h>
65 #include <sys/socketvar.h>
66 #include <sys/domain.h>
67 #include <sys/malloc.h>
68 #include <sys/mbuf.h>
69 #include <sys/errno.h>
70 #include <sys/time.h>
71 #include <sys/protosw.h>
72 
73 #include <net/if.h>
74 #include <net/route.h>
75 
76 #include <netiso/argo_debug.h>
77 #include <netiso/tp_param.h>
78 #include <netiso/tp_stat.h>
79 #include <netiso/tp_pcb.h>
80 #include <netiso/tp_trace.h>
81 #include <netiso/tp_stat.h>
82 #include <netiso/tp_tpdu.h>
83 #include <netiso/tp_clnp.h>
84 #include <netiso/cltp_var.h>
85 
86 /*
87  * CALLED FROM:
88  * 	pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR
89  * FUNCTION, ARGUMENTS:
90  * 	The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
91  */
92 
93 iso_getsufx(isop, lenp, data_out, which)
94 	struct isopcb *isop;
95 	u_short *lenp;
96 	caddr_t data_out;
97 	int which;
98 {
99 	register struct sockaddr_iso *addr = 0;
100 
101 	switch (which) {
102 	case TP_LOCAL:
103 		addr = isop->isop_laddr;
104 		break;
105 
106 	case TP_FOREIGN:
107 		addr = isop->isop_faddr;
108 	}
109 	if (addr)
110 		bcopy(TSEL(addr), data_out, (*lenp = addr->siso_tlen));
111 }
112 
113 /* CALLED FROM:
114  * 	tp_newsocket(); i.e., when a connection is being established by an
115  * 	incoming CR_TPDU.
116  *
117  * FUNCTION, ARGUMENTS:
118  * 	Put a transport suffix (found in name) into an isopcb structure (isop).
119  * 	The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
120  */
121 void
122 iso_putsufx(isop, sufxloc, sufxlen, which)
123 	struct isopcb *isop;
124 	caddr_t sufxloc;
125 	int sufxlen, which;
126 {
127 	struct sockaddr_iso **dst, *backup;
128 	register struct sockaddr_iso *addr;
129 	struct mbuf *m;
130 	int len;
131 
132 	switch (which) {
133 	default:
134 		return;
135 
136 	case TP_LOCAL:
137 		dst = &isop->isop_laddr;
138 		backup = &isop->isop_sladdr;
139 		break;
140 
141 	case TP_FOREIGN:
142 		dst = &isop->isop_faddr;
143 		backup = &isop->isop_sfaddr;
144 	}
145 	if ((addr = *dst) == 0) {
146 		addr = *dst = backup;
147 		addr->siso_nlen = 0;
148 		addr->siso_slen = 0;
149 		addr->siso_plen = 0;
150 		printf("iso_putsufx on un-initialized isopcb\n");
151 	}
152 	len = sufxlen + addr->siso_nlen +
153 			(sizeof(*addr) - sizeof(addr->siso_data));
154 	if (addr == backup) {
155 		if (len > sizeof(*addr)) {
156 				m = m_getclr(M_DONTWAIT, MT_SONAME);
157 				if (m == 0)
158 					return;
159 				addr = *dst = mtod(m, struct sockaddr_iso *);
160 				*addr = *backup;
161 				m->m_len = len;
162 		}
163 	}
164 	bcopy(sufxloc, TSEL(addr), sufxlen);
165 	addr->siso_tlen = sufxlen;
166 	addr->siso_len = len;
167 }
168 
169 /*
170  * CALLED FROM:
171  * 	tp.trans whenever we go into REFWAIT state.
172  * FUNCTION and ARGUMENT:
173  *	 Called when a ref is frozen, to allow the suffix to be reused.
174  * 	(isop) is the net level pcb.  This really shouldn't have to be
175  * 	done in a NET level pcb but... for the internet world that just
176  * 	the way it is done in BSD...
177  * 	The alternative is to have the port unusable until the reference
178  * 	timer goes off.
179  */
180 void
181 iso_recycle_tsuffix(isop)
182 	struct isopcb	*isop;
183 {
184 	isop->isop_laddr->siso_tlen = isop->isop_faddr->siso_tlen = 0;
185 }
186 
187 /*
188  * CALLED FROM:
189  * 	tp_newsocket(); i.e., when a connection is being established by an
190  * 	incoming CR_TPDU.
191  *
192  * FUNCTION and ARGUMENTS:
193  * 	Copy a whole net addr from a struct sockaddr (name).
194  * 	into an isopcb (isop).
195  * 	The argument (which) takes values TP_LOCAL or TP_FOREIGN
196  */
197 void
198 iso_putnetaddr(isop, name, which)
199 	register struct isopcb	*isop;
200 	struct sockaddr_iso	*name;
201 	int which;
202 {
203 	struct sockaddr_iso **sisop, *backup;
204 	register struct sockaddr_iso *siso;
205 
206 	switch (which) {
207 	default:
208 		printf("iso_putnetaddr: should panic\n");
209 		return;
210 	case TP_LOCAL:
211 		sisop = &isop->isop_laddr;
212 		backup = &isop->isop_sladdr;
213 		break;
214 	case TP_FOREIGN:
215 		sisop = &isop->isop_faddr;
216 		backup = &isop->isop_sfaddr;
217 	}
218 	siso = ((*sisop == 0) ? (*sisop = backup) : *sisop);
219 	IFDEBUG(D_TPISO)
220 		printf("ISO_PUTNETADDR\n");
221 		dump_isoaddr(isop->isop_faddr);
222 	ENDDEBUG
223 	siso->siso_addr = name->siso_addr;
224 }
225 
226 /*
227  * CALLED FROM:
228  * 	tp_input() when a connection is being established by an
229  * 	incoming CR_TPDU, and considered for interception.
230  *
231  * FUNCTION and ARGUMENTS:
232  * 	compare a whole net addr from a struct sockaddr (name),
233  * 	with that implicitly stored in an isopcb (isop).
234  * 	The argument (which) takes values TP_LOCAL or TP_FOREIGN.
235  */
236 iso_cmpnetaddr(isop, name, which)
237 	register struct isopcb	*isop;
238 	register struct sockaddr_iso	*name;
239 	int which;
240 {
241 	struct sockaddr_iso **sisop, *backup;
242 	register struct sockaddr_iso *siso;
243 
244 	switch (which) {
245 	default:
246 		printf("iso_cmpnetaddr: should panic\n");
247 		return 0;
248 	case TP_LOCAL:
249 		sisop = &isop->isop_laddr;
250 		backup = &isop->isop_sladdr;
251 		break;
252 	case TP_FOREIGN:
253 		sisop = &isop->isop_faddr;
254 		backup = &isop->isop_sfaddr;
255 	}
256 	siso = ((*sisop == 0) ? (*sisop = backup) : *sisop);
257 	IFDEBUG(D_TPISO)
258 		printf("ISO_CMPNETADDR\n");
259 		dump_isoaddr(siso);
260 	ENDDEBUG
261 	if (name->siso_tlen && bcmp(TSEL(name), TSEL(siso), name->siso_tlen))
262 		return (0);
263 	return (bcmp((caddr_t)name->siso_data,
264 			 (caddr_t)siso->siso_data, name->siso_nlen) == 0);
265 }
266 
267 /*
268  * CALLED FROM:
269  *  pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR
270  * FUNCTION and ARGUMENTS:
271  * 	Copy a whole net addr from an isopcb (isop) into
272  * 	a struct sockaddr (name).
273  * 	The argument (which) takes values TP_LOCAL or TP_FOREIGN.
274  */
275 
276 void
277 iso_getnetaddr( isop, name, which)
278 	struct isopcb *isop;
279 	struct mbuf *name;
280 	int which;
281 {
282 	struct sockaddr_iso *siso =
283 		(which == TP_LOCAL ? isop->isop_laddr : isop->isop_faddr);
284 	if (siso)
285 		bcopy((caddr_t)siso, mtod(name, caddr_t),
286 				(unsigned)(name->m_len = siso->siso_len));
287 	else
288 		name->m_len = 0;
289 }
290 /*
291  * NAME: 	tpclnp_mtu()
292  *
293  * CALLED FROM:
294  *  tp_route_to() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
295  *
296  * FUNCTION, ARGUMENTS, and RETURN VALUE:
297  *
298  * Perform subnetwork dependent part of determining MTU information.
299  * It appears that setting a double pointer to the rtentry associated with
300  * the destination, and returning the header size for the network protocol
301  * suffices.
302  *
303  * SIDE EFFECTS:
304  * Sets tp_routep pointer in pcb.
305  *
306  * NOTES:
307  */
308 tpclnp_mtu(tpcb)
309 register struct tp_pcb *tpcb;
310 {
311 	struct isopcb			*isop = (struct isopcb *)tpcb->tp_npcb;
312 
313 	IFDEBUG(D_CONN)
314 		printf("tpclnp_mtu(tpcb)\n", tpcb);
315 	ENDDEBUG
316 	tpcb->tp_routep = &(isop->isop_route.ro_rt);
317 	if (tpcb->tp_netservice == ISO_CONS)
318 		return 0;
319 	else
320 		return (sizeof(struct clnp_fixed) + sizeof(struct clnp_segment) +
321 			2 * sizeof(struct iso_addr));
322 
323 }
324 
325 /*
326  * CALLED FROM:
327  *  tp_emit()
328  * FUNCTION and ARGUMENTS:
329  *  Take a packet(m0) from tp and package it so that clnp will accept it.
330  *  This means prepending space for the clnp header and filling in a few
331  *  of the fields.
332  *  isop is the isopcb structure; datalen is the length of the data in the
333  *  mbuf string m0.
334  * RETURN VALUE:
335  *  whatever (E*) is returned form the net layer output routine.
336  */
337 
338 int
339 tpclnp_output(isop, m0, datalen, nochksum)
340 	struct isopcb		*isop;
341 	struct mbuf 		*m0;
342 	int 				datalen;
343 	int					nochksum;
344 {
345 	register struct mbuf *m = m0;
346 	IncStat(ts_tpdu_sent);
347 
348 	IFDEBUG(D_TPISO)
349 		struct tpdu *hdr = mtod(m0, struct tpdu *);
350 
351 		printf(
352 "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n",
353 			datalen,
354 			(int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum);
355 		dump_isoaddr(isop->isop_faddr);
356 		printf("\nsrc addr:\n");
357 		dump_isoaddr(isop->isop_laddr);
358 		dump_mbuf(m0, "at tpclnp_output");
359 	ENDDEBUG
360 
361 	return
362 		clnp_output(m0, isop, datalen,  /* flags */nochksum ? CLNP_NO_CKSUM : 0);
363 }
364 
365 /*
366  * CALLED FROM:
367  *  tp_error_emit()
368  * FUNCTION and ARGUMENTS:
369  *  This is a copy of tpclnp_output that takes the addresses
370  *  instead of a pcb.  It's used by the tp_error_emit, when we
371  *  don't have an iso_pcb with which to call the normal output rtn.
372  * RETURN VALUE:
373  *  ENOBUFS or
374  *  whatever (E*) is returned form the net layer output routine.
375  */
376 
377 int
378 tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
379 	struct iso_addr		*laddr, *faddr;
380 	struct mbuf 		*m0;
381 	int 				datalen;
382 	struct route 		*ro;
383 	int					nochksum;
384 {
385 	struct isopcb		tmppcb;
386 	int					err;
387 	int					flags;
388 	register struct mbuf *m = m0;
389 
390 	IFDEBUG(D_TPISO)
391 		printf("tpclnp_output_dg  datalen 0x%x m0 0x%x\n", datalen, m0);
392 	ENDDEBUG
393 
394 	/*
395 	 *	Fill in minimal portion of isopcb so that clnp can send the
396 	 *	packet.
397 	 */
398 	bzero((caddr_t)&tmppcb, sizeof(tmppcb));
399 	tmppcb.isop_laddr = &tmppcb.isop_sladdr;
400 	tmppcb.isop_laddr->siso_addr = *laddr;
401 	tmppcb.isop_faddr = &tmppcb.isop_sfaddr;
402 	tmppcb.isop_faddr->siso_addr = *faddr;
403 
404 	IFDEBUG(D_TPISO)
405 		printf("tpclnp_output_dg  faddr: \n");
406 		dump_isoaddr(&tmppcb.isop_sfaddr);
407 		printf("\ntpclnp_output_dg  laddr: \n");
408 		dump_isoaddr(&tmppcb.isop_sladdr);
409 		printf("\n");
410 	ENDDEBUG
411 
412 	/*
413 	 *	Do not use packet cache since this is a one shot error packet
414 	 */
415 	flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0));
416 
417 	IncStat(ts_tpdu_sent);
418 
419 	err = clnp_output(m0, &tmppcb, datalen,  flags);
420 
421 	/*
422 	 *	Free route allocated by clnp (if the route was indeed allocated)
423 	 */
424 	if (tmppcb.isop_route.ro_rt)
425 		RTFREE(tmppcb.isop_route.ro_rt);
426 
427 	return(err);
428 }
429 /*
430  * CALLED FROM:
431  * 	clnp's input routine, indirectly through the protosw.
432  * FUNCTION and ARGUMENTS:
433  * Take a packet (m) from clnp, strip off the clnp header and give it to tp
434  * No return value.
435  */
436 ProtoHook
437 tpclnp_input(m, src, dst, clnp_len, ce_bit)
438 	register struct mbuf *m;
439 	struct sockaddr_iso *src, *dst;
440 	int clnp_len, ce_bit;
441 {
442 	struct mbuf *tp_inputprep();
443 	int tp_input(), cltp_input(), (*input)() = tp_input;
444 
445 	IncStat(ts_pkt_rcvd);
446 
447 	IFDEBUG(D_TPINPUT)
448 		printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len);
449 		dump_mbuf(m, "at tpclnp_input");
450 	ENDDEBUG
451 	/*
452 	 * CLNP gives us an mbuf chain WITH the clnp header pulled up,
453 	 * and the length of the clnp header.
454 	 * First, strip off the Clnp header. leave the mbuf there for the
455 	 * pullup that follows.
456 	 */
457 	m->m_len -= clnp_len;
458 	m->m_data += clnp_len;
459 	m->m_pkthdr.len -= clnp_len;
460 	/* XXXX: should probably be in clnp_input */
461 	switch (dst->siso_data[dst->siso_nlen - 1]) {
462 #ifdef TUBA
463 	case ISOPROTO_TCP:
464 		return (tuba_tcpinput(m, src, dst));
465 #endif
466 	case 0:
467 		if (m->m_len == 0 && (m = m_pullup(m, 1)) == 0)
468 			return 0;
469 		if (*(mtod(m, u_char *)) == ISO10747_IDRP)
470 			return (idrp_input(m, src, dst));
471 	}
472 	m = tp_inputprep(m);
473 	if (m == 0)
474 		return 0;
475 	if (mtod(m, u_char *)[1] == UD_TPDU_type)
476 		input = cltp_input;
477 
478 	IFDEBUG(D_TPINPUT)
479 		dump_mbuf(m, "after tpclnp_input both pullups");
480 	ENDDEBUG
481 
482 	IFDEBUG(D_TPISO)
483 		printf("calling %sinput : src 0x%x, dst 0x%x, src addr:\n",
484 			(input == tp_input ? "tp_" : "clts_"), src, dst);
485 		dump_isoaddr(src);
486 		printf(" dst addr:\n");
487 		dump_isoaddr(dst);
488 	ENDDEBUG
489 
490 	(void) (*input)(m, (struct sockaddr *)src, (struct sockaddr *)dst,
491 				0, tpclnp_output_dg, ce_bit);
492 
493 	IFDEBUG(D_QUENCH)
494 		{
495 			if(time.tv_usec & 0x4 && time.tv_usec & 0x40) {
496 				printf("tpclnp_input: FAKING %s\n",
497 					tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2");
498 				if(tp_stat.ts_pkt_rcvd & 0x1) {
499 					tpclnp_ctlinput(PRC_QUENCH, &src);
500 				} else {
501 					tpclnp_ctlinput(PRC_QUENCH2, &src);
502 				}
503 			}
504 		}
505 	ENDDEBUG
506 
507 	return 0;
508 }
509 
510 ProtoHook
511 iso_rtchange()
512 {
513 	return 0;
514 }
515 
516 /*
517  * CALLED FROM:
518  *  tpclnp_ctlinput()
519  * FUNCTION and ARGUMENTS:
520  *  find the tpcb pointer and pass it to tp_quench
521  */
522 void
523 tpiso_decbit(isop)
524 	struct isopcb *isop;
525 {
526 	tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH2);
527 }
528 /*
529  * CALLED FROM:
530  *  tpclnp_ctlinput()
531  * FUNCTION and ARGUMENTS:
532  *  find the tpcb pointer and pass it to tp_quench
533  */
534 void
535 tpiso_quench(isop)
536 	struct isopcb *isop;
537 {
538 	tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH);
539 }
540 
541 /*
542  * CALLED FROM:
543  *  The network layer through the protosw table.
544  * FUNCTION and ARGUMENTS:
545  *	When clnp an ICMP-like msg this gets called.
546  *	It either returns an error status to the user or
547  *	it causes all connections on this address to be aborted
548  *	by calling the appropriate xx_notify() routine.
549  *	(cmd) is the type of ICMP error.
550  * 	(siso) is the address of the guy who sent the ER CLNPDU
551  */
552 ProtoHook
553 tpclnp_ctlinput(cmd, siso)
554 	int cmd;
555 	struct sockaddr_iso *siso;
556 {
557 	extern u_char inetctlerrmap[];
558 	extern ProtoHook tpiso_abort();
559 	extern ProtoHook iso_rtchange();
560 	extern ProtoHook tpiso_reset();
561 	void iso_pcbnotify();
562 
563 	IFDEBUG(D_TPINPUT)
564 		printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd);
565 		dump_isoaddr(siso);
566 	ENDDEBUG
567 
568 	if (cmd < 0 || cmd > PRC_NCMDS)
569 		return 0;
570 	if (siso->siso_family != AF_ISO)
571 		return 0;
572 	switch (cmd) {
573 
574 		case	PRC_QUENCH2:
575 			iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_decbit);
576 			break;
577 
578 		case	PRC_QUENCH:
579 			iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_quench);
580 			break;
581 
582 		case	PRC_TIMXCEED_REASS:
583 		case	PRC_ROUTEDEAD:
584 			iso_pcbnotify(&tp_isopcb, siso, 0, tpiso_reset);
585 			break;
586 
587 		case	PRC_HOSTUNREACH:
588 		case	PRC_UNREACH_NET:
589 		case	PRC_IFDOWN:
590 		case	PRC_HOSTDEAD:
591 			iso_pcbnotify(&tp_isopcb, siso,
592 					(int)inetctlerrmap[cmd], iso_rtchange);
593 			break;
594 
595 		default:
596 		/*
597 		case	PRC_MSGSIZE:
598 		case	PRC_UNREACH_HOST:
599 		case	PRC_UNREACH_PROTOCOL:
600 		case	PRC_UNREACH_PORT:
601 		case	PRC_UNREACH_NEEDFRAG:
602 		case	PRC_UNREACH_SRCFAIL:
603 		case	PRC_REDIRECT_NET:
604 		case	PRC_REDIRECT_HOST:
605 		case	PRC_REDIRECT_TOSNET:
606 		case	PRC_REDIRECT_TOSHOST:
607 		case	PRC_TIMXCEED_INTRANS:
608 		case	PRC_PARAMPROB:
609 		*/
610 		iso_pcbnotify(&tp_isopcb, siso, (int)inetctlerrmap[cmd], tpiso_abort);
611 		break;
612 	}
613 	return 0;
614 }
615 /*
616  * XXX - Variant which is called by clnp_er.c with an isoaddr rather
617  * than a sockaddr_iso.
618  */
619 
620 static struct sockaddr_iso siso = {sizeof(siso), AF_ISO};
621 tpclnp_ctlinput1(cmd, isoa)
622 	int cmd;
623 	struct iso_addr *isoa;
624 {
625 	bzero((caddr_t)&siso.siso_addr, sizeof(siso.siso_addr));
626 	bcopy((caddr_t)isoa, (caddr_t)&siso.siso_addr, isoa->isoa_len);
627 	tpclnp_ctlinput(cmd, &siso);
628 }
629 
630 /*
631  * These next 2 routines are
632  * CALLED FROM:
633  *	xxx_notify() from tp_ctlinput() when
634  *  net level gets some ICMP-equiv. type event.
635  * FUNCTION and ARGUMENTS:
636  *  Cause the connection to be aborted with some sort of error
637  *  reason indicating that the network layer caused the abort.
638  *  Fakes an ER TPDU so we can go through the driver.
639  *  abort always aborts the TP connection.
640  *  reset may or may not, depending on the TP class that's in use.
641  */
642 ProtoHook
643 tpiso_abort(isop)
644 	struct isopcb *isop;
645 {
646 	struct tp_event e;
647 
648 	IFDEBUG(D_CONN)
649 		printf("tpiso_abort 0x%x\n", isop);
650 	ENDDEBUG
651 	e.ev_number = ER_TPDU;
652 	e.ATTR(ER_TPDU).e_reason = ECONNABORTED;
653 	return  tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e);
654 }
655 
656 ProtoHook
657 tpiso_reset(isop)
658 	struct isopcb *isop;
659 {
660 	struct tp_event e;
661 
662 	e.ev_number = T_NETRESET;
663 	return tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e);
664 
665 }
666 
667 #endif /* ISO */
668