1 /* $OpenBSD: uipc_syscalls.c,v 1.211 2023/01/27 21:01:59 mvs Exp $ */
2 /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */
3
4 /*
5 * Copyright (c) 1982, 1986, 1989, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/filedesc.h>
38 #include <sys/namei.h>
39 #include <sys/pool.h>
40 #include <sys/proc.h>
41 #include <sys/fcntl.h>
42 #include <sys/kernel.h>
43 #include <sys/file.h>
44 #include <sys/vnode.h>
45 #include <sys/malloc.h>
46 #include <sys/event.h>
47 #include <sys/mbuf.h>
48 #include <sys/protosw.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/signalvar.h>
52 #include <sys/pledge.h>
53 #ifdef KTRACE
54 #include <sys/ktrace.h>
55 #endif
56 #include <sys/unistd.h>
57
58 #include <sys/mount.h>
59 #include <sys/syscallargs.h>
60
61 #include <sys/domain.h>
62 #include <netinet/in.h>
63 #include <netinet/ip.h>
64 #include <net/route.h>
65 #include <netinet/in_pcb.h>
66 #include <net/rtable.h>
67
68 int copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t,
69 socklen_t *);
70
71 int
72 sys_socket(struct proc *p, void *v, register_t *retval)
73 {
74 struct sys_socket_args /* {
75 syscallarg(int) domain;
76 syscallarg(int) type;
77 syscallarg(int) protocol;
78 } */ *uap = v;
79 struct filedesc *fdp = p->p_fd;
80 struct socket *so;
81 struct file *fp;
82 int type = SCARG(uap, type);
83 int domain = SCARG(uap, domain);
84 int fd, cloexec, nonblock, fflag, error;
85 unsigned int ss = 0;
86
87 if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6))
88 return (EINVAL);
89
90 if (ISSET(type, SOCK_DNS))
91 ss |= SS_DNS;
92 error = pledge_socket(p, domain, ss);
93 if (error)
94 return (error);
95
96 type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS);
97 cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
98 nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
99 fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
100
101 error = socreate(SCARG(uap, domain), &so, type, SCARG(uap, protocol));
102 if (error)
103 return (error);
104
105 fdplock(fdp);
106 error = falloc(p, &fp, &fd);
107 if (error) {
108 fdpunlock(fdp);
109 soclose(so, MSG_DONTWAIT);
110 } else {
111 fp->f_flag = fflag;
112 fp->f_type = DTYPE_SOCKET;
113 fp->f_ops = &socketops;
114 so->so_state |= ss;
115 fp->f_data = so;
116 fdinsert(fdp, fd, cloexec, fp);
117 fdpunlock(fdp);
118 FRELE(fp, p);
119 *retval = fd;
120 }
121 return (error);
122 }
123
124 static inline int
125 isdnssocket(struct socket *so)
126 {
127 return (so->so_state & SS_DNS);
128 }
129
130 /* For SS_DNS sockets, only allow port DNS (port 53) */
131 static int
132 dns_portcheck(struct proc *p, struct socket *so, void *nam, size_t namelen)
133 {
134 int error = EINVAL;
135
136 switch (so->so_proto->pr_domain->dom_family) {
137 case AF_INET:
138 if (namelen < sizeof(struct sockaddr_in))
139 break;
140 if (((struct sockaddr_in *)nam)->sin_port == htons(53))
141 error = 0;
142 break;
143 #ifdef INET6
144 case AF_INET6:
145 if (namelen < sizeof(struct sockaddr_in6))
146 break;
147 if (((struct sockaddr_in6 *)nam)->sin6_port == htons(53))
148 error = 0;
149 #endif
150 }
151 if (error && p->p_p->ps_flags & PS_PLEDGE)
152 return (pledge_fail(p, EPERM, PLEDGE_DNS));
153 return error;
154 }
155
156 int
157 sys_bind(struct proc *p, void *v, register_t *retval)
158 {
159 struct sys_bind_args /* {
160 syscallarg(int) s;
161 syscallarg(const struct sockaddr *) name;
162 syscallarg(socklen_t) namelen;
163 } */ *uap = v;
164 struct file *fp;
165 struct mbuf *nam;
166 struct socket *so;
167 int error;
168
169 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
170 return (error);
171 so = fp->f_data;
172 error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
173 so->so_state);
174 if (error)
175 goto out;
176 if (so->so_state & SS_YP) {
177 error = ENOTSOCK;
178 goto out;
179 }
180 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
181 MT_SONAME);
182 if (error)
183 goto out;
184 #ifdef KTRACE
185 if (KTRPOINT(p, KTR_STRUCT))
186 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
187 #endif
188 solock(so);
189 error = sobind(so, nam, p);
190 sounlock(so);
191 m_freem(nam);
192 out:
193 FRELE(fp, p);
194 return (error);
195 }
196
197 int
198 sys_listen(struct proc *p, void *v, register_t *retval)
199 {
200 struct sys_listen_args /* {
201 syscallarg(int) s;
202 syscallarg(int) backlog;
203 } */ *uap = v;
204 struct file *fp;
205 struct socket *so;
206 int error;
207
208 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
209 return (error);
210 so = fp->f_data;
211 if (so->so_state & SS_YP)
212 return ENOTSOCK;
213 solock(so);
214 error = solisten(so, SCARG(uap, backlog));
215 sounlock(so);
216 FRELE(fp, p);
217 return (error);
218 }
219
220 int
221 sys_accept(struct proc *p, void *v, register_t *retval)
222 {
223 struct sys_accept_args /* {
224 syscallarg(int) s;
225 syscallarg(struct sockaddr *) name;
226 syscallarg(socklen_t *) anamelen;
227 } */ *uap = v;
228
229 return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
230 SCARG(uap, anamelen), SOCK_NONBLOCK_INHERIT, retval));
231 }
232
233 int
234 sys_accept4(struct proc *p, void *v, register_t *retval)
235 {
236 struct sys_accept4_args /* {
237 syscallarg(int) s;
238 syscallarg(struct sockaddr *) name;
239 syscallarg(socklen_t *) anamelen;
240 syscallarg(socklen_t *) int flags;
241 } */ *uap = v;
242
243 if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
244 return (EINVAL);
245
246 return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
247 SCARG(uap, anamelen), SCARG(uap, flags), retval));
248 }
249
250 int
251 doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen,
252 int flags, register_t *retval)
253 {
254 struct filedesc *fdp = p->p_fd;
255 struct file *fp, *headfp;
256 struct mbuf *nam;
257 socklen_t namelen;
258 int error, tmpfd;
259 struct socket *head, *so;
260 int cloexec, nflag, persocket;
261
262 cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
263
264 if (name && (error = copyin(anamelen, &namelen, sizeof (namelen))))
265 return (error);
266 if ((error = getsock(p, sock, &fp)) != 0)
267 return (error);
268
269 headfp = fp;
270
271 fdplock(fdp);
272 error = falloc(p, &fp, &tmpfd);
273 fdpunlock(fdp);
274 if (error) {
275 FRELE(headfp, p);
276 return (error);
277 }
278
279 nam = m_get(M_WAIT, MT_SONAME);
280
281 head = headfp->f_data;
282 solock(head);
283
284 persocket = solock_persocket(head);
285
286 if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
287 error = EINVAL;
288 goto out_unlock;
289 }
290 if ((headfp->f_flag & FNONBLOCK) && head->so_qlen == 0) {
291 if (head->so_rcv.sb_state & SS_CANTRCVMORE)
292 error = ECONNABORTED;
293 else
294 error = EWOULDBLOCK;
295 goto out_unlock;
296 }
297 while (head->so_qlen == 0 && head->so_error == 0) {
298 if (head->so_rcv.sb_state & SS_CANTRCVMORE) {
299 head->so_error = ECONNABORTED;
300 break;
301 }
302 error = sosleep_nsec(head, &head->so_timeo, PSOCK | PCATCH,
303 "netcon", INFSLP);
304 if (error)
305 goto out_unlock;
306 }
307 if (head->so_error) {
308 error = head->so_error;
309 head->so_error = 0;
310 goto out_unlock;
311 }
312
313 /*
314 * Do not sleep after we have taken the socket out of the queue.
315 */
316 so = TAILQ_FIRST(&head->so_q);
317
318 if (persocket)
319 solock(so);
320
321 if (soqremque(so, 1) == 0)
322 panic("accept");
323
324 /* Figure out whether the new socket should be non-blocking. */
325 nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK)
326 : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0);
327
328 /* connection has been removed from the listen queue */
329 KNOTE(&head->so_rcv.sb_klist, 0);
330
331 if (persocket)
332 sounlock(head);
333
334 fp->f_type = DTYPE_SOCKET;
335 fp->f_flag = FREAD | FWRITE | nflag;
336 fp->f_ops = &socketops;
337 fp->f_data = so;
338
339 error = soaccept(so, nam);
340
341 if (persocket)
342 sounlock(so);
343 else
344 sounlock(head);
345
346 if (error)
347 goto out;
348
349 if (name != NULL) {
350 error = copyaddrout(p, nam, name, namelen, anamelen);
351 if (error)
352 goto out;
353 }
354
355 fdplock(fdp);
356 fdinsert(fdp, tmpfd, cloexec, fp);
357 fdpunlock(fdp);
358 FRELE(fp, p);
359 *retval = tmpfd;
360
361 m_freem(nam);
362 FRELE(headfp, p);
363
364 return 0;
365
366 out_unlock:
367 sounlock(head);
368 out:
369 fdplock(fdp);
370 fdremove(fdp, tmpfd);
371 fdpunlock(fdp);
372 closef(fp, p);
373
374 m_freem(nam);
375 FRELE(headfp, p);
376
377 return (error);
378 }
379
380 int
381 sys_connect(struct proc *p, void *v, register_t *retval)
382 {
383 struct sys_connect_args /* {
384 syscallarg(int) s;
385 syscallarg(const struct sockaddr *) name;
386 syscallarg(socklen_t) namelen;
387 } */ *uap = v;
388 struct file *fp;
389 struct socket *so;
390 struct mbuf *nam;
391 int error, interrupted = 0;
392
393 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
394 return (error);
395 so = fp->f_data;
396 error = pledge_socket(p, so->so_proto->pr_domain->dom_family,
397 so->so_state);
398 if (error)
399 goto out;
400 if (so->so_state & SS_YP) {
401 error = ENOTSOCK;
402 goto out;
403 }
404 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
405 MT_SONAME);
406 if (error)
407 goto out;
408 #ifdef KTRACE
409 if (KTRPOINT(p, KTR_STRUCT))
410 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
411 #endif
412 solock(so);
413 if (isdnssocket(so)) {
414 error = dns_portcheck(p, so, mtod(nam, void *), nam->m_len);
415 if (error)
416 goto unlock;
417 }
418 if (so->so_state & SS_ISCONNECTING) {
419 error = EALREADY;
420 goto unlock;
421 }
422 error = soconnect(so, nam);
423 if (error)
424 goto bad;
425 if ((fp->f_flag & FNONBLOCK) && (so->so_state & SS_ISCONNECTING)) {
426 error = EINPROGRESS;
427 goto unlock;
428 }
429 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
430 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
431 "netcon2", INFSLP);
432 if (error) {
433 if (error == EINTR || error == ERESTART)
434 interrupted = 1;
435 break;
436 }
437 }
438 if (error == 0) {
439 error = so->so_error;
440 so->so_error = 0;
441 }
442 bad:
443 if (!interrupted)
444 so->so_state &= ~SS_ISCONNECTING;
445 unlock:
446 sounlock(so);
447 m_freem(nam);
448 out:
449 FRELE(fp, p);
450 if (error == ERESTART)
451 error = EINTR;
452 return (error);
453 }
454
455 int
456 sys_socketpair(struct proc *p, void *v, register_t *retval)
457 {
458 struct sys_socketpair_args /* {
459 syscallarg(int) domain;
460 syscallarg(int) type;
461 syscallarg(int) protocol;
462 syscallarg(int *) rsv;
463 } */ *uap = v;
464 struct filedesc *fdp = p->p_fd;
465 struct file *fp1 = NULL, *fp2 = NULL;
466 struct socket *so1, *so2;
467 int type, cloexec, nonblock, fflag, error, sv[2];
468
469 type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
470 cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
471 nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
472 fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
473
474 error = socreate(SCARG(uap, domain), &so1, type, SCARG(uap, protocol));
475 if (error)
476 return (error);
477 error = socreate(SCARG(uap, domain), &so2, type, SCARG(uap, protocol));
478 if (error)
479 goto free1;
480
481 error = soconnect2(so1, so2);
482 if (error != 0)
483 goto free2;
484
485 if ((SCARG(uap, type) & SOCK_TYPE_MASK) == SOCK_DGRAM) {
486 /*
487 * Datagram socket connection is asymmetric.
488 */
489 error = soconnect2(so2, so1);
490 if (error != 0)
491 goto free2;
492 }
493 fdplock(fdp);
494 if ((error = falloc(p, &fp1, &sv[0])) != 0)
495 goto free3;
496 fp1->f_flag = fflag;
497 fp1->f_type = DTYPE_SOCKET;
498 fp1->f_ops = &socketops;
499 fp1->f_data = so1;
500 if ((error = falloc(p, &fp2, &sv[1])) != 0)
501 goto free4;
502 fp2->f_flag = fflag;
503 fp2->f_type = DTYPE_SOCKET;
504 fp2->f_ops = &socketops;
505 fp2->f_data = so2;
506 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
507 if (error == 0) {
508 fdinsert(fdp, sv[0], cloexec, fp1);
509 fdinsert(fdp, sv[1], cloexec, fp2);
510 fdpunlock(fdp);
511 #ifdef KTRACE
512 if (KTRPOINT(p, KTR_STRUCT))
513 ktrfds(p, sv, 2);
514 #endif
515 FRELE(fp1, p);
516 FRELE(fp2, p);
517 return (0);
518 }
519 fdremove(fdp, sv[1]);
520 free4:
521 fdremove(fdp, sv[0]);
522 free3:
523 fdpunlock(fdp);
524
525 if (fp2 != NULL) {
526 closef(fp2, p);
527 so2 = NULL;
528 }
529 if (fp1 != NULL) {
530 closef(fp1, p);
531 so1 = NULL;
532 }
533 free2:
534 if (so2 != NULL)
535 (void)soclose(so2, 0);
536 free1:
537 if (so1 != NULL)
538 (void)soclose(so1, 0);
539 return (error);
540 }
541
542 int
543 sys_sendto(struct proc *p, void *v, register_t *retval)
544 {
545 struct sys_sendto_args /* {
546 syscallarg(int) s;
547 syscallarg(const void *) buf;
548 syscallarg(size_t) len;
549 syscallarg(int) flags;
550 syscallarg(const struct sockaddr *) to;
551 syscallarg(socklen_t) tolen;
552 } */ *uap = v;
553 struct msghdr msg;
554 struct iovec aiov;
555
556 msg.msg_name = (caddr_t)SCARG(uap, to);
557 msg.msg_namelen = SCARG(uap, tolen);
558 msg.msg_iov = &aiov;
559 msg.msg_iovlen = 1;
560 msg.msg_control = NULL;
561 msg.msg_flags = 0;
562 aiov.iov_base = (char *)SCARG(uap, buf);
563 aiov.iov_len = SCARG(uap, len);
564 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
565 }
566
567 int
568 sys_sendmsg(struct proc *p, void *v, register_t *retval)
569 {
570 struct sys_sendmsg_args /* {
571 syscallarg(int) s;
572 syscallarg(const struct msghdr *) msg;
573 syscallarg(int) flags;
574 } */ *uap = v;
575 struct msghdr msg;
576 struct iovec aiov[UIO_SMALLIOV], *iov;
577 int error;
578
579 error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
580 if (error)
581 return (error);
582 #ifdef KTRACE
583 if (KTRPOINT(p, KTR_STRUCT))
584 ktrmsghdr(p, &msg);
585 #endif
586
587 if (msg.msg_iovlen > IOV_MAX)
588 return (EMSGSIZE);
589 if (msg.msg_iovlen > UIO_SMALLIOV)
590 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
591 M_IOV, M_WAITOK);
592 else
593 iov = aiov;
594 if (msg.msg_iovlen &&
595 (error = copyin(msg.msg_iov, iov,
596 msg.msg_iovlen * sizeof (struct iovec))))
597 goto done;
598 #ifdef KTRACE
599 if (msg.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
600 ktriovec(p, iov, msg.msg_iovlen);
601 #endif
602 msg.msg_iov = iov;
603 msg.msg_flags = 0;
604 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
605 done:
606 if (iov != aiov)
607 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
608 return (error);
609 }
610
611 int
612 sys_sendmmsg(struct proc *p, void *v, register_t *retval)
613 {
614 struct sys_sendmmsg_args /* {
615 syscallarg(int) s;
616 syscallarg(struct mmsghdr *) mmsg;
617 syscallarg(unsigned int) vlen;
618 syscallarg(int) flags;
619 } */ *uap = v;
620 struct mmsghdr mmsg, *mmsgp;
621 struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *uiov;
622 size_t iovlen = UIO_SMALLIOV;
623 register_t retsnd;
624 unsigned int vlen, dgrams;
625 int error = 0, flags, s;
626
627 s = SCARG(uap, s);
628 flags = SCARG(uap, flags);
629
630 /* Arbitrarily capped at 1024 datagrams. */
631 vlen = SCARG(uap, vlen);
632 if (vlen > 1024)
633 vlen = 1024;
634
635 mmsgp = SCARG(uap, mmsg);
636 for (dgrams = 0; dgrams < vlen; dgrams++) {
637 error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
638 if (error)
639 break;
640
641 #ifdef KTRACE
642 if (KTRPOINT(p, KTR_STRUCT))
643 ktrmmsghdr(p, &mmsg);
644 #endif
645
646 if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) {
647 error = EMSGSIZE;
648 break;
649 }
650
651 if (mmsg.msg_hdr.msg_iovlen > iovlen) {
652 if (iov != aiov)
653 free(iov, M_IOV, iovlen *
654 sizeof(struct iovec));
655
656 iovlen = mmsg.msg_hdr.msg_iovlen;
657 iov = mallocarray(iovlen, sizeof(struct iovec),
658 M_IOV, M_WAITOK);
659 }
660
661 if (mmsg.msg_hdr.msg_iovlen > 0) {
662 error = copyin(mmsg.msg_hdr.msg_iov, iov,
663 mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec));
664 if (error)
665 break;
666 }
667
668 #ifdef KTRACE
669 if (mmsg.msg_hdr.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
670 ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
671 #endif
672
673 uiov = mmsg.msg_hdr.msg_iov;
674 mmsg.msg_hdr.msg_iov = iov;
675 mmsg.msg_hdr.msg_flags = 0;
676
677 error = sendit(p, s, &mmsg.msg_hdr, flags, &retsnd);
678 if (error)
679 break;
680
681 mmsg.msg_hdr.msg_iov = uiov;
682 mmsg.msg_len = retsnd;
683
684 error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
685 if (error)
686 break;
687 }
688
689 if (iov != aiov)
690 free(iov, M_IOV, sizeof(struct iovec) * iovlen);
691
692 *retval = dgrams;
693
694 if (error && dgrams > 0)
695 error = 0;
696
697 return (error);
698 }
699
700 int
701 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
702 {
703 struct file *fp;
704 struct uio auio;
705 struct iovec *iov;
706 int i;
707 struct mbuf *to, *control;
708 struct socket *so;
709 size_t len;
710 int error;
711 #ifdef KTRACE
712 struct iovec *ktriov = NULL;
713 int iovlen = 0;
714 #endif
715
716 to = NULL;
717
718 if ((error = getsock(p, s, &fp)) != 0)
719 return (error);
720 so = fp->f_data;
721 if (fp->f_flag & FNONBLOCK)
722 flags |= MSG_DONTWAIT;
723
724 error = pledge_sendit(p, mp->msg_name);
725 if (error)
726 goto bad;
727
728 auio.uio_iov = mp->msg_iov;
729 auio.uio_iovcnt = mp->msg_iovlen;
730 auio.uio_segflg = UIO_USERSPACE;
731 auio.uio_rw = UIO_WRITE;
732 auio.uio_procp = p;
733 auio.uio_offset = 0; /* XXX */
734 auio.uio_resid = 0;
735 iov = mp->msg_iov;
736 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
737 /* Don't allow sum > SSIZE_MAX */
738 if (iov->iov_len > SSIZE_MAX ||
739 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
740 error = EINVAL;
741 goto bad;
742 }
743 }
744 if (mp->msg_name) {
745 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
746 MT_SONAME);
747 if (error)
748 goto bad;
749 if (isdnssocket(so)) {
750 error = dns_portcheck(p, so, mtod(to, caddr_t),
751 mp->msg_namelen);
752 if (error)
753 goto bad;
754 }
755 #ifdef KTRACE
756 if (KTRPOINT(p, KTR_STRUCT))
757 ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen);
758 #endif
759 }
760 if (mp->msg_control) {
761 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) {
762 error = EINVAL;
763 goto bad;
764 }
765 error = sockargs(&control, mp->msg_control,
766 mp->msg_controllen, MT_CONTROL);
767 if (error)
768 goto bad;
769 #ifdef KTRACE
770 if (KTRPOINT(p, KTR_STRUCT) && mp->msg_controllen)
771 ktrcmsghdr(p, mtod(control, char *),
772 mp->msg_controllen);
773 #endif
774 } else
775 control = NULL;
776 #ifdef KTRACE
777 if (KTRPOINT(p, KTR_GENIO)) {
778 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
779 M_TEMP, M_WAITOK);
780 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
781
782 memcpy(ktriov, auio.uio_iov, iovlen);
783 }
784 #endif
785 len = auio.uio_resid;
786 error = sosend(so, to, &auio, NULL, control, flags);
787 if (error) {
788 if (auio.uio_resid != len && (error == ERESTART ||
789 error == EINTR || error == EWOULDBLOCK))
790 error = 0;
791 if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
792 KERNEL_LOCK();
793 ptsignal(p, SIGPIPE, STHREAD);
794 KERNEL_UNLOCK();
795 }
796 }
797 if (error == 0) {
798 *retsize = len - auio.uio_resid;
799 mtx_enter(&fp->f_mtx);
800 fp->f_wxfer++;
801 fp->f_wbytes += *retsize;
802 mtx_leave(&fp->f_mtx);
803 }
804 #ifdef KTRACE
805 if (ktriov != NULL) {
806 if (error == 0)
807 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize);
808 free(ktriov, M_TEMP, iovlen);
809 }
810 #endif
811 bad:
812 FRELE(fp, p);
813 m_freem(to);
814 return (error);
815 }
816
817 int
818 sys_recvfrom(struct proc *p, void *v, register_t *retval)
819 {
820 struct sys_recvfrom_args /* {
821 syscallarg(int) s;
822 syscallarg(void *) buf;
823 syscallarg(size_t) len;
824 syscallarg(int) flags;
825 syscallarg(struct sockaddr *) from;
826 syscallarg(socklen_t *) fromlenaddr;
827 } */ *uap = v;
828 struct msghdr msg;
829 struct iovec aiov;
830 int error;
831
832 if (SCARG(uap, fromlenaddr)) {
833 error = copyin(SCARG(uap, fromlenaddr),
834 &msg.msg_namelen, sizeof (msg.msg_namelen));
835 if (error)
836 return (error);
837 } else
838 msg.msg_namelen = 0;
839 msg.msg_name = (caddr_t)SCARG(uap, from);
840 msg.msg_iov = &aiov;
841 msg.msg_iovlen = 1;
842 aiov.iov_base = SCARG(uap, buf);
843 aiov.iov_len = SCARG(uap, len);
844 msg.msg_control = NULL;
845 msg.msg_flags = SCARG(uap, flags);
846 return (recvit(p, SCARG(uap, s), &msg,
847 (caddr_t)SCARG(uap, fromlenaddr), retval));
848 }
849
850 int
851 sys_recvmsg(struct proc *p, void *v, register_t *retval)
852 {
853 struct sys_recvmsg_args /* {
854 syscallarg(int) s;
855 syscallarg(struct msghdr *) msg;
856 syscallarg(int) flags;
857 } */ *uap = v;
858 struct msghdr msg;
859 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
860 int error;
861
862 error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
863 if (error)
864 return (error);
865
866 if (msg.msg_iovlen > IOV_MAX)
867 return (EMSGSIZE);
868 if (msg.msg_iovlen > UIO_SMALLIOV)
869 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
870 M_IOV, M_WAITOK);
871 else
872 iov = aiov;
873 msg.msg_flags = SCARG(uap, flags);
874 if (msg.msg_iovlen > 0) {
875 error = copyin(msg.msg_iov, iov,
876 msg.msg_iovlen * sizeof(struct iovec));
877 if (error)
878 goto done;
879 }
880 uiov = msg.msg_iov;
881 msg.msg_iov = iov;
882 if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
883 msg.msg_iov = uiov;
884 #ifdef KTRACE
885 if (KTRPOINT(p, KTR_STRUCT)) {
886 ktrmsghdr(p, &msg);
887 if (msg.msg_iovlen)
888 ktriovec(p, iov, msg.msg_iovlen);
889 }
890 #endif
891 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
892 }
893 done:
894 if (iov != aiov)
895 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
896 return (error);
897 }
898
899 int
900 sys_recvmmsg(struct proc *p, void *v, register_t *retval)
901 {
902 struct sys_recvmmsg_args /* {
903 syscallarg(int) s;
904 syscallarg(struct mmsghdr *) mmsg;
905 syscallarg(unsigned int) vlen;
906 syscallarg(int) flags;
907 syscallarg(struct timespec *) timeout;
908 } */ *uap = v;
909 struct mmsghdr mmsg, *mmsgp;
910 struct timespec ts, now, *timeout;
911 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov = aiov;
912 size_t iovlen = UIO_SMALLIOV;
913 register_t retrec;
914 unsigned int vlen, dgrams;
915 int error = 0, flags, s;
916
917 timeout = SCARG(uap, timeout);
918 if (timeout != NULL) {
919 error = copyin(timeout, &ts, sizeof(ts));
920 if (error)
921 return (error);
922 #ifdef KTRACE
923 if (KTRPOINT(p, KTR_STRUCT))
924 ktrreltimespec(p, &ts);
925 #endif
926 if (!timespecisvalid(&ts))
927 return (EINVAL);
928
929 getnanotime(&now);
930 timespecadd(&now, &ts, &ts);
931 }
932
933 s = SCARG(uap, s);
934 flags = SCARG(uap, flags);
935
936 /* Arbitrarily capped at 1024 datagrams. */
937 vlen = SCARG(uap, vlen);
938 if (vlen > 1024)
939 vlen = 1024;
940
941 mmsgp = SCARG(uap, mmsg);
942 for (dgrams = 0; dgrams < vlen;) {
943 error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
944 if (error)
945 break;
946
947 if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) {
948 error = EMSGSIZE;
949 break;
950 }
951
952 if (mmsg.msg_hdr.msg_iovlen > iovlen) {
953 if (iov != aiov)
954 free(iov, M_IOV, iovlen *
955 sizeof(struct iovec));
956
957 iovlen = mmsg.msg_hdr.msg_iovlen;
958 iov = mallocarray(iovlen, sizeof(struct iovec),
959 M_IOV, M_WAITOK);
960 }
961
962 if (mmsg.msg_hdr.msg_iovlen > 0) {
963 error = copyin(mmsg.msg_hdr.msg_iov, iov,
964 mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec));
965 if (error)
966 break;
967 }
968
969 uiov = mmsg.msg_hdr.msg_iov;
970 mmsg.msg_hdr.msg_iov = iov;
971 mmsg.msg_hdr.msg_flags = flags & ~MSG_WAITFORONE;
972
973 error = recvit(p, s, &mmsg.msg_hdr, NULL, &retrec);
974 if (error) {
975 if (error == EAGAIN && dgrams > 0)
976 error = 0;
977 break;
978 }
979
980 if (flags & MSG_WAITFORONE)
981 flags |= MSG_DONTWAIT;
982
983 mmsg.msg_hdr.msg_iov = uiov;
984 mmsg.msg_len = retrec;
985 #ifdef KTRACE
986 if (KTRPOINT(p, KTR_STRUCT)) {
987 ktrmmsghdr(p, &mmsg);
988 if (mmsg.msg_hdr.msg_iovlen)
989 ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
990 }
991 #endif
992
993 error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
994 if (error)
995 break;
996
997 dgrams++;
998 if (mmsg.msg_hdr.msg_flags & MSG_OOB)
999 break;
1000
1001 if (timeout != NULL) {
1002 getnanotime(&now);
1003 timespecsub(&now, &ts, &now);
1004 if (now.tv_sec > 0)
1005 break;
1006 }
1007 }
1008
1009 if (iov != aiov)
1010 free(iov, M_IOV, iovlen * sizeof(struct iovec));
1011
1012 *retval = dgrams;
1013
1014 /*
1015 * If we succeeded at least once, return 0, hopefully so->so_error
1016 * will catch it next time.
1017 */
1018 if (error && dgrams > 0) {
1019 struct file *fp;
1020 struct socket *so;
1021
1022 if (getsock(p, s, &fp) == 0) {
1023 so = (struct socket *)fp->f_data;
1024 so->so_error = error;
1025
1026 FRELE(fp, p);
1027 }
1028 error = 0;
1029 }
1030
1031 return (error);
1032 }
1033
1034 int
1035 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
1036 register_t *retsize)
1037 {
1038 struct file *fp;
1039 struct uio auio;
1040 struct iovec *iov;
1041 int i;
1042 size_t len;
1043 int error;
1044 struct mbuf *from = NULL, *control = NULL;
1045 #ifdef KTRACE
1046 struct iovec *ktriov = NULL;
1047 int iovlen = 0, kmsgflags;
1048 #endif
1049
1050 if ((error = getsock(p, s, &fp)) != 0)
1051 return (error);
1052
1053 auio.uio_iov = mp->msg_iov;
1054 auio.uio_iovcnt = mp->msg_iovlen;
1055 auio.uio_segflg = UIO_USERSPACE;
1056 auio.uio_rw = UIO_READ;
1057 auio.uio_procp = p;
1058 auio.uio_offset = 0; /* XXX */
1059 auio.uio_resid = 0;
1060 iov = mp->msg_iov;
1061 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
1062 /* Don't allow sum > SSIZE_MAX */
1063 if (iov->iov_len > SSIZE_MAX ||
1064 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
1065 error = EINVAL;
1066 goto out;
1067 }
1068 }
1069 #ifdef KTRACE
1070 if (KTRPOINT(p, KTR_GENIO)) {
1071 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
1072 M_TEMP, M_WAITOK);
1073 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
1074
1075 memcpy(ktriov, auio.uio_iov, iovlen);
1076 }
1077 kmsgflags = mp->msg_flags;
1078 #endif
1079 len = auio.uio_resid;
1080 if (fp->f_flag & FNONBLOCK)
1081 mp->msg_flags |= MSG_DONTWAIT;
1082 error = soreceive(fp->f_data, &from, &auio, NULL,
1083 mp->msg_control ? &control : NULL,
1084 &mp->msg_flags,
1085 mp->msg_control ? mp->msg_controllen : 0);
1086 if (error) {
1087 if (auio.uio_resid != len && (error == ERESTART ||
1088 error == EINTR || error == EWOULDBLOCK))
1089 error = 0;
1090 }
1091 #ifdef KTRACE
1092 if (ktriov != NULL) {
1093 if (error == 0)
1094 ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid);
1095 free(ktriov, M_TEMP, iovlen);
1096 }
1097 #endif
1098 if (error)
1099 goto out;
1100 *retsize = len - auio.uio_resid;
1101 if (mp->msg_name) {
1102 socklen_t alen;
1103
1104 if (from == NULL)
1105 alen = 0;
1106 else {
1107 alen = from->m_len;
1108 error = copyout(mtod(from, caddr_t), mp->msg_name,
1109 MIN(alen, mp->msg_namelen));
1110 if (error)
1111 goto out;
1112 #ifdef KTRACE
1113 if (KTRPOINT(p, KTR_STRUCT))
1114 ktrsockaddr(p, mtod(from, caddr_t), alen);
1115 #endif
1116 }
1117 mp->msg_namelen = alen;
1118 if (namelenp &&
1119 (error = copyout(&alen, namelenp, sizeof(alen)))) {
1120 goto out;
1121 }
1122 }
1123 if (mp->msg_control) {
1124 len = mp->msg_controllen;
1125 if (len <= 0 || control == NULL)
1126 len = 0;
1127 else {
1128 struct mbuf *m = control;
1129 caddr_t cp = mp->msg_control;
1130
1131 do {
1132 i = m->m_len;
1133 if (len < i) {
1134 mp->msg_flags |= MSG_CTRUNC;
1135 i = len;
1136 }
1137 error = copyout(mtod(m, caddr_t), cp, i);
1138 #ifdef KTRACE
1139 if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) {
1140 /* msg_flags potentially incorrect */
1141 int rmsgflags = mp->msg_flags;
1142
1143 mp->msg_flags = kmsgflags;
1144 ktrcmsghdr(p, mtod(m, char *), i);
1145 mp->msg_flags = rmsgflags;
1146 }
1147 #endif
1148 if (m->m_next)
1149 i = ALIGN(i);
1150 cp += i;
1151 len -= i;
1152 if (error != 0 || len <= 0)
1153 break;
1154 } while ((m = m->m_next) != NULL);
1155 len = cp - (caddr_t)mp->msg_control;
1156 }
1157 mp->msg_controllen = len;
1158 }
1159 if (!error) {
1160 mtx_enter(&fp->f_mtx);
1161 fp->f_rxfer++;
1162 fp->f_rbytes += *retsize;
1163 mtx_leave(&fp->f_mtx);
1164 }
1165 out:
1166 FRELE(fp, p);
1167 m_freem(from);
1168 m_freem(control);
1169 return (error);
1170 }
1171
1172 int
1173 sys_shutdown(struct proc *p, void *v, register_t *retval)
1174 {
1175 struct sys_shutdown_args /* {
1176 syscallarg(int) s;
1177 syscallarg(int) how;
1178 } */ *uap = v;
1179 struct file *fp;
1180 int error;
1181
1182 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1183 return (error);
1184 error = soshutdown(fp->f_data, SCARG(uap, how));
1185 FRELE(fp, p);
1186 return (error);
1187 }
1188
1189 int
1190 sys_setsockopt(struct proc *p, void *v, register_t *retval)
1191 {
1192 struct sys_setsockopt_args /* {
1193 syscallarg(int) s;
1194 syscallarg(int) level;
1195 syscallarg(int) name;
1196 syscallarg(const void *) val;
1197 syscallarg(socklen_t) valsize;
1198 } */ *uap = v;
1199 struct file *fp;
1200 struct mbuf *m = NULL;
1201 struct socket *so;
1202 int error;
1203
1204
1205 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1206 return (error);
1207 error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name));
1208 if (error)
1209 goto bad;
1210 if (SCARG(uap, valsize) > MCLBYTES) {
1211 error = EINVAL;
1212 goto bad;
1213 }
1214 if (SCARG(uap, val)) {
1215 m = m_get(M_WAIT, MT_SOOPTS);
1216 if (SCARG(uap, valsize) > MLEN) {
1217 MCLGET(m, M_DONTWAIT);
1218 if ((m->m_flags & M_EXT) == 0) {
1219 error = ENOBUFS;
1220 goto bad;
1221 }
1222 }
1223 if (m == NULL) {
1224 error = ENOBUFS;
1225 goto bad;
1226 }
1227 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
1228 SCARG(uap, valsize));
1229 if (error) {
1230 goto bad;
1231 }
1232 m->m_len = SCARG(uap, valsize);
1233 }
1234 so = fp->f_data;
1235 solock(so);
1236 error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1237 sounlock(so);
1238 bad:
1239 m_freem(m);
1240 FRELE(fp, p);
1241 return (error);
1242 }
1243
1244 int
1245 sys_getsockopt(struct proc *p, void *v, register_t *retval)
1246 {
1247 struct sys_getsockopt_args /* {
1248 syscallarg(int) s;
1249 syscallarg(int) level;
1250 syscallarg(int) name;
1251 syscallarg(void *) val;
1252 syscallarg(socklen_t *) avalsize;
1253 } */ *uap = v;
1254 struct file *fp;
1255 struct mbuf *m = NULL;
1256 socklen_t valsize;
1257 struct socket *so;
1258 int error;
1259
1260 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1261 return (error);
1262 error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name));
1263 if (error)
1264 goto out;
1265 if (SCARG(uap, val)) {
1266 error = copyin(SCARG(uap, avalsize),
1267 &valsize, sizeof (valsize));
1268 if (error)
1269 goto out;
1270 } else
1271 valsize = 0;
1272 m = m_get(M_WAIT, MT_SOOPTS);
1273 so = fp->f_data;
1274 error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1275 if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
1276 if (valsize > m->m_len)
1277 valsize = m->m_len;
1278 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
1279 if (error == 0)
1280 error = copyout(&valsize,
1281 SCARG(uap, avalsize), sizeof (valsize));
1282 }
1283 m_free(m);
1284 out:
1285 FRELE(fp, p);
1286 return (error);
1287 }
1288
1289 /*
1290 * Get socket name.
1291 */
1292 int
1293 sys_getsockname(struct proc *p, void *v, register_t *retval)
1294 {
1295 struct sys_getsockname_args /* {
1296 syscallarg(int) fdes;
1297 syscallarg(struct sockaddr *) asa;
1298 syscallarg(socklen_t *) alen;
1299 } */ *uap = v;
1300 struct file *fp;
1301 struct socket *so;
1302 struct mbuf *m = NULL;
1303 socklen_t len;
1304 int error;
1305
1306 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1307 return (error);
1308 error = copyin(SCARG(uap, alen), &len, sizeof (len));
1309 if (error)
1310 goto bad;
1311 so = fp->f_data;
1312 if (so->so_state & SS_YP) {
1313 error = ENOTSOCK;
1314 goto bad;
1315 }
1316 error = pledge_socket(p, -1, so->so_state);
1317 if (error)
1318 goto bad;
1319 if (so->so_state & SS_YP) {
1320 error = ENOTSOCK;
1321 goto bad;
1322 }
1323 m = m_getclr(M_WAIT, MT_SONAME);
1324 solock_shared(so);
1325 error = pru_sockaddr(so, m);
1326 sounlock_shared(so);
1327 if (error)
1328 goto bad;
1329 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1330 bad:
1331 FRELE(fp, p);
1332 m_freem(m);
1333 return (error);
1334 }
1335
1336 /*
1337 * Get name of peer for connected socket.
1338 */
1339 int
1340 sys_getpeername(struct proc *p, void *v, register_t *retval)
1341 {
1342 struct sys_getpeername_args /* {
1343 syscallarg(int) fdes;
1344 syscallarg(struct sockaddr *) asa;
1345 syscallarg(socklen_t *) alen;
1346 } */ *uap = v;
1347 struct file *fp;
1348 struct socket *so;
1349 struct mbuf *m = NULL;
1350 socklen_t len;
1351 int error;
1352
1353 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1354 return (error);
1355 so = fp->f_data;
1356 error = pledge_socket(p, -1, so->so_state);
1357 if (error)
1358 goto bad;
1359 if (so->so_state & SS_YP) {
1360 error = ENOTSOCK;
1361 goto bad;
1362 }
1363 if ((so->so_state & SS_ISCONNECTED) == 0) {
1364 error = ENOTCONN;
1365 goto bad;
1366 }
1367 error = copyin(SCARG(uap, alen), &len, sizeof (len));
1368 if (error)
1369 goto bad;
1370 m = m_getclr(M_WAIT, MT_SONAME);
1371 solock_shared(so);
1372 error = pru_peeraddr(so, m);
1373 sounlock_shared(so);
1374 if (error)
1375 goto bad;
1376 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1377 bad:
1378 FRELE(fp, p);
1379 m_freem(m);
1380 return (error);
1381 }
1382
1383 int
1384 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1385 {
1386 struct sockaddr *sa;
1387 struct mbuf *m;
1388 int error;
1389
1390 /*
1391 * We can't allow socket names > UCHAR_MAX in length, since that
1392 * will overflow sa_len. Also, control data more than MCLBYTES in
1393 * length is just too much.
1394 * Memory for sa_len and sa_family must exist.
1395 */
1396 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1397 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1398 return (EINVAL);
1399
1400 /* Allocate an mbuf to hold the arguments. */
1401 m = m_get(M_WAIT, type);
1402 if (buflen > MLEN) {
1403 MCLGET(m, M_WAITOK);
1404 if ((m->m_flags & M_EXT) == 0) {
1405 m_free(m);
1406 return ENOBUFS;
1407 }
1408 }
1409 m->m_len = buflen;
1410 error = copyin(buf, mtod(m, caddr_t), buflen);
1411 if (error) {
1412 (void) m_free(m);
1413 return (error);
1414 }
1415 *mp = m;
1416 if (type == MT_SONAME) {
1417 sa = mtod(m, struct sockaddr *);
1418 sa->sa_len = buflen;
1419 }
1420 return (0);
1421 }
1422
1423 int
1424 getsock(struct proc *p, int fdes, struct file **fpp)
1425 {
1426 struct file *fp;
1427
1428 fp = fd_getfile(p->p_fd, fdes);
1429 if (fp == NULL)
1430 return (EBADF);
1431 if (fp->f_type != DTYPE_SOCKET) {
1432 FRELE(fp, p);
1433 return (ENOTSOCK);
1434 }
1435 *fpp = fp;
1436
1437 return (0);
1438 }
1439
1440 int
1441 sys_setrtable(struct proc *p, void *v, register_t *retval)
1442 {
1443 struct sys_setrtable_args /* {
1444 syscallarg(int) rtableid;
1445 } */ *uap = v;
1446 u_int ps_rtableid = p->p_p->ps_rtableid;
1447 int rtableid, error;
1448
1449 rtableid = SCARG(uap, rtableid);
1450
1451 if (ps_rtableid == rtableid)
1452 return (0);
1453 if (ps_rtableid != 0 && (error = suser(p)) != 0)
1454 return (error);
1455 if (rtableid < 0 || !rtable_exists((u_int)rtableid))
1456 return (EINVAL);
1457
1458 p->p_p->ps_rtableid = (u_int)rtableid;
1459 return (0);
1460 }
1461
1462 int
1463 sys_getrtable(struct proc *p, void *v, register_t *retval)
1464 {
1465 *retval = (int)p->p_p->ps_rtableid;
1466 return (0);
1467 }
1468
1469 int
1470 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
1471 socklen_t buflen, socklen_t *outlen)
1472 {
1473 int error;
1474 socklen_t namelen = name->m_len;
1475
1476 /* SHOULD COPY OUT A CHAIN HERE */
1477 error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
1478 if (error == 0) {
1479 #ifdef KTRACE
1480 if (KTRPOINT(p, KTR_STRUCT))
1481 ktrsockaddr(p, mtod(name, caddr_t), namelen);
1482 #endif
1483 error = copyout(&namelen, outlen, sizeof(*outlen));
1484 }
1485
1486 return (error);
1487 }
1488
1489 #ifndef SMALL_KERNEL
1490 int
1491 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1492 {
1493 struct sockaddr *sa;
1494 struct mbuf *m;
1495
1496 /*
1497 * We can't allow socket names > UCHAR_MAX in length, since that
1498 * will overflow sa_len. Also, control data more than MCLBYTES in
1499 * length is just too much.
1500 * Memory for sa_len and sa_family must exist.
1501 */
1502 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1503 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1504 return (EINVAL);
1505
1506 /* Allocate an mbuf to hold the arguments. */
1507 m = m_get(M_WAIT, type);
1508 if (buflen > MLEN) {
1509 MCLGET(m, M_WAITOK);
1510 if ((m->m_flags & M_EXT) == 0) {
1511 m_free(m);
1512 return ENOBUFS;
1513 }
1514 }
1515 m->m_len = buflen;
1516 bcopy(buf, mtod(m, caddr_t), buflen);
1517 *mp = m;
1518 if (type == MT_SONAME) {
1519 sa = mtod(m, struct sockaddr *);
1520 sa->sa_len = buflen;
1521 }
1522 return (0);
1523 }
1524 #endif /* SMALL_KERNEL */
1525
1526 int
1527 sys_ypconnect(struct proc *p, void *v, register_t *retval)
1528 {
1529 #ifdef SMALL_KERNEL
1530 return EAFNOSUPPORT;
1531 #else
1532 struct sys_ypconnect_args /* {
1533 syscallarg(int) type;
1534 } */ *uap = v;
1535 struct nameidata nid;
1536 struct vattr va;
1537 struct uio uio;
1538 struct iovec iov;
1539 struct filedesc *fdp = p->p_fd;
1540 struct socket *so;
1541 struct file *fp;
1542 struct flock fl;
1543 char *name;
1544 struct mbuf *nam = NULL;
1545 int error, fd = -1;
1546 struct ypbinding {
1547 u_short ypbind_port;
1548 int status;
1549 in_addr_t in;
1550 u_short ypserv_udp_port;
1551 u_short garbage;
1552 u_short ypserv_tcp_port;
1553 } __packed data;
1554 struct sockaddr_in ypsin;
1555
1556 if (!domainname[0] || strchr(domainname, '/'))
1557 return EAFNOSUPPORT;
1558
1559 switch (SCARG(uap, type)) {
1560 case SOCK_STREAM:
1561 case SOCK_DGRAM:
1562 break;
1563 default:
1564 return EAFNOSUPPORT;
1565 }
1566
1567 if (p->p_p->ps_flags & PS_CHROOT)
1568 return EACCES;
1569 name = pool_get(&namei_pool, PR_WAITOK);
1570 snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname);
1571 NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p);
1572 nid.ni_pledge = PLEDGE_RPATH;
1573
1574 KERNEL_LOCK();
1575 error = namei(&nid);
1576 pool_put(&namei_pool, name);
1577 if (error)
1578 goto out;
1579 error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
1580 if (error)
1581 goto verror;
1582 if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) {
1583 error = EFTYPE;
1584 goto verror;
1585 }
1586
1587 /*
1588 * Check that a lock is held on the file (hopefully by ypbind),
1589 * otherwise the file might be old
1590 */
1591 fl.l_start = 0;
1592 fl.l_len = 0;
1593 fl.l_pid = 0;
1594 fl.l_type = F_WRLCK;
1595 fl.l_whence = SEEK_SET;
1596 error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX);
1597 if (error)
1598 goto verror;
1599 if (fl.l_type == F_UNLCK) {
1600 error = EOWNERDEAD;
1601 goto verror;
1602 }
1603
1604 iov.iov_base = &data;
1605 iov.iov_len = sizeof data;
1606 uio.uio_iov = &iov;
1607 uio.uio_iovcnt = 1;
1608 uio.uio_offset = 0;
1609 uio.uio_resid = iov.iov_len;
1610 uio.uio_segflg = UIO_SYSSPACE;
1611 uio.uio_rw = UIO_READ;
1612 uio.uio_procp = p;
1613
1614 error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred);
1615 if (error) {
1616 verror:
1617 if (nid.ni_vp)
1618 vput(nid.ni_vp);
1619 out:
1620 KERNEL_UNLOCK();
1621 return (error);
1622 }
1623 vput(nid.ni_vp);
1624 KERNEL_UNLOCK();
1625
1626 bzero(&ypsin, sizeof ypsin);
1627 ypsin.sin_len = sizeof ypsin;
1628 ypsin.sin_family = AF_INET;
1629 if (SCARG(uap, type) == SOCK_STREAM)
1630 ypsin.sin_port = data.ypserv_tcp_port;
1631 else
1632 ypsin.sin_port = data.ypserv_udp_port;
1633 if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20)
1634 return EPERM;
1635 memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr);
1636
1637 error = socreate(AF_INET, &so, SCARG(uap, type), 0);
1638 if (error)
1639 return (error);
1640
1641 error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME);
1642 if (error) {
1643 soclose(so, MSG_DONTWAIT);
1644 return (error);
1645 }
1646
1647 #ifdef KTRACE
1648 if (KTRPOINT(p, KTR_STRUCT))
1649 ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in));
1650 #endif
1651 solock(so);
1652
1653 /* Secure YP maps require reserved ports */
1654 if (suser(p) == 0)
1655 sotoinpcb(so)->inp_flags |= INP_LOWPORT;
1656
1657 error = soconnect(so, nam);
1658 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
1659 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
1660 "netcon2", INFSLP);
1661 if (error)
1662 break;
1663 }
1664 m_freem(nam);
1665 so->so_state |= SS_YP; /* impose some restrictions */
1666 sounlock(so);
1667 if (error) {
1668 soclose(so, MSG_DONTWAIT);
1669 return (error);
1670 }
1671
1672 fdplock(fdp);
1673 error = falloc(p, &fp, &fd);
1674 if (error) {
1675 fdpunlock(fdp);
1676 soclose(so, MSG_DONTWAIT);
1677 return (error);
1678 }
1679
1680 fp->f_flag = FREAD | FWRITE | FNONBLOCK;
1681 fp->f_type = DTYPE_SOCKET;
1682 fp->f_ops = &socketops;
1683 fp->f_data = so;
1684 fdinsert(fdp, fd, UF_EXCLOSE, fp);
1685 fdpunlock(fdp);
1686 FRELE(fp, p);
1687 *retval = fd;
1688 return (error);
1689 #endif /* SMALL_KERNEL */
1690 }
Cache object: 5e4f6c32e3225d8ff80157b4f682a4a9
|