checkpoint for initial shipment to NIST
[unix-history] / usr / src / sys / netiso / tp_iso.c
CommitLineData
238ab140
KS
1/***********************************************************
2 Copyright IBM Corporation 1987
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of IBM not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
21
22******************************************************************/
23
24/*
25 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26 */
27/*
28 * ARGO TP
a50e2bc0
KS
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 $
78def00d 31 * @(#)tp_iso.c 7.4 (Berkeley) %G%
238ab140
KS
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
a50e2bc0 53static char *rcsid = "$Header: /var/src/sys/netiso/RCS/tp_iso.c,v 5.1 89/02/09 16:20:51 hagens Exp $";
238ab140
KS
54#endif lint
55
56#ifdef ISO
57
a50e2bc0
KS
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
238ab140
KS
68#include "../net/if.h"
69#include "../net/route.h"
238ab140 70
a50e2bc0
KS
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"
238ab140
KS
79
80/*
81 * CALLED FROM:
82 * pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR
a50e2bc0 83 * FUNCTION, ARGUMENTS:
238ab140
KS
84 * The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
85 */
86
a50e2bc0 87iso_getsufx(isop, lenp, data_out, which)
238ab140 88 struct isopcb *isop;
a50e2bc0
KS
89 u_short *lenp;
90 caddr_t data_out;
238ab140
KS
91 int which;
92{
a50e2bc0
KS
93 register struct sockaddr_iso *addr = 0;
94
238ab140
KS
95 switch (which) {
96 case TP_LOCAL:
a50e2bc0
KS
97 addr = isop->isop_laddr;
98 break;
238ab140
KS
99
100 case TP_FOREIGN:
a50e2bc0 101 addr = isop->isop_faddr;
238ab140 102 }
a50e2bc0 103 if (addr)
44f52ea5 104 bcopy(TSEL(addr), data_out, (*lenp = addr->siso_tlen));
238ab140
KS
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 */
115void
a50e2bc0 116iso_putsufx(isop, sufxloc, sufxlen, which)
238ab140 117 struct isopcb *isop;
a50e2bc0
KS
118 caddr_t sufxloc;
119 int sufxlen, which;
238ab140 120{
a50e2bc0
KS
121 struct sockaddr_iso **dst, *backup;
122 register struct sockaddr_iso *addr;
123 struct mbuf *m;
124 int len;
125
238ab140 126 switch (which) {
a50e2bc0
KS
127 default:
128 return;
129
238ab140 130 case TP_LOCAL:
a50e2bc0
KS
131 dst = &isop->isop_laddr;
132 backup = &isop->isop_sladdr;
238ab140 133 break;
a50e2bc0 134
238ab140 135 case TP_FOREIGN:
a50e2bc0
KS
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;
44f52ea5
KS
142 addr->siso_slen = 0;
143 addr->siso_plen = 0;
a50e2bc0 144 printf("iso_putsufx on un-initialized isopcb\n");
238ab140 145 }
a50e2bc0 146 len = sufxlen + addr->siso_nlen +
44f52ea5 147 (sizeof(*addr) - sizeof(addr->siso_data));
a50e2bc0 148 if (addr == backup) {
44f52ea5 149 if (len > sizeof(*addr)) {
a50e2bc0
KS
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 }
44f52ea5 157 }
a50e2bc0 158 bcopy(sufxloc, TSEL(addr), sufxlen);
44f52ea5 159 addr->siso_tlen = sufxlen;
a50e2bc0 160 addr->siso_len = len;
238ab140
KS
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 */
174void
175iso_recycle_tsuffix(isop)
176 struct isopcb *isop;
177{
44f52ea5 178 isop->isop_laddr->siso_tlen = isop->isop_faddr->siso_tlen = 0;
238ab140
KS
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 */
191void
192iso_putnetaddr(isop, name, which)
193 register struct isopcb *isop;
194 struct sockaddr_iso *name;
195 int which;
196{
a50e2bc0
KS
197 struct sockaddr_iso **sisop, *backup;
198 register struct sockaddr_iso *siso;
199
238ab140
KS
200 switch (which) {
201 case TP_LOCAL:
a50e2bc0
KS
202 sisop = &isop->isop_laddr;
203 backup = &isop->isop_sladdr;
238ab140
KS
204 break;
205 case TP_FOREIGN:
a50e2bc0
KS
206 sisop = &isop->isop_faddr;
207 backup = &isop->isop_sfaddr;
238ab140 208 }
a50e2bc0
KS
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;
238ab140
KS
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
226void
227iso_getnetaddr( isop, name, which)
228 struct isopcb *isop;
a50e2bc0 229 struct mbuf *name;
238ab140
KS
230 int which;
231{
a50e2bc0
KS
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;
238ab140
KS
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
263void
264tpclnp_mtu(so, isop, size, negot )
265 struct socket *so;
266 struct isopcb *isop;
267 int *size;
268 u_char *negot;
269{
78def00d
KS
270 struct ifnet *ifp = 0;
271 struct iso_ifaddr *ia = 0;
238ab140
KS
272 register int i;
273 int windowsize = so->so_rcv.sb_hiwat;
274 int clnp_size;
275 int sizeismtu = 0;
78def00d 276 register struct rtentry *rt = isop->isop_route.ro_rt;
238ab140
KS
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
78def00d
KS
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
238ab140 298 return;
78def00d 299 }
238ab140
KS
300
301 /* TODO - make this indirect off the socket structure to the
302 * network layer to get headersize
303 */
a50e2bc0
KS
304 if (isop->isop_laddr)
305 clnp_size = clnp_hdrsize(isop->isop_laddr->siso_addr.isoa_len);
306 else
307 clnp_size = 20;
238ab140
KS
308
309 if(*size > ifp->if_mtu - clnp_size) {
310 *size = ifp->if_mtu - clnp_size;
311 sizeismtu = 1;
312 }
238ab140
KS
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
a50e2bc0
KS
318 IFTRACE(D_CONN)
319 tptrace(TPPTmisc, "GET MTU MID: tpcb size negot i \n",
320 *size, *negot, i, 0);
321 ENDTRACE
322
238ab140
KS
323 /* are we on the same LAN? if so, negotiate one tpdu size larger,
324 * and actually send the real mtu size
325 */
a50e2bc0 326 if (iso_localifa(isop->isop_faddr)) {
238ab140
KS
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
357int
358tpclnp_output(isop, m0, datalen, nochksum)
359 struct isopcb *isop;
360 struct mbuf *m0;
361 int datalen;
362 int nochksum;
363{
a50e2bc0 364 register struct mbuf *m = m0;
238ab140
KS
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);
a50e2bc0 374 dump_isoaddr(isop->isop_faddr);
238ab140 375 printf("\nsrc addr:\n");
a50e2bc0 376 dump_isoaddr(isop->isop_laddr);
238ab140
KS
377 dump_mbuf(m0, "at tpclnp_output");
378 ENDDEBUG
379
380 return
44f52ea5 381 clnp_output(m0, isop, datalen, /* flags */nochksum ? CLNP_NO_CKSUM : 0);
238ab140
KS
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
396int
397tpclnp_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;
238ab140
KS
405 int err;
406 int flags;
a50e2bc0 407 register struct mbuf *m = m0;
238ab140
KS
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));
a50e2bc0
KS
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;
238ab140
KS
422
423 IFDEBUG(D_TPISO)
424 printf("tpclnp_output_dg faddr: \n");
a50e2bc0 425 dump_isoaddr(&tmppcb.isop_sfaddr);
238ab140 426 printf("\ntpclnp_output_dg laddr: \n");
a50e2bc0 427 dump_isoaddr(&tmppcb.isop_sladdr);
238ab140
KS
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
44f52ea5 438 err = clnp_output(m0, &tmppcb, datalen, flags);
238ab140
KS
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}
a50e2bc0 448extern struct sockaddr_iso blank_siso;
238ab140
KS
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 */
456ProtoHook
457tpclnp_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();
a50e2bc0 464 struct mbuf *tp_inputprep();
238ab140
KS
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;
a50e2bc0 480 m->m_data += clnp_len;
238ab140 481
a50e2bc0 482 m = tp_inputprep(m);
238ab140
KS
483
484 IFDEBUG(D_TPINPUT)
485 dump_mbuf(m, "after tpclnp_input both pullups");
486 ENDDEBUG
487
a50e2bc0
KS
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);
238ab140
KS
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
a50e2bc0
KS
500 (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst,
501 0, tpclnp_output_dg);
238ab140
KS
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;
238ab140
KS
519}
520
521ProtoHook
522iso_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 */
533void
534tpiso_decbit(isop)
535 struct isopcb *isop;
536{
a50e2bc0 537 tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH2);
238ab140
KS
538}
539/*
540 * CALLED FROM:
541 * tpclnp_ctlinput()
542 * FUNCTION and ARGUMENTS:
543 * find the tpcb pointer and pass it to tp_quench
544 */
545void
546tpiso_quench(isop)
547 struct isopcb *isop;
548{
a50e2bc0 549 tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH);
238ab140
KS
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 */
563ProtoHook
564tpclnp_ctlinput(cmd, siso)
565 int cmd;
566 struct sockaddr_iso *siso;
a50e2bc0
KS
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 */
574ProtoHook
575tpclnp_ctlinput1(cmd, isoa)
576 int cmd;
577 struct iso_addr *isoa;
238ab140
KS
578{
579 extern u_char inetctlerrmap[];
580 extern ProtoHook tpiso_abort();
581 extern ProtoHook iso_rtchange();
582 extern ProtoHook tpiso_reset();
a50e2bc0 583 void iso_pcbnotify();
238ab140
KS
584
585 IFDEBUG(D_TPINPUT)
a50e2bc0
KS
586 printf("tpclnp_ctlinput1: cmd 0x%x addr: %s\n", cmd,
587 clnp_iso_addrp(isoa));
238ab140
KS
588 ENDDEBUG
589
590 if (cmd < 0 || cmd > PRC_NCMDS)
591 return 0;
592 switch (cmd) {
593
594 case PRC_QUENCH2:
a50e2bc0 595 iso_pcbnotify(&tp_isopcb, isoa, 0, (int (*)())tpiso_decbit);
238ab140
KS
596 break;
597
598 case PRC_QUENCH:
a50e2bc0 599 iso_pcbnotify(&tp_isopcb, isoa, 0, (int (*)())tpiso_quench);
238ab140
KS
600 break;
601
602 case PRC_TIMXCEED_REASS:
603 case PRC_ROUTEDEAD:
a50e2bc0 604 iso_pcbnotify(&tp_isopcb, isoa, 0, tpiso_reset);
238ab140
KS
605 break;
606
607 case PRC_HOSTUNREACH:
608 case PRC_UNREACH_NET:
609 case PRC_IFDOWN:
610 case PRC_HOSTDEAD:
a50e2bc0 611 iso_pcbnotify(&tp_isopcb, isoa,
238ab140
KS
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 */
a50e2bc0 630 iso_pcbnotify(&tp_isopcb, isoa, (int)inetctlerrmap[cmd], tpiso_abort);
238ab140
KS
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 */
648ProtoHook
649tpiso_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
662ProtoHook
663tpiso_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