syscons util remove use kbdcontrol & vidcontrol instead
[unix-history] / sys / netinet / raw_ip.c
CommitLineData
15637ed4 1/*
4cf615e1
JH
2 * Copyright (c) 1982, 1986, 1988, 1993
3 * Regents of the University of California. All rights reserved.
15637ed4
RG
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 *
38e82238 33 * from: @(#)raw_ip.c 7.8 (Berkeley) 7/25/90
4cf615e1 34 * $Id: raw_ip.c,v 1.4 1993/12/19 00:52:46 wollman Exp $
15637ed4
RG
35 */
36
37#include "param.h"
38#include "malloc.h"
39#include "mbuf.h"
40#include "socket.h"
41#include "protosw.h"
42#include "socketvar.h"
43#include "errno.h"
44
45#include "../net/if.h"
46#include "../net/route.h"
47#include "../net/raw_cb.h"
48
49#include "in.h"
50#include "in_systm.h"
51#include "ip.h"
52#include "ip_var.h"
53#include "in_pcb.h"
54
55/*
56 * Raw interface to IP protocol.
57 */
fde1aeb2
GW
58static struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET };
59static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
60static struct sockproto ripproto = { PF_INET };
15637ed4 61
15637ed4
RG
62/*
63 * Setup generic address and protocol structures
64 * for raw_input routine, then pass them along with
65 * mbuf chain.
66 */
4c45483e 67void
15637ed4
RG
68rip_input(m)
69 struct mbuf *m;
70{
71 register struct ip *ip = mtod(m, struct ip *);
72
73 ripproto.sp_protocol = ip->ip_p;
74 ripdst.sin_addr = ip->ip_dst;
75 ripsrc.sin_addr = ip->ip_src;
76 if (raw_input(m, &ripproto, (struct sockaddr *)&ripsrc,
77 (struct sockaddr *)&ripdst) == 0) {
78 ipstat.ips_noproto++;
79 ipstat.ips_delivered--;
80 }
81}
82
83/*
84 * Generate IP header and pass packet to ip_output.
85 * Tack on options user may have setup with control call.
86 */
87#define satosin(sa) ((struct sockaddr_in *)(sa))
4c45483e 88int
15637ed4
RG
89rip_output(m, so)
90 register struct mbuf *m;
91 struct socket *so;
92{
93 register struct ip *ip;
94 register struct raw_inpcb *rp = sotorawinpcb(so);
95 register struct sockaddr_in *sin;
96
97 /*
98 * If the user handed us a complete IP packet, use it.
99 * Otherwise, allocate an mbuf for a header and fill it in.
100 */
101 if (rp->rinp_flags & RINPF_HDRINCL)
102 ip = mtod(m, struct ip *);
103 else {
104 M_PREPEND(m, sizeof(struct ip), M_WAIT);
105 ip = mtod(m, struct ip *);
106 ip->ip_tos = 0;
107 ip->ip_off = 0;
108 ip->ip_p = rp->rinp_rcb.rcb_proto.sp_protocol;
109 ip->ip_len = m->m_pkthdr.len;
110 if (sin = satosin(rp->rinp_rcb.rcb_laddr)) {
111 ip->ip_src = sin->sin_addr;
112 } else
113 ip->ip_src.s_addr = 0;
114 if (sin = satosin(rp->rinp_rcb.rcb_faddr))
115 ip->ip_dst = sin->sin_addr;
116 ip->ip_ttl = MAXTTL;
117 }
118 return (ip_output(m,
119 (rp->rinp_flags & RINPF_HDRINCL)? (struct mbuf *)0: rp->rinp_options,
120 &rp->rinp_route,
4cf615e1
JH
121 (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST
122#ifdef MULTICAST
123 | IP_MULTICASTOPTS, rp->rinp_rcb.rcb_moptions
124#endif
125 ));
15637ed4
RG
126}
127
128/*
129 * Raw IP socket option processing.
130 */
4c45483e 131int
15637ed4
RG
132rip_ctloutput(op, so, level, optname, m)
133 int op;
134 struct socket *so;
135 int level, optname;
136 struct mbuf **m;
137{
138 int error = 0;
139 register struct raw_inpcb *rp = sotorawinpcb(so);
140
141 if (level != IPPROTO_IP)
142 error = EINVAL;
143 else switch (op) {
144
145 case PRCO_SETOPT:
146 switch (optname) {
147
148 case IP_OPTIONS:
149 return (ip_pcbopts(&rp->rinp_options, *m));
150
151 case IP_HDRINCL:
152 if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) {
153 error = EINVAL;
154 break;
155 }
156 if (*mtod(*m, int *))
157 rp->rinp_flags |= RINPF_HDRINCL;
158 else
159 rp->rinp_flags &= ~RINPF_HDRINCL;
160 break;
4cf615e1
JH
161#ifdef MULTICAST
162 case IP_MULTICAST_IF:
163 case IP_MULTICAST_TTL:
164 case IP_MULTICAST_LOOP:
165 case IP_ADD_MEMBERSHIP:
166 case IP_DROP_MEMBERSHIP:
167 error = ip_setmoptions(optname,
168 &rp->rinp_rcb.rcb_moptions, *m);
169 break;
170 default:
171#ifdef MROUTING
172 error = ip_mrouter_cmd(optname, so, *m);
173#else
174 error = EINVAL;
175#endif
176 break;
177#else
15637ed4
RG
178 default:
179 error = EINVAL;
180 break;
4cf615e1 181#endif
15637ed4
RG
182 }
183 break;
184
185 case PRCO_GETOPT:
186 *m = m_get(M_WAIT, MT_SOOPTS);
187 switch (optname) {
188
189 case IP_OPTIONS:
190 if (rp->rinp_options) {
191 (*m)->m_len = rp->rinp_options->m_len;
192 bcopy(mtod(rp->rinp_options, caddr_t),
193 mtod(*m, caddr_t), (unsigned)(*m)->m_len);
194 } else
195 (*m)->m_len = 0;
196 break;
197
198 case IP_HDRINCL:
199 (*m)->m_len = sizeof (int);
200 *mtod(*m, int *) = rp->rinp_flags & RINPF_HDRINCL;
201 break;
4cf615e1
JH
202#ifdef MULTICAST
203 case IP_MULTICAST_IF:
204 case IP_MULTICAST_TTL:
205 case IP_MULTICAST_LOOP:
206 case IP_ADD_MEMBERSHIP:
207 case IP_DROP_MEMBERSHIP:
208 error = ip_getmoptions(optname,
209 rp->rinp_rcb.rcb_moptions, m);
210 break;
211#endif
15637ed4
RG
212 default:
213 error = EINVAL;
214 m_freem(*m);
215 *m = 0;
216 break;
217 }
218 break;
219 }
220 if (op == PRCO_SETOPT && *m)
221 (void)m_free(*m);
222 return (error);
223}
224
225/*ARGSUSED*/
4c45483e 226int
15637ed4
RG
227rip_usrreq(so, req, m, nam, control)
228 register struct socket *so;
229 int req;
230 struct mbuf *m, *nam, *control;
231{
232 register int error = 0;
233 register struct raw_inpcb *rp = sotorawinpcb(so);
4cf615e1
JH
234#if defined(MULTICAST) && defined(MROUTING)
235 extern struct socket *ip_mrouter;
236#endif
15637ed4
RG
237 switch (req) {
238
239 case PRU_ATTACH:
240 if (rp)
241 panic("rip_attach");
242 MALLOC(rp, struct raw_inpcb *, sizeof *rp, M_PCB, M_WAITOK);
243 if (rp == 0)
244 return (ENOBUFS);
245 bzero((caddr_t)rp, sizeof *rp);
246 so->so_pcb = (caddr_t)rp;
247 break;
248
249 case PRU_DETACH:
250 if (rp == 0)
251 panic("rip_detach");
4cf615e1
JH
252#if defined(MULTICAST) && defined(MROUTING)
253 if (so == ip_mrouter)
254 ip_mrouter_done();
255#endif
15637ed4
RG
256 if (rp->rinp_options)
257 m_freem(rp->rinp_options);
4cf615e1
JH
258#ifdef MULTICAST
259 if (rp->rinp_rcb.rcb_moptions)
260 ip_freemoptions(rp->rinp_rcb.rcb_moptions);
261#endif
15637ed4
RG
262 if (rp->rinp_route.ro_rt)
263 RTFREE(rp->rinp_route.ro_rt);
264 if (rp->rinp_rcb.rcb_laddr)
265 rp->rinp_rcb.rcb_laddr = 0;
266 break;
267
268 case PRU_BIND:
269 {
270 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
271
272 if (nam->m_len != sizeof(*addr))
273 return (EINVAL);
274 if ((ifnet == 0) ||
275 ((addr->sin_family != AF_INET) &&
276 (addr->sin_family != AF_IMPLINK)) ||
277 (addr->sin_addr.s_addr &&
278 ifa_ifwithaddr((struct sockaddr *)addr) == 0))
279 return (EADDRNOTAVAIL);
280 rp->rinp_rcb.rcb_laddr = (struct sockaddr *)&rp->rinp_laddr;
281 rp->rinp_laddr = *addr;
282 return (0);
283 }
284 case PRU_CONNECT:
285 {
286 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
287
288 if (nam->m_len != sizeof(*addr))
289 return (EINVAL);
290 if (ifnet == 0)
291 return (EADDRNOTAVAIL);
292 if ((addr->sin_family != AF_INET) &&
293 (addr->sin_family != AF_IMPLINK))
294 return (EAFNOSUPPORT);
295 rp->rinp_rcb.rcb_faddr = (struct sockaddr *)&rp->rinp_faddr;
296 rp->rinp_faddr = *addr;
297 soisconnected(so);
298 return (0);
299 }
300 }
fde1aeb2 301 error = raw_usrreq(so, req, m, nam, control, 0);
15637ed4
RG
302
303 if (error && (req == PRU_ATTACH) && so->so_pcb)
304 free(so->so_pcb, M_PCB);
305 return (error);
306}