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