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