uipc_syscalls.c revision 1.175 1 /* $NetBSD: uipc_syscalls.c,v 1.175 2015/04/03 20:01:07 rtr Exp $ */
2
3 /*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1982, 1986, 1989, 1990, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. 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 * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95
61 */
62
63 #include <sys/cdefs.h>
64 __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.175 2015/04/03 20:01:07 rtr Exp $");
65
66 #include "opt_pipe.h"
67
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/filedesc.h>
71 #include <sys/proc.h>
72 #include <sys/file.h>
73 #include <sys/buf.h>
74 #define MBUFTYPES
75 #include <sys/mbuf.h>
76 #include <sys/protosw.h>
77 #include <sys/socket.h>
78 #include <sys/socketvar.h>
79 #include <sys/signalvar.h>
80 #include <sys/un.h>
81 #include <sys/ktrace.h>
82 #include <sys/event.h>
83 #include <sys/atomic.h>
84 #include <sys/kauth.h>
85
86 #include <sys/mount.h>
87 #include <sys/syscallargs.h>
88
89 /*
90 * System call interface to the socket abstraction.
91 */
92 extern const struct fileops socketops;
93
94 static int sockargs_sb(struct sockaddr_big *, const void *, socklen_t);
95
96 int
97 sys___socket30(struct lwp *l, const struct sys___socket30_args *uap,
98 register_t *retval)
99 {
100 /* {
101 syscallarg(int) domain;
102 syscallarg(int) type;
103 syscallarg(int) protocol;
104 } */
105 int fd, error;
106
107 error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type),
108 SCARG(uap, protocol), &fd);
109 if (error == 0) {
110 *retval = fd;
111 }
112 return error;
113 }
114
115 int
116 sys_bind(struct lwp *l, const struct sys_bind_args *uap, register_t *retval)
117 {
118 /* {
119 syscallarg(int) s;
120 syscallarg(const struct sockaddr *) name;
121 syscallarg(unsigned int) namelen;
122 } */
123 int error;
124 struct sockaddr_big sb;
125
126 error = sockargs_sb(&sb, SCARG(uap, name), SCARG(uap, namelen));
127 if (error)
128 return error;
129
130 return do_sys_bind(l, SCARG(uap, s), (struct sockaddr *)&sb);
131 }
132
133 int
134 do_sys_bind(struct lwp *l, int fd, struct sockaddr *nam)
135 {
136 struct socket *so;
137 int error;
138
139 if ((error = fd_getsock(fd, &so)) != 0)
140 return error;
141 error = sobind(so, nam, l);
142 fd_putfile(fd);
143 return error;
144 }
145
146 int
147 sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval)
148 {
149 /* {
150 syscallarg(int) s;
151 syscallarg(int) backlog;
152 } */
153 struct socket *so;
154 int error;
155
156 if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
157 return (error);
158 error = solisten(so, SCARG(uap, backlog), l);
159 fd_putfile(SCARG(uap, s));
160 return error;
161 }
162
163 int
164 do_sys_accept(struct lwp *l, int sock, struct mbuf **name,
165 register_t *new_sock, const sigset_t *mask, int flags, int clrflags)
166 {
167 file_t *fp, *fp2;
168 struct mbuf *nam;
169 int error, fd;
170 struct socket *so, *so2;
171 short wakeup_state = 0;
172
173 if ((fp = fd_getfile(sock)) == NULL)
174 return EBADF;
175 if (fp->f_type != DTYPE_SOCKET) {
176 fd_putfile(sock);
177 return ENOTSOCK;
178 }
179 if ((error = fd_allocfile(&fp2, &fd)) != 0) {
180 fd_putfile(sock);
181 return error;
182 }
183 nam = m_get(M_WAIT, MT_SONAME);
184 *new_sock = fd;
185 so = fp->f_socket;
186 solock(so);
187
188 if (__predict_false(mask))
189 sigsuspendsetup(l, mask);
190
191 if (!(so->so_proto->pr_flags & PR_LISTEN)) {
192 error = EOPNOTSUPP;
193 goto bad;
194 }
195 if ((so->so_options & SO_ACCEPTCONN) == 0) {
196 error = EINVAL;
197 goto bad;
198 }
199 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
200 error = EWOULDBLOCK;
201 goto bad;
202 }
203 while (so->so_qlen == 0 && so->so_error == 0) {
204 if (so->so_state & SS_CANTRCVMORE) {
205 so->so_error = ECONNABORTED;
206 break;
207 }
208 if (wakeup_state & SS_RESTARTSYS) {
209 error = ERESTART;
210 goto bad;
211 }
212 error = sowait(so, true, 0);
213 if (error) {
214 goto bad;
215 }
216 wakeup_state = so->so_state;
217 }
218 if (so->so_error) {
219 error = so->so_error;
220 so->so_error = 0;
221 goto bad;
222 }
223 /* connection has been removed from the listen queue */
224 KNOTE(&so->so_rcv.sb_sel.sel_klist, NOTE_SUBMIT);
225 so2 = TAILQ_FIRST(&so->so_q);
226 if (soqremque(so2, 1) == 0)
227 panic("accept");
228 fp2->f_type = DTYPE_SOCKET;
229 fp2->f_flag = (fp->f_flag & ~clrflags) |
230 ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
231 ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
232 fp2->f_ops = &socketops;
233 fp2->f_socket = so2;
234 if (fp2->f_flag & FNONBLOCK)
235 so2->so_state |= SS_NBIO;
236 else
237 so2->so_state &= ~SS_NBIO;
238 error = soaccept(so2, nam);
239 so2->so_cred = kauth_cred_dup(so->so_cred);
240 sounlock(so);
241 if (error) {
242 /* an error occurred, free the file descriptor and mbuf */
243 m_freem(nam);
244 mutex_enter(&fp2->f_lock);
245 fp2->f_count++;
246 mutex_exit(&fp2->f_lock);
247 closef(fp2);
248 fd_abort(curproc, NULL, fd);
249 } else {
250 fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
251 fd_affix(curproc, fp2, fd);
252 *name = nam;
253 }
254 fd_putfile(sock);
255 if (__predict_false(mask))
256 sigsuspendteardown(l);
257 return error;
258 bad:
259 sounlock(so);
260 m_freem(nam);
261 fd_putfile(sock);
262 fd_abort(curproc, fp2, fd);
263 if (__predict_false(mask))
264 sigsuspendteardown(l);
265 return error;
266 }
267
268 int
269 sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval)
270 {
271 /* {
272 syscallarg(int) s;
273 syscallarg(struct sockaddr *) name;
274 syscallarg(unsigned int *) anamelen;
275 } */
276 int error, fd;
277 struct mbuf *name;
278
279 error = do_sys_accept(l, SCARG(uap, s), &name, retval, NULL, 0, 0);
280 if (error != 0)
281 return error;
282 error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
283 MSG_LENUSRSPACE, name);
284 if (name != NULL)
285 m_free(name);
286 if (error != 0) {
287 fd = (int)*retval;
288 if (fd_getfile(fd) != NULL)
289 (void)fd_close(fd);
290 }
291 return error;
292 }
293
294 int
295 sys_paccept(struct lwp *l, const struct sys_paccept_args *uap,
296 register_t *retval)
297 {
298 /* {
299 syscallarg(int) s;
300 syscallarg(struct sockaddr *) name;
301 syscallarg(unsigned int *) anamelen;
302 syscallarg(const sigset_t *) mask;
303 syscallarg(int) flags;
304 } */
305 int error, fd;
306 struct mbuf *name;
307 sigset_t *mask, amask;
308
309 if (SCARG(uap, mask) != NULL) {
310 error = copyin(SCARG(uap, mask), &amask, sizeof(amask));
311 if (error)
312 return error;
313 mask = &amask;
314 } else
315 mask = NULL;
316
317 error = do_sys_accept(l, SCARG(uap, s), &name, retval, mask,
318 SCARG(uap, flags), FNONBLOCK);
319 if (error != 0)
320 return error;
321 error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
322 MSG_LENUSRSPACE, name);
323 if (name != NULL)
324 m_free(name);
325 if (error != 0) {
326 fd = (int)*retval;
327 if (fd_getfile(fd) != NULL)
328 (void)fd_close(fd);
329 }
330 return error;
331 }
332
333 int
334 sys_connect(struct lwp *l, const struct sys_connect_args *uap,
335 register_t *retval)
336 {
337 /* {
338 syscallarg(int) s;
339 syscallarg(const struct sockaddr *) name;
340 syscallarg(unsigned int) namelen;
341 } */
342 int error;
343 struct mbuf *nam;
344
345 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
346 MT_SONAME);
347 if (error)
348 return error;
349 return do_sys_connect(l, SCARG(uap, s), nam);
350 }
351
352 int
353 do_sys_connect(struct lwp *l, int fd, struct mbuf *nam)
354 {
355 struct socket *so;
356 int error;
357 int interrupted = 0;
358
359 if ((error = fd_getsock(fd, &so)) != 0) {
360 m_freem(nam);
361 return (error);
362 }
363 solock(so);
364 MCLAIM(nam, so->so_mowner);
365 if ((so->so_state & SS_ISCONNECTING) != 0) {
366 error = EALREADY;
367 goto out;
368 }
369
370 error = soconnect(so, nam, l);
371 if (error)
372 goto bad;
373 if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) ==
374 (SS_NBIO|SS_ISCONNECTING)) {
375 error = EINPROGRESS;
376 goto out;
377 }
378 while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) {
379 error = sowait(so, true, 0);
380 if (__predict_false((so->so_state & SS_ISABORTING) != 0)) {
381 error = EPIPE;
382 interrupted = 1;
383 break;
384 }
385 if (error) {
386 if (error == EINTR || error == ERESTART)
387 interrupted = 1;
388 break;
389 }
390 }
391 if (error == 0) {
392 error = so->so_error;
393 so->so_error = 0;
394 }
395 bad:
396 if (!interrupted)
397 so->so_state &= ~SS_ISCONNECTING;
398 if (error == ERESTART)
399 error = EINTR;
400 out:
401 sounlock(so);
402 fd_putfile(fd);
403 m_freem(nam);
404 return error;
405 }
406
407 static int
408 makesocket(struct lwp *l, file_t **fp, int *fd, int flags, int type,
409 int domain, int proto, struct socket *soo)
410 {
411 struct socket *so;
412 int error;
413
414 if ((error = socreate(domain, &so, type, proto, l, soo)) != 0) {
415 return error;
416 }
417 if (flags & SOCK_NONBLOCK) {
418 so->so_state |= SS_NBIO;
419 }
420
421 if ((error = fd_allocfile(fp, fd)) != 0) {
422 soclose(so);
423 return error;
424 }
425 fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0);
426 (*fp)->f_flag = FREAD|FWRITE|
427 ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
428 ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
429 (*fp)->f_type = DTYPE_SOCKET;
430 (*fp)->f_ops = &socketops;
431 (*fp)->f_socket = so;
432 return 0;
433 }
434
435 int
436 sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap,
437 register_t *retval)
438 {
439 /* {
440 syscallarg(int) domain;
441 syscallarg(int) type;
442 syscallarg(int) protocol;
443 syscallarg(int *) rsv;
444 } */
445 file_t *fp1, *fp2;
446 struct socket *so1, *so2;
447 int fd, error, sv[2];
448 proc_t *p = curproc;
449 int flags = SCARG(uap, type) & SOCK_FLAGS_MASK;
450 int type = SCARG(uap, type) & ~SOCK_FLAGS_MASK;
451 int domain = SCARG(uap, domain);
452 int proto = SCARG(uap, protocol);
453
454 error = makesocket(l, &fp1, &fd, flags, type, domain, proto, NULL);
455 if (error)
456 return error;
457 so1 = fp1->f_socket;
458 sv[0] = fd;
459
460 error = makesocket(l, &fp2, &fd, flags, type, domain, proto, so1);
461 if (error)
462 goto out;
463 so2 = fp2->f_socket;
464 sv[1] = fd;
465
466 solock(so1);
467 error = soconnect2(so1, so2);
468 if (error == 0 && type == SOCK_DGRAM) {
469 /*
470 * Datagram socket connection is asymmetric.
471 */
472 error = soconnect2(so2, so1);
473 }
474 sounlock(so1);
475
476 if (error == 0)
477 error = copyout(sv, SCARG(uap, rsv), sizeof(sv));
478 if (error == 0) {
479 fd_affix(p, fp2, sv[1]);
480 fd_affix(p, fp1, sv[0]);
481 return 0;
482 }
483 fd_abort(p, fp2, sv[1]);
484 (void)soclose(so2);
485 out:
486 fd_abort(p, fp1, sv[0]);
487 (void)soclose(so1);
488 return error;
489 }
490
491 int
492 sys_sendto(struct lwp *l, const struct sys_sendto_args *uap,
493 register_t *retval)
494 {
495 /* {
496 syscallarg(int) s;
497 syscallarg(const void *) buf;
498 syscallarg(size_t) len;
499 syscallarg(int) flags;
500 syscallarg(const struct sockaddr *) to;
501 syscallarg(unsigned int) tolen;
502 } */
503 struct msghdr msg;
504 struct iovec aiov;
505
506 msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */
507 msg.msg_namelen = SCARG(uap, tolen);
508 msg.msg_iov = &aiov;
509 msg.msg_iovlen = 1;
510 msg.msg_control = NULL;
511 msg.msg_flags = 0;
512 aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */
513 aiov.iov_len = SCARG(uap, len);
514 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
515 }
516
517 int
518 sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap,
519 register_t *retval)
520 {
521 /* {
522 syscallarg(int) s;
523 syscallarg(const struct msghdr *) msg;
524 syscallarg(int) flags;
525 } */
526 struct msghdr msg;
527 int error;
528
529 error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
530 if (error)
531 return (error);
532
533 msg.msg_flags = MSG_IOVUSRSPACE;
534 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
535 }
536
537 static int
538 do_sys_sendmsg_so(struct lwp *l, int s, struct socket *so, file_t *fp,
539 struct msghdr *mp, int flags, register_t *retsize)
540 {
541
542 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
543 struct mbuf *to, *control;
544 struct uio auio;
545 size_t len, iovsz;
546 int i, error;
547
548 ktrkuser("msghdr", mp, sizeof *mp);
549
550 /* If the caller passed us stuff in mbufs, we must free them. */
551 to = (mp->msg_flags & MSG_NAMEMBUF) ? mp->msg_name : NULL;
552 control = (mp->msg_flags & MSG_CONTROLMBUF) ? mp->msg_control : NULL;
553 iovsz = mp->msg_iovlen * sizeof(struct iovec);
554
555 if (mp->msg_flags & MSG_IOVUSRSPACE) {
556 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
557 if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
558 error = EMSGSIZE;
559 goto bad;
560 }
561 iov = kmem_alloc(iovsz, KM_SLEEP);
562 }
563 if (mp->msg_iovlen != 0) {
564 error = copyin(mp->msg_iov, iov, iovsz);
565 if (error)
566 goto bad;
567 }
568 mp->msg_iov = iov;
569 }
570
571 auio.uio_iov = mp->msg_iov;
572 auio.uio_iovcnt = mp->msg_iovlen;
573 auio.uio_rw = UIO_WRITE;
574 auio.uio_offset = 0; /* XXX */
575 auio.uio_resid = 0;
576 KASSERT(l == curlwp);
577 auio.uio_vmspace = l->l_proc->p_vmspace;
578
579 for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) {
580 /*
581 * Writes return ssize_t because -1 is returned on error.
582 * Therefore, we must restrict the length to SSIZE_MAX to
583 * avoid garbage return values.
584 */
585 auio.uio_resid += tiov->iov_len;
586 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
587 error = EINVAL;
588 goto bad;
589 }
590 }
591
592 if (mp->msg_name && to == NULL) {
593 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
594 MT_SONAME);
595 if (error)
596 goto bad;
597 }
598
599 if (mp->msg_control) {
600 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
601 error = EINVAL;
602 goto bad;
603 }
604 if (control == NULL) {
605 error = sockargs(&control, mp->msg_control,
606 mp->msg_controllen, MT_CONTROL);
607 if (error)
608 goto bad;
609 }
610 }
611
612 if (ktrpoint(KTR_GENIO) && iovsz > 0) {
613 ktriov = kmem_alloc(iovsz, KM_SLEEP);
614 memcpy(ktriov, auio.uio_iov, iovsz);
615 }
616
617 if (mp->msg_name)
618 MCLAIM(to, so->so_mowner);
619 if (mp->msg_control)
620 MCLAIM(control, so->so_mowner);
621
622 len = auio.uio_resid;
623 error = (*so->so_send)(so, to, &auio, NULL, control, flags, l);
624 /* Protocol is responsible for freeing 'control' */
625 control = NULL;
626
627 if (error) {
628 if (auio.uio_resid != len && (error == ERESTART ||
629 error == EINTR || error == EWOULDBLOCK))
630 error = 0;
631 if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0 &&
632 (flags & MSG_NOSIGNAL) == 0) {
633 mutex_enter(proc_lock);
634 psignal(l->l_proc, SIGPIPE);
635 mutex_exit(proc_lock);
636 }
637 }
638 if (error == 0)
639 *retsize = len - auio.uio_resid;
640
641 bad:
642 if (ktriov != NULL) {
643 ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error);
644 kmem_free(ktriov, iovsz);
645 }
646
647 if (iov != aiov)
648 kmem_free(iov, iovsz);
649 if (to)
650 m_freem(to);
651 if (control)
652 m_freem(control);
653
654 return error;
655 }
656
657 int
658 do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
659 register_t *retsize)
660 {
661 int error;
662 struct socket *so;
663 file_t *fp;
664
665 if ((error = fd_getsock1(s, &so, &fp)) != 0)
666 return error;
667 error = do_sys_sendmsg_so(l, s, so, fp, mp, flags, retsize);
668 fd_putfile(s);
669 return error;
670 }
671
672 int
673 sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap,
674 register_t *retval)
675 {
676 /* {
677 syscallarg(int) s;
678 syscallarg(void *) buf;
679 syscallarg(size_t) len;
680 syscallarg(int) flags;
681 syscallarg(struct sockaddr *) from;
682 syscallarg(unsigned int *) fromlenaddr;
683 } */
684 struct msghdr msg;
685 struct iovec aiov;
686 int error;
687 struct mbuf *from;
688
689 msg.msg_name = NULL;
690 msg.msg_iov = &aiov;
691 msg.msg_iovlen = 1;
692 aiov.iov_base = SCARG(uap, buf);
693 aiov.iov_len = SCARG(uap, len);
694 msg.msg_control = NULL;
695 msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
696
697 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
698 if (error != 0)
699 return error;
700
701 error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr),
702 MSG_LENUSRSPACE, from);
703 if (from != NULL)
704 m_free(from);
705 return error;
706 }
707
708 int
709 sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap,
710 register_t *retval)
711 {
712 /* {
713 syscallarg(int) s;
714 syscallarg(struct msghdr *) msg;
715 syscallarg(int) flags;
716 } */
717 struct msghdr msg;
718 int error;
719 struct mbuf *from, *control;
720
721 error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
722 if (error)
723 return error;
724
725 msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
726
727 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
728 msg.msg_control != NULL ? &control : NULL, retval);
729 if (error != 0)
730 return error;
731
732 if (msg.msg_control != NULL)
733 error = copyout_msg_control(l, &msg, control);
734
735 if (error == 0)
736 error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
737 from);
738 if (from != NULL)
739 m_free(from);
740 if (error == 0) {
741 ktrkuser("msghdr", &msg, sizeof msg);
742 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
743 }
744
745 return error;
746 }
747
748 int
749 sys_sendmmsg(struct lwp *l, const struct sys_sendmmsg_args *uap,
750 register_t *retval)
751 {
752 /* {
753 syscallarg(int) s;
754 syscallarg(struct mmsghdr *) mmsg;
755 syscallarg(unsigned int) vlen;
756 syscallarg(unsigned int) flags;
757 } */
758 struct mmsghdr mmsg;
759 struct socket *so;
760 file_t *fp;
761 struct msghdr *msg = &mmsg.msg_hdr;
762 int error, s;
763 unsigned int vlen, flags, dg;
764
765 s = SCARG(uap, s);
766 if ((error = fd_getsock1(s, &so, &fp)) != 0)
767 return error;
768
769 vlen = SCARG(uap, vlen);
770 if (vlen > 1024)
771 vlen = 1024;
772
773 flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
774
775 for (dg = 0; dg < vlen;) {
776 error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
777 if (error)
778 break;
779
780 msg->msg_flags = flags;
781
782 error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval);
783 if (error)
784 break;
785
786 ktrkuser("msghdr", msg, sizeof *msg);
787 mmsg.msg_len = *retval;
788 error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
789 if (error)
790 break;
791 dg++;
792
793 }
794
795 *retval = dg;
796 if (error)
797 so->so_error = error;
798
799 fd_putfile(s);
800
801 /*
802 * If we succeeded at least once, return 0, hopefully so->so_error
803 * will catch it next time.
804 */
805 if (dg)
806 return 0;
807 return error;
808 }
809
810 /*
811 * Adjust for a truncated SCM_RIGHTS control message.
812 * This means closing any file descriptors that aren't present
813 * in the returned buffer.
814 * m is the mbuf holding the (already externalized) SCM_RIGHTS message.
815 */
816 static void
817 free_rights(struct mbuf *m)
818 {
819 struct cmsghdr *cm;
820 int *fdv;
821 unsigned int nfds, i;
822
823 KASSERT(sizeof(*cm) <= m->m_len);
824 cm = mtod(m, struct cmsghdr *);
825
826 KASSERT(CMSG_ALIGN(sizeof(*cm)) <= cm->cmsg_len);
827 KASSERT(cm->cmsg_len <= m->m_len);
828 nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(int);
829 fdv = (int *)CMSG_DATA(cm);
830
831 for (i = 0; i < nfds; i++)
832 if (fd_getfile(fdv[i]) != NULL)
833 (void)fd_close(fdv[i]);
834 }
835
836 void
837 free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied)
838 {
839 struct mbuf *next;
840 struct cmsghdr *cmsg;
841 bool do_free_rights = false;
842
843 while (control != NULL) {
844 cmsg = mtod(control, struct cmsghdr *);
845 if (control == uncopied)
846 do_free_rights = true;
847 if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET
848 && cmsg->cmsg_type == SCM_RIGHTS)
849 free_rights(control);
850 next = control->m_next;
851 m_free(control);
852 control = next;
853 }
854 }
855
856 /* Copy socket control/CMSG data to user buffer, frees the mbuf */
857 int
858 copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
859 {
860 int i, len, error = 0;
861 struct cmsghdr *cmsg;
862 struct mbuf *m;
863 char *q;
864
865 len = mp->msg_controllen;
866 if (len <= 0 || control == 0) {
867 mp->msg_controllen = 0;
868 free_control_mbuf(l, control, control);
869 return 0;
870 }
871
872 q = (char *)mp->msg_control;
873
874 for (m = control; m != NULL; ) {
875 cmsg = mtod(m, struct cmsghdr *);
876 i = m->m_len;
877 if (len < i) {
878 mp->msg_flags |= MSG_CTRUNC;
879 if (cmsg->cmsg_level == SOL_SOCKET
880 && cmsg->cmsg_type == SCM_RIGHTS)
881 /* Do not truncate me ... */
882 break;
883 i = len;
884 }
885 error = copyout(mtod(m, void *), q, i);
886 ktrkuser("msgcontrol", mtod(m, void *), i);
887 if (error != 0) {
888 /* We must free all the SCM_RIGHTS */
889 m = control;
890 break;
891 }
892 m = m->m_next;
893 if (m)
894 i = ALIGN(i);
895 q += i;
896 len -= i;
897 if (len <= 0)
898 break;
899 }
900
901 free_control_mbuf(l, control, m);
902
903 mp->msg_controllen = q - (char *)mp->msg_control;
904 return error;
905 }
906
907 static int
908 do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp,
909 struct mbuf **from, struct mbuf **control, register_t *retsize)
910 {
911 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
912 struct uio auio;
913 size_t len, iovsz;
914 int i, error;
915
916 ktrkuser("msghdr", mp, sizeof *mp);
917
918 *from = NULL;
919 if (control != NULL)
920 *control = NULL;
921
922 iovsz = mp->msg_iovlen * sizeof(struct iovec);
923
924 if (mp->msg_flags & MSG_IOVUSRSPACE) {
925 if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
926 if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
927 error = EMSGSIZE;
928 goto out;
929 }
930 iov = kmem_alloc(iovsz, KM_SLEEP);
931 }
932 if (mp->msg_iovlen != 0) {
933 error = copyin(mp->msg_iov, iov, iovsz);
934 if (error)
935 goto out;
936 }
937 auio.uio_iov = iov;
938 } else
939 auio.uio_iov = mp->msg_iov;
940 auio.uio_iovcnt = mp->msg_iovlen;
941 auio.uio_rw = UIO_READ;
942 auio.uio_offset = 0; /* XXX */
943 auio.uio_resid = 0;
944 KASSERT(l == curlwp);
945 auio.uio_vmspace = l->l_proc->p_vmspace;
946
947 tiov = auio.uio_iov;
948 for (i = 0; i < mp->msg_iovlen; i++, tiov++) {
949 /*
950 * Reads return ssize_t because -1 is returned on error.
951 * Therefore we must restrict the length to SSIZE_MAX to
952 * avoid garbage return values.
953 */
954 auio.uio_resid += tiov->iov_len;
955 if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
956 error = EINVAL;
957 goto out;
958 }
959 }
960
961 if (ktrpoint(KTR_GENIO) && iovsz > 0) {
962 ktriov = kmem_alloc(iovsz, KM_SLEEP);
963 memcpy(ktriov, auio.uio_iov, iovsz);
964 }
965
966 len = auio.uio_resid;
967 mp->msg_flags &= MSG_USERFLAGS;
968 error = (*so->so_receive)(so, from, &auio, NULL, control,
969 &mp->msg_flags);
970 len -= auio.uio_resid;
971 *retsize = len;
972 if (error != 0 && len != 0
973 && (error == ERESTART || error == EINTR || error == EWOULDBLOCK))
974 /* Some data transferred */
975 error = 0;
976
977 if (ktriov != NULL) {
978 ktrgeniov(s, UIO_READ, ktriov, len, error);
979 kmem_free(ktriov, iovsz);
980 }
981
982 if (error != 0) {
983 m_freem(*from);
984 *from = NULL;
985 if (control != NULL) {
986 free_control_mbuf(l, *control, *control);
987 *control = NULL;
988 }
989 }
990 out:
991 if (iov != aiov)
992 kmem_free(iov, iovsz);
993 return error;
994 }
995
996
997 int
998 do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
999 struct mbuf **control, register_t *retsize)
1000 {
1001 int error;
1002 struct socket *so;
1003
1004 if ((error = fd_getsock(s, &so)) != 0)
1005 return error;
1006 error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize);
1007 fd_putfile(s);
1008 return error;
1009 }
1010
1011 int
1012 sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap,
1013 register_t *retval)
1014 {
1015 /* {
1016 syscallarg(int) s;
1017 syscallarg(struct mmsghdr *) mmsg;
1018 syscallarg(unsigned int) vlen;
1019 syscallarg(unsigned int) flags;
1020 syscallarg(struct timespec *) timeout;
1021 } */
1022 struct mmsghdr mmsg;
1023 struct socket *so;
1024 struct msghdr *msg = &mmsg.msg_hdr;
1025 int error, s;
1026 struct mbuf *from, *control;
1027 struct timespec ts, now;
1028 unsigned int vlen, flags, dg;
1029
1030 if (SCARG(uap, timeout)) {
1031 if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0)
1032 return error;
1033 getnanotime(&now);
1034 timespecadd(&now, &ts, &ts);
1035 }
1036
1037 s = SCARG(uap, s);
1038 if ((error = fd_getsock(s, &so)) != 0)
1039 return error;
1040
1041 vlen = SCARG(uap, vlen);
1042 if (vlen > 1024)
1043 vlen = 1024;
1044
1045 from = NULL;
1046 flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
1047
1048 for (dg = 0; dg < vlen;) {
1049 error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
1050 if (error)
1051 break;
1052
1053 msg->msg_flags = flags & ~MSG_WAITFORONE;
1054
1055 if (from != NULL) {
1056 m_free(from);
1057 from = NULL;
1058 }
1059
1060 error = do_sys_recvmsg_so(l, s, so, msg, &from,
1061 msg->msg_control != NULL ? &control : NULL, retval);
1062 if (error) {
1063 if (error == EAGAIN && dg > 0)
1064 error = 0;
1065 break;
1066 }
1067
1068 if (msg->msg_control != NULL)
1069 error = copyout_msg_control(l, msg, control);
1070 if (error)
1071 break;
1072
1073 error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
1074 from);
1075 if (error)
1076 break;
1077
1078 ktrkuser("msghdr", msg, sizeof *msg);
1079 mmsg.msg_len = *retval;
1080
1081 error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
1082 if (error)
1083 break;
1084
1085 dg++;
1086 if (msg->msg_flags & MSG_OOB)
1087 break;
1088
1089 if (SCARG(uap, timeout)) {
1090 getnanotime(&now);
1091 timespecsub(&now, &ts, &now);
1092 if (now.tv_sec > 0)
1093 break;
1094 }
1095
1096 if (flags & MSG_WAITFORONE)
1097 flags |= MSG_DONTWAIT;
1098
1099 }
1100
1101 if (from != NULL)
1102 m_free(from);
1103
1104 *retval = dg;
1105 if (error)
1106 so->so_error = error;
1107
1108 fd_putfile(s);
1109
1110 /*
1111 * If we succeeded at least once, return 0, hopefully so->so_error
1112 * will catch it next time.
1113 */
1114 if (dg)
1115 return 0;
1116
1117 return error;
1118 }
1119
1120 int
1121 sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap,
1122 register_t *retval)
1123 {
1124 /* {
1125 syscallarg(int) s;
1126 syscallarg(int) how;
1127 } */
1128 struct socket *so;
1129 int error;
1130
1131 if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1132 return error;
1133 solock(so);
1134 error = soshutdown(so, SCARG(uap, how));
1135 sounlock(so);
1136 fd_putfile(SCARG(uap, s));
1137 return error;
1138 }
1139
1140 int
1141 sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap,
1142 register_t *retval)
1143 {
1144 /* {
1145 syscallarg(int) s;
1146 syscallarg(int) level;
1147 syscallarg(int) name;
1148 syscallarg(const void *) val;
1149 syscallarg(unsigned int) valsize;
1150 } */
1151 struct sockopt sopt;
1152 struct socket *so;
1153 file_t *fp;
1154 int error;
1155 unsigned int len;
1156
1157 len = SCARG(uap, valsize);
1158 if (len > 0 && SCARG(uap, val) == NULL)
1159 return EINVAL;
1160
1161 if (len > MCLBYTES)
1162 return EINVAL;
1163
1164 if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
1165 return (error);
1166
1167 sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len);
1168
1169 if (len > 0) {
1170 error = copyin(SCARG(uap, val), sopt.sopt_data, len);
1171 if (error)
1172 goto out;
1173 }
1174
1175 error = sosetopt(so, &sopt);
1176 if (so->so_options & SO_NOSIGPIPE)
1177 atomic_or_uint(&fp->f_flag, FNOSIGPIPE);
1178 else
1179 atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE);
1180
1181 out:
1182 sockopt_destroy(&sopt);
1183 fd_putfile(SCARG(uap, s));
1184 return error;
1185 }
1186
1187 int
1188 sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap,
1189 register_t *retval)
1190 {
1191 /* {
1192 syscallarg(int) s;
1193 syscallarg(int) level;
1194 syscallarg(int) name;
1195 syscallarg(void *) val;
1196 syscallarg(unsigned int *) avalsize;
1197 } */
1198 struct sockopt sopt;
1199 struct socket *so;
1200 file_t *fp;
1201 unsigned int valsize, len;
1202 int error;
1203
1204 if (SCARG(uap, val) != NULL) {
1205 error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize));
1206 if (error)
1207 return error;
1208 } else
1209 valsize = 0;
1210
1211 if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
1212 return (error);
1213
1214 sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0);
1215
1216 if (fp->f_flag & FNOSIGPIPE)
1217 so->so_options |= SO_NOSIGPIPE;
1218 else
1219 so->so_options &= ~SO_NOSIGPIPE;
1220 error = sogetopt(so, &sopt);
1221 if (error)
1222 goto out;
1223
1224 if (valsize > 0) {
1225 len = min(valsize, sopt.sopt_size);
1226 error = copyout(sopt.sopt_data, SCARG(uap, val), len);
1227 if (error)
1228 goto out;
1229
1230 error = copyout(&len, SCARG(uap, avalsize), sizeof(len));
1231 if (error)
1232 goto out;
1233 }
1234
1235 out:
1236 sockopt_destroy(&sopt);
1237 fd_putfile(SCARG(uap, s));
1238 return error;
1239 }
1240
1241 #ifdef PIPE_SOCKETPAIR
1242
1243 int
1244 pipe1(struct lwp *l, register_t *retval, int flags)
1245 {
1246 file_t *rf, *wf;
1247 struct socket *rso, *wso;
1248 int fd, error;
1249 proc_t *p;
1250
1251 if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
1252 return EINVAL;
1253 p = curproc;
1254 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
1255 return error;
1256 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
1257 goto free1;
1258 /* remember this socket pair implements a pipe */
1259 wso->so_state |= SS_ISAPIPE;
1260 rso->so_state |= SS_ISAPIPE;
1261 if ((error = fd_allocfile(&rf, &fd)) != 0)
1262 goto free2;
1263 retval[0] = fd;
1264 rf->f_flag = FREAD | flags;
1265 rf->f_type = DTYPE_SOCKET;
1266 rf->f_ops = &socketops;
1267 rf->f_socket = rso;
1268 if ((error = fd_allocfile(&wf, &fd)) != 0)
1269 goto free3;
1270 wf->f_flag = FWRITE | flags;
1271 wf->f_type = DTYPE_SOCKET;
1272 wf->f_ops = &socketops;
1273 wf->f_socket = wso;
1274 retval[1] = fd;
1275 solock(wso);
1276 error = unp_connect2(wso, rso);
1277 sounlock(wso);
1278 if (error != 0)
1279 goto free4;
1280 fd_affix(p, wf, (int)retval[1]);
1281 fd_affix(p, rf, (int)retval[0]);
1282 return (0);
1283 free4:
1284 fd_abort(p, wf, (int)retval[1]);
1285 free3:
1286 fd_abort(p, rf, (int)retval[0]);
1287 free2:
1288 (void)soclose(wso);
1289 free1:
1290 (void)soclose(rso);
1291 return error;
1292 }
1293 #endif /* PIPE_SOCKETPAIR */
1294
1295 /*
1296 * Get peer socket name.
1297 */
1298 int
1299 do_sys_getpeername(int fd, struct mbuf **nam)
1300 {
1301 struct socket *so;
1302 struct mbuf *m;
1303 int error;
1304
1305 if ((error = fd_getsock(fd, &so)) != 0)
1306 return error;
1307
1308 m = m_getclr(M_WAIT, MT_SONAME);
1309 MCLAIM(m, so->so_mowner);
1310
1311 solock(so);
1312 if ((so->so_state & SS_ISCONNECTED) == 0)
1313 error = ENOTCONN;
1314 else {
1315 *nam = m;
1316 error = (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, m);
1317 }
1318 sounlock(so);
1319 if (error != 0)
1320 m_free(m);
1321 fd_putfile(fd);
1322 return error;
1323 }
1324
1325 /*
1326 * Get local socket name.
1327 */
1328 int
1329 do_sys_getsockname(int fd, struct mbuf **nam)
1330 {
1331 struct socket *so;
1332 struct mbuf *m;
1333 int error;
1334
1335 if ((error = fd_getsock(fd, &so)) != 0)
1336 return error;
1337
1338 m = m_getclr(M_WAIT, MT_SONAME);
1339 MCLAIM(m, so->so_mowner);
1340
1341 *nam = m;
1342 solock(so);
1343 error = (*so->so_proto->pr_usrreqs->pr_sockaddr)(so, m);
1344 sounlock(so);
1345 if (error != 0)
1346 m_free(m);
1347 fd_putfile(fd);
1348 return error;
1349 }
1350
1351 int
1352 copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags,
1353 struct mbuf *addr)
1354 {
1355 int len;
1356 int error;
1357
1358 if (asa == NULL)
1359 /* Assume application not interested */
1360 return 0;
1361
1362 if (flags & MSG_LENUSRSPACE) {
1363 error = copyin(alen, &len, sizeof(len));
1364 if (error)
1365 return error;
1366 } else
1367 len = *alen;
1368 if (len < 0)
1369 return EINVAL;
1370
1371 if (addr == NULL) {
1372 len = 0;
1373 error = 0;
1374 } else {
1375 if (len > addr->m_len)
1376 len = addr->m_len;
1377 /* Maybe this ought to copy a chain ? */
1378 ktrkuser(mbuftypes[MT_SONAME], mtod(addr, void *), len);
1379 error = copyout(mtod(addr, void *), asa, len);
1380 }
1381
1382 if (error == 0) {
1383 if (flags & MSG_LENUSRSPACE)
1384 error = copyout(&len, alen, sizeof(len));
1385 else
1386 *alen = len;
1387 }
1388
1389 return error;
1390 }
1391
1392 /*
1393 * Get socket name.
1394 */
1395 int
1396 sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap,
1397 register_t *retval)
1398 {
1399 /* {
1400 syscallarg(int) fdes;
1401 syscallarg(struct sockaddr *) asa;
1402 syscallarg(unsigned int *) alen;
1403 } */
1404 struct mbuf *m;
1405 int error;
1406
1407 error = do_sys_getsockname(SCARG(uap, fdes), &m);
1408 if (error != 0)
1409 return error;
1410
1411 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
1412 MSG_LENUSRSPACE, m);
1413 if (m != NULL)
1414 m_free(m);
1415 return error;
1416 }
1417
1418 /*
1419 * Get name of peer for connected socket.
1420 */
1421 int
1422 sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap,
1423 register_t *retval)
1424 {
1425 /* {
1426 syscallarg(int) fdes;
1427 syscallarg(struct sockaddr *) asa;
1428 syscallarg(unsigned int *) alen;
1429 } */
1430 struct mbuf *m;
1431 int error;
1432
1433 error = do_sys_getpeername(SCARG(uap, fdes), &m);
1434 if (error != 0)
1435 return error;
1436
1437 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
1438 MSG_LENUSRSPACE, m);
1439 if (m != NULL)
1440 m_free(m);
1441 return error;
1442 }
1443
1444 static int
1445 sockargs_sb(struct sockaddr_big *sb, const void *name, socklen_t buflen)
1446 {
1447 int error;
1448
1449 /*
1450 * We can't allow socket names > UCHAR_MAX in length, since that
1451 * will overflow sb_len. Further no reasonable buflen is <=
1452 * offsetof(sockaddr_big, sb_data) since it shall be at least
1453 * the size of the preamble sb_len and sb_family members.
1454 */
1455 if (buflen > UCHAR_MAX ||
1456 buflen <= offsetof(struct sockaddr_big, sb_data))
1457 return EINVAL;
1458
1459 error = copyin(name, (void *)sb, buflen);
1460 if (error)
1461 return error;
1462
1463 #if BYTE_ORDER != BIG_ENDIAN
1464 /*
1465 * 4.3BSD compat thing - need to stay, since bind(2),
1466 * connect(2), sendto(2) were not versioned for COMPAT_43.
1467 */
1468 if (sb->sb_family == 0 && sb->sb_len < AF_MAX)
1469 sb->sb_family = sb->sb_len;
1470 #endif
1471 sb->sb_len = buflen;
1472 return 0;
1473 }
1474
1475 /*
1476 * XXX In a perfect world, we wouldn't pass around socket control
1477 * XXX arguments in mbufs, and this could go away.
1478 */
1479 int
1480 sockargs(struct mbuf **mp, const void *bf, size_t buflen, int type)
1481 {
1482 struct sockaddr *sa;
1483 struct mbuf *m;
1484 int error;
1485
1486 /*
1487 * We can't allow socket names > UCHAR_MAX in length, since that
1488 * will overflow sa_len. Control data more than a page size in
1489 * length is just too much.
1490 */
1491 if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
1492 return EINVAL;
1493
1494 /*
1495 * length must greater than sizeof(sa_family) + sizeof(sa_len)
1496 */
1497 if (type == MT_SONAME && buflen <= 2)
1498 return EINVAL;
1499
1500 /* Allocate an mbuf to hold the arguments. */
1501 m = m_get(M_WAIT, type);
1502 /* can't claim. don't who to assign it to. */
1503 if (buflen > MLEN) {
1504 /*
1505 * Won't fit into a regular mbuf, so we allocate just
1506 * enough external storage to hold the argument.
1507 */
1508 MEXTMALLOC(m, buflen, M_WAITOK);
1509 }
1510 m->m_len = buflen;
1511 error = copyin(bf, mtod(m, void *), buflen);
1512 if (error) {
1513 (void)m_free(m);
1514 return error;
1515 }
1516 ktrkuser(mbuftypes[type], mtod(m, void *), buflen);
1517 *mp = m;
1518 if (type == MT_SONAME) {
1519 sa = mtod(m, struct sockaddr *);
1520 #if BYTE_ORDER != BIG_ENDIAN
1521 /*
1522 * 4.3BSD compat thing - need to stay, since bind(2),
1523 * connect(2), sendto(2) were not versioned for COMPAT_43.
1524 */
1525 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1526 sa->sa_family = sa->sa_len;
1527 #endif
1528 sa->sa_len = buflen;
1529 }
1530 return 0;
1531 }
1532