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