Annotation of src/sys/netinet/raw_ip.c, Revision 1.36.10.1
1.36.10.1! thorpej 1: /* $NetBSD: raw_ip.c,v 1.37 1997/10/14 00:52:54 matt 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 =
1.36.10.1! thorpej 184: (inp->inp_socket->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST
! 185: | IP_RETURNMTU;
1.1 cgd 186:
187: /*
188: * If the user handed us a complete IP packet, use it.
189: * Otherwise, allocate an mbuf for a header and fill it in.
190: */
1.13 mycroft 191: if ((inp->inp_flags & INP_HDRINCL) == 0) {
1.35 thorpej 192: if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
193: m_freem(m);
194: return (EMSGSIZE);
195: }
1.1 cgd 196: M_PREPEND(m, sizeof(struct ip), M_WAIT);
197: ip = mtod(m, struct ip *);
198: ip->ip_tos = 0;
199: ip->ip_off = 0;
1.13 mycroft 200: ip->ip_p = inp->inp_ip.ip_p;
1.1 cgd 201: ip->ip_len = m->m_pkthdr.len;
1.13 mycroft 202: ip->ip_src = inp->inp_laddr;
1.27 mycroft 203: ip->ip_dst = inp->inp_faddr;
1.1 cgd 204: ip->ip_ttl = MAXTTL;
1.13 mycroft 205: opts = inp->inp_options;
206: } else {
1.35 thorpej 207: if (m->m_pkthdr.len > IP_MAXPACKET) {
208: m_freem(m);
209: return (EMSGSIZE);
210: }
1.13 mycroft 211: ip = mtod(m, struct ip *);
212: if (ip->ip_id == 0)
213: ip->ip_id = htons(ip_id++);
214: opts = NULL;
215: /* XXX prevent ip_output from overwriting header fields */
216: flags |= IP_RAWOUTPUT;
217: ipstat.ips_rawout++;
1.1 cgd 218: }
1.36.10.1! thorpej 219: return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions, &inp->inp_errormtu));
1.1 cgd 220: }
221:
222: /*
223: * Raw IP socket option processing.
224: */
1.9 mycroft 225: int
1.1 cgd 226: rip_ctloutput(op, so, level, optname, m)
227: int op;
228: struct socket *so;
229: int level, optname;
230: struct mbuf **m;
231: {
1.13 mycroft 232: register struct inpcb *inp = sotoinpcb(so);
1.31 mycroft 233: int error = 0;
1.1 cgd 234:
1.15 mycroft 235: if (level != IPPROTO_IP) {
1.31 mycroft 236: error = ENOPROTOOPT;
237: if (op == PRCO_SETOPT && *m != 0)
238: (void) m_free(*m);
239: } else switch (op) {
240:
241: case PRCO_SETOPT:
242: switch (optname) {
243: case IP_HDRINCL:
244: if (*m == 0 || (*m)->m_len < sizeof (int))
245: error = EINVAL;
246: else {
1.13 mycroft 247: if (*mtod(*m, int *))
248: inp->inp_flags |= INP_HDRINCL;
249: else
250: inp->inp_flags &= ~INP_HDRINCL;
251: }
1.31 mycroft 252: if (*m != 0)
253: (void) m_free(*m);
254: break;
255:
256: #ifdef MROUTING
257: case MRT_INIT:
258: case MRT_DONE:
259: case MRT_ADD_VIF:
260: case MRT_DEL_VIF:
261: case MRT_ADD_MFC:
262: case MRT_DEL_MFC:
263: case MRT_ASSERT:
264: error = ip_mrouter_set(so, optname, m);
265: break;
266: #endif
267:
268: default:
269: error = ip_ctloutput(op, so, level, optname, m);
270: break;
1.13 mycroft 271: }
272: break;
1.1 cgd 273:
1.31 mycroft 274: case PRCO_GETOPT:
275: switch (optname) {
276: case IP_HDRINCL:
277: *m = m_get(M_WAIT, M_SOOPTS);
278: (*m)->m_len = sizeof (int);
279: *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL ? 1 : 0;
280: break;
281:
1.6 hpeyerl 282: #ifdef MROUTING
1.31 mycroft 283: case MRT_VERSION:
284: case MRT_ASSERT:
285: error = ip_mrouter_get(so, optname, m);
1.18 mycroft 286: break;
1.31 mycroft 287: #endif
288:
1.18 mycroft 289: default:
1.31 mycroft 290: error = ip_ctloutput(op, so, level, optname, m);
1.18 mycroft 291: break;
292: }
1.31 mycroft 293: break;
1.1 cgd 294: }
1.31 mycroft 295: return (error);
1.1 cgd 296: }
297:
1.27 mycroft 298: int
1.29 mycroft 299: rip_bind(inp, nam)
300: struct inpcb *inp;
301: struct mbuf *nam;
302: {
303: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
304:
305: if (nam->m_len != sizeof(*addr))
306: return (EINVAL);
307: if (ifnet.tqh_first == 0)
308: return (EADDRNOTAVAIL);
309: if (addr->sin_family != AF_INET &&
310: addr->sin_family != AF_IMPLINK)
311: return (EAFNOSUPPORT);
1.32 mycroft 312: if (!in_nullhost(addr->sin_addr) &&
1.29 mycroft 313: ifa_ifwithaddr(sintosa(addr)) == 0)
314: return (EADDRNOTAVAIL);
315: inp->inp_laddr = addr->sin_addr;
316: return (0);
317: }
318:
319: int
1.27 mycroft 320: rip_connect(inp, nam)
321: struct inpcb *inp;
322: struct mbuf *nam;
323: {
324: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
325:
326: if (nam->m_len != sizeof(*addr))
327: return (EINVAL);
328: if (ifnet.tqh_first == 0)
329: return (EADDRNOTAVAIL);
330: if (addr->sin_family != AF_INET &&
331: addr->sin_family != AF_IMPLINK)
332: return (EAFNOSUPPORT);
333: inp->inp_faddr = addr->sin_addr;
334: return (0);
335: }
336:
337: void
338: rip_disconnect(inp)
339: struct inpcb *inp;
340: {
341:
1.32 mycroft 342: inp->inp_faddr = zeroin_addr;
1.27 mycroft 343: }
344:
1.13 mycroft 345: u_long rip_sendspace = RIPSNDQ;
346: u_long rip_recvspace = RIPRCVQ;
347:
1.1 cgd 348: /*ARGSUSED*/
1.9 mycroft 349: int
1.26 mycroft 350: rip_usrreq(so, req, m, nam, control, p)
1.1 cgd 351: register struct socket *so;
352: int req;
1.2 cgd 353: struct mbuf *m, *nam, *control;
1.26 mycroft 354: struct proc *p;
1.1 cgd 355: {
1.27 mycroft 356: register struct inpcb *inp;
357: int s;
1.1 cgd 358: register int error = 0;
1.13 mycroft 359: #ifdef MROUTING
1.6 hpeyerl 360: extern struct socket *ip_mrouter;
361: #endif
1.27 mycroft 362:
1.22 pk 363: if (req == PRU_CONTROL)
364: return (in_control(so, (long)m, (caddr_t)nam,
1.26 mycroft 365: (struct ifnet *)control, p));
1.22 pk 366:
1.27 mycroft 367: s = splsoftnet();
368: inp = sotoinpcb(so);
1.28 mycroft 369: #ifdef DIAGNOSTIC
370: if (req != PRU_SEND && req != PRU_SENDOOB && control)
371: panic("rip_usrreq: unexpected control mbuf");
372: #endif
1.27 mycroft 373: if (inp == 0 && req != PRU_ATTACH) {
1.22 pk 374: error = EINVAL;
375: goto release;
376: }
377:
1.1 cgd 378: switch (req) {
379:
380: case PRU_ATTACH:
1.27 mycroft 381: if (inp != 0) {
382: error = EISCONN;
383: break;
384: }
1.26 mycroft 385: if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) {
1.13 mycroft 386: error = EACCES;
387: break;
388: }
1.27 mycroft 389: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
390: error = soreserve(so, rip_sendspace, rip_recvspace);
391: if (error)
392: break;
393: }
394: error = in_pcballoc(so, &rawcbtable);
395: if (error)
1.13 mycroft 396: break;
1.27 mycroft 397: inp = sotoinpcb(so);
1.17 cgd 398: inp->inp_ip.ip_p = (long)nam;
1.1 cgd 399: break;
400:
401: case PRU_DETACH:
1.13 mycroft 402: #ifdef MROUTING
1.6 hpeyerl 403: if (so == ip_mrouter)
404: ip_mrouter_done();
405: #endif
1.13 mycroft 406: in_pcbdetach(inp);
1.1 cgd 407: break;
408:
409: case PRU_BIND:
1.29 mycroft 410: error = rip_bind(inp, nam);
1.27 mycroft 411: break;
412:
413: case PRU_LISTEN:
414: error = EOPNOTSUPP;
415: break;
416:
417: case PRU_CONNECT:
418: error = rip_connect(inp, nam);
419: if (error)
1.13 mycroft 420: break;
1.1 cgd 421: soisconnected(so);
1.13 mycroft 422: break;
423:
424: case PRU_CONNECT2:
425: error = EOPNOTSUPP;
426: break;
427:
1.27 mycroft 428: case PRU_DISCONNECT:
429: soisdisconnected(so);
430: rip_disconnect(inp);
431: break;
432:
1.13 mycroft 433: /*
434: * Mark the connection as being incapable of further input.
435: */
436: case PRU_SHUTDOWN:
437: socantsendmore(so);
438: break;
439:
1.27 mycroft 440: case PRU_RCVD:
441: error = EOPNOTSUPP;
442: break;
443:
1.13 mycroft 444: /*
445: * Ship a packet out. The appropriate raw output
446: * routine handles any massaging necessary.
447: */
448: case PRU_SEND:
1.28 mycroft 449: if (control && control->m_len) {
450: m_freem(control);
451: m_freem(m);
452: error = EINVAL;
453: break;
454: }
455: {
1.27 mycroft 456: if (nam) {
457: if ((so->so_state & SS_ISCONNECTED) != 0) {
1.13 mycroft 458: error = EISCONN;
1.28 mycroft 459: goto die;
1.13 mycroft 460: }
1.27 mycroft 461: error = rip_connect(inp, nam);
462: if (error) {
1.28 mycroft 463: die:
1.27 mycroft 464: m_freem(m);
465: break;
466: }
1.13 mycroft 467: } else {
1.27 mycroft 468: if ((so->so_state & SS_ISCONNECTED) == 0) {
1.13 mycroft 469: error = ENOTCONN;
1.28 mycroft 470: goto die;
1.13 mycroft 471: }
472: }
1.27 mycroft 473: error = rip_output(m, inp);
474: if (nam)
475: rip_disconnect(inp);
1.28 mycroft 476: }
1.13 mycroft 477: break;
478:
479: case PRU_SENSE:
480: /*
481: * stat: don't bother with a blocksize.
482: */
1.27 mycroft 483: splx(s);
1.1 cgd 484: return (0);
1.13 mycroft 485:
486: case PRU_RCVOOB:
1.27 mycroft 487: error = EOPNOTSUPP;
488: break;
489:
1.13 mycroft 490: case PRU_SENDOOB:
1.28 mycroft 491: m_freem(control);
1.27 mycroft 492: m_freem(m);
1.13 mycroft 493: error = EOPNOTSUPP;
494: break;
495:
496: case PRU_SOCKADDR:
497: in_setsockaddr(inp, nam);
498: break;
499:
500: case PRU_PEERADDR:
501: in_setpeeraddr(inp, nam);
502: break;
503:
504: default:
505: panic("rip_usrreq");
1.1 cgd 506: }
1.27 mycroft 507:
1.22 pk 508: release:
1.27 mycroft 509: splx(s);
1.1 cgd 510: return (error);
511: }
CVSweb <webmaster@jp.NetBSD.org>