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