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