Annotation of src/sys/kern/uipc_syscalls.c, Revision 1.145
1.145 ! christos 1: /* $NetBSD: uipc_syscalls.c,v 1.144 2011/06/26 16:42:42 christos Exp $ */
1.129 ad 2:
3: /*-
1.136 ad 4: * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
1.129 ad 5: * All rights reserved.
6: *
1.136 ad 7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Andrew Doran.
9: *
1.129 ad 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: */
1.8 cgd 31:
1.1 cgd 32: /*
1.7 mycroft 33: * Copyright (c) 1982, 1986, 1989, 1990, 1993
34: * The Regents of the University of California. All rights reserved.
1.1 cgd 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.
1.82 agc 44: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 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: *
1.29 fvdl 60: * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95
1.1 cgd 61: */
1.67 lukem 62:
63: #include <sys/cdefs.h>
1.145 ! christos 64: __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.144 2011/06/26 16:42:42 christos Exp $");
1.31 thorpej 65:
1.68 jdolecek 66: #include "opt_pipe.h"
1.55 jdolecek 67:
1.6 mycroft 68: #include <sys/param.h>
1.9 cgd 69: #include <sys/systm.h>
1.6 mycroft 70: #include <sys/filedesc.h>
71: #include <sys/proc.h>
72: #include <sys/file.h>
73: #include <sys/buf.h>
74: #include <sys/mbuf.h>
75: #include <sys/protosw.h>
76: #include <sys/socket.h>
77: #include <sys/socketvar.h>
1.18 christos 78: #include <sys/signalvar.h>
79: #include <sys/un.h>
1.6 mycroft 80: #include <sys/ktrace.h>
1.71 jdolecek 81: #include <sys/event.h>
1.139 elad 82: #include <sys/kauth.h>
1.1 cgd 83:
1.9 cgd 84: #include <sys/mount.h>
85: #include <sys/syscallargs.h>
86:
1.44 darrenr 87: #include <uvm/uvm_extern.h>
88:
1.1 cgd 89: /*
90: * System call interface to the socket abstraction.
91: */
1.89 christos 92: extern const struct fileops socketops;
1.1 cgd 93:
1.7 mycroft 94: int
1.125 dsl 95: sys___socket30(struct lwp *l, const struct sys___socket30_args *uap, register_t *retval)
1.15 thorpej 96: {
1.125 dsl 97: /* {
1.57 lukem 98: syscallarg(int) domain;
99: syscallarg(int) type;
100: syscallarg(int) protocol;
1.125 dsl 101: } */
1.57 lukem 102: int fd, error;
1.1 cgd 103:
1.120 dyoung 104: error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type),
105: SCARG(uap, protocol), l, &fd);
106: if (error == 0)
1.1 cgd 107: *retval = fd;
1.120 dyoung 108: return error;
1.1 cgd 109: }
110:
111: /* ARGSUSED */
1.7 mycroft 112: int
1.125 dsl 113: sys_bind(struct lwp *l, const struct sys_bind_args *uap, register_t *retval)
1.15 thorpej 114: {
1.125 dsl 115: /* {
1.57 lukem 116: syscallarg(int) s;
117: syscallarg(const struct sockaddr *) name;
118: syscallarg(unsigned int) namelen;
1.125 dsl 119: } */
1.111 dsl 120: struct mbuf *nam;
121: int error;
122:
1.112 enami 123: error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
124: MT_SONAME);
1.111 dsl 125: if (error)
126: return error;
127:
128: return do_sys_bind(l, SCARG(uap, s), nam);
129: }
130:
131: int
1.128 ad 132: do_sys_bind(struct lwp *l, int fd, struct mbuf *nam)
1.111 dsl 133: {
1.128 ad 134: struct socket *so;
1.57 lukem 135: int error;
1.1 cgd 136:
1.128 ad 137: if ((error = fd_getsock(fd, &so)) != 0) {
1.111 dsl 138: m_freem(nam);
1.1 cgd 139: return (error);
1.43 thorpej 140: }
1.128 ad 141: MCLAIM(nam, so->so_mowner);
142: error = sobind(so, nam, l);
1.1 cgd 143: m_freem(nam);
1.128 ad 144: fd_putfile(fd);
1.111 dsl 145: return error;
1.1 cgd 146: }
147:
148: /* ARGSUSED */
1.7 mycroft 149: int
1.125 dsl 150: sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval)
1.15 thorpej 151: {
1.125 dsl 152: /* {
1.57 lukem 153: syscallarg(int) s;
154: syscallarg(int) backlog;
1.125 dsl 155: } */
1.128 ad 156: struct socket *so;
1.57 lukem 157: int error;
1.1 cgd 158:
1.128 ad 159: if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1.1 cgd 160: return (error);
1.128 ad 161: error = solisten(so, SCARG(uap, backlog), l);
162: fd_putfile(SCARG(uap, s));
1.111 dsl 163: return error;
1.1 cgd 164: }
165:
1.7 mycroft 166: int
1.144 christos 167: do_sys_accept(struct lwp *l, int sock, struct mbuf **name, register_t *new_sock,
168: const sigset_t *mask, int flags, int clrflags)
1.15 thorpej 169: {
1.128 ad 170: file_t *fp, *fp2;
1.57 lukem 171: struct mbuf *nam;
1.129 ad 172: int error, fd;
1.128 ad 173: struct socket *so, *so2;
1.138 dsl 174: short wakeup_state = 0;
1.1 cgd 175:
1.128 ad 176: if ((fp = fd_getfile(sock)) == NULL)
177: return (EBADF);
1.132 rmind 178: if (fp->f_type != DTYPE_SOCKET) {
179: fd_putfile(sock);
1.128 ad 180: return (ENOTSOCK);
1.132 rmind 181: }
182: if ((error = fd_allocfile(&fp2, &fd)) != 0) {
183: fd_putfile(sock);
1.1 cgd 184: return (error);
1.132 rmind 185: }
1.128 ad 186: nam = m_get(M_WAIT, MT_SONAME);
187: *new_sock = fd;
188: so = fp->f_data;
1.129 ad 189: solock(so);
1.144 christos 190:
191: if (__predict_false(mask))
192: sigsuspendsetup(l, mask);
193:
1.44 darrenr 194: if (!(so->so_proto->pr_flags & PR_LISTEN)) {
1.128 ad 195: error = EOPNOTSUPP;
196: goto bad;
1.44 darrenr 197: }
1.1 cgd 198: if ((so->so_options & SO_ACCEPTCONN) == 0) {
1.128 ad 199: error = EINVAL;
200: goto bad;
1.1 cgd 201: }
1.127 ad 202: if (so->so_nbio && so->so_qlen == 0) {
1.128 ad 203: error = EWOULDBLOCK;
204: goto bad;
1.1 cgd 205: }
206: while (so->so_qlen == 0 && so->so_error == 0) {
207: if (so->so_state & SS_CANTRCVMORE) {
208: so->so_error = ECONNABORTED;
209: break;
210: }
1.138 dsl 211: if (wakeup_state & SS_RESTARTSYS) {
212: error = ERESTART;
213: goto bad;
214: }
1.135 yamt 215: error = sowait(so, true, 0);
1.18 christos 216: if (error) {
1.128 ad 217: goto bad;
1.1 cgd 218: }
1.138 dsl 219: wakeup_state = so->so_state;
1.1 cgd 220: }
221: if (so->so_error) {
222: error = so->so_error;
223: so->so_error = 0;
1.128 ad 224: goto bad;
1.1 cgd 225: }
1.71 jdolecek 226: /* connection has been removed from the listen queue */
1.129 ad 227: KNOTE(&so->so_rcv.sb_sel.sel_klist, NOTE_SUBMIT);
1.128 ad 228: so2 = TAILQ_FIRST(&so->so_q);
229: if (soqremque(so2, 1) == 0)
1.1 cgd 230: panic("accept");
1.128 ad 231: fp2->f_type = DTYPE_SOCKET;
1.144 christos 232: fp2->f_flag = (fp->f_flag & ~clrflags) |
233: ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0);
1.128 ad 234: fp2->f_ops = &socketops;
235: fp2->f_data = so2;
236: error = soaccept(so2, nam);
1.139 elad 237: so2->so_cred = kauth_cred_dup(so->so_cred);
1.129 ad 238: sounlock(so);
1.49 mycroft 239: if (error) {
1.113 dsl 240: /* an error occurred, free the file descriptor and mbuf */
241: m_freem(nam);
1.128 ad 242: mutex_enter(&fp2->f_lock);
243: fp2->f_count++;
244: mutex_exit(&fp2->f_lock);
245: closef(fp2);
246: fd_abort(curproc, NULL, fd);
1.99 christos 247: } else {
1.144 christos 248: fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
1.128 ad 249: fd_affix(curproc, fp2, fd);
1.113 dsl 250: *name = nam;
1.49 mycroft 251: }
1.129 ad 252: fd_putfile(sock);
1.144 christos 253: if (__predict_false(mask))
254: sigsuspendteardown(l);
1.128 ad 255: return (error);
256: bad:
1.129 ad 257: sounlock(so);
1.128 ad 258: m_freem(nam);
1.129 ad 259: fd_putfile(sock);
1.128 ad 260: fd_abort(curproc, fp2, fd);
1.144 christos 261: if (__predict_false(mask))
262: sigsuspendteardown(l);
1.128 ad 263: return (error);
1.1 cgd 264: }
265:
1.113 dsl 266: int
1.125 dsl 267: sys_accept(struct lwp *l, const struct sys_accept_args *uap, register_t *retval)
1.113 dsl 268: {
1.125 dsl 269: /* {
1.113 dsl 270: syscallarg(int) s;
271: syscallarg(struct sockaddr *) name;
272: syscallarg(unsigned int *) anamelen;
1.125 dsl 273: } */
1.128 ad 274: int error, fd;
1.113 dsl 275: struct mbuf *name;
276:
1.144 christos 277: error = do_sys_accept(l, SCARG(uap, s), &name, retval, NULL, 0, 0);
278: if (error != 0)
279: return error;
280: error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
281: MSG_LENUSRSPACE, name);
282: if (name != NULL)
283: m_free(name);
284: if (error != 0) {
285: fd = (int)*retval;
286: if (fd_getfile(fd) != NULL)
287: (void)fd_close(fd);
288: }
289: return error;
290: }
291:
292: int
293: sys_paccept(struct lwp *l, const struct sys_paccept_args *uap,
294: register_t *retval)
295: {
296: /* {
297: syscallarg(int) s;
298: syscallarg(struct sockaddr *) name;
299: syscallarg(unsigned int *) anamelen;
300: syscallarg(const sigset_t *) mask;
301: syscallarg(int) flags;
302: } */
303: int error, fd;
304: struct mbuf *name;
305: sigset_t *mask, amask;
306:
307: if (SCARG(uap, mask) != NULL) {
308: error = copyin(SCARG(uap, mask), &amask, sizeof(amask));
309: if (error)
310: return error;
311: mask = &amask;
312: } else
313: mask = NULL;
314:
315: error = do_sys_accept(l, SCARG(uap, s), &name, retval, mask,
316: SCARG(uap, flags), FNONBLOCK);
1.113 dsl 317: if (error != 0)
318: return error;
319: error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
320: MSG_LENUSRSPACE, name);
321: if (name != NULL)
322: m_free(name);
1.128 ad 323: if (error != 0) {
324: fd = (int)*retval;
325: if (fd_getfile(fd) != NULL)
326: (void)fd_close(fd);
327: }
1.113 dsl 328: return error;
329: }
330:
1.1 cgd 331: /* ARGSUSED */
1.7 mycroft 332: int
1.125 dsl 333: sys_connect(struct lwp *l, const struct sys_connect_args *uap, register_t *retval)
1.15 thorpej 334: {
1.125 dsl 335: /* {
1.57 lukem 336: syscallarg(int) s;
337: syscallarg(const struct sockaddr *) name;
338: syscallarg(unsigned int) namelen;
1.125 dsl 339: } */
1.111 dsl 340: int error;
341: struct mbuf *nam;
342:
1.112 enami 343: error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
344: MT_SONAME);
1.111 dsl 345: if (error)
346: return error;
347: return do_sys_connect(l, SCARG(uap, s), nam);
348: }
349:
350: int
1.128 ad 351: do_sys_connect(struct lwp *l, int fd, struct mbuf *nam)
1.111 dsl 352: {
1.57 lukem 353: struct socket *so;
1.111 dsl 354: int error;
1.87 ragge 355: int interrupted = 0;
1.1 cgd 356:
1.128 ad 357: if ((error = fd_getsock(fd, &so)) != 0) {
1.111 dsl 358: m_freem(nam);
1.1 cgd 359: return (error);
1.111 dsl 360: }
1.129 ad 361: solock(so);
1.111 dsl 362: MCLAIM(nam, so->so_mowner);
1.136 ad 363: if ((so->so_state & SS_ISCONNECTING) != 0) {
1.62 jdolecek 364: error = EALREADY;
365: goto out;
366: }
1.111 dsl 367:
1.95 christos 368: error = soconnect(so, nam, l);
1.1 cgd 369: if (error)
370: goto bad;
1.136 ad 371: if (so->so_nbio && (so->so_state & SS_ISCONNECTING) != 0) {
1.62 jdolecek 372: error = EINPROGRESS;
373: goto out;
1.1 cgd 374: }
1.136 ad 375: while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) {
1.135 yamt 376: error = sowait(so, true, 0);
1.137 dsl 377: if (__predict_false((so->so_state & SS_ISABORTING) != 0)) {
1.136 ad 378: error = EPIPE;
379: interrupted = 1;
380: break;
381: }
1.87 ragge 382: if (error) {
383: if (error == EINTR || error == ERESTART)
384: interrupted = 1;
1.1 cgd 385: break;
1.87 ragge 386: }
1.18 christos 387: }
1.1 cgd 388: if (error == 0) {
389: error = so->so_error;
390: so->so_error = 0;
391: }
1.57 lukem 392: bad:
1.87 ragge 393: if (!interrupted)
394: so->so_state &= ~SS_ISCONNECTING;
1.1 cgd 395: if (error == ERESTART)
396: error = EINTR;
1.62 jdolecek 397: out:
1.129 ad 398: sounlock(so);
1.128 ad 399: fd_putfile(fd);
1.111 dsl 400: m_freem(nam);
1.1 cgd 401: return (error);
402: }
403:
1.7 mycroft 404: int
1.125 dsl 405: sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap, register_t *retval)
1.15 thorpej 406: {
1.125 dsl 407: /* {
1.57 lukem 408: syscallarg(int) domain;
409: syscallarg(int) type;
410: syscallarg(int) protocol;
411: syscallarg(int *) rsv;
1.125 dsl 412: } */
1.128 ad 413: file_t *fp1, *fp2;
1.57 lukem 414: struct socket *so1, *so2;
415: int fd, error, sv[2];
1.128 ad 416: proc_t *p;
1.144 christos 417: int flags = SCARG(uap, type) & SOCK_FLAGS_MASK;
418: int type = SCARG(uap, type) & ~SOCK_FLAGS_MASK;
419: int fnonblock = (flags & SOCK_NONBLOCK) ? FNONBLOCK : 0;
1.1 cgd 420:
1.128 ad 421: p = curproc;
1.144 christos 422: error = socreate(SCARG(uap, domain), &so1, type,
1.129 ad 423: SCARG(uap, protocol), l, NULL);
1.18 christos 424: if (error)
1.1 cgd 425: return (error);
1.144 christos 426: error = socreate(SCARG(uap, domain), &so2, type,
1.129 ad 427: SCARG(uap, protocol), l, so1);
1.18 christos 428: if (error)
1.1 cgd 429: goto free1;
1.128 ad 430: if ((error = fd_allocfile(&fp1, &fd)) != 0)
1.1 cgd 431: goto free2;
1.144 christos 432: fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
1.1 cgd 433: sv[0] = fd;
1.144 christos 434: fp1->f_flag = FREAD|FWRITE|fnonblock;
1.1 cgd 435: fp1->f_type = DTYPE_SOCKET;
436: fp1->f_ops = &socketops;
1.110 dsl 437: fp1->f_data = so1;
1.128 ad 438: if ((error = fd_allocfile(&fp2, &fd)) != 0)
1.1 cgd 439: goto free3;
1.144 christos 440: fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
441: fp2->f_flag = FREAD|FWRITE|fnonblock;
1.1 cgd 442: fp2->f_type = DTYPE_SOCKET;
443: fp2->f_ops = &socketops;
1.110 dsl 444: fp2->f_data = so2;
1.1 cgd 445: sv[1] = fd;
1.129 ad 446: solock(so1);
447: error = soconnect2(so1, so2);
448: if (error == 0 && SCARG(uap, type) == SOCK_DGRAM) {
1.1 cgd 449: /*
450: * Datagram socket connection is asymmetric.
451: */
1.129 ad 452: error = soconnect2(so2, so1);
453: }
454: sounlock(so1);
455: if (error == 0)
456: error = copyout(sv, SCARG(uap, rsv), 2 * sizeof(int));
457: if (error == 0) {
458: fd_affix(p, fp2, sv[1]);
459: fd_affix(p, fp1, sv[0]);
460: return (0);
1.1 cgd 461: }
1.128 ad 462: fd_abort(p, fp2, sv[1]);
1.57 lukem 463: free3:
1.128 ad 464: fd_abort(p, fp1, sv[0]);
1.57 lukem 465: free2:
1.1 cgd 466: (void)soclose(so2);
1.57 lukem 467: free1:
1.1 cgd 468: (void)soclose(so1);
469: return (error);
470: }
471:
1.7 mycroft 472: int
1.125 dsl 473: sys_sendto(struct lwp *l, const struct sys_sendto_args *uap, register_t *retval)
1.15 thorpej 474: {
1.125 dsl 475: /* {
1.57 lukem 476: syscallarg(int) s;
477: syscallarg(const void *) buf;
478: syscallarg(size_t) len;
479: syscallarg(int) flags;
480: syscallarg(const struct sockaddr *) to;
481: syscallarg(unsigned int) tolen;
1.125 dsl 482: } */
1.57 lukem 483: struct msghdr msg;
484: struct iovec aiov;
1.1 cgd 485:
1.91 christos 486: msg.msg_name = __UNCONST(SCARG(uap, to)); /* XXXUNCONST kills const */
1.9 cgd 487: msg.msg_namelen = SCARG(uap, tolen);
1.1 cgd 488: msg.msg_iov = &aiov;
489: msg.msg_iovlen = 1;
1.121 christos 490: msg.msg_control = NULL;
1.1 cgd 491: msg.msg_flags = 0;
1.91 christos 492: aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */
1.9 cgd 493: aiov.iov_len = SCARG(uap, len);
1.111 dsl 494: return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
1.1 cgd 495: }
496:
1.7 mycroft 497: int
1.125 dsl 498: sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, register_t *retval)
1.15 thorpej 499: {
1.125 dsl 500: /* {
1.57 lukem 501: syscallarg(int) s;
502: syscallarg(const struct msghdr *) msg;
503: syscallarg(int) flags;
1.125 dsl 504: } */
1.57 lukem 505: struct msghdr msg;
506: int error;
1.1 cgd 507:
1.110 dsl 508: error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
1.18 christos 509: if (error)
1.1 cgd 510: return (error);
1.111 dsl 511:
512: msg.msg_flags = MSG_IOVUSRSPACE;
513: return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
1.1 cgd 514: }
515:
1.7 mycroft 516: int
1.111 dsl 517: do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
518: register_t *retsize)
1.1 cgd 519: {
1.141 rmind 520: struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
1.57 lukem 521: struct mbuf *to, *control;
522: struct socket *so;
1.141 rmind 523: struct uio auio;
524: size_t len, iovsz;
525: int i, error;
1.90 perry 526:
1.117 dsl 527: ktrkuser("msghdr", mp, sizeof *mp);
528:
1.141 rmind 529: /* If the caller passed us stuff in mbufs, we must free them. */
530: to = (mp->msg_flags & MSG_NAMEMBUF) ? mp->msg_name : NULL;
531: control = (mp->msg_flags & MSG_CONTROLMBUF) ? mp->msg_control : NULL;
532: iovsz = mp->msg_iovlen * sizeof(struct iovec);
1.111 dsl 533:
534: if (mp->msg_flags & MSG_IOVUSRSPACE) {
535: if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
536: if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
537: error = EMSGSIZE;
538: goto bad;
539: }
1.141 rmind 540: iov = kmem_alloc(iovsz, KM_SLEEP);
1.111 dsl 541: }
542: if (mp->msg_iovlen != 0) {
1.141 rmind 543: error = copyin(mp->msg_iov, iov, iovsz);
1.111 dsl 544: if (error)
545: goto bad;
546: }
547: mp->msg_iov = iov;
548: }
549:
1.1 cgd 550: auio.uio_iov = mp->msg_iov;
551: auio.uio_iovcnt = mp->msg_iovlen;
552: auio.uio_rw = UIO_WRITE;
553: auio.uio_offset = 0; /* XXX */
554: auio.uio_resid = 0;
1.97 yamt 555: KASSERT(l == curlwp);
556: auio.uio_vmspace = l->l_proc->p_vmspace;
1.111 dsl 557:
558: for (i = 0, tiov = mp->msg_iov; i < mp->msg_iovlen; i++, tiov++) {
1.33 thorpej 559: /*
560: * Writes return ssize_t because -1 is returned on error.
561: * Therefore, we must restrict the length to SSIZE_MAX to
562: * avoid garbage return values.
563: */
1.111 dsl 564: auio.uio_resid += tiov->iov_len;
565: if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
1.43 thorpej 566: error = EINVAL;
1.111 dsl 567: goto bad;
1.43 thorpej 568: }
1.1 cgd 569: }
1.111 dsl 570:
1.112 enami 571: if (mp->msg_name && to == NULL) {
1.63 jdolecek 572: error = sockargs(&to, mp->msg_name, mp->msg_namelen,
1.112 enami 573: MT_SONAME);
1.63 jdolecek 574: if (error)
1.111 dsl 575: goto bad;
576: }
577:
1.1 cgd 578: if (mp->msg_control) {
1.104 elad 579: if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
1.1 cgd 580: error = EINVAL;
581: goto bad;
582: }
1.112 enami 583: if (control == NULL) {
1.111 dsl 584: error = sockargs(&control, mp->msg_control,
1.112 enami 585: mp->msg_controllen, MT_CONTROL);
1.111 dsl 586: if (error)
587: goto bad;
588: }
589: }
590:
1.116 ad 591: if (ktrpoint(KTR_GENIO)) {
1.141 rmind 592: ktriov = kmem_alloc(iovsz, KM_SLEEP);
593: memcpy(ktriov, auio.uio_iov, iovsz);
1.1 cgd 594: }
1.111 dsl 595:
1.128 ad 596: if ((error = fd_getsock(s, &so)) != 0)
1.111 dsl 597: goto bad;
598:
599: if (mp->msg_name)
600: MCLAIM(to, so->so_mowner);
601: if (mp->msg_control)
602: MCLAIM(control, so->so_mowner);
603:
1.1 cgd 604: len = auio.uio_resid;
1.95 christos 605: error = (*so->so_send)(so, to, &auio, NULL, control, flags, l);
1.111 dsl 606: /* Protocol is responsible for freeing 'control' */
607: control = NULL;
608:
1.128 ad 609: fd_putfile(s);
1.111 dsl 610:
1.18 christos 611: if (error) {
1.1 cgd 612: if (auio.uio_resid != len && (error == ERESTART ||
613: error == EINTR || error == EWOULDBLOCK))
614: error = 0;
1.106 ad 615: if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
1.130 ad 616: mutex_enter(proc_lock);
1.111 dsl 617: psignal(l->l_proc, SIGPIPE);
1.130 ad 618: mutex_exit(proc_lock);
1.106 ad 619: }
1.1 cgd 620: }
621: if (error == 0)
622: *retsize = len - auio.uio_resid;
1.111 dsl 623:
1.119 rmind 624: bad:
1.1 cgd 625: if (ktriov != NULL) {
1.116 ad 626: ktrgeniov(s, UIO_WRITE, ktriov, *retsize, error);
1.141 rmind 627: kmem_free(ktriov, iovsz);
1.1 cgd 628: }
1.111 dsl 629:
1.119 rmind 630: if (iov != aiov)
1.141 rmind 631: kmem_free(iov, iovsz);
1.1 cgd 632: if (to)
633: m_freem(to);
1.121 christos 634: if (control)
1.111 dsl 635: m_freem(control);
636:
1.1 cgd 637: return (error);
638: }
639:
1.7 mycroft 640: int
1.125 dsl 641: sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval)
1.15 thorpej 642: {
1.125 dsl 643: /* {
1.57 lukem 644: syscallarg(int) s;
645: syscallarg(void *) buf;
646: syscallarg(size_t) len;
647: syscallarg(int) flags;
648: syscallarg(struct sockaddr *) from;
649: syscallarg(unsigned int *) fromlenaddr;
1.125 dsl 650: } */
1.57 lukem 651: struct msghdr msg;
652: struct iovec aiov;
653: int error;
1.113 dsl 654: struct mbuf *from;
1.1 cgd 655:
1.121 christos 656: msg.msg_name = NULL;
1.1 cgd 657: msg.msg_iov = &aiov;
658: msg.msg_iovlen = 1;
1.9 cgd 659: aiov.iov_base = SCARG(uap, buf);
660: aiov.iov_len = SCARG(uap, len);
1.113 dsl 661: msg.msg_control = NULL;
662: msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
663:
664: error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
665: if (error != 0)
666: return error;
667:
668: error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr),
669: MSG_LENUSRSPACE, from);
670: if (from != NULL)
671: m_free(from);
672: return error;
1.1 cgd 673: }
674:
1.7 mycroft 675: int
1.125 dsl 676: sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, register_t *retval)
1.15 thorpej 677: {
1.125 dsl 678: /* {
1.57 lukem 679: syscallarg(int) s;
680: syscallarg(struct msghdr *) msg;
681: syscallarg(int) flags;
1.125 dsl 682: } */
1.81 fvdl 683: struct msghdr msg;
1.57 lukem 684: int error;
1.113 dsl 685: struct mbuf *from, *control;
1.1 cgd 686:
1.110 dsl 687: error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
1.18 christos 688: if (error)
1.1 cgd 689: return (error);
1.113 dsl 690:
691: msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
692:
693: error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
694: msg.msg_control != NULL ? &control : NULL, retval);
695: if (error != 0)
696: return error;
697:
698: if (msg.msg_control != NULL)
699: error = copyout_msg_control(l, &msg, control);
700:
701: if (error == 0)
702: error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
703: from);
704: if (from != NULL)
705: m_free(from);
1.117 dsl 706: if (error == 0) {
707: ktrkuser("msghdr", &msg, sizeof msg);
1.110 dsl 708: error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
1.117 dsl 709: }
1.113 dsl 710:
1.1 cgd 711: return (error);
712: }
713:
1.92 martin 714: /*
1.113 dsl 715: * Adjust for a truncated SCM_RIGHTS control message.
716: * This means closing any file descriptors that aren't present
717: * in the returned buffer.
718: * m is the mbuf holding the (already externalized) SCM_RIGHTS message.
1.92 martin 719: */
1.93 martin 720: static void
1.128 ad 721: free_rights(struct mbuf *m)
1.92 martin 722: {
723: int nfd;
724: int i;
725: int *fdv;
726:
1.94 martin 727: nfd = m->m_len < CMSG_SPACE(sizeof(int)) ? 0
728: : (m->m_len - CMSG_SPACE(sizeof(int))) / sizeof(int) + 1;
1.92 martin 729: fdv = (int *) CMSG_DATA(mtod(m,struct cmsghdr *));
1.128 ad 730: for (i = 0; i < nfd; i++) {
731: if (fd_getfile(fdv[i]) != NULL)
732: (void)fd_close(fdv[i]);
733: }
1.113 dsl 734: }
735:
736: void
737: free_control_mbuf(struct lwp *l, struct mbuf *control, struct mbuf *uncopied)
738: {
739: struct mbuf *next;
1.114 dsl 740: struct cmsghdr *cmsg;
1.113 dsl 741: bool do_free_rights = false;
742:
743: while (control != NULL) {
1.114 dsl 744: cmsg = mtod(control, struct cmsghdr *);
1.113 dsl 745: if (control == uncopied)
746: do_free_rights = true;
1.114 dsl 747: if (do_free_rights && cmsg->cmsg_level == SOL_SOCKET
748: && cmsg->cmsg_type == SCM_RIGHTS)
1.128 ad 749: free_rights(control);
1.113 dsl 750: next = control->m_next;
751: m_free(control);
752: control = next;
753: }
754: }
755:
756: /* Copy socket control/CMSG data to user buffer, frees the mbuf */
757: int
758: copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
759: {
760: int i, len, error = 0;
1.114 dsl 761: struct cmsghdr *cmsg;
1.113 dsl 762: struct mbuf *m;
763: char *q;
764:
765: len = mp->msg_controllen;
766: if (len <= 0 || control == 0) {
767: mp->msg_controllen = 0;
768: free_control_mbuf(l, control, control);
769: return 0;
770: }
771:
772: q = (char *)mp->msg_control;
773:
774: for (m = control; m != NULL; ) {
1.114 dsl 775: cmsg = mtod(m, struct cmsghdr *);
1.113 dsl 776: i = m->m_len;
777: if (len < i) {
778: mp->msg_flags |= MSG_CTRUNC;
1.114 dsl 779: if (cmsg->cmsg_level == SOL_SOCKET
780: && cmsg->cmsg_type == SCM_RIGHTS)
1.113 dsl 781: /* Do not truncate me ... */
782: break;
783: i = len;
784: }
785: error = copyout(mtod(m, void *), q, i);
1.117 dsl 786: ktrkuser("msgcontrol", mtod(m, void *), i);
1.113 dsl 787: if (error != 0) {
788: /* We must free all the SCM_RIGHTS */
789: m = control;
790: break;
791: }
792: m = m->m_next;
793: if (m)
794: i = ALIGN(i);
795: q += i;
796: len -= i;
797: if (len <= 0)
798: break;
799: }
800:
801: free_control_mbuf(l, control, m);
802:
803: mp->msg_controllen = q - (char *)mp->msg_control;
804: return error;
1.92 martin 805: }
806:
1.7 mycroft 807: int
1.113 dsl 808: do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
809: struct mbuf **control, register_t *retsize)
1.1 cgd 810: {
1.141 rmind 811: struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov;
812: struct socket *so;
1.57 lukem 813: struct uio auio;
1.141 rmind 814: size_t len, iovsz;
815: int i, error;
1.57 lukem 816:
1.117 dsl 817: ktrkuser("msghdr", mp, sizeof *mp);
818:
1.113 dsl 819: *from = NULL;
820: if (control != NULL)
821: *control = NULL;
1.90 perry 822:
1.128 ad 823: if ((error = fd_getsock(s, &so)) != 0)
1.1 cgd 824: return (error);
1.113 dsl 825:
1.141 rmind 826: iovsz = mp->msg_iovlen * sizeof(struct iovec);
827:
1.113 dsl 828: if (mp->msg_flags & MSG_IOVUSRSPACE) {
829: if ((unsigned int)mp->msg_iovlen > UIO_SMALLIOV) {
830: if ((unsigned int)mp->msg_iovlen > IOV_MAX) {
831: error = EMSGSIZE;
832: goto out;
833: }
1.141 rmind 834: iov = kmem_alloc(iovsz, KM_SLEEP);
1.113 dsl 835: }
836: if (mp->msg_iovlen != 0) {
1.141 rmind 837: error = copyin(mp->msg_iov, iov, iovsz);
1.113 dsl 838: if (error)
839: goto out;
840: }
841: auio.uio_iov = iov;
842: } else
843: auio.uio_iov = mp->msg_iov;
1.1 cgd 844: auio.uio_iovcnt = mp->msg_iovlen;
845: auio.uio_rw = UIO_READ;
846: auio.uio_offset = 0; /* XXX */
847: auio.uio_resid = 0;
1.97 yamt 848: KASSERT(l == curlwp);
849: auio.uio_vmspace = l->l_proc->p_vmspace;
1.113 dsl 850:
851: tiov = auio.uio_iov;
852: for (i = 0; i < mp->msg_iovlen; i++, tiov++) {
1.33 thorpej 853: /*
854: * Reads return ssize_t because -1 is returned on error.
855: * Therefore we must restrict the length to SSIZE_MAX to
856: * avoid garbage return values.
857: */
1.113 dsl 858: auio.uio_resid += tiov->iov_len;
859: if (tiov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
1.43 thorpej 860: error = EINVAL;
1.113 dsl 861: goto out;
1.43 thorpej 862: }
1.1 cgd 863: }
864:
1.116 ad 865: ktriov = NULL;
866: if (ktrpoint(KTR_GENIO)) {
1.141 rmind 867: ktriov = kmem_alloc(iovsz, KM_SLEEP);
868: memcpy(ktriov, auio.uio_iov, iovsz);
1.1 cgd 869: }
1.113 dsl 870:
1.1 cgd 871: len = auio.uio_resid;
1.115 dsl 872: mp->msg_flags &= MSG_USERFLAGS;
1.113 dsl 873: error = (*so->so_receive)(so, from, &auio, NULL, control,
1.129 ad 874: &mp->msg_flags);
1.113 dsl 875: len -= auio.uio_resid;
876: *retsize = len;
877: if (error != 0 && len != 0
878: && (error == ERESTART || error == EINTR || error == EWOULDBLOCK))
879: /* Some data transferred */
880: error = 0;
1.116 ad 881:
1.1 cgd 882: if (ktriov != NULL) {
1.116 ad 883: ktrgeniov(s, UIO_READ, ktriov, len, error);
1.141 rmind 884: kmem_free(ktriov, iovsz);
1.1 cgd 885: }
1.116 ad 886:
1.113 dsl 887: if (error != 0) {
888: m_freem(*from);
889: *from = NULL;
890: if (control != NULL) {
891: free_control_mbuf(l, *control, *control);
892: *control = NULL;
1.1 cgd 893: }
894: }
1.43 thorpej 895: out:
1.113 dsl 896: if (iov != aiov)
1.141 rmind 897: kmem_free(iov, iovsz);
1.128 ad 898: fd_putfile(s);
1.1 cgd 899: return (error);
900: }
901:
1.113 dsl 902:
1.1 cgd 903: /* ARGSUSED */
1.7 mycroft 904: int
1.125 dsl 905: sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval)
1.15 thorpej 906: {
1.125 dsl 907: /* {
1.57 lukem 908: syscallarg(int) s;
909: syscallarg(int) how;
1.125 dsl 910: } */
1.128 ad 911: struct socket *so;
1.57 lukem 912: int error;
1.1 cgd 913:
1.128 ad 914: if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1.1 cgd 915: return (error);
1.129 ad 916: solock(so);
1.128 ad 917: error = soshutdown(so, SCARG(uap, how));
1.129 ad 918: sounlock(so);
1.128 ad 919: fd_putfile(SCARG(uap, s));
1.43 thorpej 920: return (error);
1.1 cgd 921: }
922:
923: /* ARGSUSED */
1.7 mycroft 924: int
1.125 dsl 925: sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap, register_t *retval)
1.15 thorpej 926: {
1.125 dsl 927: /* {
1.57 lukem 928: syscallarg(int) s;
929: syscallarg(int) level;
930: syscallarg(int) name;
931: syscallarg(const void *) val;
932: syscallarg(unsigned int) valsize;
1.125 dsl 933: } */
1.134 plunky 934: struct sockopt sopt;
1.76 matt 935: struct socket *so;
1.57 lukem 936: int error;
1.75 thorpej 937: unsigned int len;
1.1 cgd 938:
1.134 plunky 939: len = SCARG(uap, valsize);
940: if (len > 0 && SCARG(uap, val) == NULL)
941: return (EINVAL);
942:
943: if (len > MCLBYTES)
944: return (EINVAL);
945:
1.128 ad 946: if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1.1 cgd 947: return (error);
1.134 plunky 948:
949: sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len);
950:
951: if (len > 0) {
952: error = copyin(SCARG(uap, val), sopt.sopt_data, len);
953: if (error)
1.43 thorpej 954: goto out;
1.1 cgd 955: }
1.134 plunky 956:
957: error = sosetopt(so, &sopt);
958:
1.43 thorpej 959: out:
1.134 plunky 960: sockopt_destroy(&sopt);
1.128 ad 961: fd_putfile(SCARG(uap, s));
1.43 thorpej 962: return (error);
1.1 cgd 963: }
964:
965: /* ARGSUSED */
1.7 mycroft 966: int
1.125 dsl 967: sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap, register_t *retval)
1.15 thorpej 968: {
1.125 dsl 969: /* {
1.57 lukem 970: syscallarg(int) s;
971: syscallarg(int) level;
972: syscallarg(int) name;
973: syscallarg(void *) val;
974: syscallarg(unsigned int *) avalsize;
1.125 dsl 975: } */
1.134 plunky 976: struct sockopt sopt;
1.128 ad 977: struct socket *so;
1.134 plunky 978: unsigned int valsize, len;
1.57 lukem 979: int error;
1.1 cgd 980:
1.134 plunky 981: if (SCARG(uap, val) != NULL) {
982: error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize));
983: if (error)
984: return (error);
985: } else
986: valsize = 0;
987:
1.128 ad 988: if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
1.1 cgd 989: return (error);
1.134 plunky 990:
991: sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0);
992:
993: error = sogetopt(so, &sopt);
994: if (error)
995: goto out;
996:
997: if (valsize > 0) {
998: len = min(valsize, sopt.sopt_size);
999: error = copyout(sopt.sopt_data, SCARG(uap, val), len);
1000: if (error)
1001: goto out;
1002:
1003: error = copyout(&len, SCARG(uap, avalsize), sizeof(len));
1.18 christos 1004: if (error)
1.43 thorpej 1005: goto out;
1.1 cgd 1006: }
1.134 plunky 1007:
1.43 thorpej 1008: out:
1.134 plunky 1009: sockopt_destroy(&sopt);
1.128 ad 1010: fd_putfile(SCARG(uap, s));
1.1 cgd 1011: return (error);
1012: }
1013:
1.68 jdolecek 1014: #ifdef PIPE_SOCKETPAIR
1.1 cgd 1015: /* ARGSUSED */
1.7 mycroft 1016: int
1.142 christos 1017: pipe1(struct lwp *l, register_t *retval, int flags)
1.1 cgd 1018: {
1.128 ad 1019: file_t *rf, *wf;
1.57 lukem 1020: struct socket *rso, *wso;
1021: int fd, error;
1.128 ad 1022: proc_t *p;
1.1 cgd 1023:
1.145 ! christos 1024: if (flags & ~(O_CLOEXEC|O_NONBLOCK))
! 1025: return EINVAL;
1.128 ad 1026: p = curproc;
1.129 ad 1027: if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
1.1 cgd 1028: return (error);
1.129 ad 1029: if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
1.1 cgd 1030: goto free1;
1.58 manu 1031: /* remember this socket pair implements a pipe */
1032: wso->so_state |= SS_ISAPIPE;
1033: rso->so_state |= SS_ISAPIPE;
1.128 ad 1034: if ((error = fd_allocfile(&rf, &fd)) != 0)
1.1 cgd 1035: goto free2;
1036: retval[0] = fd;
1.142 christos 1037: rf->f_flag = FREAD | flags;
1.1 cgd 1038: rf->f_type = DTYPE_SOCKET;
1039: rf->f_ops = &socketops;
1.110 dsl 1040: rf->f_data = rso;
1.128 ad 1041: if ((error = fd_allocfile(&wf, &fd)) != 0)
1.1 cgd 1042: goto free3;
1.142 christos 1043: wf->f_flag = FWRITE | flags;
1.1 cgd 1044: wf->f_type = DTYPE_SOCKET;
1045: wf->f_ops = &socketops;
1.110 dsl 1046: wf->f_data = wso;
1.1 cgd 1047: retval[1] = fd;
1.129 ad 1048: solock(wso);
1049: error = unp_connect2(wso, rso, PRU_CONNECT2);
1050: sounlock(wso);
1051: if (error != 0)
1.1 cgd 1052: goto free4;
1.128 ad 1053: fd_affix(p, wf, (int)retval[1]);
1054: fd_affix(p, rf, (int)retval[0]);
1.1 cgd 1055: return (0);
1.57 lukem 1056: free4:
1.128 ad 1057: fd_abort(p, wf, (int)retval[1]);
1.57 lukem 1058: free3:
1.128 ad 1059: fd_abort(p, rf, (int)retval[0]);
1.57 lukem 1060: free2:
1.1 cgd 1061: (void)soclose(wso);
1.57 lukem 1062: free1:
1.1 cgd 1063: (void)soclose(rso);
1064: return (error);
1065: }
1.68 jdolecek 1066: #endif /* PIPE_SOCKETPAIR */
1.1 cgd 1067:
1068: /*
1069: * Get socket name.
1070: */
1.13 christos 1071: /* ARGSUSED */
1.7 mycroft 1072: int
1.113 dsl 1073: do_sys_getsockname(struct lwp *l, int fd, int which, struct mbuf **nam)
1.15 thorpej 1074: {
1.57 lukem 1075: struct socket *so;
1076: struct mbuf *m;
1077: int error;
1.1 cgd 1078:
1.128 ad 1079: if ((error = fd_getsock(fd, &so)) != 0)
1.113 dsl 1080: return error;
1081:
1.129 ad 1082: m = m_getclr(M_WAIT, MT_SONAME);
1083: MCLAIM(m, so->so_mowner);
1084:
1085: solock(so);
1.113 dsl 1086: if (which == PRU_PEERADDR
1087: && (so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) {
1088: error = ENOTCONN;
1.129 ad 1089: } else {
1090: *nam = m;
1091: error = (*so->so_proto->pr_usrreq)(so, which, NULL, m, NULL,
1092: NULL);
1.113 dsl 1093: }
1.129 ad 1094: sounlock(so);
1.113 dsl 1095: if (error != 0)
1096: m_free(m);
1.128 ad 1097: fd_putfile(fd);
1.113 dsl 1098: return error;
1099: }
1100:
1101: int
1102: copyout_sockname(struct sockaddr *asa, unsigned int *alen, int flags,
1103: struct mbuf *addr)
1104: {
1105: int len;
1106: int error;
1107:
1108: if (asa == NULL)
1109: /* Assume application not interested */
1110: return 0;
1111:
1112: if (flags & MSG_LENUSRSPACE) {
1113: error = copyin(alen, &len, sizeof(len));
1114: if (error)
1115: return error;
1116: } else
1117: len = *alen;
1.118 dsl 1118: if (len < 0)
1.113 dsl 1119: return EINVAL;
1120:
1121: if (addr == NULL) {
1122: len = 0;
1123: error = 0;
1124: } else {
1125: if (len > addr->m_len)
1126: len = addr->m_len;
1127: /* Maybe this ought to copy a chain ? */
1.117 dsl 1128: ktrkuser("sockname", mtod(addr, void *), len);
1.113 dsl 1129: error = copyout(mtod(addr, void *), asa, len);
1130: }
1131:
1132: if (error == 0) {
1133: if (flags & MSG_LENUSRSPACE)
1134: error = copyout(&len, alen, sizeof(len));
1135: else
1136: *alen = len;
1137: }
1138:
1139: return error;
1140: }
1141:
1142: /*
1143: * Get socket name.
1144: */
1145: /* ARGSUSED */
1146: int
1.125 dsl 1147: sys_getsockname(struct lwp *l, const struct sys_getsockname_args *uap, register_t *retval)
1.113 dsl 1148: {
1.125 dsl 1149: /* {
1.113 dsl 1150: syscallarg(int) fdes;
1151: syscallarg(struct sockaddr *) asa;
1152: syscallarg(unsigned int *) alen;
1.125 dsl 1153: } */
1.113 dsl 1154: struct mbuf *m;
1155: int error;
1156:
1157: error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_SOCKADDR, &m);
1158: if (error != 0)
1159: return error;
1160:
1161: error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
1162: MSG_LENUSRSPACE, m);
1163: if (m != NULL)
1164: m_free(m);
1165: return error;
1.1 cgd 1166: }
1167:
1168: /*
1169: * Get name of peer for connected socket.
1170: */
1.13 christos 1171: /* ARGSUSED */
1.7 mycroft 1172: int
1.125 dsl 1173: sys_getpeername(struct lwp *l, const struct sys_getpeername_args *uap, register_t *retval)
1.15 thorpej 1174: {
1.125 dsl 1175: /* {
1.57 lukem 1176: syscallarg(int) fdes;
1177: syscallarg(struct sockaddr *) asa;
1178: syscallarg(unsigned int *) alen;
1.125 dsl 1179: } */
1.57 lukem 1180: struct mbuf *m;
1181: int error;
1.1 cgd 1182:
1.113 dsl 1183: error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_PEERADDR, &m);
1184: if (error != 0)
1185: return error;
1186:
1187: error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
1188: MSG_LENUSRSPACE, m);
1189: if (m != NULL)
1190: m_free(m);
1191: return error;
1.1 cgd 1192: }
1193:
1.24 thorpej 1194: /*
1195: * XXX In a perfect world, we wouldn't pass around socket control
1196: * XXX arguments in mbufs, and this could go away.
1197: */
1.7 mycroft 1198: int
1.91 christos 1199: sockargs(struct mbuf **mp, const void *bf, size_t buflen, int type)
1.1 cgd 1200: {
1.57 lukem 1201: struct sockaddr *sa;
1202: struct mbuf *m;
1203: int error;
1.1 cgd 1204:
1.24 thorpej 1205: /*
1.25 thorpej 1206: * We can't allow socket names > UCHAR_MAX in length, since that
1.64 matt 1207: * will overflow sa_len. Control data more than a page size in
1208: * length is just too much.
1.24 thorpej 1209: */
1.64 matt 1210: if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
1.24 thorpej 1211: return (EINVAL);
1212:
1213: /* Allocate an mbuf to hold the arguments. */
1214: m = m_get(M_WAIT, type);
1.76 matt 1215: /* can't claim. don't who to assign it to. */
1.64 matt 1216: if (buflen > MLEN) {
1.24 thorpej 1217: /*
1218: * Won't fit into a regular mbuf, so we allocate just
1219: * enough external storage to hold the argument.
1220: */
1221: MEXTMALLOC(m, buflen, M_WAITOK);
1.1 cgd 1222: }
1223: m->m_len = buflen;
1.107 christos 1224: error = copyin(bf, mtod(m, void *), buflen);
1.1 cgd 1225: if (error) {
1226: (void) m_free(m);
1.7 mycroft 1227: return (error);
1.1 cgd 1228: }
1.117 dsl 1229: ktrkuser("sockargs", mtod(m, void *), buflen);
1.1 cgd 1230: *mp = m;
1231: if (type == MT_SONAME) {
1.7 mycroft 1232: sa = mtod(m, struct sockaddr *);
1.65 jdolecek 1233: #if BYTE_ORDER != BIG_ENDIAN
1234: /*
1235: * 4.3BSD compat thing - need to stay, since bind(2),
1236: * connect(2), sendto(2) were not versioned for COMPAT_43.
1237: */
1.1 cgd 1238: if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1239: sa->sa_family = sa->sa_len;
1240: #endif
1241: sa->sa_len = buflen;
1242: }
1243: return (0);
1244: }
CVSweb <webmaster@jp.NetBSD.org>