xref: /freebsd/sys/compat/linux/linux_socket.c (revision 3d11b6c8f01e1fca5936a11d6996448467851a94)
1 /*-
2  * Copyright (c) 1995 S�ren Schmidt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 /* XXX we use functions that might not exist. */
33 #include "opt_compat.h"
34 #include "opt_inet6.h"
35 
36 #include <sys/param.h>
37 #include <sys/proc.h>
38 #include <sys/systm.h>
39 #include <sys/sysproto.h>
40 #include <sys/fcntl.h>
41 #include <sys/file.h>
42 #include <sys/limits.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mutex.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/syscallsubr.h>
50 #include <sys/uio.h>
51 #include <sys/syslog.h>
52 
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #ifdef INET6
57 #include <netinet/ip6.h>
58 #include <netinet6/ip6_var.h>
59 #endif
60 
61 #ifdef COMPAT_LINUX32
62 #include <machine/../linux32/linux.h>
63 #include <machine/../linux32/linux32_proto.h>
64 #else
65 #include <machine/../linux/linux.h>
66 #include <machine/../linux/linux_proto.h>
67 #endif
68 #include <compat/linux/linux_socket.h>
69 #include <compat/linux/linux_util.h>
70 
71 static int do_sa_get(struct sockaddr **, const struct osockaddr *, int *,
72     struct malloc_type *);
73 static int linux_to_bsd_domain(int);
74 
75 #ifdef __alpha__
76 #define	STATIC
77 #else
78 #define	STATIC static
79 #endif
80 
81 /*
82  * Reads a linux sockaddr and does any necessary translation.
83  * Linux sockaddrs don't have a length field, only a family.
84  */
85 static int
86 linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int len)
87 {
88 	int osalen = len;
89 
90 	return (do_sa_get(sap, osa, &osalen, M_SONAME));
91 }
92 
93 /*
94  * Copy the osockaddr structure pointed to by osa to kernel, adjust
95  * family and convert to sockaddr.
96  */
97 static int
98 do_sa_get(struct sockaddr **sap, const struct osockaddr *osa, int *osalen,
99     struct malloc_type *mtype)
100 {
101 	int error=0, bdom;
102 	struct sockaddr *sa;
103 	struct osockaddr *kosa;
104 	int alloclen;
105 #ifdef INET6
106 	int oldv6size;
107 	struct sockaddr_in6 *sin6;
108 #endif
109 
110 	if (*osalen < 2 || *osalen > UCHAR_MAX || !osa)
111 		return (EINVAL);
112 
113 	alloclen = *osalen;
114 #ifdef INET6
115 	oldv6size = 0;
116 	/*
117 	 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
118 	 * if it's a v4-mapped address, so reserve the proper space
119 	 * for it.
120 	 */
121 	if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
122 		alloclen = sizeof (struct sockaddr_in6);
123 		oldv6size = 1;
124 	}
125 #endif
126 
127 	MALLOC(kosa, struct osockaddr *, alloclen, mtype, M_WAITOK);
128 
129 	if ((error = copyin(osa, kosa, *osalen)))
130 		goto out;
131 
132 	bdom = linux_to_bsd_domain(kosa->sa_family);
133 	if (bdom == -1) {
134 		error = EINVAL;
135 		goto out;
136 	}
137 
138 #ifdef INET6
139 	/*
140 	 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
141 	 * which lacks the scope id compared with RFC2553 one. If we detect
142 	 * the situation, reject the address and write a message to system log.
143 	 *
144 	 * Still accept addresses for which the scope id is not used.
145 	 */
146 	if (oldv6size && bdom == AF_INET6) {
147 		sin6 = (struct sockaddr_in6 *)kosa;
148 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
149 		    (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
150 		     !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
151 		     !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
152 		     !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
153 		     !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
154 			sin6->sin6_scope_id = 0;
155 		} else {
156 			log(LOG_DEBUG,
157 			    "obsolete pre-RFC2553 sockaddr_in6 rejected\n");
158 			error = EINVAL;
159 			goto out;
160 		}
161 	} else
162 #endif
163 	if (bdom == AF_INET)
164 		alloclen = sizeof(struct sockaddr_in);
165 
166 	sa = (struct sockaddr *) kosa;
167 	sa->sa_family = bdom;
168 	sa->sa_len = alloclen;
169 
170 	*sap = sa;
171 	*osalen = alloclen;
172 	return (0);
173 
174 out:
175 	FREE(kosa, mtype);
176 	return (error);
177 }
178 
179 static int
180 linux_to_bsd_domain(int domain)
181 {
182 
183 	switch (domain) {
184 	case LINUX_AF_UNSPEC:
185 		return (AF_UNSPEC);
186 	case LINUX_AF_UNIX:
187 		return (AF_LOCAL);
188 	case LINUX_AF_INET:
189 		return (AF_INET);
190 	case LINUX_AF_INET6:
191 		return (AF_INET6);
192 	case LINUX_AF_AX25:
193 		return (AF_CCITT);
194 	case LINUX_AF_IPX:
195 		return (AF_IPX);
196 	case LINUX_AF_APPLETALK:
197 		return (AF_APPLETALK);
198 	}
199 	return (-1);
200 }
201 
202 static int
203 bsd_to_linux_domain(int domain)
204 {
205 
206 	switch (domain) {
207 	case AF_UNSPEC:
208 		return (LINUX_AF_UNSPEC);
209 	case AF_LOCAL:
210 		return (LINUX_AF_UNIX);
211 	case AF_INET:
212 		return (LINUX_AF_INET);
213 	case AF_INET6:
214 		return (LINUX_AF_INET6);
215 	case AF_CCITT:
216 		return (LINUX_AF_AX25);
217 	case AF_IPX:
218 		return (LINUX_AF_IPX);
219 	case AF_APPLETALK:
220 		return (LINUX_AF_APPLETALK);
221 	}
222 	return (-1);
223 }
224 
225 static int
226 linux_to_bsd_sockopt_level(int level)
227 {
228 
229 	switch (level) {
230 	case LINUX_SOL_SOCKET:
231 		return (SOL_SOCKET);
232 	}
233 	return (level);
234 }
235 
236 static int
237 bsd_to_linux_sockopt_level(int level)
238 {
239 
240 	switch (level) {
241 	case SOL_SOCKET:
242 		return (LINUX_SOL_SOCKET);
243 	}
244 	return (level);
245 }
246 
247 #ifndef __alpha__
248 static int
249 linux_to_bsd_ip_sockopt(int opt)
250 {
251 
252 	switch (opt) {
253 	case LINUX_IP_TOS:
254 		return (IP_TOS);
255 	case LINUX_IP_TTL:
256 		return (IP_TTL);
257 	case LINUX_IP_OPTIONS:
258 		return (IP_OPTIONS);
259 	case LINUX_IP_MULTICAST_IF:
260 		return (IP_MULTICAST_IF);
261 	case LINUX_IP_MULTICAST_TTL:
262 		return (IP_MULTICAST_TTL);
263 	case LINUX_IP_MULTICAST_LOOP:
264 		return (IP_MULTICAST_LOOP);
265 	case LINUX_IP_ADD_MEMBERSHIP:
266 		return (IP_ADD_MEMBERSHIP);
267 	case LINUX_IP_DROP_MEMBERSHIP:
268 		return (IP_DROP_MEMBERSHIP);
269 	case LINUX_IP_HDRINCL:
270 		return (IP_HDRINCL);
271 	}
272 	return (-1);
273 }
274 
275 static int
276 linux_to_bsd_so_sockopt(int opt)
277 {
278 
279 	switch (opt) {
280 	case LINUX_SO_DEBUG:
281 		return (SO_DEBUG);
282 	case LINUX_SO_REUSEADDR:
283 		return (SO_REUSEADDR);
284 	case LINUX_SO_TYPE:
285 		return (SO_TYPE);
286 	case LINUX_SO_ERROR:
287 		return (SO_ERROR);
288 	case LINUX_SO_DONTROUTE:
289 		return (SO_DONTROUTE);
290 	case LINUX_SO_BROADCAST:
291 		return (SO_BROADCAST);
292 	case LINUX_SO_SNDBUF:
293 		return (SO_SNDBUF);
294 	case LINUX_SO_RCVBUF:
295 		return (SO_RCVBUF);
296 	case LINUX_SO_KEEPALIVE:
297 		return (SO_KEEPALIVE);
298 	case LINUX_SO_OOBINLINE:
299 		return (SO_OOBINLINE);
300 	case LINUX_SO_LINGER:
301 		return (SO_LINGER);
302 	}
303 	return (-1);
304 }
305 #endif /* !__alpha__*/
306 
307 static int
308 linux_to_bsd_msg_flags(int flags)
309 {
310 	int ret_flags = 0;
311 
312 	if (flags & LINUX_MSG_OOB)
313 		ret_flags |= MSG_OOB;
314 	if (flags & LINUX_MSG_PEEK)
315 		ret_flags |= MSG_PEEK;
316 	if (flags & LINUX_MSG_DONTROUTE)
317 		ret_flags |= MSG_DONTROUTE;
318 	if (flags & LINUX_MSG_CTRUNC)
319 		ret_flags |= MSG_CTRUNC;
320 	if (flags & LINUX_MSG_TRUNC)
321 		ret_flags |= MSG_TRUNC;
322 	if (flags & LINUX_MSG_DONTWAIT)
323 		ret_flags |= MSG_DONTWAIT;
324 	if (flags & LINUX_MSG_EOR)
325 		ret_flags |= MSG_EOR;
326 	if (flags & LINUX_MSG_WAITALL)
327 		ret_flags |= MSG_WAITALL;
328 	if (flags & LINUX_MSG_NOSIGNAL)
329 		ret_flags |= MSG_NOSIGNAL;
330 #if 0 /* not handled */
331 	if (flags & LINUX_MSG_PROXY)
332 		;
333 	if (flags & LINUX_MSG_FIN)
334 		;
335 	if (flags & LINUX_MSG_SYN)
336 		;
337 	if (flags & LINUX_MSG_CONFIRM)
338 		;
339 	if (flags & LINUX_MSG_RST)
340 		;
341 	if (flags & LINUX_MSG_ERRQUEUE)
342 		;
343 #endif
344 	return ret_flags;
345 }
346 
347 /*
348 * If bsd_to_linux_sockaddr() or linux_to_bsd_sockaddr() faults, then the
349 * native syscall will fault.  Thus, we don't really need to check the
350 * return values for these functions.
351 */
352 
353 static int
354 bsd_to_linux_sockaddr(struct sockaddr *arg)
355 {
356 	struct sockaddr sa;
357 	size_t sa_len = sizeof(struct sockaddr);
358 	int error;
359 
360 	if ((error = copyin(arg, &sa, sa_len)))
361 		return (error);
362 
363 	*(u_short *)&sa = sa.sa_family;
364 
365 	error = copyout(&sa, arg, sa_len);
366 
367 	return (error);
368 }
369 
370 static int
371 linux_to_bsd_sockaddr(struct sockaddr *arg, int len)
372 {
373 	struct sockaddr sa;
374 	size_t sa_len = sizeof(struct sockaddr);
375 	int error;
376 
377 	if ((error = copyin(arg, &sa, sa_len)))
378 		return (error);
379 
380 	sa.sa_family = *(sa_family_t *)&sa;
381 	sa.sa_len = len;
382 
383 	error = copyout(&sa, arg, sa_len);
384 
385 	return (error);
386 }
387 
388 
389 static int
390 linux_sa_put(struct osockaddr *osa)
391 {
392 	struct osockaddr sa;
393 	int error, bdom;
394 
395 	/*
396 	 * Only read/write the osockaddr family part, the rest is
397 	 * not changed.
398 	 */
399 	error = copyin(osa, &sa, sizeof(sa.sa_family));
400 	if (error)
401 		return (error);
402 
403 	bdom = bsd_to_linux_domain(sa.sa_family);
404 	if (bdom == -1)
405 		return (EINVAL);
406 
407 	sa.sa_family = bdom;
408 	error = copyout(&sa, osa, sizeof(sa.sa_family));
409 	if (error)
410 		return (error);
411 
412 	return (0);
413 }
414 
415 static int
416 linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
417     enum uio_seg segflg)
418 {
419 	struct mbuf *control;
420 	struct sockaddr *to;
421 	int error;
422 
423 	if (mp->msg_name != NULL) {
424 		error = linux_getsockaddr(&to, mp->msg_name, mp->msg_namelen);
425 		if (error)
426 			return (error);
427 		mp->msg_name = to;
428 	} else
429 		to = NULL;
430 
431 	if (mp->msg_control != NULL) {
432 		struct cmsghdr *cmsg;
433 
434 		if (mp->msg_controllen < sizeof(struct cmsghdr)) {
435 			error = EINVAL;
436 			goto bad;
437 		}
438 		error = sockargs(&control, mp->msg_control,
439 		    mp->msg_controllen, MT_CONTROL);
440 		if (error)
441 			goto bad;
442 
443 		cmsg = mtod(control, struct cmsghdr *);
444 		cmsg->cmsg_level = linux_to_bsd_sockopt_level(cmsg->cmsg_level);
445 	} else
446 		control = NULL;
447 
448 	error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control,
449 	    segflg);
450 
451 bad:
452 	if (to)
453 		FREE(to, M_SONAME);
454 	return (error);
455 }
456 
457 #ifndef __alpha__
458 /* Return 0 if IP_HDRINCL is set for the given socket. */
459 static int
460 linux_check_hdrincl(struct thread *td, int s)
461 {
462 	int error, optval, size_val;
463 
464 	size_val = sizeof(optval);
465 	error = kern_getsockopt(td, s, IPPROTO_IP, IP_HDRINCL,
466 	    &optval, UIO_SYSSPACE, &size_val);
467 	if (error)
468 		return (error);
469 
470 	return (optval == 0);
471 }
472 
473 struct linux_sendto_args {
474 	int s;
475 	l_uintptr_t msg;
476 	int len;
477 	int flags;
478 	l_uintptr_t to;
479 	int tolen;
480 };
481 
482 /*
483  * Updated sendto() when IP_HDRINCL is set:
484  * tweak endian-dependent fields in the IP packet.
485  */
486 static int
487 linux_sendto_hdrincl(struct thread *td, struct linux_sendto_args *linux_args)
488 {
489 /*
490  * linux_ip_copysize defines how many bytes we should copy
491  * from the beginning of the IP packet before we customize it for BSD.
492  * It should include all the fields we modify (ip_len and ip_off).
493  */
494 #define linux_ip_copysize	8
495 
496 	struct ip *packet;
497 	struct msghdr msg;
498 	struct iovec aiov[1];
499 	int error;
500 
501 	/* Check that the packet isn't too big or too small. */
502 	if (linux_args->len < linux_ip_copysize ||
503 	    linux_args->len > IP_MAXPACKET)
504 		return (EINVAL);
505 
506 	packet = (struct ip *)malloc(linux_args->len, M_TEMP, M_WAITOK);
507 
508 	/* Make kernel copy of the packet to be sent */
509 	if ((error = copyin(PTRIN(linux_args->msg), packet,
510 	    linux_args->len)))
511 		goto goout;
512 
513 	/* Convert fields from Linux to BSD raw IP socket format */
514 	packet->ip_len = linux_args->len;
515 	packet->ip_off = ntohs(packet->ip_off);
516 
517 	/* Prepare the msghdr and iovec structures describing the new packet */
518 	msg.msg_name = PTRIN(linux_args->to);
519 	msg.msg_namelen = linux_args->tolen;
520 	msg.msg_iov = aiov;
521 	msg.msg_iovlen = 1;
522 	msg.msg_control = NULL;
523 	msg.msg_flags = 0;
524 	aiov[0].iov_base = (char *)packet;
525 	aiov[0].iov_len = linux_args->len;
526 	error = linux_sendit(td, linux_args->s, &msg, linux_args->flags,
527 	    UIO_SYSSPACE);
528 goout:
529 	free(packet, M_TEMP);
530 	return (error);
531 }
532 
533 struct linux_socket_args {
534 	int domain;
535 	int type;
536 	int protocol;
537 };
538 
539 static int
540 linux_socket(struct thread *td, struct linux_socket_args *args)
541 {
542 	struct linux_socket_args linux_args;
543 	struct socket_args /* {
544 		int domain;
545 		int type;
546 		int protocol;
547 	} */ bsd_args;
548 	int error;
549 	int retval_socket;
550 
551 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
552 		return (error);
553 
554 	bsd_args.protocol = linux_args.protocol;
555 	bsd_args.type = linux_args.type;
556 	bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
557 	if (bsd_args.domain == -1)
558 		return (EINVAL);
559 
560 	retval_socket = socket(td, &bsd_args);
561 	if (bsd_args.type == SOCK_RAW
562 	    && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)
563 	    && bsd_args.domain == AF_INET
564 	    && retval_socket >= 0) {
565 		/* It's a raw IP socket: set the IP_HDRINCL option. */
566 		int hdrincl;
567 
568 		hdrincl = 1;
569 		/* We ignore any error returned by kern_setsockopt() */
570 		kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL,
571 		    &hdrincl, UIO_SYSSPACE, sizeof(hdrincl));
572 	}
573 #ifdef INET6
574 	/*
575 	 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by
576 	 * default and some apps depend on this. So, set V6ONLY to 0
577 	 * for Linux apps if the sysctl value is set to 1.
578 	 */
579 	if (bsd_args.domain == PF_INET6 && retval_socket >= 0
580 #ifndef KLD_MODULE
581 	    /*
582 	     * XXX: Avoid undefined symbol error with an IPv4 only
583 	     * kernel.
584 	     */
585 	    && ip6_v6only
586 #endif
587 	    ) {
588 		int v6only;
589 
590 		v6only = 0;
591 		/* We ignore any error returned by setsockopt() */
592 		kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY,
593 		    &v6only, UIO_SYSSPACE, sizeof(v6only));
594 	}
595 #endif
596 
597 	return (retval_socket);
598 }
599 
600 struct linux_bind_args {
601 	int s;
602 	l_uintptr_t name;
603 	int namelen;
604 };
605 
606 static int
607 linux_bind(struct thread *td, struct linux_bind_args *args)
608 {
609 	struct linux_bind_args linux_args;
610 	struct sockaddr *sa;
611 	int error;
612 
613 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
614 		return (error);
615 
616 	error = linux_getsockaddr(&sa, PTRIN(linux_args.name),
617 	    linux_args.namelen);
618 	if (error)
619 		return (error);
620 
621 	return (kern_bind(td, linux_args.s, sa));
622 }
623 #endif /* !__alpha__*/
624 
625 struct l_connect_args {
626 	int s;
627 	l_uintptr_t name;
628 	int namelen;
629 };
630 #ifndef __alpha__
631 #define	linux_connect_args l_connect_args
632 int linux_connect(struct thread *, struct linux_connect_args *);
633 #endif /* !__alpha__*/
634 
635 int
636 linux_connect(struct thread *td, struct linux_connect_args *args)
637 {
638 	struct l_connect_args linux_args;
639 	struct socket *so;
640 	struct sockaddr *sa;
641 	u_int fflag;
642 	int error;
643 
644 #ifdef __alpha__
645 	bcopy(args, &linux_args, sizeof(linux_args));
646 #else
647 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
648 		return (error);
649 #endif /* __alpha__ */
650 
651 	error = linux_getsockaddr(&sa,
652 	    (struct osockaddr *)PTRIN(linux_args.name),
653 	    linux_args.namelen);
654 	if (error)
655 		return (error);
656 
657 	error = kern_connect(td, linux_args.s, sa);
658 	if (error != EISCONN)
659 		return (error);
660 
661 	/*
662 	 * Linux doesn't return EISCONN the first time it occurs,
663 	 * when on a non-blocking socket. Instead it returns the
664 	 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
665 	 *
666 	 * XXXRW: Instead of using fgetsock(), check that it is a
667 	 * socket and use the file descriptor reference instead of
668 	 * creating a new one.
669 	 */
670 	NET_LOCK_GIANT();
671 	error = fgetsock(td, linux_args.s, &so, &fflag);
672 	if (error == 0) {
673 		error = EISCONN;
674 		if (fflag & FNONBLOCK) {
675 			SOCK_LOCK(so);
676 			if (so->so_emuldata == 0)
677 				error = so->so_error;
678 			so->so_emuldata = (void *)1;
679 			SOCK_UNLOCK(so);
680 		}
681 		fputsock(so);
682 	}
683 	NET_UNLOCK_GIANT();
684 	return (error);
685 }
686 
687 #ifndef __alpha__
688 struct linux_listen_args {
689 	int s;
690 	int backlog;
691 };
692 
693 static int
694 linux_listen(struct thread *td, struct linux_listen_args *args)
695 {
696 	struct linux_listen_args linux_args;
697 	struct listen_args /* {
698 		int s;
699 		int backlog;
700 	} */ bsd_args;
701 	int error;
702 
703 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
704 		return (error);
705 
706 	bsd_args.s = linux_args.s;
707 	bsd_args.backlog = linux_args.backlog;
708 	return (listen(td, &bsd_args));
709 }
710 #endif /* !__alpha__*/
711 
712 struct l_accept_args {
713 	int s;
714 	l_uintptr_t addr;
715 	l_uintptr_t namelen;
716 };
717 
718 #ifndef __alpha__
719 #define	linux_accept_args l_accept_args
720 #endif
721 
722 STATIC int
723 linux_accept(struct thread *td, struct linux_accept_args *args)
724 {
725 	struct l_accept_args linux_args;
726 	struct accept_args /* {
727 		int	s;
728 		struct sockaddr * __restrict name;
729 		socklen_t * __restrict anamelen;
730 	} */ bsd_args;
731 	struct close_args /* {
732 		int     fd;
733 	} */ c_args;
734 	int error, fd;
735 
736 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
737 		return (error);
738 
739 	bsd_args.s = linux_args.s;
740 	/* XXX: */
741 	bsd_args.name = (struct sockaddr * __restrict)PTRIN(linux_args.addr);
742 	bsd_args.anamelen = PTRIN(linux_args.namelen);/* XXX */
743 	error = accept(td, &bsd_args);
744 	bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.name);
745 	if (error)
746 		return (error);
747 	if (linux_args.addr) {
748 		error = linux_sa_put(PTRIN(linux_args.addr));
749 		if (error) {
750 			c_args.fd = td->td_retval[0];
751 			(void)close(td, &c_args);
752 			return (error);
753 		}
754 	}
755 
756 	/*
757 	 * linux appears not to copy flags from the parent socket to the
758 	 * accepted one, so we must clear the flags in the new descriptor.
759 	 * Ignore any errors, because we already have an open fd.
760 	 */
761 	fd = td->td_retval[0];
762 	(void)kern_fcntl(td, fd, F_SETFL, 0);
763 	td->td_retval[0] = fd;
764 	return (0);
765 }
766 
767 struct l_getsockname_args {
768 	int s;
769 	l_uintptr_t addr;
770 	l_uintptr_t namelen;
771 };
772 
773 #ifndef __alpha__
774 #define linux_getsockname_args l_getsockname_args
775 #endif
776 
777 STATIC int
778 linux_getsockname(struct thread *td, struct linux_getsockname_args *args)
779 {
780 	struct l_getsockname_args linux_args;
781 	struct getsockname_args /* {
782 		int	fdes;
783 		struct sockaddr * __restrict asa;
784 		socklen_t * __restrict alen;
785 	} */ bsd_args;
786 	int error;
787 
788 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
789 		return (error);
790 
791 	bsd_args.fdes = linux_args.s;
792 	/* XXX: */
793 	bsd_args.asa = (struct sockaddr * __restrict)PTRIN(linux_args.addr);
794 	bsd_args.alen = PTRIN(linux_args.namelen);	/* XXX */
795 	error = getsockname(td, &bsd_args);
796 	bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa);
797 	if (error)
798 		return (error);
799 	error = linux_sa_put(PTRIN(linux_args.addr));
800 	if (error)
801 		return (error);
802 	return (0);
803 }
804 
805 struct l_getpeername_args {
806 	int s;
807 	l_uintptr_t addr;
808 	l_uintptr_t namelen;
809 };
810 
811 #ifndef __alpha__
812 #define linux_getpeername_args l_getpeername_args
813 #endif
814 
815 STATIC int
816 linux_getpeername(struct thread *td, struct linux_getpeername_args *args)
817 {
818 	struct l_getpeername_args linux_args;
819 	struct getpeername_args /* {
820 		int fdes;
821 		caddr_t asa;
822 		int *alen;
823 	} */ bsd_args;
824 	int error;
825 
826 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
827 		return (error);
828 
829 	bsd_args.fdes = linux_args.s;
830 	bsd_args.asa = (struct sockaddr *)PTRIN(linux_args.addr);
831 	bsd_args.alen = (int *)PTRIN(linux_args.namelen);
832 	error = getpeername(td, &bsd_args);
833 	bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa);
834 	if (error)
835 		return (error);
836 	error = linux_sa_put(PTRIN(linux_args.addr));
837 	if (error)
838 		return (error);
839 	return (0);
840 }
841 
842 struct l_socketpair_args {
843 	int domain;
844 	int type;
845 	int protocol;
846 	l_uintptr_t rsv;
847 };
848 
849 #ifndef __alpha__
850 #define linux_socketpair_args l_socketpair_args
851 #endif
852 
853 STATIC int
854 linux_socketpair(struct thread *td, struct linux_socketpair_args *args)
855 {
856 	struct l_socketpair_args linux_args;
857 	struct socketpair_args /* {
858 		int domain;
859 		int type;
860 		int protocol;
861 		int *rsv;
862 	} */ bsd_args;
863 	int error;
864 
865 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
866 		return (error);
867 
868 	bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
869 	if (bsd_args.domain == -1)
870 		return (EINVAL);
871 
872 	bsd_args.type = linux_args.type;
873 	bsd_args.protocol = linux_args.protocol;
874 	bsd_args.rsv = (int *)PTRIN(linux_args.rsv);
875 	return (socketpair(td, &bsd_args));
876 }
877 
878 struct l_send_args {
879 	int s;
880 	l_uintptr_t msg;
881 	int len;
882 	int flags;
883 };
884 
885 #ifndef __alpha__
886 #define linux_send_args l_send_args
887 #endif
888 
889 STATIC int
890 linux_send(struct thread *td, struct linux_send_args *args)
891 {
892 	struct l_send_args linux_args;
893 	struct sendto_args /* {
894 		int s;
895 		caddr_t buf;
896 		int len;
897 		int flags;
898 		caddr_t to;
899 		int tolen;
900 	} */ bsd_args;
901 	int error;
902 
903 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
904 		return (error);
905 
906 	bsd_args.s = linux_args.s;
907 	bsd_args.buf = (caddr_t)PTRIN(linux_args.msg);
908 	bsd_args.len = linux_args.len;
909 	bsd_args.flags = linux_args.flags;
910 	bsd_args.to = NULL;
911 	bsd_args.tolen = 0;
912 	return sendto(td, &bsd_args);
913 }
914 
915 struct l_recv_args {
916 	int s;
917 	l_uintptr_t msg;
918 	int len;
919 	int flags;
920 };
921 
922 #ifndef __alpha__
923 #define linux_recv_args l_recv_args
924 #endif
925 
926 STATIC int
927 linux_recv(struct thread *td, struct linux_recv_args *args)
928 {
929 	struct l_recv_args linux_args;
930 	struct recvfrom_args /* {
931 		int s;
932 		caddr_t buf;
933 		int len;
934 		int flags;
935 		struct sockaddr *from;
936 		socklen_t fromlenaddr;
937 	} */ bsd_args;
938 	int error;
939 
940 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
941 		return (error);
942 
943 	bsd_args.s = linux_args.s;
944 	bsd_args.buf = (caddr_t)PTRIN(linux_args.msg);
945 	bsd_args.len = linux_args.len;
946 	bsd_args.flags = linux_args.flags;
947 	bsd_args.from = NULL;
948 	bsd_args.fromlenaddr = 0;
949 	return (recvfrom(td, &bsd_args));
950 }
951 
952 #ifndef __alpha__
953 static int
954 linux_sendto(struct thread *td, struct linux_sendto_args *args)
955 {
956 	struct linux_sendto_args linux_args;
957 	struct msghdr msg;
958 	struct iovec aiov;
959 	int error;
960 
961 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
962 		return (error);
963 
964 	if (linux_check_hdrincl(td, linux_args.s) == 0)
965 		/* IP_HDRINCL set, tweak the packet before sending */
966 		return (linux_sendto_hdrincl(td, &linux_args));
967 
968 	msg.msg_name = PTRIN(linux_args.to);
969 	msg.msg_namelen = linux_args.tolen;
970 	msg.msg_iov = &aiov;
971 	msg.msg_iovlen = 1;
972 	msg.msg_control = NULL;
973 	msg.msg_flags = 0;
974 	aiov.iov_base = PTRIN(linux_args.msg);
975 	aiov.iov_len = linux_args.len;
976 	error = linux_sendit(td, linux_args.s, &msg, linux_args.flags,
977 	    UIO_USERSPACE);
978 	return (error);
979 }
980 #endif /* !__alpha__*/
981 
982 struct l_recvfrom_args {
983 	int s;
984 	l_uintptr_t buf;
985 	int len;
986 	int flags;
987 	l_uintptr_t from;
988 	l_uintptr_t fromlen;
989 };
990 
991 #ifndef __alpha__
992 #define linux_recvfrom_args l_recvfrom_args
993 #endif
994 
995 STATIC int
996 linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
997 {
998 	struct l_recvfrom_args linux_args;
999 	struct recvfrom_args /* {
1000 		int	s;
1001 		caddr_t	buf;
1002 		size_t	len;
1003 		int	flags;
1004 		struct sockaddr * __restrict from;
1005 		socklen_t * __restrict fromlenaddr;
1006 	} */ bsd_args;
1007 	size_t len;
1008 	int error;
1009 
1010 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
1011 		return (error);
1012 
1013 	if ((error = copyin(PTRIN(linux_args.fromlen), &len, sizeof(size_t))))
1014 		return (error);
1015 
1016 	bsd_args.s = linux_args.s;
1017 	bsd_args.buf = PTRIN(linux_args.buf);
1018 	bsd_args.len = linux_args.len;
1019 	bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
1020 	/* XXX: */
1021 	bsd_args.from = (struct sockaddr * __restrict)PTRIN(linux_args.from);
1022 	bsd_args.fromlenaddr = PTRIN(linux_args.fromlen);/* XXX */
1023 
1024 	linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.from, len);
1025 	error = recvfrom(td, &bsd_args);
1026 	bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.from);
1027 
1028 	if (error)
1029 		return (error);
1030 	if (linux_args.from) {
1031 		error = linux_sa_put((struct osockaddr *)
1032 		    PTRIN(linux_args.from));
1033 		if (error)
1034 			return (error);
1035 	}
1036 	return (0);
1037 }
1038 
1039 struct l_sendmsg_args {
1040 	int s;
1041 	l_uintptr_t msg;
1042 	int flags;
1043 };
1044 
1045 #ifndef __alpha__
1046 #define linux_sendmsg_args l_sendmsg_args
1047 #endif
1048 
1049 STATIC int
1050 linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
1051 {
1052 	struct l_sendmsg_args linux_args;
1053 	struct msghdr msg;
1054 	struct iovec *iov;
1055 	int error;
1056 
1057 	/* XXXTJR sendmsg is broken on amd64 */
1058 
1059 	error = copyin(args, &linux_args, sizeof(linux_args));
1060 	if (error)
1061 		return (error);
1062 	error = copyin(PTRIN(linux_args.msg), &msg, sizeof(msg));
1063 	if (error)
1064 		return (error);
1065 	error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
1066 	if (error)
1067 		return (error);
1068 	msg.msg_iov = iov;
1069 	msg.msg_flags = 0;
1070 	error = linux_sendit(td, linux_args.s, &msg, linux_args.flags,
1071 	    UIO_USERSPACE);
1072 	free(iov, M_IOV);
1073 	return (error);
1074 }
1075 
1076 struct l_recvmsg_args {
1077 	int s;
1078 	l_uintptr_t msg;
1079 	int flags;
1080 };
1081 
1082 #ifndef __alpha__
1083 #define linux_recvmsg_args l_recvmsg_args
1084 #endif
1085 
1086 STATIC int
1087 linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
1088 {
1089 	struct l_recvmsg_args linux_args;
1090 	struct recvmsg_args /* {
1091 		int	s;
1092 		struct	msghdr *msg;
1093 		int	flags;
1094 	} */ bsd_args;
1095 	struct msghdr msg;
1096 	struct cmsghdr *cmsg;
1097 	int error;
1098 
1099 	/* XXXTJR recvmsg is broken on amd64 */
1100 
1101 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
1102 		return (error);
1103 
1104 	bsd_args.s = linux_args.s;
1105 	bsd_args.msg = PTRIN(linux_args.msg);
1106 	bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
1107 	if (msg.msg_name) {
1108 	   	linux_to_bsd_sockaddr((struct sockaddr *)msg.msg_name,
1109 		      msg.msg_namelen);
1110 		error = recvmsg(td, &bsd_args);
1111 		bsd_to_linux_sockaddr((struct sockaddr *)msg.msg_name);
1112 	} else
1113 	   	error = recvmsg(td, &bsd_args);
1114 	if (error)
1115 		return (error);
1116 
1117 	if (bsd_args.msg->msg_control != NULL &&
1118 	    bsd_args.msg->msg_controllen > 0) {
1119 		cmsg = (struct cmsghdr*)bsd_args.msg->msg_control;
1120 		cmsg->cmsg_level = bsd_to_linux_sockopt_level(cmsg->cmsg_level);
1121 	}
1122 
1123 	error = copyin(PTRIN(linux_args.msg), &msg, sizeof(msg));
1124 	if (error)
1125 		return (error);
1126 	if (msg.msg_name && msg.msg_namelen > 2)
1127 		error = linux_sa_put(msg.msg_name);
1128 	return (error);
1129 }
1130 
1131 #ifndef __alpha__
1132 struct linux_shutdown_args {
1133 	int s;
1134 	int how;
1135 };
1136 
1137 static int
1138 linux_shutdown(struct thread *td, struct linux_shutdown_args *args)
1139 {
1140 	struct linux_shutdown_args linux_args;
1141 	struct shutdown_args /* {
1142 		int s;
1143 		int how;
1144 	} */ bsd_args;
1145 	int error;
1146 
1147 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
1148 		return (error);
1149 
1150 	bsd_args.s = linux_args.s;
1151 	bsd_args.how = linux_args.how;
1152 	return (shutdown(td, &bsd_args));
1153 }
1154 
1155 struct linux_setsockopt_args {
1156 	int s;
1157 	int level;
1158 	int optname;
1159 	l_uintptr_t optval;
1160 	int optlen;
1161 };
1162 
1163 static int
1164 linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
1165 {
1166 	struct linux_setsockopt_args linux_args;
1167 	struct setsockopt_args /* {
1168 		int s;
1169 		int level;
1170 		int name;
1171 		caddr_t val;
1172 		int valsize;
1173 	} */ bsd_args;
1174 	int error, name;
1175 
1176 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
1177 		return (error);
1178 
1179 	bsd_args.s = linux_args.s;
1180 	bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
1181 	switch (bsd_args.level) {
1182 	case SOL_SOCKET:
1183 		name = linux_to_bsd_so_sockopt(linux_args.optname);
1184 		break;
1185 	case IPPROTO_IP:
1186 		name = linux_to_bsd_ip_sockopt(linux_args.optname);
1187 		break;
1188 	case IPPROTO_TCP:
1189 		/* Linux TCP option values match BSD's */
1190 		name = linux_args.optname;
1191 		break;
1192 	default:
1193 		name = -1;
1194 		break;
1195 	}
1196 	if (name == -1)
1197 		return (EINVAL);
1198 
1199 	bsd_args.name = name;
1200 	bsd_args.val = PTRIN(linux_args.optval);
1201 	bsd_args.valsize = linux_args.optlen;
1202 
1203 	if (name == IPV6_NEXTHOP) {
1204 		linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.val,
1205 			bsd_args.valsize);
1206 		error = setsockopt(td, &bsd_args);
1207 		bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val);
1208 	} else
1209 		error = setsockopt(td, &bsd_args);
1210 
1211 	return (error);
1212 }
1213 
1214 struct linux_getsockopt_args {
1215 	int s;
1216 	int level;
1217 	int optname;
1218 	l_uintptr_t optval;
1219 	l_uintptr_t optlen;
1220 };
1221 
1222 static int
1223 linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
1224 {
1225 	struct linux_getsockopt_args linux_args;
1226 	struct getsockopt_args /* {
1227 		int s;
1228 		int level;
1229 		int name;
1230 		caddr_t val;
1231 		int *avalsize;
1232 	} */ bsd_args;
1233 	int error, name;
1234 
1235 	if ((error = copyin(args, &linux_args, sizeof(linux_args))))
1236 		return (error);
1237 
1238 	bsd_args.s = linux_args.s;
1239 	bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
1240 	switch (bsd_args.level) {
1241 	case SOL_SOCKET:
1242 		name = linux_to_bsd_so_sockopt(linux_args.optname);
1243 		break;
1244 	case IPPROTO_IP:
1245 		name = linux_to_bsd_ip_sockopt(linux_args.optname);
1246 		break;
1247 	case IPPROTO_TCP:
1248 		/* Linux TCP option values match BSD's */
1249 		name = linux_args.optname;
1250 		break;
1251 	default:
1252 		name = -1;
1253 		break;
1254 	}
1255 	if (name == -1)
1256 		return (EINVAL);
1257 
1258 	bsd_args.name = name;
1259 	bsd_args.val = PTRIN(linux_args.optval);
1260 	bsd_args.avalsize = PTRIN(linux_args.optlen);
1261 
1262 	if (name == IPV6_NEXTHOP) {
1263 		error = getsockopt(td, &bsd_args);
1264 		bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val);
1265 	} else
1266 		error = getsockopt(td, &bsd_args);
1267 
1268 	return (error);
1269 }
1270 
1271 int
1272 linux_socketcall(struct thread *td, struct linux_socketcall_args *args)
1273 {
1274 	void *arg = (void *)(intptr_t)args->args;
1275 
1276 	switch (args->what) {
1277 	case LINUX_SOCKET:
1278 		return (linux_socket(td, arg));
1279 	case LINUX_BIND:
1280 		return (linux_bind(td, arg));
1281 	case LINUX_CONNECT:
1282 		return (linux_connect(td, arg));
1283 	case LINUX_LISTEN:
1284 		return (linux_listen(td, arg));
1285 	case LINUX_ACCEPT:
1286 		return (linux_accept(td, arg));
1287 	case LINUX_GETSOCKNAME:
1288 		return (linux_getsockname(td, arg));
1289 	case LINUX_GETPEERNAME:
1290 		return (linux_getpeername(td, arg));
1291 	case LINUX_SOCKETPAIR:
1292 		return (linux_socketpair(td, arg));
1293 	case LINUX_SEND:
1294 		return (linux_send(td, arg));
1295 	case LINUX_RECV:
1296 		return (linux_recv(td, arg));
1297 	case LINUX_SENDTO:
1298 		return (linux_sendto(td, arg));
1299 	case LINUX_RECVFROM:
1300 		return (linux_recvfrom(td, arg));
1301 	case LINUX_SHUTDOWN:
1302 		return (linux_shutdown(td, arg));
1303 	case LINUX_SETSOCKOPT:
1304 		return (linux_setsockopt(td, arg));
1305 	case LINUX_GETSOCKOPT:
1306 		return (linux_getsockopt(td, arg));
1307 	case LINUX_SENDMSG:
1308 		return (linux_sendmsg(td, arg));
1309 	case LINUX_RECVMSG:
1310 		return (linux_recvmsg(td, arg));
1311 	}
1312 
1313 	uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
1314 	return (ENOSYS);
1315 }
1316 #endif /*!__alpha__*/
1317