FreeBSD/Linux Kernel Cross Reference
sys/net/raw_usrreq.c
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 * $FreeBSD: releng/5.0/sys/net/raw_usrreq.c 107113 2002-11-20 19:00:54Z luigi $
35 */
36
37 #include <sys/param.h>
38 #include <sys/lock.h>
39 #include <sys/mbuf.h>
40 #include <sys/protosw.h>
41 #include <sys/signalvar.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/sx.h>
45 #include <sys/systm.h>
46
47 #include <net/raw_cb.h>
48
49 /*
50 * Initialize raw connection block q.
51 */
52 void
53 raw_init()
54 {
55 LIST_INIT(&rawcb_list);
56 }
57
58
59 /*
60 * Raw protocol input routine. Find the socket
61 * associated with the packet(s) and move them over. If
62 * nothing exists for this packet, drop it.
63 */
64 /*
65 * Raw protocol interface.
66 */
67 void
68 raw_input(m0, proto, src, dst)
69 struct mbuf *m0;
70 register struct sockproto *proto;
71 struct sockaddr *src, *dst;
72 {
73 register struct rawcb *rp;
74 register struct mbuf *m = m0;
75 register int sockets = 0;
76 struct socket *last;
77
78 last = 0;
79 LIST_FOREACH(rp, &rawcb_list, list) {
80 if (rp->rcb_proto.sp_family != proto->sp_family)
81 continue;
82 if (rp->rcb_proto.sp_protocol &&
83 rp->rcb_proto.sp_protocol != proto->sp_protocol)
84 continue;
85 /*
86 * We assume the lower level routines have
87 * placed the address in a canonical format
88 * suitable for a structure comparison.
89 *
90 * Note that if the lengths are not the same
91 * the comparison will fail at the first byte.
92 */
93 #define equal(a1, a2) \
94 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
95 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
96 continue;
97 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
98 continue;
99 if (last) {
100 struct mbuf *n;
101 n = m_copy(m, 0, (int)M_COPYALL);
102 if (n) {
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, dummy)
130 int cmd;
131 struct sockaddr *arg;
132 void *dummy;
133 {
134
135 if (cmd < 0 || cmd > PRC_NCMDS)
136 return;
137 /* INCOMPLETE */
138 }
139
140 static int
141 raw_uabort(struct socket *so)
142 {
143 struct rawcb *rp = sotorawcb(so);
144
145 if (rp == 0)
146 return EINVAL;
147 raw_disconnect(rp);
148 sotryfree(so);
149 soisdisconnected(so); /* XXX huh? called after the sofree()? */
150 return 0;
151 }
152
153 /* pru_accept is EOPNOTSUPP */
154
155 static int
156 raw_uattach(struct socket *so, int proto, struct thread *td)
157 {
158 struct rawcb *rp = sotorawcb(so);
159 int error;
160
161 if (rp == 0)
162 return EINVAL;
163 if (td && (error = suser(td)) != 0)
164 return error;
165 return raw_attach(so, proto);
166 }
167
168 static int
169 raw_ubind(struct socket *so, struct sockaddr *nam, struct thread *td)
170 {
171 return EINVAL;
172 }
173
174 static int
175 raw_uconnect(struct socket *so, struct sockaddr *nam, struct thread *td)
176 {
177 return EINVAL;
178 }
179
180 /* pru_connect2 is EOPNOTSUPP */
181 /* pru_control is EOPNOTSUPP */
182
183 static int
184 raw_udetach(struct socket *so)
185 {
186 struct rawcb *rp = sotorawcb(so);
187
188 if (rp == 0)
189 return EINVAL;
190
191 raw_detach(rp);
192 return 0;
193 }
194
195 static int
196 raw_udisconnect(struct socket *so)
197 {
198 struct rawcb *rp = sotorawcb(so);
199
200 if (rp == 0)
201 return EINVAL;
202 if (rp->rcb_faddr == 0) {
203 return ENOTCONN;
204 }
205 raw_disconnect(rp);
206 soisdisconnected(so);
207 return 0;
208 }
209
210 /* pru_listen is EOPNOTSUPP */
211
212 static int
213 raw_upeeraddr(struct socket *so, struct sockaddr **nam)
214 {
215 struct rawcb *rp = sotorawcb(so);
216
217 if (rp == 0)
218 return EINVAL;
219 if (rp->rcb_faddr == 0) {
220 return ENOTCONN;
221 }
222 *nam = dup_sockaddr(rp->rcb_faddr, 1);
223 return 0;
224 }
225
226 /* pru_rcvd is EOPNOTSUPP */
227 /* pru_rcvoob is EOPNOTSUPP */
228
229 static int
230 raw_usend(struct socket *so, int flags, struct mbuf *m,
231 struct sockaddr *nam, struct mbuf *control, struct thread *td)
232 {
233 int error;
234 struct rawcb *rp = sotorawcb(so);
235
236 if (rp == 0) {
237 error = EINVAL;
238 goto release;
239 }
240
241 if (flags & PRUS_OOB) {
242 error = EOPNOTSUPP;
243 goto release;
244 }
245
246 if (control && control->m_len) {
247 error = EOPNOTSUPP;
248 goto release;
249 }
250 if (nam) {
251 if (rp->rcb_faddr) {
252 error = EISCONN;
253 goto release;
254 }
255 rp->rcb_faddr = nam;
256 } else if (rp->rcb_faddr == 0) {
257 error = ENOTCONN;
258 goto release;
259 }
260 error = (*so->so_proto->pr_output)(m, so);
261 m = NULL;
262 if (nam)
263 rp->rcb_faddr = 0;
264 release:
265 if (m != NULL)
266 m_freem(m);
267 return (error);
268 }
269
270 /* pru_sense is null */
271
272 static int
273 raw_ushutdown(struct socket *so)
274 {
275 struct rawcb *rp = sotorawcb(so);
276
277 if (rp == 0)
278 return EINVAL;
279 socantsendmore(so);
280 return 0;
281 }
282
283 static int
284 raw_usockaddr(struct socket *so, struct sockaddr **nam)
285 {
286 struct rawcb *rp = sotorawcb(so);
287
288 if (rp == 0)
289 return EINVAL;
290 if (rp->rcb_laddr == 0)
291 return EINVAL;
292 *nam = dup_sockaddr(rp->rcb_laddr, 1);
293 return 0;
294 }
295
296 struct pr_usrreqs raw_usrreqs = {
297 raw_uabort, pru_accept_notsupp, raw_uattach, raw_ubind, raw_uconnect,
298 pru_connect2_notsupp, pru_control_notsupp, raw_udetach,
299 raw_udisconnect, pru_listen_notsupp, raw_upeeraddr, pru_rcvd_notsupp,
300 pru_rcvoob_notsupp, raw_usend, pru_sense_null, raw_ushutdown,
301 raw_usockaddr, sosend, soreceive, sopoll
302 };
Cache object: 36650d465491e33020debe22212fea5c
|