2 * Copyright (c) 1995 Søren Schmidt
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
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.
28 * $FreeBSD: src/sys/compat/linux/linux_socket.c,v 1.19.2.8 2001/11/07 20:33:55 marcel Exp $
31 /* XXX we use functions that might not exist. */
32 #include "opt_compat.h"
35 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
38 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/sysproto.h>
42 #include <sys/fcntl.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
48 #include <netinet/in.h>
49 #include <netinet/in_systm.h>
50 #include <netinet/ip.h>
52 #include <machine/../linux/linux.h>
53 #include <machine/../linux/linux_proto.h>
54 #include <compat/linux/linux_socket.h>
55 #include <compat/linux/linux_util.h>
58 * FreeBSD's socket calls require the sockaddr struct length to agree
59 * with the address family. Linux does not, so we must force it.
62 linux_to_bsd_namelen(caddr_t name, int namelen)
64 uint16_t family; /* XXX must match Linux sockaddr */
66 if (copyin(name, &family, sizeof(family)))
71 return sizeof(struct sockaddr_in);
73 return sizeof(struct sockaddr_in6);
80 linux_to_bsd_domain(int domain)
94 case LINUX_AF_APPLETALK:
95 return (AF_APPLETALK);
101 linux_to_bsd_sockopt_level(int level)
105 case LINUX_SOL_SOCKET:
112 linux_to_bsd_ip_sockopt(int opt)
120 case LINUX_IP_OPTIONS:
122 case LINUX_IP_MULTICAST_IF:
123 return (IP_MULTICAST_IF);
124 case LINUX_IP_MULTICAST_TTL:
125 return (IP_MULTICAST_TTL);
126 case LINUX_IP_MULTICAST_LOOP:
127 return (IP_MULTICAST_LOOP);
128 case LINUX_IP_ADD_MEMBERSHIP:
129 return (IP_ADD_MEMBERSHIP);
130 case LINUX_IP_DROP_MEMBERSHIP:
131 return (IP_DROP_MEMBERSHIP);
132 case LINUX_IP_HDRINCL:
139 linux_to_bsd_so_sockopt(int opt)
145 case LINUX_SO_REUSEADDR:
146 return (SO_REUSEADDR);
151 case LINUX_SO_DONTROUTE:
152 return (SO_DONTROUTE);
153 case LINUX_SO_BROADCAST:
154 return (SO_BROADCAST);
155 case LINUX_SO_SNDBUF:
157 case LINUX_SO_RCVBUF:
159 case LINUX_SO_KEEPALIVE:
160 return (SO_KEEPALIVE);
161 case LINUX_SO_OOBINLINE:
162 return (SO_OOBINLINE);
163 case LINUX_SO_LINGER:
170 linux_to_bsd_msg_flags(int flags)
174 if (flags & LINUX_MSG_OOB)
175 ret_flags |= MSG_OOB;
176 if (flags & LINUX_MSG_PEEK)
177 ret_flags |= MSG_PEEK;
178 if (flags & LINUX_MSG_DONTROUTE)
179 ret_flags |= MSG_DONTROUTE;
180 if (flags & LINUX_MSG_CTRUNC)
181 ret_flags |= MSG_CTRUNC;
182 if (flags & LINUX_MSG_TRUNC)
183 ret_flags |= MSG_TRUNC;
184 if (flags & LINUX_MSG_DONTWAIT)
185 ret_flags |= MSG_DONTWAIT;
186 if (flags & LINUX_MSG_EOR)
187 ret_flags |= MSG_EOR;
188 if (flags & LINUX_MSG_WAITALL)
189 ret_flags |= MSG_WAITALL;
190 #if 0 /* not handled */
191 if (flags & LINUX_MSG_PROXY)
193 if (flags & LINUX_MSG_FIN)
195 if (flags & LINUX_MSG_SYN)
197 if (flags & LINUX_MSG_CONFIRM)
199 if (flags & LINUX_MSG_RST)
201 if (flags & LINUX_MSG_ERRQUEUE)
203 if (flags & LINUX_MSG_NOSIGNAL)
209 /* Return 0 if IP_HDRINCL is set for the given socket. */
211 linux_check_hdrincl(struct proc *p, int s)
213 struct getsockopt_args /* {
221 caddr_t sg, val, valsize;
222 int size_val = sizeof val;
225 sg = stackgap_init();
226 val = stackgap_alloc(&sg, sizeof(int));
227 valsize = stackgap_alloc(&sg, sizeof(int));
229 if ((error = copyout(&size_val, valsize, sizeof(size_val))))
233 bsd_args.level = IPPROTO_IP;
234 bsd_args.name = IP_HDRINCL;
236 bsd_args.avalsize = (int *)valsize;
237 if ((error = getsockopt(p, &bsd_args)))
240 if ((error = copyin(val, &optval, sizeof(optval))))
243 return (optval == 0);
247 * Updated sendto() when IP_HDRINCL is set:
248 * tweak endian-dependent fields in the IP packet.
251 linux_sendto_hdrincl(struct proc *p, struct sendto_args *bsd_args)
254 * linux_ip_copysize defines how many bytes we should copy
255 * from the beginning of the IP packet before we customize it for BSD.
256 * It should include all the fields we modify (ip_len and ip_off)
257 * and be as small as possible to minimize copying overhead.
259 #define linux_ip_copysize 8
267 struct sendmsg_args /* {
273 /* Check the packet isn't too small before we mess with it */
274 if (bsd_args->len < linux_ip_copysize)
278 * Tweaking the user buffer in place would be bad manners.
279 * We create a corrected IP header with just the needed length,
280 * then use an iovec to glue it to the rest of the user packet
281 * when calling sendmsg().
283 sg = stackgap_init();
284 packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize);
285 msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg));
286 iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2);
288 /* Make a copy of the beginning of the packet to be sent */
289 if ((error = copyin(bsd_args->buf, packet, linux_ip_copysize)))
292 /* Convert fields from Linux to BSD raw IP socket format */
293 packet->ip_len = bsd_args->len;
294 packet->ip_off = ntohs(packet->ip_off);
296 /* Prepare the msghdr and iovec structures describing the new packet */
297 msg->msg_name = bsd_args->to;
298 msg->msg_namelen = bsd_args->tolen;
301 msg->msg_control = NULL;
302 msg->msg_controllen = 0;
304 iov[0].iov_base = (char *)packet;
305 iov[0].iov_len = linux_ip_copysize;
306 iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize;
307 iov[1].iov_len = bsd_args->len - linux_ip_copysize;
309 sendmsg_args.s = bsd_args->s;
310 sendmsg_args.msg = (caddr_t)msg;
311 sendmsg_args.flags = bsd_args->flags;
312 return (sendmsg(p, &sendmsg_args));
315 struct linux_socket_args {
322 linux_socket(struct proc *p, struct linux_socket_args *args)
324 struct linux_socket_args linux_args;
325 struct socket_args /* {
333 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
336 bsd_args.protocol = linux_args.protocol;
337 bsd_args.type = linux_args.type;
338 bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
339 if (bsd_args.domain == -1)
342 retval_socket = socket(p, &bsd_args);
343 if (bsd_args.type == SOCK_RAW
344 && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)
345 && bsd_args.domain == AF_INET
346 && retval_socket >= 0) {
347 /* It's a raw IP socket: set the IP_HDRINCL option. */
348 struct setsockopt_args /* {
354 } */ bsd_setsockopt_args;
358 sg = stackgap_init();
359 hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl));
361 bsd_setsockopt_args.s = p->p_retval[0];
362 bsd_setsockopt_args.level = IPPROTO_IP;
363 bsd_setsockopt_args.name = IP_HDRINCL;
364 bsd_setsockopt_args.val = (caddr_t)hdrincl;
365 bsd_setsockopt_args.valsize = sizeof(*hdrincl);
366 /* We ignore any error returned by setsockopt() */
367 setsockopt(p, &bsd_setsockopt_args);
368 /* Copy back the return value from socket() */
369 p->p_retval[0] = bsd_setsockopt_args.s;
372 return (retval_socket);
375 struct linux_bind_args {
377 struct sockaddr *name;
382 linux_bind(struct proc *p, struct linux_bind_args *args)
384 struct linux_bind_args linux_args;
385 struct bind_args /* {
392 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
395 bsd_args.s = linux_args.s;
396 bsd_args.name = (caddr_t)linux_args.name;
397 bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name,
399 return (bind(p, &bsd_args));
402 struct linux_connect_args {
404 struct sockaddr * name;
407 int linux_connect(struct proc *, struct linux_connect_args *);
408 #endif /* !__alpha__*/
411 linux_connect(struct proc *p, struct linux_connect_args *args)
413 struct linux_connect_args linux_args;
414 struct connect_args /* {
424 bcopy(args, &linux_args, sizeof(linux_args));
426 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
428 #endif /* __alpha__ */
430 bsd_args.s = linux_args.s;
431 bsd_args.name = (caddr_t)linux_args.name;
432 bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name,
434 error = connect(p, &bsd_args);
435 if (error != EISCONN)
439 * Linux doesn't return EISCONN the first time it occurs,
440 * when on a non-blocking socket. Instead it returns the
441 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
443 error = holdsock(p->p_fd, linux_args.s, &fp);
447 if (fp->f_flag & FNONBLOCK) {
448 so = (struct socket *)fp->f_data;
449 if (so->so_emuldata == 0)
450 error = so->so_error;
451 so->so_emuldata = (void *)1;
459 struct linux_listen_args {
465 linux_listen(struct proc *p, struct linux_listen_args *args)
467 struct linux_listen_args linux_args;
468 struct listen_args /* {
474 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
477 bsd_args.s = linux_args.s;
478 bsd_args.backlog = linux_args.backlog;
479 return (listen(p, &bsd_args));
482 struct linux_accept_args {
484 struct sockaddr *addr;
489 linux_accept(struct proc *p, struct linux_accept_args *args)
491 struct linux_accept_args linux_args;
492 struct accept_args /* {
497 struct fcntl_args /* {
504 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
507 bsd_args.s = linux_args.s;
508 bsd_args.name = (caddr_t)linux_args.addr;
509 bsd_args.anamelen = linux_args.namelen;
510 error = oaccept(p, &bsd_args);
515 * linux appears not to copy flags from the parent socket to the
516 * accepted one, so we must clear the flags in the new descriptor.
517 * Ignore any errors, because we already have an open fd.
519 f_args.fd = p->p_retval[0];
520 f_args.cmd = F_SETFL;
522 (void)fcntl(p, &f_args);
523 p->p_retval[0] = f_args.fd;
527 struct linux_getsockname_args {
529 struct sockaddr *addr;
534 linux_getsockname(struct proc *p, struct linux_getsockname_args *args)
536 struct linux_getsockname_args linux_args;
537 struct getsockname_args /* {
544 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
547 bsd_args.fdes = linux_args.s;
548 bsd_args.asa = (caddr_t) linux_args.addr;
549 bsd_args.alen = linux_args.namelen;
550 return (ogetsockname(p, &bsd_args));
553 struct linux_getpeername_args {
555 struct sockaddr *addr;
560 linux_getpeername(struct proc *p, struct linux_getpeername_args *args)
562 struct linux_getpeername_args linux_args;
563 struct ogetpeername_args /* {
570 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
573 bsd_args.fdes = linux_args.s;
574 bsd_args.asa = (caddr_t) linux_args.addr;
575 bsd_args.alen = linux_args.namelen;
576 return (ogetpeername(p, &bsd_args));
579 struct linux_socketpair_args {
587 linux_socketpair(struct proc *p, struct linux_socketpair_args *args)
589 struct linux_socketpair_args linux_args;
590 struct socketpair_args /* {
598 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
601 bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
602 if (bsd_args.domain == -1)
605 bsd_args.type = linux_args.type;
606 bsd_args.protocol = linux_args.protocol;
607 bsd_args.rsv = linux_args.rsv;
608 return (socketpair(p, &bsd_args));
611 struct linux_send_args {
619 linux_send(struct proc *p, struct linux_send_args *args)
621 struct linux_send_args linux_args;
622 struct osend_args /* {
630 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
633 bsd_args.s = linux_args.s;
634 bsd_args.buf = linux_args.msg;
635 bsd_args.len = linux_args.len;
636 bsd_args.flags = linux_args.flags;
637 return (osend(p, &bsd_args));
640 struct linux_recv_args {
648 linux_recv(struct proc *p, struct linux_recv_args *args)
650 struct linux_recv_args linux_args;
651 struct orecv_args /* {
659 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
662 bsd_args.s = linux_args.s;
663 bsd_args.buf = linux_args.msg;
664 bsd_args.len = linux_args.len;
665 bsd_args.flags = linux_args.flags;
666 return (orecv(p, &bsd_args));
669 struct linux_sendto_args {
679 linux_sendto(struct proc *p, struct linux_sendto_args *args)
681 struct linux_sendto_args linux_args;
682 struct sendto_args /* {
692 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
695 bsd_args.s = linux_args.s;
696 bsd_args.buf = linux_args.msg;
697 bsd_args.len = linux_args.len;
698 bsd_args.flags = linux_args.flags;
699 bsd_args.to = linux_args.to;
700 bsd_args.tolen = linux_args.tolen;
702 if (linux_check_hdrincl(p, linux_args.s) == 0)
703 /* IP_HDRINCL set, tweak the packet before sending */
704 return (linux_sendto_hdrincl(p, &bsd_args));
706 return (sendto(p, &bsd_args));
709 struct linux_recvfrom_args {
719 linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args)
721 struct linux_recvfrom_args linux_args;
722 struct recvfrom_args /* {
732 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
735 bsd_args.s = linux_args.s;
736 bsd_args.buf = linux_args.buf;
737 bsd_args.len = linux_args.len;
738 bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
739 bsd_args.from = linux_args.from;
740 bsd_args.fromlenaddr = linux_args.fromlen;
741 return (orecvfrom(p, &bsd_args));
744 struct linux_recvmsg_args {
751 linux_recvmsg(struct proc *p, struct linux_recvmsg_args *args)
753 struct linux_recvmsg_args linux_args;
754 struct recvmsg_args /* {
761 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
764 bsd_args.s = linux_args.s;
765 bsd_args.msg = linux_args.msg;
766 bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
767 return (recvmsg(p, &bsd_args));
770 struct linux_shutdown_args {
776 linux_shutdown(struct proc *p, struct linux_shutdown_args *args)
778 struct linux_shutdown_args linux_args;
779 struct shutdown_args /* {
785 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
788 bsd_args.s = linux_args.s;
789 bsd_args.how = linux_args.how;
790 return (shutdown(p, &bsd_args));
793 struct linux_setsockopt_args {
802 linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args)
804 struct linux_setsockopt_args linux_args;
805 struct setsockopt_args /* {
814 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
817 bsd_args.s = linux_args.s;
818 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
819 switch (bsd_args.level) {
821 name = linux_to_bsd_so_sockopt(linux_args.optname);
824 name = linux_to_bsd_ip_sockopt(linux_args.optname);
827 /* Linux TCP option values match BSD's */
828 name = linux_args.optname;
837 bsd_args.name = name;
838 bsd_args.val = linux_args.optval;
839 bsd_args.valsize = linux_args.optlen;
840 return (setsockopt(p, &bsd_args));
843 struct linux_getsockopt_args {
852 linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args)
854 struct linux_getsockopt_args linux_args;
855 struct getsockopt_args /* {
864 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
867 bsd_args.s = linux_args.s;
868 bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
869 switch (bsd_args.level) {
871 name = linux_to_bsd_so_sockopt(linux_args.optname);
874 name = linux_to_bsd_ip_sockopt(linux_args.optname);
877 /* Linux TCP option values match BSD's */
878 name = linux_args.optname;
887 bsd_args.name = name;
888 bsd_args.val = linux_args.optval;
889 bsd_args.avalsize = linux_args.optlen;
890 return (getsockopt(p, &bsd_args));
894 linux_socketcall(struct proc *p, struct linux_socketcall_args *args)
896 void *arg = (void *)args->args;
898 switch (args->what) {
900 return (linux_socket(p, arg));
902 return (linux_bind(p, arg));
904 return (linux_connect(p, arg));
906 return (linux_listen(p, arg));
908 return (linux_accept(p, arg));
909 case LINUX_GETSOCKNAME:
910 return (linux_getsockname(p, arg));
911 case LINUX_GETPEERNAME:
912 return (linux_getpeername(p, arg));
913 case LINUX_SOCKETPAIR:
914 return (linux_socketpair(p, arg));
916 return (linux_send(p, arg));
918 return (linux_recv(p, arg));
920 return (linux_sendto(p, arg));
922 return (linux_recvfrom(p, arg));
924 return (linux_shutdown(p, arg));
925 case LINUX_SETSOCKOPT:
926 return (linux_setsockopt(p, arg));
927 case LINUX_GETSOCKOPT:
928 return (linux_getsockopt(p, arg));
936 const struct msghdr *msg;
940 error = copyin(&uap->msg->msg_control, &control,
948 error = copyin(&((struct cmsghdr*)control)->cmsg_level,
949 &level, sizeof(int));
955 * Linux thinks that SOL_SOCKET is 1; we know
956 * that it's really 0xffff, of course.
959 error = copyout(&level,
960 &((struct cmsghdr *)control)->cmsg_level,
966 return (sendmsg(p, arg));
969 return (linux_recvmsg(p, arg));
972 uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
975 #endif /*!__alpha__*/