d7749eb6326029bea57739346909d2de836b3562
[dragonfly.git] / sys / emulation / 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 withough 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  * $FreeBSD: src/sys/compat/linux/linux_socket.c,v 1.19.2.8 2001/11/07 20:33:55 marcel Exp $
29  * $DragonFly: src/sys/emulation/linux/linux_socket.c,v 1.28 2008/07/10 00:19:27 aggelos Exp $
30  */
31
32 #include <sys/param.h>
33 #include <sys/proc.h>
34 #include <sys/systm.h>
35 #include <sys/sysproto.h>
36 #include <sys/fcntl.h>
37 #include <sys/file.h>
38 #include <sys/kern_syscall.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41 #include <sys/uio.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44
45 #include <netinet/in.h>
46 #include <netinet/in_systm.h>
47 #include <netinet/ip.h>
48
49 #include <arch_linux/linux.h>
50 #include <arch_linux/linux_proto.h>
51 #include "linux_socket.h"
52 #include "linux_util.h"
53
54 /*
55  * Copyin a sockaddr structure provided by a Linux binary.  Linux uses
56  * the 4.3BSD sockaddr structure which has no sa_len field.  We must
57  * pass 4.4BSD sockaddr structures when we call native functions in the
58  * BSD kernel.  This function does the conversion for us.
59  *
60  * Also, our socket calls require the sockaddr structure length to agree
61  * with the address family.  Linux does not, so we must force it.
62  *
63  * This function should only need to be called from linux_connect()
64  * and linux_bind().
65  */
66 static int
67 linux_getsockaddr(struct sockaddr **namp, struct sockaddr *uaddr, size_t len)
68 {
69         struct sockaddr *sa;
70         uint16_t family;        /* XXX: must match Linux sockaddr */
71         int error;
72         int sa_len;
73
74         *namp = NULL;
75
76         if (len > SOCK_MAXADDRLEN)
77                 return ENAMETOOLONG;
78         error = copyin(uaddr, &family, sizeof(family));
79         if (error)
80                 return (error);
81
82         /*
83          * Force the sa_len field to match the address family.
84          */
85         switch (family) {
86         case AF_INET:
87                 sa_len = sizeof(struct sockaddr_in);
88                 break;
89         case AF_INET6:
90                 sa_len = sizeof(struct sockaddr_in6);
91                 break;
92         default:
93                 /*
94                  * This is the default behavior of the old
95                  * linux_to_bsd_namelen() function.  NOTE!  The
96                  * minimum length we allocate must cover sa->sa_len and
97                  * sa->sa_family.
98                  */
99                 sa_len = offsetof(struct sockaddr, sa_data[0]);
100                 if (sa_len < len)
101                         sa_len = len;
102                 break;
103         }
104
105         MALLOC(sa, struct sockaddr *, sa_len, M_SONAME, M_WAITOK);
106         error = copyin(uaddr, sa, sa_len);
107         if (error) {
108                 FREE(sa, M_SONAME);
109         } else {
110                 /*
111                  * Convert to the 4.4BSD sockaddr structure.
112                  */
113                 sa->sa_family = *(sa_family_t *)sa;
114                 sa->sa_len = sa_len;
115                 *namp = sa;
116         }
117
118         return (error);
119 }
120
121 /*
122  * Transform a 4.4BSD sockaddr structure into a Linux sockaddr structure
123  * and copy it out to a user address.
124  */
125 static int
126 linux_copyout_sockaddr(struct sockaddr *sa, struct sockaddr *uaddr, int sa_len)
127 {
128         int error;
129
130         if (sa_len < (int)sizeof(u_short))
131                 return (EINVAL);
132
133         *(u_short *)sa = sa->sa_family;
134         error = copyout(sa, uaddr, sa_len);
135
136         return (error);
137 }
138  
139 static int
140 linux_to_bsd_domain(int domain)
141 {
142
143         switch (domain) {
144         case LINUX_AF_UNSPEC:
145                 return (AF_UNSPEC);
146         case LINUX_AF_UNIX:
147                 return (AF_LOCAL);
148         case LINUX_AF_INET:
149                 return (AF_INET);
150         case LINUX_AF_AX25:
151                 return (AF_CCITT);
152         case LINUX_AF_IPX:
153                 return (AF_IPX);
154         case LINUX_AF_APPLETALK:
155                 return (AF_APPLETALK);
156         }
157         return (-1);
158 }
159
160 static int
161 linux_to_bsd_sockopt_level(int level)
162 {
163
164         switch (level) {
165         case LINUX_SOL_SOCKET:
166                 return (SOL_SOCKET);
167         }
168         return (level);
169 }
170
171 static int
172 linux_to_bsd_ip_sockopt(int opt)
173 {
174
175         switch (opt) {
176         case LINUX_IP_TOS:
177                 return (IP_TOS);
178         case LINUX_IP_TTL:
179                 return (IP_TTL);
180         case LINUX_IP_OPTIONS:
181                 return (IP_OPTIONS);
182         case LINUX_IP_MULTICAST_IF:
183                 return (IP_MULTICAST_IF);
184         case LINUX_IP_MULTICAST_TTL:
185                 return (IP_MULTICAST_TTL);
186         case LINUX_IP_MULTICAST_LOOP:
187                 return (IP_MULTICAST_LOOP);
188         case LINUX_IP_ADD_MEMBERSHIP:
189                 return (IP_ADD_MEMBERSHIP);
190         case LINUX_IP_DROP_MEMBERSHIP:
191                 return (IP_DROP_MEMBERSHIP);
192         case LINUX_IP_HDRINCL:
193                 return (IP_HDRINCL);
194         }
195         return (-1);
196 }
197
198 static int
199 linux_to_bsd_so_sockopt(int opt)
200 {
201
202         switch (opt) {
203         case LINUX_SO_DEBUG:
204                 return (SO_DEBUG);
205         case LINUX_SO_REUSEADDR:
206                 return (SO_REUSEADDR);
207         case LINUX_SO_TYPE:
208                 return (SO_TYPE);
209         case LINUX_SO_ERROR:
210                 return (SO_ERROR);
211         case LINUX_SO_DONTROUTE:
212                 return (SO_DONTROUTE);
213         case LINUX_SO_BROADCAST:
214                 return (SO_BROADCAST);
215         case LINUX_SO_SNDBUF:
216                 return (SO_SNDBUF);
217         case LINUX_SO_RCVBUF:
218                 return (SO_RCVBUF);
219         case LINUX_SO_KEEPALIVE:
220                 return (SO_KEEPALIVE);
221         case LINUX_SO_OOBINLINE:
222                 return (SO_OOBINLINE);
223         case LINUX_SO_LINGER:
224                 return (SO_LINGER);
225         }
226         return (-1);
227 }
228
229 static int
230 linux_to_bsd_msg_flags(int flags)
231 {
232         int ret_flags = 0;
233
234         if (flags & LINUX_MSG_OOB)
235                 ret_flags |= MSG_OOB;
236         if (flags & LINUX_MSG_PEEK)
237                 ret_flags |= MSG_PEEK;
238         if (flags & LINUX_MSG_DONTROUTE)
239                 ret_flags |= MSG_DONTROUTE;
240         if (flags & LINUX_MSG_CTRUNC)
241                 ret_flags |= MSG_CTRUNC;
242         if (flags & LINUX_MSG_TRUNC)
243                 ret_flags |= MSG_TRUNC;
244         if (flags & LINUX_MSG_DONTWAIT)
245                 ret_flags |= MSG_DONTWAIT;
246         if (flags & LINUX_MSG_EOR)
247                 ret_flags |= MSG_EOR;
248         if (flags & LINUX_MSG_WAITALL)
249                 ret_flags |= MSG_WAITALL;
250 #if 0 /* not handled */
251         if (flags & LINUX_MSG_PROXY)
252                 ;
253         if (flags & LINUX_MSG_FIN)
254                 ;
255         if (flags & LINUX_MSG_SYN)
256                 ;
257         if (flags & LINUX_MSG_CONFIRM)
258                 ;
259         if (flags & LINUX_MSG_RST)
260                 ;
261         if (flags & LINUX_MSG_ERRQUEUE)
262                 ;
263         if (flags & LINUX_MSG_NOSIGNAL)
264                 ;
265 #endif
266         return ret_flags;
267 }
268
269 struct linux_socket_args {
270         int domain;
271         int type;
272         int protocol;
273 };
274
275 static int
276 linux_socket(struct linux_socket_args *args, int *res)
277 {
278         struct linux_socket_args linux_args;
279         struct sockopt sopt;
280         int error, domain, optval;
281
282         error = copyin(args, &linux_args, sizeof(linux_args));
283         if (error)
284                 return (error);
285
286         domain = linux_to_bsd_domain(linux_args.domain);
287         if (domain == -1)
288                 return (EINVAL);
289
290         error = kern_socket(domain, linux_args.type, linux_args.protocol, res);
291
292         /* Copy back the return value from socket() */
293         if (error == 0 && linux_args.type == SOCK_RAW &&
294             (linux_args.protocol == IPPROTO_RAW || linux_args.protocol == 0) &&
295             linux_args.domain == AF_INET) {
296                 /* It's a raw IP socket: set the IP_HDRINCL option. */
297                 optval = 1;
298                 sopt.sopt_dir = SOPT_SET;
299                 sopt.sopt_level = IPPROTO_IP;
300                 sopt.sopt_name = IP_HDRINCL;
301                 sopt.sopt_val = &optval;
302                 sopt.sopt_valsize = sizeof(optval);
303                 sopt.sopt_td = NULL;
304
305                 /* We ignore any error returned by setsockopt() */
306                 kern_setsockopt(*res, &sopt);
307         }
308
309         return (error);
310 }
311
312 struct linux_bind_args {
313         int s;
314         struct sockaddr *name;
315         int namelen;
316 };
317
318 static int
319 linux_bind(struct linux_bind_args *args, int *res)
320 {
321         struct linux_bind_args linux_args;
322         struct sockaddr *sa;
323         int error;
324
325         error = copyin(args, &linux_args, sizeof(linux_args));
326         if (error)
327                 return (error);
328         error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen);
329         if (error)
330                 return (error);
331
332         error = kern_bind(linux_args.s, sa);
333         FREE(sa, M_SONAME);
334
335         return (error);
336 }
337
338 struct linux_connect_args {
339         int s;
340         struct sockaddr * name;
341         int namelen;
342 };
343
344 static int
345 linux_connect(struct linux_connect_args *args, int *res)
346 {
347         struct thread *td = curthread;  /* XXX */
348         struct proc *p = td->td_proc;
349         struct linux_connect_args linux_args;
350         struct sockaddr *sa;
351         struct socket *so;
352         struct file *fp;
353         int error;
354
355         KKASSERT(p);
356
357         error = copyin(args, &linux_args, sizeof(linux_args));
358         if (error)
359                 return (error);
360         error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen);
361         if (error)
362                 return (error);
363
364         error = kern_connect(linux_args.s, 0, sa);
365         FREE(sa, M_SONAME);
366
367         if (error != EISCONN)
368                 return (error);
369
370         /*
371          * Linux doesn't return EISCONN the first time it occurs,
372          * when on a non-blocking socket. Instead it returns the
373          * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
374          */
375         error = holdsock(p->p_fd, linux_args.s, &fp);
376         if (error)
377                 return (error);
378         error = EISCONN;
379         if (fp->f_flag & FNONBLOCK) {
380                 so = (struct socket *)fp->f_data;
381                 if (so->so_emuldata == 0)
382                         error = so->so_error;
383                 so->so_emuldata = (void *)1;
384         }
385         fdrop(fp);
386         return (error);
387 }
388
389 struct linux_listen_args {
390         int s;
391         int backlog;
392 };
393
394 static int
395 linux_listen(struct linux_listen_args *args, int *res)
396 {
397         struct linux_listen_args linux_args;
398         int error;
399
400         error = copyin(args, &linux_args, sizeof(linux_args));
401         if (error)
402                 return (error);
403
404         error = kern_listen(linux_args.s, linux_args.backlog);
405
406         return(error);
407 }
408
409 struct linux_accept_args {
410         int s;
411         struct sockaddr *addr;
412         int *namelen;
413 };
414
415 static int
416 linux_accept(struct linux_accept_args *args, int *res)
417 {
418         struct linux_accept_args linux_args;
419         struct sockaddr *sa = NULL;
420         union fcntl_dat dat = { 0 };
421         int error, sa_len;
422
423         error = copyin(args, &linux_args, sizeof(linux_args));
424         if (error)
425                 return (error);
426
427         if (linux_args.addr) {
428                 error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
429                 if (error)
430                         return (error);
431
432                 error = kern_accept(linux_args.s, 0, &sa, &sa_len, res);
433
434                 if (error) {
435                         /*
436                          * Return a namelen of zero for older code which
437                          * might ignore the return value from accept().
438                          */
439                         sa_len = 0;
440                         copyout(&sa_len, linux_args.namelen,
441                             sizeof(*linux_args.namelen));
442                 } else {
443                         error = linux_copyout_sockaddr(sa, linux_args.addr,
444                             sa_len);
445                         if (error == 0) {
446                                 error = copyout(&sa_len, linux_args.namelen,
447                                     sizeof(*linux_args.namelen));
448                         }
449                 }
450                 if (sa)
451                         FREE(sa, M_SONAME);
452         } else {
453                 error = kern_accept(linux_args.s, 0, NULL, 0, res);
454         }
455
456         if (error)
457                 return (error);
458
459         /*
460          * linux appears not to copy flags from the parent socket to the
461          * accepted one, so we must clear the flags in the new descriptor.
462          * Ignore any errors, because we already have an open fd.
463          */
464         kern_fcntl(*res, F_SETFL, &dat, curproc->p_ucred);
465         return (0);
466 }
467
468 struct linux_getsockname_args {
469         int s;
470         struct sockaddr *addr;
471         int *namelen;
472 };
473
474 static int
475 linux_getsockname(struct linux_getsockname_args *args, int *res)
476 {
477         struct linux_getsockname_args linux_args;
478         struct sockaddr *sa = NULL;
479         int error, sa_len;
480          
481
482         error = copyin(args, &linux_args, sizeof(linux_args));
483         if (error)
484                 return (error);
485         error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
486         if (error)
487                 return (error);
488
489         error = kern_getsockname(linux_args.s, &sa, &sa_len);
490
491         if (error == 0)
492                 error = linux_copyout_sockaddr(sa, linux_args.addr, sa_len);
493         if (error == 0)
494                 error = copyout(&sa_len, linux_args.namelen,
495                     sizeof(*linux_args.namelen));
496         if (sa)
497                 FREE(sa, M_SONAME);
498         return(error);
499 }
500
501 struct linux_getpeername_args {
502         int s;
503         struct sockaddr *addr;
504         int *namelen;
505 };
506
507 static int
508 linux_getpeername(struct linux_getpeername_args *args, int *res)
509 {
510         struct linux_getpeername_args linux_args;
511         struct sockaddr *sa = NULL;
512         int error, sa_len;
513
514         error = copyin(args, &linux_args, sizeof(linux_args));
515         if (error)
516                 return (error);
517         error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
518         if (error)
519                 return (error);
520
521         error = kern_getpeername(linux_args.s, &sa, &sa_len);
522
523         if (error == 0)
524                 error = linux_copyout_sockaddr(sa, linux_args.addr, sa_len);
525         if (error == 0)
526                 error = copyout(&sa_len, linux_args.namelen,
527                     sizeof(*linux_args.namelen));
528         if (sa)
529                 FREE(sa, M_SONAME);
530         return(error);
531 }
532
533 struct linux_socketpair_args {
534         int domain;
535         int type;
536         int protocol;
537         int *rsv;
538 };
539
540 static int
541 linux_socketpair(struct linux_socketpair_args *args, int *res)
542 {
543         struct linux_socketpair_args linux_args;
544         int error, domain, sockv[2];
545
546         error = copyin(args, &linux_args, sizeof(linux_args));
547         if (error)
548                 return (error);
549
550         domain = linux_to_bsd_domain(linux_args.domain);
551         if (domain == -1)
552                 return (EINVAL);
553         error = kern_socketpair(domain, linux_args.type, linux_args.protocol,
554             sockv);
555
556         if (error == 0)
557                 error = copyout(sockv, linux_args.rsv, sizeof(sockv));
558         return(error);
559 }
560
561 struct linux_send_args {
562         int s;
563         void *msg;
564         int len;
565         int flags;
566 };
567
568 static int
569 linux_send(struct linux_send_args *args, int *res)
570 {
571         struct linux_send_args linux_args;
572         struct thread *td = curthread;
573         struct uio auio;
574         struct iovec aiov;
575         int error;
576
577         error = copyin(args, &linux_args, sizeof(linux_args));
578         if (error)
579                 return (error);
580
581         aiov.iov_base = linux_args.msg;
582         aiov.iov_len = linux_args.len;
583         auio.uio_iov = &aiov;
584         auio.uio_iovcnt = 1;
585         auio.uio_offset = 0;
586         auio.uio_resid = linux_args.len;
587         auio.uio_segflg = UIO_USERSPACE;
588         auio.uio_rw = UIO_WRITE;
589         auio.uio_td = td;
590
591         error = kern_sendmsg(linux_args.s, NULL, &auio, NULL,
592             linux_args.flags, res);
593
594         return(error);
595 }
596
597 struct linux_recv_args {
598         int s;
599         void *msg;
600         int len;
601         int flags;
602 };
603
604 static int
605 linux_recv(struct linux_recv_args *args, int *res)
606 {
607         struct linux_recv_args linux_args;
608         struct thread *td = curthread;
609         struct uio auio;
610         struct iovec aiov;
611         int error;
612
613         error = copyin(args, &linux_args, sizeof(linux_args));
614         if (error)
615                 return (error);
616
617         aiov.iov_base = linux_args.msg;
618         aiov.iov_len = linux_args.len;
619         auio.uio_iov = &aiov;
620         auio.uio_iovcnt = 1;
621         auio.uio_offset = 0;
622         auio.uio_resid = linux_args.len;
623         auio.uio_segflg = UIO_USERSPACE;
624         auio.uio_rw = UIO_READ;
625         auio.uio_td = td;
626
627         error = kern_recvmsg(linux_args.s, NULL, &auio, NULL,
628             &linux_args.flags, res);
629
630         return(error);
631 }
632
633 struct linux_sendto_args {
634         int s;
635         void *msg;
636         int len;
637         int flags;
638         struct sockaddr *to;
639         int tolen;
640 };
641
642 static int
643 linux_sendto(struct linux_sendto_args *args, int *res)
644 {
645         struct linux_sendto_args linux_args;
646         struct thread *td = curthread;
647         struct uio auio;
648         struct iovec aiov;
649         struct sockopt sopt;
650         struct sockaddr *sa = NULL;
651         caddr_t msg = NULL;
652         int error, optval;
653
654         error = copyin(args, &linux_args, sizeof(linux_args));
655         if (error)
656                 return (error);
657
658         if (linux_args.to) {
659                 error = linux_getsockaddr(&sa, linux_args.to,
660                     linux_args.tolen);
661                 if (error)
662                         return (error);
663         }
664
665         /*
666          * Check to see if the IP_HDRINCL option is set.
667          */
668         sopt.sopt_dir = SOPT_GET;
669         sopt.sopt_level = IPPROTO_IP;
670         sopt.sopt_name = IP_HDRINCL;
671         sopt.sopt_val = &optval;
672         sopt.sopt_valsize = sizeof(optval);
673         sopt.sopt_td = NULL;
674
675         if (kern_getsockopt(linux_args.s, &sopt) != 0)
676                 optval = 0;
677
678         if (optval == 0) {
679                 /*
680                  * IP_HDRINCL is not set.  Package the message as usual.
681                  */
682                 aiov.iov_base = linux_args.msg;
683                 aiov.iov_len = linux_args.len;
684                 auio.uio_iov = &aiov;
685                 auio.uio_iovcnt = 1;
686                 auio.uio_offset = 0;
687                 auio.uio_resid = linux_args.len;
688                 auio.uio_segflg = UIO_USERSPACE;
689                 auio.uio_rw = UIO_WRITE;
690                 auio.uio_td = td;
691         } else {
692                 /*
693                  * IP_HDRINCL is set.  We must convert the beginning of
694                  * the packet header so we can feed it to the BSD kernel.
695                  */
696
697                 /*
698                  * Check that the packet header is long enough to contain
699                  * the fields of interest.  This relies on the fact that
700                  * the fragment offset field comes after the length field.
701                  */
702                 if (linux_args.len < offsetof(struct ip, ip_off))
703                         return (EINVAL);
704
705                 MALLOC(msg, caddr_t, linux_args.len, M_LINUX, M_WAITOK);
706                 error = copyin(linux_args.msg, msg, linux_args.len);
707                 if (error)
708                         goto cleanup;
709
710                 /* Fix the ip_len and ip_off fields.  */
711                 ((struct ip *)msg)->ip_len = linux_args.len;
712                 ((struct ip *)msg)->ip_off = ntohs(((struct ip *)msg)->ip_off);
713
714                 aiov.iov_base = msg;
715                 aiov.iov_len = linux_args.len;
716                 auio.uio_iov = &aiov;
717                 auio.uio_iovcnt = 1;
718                 auio.uio_offset = 0;
719                 auio.uio_resid = linux_args.len;
720                 auio.uio_segflg = UIO_SYSSPACE;
721                 auio.uio_rw = UIO_WRITE;
722                 auio.uio_td = td;
723         }
724
725         error = kern_sendmsg(linux_args.s, sa, &auio, NULL, linux_args.flags,
726             res);
727
728 cleanup:
729         if (sa)
730                 FREE(sa, M_SONAME);
731         if (msg)
732                 FREE(msg, M_LINUX);
733         return(error);
734 }
735
736 struct linux_recvfrom_args {
737         int s;
738         void *buf;
739         int len;
740         int flags;
741         struct sockaddr *from;
742         int *fromlen;
743 };
744
745 static int
746 linux_recvfrom(struct linux_recvfrom_args *args, int *res)
747 {
748         struct linux_recvfrom_args linux_args;
749         struct thread *td = curthread;
750         struct uio auio;
751         struct iovec aiov;
752         struct sockaddr *sa = NULL;
753         int error, fromlen, flags;
754
755         error = copyin(args, &linux_args, sizeof(linux_args));
756         if (error)
757                 return (error);
758
759         if (linux_args.from && linux_args.fromlen) {
760                 error = copyin(linux_args.fromlen, &fromlen, sizeof(fromlen));
761                 if (error)
762                         return (error);
763                 if (fromlen < 0)
764                         return (EINVAL);
765         } else {
766                 fromlen = 0;
767         }
768         aiov.iov_base = linux_args.buf;
769         aiov.iov_len = linux_args.len;
770         auio.uio_iov = &aiov;
771         auio.uio_iovcnt = 1;
772         auio.uio_offset = 0;
773         auio.uio_resid = linux_args.len;
774         auio.uio_segflg = UIO_USERSPACE;
775         auio.uio_rw = UIO_READ;
776         auio.uio_td = td;
777
778         flags = linux_to_bsd_msg_flags(linux_args.flags);
779
780         error = kern_recvmsg(linux_args.s, linux_args.from ? &sa : NULL, &auio,
781             NULL, &flags, res);
782
783         if (error == 0 && linux_args.from) {
784                 if (sa != NULL) {
785                         fromlen = MIN(fromlen, sa->sa_len);
786                         error = linux_copyout_sockaddr(sa, linux_args.from,
787                                                         fromlen);
788                 } else
789                         fromlen = 0;
790                 if (error == 0)
791                         copyout(&fromlen, linux_args.fromlen,
792                             sizeof(fromlen));
793         }
794         if (sa)
795                 FREE(sa, M_SONAME);
796
797         return(error);
798 }
799
800 struct linux_sendmsg_args {
801         int s;
802         struct msghdr *msg;
803         int flags;
804 };
805
806 static int
807 linux_sendmsg(struct linux_sendmsg_args *args, int *res)
808 {
809         struct linux_sendmsg_args linux_args;
810         struct thread *td = curthread;
811         struct msghdr msg;
812         struct uio auio;
813         struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
814         struct sockaddr *sa = NULL;
815         struct mbuf *control = NULL;
816         int error;
817
818         error = copyin(args, &linux_args, sizeof(linux_args));
819         if (error)
820                 return (error);
821
822         error = copyin(linux_args.msg, &msg, sizeof(msg));
823         if (error)
824                 return (error);
825
826         /*
827          * Conditionally copyin msg.msg_name.
828          */
829         if (msg.msg_name) {
830                 error = linux_getsockaddr(&sa, msg.msg_name, msg.msg_namelen);
831                 if (error)
832                         return (error);
833         }
834
835         /*
836          * Populate auio.
837          */
838         error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
839                              &auio.uio_resid);
840         if (error)
841                 goto cleanup2;
842         auio.uio_iov = iov;
843         auio.uio_iovcnt = msg.msg_iovlen;
844         auio.uio_offset = 0;
845         auio.uio_segflg = UIO_USERSPACE;
846         auio.uio_rw = UIO_WRITE;
847         auio.uio_td = td;
848
849         /*
850          * Conditionally copyin msg.msg_control.
851          */
852         if (msg.msg_control) {
853                 if (msg.msg_controllen < sizeof(struct cmsghdr) ||
854                     msg.msg_controllen > MLEN) {
855                         error = EINVAL;
856                         goto cleanup;
857                 }
858                 control = m_get(MB_WAIT, MT_CONTROL);
859                 if (control == NULL) {
860                         error = ENOBUFS;
861                         goto cleanup;
862                 }
863                 control->m_len = msg.msg_controllen;
864                 error = copyin(msg.msg_control, mtod(control, caddr_t),
865                     msg.msg_controllen);
866                 if (error) {
867                         m_free(control);
868                         goto cleanup;
869                 }
870                 /*
871                  * Linux and BSD both support SCM_RIGHTS.  If a linux binary
872                  * wants anything else with an option level of SOL_SOCKET,
873                  * we don't support it.
874                  */
875                 if (mtod(control, struct cmsghdr *)->cmsg_level ==
876                     SOL_SOCKET &&
877                     mtod(control, struct cmsghdr *)->cmsg_type !=
878                     SCM_RIGHTS) {
879                         m_free(control);
880                         error = EINVAL;
881                         goto cleanup;
882                 }
883         }
884
885         error = kern_sendmsg(linux_args.s, sa, &auio, control,
886             linux_args.flags, res);
887
888 cleanup:
889         iovec_free(&iov, aiov);
890 cleanup2:
891         if (sa)
892                 FREE(sa, M_SONAME);
893         return (error);
894 }
895
896 struct linux_recvmsg_args {
897         int s;
898         struct msghdr *msg;
899         int flags;
900 };
901
902 static int
903 linux_recvmsg(struct linux_recvmsg_args *args, int *res)
904 {
905         struct linux_recvmsg_args linux_args;
906         struct thread *td = curthread;
907         struct msghdr msg;
908         struct uio auio;
909         struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
910         struct mbuf *m, *control = NULL;
911         struct sockaddr *sa = NULL;
912         caddr_t ctlbuf;
913         socklen_t *ufromlenp, *ucontrollenp;
914         int error, fromlen, controllen, len, flags, *uflagsp;
915
916         error = copyin(args, &linux_args, sizeof(linux_args));
917         if (error)
918                 return (error);
919
920         error = copyin(linux_args.msg, &msg, sizeof(struct msghdr));
921         if (error)
922                 return (error);
923
924         if (msg.msg_name && msg.msg_namelen < 0)
925                 return (EINVAL);
926         if (msg.msg_control && msg.msg_controllen < 0)
927                 return (EINVAL);
928
929         ufromlenp = (socklen_t *)((caddr_t)linux_args.msg +
930             offsetof(struct msghdr, msg_namelen));
931         ucontrollenp = (socklen_t *)((caddr_t)linux_args.msg +
932             offsetof(struct msghdr, msg_controllen));
933         uflagsp = (int *)((caddr_t)linux_args.msg +
934             offsetof(struct msghdr, msg_flags));
935
936         /*
937          * Populate auio.
938          */
939         error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
940                              &auio.uio_resid);
941         if (error)
942                 return (error);
943         auio.uio_iov = iov;
944         auio.uio_iovcnt = msg.msg_iovlen;
945         auio.uio_offset = 0;
946         auio.uio_segflg = UIO_USERSPACE;
947         auio.uio_rw = UIO_READ;
948         auio.uio_td = td;
949
950         flags = linux_to_bsd_msg_flags(linux_args.flags);
951
952         error = kern_recvmsg(linux_args.s, msg.msg_name ? &sa : NULL, &auio,
953             msg.msg_control ? &control : NULL, &flags, res);
954
955         /*
956          * Copyout msg.msg_name and msg.msg_namelen.
957          */
958         if (error == 0 && msg.msg_name) {
959                 if (sa != NULL) {
960                         fromlen = MIN(msg.msg_namelen, sa->sa_len);
961                         error = linux_copyout_sockaddr(sa, msg.msg_name,
962                                                         fromlen);
963                 } else
964                         fromlen = 0;
965                 if (error == 0)
966                         error = copyout(&fromlen, ufromlenp,
967                             sizeof(*ufromlenp));
968         }
969
970         /*
971          * Copyout msg.msg_control and msg.msg_controllen.
972          */
973         if (error == 0 && msg.msg_control) {
974                 /*
975                  * Linux and BSD both support SCM_RIGHTS.  If a linux binary
976                  * wants anything else with an option level of SOL_SOCKET,
977                  * we don't support it.
978                  */
979                 if (mtod((struct mbuf *)msg.msg_control,
980                     struct cmsghdr *)->cmsg_level == SOL_SOCKET &&
981                     mtod((struct mbuf *)msg.msg_control,
982                     struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
983                         error = EINVAL;
984                         goto cleanup;
985                 }
986
987                 len = msg.msg_controllen;
988                 m = control;
989                 ctlbuf = (caddr_t)msg.msg_control;
990
991                 while (m && len > 0) {
992                         unsigned int tocopy;
993
994                         if (len >= m->m_len) {
995                                 tocopy = m->m_len;
996                         } else {
997                                 msg.msg_flags |= MSG_CTRUNC;
998                                 tocopy = len;
999                         }
1000
1001                         error = copyout(mtod(m, caddr_t), ctlbuf,
1002                             tocopy);
1003                         if (error)
1004                                 goto cleanup;
1005
1006                         ctlbuf += tocopy;
1007                         len -= tocopy;
1008                         m = m->m_next;
1009                 }
1010                 controllen = ctlbuf - (caddr_t)msg.msg_control;
1011                 error = copyout(&controllen, ucontrollenp,
1012                     sizeof(*ucontrollenp));
1013         }
1014
1015         if (error == 0)
1016                 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
1017
1018 cleanup:
1019         if (sa)
1020                 FREE(sa, M_SONAME);
1021         iovec_free(&iov, aiov);
1022         if (control)
1023                 m_freem(control);
1024         return (error);
1025 }
1026
1027 struct linux_shutdown_args {
1028         int s;
1029         int how;
1030 };
1031
1032 static int
1033 linux_shutdown(struct linux_shutdown_args *args, int *res)
1034 {
1035         struct linux_shutdown_args linux_args;
1036         int error;
1037
1038         error = copyin(args, &linux_args, sizeof(linux_args));
1039         if (error)
1040                 return (error);
1041
1042         error = kern_shutdown(linux_args.s, linux_args.how);
1043
1044         return (error);
1045 }
1046
1047 struct linux_setsockopt_args {
1048         int s;
1049         int level;
1050         int optname;
1051         void *optval;
1052         int optlen;
1053 };
1054
1055 static int
1056 linux_setsockopt(struct linux_setsockopt_args *args, int *res)
1057 {
1058         struct linux_setsockopt_args linux_args;
1059         struct thread *td = curthread;
1060         struct sockopt sopt;
1061         int error, name, level;
1062
1063         error = copyin(args, &linux_args, sizeof(linux_args));
1064         if (error)
1065                 return (error);
1066
1067         level = linux_to_bsd_sockopt_level(linux_args.level);
1068         switch (level) {
1069         case SOL_SOCKET:
1070                 name = linux_to_bsd_so_sockopt(linux_args.optname);
1071                 break;
1072         case IPPROTO_IP:
1073                 name = linux_to_bsd_ip_sockopt(linux_args.optname);
1074                 break;
1075         case IPPROTO_TCP:
1076                 /* Linux TCP option values match BSD's */
1077                 name = linux_args.optname;
1078                 break;
1079         default:
1080                 name = -1;
1081                 break;
1082         }
1083         if (name == -1)
1084                 return (EINVAL);
1085
1086         sopt.sopt_dir = SOPT_SET;
1087         sopt.sopt_level = level;
1088         sopt.sopt_name = name;
1089         sopt.sopt_valsize = linux_args.optlen;
1090         sopt.sopt_td = td;
1091
1092         if (sopt.sopt_valsize < 0 || sopt.sopt_valsize > SOMAXOPT_SIZE)
1093                 return (EINVAL);
1094
1095         if (linux_args.optval) {
1096                 sopt.sopt_val = kmalloc(sopt.sopt_valsize, M_TEMP, M_WAITOK);
1097                 error = copyin(linux_args.optval, sopt.sopt_val, sopt.sopt_valsize);
1098                 if (error)
1099                         goto out;
1100         } else {
1101                 sopt.sopt_val = NULL;
1102         }
1103         error = kern_setsockopt(linux_args.s, &sopt);
1104         if (error)
1105                 goto out;
1106         if (linux_args.optval)
1107                 error = copyout(sopt.sopt_val, linux_args.optval,
1108                                 sopt.sopt_valsize);
1109 out:
1110         if (linux_args.optval)
1111                 kfree(sopt.sopt_val, M_TEMP);
1112         return(error);
1113 }
1114
1115 struct linux_getsockopt_args {
1116         int s;
1117         int level;
1118         int optname;
1119         void *optval;
1120         int *optlen;
1121 };
1122
1123 static int
1124 linux_getsockopt(struct linux_getsockopt_args *args, int *res)
1125 {
1126         struct linux_getsockopt_args linux_args;
1127         struct thread *td = curthread;
1128         struct sockopt sopt;
1129         int error, name, valsize, level;
1130
1131         error = copyin(args, &linux_args, sizeof(linux_args));
1132         if (error)
1133                 return (error);
1134
1135         if (linux_args.optval) {
1136                 error = copyin(linux_args.optlen, &valsize, sizeof(valsize));
1137                 if (error)
1138                         return (error);
1139                 if (valsize < 0 || valsize > SOMAXOPT_SIZE)
1140                         return (EINVAL);
1141         } else {
1142                 valsize = 0;
1143         }
1144
1145         level = linux_to_bsd_sockopt_level(linux_args.level);
1146         switch (level) {
1147         case SOL_SOCKET:
1148                 name = linux_to_bsd_so_sockopt(linux_args.optname);
1149                 break;
1150         case IPPROTO_IP:
1151                 name = linux_to_bsd_ip_sockopt(linux_args.optname);
1152                 break;
1153         case IPPROTO_TCP:
1154                 /* Linux TCP option values match BSD's */
1155                 name = linux_args.optname;
1156                 break;
1157         default:
1158                 name = -1;
1159                 break;
1160         }
1161         if (name == -1)
1162                 return (EINVAL);
1163
1164         sopt.sopt_dir = SOPT_GET;
1165         sopt.sopt_level = level;
1166         sopt.sopt_name = name;
1167         sopt.sopt_valsize = valsize;
1168         sopt.sopt_td = td;
1169
1170         if (linux_args.optval) {
1171                 sopt.sopt_val = kmalloc(sopt.sopt_valsize, M_TEMP, M_WAITOK);
1172                 error = copyin(linux_args.optval, sopt.sopt_val, sopt.sopt_valsize);
1173                 if (error)
1174                         goto out;
1175         } else {
1176                 sopt.sopt_val = NULL;
1177         }
1178         error = kern_getsockopt(linux_args.s, &sopt);
1179         if (error)
1180                 goto out;
1181         valsize = sopt.sopt_valsize;
1182         error = copyout(&valsize, linux_args.optlen, sizeof(valsize));
1183         if (error)
1184                 goto out;
1185         if (linux_args.optval)
1186                 error = copyout(sopt.sopt_val, linux_args.optval, sopt.sopt_valsize);
1187 out:
1188         if (linux_args.optval)
1189                 kfree(sopt.sopt_val, M_TEMP);
1190         return(error);
1191 }
1192
1193 int
1194 sys_linux_socketcall(struct linux_socketcall_args *args)
1195 {
1196         void *arg = (void *)args->args;
1197
1198         switch (args->what) {
1199         case LINUX_SOCKET:
1200                 return (linux_socket(arg, &args->sysmsg_result));
1201         case LINUX_BIND:
1202                 return (linux_bind(arg, &args->sysmsg_result));
1203         case LINUX_CONNECT:
1204                 return (linux_connect(arg, &args->sysmsg_result));
1205         case LINUX_LISTEN:
1206                 return (linux_listen(arg, &args->sysmsg_result));
1207         case LINUX_ACCEPT:
1208                 return (linux_accept(arg, &args->sysmsg_result));
1209         case LINUX_GETSOCKNAME:
1210                 return (linux_getsockname(arg, &args->sysmsg_result));
1211         case LINUX_GETPEERNAME:
1212                 return (linux_getpeername(arg, &args->sysmsg_result));
1213         case LINUX_SOCKETPAIR:
1214                 return (linux_socketpair(arg, &args->sysmsg_result));
1215         case LINUX_SEND:
1216                 return (linux_send(arg, &args->sysmsg_result));
1217         case LINUX_RECV:
1218                 return (linux_recv(arg, &args->sysmsg_result));
1219         case LINUX_SENDTO:
1220                 return (linux_sendto(arg, &args->sysmsg_result));
1221         case LINUX_RECVFROM:
1222                 return (linux_recvfrom(arg, &args->sysmsg_result));
1223         case LINUX_SHUTDOWN:
1224                 return (linux_shutdown(arg, &args->sysmsg_result));
1225         case LINUX_SETSOCKOPT:
1226                 return (linux_setsockopt(arg, &args->sysmsg_result));
1227         case LINUX_GETSOCKOPT:
1228                 return (linux_getsockopt(arg, &args->sysmsg_result));
1229         case LINUX_SENDMSG:
1230                 return (linux_sendmsg(arg, &args->sysmsg_result));
1231         case LINUX_RECVMSG:
1232                 return (linux_recvmsg(arg, &args->sysmsg_result));
1233         }
1234
1235         uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
1236         return (ENOSYS);
1237 }