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