Annotation of src/sys/netinet/raw_ip.c, Revision 1.1.1.2
1.1 cgd 1: /*
1.1.1.2 ! thorpej 2: * Copyright (c) 1982, 1986, 1988, 1993
! 3: * The Regents of the University of California. All rights reserved.
1.1 cgd 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: *
1.1.1.2 ! thorpej 33: * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
1.1 cgd 34: */
35:
1.1.1.2 ! thorpej 36: #include <sys/param.h>
! 37: #include <sys/malloc.h>
! 38: #include <sys/mbuf.h>
! 39: #include <sys/socket.h>
! 40: #include <sys/protosw.h>
! 41: #include <sys/socketvar.h>
! 42: #include <sys/errno.h>
! 43: #include <sys/systm.h>
! 44:
! 45: #include <net/if.h>
! 46: #include <net/route.h>
! 47:
! 48: #include <netinet/in.h>
! 49: #include <netinet/in_systm.h>
! 50: #include <netinet/ip.h>
! 51: #include <netinet/ip_var.h>
! 52: #include <netinet/ip_mroute.h>
! 53: #include <netinet/in_pcb.h>
! 54:
! 55: struct inpcb rawinpcb;
! 56:
! 57: /*
! 58: * Nominal space allocated to a raw ip socket.
! 59: */
! 60: #define RIPSNDQ 8192
! 61: #define RIPRCVQ 8192
1.1 cgd 62:
63: /*
64: * Raw interface to IP protocol.
65: */
66:
1.1.1.2 ! thorpej 67: /*
! 68: * Initialize raw connection block q.
! 69: */
! 70: void
! 71: rip_init()
! 72: {
! 73:
! 74: rawinpcb.inp_next = rawinpcb.inp_prev = &rawinpcb;
! 75: }
! 76:
1.1 cgd 77: struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
78: /*
79: * Setup generic address and protocol structures
80: * for raw_input routine, then pass them along with
81: * mbuf chain.
82: */
1.1.1.2 ! thorpej 83: void
1.1 cgd 84: rip_input(m)
85: struct mbuf *m;
86: {
87: register struct ip *ip = mtod(m, struct ip *);
1.1.1.2 ! thorpej 88: register struct inpcb *inp;
! 89: struct socket *last = 0;
1.1 cgd 90:
91: ripsrc.sin_addr = ip->ip_src;
1.1.1.2 ! thorpej 92: for (inp = rawinpcb.inp_next; inp != &rawinpcb; inp = inp->inp_next) {
! 93: if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p)
! 94: continue;
! 95: if (inp->inp_laddr.s_addr &&
! 96: inp->inp_laddr.s_addr == ip->ip_dst.s_addr)
! 97: continue;
! 98: if (inp->inp_faddr.s_addr &&
! 99: inp->inp_faddr.s_addr == ip->ip_src.s_addr)
! 100: continue;
! 101: if (last) {
! 102: struct mbuf *n;
! 103: if (n = m_copy(m, 0, (int)M_COPYALL)) {
! 104: if (sbappendaddr(&last->so_rcv, &ripsrc,
! 105: n, (struct mbuf *)0) == 0)
! 106: /* should notify about lost packet */
! 107: m_freem(n);
! 108: else
! 109: sorwakeup(last);
! 110: }
! 111: }
! 112: last = inp->inp_socket;
! 113: }
! 114: if (last) {
! 115: if (sbappendaddr(&last->so_rcv, &ripsrc,
! 116: m, (struct mbuf *)0) == 0)
! 117: m_freem(m);
! 118: else
! 119: sorwakeup(last);
! 120: } else {
! 121: m_freem(m);
1.1 cgd 122: ipstat.ips_noproto++;
123: ipstat.ips_delivered--;
124: }
125: }
126:
127: /*
128: * Generate IP header and pass packet to ip_output.
129: * Tack on options user may have setup with control call.
130: */
1.1.1.2 ! thorpej 131: int
! 132: rip_output(m, so, dst)
1.1 cgd 133: register struct mbuf *m;
134: struct socket *so;
1.1.1.2 ! thorpej 135: u_long dst;
1.1 cgd 136: {
137: register struct ip *ip;
1.1.1.2 ! thorpej 138: register struct inpcb *inp = sotoinpcb(so);
! 139: struct mbuf *opts;
! 140: int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
1.1 cgd 141:
142: /*
143: * If the user handed us a complete IP packet, use it.
144: * Otherwise, allocate an mbuf for a header and fill it in.
145: */
1.1.1.2 ! thorpej 146: if ((inp->inp_flags & INP_HDRINCL) == 0) {
1.1 cgd 147: M_PREPEND(m, sizeof(struct ip), M_WAIT);
148: ip = mtod(m, struct ip *);
149: ip->ip_tos = 0;
150: ip->ip_off = 0;
1.1.1.2 ! thorpej 151: ip->ip_p = inp->inp_ip.ip_p;
1.1 cgd 152: ip->ip_len = m->m_pkthdr.len;
1.1.1.2 ! thorpej 153: ip->ip_src = inp->inp_laddr;
! 154: ip->ip_dst.s_addr = dst;
1.1 cgd 155: ip->ip_ttl = MAXTTL;
1.1.1.2 ! thorpej 156: opts = inp->inp_options;
! 157: } else {
! 158: ip = mtod(m, struct ip *);
! 159: if (ip->ip_id == 0)
! 160: ip->ip_id = htons(ip_id++);
! 161: opts = NULL;
! 162: /* XXX prevent ip_output from overwriting header fields */
! 163: flags |= IP_RAWOUTPUT;
! 164: ipstat.ips_rawout++;
1.1 cgd 165: }
1.1.1.2 ! thorpej 166: return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions));
1.1 cgd 167: }
168:
169: /*
170: * Raw IP socket option processing.
171: */
1.1.1.2 ! thorpej 172: int
1.1 cgd 173: rip_ctloutput(op, so, level, optname, m)
174: int op;
175: struct socket *so;
176: int level, optname;
177: struct mbuf **m;
178: {
1.1.1.2 ! thorpej 179: register struct inpcb *inp = sotoinpcb(so);
! 180: register int error;
1.1 cgd 181:
182: if (level != IPPROTO_IP)
1.1.1.2 ! thorpej 183: return (EINVAL);
1.1 cgd 184:
1.1.1.2 ! thorpej 185: switch (optname) {
1.1 cgd 186:
1.1.1.2 ! thorpej 187: case IP_HDRINCL:
! 188: if (op == PRCO_SETOPT || op == PRCO_GETOPT) {
! 189: if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int))
! 190: return (EINVAL);
! 191: if (op == PRCO_SETOPT) {
! 192: if (*mtod(*m, int *))
! 193: inp->inp_flags |= INP_HDRINCL;
! 194: else
! 195: inp->inp_flags &= ~INP_HDRINCL;
! 196: (void)m_free(*m);
! 197: } else {
! 198: (*m)->m_len = sizeof (int);
! 199: *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
1.1 cgd 200: }
1.1.1.2 ! thorpej 201: return (0);
1.1 cgd 202: }
203: break;
204:
1.1.1.2 ! thorpej 205: case DVMRP_INIT:
! 206: case DVMRP_DONE:
! 207: case DVMRP_ADD_VIF:
! 208: case DVMRP_DEL_VIF:
! 209: case DVMRP_ADD_LGRP:
! 210: case DVMRP_DEL_LGRP:
! 211: case DVMRP_ADD_MRT:
! 212: case DVMRP_DEL_MRT:
! 213: #ifdef MROUTING
! 214: if (op == PRCO_SETOPT) {
! 215: error = ip_mrouter_cmd(optname, so, *m);
! 216: if (*m)
! 217: (void)m_free(*m);
! 218: } else
1.1 cgd 219: error = EINVAL;
1.1.1.2 ! thorpej 220: return (error);
! 221: #else
! 222: if (op == PRCO_SETOPT && *m)
! 223: (void)m_free(*m);
! 224: return (EOPNOTSUPP);
! 225: #endif
1.1 cgd 226: }
1.1.1.2 ! thorpej 227: return (ip_ctloutput(op, so, level, optname, m));
1.1 cgd 228: }
229:
1.1.1.2 ! thorpej 230: u_long rip_sendspace = RIPSNDQ;
! 231: u_long rip_recvspace = RIPRCVQ;
! 232:
1.1 cgd 233: /*ARGSUSED*/
1.1.1.2 ! thorpej 234: int
! 235: rip_usrreq(so, req, m, nam, control)
1.1 cgd 236: register struct socket *so;
237: int req;
1.1.1.2 ! thorpej 238: struct mbuf *m, *nam, *control;
1.1 cgd 239: {
240: register int error = 0;
1.1.1.2 ! thorpej 241: register struct inpcb *inp = sotoinpcb(so);
! 242: #ifdef MROUTING
! 243: extern struct socket *ip_mrouter;
! 244: #endif
1.1 cgd 245: switch (req) {
246:
247: case PRU_ATTACH:
1.1.1.2 ! thorpej 248: if (inp)
1.1 cgd 249: panic("rip_attach");
1.1.1.2 ! thorpej 250: if ((so->so_state & SS_PRIV) == 0) {
! 251: error = EACCES;
! 252: break;
! 253: }
! 254: if ((error = soreserve(so, rip_sendspace, rip_recvspace)) ||
! 255: (error = in_pcballoc(so, &rawinpcb)))
! 256: break;
! 257: inp = (struct inpcb *)so->so_pcb;
! 258: inp->inp_ip.ip_p = (int)nam;
1.1 cgd 259: break;
260:
1.1.1.2 ! thorpej 261: case PRU_DISCONNECT:
! 262: if ((so->so_state & SS_ISCONNECTED) == 0) {
! 263: error = ENOTCONN;
! 264: break;
! 265: }
! 266: /* FALLTHROUGH */
! 267: case PRU_ABORT:
! 268: soisdisconnected(so);
! 269: /* FALLTHROUGH */
1.1 cgd 270: case PRU_DETACH:
1.1.1.2 ! thorpej 271: if (inp == 0)
1.1 cgd 272: panic("rip_detach");
1.1.1.2 ! thorpej 273: #ifdef MROUTING
! 274: if (so == ip_mrouter)
! 275: ip_mrouter_done();
! 276: #endif
! 277: in_pcbdetach(inp);
1.1 cgd 278: break;
279:
280: case PRU_BIND:
281: {
282: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
283:
1.1.1.2 ! thorpej 284: if (nam->m_len != sizeof(*addr)) {
! 285: error = EINVAL;
! 286: break;
! 287: }
1.1 cgd 288: if ((ifnet == 0) ||
289: ((addr->sin_family != AF_INET) &&
290: (addr->sin_family != AF_IMPLINK)) ||
291: (addr->sin_addr.s_addr &&
1.1.1.2 ! thorpej 292: ifa_ifwithaddr((struct sockaddr *)addr) == 0)) {
! 293: error = EADDRNOTAVAIL;
! 294: break;
! 295: }
! 296: inp->inp_laddr = addr->sin_addr;
! 297: break;
1.1 cgd 298: }
299: case PRU_CONNECT:
300: {
301: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
302:
1.1.1.2 ! thorpej 303: if (nam->m_len != sizeof(*addr)) {
! 304: error = EINVAL;
! 305: break;
! 306: }
! 307: if (ifnet == 0) {
! 308: error = EADDRNOTAVAIL;
! 309: break;
! 310: }
1.1 cgd 311: if ((addr->sin_family != AF_INET) &&
1.1.1.2 ! thorpej 312: (addr->sin_family != AF_IMPLINK)) {
! 313: error = EAFNOSUPPORT;
! 314: break;
! 315: }
! 316: inp->inp_faddr = addr->sin_addr;
1.1 cgd 317: soisconnected(so);
1.1.1.2 ! thorpej 318: break;
1.1 cgd 319: }
320:
1.1.1.2 ! thorpej 321: case PRU_CONNECT2:
! 322: error = EOPNOTSUPP;
! 323: break;
! 324:
! 325: /*
! 326: * Mark the connection as being incapable of further input.
! 327: */
! 328: case PRU_SHUTDOWN:
! 329: socantsendmore(so);
! 330: break;
! 331:
! 332: /*
! 333: * Ship a packet out. The appropriate raw output
! 334: * routine handles any massaging necessary.
! 335: */
! 336: case PRU_SEND:
! 337: {
! 338: register u_long dst;
! 339:
! 340: if (so->so_state & SS_ISCONNECTED) {
! 341: if (nam) {
! 342: error = EISCONN;
! 343: break;
! 344: }
! 345: dst = inp->inp_faddr.s_addr;
! 346: } else {
! 347: if (nam == NULL) {
! 348: error = ENOTCONN;
! 349: break;
! 350: }
! 351: dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
! 352: }
! 353: error = rip_output(m, so, dst);
! 354: m = NULL;
! 355: break;
! 356: }
! 357:
! 358: case PRU_SENSE:
! 359: /*
! 360: * stat: don't bother with a blocksize.
! 361: */
! 362: return (0);
! 363:
! 364: /*
! 365: * Not supported.
! 366: */
! 367: case PRU_RCVOOB:
! 368: case PRU_RCVD:
! 369: case PRU_LISTEN:
! 370: case PRU_ACCEPT:
! 371: case PRU_SENDOOB:
! 372: error = EOPNOTSUPP;
! 373: break;
! 374:
! 375: case PRU_SOCKADDR:
! 376: in_setsockaddr(inp, nam);
! 377: break;
! 378:
! 379: case PRU_PEERADDR:
! 380: in_setpeeraddr(inp, nam);
! 381: break;
! 382:
! 383: default:
! 384: panic("rip_usrreq");
! 385: }
! 386: if (m != NULL)
! 387: m_freem(m);
1.1 cgd 388: return (error);
389: }
CVSweb <webmaster@jp.NetBSD.org>