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