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