1 /* $OpenBSD: uipc_syscalls.c,v 1.220 2024/11/05 09:14:19 claudio 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
sys_socket(struct proc * p,void * v,register_t * retval)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
isdnssocket(struct socket * so)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
dns_portcheck(struct proc * p,struct socket * so,void * nam,size_t namelen)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
sys_bind(struct proc * p,void * v,register_t * retval)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_shared(so);
189 error = sobind(so, nam, p);
190 sounlock_shared(so);
191 m_freem(nam);
192 out:
193 FRELE(fp, p);
194 return (error);
195 }
196
197 int
sys_listen(struct proc * p,void * v,register_t * retval)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
sys_accept(struct proc * p,void * v,register_t * retval)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
sys_accept4(struct proc * p,void * v,register_t * retval)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
doaccept(struct proc * p,int sock,struct sockaddr * name,socklen_t * anamelen,int flags,register_t * retval)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 "netacc", 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
sys_connect(struct proc * p,void * v,register_t * retval)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_shared(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 "netcon", 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_shared(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
sys_socketpair(struct proc * p,void * v,register_t * retval)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
sys_sendto(struct proc * p,void * v,register_t * retval)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
sys_sendmsg(struct proc * p,void * v,register_t * retval)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
sys_sendmmsg(struct proc * p,void * v,register_t * retval)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
sendit(struct proc * p,int s,struct msghdr * mp,int flags,register_t * retsize)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 ptsignal(p, SIGPIPE, STHREAD);
793 }
794 if (error == 0) {
795 *retsize = len - auio.uio_resid;
796 mtx_enter(&fp->f_mtx);
797 fp->f_wxfer++;
798 fp->f_wbytes += *retsize;
799 mtx_leave(&fp->f_mtx);
800 }
801 #ifdef KTRACE
802 if (ktriov != NULL) {
803 if (error == 0)
804 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize);
805 free(ktriov, M_TEMP, iovlen);
806 }
807 #endif
808 bad:
809 FRELE(fp, p);
810 m_freem(to);
811 return (error);
812 }
813
814 int
sys_recvfrom(struct proc * p,void * v,register_t * retval)815 sys_recvfrom(struct proc *p, void *v, register_t *retval)
816 {
817 struct sys_recvfrom_args /* {
818 syscallarg(int) s;
819 syscallarg(void *) buf;
820 syscallarg(size_t) len;
821 syscallarg(int) flags;
822 syscallarg(struct sockaddr *) from;
823 syscallarg(socklen_t *) fromlenaddr;
824 } */ *uap = v;
825 struct msghdr msg;
826 struct iovec aiov;
827 int error;
828
829 if (SCARG(uap, fromlenaddr)) {
830 error = copyin(SCARG(uap, fromlenaddr),
831 &msg.msg_namelen, sizeof (msg.msg_namelen));
832 if (error)
833 return (error);
834 } else
835 msg.msg_namelen = 0;
836 msg.msg_name = (caddr_t)SCARG(uap, from);
837 msg.msg_iov = &aiov;
838 msg.msg_iovlen = 1;
839 aiov.iov_base = SCARG(uap, buf);
840 aiov.iov_len = SCARG(uap, len);
841 msg.msg_control = NULL;
842 msg.msg_flags = SCARG(uap, flags);
843 return (recvit(p, SCARG(uap, s), &msg,
844 (caddr_t)SCARG(uap, fromlenaddr), retval));
845 }
846
847 int
sys_recvmsg(struct proc * p,void * v,register_t * retval)848 sys_recvmsg(struct proc *p, void *v, register_t *retval)
849 {
850 struct sys_recvmsg_args /* {
851 syscallarg(int) s;
852 syscallarg(struct msghdr *) msg;
853 syscallarg(int) flags;
854 } */ *uap = v;
855 struct msghdr msg;
856 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
857 int error;
858
859 error = copyin(SCARG(uap, msg), &msg, sizeof (msg));
860 if (error)
861 return (error);
862
863 if (msg.msg_iovlen > IOV_MAX)
864 return (EMSGSIZE);
865 if (msg.msg_iovlen > UIO_SMALLIOV)
866 iov = mallocarray(msg.msg_iovlen, sizeof(struct iovec),
867 M_IOV, M_WAITOK);
868 else
869 iov = aiov;
870 msg.msg_flags = SCARG(uap, flags);
871 if (msg.msg_iovlen > 0) {
872 error = copyin(msg.msg_iov, iov,
873 msg.msg_iovlen * sizeof(struct iovec));
874 if (error)
875 goto done;
876 }
877 uiov = msg.msg_iov;
878 msg.msg_iov = iov;
879 if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) {
880 msg.msg_iov = uiov;
881 #ifdef KTRACE
882 if (KTRPOINT(p, KTR_STRUCT)) {
883 ktrmsghdr(p, &msg);
884 if (msg.msg_iovlen)
885 ktriovec(p, iov, msg.msg_iovlen);
886 }
887 #endif
888 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
889 }
890 done:
891 if (iov != aiov)
892 free(iov, M_IOV, sizeof(struct iovec) * msg.msg_iovlen);
893 return (error);
894 }
895
896 int
sys_recvmmsg(struct proc * p,void * v,register_t * retval)897 sys_recvmmsg(struct proc *p, void *v, register_t *retval)
898 {
899 struct sys_recvmmsg_args /* {
900 syscallarg(int) s;
901 syscallarg(struct mmsghdr *) mmsg;
902 syscallarg(unsigned int) vlen;
903 syscallarg(int) flags;
904 syscallarg(struct timespec *) timeout;
905 } */ *uap = v;
906 struct mmsghdr mmsg, *mmsgp;
907 struct timespec ts, now, *timeout;
908 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov = aiov;
909 size_t iovlen = UIO_SMALLIOV;
910 register_t retrec;
911 unsigned int vlen, dgrams;
912 int error = 0, flags, s;
913
914 timeout = SCARG(uap, timeout);
915 if (timeout != NULL) {
916 error = copyin(timeout, &ts, sizeof(ts));
917 if (error)
918 return (error);
919 #ifdef KTRACE
920 if (KTRPOINT(p, KTR_STRUCT))
921 ktrreltimespec(p, &ts);
922 #endif
923 if (!timespecisvalid(&ts))
924 return (EINVAL);
925
926 getnanotime(&now);
927 timespecadd(&now, &ts, &ts);
928 }
929
930 s = SCARG(uap, s);
931 flags = SCARG(uap, flags);
932
933 /* Arbitrarily capped at 1024 datagrams. */
934 vlen = SCARG(uap, vlen);
935 if (vlen > 1024)
936 vlen = 1024;
937
938 mmsgp = SCARG(uap, mmsg);
939 for (dgrams = 0; dgrams < vlen;) {
940 error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
941 if (error)
942 break;
943
944 if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) {
945 error = EMSGSIZE;
946 break;
947 }
948
949 if (mmsg.msg_hdr.msg_iovlen > iovlen) {
950 if (iov != aiov)
951 free(iov, M_IOV, iovlen *
952 sizeof(struct iovec));
953
954 iovlen = mmsg.msg_hdr.msg_iovlen;
955 iov = mallocarray(iovlen, sizeof(struct iovec),
956 M_IOV, M_WAITOK);
957 }
958
959 if (mmsg.msg_hdr.msg_iovlen > 0) {
960 error = copyin(mmsg.msg_hdr.msg_iov, iov,
961 mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec));
962 if (error)
963 break;
964 }
965
966 uiov = mmsg.msg_hdr.msg_iov;
967 mmsg.msg_hdr.msg_iov = iov;
968 mmsg.msg_hdr.msg_flags = flags & ~MSG_WAITFORONE;
969
970 error = recvit(p, s, &mmsg.msg_hdr, NULL, &retrec);
971 if (error) {
972 if (error == EAGAIN && dgrams > 0)
973 error = 0;
974 break;
975 }
976
977 if (flags & MSG_WAITFORONE)
978 flags |= MSG_DONTWAIT;
979
980 mmsg.msg_hdr.msg_iov = uiov;
981 mmsg.msg_len = retrec;
982 #ifdef KTRACE
983 if (KTRPOINT(p, KTR_STRUCT)) {
984 ktrmmsghdr(p, &mmsg);
985 if (mmsg.msg_hdr.msg_iovlen)
986 ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
987 }
988 #endif
989
990 error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
991 if (error)
992 break;
993
994 dgrams++;
995 if (mmsg.msg_hdr.msg_flags & MSG_OOB)
996 break;
997
998 if (timeout != NULL) {
999 getnanotime(&now);
1000 timespecsub(&now, &ts, &now);
1001 if (now.tv_sec > 0)
1002 break;
1003 }
1004 }
1005
1006 if (iov != aiov)
1007 free(iov, M_IOV, iovlen * sizeof(struct iovec));
1008
1009 *retval = dgrams;
1010
1011 /*
1012 * If we succeeded at least once, return 0, hopefully so->so_error
1013 * will catch it next time.
1014 */
1015 if (error && dgrams > 0) {
1016 struct file *fp;
1017 struct socket *so;
1018
1019 if (getsock(p, s, &fp) == 0) {
1020 so = (struct socket *)fp->f_data;
1021 so->so_error = error;
1022
1023 FRELE(fp, p);
1024 }
1025 error = 0;
1026 }
1027
1028 return (error);
1029 }
1030
1031 int
recvit(struct proc * p,int s,struct msghdr * mp,caddr_t namelenp,register_t * retsize)1032 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
1033 register_t *retsize)
1034 {
1035 struct file *fp;
1036 struct uio auio;
1037 struct iovec *iov;
1038 int i;
1039 size_t len;
1040 int error;
1041 struct mbuf *from = NULL, *control = NULL;
1042 #ifdef KTRACE
1043 struct iovec *ktriov = NULL;
1044 int iovlen = 0, kmsgflags;
1045 #endif
1046
1047 if ((error = getsock(p, s, &fp)) != 0)
1048 return (error);
1049
1050 auio.uio_iov = mp->msg_iov;
1051 auio.uio_iovcnt = mp->msg_iovlen;
1052 auio.uio_segflg = UIO_USERSPACE;
1053 auio.uio_rw = UIO_READ;
1054 auio.uio_procp = p;
1055 auio.uio_offset = 0; /* XXX */
1056 auio.uio_resid = 0;
1057 iov = mp->msg_iov;
1058 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
1059 /* Don't allow sum > SSIZE_MAX */
1060 if (iov->iov_len > SSIZE_MAX ||
1061 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
1062 error = EINVAL;
1063 goto out;
1064 }
1065 }
1066 #ifdef KTRACE
1067 if (KTRPOINT(p, KTR_GENIO)) {
1068 ktriov = mallocarray(auio.uio_iovcnt, sizeof(struct iovec),
1069 M_TEMP, M_WAITOK);
1070 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
1071
1072 memcpy(ktriov, auio.uio_iov, iovlen);
1073 }
1074 kmsgflags = mp->msg_flags;
1075 #endif
1076 len = auio.uio_resid;
1077 if (fp->f_flag & FNONBLOCK)
1078 mp->msg_flags |= MSG_DONTWAIT;
1079 error = soreceive(fp->f_data, &from, &auio, NULL,
1080 mp->msg_control ? &control : NULL,
1081 &mp->msg_flags,
1082 mp->msg_control ? mp->msg_controllen : 0);
1083 if (error) {
1084 if (auio.uio_resid != len && (error == ERESTART ||
1085 error == EINTR || error == EWOULDBLOCK))
1086 error = 0;
1087 }
1088 #ifdef KTRACE
1089 if (ktriov != NULL) {
1090 if (error == 0)
1091 ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid);
1092 free(ktriov, M_TEMP, iovlen);
1093 }
1094 #endif
1095 if (error)
1096 goto out;
1097 *retsize = len - auio.uio_resid;
1098 if (mp->msg_name) {
1099 socklen_t alen;
1100
1101 if (from == NULL)
1102 alen = 0;
1103 else {
1104 alen = from->m_len;
1105 error = copyout(mtod(from, caddr_t), mp->msg_name,
1106 MIN(alen, mp->msg_namelen));
1107 if (error)
1108 goto out;
1109 #ifdef KTRACE
1110 if (KTRPOINT(p, KTR_STRUCT))
1111 ktrsockaddr(p, mtod(from, caddr_t), alen);
1112 #endif
1113 }
1114 mp->msg_namelen = alen;
1115 if (namelenp &&
1116 (error = copyout(&alen, namelenp, sizeof(alen)))) {
1117 goto out;
1118 }
1119 }
1120 if (mp->msg_control) {
1121 len = mp->msg_controllen;
1122 if (len <= 0 || control == NULL)
1123 len = 0;
1124 else {
1125 struct mbuf *m = control;
1126 caddr_t cp = mp->msg_control;
1127
1128 do {
1129 i = m->m_len;
1130 if (len < i) {
1131 mp->msg_flags |= MSG_CTRUNC;
1132 i = len;
1133 }
1134 error = copyout(mtod(m, caddr_t), cp, i);
1135 #ifdef KTRACE
1136 if (KTRPOINT(p, KTR_STRUCT) && error == 0 && i) {
1137 /* msg_flags potentially incorrect */
1138 int rmsgflags = mp->msg_flags;
1139
1140 mp->msg_flags = kmsgflags;
1141 ktrcmsghdr(p, mtod(m, char *), i);
1142 mp->msg_flags = rmsgflags;
1143 }
1144 #endif
1145 if (m->m_next)
1146 i = ALIGN(i);
1147 cp += i;
1148 len -= i;
1149 if (error != 0 || len <= 0)
1150 break;
1151 } while ((m = m->m_next) != NULL);
1152 len = cp - (caddr_t)mp->msg_control;
1153 }
1154 mp->msg_controllen = len;
1155 }
1156 if (!error) {
1157 mtx_enter(&fp->f_mtx);
1158 fp->f_rxfer++;
1159 fp->f_rbytes += *retsize;
1160 mtx_leave(&fp->f_mtx);
1161 }
1162 out:
1163 FRELE(fp, p);
1164 m_freem(from);
1165 m_freem(control);
1166 return (error);
1167 }
1168
1169 int
sys_shutdown(struct proc * p,void * v,register_t * retval)1170 sys_shutdown(struct proc *p, void *v, register_t *retval)
1171 {
1172 struct sys_shutdown_args /* {
1173 syscallarg(int) s;
1174 syscallarg(int) how;
1175 } */ *uap = v;
1176 struct file *fp;
1177 int error;
1178
1179 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1180 return (error);
1181 error = soshutdown(fp->f_data, SCARG(uap, how));
1182 FRELE(fp, p);
1183 return (error);
1184 }
1185
1186 int
sys_setsockopt(struct proc * p,void * v,register_t * retval)1187 sys_setsockopt(struct proc *p, void *v, register_t *retval)
1188 {
1189 struct sys_setsockopt_args /* {
1190 syscallarg(int) s;
1191 syscallarg(int) level;
1192 syscallarg(int) name;
1193 syscallarg(const void *) val;
1194 syscallarg(socklen_t) valsize;
1195 } */ *uap = v;
1196 struct file *fp;
1197 struct mbuf *m = NULL;
1198 struct socket *so;
1199 int error;
1200
1201
1202 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1203 return (error);
1204 error = pledge_sockopt(p, 1, SCARG(uap, level), SCARG(uap, name));
1205 if (error)
1206 goto bad;
1207 if (SCARG(uap, valsize) > MCLBYTES) {
1208 error = EINVAL;
1209 goto bad;
1210 }
1211 if (SCARG(uap, val)) {
1212 m = m_get(M_WAIT, MT_SOOPTS);
1213 if (SCARG(uap, valsize) > MLEN) {
1214 MCLGET(m, M_WAIT);
1215 if ((m->m_flags & M_EXT) == 0) {
1216 error = ENOBUFS;
1217 goto bad;
1218 }
1219 }
1220 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
1221 SCARG(uap, valsize));
1222 if (error) {
1223 goto bad;
1224 }
1225 m->m_len = SCARG(uap, valsize);
1226 }
1227 so = fp->f_data;
1228 error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1229 bad:
1230 m_freem(m);
1231 FRELE(fp, p);
1232 return (error);
1233 }
1234
1235 int
sys_getsockopt(struct proc * p,void * v,register_t * retval)1236 sys_getsockopt(struct proc *p, void *v, register_t *retval)
1237 {
1238 struct sys_getsockopt_args /* {
1239 syscallarg(int) s;
1240 syscallarg(int) level;
1241 syscallarg(int) name;
1242 syscallarg(void *) val;
1243 syscallarg(socklen_t *) avalsize;
1244 } */ *uap = v;
1245 struct file *fp;
1246 struct mbuf *m = NULL;
1247 socklen_t valsize;
1248 struct socket *so;
1249 int error;
1250
1251 if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
1252 return (error);
1253 error = pledge_sockopt(p, 0, SCARG(uap, level), SCARG(uap, name));
1254 if (error)
1255 goto out;
1256 if (SCARG(uap, val)) {
1257 error = copyin(SCARG(uap, avalsize),
1258 &valsize, sizeof (valsize));
1259 if (error)
1260 goto out;
1261 } else
1262 valsize = 0;
1263 m = m_get(M_WAIT, MT_SOOPTS);
1264 so = fp->f_data;
1265 error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
1266 if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
1267 if (valsize > m->m_len)
1268 valsize = m->m_len;
1269 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
1270 if (error == 0)
1271 error = copyout(&valsize,
1272 SCARG(uap, avalsize), sizeof (valsize));
1273 }
1274 m_free(m);
1275 out:
1276 FRELE(fp, p);
1277 return (error);
1278 }
1279
1280 /*
1281 * Get socket name.
1282 */
1283 int
sys_getsockname(struct proc * p,void * v,register_t * retval)1284 sys_getsockname(struct proc *p, void *v, register_t *retval)
1285 {
1286 struct sys_getsockname_args /* {
1287 syscallarg(int) fdes;
1288 syscallarg(struct sockaddr *) asa;
1289 syscallarg(socklen_t *) alen;
1290 } */ *uap = v;
1291 struct file *fp;
1292 struct socket *so;
1293 struct mbuf *m = NULL;
1294 socklen_t len;
1295 int error;
1296
1297 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1298 return (error);
1299 error = copyin(SCARG(uap, alen), &len, sizeof (len));
1300 if (error)
1301 goto bad;
1302 so = fp->f_data;
1303 if (so->so_state & SS_YP) {
1304 error = ENOTSOCK;
1305 goto bad;
1306 }
1307 error = pledge_socket(p, -1, so->so_state);
1308 if (error)
1309 goto bad;
1310 if (so->so_state & SS_YP) {
1311 error = ENOTSOCK;
1312 goto bad;
1313 }
1314 m = m_getclr(M_WAIT, MT_SONAME);
1315 solock_shared(so);
1316 error = pru_sockaddr(so, m);
1317 sounlock_shared(so);
1318 if (error)
1319 goto bad;
1320 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1321 bad:
1322 FRELE(fp, p);
1323 m_freem(m);
1324 return (error);
1325 }
1326
1327 /*
1328 * Get name of peer for connected socket.
1329 */
1330 int
sys_getpeername(struct proc * p,void * v,register_t * retval)1331 sys_getpeername(struct proc *p, void *v, register_t *retval)
1332 {
1333 struct sys_getpeername_args /* {
1334 syscallarg(int) fdes;
1335 syscallarg(struct sockaddr *) asa;
1336 syscallarg(socklen_t *) alen;
1337 } */ *uap = v;
1338 struct file *fp;
1339 struct socket *so;
1340 struct mbuf *m = NULL;
1341 socklen_t len;
1342 int error;
1343
1344 if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
1345 return (error);
1346 so = fp->f_data;
1347 error = pledge_socket(p, -1, so->so_state);
1348 if (error)
1349 goto bad;
1350 if (so->so_state & SS_YP) {
1351 error = ENOTSOCK;
1352 goto bad;
1353 }
1354 if ((so->so_state & SS_ISCONNECTED) == 0) {
1355 error = ENOTCONN;
1356 goto bad;
1357 }
1358 error = copyin(SCARG(uap, alen), &len, sizeof (len));
1359 if (error)
1360 goto bad;
1361 m = m_getclr(M_WAIT, MT_SONAME);
1362 solock_shared(so);
1363 error = pru_peeraddr(so, m);
1364 sounlock_shared(so);
1365 if (error)
1366 goto bad;
1367 error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
1368 bad:
1369 FRELE(fp, p);
1370 m_freem(m);
1371 return (error);
1372 }
1373
1374 int
sockargs(struct mbuf ** mp,const void * buf,size_t buflen,int type)1375 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1376 {
1377 struct sockaddr *sa;
1378 struct mbuf *m;
1379 int error;
1380
1381 /*
1382 * We can't allow socket names > UCHAR_MAX in length, since that
1383 * will overflow sa_len. Also, control data more than MCLBYTES in
1384 * length is just too much.
1385 * Memory for sa_len and sa_family must exist.
1386 */
1387 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1388 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1389 return (EINVAL);
1390
1391 /* Allocate an mbuf to hold the arguments. */
1392 m = m_get(M_WAIT, type);
1393 if (buflen > MLEN) {
1394 MCLGET(m, M_WAITOK);
1395 if ((m->m_flags & M_EXT) == 0) {
1396 m_free(m);
1397 return ENOBUFS;
1398 }
1399 }
1400 m->m_len = buflen;
1401 error = copyin(buf, mtod(m, caddr_t), buflen);
1402 if (error) {
1403 (void) m_free(m);
1404 return (error);
1405 }
1406 *mp = m;
1407 if (type == MT_SONAME) {
1408 sa = mtod(m, struct sockaddr *);
1409 sa->sa_len = buflen;
1410 }
1411 return (0);
1412 }
1413
1414 int
getsock(struct proc * p,int fdes,struct file ** fpp)1415 getsock(struct proc *p, int fdes, struct file **fpp)
1416 {
1417 struct file *fp;
1418
1419 fp = fd_getfile(p->p_fd, fdes);
1420 if (fp == NULL)
1421 return (EBADF);
1422 if (fp->f_type != DTYPE_SOCKET) {
1423 FRELE(fp, p);
1424 return (ENOTSOCK);
1425 }
1426 *fpp = fp;
1427
1428 return (0);
1429 }
1430
1431 int
sys_setrtable(struct proc * p,void * v,register_t * retval)1432 sys_setrtable(struct proc *p, void *v, register_t *retval)
1433 {
1434 struct sys_setrtable_args /* {
1435 syscallarg(int) rtableid;
1436 } */ *uap = v;
1437 u_int ps_rtableid = p->p_p->ps_rtableid;
1438 int rtableid, error;
1439
1440 rtableid = SCARG(uap, rtableid);
1441
1442 if (ps_rtableid == rtableid)
1443 return (0);
1444 if (ps_rtableid != 0 && (error = suser(p)) != 0)
1445 return (error);
1446 if (rtableid < 0 || !rtable_exists((u_int)rtableid))
1447 return (EINVAL);
1448
1449 p->p_p->ps_rtableid = (u_int)rtableid;
1450 return (0);
1451 }
1452
1453 int
sys_getrtable(struct proc * p,void * v,register_t * retval)1454 sys_getrtable(struct proc *p, void *v, register_t *retval)
1455 {
1456 *retval = (int)p->p_p->ps_rtableid;
1457 return (0);
1458 }
1459
1460 int
copyaddrout(struct proc * p,struct mbuf * name,struct sockaddr * sa,socklen_t buflen,socklen_t * outlen)1461 copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
1462 socklen_t buflen, socklen_t *outlen)
1463 {
1464 int error;
1465 socklen_t namelen = name->m_len;
1466
1467 /* SHOULD COPY OUT A CHAIN HERE */
1468 error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
1469 if (error == 0) {
1470 #ifdef KTRACE
1471 if (KTRPOINT(p, KTR_STRUCT))
1472 ktrsockaddr(p, mtod(name, caddr_t), namelen);
1473 #endif
1474 error = copyout(&namelen, outlen, sizeof(*outlen));
1475 }
1476
1477 return (error);
1478 }
1479
1480 #ifndef SMALL_KERNEL
1481 int
ypsockargs(struct mbuf ** mp,const void * buf,size_t buflen,int type)1482 ypsockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1483 {
1484 struct sockaddr *sa;
1485 struct mbuf *m;
1486
1487 /*
1488 * We can't allow socket names > UCHAR_MAX in length, since that
1489 * will overflow sa_len. Also, control data more than MCLBYTES in
1490 * length is just too much.
1491 * Memory for sa_len and sa_family must exist.
1492 */
1493 if ((buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) ||
1494 (type == MT_SONAME && buflen < offsetof(struct sockaddr, sa_data)))
1495 return (EINVAL);
1496
1497 /* Allocate an mbuf to hold the arguments. */
1498 m = m_get(M_WAIT, type);
1499 if (buflen > MLEN) {
1500 MCLGET(m, M_WAITOK);
1501 if ((m->m_flags & M_EXT) == 0) {
1502 m_free(m);
1503 return ENOBUFS;
1504 }
1505 }
1506 m->m_len = buflen;
1507 bcopy(buf, mtod(m, caddr_t), buflen);
1508 *mp = m;
1509 if (type == MT_SONAME) {
1510 sa = mtod(m, struct sockaddr *);
1511 sa->sa_len = buflen;
1512 }
1513 return (0);
1514 }
1515 #endif /* SMALL_KERNEL */
1516
1517 int
sys_ypconnect(struct proc * p,void * v,register_t * retval)1518 sys_ypconnect(struct proc *p, void *v, register_t *retval)
1519 {
1520 #ifdef SMALL_KERNEL
1521 return EAFNOSUPPORT;
1522 #else
1523 struct sys_ypconnect_args /* {
1524 syscallarg(int) type;
1525 } */ *uap = v;
1526 struct nameidata nid;
1527 struct vattr va;
1528 struct uio uio;
1529 struct iovec iov;
1530 struct filedesc *fdp = p->p_fd;
1531 struct socket *so;
1532 struct file *fp;
1533 struct flock fl;
1534 char *name;
1535 struct mbuf *nam = NULL;
1536 int error, fd = -1;
1537 struct ypbinding {
1538 u_short ypbind_port;
1539 int status;
1540 in_addr_t in;
1541 u_short ypserv_udp_port;
1542 u_short garbage;
1543 u_short ypserv_tcp_port;
1544 } __packed data;
1545 struct sockaddr_in ypsin;
1546
1547 if (!domainname[0] || strchr(domainname, '/'))
1548 return EAFNOSUPPORT;
1549
1550 switch (SCARG(uap, type)) {
1551 case SOCK_STREAM:
1552 case SOCK_DGRAM:
1553 break;
1554 default:
1555 return EAFNOSUPPORT;
1556 }
1557
1558 if (p->p_p->ps_flags & PS_CHROOT)
1559 return EACCES;
1560 KERNEL_LOCK();
1561 name = pool_get(&namei_pool, PR_WAITOK);
1562 snprintf(name, MAXPATHLEN, "/var/yp/binding/%s.2", domainname);
1563 NDINIT(&nid, 0, NOFOLLOW|LOCKLEAF|KERNELPATH, UIO_SYSSPACE, name, p);
1564 nid.ni_pledge = PLEDGE_RPATH;
1565
1566 error = namei(&nid);
1567 pool_put(&namei_pool, name);
1568 if (error)
1569 goto out;
1570 error = VOP_GETATTR(nid.ni_vp, &va, p->p_ucred, p);
1571 if (error)
1572 goto verror;
1573 if (nid.ni_vp->v_type != VREG || va.va_size != sizeof data) {
1574 error = EFTYPE;
1575 goto verror;
1576 }
1577
1578 /*
1579 * Check that a lock is held on the file (hopefully by ypbind),
1580 * otherwise the file might be old
1581 */
1582 fl.l_start = 0;
1583 fl.l_len = 0;
1584 fl.l_pid = 0;
1585 fl.l_type = F_WRLCK;
1586 fl.l_whence = SEEK_SET;
1587 error = VOP_ADVLOCK(nid.ni_vp, fdp, F_GETLK, &fl, F_POSIX);
1588 if (error)
1589 goto verror;
1590 if (fl.l_type == F_UNLCK) {
1591 error = EOWNERDEAD;
1592 goto verror;
1593 }
1594
1595 iov.iov_base = &data;
1596 iov.iov_len = sizeof data;
1597 uio.uio_iov = &iov;
1598 uio.uio_iovcnt = 1;
1599 uio.uio_offset = 0;
1600 uio.uio_resid = iov.iov_len;
1601 uio.uio_segflg = UIO_SYSSPACE;
1602 uio.uio_rw = UIO_READ;
1603 uio.uio_procp = p;
1604
1605 error = VOP_READ(nid.ni_vp, &uio, 0, p->p_ucred);
1606 if (error) {
1607 verror:
1608 if (nid.ni_vp)
1609 vput(nid.ni_vp);
1610 out:
1611 KERNEL_UNLOCK();
1612 return (error);
1613 }
1614 vput(nid.ni_vp);
1615 KERNEL_UNLOCK();
1616
1617 bzero(&ypsin, sizeof ypsin);
1618 ypsin.sin_len = sizeof ypsin;
1619 ypsin.sin_family = AF_INET;
1620 if (SCARG(uap, type) == SOCK_STREAM)
1621 ypsin.sin_port = data.ypserv_tcp_port;
1622 else
1623 ypsin.sin_port = data.ypserv_udp_port;
1624 if (ntohs(ypsin.sin_port) >= IPPORT_RESERVED || ntohs(ypsin.sin_port) == 20)
1625 return EPERM;
1626 memcpy(&ypsin.sin_addr.s_addr, &data.in, sizeof ypsin.sin_addr.s_addr);
1627
1628 error = socreate(AF_INET, &so, SCARG(uap, type), 0);
1629 if (error)
1630 return (error);
1631
1632 error = ypsockargs(&nam, &ypsin, sizeof ypsin, MT_SONAME);
1633 if (error) {
1634 soclose(so, MSG_DONTWAIT);
1635 return (error);
1636 }
1637
1638 #ifdef KTRACE
1639 if (KTRPOINT(p, KTR_STRUCT))
1640 ktrsockaddr(p, mtod(nam, caddr_t), sizeof(struct sockaddr_in));
1641 #endif
1642 solock(so);
1643
1644 /* Secure YP maps require reserved ports */
1645 if (suser(p) == 0)
1646 sotoinpcb(so)->inp_flags |= INP_LOWPORT;
1647
1648 error = soconnect(so, nam);
1649 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
1650 error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
1651 "ypcon", INFSLP);
1652 if (error)
1653 break;
1654 }
1655 m_freem(nam);
1656 so->so_state |= SS_YP; /* impose some restrictions */
1657 sounlock(so);
1658 if (error) {
1659 soclose(so, MSG_DONTWAIT);
1660 return (error);
1661 }
1662
1663 fdplock(fdp);
1664 error = falloc(p, &fp, &fd);
1665 if (error) {
1666 fdpunlock(fdp);
1667 soclose(so, MSG_DONTWAIT);
1668 return (error);
1669 }
1670
1671 fp->f_flag = FREAD | FWRITE | FNONBLOCK;
1672 fp->f_type = DTYPE_SOCKET;
1673 fp->f_ops = &socketops;
1674 fp->f_data = so;
1675 fdinsert(fdp, fd, UF_EXCLOSE, fp);
1676 fdpunlock(fdp);
1677 FRELE(fp, p);
1678 *retval = fd;
1679 return (error);
1680 #endif /* SMALL_KERNEL */
1681 }
1682