Annotation of src/sys/netinet/raw_ip.c, Revision 1.33
1.33 ! mycroft 1: /* $NetBSD: raw_ip.c,v 1.32 1996/09/09 14:51:19 mycroft 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;
103: struct socket *last = 0;
1.32 mycroft 104: struct sockaddr_in ripsrc;
1.1 cgd 105:
1.32 mycroft 106: ripsrc.sin_family = AF_INET;
107: ripsrc.sin_len = sizeof(struct sockaddr_in);
1.1 cgd 108: ripsrc.sin_addr = ip->ip_src;
1.32 mycroft 109:
1.21 cgd 110: for (inp = rawcbtable.inpt_queue.cqh_first;
111: inp != (struct inpcb *)&rawcbtable.inpt_queue;
112: inp = inp->inp_queue.cqe_next) {
1.13 mycroft 113: if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p)
114: continue;
1.32 mycroft 115: if (!in_nullhost(inp->inp_laddr) &&
116: !in_hosteq(inp->inp_laddr, ip->ip_dst))
1.13 mycroft 117: continue;
1.32 mycroft 118: if (!in_nullhost(inp->inp_faddr) &&
119: !in_hosteq(inp->inp_faddr, ip->ip_src))
1.13 mycroft 120: continue;
121: if (last) {
122: struct mbuf *n;
1.24 christos 123: if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
1.13 mycroft 124: if (sbappendaddr(&last->so_rcv,
1.19 mycroft 125: sintosa(&ripsrc), n,
126: (struct mbuf *)0) == 0)
1.13 mycroft 127: /* should notify about lost packet */
128: m_freem(n);
129: else
130: sorwakeup(last);
131: }
132: }
133: last = inp->inp_socket;
134: }
135: if (last) {
1.19 mycroft 136: if (sbappendaddr(&last->so_rcv, sintosa(&ripsrc), m,
137: (struct mbuf *)0) == 0)
1.13 mycroft 138: m_freem(m);
139: else
140: sorwakeup(last);
141: } else {
142: m_freem(m);
1.1 cgd 143: ipstat.ips_noproto++;
144: ipstat.ips_delivered--;
145: }
146: }
147:
148: /*
149: * Generate IP header and pass packet to ip_output.
150: * Tack on options user may have setup with control call.
151: */
1.9 mycroft 152: int
1.24 christos 153: #if __STDC__
154: rip_output(struct mbuf *m, ...)
155: #else
156: rip_output(m, va_alist)
157: struct mbuf *m;
158: va_dcl
159: #endif
160: {
1.27 mycroft 161: register struct inpcb *inp;
1.1 cgd 162: register struct ip *ip;
1.10 mycroft 163: struct mbuf *opts;
1.24 christos 164: int flags;
165: va_list ap;
166:
167: va_start(ap, m);
1.27 mycroft 168: inp = va_arg(ap, struct inpcb *);
1.24 christos 169: va_end(ap);
170:
1.27 mycroft 171: flags =
172: (inp->inp_socket->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
1.1 cgd 173:
174: /*
175: * If the user handed us a complete IP packet, use it.
176: * Otherwise, allocate an mbuf for a header and fill it in.
177: */
1.13 mycroft 178: if ((inp->inp_flags & INP_HDRINCL) == 0) {
1.1 cgd 179: M_PREPEND(m, sizeof(struct ip), M_WAIT);
180: ip = mtod(m, struct ip *);
181: ip->ip_tos = 0;
182: ip->ip_off = 0;
1.13 mycroft 183: ip->ip_p = inp->inp_ip.ip_p;
1.1 cgd 184: ip->ip_len = m->m_pkthdr.len;
1.13 mycroft 185: ip->ip_src = inp->inp_laddr;
1.27 mycroft 186: ip->ip_dst = inp->inp_faddr;
1.1 cgd 187: ip->ip_ttl = MAXTTL;
1.13 mycroft 188: opts = inp->inp_options;
189: } else {
190: ip = mtod(m, struct ip *);
191: if (ip->ip_id == 0)
192: ip->ip_id = htons(ip_id++);
193: opts = NULL;
194: /* XXX prevent ip_output from overwriting header fields */
195: flags |= IP_RAWOUTPUT;
196: ipstat.ips_rawout++;
1.1 cgd 197: }
1.13 mycroft 198: return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions));
1.1 cgd 199: }
200:
201: /*
202: * Raw IP socket option processing.
203: */
1.9 mycroft 204: int
1.1 cgd 205: rip_ctloutput(op, so, level, optname, m)
206: int op;
207: struct socket *so;
208: int level, optname;
209: struct mbuf **m;
210: {
1.13 mycroft 211: register struct inpcb *inp = sotoinpcb(so);
1.31 mycroft 212: int error = 0;
1.1 cgd 213:
1.15 mycroft 214: if (level != IPPROTO_IP) {
1.31 mycroft 215: error = ENOPROTOOPT;
216: if (op == PRCO_SETOPT && *m != 0)
217: (void) m_free(*m);
218: } else switch (op) {
219:
220: case PRCO_SETOPT:
221: switch (optname) {
222: case IP_HDRINCL:
223: if (*m == 0 || (*m)->m_len < sizeof (int))
224: error = EINVAL;
225: else {
1.13 mycroft 226: if (*mtod(*m, int *))
227: inp->inp_flags |= INP_HDRINCL;
228: else
229: inp->inp_flags &= ~INP_HDRINCL;
230: }
1.31 mycroft 231: if (*m != 0)
232: (void) m_free(*m);
233: break;
234:
235: #ifdef MROUTING
236: case MRT_INIT:
237: case MRT_DONE:
238: case MRT_ADD_VIF:
239: case MRT_DEL_VIF:
240: case MRT_ADD_MFC:
241: case MRT_DEL_MFC:
242: case MRT_ASSERT:
243: error = ip_mrouter_set(so, optname, m);
244: break;
245: #endif
246:
247: default:
248: error = ip_ctloutput(op, so, level, optname, m);
249: break;
1.13 mycroft 250: }
251: break;
1.1 cgd 252:
1.31 mycroft 253: case PRCO_GETOPT:
254: switch (optname) {
255: case IP_HDRINCL:
256: *m = m_get(M_WAIT, M_SOOPTS);
257: (*m)->m_len = sizeof (int);
258: *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL ? 1 : 0;
259: break;
260:
1.6 hpeyerl 261: #ifdef MROUTING
1.31 mycroft 262: case MRT_VERSION:
263: case MRT_ASSERT:
264: error = ip_mrouter_get(so, optname, m);
1.18 mycroft 265: break;
1.31 mycroft 266: #endif
267:
1.18 mycroft 268: default:
1.31 mycroft 269: error = ip_ctloutput(op, so, level, optname, m);
1.18 mycroft 270: break;
271: }
1.31 mycroft 272: break;
1.1 cgd 273: }
1.31 mycroft 274: return (error);
1.1 cgd 275: }
276:
1.27 mycroft 277: int
1.29 mycroft 278: rip_bind(inp, nam)
279: struct inpcb *inp;
280: struct mbuf *nam;
281: {
282: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
283:
284: if (nam->m_len != sizeof(*addr))
285: return (EINVAL);
286: if (ifnet.tqh_first == 0)
287: return (EADDRNOTAVAIL);
288: if (addr->sin_family != AF_INET &&
289: addr->sin_family != AF_IMPLINK)
290: return (EAFNOSUPPORT);
1.32 mycroft 291: if (!in_nullhost(addr->sin_addr) &&
1.29 mycroft 292: ifa_ifwithaddr(sintosa(addr)) == 0)
293: return (EADDRNOTAVAIL);
294: inp->inp_laddr = addr->sin_addr;
295: return (0);
296: }
297:
298: int
1.27 mycroft 299: rip_connect(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);
312: inp->inp_faddr = addr->sin_addr;
313: return (0);
314: }
315:
316: void
317: rip_disconnect(inp)
318: struct inpcb *inp;
319: {
320:
1.32 mycroft 321: inp->inp_faddr = zeroin_addr;
1.27 mycroft 322: }
323:
1.13 mycroft 324: u_long rip_sendspace = RIPSNDQ;
325: u_long rip_recvspace = RIPRCVQ;
326:
1.1 cgd 327: /*ARGSUSED*/
1.9 mycroft 328: int
1.26 mycroft 329: rip_usrreq(so, req, m, nam, control, p)
1.1 cgd 330: register struct socket *so;
331: int req;
1.2 cgd 332: struct mbuf *m, *nam, *control;
1.26 mycroft 333: struct proc *p;
1.1 cgd 334: {
1.27 mycroft 335: register struct inpcb *inp;
336: int s;
1.1 cgd 337: register int error = 0;
1.13 mycroft 338: #ifdef MROUTING
1.6 hpeyerl 339: extern struct socket *ip_mrouter;
340: #endif
1.27 mycroft 341:
1.22 pk 342: if (req == PRU_CONTROL)
343: return (in_control(so, (long)m, (caddr_t)nam,
1.26 mycroft 344: (struct ifnet *)control, p));
1.22 pk 345:
1.27 mycroft 346: s = splsoftnet();
347: inp = sotoinpcb(so);
1.28 mycroft 348: #ifdef DIAGNOSTIC
349: if (req != PRU_SEND && req != PRU_SENDOOB && control)
350: panic("rip_usrreq: unexpected control mbuf");
351: #endif
1.27 mycroft 352: if (inp == 0 && req != PRU_ATTACH) {
1.22 pk 353: error = EINVAL;
354: goto release;
355: }
356:
1.1 cgd 357: switch (req) {
358:
359: case PRU_ATTACH:
1.27 mycroft 360: if (inp != 0) {
361: error = EISCONN;
362: break;
363: }
1.26 mycroft 364: if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) {
1.13 mycroft 365: error = EACCES;
366: break;
367: }
1.27 mycroft 368: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
369: error = soreserve(so, rip_sendspace, rip_recvspace);
370: if (error)
371: break;
372: }
373: error = in_pcballoc(so, &rawcbtable);
374: if (error)
1.13 mycroft 375: break;
1.27 mycroft 376: inp = sotoinpcb(so);
1.17 cgd 377: inp->inp_ip.ip_p = (long)nam;
1.1 cgd 378: break;
379:
380: case PRU_DETACH:
1.13 mycroft 381: #ifdef MROUTING
1.6 hpeyerl 382: if (so == ip_mrouter)
383: ip_mrouter_done();
384: #endif
1.13 mycroft 385: in_pcbdetach(inp);
1.1 cgd 386: break;
387:
388: case PRU_BIND:
1.29 mycroft 389: error = rip_bind(inp, nam);
1.27 mycroft 390: break;
391:
392: case PRU_LISTEN:
393: error = EOPNOTSUPP;
394: break;
395:
396: case PRU_CONNECT:
397: error = rip_connect(inp, nam);
398: if (error)
1.13 mycroft 399: break;
1.1 cgd 400: soisconnected(so);
1.13 mycroft 401: break;
402:
403: case PRU_CONNECT2:
404: error = EOPNOTSUPP;
405: break;
406:
1.27 mycroft 407: case PRU_DISCONNECT:
408: soisdisconnected(so);
409: rip_disconnect(inp);
410: break;
411:
1.13 mycroft 412: /*
413: * Mark the connection as being incapable of further input.
414: */
415: case PRU_SHUTDOWN:
416: socantsendmore(so);
417: break;
418:
1.27 mycroft 419: case PRU_RCVD:
420: error = EOPNOTSUPP;
421: break;
422:
1.13 mycroft 423: /*
424: * Ship a packet out. The appropriate raw output
425: * routine handles any massaging necessary.
426: */
427: case PRU_SEND:
1.28 mycroft 428: if (control && control->m_len) {
429: m_freem(control);
430: m_freem(m);
431: error = EINVAL;
432: break;
433: }
434: {
1.27 mycroft 435: if (nam) {
436: if ((so->so_state & SS_ISCONNECTED) != 0) {
1.13 mycroft 437: error = EISCONN;
1.28 mycroft 438: goto die;
1.13 mycroft 439: }
1.27 mycroft 440: error = rip_connect(inp, nam);
441: if (error) {
1.28 mycroft 442: die:
1.27 mycroft 443: m_freem(m);
444: break;
445: }
1.13 mycroft 446: } else {
1.27 mycroft 447: if ((so->so_state & SS_ISCONNECTED) == 0) {
1.13 mycroft 448: error = ENOTCONN;
1.28 mycroft 449: goto die;
1.13 mycroft 450: }
451: }
1.27 mycroft 452: error = rip_output(m, inp);
453: if (nam)
454: rip_disconnect(inp);
1.28 mycroft 455: }
1.13 mycroft 456: break;
457:
458: case PRU_SENSE:
459: /*
460: * stat: don't bother with a blocksize.
461: */
1.27 mycroft 462: splx(s);
1.1 cgd 463: return (0);
1.13 mycroft 464:
465: case PRU_RCVOOB:
1.27 mycroft 466: error = EOPNOTSUPP;
467: break;
468:
1.13 mycroft 469: case PRU_SENDOOB:
1.28 mycroft 470: m_freem(control);
1.27 mycroft 471: m_freem(m);
1.13 mycroft 472: error = EOPNOTSUPP;
473: break;
474:
475: case PRU_SOCKADDR:
476: in_setsockaddr(inp, nam);
477: break;
478:
479: case PRU_PEERADDR:
480: in_setpeeraddr(inp, nam);
481: break;
482:
483: default:
484: panic("rip_usrreq");
1.1 cgd 485: }
1.27 mycroft 486:
1.22 pk 487: release:
1.27 mycroft 488: splx(s);
1.1 cgd 489: return (error);
490: }
CVSweb <webmaster@jp.NetBSD.org>