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