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