xref: /csrg-svn/sys/netiso/tp_iso.c (revision 39230)
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.4 (Berkeley) 09/26/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 = 0;
271 	struct iso_ifaddr *ia = 0;
272 	register int i;
273 	int windowsize = so->so_rcv.sb_hiwat;
274 	int clnp_size;
275 	int sizeismtu = 0;
276 	register struct rtentry *rt = isop->isop_route.ro_rt;
277 
278 	IFDEBUG(D_CONN)
279 		printf("tpclnp_mtu(0x%x,0x%x,0x%x,0x%x)\n", so, isop, size, negot);
280 	ENDDEBUG
281 	IFTRACE(D_CONN)
282 		tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0);
283 	ENDTRACE
284 
285 	*size = 1 << *negot;
286 
287 	if( *size > windowsize ) {
288 		*size = windowsize;
289 	}
290 
291 	if (rt == 0 || (rt->rt_flags & RTF_UP == 0) ||
292 		(ia = (struct iso_ifaddr *)rt->rt_ifa) == 0 ||
293 	    (ifp = ia->ia_ifp) == 0) {
294 		IFDEBUG(D_CONN)
295 			printf("tpclnp_mtu routing abort rt=0x%x ia=0x%x ifp=0x%x\n",
296 					rt, ia, ifp)
297 		ENDDEBUG
298 		return;
299 	}
300 
301 	/* TODO - make this indirect off the socket structure to the
302 	 * network layer to get headersize
303 	 */
304 	if (isop->isop_laddr)
305 		clnp_size = clnp_hdrsize(isop->isop_laddr->siso_addr.isoa_len);
306 	else
307 		clnp_size = 20;
308 
309 	if(*size > ifp->if_mtu - clnp_size) {
310 		*size = ifp->if_mtu - clnp_size;
311 		sizeismtu = 1;
312 	}
313 	/* have to transform size to the log2 of size */
314 	for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i) <= *size)) ; i++)
315 		;
316 	i--;
317 
318 	IFTRACE(D_CONN)
319 		tptrace(TPPTmisc, "GET MTU MID: tpcb size negot i \n",
320 		*size, *negot, i, 0);
321 	ENDTRACE
322 
323 	/* are we on the same LAN? if so, negotiate one tpdu size larger,
324 	 * and actually send the real mtu size
325 	 */
326 	if (iso_localifa(isop->isop_faddr)) {
327 		i++;
328 	} else {
329 		*size = 1<<i;
330 	}
331 	*negot = i;
332 
333 	IFDEBUG(D_CONN)
334 		printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
335 		ifp->if_name,	*size, *negot);
336 	ENDDEBUG
337 	IFTRACE(D_CONN)
338 		tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n",
339 		*size, *negot, 0, 0);
340 	ENDTRACE
341 }
342 
343 
344 /*
345  * CALLED FROM:
346  *  tp_emit()
347  * FUNCTION and ARGUMENTS:
348  *  Take a packet(m0) from tp and package it so that clnp will accept it.
349  *  This means prepending space for the clnp header and filling in a few
350  *  of the fields.
351  *  inp is the isopcb structure; datalen is the length of the data in the
352  *  mbuf string m0.
353  * RETURN VALUE:
354  *  whatever (E*) is returned form the net layer output routine.
355  */
356 
357 int
358 tpclnp_output(isop, m0, datalen, nochksum)
359 	struct isopcb		*isop;
360 	struct mbuf 		*m0;
361 	int 				datalen;
362 	int					nochksum;
363 {
364 	register struct mbuf *m = m0;
365 	IncStat(ts_tpdu_sent);
366 
367 	IFDEBUG(D_TPISO)
368 		struct tpdu *hdr = mtod(m0, struct tpdu *);
369 
370 		printf(
371 "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n",
372 			datalen,
373 			(int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum);
374 		dump_isoaddr(isop->isop_faddr);
375 		printf("\nsrc addr:\n");
376 		dump_isoaddr(isop->isop_laddr);
377 		dump_mbuf(m0, "at tpclnp_output");
378 	ENDDEBUG
379 
380 	return
381 		clnp_output(m0, isop, datalen,  /* flags */nochksum ? CLNP_NO_CKSUM : 0);
382 }
383 
384 /*
385  * CALLED FROM:
386  *  tp_error_emit()
387  * FUNCTION and ARGUMENTS:
388  *  This is a copy of tpclnp_output that takes the addresses
389  *  instead of a pcb.  It's used by the tp_error_emit, when we
390  *  don't have an iso_pcb with which to call the normal output rtn.
391  * RETURN VALUE:
392  *  ENOBUFS or
393  *  whatever (E*) is returned form the net layer output routine.
394  */
395 
396 int
397 tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
398 	struct iso_addr		*laddr, *faddr;
399 	struct mbuf 		*m0;
400 	int 				datalen;
401 	struct route 		*ro;
402 	int					nochksum;
403 {
404 	struct isopcb		tmppcb;
405 	int					err;
406 	int					flags;
407 	register struct mbuf *m = m0;
408 
409 	IFDEBUG(D_TPISO)
410 		printf("tpclnp_output_dg  datalen 0x%x m0 0x%x\n", datalen, m0);
411 	ENDDEBUG
412 
413 	/*
414 	 *	Fill in minimal portion of isopcb so that clnp can send the
415 	 *	packet.
416 	 */
417 	bzero((caddr_t)&tmppcb, sizeof(tmppcb));
418 	tmppcb.isop_laddr = &tmppcb.isop_sladdr;
419 	tmppcb.isop_laddr->siso_addr = *laddr;
420 	tmppcb.isop_faddr = &tmppcb.isop_sfaddr;
421 	tmppcb.isop_faddr->siso_addr = *faddr;
422 
423 	IFDEBUG(D_TPISO)
424 		printf("tpclnp_output_dg  faddr: \n");
425 		dump_isoaddr(&tmppcb.isop_sfaddr);
426 		printf("\ntpclnp_output_dg  laddr: \n");
427 		dump_isoaddr(&tmppcb.isop_sladdr);
428 		printf("\n");
429 	ENDDEBUG
430 
431 	/*
432 	 *	Do not use packet cache since this is a one shot error packet
433 	 */
434 	flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0));
435 
436 	IncStat(ts_tpdu_sent);
437 
438 	err = clnp_output(m0, &tmppcb, datalen,  flags);
439 
440 	/*
441 	 *	Free route allocated by clnp (if the route was indeed allocated)
442 	 */
443 	if (tmppcb.isop_route.ro_rt)
444 		RTFREE(tmppcb.isop_route.ro_rt);
445 
446 	return(err);
447 }
448 extern struct sockaddr_iso blank_siso;
449 /*
450  * CALLED FROM:
451  * 	clnp's input routine, indirectly through the protosw.
452  * FUNCTION and ARGUMENTS:
453  * Take a packet (m) from clnp, strip off the clnp header and give it to tp
454  * No return value.
455  */
456 ProtoHook
457 tpclnp_input(m, faddr, laddr, clnp_len)
458 	struct mbuf *m;
459 	struct iso_addr *faddr, *laddr;
460 	int clnp_len;
461 {
462 	struct sockaddr_iso src, dst;
463 	int s = splnet();
464 	struct mbuf *tp_inputprep();
465 
466 	IncStat(ts_pkt_rcvd);
467 
468 	IFDEBUG(D_TPINPUT)
469 		printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len);
470 		dump_mbuf(m, "at tpclnp_input");
471 	ENDDEBUG
472 	/*
473 	 * CLNP gives us an mbuf chain WITH the clnp header pulled up,
474 	 * and the length of the clnp header.
475 	 * First, strip off the Clnp header. leave the mbuf there for the
476 	 * pullup that follows.
477 	 */
478 
479 	m->m_len -= clnp_len;
480 	m->m_data += clnp_len;
481 
482 	m = tp_inputprep(m);
483 
484 	IFDEBUG(D_TPINPUT)
485 		dump_mbuf(m, "after tpclnp_input both pullups");
486 	ENDDEBUG
487 
488 	src = blank_siso; dst = blank_siso;
489 	bcopy((caddr_t)faddr, (caddr_t)&src.siso_addr, 1 + faddr->isoa_len);
490 	bcopy((caddr_t)laddr, (caddr_t)&dst.siso_addr, 1 + laddr->isoa_len);
491 
492 	IFDEBUG(D_TPISO)
493 		printf("calling tp_input: &src 0x%x  &dst 0x%x, src addr:\n",
494 			&src, &dst);
495 		printf(" dst addr:\n");
496 		dump_isoaddr(&src);
497 		dump_isoaddr(&dst);
498 	ENDDEBUG
499 
500 	(void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst,
501 				0, tpclnp_output_dg);
502 
503 	IFDEBUG(D_QUENCH)
504 		{
505 			if(time.tv_usec & 0x4 && time.tv_usec & 0x40) {
506 				printf("tpclnp_input: FAKING %s\n",
507 					tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2");
508 				if(tp_stat.ts_pkt_rcvd & 0x1) {
509 					tpclnp_ctlinput(PRC_QUENCH, &src);
510 				} else {
511 					tpclnp_ctlinput(PRC_QUENCH2, &src);
512 				}
513 			}
514 		}
515 	ENDDEBUG
516 
517 	splx(s);
518 	return 0;
519 }
520 
521 ProtoHook
522 iso_rtchange()
523 {
524 	return 0;
525 }
526 
527 /*
528  * CALLED FROM:
529  *  tpclnp_ctlinput()
530  * FUNCTION and ARGUMENTS:
531  *  find the tpcb pointer and pass it to tp_quench
532  */
533 void
534 tpiso_decbit(isop)
535 	struct isopcb *isop;
536 {
537 	tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH2);
538 }
539 /*
540  * CALLED FROM:
541  *  tpclnp_ctlinput()
542  * FUNCTION and ARGUMENTS:
543  *  find the tpcb pointer and pass it to tp_quench
544  */
545 void
546 tpiso_quench(isop)
547 	struct isopcb *isop;
548 {
549 	tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH);
550 }
551 
552 /*
553  * CALLED FROM:
554  *  The network layer through the protosw table.
555  * FUNCTION and ARGUMENTS:
556  *	When clnp an ICMP-like msg this gets called.
557  *	It either returns an error status to the user or
558  *	it causes all connections on this address to be aborted
559  *	by calling the appropriate xx_notify() routine.
560  *	(cmd) is the type of ICMP error.
561  * 	(siso) is the address of the guy who sent the ER CLNPDU
562  */
563 ProtoHook
564 tpclnp_ctlinput(cmd, siso)
565 	int cmd;
566 	struct sockaddr_iso *siso;
567 {
568 	return tpclnp_ctlinput1(cmd, &siso->siso_addr);
569 }
570 
571 /*
572  *	Entry to ctlinput with argument of an iso_addr rather than a sockaddr
573  */
574 ProtoHook
575 tpclnp_ctlinput1(cmd, isoa)
576 	int cmd;
577 	struct iso_addr	*isoa;
578 {
579 	extern u_char inetctlerrmap[];
580 	extern ProtoHook tpiso_abort();
581 	extern ProtoHook iso_rtchange();
582 	extern ProtoHook tpiso_reset();
583 	void iso_pcbnotify();
584 
585 	IFDEBUG(D_TPINPUT)
586 		printf("tpclnp_ctlinput1: cmd 0x%x addr: %s\n", cmd,
587 			clnp_iso_addrp(isoa));
588 	ENDDEBUG
589 
590 	if (cmd < 0 || cmd > PRC_NCMDS)
591 		return 0;
592 	switch (cmd) {
593 
594 		case	PRC_QUENCH2:
595 			iso_pcbnotify(&tp_isopcb, isoa, 0, (int (*)())tpiso_decbit);
596 			break;
597 
598 		case	PRC_QUENCH:
599 			iso_pcbnotify(&tp_isopcb, isoa, 0, (int (*)())tpiso_quench);
600 			break;
601 
602 		case	PRC_TIMXCEED_REASS:
603 		case	PRC_ROUTEDEAD:
604 			iso_pcbnotify(&tp_isopcb, isoa, 0, tpiso_reset);
605 			break;
606 
607 		case	PRC_HOSTUNREACH:
608 		case	PRC_UNREACH_NET:
609 		case	PRC_IFDOWN:
610 		case	PRC_HOSTDEAD:
611 			iso_pcbnotify(&tp_isopcb, isoa,
612 					(int)inetctlerrmap[cmd], iso_rtchange);
613 			break;
614 
615 		default:
616 		/*
617 		case	PRC_MSGSIZE:
618 		case	PRC_UNREACH_HOST:
619 		case	PRC_UNREACH_PROTOCOL:
620 		case	PRC_UNREACH_PORT:
621 		case	PRC_UNREACH_NEEDFRAG:
622 		case	PRC_UNREACH_SRCFAIL:
623 		case	PRC_REDIRECT_NET:
624 		case	PRC_REDIRECT_HOST:
625 		case	PRC_REDIRECT_TOSNET:
626 		case	PRC_REDIRECT_TOSHOST:
627 		case	PRC_TIMXCEED_INTRANS:
628 		case	PRC_PARAMPROB:
629 		*/
630 		iso_pcbnotify(&tp_isopcb, isoa, (int)inetctlerrmap[cmd], tpiso_abort);
631 		break;
632 	}
633 	return 0;
634 }
635 
636 /*
637  * These next 2 routines are
638  * CALLED FROM:
639  *	xxx_notify() from tp_ctlinput() when
640  *  net level gets some ICMP-equiv. type event.
641  * FUNCTION and ARGUMENTS:
642  *  Cause the connection to be aborted with some sort of error
643  *  reason indicating that the network layer caused the abort.
644  *  Fakes an ER TPDU so we can go through the driver.
645  *  abort always aborts the TP connection.
646  *  reset may or may not, depending on the TP class that's in use.
647  */
648 ProtoHook
649 tpiso_abort(isop)
650 	struct isopcb *isop;
651 {
652 	struct tp_event e;
653 
654 	IFDEBUG(D_CONN)
655 		printf("tpiso_abort 0x%x\n", isop);
656 	ENDDEBUG
657 	e.ev_number = ER_TPDU;
658 	e.ATTR(ER_TPDU).e_reason = ECONNABORTED;
659 	return  tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e);
660 }
661 
662 ProtoHook
663 tpiso_reset(isop)
664 	struct isopcb *isop;
665 {
666 	struct tp_event e;
667 
668 	e.ev_number = T_NETRESET;
669 	return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e);
670 
671 }
672 
673 #endif ISO
674