|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1982, 1986, 1988, 1993 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 ! 55: */ ! 56: ! 57: #include <sys/param.h> ! 58: #include <sys/systm.h> ! 59: #include <sys/kernel.h> ! 60: #include <sys/malloc.h> ! 61: #include <sys/mbuf.h> ! 62: #include <sys/proc.h> ! 63: #include <sys/protosw.h> ! 64: #include <sys/socket.h> ! 65: #include <sys/socketvar.h> ! 66: #include <sys/sysctl.h> ! 67: ! 68: #if ISFB31 ! 69: #include <vm/vm_zone.h> ! 70: #endif ! 71: ! 72: #include <net/if.h> ! 73: #include <net/route.h> ! 74: ! 75: #define _IP_VHL ! 76: #include <netinet/in.h> ! 77: #include <netinet/in_systm.h> ! 78: #include <netinet/ip.h> ! 79: #include <netinet/in_pcb.h> ! 80: #include <netinet/in_var.h> ! 81: #include <netinet/ip_var.h> ! 82: #include <netinet/ip_mroute.h> ! 83: ! 84: #include <netinet/ip_fw.h> ! 85: ! 86: #if ISFB31 ! 87: #include "opt_ipdn.h" ! 88: #endif ! 89: ! 90: #if DUMMYNET ! 91: #include <netinet/ip_dummynet.h> ! 92: #endif ! 93: #if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1 ! 94: #undef COMPAT_IPFW ! 95: #define COMPAT_IPFW 1 ! 96: #else ! 97: #undef COMPAT_IPFW ! 98: #endif ! 99: ! 100: static struct inpcbhead ripcb; ! 101: static struct inpcbinfo ripcbinfo; ! 102: ! 103: /* ! 104: * Nominal space allocated to a raw ip socket. ! 105: */ ! 106: #define RIPSNDQ 8192 ! 107: #define RIPRCVQ 8192 ! 108: ! 109: /* ! 110: * Raw interface to IP protocol. ! 111: */ ! 112: ! 113: /* ! 114: * Initialize raw connection block q. ! 115: */ ! 116: void ! 117: rip_init() ! 118: { ! 119: LIST_INIT(&ripcb); ! 120: ripcbinfo.listhead = &ripcb; ! 121: /* ! 122: * XXX We don't use the hash list for raw IP, but it's easier ! 123: * to allocate a one entry hash list than it is to check all ! 124: * over the place for hashbase == NULL. ! 125: */ ! 126: ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask); ! 127: ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask); ! 128: ! 129: ripcbinfo.ipi_zone = (void *) zinit(sizeof(struct inpcb), ! 130: (4096 * sizeof(struct inpcb)), ! 131: 4096, "ripzone"); ! 132: ! 133: } ! 134: ! 135: static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; ! 136: /* ! 137: * Setup generic address and protocol structures ! 138: * for raw_input routine, then pass them along with ! 139: * mbuf chain. ! 140: */ ! 141: void ! 142: rip_input(m, iphlen) ! 143: struct mbuf *m; ! 144: int iphlen; ! 145: { ! 146: register struct ip *ip = mtod(m, struct ip *); ! 147: register struct inpcb *inp; ! 148: struct inpcb *last = 0; ! 149: struct mbuf *opts = 0; ! 150: ! 151: ripsrc.sin_addr = ip->ip_src; ! 152: for (inp = ripcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { ! 153: if (inp->inp_ip_p && inp->inp_ip_p != ip->ip_p) ! 154: continue; ! 155: if (inp->inp_laddr.s_addr && ! 156: inp->inp_laddr.s_addr != ip->ip_dst.s_addr) ! 157: continue; ! 158: if (inp->inp_faddr.s_addr && ! 159: inp->inp_faddr.s_addr != ip->ip_src.s_addr) ! 160: continue; ! 161: if (last) { ! 162: struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); ! 163: if (n) { ! 164: if (last->inp_flags & INP_CONTROLOPTS || ! 165: last->inp_socket->so_options & SO_TIMESTAMP) ! 166: ip_savecontrol(last, &opts, ip, n); ! 167: if (last->inp_flags & INP_STRIPHDR) { ! 168: n->m_len -= iphlen; ! 169: n->m_pkthdr.len -= iphlen; ! 170: n->m_data += iphlen; ! 171: } ! 172: if (sbappendaddr(&last->inp_socket->so_rcv, ! 173: (struct sockaddr *)&ripsrc, n, ! 174: opts) == 0) { ! 175: /* should notify about lost packet */ ! 176: kprintf("rip_input can't append to socket\n"); ! 177: m_freem(n); ! 178: if (opts) ! 179: m_freem(opts); ! 180: } else { ! 181: /* kprintf("rip_input calling sorwakeup\n"); */ ! 182: sorwakeup(last->inp_socket); ! 183: } ! 184: opts = 0; ! 185: } ! 186: } ! 187: last = inp; ! 188: } ! 189: if (last) { ! 190: if (last->inp_flags & INP_CONTROLOPTS || ! 191: last->inp_socket->so_options & SO_TIMESTAMP) ! 192: ip_savecontrol(last, &opts, ip, m); ! 193: if (last->inp_flags & INP_STRIPHDR) { ! 194: m->m_len -= iphlen; ! 195: m->m_pkthdr.len -= iphlen; ! 196: m->m_data += iphlen; ! 197: } ! 198: if (sbappendaddr(&last->inp_socket->so_rcv, ! 199: (struct sockaddr *)&ripsrc, m, opts) == 0) { ! 200: kprintf("rip_input(2) can't append to socket\n"); ! 201: m_freem(m); ! 202: if (opts) ! 203: m_freem(opts); ! 204: } else { ! 205: /* kprintf("rip_input calling sorwakeup\n"); */ ! 206: sorwakeup(last->inp_socket); ! 207: } ! 208: } else { ! 209: m_freem(m); ! 210: ipstat.ips_noproto++; ! 211: ipstat.ips_delivered--; ! 212: } ! 213: } ! 214: ! 215: /* ! 216: * Generate IP header and pass packet to ip_output. ! 217: * Tack on options user may have setup with control call. ! 218: */ ! 219: int ! 220: rip_output(m, so, dst) ! 221: register struct mbuf *m; ! 222: struct socket *so; ! 223: u_long dst; ! 224: { ! 225: register struct ip *ip; ! 226: register struct inpcb *inp = sotoinpcb(so); ! 227: int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; ! 228: ! 229: /* ! 230: * If the user handed us a complete IP packet, use it. ! 231: * Otherwise, allocate an mbuf for a header and fill it in. ! 232: */ ! 233: if ((inp->inp_flags & INP_HDRINCL) == 0) { ! 234: if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { ! 235: m_freem(m); ! 236: return(EMSGSIZE); ! 237: } ! 238: M_PREPEND(m, sizeof(struct ip), M_WAIT); ! 239: ip = mtod(m, struct ip *); ! 240: ip->ip_tos = 0; ! 241: ip->ip_off = 0; ! 242: ip->ip_p = inp->inp_ip_p; ! 243: ip->ip_len = m->m_pkthdr.len; ! 244: ip->ip_src = inp->inp_laddr; ! 245: ip->ip_dst.s_addr = dst; ! 246: ip->ip_ttl = MAXTTL; ! 247: } else { ! 248: if (m->m_pkthdr.len > IP_MAXPACKET) { ! 249: m_freem(m); ! 250: return(EMSGSIZE); ! 251: } ! 252: ip = mtod(m, struct ip *); ! 253: /* don't allow both user specified and setsockopt options, ! 254: and don't allow packet length sizes that will crash */ ! 255: if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2)) ! 256: && inp->inp_options) ! 257: || (ip->ip_len > m->m_pkthdr.len) ! 258: || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) { ! 259: m_freem(m); ! 260: return EINVAL; ! 261: } ! 262: if (ip->ip_id == 0) ! 263: ip->ip_id = htons(ip_id++); ! 264: /* XXX prevent ip_output from overwriting header fields */ ! 265: flags |= IP_RAWOUTPUT; ! 266: ipstat.ips_rawout++; ! 267: } ! 268: return (ip_output(m, inp->inp_options, &inp->inp_route, flags, ! 269: inp->inp_moptions)); ! 270: } ! 271: ! 272: /* ! 273: * Raw IP socket option processing. ! 274: */ ! 275: int ! 276: rip_ctloutput(so, sopt) ! 277: struct socket *so; ! 278: struct sockopt *sopt; ! 279: { ! 280: struct inpcb *inp = sotoinpcb(so); ! 281: int error, optval; ! 282: ! 283: if (sopt->sopt_level != IPPROTO_IP) ! 284: return (EINVAL); ! 285: ! 286: error = 0; ! 287: ! 288: switch (sopt->sopt_dir) { ! 289: case SOPT_GET: ! 290: switch (sopt->sopt_name) { ! 291: case IP_HDRINCL: ! 292: optval = inp->inp_flags & INP_HDRINCL; ! 293: error = sooptcopyout(sopt, &optval, sizeof optval); ! 294: break; ! 295: ! 296: case IP_STRIPHDR: ! 297: optval = inp->inp_flags & INP_STRIPHDR; ! 298: error = sooptcopyout(sopt, &optval, sizeof optval); ! 299: break; ! 300: ! 301: #if COMPAT_IPFW ! 302: case IP_FW_GET: ! 303: if (ip_fw_ctl_ptr == 0) ! 304: error = ENOPROTOOPT; ! 305: else ! 306: error = ip_fw_ctl_ptr(sopt); ! 307: break; ! 308: ! 309: case IP_NAT: ! 310: if (ip_nat_ctl_ptr == 0) ! 311: error = ENOPROTOOPT; ! 312: else ! 313: error = ip_nat_ctl_ptr(sopt); ! 314: break; ! 315: #if DUMMYNET ! 316: case IP_DUMMYNET_GET: ! 317: if (ip_dn_ctl_ptr == NULL) ! 318: error = ENOPROTOOPT ; ! 319: else ! 320: error = ip_dn_ctl_ptr(sopt); ! 321: break ; ! 322: #endif /* DUMMYNET */ ! 323: #endif /* COMPAT_IPFW */ ! 324: ! 325: case MRT_INIT: ! 326: case MRT_DONE: ! 327: case MRT_ADD_VIF: ! 328: case MRT_DEL_VIF: ! 329: case MRT_ADD_MFC: ! 330: case MRT_DEL_MFC: ! 331: case MRT_VERSION: ! 332: case MRT_ASSERT: ! 333: error = ip_mrouter_get(so, sopt); ! 334: break; ! 335: ! 336: default: ! 337: error = ip_ctloutput(so, sopt); ! 338: break; ! 339: } ! 340: break; ! 341: ! 342: case SOPT_SET: ! 343: switch (sopt->sopt_name) { ! 344: case IP_HDRINCL: ! 345: error = sooptcopyin(sopt, &optval, sizeof optval, ! 346: sizeof optval); ! 347: if (error) ! 348: break; ! 349: if (optval) ! 350: inp->inp_flags |= INP_HDRINCL; ! 351: else ! 352: inp->inp_flags &= ~INP_HDRINCL; ! 353: break; ! 354: ! 355: case IP_STRIPHDR: ! 356: error = sooptcopyin(sopt, &optval, sizeof optval, ! 357: sizeof optval); ! 358: if (error) ! 359: break; ! 360: if (optval) ! 361: inp->inp_flags |= INP_STRIPHDR; ! 362: else ! 363: inp->inp_flags &= ~INP_STRIPHDR; ! 364: break; ! 365: ! 366: ! 367: #if COMPAT_IPFW ! 368: case IP_FW_ADD: ! 369: case IP_FW_DEL: ! 370: case IP_FW_FLUSH: ! 371: case IP_FW_ZERO: ! 372: if (ip_fw_ctl_ptr == 0) ! 373: error = ENOPROTOOPT; ! 374: else ! 375: error = ip_fw_ctl_ptr(sopt); ! 376: break; ! 377: ! 378: case IP_NAT: ! 379: if (ip_nat_ctl_ptr == 0) ! 380: error = ENOPROTOOPT; ! 381: else ! 382: error = ip_nat_ctl_ptr(sopt); ! 383: break; ! 384: #if DUMMYNET ! 385: case IP_DUMMYNET_CONFIGURE: ! 386: case IP_DUMMYNET_DEL: ! 387: case IP_DUMMYNET_FLUSH: ! 388: if (ip_dn_ctl_ptr == NULL) ! 389: error = ENOPROTOOPT ; ! 390: else ! 391: error = ip_dn_ctl_ptr(sopt); ! 392: break ; ! 393: #endif ! 394: #endif /* COMPAT_IPFW */ ! 395: ! 396: case IP_RSVP_ON: ! 397: error = ip_rsvp_init(so); ! 398: break; ! 399: ! 400: case IP_RSVP_OFF: ! 401: error = ip_rsvp_done(); ! 402: break; ! 403: ! 404: /* XXX - should be combined */ ! 405: case IP_RSVP_VIF_ON: ! 406: error = ip_rsvp_vif_init(so, sopt); ! 407: break; ! 408: ! 409: case IP_RSVP_VIF_OFF: ! 410: error = ip_rsvp_vif_done(so, sopt); ! 411: break; ! 412: ! 413: case MRT_INIT: ! 414: case MRT_DONE: ! 415: case MRT_ADD_VIF: ! 416: case MRT_DEL_VIF: ! 417: case MRT_ADD_MFC: ! 418: case MRT_DEL_MFC: ! 419: case MRT_VERSION: ! 420: case MRT_ASSERT: ! 421: error = ip_mrouter_set(so, sopt); ! 422: break; ! 423: ! 424: default: ! 425: error = ip_ctloutput(so, sopt); ! 426: break; ! 427: } ! 428: break; ! 429: } ! 430: ! 431: return (error); ! 432: } ! 433: ! 434: /* ! 435: * This function exists solely to receive the PRC_IFDOWN messages which ! 436: * are sent by if_down(). It looks for an ifaddr whose ifa_addr is sa, ! 437: * and calls in_ifadown() to remove all routes corresponding to that address. ! 438: * It also receives the PRC_IFUP messages from if_up() and reinstalls the ! 439: * interface routes. ! 440: */ ! 441: void ! 442: rip_ctlinput(cmd, sa, vip) ! 443: int cmd; ! 444: struct sockaddr *sa; ! 445: void *vip; ! 446: { ! 447: struct in_ifaddr *ia; ! 448: struct ifnet *ifp; ! 449: int err; ! 450: int flags; ! 451: ! 452: switch (cmd) { ! 453: case PRC_IFDOWN: ! 454: for (ia = in_ifaddrhead.tqh_first; ia; ! 455: ia = ia->ia_link.tqe_next) { ! 456: if (ia->ia_ifa.ifa_addr == sa ! 457: && (ia->ia_flags & IFA_ROUTE)) { ! 458: /* ! 459: * in_ifscrub kills the interface route. ! 460: */ ! 461: in_ifscrub(ia->ia_ifp, ia); ! 462: /* ! 463: * in_ifadown gets rid of all the rest of ! 464: * the routes. This is not quite the right ! 465: * thing to do, but at least if we are running ! 466: * a routing process they will come back. ! 467: */ ! 468: in_ifadown(&ia->ia_ifa); ! 469: break; ! 470: } ! 471: } ! 472: break; ! 473: ! 474: case PRC_IFUP: ! 475: for (ia = in_ifaddrhead.tqh_first; ia; ! 476: ia = ia->ia_link.tqe_next) { ! 477: if (ia->ia_ifa.ifa_addr == sa) ! 478: break; ! 479: } ! 480: if (ia == 0 || (ia->ia_flags & IFA_ROUTE)) ! 481: return; ! 482: flags = RTF_UP; ! 483: ifp = ia->ia_ifa.ifa_ifp; ! 484: ! 485: if ((ifp->if_flags & IFF_LOOPBACK) ! 486: || (ifp->if_flags & IFF_POINTOPOINT)) ! 487: flags |= RTF_HOST; ! 488: ! 489: err = rtinit(&ia->ia_ifa, RTM_ADD, flags); ! 490: if (err == 0) ! 491: ia->ia_flags |= IFA_ROUTE; ! 492: break; ! 493: } ! 494: } ! 495: ! 496: static u_long rip_sendspace = RIPSNDQ; ! 497: static u_long rip_recvspace = RIPRCVQ; ! 498: ! 499: ! 500: SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW, &rip_sendspace, ! 501: 0, ""); ! 502: SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW, &rip_recvspace, ! 503: 0, ""); ! 504: ! 505: static int ! 506: rip_attach(struct socket *so, int proto, struct proc *p) ! 507: { ! 508: struct inpcb *inp; ! 509: int error, s; ! 510: ! 511: inp = sotoinpcb(so); ! 512: if (inp) ! 513: panic("rip_attach"); ! 514: ! 515: ! 516: #if ISFB31 ! 517: if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0) ! 518: return error; ! 519: #else ! 520: if ((so->so_state & SS_PRIV) == 0) ! 521: return (EPERM); ! 522: #endif ! 523: ! 524: s = splnet(); ! 525: error = in_pcballoc(so, &ripcbinfo, p); ! 526: splx(s); ! 527: if (error) ! 528: return error; ! 529: error = soreserve(so, rip_sendspace, rip_recvspace); ! 530: if (error) ! 531: return error; ! 532: inp = (struct inpcb *)so->so_pcb; ! 533: inp->inp_ip_p = proto; ! 534: return 0; ! 535: } ! 536: ! 537: static int ! 538: rip_detach(struct socket *so) ! 539: { ! 540: struct inpcb *inp; ! 541: ! 542: inp = sotoinpcb(so); ! 543: if (inp == 0) ! 544: panic("rip_detach"); ! 545: if (so == ip_mrouter) ! 546: ip_mrouter_done(); ! 547: ip_rsvp_force_done(so); ! 548: if (so == ip_rsvpd) ! 549: ip_rsvp_done(); ! 550: in_pcbdetach(inp); ! 551: return 0; ! 552: } ! 553: ! 554: static int ! 555: rip_abort(struct socket *so) ! 556: { ! 557: soisdisconnected(so); ! 558: return rip_detach(so); ! 559: } ! 560: ! 561: static int ! 562: rip_disconnect(struct socket *so) ! 563: { ! 564: if ((so->so_state & SS_ISCONNECTED) == 0) ! 565: return ENOTCONN; ! 566: return rip_abort(so); ! 567: } ! 568: ! 569: static int ! 570: rip_bind(struct socket *so, struct sockaddr *nam, struct proc *p) ! 571: { ! 572: struct inpcb *inp = sotoinpcb(so); ! 573: struct sockaddr_in *addr = (struct sockaddr_in *)nam; ! 574: ! 575: if (nam->sa_len != sizeof(*addr)) ! 576: return EINVAL; ! 577: ! 578: if (TAILQ_EMPTY(&ifnet) || ((addr->sin_family != AF_INET) && ! 579: (addr->sin_family != AF_IMPLINK)) || ! 580: (addr->sin_addr.s_addr && ! 581: ifa_ifwithaddr((struct sockaddr *)addr) == 0)) ! 582: return EADDRNOTAVAIL; ! 583: inp->inp_laddr = addr->sin_addr; ! 584: return 0; ! 585: } ! 586: ! 587: static int ! 588: rip_connect(struct socket *so, struct sockaddr *nam, struct proc *p) ! 589: { ! 590: struct inpcb *inp = sotoinpcb(so); ! 591: struct sockaddr_in *addr = (struct sockaddr_in *)nam; ! 592: ! 593: if (nam->sa_len != sizeof(*addr)) ! 594: return EINVAL; ! 595: if (TAILQ_EMPTY(&ifnet)) ! 596: return EADDRNOTAVAIL; ! 597: if ((addr->sin_family != AF_INET) && ! 598: (addr->sin_family != AF_IMPLINK)) ! 599: return EAFNOSUPPORT; ! 600: inp->inp_faddr = addr->sin_addr; ! 601: soisconnected(so); ! 602: return 0; ! 603: } ! 604: ! 605: static int ! 606: rip_shutdown(struct socket *so) ! 607: { ! 608: socantsendmore(so); ! 609: return 0; ! 610: } ! 611: ! 612: static int ! 613: rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, ! 614: struct mbuf *control, struct proc *p) ! 615: { ! 616: struct inpcb *inp = sotoinpcb(so); ! 617: register u_long dst; ! 618: ! 619: if (so->so_state & SS_ISCONNECTED) { ! 620: if (nam) { ! 621: m_freem(m); ! 622: return EISCONN; ! 623: } ! 624: dst = inp->inp_faddr.s_addr; ! 625: } else { ! 626: if (nam == NULL) { ! 627: m_freem(m); ! 628: return ENOTCONN; ! 629: } ! 630: dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; ! 631: } ! 632: return rip_output(m, so, dst); ! 633: } ! 634: ! 635: ! 636: static int ! 637: rip_pcblist SYSCTL_HANDLER_ARGS ! 638: { ! 639: int error, i, n, s; ! 640: struct inpcb *inp, **inp_list; ! 641: inp_gen_t gencnt; ! 642: struct xinpgen xig; ! 643: ! 644: /* ! 645: * The process of preparing the TCB list is too time-consuming and ! 646: * resource-intensive to repeat twice on every request. ! 647: */ ! 648: if (req->oldptr == 0) { ! 649: n = ripcbinfo.ipi_count; ! 650: req->oldidx = 2 * (sizeof xig) ! 651: + (n + n/8) * sizeof(struct xinpcb); ! 652: return 0; ! 653: } ! 654: ! 655: if (req->newptr != 0) ! 656: return EPERM; ! 657: ! 658: /* ! 659: * OK, now we're committed to doing something. ! 660: */ ! 661: s = splnet(); ! 662: gencnt = ripcbinfo.ipi_gencnt; ! 663: n = ripcbinfo.ipi_count; ! 664: splx(s); ! 665: ! 666: xig.xig_len = sizeof xig; ! 667: xig.xig_count = n; ! 668: xig.xig_gen = gencnt; ! 669: xig.xig_sogen = so_gencnt; ! 670: error = SYSCTL_OUT(req, &xig, sizeof xig); ! 671: if (error) ! 672: return error; ! 673: ! 674: inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK); ! 675: if (inp_list == 0) ! 676: return ENOMEM; ! 677: ! 678: s = splnet(); ! 679: for (inp = ripcbinfo.listhead->lh_first, i = 0; inp && i < n; ! 680: inp = inp->inp_list.le_next) { ! 681: if (inp->inp_gencnt <= gencnt) ! 682: inp_list[i++] = inp; ! 683: } ! 684: splx(s); ! 685: n = i; ! 686: ! 687: error = 0; ! 688: for (i = 0; i < n; i++) { ! 689: inp = inp_list[i]; ! 690: if (inp->inp_gencnt <= gencnt) { ! 691: struct xinpcb xi; ! 692: xi.xi_len = sizeof xi; ! 693: /* XXX should avoid extra copy */ ! 694: bcopy(inp, &xi.xi_inp, sizeof *inp); ! 695: if (inp->inp_socket) ! 696: sotoxsocket(inp->inp_socket, &xi.xi_socket); ! 697: error = SYSCTL_OUT(req, &xi, sizeof xi); ! 698: } ! 699: } ! 700: if (!error) { ! 701: /* ! 702: * Give the user an updated idea of our state. ! 703: * If the generation differs from what we told ! 704: * her before, she knows that something happened ! 705: * while we were processing this request, and it ! 706: * might be necessary to retry. ! 707: */ ! 708: s = splnet(); ! 709: xig.xig_gen = ripcbinfo.ipi_gencnt; ! 710: xig.xig_sogen = so_gencnt; ! 711: xig.xig_count = ripcbinfo.ipi_count; ! 712: splx(s); ! 713: error = SYSCTL_OUT(req, &xig, sizeof xig); ! 714: } ! 715: FREE(inp_list, M_TEMP); ! 716: return error; ! 717: } ! 718: ! 719: ! 720: SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, 0, 0, ! 721: rip_pcblist, "S,xinpcb", "List of active raw IP sockets"); ! 722: ! 723: struct pr_usrreqs rip_usrreqs = { ! 724: rip_abort, pru_accept_notsupp, rip_attach, rip_bind, rip_connect, ! 725: pru_connect2_notsupp, in_control, rip_detach, rip_disconnect, ! 726: pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp, ! 727: pru_rcvoob_notsupp, rip_send, pru_sense_null, rip_shutdown, ! 728: in_setsockaddr, sosend, soreceive, sopoll ! 729: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.