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