|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /*- ! 26: * Copyright (c) 1991, 1993 ! 27: * The Regents of the University of California. All rights reserved. ! 28: * ! 29: * Redistribution and use in source and binary forms, with or without ! 30: * modification, are permitted provided that the following conditions ! 31: * are met: ! 32: * 1. Redistributions of source code must retain the above copyright ! 33: * notice, this list of conditions and the following disclaimer. ! 34: * 2. Redistributions in binary form must reproduce the above copyright ! 35: * notice, this list of conditions and the following disclaimer in the ! 36: * documentation and/or other materials provided with the distribution. ! 37: * 3. All advertising materials mentioning features or use of this software ! 38: * must display the following acknowledgement: ! 39: * This product includes software developed by the University of ! 40: * California, Berkeley and its contributors. ! 41: * 4. Neither the name of the University nor the names of its contributors ! 42: * may be used to endorse or promote products derived from this software ! 43: * without specific prior written permission. ! 44: * ! 45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 55: * SUCH DAMAGE. ! 56: * ! 57: * @(#)tp_inet.c 8.1 (Berkeley) 6/10/93 ! 58: */ ! 59: ! 60: /*********************************************************** ! 61: Copyright IBM Corporation 1987 ! 62: ! 63: All Rights Reserved ! 64: ! 65: Permission to use, copy, modify, and distribute this software and its ! 66: documentation for any purpose and without fee is hereby granted, ! 67: provided that the above copyright notice appear in all copies and that ! 68: both that copyright notice and this permission notice appear in ! 69: supporting documentation, and that the name of IBM not be ! 70: used in advertising or publicity pertaining to distribution of the ! 71: software without specific, written prior permission. ! 72: ! 73: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 74: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 75: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 76: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 77: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 78: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 79: SOFTWARE. ! 80: ! 81: ******************************************************************/ ! 82: ! 83: /* ! 84: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison ! 85: */ ! 86: /* ! 87: * ARGO TP ! 88: * ! 89: * Here is where you find the inet-dependent code. We've tried ! 90: * keep all net-level and (primarily) address-family-dependent stuff ! 91: * out of the tp source, and everthing here is reached indirectly ! 92: * through a switch table (struct nl_protosw *) tpcb->tp_nlproto ! 93: * (see tp_pcb.c). ! 94: * The routines here are: ! 95: * in_getsufx: gets transport suffix out of an inpcb structure. ! 96: * in_putsufx: put transport suffix into an inpcb structure. ! 97: * in_putnetaddr: put a whole net addr into an inpcb. ! 98: * in_getnetaddr: get a whole net addr from an inpcb. ! 99: * in_cmpnetaddr: compare a whole net addr from an isopcb. ! 100: * in_recycle_suffix: clear suffix for reuse in inpcb ! 101: * tpip_mtu: figure out what size tpdu to use ! 102: * tpip_input: take a pkt from ip, strip off its ip header, give to tp ! 103: * tpip_output_dg: package a pkt for ip given 2 addresses & some data ! 104: * tpip_output: package a pkt for ip given an inpcb & some data ! 105: */ ! 106: ! 107: #if INET ! 108: ! 109: #include <sys/param.h> ! 110: #include <sys/socket.h> ! 111: #include <sys/socketvar.h> ! 112: #include <sys/mbuf.h> ! 113: #include <sys/errno.h> ! 114: #include <sys/time.h> ! 115: ! 116: #include <net/if.h> ! 117: ! 118: #include <netiso/tp_param.h> ! 119: #include <netiso/argo_debug.h> ! 120: #include <netiso/tp_stat.h> ! 121: #include <netiso/tp_ip.h> ! 122: #include <netiso/tp_pcb.h> ! 123: #include <netiso/tp_trace.h> ! 124: #include <netiso/tp_stat.h> ! 125: #include <netiso/tp_tpdu.h> ! 126: #include <netinet/in_var.h> ! 127: ! 128: #ifndef ISO ! 129: #include <netiso/iso_chksum.c> ! 130: #endif ! 131: ! 132: /* ! 133: * NAME: in_getsufx() ! 134: ! 135: * CALLED FROM: pr_usrreq() on PRU_BIND, ! 136: * PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR ! 137: * ! 138: * FUNCTION, ARGUMENTS, and RETURN VALUE: ! 139: * Get a transport suffix from an inpcb structure (inp). ! 140: * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. ! 141: * ! 142: * RETURNS: internet port / transport suffix ! 143: * (CAST TO AN INT) ! 144: * ! 145: * SIDE EFFECTS: ! 146: * ! 147: * NOTES: ! 148: */ ! 149: in_getsufx(inp, lenp, data_out, which) ! 150: struct inpcb *inp; ! 151: u_short *lenp; ! 152: caddr_t data_out; ! 153: int which; ! 154: { ! 155: *lenp = sizeof(u_short); ! 156: switch (which) { ! 157: case TP_LOCAL: ! 158: *(u_short *)data_out = inp->inp_lport; ! 159: return; ! 160: ! 161: case TP_FOREIGN: ! 162: *(u_short *)data_out = inp->inp_fport; ! 163: } ! 164: ! 165: } ! 166: ! 167: /* ! 168: * NAME: in_putsufx() ! 169: * ! 170: * CALLED FROM: tp_newsocket(); i.e., when a connection ! 171: * is being established by an incoming CR_TPDU. ! 172: * ! 173: * FUNCTION, ARGUMENTS: ! 174: * Put a transport suffix (found in name) into an inpcb structure (inp). ! 175: * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. ! 176: * ! 177: * RETURNS: Nada ! 178: * ! 179: * SIDE EFFECTS: ! 180: * ! 181: * NOTES: ! 182: */ ! 183: /*ARGSUSED*/ ! 184: void ! 185: in_putsufx(inp, sufxloc, sufxlen, which) ! 186: struct inpcb *inp; ! 187: caddr_t sufxloc; ! 188: int which; ! 189: { ! 190: if (which == TP_FOREIGN) { ! 191: bcopy(sufxloc, (caddr_t)&inp->inp_fport, sizeof(inp->inp_fport)); ! 192: } ! 193: } ! 194: ! 195: /* ! 196: * NAME: in_recycle_tsuffix() ! 197: * ! 198: * CALLED FROM: tp.trans whenever we go into REFWAIT state. ! 199: * ! 200: * FUNCTION and ARGUMENT: ! 201: * Called when a ref is frozen, to allow the suffix to be reused. ! 202: * (inp) is the net level pcb. ! 203: * ! 204: * RETURNS: Nada ! 205: * ! 206: * SIDE EFFECTS: ! 207: * ! 208: * NOTES: This really shouldn't have to be done in a NET level pcb ! 209: * but... for the internet world that just the way it is done in BSD... ! 210: * The alternative is to have the port unusable until the reference ! 211: * timer goes off. ! 212: */ ! 213: void ! 214: in_recycle_tsuffix(inp) ! 215: struct inpcb *inp; ! 216: { ! 217: inp->inp_fport = inp->inp_lport = 0; ! 218: } ! 219: ! 220: /* ! 221: * NAME: in_putnetaddr() ! 222: * ! 223: * CALLED FROM: ! 224: * tp_newsocket(); i.e., when a connection is being established by an ! 225: * incoming CR_TPDU. ! 226: * ! 227: * FUNCTION and ARGUMENTS: ! 228: * Copy a whole net addr from a struct sockaddr (name). ! 229: * into an inpcb (inp). ! 230: * The argument (which) takes values TP_LOCAL or TP_FOREIGN ! 231: * ! 232: * RETURNS: Nada ! 233: * ! 234: * SIDE EFFECTS: ! 235: * ! 236: * NOTES: ! 237: */ ! 238: void ! 239: in_putnetaddr(inp, name, which) ! 240: register struct inpcb *inp; ! 241: struct sockaddr_in *name; ! 242: int which; ! 243: { ! 244: switch (which) { ! 245: case TP_LOCAL: ! 246: bcopy((caddr_t)&name->sin_addr, ! 247: (caddr_t)&inp->inp_laddr, sizeof(struct in_addr)); ! 248: /* won't work if the dst address (name) is INADDR_ANY */ ! 249: ! 250: break; ! 251: case TP_FOREIGN: ! 252: if( name != (struct sockaddr_in *)0 ) { ! 253: bcopy((caddr_t)&name->sin_addr, ! 254: (caddr_t)&inp->inp_faddr, sizeof(struct in_addr)); ! 255: } ! 256: } ! 257: } ! 258: ! 259: /* ! 260: * NAME: in_putnetaddr() ! 261: * ! 262: * CALLED FROM: ! 263: * tp_input() when a connection is being established by an ! 264: * incoming CR_TPDU, and considered for interception. ! 265: * ! 266: * FUNCTION and ARGUMENTS: ! 267: * Compare a whole net addr from a struct sockaddr (name), ! 268: * with that implicitly stored in an inpcb (inp). ! 269: * The argument (which) takes values TP_LOCAL or TP_FOREIGN ! 270: * ! 271: * RETURNS: Nada ! 272: * ! 273: * SIDE EFFECTS: ! 274: * ! 275: * NOTES: ! 276: */ ! 277: in_cmpnetaddr(inp, name, which) ! 278: register struct inpcb *inp; ! 279: register struct sockaddr_in *name; ! 280: int which; ! 281: { ! 282: if (which == TP_LOCAL) { ! 283: if (name->sin_port && name->sin_port != inp->inp_lport) ! 284: return 0; ! 285: return (name->sin_addr.s_addr == inp->inp_laddr.s_addr); ! 286: } ! 287: if (name->sin_port && name->sin_port != inp->inp_fport) ! 288: return 0; ! 289: return (name->sin_addr.s_addr == inp->inp_faddr.s_addr); ! 290: } ! 291: ! 292: /* ! 293: * NAME: in_getnetaddr() ! 294: * ! 295: * CALLED FROM: ! 296: * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR ! 297: * FUNCTION and ARGUMENTS: ! 298: * Copy a whole net addr from an inpcb (inp) into ! 299: * an mbuf (name); ! 300: * The argument (which) takes values TP_LOCAL or TP_FOREIGN. ! 301: * ! 302: * RETURNS: Nada ! 303: * ! 304: * SIDE EFFECTS: ! 305: * ! 306: * NOTES: ! 307: */ ! 308: ! 309: void ! 310: in_getnetaddr( inp, name, which) ! 311: register struct mbuf *name; ! 312: struct inpcb *inp; ! 313: int which; ! 314: { ! 315: register struct sockaddr_in *sin = mtod(name, struct sockaddr_in *); ! 316: bzero((caddr_t)sin, sizeof(*sin)); ! 317: switch (which) { ! 318: case TP_LOCAL: ! 319: sin->sin_addr = inp->inp_laddr; ! 320: sin->sin_port = inp->inp_lport; ! 321: break; ! 322: case TP_FOREIGN: ! 323: sin->sin_addr = inp->inp_faddr; ! 324: sin->sin_port = inp->inp_fport; ! 325: break; ! 326: default: ! 327: return; ! 328: } ! 329: name->m_len = sin->sin_len = sizeof (*sin); ! 330: sin->sin_family = AF_INET; ! 331: } ! 332: ! 333: /* ! 334: * NAME: tpip_mtu() ! 335: * ! 336: * CALLED FROM: ! 337: * tp_route_to() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT ! 338: * ! 339: * FUNCTION, ARGUMENTS, and RETURN VALUE: ! 340: * ! 341: * Perform subnetwork dependent part of determining MTU information. ! 342: * It appears that setting a double pointer to the rtentry associated with ! 343: * the destination, and returning the header size for the network protocol ! 344: * suffices. ! 345: * ! 346: * SIDE EFFECTS: ! 347: * Sets tp_routep pointer in pcb. ! 348: * ! 349: * NOTES: ! 350: */ ! 351: ! 352: tpip_mtu(tpcb) ! 353: register struct tp_pcb *tpcb; ! 354: { ! 355: struct inpcb *inp = (struct inpcb *)tpcb->tp_npcb; ! 356: ! 357: IFDEBUG(D_CONN) ! 358: printf("tpip_mtu(tpcb)\n", tpcb); ! 359: printf("tpip_mtu routing to addr 0x%x\n", inp->inp_faddr.s_addr); ! 360: ENDDEBUG ! 361: tpcb->tp_routep = &(inp->inp_route.ro_rt); ! 362: return (sizeof (struct ip)); ! 363: ! 364: } ! 365: ! 366: /* ! 367: * NAME: tpip_output() ! 368: * ! 369: * CALLED FROM: tp_emit() ! 370: * ! 371: * FUNCTION and ARGUMENTS: ! 372: * Take a packet(m0) from tp and package it so that ip will accept it. ! 373: * This means prepending space for the ip header and filling in a few ! 374: * of the fields. ! 375: * inp is the inpcb structure; datalen is the length of the data in the ! 376: * mbuf string m0. ! 377: * RETURNS: ! 378: * whatever (E*) is returned form the net layer output routine. ! 379: * ! 380: * SIDE EFFECTS: ! 381: * ! 382: * NOTES: ! 383: */ ! 384: ! 385: int ! 386: tpip_output(inp, m0, datalen, nochksum) ! 387: struct inpcb *inp; ! 388: struct mbuf *m0; ! 389: int datalen; ! 390: int nochksum; ! 391: { ! 392: return tpip_output_dg( &inp->inp_laddr, &inp->inp_faddr, m0, datalen, ! 393: &inp->inp_route, nochksum); ! 394: } ! 395: ! 396: /* ! 397: * NAME: tpip_output_dg() ! 398: * ! 399: * CALLED FROM: tp_error_emit() ! 400: * ! 401: * FUNCTION and ARGUMENTS: ! 402: * This is a copy of tpip_output that takes the addresses ! 403: * instead of a pcb. It's used by the tp_error_emit, when we ! 404: * don't have an in_pcb with which to call the normal output rtn. ! 405: * ! 406: * RETURNS: ENOBUFS or whatever (E*) is ! 407: * returned form the net layer output routine. ! 408: * ! 409: * SIDE EFFECTS: ! 410: * ! 411: * NOTES: ! 412: */ ! 413: ! 414: /*ARGSUSED*/ ! 415: int ! 416: tpip_output_dg(laddr, faddr, m0, datalen, ro, nochksum) ! 417: struct in_addr *laddr, *faddr; ! 418: struct mbuf *m0; ! 419: int datalen; ! 420: struct route *ro; ! 421: int nochksum; ! 422: { ! 423: register struct mbuf *m; ! 424: register struct ip *ip; ! 425: int error; ! 426: ! 427: IFDEBUG(D_EMIT) ! 428: printf("tpip_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); ! 429: ENDDEBUG ! 430: ! 431: ! 432: MGETHDR(m, M_DONTWAIT, TPMT_IPHDR); ! 433: if (m == 0) { ! 434: error = ENOBUFS; ! 435: goto bad; ! 436: } ! 437: m->m_next = m0; ! 438: MH_ALIGN(m, sizeof(struct ip)); ! 439: m->m_len = sizeof(struct ip); ! 440: ! 441: ip = mtod(m, struct ip *); ! 442: bzero((caddr_t)ip, sizeof *ip); ! 443: ! 444: ip->ip_p = IPPROTO_TP; ! 445: m->m_pkthdr.len = ip->ip_len = sizeof(struct ip) + datalen; ! 446: ip->ip_ttl = MAXTTL; ! 447: /* don't know why you need to set ttl; ! 448: * overlay doesn't even make this available ! 449: */ ! 450: ! 451: ip->ip_src = *laddr; ! 452: ip->ip_dst = *faddr; ! 453: ! 454: IncStat(ts_tpdu_sent); ! 455: IFDEBUG(D_EMIT) ! 456: dump_mbuf(m, "tpip_output_dg before ip_output\n"); ! 457: ENDDEBUG ! 458: ! 459: error = ip_output(m, (struct mbuf *)0, ro, IP_ALLOWBROADCAST, NULL); ! 460: ! 461: IFDEBUG(D_EMIT) ! 462: printf("tpip_output_dg after ip_output\n"); ! 463: ENDDEBUG ! 464: ! 465: return error; ! 466: ! 467: bad: ! 468: m_freem(m); ! 469: IncStat(ts_send_drop); ! 470: return error; ! 471: } ! 472: ! 473: /* ! 474: * NAME: tpip_input() ! 475: * ! 476: * CALLED FROM: ! 477: * ip's input routine, indirectly through the protosw. ! 478: * ! 479: * FUNCTION and ARGUMENTS: ! 480: * Take a packet (m) from ip, strip off the ip header and give it to tp ! 481: * ! 482: * RETURNS: No return value. ! 483: * ! 484: * SIDE EFFECTS: ! 485: * ! 486: * NOTES: ! 487: */ ! 488: ProtoHook ! 489: tpip_input(m, iplen) ! 490: struct mbuf *m; ! 491: int iplen; ! 492: { ! 493: struct sockaddr_in src, dst; ! 494: register struct ip *ip; ! 495: int s = splnet(), hdrlen; ! 496: ! 497: IncStat(ts_pkt_rcvd); ! 498: ! 499: /* ! 500: * IP layer has already pulled up the IP header, ! 501: * but the first byte after the IP header may not be there, ! 502: * e.g. if you came in via loopback, so you have to do an ! 503: * m_pullup to before you can even look to see how much you ! 504: * really need. The good news is that m_pullup will round ! 505: * up to almost the next mbuf's worth. ! 506: */ ! 507: ! 508: ! 509: if((m = m_pullup(m, iplen + 1)) == MNULL) ! 510: goto discard; ! 511: CHANGE_MTYPE(m, TPMT_DATA); ! 512: ! 513: /* ! 514: * Now pull up the whole tp header: ! 515: * Unfortunately, there may be IP options to skip past so we ! 516: * just fetch it as an unsigned char. ! 517: */ ! 518: hdrlen = iplen + 1 + mtod(m, u_char *)[iplen]; ! 519: ! 520: if( m->m_len < hdrlen ) { ! 521: if((m = m_pullup(m, hdrlen)) == MNULL){ ! 522: IFDEBUG(D_TPINPUT) ! 523: printf("tp_input, pullup 2!\n"); ! 524: ENDDEBUG ! 525: goto discard; ! 526: } ! 527: } ! 528: /* ! 529: * cannot use tp_inputprep() here 'cause you don't ! 530: * have quite the same situation ! 531: */ ! 532: ! 533: IFDEBUG(D_TPINPUT) ! 534: dump_mbuf(m, "after tpip_input both pullups"); ! 535: ENDDEBUG ! 536: /* ! 537: * m_pullup may have returned a different mbuf ! 538: */ ! 539: ip = mtod(m, struct ip *); ! 540: ! 541: /* ! 542: * drop the ip header from the front of the mbuf ! 543: * this is necessary for the tp checksum ! 544: */ ! 545: m->m_len -= iplen; ! 546: m->m_data += iplen; ! 547: ! 548: src.sin_addr = *(struct in_addr *)&(ip->ip_src); ! 549: src.sin_family = AF_INET; ! 550: src.sin_len = sizeof(src); ! 551: dst.sin_addr = *(struct in_addr *)&(ip->ip_dst); ! 552: dst.sin_family = AF_INET; ! 553: dst.sin_len = sizeof(dst); ! 554: ! 555: (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst, ! 556: 0, tpip_output_dg, 0); ! 557: return 0; ! 558: ! 559: discard: ! 560: IFDEBUG(D_TPINPUT) ! 561: printf("tpip_input DISCARD\n"); ! 562: ENDDEBUG ! 563: IFTRACE(D_TPINPUT) ! 564: tptrace(TPPTmisc, "tpip_input DISCARD m", m,0,0,0); ! 565: ENDTRACE ! 566: m_freem(m); ! 567: IncStat(ts_recv_drop); ! 568: splx(s); ! 569: return 0; ! 570: } ! 571: ! 572: ! 573: #include <sys/protosw.h> ! 574: #include <netinet/ip_icmp.h> ! 575: ! 576: extern void tp_quench(); ! 577: /* ! 578: * NAME: tpin_quench() ! 579: * ! 580: * CALLED FROM: tpip_ctlinput() ! 581: * ! 582: * FUNCTION and ARGUMENTS: find the tpcb pointer and pass it to tp_quench ! 583: * ! 584: * RETURNS: Nada ! 585: * ! 586: * SIDE EFFECTS: ! 587: * ! 588: * NOTES: ! 589: */ ! 590: ! 591: void ! 592: tpin_quench(inp) ! 593: struct inpcb *inp; ! 594: { ! 595: tp_quench((struct tp_pcb *)inp->inp_socket->so_pcb, PRC_QUENCH); ! 596: } ! 597: ! 598: /* ! 599: * NAME: tpip_ctlinput() ! 600: * ! 601: * CALLED FROM: ! 602: * The network layer through the protosw table. ! 603: * ! 604: * FUNCTION and ARGUMENTS: ! 605: * When clnp gets an ICMP msg this gets called. ! 606: * It either returns an error status to the user or ! 607: * causes all connections on this address to be aborted ! 608: * by calling the appropriate xx_notify() routine. ! 609: * (cmd) is the type of ICMP error. ! 610: * (sa) the address of the sender ! 611: * ! 612: * RETURNS: Nothing ! 613: * ! 614: * SIDE EFFECTS: ! 615: * ! 616: * NOTES: ! 617: */ ! 618: ProtoHook ! 619: tpip_ctlinput(cmd, sin) ! 620: int cmd; ! 621: struct sockaddr_in *sin; ! 622: { ! 623: extern u_char inetctlerrmap[]; ! 624: extern struct in_addr zeroin_addr; ! 625: void tp_quench __P((struct inpcb *,int)); ! 626: void tpin_abort __P((struct inpcb *,int)); ! 627: ! 628: if (sin->sin_family != AF_INET && sin->sin_family != AF_IMPLINK) ! 629: return 0; ! 630: if (sin->sin_addr.s_addr == INADDR_ANY) ! 631: return 0; ! 632: if (cmd < 0 || cmd > PRC_NCMDS) ! 633: return 0; ! 634: switch (cmd) { ! 635: ! 636: case PRC_QUENCH: ! 637: in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0, ! 638: zeroin_addr, 0, cmd, tp_quench); ! 639: break; ! 640: ! 641: case PRC_ROUTEDEAD: ! 642: case PRC_HOSTUNREACH: ! 643: case PRC_UNREACH_NET: ! 644: case PRC_IFDOWN: ! 645: case PRC_HOSTDEAD: ! 646: in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0, ! 647: zeroin_addr, 0, cmd, in_rtchange); ! 648: break; ! 649: ! 650: default: ! 651: /* ! 652: case PRC_MSGSIZE: ! 653: case PRC_UNREACH_HOST: ! 654: case PRC_UNREACH_PROTOCOL: ! 655: case PRC_UNREACH_PORT: ! 656: case PRC_UNREACH_NEEDFRAG: ! 657: case PRC_UNREACH_SRCFAIL: ! 658: case PRC_REDIRECT_NET: ! 659: case PRC_REDIRECT_HOST: ! 660: case PRC_REDIRECT_TOSNET: ! 661: case PRC_REDIRECT_TOSHOST: ! 662: case PRC_TIMXCEED_INTRANS: ! 663: case PRC_TIMXCEED_REASS: ! 664: case PRC_PARAMPROB: ! 665: */ ! 666: in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0, ! 667: zeroin_addr, 0, cmd, tpin_abort); ! 668: } ! 669: return 0; ! 670: } ! 671: ! 672: /* ! 673: * NAME: tpin_abort() ! 674: * ! 675: * CALLED FROM: ! 676: * xxx_notify() from tp_ctlinput() when ! 677: * net level gets some ICMP-equiv. type event. ! 678: * ! 679: * FUNCTION and ARGUMENTS: ! 680: * Cause the connection to be aborted with some sort of error ! 681: * reason indicating that the network layer caused the abort. ! 682: * Fakes an ER TPDU so we can go through the driver. ! 683: * ! 684: * RETURNS: Nothing ! 685: * ! 686: * SIDE EFFECTS: ! 687: * ! 688: * NOTES: ! 689: */ ! 690: ! 691: ProtoHook ! 692: tpin_abort(inp) ! 693: struct inpcb *inp; ! 694: { ! 695: struct tp_event e; ! 696: ! 697: e.ev_number = ER_TPDU; ! 698: e.ATTR(ER_TPDU).e_reason = ENETRESET; ! 699: (void) tp_driver((struct tp_pcb *)inp->inp_ppcb, &e); ! 700: return 0; ! 701: } ! 702: ! 703: #ifdef ARGO_DEBUG ! 704: dump_inaddr(addr) ! 705: register struct sockaddr_in *addr; ! 706: { ! 707: printf("INET: port 0x%x; addr 0x%x\n", addr->sin_port, addr->sin_addr); ! 708: } ! 709: #endif /* ARGO_DEBUG */ ! 710: #endif /* INET */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.