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