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