1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1995 Søren Schmidt
5 * 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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 /* XXX we use functions that might not exist. */
33 #include "opt_compat.h"
34 #include "opt_inet6.h"
35
36 #include <sys/param.h>
37 #include <sys/proc.h>
38 #include <sys/systm.h>
39 #include <sys/sysproto.h>
40 #include <sys/capsicum.h>
41 #include <sys/fcntl.h>
42 #include <sys/file.h>
43 #include <sys/filedesc.h>
44 #include <sys/limits.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/mutex.h>
48 #include <sys/mbuf.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/syscallsubr.h>
52 #include <sys/uio.h>
53 #include <sys/syslog.h>
54 #include <sys/un.h>
55
56 #include <net/if.h>
57 #include <net/vnet.h>
58 #include <netinet/in.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/ip.h>
61 #include <netinet/tcp.h>
62 #ifdef INET6
63 #include <netinet/ip6.h>
64 #include <netinet6/ip6_var.h>
65 #endif
66
67 #ifdef COMPAT_LINUX32
68 #include <machine/../linux32/linux.h>
69 #include <machine/../linux32/linux32_proto.h>
70 #else
71 #include <machine/../linux/linux.h>
72 #include <machine/../linux/linux_proto.h>
73 #endif
74 #include <compat/linux/linux_common.h>
75 #include <compat/linux/linux_file.h>
76 #include <compat/linux/linux_mib.h>
77 #include <compat/linux/linux_socket.h>
78 #include <compat/linux/linux_timer.h>
79 #include <compat/linux/linux_util.h>
80
81 static int linux_sendmsg_common(struct thread *, l_int, struct l_msghdr *,
82 l_uint);
83 static int linux_recvmsg_common(struct thread *, l_int, struct l_msghdr *,
84 l_uint, struct msghdr *);
85 static int linux_set_socket_flags(int, int *);
86
87
88 static int
89 linux_to_bsd_sockopt_level(int level)
90 {
91
92 if (level == LINUX_SOL_SOCKET)
93 return (SOL_SOCKET);
94 /* Remaining values are RFC-defined protocol numbers. */
95 return (level);
96 }
97
98 static int
99 bsd_to_linux_sockopt_level(int level)
100 {
101
102 if (level == SOL_SOCKET)
103 return (LINUX_SOL_SOCKET);
104 return (level);
105 }
106
107 static int
108 linux_to_bsd_ip_sockopt(int opt)
109 {
110
111 switch (opt) {
112 case LINUX_IP_TOS:
113 return (IP_TOS);
114 case LINUX_IP_TTL:
115 return (IP_TTL);
116 case LINUX_IP_OPTIONS:
117 return (IP_OPTIONS);
118 case LINUX_IP_MULTICAST_IF:
119 return (IP_MULTICAST_IF);
120 case LINUX_IP_MULTICAST_TTL:
121 return (IP_MULTICAST_TTL);
122 case LINUX_IP_MULTICAST_LOOP:
123 return (IP_MULTICAST_LOOP);
124 case LINUX_IP_ADD_MEMBERSHIP:
125 return (IP_ADD_MEMBERSHIP);
126 case LINUX_IP_DROP_MEMBERSHIP:
127 return (IP_DROP_MEMBERSHIP);
128 case LINUX_IP_HDRINCL:
129 return (IP_HDRINCL);
130 }
131 return (-1);
132 }
133
134 static int
135 linux_to_bsd_ip6_sockopt(int opt)
136 {
137
138 switch (opt) {
139 case LINUX_IPV6_NEXTHOP:
140 return (IPV6_NEXTHOP);
141 case LINUX_IPV6_UNICAST_HOPS:
142 return (IPV6_UNICAST_HOPS);
143 case LINUX_IPV6_MULTICAST_IF:
144 return (IPV6_MULTICAST_IF);
145 case LINUX_IPV6_MULTICAST_HOPS:
146 return (IPV6_MULTICAST_HOPS);
147 case LINUX_IPV6_MULTICAST_LOOP:
148 return (IPV6_MULTICAST_LOOP);
149 case LINUX_IPV6_ADD_MEMBERSHIP:
150 return (IPV6_JOIN_GROUP);
151 case LINUX_IPV6_DROP_MEMBERSHIP:
152 return (IPV6_LEAVE_GROUP);
153 case LINUX_IPV6_V6ONLY:
154 return (IPV6_V6ONLY);
155 case LINUX_IPV6_DONTFRAG:
156 return (IPV6_DONTFRAG);
157 #if 0
158 case LINUX_IPV6_CHECKSUM:
159 return (IPV6_CHECKSUM);
160 case LINUX_IPV6_RECVPKTINFO:
161 return (IPV6_RECVPKTINFO);
162 case LINUX_IPV6_PKTINFO:
163 return (IPV6_PKTINFO);
164 case LINUX_IPV6_RECVHOPLIMIT:
165 return (IPV6_RECVHOPLIMIT);
166 case LINUX_IPV6_HOPLIMIT:
167 return (IPV6_HOPLIMIT);
168 case LINUX_IPV6_RECVHOPOPTS:
169 return (IPV6_RECVHOPOPTS);
170 case LINUX_IPV6_HOPOPTS:
171 return (IPV6_HOPOPTS);
172 case LINUX_IPV6_RTHDRDSTOPTS:
173 return (IPV6_RTHDRDSTOPTS);
174 case LINUX_IPV6_RECVRTHDR:
175 return (IPV6_RECVRTHDR);
176 case LINUX_IPV6_RTHDR:
177 return (IPV6_RTHDR);
178 case LINUX_IPV6_RECVDSTOPTS:
179 return (IPV6_RECVDSTOPTS);
180 case LINUX_IPV6_DSTOPTS:
181 return (IPV6_DSTOPTS);
182 case LINUX_IPV6_RECVPATHMTU:
183 return (IPV6_RECVPATHMTU);
184 case LINUX_IPV6_PATHMTU:
185 return (IPV6_PATHMTU);
186 #endif
187 }
188 return (-1);
189 }
190
191 static int
192 linux_to_bsd_so_sockopt(int opt)
193 {
194
195 switch (opt) {
196 case LINUX_SO_DEBUG:
197 return (SO_DEBUG);
198 case LINUX_SO_REUSEADDR:
199 return (SO_REUSEADDR);
200 case LINUX_SO_TYPE:
201 return (SO_TYPE);
202 case LINUX_SO_ERROR:
203 return (SO_ERROR);
204 case LINUX_SO_DONTROUTE:
205 return (SO_DONTROUTE);
206 case LINUX_SO_BROADCAST:
207 return (SO_BROADCAST);
208 case LINUX_SO_SNDBUF:
209 case LINUX_SO_SNDBUFFORCE:
210 return (SO_SNDBUF);
211 case LINUX_SO_RCVBUF:
212 case LINUX_SO_RCVBUFFORCE:
213 return (SO_RCVBUF);
214 case LINUX_SO_KEEPALIVE:
215 return (SO_KEEPALIVE);
216 case LINUX_SO_OOBINLINE:
217 return (SO_OOBINLINE);
218 case LINUX_SO_LINGER:
219 return (SO_LINGER);
220 case LINUX_SO_REUSEPORT:
221 return (SO_REUSEPORT_LB);
222 case LINUX_SO_PEERCRED:
223 return (LOCAL_PEERCRED);
224 case LINUX_SO_RCVLOWAT:
225 return (SO_RCVLOWAT);
226 case LINUX_SO_SNDLOWAT:
227 return (SO_SNDLOWAT);
228 case LINUX_SO_RCVTIMEO:
229 return (SO_RCVTIMEO);
230 case LINUX_SO_SNDTIMEO:
231 return (SO_SNDTIMEO);
232 case LINUX_SO_TIMESTAMP:
233 return (SO_TIMESTAMP);
234 case LINUX_SO_ACCEPTCONN:
235 return (SO_ACCEPTCONN);
236 case LINUX_SO_PROTOCOL:
237 return (SO_PROTOCOL);
238 }
239 return (-1);
240 }
241
242 static int
243 linux_to_bsd_tcp_sockopt(int opt)
244 {
245
246 switch (opt) {
247 case LINUX_TCP_NODELAY:
248 return (TCP_NODELAY);
249 case LINUX_TCP_MAXSEG:
250 return (TCP_MAXSEG);
251 case LINUX_TCP_CORK:
252 return (TCP_NOPUSH);
253 case LINUX_TCP_KEEPIDLE:
254 return (TCP_KEEPIDLE);
255 case LINUX_TCP_KEEPINTVL:
256 return (TCP_KEEPINTVL);
257 case LINUX_TCP_KEEPCNT:
258 return (TCP_KEEPCNT);
259 case LINUX_TCP_MD5SIG:
260 return (TCP_MD5SIG);
261 }
262 return (-1);
263 }
264
265 static int
266 linux_to_bsd_msg_flags(int flags)
267 {
268 int ret_flags = 0;
269
270 if (flags & LINUX_MSG_OOB)
271 ret_flags |= MSG_OOB;
272 if (flags & LINUX_MSG_PEEK)
273 ret_flags |= MSG_PEEK;
274 if (flags & LINUX_MSG_DONTROUTE)
275 ret_flags |= MSG_DONTROUTE;
276 if (flags & LINUX_MSG_CTRUNC)
277 ret_flags |= MSG_CTRUNC;
278 if (flags & LINUX_MSG_TRUNC)
279 ret_flags |= MSG_TRUNC;
280 if (flags & LINUX_MSG_DONTWAIT)
281 ret_flags |= MSG_DONTWAIT;
282 if (flags & LINUX_MSG_EOR)
283 ret_flags |= MSG_EOR;
284 if (flags & LINUX_MSG_WAITALL)
285 ret_flags |= MSG_WAITALL;
286 if (flags & LINUX_MSG_NOSIGNAL)
287 ret_flags |= MSG_NOSIGNAL;
288 #if 0 /* not handled */
289 if (flags & LINUX_MSG_PROXY)
290 ;
291 if (flags & LINUX_MSG_FIN)
292 ;
293 if (flags & LINUX_MSG_SYN)
294 ;
295 if (flags & LINUX_MSG_CONFIRM)
296 ;
297 if (flags & LINUX_MSG_RST)
298 ;
299 if (flags & LINUX_MSG_ERRQUEUE)
300 ;
301 #endif
302 return (ret_flags);
303 }
304
305 static int
306 linux_to_bsd_cmsg_type(int cmsg_type)
307 {
308
309 switch (cmsg_type) {
310 case LINUX_SCM_RIGHTS:
311 return (SCM_RIGHTS);
312 case LINUX_SCM_CREDENTIALS:
313 return (SCM_CREDS);
314 }
315 return (-1);
316 }
317
318 static int
319 bsd_to_linux_cmsg_type(int cmsg_type)
320 {
321
322 switch (cmsg_type) {
323 case SCM_RIGHTS:
324 return (LINUX_SCM_RIGHTS);
325 case SCM_CREDS:
326 return (LINUX_SCM_CREDENTIALS);
327 case SCM_TIMESTAMP:
328 return (LINUX_SCM_TIMESTAMP);
329 }
330 return (-1);
331 }
332
333 static int
334 linux_to_bsd_msghdr(struct msghdr *bhdr, const struct l_msghdr *lhdr)
335 {
336 if (lhdr->msg_controllen > INT_MAX)
337 return (ENOBUFS);
338
339 bhdr->msg_name = PTRIN(lhdr->msg_name);
340 bhdr->msg_namelen = lhdr->msg_namelen;
341 bhdr->msg_iov = PTRIN(lhdr->msg_iov);
342 bhdr->msg_iovlen = lhdr->msg_iovlen;
343 bhdr->msg_control = PTRIN(lhdr->msg_control);
344
345 /*
346 * msg_controllen is skipped since BSD and LINUX control messages
347 * are potentially different sizes (e.g. the cred structure used
348 * by SCM_CREDS is different between the two operating system).
349 *
350 * The caller can set it (if necessary) after converting all the
351 * control messages.
352 */
353
354 bhdr->msg_flags = linux_to_bsd_msg_flags(lhdr->msg_flags);
355 return (0);
356 }
357
358 static int
359 bsd_to_linux_msghdr(const struct msghdr *bhdr, struct l_msghdr *lhdr)
360 {
361 lhdr->msg_name = PTROUT(bhdr->msg_name);
362 lhdr->msg_namelen = bhdr->msg_namelen;
363 lhdr->msg_iov = PTROUT(bhdr->msg_iov);
364 lhdr->msg_iovlen = bhdr->msg_iovlen;
365 lhdr->msg_control = PTROUT(bhdr->msg_control);
366
367 /*
368 * msg_controllen is skipped since BSD and LINUX control messages
369 * are potentially different sizes (e.g. the cred structure used
370 * by SCM_CREDS is different between the two operating system).
371 *
372 * The caller can set it (if necessary) after converting all the
373 * control messages.
374 */
375
376 /* msg_flags skipped */
377 return (0);
378 }
379
380 static int
381 linux_set_socket_flags(int lflags, int *flags)
382 {
383
384 if (lflags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
385 return (EINVAL);
386 if (lflags & LINUX_SOCK_NONBLOCK)
387 *flags |= SOCK_NONBLOCK;
388 if (lflags & LINUX_SOCK_CLOEXEC)
389 *flags |= SOCK_CLOEXEC;
390 return (0);
391 }
392
393 static int
394 linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
395 struct mbuf *control, enum uio_seg segflg)
396 {
397 struct sockaddr *to;
398 int error, len;
399
400 if (mp->msg_name != NULL) {
401 len = mp->msg_namelen;
402 error = linux_to_bsd_sockaddr(mp->msg_name, &to, &len);
403 if (error != 0)
404 return (error);
405 mp->msg_name = to;
406 } else
407 to = NULL;
408
409 error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control,
410 segflg);
411
412 if (to)
413 free(to, M_SONAME);
414 return (error);
415 }
416
417 /* Return 0 if IP_HDRINCL is set for the given socket. */
418 static int
419 linux_check_hdrincl(struct thread *td, int s)
420 {
421 int error, optval;
422 socklen_t size_val;
423
424 size_val = sizeof(optval);
425 error = kern_getsockopt(td, s, IPPROTO_IP, IP_HDRINCL,
426 &optval, UIO_SYSSPACE, &size_val);
427 if (error != 0)
428 return (error);
429
430 return (optval == 0);
431 }
432
433 /*
434 * Updated sendto() when IP_HDRINCL is set:
435 * tweak endian-dependent fields in the IP packet.
436 */
437 static int
438 linux_sendto_hdrincl(struct thread *td, struct linux_sendto_args *linux_args)
439 {
440 /*
441 * linux_ip_copysize defines how many bytes we should copy
442 * from the beginning of the IP packet before we customize it for BSD.
443 * It should include all the fields we modify (ip_len and ip_off).
444 */
445 #define linux_ip_copysize 8
446
447 struct ip *packet;
448 struct msghdr msg;
449 struct iovec aiov[1];
450 int error;
451
452 /* Check that the packet isn't too big or too small. */
453 if (linux_args->len < linux_ip_copysize ||
454 linux_args->len > IP_MAXPACKET)
455 return (EINVAL);
456
457 packet = (struct ip *)malloc(linux_args->len, M_LINUX, M_WAITOK);
458
459 /* Make kernel copy of the packet to be sent */
460 if ((error = copyin(PTRIN(linux_args->msg), packet,
461 linux_args->len)))
462 goto goout;
463
464 /* Convert fields from Linux to BSD raw IP socket format */
465 packet->ip_len = linux_args->len;
466 packet->ip_off = ntohs(packet->ip_off);
467
468 /* Prepare the msghdr and iovec structures describing the new packet */
469 msg.msg_name = PTRIN(linux_args->to);
470 msg.msg_namelen = linux_args->tolen;
471 msg.msg_iov = aiov;
472 msg.msg_iovlen = 1;
473 msg.msg_control = NULL;
474 msg.msg_flags = 0;
475 aiov[0].iov_base = (char *)packet;
476 aiov[0].iov_len = linux_args->len;
477 error = linux_sendit(td, linux_args->s, &msg, linux_args->flags,
478 NULL, UIO_SYSSPACE);
479 goout:
480 free(packet, M_LINUX);
481 return (error);
482 }
483
484 int
485 linux_socket(struct thread *td, struct linux_socket_args *args)
486 {
487 int domain, retval_socket, type;
488
489 type = args->type & LINUX_SOCK_TYPE_MASK;
490 if (type < 0 || type > LINUX_SOCK_MAX)
491 return (EINVAL);
492 retval_socket = linux_set_socket_flags(args->type & ~LINUX_SOCK_TYPE_MASK,
493 &type);
494 if (retval_socket != 0)
495 return (retval_socket);
496 domain = linux_to_bsd_domain(args->domain);
497 if (domain == -1)
498 return (EAFNOSUPPORT);
499
500 retval_socket = kern_socket(td, domain, type, args->protocol);
501 if (retval_socket)
502 return (retval_socket);
503
504 if (type == SOCK_RAW
505 && (args->protocol == IPPROTO_RAW || args->protocol == 0)
506 && domain == PF_INET) {
507 /* It's a raw IP socket: set the IP_HDRINCL option. */
508 int hdrincl;
509
510 hdrincl = 1;
511 /* We ignore any error returned by kern_setsockopt() */
512 kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL,
513 &hdrincl, UIO_SYSSPACE, sizeof(hdrincl));
514 }
515 #ifdef INET6
516 /*
517 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by default
518 * and some apps depend on this. So, set V6ONLY to 0 for Linux apps.
519 * For simplicity we do this unconditionally of the net.inet6.ip6.v6only
520 * sysctl value.
521 */
522 if (domain == PF_INET6) {
523 int v6only;
524
525 v6only = 0;
526 /* We ignore any error returned by setsockopt() */
527 kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY,
528 &v6only, UIO_SYSSPACE, sizeof(v6only));
529 }
530 #endif
531
532 return (retval_socket);
533 }
534
535 int
536 linux_bind(struct thread *td, struct linux_bind_args *args)
537 {
538 struct sockaddr *sa;
539 int error;
540
541 error = linux_to_bsd_sockaddr(PTRIN(args->name), &sa,
542 &args->namelen);
543 if (error != 0)
544 return (error);
545
546 error = kern_bindat(td, AT_FDCWD, args->s, sa);
547 free(sa, M_SONAME);
548
549 /* XXX */
550 if (error == EADDRNOTAVAIL && args->namelen != sizeof(struct sockaddr_in))
551 return (EINVAL);
552 return (error);
553 }
554
555 int
556 linux_connect(struct thread *td, struct linux_connect_args *args)
557 {
558 struct socket *so;
559 struct sockaddr *sa;
560 struct file *fp;
561 u_int fflag;
562 int error;
563
564 error = linux_to_bsd_sockaddr(PTRIN(args->name), &sa,
565 &args->namelen);
566 if (error != 0)
567 return (error);
568
569 error = kern_connectat(td, AT_FDCWD, args->s, sa);
570 free(sa, M_SONAME);
571 if (error != EISCONN)
572 return (error);
573
574 /*
575 * Linux doesn't return EISCONN the first time it occurs,
576 * when on a non-blocking socket. Instead it returns the
577 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
578 */
579 error = getsock_cap(td, args->s, &cap_connect_rights,
580 &fp, &fflag, NULL);
581 if (error != 0)
582 return (error);
583
584 error = EISCONN;
585 so = fp->f_data;
586 if (fflag & FNONBLOCK) {
587 SOCK_LOCK(so);
588 if (so->so_emuldata == 0)
589 error = so->so_error;
590 so->so_emuldata = (void *)1;
591 SOCK_UNLOCK(so);
592 }
593 fdrop(fp, td);
594
595 return (error);
596 }
597
598 int
599 linux_listen(struct thread *td, struct linux_listen_args *args)
600 {
601
602 return (kern_listen(td, args->s, args->backlog));
603 }
604
605 static int
606 linux_accept_common(struct thread *td, int s, l_uintptr_t addr,
607 l_uintptr_t namelen, int flags)
608 {
609 struct l_sockaddr *lsa;
610 struct sockaddr *sa;
611 struct file *fp, *fp1;
612 int bflags, len;
613 struct socket *so;
614 int error, error1;
615
616 bflags = 0;
617 fp = NULL;
618 sa = NULL;
619
620 error = linux_set_socket_flags(flags, &bflags);
621 if (error != 0)
622 return (error);
623
624 if (PTRIN(addr) == NULL) {
625 len = 0;
626 error = kern_accept4(td, s, NULL, NULL, bflags, NULL);
627 } else {
628 error = copyin(PTRIN(namelen), &len, sizeof(len));
629 if (error != 0)
630 return (error);
631 if (len < 0)
632 return (EINVAL);
633 error = kern_accept4(td, s, &sa, &len, bflags, &fp);
634 }
635
636 /*
637 * Translate errno values into ones used by Linux.
638 */
639 if (error != 0) {
640 /*
641 * XXX. This is wrong, different sockaddr structures
642 * have different sizes.
643 */
644 switch (error) {
645 case EFAULT:
646 if (namelen != sizeof(struct sockaddr_in))
647 error = EINVAL;
648 break;
649 case EINVAL:
650 error1 = getsock_cap(td, s, &cap_accept_rights, &fp1, NULL, NULL);
651 if (error1 != 0) {
652 error = error1;
653 break;
654 }
655 so = fp1->f_data;
656 if (so->so_type == SOCK_DGRAM)
657 error = EOPNOTSUPP;
658 fdrop(fp1, td);
659 break;
660 }
661 return (error);
662 }
663
664 if (len != 0) {
665 error = bsd_to_linux_sockaddr(sa, &lsa, len);
666 if (error == 0)
667 error = copyout(lsa, PTRIN(addr), len);
668 free(lsa, M_SONAME);
669
670 /*
671 * XXX: We should also copyout the len, shouldn't we?
672 */
673
674 if (error != 0) {
675 fdclose(td, fp, td->td_retval[0]);
676 td->td_retval[0] = 0;
677 }
678 }
679 if (fp != NULL)
680 fdrop(fp, td);
681 free(sa, M_SONAME);
682 return (error);
683 }
684
685 int
686 linux_accept(struct thread *td, struct linux_accept_args *args)
687 {
688
689 return (linux_accept_common(td, args->s, args->addr,
690 args->namelen, 0));
691 }
692
693 int
694 linux_accept4(struct thread *td, struct linux_accept4_args *args)
695 {
696
697 return (linux_accept_common(td, args->s, args->addr,
698 args->namelen, args->flags));
699 }
700
701 int
702 linux_getsockname(struct thread *td, struct linux_getsockname_args *args)
703 {
704 struct l_sockaddr *lsa;
705 struct sockaddr *sa;
706 int len, error;
707
708 error = copyin(PTRIN(args->namelen), &len, sizeof(len));
709 if (error != 0)
710 return (error);
711
712 error = kern_getsockname(td, args->s, &sa, &len);
713 if (error != 0)
714 return (error);
715
716 if (len != 0) {
717 error = bsd_to_linux_sockaddr(sa, &lsa, len);
718 if (error == 0)
719 error = copyout(lsa, PTRIN(args->addr),
720 len);
721 free(lsa, M_SONAME);
722 }
723
724 free(sa, M_SONAME);
725 if (error == 0)
726 error = copyout(&len, PTRIN(args->namelen), sizeof(len));
727 return (error);
728 }
729
730 int
731 linux_getpeername(struct thread *td, struct linux_getpeername_args *args)
732 {
733 struct l_sockaddr *lsa;
734 struct sockaddr *sa;
735 int len, error;
736
737 error = copyin(PTRIN(args->namelen), &len, sizeof(len));
738 if (error != 0)
739 return (error);
740 if (len < 0)
741 return (EINVAL);
742
743 error = kern_getpeername(td, args->s, &sa, &len);
744 if (error != 0)
745 return (error);
746
747 if (len != 0) {
748 error = bsd_to_linux_sockaddr(sa, &lsa, len);
749 if (error == 0)
750 error = copyout(lsa, PTRIN(args->addr),
751 len);
752 free(lsa, M_SONAME);
753 }
754
755 free(sa, M_SONAME);
756 if (error == 0)
757 error = copyout(&len, PTRIN(args->namelen), sizeof(len));
758 return (error);
759 }
760
761 int
762 linux_socketpair(struct thread *td, struct linux_socketpair_args *args)
763 {
764 struct socketpair_args /* {
765 int domain;
766 int type;
767 int protocol;
768 int *rsv;
769 } */ bsd_args;
770 int error;
771
772 bsd_args.domain = linux_to_bsd_domain(args->domain);
773 if (bsd_args.domain != PF_LOCAL)
774 return (EAFNOSUPPORT);
775 bsd_args.type = args->type & LINUX_SOCK_TYPE_MASK;
776 if (bsd_args.type < 0 || bsd_args.type > LINUX_SOCK_MAX)
777 return (EINVAL);
778 error = linux_set_socket_flags(args->type & ~LINUX_SOCK_TYPE_MASK,
779 &bsd_args.type);
780 if (error != 0)
781 return (error);
782 if (args->protocol != 0 && args->protocol != PF_UNIX)
783
784 /*
785 * Use of PF_UNIX as protocol argument is not right,
786 * but Linux does it.
787 * Do not map PF_UNIX as its Linux value is identical
788 * to FreeBSD one.
789 */
790 return (EPROTONOSUPPORT);
791 else
792 bsd_args.protocol = 0;
793 bsd_args.rsv = (int *)PTRIN(args->rsv);
794 return (sys_socketpair(td, &bsd_args));
795 }
796
797 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
798 struct linux_send_args {
799 register_t s;
800 register_t msg;
801 register_t len;
802 register_t flags;
803 };
804
805 static int
806 linux_send(struct thread *td, struct linux_send_args *args)
807 {
808 struct sendto_args /* {
809 int s;
810 caddr_t buf;
811 int len;
812 int flags;
813 caddr_t to;
814 int tolen;
815 } */ bsd_args;
816 struct file *fp;
817 int error, fflag;
818
819 bsd_args.s = args->s;
820 bsd_args.buf = (caddr_t)PTRIN(args->msg);
821 bsd_args.len = args->len;
822 bsd_args.flags = args->flags;
823 bsd_args.to = NULL;
824 bsd_args.tolen = 0;
825 error = sys_sendto(td, &bsd_args);
826 if (error == ENOTCONN) {
827 /*
828 * Linux doesn't return ENOTCONN for non-blocking sockets.
829 * Instead it returns the EAGAIN.
830 */
831 error = getsock_cap(td, args->s, &cap_send_rights, &fp,
832 &fflag, NULL);
833 if (error == 0) {
834 if (fflag & FNONBLOCK)
835 error = EAGAIN;
836 fdrop(fp, td);
837 }
838 }
839 return (error);
840 }
841
842 struct linux_recv_args {
843 register_t s;
844 register_t msg;
845 register_t len;
846 register_t flags;
847 };
848
849 static int
850 linux_recv(struct thread *td, struct linux_recv_args *args)
851 {
852 struct recvfrom_args /* {
853 int s;
854 caddr_t buf;
855 int len;
856 int flags;
857 struct sockaddr *from;
858 socklen_t fromlenaddr;
859 } */ bsd_args;
860
861 bsd_args.s = args->s;
862 bsd_args.buf = (caddr_t)PTRIN(args->msg);
863 bsd_args.len = args->len;
864 bsd_args.flags = linux_to_bsd_msg_flags(args->flags);
865 bsd_args.from = NULL;
866 bsd_args.fromlenaddr = 0;
867 return (sys_recvfrom(td, &bsd_args));
868 }
869 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
870
871 int
872 linux_sendto(struct thread *td, struct linux_sendto_args *args)
873 {
874 struct msghdr msg;
875 struct iovec aiov;
876
877 if (linux_check_hdrincl(td, args->s) == 0)
878 /* IP_HDRINCL set, tweak the packet before sending */
879 return (linux_sendto_hdrincl(td, args));
880
881 msg.msg_name = PTRIN(args->to);
882 msg.msg_namelen = args->tolen;
883 msg.msg_iov = &aiov;
884 msg.msg_iovlen = 1;
885 msg.msg_control = NULL;
886 msg.msg_flags = 0;
887 aiov.iov_base = PTRIN(args->msg);
888 aiov.iov_len = args->len;
889 return (linux_sendit(td, args->s, &msg, args->flags, NULL,
890 UIO_USERSPACE));
891 }
892
893 int
894 linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
895 {
896 struct l_sockaddr *lsa;
897 struct sockaddr *sa;
898 struct msghdr msg;
899 struct iovec aiov;
900 int error, fromlen;
901
902 if (PTRIN(args->fromlen) != NULL) {
903 error = copyin(PTRIN(args->fromlen), &fromlen,
904 sizeof(fromlen));
905 if (error != 0)
906 return (error);
907 if (fromlen < 0)
908 return (EINVAL);
909 sa = malloc(fromlen, M_SONAME, M_WAITOK);
910 } else {
911 fromlen = 0;
912 sa = NULL;
913 }
914
915 msg.msg_name = sa;
916 msg.msg_namelen = fromlen;
917 msg.msg_iov = &aiov;
918 msg.msg_iovlen = 1;
919 aiov.iov_base = PTRIN(args->buf);
920 aiov.iov_len = args->len;
921 msg.msg_control = 0;
922 msg.msg_flags = linux_to_bsd_msg_flags(args->flags);
923
924 error = kern_recvit(td, args->s, &msg, UIO_SYSSPACE, NULL);
925 if (error != 0)
926 goto out;
927
928 if (PTRIN(args->from) != NULL) {
929 error = bsd_to_linux_sockaddr(sa, &lsa, msg.msg_namelen);
930 if (error == 0)
931 error = copyout(lsa, PTRIN(args->from),
932 msg.msg_namelen);
933 free(lsa, M_SONAME);
934 }
935
936 if (error == 0 && PTRIN(args->fromlen) != NULL)
937 error = copyout(&msg.msg_namelen, PTRIN(args->fromlen),
938 sizeof(msg.msg_namelen));
939 out:
940 free(sa, M_SONAME);
941 return (error);
942 }
943
944 static int
945 linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
946 l_uint flags)
947 {
948 struct cmsghdr *cmsg;
949 struct mbuf *control;
950 struct msghdr msg;
951 struct l_cmsghdr linux_cmsg;
952 struct l_cmsghdr *ptr_cmsg;
953 struct l_msghdr linux_msghdr;
954 struct iovec *iov;
955 socklen_t datalen;
956 struct sockaddr *sa;
957 struct socket *so;
958 sa_family_t sa_family;
959 struct file *fp;
960 void *data;
961 l_size_t len;
962 l_size_t clen;
963 int error, fflag;
964
965 error = copyin(msghdr, &linux_msghdr, sizeof(linux_msghdr));
966 if (error != 0)
967 return (error);
968
969 /*
970 * Some Linux applications (ping) define a non-NULL control data
971 * pointer, but a msg_controllen of 0, which is not allowed in the
972 * FreeBSD system call interface. NULL the msg_control pointer in
973 * order to handle this case. This should be checked, but allows the
974 * Linux ping to work.
975 */
976 if (PTRIN(linux_msghdr.msg_control) != NULL &&
977 linux_msghdr.msg_controllen == 0)
978 linux_msghdr.msg_control = PTROUT(NULL);
979
980 error = linux_to_bsd_msghdr(&msg, &linux_msghdr);
981 if (error != 0)
982 return (error);
983
984 #ifdef COMPAT_LINUX32
985 error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
986 &iov, EMSGSIZE);
987 #else
988 error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
989 #endif
990 if (error != 0)
991 return (error);
992
993 control = NULL;
994
995 error = kern_getsockname(td, s, &sa, &datalen);
996 if (error != 0)
997 goto bad;
998 sa_family = sa->sa_family;
999 free(sa, M_SONAME);
1000
1001 if (flags & LINUX_MSG_OOB) {
1002 error = EOPNOTSUPP;
1003 if (sa_family == AF_UNIX)
1004 goto bad;
1005
1006 error = getsock_cap(td, s, &cap_send_rights, &fp,
1007 &fflag, NULL);
1008 if (error != 0)
1009 goto bad;
1010 so = fp->f_data;
1011 if (so->so_type != SOCK_STREAM)
1012 error = EOPNOTSUPP;
1013 fdrop(fp, td);
1014 if (error != 0)
1015 goto bad;
1016 }
1017
1018 if (linux_msghdr.msg_controllen >= sizeof(struct l_cmsghdr)) {
1019
1020 error = ENOBUFS;
1021 control = m_get(M_WAITOK, MT_CONTROL);
1022 MCLGET(control, M_WAITOK);
1023 data = mtod(control, void *);
1024 datalen = 0;
1025
1026 ptr_cmsg = PTRIN(linux_msghdr.msg_control);
1027 clen = linux_msghdr.msg_controllen;
1028 do {
1029 error = copyin(ptr_cmsg, &linux_cmsg,
1030 sizeof(struct l_cmsghdr));
1031 if (error != 0)
1032 goto bad;
1033
1034 error = EINVAL;
1035 if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr) ||
1036 linux_cmsg.cmsg_len > clen)
1037 goto bad;
1038
1039 if (datalen + CMSG_HDRSZ > MCLBYTES)
1040 goto bad;
1041
1042 /*
1043 * Now we support only SCM_RIGHTS and SCM_CRED,
1044 * so return EINVAL in any other cmsg_type
1045 */
1046 cmsg = data;
1047 cmsg->cmsg_type =
1048 linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
1049 cmsg->cmsg_level =
1050 linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
1051 if (cmsg->cmsg_type == -1
1052 || cmsg->cmsg_level != SOL_SOCKET) {
1053 linux_msg(curthread,
1054 "unsupported sendmsg cmsg level %d type %d",
1055 linux_cmsg.cmsg_level, linux_cmsg.cmsg_type);
1056 goto bad;
1057 }
1058
1059 /*
1060 * Some applications (e.g. pulseaudio) attempt to
1061 * send ancillary data even if the underlying protocol
1062 * doesn't support it which is not allowed in the
1063 * FreeBSD system call interface.
1064 */
1065 if (sa_family != AF_UNIX)
1066 goto next;
1067
1068 if (cmsg->cmsg_type == SCM_CREDS) {
1069 len = sizeof(struct cmsgcred);
1070 if (datalen + CMSG_SPACE(len) > MCLBYTES)
1071 goto bad;
1072
1073 /*
1074 * The lower levels will fill in the structure
1075 */
1076 memset(CMSG_DATA(data), 0, len);
1077 } else {
1078 len = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
1079 if (datalen + CMSG_SPACE(len) < datalen ||
1080 datalen + CMSG_SPACE(len) > MCLBYTES)
1081 goto bad;
1082
1083 error = copyin(LINUX_CMSG_DATA(ptr_cmsg),
1084 CMSG_DATA(data), len);
1085 if (error != 0)
1086 goto bad;
1087 }
1088
1089 cmsg->cmsg_len = CMSG_LEN(len);
1090 data = (char *)data + CMSG_SPACE(len);
1091 datalen += CMSG_SPACE(len);
1092
1093 next:
1094 if (clen <= LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len))
1095 break;
1096
1097 clen -= LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len);
1098 ptr_cmsg = (struct l_cmsghdr *)((char *)ptr_cmsg +
1099 LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len));
1100 } while(clen >= sizeof(struct l_cmsghdr));
1101
1102 control->m_len = datalen;
1103 if (datalen == 0) {
1104 m_freem(control);
1105 control = NULL;
1106 }
1107 }
1108
1109 msg.msg_iov = iov;
1110 msg.msg_flags = 0;
1111 error = linux_sendit(td, s, &msg, flags, control, UIO_USERSPACE);
1112 control = NULL;
1113
1114 bad:
1115 m_freem(control);
1116 free(iov, M_IOV);
1117 return (error);
1118 }
1119
1120 int
1121 linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
1122 {
1123
1124 return (linux_sendmsg_common(td, args->s, PTRIN(args->msg),
1125 args->flags));
1126 }
1127
1128 int
1129 linux_sendmmsg(struct thread *td, struct linux_sendmmsg_args *args)
1130 {
1131 struct l_mmsghdr *msg;
1132 l_uint retval;
1133 int error, datagrams;
1134
1135 if (args->vlen > UIO_MAXIOV)
1136 args->vlen = UIO_MAXIOV;
1137
1138 msg = PTRIN(args->msg);
1139 datagrams = 0;
1140 while (datagrams < args->vlen) {
1141 error = linux_sendmsg_common(td, args->s, &msg->msg_hdr,
1142 args->flags);
1143 if (error != 0)
1144 break;
1145
1146 retval = td->td_retval[0];
1147 error = copyout(&retval, &msg->msg_len, sizeof(msg->msg_len));
1148 if (error != 0)
1149 break;
1150 ++msg;
1151 ++datagrams;
1152 }
1153 if (error == 0)
1154 td->td_retval[0] = datagrams;
1155 return (error);
1156 }
1157
1158 static int
1159 linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
1160 l_uint flags, struct msghdr *msg)
1161 {
1162 struct cmsghdr *cm;
1163 struct cmsgcred *cmcred;
1164 struct l_cmsghdr *linux_cmsg = NULL;
1165 struct l_ucred linux_ucred;
1166 socklen_t datalen, maxlen, outlen;
1167 struct l_msghdr linux_msghdr;
1168 struct iovec *iov, *uiov;
1169 struct mbuf *control = NULL;
1170 struct mbuf **controlp;
1171 struct timeval *ftmvl;
1172 struct l_sockaddr *lsa;
1173 struct sockaddr *sa;
1174 l_timeval ltmvl;
1175 caddr_t outbuf;
1176 void *data;
1177 int error, i, fd, fds, *fdp;
1178
1179 error = copyin(msghdr, &linux_msghdr, sizeof(linux_msghdr));
1180 if (error != 0)
1181 return (error);
1182
1183 error = linux_to_bsd_msghdr(msg, &linux_msghdr);
1184 if (error != 0)
1185 return (error);
1186
1187 #ifdef COMPAT_LINUX32
1188 error = linux32_copyiniov(PTRIN(msg->msg_iov), msg->msg_iovlen,
1189 &iov, EMSGSIZE);
1190 #else
1191 error = copyiniov(msg->msg_iov, msg->msg_iovlen, &iov, EMSGSIZE);
1192 #endif
1193 if (error != 0)
1194 return (error);
1195
1196 if (msg->msg_name != NULL && msg->msg_namelen > 0) {
1197 msg->msg_namelen = min(msg->msg_namelen, SOCK_MAXADDRLEN);
1198 sa = malloc(msg->msg_namelen, M_SONAME, M_WAITOK);
1199 msg->msg_name = sa;
1200 } else {
1201 sa = NULL;
1202 msg->msg_name = NULL;
1203 }
1204
1205 uiov = msg->msg_iov;
1206 msg->msg_iov = iov;
1207 controlp = (msg->msg_control != NULL) ? &control : NULL;
1208 error = kern_recvit(td, s, msg, UIO_SYSSPACE, controlp);
1209 msg->msg_iov = uiov;
1210 if (error != 0)
1211 goto bad;
1212
1213 /*
1214 * Note that kern_recvit() updates msg->msg_namelen.
1215 */
1216 if (msg->msg_name != NULL && msg->msg_namelen > 0) {
1217 msg->msg_name = PTRIN(linux_msghdr.msg_name);
1218 error = bsd_to_linux_sockaddr(sa, &lsa, msg->msg_namelen);
1219 if (error == 0)
1220 error = copyout(lsa, PTRIN(msg->msg_name),
1221 msg->msg_namelen);
1222 free(lsa, M_SONAME);
1223 if (error != 0)
1224 goto bad;
1225 }
1226
1227 error = bsd_to_linux_msghdr(msg, &linux_msghdr);
1228 if (error != 0)
1229 goto bad;
1230
1231 maxlen = linux_msghdr.msg_controllen;
1232 linux_msghdr.msg_controllen = 0;
1233 if (control) {
1234 linux_cmsg = malloc(L_CMSG_HDRSZ, M_LINUX, M_WAITOK | M_ZERO);
1235
1236 msg->msg_control = mtod(control, struct cmsghdr *);
1237 msg->msg_controllen = control->m_len;
1238
1239 cm = CMSG_FIRSTHDR(msg);
1240 outbuf = PTRIN(linux_msghdr.msg_control);
1241 outlen = 0;
1242 while (cm != NULL) {
1243 linux_cmsg->cmsg_type =
1244 bsd_to_linux_cmsg_type(cm->cmsg_type);
1245 linux_cmsg->cmsg_level =
1246 bsd_to_linux_sockopt_level(cm->cmsg_level);
1247 if (linux_cmsg->cmsg_type == -1 ||
1248 cm->cmsg_level != SOL_SOCKET) {
1249 linux_msg(curthread,
1250 "unsupported recvmsg cmsg level %d type %d",
1251 cm->cmsg_level, cm->cmsg_type);
1252 error = EINVAL;
1253 goto bad;
1254 }
1255
1256 data = CMSG_DATA(cm);
1257 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1258
1259 switch (cm->cmsg_type) {
1260 case SCM_RIGHTS:
1261 if (flags & LINUX_MSG_CMSG_CLOEXEC) {
1262 fds = datalen / sizeof(int);
1263 fdp = data;
1264 for (i = 0; i < fds; i++) {
1265 fd = *fdp++;
1266 (void)kern_fcntl(td, fd,
1267 F_SETFD, FD_CLOEXEC);
1268 }
1269 }
1270 break;
1271
1272 case SCM_CREDS:
1273 /*
1274 * Currently LOCAL_CREDS is never in
1275 * effect for Linux so no need to worry
1276 * about sockcred
1277 */
1278 if (datalen != sizeof(*cmcred)) {
1279 error = EMSGSIZE;
1280 goto bad;
1281 }
1282 cmcred = (struct cmsgcred *)data;
1283 bzero(&linux_ucred, sizeof(linux_ucred));
1284 linux_ucred.pid = cmcred->cmcred_pid;
1285 linux_ucred.uid = cmcred->cmcred_uid;
1286 linux_ucred.gid = cmcred->cmcred_gid;
1287 data = &linux_ucred;
1288 datalen = sizeof(linux_ucred);
1289 break;
1290
1291 case SCM_TIMESTAMP:
1292 if (datalen != sizeof(struct timeval)) {
1293 error = EMSGSIZE;
1294 goto bad;
1295 }
1296 ftmvl = (struct timeval *)data;
1297 ltmvl.tv_sec = ftmvl->tv_sec;
1298 ltmvl.tv_usec = ftmvl->tv_usec;
1299 data = <mvl;
1300 datalen = sizeof(ltmvl);
1301 break;
1302 }
1303
1304 if (outlen + LINUX_CMSG_LEN(datalen) > maxlen) {
1305 if (outlen == 0) {
1306 error = EMSGSIZE;
1307 goto bad;
1308 } else {
1309 linux_msghdr.msg_flags |= LINUX_MSG_CTRUNC;
1310 m_dispose_extcontrolm(control);
1311 goto out;
1312 }
1313 }
1314
1315 linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
1316
1317 error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
1318 if (error != 0)
1319 goto bad;
1320 outbuf += L_CMSG_HDRSZ;
1321
1322 error = copyout(data, outbuf, datalen);
1323 if (error != 0)
1324 goto bad;
1325
1326 outbuf += LINUX_CMSG_ALIGN(datalen);
1327 outlen += LINUX_CMSG_LEN(datalen);
1328
1329 cm = CMSG_NXTHDR(msg, cm);
1330 }
1331 linux_msghdr.msg_controllen = outlen;
1332 }
1333
1334 out:
1335 error = copyout(&linux_msghdr, msghdr, sizeof(linux_msghdr));
1336
1337 bad:
1338 if (control != NULL) {
1339 if (error != 0)
1340 m_dispose_extcontrolm(control);
1341 m_freem(control);
1342 }
1343 free(iov, M_IOV);
1344 free(linux_cmsg, M_LINUX);
1345 free(sa, M_SONAME);
1346
1347 return (error);
1348 }
1349
1350 int
1351 linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
1352 {
1353 struct msghdr bsd_msg;
1354
1355 return (linux_recvmsg_common(td, args->s, PTRIN(args->msg),
1356 args->flags, &bsd_msg));
1357 }
1358
1359 int
1360 linux_recvmmsg(struct thread *td, struct linux_recvmmsg_args *args)
1361 {
1362 struct l_mmsghdr *msg;
1363 struct msghdr bsd_msg;
1364 struct l_timespec lts;
1365 struct timespec ts, tts;
1366 l_uint retval;
1367 int error, datagrams;
1368
1369 if (args->timeout) {
1370 error = copyin(args->timeout, <s, sizeof(struct l_timespec));
1371 if (error != 0)
1372 return (error);
1373 error = linux_to_native_timespec(&ts, <s);
1374 if (error != 0)
1375 return (error);
1376 getnanotime(&tts);
1377 timespecadd(&tts, &ts, &tts);
1378 }
1379
1380 msg = PTRIN(args->msg);
1381 datagrams = 0;
1382 while (datagrams < args->vlen) {
1383 error = linux_recvmsg_common(td, args->s, &msg->msg_hdr,
1384 args->flags & ~LINUX_MSG_WAITFORONE, &bsd_msg);
1385 if (error != 0)
1386 break;
1387
1388 retval = td->td_retval[0];
1389 error = copyout(&retval, &msg->msg_len, sizeof(msg->msg_len));
1390 if (error != 0)
1391 break;
1392 ++msg;
1393 ++datagrams;
1394
1395 /*
1396 * MSG_WAITFORONE turns on MSG_DONTWAIT after one packet.
1397 */
1398 if (args->flags & LINUX_MSG_WAITFORONE)
1399 args->flags |= LINUX_MSG_DONTWAIT;
1400
1401 /*
1402 * See BUGS section of recvmmsg(2).
1403 */
1404 if (args->timeout) {
1405 getnanotime(&ts);
1406 timespecsub(&ts, &tts, &ts);
1407 if (!timespecisset(&ts) || ts.tv_sec > 0)
1408 break;
1409 }
1410 /* Out of band data, return right away. */
1411 if (bsd_msg.msg_flags & MSG_OOB)
1412 break;
1413 }
1414 if (error == 0)
1415 td->td_retval[0] = datagrams;
1416 return (error);
1417 }
1418
1419 int
1420 linux_shutdown(struct thread *td, struct linux_shutdown_args *args)
1421 {
1422
1423 return (kern_shutdown(td, args->s, args->how));
1424 }
1425
1426 int
1427 linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
1428 {
1429 l_timeval linux_tv;
1430 struct sockaddr *sa;
1431 struct timeval tv;
1432 socklen_t len;
1433 int error, level, name;
1434
1435 level = linux_to_bsd_sockopt_level(args->level);
1436 switch (level) {
1437 case SOL_SOCKET:
1438 name = linux_to_bsd_so_sockopt(args->optname);
1439 switch (name) {
1440 case SO_RCVTIMEO:
1441 /* FALLTHROUGH */
1442 case SO_SNDTIMEO:
1443 error = copyin(PTRIN(args->optval), &linux_tv,
1444 sizeof(linux_tv));
1445 if (error != 0)
1446 return (error);
1447 tv.tv_sec = linux_tv.tv_sec;
1448 tv.tv_usec = linux_tv.tv_usec;
1449 return (kern_setsockopt(td, args->s, level,
1450 name, &tv, UIO_SYSSPACE, sizeof(tv)));
1451 /* NOTREACHED */
1452 default:
1453 break;
1454 }
1455 break;
1456 case IPPROTO_IP:
1457 if (args->optname == LINUX_IP_RECVERR &&
1458 linux_ignore_ip_recverr) {
1459 /*
1460 * XXX: This is a hack to unbreak DNS resolution
1461 * with glibc 2.30 and above.
1462 */
1463 return (0);
1464 }
1465 name = linux_to_bsd_ip_sockopt(args->optname);
1466 break;
1467 case IPPROTO_IPV6:
1468 name = linux_to_bsd_ip6_sockopt(args->optname);
1469 break;
1470 case IPPROTO_TCP:
1471 name = linux_to_bsd_tcp_sockopt(args->optname);
1472 break;
1473 default:
1474 name = -1;
1475 break;
1476 }
1477 if (name == -1)
1478 return (ENOPROTOOPT);
1479
1480
1481 if (name == IPV6_NEXTHOP) {
1482 len = args->optlen;
1483 error = linux_to_bsd_sockaddr(PTRIN(args->optval), &sa, &len);
1484 if (error != 0)
1485 return (error);
1486
1487 error = kern_setsockopt(td, args->s, level,
1488 name, sa, UIO_SYSSPACE, len);
1489 free(sa, M_SONAME);
1490 } else {
1491 error = kern_setsockopt(td, args->s, level,
1492 name, PTRIN(args->optval), UIO_USERSPACE, args->optlen);
1493 }
1494
1495 return (error);
1496 }
1497
1498 int
1499 linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
1500 {
1501 l_timeval linux_tv;
1502 struct timeval tv;
1503 socklen_t tv_len, xulen, len;
1504 struct l_sockaddr *lsa;
1505 struct sockaddr *sa;
1506 struct xucred xu;
1507 struct l_ucred lxu;
1508 int error, level, name, newval;
1509
1510 level = linux_to_bsd_sockopt_level(args->level);
1511 switch (level) {
1512 case SOL_SOCKET:
1513 name = linux_to_bsd_so_sockopt(args->optname);
1514 switch (name) {
1515 case SO_RCVTIMEO:
1516 /* FALLTHROUGH */
1517 case SO_SNDTIMEO:
1518 tv_len = sizeof(tv);
1519 error = kern_getsockopt(td, args->s, level,
1520 name, &tv, UIO_SYSSPACE, &tv_len);
1521 if (error != 0)
1522 return (error);
1523 linux_tv.tv_sec = tv.tv_sec;
1524 linux_tv.tv_usec = tv.tv_usec;
1525 return (copyout(&linux_tv, PTRIN(args->optval),
1526 sizeof(linux_tv)));
1527 /* NOTREACHED */
1528 case LOCAL_PEERCRED:
1529 if (args->optlen < sizeof(lxu))
1530 return (EINVAL);
1531 /*
1532 * LOCAL_PEERCRED is not served at the SOL_SOCKET level,
1533 * but by the Unix socket's level 0.
1534 */
1535 level = 0;
1536 xulen = sizeof(xu);
1537 error = kern_getsockopt(td, args->s, level,
1538 name, &xu, UIO_SYSSPACE, &xulen);
1539 if (error != 0)
1540 return (error);
1541 lxu.pid = xu.cr_pid;
1542 lxu.uid = xu.cr_uid;
1543 lxu.gid = xu.cr_gid;
1544 return (copyout(&lxu, PTRIN(args->optval), sizeof(lxu)));
1545 /* NOTREACHED */
1546 case SO_ERROR:
1547 len = sizeof(newval);
1548 error = kern_getsockopt(td, args->s, level,
1549 name, &newval, UIO_SYSSPACE, &len);
1550 if (error != 0)
1551 return (error);
1552 newval = -SV_ABI_ERRNO(td->td_proc, newval);
1553 return (copyout(&newval, PTRIN(args->optval), len));
1554 /* NOTREACHED */
1555 default:
1556 break;
1557 }
1558 break;
1559 case IPPROTO_IP:
1560 name = linux_to_bsd_ip_sockopt(args->optname);
1561 break;
1562 case IPPROTO_IPV6:
1563 name = linux_to_bsd_ip6_sockopt(args->optname);
1564 break;
1565 case IPPROTO_TCP:
1566 name = linux_to_bsd_tcp_sockopt(args->optname);
1567 break;
1568 default:
1569 name = -1;
1570 break;
1571 }
1572 if (name == -1)
1573 return (EINVAL);
1574
1575 if (name == IPV6_NEXTHOP) {
1576 error = copyin(PTRIN(args->optlen), &len, sizeof(len));
1577 if (error != 0)
1578 return (error);
1579 sa = malloc(len, M_SONAME, M_WAITOK);
1580
1581 error = kern_getsockopt(td, args->s, level,
1582 name, sa, UIO_SYSSPACE, &len);
1583 if (error != 0)
1584 goto out;
1585
1586 error = bsd_to_linux_sockaddr(sa, &lsa, len);
1587 if (error == 0)
1588 error = copyout(lsa, PTRIN(args->optval), len);
1589 free(lsa, M_SONAME);
1590 if (error == 0)
1591 error = copyout(&len, PTRIN(args->optlen),
1592 sizeof(len));
1593 out:
1594 free(sa, M_SONAME);
1595 } else {
1596 if (args->optval) {
1597 error = copyin(PTRIN(args->optlen), &len, sizeof(len));
1598 if (error != 0)
1599 return (error);
1600 }
1601 error = kern_getsockopt(td, args->s, level,
1602 name, PTRIN(args->optval), UIO_USERSPACE, &len);
1603 if (error == 0)
1604 error = copyout(&len, PTRIN(args->optlen),
1605 sizeof(len));
1606 }
1607
1608 return (error);
1609 }
1610
1611 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1612
1613 /* Argument list sizes for linux_socketcall */
1614 static const unsigned char lxs_args_cnt[] = {
1615 0 /* unused*/, 3 /* socket */,
1616 3 /* bind */, 3 /* connect */,
1617 2 /* listen */, 3 /* accept */,
1618 3 /* getsockname */, 3 /* getpeername */,
1619 4 /* socketpair */, 4 /* send */,
1620 4 /* recv */, 6 /* sendto */,
1621 6 /* recvfrom */, 2 /* shutdown */,
1622 5 /* setsockopt */, 5 /* getsockopt */,
1623 3 /* sendmsg */, 3 /* recvmsg */,
1624 4 /* accept4 */, 5 /* recvmmsg */,
1625 4 /* sendmmsg */
1626 };
1627 #define LINUX_ARGS_CNT (nitems(lxs_args_cnt) - 1)
1628 #define LINUX_ARG_SIZE(x) (lxs_args_cnt[x] * sizeof(l_ulong))
1629
1630 int
1631 linux_socketcall(struct thread *td, struct linux_socketcall_args *args)
1632 {
1633 l_ulong a[6];
1634 #if defined(__amd64__) && defined(COMPAT_LINUX32)
1635 register_t l_args[6];
1636 #endif
1637 void *arg;
1638 int error;
1639
1640 if (args->what < LINUX_SOCKET || args->what > LINUX_ARGS_CNT)
1641 return (EINVAL);
1642 error = copyin(PTRIN(args->args), a, LINUX_ARG_SIZE(args->what));
1643 if (error != 0)
1644 return (error);
1645
1646 #if defined(__amd64__) && defined(COMPAT_LINUX32)
1647 for (int i = 0; i < lxs_args_cnt[args->what]; ++i)
1648 l_args[i] = a[i];
1649 arg = l_args;
1650 #else
1651 arg = a;
1652 #endif
1653 switch (args->what) {
1654 case LINUX_SOCKET:
1655 return (linux_socket(td, arg));
1656 case LINUX_BIND:
1657 return (linux_bind(td, arg));
1658 case LINUX_CONNECT:
1659 return (linux_connect(td, arg));
1660 case LINUX_LISTEN:
1661 return (linux_listen(td, arg));
1662 case LINUX_ACCEPT:
1663 return (linux_accept(td, arg));
1664 case LINUX_GETSOCKNAME:
1665 return (linux_getsockname(td, arg));
1666 case LINUX_GETPEERNAME:
1667 return (linux_getpeername(td, arg));
1668 case LINUX_SOCKETPAIR:
1669 return (linux_socketpair(td, arg));
1670 case LINUX_SEND:
1671 return (linux_send(td, arg));
1672 case LINUX_RECV:
1673 return (linux_recv(td, arg));
1674 case LINUX_SENDTO:
1675 return (linux_sendto(td, arg));
1676 case LINUX_RECVFROM:
1677 return (linux_recvfrom(td, arg));
1678 case LINUX_SHUTDOWN:
1679 return (linux_shutdown(td, arg));
1680 case LINUX_SETSOCKOPT:
1681 return (linux_setsockopt(td, arg));
1682 case LINUX_GETSOCKOPT:
1683 return (linux_getsockopt(td, arg));
1684 case LINUX_SENDMSG:
1685 return (linux_sendmsg(td, arg));
1686 case LINUX_RECVMSG:
1687 return (linux_recvmsg(td, arg));
1688 case LINUX_ACCEPT4:
1689 return (linux_accept4(td, arg));
1690 case LINUX_RECVMMSG:
1691 return (linux_recvmmsg(td, arg));
1692 case LINUX_SENDMMSG:
1693 return (linux_sendmmsg(td, arg));
1694 }
1695
1696 linux_msg(td, "socket type %d not implemented", args->what);
1697 return (ENOSYS);
1698 }
1699 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
Cache object: b135856069081f41fd52697d368842a9
|