1 /*
2 * 43BSD_SOCKET.C - 4.3BSD compatibility socket syscalls
3 *
4 * Copyright (c) 1982, 1986, 1989, 1990, 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 * The original versions of these syscalls used to live in
36 * kern/uipc_syscalls.c. These are heavily modified to use the
37 * new split syscalls.
38 */
39
40 #include "opt_compat.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/sysproto.h>
46 #include <sys/kern_syscall.h>
47 #include <sys/malloc.h>
48 #include <sys/mbuf.h>
49 #include <sys/proc.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/uio.h>
53
54 #include <sys/mplock2.h>
55
56 #include "43bsd_socket.h"
57
58 /*
59 * System call interface to the socket abstraction.
60 */
61
62 static int
63 compat_43_getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
64 {
65 struct sockaddr *sa;
66 int error;
67
68 *namp = NULL;
69 if (len > SOCK_MAXADDRLEN)
70 return ENAMETOOLONG;
71 if (len < offsetof(struct sockaddr, sa_data[0]))
72 return EDOM;
73 sa = kmalloc(len, M_SONAME, M_WAITOK);
74 error = copyin(uaddr, sa, len);
75 if (error) {
76 kfree(sa, M_SONAME);
77 } else {
78 /*
79 * Convert to the 4.4BSD sockaddr structure.
80 */
81 sa->sa_family = sa->sa_len;
82 sa->sa_len = len;
83 *namp = sa;
84 }
85 return error;
86 }
87
88 static int
89 compat_43_copyout_sockaddr(struct sockaddr *sa, caddr_t uaddr, int sa_len)
90 {
91 int error;
92
93 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
94 error = copyout(sa, uaddr, sa_len);
95
96 return (error);
97 }
98
99 /*
100 * MPALMOSTSAFE
101 */
102 int
103 sys_oaccept(struct accept_args *uap)
104 {
105 struct sockaddr *sa = NULL;
106 int sa_len;
107 int error;
108
109 if (uap->name) {
110 error = copyin(uap->anamelen, &sa_len, sizeof(sa_len));
111 if (error)
112 return (error);
113
114 get_mplock();
115 error = kern_accept(uap->s, 0, &sa, &sa_len,
116 &uap->sysmsg_iresult);
117 rel_mplock();
118
119 if (error) {
120 /*
121 * return a namelen of zero for older code which
122 * might ignore the return value from accept.
123 */
124 sa_len = 0;
125 copyout(&sa_len, uap->anamelen, sizeof(*uap->anamelen));
126 } else {
127 compat_43_copyout_sockaddr(sa, uap->name, sa_len);
128 if (error == 0) {
129 error = copyout(&sa_len, uap->anamelen,
130 sizeof(*uap->anamelen));
131 }
132 }
133 if (sa)
134 kfree(sa, M_SONAME);
135 } else {
136 get_mplock();
137 error = kern_accept(uap->s, 0, NULL, 0, &uap->sysmsg_iresult);
138 rel_mplock();
139 }
140 return (error);
141 }
142
143 /*
144 * MPALMOSTSAFE
145 */
146 int
147 sys_ogetsockname(struct getsockname_args *uap)
148 {
149 struct sockaddr *sa = NULL;
150 int error, sa_len;
151
152 error = copyin(uap->alen, &sa_len, sizeof(sa_len));
153 if (error)
154 return (error);
155
156 get_mplock();
157 error = kern_getsockname(uap->fdes, &sa, &sa_len);
158 rel_mplock();
159
160 if (error == 0)
161 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
162 if (error == 0) {
163 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
164 }
165 if (sa)
166 kfree(sa, M_SONAME);
167 return (error);
168 }
169
170 /*
171 * MPALMOSTSAFE
172 */
173 int
174 sys_ogetpeername(struct ogetpeername_args *uap)
175 {
176 struct sockaddr *sa = NULL;
177 int error, sa_len;
178
179 error = copyin(uap->alen, &sa_len, sizeof(sa_len));
180 if (error)
181 return (error);
182
183 get_mplock();
184 error = kern_getpeername(uap->fdes, &sa, &sa_len);
185 rel_mplock();
186
187 if (error == 0) {
188 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
189 }
190 if (error == 0)
191 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
192 if (sa)
193 kfree(sa, M_SONAME);
194 return (error);
195 }
196
197 /*
198 * MPALMOSTSAFE
199 */
200 int
201 sys_osend(struct osend_args *uap)
202 {
203 struct thread *td = curthread;
204 struct uio auio;
205 struct iovec aiov;
206 int error;
207
208 aiov.iov_base = uap->buf;
209 aiov.iov_len = uap->len;
210 auio.uio_iov = &aiov;
211 auio.uio_iovcnt = 1;
212 auio.uio_offset = 0;
213 auio.uio_resid = uap->len;
214 auio.uio_segflg = UIO_USERSPACE;
215 auio.uio_rw = UIO_WRITE;
216 auio.uio_td = td;
217
218 get_mplock();
219 error = kern_sendmsg(uap->s, NULL, &auio, NULL, uap->flags,
220 &uap->sysmsg_szresult);
221 rel_mplock();
222
223 return (error);
224 }
225
226 /*
227 * MPALMOSTSAFE
228 */
229 int
230 sys_osendmsg(struct osendmsg_args *uap)
231 {
232 struct thread *td = curthread;
233 struct msghdr msg;
234 struct uio auio;
235 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
236 struct sockaddr *sa = NULL;
237 struct mbuf *control = NULL;
238 struct cmsghdr *cm;
239 int error;
240
241 error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
242 if (error)
243 return (error);
244
245 /*
246 * Conditionally copyin msg.msg_name.
247 */
248 if (msg.msg_name) {
249 error = compat_43_getsockaddr(&sa, msg.msg_name,
250 msg.msg_namelen);
251 if (error)
252 return (error);
253 }
254
255 /*
256 * Populate auio.
257 */
258 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
259 &auio.uio_resid);
260 if (error)
261 goto cleanup2;
262 auio.uio_iov = iov;
263 auio.uio_iovcnt = msg.msg_iovlen;
264 auio.uio_offset = 0;
265 auio.uio_segflg = UIO_USERSPACE;
266 auio.uio_rw = UIO_WRITE;
267 auio.uio_td = td;
268
269 /*
270 * Conditionally copyin msg.msg_control.
271 */
272 if (msg.msg_control) {
273 if (msg.msg_controllen < 0 || msg.msg_controllen > MLEN) {
274 error = EINVAL;
275 goto cleanup;
276 }
277 control = m_get(MB_WAIT, MT_CONTROL);
278 if (control == NULL) {
279 error = ENOBUFS;
280 goto cleanup;
281 }
282 control->m_len = msg.msg_controllen;
283 error = copyin(msg.msg_control, mtod(control, caddr_t),
284 msg.msg_controllen);
285 if (error) {
286 m_free(control);
287 goto cleanup;
288 }
289 /*
290 * In 4.3BSD, the only type of ancillary data was
291 * access rights and this data did not use a header
292 * to identify it's type. Thus, we must prepend the
293 * control data with the proper cmsghdr structure
294 * so that the kernel recognizes it as access rights.
295 */
296 M_PREPEND(control, sizeof(*cm), MB_WAIT);
297 if (control == NULL) {
298 error = ENOBUFS;
299 goto cleanup;
300 } else {
301 cm = mtod(control, struct cmsghdr *);
302 cm->cmsg_len = control->m_len;
303 cm->cmsg_level = SOL_SOCKET;
304 cm->cmsg_type = SCM_RIGHTS;
305 }
306 }
307
308 get_mplock();
309 error = kern_sendmsg(uap->s, sa, &auio, control, uap->flags,
310 &uap->sysmsg_szresult);
311 rel_mplock();
312
313 cleanup:
314 iovec_free(&iov, aiov);
315 cleanup2:
316 if (sa)
317 kfree(sa, M_SONAME);
318 return (error);
319 }
320
321 /*
322 * MPALMOSTSAFE
323 */
324 int
325 sys_orecv(struct orecv_args *uap)
326 {
327 struct thread *td = curthread;
328 struct uio auio;
329 struct iovec aiov;
330 int error;
331
332 aiov.iov_base = uap->buf;
333 aiov.iov_len = uap->len;
334 auio.uio_iov = &aiov;
335 auio.uio_iovcnt = 1;
336 auio.uio_offset = 0;
337 auio.uio_resid = uap->len;
338 auio.uio_segflg = UIO_USERSPACE;
339 auio.uio_rw = UIO_READ;
340 auio.uio_td = td;
341
342 get_mplock();
343 error = kern_recvmsg(uap->s, NULL, &auio, NULL, &uap->flags,
344 &uap->sysmsg_szresult);
345 rel_mplock();
346
347 return (error);
348 }
349
350 /*
351 * MPALMOSTSAFE
352 */
353 int
354 sys_orecvfrom(struct recvfrom_args *uap)
355 {
356 struct thread *td = curthread;
357 struct uio auio;
358 struct iovec aiov;
359 struct sockaddr *sa = NULL;
360 int error, fromlen;
361
362 if (uap->from && uap->fromlenaddr) {
363 error = copyin(uap->fromlenaddr, &fromlen, sizeof(fromlen));
364 if (error)
365 return (error);
366 if (fromlen < 0)
367 return (EINVAL);
368 } else {
369 fromlen = 0;
370 }
371 aiov.iov_base = uap->buf;
372 aiov.iov_len = uap->len;
373 auio.uio_iov = &aiov;
374 auio.uio_iovcnt = 1;
375 auio.uio_offset = 0;
376 auio.uio_resid = uap->len;
377 auio.uio_segflg = UIO_USERSPACE;
378 auio.uio_rw = UIO_READ;
379 auio.uio_td = td;
380
381 get_mplock();
382 error = kern_recvmsg(uap->s, uap->from ? &sa : NULL, &auio, NULL,
383 &uap->flags, &uap->sysmsg_szresult);
384 rel_mplock();
385
386 if (error == 0 && uap->from) {
387 if (sa != NULL) {
388 fromlen = MIN(fromlen, sa->sa_len);
389 error = compat_43_copyout_sockaddr(sa, uap->from,
390 fromlen);
391 } else
392 fromlen = 0;
393 if (error == 0)
394 /*
395 * Old recvfrom didn't signal an error if this
396 * next copyout failed.
397 */
398 copyout(&fromlen, uap->fromlenaddr, sizeof(fromlen));
399 }
400 if (sa)
401 kfree(sa, M_SONAME);
402
403 return (error);
404 }
405
406 /*
407 * MPALMOSTSAFE
408 */
409 int
410 sys_orecvmsg(struct orecvmsg_args *uap)
411 {
412 struct thread *td = curthread;
413 struct msghdr msg;
414 struct uio auio;
415 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
416 struct mbuf *m, *control = NULL;
417 struct sockaddr *sa = NULL;
418 caddr_t ctlbuf;
419 socklen_t *ufromlenp, *ucontrollenp;
420 int error, fromlen, controllen, len, flags, *uflagsp;
421
422 /*
423 * This copyin handles everything except the iovec.
424 */
425 error = copyin(uap->msg, &msg, sizeof(struct omsghdr));
426 if (error)
427 return (error);
428
429 if (msg.msg_name && msg.msg_namelen < 0)
430 return (EINVAL);
431 if (msg.msg_control && msg.msg_controllen < 0)
432 return (EINVAL);
433
434 ufromlenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
435 msg_namelen));
436 ucontrollenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
437 msg_controllen));
438 uflagsp = (int *)((caddr_t)uap->msg + offsetof(struct msghdr,
439 msg_flags));
440
441 /*
442 * Populate auio.
443 */
444 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
445 &auio.uio_resid);
446 if (error)
447 return (error);
448 auio.uio_iov = iov;
449 auio.uio_iovcnt = msg.msg_iovlen;
450 auio.uio_offset = 0;
451 auio.uio_segflg = UIO_USERSPACE;
452 auio.uio_rw = UIO_READ;
453 auio.uio_td = td;
454
455 flags = msg.msg_flags;
456
457 get_mplock();
458 error = kern_recvmsg(uap->s, (msg.msg_name ? &sa : NULL), &auio,
459 (msg.msg_control ? &control : NULL), &flags,
460 &uap->sysmsg_szresult);
461 rel_mplock();
462
463 /*
464 * Copyout msg.msg_name and msg.msg_namelen.
465 */
466 if (error == 0 && msg.msg_name) {
467 if (sa != NULL) {
468 fromlen = MIN(msg.msg_namelen, sa->sa_len);
469 error = compat_43_copyout_sockaddr(sa, msg.msg_name,
470 fromlen);
471 } else
472 fromlen = 0;
473 if (error == 0)
474 /*
475 * Old recvfrom didn't signal an error if this
476 * next copyout failed.
477 */
478 copyout(&fromlen, ufromlenp, sizeof(*ufromlenp));
479 }
480
481 /*
482 * Copyout msg.msg_control and msg.msg_controllen.
483 */
484 if (error == 0 && msg.msg_control) {
485 /*
486 * If we receive access rights, trim the cmsghdr; anything
487 * else is tossed.
488 */
489 if (mtod((struct mbuf *)msg.msg_control,
490 struct cmsghdr *)->cmsg_level != SOL_SOCKET ||
491 mtod((struct mbuf *)msg.msg_control,
492 struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
493 int temp = 0;
494 error = copyout(&temp, ucontrollenp,
495 sizeof(*ucontrollenp));
496 goto cleanup;
497 }
498 ((struct mbuf *)msg.msg_control)->m_len -=
499 sizeof(struct cmsghdr);
500 ((struct mbuf *)msg.msg_control)->m_data +=
501 sizeof(struct cmsghdr);
502
503 len = msg.msg_controllen;
504 m = control;
505 ctlbuf = (caddr_t)msg.msg_control;
506
507 while(m && len > 0) {
508 unsigned int tocopy;
509
510 if (len >= m->m_len) {
511 tocopy = m->m_len;
512 } else {
513 msg.msg_flags |= MSG_CTRUNC;
514 tocopy = len;
515 }
516
517 error = copyout(mtod(m, caddr_t), ctlbuf,
518 tocopy);
519 if (error)
520 goto cleanup;
521
522 ctlbuf += tocopy;
523 len -= tocopy;
524 m = m->m_next;
525 }
526 controllen = ctlbuf - (caddr_t)msg.msg_control;
527 error = copyout(&controllen, ucontrollenp,
528 sizeof(*ucontrollenp));
529 }
530
531 if (error == 0)
532 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
533
534 cleanup:
535 if (sa)
536 kfree(sa, M_SONAME);
537 iovec_free(&iov, aiov);
538 if (control)
539 m_freem(control);
540 return (error);
541 }
542
Cache object: 0a1a5d157df1d045a845a336484bb12f
|