|
|
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: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $ ! 30: * $Source: /usr/argo/sys/netiso/RCS/tp_inet.c,v $ ! 31: * @(#)tp_inet.c 7.6 (Berkeley) 6/28/90 * ! 32: * ! 33: * Here is where you find the inet-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: * in_getsufx: gets transport suffix out of an inpcb structure. ! 40: * in_putsufx: put transport suffix into an inpcb structure. ! 41: * in_putnetaddr: put a whole net addr into an inpcb. ! 42: * in_getnetaddr: get a whole net addr from an inpcb. ! 43: * in_cmpnetaddr: compare a whole net addr from an isopcb. ! 44: * in_recycle_suffix: clear suffix for reuse in inpcb ! 45: * tpip_mtu: figure out what size tpdu to use ! 46: * tpip_input: take a pkt from ip, strip off its ip header, give to tp ! 47: * tpip_output_dg: package a pkt for ip given 2 addresses & some data ! 48: * tpip_output: package a pkt for ip given an inpcb & some data ! 49: */ ! 50: ! 51: #ifndef lint ! 52: static char *rcsid = "$Header: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $"; ! 53: #endif lint ! 54: ! 55: #ifdef INET ! 56: ! 57: #include "param.h" ! 58: #include "socket.h" ! 59: #include "socketvar.h" ! 60: #include "mbuf.h" ! 61: #include "errno.h" ! 62: #include "time.h" ! 63: #include "../net/if.h" ! 64: #include "tp_param.h" ! 65: #include "argo_debug.h" ! 66: #include "tp_stat.h" ! 67: #include "tp_ip.h" ! 68: #include "tp_pcb.h" ! 69: #include "tp_trace.h" ! 70: #include "tp_stat.h" ! 71: #include "tp_tpdu.h" ! 72: #include "../netinet/in_var.h" ! 73: ! 74: #ifndef ISO ! 75: #include "iso_chksum.c" ! 76: #endif ! 77: ! 78: /* ! 79: * NAME: in_getsufx() ! 80: ! 81: * CALLED FROM: pr_usrreq() on PRU_BIND, ! 82: * PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR ! 83: * ! 84: * FUNCTION, ARGUMENTS, and RETURN VALUE: ! 85: * Get a transport suffix from an inpcb structure (inp). ! 86: * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. ! 87: * ! 88: * RETURNS: internet port / transport suffix ! 89: * (CAST TO AN INT) ! 90: * ! 91: * SIDE EFFECTS: ! 92: * ! 93: * NOTES: ! 94: */ ! 95: in_getsufx(inp, lenp, data_out, which) ! 96: struct inpcb *inp; ! 97: u_short *lenp; ! 98: caddr_t data_out; ! 99: int which; ! 100: { ! 101: *lenp = sizeof(u_short); ! 102: switch (which) { ! 103: case TP_LOCAL: ! 104: *(u_short *)data_out = inp->inp_lport; ! 105: return; ! 106: ! 107: case TP_FOREIGN: ! 108: *(u_short *)data_out = inp->inp_fport; ! 109: } ! 110: ! 111: } ! 112: ! 113: /* ! 114: * NAME: in_putsufx() ! 115: * ! 116: * CALLED FROM: tp_newsocket(); i.e., when a connection ! 117: * is being established by an incoming CR_TPDU. ! 118: * ! 119: * FUNCTION, ARGUMENTS: ! 120: * Put a transport suffix (found in name) into an inpcb structure (inp). ! 121: * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. ! 122: * ! 123: * RETURNS: Nada ! 124: * ! 125: * SIDE EFFECTS: ! 126: * ! 127: * NOTES: ! 128: */ ! 129: /*ARGSUSED*/ ! 130: void ! 131: in_putsufx(inp, sufxloc, sufxlen, which) ! 132: struct inpcb *inp; ! 133: caddr_t sufxloc; ! 134: int which; ! 135: { ! 136: if (which == TP_FOREIGN) { ! 137: bcopy(sufxloc, (caddr_t)&inp->inp_fport, sizeof(inp->inp_fport)); ! 138: } ! 139: } ! 140: ! 141: /* ! 142: * NAME: in_recycle_tsuffix() ! 143: * ! 144: * CALLED FROM: tp.trans whenever we go into REFWAIT state. ! 145: * ! 146: * FUNCTION and ARGUMENT: ! 147: * Called when a ref is frozen, to allow the suffix to be reused. ! 148: * (inp) is the net level pcb. ! 149: * ! 150: * RETURNS: Nada ! 151: * ! 152: * SIDE EFFECTS: ! 153: * ! 154: * NOTES: This really shouldn't have to be done in a NET level pcb ! 155: * but... for the internet world that just the way it is done in BSD... ! 156: * The alternative is to have the port unusable until the reference ! 157: * timer goes off. ! 158: */ ! 159: void ! 160: in_recycle_tsuffix(inp) ! 161: struct inpcb *inp; ! 162: { ! 163: inp->inp_fport = inp->inp_lport = 0; ! 164: } ! 165: ! 166: /* ! 167: * NAME: in_putnetaddr() ! 168: * ! 169: * CALLED FROM: ! 170: * tp_newsocket(); i.e., when a connection is being established by an ! 171: * incoming CR_TPDU. ! 172: * ! 173: * FUNCTION and ARGUMENTS: ! 174: * Copy a whole net addr from a struct sockaddr (name). ! 175: * into an inpcb (inp). ! 176: * The argument (which) takes values TP_LOCAL or TP_FOREIGN ! 177: * ! 178: * RETURNS: Nada ! 179: * ! 180: * SIDE EFFECTS: ! 181: * ! 182: * NOTES: ! 183: */ ! 184: void ! 185: in_putnetaddr(inp, name, which) ! 186: register struct inpcb *inp; ! 187: struct sockaddr_in *name; ! 188: int which; ! 189: { ! 190: switch (which) { ! 191: case TP_LOCAL: ! 192: bcopy((caddr_t)&name->sin_addr, ! 193: (caddr_t)&inp->inp_laddr, sizeof(struct in_addr)); ! 194: /* won't work if the dst address (name) is INADDR_ANY */ ! 195: ! 196: break; ! 197: case TP_FOREIGN: ! 198: if( name != (struct sockaddr_in *)0 ) { ! 199: bcopy((caddr_t)&name->sin_addr, ! 200: (caddr_t)&inp->inp_faddr, sizeof(struct in_addr)); ! 201: } ! 202: } ! 203: } ! 204: ! 205: /* ! 206: * NAME: in_putnetaddr() ! 207: * ! 208: * CALLED FROM: ! 209: * tp_input() when a connection is being established by an ! 210: * incoming CR_TPDU, and considered for interception. ! 211: * ! 212: * FUNCTION and ARGUMENTS: ! 213: * Compare a whole net addr from a struct sockaddr (name), ! 214: * with that implicitly stored in an inpcb (inp). ! 215: * The argument (which) takes values TP_LOCAL or TP_FOREIGN ! 216: * ! 217: * RETURNS: Nada ! 218: * ! 219: * SIDE EFFECTS: ! 220: * ! 221: * NOTES: ! 222: */ ! 223: in_cmpnetaddr(inp, name, which) ! 224: register struct inpcb *inp; ! 225: register struct sockaddr_in *name; ! 226: int which; ! 227: { ! 228: if (which == TP_LOCAL) { ! 229: if (name->sin_port && name->sin_port != inp->inp_lport) ! 230: return 0; ! 231: return (name->sin_addr.s_addr == inp->inp_laddr.s_addr); ! 232: } ! 233: if (name->sin_port && name->sin_port != inp->inp_fport) ! 234: return 0; ! 235: return (name->sin_addr.s_addr == inp->inp_faddr.s_addr); ! 236: } ! 237: ! 238: /* ! 239: * NAME: in_getnetaddr() ! 240: * ! 241: * CALLED FROM: ! 242: * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR ! 243: * FUNCTION and ARGUMENTS: ! 244: * Copy a whole net addr from an inpcb (inp) into ! 245: * an mbuf (name); ! 246: * The argument (which) takes values TP_LOCAL or TP_FOREIGN. ! 247: * ! 248: * RETURNS: Nada ! 249: * ! 250: * SIDE EFFECTS: ! 251: * ! 252: * NOTES: ! 253: */ ! 254: ! 255: void ! 256: in_getnetaddr( inp, name, which) ! 257: register struct mbuf *name; ! 258: struct inpcb *inp; ! 259: int which; ! 260: { ! 261: register struct sockaddr_in *sin = mtod(name, struct sockaddr_in *); ! 262: bzero((caddr_t)sin, sizeof(*sin)); ! 263: switch (which) { ! 264: case TP_LOCAL: ! 265: sin->sin_addr = inp->inp_laddr; ! 266: sin->sin_port = inp->inp_lport; ! 267: break; ! 268: case TP_FOREIGN: ! 269: sin->sin_addr = inp->inp_faddr; ! 270: sin->sin_port = inp->inp_fport; ! 271: break; ! 272: default: ! 273: return; ! 274: } ! 275: name->m_len = sin->sin_len = sizeof (*sin); ! 276: sin->sin_family = AF_INET; ! 277: } ! 278: ! 279: /* ! 280: * NAME: tpip_mtu() ! 281: * ! 282: * CALLED FROM: ! 283: * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT ! 284: * ! 285: * FUNCTION, ARGUMENTS, and RETURN VALUE: ! 286: * ! 287: * Determine the proper maximum transmission unit, i.e., MTU, to use, given ! 288: * a) the header size for the network protocol and the max transmission ! 289: * unit on the subnet interface, determined from the information in (inp), ! 290: * b) the max size negotiated so far (negot) ! 291: * c) the window size used by the tp connection (found in so), ! 292: * ! 293: * The result is put in the integer *size in its integer form and in ! 294: * *negot in its logarithmic form. ! 295: * ! 296: * The rules are: ! 297: * a) can only negotiate down from the value found in *negot. ! 298: * b) the MTU must be < the windowsize, ! 299: * c) If src and dest are on the same net, ! 300: * we will negotiate the closest size larger than MTU but really USE ! 301: * the actual device mtu - ll hdr sizes. ! 302: * otherwise we negotiate the closest size smaller than MTU - ll hdr sizes. ! 303: * ! 304: * SIDE EFFECTS: ! 305: * changes the values addressed by the arguments (size) and (negot) ! 306: * and ! 307: * when the peer is not on one of our directly connected subnets, it ! 308: * looks up a route, leaving the route in the inpcb addressed by (inp) ! 309: * ! 310: * NOTES: ! 311: */ ! 312: ! 313: void ! 314: tpip_mtu(so, inp, size, negot) ! 315: struct socket *so; ! 316: struct inpcb *inp; ! 317: int *size; ! 318: u_char *negot; ! 319: { ! 320: register struct ifnet *ifp; ! 321: struct ifnet *tpip_route(); ! 322: struct in_ifaddr *ia; ! 323: register int i; ! 324: int windowsize = so->so_rcv.sb_hiwat; ! 325: ! 326: IFDEBUG(D_CONN) ! 327: printf("tpip_mtu(0x%x,0x%x,0x%x,0x%x)\n", ! 328: so, inp, size, negot); ! 329: printf("tpip_mtu routing to addr 0x%x\n", inp->inp_faddr); ! 330: ENDDEBUG ! 331: IFTRACE(D_CONN) ! 332: tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0); ! 333: ENDTRACE ! 334: ! 335: *size = 1 << *negot; ! 336: ! 337: if( *size > windowsize ) { ! 338: *size = windowsize; ! 339: } ! 340: ! 341: ia = in_iaonnetof(in_netof(inp->inp_faddr)); ! 342: if ( ia == (struct in_ifaddr *)0 ) { ! 343: ifp = tpip_route(&inp->inp_faddr); ! 344: if( ifp == (struct ifnet *)0 ) ! 345: return ; ! 346: } else ! 347: ifp = ia->ia_ifp; ! 348: ! 349: ! 350: /**************************************************************** ! 351: * TODO - make this indirect off the socket structure to the ! 352: * network layer to get headersize ! 353: * After all, who knows what lies below the IP layer? ! 354: * Who knows how big the NL header will be? ! 355: ***************************************************************/ ! 356: ! 357: if( *size > ifp->if_mtu - sizeof(struct ip)) { ! 358: *size = ifp->if_mtu - sizeof(struct ip); ! 359: } ! 360: for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++) ! 361: ; ! 362: i--; ! 363: ! 364: if (in_netof(inp->inp_laddr) != in_netof(inp->inp_faddr)) { ! 365: i++; ! 366: } else { ! 367: *size = 1<<i; ! 368: } ! 369: *negot = i; ! 370: ! 371: IFDEBUG(D_CONN) ! 372: printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", ! 373: ifp->if_name, *size, *negot); ! 374: ENDDEBUG ! 375: IFTRACE(D_CONN) ! 376: tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n", ! 377: *size, *negot, 0, 0); ! 378: ENDTRACE ! 379: ! 380: } ! 381: ! 382: /* ! 383: * NAME: tpip_output() ! 384: * ! 385: * CALLED FROM: tp_emit() ! 386: * ! 387: * FUNCTION and ARGUMENTS: ! 388: * Take a packet(m0) from tp and package it so that ip will accept it. ! 389: * This means prepending space for the ip header and filling in a few ! 390: * of the fields. ! 391: * inp is the inpcb structure; datalen is the length of the data in the ! 392: * mbuf string m0. ! 393: * RETURNS: ! 394: * whatever (E*) is returned form the net layer output routine. ! 395: * ! 396: * SIDE EFFECTS: ! 397: * ! 398: * NOTES: ! 399: */ ! 400: ! 401: int ! 402: tpip_output(inp, m0, datalen, nochksum) ! 403: struct inpcb *inp; ! 404: struct mbuf *m0; ! 405: int datalen; ! 406: int nochksum; ! 407: { ! 408: return tpip_output_dg( &inp->inp_laddr, &inp->inp_faddr, m0, datalen, ! 409: &inp->inp_route, nochksum); ! 410: } ! 411: ! 412: /* ! 413: * NAME: tpip_output_dg() ! 414: * ! 415: * CALLED FROM: tp_error_emit() ! 416: * ! 417: * FUNCTION and ARGUMENTS: ! 418: * This is a copy of tpip_output that takes the addresses ! 419: * instead of a pcb. It's used by the tp_error_emit, when we ! 420: * don't have an in_pcb with which to call the normal output rtn. ! 421: * ! 422: * RETURNS: ENOBUFS or whatever (E*) is ! 423: * returned form the net layer output routine. ! 424: * ! 425: * SIDE EFFECTS: ! 426: * ! 427: * NOTES: ! 428: */ ! 429: ! 430: /*ARGSUSED*/ ! 431: int ! 432: tpip_output_dg(laddr, faddr, m0, datalen, ro, nochksum) ! 433: struct in_addr *laddr, *faddr; ! 434: struct mbuf *m0; ! 435: int datalen; ! 436: struct route *ro; ! 437: int nochksum; ! 438: { ! 439: register struct mbuf *m; ! 440: register struct ip *ip; ! 441: int error; ! 442: ! 443: IFDEBUG(D_EMIT) ! 444: printf("tpip_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); ! 445: ENDDEBUG ! 446: ! 447: ! 448: MGETHDR(m, M_DONTWAIT, TPMT_IPHDR); ! 449: if (m == 0) { ! 450: error = ENOBUFS; ! 451: goto bad; ! 452: } ! 453: m->m_next = m0; ! 454: MH_ALIGN(m, sizeof(struct ip)); ! 455: m->m_len = sizeof(struct ip); ! 456: ! 457: ip = mtod(m, struct ip *); ! 458: bzero((caddr_t)ip, sizeof *ip); ! 459: ! 460: ip->ip_p = IPPROTO_TP; ! 461: m->m_pkthdr.len = ip->ip_len = sizeof(struct ip) + datalen; ! 462: ip->ip_ttl = MAXTTL; ! 463: /* don't know why you need to set ttl; ! 464: * overlay doesn't even make this available ! 465: */ ! 466: ! 467: ip->ip_src = *laddr; ! 468: ip->ip_dst = *faddr; ! 469: ! 470: IncStat(ts_tpdu_sent); ! 471: IFDEBUG(D_EMIT) ! 472: dump_mbuf(m, "tpip_output_dg before ip_output\n"); ! 473: ENDDEBUG ! 474: ! 475: error = ip_output(m, (struct mbuf *)0, ro, IP_ALLOWBROADCAST); ! 476: ! 477: IFDEBUG(D_EMIT) ! 478: printf("tpip_output_dg after ip_output\n"); ! 479: ENDDEBUG ! 480: ! 481: return error; ! 482: ! 483: bad: ! 484: m_freem(m); ! 485: IncStat(ts_send_drop); ! 486: return error; ! 487: } ! 488: ! 489: /* ! 490: * NAME: tpip_input() ! 491: * ! 492: * CALLED FROM: ! 493: * ip's input routine, indirectly through the protosw. ! 494: * ! 495: * FUNCTION and ARGUMENTS: ! 496: * Take a packet (m) from ip, strip off the ip header and give it to tp ! 497: * ! 498: * RETURNS: No return value. ! 499: * ! 500: * SIDE EFFECTS: ! 501: * ! 502: * NOTES: ! 503: */ ! 504: ProtoHook ! 505: tpip_input(m, iplen) ! 506: struct mbuf *m; ! 507: int iplen; ! 508: { ! 509: struct sockaddr_in src, dst; ! 510: register struct ip *ip; ! 511: int s = splnet(), hdrlen; ! 512: ! 513: IncStat(ts_pkt_rcvd); ! 514: ! 515: /* ! 516: * IP layer has already pulled up the IP header, ! 517: * but the first byte after the IP header may not be there, ! 518: * e.g. if you came in via loopback, so you have to do an ! 519: * m_pullup to before you can even look to see how much you ! 520: * really need. The good news is that m_pullup will round ! 521: * up to almost the next mbuf's worth. ! 522: */ ! 523: ! 524: ! 525: if((m = m_pullup(m, iplen + 1)) == MNULL) ! 526: goto discard; ! 527: CHANGE_MTYPE(m, TPMT_DATA); ! 528: ! 529: /* ! 530: * Now pull up the whole tp header: ! 531: * Unfortunately, there may be IP options to skip past so we ! 532: * just fetch it as an unsigned char. ! 533: */ ! 534: hdrlen = iplen + 1 + mtod(m, u_char *)[iplen]; ! 535: ! 536: if( m->m_len < hdrlen ) { ! 537: if((m = m_pullup(m, hdrlen)) == MNULL){ ! 538: IFDEBUG(D_TPINPUT) ! 539: printf("tp_input, pullup 2!\n"); ! 540: ENDDEBUG ! 541: goto discard; ! 542: } ! 543: } ! 544: /* ! 545: * cannot use tp_inputprep() here 'cause you don't ! 546: * have quite the same situation ! 547: */ ! 548: ! 549: IFDEBUG(D_TPINPUT) ! 550: dump_mbuf(m, "after tpip_input both pullups"); ! 551: ENDDEBUG ! 552: /* ! 553: * m_pullup may have returned a different mbuf ! 554: */ ! 555: ip = mtod(m, struct ip *); ! 556: ! 557: /* ! 558: * drop the ip header from the front of the mbuf ! 559: * this is necessary for the tp checksum ! 560: */ ! 561: m->m_len -= iplen; ! 562: m->m_data += iplen; ! 563: ! 564: src.sin_addr = *(struct in_addr *)&(ip->ip_src); ! 565: src.sin_family = AF_INET; ! 566: src.sin_len = sizeof(src); ! 567: dst.sin_addr = *(struct in_addr *)&(ip->ip_dst); ! 568: dst.sin_family = AF_INET; ! 569: dst.sin_len = sizeof(dst); ! 570: ! 571: (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst, ! 572: 0, tpip_output_dg, 0); ! 573: return 0; ! 574: ! 575: discard: ! 576: IFDEBUG(D_TPINPUT) ! 577: printf("tpip_input DISCARD\n"); ! 578: ENDDEBUG ! 579: IFTRACE(D_TPINPUT) ! 580: tptrace(TPPTmisc, "tpip_input DISCARD m", m,0,0,0); ! 581: ENDTRACE ! 582: m_freem(m); ! 583: IncStat(ts_recv_drop); ! 584: splx(s); ! 585: return 0; ! 586: } ! 587: ! 588: ! 589: #include "protosw.h" ! 590: #include "../netinet/ip_icmp.h" ! 591: ! 592: extern void tp_quench(); ! 593: /* ! 594: * NAME: tpin_quench() ! 595: * ! 596: * CALLED FROM: tpip_ctlinput() ! 597: * ! 598: * FUNCTION and ARGUMENTS: find the tpcb pointer and pass it to tp_quench ! 599: * ! 600: * RETURNS: Nada ! 601: * ! 602: * SIDE EFFECTS: ! 603: * ! 604: * NOTES: ! 605: */ ! 606: ! 607: void ! 608: tpin_quench(inp) ! 609: struct inpcb *inp; ! 610: { ! 611: tp_quench((struct tp_pcb *)inp->inp_socket->so_tpcb, PRC_QUENCH); ! 612: } ! 613: ! 614: /* ! 615: * NAME: tpip_ctlinput() ! 616: * ! 617: * CALLED FROM: ! 618: * The network layer through the protosw table. ! 619: * ! 620: * FUNCTION and ARGUMENTS: ! 621: * When clnp gets an ICMP msg this gets called. ! 622: * It either returns an error status to the user or ! 623: * causes all connections on this address to be aborted ! 624: * by calling the appropriate xx_notify() routine. ! 625: * (cmd) is the type of ICMP error. ! 626: * (sa) the address of the sender ! 627: * ! 628: * RETURNS: Nothing ! 629: * ! 630: * SIDE EFFECTS: ! 631: * ! 632: * NOTES: ! 633: */ ! 634: ProtoHook ! 635: tpip_ctlinput(cmd, sin) ! 636: int cmd; ! 637: struct sockaddr_in *sin; ! 638: { ! 639: extern u_char inetctlerrmap[]; ! 640: extern ProtoHook tpin_abort(); ! 641: extern ProtoHook in_rtchange(); ! 642: ! 643: if (sin->sin_family != AF_INET && sin->sin_family != AF_IMPLINK) ! 644: return 0; ! 645: if (sin->sin_addr.s_addr == INADDR_ANY) ! 646: return 0; ! 647: if (cmd < 0 || cmd > PRC_NCMDS) ! 648: return 0; ! 649: switch (cmd) { ! 650: ! 651: case PRC_QUENCH: ! 652: in_pcbnotify(&tp_inpcb, sin, ! 653: 0, (int (*)())tp_quench); ! 654: break; ! 655: ! 656: case PRC_ROUTEDEAD: ! 657: case PRC_HOSTUNREACH: ! 658: case PRC_UNREACH_NET: ! 659: case PRC_IFDOWN: ! 660: case PRC_HOSTDEAD: ! 661: in_pcbnotify(&tp_inpcb, sin, ! 662: (int)inetctlerrmap[cmd], in_rtchange); ! 663: break; ! 664: ! 665: default: ! 666: /* ! 667: case PRC_MSGSIZE: ! 668: case PRC_UNREACH_HOST: ! 669: case PRC_UNREACH_PROTOCOL: ! 670: case PRC_UNREACH_PORT: ! 671: case PRC_UNREACH_NEEDFRAG: ! 672: case PRC_UNREACH_SRCFAIL: ! 673: case PRC_REDIRECT_NET: ! 674: case PRC_REDIRECT_HOST: ! 675: case PRC_REDIRECT_TOSNET: ! 676: case PRC_REDIRECT_TOSHOST: ! 677: case PRC_TIMXCEED_INTRANS: ! 678: case PRC_TIMXCEED_REASS: ! 679: case PRC_PARAMPROB: ! 680: */ ! 681: in_pcbnotify(&tp_inpcb, sin, ! 682: (int)inetctlerrmap[cmd], tpin_abort); ! 683: } ! 684: return 0; ! 685: } ! 686: ! 687: /* ! 688: * NAME: tpin_abort() ! 689: * ! 690: * CALLED FROM: ! 691: * xxx_notify() from tp_ctlinput() when ! 692: * net level gets some ICMP-equiv. type event. ! 693: * ! 694: * FUNCTION and ARGUMENTS: ! 695: * Cause the connection to be aborted with some sort of error ! 696: * reason indicating that the network layer caused the abort. ! 697: * Fakes an ER TPDU so we can go through the driver. ! 698: * ! 699: * RETURNS: Nothing ! 700: * ! 701: * SIDE EFFECTS: ! 702: * ! 703: * NOTES: ! 704: */ ! 705: ! 706: ProtoHook ! 707: tpin_abort(inp) ! 708: struct inpcb *inp; ! 709: { ! 710: struct tp_event e; ! 711: ! 712: e.ev_number = ER_TPDU; ! 713: e.ATTR(ER_TPDU).e_reason = ENETRESET; ! 714: (void) tp_driver((struct tp_pcb *)inp->inp_ppcb, &e); ! 715: return 0; ! 716: } ! 717: ! 718: #ifdef ARGO_DEBUG ! 719: dump_inaddr(addr) ! 720: register struct sockaddr_in *addr; ! 721: { ! 722: printf("INET: port 0x%x; addr 0x%x\n", addr->sin_port, addr->sin_addr); ! 723: } ! 724: #endif ARGO_DEBUG ! 725: ! 726: /* ! 727: * NAME: tpip_route() ! 728: * ! 729: * CALLED FROM: tpip_mtu() ! 730: * ! 731: * FUNCTION and ARGUMENTS: given a destination addresss, ! 732: * find the interface that would be used to send something to this address. ! 733: * ! 734: * RETURNS: pointer to an ifnet structure ! 735: * ! 736: * SIDE EFFECTS: ! 737: * ! 738: * NOTES: ! 739: */ ! 740: struct ifnet * ! 741: tpip_route(dst) ! 742: struct in_addr *dst; ! 743: { ! 744: struct ifnet *ifp = (struct ifnet *)0; ! 745: struct sockaddr_in insock; ! 746: struct sockaddr_in *sin = &insock; ! 747: struct rtentry *rt; ! 748: struct ifaddr *ia; ! 749: ! 750: IFDEBUG(D_CONN) ! 751: printf("tpip_route: dst is x%x\n", *dst); ! 752: ENDDEBUG ! 753: ! 754: bzero((caddr_t)sin, sizeof (*sin)); ! 755: sin->sin_family = AF_INET; ! 756: sin->sin_len = sizeof(*sin); ! 757: sin->sin_addr = *dst; ! 758: ! 759: ia = ifa_ifwithdstaddr((struct sockaddr *)sin); ! 760: if (ia == 0) ! 761: ia = ifa_ifwithnet((struct sockaddr *)sin); ! 762: if (ia != 0) { ! 763: ifp = ia->ifa_ifp; ! 764: IFDEBUG(D_CONN) ! 765: printf("tpip_route: ifp from ia:0x%x\n", ia); ! 766: ENDDEBUG ! 767: } else { ! 768: rt = rtalloc1((struct sockaddr *)sin, 0); ! 769: if (rt != 0) { ! 770: ifp = rt->rt_ifp; ! 771: IFDEBUG(D_CONN) ! 772: printf("tpip_route: ifp from rentry: 0x%x\n", rt); ! 773: ENDDEBUG ! 774: rtfree(rt); ! 775: } ! 776: } ! 777: IFDEBUG(D_CONN) ! 778: printf("tpip_route: returning 0x%x\n", ifp); ! 779: if (ifp) ! 780: printf("tpip_route: if name %s unit 0x%x, mtu 0x%x\n", ! 781: ifp->if_name, ifp->if_unit, ifp->if_mtu); ! 782: ENDDEBUG ! 783: return ifp; ! 784: } ! 785: ! 786: #endif INET
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.