|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989, 1990 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
1.1.1.3 ! root 33: * from: @(#)uipc_syscalls.c 7.24 (Berkeley) 6/3/91
! 34: * uipc_syscalls.c,v 1.5 1993/07/17 15:24:42 mycroft Exp
1.1 root 35: */
36:
37: #include "param.h"
38: #include "filedesc.h"
39: #include "proc.h"
40: #include "file.h"
41: #include "buf.h"
42: #include "malloc.h"
43: #include "mbuf.h"
44: #include "protosw.h"
45: #include "socket.h"
46: #include "socketvar.h"
47: #ifdef KTRACE
48: #include "ktrace.h"
49: #endif
50:
51: /*
52: * System call interface to the socket abstraction.
53: */
54:
55: extern struct fileops socketops;
56:
1.1.1.3 ! root 57: struct socket_args {
! 58: int domain;
! 59: int type;
! 60: int protocol;
! 61: };
! 62:
1.1 root 63: socket(p, uap, retval)
64: struct proc *p;
1.1.1.3 ! root 65: register struct socket_args *uap;
1.1 root 66: int *retval;
67: {
68: struct filedesc *fdp = p->p_fd;
69: struct socket *so;
70: struct file *fp;
71: int fd, error;
72:
73: if (error = falloc(p, &fp, &fd))
74: return (error);
75: fp->f_flag = FREAD|FWRITE;
76: fp->f_type = DTYPE_SOCKET;
77: fp->f_ops = &socketops;
78: if (error = socreate(uap->domain, &so, uap->type, uap->protocol)) {
79: fdp->fd_ofiles[fd] = 0;
80: ffree(fp);
81: } else {
82: fp->f_data = (caddr_t)so;
83: *retval = fd;
84: }
85: return (error);
86: }
87:
1.1.1.3 ! root 88: struct bind_args {
! 89: int s;
! 90: caddr_t name;
! 91: int namelen;
! 92: };
! 93:
1.1 root 94: /* ARGSUSED */
95: bind(p, uap, retval)
96: struct proc *p;
1.1.1.3 ! root 97: register struct bind_args *uap;
1.1 root 98: int *retval;
99: {
100: struct file *fp;
101: struct mbuf *nam;
102: int error;
103:
104: if (error = getsock(p->p_fd, uap->s, &fp))
105: return (error);
106: if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME))
107: return (error);
108: error = sobind((struct socket *)fp->f_data, nam);
109: m_freem(nam);
110: return (error);
111: }
112:
1.1.1.3 ! root 113: struct listen_args {
! 114: int s;
! 115: int backlog;
! 116: };
! 117:
1.1 root 118: /* ARGSUSED */
119: listen(p, uap, retval)
120: struct proc *p;
1.1.1.3 ! root 121: register struct listen_args *uap;
1.1 root 122: int *retval;
123: {
124: struct file *fp;
125: int error;
126:
127: if (error = getsock(p->p_fd, uap->s, &fp))
128: return (error);
129: return (solisten((struct socket *)fp->f_data, uap->backlog));
130: }
131:
132: #ifdef COMPAT_43
1.1.1.3 ! root 133: struct accept_args {
! 134: int s;
! 135: caddr_t name;
! 136: int *anamelen;
! 137: int compat_43;
! 138: };
! 139:
1.1 root 140: accept(p, uap, retval)
141: struct proc *p;
1.1.1.3 ! root 142: struct accept_args *uap;
1.1 root 143: int *retval;
144: {
145:
146: uap->compat_43 = 0;
147: return (accept1(p, uap, retval));
148: }
149:
1.1.1.3 ! root 150: struct oaccept_args {
! 151: int s;
! 152: caddr_t name;
! 153: int *anamelen;
! 154: int compat_43;
! 155: };
! 156:
1.1 root 157: oaccept(p, uap, retval)
158: struct proc *p;
1.1.1.3 ! root 159: struct oaccept_args *uap;
1.1 root 160: int *retval;
161: {
162:
163: uap->compat_43 = 1;
164: return (accept1(p, uap, retval));
165: }
166: #else /* COMPAT_43 */
167:
168: #define accept1 accept
169: #endif
170:
1.1.1.3 ! root 171: struct accept1_args {
! 172: int s;
! 173: caddr_t name;
! 174: int *anamelen;
1.1 root 175: #ifdef COMPAT_43
1.1.1.3 ! root 176: int compat_43;
1.1 root 177: #endif
1.1.1.3 ! root 178: };
! 179:
! 180: accept1(p, uap, retval)
! 181: struct proc *p;
! 182: register struct accept1_args *uap;
1.1 root 183: int *retval;
184: {
185: struct file *fp;
186: struct mbuf *nam;
187: int namelen, error, s;
188: register struct socket *so;
189:
190: if (uap->name && (error = copyin((caddr_t)uap->anamelen,
191: (caddr_t)&namelen, sizeof (namelen))))
192: return (error);
193: if (error = getsock(p->p_fd, uap->s, &fp))
194: return (error);
195: s = splnet();
196: so = (struct socket *)fp->f_data;
197: if ((so->so_options & SO_ACCEPTCONN) == 0) {
198: splx(s);
199: return (EINVAL);
200: }
201: if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
202: splx(s);
203: return (EWOULDBLOCK);
204: }
205: while (so->so_qlen == 0 && so->so_error == 0) {
206: if (so->so_state & SS_CANTRCVMORE) {
207: so->so_error = ECONNABORTED;
208: break;
209: }
210: if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
211: netcon, 0)) {
212: splx(s);
213: return (error);
214: }
215: }
216: if (so->so_error) {
217: error = so->so_error;
218: so->so_error = 0;
219: splx(s);
220: return (error);
221: }
222: if (error = falloc(p, &fp, retval)) {
223: splx(s);
224: return (error);
225: }
226: { struct socket *aso = so->so_q;
227: if (soqremque(aso, 1) == 0)
228: panic("accept");
229: so = aso;
230: }
231: fp->f_type = DTYPE_SOCKET;
232: fp->f_flag = FREAD|FWRITE;
233: fp->f_ops = &socketops;
234: fp->f_data = (caddr_t)so;
235: nam = m_get(M_WAIT, MT_SONAME);
236: (void) soaccept(so, nam);
237: if (uap->name) {
238: #ifdef COMPAT_43
239: if (uap->compat_43)
240: mtod(nam, struct osockaddr *)->sa_family =
241: mtod(nam, struct sockaddr *)->sa_family;
242: #endif
243: if (namelen > nam->m_len)
244: namelen = nam->m_len;
245: /* SHOULD COPY OUT A CHAIN HERE */
246: if ((error = copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
247: (u_int)namelen)) == 0)
248: error = copyout((caddr_t)&namelen,
249: (caddr_t)uap->anamelen, sizeof (*uap->anamelen));
250: }
251: m_freem(nam);
252: splx(s);
253: return (error);
254: }
255:
1.1.1.3 ! root 256: struct connect_args {
! 257: int s;
! 258: caddr_t name;
! 259: int namelen;
! 260: };
! 261:
1.1 root 262: /* ARGSUSED */
263: connect(p, uap, retval)
264: struct proc *p;
1.1.1.3 ! root 265: register struct connect_args *uap;
1.1 root 266: int *retval;
267: {
268: struct file *fp;
269: register struct socket *so;
270: struct mbuf *nam;
271: int error, s;
272:
273: if (error = getsock(p->p_fd, uap->s, &fp))
274: return (error);
275: so = (struct socket *)fp->f_data;
276: if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
277: return (EALREADY);
278: if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME))
279: return (error);
280: error = soconnect(so, nam);
281: if (error)
282: goto bad;
283: if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
284: m_freem(nam);
285: return (EINPROGRESS);
286: }
287: s = splnet();
288: while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
289: if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
290: netcon, 0))
291: break;
292: if (error == 0) {
293: error = so->so_error;
294: so->so_error = 0;
295: }
296: splx(s);
297: bad:
298: so->so_state &= ~SS_ISCONNECTING;
299: m_freem(nam);
300: if (error == ERESTART)
301: error = EINTR;
302: return (error);
303: }
304:
1.1.1.3 ! root 305: struct socketpair_args {
! 306: int domain;
! 307: int type;
! 308: int protocol;
! 309: int *rsv;
! 310: };
! 311:
1.1 root 312: socketpair(p, uap, retval)
313: struct proc *p;
1.1.1.3 ! root 314: register struct socketpair_args *uap;
1.1 root 315: int retval[];
316: {
317: register struct filedesc *fdp = p->p_fd;
318: struct file *fp1, *fp2;
319: struct socket *so1, *so2;
320: int fd, error, sv[2];
321:
322: if (error = socreate(uap->domain, &so1, uap->type, uap->protocol))
323: return (error);
324: if (error = socreate(uap->domain, &so2, uap->type, uap->protocol))
325: goto free1;
326: if (error = falloc(p, &fp1, &fd))
327: goto free2;
328: sv[0] = fd;
329: fp1->f_flag = FREAD|FWRITE;
330: fp1->f_type = DTYPE_SOCKET;
331: fp1->f_ops = &socketops;
332: fp1->f_data = (caddr_t)so1;
333: if (error = falloc(p, &fp2, &fd))
334: goto free3;
335: fp2->f_flag = FREAD|FWRITE;
336: fp2->f_type = DTYPE_SOCKET;
337: fp2->f_ops = &socketops;
338: fp2->f_data = (caddr_t)so2;
339: sv[1] = fd;
340: if (error = soconnect2(so1, so2))
341: goto free4;
342: if (uap->type == SOCK_DGRAM) {
343: /*
344: * Datagram socket connection is asymmetric.
345: */
346: if (error = soconnect2(so2, so1))
347: goto free4;
348: }
349: error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
350: retval[0] = sv[0]; /* XXX ??? */
351: retval[1] = sv[1]; /* XXX ??? */
352: return (error);
353: free4:
354: ffree(fp2);
355: fdp->fd_ofiles[sv[1]] = 0;
356: free3:
357: ffree(fp1);
358: fdp->fd_ofiles[sv[0]] = 0;
359: free2:
360: (void)soclose(so2);
361: free1:
362: (void)soclose(so1);
363: return (error);
364: }
365:
1.1.1.3 ! root 366: struct sendto_args {
! 367: int s;
! 368: caddr_t buf;
! 369: int len;
! 370: int flags;
! 371: caddr_t to;
! 372: int tolen;
! 373: };
! 374:
1.1 root 375: sendto(p, uap, retval)
376: struct proc *p;
1.1.1.3 ! root 377: register struct sendto_args *uap;
1.1 root 378: int *retval;
379: {
380: struct msghdr msg;
381: struct iovec aiov;
382: int error;
383:
384: msg.msg_name = uap->to;
385: msg.msg_namelen = uap->tolen;
386: msg.msg_iov = &aiov;
387: msg.msg_iovlen = 1;
388: msg.msg_control = 0;
389: #ifdef COMPAT_43
390: msg.msg_flags = 0;
391: #endif
392: aiov.iov_base = uap->buf;
393: aiov.iov_len = uap->len;
394: return (sendit(p, uap->s, &msg, uap->flags, retval));
395: }
396:
397: #ifdef COMPAT_43
1.1.1.3 ! root 398: struct osend_args {
! 399: int s;
! 400: caddr_t buf;
! 401: int len;
! 402: int flags;
! 403: };
! 404:
1.1 root 405: osend(p, uap, retval)
406: struct proc *p;
1.1.1.3 ! root 407: register struct osend_args *uap;
1.1 root 408: int *retval;
409: {
410: struct msghdr msg;
411: struct iovec aiov;
412:
413: msg.msg_name = 0;
414: msg.msg_namelen = 0;
415: msg.msg_iov = &aiov;
416: msg.msg_iovlen = 1;
417: aiov.iov_base = uap->buf;
418: aiov.iov_len = uap->len;
419: msg.msg_control = 0;
420: msg.msg_flags = 0;
421: return (sendit(p, uap->s, &msg, uap->flags, retval));
422: }
423:
1.1.1.3 ! root 424: struct osendmsg_args {
! 425: int s;
! 426: caddr_t msg;
! 427: int flags;
! 428: };
! 429:
1.1 root 430: #define MSG_COMPAT 0x8000
431: osendmsg(p, uap, retval)
432: struct proc *p;
1.1.1.3 ! root 433: register struct osendmsg_args *uap;
1.1 root 434: int *retval;
435: {
436: struct msghdr msg;
437: struct iovec aiov[UIO_SMALLIOV], *iov;
438: int error;
439:
440: if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr)))
441: return (error);
442: if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
443: if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
444: return (EMSGSIZE);
445: MALLOC(iov, struct iovec *,
446: sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
447: M_WAITOK);
448: } else
449: iov = aiov;
450: if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
451: (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
452: goto done;
453: msg.msg_flags = MSG_COMPAT;
454: msg.msg_iov = iov;
455: error = sendit(p, uap->s, &msg, uap->flags, retval);
456: done:
457: if (iov != aiov)
458: FREE(iov, M_IOV);
459: return (error);
460: }
461: #endif
462:
1.1.1.3 ! root 463: struct sendmsg_args {
! 464: int s;
! 465: caddr_t msg;
! 466: int flags;
! 467: };
! 468:
1.1 root 469: sendmsg(p, uap, retval)
470: struct proc *p;
1.1.1.3 ! root 471: register struct sendmsg_args *uap;
1.1 root 472: int *retval;
473: {
474: struct msghdr msg;
475: struct iovec aiov[UIO_SMALLIOV], *iov;
476: int error;
477:
478: if (error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)))
479: return (error);
480: if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
481: if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
482: return (EMSGSIZE);
483: MALLOC(iov, struct iovec *,
484: sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
485: M_WAITOK);
486: } else
487: iov = aiov;
488: if (msg.msg_iovlen &&
489: (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
490: (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
491: goto done;
492: msg.msg_iov = iov;
493: #ifdef COMPAT_43
494: msg.msg_flags = 0;
495: #endif
496: error = sendit(p, uap->s, &msg, uap->flags, retval);
497: done:
498: if (iov != aiov)
499: FREE(iov, M_IOV);
500: return (error);
501: }
502:
503: sendit(p, s, mp, flags, retsize)
504: register struct proc *p;
505: int s;
506: register struct msghdr *mp;
507: int flags, *retsize;
508: {
509: struct file *fp;
510: struct uio auio;
511: register struct iovec *iov;
512: register int i;
513: struct mbuf *to, *control;
514: int len, error;
515: #ifdef KTRACE
516: struct iovec *ktriov = NULL;
517: #endif
518:
519: if (error = getsock(p->p_fd, s, &fp))
520: return (error);
521: auio.uio_iov = mp->msg_iov;
522: auio.uio_iovcnt = mp->msg_iovlen;
523: auio.uio_segflg = UIO_USERSPACE;
524: auio.uio_rw = UIO_WRITE;
525: auio.uio_procp = p;
526: auio.uio_offset = 0; /* XXX */
527: auio.uio_resid = 0;
528: iov = mp->msg_iov;
529: for (i = 0; i < mp->msg_iovlen; i++, iov++) {
530: if (iov->iov_len < 0)
531: return (EINVAL);
532: if ((auio.uio_resid += iov->iov_len) < 0)
533: return (EINVAL);
534: }
535: if (mp->msg_name) {
536: if (error = sockargs(&to, mp->msg_name, mp->msg_namelen,
537: MT_SONAME))
538: return (error);
539: } else
540: to = 0;
541: if (mp->msg_control) {
542: if (mp->msg_controllen < sizeof(struct cmsghdr)
543: #ifdef COMPAT_43
544: && mp->msg_flags != MSG_COMPAT
545: #endif
546: ) {
547: error = EINVAL;
548: goto bad;
549: }
550: if (error = sockargs(&control, mp->msg_control,
551: mp->msg_controllen, MT_CONTROL))
552: goto bad;
553: #ifdef COMPAT_43
554: if (mp->msg_flags == MSG_COMPAT) {
555: register struct cmsghdr *cm;
556:
557: M_PREPEND(control, sizeof(*cm), M_WAIT);
558: if (control == 0) {
559: error = ENOBUFS;
560: goto bad;
561: } else {
562: cm = mtod(control, struct cmsghdr *);
563: cm->cmsg_len = control->m_len;
564: cm->cmsg_level = SOL_SOCKET;
565: cm->cmsg_type = SCM_RIGHTS;
566: }
567: }
568: #endif
569: } else
570: control = 0;
571: #ifdef KTRACE
572: if (KTRPOINT(p, KTR_GENIO)) {
573: int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
574:
575: MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
576: bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
577: }
578: #endif
579: len = auio.uio_resid;
580: if (error = sosend((struct socket *)fp->f_data, to, &auio,
581: (struct mbuf *)0, control, flags)) {
582: if (auio.uio_resid != len && (error == ERESTART ||
583: error == EINTR || error == EWOULDBLOCK))
584: error = 0;
585: if (error == EPIPE)
586: psignal(p, SIGPIPE);
587: }
588: if (error == 0)
589: *retsize = len - auio.uio_resid;
590: #ifdef KTRACE
591: if (ktriov != NULL) {
592: if (error == 0)
593: ktrgenio(p->p_tracep, s, UIO_WRITE,
594: ktriov, *retsize, error);
595: FREE(ktriov, M_TEMP);
596: }
597: #endif
598: bad:
599: if (to)
600: m_freem(to);
601: return (error);
602: }
603:
604: #ifdef COMPAT_43
1.1.1.3 ! root 605: struct orecvfrom_args {
! 606: int s;
! 607: caddr_t buf;
! 608: int len;
! 609: int flags;
! 610: caddr_t from;
! 611: int *fromlenaddr;
! 612: };
! 613:
1.1 root 614: orecvfrom(p, uap, retval)
615: struct proc *p;
1.1.1.3 ! root 616: struct orecvfrom_args *uap;
1.1 root 617: int *retval;
618: {
619:
620: uap->flags |= MSG_COMPAT;
621: return (recvfrom(p, uap, retval));
622: }
623: #endif
624:
1.1.1.3 ! root 625: struct recvfrom_args {
! 626: int s;
! 627: caddr_t buf;
! 628: int len;
! 629: int flags;
! 630: caddr_t from;
! 631: int *fromlenaddr;
! 632: };
! 633:
1.1 root 634: recvfrom(p, uap, retval)
635: struct proc *p;
1.1.1.3 ! root 636: register struct recvfrom_args *uap;
1.1 root 637: int *retval;
638: {
639: struct msghdr msg;
640: struct iovec aiov;
641: int error;
642:
643: if (uap->fromlenaddr) {
644: if (error = copyin((caddr_t)uap->fromlenaddr,
645: (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen)))
646: return (error);
647: } else
648: msg.msg_namelen = 0;
649: msg.msg_name = uap->from;
650: msg.msg_iov = &aiov;
651: msg.msg_iovlen = 1;
652: aiov.iov_base = uap->buf;
653: aiov.iov_len = uap->len;
654: msg.msg_control = 0;
655: msg.msg_flags = uap->flags;
656: return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr, retval));
657: }
658:
659: #ifdef COMPAT_43
1.1.1.3 ! root 660: struct orecv_args {
! 661: int s;
! 662: caddr_t buf;
! 663: int len;
! 664: int flags;
! 665: };
! 666:
1.1 root 667: orecv(p, uap, retval)
668: struct proc *p;
1.1.1.3 ! root 669: register struct orecv_args *uap;
1.1 root 670: int *retval;
671: {
672: struct msghdr msg;
673: struct iovec aiov;
674:
675: msg.msg_name = 0;
676: msg.msg_namelen = 0;
677: msg.msg_iov = &aiov;
678: msg.msg_iovlen = 1;
679: aiov.iov_base = uap->buf;
680: aiov.iov_len = uap->len;
681: msg.msg_control = 0;
682: msg.msg_flags = uap->flags;
683: return (recvit(p, uap->s, &msg, (caddr_t)0, retval));
684: }
685:
1.1.1.3 ! root 686: struct orecvmsg_args {
! 687: int s;
! 688: struct omsghdr *msg;
! 689: int flags;
! 690: };
! 691:
1.1 root 692: /*
693: * Old recvmsg. This code takes advantage of the fact that the old msghdr
694: * overlays the new one, missing only the flags, and with the (old) access
695: * rights where the control fields are now.
696: */
697: orecvmsg(p, uap, retval)
698: struct proc *p;
1.1.1.3 ! root 699: register struct orecvmsg_args *uap;
1.1 root 700: int *retval;
701: {
702: struct msghdr msg;
703: struct iovec aiov[UIO_SMALLIOV], *iov;
704: int error;
705:
706: if (error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
707: sizeof (struct omsghdr)))
708: return (error);
709: if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
710: if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
711: return (EMSGSIZE);
712: MALLOC(iov, struct iovec *,
713: sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
714: M_WAITOK);
715: } else
716: iov = aiov;
717: msg.msg_flags = uap->flags | MSG_COMPAT;
718: if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
719: (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
720: goto done;
721: msg.msg_iov = iov;
722: error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen, retval);
723:
724: if (msg.msg_controllen && error == 0)
725: error = copyout((caddr_t)&msg.msg_controllen,
726: (caddr_t)&uap->msg->msg_accrightslen, sizeof (int));
727: done:
728: if (iov != aiov)
729: FREE(iov, M_IOV);
730: return (error);
731: }
732: #endif
733:
1.1.1.3 ! root 734: struct recvmsg_args {
! 735: int s;
! 736: struct msghdr *msg;
! 737: int flags;
! 738: };
! 739:
1.1 root 740: recvmsg(p, uap, retval)
741: struct proc *p;
1.1.1.3 ! root 742: register struct recvmsg_args *uap;
1.1 root 743: int *retval;
744: {
745: struct msghdr msg;
746: struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
747: register int error;
748:
749: if (error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)))
750: return (error);
751: if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
752: if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
753: return (EMSGSIZE);
754: MALLOC(iov, struct iovec *,
755: sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
756: M_WAITOK);
757: } else
758: iov = aiov;
759: #ifdef COMPAT_43
760: msg.msg_flags = uap->flags &~ MSG_COMPAT;
761: #else
762: msg.msg_flags = uap->flags;
763: #endif
764: uiov = msg.msg_iov;
765: msg.msg_iov = iov;
766: if (error = copyin((caddr_t)uiov, (caddr_t)iov,
767: (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
768: goto done;
769: if ((error = recvit(p, uap->s, &msg, (caddr_t)0, retval)) == 0) {
770: msg.msg_iov = uiov;
771: error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg));
772: }
773: done:
774: if (iov != aiov)
775: FREE(iov, M_IOV);
776: return (error);
777: }
778:
779: recvit(p, s, mp, namelenp, retsize)
780: register struct proc *p;
781: int s;
782: register struct msghdr *mp;
783: caddr_t namelenp;
784: int *retsize;
785: {
786: struct file *fp;
787: struct uio auio;
788: register struct iovec *iov;
789: register int i;
790: int len, error;
791: struct mbuf *from = 0, *control = 0;
792: #ifdef KTRACE
793: struct iovec *ktriov = NULL;
794: #endif
795:
796: if (error = getsock(p->p_fd, s, &fp))
797: return (error);
798: auio.uio_iov = mp->msg_iov;
799: auio.uio_iovcnt = mp->msg_iovlen;
800: auio.uio_segflg = UIO_USERSPACE;
801: auio.uio_rw = UIO_READ;
802: auio.uio_procp = p;
803: auio.uio_offset = 0; /* XXX */
804: auio.uio_resid = 0;
805: iov = mp->msg_iov;
806: for (i = 0; i < mp->msg_iovlen; i++, iov++) {
807: if (iov->iov_len < 0)
808: return (EINVAL);
809: if ((auio.uio_resid += iov->iov_len) < 0)
810: return (EINVAL);
811: }
812: #ifdef KTRACE
813: if (KTRPOINT(p, KTR_GENIO)) {
814: int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
815:
816: MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
817: bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
818: }
819: #endif
820: len = auio.uio_resid;
821: if (error = soreceive((struct socket *)fp->f_data, &from, &auio,
1.1.1.3 ! root 822: (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
! 823: &mp->msg_flags)) {
1.1 root 824: if (auio.uio_resid != len && (error == ERESTART ||
825: error == EINTR || error == EWOULDBLOCK))
826: error = 0;
827: }
828: #ifdef KTRACE
829: if (ktriov != NULL) {
830: if (error == 0)
831: ktrgenio(p->p_tracep, s, UIO_READ,
832: ktriov, len - auio.uio_resid, error);
833: FREE(ktriov, M_TEMP);
834: }
835: #endif
836: if (error)
837: goto out;
838: *retsize = len - auio.uio_resid;
839: if (mp->msg_name) {
840: len = mp->msg_namelen;
841: if (len <= 0 || from == 0)
842: len = 0;
843: else {
844: #ifdef COMPAT_43
845: if (mp->msg_flags & MSG_COMPAT)
846: mtod(from, struct osockaddr *)->sa_family =
847: mtod(from, struct sockaddr *)->sa_family;
848: #endif
849: if (len > from->m_len)
850: len = from->m_len;
851: /* else if len < from->m_len ??? */
852: if (error = copyout(mtod(from, caddr_t),
853: (caddr_t)mp->msg_name, (unsigned)len))
854: goto out;
855: }
856: mp->msg_namelen = len;
857: if (namelenp &&
858: (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
859: #ifdef COMPAT_43
860: if (mp->msg_flags & MSG_COMPAT)
861: error = 0; /* old recvfrom didn't check */
862: else
863: #endif
864: goto out;
865: }
866: }
867: if (mp->msg_control) {
868: #ifdef COMPAT_43
869: /*
870: * We assume that old recvmsg calls won't receive access
871: * rights and other control info, esp. as control info
872: * is always optional and those options didn't exist in 4.3.
873: * If we receive rights, trim the cmsghdr; anything else
874: * is tossed.
875: */
876: if (control && mp->msg_flags & MSG_COMPAT) {
877: if (mtod(control, struct cmsghdr *)->cmsg_level !=
878: SOL_SOCKET ||
879: mtod(control, struct cmsghdr *)->cmsg_type !=
880: SCM_RIGHTS) {
881: mp->msg_controllen = 0;
882: goto out;
883: }
884: control->m_len -= sizeof (struct cmsghdr);
885: control->m_data += sizeof (struct cmsghdr);
886: }
887: #endif
888: len = mp->msg_controllen;
889: if (len <= 0 || control == 0)
890: len = 0;
891: else {
892: if (len >= control->m_len)
893: len = control->m_len;
894: else
895: mp->msg_flags |= MSG_CTRUNC;
896: error = copyout((caddr_t)mtod(control, caddr_t),
897: (caddr_t)mp->msg_control, (unsigned)len);
898: }
899: mp->msg_controllen = len;
900: }
901: out:
902: if (from)
903: m_freem(from);
904: if (control)
905: m_freem(control);
906: return (error);
907: }
908:
1.1.1.3 ! root 909: struct shutdown_args {
! 910: int s;
! 911: int how;
! 912: };
! 913:
1.1 root 914: /* ARGSUSED */
915: shutdown(p, uap, retval)
916: struct proc *p;
1.1.1.3 ! root 917: register struct shutdown_args *uap;
1.1 root 918: int *retval;
919: {
920: struct file *fp;
921: int error;
922:
923: if (error = getsock(p->p_fd, uap->s, &fp))
924: return (error);
925: return (soshutdown((struct socket *)fp->f_data, uap->how));
926: }
927:
1.1.1.3 ! root 928: struct setsockopt_args {
! 929: int s;
! 930: int level;
! 931: int name;
! 932: caddr_t val;
! 933: int valsize;
! 934: };
! 935:
1.1 root 936: /* ARGSUSED */
937: setsockopt(p, uap, retval)
938: struct proc *p;
1.1.1.3 ! root 939: register struct setsockopt_args *uap;
1.1 root 940: int *retval;
941: {
942: struct file *fp;
943: struct mbuf *m = NULL;
944: int error;
945:
946: if (error = getsock(p->p_fd, uap->s, &fp))
947: return (error);
948: if (uap->valsize > MLEN)
949: return (EINVAL);
950: if (uap->val) {
951: m = m_get(M_WAIT, MT_SOOPTS);
952: if (m == NULL)
953: return (ENOBUFS);
954: if (error = copyin(uap->val, mtod(m, caddr_t),
955: (u_int)uap->valsize)) {
956: (void) m_free(m);
957: return (error);
958: }
959: m->m_len = uap->valsize;
960: }
961: return (sosetopt((struct socket *)fp->f_data, uap->level,
962: uap->name, m));
963: }
964:
1.1.1.3 ! root 965: struct getsockopt_args {
! 966: int s;
! 967: int level;
! 968: int name;
! 969: caddr_t val;
! 970: int *avalsize;
! 971: };
! 972:
1.1 root 973: /* ARGSUSED */
974: getsockopt(p, uap, retval)
975: struct proc *p;
1.1.1.3 ! root 976: register struct getsockopt_args *uap;
1.1 root 977: int *retval;
978: {
979: struct file *fp;
980: struct mbuf *m = NULL;
981: int valsize, error;
982:
983: if (error = getsock(p->p_fd, uap->s, &fp))
984: return (error);
985: if (uap->val) {
986: if (error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
987: sizeof (valsize)))
988: return (error);
989: } else
990: valsize = 0;
991: if ((error = sogetopt((struct socket *)fp->f_data, uap->level,
992: uap->name, &m)) == 0 && uap->val && valsize && m != NULL) {
993: if (valsize > m->m_len)
994: valsize = m->m_len;
995: error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
996: if (error == 0)
997: error = copyout((caddr_t)&valsize,
998: (caddr_t)uap->avalsize, sizeof (valsize));
999: }
1000: if (m != NULL)
1001: (void) m_free(m);
1002: return (error);
1003: }
1004:
1005: /* ARGSUSED */
1006: pipe(p, uap, retval)
1007: struct proc *p;
1008: struct args *uap;
1009: int retval[];
1010: {
1011: register struct filedesc *fdp = p->p_fd;
1012: struct file *rf, *wf;
1013: struct socket *rso, *wso;
1014: int fd, error;
1015:
1016: if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0))
1017: return (error);
1018: if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0))
1019: goto free1;
1020: if (error = falloc(p, &rf, &fd))
1021: goto free2;
1022: retval[0] = fd;
1023: rf->f_flag = FREAD;
1024: rf->f_type = DTYPE_SOCKET;
1025: rf->f_ops = &socketops;
1026: rf->f_data = (caddr_t)rso;
1027: if (error = falloc(p, &wf, &fd))
1028: goto free3;
1029: wf->f_flag = FWRITE;
1030: wf->f_type = DTYPE_SOCKET;
1031: wf->f_ops = &socketops;
1032: wf->f_data = (caddr_t)wso;
1033: retval[1] = fd;
1034: if (error = unp_connect2(wso, rso))
1035: goto free4;
1036: return (0);
1037: free4:
1038: ffree(wf);
1039: fdp->fd_ofiles[retval[1]] = 0;
1040: free3:
1041: ffree(rf);
1042: fdp->fd_ofiles[retval[0]] = 0;
1043: free2:
1044: (void)soclose(wso);
1045: free1:
1046: (void)soclose(rso);
1047: return (error);
1048: }
1049:
1050: /*
1051: * Get socket name.
1052: */
1053: #ifdef COMPAT_43
1.1.1.3 ! root 1054: struct getsockname_args {
! 1055: int fdes;
! 1056: caddr_t asa;
! 1057: int *alen;
! 1058: int compat_43;
! 1059: };
! 1060:
1.1 root 1061: getsockname(p, uap, retval)
1062: struct proc *p;
1.1.1.3 ! root 1063: struct getsockname_args *uap;
1.1 root 1064: int *retval;
1065: {
1066:
1067: uap->compat_43 = 0;
1068: return (getsockname1(p, uap, retval));
1069: }
1070:
1.1.1.3 ! root 1071: struct ogetsockname_args {
! 1072: int fdes;
! 1073: caddr_t asa;
! 1074: int *alen;
! 1075: int compat_43;
! 1076: };
! 1077:
1.1 root 1078: ogetsockname(p, uap, retval)
1079: struct proc *p;
1.1.1.3 ! root 1080: struct ogetsockname_args *uap;
1.1 root 1081: int *retval;
1082: {
1083:
1084: uap->compat_43 = 1;
1085: return (getsockname1(p, uap, retval));
1086: }
1087: #else /* COMPAT_43 */
1088:
1089: #define getsockname1 getsockname
1090: #endif
1091:
1.1.1.3 ! root 1092: struct getsockname1_args {
! 1093: int fdes;
! 1094: caddr_t asa;
! 1095: int *alen;
! 1096: #ifdef COMPAT_43
! 1097: int compat_43;
! 1098: #endif
! 1099: };
! 1100:
1.1 root 1101: /* ARGSUSED */
1102: getsockname1(p, uap, retval)
1103: struct proc *p;
1.1.1.3 ! root 1104: register struct getsockname1_args *uap;
1.1 root 1105: int *retval;
1106: {
1107: struct file *fp;
1108: register struct socket *so;
1109: struct mbuf *m;
1110: int len, error;
1111:
1112: if (error = getsock(p->p_fd, uap->fdes, &fp))
1113: return (error);
1114: if (error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)))
1115: return (error);
1116: so = (struct socket *)fp->f_data;
1117: m = m_getclr(M_WAIT, MT_SONAME);
1118: if (m == NULL)
1119: return (ENOBUFS);
1120: if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0))
1121: goto bad;
1122: if (len > m->m_len)
1123: len = m->m_len;
1124: #ifdef COMPAT_43
1125: if (uap->compat_43)
1126: mtod(m, struct osockaddr *)->sa_family =
1127: mtod(m, struct sockaddr *)->sa_family;
1128: #endif
1129: error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
1130: if (error == 0)
1131: error = copyout((caddr_t)&len, (caddr_t)uap->alen,
1132: sizeof (len));
1133: bad:
1134: m_freem(m);
1135: return (error);
1136: }
1137:
1138: /*
1139: * Get name of peer for connected socket.
1140: */
1141: #ifdef COMPAT_43
1.1.1.3 ! root 1142: struct getpeername_args {
! 1143: int fdes;
! 1144: caddr_t asa;
! 1145: int *alen;
! 1146: int compat_43;
! 1147: };
! 1148:
1.1 root 1149: getpeername(p, uap, retval)
1150: struct proc *p;
1.1.1.3 ! root 1151: struct getpeername_args *uap;
1.1 root 1152: int *retval;
1153: {
1154:
1155: uap->compat_43 = 0;
1156: return (getpeername1(p, uap, retval));
1157: }
1158:
1.1.1.3 ! root 1159: struct ogetpeername_args {
! 1160: int fdes;
! 1161: caddr_t asa;
! 1162: int *alen;
! 1163: int compat_43;
! 1164: };
! 1165:
1.1 root 1166: ogetpeername(p, uap, retval)
1167: struct proc *p;
1.1.1.3 ! root 1168: struct ogetpeername_args *uap;
1.1 root 1169: int *retval;
1170: {
1171:
1172: uap->compat_43 = 1;
1173: return (getpeername1(p, uap, retval));
1174: }
1175: #else /* COMPAT_43 */
1176:
1177: #define getpeername1 getpeername
1178: #endif
1179:
1.1.1.3 ! root 1180: struct getpeername1_args {
! 1181: int fdes;
! 1182: caddr_t asa;
! 1183: int *alen;
! 1184: #ifdef COMPAT_43
! 1185: int compat_43;
! 1186: #endif
! 1187: };
! 1188:
1.1 root 1189: /* ARGSUSED */
1190: getpeername1(p, uap, retval)
1191: struct proc *p;
1.1.1.3 ! root 1192: register struct getpeername1_args *uap;
1.1 root 1193: int *retval;
1194: {
1195: struct file *fp;
1196: register struct socket *so;
1197: struct mbuf *m;
1198: int len, error;
1199:
1200: if (error = getsock(p->p_fd, uap->fdes, &fp))
1201: return (error);
1202: so = (struct socket *)fp->f_data;
1203: if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
1204: return (ENOTCONN);
1205: m = m_getclr(M_WAIT, MT_SONAME);
1206: if (m == NULL)
1207: return (ENOBUFS);
1208: if (error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)))
1209: return (error);
1210: if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0))
1211: goto bad;
1212: if (len > m->m_len)
1213: len = m->m_len;
1214: #ifdef COMPAT_43
1215: if (uap->compat_43)
1216: mtod(m, struct osockaddr *)->sa_family =
1217: mtod(m, struct sockaddr *)->sa_family;
1218: #endif
1219: if (error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len))
1220: goto bad;
1221: error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
1222: bad:
1223: m_freem(m);
1224: return (error);
1225: }
1226:
1227: sockargs(mp, buf, buflen, type)
1228: struct mbuf **mp;
1229: caddr_t buf;
1230: int buflen, type;
1231: {
1232: register struct mbuf *m;
1233: int error;
1234:
1235: if ((u_int)buflen > MLEN) {
1236: #ifdef COMPAT_43
1237: if (type == MT_SONAME && (u_int)buflen <= 112)
1238: buflen = MLEN; /* unix domain compat. hack */
1239: else
1240: #endif
1241: return (EINVAL);
1242: }
1243: m = m_get(M_WAIT, type);
1244: if (m == NULL)
1245: return (ENOBUFS);
1246: m->m_len = buflen;
1247: error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1.1.1.2 root 1248: if (error) {
1.1 root 1249: (void) m_free(m);
1.1.1.2 root 1250: return(error);
1251: }
1252: *mp = m;
1.1 root 1253: if (type == MT_SONAME) {
1254: register struct sockaddr *sa = mtod(m, struct sockaddr *);
1255:
1256: #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN
1257: if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1258: sa->sa_family = sa->sa_len;
1259: #endif
1260: sa->sa_len = buflen;
1261: }
1.1.1.2 root 1262: return (0);
1.1 root 1263: }
1264:
1265: getsock(fdp, fdes, fpp)
1266: struct filedesc *fdp;
1267: int fdes;
1268: struct file **fpp;
1269: {
1270: register struct file *fp;
1271:
1272: if ((unsigned)fdes >= fdp->fd_nfiles ||
1273: (fp = fdp->fd_ofiles[fdes]) == NULL)
1274: return (EBADF);
1275: if (fp->f_type != DTYPE_SOCKET)
1276: return (ENOTSOCK);
1277: *fpp = fp;
1278: return (0);
1279: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.