Annotation of src/sys/netinet/raw_ip.c, Revision 1.42.6.2
1.42.6.2! itojun 1: /* $NetBSD: raw_ip.c,v 1.42.6.1 1999/06/28 06:37:01 itojun Exp $ */
! 2:
! 3: /*
! 4: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. Neither the name of the project nor the names of its contributors
! 16: * may be used to endorse or promote products derived from this software
! 17: * without specific prior written permission.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 22: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 29: * SUCH DAMAGE.
! 30: */
1.14 cgd 31:
1.1 cgd 32: /*
1.13 mycroft 33: * Copyright (c) 1982, 1986, 1988, 1993
34: * The Regents of the University of California. All rights reserved.
1.1 cgd 35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: * 3. All advertising materials mentioning features or use of this software
45: * must display the following acknowledgement:
46: * This product includes software developed by the University of
47: * California, Berkeley and its contributors.
48: * 4. Neither the name of the University nor the names of its contributors
49: * may be used to endorse or promote products derived from this software
50: * without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62: * SUCH DAMAGE.
63: *
1.39 thorpej 64: * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95
1.1 cgd 65: */
1.40 scottr 66:
67: #include "opt_mrouting.h"
1.1 cgd 68:
1.7 mycroft 69: #include <sys/param.h>
70: #include <sys/malloc.h>
71: #include <sys/mbuf.h>
72: #include <sys/socket.h>
73: #include <sys/protosw.h>
74: #include <sys/socketvar.h>
75: #include <sys/errno.h>
1.13 mycroft 76: #include <sys/systm.h>
1.26 mycroft 77: #include <sys/proc.h>
1.1 cgd 78:
1.7 mycroft 79: #include <net/if.h>
80: #include <net/route.h>
1.1 cgd 81:
1.7 mycroft 82: #include <netinet/in.h>
83: #include <netinet/in_systm.h>
84: #include <netinet/ip.h>
85: #include <netinet/ip_var.h>
1.13 mycroft 86: #include <netinet/ip_mroute.h>
1.7 mycroft 87: #include <netinet/in_pcb.h>
1.24 christos 88: #include <netinet/in_var.h>
89:
90: #include <machine/stdarg.h>
1.13 mycroft 91:
1.42.6.1 itojun 92: #ifdef IPSEC
93: #include <netinet6/ipsec.h>
94: #endif /*IPSEC*/
95:
1.20 mycroft 96: struct inpcbtable rawcbtable;
1.30 pk 97:
98: int rip_bind __P((struct inpcb *, struct mbuf *));
99: int rip_connect __P((struct inpcb *, struct mbuf *));
100: void rip_disconnect __P((struct inpcb *));
1.13 mycroft 101:
102: /*
103: * Nominal space allocated to a raw ip socket.
104: */
105: #define RIPSNDQ 8192
106: #define RIPRCVQ 8192
1.1 cgd 107:
108: /*
109: * Raw interface to IP protocol.
110: */
1.13 mycroft 111:
112: /*
113: * Initialize raw connection block q.
114: */
115: void
116: rip_init()
117: {
118:
1.33 mycroft 119: in_pcbinit(&rawcbtable, 1, 1);
1.13 mycroft 120: }
121:
1.42.6.1 itojun 122: static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
123:
1.1 cgd 124: /*
125: * Setup generic address and protocol structures
126: * for raw_input routine, then pass them along with
127: * mbuf chain.
128: */
1.9 mycroft 129: void
1.24 christos 130: #if __STDC__
131: rip_input(struct mbuf *m, ...)
132: #else
133: rip_input(m, va_alist)
1.1 cgd 134: struct mbuf *m;
1.24 christos 135: va_dcl
136: #endif
1.1 cgd 137: {
1.42.6.1 itojun 138: int off, proto;
1.1 cgd 139: register struct ip *ip = mtod(m, struct ip *);
1.13 mycroft 140: register struct inpcb *inp;
1.36 thorpej 141: struct inpcb *last = 0;
142: struct mbuf *opts = 0;
1.32 mycroft 143: struct sockaddr_in ripsrc;
1.42.6.1 itojun 144: va_list ap;
145:
146: va_start(ap, m);
147: off = va_arg(ap, int);
148: proto = va_arg(ap, int);
149: va_end(ap);
1.1 cgd 150:
1.32 mycroft 151: ripsrc.sin_family = AF_INET;
152: ripsrc.sin_len = sizeof(struct sockaddr_in);
1.1 cgd 153: ripsrc.sin_addr = ip->ip_src;
1.34 mycroft 154: ripsrc.sin_port = 0;
155: bzero((caddr_t)ripsrc.sin_zero, sizeof(ripsrc.sin_zero));
1.42 thorpej 156:
157: /*
158: * XXX Compatibility: programs using raw IP expect ip_len
159: * XXX to have the header length subtracted.
160: */
161: ip->ip_len -= ip->ip_hl << 2;
1.32 mycroft 162:
1.21 cgd 163: for (inp = rawcbtable.inpt_queue.cqh_first;
164: inp != (struct inpcb *)&rawcbtable.inpt_queue;
165: inp = inp->inp_queue.cqe_next) {
1.42.6.1 itojun 166: if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto)
1.13 mycroft 167: continue;
1.32 mycroft 168: if (!in_nullhost(inp->inp_laddr) &&
169: !in_hosteq(inp->inp_laddr, ip->ip_dst))
1.13 mycroft 170: continue;
1.32 mycroft 171: if (!in_nullhost(inp->inp_faddr) &&
172: !in_hosteq(inp->inp_faddr, ip->ip_src))
1.13 mycroft 173: continue;
174: if (last) {
175: struct mbuf *n;
1.24 christos 176: if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
1.36 thorpej 177: if (last->inp_flags & INP_CONTROLOPTS ||
178: last->inp_socket->so_options & SO_TIMESTAMP)
179: ip_savecontrol(last, &opts, ip, n);
180: if (sbappendaddr(&last->inp_socket->so_rcv,
181: sintosa(&ripsrc), n, opts) == 0) {
1.13 mycroft 182: /* should notify about lost packet */
183: m_freem(n);
1.36 thorpej 184: if (opts)
185: m_freem(opts);
186: } else
187: sorwakeup(last->inp_socket);
1.41 thorpej 188: opts = NULL;
1.13 mycroft 189: }
190: }
1.36 thorpej 191: last = inp;
1.13 mycroft 192: }
193: if (last) {
1.36 thorpej 194: if (last->inp_flags & INP_CONTROLOPTS ||
195: last->inp_socket->so_options & SO_TIMESTAMP)
196: ip_savecontrol(last, &opts, ip, m);
197: if (sbappendaddr(&last->inp_socket->so_rcv,
198: sintosa(&ripsrc), m, opts) == 0) {
1.13 mycroft 199: m_freem(m);
1.36 thorpej 200: if (opts)
201: m_freem(opts);
202: } else
203: sorwakeup(last->inp_socket);
1.13 mycroft 204: } else {
205: m_freem(m);
1.1 cgd 206: ipstat.ips_noproto++;
207: ipstat.ips_delivered--;
208: }
1.42.6.1 itojun 209: return;
1.1 cgd 210: }
211:
212: /*
213: * Generate IP header and pass packet to ip_output.
214: * Tack on options user may have setup with control call.
215: */
1.9 mycroft 216: int
1.24 christos 217: #if __STDC__
218: rip_output(struct mbuf *m, ...)
219: #else
220: rip_output(m, va_alist)
221: struct mbuf *m;
222: va_dcl
223: #endif
224: {
1.27 mycroft 225: register struct inpcb *inp;
1.1 cgd 226: register struct ip *ip;
1.10 mycroft 227: struct mbuf *opts;
1.24 christos 228: int flags;
229: va_list ap;
230:
231: va_start(ap, m);
1.27 mycroft 232: inp = va_arg(ap, struct inpcb *);
1.24 christos 233: va_end(ap);
234:
1.27 mycroft 235: flags =
1.37 matt 236: (inp->inp_socket->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST
237: | IP_RETURNMTU;
1.1 cgd 238:
239: /*
240: * If the user handed us a complete IP packet, use it.
241: * Otherwise, allocate an mbuf for a header and fill it in.
242: */
1.13 mycroft 243: if ((inp->inp_flags & INP_HDRINCL) == 0) {
1.35 thorpej 244: if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
245: m_freem(m);
246: return (EMSGSIZE);
247: }
1.1 cgd 248: M_PREPEND(m, sizeof(struct ip), M_WAIT);
249: ip = mtod(m, struct ip *);
250: ip->ip_tos = 0;
251: ip->ip_off = 0;
1.13 mycroft 252: ip->ip_p = inp->inp_ip.ip_p;
1.1 cgd 253: ip->ip_len = m->m_pkthdr.len;
1.13 mycroft 254: ip->ip_src = inp->inp_laddr;
1.27 mycroft 255: ip->ip_dst = inp->inp_faddr;
1.1 cgd 256: ip->ip_ttl = MAXTTL;
1.13 mycroft 257: opts = inp->inp_options;
258: } else {
1.35 thorpej 259: if (m->m_pkthdr.len > IP_MAXPACKET) {
260: m_freem(m);
261: return (EMSGSIZE);
262: }
1.13 mycroft 263: ip = mtod(m, struct ip *);
1.38 mycroft 264: if (m->m_pkthdr.len != ip->ip_len) {
265: m_freem(m);
266: return (EINVAL);
267: }
1.13 mycroft 268: if (ip->ip_id == 0)
269: ip->ip_id = htons(ip_id++);
270: opts = NULL;
271: /* XXX prevent ip_output from overwriting header fields */
272: flags |= IP_RAWOUTPUT;
273: ipstat.ips_rawout++;
1.1 cgd 274: }
1.42.6.1 itojun 275: #ifdef IPSEC
276: m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket; /*XXX*/
277: #endif /*IPSEC*/
1.37 matt 278: return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions, &inp->inp_errormtu));
1.1 cgd 279: }
280:
281: /*
282: * Raw IP socket option processing.
283: */
1.9 mycroft 284: int
1.1 cgd 285: rip_ctloutput(op, so, level, optname, m)
286: int op;
287: struct socket *so;
288: int level, optname;
289: struct mbuf **m;
290: {
1.13 mycroft 291: register struct inpcb *inp = sotoinpcb(so);
1.31 mycroft 292: int error = 0;
1.1 cgd 293:
1.15 mycroft 294: if (level != IPPROTO_IP) {
1.31 mycroft 295: error = ENOPROTOOPT;
296: if (op == PRCO_SETOPT && *m != 0)
297: (void) m_free(*m);
298: } else switch (op) {
299:
300: case PRCO_SETOPT:
301: switch (optname) {
302: case IP_HDRINCL:
303: if (*m == 0 || (*m)->m_len < sizeof (int))
304: error = EINVAL;
305: else {
1.13 mycroft 306: if (*mtod(*m, int *))
307: inp->inp_flags |= INP_HDRINCL;
308: else
309: inp->inp_flags &= ~INP_HDRINCL;
310: }
1.31 mycroft 311: if (*m != 0)
312: (void) m_free(*m);
313: break;
314:
315: #ifdef MROUTING
316: case MRT_INIT:
317: case MRT_DONE:
318: case MRT_ADD_VIF:
319: case MRT_DEL_VIF:
320: case MRT_ADD_MFC:
321: case MRT_DEL_MFC:
322: case MRT_ASSERT:
323: error = ip_mrouter_set(so, optname, m);
324: break;
325: #endif
326:
327: default:
328: error = ip_ctloutput(op, so, level, optname, m);
329: break;
1.13 mycroft 330: }
331: break;
1.1 cgd 332:
1.31 mycroft 333: case PRCO_GETOPT:
334: switch (optname) {
335: case IP_HDRINCL:
336: *m = m_get(M_WAIT, M_SOOPTS);
337: (*m)->m_len = sizeof (int);
338: *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL ? 1 : 0;
339: break;
340:
1.6 hpeyerl 341: #ifdef MROUTING
1.31 mycroft 342: case MRT_VERSION:
343: case MRT_ASSERT:
344: error = ip_mrouter_get(so, optname, m);
1.18 mycroft 345: break;
1.31 mycroft 346: #endif
347:
1.18 mycroft 348: default:
1.31 mycroft 349: error = ip_ctloutput(op, so, level, optname, m);
1.18 mycroft 350: break;
351: }
1.31 mycroft 352: break;
1.1 cgd 353: }
1.31 mycroft 354: return (error);
1.1 cgd 355: }
356:
1.27 mycroft 357: int
1.29 mycroft 358: rip_bind(inp, nam)
359: struct inpcb *inp;
360: struct mbuf *nam;
361: {
362: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
363:
364: if (nam->m_len != sizeof(*addr))
365: return (EINVAL);
366: if (ifnet.tqh_first == 0)
367: return (EADDRNOTAVAIL);
368: if (addr->sin_family != AF_INET &&
369: addr->sin_family != AF_IMPLINK)
370: return (EAFNOSUPPORT);
1.32 mycroft 371: if (!in_nullhost(addr->sin_addr) &&
1.29 mycroft 372: ifa_ifwithaddr(sintosa(addr)) == 0)
373: return (EADDRNOTAVAIL);
374: inp->inp_laddr = addr->sin_addr;
375: return (0);
376: }
377:
378: int
1.27 mycroft 379: rip_connect(inp, nam)
380: struct inpcb *inp;
381: struct mbuf *nam;
382: {
383: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
384:
385: if (nam->m_len != sizeof(*addr))
386: return (EINVAL);
387: if (ifnet.tqh_first == 0)
388: return (EADDRNOTAVAIL);
389: if (addr->sin_family != AF_INET &&
390: addr->sin_family != AF_IMPLINK)
391: return (EAFNOSUPPORT);
392: inp->inp_faddr = addr->sin_addr;
393: return (0);
394: }
395:
396: void
397: rip_disconnect(inp)
398: struct inpcb *inp;
399: {
400:
1.32 mycroft 401: inp->inp_faddr = zeroin_addr;
1.27 mycroft 402: }
403:
1.13 mycroft 404: u_long rip_sendspace = RIPSNDQ;
405: u_long rip_recvspace = RIPRCVQ;
406:
1.1 cgd 407: /*ARGSUSED*/
1.9 mycroft 408: int
1.26 mycroft 409: rip_usrreq(so, req, m, nam, control, p)
1.1 cgd 410: register struct socket *so;
411: int req;
1.2 cgd 412: struct mbuf *m, *nam, *control;
1.26 mycroft 413: struct proc *p;
1.1 cgd 414: {
1.27 mycroft 415: register struct inpcb *inp;
416: int s;
1.1 cgd 417: register int error = 0;
1.13 mycroft 418: #ifdef MROUTING
1.6 hpeyerl 419: extern struct socket *ip_mrouter;
420: #endif
1.27 mycroft 421:
1.22 pk 422: if (req == PRU_CONTROL)
423: return (in_control(so, (long)m, (caddr_t)nam,
1.26 mycroft 424: (struct ifnet *)control, p));
1.22 pk 425:
1.27 mycroft 426: s = splsoftnet();
427: inp = sotoinpcb(so);
1.28 mycroft 428: #ifdef DIAGNOSTIC
429: if (req != PRU_SEND && req != PRU_SENDOOB && control)
430: panic("rip_usrreq: unexpected control mbuf");
431: #endif
1.27 mycroft 432: if (inp == 0 && req != PRU_ATTACH) {
1.22 pk 433: error = EINVAL;
434: goto release;
435: }
436:
1.1 cgd 437: switch (req) {
438:
439: case PRU_ATTACH:
1.27 mycroft 440: if (inp != 0) {
441: error = EISCONN;
442: break;
443: }
1.26 mycroft 444: if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) {
1.13 mycroft 445: error = EACCES;
446: break;
447: }
1.27 mycroft 448: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
449: error = soreserve(so, rip_sendspace, rip_recvspace);
450: if (error)
451: break;
452: }
453: error = in_pcballoc(so, &rawcbtable);
454: if (error)
1.13 mycroft 455: break;
1.27 mycroft 456: inp = sotoinpcb(so);
1.17 cgd 457: inp->inp_ip.ip_p = (long)nam;
1.42.6.1 itojun 458: #ifdef IPSEC
459: error = ipsec_init_policy(&inp->inp_sp);
460: #endif /*IPSEC*/
1.1 cgd 461: break;
462:
463: case PRU_DETACH:
1.13 mycroft 464: #ifdef MROUTING
1.6 hpeyerl 465: if (so == ip_mrouter)
466: ip_mrouter_done();
467: #endif
1.13 mycroft 468: in_pcbdetach(inp);
1.1 cgd 469: break;
470:
471: case PRU_BIND:
1.29 mycroft 472: error = rip_bind(inp, nam);
1.27 mycroft 473: break;
474:
475: case PRU_LISTEN:
476: error = EOPNOTSUPP;
477: break;
478:
479: case PRU_CONNECT:
480: error = rip_connect(inp, nam);
481: if (error)
1.13 mycroft 482: break;
1.1 cgd 483: soisconnected(so);
1.13 mycroft 484: break;
485:
486: case PRU_CONNECT2:
487: error = EOPNOTSUPP;
488: break;
489:
1.27 mycroft 490: case PRU_DISCONNECT:
491: soisdisconnected(so);
492: rip_disconnect(inp);
493: break;
494:
1.13 mycroft 495: /*
496: * Mark the connection as being incapable of further input.
497: */
498: case PRU_SHUTDOWN:
499: socantsendmore(so);
500: break;
501:
1.27 mycroft 502: case PRU_RCVD:
503: error = EOPNOTSUPP;
504: break;
505:
1.13 mycroft 506: /*
507: * Ship a packet out. The appropriate raw output
508: * routine handles any massaging necessary.
509: */
510: case PRU_SEND:
1.28 mycroft 511: if (control && control->m_len) {
512: m_freem(control);
513: m_freem(m);
514: error = EINVAL;
515: break;
516: }
517: {
1.27 mycroft 518: if (nam) {
519: if ((so->so_state & SS_ISCONNECTED) != 0) {
1.13 mycroft 520: error = EISCONN;
1.28 mycroft 521: goto die;
1.13 mycroft 522: }
1.27 mycroft 523: error = rip_connect(inp, nam);
524: if (error) {
1.28 mycroft 525: die:
1.27 mycroft 526: m_freem(m);
527: break;
528: }
1.13 mycroft 529: } else {
1.27 mycroft 530: if ((so->so_state & SS_ISCONNECTED) == 0) {
1.13 mycroft 531: error = ENOTCONN;
1.28 mycroft 532: goto die;
1.13 mycroft 533: }
534: }
1.27 mycroft 535: error = rip_output(m, inp);
536: if (nam)
537: rip_disconnect(inp);
1.28 mycroft 538: }
1.13 mycroft 539: break;
540:
541: case PRU_SENSE:
542: /*
543: * stat: don't bother with a blocksize.
544: */
1.27 mycroft 545: splx(s);
1.1 cgd 546: return (0);
1.13 mycroft 547:
548: case PRU_RCVOOB:
1.27 mycroft 549: error = EOPNOTSUPP;
550: break;
551:
1.13 mycroft 552: case PRU_SENDOOB:
1.28 mycroft 553: m_freem(control);
1.27 mycroft 554: m_freem(m);
1.13 mycroft 555: error = EOPNOTSUPP;
556: break;
557:
558: case PRU_SOCKADDR:
559: in_setsockaddr(inp, nam);
560: break;
561:
562: case PRU_PEERADDR:
563: in_setpeeraddr(inp, nam);
564: break;
565:
566: default:
567: panic("rip_usrreq");
1.1 cgd 568: }
1.27 mycroft 569:
1.22 pk 570: release:
1.27 mycroft 571: splx(s);
1.1 cgd 572: return (error);
573: }
CVSweb <webmaster@jp.NetBSD.org>