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