|
|
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: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1982, 1986, 1988, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 ! 59: */ ! 60: ! 61: #include <sys/param.h> ! 62: #include <sys/malloc.h> ! 63: #include <sys/mbuf.h> ! 64: #include <sys/socket.h> ! 65: #include <sys/protosw.h> ! 66: #include <sys/socketvar.h> ! 67: #include <sys/errno.h> ! 68: #include <sys/systm.h> ! 69: ! 70: #include <net/if.h> ! 71: #include <net/route.h> ! 72: ! 73: #include <netinet/in.h> ! 74: #include <netinet/in_systm.h> ! 75: #include <netinet/ip.h> ! 76: #include <netinet/ip_var.h> ! 77: #include <netinet/ip_mroute.h> ! 78: #include <netinet/in_pcb.h> ! 79: ! 80: struct inpcb rawinpcb; ! 81: ! 82: /* ! 83: * Nominal space allocated to a raw ip socket. ! 84: */ ! 85: #define RIPSNDQ 8192 ! 86: #define RIPRCVQ 8192 ! 87: ! 88: /* ! 89: * Raw interface to IP protocol. ! 90: */ ! 91: ! 92: /* ! 93: * Initialize raw connection block q. ! 94: */ ! 95: void ! 96: rip_init() ! 97: { ! 98: ! 99: rawinpcb.inp_next = rawinpcb.inp_prev = &rawinpcb; ! 100: } ! 101: ! 102: struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; ! 103: /* ! 104: * Setup generic address and protocol structures ! 105: * for raw_input routine, then pass them along with ! 106: * mbuf chain. ! 107: */ ! 108: void ! 109: rip_input(m) ! 110: struct mbuf *m; ! 111: { ! 112: register struct ip *ip = mtod(m, struct ip *); ! 113: register struct inpcb *inp; ! 114: struct socket *last = 0; ! 115: ! 116: ripsrc.sin_addr = ip->ip_src; ! 117: for (inp = rawinpcb.inp_next; inp != &rawinpcb; inp = inp->inp_next) { ! 118: if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) ! 119: continue; ! 120: if (inp->inp_laddr.s_addr && ! 121: inp->inp_laddr.s_addr != ip->ip_dst.s_addr) ! 122: continue; ! 123: if (inp->inp_faddr.s_addr && ! 124: inp->inp_faddr.s_addr != ip->ip_src.s_addr) ! 125: continue; ! 126: if (last) { ! 127: struct mbuf *n; ! 128: if (n = m_copy(m, 0, (int)M_COPYALL)) { ! 129: if (sbappendaddr(&last->so_rcv, ! 130: (struct sockaddr *)&ripsrc, n, ! 131: (struct mbuf *)0) == 0) ! 132: /* should notify about lost packet */ ! 133: m_freem(n); ! 134: else ! 135: sorwakeup(last); ! 136: } ! 137: } ! 138: last = inp->inp_socket; ! 139: } ! 140: if (last) { ! 141: if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&ripsrc, ! 142: m, (struct mbuf *)0) == 0) ! 143: m_freem(m); ! 144: else ! 145: sorwakeup(last); ! 146: } else { ! 147: m_freem(m); ! 148: ipstat.ips_noproto++; ! 149: ipstat.ips_delivered--; ! 150: } ! 151: } ! 152: ! 153: /* ! 154: * Generate IP header and pass packet to ip_output. ! 155: * Tack on options user may have setup with control call. ! 156: */ ! 157: int ! 158: rip_output(m, so, dst) ! 159: register struct mbuf *m; ! 160: struct socket *so; ! 161: u_long dst; ! 162: { ! 163: register struct ip *ip; ! 164: register struct inpcb *inp = sotoinpcb(so); ! 165: struct mbuf *opts; ! 166: int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; ! 167: ! 168: /* ! 169: * If the user handed us a complete IP packet, use it. ! 170: * Otherwise, allocate an mbuf for a header and fill it in. ! 171: */ ! 172: if ((inp->inp_flags & INP_HDRINCL) == 0) { ! 173: M_PREPEND(m, sizeof(struct ip), M_WAIT); ! 174: ip = mtod(m, struct ip *); ! 175: ip->ip_tos = 0; ! 176: ip->ip_off = 0; ! 177: ip->ip_p = inp->inp_ip.ip_p; ! 178: ip->ip_len = m->m_pkthdr.len; ! 179: ip->ip_src = inp->inp_laddr; ! 180: ip->ip_dst.s_addr = dst; ! 181: ip->ip_ttl = MAXTTL; ! 182: opts = inp->inp_options; ! 183: } else { ! 184: ip = mtod(m, struct ip *); ! 185: if (ip->ip_id == 0) ! 186: ip->ip_id = htons(ip_id++); ! 187: opts = NULL; ! 188: /* XXX prevent ip_output from overwriting header fields */ ! 189: flags |= IP_RAWOUTPUT; ! 190: ipstat.ips_rawout++; ! 191: } ! 192: return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions)); ! 193: } ! 194: ! 195: /* ! 196: * Raw IP socket option processing. ! 197: */ ! 198: int ! 199: rip_ctloutput(op, so, level, optname, m) ! 200: int op; ! 201: struct socket *so; ! 202: int level, optname; ! 203: struct mbuf **m; ! 204: { ! 205: register struct inpcb *inp = sotoinpcb(so); ! 206: register int error; ! 207: ! 208: if (level != IPPROTO_IP) { ! 209: if (op == PRCO_SETOPT && *m) ! 210: (void) m_free(*m); ! 211: return (EINVAL); ! 212: } ! 213: ! 214: switch (optname) { ! 215: ! 216: case IP_HDRINCL: ! 217: error = 0; ! 218: if (op == PRCO_SETOPT) { ! 219: if (*m == 0 || (*m)->m_len < sizeof (int)) ! 220: error = EINVAL; ! 221: else if (*mtod(*m, int *)) ! 222: inp->inp_flags |= INP_HDRINCL; ! 223: else ! 224: inp->inp_flags &= ~INP_HDRINCL; ! 225: if (*m) ! 226: (void)m_free(*m); ! 227: } else { ! 228: *m = m_get(M_WAIT, MT_SOOPTS); ! 229: (*m)->m_len = sizeof (int); ! 230: *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL; ! 231: } ! 232: return (error); ! 233: ! 234: case DVMRP_INIT: ! 235: case DVMRP_DONE: ! 236: case DVMRP_ADD_VIF: ! 237: case DVMRP_DEL_VIF: ! 238: case DVMRP_ADD_LGRP: ! 239: case DVMRP_DEL_LGRP: ! 240: case DVMRP_ADD_MRT: ! 241: case DVMRP_DEL_MRT: ! 242: #if MROUTING ! 243: if (op == PRCO_SETOPT) { ! 244: error = ip_mrouter_cmd(optname, so, *m); ! 245: if (*m) ! 246: (void)m_free(*m); ! 247: } else ! 248: error = EINVAL; ! 249: return (error); ! 250: #else ! 251: if (op == PRCO_SETOPT && *m) ! 252: (void)m_free(*m); ! 253: return (EOPNOTSUPP); ! 254: #endif ! 255: ! 256: default: ! 257: if (optname >= DVMRP_INIT) { ! 258: #if MROUTING ! 259: if (op == PRCO_SETOPT) { ! 260: error = ip_mrouter_cmd(optname, so, *m); ! 261: if (*m) ! 262: (void)m_free(*m); ! 263: } else ! 264: error = EINVAL; ! 265: return (error); ! 266: #else ! 267: if (op == PRCO_SETOPT && *m) ! 268: (void)m_free(*m); ! 269: return (EOPNOTSUPP); ! 270: #endif ! 271: } ! 272: ! 273: } ! 274: return (ip_ctloutput(op, so, level, optname, m)); ! 275: } ! 276: ! 277: u_long rip_sendspace = RIPSNDQ; ! 278: u_long rip_recvspace = RIPRCVQ; ! 279: ! 280: /*ARGSUSED*/ ! 281: int ! 282: rip_usrreq(so, req, m, nam, control) ! 283: register struct socket *so; ! 284: int req; ! 285: struct mbuf *m, *nam, *control; ! 286: { ! 287: register int error = 0; ! 288: register struct inpcb *inp = sotoinpcb(so); ! 289: #if MROUTING ! 290: extern struct socket *ip_mrouter; ! 291: #endif ! 292: switch (req) { ! 293: ! 294: case PRU_ATTACH: ! 295: if (inp) ! 296: panic("rip_attach"); ! 297: if ((so->so_state & SS_PRIV) == 0) { ! 298: error = EACCES; ! 299: break; ! 300: } ! 301: if ((error = soreserve(so, rip_sendspace, rip_recvspace)) || ! 302: (error = in_pcballoc(so, &rawinpcb, 0, 0))) ! 303: break; ! 304: inp = (struct inpcb *)so->so_pcb; ! 305: inp->inp_ip.ip_p = (int)nam; ! 306: break; ! 307: ! 308: case PRU_DISCONNECT: ! 309: if ((so->so_state & SS_ISCONNECTED) == 0) { ! 310: error = ENOTCONN; ! 311: break; ! 312: } ! 313: /* FALLTHROUGH */ ! 314: case PRU_ABORT: ! 315: soisdisconnected(so); ! 316: /* FALLTHROUGH */ ! 317: case PRU_DETACH: ! 318: if (inp == 0) ! 319: panic("rip_detach"); ! 320: #if MROUTING ! 321: if (so == ip_mrouter) ! 322: ip_mrouter_done(); ! 323: #endif ! 324: in_pcbdetach(inp); ! 325: break; ! 326: ! 327: case PRU_BIND: ! 328: { ! 329: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); ! 330: ! 331: if (nam->m_len != sizeof(*addr)) { ! 332: error = EINVAL; ! 333: break; ! 334: } ! 335: if ((ifnet == 0) || ! 336: ((addr->sin_family != AF_INET) && ! 337: (addr->sin_family != AF_IMPLINK)) || ! 338: (addr->sin_addr.s_addr && ! 339: ifa_ifwithaddr((struct sockaddr *)addr) == 0)) { ! 340: error = EADDRNOTAVAIL; ! 341: break; ! 342: } ! 343: inp->inp_laddr = addr->sin_addr; ! 344: break; ! 345: } ! 346: case PRU_CONNECT: ! 347: { ! 348: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); ! 349: ! 350: if (nam->m_len != sizeof(*addr)) { ! 351: error = EINVAL; ! 352: break; ! 353: } ! 354: if (ifnet == 0) { ! 355: error = EADDRNOTAVAIL; ! 356: break; ! 357: } ! 358: if ((addr->sin_family != AF_INET) && ! 359: (addr->sin_family != AF_IMPLINK)) { ! 360: error = EAFNOSUPPORT; ! 361: break; ! 362: } ! 363: inp->inp_faddr = addr->sin_addr; ! 364: soisconnected(so); ! 365: break; ! 366: } ! 367: ! 368: case PRU_CONNECT2: ! 369: error = EOPNOTSUPP; ! 370: break; ! 371: ! 372: /* ! 373: * Mark the connection as being incapable of further input. ! 374: */ ! 375: case PRU_SHUTDOWN: ! 376: socantsendmore(so); ! 377: break; ! 378: ! 379: /* ! 380: * Ship a packet out. The appropriate raw output ! 381: * routine handles any massaging necessary. ! 382: */ ! 383: case PRU_SEND: ! 384: { ! 385: register u_long dst; ! 386: ! 387: if (so->so_state & SS_ISCONNECTED) { ! 388: if (nam) { ! 389: error = EISCONN; ! 390: break; ! 391: } ! 392: dst = inp->inp_faddr.s_addr; ! 393: } else { ! 394: if (nam == NULL) { ! 395: error = ENOTCONN; ! 396: break; ! 397: } ! 398: dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr; ! 399: } ! 400: error = rip_output(m, so, dst); ! 401: m = NULL; ! 402: break; ! 403: } ! 404: ! 405: case PRU_SENSE: ! 406: /* ! 407: * stat: don't bother with a blocksize. ! 408: */ ! 409: return (0); ! 410: ! 411: /* ! 412: * Not supported. ! 413: */ ! 414: case PRU_RCVOOB: ! 415: case PRU_RCVD: ! 416: case PRU_LISTEN: ! 417: case PRU_ACCEPT: ! 418: case PRU_SENDOOB: ! 419: error = EOPNOTSUPP; ! 420: break; ! 421: ! 422: case PRU_SOCKADDR: ! 423: in_setsockaddr(inp, nam); ! 424: break; ! 425: ! 426: case PRU_PEERADDR: ! 427: in_setpeeraddr(inp, nam); ! 428: break; ! 429: ! 430: default: ! 431: panic("rip_usrreq"); ! 432: } ! 433: if (m != NULL) ! 434: m_freem(m); ! 435: return (error); ! 436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.