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