FreeBSD/Linux Kernel Cross Reference
sys/netiso/tp_iso.c
1 /* $NetBSD: tp_iso.c,v 1.19 2005/02/26 22:39:49 perry 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.19 2005/02/26 22:39:49 perry 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(void *v, u_short *lenp, caddr_t data_out, int which)
121 {
122 struct isopcb *isop = v;
123 struct sockaddr_iso *addr = 0;
124
125 switch (which) {
126 case TP_LOCAL:
127 addr = isop->isop_laddr;
128 break;
129
130 case TP_FOREIGN:
131 addr = isop->isop_faddr;
132 }
133 if (addr)
134 bcopy(TSEL(addr), data_out, (*lenp = addr->siso_tlen));
135 }
136
137 /*
138 * CALLED FROM: tp_newsocket(); i.e., when a connection is being established
139 * by an incoming CR_TPDU.
140 *
141 * FUNCTION, ARGUMENTS: Put a transport suffix (found in name) into an isopcb
142 * structure (isop). The argument (which) takes the value TP_LOCAL or
143 * TP_FOREIGN.
144 */
145 void
146 iso_putsufx(void *v, caddr_t sufxloc, int sufxlen, int which)
147 {
148 struct isopcb *isop = v;
149 struct sockaddr_iso **dst, *backup;
150 struct sockaddr_iso *addr;
151 struct mbuf *m;
152 int len;
153
154 switch (which) {
155 default:
156 return;
157
158 case TP_LOCAL:
159 dst = &isop->isop_laddr;
160 backup = &isop->isop_sladdr;
161 break;
162
163 case TP_FOREIGN:
164 dst = &isop->isop_faddr;
165 backup = &isop->isop_sfaddr;
166 }
167 if ((addr = *dst) == 0) {
168 addr = *dst = backup;
169 addr->siso_nlen = 0;
170 addr->siso_slen = 0;
171 addr->siso_plen = 0;
172 printf("iso_putsufx on un-initialized isopcb\n");
173 }
174 len = sufxlen + addr->siso_nlen +
175 (sizeof(*addr) - sizeof(addr->siso_data));
176 if (addr == backup) {
177 if (len > sizeof(*addr)) {
178 m = m_getclr(M_DONTWAIT, MT_SONAME);
179 if (m == 0)
180 return;
181 addr = *dst = mtod(m, struct sockaddr_iso *);
182 *addr = *backup;
183 m->m_len = len;
184 }
185 }
186 bcopy(sufxloc, TSEL(addr), sufxlen);
187 addr->siso_tlen = sufxlen;
188 addr->siso_len = len;
189 }
190
191 /*
192 * CALLED FROM:
193 * tp.trans whenever we go into REFWAIT state.
194 * FUNCTION and ARGUMENT:
195 * Called when a ref is frozen, to allow the suffix to be reused.
196 * (isop) is the net level pcb. This really shouldn't have to be
197 * done in a NET level pcb but... for the internet world that just
198 * the way it is done in BSD...
199 * The alternative is to have the port unusable until the reference
200 * timer goes off.
201 */
202 void
203 iso_recycle_tsuffix(void *v)
204 {
205 struct isopcb *isop = v;
206 isop->isop_laddr->siso_tlen = isop->isop_faddr->siso_tlen = 0;
207 }
208
209 /*
210 * CALLED FROM:
211 * tp_newsocket(); i.e., when a connection is being established by an
212 * incoming CR_TPDU.
213 *
214 * FUNCTION and ARGUMENTS:
215 * Copy a whole net addr from a struct sockaddr (name).
216 * into an isopcb (isop).
217 * The argument (which) takes values TP_LOCAL or TP_FOREIGN
218 */
219 void
220 iso_putnetaddr(void *v, struct sockaddr *nm, int which)
221 {
222 struct isopcb *isop = v;
223 struct sockaddr_iso *name = (struct sockaddr_iso *) nm;
224 struct sockaddr_iso **sisop, *backup;
225 struct sockaddr_iso *siso;
226
227 switch (which) {
228 default:
229 printf("iso_putnetaddr: should panic\n");
230 return;
231 case TP_LOCAL:
232 sisop = &isop->isop_laddr;
233 backup = &isop->isop_sladdr;
234 break;
235 case TP_FOREIGN:
236 sisop = &isop->isop_faddr;
237 backup = &isop->isop_sfaddr;
238 }
239 siso = ((*sisop == 0) ? (*sisop = backup) : *sisop);
240 #ifdef ARGO_DEBUG
241 if (argo_debug[D_TPISO]) {
242 printf("ISO_PUTNETADDR\n");
243 dump_isoaddr(isop->isop_faddr);
244 }
245 #endif
246 siso->siso_addr = name->siso_addr;
247 }
248
249 /*
250 * CALLED FROM:
251 * tp_input() when a connection is being established by an
252 * incoming CR_TPDU, and considered for interception.
253 *
254 * FUNCTION and ARGUMENTS:
255 * compare a whole net addr from a struct sockaddr (name),
256 * with that implicitly stored in an isopcb (isop).
257 * The argument (which) takes values TP_LOCAL or TP_FOREIGN.
258 */
259 int
260 iso_cmpnetaddr(void *v, struct sockaddr *nm, int which)
261 {
262 struct isopcb *isop = v;
263 struct sockaddr_iso *name = (struct sockaddr_iso *) nm;
264 struct sockaddr_iso **sisop, *backup;
265 struct sockaddr_iso *siso;
266
267 switch (which) {
268 default:
269 printf("iso_cmpnetaddr: should panic\n");
270 return 0;
271 case TP_LOCAL:
272 sisop = &isop->isop_laddr;
273 backup = &isop->isop_sladdr;
274 break;
275 case TP_FOREIGN:
276 sisop = &isop->isop_faddr;
277 backup = &isop->isop_sfaddr;
278 }
279 siso = ((*sisop == 0) ? (*sisop = backup) : *sisop);
280 #ifdef ARGO_DEBUG
281 if (argo_debug[D_TPISO]) {
282 printf("ISO_CMPNETADDR\n");
283 dump_isoaddr(siso);
284 }
285 #endif
286 if (name->siso_tlen && bcmp(TSEL(name), TSEL(siso), name->siso_tlen))
287 return (0);
288 return (bcmp((caddr_t) name->siso_data,
289 (caddr_t) siso->siso_data, name->siso_nlen) == 0);
290 }
291
292 /*
293 * CALLED FROM:
294 * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR
295 * FUNCTION and ARGUMENTS:
296 * Copy a whole net addr from an isopcb (isop) into
297 * a struct sockaddr (name).
298 * The argument (which) takes values TP_LOCAL or TP_FOREIGN.
299 */
300
301 void
302 iso_getnetaddr(void *v, struct mbuf *name, int which)
303 {
304 struct inpcb *inp = v;
305 struct isopcb *isop = (struct isopcb *) inp;
306 struct sockaddr_iso *siso =
307 (which == TP_LOCAL ? isop->isop_laddr : isop->isop_faddr);
308 if (siso)
309 bcopy((caddr_t) siso, mtod(name, caddr_t),
310 (unsigned) (name->m_len = siso->siso_len));
311 else
312 name->m_len = 0;
313 }
314 /*
315 * NAME: tpclnp_mtu()
316 *
317 * CALLED FROM:
318 * tp_route_to() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
319 *
320 * FUNCTION, ARGUMENTS, and RETURN VALUE:
321 *
322 * Perform subnetwork dependent part of determining MTU information.
323 * It appears that setting a double pointer to the rtentry associated with
324 * the destination, and returning the header size for the network protocol
325 * suffices.
326 *
327 * SIDE EFFECTS:
328 * Sets tp_routep pointer in pcb.
329 *
330 * NOTES:
331 */
332 int
333 tpclnp_mtu(void *v)
334 {
335 struct tp_pcb *tpcb = v;
336 struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
337
338 #ifdef ARGO_DEBUG
339 if (argo_debug[D_CONN]) {
340 printf("tpclnp_mtu(tpcb %p)\n", tpcb);
341 }
342 #endif
343 tpcb->tp_routep = &(isop->isop_route.ro_rt);
344 if (tpcb->tp_netservice == ISO_CONS)
345 return 0;
346 else
347 return (sizeof(struct clnp_fixed) + sizeof(struct clnp_segment) +
348 2 * sizeof(struct iso_addr));
349
350 }
351
352 /*
353 * CALLED FROM:
354 * tp_emit()
355 * FUNCTION and ARGUMENTS:
356 * Take a packet(m0) from tp and package it so that clnp will accept it.
357 * This means prepending space for the clnp header and filling in a few
358 * of the fields.
359 * isop is the isopcb structure; datalen is the length of the data in the
360 * mbuf string m0.
361 * RETURN VALUE:
362 * whatever (E*) is returned form the net layer output routine.
363 */
364
365 int
366 tpclnp_output(struct mbuf *m0, ...)
367 {
368 int datalen;
369 struct isopcb *isop;
370 int nochksum;
371 va_list ap;
372
373 va_start(ap, m0);
374 datalen = va_arg(ap, int);
375 isop = va_arg(ap, struct isopcb *);
376 nochksum = va_arg(ap, int);
377 va_end(ap);
378
379 IncStat(ts_tpdu_sent);
380
381 #ifdef ARGO_DEBUG
382 if (argo_debug[D_TPISO]) {
383 struct tpdu *hdr = mtod(m0, struct tpdu *);
384
385 printf(
386 "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n",
387 datalen,
388 (int) hdr->tpdu_li, (int) hdr->tpdu_type, nochksum);
389 dump_isoaddr(isop->isop_faddr);
390 printf("\nsrc addr:\n");
391 dump_isoaddr(isop->isop_laddr);
392 dump_mbuf(m0, "at tpclnp_output");
393 }
394 #endif
395
396 return
397 clnp_output(m0, isop, datalen, /* flags */ nochksum ? CLNP_NO_CKSUM : 0);
398 }
399
400 /*
401 * CALLED FROM:
402 * tp_error_emit()
403 * FUNCTION and ARGUMENTS:
404 * This is a copy of tpclnp_output that takes the addresses
405 * instead of a pcb. It's used by the tp_error_emit, when we
406 * don't have an iso_pcb with which to call the normal output rtn.
407 * RETURN VALUE:
408 * ENOBUFS or
409 * whatever (E*) is returned form the net layer output routine.
410 */
411
412 int
413 tpclnp_output_dg(struct mbuf *m0, ...)
414 {
415 struct isopcb tmppcb;
416 int err;
417 int flags;
418 int datalen;
419 struct iso_addr *laddr, *faddr;
420 struct route *ro;
421 int nochksum;
422 va_list ap;
423
424 va_start(ap, m0);
425 datalen = va_arg(ap, int);
426 laddr = va_arg(ap, struct iso_addr *);
427 faddr = va_arg(ap, struct iso_addr *);
428 ro = va_arg(ap, struct route *);
429 nochksum = va_arg(ap, int);
430 va_end(ap);
431
432 #ifdef ARGO_DEBUG
433 if (argo_debug[D_TPISO]) {
434 printf("tpclnp_output_dg datalen 0x%x m0 %p\n", datalen, m0);
435 }
436 #endif
437
438 /*
439 * Fill in minimal portion of isopcb so that clnp can send the
440 * packet.
441 */
442 bzero((caddr_t) & tmppcb, sizeof(tmppcb));
443 tmppcb.isop_laddr = &tmppcb.isop_sladdr;
444 tmppcb.isop_laddr->siso_addr = *laddr;
445 tmppcb.isop_faddr = &tmppcb.isop_sfaddr;
446 tmppcb.isop_faddr->siso_addr = *faddr;
447
448 #ifdef ARGO_DEBUG
449 if (argo_debug[D_TPISO]) {
450 printf("tpclnp_output_dg faddr: \n");
451 dump_isoaddr(&tmppcb.isop_sfaddr);
452 printf("\ntpclnp_output_dg laddr: \n");
453 dump_isoaddr(&tmppcb.isop_sladdr);
454 printf("\n");
455 }
456 #endif
457
458 /*
459 * Do not use packet cache since this is a one shot error packet
460 */
461 flags = (CLNP_NOCACHE | (nochksum ? CLNP_NO_CKSUM : 0));
462
463 IncStat(ts_tpdu_sent);
464
465 err = clnp_output(m0, &tmppcb, datalen, flags);
466
467 /*
468 * Free route allocated by clnp (if the route was indeed allocated)
469 */
470 if (tmppcb.isop_route.ro_rt)
471 RTFREE(tmppcb.isop_route.ro_rt);
472
473 return (err);
474 }
475 /*
476 * CALLED FROM:
477 * clnp's input routine, indirectly through the protosw.
478 * FUNCTION and ARGUMENTS:
479 * Take a packet (m) from clnp, strip off the clnp header and give it to tp
480 * No return value.
481 */
482 void
483 tpclnp_input(struct mbuf *m, ...)
484 {
485 struct sockaddr_iso *src, *dst;
486 int clnp_len, ce_bit;
487 void (*input) (struct mbuf *, ...) = tp_input;
488 va_list ap;
489
490 va_start(ap, m);
491 src = va_arg(ap, struct sockaddr_iso *);
492 dst = va_arg(ap, struct sockaddr_iso *);
493 clnp_len = va_arg(ap, int);
494 ce_bit = va_arg(ap, int);
495 va_end(ap);
496
497 IncStat(ts_pkt_rcvd);
498
499 #ifdef ARGO_DEBUG
500 if (argo_debug[D_TPINPUT]) {
501 printf("tpclnp_input: m %p clnp_len 0x%x\n", m, clnp_len);
502 dump_mbuf(m, "at tpclnp_input");
503 }
504 #endif
505 /*
506 * CLNP gives us an mbuf chain WITH the clnp header pulled up,
507 * and the length of the clnp header.
508 * First, strip off the Clnp header. leave the mbuf there for the
509 * pullup that follows.
510 */
511 m->m_len -= clnp_len;
512 m->m_data += clnp_len;
513 m->m_pkthdr.len -= clnp_len;
514 /* XXXX: should probably be in clnp_input */
515 switch (dst->siso_data[dst->siso_nlen - 1]) {
516 case 0:
517 if (m->m_len == 0 && (m = m_pullup(m, 1)) == 0)
518 return;
519 if (*(mtod(m, u_char *)) == ISO10747_IDRP) {
520 idrp_input(m, src, dst);
521 return;
522 }
523 }
524 m = tp_inputprep(m);
525 if (m == 0)
526 return;
527 if (mtod(m, u_char *)[1] == UD_TPDU_type)
528 input = cltp_input;
529
530 #ifdef ARGO_DEBUG
531 if (argo_debug[D_TPINPUT]) {
532 dump_mbuf(m, "after tpclnp_input both pullups");
533 }
534 #endif
535
536 #ifdef ARGO_DEBUG
537 if (argo_debug[D_TPISO]) {
538 printf("calling %sinput : src %p, dst %p, src addr:\n",
539 (input == tp_input ? "tp_" : "clts_"), src, dst);
540 dump_isoaddr(src);
541 printf(" dst addr:\n");
542 dump_isoaddr(dst);
543 }
544 #endif
545
546 (*input) (m, (struct sockaddr *) src, (struct sockaddr *) dst, 0,
547 tpclnp_output_dg, ce_bit);
548
549 #ifdef ARGO_DEBUG
550 if (argo_debug[D_QUENCH]) {{
551 if (time.tv_usec & 0x4 && time.tv_usec & 0x40) {
552 printf("tpclnp_input: FAKING %s\n",
553 tp_stat.ts_pkt_rcvd & 0x1 ? "QUENCH" : "QUENCH2");
554 if (tp_stat.ts_pkt_rcvd & 0x1)
555 tpclnp_ctlinput(PRC_QUENCH,
556 (struct sockaddr *)
557 &src, NULL);
558 else
559 tpclnp_ctlinput(PRC_QUENCH2,
560 (struct sockaddr *)
561 &src, NULL);
562 }
563 }
564 }
565 #endif
566 }
567
568 /*ARGSUSED*/
569 void
570 iso_rtchange(struct isopcb *pcb)
571 {
572
573 }
574
575 /*
576 * CALLED FROM:
577 * tpclnp_ctlinput()
578 * FUNCTION and ARGUMENTS:
579 * find the tpcb pointer and pass it to tp_quench
580 */
581 void
582 tpiso_decbit(struct isopcb *isop)
583 {
584 tp_quench((struct inpcb *) isop->isop_socket->so_pcb, PRC_QUENCH2);
585 }
586 /*
587 * CALLED FROM:
588 * tpclnp_ctlinput()
589 * FUNCTION and ARGUMENTS:
590 * find the tpcb pointer and pass it to tp_quench
591 */
592 void
593 tpiso_quench(struct isopcb *isop)
594 {
595 tp_quench((struct inpcb *) isop->isop_socket->so_pcb, PRC_QUENCH);
596 }
597
598 /*
599 * CALLED FROM:
600 * The network layer through the protosw table.
601 * FUNCTION and ARGUMENTS:
602 * When clnp an ICMP-like msg this gets called.
603 * It either returns an error status to the user or
604 * it causes all connections on this address to be aborted
605 * by calling the appropriate xx_notify() routine.
606 * (cmd) is the type of ICMP error.
607 * (siso) is the address of the guy who sent the ER CLNPDU
608 */
609 void *
610 tpclnp_ctlinput(int cmd, struct sockaddr *saddr, void *dummy)
611 {
612 struct sockaddr_iso *siso = (struct sockaddr_iso *) saddr;
613
614 #ifdef ARGO_DEBUG
615 if (argo_debug[D_TPINPUT]) {
616 printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd);
617 dump_isoaddr(siso);
618 }
619 #endif
620
621 if ((unsigned)cmd >= PRC_NCMDS)
622 return NULL;
623 if (siso->siso_family != AF_ISO)
624 return NULL;
625 switch (cmd) {
626
627 case PRC_QUENCH2:
628 iso_pcbnotify(&tp_isopcb, siso, 0, tpiso_decbit);
629 break;
630
631 case PRC_QUENCH:
632 iso_pcbnotify(&tp_isopcb, siso, 0, 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) isoctlerrmap[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) isoctlerrmap[cmd], tpiso_abort);
664 break;
665 }
666 return NULL;
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 void
675 tpclnp_ctlinput1(int cmd, struct iso_addr *isoa)
676 {
677 bzero((caddr_t) & siso.siso_addr, sizeof(siso.siso_addr));
678 bcopy((caddr_t) isoa, (caddr_t) & siso.siso_addr, isoa->isoa_len);
679 tpclnp_ctlinput(cmd, (struct sockaddr *) &siso, NULL);
680 }
681
682 /*
683 * These next 2 routines are
684 * CALLED FROM:
685 * xxx_notify() from tp_ctlinput() when
686 * net level gets some ICMP-equiv. type event.
687 * FUNCTION and ARGUMENTS:
688 * Cause the connection to be aborted with some sort of error
689 * reason indicating that the network layer caused the abort.
690 * Fakes an ER TPDU so we can go through the driver.
691 * abort always aborts the TP connection.
692 * reset may or may not, depending on the TP class that's in use.
693 */
694 void
695 tpiso_abort(struct isopcb *isop)
696 {
697 struct tp_event e;
698
699 #ifdef ARGO_DEBUG
700 if (argo_debug[D_CONN]) {
701 printf("tpiso_abort %p\n", isop);
702 }
703 #endif
704 e.ev_number = ER_TPDU;
705 e.TPDU_ATTR(ER).e_reason = ECONNABORTED;
706 tp_driver((struct tp_pcb *) isop->isop_socket->so_pcb, &e);
707 }
708
709 void
710 tpiso_reset(struct isopcb *isop)
711 {
712 struct tp_event e;
713
714 e.ev_number = T_NETRESET;
715 tp_driver((struct tp_pcb *) isop->isop_socket->so_pcb, &e);
716
717 }
718
719 #endif /* ISO */
Cache object: b9ff7a96614dc5e1c653b6810dba32b4
|