1/*
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. 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 *
33 * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93
34 * $Id: raw_usrreq.c,v 1.6 1995/05/30 08:08:22 rgrimes Exp $
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/mbuf.h>
40#include <sys/domain.h>
41#include <sys/protosw.h>
42#include <sys/socket.h>
43#include <sys/socketvar.h>
44#include <sys/errno.h>
45
46#include <net/if.h>
47#include <net/route.h>
48#include <net/netisr.h>
49#include <net/raw_cb.h>
50
51/*
52 * Initialize raw connection block q.
53 */
54void
55raw_init()
56{
57
58 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
59}
60
61
62/*
63 * Raw protocol input routine. Find the socket
64 * associated with the packet(s) and move them over. If
65 * nothing exists for this packet, drop it.
66 */
67/*
68 * Raw protocol interface.
69 */
70void
71raw_input(m0, proto, src, dst)
72 struct mbuf *m0;
73 register struct sockproto *proto;
74 struct sockaddr *src, *dst;
75{
76 register struct rawcb *rp;
77 register struct mbuf *m = m0;
78 register int sockets = 0;
79 struct socket *last;
80
81 last = 0;
82 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
83 if (rp->rcb_proto.sp_family != proto->sp_family)
84 continue;
85 if (rp->rcb_proto.sp_protocol &&
86 rp->rcb_proto.sp_protocol != proto->sp_protocol)
87 continue;
88 /*
89 * We assume the lower level routines have
90 * placed the address in a canonical format
91 * suitable for a structure comparison.
92 *
93 * Note that if the lengths are not the same
94 * the comparison will fail at the first byte.
95 */
96#define equal(a1, a2) \
97 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
98 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
99 continue;
100 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
101 continue;
102 if (last) {
103 struct mbuf *n;
104 n = m_copy(m, 0, (int)M_COPYALL);
105 if (n) {
106 if (sbappendaddr(&last->so_rcv, src,
107 n, (struct mbuf *)0) == 0)
108 /* should notify about lost packet */
109 m_freem(n);
110 else {
111 sorwakeup(last);
112 sockets++;
113 }
114 }
115 }
116 last = rp->rcb_socket;
117 }
118 if (last) {
119 if (sbappendaddr(&last->so_rcv, src,
120 m, (struct mbuf *)0) == 0)
121 m_freem(m);
122 else {
123 sorwakeup(last);
124 sockets++;
125 }
126 } else
127 m_freem(m);
128}
129
130/*ARGSUSED*/
131void
132raw_ctlinput(cmd, arg, dummy)
133 int cmd;
134 struct sockaddr *arg;
135 void *dummy;
136{
137
138 if (cmd < 0 || cmd > PRC_NCMDS)
139 return;
140 /* INCOMPLETE */
141}
142
143/*ARGSUSED*/
144int
145raw_usrreq(so, req, m, nam, control)
146 struct socket *so;
147 int req;
148 struct mbuf *m, *nam, *control;
149{
150 register struct rawcb *rp = sotorawcb(so);
151 register int error = 0;
152 int len;
153
154 if (req == PRU_CONTROL)
155 return (EOPNOTSUPP);
156 if (control && control->m_len) {
157 error = EOPNOTSUPP;
158 goto release;
159 }
160 if (rp == 0) {
161 error = EINVAL;
162 goto release;
163 }
164 switch (req) {
165
166 /*
167 * Allocate a raw control block and fill in the
168 * necessary info to allow packets to be routed to
169 * the appropriate raw interface routine.
170 */
171 case PRU_ATTACH:
172 if ((so->so_state & SS_PRIV) == 0) {
173 error = EACCES;
174 break;
175 }
176 error = raw_attach(so, (int)nam);
177 break;
178
179 /*
180 * Destroy state just before socket deallocation.
181 * Flush data or not depending on the options.
182 */
183 case PRU_DETACH:
184 if (rp == 0) {
185 error = ENOTCONN;
186 break;
187 }
188 raw_detach(rp);
189 break;
190
191 /*
192 * If a socket isn't bound to a single address,
193 * the raw input routine will hand it anything
194 * within that protocol family (assuming there's
195 * nothing else around it should go to).
196 */
197 case PRU_CONNECT:
198 error = EINVAL;
199#if 0
200 if (rp->rcb_faddr) {
201 error = EISCONN;
202 break;
203 }
204 nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
205 rp->rcb_faddr = mtod(nam, struct sockaddr *);
206 soisconnected(so);
207#endif
208 break;
209
210 case PRU_BIND:
211 error = EINVAL;
212#if 0
213 if (rp->rcb_laddr) {
214 error = EINVAL; /* XXX */
215 break;
216 }
217 error = raw_bind(so, nam);
218#endif
219 break;
220
221 case PRU_CONNECT2:
222 error = EOPNOTSUPP;
223 goto release;
224
225 case PRU_DISCONNECT:
226 if (rp->rcb_faddr == 0) {
227 error = ENOTCONN;
228 break;
229 }
230 raw_disconnect(rp);
231 soisdisconnected(so);
232 break;
233
234 /*
235 * Mark the connection as being incapable of further input.
236 */
237 case PRU_SHUTDOWN:
238 socantsendmore(so);
239 break;
240
241 /*
242 * Ship a packet out. The appropriate raw output
243 * routine handles any massaging necessary.
244 */
245 case PRU_SEND:
246 if (nam) {
247 if (rp->rcb_faddr) {
248 error = EISCONN;
249 break;
250 }
251 rp->rcb_faddr = mtod(nam, struct sockaddr *);
252 } else if (rp->rcb_faddr == 0) {
253 error = ENOTCONN;
254 break;
255 }
256 error = (*so->so_proto->pr_output)(m, so);
257 m = NULL;
258 if (nam)
259 rp->rcb_faddr = 0;
260 break;
261
262 case PRU_ABORT:
263 raw_disconnect(rp);
264 sofree(so);
265 soisdisconnected(so);
266 break;
267
268 case PRU_SENSE:
269 /*
270 * stat: don't bother with a blocksize.
271 */
272 return (0);
273
274 /*
275 * Not supported.
276 */
277 case PRU_RCVOOB:
278 case PRU_RCVD:
279 return(EOPNOTSUPP);
280
281 case PRU_LISTEN:
282 case PRU_ACCEPT:
283 case PRU_SENDOOB:
284 error = EOPNOTSUPP;
285 break;
286
287 case PRU_SOCKADDR:
288 if (rp->rcb_laddr == 0) {
289 error = EINVAL;
290 break;
291 }
292 len = rp->rcb_laddr->sa_len;
293 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
294 nam->m_len = len;
295 break;
296
297 case PRU_PEERADDR:
298 if (rp->rcb_faddr == 0) {
299 error = ENOTCONN;
300 break;
301 }
302 len = rp->rcb_faddr->sa_len;
303 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
304 nam->m_len = len;
305 break;
306
307 default:
308 panic("raw_usrreq");
309 }
310release:
311 if (m != NULL)
312 m_freem(m);
313 return (error);
314}
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. 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 *
33 * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93
34 * $Id: raw_usrreq.c,v 1.6 1995/05/30 08:08:22 rgrimes Exp $
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/mbuf.h>
40#include <sys/domain.h>
41#include <sys/protosw.h>
42#include <sys/socket.h>
43#include <sys/socketvar.h>
44#include <sys/errno.h>
45
46#include <net/if.h>
47#include <net/route.h>
48#include <net/netisr.h>
49#include <net/raw_cb.h>
50
51/*
52 * Initialize raw connection block q.
53 */
54void
55raw_init()
56{
57
58 rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
59}
60
61
62/*
63 * Raw protocol input routine. Find the socket
64 * associated with the packet(s) and move them over. If
65 * nothing exists for this packet, drop it.
66 */
67/*
68 * Raw protocol interface.
69 */
70void
71raw_input(m0, proto, src, dst)
72 struct mbuf *m0;
73 register struct sockproto *proto;
74 struct sockaddr *src, *dst;
75{
76 register struct rawcb *rp;
77 register struct mbuf *m = m0;
78 register int sockets = 0;
79 struct socket *last;
80
81 last = 0;
82 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
83 if (rp->rcb_proto.sp_family != proto->sp_family)
84 continue;
85 if (rp->rcb_proto.sp_protocol &&
86 rp->rcb_proto.sp_protocol != proto->sp_protocol)
87 continue;
88 /*
89 * We assume the lower level routines have
90 * placed the address in a canonical format
91 * suitable for a structure comparison.
92 *
93 * Note that if the lengths are not the same
94 * the comparison will fail at the first byte.
95 */
96#define equal(a1, a2) \
97 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
98 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
99 continue;
100 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
101 continue;
102 if (last) {
103 struct mbuf *n;
104 n = m_copy(m, 0, (int)M_COPYALL);
105 if (n) {
106 if (sbappendaddr(&last->so_rcv, src,
107 n, (struct mbuf *)0) == 0)
108 /* should notify about lost packet */
109 m_freem(n);
110 else {
111 sorwakeup(last);
112 sockets++;
113 }
114 }
115 }
116 last = rp->rcb_socket;
117 }
118 if (last) {
119 if (sbappendaddr(&last->so_rcv, src,
120 m, (struct mbuf *)0) == 0)
121 m_freem(m);
122 else {
123 sorwakeup(last);
124 sockets++;
125 }
126 } else
127 m_freem(m);
128}
129
130/*ARGSUSED*/
131void
132raw_ctlinput(cmd, arg, dummy)
133 int cmd;
134 struct sockaddr *arg;
135 void *dummy;
136{
137
138 if (cmd < 0 || cmd > PRC_NCMDS)
139 return;
140 /* INCOMPLETE */
141}
142
143/*ARGSUSED*/
144int
145raw_usrreq(so, req, m, nam, control)
146 struct socket *so;
147 int req;
148 struct mbuf *m, *nam, *control;
149{
150 register struct rawcb *rp = sotorawcb(so);
151 register int error = 0;
152 int len;
153
154 if (req == PRU_CONTROL)
155 return (EOPNOTSUPP);
156 if (control && control->m_len) {
157 error = EOPNOTSUPP;
158 goto release;
159 }
160 if (rp == 0) {
161 error = EINVAL;
162 goto release;
163 }
164 switch (req) {
165
166 /*
167 * Allocate a raw control block and fill in the
168 * necessary info to allow packets to be routed to
169 * the appropriate raw interface routine.
170 */
171 case PRU_ATTACH:
172 if ((so->so_state & SS_PRIV) == 0) {
173 error = EACCES;
174 break;
175 }
176 error = raw_attach(so, (int)nam);
177 break;
178
179 /*
180 * Destroy state just before socket deallocation.
181 * Flush data or not depending on the options.
182 */
183 case PRU_DETACH:
184 if (rp == 0) {
185 error = ENOTCONN;
186 break;
187 }
188 raw_detach(rp);
189 break;
190
191 /*
192 * If a socket isn't bound to a single address,
193 * the raw input routine will hand it anything
194 * within that protocol family (assuming there's
195 * nothing else around it should go to).
196 */
197 case PRU_CONNECT:
198 error = EINVAL;
199#if 0
200 if (rp->rcb_faddr) {
201 error = EISCONN;
202 break;
203 }
204 nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
205 rp->rcb_faddr = mtod(nam, struct sockaddr *);
206 soisconnected(so);
207#endif
208 break;
209
210 case PRU_BIND:
211 error = EINVAL;
212#if 0
213 if (rp->rcb_laddr) {
214 error = EINVAL; /* XXX */
215 break;
216 }
217 error = raw_bind(so, nam);
218#endif
219 break;
220
221 case PRU_CONNECT2:
222 error = EOPNOTSUPP;
223 goto release;
224
225 case PRU_DISCONNECT:
226 if (rp->rcb_faddr == 0) {
227 error = ENOTCONN;
228 break;
229 }
230 raw_disconnect(rp);
231 soisdisconnected(so);
232 break;
233
234 /*
235 * Mark the connection as being incapable of further input.
236 */
237 case PRU_SHUTDOWN:
238 socantsendmore(so);
239 break;
240
241 /*
242 * Ship a packet out. The appropriate raw output
243 * routine handles any massaging necessary.
244 */
245 case PRU_SEND:
246 if (nam) {
247 if (rp->rcb_faddr) {
248 error = EISCONN;
249 break;
250 }
251 rp->rcb_faddr = mtod(nam, struct sockaddr *);
252 } else if (rp->rcb_faddr == 0) {
253 error = ENOTCONN;
254 break;
255 }
256 error = (*so->so_proto->pr_output)(m, so);
257 m = NULL;
258 if (nam)
259 rp->rcb_faddr = 0;
260 break;
261
262 case PRU_ABORT:
263 raw_disconnect(rp);
264 sofree(so);
265 soisdisconnected(so);
266 break;
267
268 case PRU_SENSE:
269 /*
270 * stat: don't bother with a blocksize.
271 */
272 return (0);
273
274 /*
275 * Not supported.
276 */
277 case PRU_RCVOOB:
278 case PRU_RCVD:
279 return(EOPNOTSUPP);
280
281 case PRU_LISTEN:
282 case PRU_ACCEPT:
283 case PRU_SENDOOB:
284 error = EOPNOTSUPP;
285 break;
286
287 case PRU_SOCKADDR:
288 if (rp->rcb_laddr == 0) {
289 error = EINVAL;
290 break;
291 }
292 len = rp->rcb_laddr->sa_len;
293 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
294 nam->m_len = len;
295 break;
296
297 case PRU_PEERADDR:
298 if (rp->rcb_faddr == 0) {
299 error = ENOTCONN;
300 break;
301 }
302 len = rp->rcb_faddr->sa_len;
303 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
304 nam->m_len = len;
305 break;
306
307 default:
308 panic("raw_usrreq");
309 }
310release:
311 if (m != NULL)
312 m_freem(m);
313 return (error);
314}