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