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