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