uipc_syscalls.c revision 1.43 1 /* $NetBSD: uipc_syscalls.c,v 1.43 1999/05/05 20:01:09 thorpej 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.6 (Berkeley) 2/14/95
36 */
37
38 #include "opt_ktrace.h"
39 #include "opt_compat_freebsd.h"
40 #include "opt_compat_linux.h"
41 #include "opt_compat_sunos.h"
42 #include "opt_compat_hpux.h"
43 #include "opt_compat_ultrix.h"
44 #include "opt_compat_43.h"
45 #include "opt_compat_osf1.h"
46 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) || \
47 defined(COMPAT_HPUX) || defined(COMPAT_FREEBSD) || \
48 defined(COMPAT_ULTRIX) || defined(COMPAT_OSF1)
49 #define COMPAT_OLDSOCK /* used by <sys/socket.h> */
50 #endif
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/filedesc.h>
55 #include <sys/proc.h>
56 #include <sys/file.h>
57 #include <sys/buf.h>
58 #include <sys/malloc.h>
59 #include <sys/mbuf.h>
60 #include <sys/protosw.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/signalvar.h>
64 #include <sys/un.h>
65 #ifdef KTRACE
66 #include <sys/ktrace.h>
67 #endif
68
69 #include <sys/mount.h>
70 #include <sys/syscallargs.h>
71
72 /*
73 * System call interface to the socket abstraction.
74 */
75 extern struct fileops socketops;
76
77 int
78 sys_socket(p, v, retval)
79 struct proc *p;
80 void *v;
81 register_t *retval;
82 {
83 register struct sys_socket_args /* {
84 syscallarg(int) domain;
85 syscallarg(int) type;
86 syscallarg(int) protocol;
87 } */ *uap = v;
88 struct filedesc *fdp = p->p_fd;
89 struct socket *so;
90 struct file *fp;
91 int fd, error;
92
93 /* falloc() will use the desciptor for us */
94 if ((error = falloc(p, &fp, &fd)) != 0)
95 return (error);
96 fp->f_flag = FREAD|FWRITE;
97 fp->f_type = DTYPE_SOCKET;
98 fp->f_ops = &socketops;
99 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
100 SCARG(uap, protocol));
101 if (error) {
102 FILE_UNUSE(fp, p);
103 fdp->fd_ofiles[fd] = 0;
104 ffree(fp);
105 } else {
106 fp->f_data = (caddr_t)so;
107 FILE_UNUSE(fp, p);
108 *retval = fd;
109 }
110 return (error);
111 }
112
113 /* ARGSUSED */
114 int
115 sys_bind(p, v, retval)
116 struct proc *p;
117 void *v;
118 register_t *retval;
119 {
120 register struct sys_bind_args /* {
121 syscallarg(int) s;
122 syscallarg(const struct sockaddr *) name;
123 syscallarg(unsigned int) namelen;
124 } */ *uap = v;
125 struct file *fp;
126 struct mbuf *nam;
127 int error;
128
129 /* getsock() will use the descriptor for us */
130 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
131 return (error);
132 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
133 MT_SONAME);
134 if (error) {
135 FILE_UNUSE(fp, p);
136 return (error);
137 }
138 error = sobind((struct socket *)fp->f_data, nam);
139 m_freem(nam);
140 FILE_UNUSE(fp, p);
141 return (error);
142 }
143
144 /* ARGSUSED */
145 int
146 sys_listen(p, v, retval)
147 struct proc *p;
148 void *v;
149 register_t *retval;
150 {
151 register struct sys_listen_args /* {
152 syscallarg(int) s;
153 syscallarg(int) backlog;
154 } */ *uap = v;
155 struct file *fp;
156 int error;
157
158 /* getsock() will use the descriptor for us */
159 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
160 return (error);
161 error = solisten((struct socket *)fp->f_data, SCARG(uap, backlog));
162 FILE_UNUSE(fp, p);
163 return (error);
164 }
165
166 int
167 sys_accept(p, v, retval)
168 struct proc *p;
169 void *v;
170 register_t *retval;
171 {
172 register struct sys_accept_args /* {
173 syscallarg(int) s;
174 syscallarg(struct sockaddr *) name;
175 syscallarg(unsigned int *) anamelen;
176 } */ *uap = v;
177 struct file *fp;
178 struct mbuf *nam;
179 unsigned int namelen;
180 int error, s, tmpfd;
181 register struct socket *so;
182
183 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
184 (caddr_t)&namelen, sizeof(namelen))))
185 return (error);
186 /* getsock() will use the descriptor for us */
187 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
188 return (error);
189 s = splsoftnet();
190 so = (struct socket *)fp->f_data;
191 FILE_UNUSE(fp, p);
192 if ((so->so_options & SO_ACCEPTCONN) == 0) {
193 splx(s);
194 return (EINVAL);
195 }
196 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
197 splx(s);
198 return (EWOULDBLOCK);
199 }
200 while (so->so_qlen == 0 && so->so_error == 0) {
201 if (so->so_state & SS_CANTRCVMORE) {
202 so->so_error = ECONNABORTED;
203 break;
204 }
205 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
206 netcon, 0);
207 if (error) {
208 splx(s);
209 return (error);
210 }
211 }
212 if (so->so_error) {
213 error = so->so_error;
214 so->so_error = 0;
215 splx(s);
216 return (error);
217 }
218 /* falloc() will use the descriptor for us */
219 if ((error = falloc(p, &fp, &tmpfd)) != 0) {
220 splx(s);
221 return (error);
222 }
223 *retval = tmpfd;
224 { struct socket *aso = so->so_q.tqh_first;
225 if (soqremque(aso, 1) == 0)
226 panic("accept");
227 so = aso;
228 }
229 fp->f_type = DTYPE_SOCKET;
230 fp->f_flag = FREAD|FWRITE;
231 fp->f_ops = &socketops;
232 fp->f_data = (caddr_t)so;
233 FILE_UNUSE(fp, p);
234 nam = m_get(M_WAIT, MT_SONAME);
235 (void) soaccept(so, nam);
236 if (SCARG(uap, name)) {
237 if (namelen > nam->m_len)
238 namelen = nam->m_len;
239 /* SHOULD COPY OUT A CHAIN HERE */
240 if ((error = copyout(mtod(nam, caddr_t),
241 (caddr_t)SCARG(uap, name), namelen)) == 0)
242 error = copyout((caddr_t)&namelen,
243 (caddr_t)SCARG(uap, anamelen),
244 sizeof(*SCARG(uap, anamelen)));
245 }
246 m_freem(nam);
247 splx(s);
248 return (error);
249 }
250
251 /* ARGSUSED */
252 int
253 sys_connect(p, v, retval)
254 struct proc *p;
255 void *v;
256 register_t *retval;
257 {
258 register struct sys_connect_args /* {
259 syscallarg(int) s;
260 syscallarg(const struct sockaddr *) name;
261 syscallarg(unsigned int) namelen;
262 } */ *uap = v;
263 struct file *fp;
264 register struct socket *so;
265 struct mbuf *nam;
266 int error, s;
267
268 /* getsock() will use the descriptor for us */
269 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
270 return (error);
271 so = (struct socket *)fp->f_data;
272 FILE_UNUSE(fp, p);
273 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
274 return (EALREADY);
275 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
276 MT_SONAME);
277 if (error)
278 return (error);
279 error = soconnect(so, nam);
280 if (error)
281 goto bad;
282 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
283 m_freem(nam);
284 return (EINPROGRESS);
285 }
286 s = splsoftnet();
287 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
288 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
289 netcon, 0);
290 if (error)
291 break;
292 }
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 sys_socketpair(p, v, retval)
308 struct proc *p;
309 void *v;
310 register_t *retval;
311 {
312 register struct sys_socketpair_args /* {
313 syscallarg(int) domain;
314 syscallarg(int) type;
315 syscallarg(int) protocol;
316 syscallarg(int *) rsv;
317 } */ *uap = v;
318 register struct filedesc *fdp = p->p_fd;
319 struct file *fp1, *fp2;
320 struct socket *so1, *so2;
321 int fd, error, sv[2];
322
323 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
324 SCARG(uap, protocol));
325 if (error)
326 return (error);
327 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
328 SCARG(uap, protocol));
329 if (error)
330 goto free1;
331 /* falloc() will use the descriptor for us */
332 if ((error = falloc(p, &fp1, &fd)) != 0)
333 goto free2;
334 sv[0] = fd;
335 fp1->f_flag = FREAD|FWRITE;
336 fp1->f_type = DTYPE_SOCKET;
337 fp1->f_ops = &socketops;
338 fp1->f_data = (caddr_t)so1;
339 if ((error = falloc(p, &fp2, &fd)) != 0)
340 goto free3;
341 fp2->f_flag = FREAD|FWRITE;
342 fp2->f_type = DTYPE_SOCKET;
343 fp2->f_ops = &socketops;
344 fp2->f_data = (caddr_t)so2;
345 sv[1] = fd;
346 if ((error = soconnect2(so1, so2)) != 0)
347 goto free4;
348 if (SCARG(uap, type) == SOCK_DGRAM) {
349 /*
350 * Datagram socket connection is asymmetric.
351 */
352 if ((error = soconnect2(so2, so1)) != 0)
353 goto free4;
354 }
355 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
356 2 * sizeof(int));
357 FILE_UNUSE(fp1, p);
358 FILE_UNUSE(fp2, p);
359 return (error);
360 free4:
361 FILE_UNUSE(fp2, p);
362 ffree(fp2);
363 fdp->fd_ofiles[sv[1]] = 0;
364 free3:
365 FILE_UNUSE(fp1, p);
366 ffree(fp1);
367 fdp->fd_ofiles[sv[0]] = 0;
368 free2:
369 (void)soclose(so2);
370 free1:
371 (void)soclose(so1);
372 return (error);
373 }
374
375 int
376 sys_sendto(p, v, retval)
377 struct proc *p;
378 void *v;
379 register_t *retval;
380 {
381 register struct sys_sendto_args /* {
382 syscallarg(int) s;
383 syscallarg(const void *) buf;
384 syscallarg(size_t) len;
385 syscallarg(int) flags;
386 syscallarg(const struct sockaddr *) to;
387 syscallarg(unsigned int) tolen;
388 } */ *uap = v;
389 struct msghdr msg;
390 struct iovec aiov;
391
392 msg.msg_name = (caddr_t)SCARG(uap, to); /* XXX kills const */
393 msg.msg_namelen = SCARG(uap, tolen);
394 msg.msg_iov = &aiov;
395 msg.msg_iovlen = 1;
396 msg.msg_control = 0;
397 #ifdef COMPAT_OLDSOCK
398 msg.msg_flags = 0;
399 #endif
400 aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */
401 aiov.iov_len = SCARG(uap, len);
402 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
403 }
404
405 int
406 sys_sendmsg(p, v, retval)
407 struct proc *p;
408 void *v;
409 register_t *retval;
410 {
411 register struct sys_sendmsg_args /* {
412 syscallarg(int) s;
413 syscallarg(const struct msghdr *) msg;
414 syscallarg(int) flags;
415 } */ *uap = v;
416 struct msghdr msg;
417 struct iovec aiov[UIO_SMALLIOV], *iov;
418 int error;
419
420 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
421 if (error)
422 return (error);
423 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
424 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
425 return (EMSGSIZE);
426 MALLOC(iov, struct iovec *,
427 sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
428 } else
429 iov = aiov;
430 if ((unsigned int)msg.msg_iovlen > 0) {
431 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
432 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
433 if (error)
434 goto done;
435 }
436 msg.msg_iov = iov;
437 #ifdef COMPAT_OLDSOCK
438 msg.msg_flags = 0;
439 #endif
440 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
441 done:
442 if (iov != aiov)
443 FREE(iov, M_IOV);
444 return (error);
445 }
446
447 int
448 sendit(p, s, mp, flags, retsize)
449 register struct proc *p;
450 int s;
451 register struct msghdr *mp;
452 int flags;
453 register_t *retsize;
454 {
455 struct file *fp;
456 struct uio auio;
457 register struct iovec *iov;
458 register int i;
459 struct mbuf *to, *control;
460 int len, error;
461 struct socket *so;
462 #ifdef KTRACE
463 struct iovec *ktriov = NULL;
464 #endif
465
466 /* getsock() will use the descriptor for us */
467 if ((error = getsock(p->p_fd, s, &fp)) != 0)
468 return (error);
469 auio.uio_iov = mp->msg_iov;
470 auio.uio_iovcnt = mp->msg_iovlen;
471 auio.uio_segflg = UIO_USERSPACE;
472 auio.uio_rw = UIO_WRITE;
473 auio.uio_procp = p;
474 auio.uio_offset = 0; /* XXX */
475 auio.uio_resid = 0;
476 iov = mp->msg_iov;
477 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
478 #if 0
479 /* cannot happen; iov_len is unsigned */
480 if (iov->iov_len < 0) {
481 error = EINVAL;
482 goto out;
483 }
484 #endif
485 /*
486 * Writes return ssize_t because -1 is returned on error.
487 * Therefore, we must restrict the length to SSIZE_MAX to
488 * avoid garbage return values.
489 */
490 auio.uio_resid += iov->iov_len;
491 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
492 error = EINVAL;
493 goto out;
494 }
495 }
496 if (mp->msg_name) {
497 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
498 MT_SONAME);
499 if (error)
500 goto out;
501 } else
502 to = 0;
503 if (mp->msg_control) {
504 if (mp->msg_controllen < sizeof(struct cmsghdr)
505 #ifdef COMPAT_OLDSOCK
506 && mp->msg_flags != MSG_COMPAT
507 #endif
508 ) {
509 error = EINVAL;
510 goto bad;
511 }
512 error = sockargs(&control, mp->msg_control,
513 mp->msg_controllen, MT_CONTROL);
514 if (error)
515 goto bad;
516 #ifdef COMPAT_OLDSOCK
517 if (mp->msg_flags == MSG_COMPAT) {
518 register struct cmsghdr *cm;
519
520 M_PREPEND(control, sizeof(*cm), M_WAIT);
521 if (control == 0) {
522 error = ENOBUFS;
523 goto bad;
524 } else {
525 cm = mtod(control, struct cmsghdr *);
526 cm->cmsg_len = control->m_len;
527 cm->cmsg_level = SOL_SOCKET;
528 cm->cmsg_type = SCM_RIGHTS;
529 }
530 }
531 #endif
532 } else
533 control = 0;
534 #ifdef KTRACE
535 if (KTRPOINT(p, KTR_GENIO)) {
536 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
537
538 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
539 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
540 }
541 #endif
542 len = auio.uio_resid;
543 so = (struct socket *)fp->f_data;
544 error = (*so->so_send)(so, to, &auio, NULL, control, flags);
545 if (error) {
546 if (auio.uio_resid != len && (error == ERESTART ||
547 error == EINTR || error == EWOULDBLOCK))
548 error = 0;
549 if (error == EPIPE)
550 psignal(p, SIGPIPE);
551 }
552 if (error == 0)
553 *retsize = len - auio.uio_resid;
554 #ifdef KTRACE
555 if (ktriov != NULL) {
556 if (error == 0)
557 ktrgenio(p->p_tracep, s, UIO_WRITE,
558 ktriov, *retsize, error);
559 FREE(ktriov, M_TEMP);
560 }
561 #endif
562 bad:
563 if (to)
564 m_freem(to);
565 out:
566 FILE_UNUSE(fp, p);
567 return (error);
568 }
569
570 int
571 sys_recvfrom(p, v, retval)
572 struct proc *p;
573 void *v;
574 register_t *retval;
575 {
576 register struct sys_recvfrom_args /* {
577 syscallarg(int) s;
578 syscallarg(void *) buf;
579 syscallarg(size_t) len;
580 syscallarg(int) flags;
581 syscallarg(struct sockaddr *) from;
582 syscallarg(unsigned int *) fromlenaddr;
583 } */ *uap = v;
584 struct msghdr msg;
585 struct iovec aiov;
586 int error;
587
588 if (SCARG(uap, fromlenaddr)) {
589 error = copyin((caddr_t)SCARG(uap, fromlenaddr),
590 (caddr_t)&msg.msg_namelen,
591 sizeof(msg.msg_namelen));
592 if (error)
593 return (error);
594 } else
595 msg.msg_namelen = 0;
596 msg.msg_name = (caddr_t)SCARG(uap, from);
597 msg.msg_iov = &aiov;
598 msg.msg_iovlen = 1;
599 aiov.iov_base = SCARG(uap, buf);
600 aiov.iov_len = SCARG(uap, len);
601 msg.msg_control = 0;
602 msg.msg_flags = SCARG(uap, flags);
603 return (recvit(p, SCARG(uap, s), &msg,
604 (caddr_t)SCARG(uap, fromlenaddr), retval));
605 }
606
607 int
608 sys_recvmsg(p, v, retval)
609 struct proc *p;
610 void *v;
611 register_t *retval;
612 {
613 register struct sys_recvmsg_args /* {
614 syscallarg(int) s;
615 syscallarg(struct msghdr *) msg;
616 syscallarg(int) flags;
617 } */ *uap = v;
618 struct msghdr msg;
619 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
620 register int error;
621
622 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
623 sizeof(msg));
624 if (error)
625 return (error);
626 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
627 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
628 return (EMSGSIZE);
629 MALLOC(iov, struct iovec *,
630 sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
631 } else
632 iov = aiov;
633 if ((unsigned int)msg.msg_iovlen > 0) {
634 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
635 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
636 if (error)
637 goto done;
638 }
639 uiov = msg.msg_iov;
640 msg.msg_iov = iov;
641 #ifdef COMPAT_OLDSOCK
642 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
643 #else
644 msg.msg_flags = SCARG(uap, flags);
645 #endif
646 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
647 msg.msg_iov = uiov;
648 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
649 sizeof(msg));
650 }
651 done:
652 if (iov != aiov)
653 FREE(iov, M_IOV);
654 return (error);
655 }
656
657 int
658 recvit(p, s, mp, namelenp, retsize)
659 register struct proc *p;
660 int s;
661 register struct msghdr *mp;
662 caddr_t namelenp;
663 register_t *retsize;
664 {
665 struct file *fp;
666 struct uio auio;
667 register struct iovec *iov;
668 register int i;
669 int len, error;
670 struct mbuf *from = 0, *control = 0;
671 struct socket *so;
672 #ifdef KTRACE
673 struct iovec *ktriov = NULL;
674 #endif
675
676 /* getsock() will use the descriptor for us */
677 if ((error = getsock(p->p_fd, s, &fp)) != 0)
678 return (error);
679 auio.uio_iov = mp->msg_iov;
680 auio.uio_iovcnt = mp->msg_iovlen;
681 auio.uio_segflg = UIO_USERSPACE;
682 auio.uio_rw = UIO_READ;
683 auio.uio_procp = p;
684 auio.uio_offset = 0; /* XXX */
685 auio.uio_resid = 0;
686 iov = mp->msg_iov;
687 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
688 #if 0
689 /* cannot happen iov_len is unsigned */
690 if (iov->iov_len < 0) {
691 error = EINVAL;
692 goto out1;
693 }
694 #endif
695 /*
696 * Reads return ssize_t because -1 is returned on error.
697 * Therefore we must restrict the length to SSIZE_MAX to
698 * avoid garbage return values.
699 */
700 auio.uio_resid += iov->iov_len;
701 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
702 error = EINVAL;
703 goto out1;
704 }
705 }
706 #ifdef KTRACE
707 if (KTRPOINT(p, KTR_GENIO)) {
708 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
709
710 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
711 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
712 }
713 #endif
714 len = auio.uio_resid;
715 so = (struct socket *)fp->f_data;
716 error = (*so->so_receive)(so, &from, &auio, NULL,
717 mp->msg_control ? &control : NULL, &mp->msg_flags);
718 if (error) {
719 if (auio.uio_resid != len && (error == ERESTART ||
720 error == EINTR || error == EWOULDBLOCK))
721 error = 0;
722 }
723 #ifdef KTRACE
724 if (ktriov != NULL) {
725 if (error == 0)
726 ktrgenio(p->p_tracep, s, UIO_READ,
727 ktriov, len - auio.uio_resid, error);
728 FREE(ktriov, M_TEMP);
729 }
730 #endif
731 if (error)
732 goto out;
733 *retsize = len - auio.uio_resid;
734 if (mp->msg_name) {
735 len = mp->msg_namelen;
736 if (len <= 0 || from == 0)
737 len = 0;
738 else {
739 #ifdef COMPAT_OLDSOCK
740 if (mp->msg_flags & MSG_COMPAT)
741 mtod(from, struct osockaddr *)->sa_family =
742 mtod(from, struct sockaddr *)->sa_family;
743 #endif
744 if (len > from->m_len)
745 len = from->m_len;
746 /* else if len < from->m_len ??? */
747 error = copyout(mtod(from, caddr_t),
748 (caddr_t)mp->msg_name, (unsigned)len);
749 if (error)
750 goto out;
751 }
752 mp->msg_namelen = len;
753 if (namelenp &&
754 (error = copyout((caddr_t)&len, namelenp, sizeof(int)))) {
755 #ifdef COMPAT_OLDSOCK
756 if (mp->msg_flags & MSG_COMPAT)
757 error = 0; /* old recvfrom didn't check */
758 else
759 #endif
760 goto out;
761 }
762 }
763 if (mp->msg_control) {
764 #ifdef COMPAT_OLDSOCK
765 /*
766 * We assume that old recvmsg calls won't receive access
767 * rights and other control info, esp. as control info
768 * is always optional and those options didn't exist in 4.3.
769 * If we receive rights, trim the cmsghdr; anything else
770 * is tossed.
771 */
772 if (control && mp->msg_flags & MSG_COMPAT) {
773 if (mtod(control, struct cmsghdr *)->cmsg_level !=
774 SOL_SOCKET ||
775 mtod(control, struct cmsghdr *)->cmsg_type !=
776 SCM_RIGHTS) {
777 mp->msg_controllen = 0;
778 goto out;
779 }
780 control->m_len -= sizeof(struct cmsghdr);
781 control->m_data += sizeof(struct cmsghdr);
782 }
783 #endif
784 len = mp->msg_controllen;
785 if (len <= 0 || control == 0)
786 len = 0;
787 else {
788 struct mbuf *m = control;
789 caddr_t p = (caddr_t)mp->msg_control;
790
791 do {
792 i = m->m_len;
793 if (len < i) {
794 mp->msg_flags |= MSG_CTRUNC;
795 i = len;
796 }
797 error = copyout(mtod(m, caddr_t), p,
798 (unsigned)i);
799 if (m->m_next)
800 i = ALIGN(i);
801 p += i;
802 len -= i;
803 if (error != 0 || len <= 0)
804 break;
805 } while ((m = m->m_next) != NULL);
806 len = p - (caddr_t)mp->msg_control;
807 }
808 mp->msg_controllen = len;
809 }
810 out:
811 if (from)
812 m_freem(from);
813 if (control)
814 m_freem(control);
815 out1:
816 FILE_UNUSE(fp, p);
817 return (error);
818 }
819
820 /* ARGSUSED */
821 int
822 sys_shutdown(p, v, retval)
823 struct proc *p;
824 void *v;
825 register_t *retval;
826 {
827 register struct sys_shutdown_args /* {
828 syscallarg(int) s;
829 syscallarg(int) how;
830 } */ *uap = v;
831 struct file *fp;
832 int error;
833
834 /* getsock() will use the descriptor for us */
835 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
836 return (error);
837 error = soshutdown((struct socket *)fp->f_data, SCARG(uap, how));
838 FILE_UNUSE(fp, p);
839 return (error);
840 }
841
842 /* ARGSUSED */
843 int
844 sys_setsockopt(p, v, retval)
845 struct proc *p;
846 void *v;
847 register_t *retval;
848 {
849 register struct sys_setsockopt_args /* {
850 syscallarg(int) s;
851 syscallarg(int) level;
852 syscallarg(int) name;
853 syscallarg(const void *) val;
854 syscallarg(unsigned int) valsize;
855 } */ *uap = v;
856 struct file *fp;
857 struct mbuf *m = NULL;
858 int error;
859
860 /* getsock() will use the descriptor for us */
861 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
862 return (error);
863 if (SCARG(uap, valsize) > MLEN) {
864 error = EINVAL;
865 goto out;
866 }
867 if (SCARG(uap, val)) {
868 m = m_get(M_WAIT, MT_SOOPTS);
869 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
870 SCARG(uap, valsize));
871 if (error) {
872 (void) m_free(m);
873 goto out;
874 }
875 m->m_len = SCARG(uap, valsize);
876 }
877 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
878 SCARG(uap, name), m);
879 out:
880 FILE_UNUSE(fp, p);
881 return (error);
882 }
883
884 /* ARGSUSED */
885 int
886 sys_getsockopt(p, v, retval)
887 struct proc *p;
888 void *v;
889 register_t *retval;
890 {
891 register struct sys_getsockopt_args /* {
892 syscallarg(int) s;
893 syscallarg(int) level;
894 syscallarg(int) name;
895 syscallarg(void *) val;
896 syscallarg(unsigned int *) avalsize;
897 } */ *uap = v;
898 struct file *fp;
899 struct mbuf *m = NULL;
900 unsigned int valsize;
901 int error;
902
903 /* getsock() will use the descriptor for us */
904 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
905 return (error);
906 if (SCARG(uap, val)) {
907 error = copyin((caddr_t)SCARG(uap, avalsize),
908 (caddr_t)&valsize, sizeof(valsize));
909 if (error)
910 goto out;
911 } else
912 valsize = 0;
913 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
914 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
915 m != NULL) {
916 if (valsize > m->m_len)
917 valsize = m->m_len;
918 error = copyout(mtod(m, caddr_t), SCARG(uap, val),
919 valsize);
920 if (error == 0)
921 error = copyout((caddr_t)&valsize,
922 (caddr_t)SCARG(uap, avalsize), sizeof(valsize));
923 }
924 if (m != NULL)
925 (void) m_free(m);
926 out:
927 FILE_UNUSE(fp, p);
928 return (error);
929 }
930
931 /* ARGSUSED */
932 int
933 sys_pipe(p, v, retval)
934 struct proc *p;
935 void *v;
936 register_t *retval;
937 {
938 register struct filedesc *fdp = p->p_fd;
939 struct file *rf, *wf;
940 struct socket *rso, *wso;
941 int fd, error;
942
943 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0)
944 return (error);
945 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0)
946 goto free1;
947 /* falloc() will use the descriptor for us */
948 if ((error = falloc(p, &rf, &fd)) != 0)
949 goto free2;
950 retval[0] = fd;
951 rf->f_flag = FREAD;
952 rf->f_type = DTYPE_SOCKET;
953 rf->f_ops = &socketops;
954 rf->f_data = (caddr_t)rso;
955 if ((error = falloc(p, &wf, &fd)) != 0)
956 goto free3;
957 wf->f_flag = FWRITE;
958 wf->f_type = DTYPE_SOCKET;
959 wf->f_ops = &socketops;
960 wf->f_data = (caddr_t)wso;
961 retval[1] = fd;
962 if ((error = unp_connect2(wso, rso)) != 0)
963 goto free4;
964 FILE_UNUSE(rf, p);
965 FILE_UNUSE(wf, p);
966 return (0);
967 free4:
968 FILE_UNUSE(wf, p);
969 ffree(wf);
970 fdp->fd_ofiles[retval[1]] = 0;
971 free3:
972 FILE_UNUSE(rf, p);
973 ffree(rf);
974 fdp->fd_ofiles[retval[0]] = 0;
975 free2:
976 (void)soclose(wso);
977 free1:
978 (void)soclose(rso);
979 return (error);
980 }
981
982 /*
983 * Get socket name.
984 */
985 /* ARGSUSED */
986 int
987 sys_getsockname(p, v, retval)
988 struct proc *p;
989 void *v;
990 register_t *retval;
991 {
992 register struct sys_getsockname_args /* {
993 syscallarg(int) fdes;
994 syscallarg(struct sockaddr *) asa;
995 syscallarg(unsigned int *) alen;
996 } */ *uap = v;
997 struct file *fp;
998 register struct socket *so;
999 struct mbuf *m;
1000 unsigned int len;
1001 int error;
1002
1003 /* getsock() will use the descriptor for us */
1004 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1005 return (error);
1006 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
1007 if (error)
1008 goto out;
1009 so = (struct socket *)fp->f_data;
1010 m = m_getclr(M_WAIT, MT_SONAME);
1011 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0,
1012 m, (struct mbuf *)0, (struct proc *)0);
1013 if (error)
1014 goto bad;
1015 if (len > m->m_len)
1016 len = m->m_len;
1017 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1018 if (error == 0)
1019 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
1020 sizeof(len));
1021 bad:
1022 m_freem(m);
1023 out:
1024 FILE_UNUSE(fp, p);
1025 return (error);
1026 }
1027
1028 /*
1029 * Get name of peer for connected socket.
1030 */
1031 /* ARGSUSED */
1032 int
1033 sys_getpeername(p, v, retval)
1034 struct proc *p;
1035 void *v;
1036 register_t *retval;
1037 {
1038 register struct sys_getpeername_args /* {
1039 syscallarg(int) fdes;
1040 syscallarg(struct sockaddr *) asa;
1041 syscallarg(unsigned int *) alen;
1042 } */ *uap = v;
1043 struct file *fp;
1044 register struct socket *so;
1045 struct mbuf *m;
1046 unsigned int len;
1047 int error;
1048
1049 /* getsock() will use the descriptor for us */
1050 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1051 return (error);
1052 so = (struct socket *)fp->f_data;
1053 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
1054 error = ENOTCONN;
1055 goto out;
1056 }
1057 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
1058 if (error)
1059 goto out;
1060 m = m_getclr(M_WAIT, MT_SONAME);
1061 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0,
1062 m, (struct mbuf *)0, (struct proc *)0);
1063 if (error)
1064 goto bad;
1065 if (len > m->m_len)
1066 len = m->m_len;
1067 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1068 if (error)
1069 goto bad;
1070 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len));
1071 bad:
1072 m_freem(m);
1073 out:
1074 FILE_UNUSE(fp, p);
1075 return (error);
1076 }
1077
1078 /*
1079 * XXX In a perfect world, we wouldn't pass around socket control
1080 * XXX arguments in mbufs, and this could go away.
1081 */
1082 int
1083 sockargs(mp, buf, buflen, type)
1084 struct mbuf **mp;
1085 const void *buf;
1086 int buflen, type;
1087 {
1088 register struct sockaddr *sa;
1089 register struct mbuf *m;
1090 int error;
1091
1092 /*
1093 * We can't allow socket names > UCHAR_MAX in length, since that
1094 * will overflow sa_len.
1095 */
1096 if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX)
1097 return (EINVAL);
1098
1099 /* Allocate an mbuf to hold the arguments. */
1100 m = m_get(M_WAIT, type);
1101 if ((u_int)buflen > MLEN) {
1102 /*
1103 * Won't fit into a regular mbuf, so we allocate just
1104 * enough external storage to hold the argument.
1105 */
1106 MEXTMALLOC(m, buflen, M_WAITOK);
1107 }
1108 m->m_len = buflen;
1109 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1110 if (error) {
1111 (void) m_free(m);
1112 return (error);
1113 }
1114 *mp = m;
1115 if (type == MT_SONAME) {
1116 sa = mtod(m, struct sockaddr *);
1117
1118 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1119 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1120 sa->sa_family = sa->sa_len;
1121 #endif
1122 sa->sa_len = buflen;
1123 }
1124 return (0);
1125 }
1126
1127 int
1128 getsock(fdp, fdes, fpp)
1129 struct filedesc *fdp;
1130 int fdes;
1131 struct file **fpp;
1132 {
1133 register struct file *fp;
1134
1135 if ((unsigned)fdes >= fdp->fd_nfiles ||
1136 (fp = fdp->fd_ofiles[fdes]) == NULL ||
1137 (fp->f_iflags & FIF_WANTCLOSE) != 0)
1138 return (EBADF);
1139
1140 FILE_USE(fp);
1141
1142 if (fp->f_type != DTYPE_SOCKET) {
1143 FILE_UNUSE(fp, NULL);
1144 return (ENOTSOCK);
1145 }
1146 *fpp = fp;
1147 return (0);
1148 }
1149