Annotation of src/sys/kern/uipc_syscalls.c, Revision 1.54
1.54 ! thorpej 1: /* $NetBSD: uipc_syscalls.c,v 1.53 2000/06/27 17:41:45 mrg Exp $ */
1.8 cgd 2:
1.1 cgd 3: /*
1.7 mycroft 4: * Copyright (c) 1982, 1986, 1989, 1990, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
1.29 fvdl 35: * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95
1.1 cgd 36: */
1.31 thorpej 37:
38: #include "opt_ktrace.h"
1.40 drochner 39: #include "opt_compat_freebsd.h"
40: #include "opt_compat_linux.h"
41: #include "opt_compat_sunos.h"
42: #include "opt_compat_hpux.h"
43: #include "opt_compat_ultrix.h"
44: #include "opt_compat_43.h"
1.42 cgd 45: #include "opt_compat_osf1.h"
1.40 drochner 46: #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) || \
1.42 cgd 47: defined(COMPAT_HPUX) || defined(COMPAT_FREEBSD) || \
48: defined(COMPAT_ULTRIX) || defined(COMPAT_OSF1)
1.40 drochner 49: #define COMPAT_OLDSOCK /* used by <sys/socket.h> */
50: #endif
1.1 cgd 51:
1.6 mycroft 52: #include <sys/param.h>
1.9 cgd 53: #include <sys/systm.h>
1.6 mycroft 54: #include <sys/filedesc.h>
55: #include <sys/proc.h>
56: #include <sys/file.h>
57: #include <sys/buf.h>
58: #include <sys/malloc.h>
59: #include <sys/mbuf.h>
60: #include <sys/protosw.h>
61: #include <sys/socket.h>
62: #include <sys/socketvar.h>
1.18 christos 63: #include <sys/signalvar.h>
64: #include <sys/un.h>
1.1 cgd 65: #ifdef KTRACE
1.6 mycroft 66: #include <sys/ktrace.h>
1.1 cgd 67: #endif
68:
1.9 cgd 69: #include <sys/mount.h>
70: #include <sys/syscallargs.h>
71:
1.44 darrenr 72: #include <uvm/uvm_extern.h>
73:
1.1 cgd 74: /*
75: * System call interface to the socket abstraction.
76: */
77: extern struct fileops socketops;
78:
1.7 mycroft 79: int
1.16 mycroft 80: sys_socket(p, v, retval)
1.1 cgd 81: struct proc *p;
1.15 thorpej 82: void *v;
83: register_t *retval;
84: {
1.51 augustss 85: struct sys_socket_args /* {
1.9 cgd 86: syscallarg(int) domain;
87: syscallarg(int) type;
88: syscallarg(int) protocol;
1.15 thorpej 89: } */ *uap = v;
1.1 cgd 90: struct filedesc *fdp = p->p_fd;
91: struct socket *so;
92: struct file *fp;
93: int fd, error;
94:
1.43 thorpej 95: /* falloc() will use the desciptor for us */
1.18 christos 96: if ((error = falloc(p, &fp, &fd)) != 0)
1.1 cgd 97: return (error);
98: fp->f_flag = FREAD|FWRITE;
99: fp->f_type = DTYPE_SOCKET;
100: fp->f_ops = &socketops;
1.18 christos 101: error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
102: SCARG(uap, protocol));
103: if (error) {
1.43 thorpej 104: FILE_UNUSE(fp, p);
1.50 thorpej 105: fdremove(fdp, fd);
1.1 cgd 106: ffree(fp);
107: } else {
108: fp->f_data = (caddr_t)so;
1.43 thorpej 109: FILE_UNUSE(fp, p);
1.1 cgd 110: *retval = fd;
111: }
112: return (error);
113: }
114:
115: /* ARGSUSED */
1.7 mycroft 116: int
1.16 mycroft 117: sys_bind(p, v, retval)
1.1 cgd 118: struct proc *p;
1.15 thorpej 119: void *v;
120: register_t *retval;
121: {
1.51 augustss 122: struct sys_bind_args /* {
1.9 cgd 123: syscallarg(int) s;
1.23 cgd 124: syscallarg(const struct sockaddr *) name;
1.41 kleink 125: syscallarg(unsigned int) namelen;
1.15 thorpej 126: } */ *uap = v;
1.1 cgd 127: struct file *fp;
128: struct mbuf *nam;
129: int error;
130:
1.43 thorpej 131: /* getsock() will use the descriptor for us */
1.18 christos 132: if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
1.1 cgd 133: return (error);
1.18 christos 134: error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
1.23 cgd 135: MT_SONAME);
1.43 thorpej 136: if (error) {
137: FILE_UNUSE(fp, p);
1.1 cgd 138: return (error);
1.43 thorpej 139: }
1.1 cgd 140: error = sobind((struct socket *)fp->f_data, nam);
141: m_freem(nam);
1.43 thorpej 142: FILE_UNUSE(fp, p);
1.1 cgd 143: return (error);
144: }
145:
146: /* ARGSUSED */
1.7 mycroft 147: int
1.16 mycroft 148: sys_listen(p, v, retval)
1.1 cgd 149: struct proc *p;
1.15 thorpej 150: void *v;
151: register_t *retval;
152: {
1.51 augustss 153: struct sys_listen_args /* {
1.9 cgd 154: syscallarg(int) s;
155: syscallarg(int) backlog;
1.15 thorpej 156: } */ *uap = v;
1.1 cgd 157: struct file *fp;
158: int error;
159:
1.43 thorpej 160: /* getsock() will use the descriptor for us */
1.18 christos 161: if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
1.1 cgd 162: return (error);
1.43 thorpej 163: error = solisten((struct socket *)fp->f_data, SCARG(uap, backlog));
164: FILE_UNUSE(fp, p);
165: return (error);
1.1 cgd 166: }
167:
1.7 mycroft 168: int
1.16 mycroft 169: sys_accept(p, v, retval)
1.1 cgd 170: struct proc *p;
1.15 thorpej 171: void *v;
172: register_t *retval;
173: {
1.51 augustss 174: struct sys_accept_args /* {
1.9 cgd 175: syscallarg(int) s;
1.23 cgd 176: syscallarg(struct sockaddr *) name;
1.41 kleink 177: syscallarg(unsigned int *) anamelen;
1.15 thorpej 178: } */ *uap = v;
1.49 mycroft 179: struct filedesc *fdp = p->p_fd;
1.1 cgd 180: struct file *fp;
181: struct mbuf *nam;
1.41 kleink 182: unsigned int namelen;
1.49 mycroft 183: int error, s, fd;
1.51 augustss 184: struct socket *so;
1.1 cgd 185:
1.9 cgd 186: if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
1.34 perry 187: (caddr_t)&namelen, sizeof(namelen))))
1.1 cgd 188: return (error);
1.44 darrenr 189: if (SCARG(uap, name) != NULL &&
190: uvm_useracc((caddr_t)SCARG(uap, name), sizeof(struct sockaddr),
191: B_WRITE) == FALSE)
192: return (EFAULT);
193:
1.43 thorpej 194: /* getsock() will use the descriptor for us */
1.49 mycroft 195: if ((error = getsock(fdp, SCARG(uap, s), &fp)) != 0)
1.1 cgd 196: return (error);
1.14 mycroft 197: s = splsoftnet();
1.1 cgd 198: so = (struct socket *)fp->f_data;
1.43 thorpej 199: FILE_UNUSE(fp, p);
1.44 darrenr 200: if (!(so->so_proto->pr_flags & PR_LISTEN)) {
201: splx(s);
202: return (EOPNOTSUPP);
203: }
1.1 cgd 204: if ((so->so_options & SO_ACCEPTCONN) == 0) {
205: splx(s);
206: return (EINVAL);
207: }
208: if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
209: splx(s);
210: return (EWOULDBLOCK);
211: }
212: while (so->so_qlen == 0 && so->so_error == 0) {
213: if (so->so_state & SS_CANTRCVMORE) {
214: so->so_error = ECONNABORTED;
215: break;
216: }
1.18 christos 217: error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
218: netcon, 0);
219: if (error) {
1.1 cgd 220: splx(s);
221: return (error);
222: }
223: }
224: if (so->so_error) {
225: error = so->so_error;
226: so->so_error = 0;
227: splx(s);
228: return (error);
229: }
1.43 thorpej 230: /* falloc() will use the descriptor for us */
1.49 mycroft 231: if ((error = falloc(p, &fp, &fd)) != 0) {
1.1 cgd 232: splx(s);
233: return (error);
234: }
1.49 mycroft 235: *retval = fd;
1.27 thorpej 236: { struct socket *aso = so->so_q.tqh_first;
1.1 cgd 237: if (soqremque(aso, 1) == 0)
238: panic("accept");
239: so = aso;
240: }
241: fp->f_type = DTYPE_SOCKET;
242: fp->f_flag = FREAD|FWRITE;
243: fp->f_ops = &socketops;
244: fp->f_data = (caddr_t)so;
1.43 thorpej 245: FILE_UNUSE(fp, p);
1.1 cgd 246: nam = m_get(M_WAIT, MT_SONAME);
1.47 jdolecek 247: if ((error = soaccept(so, nam)) == 0 && SCARG(uap, name)) {
1.1 cgd 248: if (namelen > nam->m_len)
249: namelen = nam->m_len;
250: /* SHOULD COPY OUT A CHAIN HERE */
1.9 cgd 251: if ((error = copyout(mtod(nam, caddr_t),
1.48 enami 252: (caddr_t)SCARG(uap, name), namelen)) == 0)
1.47 jdolecek 253: error = copyout((caddr_t)&namelen,
1.48 enami 254: (caddr_t)SCARG(uap, anamelen),
255: sizeof(*SCARG(uap, anamelen)));
1.1 cgd 256: }
1.47 jdolecek 257: /* if an error occured, free the file descriptor */
1.49 mycroft 258: if (error) {
1.50 thorpej 259: fdremove(fdp, fd);
1.47 jdolecek 260: ffree(fp);
1.49 mycroft 261: }
1.46 darrenr 262: m_freem(nam);
263: splx(s);
264: return (error);
1.1 cgd 265: }
266:
267: /* ARGSUSED */
1.7 mycroft 268: int
1.16 mycroft 269: sys_connect(p, v, retval)
1.1 cgd 270: struct proc *p;
1.15 thorpej 271: void *v;
272: register_t *retval;
273: {
1.51 augustss 274: struct sys_connect_args /* {
1.9 cgd 275: syscallarg(int) s;
1.23 cgd 276: syscallarg(const struct sockaddr *) name;
1.41 kleink 277: syscallarg(unsigned int) namelen;
1.15 thorpej 278: } */ *uap = v;
1.1 cgd 279: struct file *fp;
1.51 augustss 280: struct socket *so;
1.1 cgd 281: struct mbuf *nam;
282: int error, s;
283:
1.43 thorpej 284: /* getsock() will use the descriptor for us */
1.18 christos 285: if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
1.1 cgd 286: return (error);
287: so = (struct socket *)fp->f_data;
1.43 thorpej 288: FILE_UNUSE(fp, p);
1.1 cgd 289: if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
290: return (EALREADY);
1.18 christos 291: error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
1.23 cgd 292: MT_SONAME);
1.18 christos 293: if (error)
1.1 cgd 294: return (error);
295: error = soconnect(so, nam);
296: if (error)
297: goto bad;
298: if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
299: m_freem(nam);
300: return (EINPROGRESS);
301: }
1.14 mycroft 302: s = splsoftnet();
1.18 christos 303: while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
304: error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
305: netcon, 0);
306: if (error)
1.1 cgd 307: break;
1.18 christos 308: }
1.1 cgd 309: if (error == 0) {
310: error = so->so_error;
311: so->so_error = 0;
312: }
313: splx(s);
314: bad:
315: so->so_state &= ~SS_ISCONNECTING;
316: m_freem(nam);
317: if (error == ERESTART)
318: error = EINTR;
319: return (error);
320: }
321:
1.7 mycroft 322: int
1.16 mycroft 323: sys_socketpair(p, v, retval)
1.1 cgd 324: struct proc *p;
1.15 thorpej 325: void *v;
326: register_t *retval;
327: {
1.51 augustss 328: struct sys_socketpair_args /* {
1.9 cgd 329: syscallarg(int) domain;
330: syscallarg(int) type;
331: syscallarg(int) protocol;
332: syscallarg(int *) rsv;
1.15 thorpej 333: } */ *uap = v;
1.51 augustss 334: struct filedesc *fdp = p->p_fd;
1.1 cgd 335: struct file *fp1, *fp2;
336: struct socket *so1, *so2;
337: int fd, error, sv[2];
338:
1.18 christos 339: error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
340: SCARG(uap, protocol));
341: if (error)
1.1 cgd 342: return (error);
1.18 christos 343: error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
344: SCARG(uap, protocol));
345: if (error)
1.1 cgd 346: goto free1;
1.43 thorpej 347: /* falloc() will use the descriptor for us */
1.18 christos 348: if ((error = falloc(p, &fp1, &fd)) != 0)
1.1 cgd 349: goto free2;
350: sv[0] = fd;
351: fp1->f_flag = FREAD|FWRITE;
352: fp1->f_type = DTYPE_SOCKET;
353: fp1->f_ops = &socketops;
354: fp1->f_data = (caddr_t)so1;
1.18 christos 355: if ((error = falloc(p, &fp2, &fd)) != 0)
1.1 cgd 356: goto free3;
357: fp2->f_flag = FREAD|FWRITE;
358: fp2->f_type = DTYPE_SOCKET;
359: fp2->f_ops = &socketops;
360: fp2->f_data = (caddr_t)so2;
361: sv[1] = fd;
1.18 christos 362: if ((error = soconnect2(so1, so2)) != 0)
1.1 cgd 363: goto free4;
1.9 cgd 364: if (SCARG(uap, type) == SOCK_DGRAM) {
1.1 cgd 365: /*
366: * Datagram socket connection is asymmetric.
367: */
1.18 christos 368: if ((error = soconnect2(so2, so1)) != 0)
1.1 cgd 369: goto free4;
370: }
1.9 cgd 371: error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
1.34 perry 372: 2 * sizeof(int));
1.43 thorpej 373: FILE_UNUSE(fp1, p);
374: FILE_UNUSE(fp2, p);
1.1 cgd 375: return (error);
376: free4:
1.43 thorpej 377: FILE_UNUSE(fp2, p);
1.1 cgd 378: ffree(fp2);
1.50 thorpej 379: fdremove(fdp, sv[1]);
1.1 cgd 380: free3:
1.43 thorpej 381: FILE_UNUSE(fp1, p);
1.1 cgd 382: ffree(fp1);
1.50 thorpej 383: fdremove(fdp, sv[0]);
1.1 cgd 384: free2:
385: (void)soclose(so2);
386: free1:
387: (void)soclose(so1);
388: return (error);
389: }
390:
1.7 mycroft 391: int
1.16 mycroft 392: sys_sendto(p, v, retval)
1.1 cgd 393: struct proc *p;
1.15 thorpej 394: void *v;
395: register_t *retval;
396: {
1.51 augustss 397: struct sys_sendto_args /* {
1.9 cgd 398: syscallarg(int) s;
1.23 cgd 399: syscallarg(const void *) buf;
1.9 cgd 400: syscallarg(size_t) len;
401: syscallarg(int) flags;
1.23 cgd 402: syscallarg(const struct sockaddr *) to;
1.41 kleink 403: syscallarg(unsigned int) tolen;
1.15 thorpej 404: } */ *uap = v;
1.1 cgd 405: struct msghdr msg;
406: struct iovec aiov;
407:
1.23 cgd 408: msg.msg_name = (caddr_t)SCARG(uap, to); /* XXX kills const */
1.9 cgd 409: msg.msg_namelen = SCARG(uap, tolen);
1.1 cgd 410: msg.msg_iov = &aiov;
411: msg.msg_iovlen = 1;
412: msg.msg_control = 0;
1.7 mycroft 413: #ifdef COMPAT_OLDSOCK
1.1 cgd 414: msg.msg_flags = 0;
415: #endif
1.23 cgd 416: aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */
1.9 cgd 417: aiov.iov_len = SCARG(uap, len);
418: return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
1.1 cgd 419: }
420:
1.7 mycroft 421: int
1.16 mycroft 422: sys_sendmsg(p, v, retval)
1.1 cgd 423: struct proc *p;
1.15 thorpej 424: void *v;
425: register_t *retval;
426: {
1.51 augustss 427: struct sys_sendmsg_args /* {
1.9 cgd 428: syscallarg(int) s;
1.23 cgd 429: syscallarg(const struct msghdr *) msg;
1.9 cgd 430: syscallarg(int) flags;
1.15 thorpej 431: } */ *uap = v;
1.1 cgd 432: struct msghdr msg;
433: struct iovec aiov[UIO_SMALLIOV], *iov;
434: int error;
435:
1.34 perry 436: error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
1.18 christos 437: if (error)
1.1 cgd 438: return (error);
1.41 kleink 439: if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
440: if ((unsigned int)msg.msg_iovlen > IOV_MAX)
1.1 cgd 441: return (EMSGSIZE);
1.54 ! thorpej 442: iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
! 443: M_IOV, M_WAITOK);
1.39 mycroft 444: } else
1.1 cgd 445: iov = aiov;
1.41 kleink 446: if ((unsigned int)msg.msg_iovlen > 0) {
1.39 mycroft 447: error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
448: (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
449: if (error)
450: goto done;
451: }
1.1 cgd 452: msg.msg_iov = iov;
1.7 mycroft 453: #ifdef COMPAT_OLDSOCK
1.1 cgd 454: msg.msg_flags = 0;
455: #endif
1.9 cgd 456: error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
1.1 cgd 457: done:
458: if (iov != aiov)
1.54 ! thorpej 459: free(iov, M_IOV);
1.1 cgd 460: return (error);
461: }
462:
1.7 mycroft 463: int
1.1 cgd 464: sendit(p, s, mp, flags, retsize)
1.51 augustss 465: struct proc *p;
1.1 cgd 466: int s;
1.51 augustss 467: struct msghdr *mp;
1.9 cgd 468: int flags;
469: register_t *retsize;
1.1 cgd 470: {
471: struct file *fp;
472: struct uio auio;
1.51 augustss 473: struct iovec *iov;
474: int i;
1.1 cgd 475: struct mbuf *to, *control;
476: int len, error;
1.30 matt 477: struct socket *so;
1.1 cgd 478: #ifdef KTRACE
479: struct iovec *ktriov = NULL;
480: #endif
481:
1.43 thorpej 482: /* getsock() will use the descriptor for us */
1.18 christos 483: if ((error = getsock(p->p_fd, s, &fp)) != 0)
1.1 cgd 484: return (error);
485: auio.uio_iov = mp->msg_iov;
486: auio.uio_iovcnt = mp->msg_iovlen;
487: auio.uio_segflg = UIO_USERSPACE;
488: auio.uio_rw = UIO_WRITE;
489: auio.uio_procp = p;
490: auio.uio_offset = 0; /* XXX */
491: auio.uio_resid = 0;
492: iov = mp->msg_iov;
493: for (i = 0; i < mp->msg_iovlen; i++, iov++) {
1.18 christos 494: #if 0
495: /* cannot happen; iov_len is unsigned */
1.43 thorpej 496: if (iov->iov_len < 0) {
497: error = EINVAL;
498: goto out;
499: }
1.18 christos 500: #endif
1.33 thorpej 501: /*
502: * Writes return ssize_t because -1 is returned on error.
503: * Therefore, we must restrict the length to SSIZE_MAX to
504: * avoid garbage return values.
505: */
506: auio.uio_resid += iov->iov_len;
1.43 thorpej 507: if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
508: error = EINVAL;
509: goto out;
510: }
1.1 cgd 511: }
512: if (mp->msg_name) {
1.18 christos 513: error = sockargs(&to, mp->msg_name, mp->msg_namelen,
514: MT_SONAME);
515: if (error)
1.43 thorpej 516: goto out;
1.1 cgd 517: } else
518: to = 0;
519: if (mp->msg_control) {
520: if (mp->msg_controllen < sizeof(struct cmsghdr)
1.7 mycroft 521: #ifdef COMPAT_OLDSOCK
1.1 cgd 522: && mp->msg_flags != MSG_COMPAT
523: #endif
524: ) {
525: error = EINVAL;
526: goto bad;
527: }
1.18 christos 528: error = sockargs(&control, mp->msg_control,
529: mp->msg_controllen, MT_CONTROL);
530: if (error)
1.1 cgd 531: goto bad;
1.7 mycroft 532: #ifdef COMPAT_OLDSOCK
1.1 cgd 533: if (mp->msg_flags == MSG_COMPAT) {
1.51 augustss 534: struct cmsghdr *cm;
1.1 cgd 535:
536: M_PREPEND(control, sizeof(*cm), M_WAIT);
537: if (control == 0) {
538: error = ENOBUFS;
539: goto bad;
540: } else {
541: cm = mtod(control, struct cmsghdr *);
542: cm->cmsg_len = control->m_len;
543: cm->cmsg_level = SOL_SOCKET;
544: cm->cmsg_type = SCM_RIGHTS;
545: }
546: }
547: #endif
548: } else
549: control = 0;
550: #ifdef KTRACE
551: if (KTRPOINT(p, KTR_GENIO)) {
1.34 perry 552: int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
1.1 cgd 553:
1.54 ! thorpej 554: ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
1.36 perry 555: memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
1.1 cgd 556: }
557: #endif
558: len = auio.uio_resid;
1.30 matt 559: so = (struct socket *)fp->f_data;
560: error = (*so->so_send)(so, to, &auio, NULL, control, flags);
1.18 christos 561: if (error) {
1.1 cgd 562: if (auio.uio_resid != len && (error == ERESTART ||
563: error == EINTR || error == EWOULDBLOCK))
564: error = 0;
565: if (error == EPIPE)
566: psignal(p, SIGPIPE);
567: }
568: if (error == 0)
569: *retsize = len - auio.uio_resid;
570: #ifdef KTRACE
571: if (ktriov != NULL) {
572: if (error == 0)
1.52 sommerfe 573: ktrgenio(p, s, UIO_WRITE, ktriov, *retsize, error);
1.54 ! thorpej 574: free(ktriov, M_TEMP);
1.1 cgd 575: }
576: #endif
1.43 thorpej 577: bad:
1.1 cgd 578: if (to)
579: m_freem(to);
1.43 thorpej 580: out:
581: FILE_UNUSE(fp, p);
1.1 cgd 582: return (error);
583: }
584:
1.7 mycroft 585: int
1.16 mycroft 586: sys_recvfrom(p, v, retval)
1.1 cgd 587: struct proc *p;
1.15 thorpej 588: void *v;
589: register_t *retval;
590: {
1.51 augustss 591: struct sys_recvfrom_args /* {
1.9 cgd 592: syscallarg(int) s;
1.23 cgd 593: syscallarg(void *) buf;
1.9 cgd 594: syscallarg(size_t) len;
595: syscallarg(int) flags;
1.23 cgd 596: syscallarg(struct sockaddr *) from;
1.41 kleink 597: syscallarg(unsigned int *) fromlenaddr;
1.15 thorpej 598: } */ *uap = v;
1.1 cgd 599: struct msghdr msg;
600: struct iovec aiov;
601: int error;
602:
1.9 cgd 603: if (SCARG(uap, fromlenaddr)) {
1.18 christos 604: error = copyin((caddr_t)SCARG(uap, fromlenaddr),
605: (caddr_t)&msg.msg_namelen,
1.34 perry 606: sizeof(msg.msg_namelen));
1.18 christos 607: if (error)
1.1 cgd 608: return (error);
609: } else
610: msg.msg_namelen = 0;
1.23 cgd 611: msg.msg_name = (caddr_t)SCARG(uap, from);
1.1 cgd 612: msg.msg_iov = &aiov;
613: msg.msg_iovlen = 1;
1.9 cgd 614: aiov.iov_base = SCARG(uap, buf);
615: aiov.iov_len = SCARG(uap, len);
1.1 cgd 616: msg.msg_control = 0;
1.9 cgd 617: msg.msg_flags = SCARG(uap, flags);
618: return (recvit(p, SCARG(uap, s), &msg,
1.18 christos 619: (caddr_t)SCARG(uap, fromlenaddr), retval));
1.1 cgd 620: }
621:
1.7 mycroft 622: int
1.16 mycroft 623: sys_recvmsg(p, v, retval)
1.1 cgd 624: struct proc *p;
1.15 thorpej 625: void *v;
626: register_t *retval;
627: {
1.51 augustss 628: struct sys_recvmsg_args /* {
1.9 cgd 629: syscallarg(int) s;
630: syscallarg(struct msghdr *) msg;
631: syscallarg(int) flags;
1.15 thorpej 632: } */ *uap = v;
1.1 cgd 633: struct msghdr msg;
634: struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
1.51 augustss 635: int error;
1.1 cgd 636:
1.18 christos 637: error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
1.34 perry 638: sizeof(msg));
1.18 christos 639: if (error)
1.1 cgd 640: return (error);
1.41 kleink 641: if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
642: if ((unsigned int)msg.msg_iovlen > IOV_MAX)
1.1 cgd 643: return (EMSGSIZE);
1.54 ! thorpej 644: iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
! 645: M_IOV, M_WAITOK);
1.39 mycroft 646: } else
1.1 cgd 647: iov = aiov;
1.41 kleink 648: if ((unsigned int)msg.msg_iovlen > 0) {
1.39 mycroft 649: error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
650: (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
651: if (error)
652: goto done;
653: }
654: uiov = msg.msg_iov;
655: msg.msg_iov = iov;
1.7 mycroft 656: #ifdef COMPAT_OLDSOCK
1.9 cgd 657: msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
1.1 cgd 658: #else
1.9 cgd 659: msg.msg_flags = SCARG(uap, flags);
1.1 cgd 660: #endif
1.9 cgd 661: if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
1.1 cgd 662: msg.msg_iov = uiov;
1.9 cgd 663: error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
664: sizeof(msg));
1.1 cgd 665: }
666: done:
667: if (iov != aiov)
1.54 ! thorpej 668: free(iov, M_IOV);
1.1 cgd 669: return (error);
670: }
671:
1.7 mycroft 672: int
1.1 cgd 673: recvit(p, s, mp, namelenp, retsize)
1.51 augustss 674: struct proc *p;
1.1 cgd 675: int s;
1.51 augustss 676: struct msghdr *mp;
1.1 cgd 677: caddr_t namelenp;
1.9 cgd 678: register_t *retsize;
1.1 cgd 679: {
680: struct file *fp;
681: struct uio auio;
1.51 augustss 682: struct iovec *iov;
683: int i;
1.1 cgd 684: int len, error;
685: struct mbuf *from = 0, *control = 0;
1.30 matt 686: struct socket *so;
1.1 cgd 687: #ifdef KTRACE
688: struct iovec *ktriov = NULL;
689: #endif
690:
1.43 thorpej 691: /* getsock() will use the descriptor for us */
1.18 christos 692: if ((error = getsock(p->p_fd, s, &fp)) != 0)
1.1 cgd 693: return (error);
694: auio.uio_iov = mp->msg_iov;
695: auio.uio_iovcnt = mp->msg_iovlen;
696: auio.uio_segflg = UIO_USERSPACE;
697: auio.uio_rw = UIO_READ;
698: auio.uio_procp = p;
699: auio.uio_offset = 0; /* XXX */
700: auio.uio_resid = 0;
701: iov = mp->msg_iov;
702: for (i = 0; i < mp->msg_iovlen; i++, iov++) {
1.18 christos 703: #if 0
704: /* cannot happen iov_len is unsigned */
1.43 thorpej 705: if (iov->iov_len < 0) {
706: error = EINVAL;
707: goto out1;
708: }
1.18 christos 709: #endif
1.33 thorpej 710: /*
711: * Reads return ssize_t because -1 is returned on error.
712: * Therefore we must restrict the length to SSIZE_MAX to
713: * avoid garbage return values.
714: */
715: auio.uio_resid += iov->iov_len;
1.43 thorpej 716: if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
717: error = EINVAL;
718: goto out1;
719: }
1.1 cgd 720: }
721: #ifdef KTRACE
722: if (KTRPOINT(p, KTR_GENIO)) {
1.34 perry 723: int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
1.1 cgd 724:
1.54 ! thorpej 725: ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
1.36 perry 726: memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
1.1 cgd 727: }
728: #endif
729: len = auio.uio_resid;
1.30 matt 730: so = (struct socket *)fp->f_data;
731: error = (*so->so_receive)(so, &from, &auio, NULL,
732: mp->msg_control ? &control : NULL, &mp->msg_flags);
1.18 christos 733: if (error) {
1.1 cgd 734: if (auio.uio_resid != len && (error == ERESTART ||
735: error == EINTR || error == EWOULDBLOCK))
736: error = 0;
737: }
738: #ifdef KTRACE
739: if (ktriov != NULL) {
740: if (error == 0)
1.52 sommerfe 741: ktrgenio(p, s, UIO_READ, ktriov,
742: len - auio.uio_resid, error);
1.54 ! thorpej 743: free(ktriov, M_TEMP);
1.1 cgd 744: }
745: #endif
746: if (error)
747: goto out;
748: *retsize = len - auio.uio_resid;
749: if (mp->msg_name) {
750: len = mp->msg_namelen;
751: if (len <= 0 || from == 0)
752: len = 0;
753: else {
1.7 mycroft 754: #ifdef COMPAT_OLDSOCK
1.1 cgd 755: if (mp->msg_flags & MSG_COMPAT)
756: mtod(from, struct osockaddr *)->sa_family =
757: mtod(from, struct sockaddr *)->sa_family;
758: #endif
759: if (len > from->m_len)
760: len = from->m_len;
761: /* else if len < from->m_len ??? */
1.18 christos 762: error = copyout(mtod(from, caddr_t),
763: (caddr_t)mp->msg_name, (unsigned)len);
764: if (error)
1.1 cgd 765: goto out;
766: }
767: mp->msg_namelen = len;
768: if (namelenp &&
1.34 perry 769: (error = copyout((caddr_t)&len, namelenp, sizeof(int)))) {
1.7 mycroft 770: #ifdef COMPAT_OLDSOCK
1.1 cgd 771: if (mp->msg_flags & MSG_COMPAT)
772: error = 0; /* old recvfrom didn't check */
773: else
774: #endif
775: goto out;
776: }
777: }
778: if (mp->msg_control) {
1.7 mycroft 779: #ifdef COMPAT_OLDSOCK
1.1 cgd 780: /*
781: * We assume that old recvmsg calls won't receive access
782: * rights and other control info, esp. as control info
783: * is always optional and those options didn't exist in 4.3.
784: * If we receive rights, trim the cmsghdr; anything else
785: * is tossed.
786: */
787: if (control && mp->msg_flags & MSG_COMPAT) {
788: if (mtod(control, struct cmsghdr *)->cmsg_level !=
789: SOL_SOCKET ||
790: mtod(control, struct cmsghdr *)->cmsg_type !=
791: SCM_RIGHTS) {
792: mp->msg_controllen = 0;
793: goto out;
794: }
1.34 perry 795: control->m_len -= sizeof(struct cmsghdr);
796: control->m_data += sizeof(struct cmsghdr);
1.1 cgd 797: }
798: #endif
799: len = mp->msg_controllen;
800: if (len <= 0 || control == 0)
801: len = 0;
802: else {
1.26 thorpej 803: struct mbuf *m = control;
804: caddr_t p = (caddr_t)mp->msg_control;
805:
1.28 thorpej 806: do {
1.26 thorpej 807: i = m->m_len;
808: if (len < i) {
809: mp->msg_flags |= MSG_CTRUNC;
810: i = len;
811: }
812: error = copyout(mtod(m, caddr_t), p,
813: (unsigned)i);
1.28 thorpej 814: if (m->m_next)
815: i = ALIGN(i);
1.26 thorpej 816: p += i;
817: len -= i;
818: if (error != 0 || len <= 0)
819: break;
1.28 thorpej 820: } while ((m = m->m_next) != NULL);
1.26 thorpej 821: len = p - (caddr_t)mp->msg_control;
1.1 cgd 822: }
823: mp->msg_controllen = len;
824: }
1.43 thorpej 825: out:
1.1 cgd 826: if (from)
827: m_freem(from);
828: if (control)
829: m_freem(control);
1.43 thorpej 830: out1:
831: FILE_UNUSE(fp, p);
1.1 cgd 832: return (error);
833: }
834:
835: /* ARGSUSED */
1.7 mycroft 836: int
1.16 mycroft 837: sys_shutdown(p, v, retval)
1.1 cgd 838: struct proc *p;
1.15 thorpej 839: void *v;
840: register_t *retval;
841: {
1.51 augustss 842: struct sys_shutdown_args /* {
1.9 cgd 843: syscallarg(int) s;
844: syscallarg(int) how;
1.15 thorpej 845: } */ *uap = v;
1.1 cgd 846: struct file *fp;
847: int error;
848:
1.43 thorpej 849: /* getsock() will use the descriptor for us */
1.18 christos 850: if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
1.1 cgd 851: return (error);
1.43 thorpej 852: error = soshutdown((struct socket *)fp->f_data, SCARG(uap, how));
853: FILE_UNUSE(fp, p);
854: return (error);
1.1 cgd 855: }
856:
857: /* ARGSUSED */
1.7 mycroft 858: int
1.16 mycroft 859: sys_setsockopt(p, v, retval)
1.1 cgd 860: struct proc *p;
1.15 thorpej 861: void *v;
862: register_t *retval;
863: {
1.51 augustss 864: struct sys_setsockopt_args /* {
1.9 cgd 865: syscallarg(int) s;
866: syscallarg(int) level;
867: syscallarg(int) name;
1.23 cgd 868: syscallarg(const void *) val;
1.41 kleink 869: syscallarg(unsigned int) valsize;
1.15 thorpej 870: } */ *uap = v;
1.1 cgd 871: struct file *fp;
872: struct mbuf *m = NULL;
873: int error;
874:
1.43 thorpej 875: /* getsock() will use the descriptor for us */
1.18 christos 876: if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
1.1 cgd 877: return (error);
1.43 thorpej 878: if (SCARG(uap, valsize) > MLEN) {
879: error = EINVAL;
880: goto out;
881: }
1.9 cgd 882: if (SCARG(uap, val)) {
1.1 cgd 883: m = m_get(M_WAIT, MT_SOOPTS);
1.18 christos 884: error = copyin(SCARG(uap, val), mtod(m, caddr_t),
1.41 kleink 885: SCARG(uap, valsize));
1.18 christos 886: if (error) {
1.1 cgd 887: (void) m_free(m);
1.43 thorpej 888: goto out;
1.1 cgd 889: }
1.9 cgd 890: m->m_len = SCARG(uap, valsize);
1.1 cgd 891: }
1.43 thorpej 892: error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
893: SCARG(uap, name), m);
894: out:
895: FILE_UNUSE(fp, p);
896: return (error);
1.1 cgd 897: }
898:
899: /* ARGSUSED */
1.7 mycroft 900: int
1.16 mycroft 901: sys_getsockopt(p, v, retval)
1.1 cgd 902: struct proc *p;
1.15 thorpej 903: void *v;
904: register_t *retval;
905: {
1.51 augustss 906: struct sys_getsockopt_args /* {
1.9 cgd 907: syscallarg(int) s;
908: syscallarg(int) level;
909: syscallarg(int) name;
1.23 cgd 910: syscallarg(void *) val;
1.41 kleink 911: syscallarg(unsigned int *) avalsize;
1.15 thorpej 912: } */ *uap = v;
1.1 cgd 913: struct file *fp;
1.45 itojun 914: struct mbuf *m = NULL, *m0;
915: unsigned int op, i, valsize;
1.41 kleink 916: int error;
1.1 cgd 917:
1.43 thorpej 918: /* getsock() will use the descriptor for us */
1.18 christos 919: if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
1.1 cgd 920: return (error);
1.9 cgd 921: if (SCARG(uap, val)) {
1.18 christos 922: error = copyin((caddr_t)SCARG(uap, avalsize),
1.34 perry 923: (caddr_t)&valsize, sizeof(valsize));
1.18 christos 924: if (error)
1.43 thorpej 925: goto out;
1.1 cgd 926: } else
927: valsize = 0;
1.9 cgd 928: if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
929: SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
930: m != NULL) {
1.45 itojun 931: op = 0;
932: while (m && !error && op < valsize) {
933: i = min(m->m_len, (valsize - op));
934: error = copyout(mtod(m, caddr_t), SCARG(uap, val), i);
935: op += i;
936: SCARG(uap, val) = ((u_int8_t *)SCARG(uap, val)) + i;
937: m0 = m;
938: MFREE(m0, m);
939: }
940: valsize = op;
1.1 cgd 941: if (error == 0)
1.45 itojun 942: error = copyout(&valsize,
943: SCARG(uap, avalsize), sizeof(valsize));
1.1 cgd 944: }
945: if (m != NULL)
946: (void) m_free(m);
1.43 thorpej 947: out:
948: FILE_UNUSE(fp, p);
1.1 cgd 949: return (error);
950: }
951:
952: /* ARGSUSED */
1.7 mycroft 953: int
1.16 mycroft 954: sys_pipe(p, v, retval)
1.1 cgd 955: struct proc *p;
1.16 mycroft 956: void *v;
1.9 cgd 957: register_t *retval;
1.1 cgd 958: {
1.51 augustss 959: struct filedesc *fdp = p->p_fd;
1.1 cgd 960: struct file *rf, *wf;
961: struct socket *rso, *wso;
962: int fd, error;
963:
1.32 lukem 964: if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0)
1.1 cgd 965: return (error);
1.32 lukem 966: if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0)
1.1 cgd 967: goto free1;
1.43 thorpej 968: /* falloc() will use the descriptor for us */
1.18 christos 969: if ((error = falloc(p, &rf, &fd)) != 0)
1.1 cgd 970: goto free2;
971: retval[0] = fd;
972: rf->f_flag = FREAD;
973: rf->f_type = DTYPE_SOCKET;
974: rf->f_ops = &socketops;
975: rf->f_data = (caddr_t)rso;
1.18 christos 976: if ((error = falloc(p, &wf, &fd)) != 0)
1.1 cgd 977: goto free3;
978: wf->f_flag = FWRITE;
979: wf->f_type = DTYPE_SOCKET;
980: wf->f_ops = &socketops;
981: wf->f_data = (caddr_t)wso;
982: retval[1] = fd;
1.18 christos 983: if ((error = unp_connect2(wso, rso)) != 0)
1.1 cgd 984: goto free4;
1.43 thorpej 985: FILE_UNUSE(rf, p);
986: FILE_UNUSE(wf, p);
1.1 cgd 987: return (0);
988: free4:
1.43 thorpej 989: FILE_UNUSE(wf, p);
1.1 cgd 990: ffree(wf);
1.50 thorpej 991: fdremove(fdp, retval[1]);
1.1 cgd 992: free3:
1.43 thorpej 993: FILE_UNUSE(rf, p);
1.1 cgd 994: ffree(rf);
1.50 thorpej 995: fdremove(fdp, retval[0]);
1.1 cgd 996: free2:
997: (void)soclose(wso);
998: free1:
999: (void)soclose(rso);
1000: return (error);
1001: }
1002:
1003: /*
1004: * Get socket name.
1005: */
1.13 christos 1006: /* ARGSUSED */
1.7 mycroft 1007: int
1.16 mycroft 1008: sys_getsockname(p, v, retval)
1.1 cgd 1009: struct proc *p;
1.15 thorpej 1010: void *v;
1011: register_t *retval;
1012: {
1.51 augustss 1013: struct sys_getsockname_args /* {
1.9 cgd 1014: syscallarg(int) fdes;
1.23 cgd 1015: syscallarg(struct sockaddr *) asa;
1.41 kleink 1016: syscallarg(unsigned int *) alen;
1.15 thorpej 1017: } */ *uap = v;
1.1 cgd 1018: struct file *fp;
1.51 augustss 1019: struct socket *so;
1.1 cgd 1020: struct mbuf *m;
1.41 kleink 1021: unsigned int len;
1022: int error;
1.1 cgd 1023:
1.43 thorpej 1024: /* getsock() will use the descriptor for us */
1.18 christos 1025: if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1.1 cgd 1026: return (error);
1.34 perry 1027: error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
1.18 christos 1028: if (error)
1.43 thorpej 1029: goto out;
1.1 cgd 1030: so = (struct socket *)fp->f_data;
1031: m = m_getclr(M_WAIT, MT_SONAME);
1.21 mycroft 1032: error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0,
1033: m, (struct mbuf *)0, (struct proc *)0);
1.18 christos 1034: if (error)
1.1 cgd 1035: goto bad;
1036: if (len > m->m_len)
1037: len = m->m_len;
1.41 kleink 1038: error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1.1 cgd 1039: if (error == 0)
1.9 cgd 1040: error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
1.34 perry 1041: sizeof(len));
1.43 thorpej 1042: bad:
1.1 cgd 1043: m_freem(m);
1.43 thorpej 1044: out:
1045: FILE_UNUSE(fp, p);
1.1 cgd 1046: return (error);
1047: }
1048:
1049: /*
1050: * Get name of peer for connected socket.
1051: */
1.13 christos 1052: /* ARGSUSED */
1.7 mycroft 1053: int
1.16 mycroft 1054: sys_getpeername(p, v, retval)
1.1 cgd 1055: struct proc *p;
1.15 thorpej 1056: void *v;
1057: register_t *retval;
1058: {
1.51 augustss 1059: struct sys_getpeername_args /* {
1.9 cgd 1060: syscallarg(int) fdes;
1.23 cgd 1061: syscallarg(struct sockaddr *) asa;
1.41 kleink 1062: syscallarg(unsigned int *) alen;
1.15 thorpej 1063: } */ *uap = v;
1.1 cgd 1064: struct file *fp;
1.51 augustss 1065: struct socket *so;
1.1 cgd 1066: struct mbuf *m;
1.41 kleink 1067: unsigned int len;
1068: int error;
1.1 cgd 1069:
1.43 thorpej 1070: /* getsock() will use the descriptor for us */
1.18 christos 1071: if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1.1 cgd 1072: return (error);
1073: so = (struct socket *)fp->f_data;
1.43 thorpej 1074: if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
1075: error = ENOTCONN;
1076: goto out;
1077: }
1.34 perry 1078: error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
1.18 christos 1079: if (error)
1.43 thorpej 1080: goto out;
1.1 cgd 1081: m = m_getclr(M_WAIT, MT_SONAME);
1.21 mycroft 1082: error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0,
1083: m, (struct mbuf *)0, (struct proc *)0);
1.18 christos 1084: if (error)
1.1 cgd 1085: goto bad;
1086: if (len > m->m_len)
1087: len = m->m_len;
1.41 kleink 1088: error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1.18 christos 1089: if (error)
1.1 cgd 1090: goto bad;
1.34 perry 1091: error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len));
1.43 thorpej 1092: bad:
1.1 cgd 1093: m_freem(m);
1.43 thorpej 1094: out:
1095: FILE_UNUSE(fp, p);
1.1 cgd 1096: return (error);
1097: }
1098:
1.24 thorpej 1099: /*
1100: * XXX In a perfect world, we wouldn't pass around socket control
1101: * XXX arguments in mbufs, and this could go away.
1102: */
1.7 mycroft 1103: int
1.1 cgd 1104: sockargs(mp, buf, buflen, type)
1105: struct mbuf **mp;
1.23 cgd 1106: const void *buf;
1.1 cgd 1107: int buflen, type;
1108: {
1.51 augustss 1109: struct sockaddr *sa;
1110: struct mbuf *m;
1.1 cgd 1111: int error;
1112:
1.24 thorpej 1113: /*
1.25 thorpej 1114: * We can't allow socket names > UCHAR_MAX in length, since that
1.24 thorpej 1115: * will overflow sa_len.
1116: */
1.25 thorpej 1117: if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX)
1.24 thorpej 1118: return (EINVAL);
1119:
1120: /* Allocate an mbuf to hold the arguments. */
1121: m = m_get(M_WAIT, type);
1.1 cgd 1122: if ((u_int)buflen > MLEN) {
1.24 thorpej 1123: /*
1124: * Won't fit into a regular mbuf, so we allocate just
1125: * enough external storage to hold the argument.
1126: */
1127: MEXTMALLOC(m, buflen, M_WAITOK);
1.1 cgd 1128: }
1129: m->m_len = buflen;
1130: error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1131: if (error) {
1132: (void) m_free(m);
1.7 mycroft 1133: return (error);
1.1 cgd 1134: }
1135: *mp = m;
1136: if (type == MT_SONAME) {
1.7 mycroft 1137: sa = mtod(m, struct sockaddr *);
1.1 cgd 1138:
1.7 mycroft 1139: #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1.1 cgd 1140: if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1141: sa->sa_family = sa->sa_len;
1142: #endif
1143: sa->sa_len = buflen;
1144: }
1145: return (0);
1146: }
1147:
1.7 mycroft 1148: int
1.1 cgd 1149: getsock(fdp, fdes, fpp)
1150: struct filedesc *fdp;
1151: int fdes;
1152: struct file **fpp;
1153: {
1.51 augustss 1154: struct file *fp;
1.1 cgd 1155:
1156: if ((unsigned)fdes >= fdp->fd_nfiles ||
1.43 thorpej 1157: (fp = fdp->fd_ofiles[fdes]) == NULL ||
1158: (fp->f_iflags & FIF_WANTCLOSE) != 0)
1.1 cgd 1159: return (EBADF);
1.43 thorpej 1160:
1161: FILE_USE(fp);
1162:
1163: if (fp->f_type != DTYPE_SOCKET) {
1164: FILE_UNUSE(fp, NULL);
1.1 cgd 1165: return (ENOTSOCK);
1.43 thorpej 1166: }
1.1 cgd 1167: *fpp = fp;
1168: return (0);
1169: }
CVSweb <webmaster@jp.NetBSD.org>