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