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