xref: /xnu-10063.121.3/bsd/net/raw_usrreq.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1 /*
2  * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * Copyright (c) 1980, 1986, 1993
30  *	The Regents of the University of California.  All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  * 1. Redistributions of source code must retain the above copyright
36  *    notice, this list of conditions and the following disclaimer.
37  * 2. Redistributions in binary form must reproduce the above copyright
38  *    notice, this list of conditions and the following disclaimer in the
39  *    documentation and/or other materials provided with the distribution.
40  * 3. All advertising materials mentioning features or use of this software
41  *    must display the following acknowledgement:
42  *	This product includes software developed by the University of
43  *	California, Berkeley and its contributors.
44  * 4. Neither the name of the University nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58  * SUCH DAMAGE.
59  *
60  *	@(#)raw_usrreq.c	8.1 (Berkeley) 6/10/93
61  * $FreeBSD: src/sys/net/raw_usrreq.c,v 1.18 1999/08/28 00:48:28 peter Exp $
62  */
63 
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/mbuf.h>
67 #include <sys/proc.h>
68 #include <sys/domain.h>
69 #include <sys/protosw.h>
70 #include <sys/socket.h>
71 #include <sys/socketvar.h>
72 #include <kern/locks.h>
73 
74 #include <net/raw_cb.h>
75 
76 static LCK_GRP_DECLARE(raw_mtx_grp, "rawcb");
77 LCK_MTX_DECLARE(raw_mtx, &raw_mtx_grp);   /*### global raw cb mutex for now */
78 
79 
80 /*
81  * Raw protocol input routine.  Find the socket
82  * associated with the packet(s) and move them over.  If
83  * nothing exists for this packet, drop it.
84  */
85 /*
86  * Raw protocol interface.
87  */
88 void
raw_input(struct mbuf * m0,struct sockproto * proto,struct sockaddr * src,struct sockaddr * dst)89 raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src,
90     struct sockaddr *dst)
91 {
92 	struct rawcb *rp;
93 	struct mbuf *m = m0;
94 	int sockets = 0;
95 	struct socket *last;
96 	int error;
97 
98 //####LD raw_input is called from many places, input & output path. We have to assume the
99 //####LD socket we'll find and need to append to is unlocked.
100 //####LD calls from the output (locked) path need to make sure the socket is not locked when
101 //####LD we call in raw_input
102 	last = NULL;
103 	lck_mtx_lock(&raw_mtx);
104 	LIST_FOREACH(rp, &rawcb_list, list) {
105 		if (rp->rcb_proto.sp_family != proto->sp_family) {
106 			continue;
107 		}
108 		if (rp->rcb_proto.sp_protocol &&
109 		    rp->rcb_proto.sp_protocol != proto->sp_protocol) {
110 			continue;
111 		}
112 		/*
113 		 * We assume the lower level routines have
114 		 * placed the address in a canonical format
115 		 * suitable for a structure comparison.
116 		 *
117 		 * Note that if the lengths are not the same
118 		 * the comparison will fail at the first byte.
119 		 */
120 #define equal(a1, a2) \
121   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
122 		if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) {
123 			continue;
124 		}
125 		if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) {
126 			continue;
127 		}
128 		if (last) {
129 			struct mbuf *n;
130 			n = m_copy(m, 0, (int)M_COPYALL);
131 			if (n) {
132 				socket_lock(last, 1);
133 				if (sbappendaddr(&last->so_rcv, src,
134 				    n, (struct mbuf *)0, &error) != 0) {
135 					sorwakeup(last);
136 					sockets++;
137 				}
138 				socket_unlock(last, 1);
139 			}
140 		}
141 		last = rp->rcb_socket;
142 	}
143 	if (last) {
144 		socket_lock(last, 1);
145 		if (sbappendaddr(&last->so_rcv, src,
146 		    m, (struct mbuf *)0, &error) != 0) {
147 			sorwakeup(last);
148 			sockets++;
149 		}
150 		socket_unlock(last, 1);
151 	} else {
152 		m_freem(m);
153 	}
154 	lck_mtx_unlock(&raw_mtx);
155 }
156 
157 /*ARGSUSED*/
158 void
raw_ctlinput(int cmd,__unused struct sockaddr * arg,__unused void * dummy,__unused struct ifnet * ifp)159 raw_ctlinput(int cmd, __unused struct sockaddr *arg, __unused void *dummy,
160     __unused struct ifnet *ifp)
161 {
162 	if (cmd < 0 || cmd >= PRC_NCMDS) {
163 		return;
164 	}
165 	/* INCOMPLETE */
166 }
167 
168 static int
raw_uabort(struct socket * so)169 raw_uabort(struct socket *so)
170 {
171 	struct rawcb *rp = sotorawcb(so);
172 
173 	lck_mtx_t * mutex_held;
174 	if (so->so_proto->pr_getlock != NULL) {
175 		mutex_held = (*so->so_proto->pr_getlock)(so, 0);
176 	} else {
177 		mutex_held = so->so_proto->pr_domain->dom_mtx;
178 	}
179 	LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
180 
181 	if (rp == 0) {
182 		return EINVAL;
183 	}
184 	raw_disconnect(rp);
185 	sofree(so);
186 	soisdisconnected(so);
187 	return 0;
188 }
189 
190 /* pru_accept is EOPNOTSUPP */
191 
192 static int
raw_uattach(struct socket * so,int proto,__unused struct proc * p)193 raw_uattach(struct socket *so, int proto, __unused struct proc *p)
194 {
195 	struct rawcb *rp = sotorawcb(so);
196 
197 	if (rp == 0) {
198 		return EINVAL;
199 	}
200 	if ((so->so_state & SS_PRIV) == 0) {
201 		return EPERM;
202 	}
203 	return raw_attach(so, proto);
204 }
205 
206 static int
raw_ubind(__unused struct socket * so,__unused struct sockaddr * nam,__unused struct proc * p)207 raw_ubind(__unused struct socket *so, __unused struct sockaddr *nam, __unused struct proc *p)
208 {
209 	return EINVAL;
210 }
211 
212 static int
raw_uconnect(__unused struct socket * so,__unused struct sockaddr * nam,__unused struct proc * p)213 raw_uconnect(__unused struct socket *so, __unused struct sockaddr *nam, __unused struct proc *p)
214 {
215 	return EINVAL;
216 }
217 
218 /* pru_connect2 is EOPNOTSUPP */
219 /* pru_control is EOPNOTSUPP */
220 
221 static int
raw_udetach(struct socket * so)222 raw_udetach(struct socket *so)
223 {
224 	struct rawcb *rp = sotorawcb(so);
225 
226 	lck_mtx_t * mutex_held;
227 	if (so->so_proto->pr_getlock != NULL) {
228 		mutex_held = (*so->so_proto->pr_getlock)(so, 0);
229 	} else {
230 		mutex_held = so->so_proto->pr_domain->dom_mtx;
231 	}
232 	LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
233 	if (rp == 0) {
234 		return EINVAL;
235 	}
236 
237 	raw_detach_nofree(rp);
238 	kfree_type(struct rawcb, rp);
239 	return 0;
240 }
241 
242 static int
raw_udisconnect(struct socket * so)243 raw_udisconnect(struct socket *so)
244 {
245 	struct rawcb *rp = sotorawcb(so);
246 
247 	if (rp == 0) {
248 		return EINVAL;
249 	}
250 	if (rp->rcb_faddr == 0) {
251 		return ENOTCONN;
252 	}
253 	raw_disconnect(rp);
254 	soisdisconnected(so);
255 	return 0;
256 }
257 
258 /* pru_listen is EOPNOTSUPP */
259 
260 static int
raw_upeeraddr(struct socket * so,struct sockaddr ** nam)261 raw_upeeraddr(struct socket *so, struct sockaddr **nam)
262 {
263 	struct rawcb *rp = sotorawcb(so);
264 
265 	if (rp == 0) {
266 		return EINVAL;
267 	}
268 	if (rp->rcb_faddr == 0) {
269 		return ENOTCONN;
270 	}
271 	*nam = dup_sockaddr(rp->rcb_faddr, 1);
272 	return 0;
273 }
274 
275 /* pru_rcvd is EOPNOTSUPP */
276 /* pru_rcvoob is EOPNOTSUPP */
277 
278 static int
raw_usend(struct socket * so,int flags,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,__unused struct proc * p)279 raw_usend(struct socket *so, int flags, struct mbuf *m,
280     struct sockaddr *nam, struct mbuf *control, __unused struct proc *p)
281 {
282 	int error;
283 	struct rawcb *rp = sotorawcb(so);
284 
285 	lck_mtx_t * mutex_held;
286 	if (so->so_proto->pr_getlock != NULL) {
287 		mutex_held = (*so->so_proto->pr_getlock)(so, 0);
288 	} else {
289 		mutex_held = so->so_proto->pr_domain->dom_mtx;
290 	}
291 	LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
292 
293 	if (rp == 0) {
294 		error = EINVAL;
295 		goto release;
296 	}
297 
298 	if (flags & PRUS_OOB) {
299 		error = EOPNOTSUPP;
300 		goto release;
301 	}
302 
303 	if (so->so_proto->pr_output == NULL) {
304 		error = EOPNOTSUPP;
305 		goto release;
306 	}
307 
308 	if (control != NULL) {
309 		m_freem(control);
310 		error = EOPNOTSUPP;
311 		goto release;
312 	}
313 	if (nam) {
314 		if (rp->rcb_faddr) {
315 			error = EISCONN;
316 			goto release;
317 		}
318 		rp->rcb_faddr = nam;
319 	} else if (rp->rcb_faddr == 0) {
320 		error = ENOTCONN;
321 		goto release;
322 	}
323 	error = (*so->so_proto->pr_output)(m, so);
324 	m = NULL;
325 	if (nam) {
326 		rp->rcb_faddr = NULL;
327 	}
328 release:
329 	if (m != NULL) {
330 		m_freem(m);
331 	}
332 	return error;
333 }
334 
335 /* pru_sense is null */
336 
337 static int
raw_ushutdown(struct socket * so)338 raw_ushutdown(struct socket *so)
339 {
340 	struct rawcb *rp = sotorawcb(so);
341 	lck_mtx_t * mutex_held;
342 	if (so->so_proto->pr_getlock != NULL) {
343 		mutex_held = (*so->so_proto->pr_getlock)(so, 0);
344 	} else {
345 		mutex_held = so->so_proto->pr_domain->dom_mtx;
346 	}
347 	LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
348 
349 	if (rp == 0) {
350 		return EINVAL;
351 	}
352 	socantsendmore(so);
353 	return 0;
354 }
355 
356 static int
raw_usockaddr(struct socket * so,struct sockaddr ** nam)357 raw_usockaddr(struct socket *so, struct sockaddr **nam)
358 {
359 	struct rawcb *rp = sotorawcb(so);
360 
361 	if (rp == 0) {
362 		return EINVAL;
363 	}
364 	if (rp->rcb_laddr == 0) {
365 		return EINVAL;
366 	}
367 	*nam = dup_sockaddr(rp->rcb_laddr, 1);
368 	return 0;
369 }
370 
371 struct pr_usrreqs raw_usrreqs = {
372 	.pru_abort =            raw_uabort,
373 	.pru_attach =           raw_uattach,
374 	.pru_bind =             raw_ubind,
375 	.pru_connect =          raw_uconnect,
376 	.pru_detach =           raw_udetach,
377 	.pru_disconnect =       raw_udisconnect,
378 	.pru_peeraddr =         raw_upeeraddr,
379 	.pru_send =             raw_usend,
380 	.pru_shutdown =         raw_ushutdown,
381 	.pru_sockaddr =         raw_usockaddr,
382 	.pru_sosend =           sosend,
383 	.pru_soreceive =        soreceive,
384 };
385