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