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