Annotation of src/sys/netinet/raw_ip.c, Revision 1.10
1.1 cgd 1: /*
2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
1.3 cgd 33: * from: @(#)raw_ip.c 7.8 (Berkeley) 7/25/90
1.10 ! mycroft 34: * $Id: raw_ip.c,v 1.9 1994/01/09 01:06:21 mycroft Exp $
1.1 cgd 35: */
36:
1.7 mycroft 37: #include <sys/param.h>
38: #include <sys/malloc.h>
39: #include <sys/mbuf.h>
40: #include <sys/socket.h>
41: #include <sys/protosw.h>
42: #include <sys/socketvar.h>
43: #include <sys/errno.h>
1.1 cgd 44:
1.7 mycroft 45: #include <net/if.h>
46: #include <net/route.h>
47: #include <net/raw_cb.h>
1.1 cgd 48:
1.7 mycroft 49: #include <netinet/in.h>
50: #include <netinet/in_systm.h>
51: #include <netinet/ip.h>
52: #include <netinet/ip_var.h>
53: #include <netinet/in_pcb.h>
1.9 mycroft 54: #include <netinet/ip_mroute.h>
1.1 cgd 55:
56: /*
57: * Raw interface to IP protocol.
58: */
59: struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET };
60: struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
61: struct sockproto ripproto = { PF_INET };
1.9 mycroft 62:
1.1 cgd 63: /*
64: * Setup generic address and protocol structures
65: * for raw_input routine, then pass them along with
66: * mbuf chain.
67: */
1.9 mycroft 68: void
1.1 cgd 69: rip_input(m)
70: struct mbuf *m;
71: {
72: register struct ip *ip = mtod(m, struct ip *);
73:
74: ripproto.sp_protocol = ip->ip_p;
75: ripdst.sin_addr = ip->ip_dst;
76: ripsrc.sin_addr = ip->ip_src;
77: if (raw_input(m, &ripproto, (struct sockaddr *)&ripsrc,
78: (struct sockaddr *)&ripdst) == 0) {
79: ipstat.ips_noproto++;
80: ipstat.ips_delivered--;
81: }
82: }
83:
84: /*
85: * Generate IP header and pass packet to ip_output.
86: * Tack on options user may have setup with control call.
87: */
88: #define satosin(sa) ((struct sockaddr_in *)(sa))
1.9 mycroft 89: int
1.1 cgd 90: rip_output(m, so)
91: register struct mbuf *m;
92: struct socket *so;
93: {
94: register struct ip *ip;
95: register struct raw_inpcb *rp = sotorawinpcb(so);
96: register struct sockaddr_in *sin;
1.10 ! mycroft 97: struct mbuf *opts;
1.1 cgd 98:
99: /*
100: * If the user handed us a complete IP packet, use it.
101: * Otherwise, allocate an mbuf for a header and fill it in.
102: */
1.4 cgd 103: if (rp->rinp_flags & RINPF_HDRINCL) {
1.1 cgd 104: ip = mtod(m, struct ip *);
1.4 cgd 105: if (ip->ip_len > m->m_pkthdr.len)
106: return EMSGSIZE;
107: ip->ip_len = m->m_pkthdr.len;
1.10 ! mycroft 108: opts = NULL;
1.4 cgd 109: } else {
1.1 cgd 110: M_PREPEND(m, sizeof(struct ip), M_WAIT);
111: ip = mtod(m, struct ip *);
112: ip->ip_tos = 0;
113: ip->ip_off = 0;
114: ip->ip_p = rp->rinp_rcb.rcb_proto.sp_protocol;
115: ip->ip_len = m->m_pkthdr.len;
116: if (sin = satosin(rp->rinp_rcb.rcb_laddr)) {
117: ip->ip_src = sin->sin_addr;
118: } else
119: ip->ip_src.s_addr = 0;
120: if (sin = satosin(rp->rinp_rcb.rcb_faddr))
121: ip->ip_dst = sin->sin_addr;
122: ip->ip_ttl = MAXTTL;
1.10 ! mycroft 123: opts = rp->rinp_options;
1.1 cgd 124: }
1.10 ! mycroft 125: return (ip_output(m, opts, &rp->rinp_route,
! 126: (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST
1.6 hpeyerl 127: #ifdef MULTICAST
1.10 ! mycroft 128: , rp->rinp_rcb.rcb_moptions
! 129: #else
! 130: , NULL
1.6 hpeyerl 131: #endif
1.10 ! mycroft 132: ));
1.1 cgd 133: }
134:
135: /*
136: * Raw IP socket option processing.
137: */
1.9 mycroft 138: int
1.1 cgd 139: rip_ctloutput(op, so, level, optname, m)
140: int op;
141: struct socket *so;
142: int level, optname;
143: struct mbuf **m;
144: {
145: int error = 0;
146: register struct raw_inpcb *rp = sotorawinpcb(so);
147:
148: if (level != IPPROTO_IP)
149: error = EINVAL;
150: else switch (op) {
151:
152: case PRCO_SETOPT:
153: switch (optname) {
154:
155: case IP_OPTIONS:
156: return (ip_pcbopts(&rp->rinp_options, *m));
157:
158: case IP_HDRINCL:
159: if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) {
160: error = EINVAL;
161: break;
162: }
163: if (*mtod(*m, int *))
164: rp->rinp_flags |= RINPF_HDRINCL;
165: else
166: rp->rinp_flags &= ~RINPF_HDRINCL;
167: break;
1.6 hpeyerl 168: #ifdef MULTICAST
169: case IP_MULTICAST_IF:
170: case IP_MULTICAST_TTL:
171: case IP_MULTICAST_LOOP:
172: case IP_ADD_MEMBERSHIP:
173: case IP_DROP_MEMBERSHIP:
174: error = ip_setmoptions(optname,
175: &rp->rinp_rcb.rcb_moptions, *m);
176: break;
177: default:
178: #ifdef MROUTING
179: error = ip_mrouter_cmd(optname, so, *m);
180: #else
181: error = EINVAL;
182: #endif
183: break;
184: #else
1.1 cgd 185: default:
186: error = EINVAL;
187: break;
1.6 hpeyerl 188: #endif
1.1 cgd 189: }
190: break;
191:
192: case PRCO_GETOPT:
193: *m = m_get(M_WAIT, MT_SOOPTS);
194: switch (optname) {
195:
196: case IP_OPTIONS:
197: if (rp->rinp_options) {
198: (*m)->m_len = rp->rinp_options->m_len;
199: bcopy(mtod(rp->rinp_options, caddr_t),
200: mtod(*m, caddr_t), (unsigned)(*m)->m_len);
201: } else
202: (*m)->m_len = 0;
203: break;
204:
205: case IP_HDRINCL:
206: (*m)->m_len = sizeof (int);
207: *mtod(*m, int *) = rp->rinp_flags & RINPF_HDRINCL;
208: break;
1.6 hpeyerl 209: #ifdef MULTICAST
210: case IP_MULTICAST_IF:
211: case IP_MULTICAST_TTL:
212: case IP_MULTICAST_LOOP:
213: case IP_ADD_MEMBERSHIP:
214: case IP_DROP_MEMBERSHIP:
1.8 mycroft 215: error = ip_getmoptions(optname,
216: rp->rinp_rcb.rcb_moptions, m);
217: break;
1.6 hpeyerl 218: #endif
1.1 cgd 219: default:
220: error = EINVAL;
221: m_freem(*m);
222: *m = 0;
223: break;
224: }
225: break;
226: }
227: if (op == PRCO_SETOPT && *m)
228: (void)m_free(*m);
229: return (error);
230: }
231:
232: /*ARGSUSED*/
1.9 mycroft 233: int
1.2 cgd 234: rip_usrreq(so, req, m, nam, control)
1.1 cgd 235: register struct socket *so;
236: int req;
1.2 cgd 237: struct mbuf *m, *nam, *control;
1.1 cgd 238: {
239: register int error = 0;
240: register struct raw_inpcb *rp = sotorawinpcb(so);
1.6 hpeyerl 241: #if defined(MULTICAST) && defined(MROUTING)
242: extern struct socket *ip_mrouter;
243: #endif
1.1 cgd 244: switch (req) {
245:
246: case PRU_ATTACH:
247: if (rp)
248: panic("rip_attach");
249: MALLOC(rp, struct raw_inpcb *, sizeof *rp, M_PCB, M_WAITOK);
250: if (rp == 0)
251: return (ENOBUFS);
252: bzero((caddr_t)rp, sizeof *rp);
253: so->so_pcb = (caddr_t)rp;
254: break;
255:
256: case PRU_DETACH:
257: if (rp == 0)
258: panic("rip_detach");
1.6 hpeyerl 259: #if defined(MULTICAST) && defined(MROUTING)
260: if (so == ip_mrouter)
261: ip_mrouter_done();
262: #endif
1.1 cgd 263: if (rp->rinp_options)
264: m_freem(rp->rinp_options);
1.6 hpeyerl 265: #ifdef MULTICAST
266: if (rp->rinp_rcb.rcb_moptions)
267: ip_freemoptions(rp->rinp_rcb.rcb_moptions);
268: #endif
1.1 cgd 269: if (rp->rinp_route.ro_rt)
270: RTFREE(rp->rinp_route.ro_rt);
271: if (rp->rinp_rcb.rcb_laddr)
272: rp->rinp_rcb.rcb_laddr = 0;
273: break;
274:
275: case PRU_BIND:
276: {
277: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
278:
279: if (nam->m_len != sizeof(*addr))
280: return (EINVAL);
281: if ((ifnet == 0) ||
282: ((addr->sin_family != AF_INET) &&
283: (addr->sin_family != AF_IMPLINK)) ||
284: (addr->sin_addr.s_addr &&
285: ifa_ifwithaddr((struct sockaddr *)addr) == 0))
286: return (EADDRNOTAVAIL);
287: rp->rinp_rcb.rcb_laddr = (struct sockaddr *)&rp->rinp_laddr;
288: rp->rinp_laddr = *addr;
289: return (0);
290: }
291: case PRU_CONNECT:
292: {
293: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
294:
295: if (nam->m_len != sizeof(*addr))
296: return (EINVAL);
297: if (ifnet == 0)
298: return (EADDRNOTAVAIL);
299: if ((addr->sin_family != AF_INET) &&
300: (addr->sin_family != AF_IMPLINK))
301: return (EAFNOSUPPORT);
302: rp->rinp_rcb.rcb_faddr = (struct sockaddr *)&rp->rinp_faddr;
303: rp->rinp_faddr = *addr;
304: soisconnected(so);
305: return (0);
306: }
307: }
308: error = raw_usrreq(so, req, m, nam, control);
309:
310: if (error && (req == PRU_ATTACH) && so->so_pcb)
311: free(so->so_pcb, M_PCB);
312: return (error);
313: }
CVSweb <webmaster@jp.NetBSD.org>