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