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