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