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