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