raw_usrreq.c revision 1.8 1 /* $NetBSD: raw_usrreq.c,v 1.8 1994/06/29 06:36:40 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
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 *
35 * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93
36 */
37
38 #include <sys/param.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 */
54 void
55 raw_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 */
70 void
71 raw_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 if (n = m_copy(m, 0, (int)M_COPYALL)) {
105 if (sbappendaddr(&last->so_rcv, src,
106 n, (struct mbuf *)0) == 0)
107 /* should notify about lost packet */
108 m_freem(n);
109 else {
110 sorwakeup(last);
111 sockets++;
112 }
113 }
114 }
115 last = rp->rcb_socket;
116 }
117 if (last) {
118 if (sbappendaddr(&last->so_rcv, src,
119 m, (struct mbuf *)0) == 0)
120 m_freem(m);
121 else {
122 sorwakeup(last);
123 sockets++;
124 }
125 } else
126 m_freem(m);
127 }
128
129 /*ARGSUSED*/
130 void
131 raw_ctlinput(cmd, arg)
132 int cmd;
133 struct sockaddr *arg;
134 {
135
136 if (cmd < 0 || cmd > PRC_NCMDS)
137 return;
138 /* INCOMPLETE */
139 }
140
141 /*ARGSUSED*/
142 int
143 raw_usrreq(so, req, m, nam, control)
144 struct socket *so;
145 int req;
146 struct mbuf *m, *nam, *control;
147 {
148 register struct rawcb *rp = sotorawcb(so);
149 register int error = 0;
150 int len;
151
152 if (req == PRU_CONTROL)
153 return (EOPNOTSUPP);
154 if (control && control->m_len) {
155 error = EOPNOTSUPP;
156 goto release;
157 }
158 if (rp == 0) {
159 error = EINVAL;
160 goto release;
161 }
162 switch (req) {
163
164 /*
165 * Allocate a raw control block and fill in the
166 * necessary info to allow packets to be routed to
167 * the appropriate raw interface routine.
168 */
169 case PRU_ATTACH:
170 if ((so->so_state & SS_PRIV) == 0) {
171 error = EACCES;
172 break;
173 }
174 error = raw_attach(so, (int)nam);
175 break;
176
177 /*
178 * Destroy state just before socket deallocation.
179 * Flush data or not depending on the options.
180 */
181 case PRU_DETACH:
182 if (rp == 0) {
183 error = ENOTCONN;
184 break;
185 }
186 raw_detach(rp);
187 break;
188
189 #ifdef notdef
190 /*
191 * If a socket isn't bound to a single address,
192 * the raw input routine will hand it anything
193 * within that protocol family (assuming there's
194 * nothing else around it should go to).
195 */
196 case PRU_CONNECT:
197 if (rp->rcb_faddr) {
198 error = EISCONN;
199 break;
200 }
201 nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
202 rp->rcb_faddr = mtod(nam, struct sockaddr *);
203 soisconnected(so);
204 break;
205
206 case PRU_BIND:
207 if (rp->rcb_laddr) {
208 error = EINVAL; /* XXX */
209 break;
210 }
211 error = raw_bind(so, nam);
212 break;
213 #endif
214
215 case PRU_CONNECT2:
216 error = EOPNOTSUPP;
217 goto release;
218
219 case PRU_DISCONNECT:
220 if (rp->rcb_faddr == 0) {
221 error = ENOTCONN;
222 break;
223 }
224 raw_disconnect(rp);
225 soisdisconnected(so);
226 break;
227
228 /*
229 * Mark the connection as being incapable of further input.
230 */
231 case PRU_SHUTDOWN:
232 socantsendmore(so);
233 break;
234
235 /*
236 * Ship a packet out. The appropriate raw output
237 * routine handles any massaging necessary.
238 */
239 case PRU_SEND:
240 if (nam) {
241 if (rp->rcb_faddr) {
242 error = EISCONN;
243 break;
244 }
245 rp->rcb_faddr = mtod(nam, struct sockaddr *);
246 } else if (rp->rcb_faddr == 0) {
247 error = ENOTCONN;
248 break;
249 }
250 error = (*so->so_proto->pr_output)(m, so);
251 m = NULL;
252 if (nam)
253 rp->rcb_faddr = 0;
254 break;
255
256 case PRU_ABORT:
257 raw_disconnect(rp);
258 sofree(so);
259 soisdisconnected(so);
260 break;
261
262 case PRU_SENSE:
263 /*
264 * stat: don't bother with a blocksize.
265 */
266 return (0);
267
268 /*
269 * Not supported.
270 */
271 case PRU_RCVOOB:
272 case PRU_RCVD:
273 return(EOPNOTSUPP);
274
275 case PRU_LISTEN:
276 case PRU_ACCEPT:
277 case PRU_SENDOOB:
278 error = EOPNOTSUPP;
279 break;
280
281 case PRU_SOCKADDR:
282 if (rp->rcb_laddr == 0) {
283 error = EINVAL;
284 break;
285 }
286 len = rp->rcb_laddr->sa_len;
287 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
288 nam->m_len = len;
289 break;
290
291 case PRU_PEERADDR:
292 if (rp->rcb_faddr == 0) {
293 error = ENOTCONN;
294 break;
295 }
296 len = rp->rcb_faddr->sa_len;
297 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
298 nam->m_len = len;
299 break;
300
301 default:
302 panic("raw_usrreq");
303 }
304 release:
305 if (m != NULL)
306 m_freem(m);
307 return (error);
308 }
309