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