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