xref: /netbsd-src/sys/compat/linux/common/linux_socket.c (revision de2138164cd16145ee5fd4d0aef1e8f952c1a9fb)
1 /*	$NetBSD: linux_socket.c,v 1.70 2007/02/11 08:00:59 mlelstv Exp $	*/
2 
3 /*-
4  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Frank van der Linden and Eric Haszlakiewicz.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * Functions in multiarch:
41  *	linux_sys_socketcall		: linux_socketcall.c
42  */
43 
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.70 2007/02/11 08:00:59 mlelstv Exp $");
46 
47 #if defined(_KERNEL_OPT)
48 #include "opt_inet.h"
49 #endif
50 
51 #include <sys/param.h>
52 #include <sys/kernel.h>
53 #include <sys/systm.h>
54 #include <sys/buf.h>
55 #include <sys/malloc.h>
56 #include <sys/ioctl.h>
57 #include <sys/tty.h>
58 #include <sys/file.h>
59 #include <sys/filedesc.h>
60 #include <sys/select.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/domain.h>
64 #include <net/if.h>
65 #include <net/if_dl.h>
66 #include <net/if_types.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
69 #include <sys/mount.h>
70 #include <sys/proc.h>
71 #include <sys/vnode.h>
72 #include <sys/device.h>
73 #include <sys/protosw.h>
74 #include <sys/mbuf.h>
75 #include <sys/syslog.h>
76 #include <sys/exec.h>
77 #include <sys/kauth.h>
78 
79 #include <sys/syscallargs.h>
80 
81 #include <lib/libkern/libkern.h>
82 
83 #ifdef INET6
84 #include <netinet/ip6.h>
85 #include <netinet6/ip6_var.h>
86 #endif
87 
88 #include <compat/sys/socket.h>
89 
90 #include <compat/linux/common/linux_types.h>
91 #include <compat/linux/common/linux_util.h>
92 #include <compat/linux/common/linux_signal.h>
93 #include <compat/linux/common/linux_ioctl.h>
94 #include <compat/linux/common/linux_socket.h>
95 #if !defined(__alpha__) && !defined(__amd64__)
96 #include <compat/linux/common/linux_socketcall.h>
97 #endif
98 #include <compat/linux/common/linux_sockio.h>
99 
100 #include <compat/linux/linux_syscallargs.h>
101 
102 #ifdef DEBUG_LINUX
103 #define DPRINTF(a) uprintf a
104 #else
105 #define DPRINTF(a)
106 #endif
107 
108 /*
109  * The calls in this file are entered either via the linux_socketcall()
110  * interface or, on the Alpha, as individual syscalls.  The
111  * linux_socketcall function does any massaging of arguments so that all
112  * the calls in here need not think that they are anything other
113  * than a normal syscall.
114  */
115 
116 static int linux_to_bsd_domain __P((int));
117 static int bsd_to_linux_domain __P((int));
118 int linux_to_bsd_sopt_level __P((int));
119 int linux_to_bsd_so_sockopt __P((int));
120 int linux_to_bsd_ip_sockopt __P((int));
121 int linux_to_bsd_tcp_sockopt __P((int));
122 int linux_to_bsd_udp_sockopt __P((int));
123 int linux_getifhwaddr __P((struct lwp *, register_t *, u_int, void *));
124 static int linux_sa_get __P((struct lwp *, int, caddr_t *, struct sockaddr **,
125 		const struct osockaddr *, socklen_t *));
126 static int linux_sa_put __P((struct osockaddr *osa));
127 static int linux_to_bsd_msg_flags __P((int));
128 static int bsd_to_linux_msg_flags __P((int));
129 
130 static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
131 	AF_UNSPEC,
132 	AF_UNIX,
133 	AF_INET,
134 	AF_CCITT,	/* LINUX_AF_AX25 */
135 	AF_IPX,
136 	AF_APPLETALK,
137 	-1,		/* LINUX_AF_NETROM */
138 	-1,		/* LINUX_AF_BRIDGE */
139 	-1,		/* LINUX_AF_ATMPVC */
140 	AF_CCITT,	/* LINUX_AF_X25 */
141 	AF_INET6,
142 	-1,		/* LINUX_AF_ROSE */
143 	AF_DECnet,
144 	-1,		/* LINUX_AF_NETBEUI */
145 	-1,		/* LINUX_AF_SECURITY */
146 	pseudo_AF_KEY,
147 	AF_ROUTE,	/* LINUX_AF_NETLINK */
148 	-1,		/* LINUX_AF_PACKET */
149 	-1,		/* LINUX_AF_ASH */
150 	-1,		/* LINUX_AF_ECONET */
151 	-1,		/* LINUX_AF_ATMSVC */
152 	AF_SNA,
153 	/* rest up to LINUX_AF_MAX-1 is not allocated */
154 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
155 };
156 
157 static const int bsd_to_linux_domain_[AF_MAX] = {
158 	LINUX_AF_UNSPEC,
159 	LINUX_AF_UNIX,
160 	LINUX_AF_INET,
161 	-1,		/* AF_IMPLINK */
162 	-1,		/* AF_PUP */
163 	-1,		/* AF_CHAOS */
164 	-1,		/* AF_NS */
165 	-1,		/* AF_ISO */
166 	-1,		/* AF_ECMA */
167 	-1,		/* AF_DATAKIT */
168 	LINUX_AF_AX25,	/* AF_CCITT */
169 	LINUX_AF_SNA,
170 	LINUX_AF_DECnet,
171 	-1,		/* AF_DLI */
172 	-1,		/* AF_LAT */
173 	-1,		/* AF_HYLINK */
174 	LINUX_AF_APPLETALK,
175 	LINUX_AF_NETLINK,
176 	-1,		/* AF_LINK */
177 	-1,		/* AF_XTP */
178 	-1,		/* AF_COIP */
179 	-1,		/* AF_CNT */
180 	-1,		/* pseudo_AF_RTIP */
181 	LINUX_AF_IPX,
182 	LINUX_AF_INET6,
183 	-1,		/* pseudo_AF_PIP */
184 	-1,		/* AF_ISDN */
185 	-1,		/* AF_NATM */
186 	-1,		/* AF_ARP */
187 	LINUX_pseudo_AF_KEY,
188 	-1,		/* pseudo_AF_HDRCMPLT */
189 };
190 
191 static const struct {
192 	int bfl;
193 	int lfl;
194 } bsd_to_linux_msg_flags_[] = {
195 	{MSG_OOB,		LINUX_MSG_OOB},
196 	{MSG_PEEK,		LINUX_MSG_PEEK},
197 	{MSG_DONTROUTE,		LINUX_MSG_DONTROUTE},
198 	{MSG_EOR,		LINUX_MSG_EOR},
199 	{MSG_TRUNC,		LINUX_MSG_TRUNC},
200 	{MSG_CTRUNC,		LINUX_MSG_CTRUNC},
201 	{MSG_WAITALL,		LINUX_MSG_WAITALL},
202 	{MSG_DONTWAIT,		LINUX_MSG_DONTWAIT},
203 	{MSG_BCAST,		0},		/* not supported, clear */
204 	{MSG_MCAST,		0},		/* not supported, clear */
205 	{-1, /* not supp */	LINUX_MSG_PROBE},
206 	{-1, /* not supp */	LINUX_MSG_FIN},
207 	{-1, /* not supp */	LINUX_MSG_SYN},
208 	{-1, /* not supp */	LINUX_MSG_CONFIRM},
209 	{-1, /* not supp */	LINUX_MSG_RST},
210 	{-1, /* not supp */	LINUX_MSG_ERRQUEUE},
211 	{-1, /* not supp */	LINUX_MSG_NOSIGNAL},
212 	{-1, /* not supp */	LINUX_MSG_MORE},
213 };
214 
215 /*
216  * Convert between Linux and BSD socket domain values
217  */
218 static int
219 linux_to_bsd_domain(ldom)
220 	int ldom;
221 {
222 	if (ldom < 0 || ldom >= LINUX_AF_MAX)
223 		return (-1);
224 
225 	return linux_to_bsd_domain_[ldom];
226 }
227 
228 /*
229  * Convert between BSD and Linux socket domain values
230  */
231 static int
232 bsd_to_linux_domain(bdom)
233 	int bdom;
234 {
235 	if (bdom < 0 || bdom >= AF_MAX)
236 		return (-1);
237 
238 	return bsd_to_linux_domain_[bdom];
239 }
240 
241 static int
242 linux_to_bsd_msg_flags(lflag)
243 	int lflag;
244 {
245 	int i, lfl, bfl;
246 	int bflag = 0;
247 
248 	if (lflag == 0)
249 		return (0);
250 
251 	for(i = 0; i < __arraycount(bsd_to_linux_msg_flags_); i++) {
252 		bfl = bsd_to_linux_msg_flags_[i].bfl;
253 		lfl = bsd_to_linux_msg_flags_[i].lfl;
254 
255 		if (lfl == 0)
256 			continue;
257 
258 		if (lflag & lfl) {
259 			if (bfl < 0)
260 				return (-1);
261 
262 			bflag |= bfl;
263 		}
264 	}
265 
266 	return (bflag);
267 }
268 
269 static int
270 bsd_to_linux_msg_flags(bflag)
271 	int bflag;
272 {
273 	int i, lfl, bfl;
274 	int lflag = 0;
275 
276 	if (bflag == 0)
277 		return (0);
278 
279 	for(i = 0; i < __arraycount(bsd_to_linux_msg_flags_); i++) {
280 		bfl = bsd_to_linux_msg_flags_[i].bfl;
281 		lfl = bsd_to_linux_msg_flags_[i].lfl;
282 
283 		if (bfl <= 0)
284 			continue;
285 
286 		if (bflag & bfl) {
287 			if (lfl < 0)
288 				return (-1);
289 
290 			lflag |= lfl;
291 		}
292 	}
293 
294 	return (lflag);
295 }
296 
297 int
298 linux_sys_socket(l, v, retval)
299 	struct lwp *l;
300 	void *v;
301 	register_t *retval;
302 {
303 	struct linux_sys_socket_args /* {
304 		syscallarg(int)	domain;
305 		syscallarg(int)	type;
306 		syscallarg(int) protocol;
307 	} */ *uap = v;
308 	struct compat_30_sys_socket_args bsa;
309 	int error;
310 
311 	SCARG(&bsa, protocol) = SCARG(uap, protocol);
312 	SCARG(&bsa, type) = SCARG(uap, type);
313 	SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
314 	if (SCARG(&bsa, domain) == -1)
315 		return EINVAL;
316 	error = sys___socket30(l, &bsa, retval);
317 
318 #ifdef INET6
319 	/*
320 	 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by
321 	 * default and some apps depend on this. So, set V6ONLY to 0
322 	 * for Linux apps if the sysctl value is set to 1.
323 	 */
324 	if (!error && ip6_v6only && SCARG(&bsa, domain) == PF_INET6) {
325 		struct proc *p = l->l_proc;
326 		struct file *fp;
327 
328 		if (getsock(p->p_fd, *retval, &fp) == 0) {
329 			struct mbuf *m;
330 
331 			m = m_get(M_WAIT, MT_SOOPTS);
332 			m->m_len = sizeof(int);
333 			*mtod(m, int *) = 0;
334 
335 			/* ignore error */
336 			(void) sosetopt((struct socket *)fp->f_data,
337 				IPPROTO_IPV6, IPV6_V6ONLY, m);
338 
339 			FILE_UNUSE(fp, l);
340 		}
341 	}
342 #endif
343 
344 	return (error);
345 }
346 
347 int
348 linux_sys_socketpair(l, v, retval)
349 	struct lwp *l;
350 	void *v;
351 	register_t *retval;
352 {
353 	struct linux_sys_socketpair_args /* {
354 		syscallarg(int) domain;
355 		syscallarg(int) type;
356 		syscallarg(int) protocol;
357 		syscallarg(int *) rsv;
358 	} */ *uap = v;
359 	struct sys_socketpair_args bsa;
360 
361 	SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
362 	if (SCARG(&bsa, domain) == -1)
363 		return EINVAL;
364 	SCARG(&bsa, type) = SCARG(uap, type);
365 	SCARG(&bsa, protocol) = SCARG(uap, protocol);
366 	SCARG(&bsa, rsv) = SCARG(uap, rsv);
367 
368 	return sys_socketpair(l, &bsa, retval);
369 }
370 
371 int
372 linux_sys_sendto(l, v, retval)
373 	struct lwp *l;
374 	void *v;
375 	register_t *retval;
376 {
377 	struct linux_sys_sendto_args /* {
378 		syscallarg(int)				s;
379 		syscallarg(void *)			msg;
380 		syscallarg(int)				len;
381 		syscallarg(int)				flags;
382 		syscallarg(struct osockaddr *)		to;
383 		syscallarg(int)				tolen;
384 	} */ *uap = v;
385 	struct proc *p = l->l_proc;
386 	struct sys_sendto_args bsa;
387 	socklen_t tolen;
388 
389 	SCARG(&bsa, s) = SCARG(uap, s);
390 	SCARG(&bsa, buf) = SCARG(uap, msg);
391 	SCARG(&bsa, len) = (size_t) SCARG(uap, len);
392 	SCARG(&bsa, flags) = SCARG(uap, flags);
393 	tolen = SCARG(uap, tolen);
394 	if (SCARG(uap, to)) {
395 		struct sockaddr *sa;
396 		int error;
397 		caddr_t sg = stackgap_init(p, 0);
398 
399 		error = linux_sa_get(l, SCARG(uap, s), &sg, &sa,
400 		    SCARG(uap, to), &tolen);
401 		if (error)
402 			return (error);
403 
404 		SCARG(&bsa, to) = sa;
405 	} else
406 		SCARG(&bsa, to) = NULL;
407 	SCARG(&bsa, tolen) = tolen;
408 
409 	return (sys_sendto(l, &bsa, retval));
410 }
411 
412 int
413 linux_sys_sendmsg(l, v, retval)
414 	struct lwp *l;
415 	void *v;
416 	register_t *retval;
417 {
418 	struct linux_sys_sendmsg_args /* {
419 		syscallarg(int) s;
420 		syscallarg(struct msghdr *) msg;
421 		syscallarg(u_int) flags;
422 	} */ *uap = v;
423 	struct proc *p = l->l_proc;
424 	struct msghdr	msg;
425 	int		error;
426 	struct iovec	aiov[UIO_SMALLIOV], *iov;
427 	caddr_t sg = 0;
428 	int		bflags;
429 	u_int8_t	*control=NULL;
430 
431 	error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
432 	if (error)
433 		return (error);
434 	if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
435 		if ((unsigned int)msg.msg_iovlen > IOV_MAX)
436 			return (EMSGSIZE);
437 		iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
438 		    M_IOV, M_WAITOK);
439 	} else
440 		iov = aiov;
441 	if ((unsigned int)msg.msg_iovlen > 0) {
442 		error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
443 		    (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
444 		if (error)
445 			goto done;
446 	}
447 	msg.msg_iov = iov;
448 	msg.msg_flags = 0;
449 
450 	/* Convert the sockaddr if necessary */
451 	if (msg.msg_name) {
452 		struct sockaddr *sa;
453 		sg = stackgap_init(p, 0);
454 
455 		error = linux_sa_get(l, SCARG(uap, s), &sg, &sa,
456 		    (struct osockaddr *) msg.msg_name, &msg.msg_namelen);
457 		if (error)
458 			goto done;
459 		msg.msg_name = sa;
460 	}
461 
462 	/*
463 	 * Translate message flags.
464 	 */
465 	bflags = linux_to_bsd_msg_flags(SCARG(uap, flags));
466 	if (bflags < 0) {
467 		/* Some supported flag */
468 		error = EINVAL;
469 		goto done;
470 	}
471 
472 	/*
473 	 * Handle cmsg if there is any.
474 	 */
475 	if (CMSG_FIRSTHDR(&msg)) {
476 		struct cmsghdr cmsg, *cc;
477 		int changed = 0;
478 		ssize_t resid = msg.msg_controllen;
479 		size_t clen, cidx = 0, cspace;
480 
481 		/*
482 		 * Limit the size even more than what sockargs() would do,
483 		 * We need to fit into stackgap space.
484 		 */
485 		if (msg.msg_controllen > (STACKGAPLEN / 2)) {
486 			/* Sorry guys! */
487 			error = EMSGSIZE;
488 			goto done;
489 		}
490 
491 		control = malloc((clen = msg.msg_controllen), M_TEMP, M_WAITOK);
492 		if (!control) {
493 			error = ENOMEM;
494 			goto done;
495 		}
496 
497 		cc = CMSG_FIRSTHDR(&msg);
498 		do {
499 			error = copyin(cc, &cmsg, sizeof(cmsg));
500 			if (error)
501 				goto done;
502 
503 			/*
504 			 * Sanity check the control message length.
505 			 */
506 			if (cmsg.cmsg_len > resid
507 			    || cmsg.cmsg_len < sizeof(struct cmsghdr)) {
508 				error = EINVAL;
509 				goto done;
510 			}
511 
512 			/*
513 			 * Refuse unsupported control messages, and
514 			 * translate fields as appropriate.
515 			 */
516 			switch (cmsg.cmsg_level) {
517 			case LINUX_SOL_SOCKET:
518 				/* It only differs on some archs */
519 				if (LINUX_SOL_SOCKET != SOL_SOCKET) {
520 					cmsg.cmsg_level = SOL_SOCKET;
521 					changed = 1;
522 				}
523 
524 				switch(cmsg.cmsg_type) {
525 				case LINUX_SCM_RIGHTS:
526 					/* Linux SCM_RIGHTS is same as NetBSD */
527 					break;
528 
529 				default:
530 					/* other types not supported */
531 					error = EINVAL;
532 					goto done;
533 				}
534 				break;
535 			default:
536 				/* pray and leave intact */
537 				break;
538 			}
539 
540 			cspace = CMSG_SPACE(cmsg.cmsg_len - sizeof(cmsg));
541 
542 			/* Check the buffer is big enough */
543 			if (__predict_false(cidx + cspace > clen)) {
544 				u_int8_t *nc;
545 
546 				clen = cidx + cspace;
547 				nc = realloc(control, clen, M_TEMP, M_WAITOK);
548 				if (!nc) {
549 					error = ENOMEM;
550 					goto done;
551 				}
552 				control = nc;
553 			}
554 
555 			/* Copy header */
556 			memcpy(&control[cidx], &cmsg, sizeof(cmsg));
557 
558 			/* Zero are between header and data */
559 			memset(&control[cidx+sizeof(cmsg)], 0,
560 				CMSG_ALIGN(sizeof(cmsg)) - sizeof(cmsg));
561 
562 			/* Copyin the data */
563 			error = copyin(LINUX_CMSG_DATA(cc),
564 				CMSG_DATA(control),
565 				cmsg.cmsg_len - sizeof(cmsg));
566 			if (error)
567 				goto done;
568 
569 			/*
570 			 * If there is alignment difference, we changed
571 			 * layout of cmsg.
572 			 */
573 			if (LINUX_CMSG_ALIGNDIFF)
574 				changed = 1;
575 
576 			resid -= cspace;
577 			cidx += cspace;
578 		} while ((cc = LINUX_CMSG_NXTHDR(&msg, cc)) && resid > 0);
579 
580 		/*
581 		 * If any of the passed control message needed
582 		 * a change, put the changed data into stackgap
583 		 * and adjust msg appropriately.
584 		 */
585 		if (changed) {
586 			char *newc;
587 
588 			/*
589 			 * Check again the total len is maximum half of
590 			 * stackgap. The length might change if the
591 			 * alignment is different.
592 			 */
593 			if (clen > STACKGAPLEN/2) {
594 				error = EMSGSIZE;
595 				goto done;
596 			}
597 
598 			/*
599 			 * Allocate space on stack within stackgap, and
600 			 * copy changed data there.
601 			 */
602 			if (!sg)
603 				sg = stackgap_init(p, STACKGAPLEN/3);
604 			newc = stackgap_alloc(p, &sg, clen);
605 			if (!newc) {
606 				error = ENOMEM;
607 				goto done;
608 			}
609 
610 			error = copyout(control, newc, clen);
611 			if (error)
612 				goto done;
613 
614 			msg.msg_control = newc;
615 			msg.msg_controllen = clen;
616 		}
617 
618 		free(control, M_TEMP);
619 		control = NULL;
620 	}
621 
622 	error = sendit(l, SCARG(uap, s), &msg, bflags, retval);
623 
624 done:
625 	if (control)
626 		free(control, M_TEMP);
627 	if (iov != aiov)
628 		free(iov, M_IOV);
629 	return (error);
630 }
631 
632 int
633 linux_sys_recvfrom(l, v, retval)
634 	struct lwp *l;
635 	void *v;
636 	register_t *retval;
637 {
638 	struct linux_sys_recvfrom_args /* {
639 		syscallarg(int) s;
640 		syscallarg(void *) buf;
641 		syscallarg(int) len;
642 		syscallarg(int) flags;
643 		syscallarg(struct osockaddr *) from;
644 		syscallarg(int *) fromlenaddr;
645 	} */ *uap = v;
646 	int		error;
647 	struct sys_recvfrom_args bra;
648 
649 	SCARG(&bra, s) = SCARG(uap, s);
650 	SCARG(&bra, buf) = SCARG(uap, buf);
651 	SCARG(&bra, len) = SCARG(uap, len);
652 	SCARG(&bra, flags) = SCARG(uap, flags);
653 	SCARG(&bra, from) = (struct sockaddr *) SCARG(uap, from);
654 	SCARG(&bra, fromlenaddr) = (socklen_t *)SCARG(uap, fromlenaddr);
655 
656 	if ((error = sys_recvfrom(l, &bra, retval)))
657 		return (error);
658 
659 	if (SCARG(uap, from) && (error = linux_sa_put(SCARG(uap, from))))
660 		return (error);
661 
662 	return (0);
663 }
664 
665 int
666 linux_sys_recvmsg(l, v, retval)
667 	struct lwp *l;
668 	void *v;
669 	register_t *retval;
670 {
671 	struct linux_sys_recvmsg_args /* {
672 		syscallarg(int) s;
673 		syscallarg(struct msghdr *) msg;
674 		syscallarg(u_int) flags;
675 	} */ *uap = v;
676 	struct msghdr	msg;
677 	int		error;
678 	struct sys_recvmsg_args bsa;
679 	int lflags;
680 	u_int8_t *ocontrol = NULL; /* XXX: gcc */
681 	socklen_t ocontrollen = 0;
682 
683 	/*
684 	 * Data alignment is different on some architectures. If control
685 	 * message is expected, we must arrange for the control message
686 	 * to be initially put elsewhere, and copy to target place
687 	 * with Linux alignment.
688 	 */
689 	if (LINUX_CMSG_ALIGNDIFF) {
690 		error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
691 		if (error)
692 			return (error);
693 
694 		if (CMSG_FIRSTHDR(&msg)) {
695 			caddr_t sg;
696 
697 			/* Need to fit within stackgap */
698 			if (msg.msg_controllen > STACKGAPLEN/2) {
699 				/* Sorry guys! */
700 				return (EINVAL);
701 			}
702 
703 			sg = stackgap_init(l->l_proc, STACKGAPLEN/3);
704 
705 			ocontrol = msg.msg_control;
706 			ocontrollen = msg.msg_controllen;
707 
708 			/* space for at least one message's worth align */
709 			msg.msg_controllen += CMSG_ALIGN(1);
710 
711 			msg.msg_control = stackgap_alloc(l->l_proc, &sg,
712 				msg.msg_controllen);
713 			if (!msg.msg_control)
714 				return (ENOMEM);
715 
716 			/*
717 			 * Okay to overwrite the original structure, it's
718 			 * supposed to be writable.
719 			 */
720 			error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
721 			if (error)
722 				return (error);
723 		}
724 	}
725 
726 	SCARG(&bsa, s) = SCARG(uap, s);
727 	SCARG(&bsa, msg) = SCARG(uap, msg);
728 	SCARG(&bsa, flags) = linux_to_bsd_msg_flags(SCARG(uap, flags));
729 
730 	if (SCARG(&bsa, flags) < 0) {
731 		/* Some unsupported flag */
732 		return (EINVAL);
733 	}
734 
735 	if ((error = sys_recvmsg(l, &bsa, retval)))
736 		goto done;
737 
738 	/* Fixup sockaddr */
739 	error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
740 		       sizeof(msg));
741 	if (error)
742 		goto done;
743 
744 	if (msg.msg_name && msg.msg_namelen > 2) {
745 		if ((error = linux_sa_put(msg.msg_name)))
746 			goto done;
747 	}
748 
749 	/* Fixup msg flags */
750 	lflags = bsd_to_linux_msg_flags(msg.msg_flags);
751 	if (lflags < 0) {
752 		/* Some flag unsupported by Linux */
753 		error = EINVAL;
754 		goto done;
755 	}
756 	error = copyout(&lflags, (u_int8_t *) SCARG(uap, msg) +
757 			offsetof(struct msghdr, msg_flags), sizeof(lflags));
758 	if (error)
759 		goto done;
760 
761 	/*
762 	 * Fixup cmsg. We handle two things:
763 	 * 1. different values for level/type on some archs
764 	 * 2. different alignment of CMSG_DATA on some archs
765 	 */
766 	if (CMSG_FIRSTHDR(&msg)) {
767 		struct cmsghdr cmsg, *cc;
768 		int changed = 0;
769 		size_t resid = ocontrollen;
770 
771 		cc = CMSG_FIRSTHDR(&msg);
772 		do {
773 			error = copyin(cc, &cmsg, sizeof(cmsg));
774 			if (error)
775 				goto done;
776 
777 			switch (cmsg.cmsg_level) {
778 			case SOL_SOCKET:
779 				if (SOL_SOCKET != LINUX_SOL_SOCKET) {
780 					cmsg.cmsg_level = LINUX_SOL_SOCKET;
781 					changed = 1;
782 				}
783 
784 				switch (cmsg.cmsg_type) {
785 				case SCM_RIGHTS:
786 					/* Linux SCM_RIGHTS is same as NetBSD */
787 					break;
788 
789 				default:
790 					/* other types not supported */
791 					error = EINVAL;
792 					goto done;
793 				}
794 			default:
795 				/* pray and leave intact */
796 				break;
797 			}
798 
799 			if (LINUX_CMSG_ALIGNDIFF) {
800 				int i;
801 				u_int8_t d, *sd, *td;
802 
803 				/*
804 				 * Sanity check.
805 				 */
806 				if (cmsg.cmsg_len > resid
807 				    || cmsg.cmsg_len < sizeof(cmsg)) {
808 					error = EINVAL;
809 					goto done;
810 				}
811 
812 				/*
813 				 * Need to copy the cmsg from scratch area
814 				 * to the original place, converting data
815 				 * alignment from NetBSD to Linux one.
816 				 */
817 				error = copyout(&cmsg, ocontrol, sizeof(cmsg));
818 				if (error)
819 					goto done;
820 				/* zero pad */
821 #if 0
822 				for(i=0; i < LINUX_CMSG_ALIGN(sizeof(cmsg)) - sizeof(cmsg); i++) {
823 					copyout("",&ocontrol[sizeof(cmsg)+i],1);
824 				}
825 #endif
826 
827 				sd = CMSG_DATA(cc);
828 				td = LINUX_CMSG_DATA(ocontrol);
829 
830 				/* This is not particularily effective, but ..*/
831 				d = '\0';
832 				for(i=0; i < cmsg.cmsg_len - sizeof(cmsg); i++){
833 					copyin(sd++, &d, 1);
834 					copyout(&d, td++, 1);
835 				}
836 
837 				resid -= (td - ocontrol);
838 				ocontrol = td;
839 			} else if (changed) {
840 				/* Update cmsghdr in-place */
841 				error = copyout(&cmsg, cc, sizeof(cmsg));
842 				if (error)
843 					goto done;
844 				changed = 0;
845 			}
846 		} while((cc = CMSG_NXTHDR(&msg, cc)));
847 	}
848 
849 done:
850 	return (error);
851 }
852 
853 /*
854  * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
855  * is different, the rest matches IPPROTO_* on both systems.
856  */
857 int
858 linux_to_bsd_sopt_level(llevel)
859 	int llevel;
860 {
861 
862 	switch (llevel) {
863 	case LINUX_SOL_SOCKET:
864 		return SOL_SOCKET;
865 	case LINUX_SOL_IP:
866 		return IPPROTO_IP;
867 	case LINUX_SOL_TCP:
868 		return IPPROTO_TCP;
869 	case LINUX_SOL_UDP:
870 		return IPPROTO_UDP;
871 	default:
872 		return -1;
873 	}
874 }
875 
876 /*
877  * Convert Linux socket level socket option numbers to NetBSD values.
878  */
879 int
880 linux_to_bsd_so_sockopt(lopt)
881 	int lopt;
882 {
883 
884 	switch (lopt) {
885 	case LINUX_SO_DEBUG:
886 		return SO_DEBUG;
887 	case LINUX_SO_REUSEADDR:
888 		/*
889 		 * Linux does not implement SO_REUSEPORT, but allows reuse of a
890 		 * host:port pair through SO_REUSEADDR even if the address is not a
891 		 * multicast-address.  Effectively, this means that we should use
892 		 * SO_REUSEPORT to allow Linux applications to not exit with
893 		 * EADDRINUSE
894 		 */
895 		return SO_REUSEPORT;
896 	case LINUX_SO_TYPE:
897 		return SO_TYPE;
898 	case LINUX_SO_ERROR:
899 		return SO_ERROR;
900 	case LINUX_SO_DONTROUTE:
901 		return SO_DONTROUTE;
902 	case LINUX_SO_BROADCAST:
903 		return SO_BROADCAST;
904 	case LINUX_SO_SNDBUF:
905 		return SO_SNDBUF;
906 	case LINUX_SO_RCVBUF:
907 		return SO_RCVBUF;
908 	case LINUX_SO_KEEPALIVE:
909 		return SO_KEEPALIVE;
910 	case LINUX_SO_OOBINLINE:
911 		return SO_OOBINLINE;
912 	case LINUX_SO_LINGER:
913 		return SO_LINGER;
914 	case LINUX_SO_PRIORITY:
915 	case LINUX_SO_NO_CHECK:
916 	default:
917 		return -1;
918 	}
919 }
920 
921 /*
922  * Convert Linux IP level socket option number to NetBSD values.
923  */
924 int
925 linux_to_bsd_ip_sockopt(lopt)
926 	int lopt;
927 {
928 
929 	switch (lopt) {
930 	case LINUX_IP_TOS:
931 		return IP_TOS;
932 	case LINUX_IP_TTL:
933 		return IP_TTL;
934 	case LINUX_IP_MULTICAST_TTL:
935 		return IP_MULTICAST_TTL;
936 	case LINUX_IP_MULTICAST_LOOP:
937 		return IP_MULTICAST_LOOP;
938 	case LINUX_IP_MULTICAST_IF:
939 		return IP_MULTICAST_IF;
940 	case LINUX_IP_ADD_MEMBERSHIP:
941 		return IP_ADD_MEMBERSHIP;
942 	case LINUX_IP_DROP_MEMBERSHIP:
943 		return IP_DROP_MEMBERSHIP;
944 	default:
945 		return -1;
946 	}
947 }
948 
949 /*
950  * Convert Linux TCP level socket option number to NetBSD values.
951  */
952 int
953 linux_to_bsd_tcp_sockopt(lopt)
954 	int lopt;
955 {
956 
957 	switch (lopt) {
958 	case LINUX_TCP_NODELAY:
959 		return TCP_NODELAY;
960 	case LINUX_TCP_MAXSEG:
961 		return TCP_MAXSEG;
962 	default:
963 		return -1;
964 	}
965 }
966 
967 /*
968  * Convert Linux UDP level socket option number to NetBSD values.
969  */
970 int
971 linux_to_bsd_udp_sockopt(lopt)
972 	int lopt;
973 {
974 
975 	switch (lopt) {
976 	default:
977 		return -1;
978 	}
979 }
980 
981 /*
982  * Another reasonably straightforward function: setsockopt(2).
983  * The level and option numbers are converted; the values passed
984  * are not (yet) converted, the ones currently implemented don't
985  * need conversion, as they are the same on both systems.
986  */
987 int
988 linux_sys_setsockopt(l, v, retval)
989 	struct lwp *l;
990 	void *v;
991 	register_t *retval;
992 {
993 	struct linux_sys_setsockopt_args /* {
994 		syscallarg(int) s;
995 		syscallarg(int) level;
996 		syscallarg(int) optname;
997 		syscallarg(void *) optval;
998 		syscallarg(int) optlen;
999 	} */ *uap = v;
1000 	struct proc *p = l->l_proc;
1001 	struct sys_setsockopt_args bsa;
1002 	int name;
1003 
1004 	SCARG(&bsa, s) = SCARG(uap, s);
1005 	SCARG(&bsa, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
1006 	SCARG(&bsa, val) = SCARG(uap, optval);
1007 	SCARG(&bsa, valsize) = SCARG(uap, optlen);
1008 
1009 	/*
1010 	 * Linux supports only SOL_SOCKET for AF_LOCAL domain sockets
1011 	 * and returns EOPNOTSUPP for other levels
1012 	 */
1013 	if (SCARG(&bsa, level) != SOL_SOCKET) {
1014 		struct file *fp;
1015 		struct socket *so;
1016 		int error, s, family;
1017 
1018 		/* getsock() will use the descriptor for us */
1019 	    	if ((error = getsock(p->p_fd, SCARG(&bsa, s), &fp)) != 0)
1020 		    	return error;
1021 
1022 		s = splsoftnet();
1023 		so = (struct socket *)fp->f_data;
1024 		family = so->so_proto->pr_domain->dom_family;
1025 		splx(s);
1026 		FILE_UNUSE(fp, l);
1027 
1028 		if (family == AF_LOCAL)
1029 			return EOPNOTSUPP;
1030 	}
1031 
1032 	switch (SCARG(&bsa, level)) {
1033 	case SOL_SOCKET:
1034 		name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
1035 		break;
1036 	case IPPROTO_IP:
1037 		name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
1038 		break;
1039 	case IPPROTO_TCP:
1040 		name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
1041 		break;
1042 	case IPPROTO_UDP:
1043 		name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
1044 		break;
1045 	default:
1046 		return EINVAL;
1047 	}
1048 
1049 	if (name == -1)
1050 		return EINVAL;
1051 	SCARG(&bsa, name) = name;
1052 
1053 	return sys_setsockopt(l, &bsa, retval);
1054 }
1055 
1056 /*
1057  * getsockopt(2) is very much the same as setsockopt(2) (see above)
1058  */
1059 int
1060 linux_sys_getsockopt(l, v, retval)
1061 	struct lwp *l;
1062 	void *v;
1063 	register_t *retval;
1064 {
1065 	struct linux_sys_getsockopt_args /* {
1066 		syscallarg(int) s;
1067 		syscallarg(int) level;
1068 		syscallarg(int) optname;
1069 		syscallarg(void *) optval;
1070 		syscallarg(int *) optlen;
1071 	} */ *uap = v;
1072 	struct sys_getsockopt_args bga;
1073 	int name;
1074 
1075 	SCARG(&bga, s) = SCARG(uap, s);
1076 	SCARG(&bga, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
1077 	SCARG(&bga, val) = SCARG(uap, optval);
1078 	SCARG(&bga, avalsize) = (socklen_t *)SCARG(uap, optlen);
1079 
1080 	switch (SCARG(&bga, level)) {
1081 	case SOL_SOCKET:
1082 		name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
1083 		break;
1084 	case IPPROTO_IP:
1085 		name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
1086 		break;
1087 	case IPPROTO_TCP:
1088 		name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
1089 		break;
1090 	case IPPROTO_UDP:
1091 		name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
1092 		break;
1093 	default:
1094 		return EINVAL;
1095 	}
1096 
1097 	if (name == -1)
1098 		return EINVAL;
1099 	SCARG(&bga, name) = name;
1100 
1101 	return sys_getsockopt(l, &bga, retval);
1102 }
1103 
1104 #define IF_NAME_LEN 16
1105 
1106 int
1107 linux_getifhwaddr(struct lwp *l, register_t *retval, u_int fd,
1108     void *data)
1109 {
1110 	/* Not the full structure, just enough to map what we do here */
1111 	struct linux_ifreq {
1112 		char if_name[IF_NAME_LEN];
1113 		struct osockaddr hwaddr;
1114 	} lreq;
1115 	struct proc *p = l->l_proc;
1116 	struct filedesc *fdp;
1117 	struct file *fp;
1118 	struct ifaddr *ifa;
1119 	struct ifnet *ifp;
1120 	struct sockaddr_dl *sadl;
1121 	int error, found;
1122 	int index, ifnum;
1123 
1124 	/*
1125 	 * We can't emulate this ioctl by calling sys_ioctl() to run
1126 	 * SIOCGIFCONF, because the user buffer is not of the right
1127 	 * type to take those results.  We can't use kernel buffers to
1128 	 * receive the results, as the implementation of sys_ioctl()
1129 	 * and ifconf() [which implements SIOCGIFCONF] use
1130 	 * copyin()/copyout() which will fail on kernel addresses.
1131 	 *
1132 	 * So, we must duplicate code from sys_ioctl() and ifconf().  Ugh.
1133 	 */
1134 
1135 	fdp = p->p_fd;
1136 	if ((fp = fd_getfile(fdp, fd)) == NULL)
1137 		return (EBADF);
1138 
1139 	FILE_USE(fp);
1140 	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
1141 		error = EBADF;
1142 		goto out;
1143 	}
1144 
1145 	error = copyin(data, (caddr_t)&lreq, sizeof(lreq));
1146 	if (error)
1147 		goto out;
1148 	lreq.if_name[IF_NAME_LEN-1] = '\0';		/* just in case */
1149 
1150 	/*
1151 	 * Try real interface name first, then fake "ethX"
1152 	 */
1153 	for (ifp = ifnet.tqh_first, found = 0;
1154 	     ifp != 0 && !found;
1155 	     ifp = ifp->if_list.tqe_next) {
1156 		if (strcmp(lreq.if_name, ifp->if_xname))
1157 			/* not this interface */
1158 			continue;
1159 		found=1;
1160 		if ((ifa = ifp->if_addrlist.tqh_first) != 0) {
1161 			for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1162 				sadl = (struct sockaddr_dl *)ifa->ifa_addr;
1163 				/* only return ethernet addresses */
1164 				/* XXX what about FDDI, etc. ? */
1165 				if (sadl->sdl_family != AF_LINK ||
1166 				    sadl->sdl_type != IFT_ETHER)
1167 					continue;
1168 				memcpy((caddr_t)&lreq.hwaddr.sa_data,
1169 				       LLADDR(sadl),
1170 				       MIN(sadl->sdl_alen,
1171 					   sizeof(lreq.hwaddr.sa_data)));
1172 				lreq.hwaddr.sa_family =
1173 					sadl->sdl_family;
1174 				error = copyout((caddr_t)&lreq, data,
1175 						sizeof(lreq));
1176 				goto out;
1177 			}
1178 		} else {
1179 			error = ENODEV;
1180 			goto out;
1181 		}
1182 	}
1183 
1184 	if (strncmp(lreq.if_name, "eth", 3) == 0) {
1185 		for (ifnum = 0, index = 3;
1186 		     lreq.if_name[index] != '\0' && index < IF_NAME_LEN;
1187 		     index++) {
1188 			ifnum *= 10;
1189 			ifnum += lreq.if_name[index] - '0';
1190 		}
1191 
1192 		error = EINVAL;			/* in case we don't find one */
1193 		for (ifp = ifnet.tqh_first, found = 0;
1194 		     ifp != 0 && !found;
1195 		     ifp = ifp->if_list.tqe_next) {
1196 			memcpy(lreq.if_name, ifp->if_xname,
1197 			       MIN(IF_NAME_LEN, IFNAMSIZ));
1198 			if ((ifa = ifp->if_addrlist.tqh_first) == 0)
1199 				/* no addresses on this interface */
1200 				continue;
1201 			else
1202 				for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1203 					sadl = (struct sockaddr_dl *)ifa->ifa_addr;
1204 					/* only return ethernet addresses */
1205 					/* XXX what about FDDI, etc. ? */
1206 					if (sadl->sdl_family != AF_LINK ||
1207 					    sadl->sdl_type != IFT_ETHER)
1208 						continue;
1209 					if (ifnum--)
1210 						/* not the reqested iface */
1211 						continue;
1212 					memcpy((caddr_t)&lreq.hwaddr.sa_data,
1213 					       LLADDR(sadl),
1214 					       MIN(sadl->sdl_alen,
1215 						   sizeof(lreq.hwaddr.sa_data)));
1216 					lreq.hwaddr.sa_family =
1217 						sadl->sdl_family;
1218 					error = copyout((caddr_t)&lreq, data,
1219 							sizeof(lreq));
1220 					found = 1;
1221 					break;
1222 				}
1223 		}
1224 	} else {
1225 		/* unknown interface, not even an "eth*" name */
1226 		error = ENODEV;
1227 	}
1228 
1229 out:
1230 	FILE_UNUSE(fp, l);
1231 	return error;
1232 }
1233 #undef IF_NAME_LEN
1234 
1235 int
1236 linux_ioctl_socket(l, uap, retval)
1237 	struct lwp *l;
1238 	struct linux_sys_ioctl_args /* {
1239 		syscallarg(int) fd;
1240 		syscallarg(u_long) com;
1241 		syscallarg(caddr_t) data;
1242 	} */ *uap;
1243 	register_t *retval;
1244 {
1245 	struct proc *p = l->l_proc;
1246 	u_long com;
1247 	int error = 0, isdev = 0, dosys = 1;
1248 	struct sys_ioctl_args ia;
1249 	struct file *fp;
1250 	struct filedesc *fdp;
1251 	struct vnode *vp;
1252 	int (*ioctlf)(struct file *, u_long, void *, struct lwp *);
1253 	struct ioctl_pt pt;
1254 
1255         fdp = p->p_fd;
1256 	if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
1257 		return (EBADF);
1258 
1259 	FILE_USE(fp);
1260 
1261 	if (fp->f_type == DTYPE_VNODE) {
1262 		vp = (struct vnode *)fp->f_data;
1263 		isdev = vp->v_type == VCHR;
1264 	}
1265 
1266 	/*
1267 	 * Don't try to interpret socket ioctl calls that are done
1268 	 * on a device filedescriptor, just pass them through, to
1269 	 * emulate Linux behaviour. Use PTIOCLINUX so that the
1270 	 * device will only handle these if it's prepared to do
1271 	 * so, to avoid unexpected things from happening.
1272 	 */
1273 	if (isdev) {
1274 		dosys = 0;
1275 		ioctlf = fp->f_ops->fo_ioctl;
1276 		pt.com = SCARG(uap, com);
1277 		pt.data = SCARG(uap, data);
1278 		error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, l);
1279 		/*
1280 		 * XXX hack: if the function returns EJUSTRETURN,
1281 		 * it has stuffed a sysctl return value in pt.data.
1282 		 */
1283 		if (error == EJUSTRETURN) {
1284 			retval[0] = (register_t)pt.data;
1285 			error = 0;
1286 		}
1287 		goto out;
1288 	}
1289 
1290 	com = SCARG(uap, com);
1291 	retval[0] = 0;
1292 
1293 	switch (com) {
1294 	case LINUX_SIOCGIFCONF:
1295 		SCARG(&ia, com) = OSIOCGIFCONF;
1296 		break;
1297 	case LINUX_SIOCGIFFLAGS:
1298 		SCARG(&ia, com) = SIOCGIFFLAGS;
1299 		break;
1300 	case LINUX_SIOCSIFFLAGS:
1301 		SCARG(&ia, com) = SIOCSIFFLAGS;
1302 		break;
1303 	case LINUX_SIOCGIFADDR:
1304 		SCARG(&ia, com) = OSIOCGIFADDR;
1305 		break;
1306 	case LINUX_SIOCGIFDSTADDR:
1307 		SCARG(&ia, com) = OSIOCGIFDSTADDR;
1308 		break;
1309 	case LINUX_SIOCGIFBRDADDR:
1310 		SCARG(&ia, com) = OSIOCGIFBRDADDR;
1311 		break;
1312 	case LINUX_SIOCGIFNETMASK:
1313 		SCARG(&ia, com) = OSIOCGIFNETMASK;
1314 		break;
1315 	case LINUX_SIOCADDMULTI:
1316 		SCARG(&ia, com) = SIOCADDMULTI;
1317 		break;
1318 	case LINUX_SIOCDELMULTI:
1319 		SCARG(&ia, com) = SIOCDELMULTI;
1320 		break;
1321 	case LINUX_SIOCGIFHWADDR:
1322 	        error = linux_getifhwaddr(l, retval, SCARG(uap, fd),
1323 					 SCARG(uap, data));
1324 		dosys = 0;
1325 		break;
1326 	default:
1327 		error = EINVAL;
1328 	}
1329 
1330 out:
1331 	FILE_UNUSE(fp, l);
1332 
1333 	if (error ==0 && dosys) {
1334 		SCARG(&ia, fd) = SCARG(uap, fd);
1335 		SCARG(&ia, data) = SCARG(uap, data);
1336 		/* XXX NJWLWP */
1337 		error = sys_ioctl(curlwp, &ia, retval);
1338 	}
1339 
1340 	return error;
1341 }
1342 
1343 int
1344 linux_sys_connect(l, v, retval)
1345 	struct lwp *l;
1346 	void *v;
1347 	register_t *retval;
1348 {
1349 	struct linux_sys_connect_args /* {
1350 		syscallarg(int) s;
1351 		syscallarg(const struct sockaddr *) name;
1352 		syscallarg(int) namelen;
1353 	} */ *uap = v;
1354 	struct proc *p = l->l_proc;
1355 	int		error;
1356 	struct sockaddr *sa;
1357 	struct sys_connect_args bca;
1358 	caddr_t sg = stackgap_init(p, 0);
1359 	socklen_t namlen;
1360 
1361 	namlen = SCARG(uap, namelen);
1362 	error = linux_sa_get(l, SCARG(uap, s), &sg, &sa,
1363 	    SCARG(uap, name), &namlen);
1364 	if (error)
1365 		return (error);
1366 
1367 	SCARG(&bca, s) = SCARG(uap, s);
1368 	SCARG(&bca, name) = sa;
1369 	SCARG(&bca, namelen) =  namlen;
1370 
1371 	error = sys_connect(l, &bca, retval);
1372 
1373 	if (error == EISCONN) {
1374 		struct file *fp;
1375 		struct socket *so;
1376 		int s, state, prflags;
1377 
1378 		/* getsock() will use the descriptor for us */
1379 	    	if (getsock(p->p_fd, SCARG(uap, s), &fp) != 0)
1380 		    	return EISCONN;
1381 
1382 		s = splsoftnet();
1383 		so = (struct socket *)fp->f_data;
1384 		state = so->so_state;
1385 		prflags = so->so_proto->pr_flags;
1386 		splx(s);
1387 		FILE_UNUSE(fp, l);
1388 		/*
1389 		 * We should only let this call succeed once per
1390 		 * non-blocking connect; however we don't have
1391 		 * a convenient place to keep that state..
1392 		 */
1393 		if ((state & SS_NBIO) && (state & SS_ISCONNECTED) &&
1394 		    (prflags & PR_CONNREQUIRED))
1395 			return 0;
1396 	}
1397 
1398 	return (error);
1399 }
1400 
1401 int
1402 linux_sys_bind(l, v, retval)
1403 	struct lwp *l;
1404 	void *v;
1405 	register_t *retval;
1406 {
1407 	struct linux_sys_bind_args /* {
1408 		syscallarg(int) s;
1409 		syscallarg(const struct osockaddr *) name;
1410 		syscallarg(int) namelen;
1411 	} */ *uap = v;
1412 	struct proc *p = l->l_proc;
1413 	int		error;
1414 	socklen_t	namlen;
1415 	struct sys_bind_args bsa;
1416 
1417 	namlen = SCARG(uap, namelen);
1418 	SCARG(&bsa, s) = SCARG(uap, s);
1419 	if (SCARG(uap, name)) {
1420 		struct sockaddr *sa;
1421 		caddr_t sg = stackgap_init(p, 0);
1422 
1423 		error = linux_sa_get(l, SCARG(uap, s), &sg, &sa,
1424 		    SCARG(uap, name), &namlen);
1425 		if (error)
1426 			return (error);
1427 
1428 		SCARG(&bsa, name) = sa;
1429 	} else
1430 		SCARG(&bsa, name) = NULL;
1431 	SCARG(&bsa, namelen) = namlen;
1432 
1433 	return (sys_bind(l, &bsa, retval));
1434 }
1435 
1436 int
1437 linux_sys_getsockname(l, v, retval)
1438 	struct lwp *l;
1439 	void *v;
1440 	register_t *retval;
1441 {
1442 	struct linux_sys_getsockname_args /* {
1443 		syscallarg(int) fdes;
1444 		syscallarg(caddr_t) asa;
1445 		syscallarg(int *) alen;
1446 	} */ *uap = v;
1447 	int error;
1448 
1449 	if ((error = sys_getsockname(l, uap, retval)) != 0)
1450 		return (error);
1451 
1452 	if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
1453 		return (error);
1454 
1455 	return (0);
1456 }
1457 
1458 int
1459 linux_sys_getpeername(l, v, retval)
1460 	struct lwp *l;
1461 	void *v;
1462 	register_t *retval;
1463 {
1464 	struct sys_getpeername_args /* {
1465 		syscallarg(int) fdes;
1466 		syscallarg(caddr_t) asa;
1467 		syscallarg(int *) alen;
1468 	} */ *uap = v;
1469 	int error;
1470 
1471 	if ((error = sys_getpeername(l, uap, retval)) != 0)
1472 		return (error);
1473 
1474 	if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
1475 		return (error);
1476 
1477 	return (0);
1478 }
1479 
1480 /*
1481  * Copy the osockaddr structure pointed to by osa to kernel, adjust
1482  * family and convert to sockaddr, allocate stackgap and put the
1483  * the converted structure there, address on stackgap returned in sap.
1484  */
1485 static int
1486 linux_sa_get(l, s, sgp, sap, osa, osalen)
1487 	struct lwp *l;
1488 	int s;
1489 	caddr_t *sgp;
1490 	struct sockaddr **sap;
1491 	const struct osockaddr *osa;
1492 	socklen_t *osalen;
1493 {
1494 	int error=0, bdom;
1495 	struct sockaddr *sa, *usa;
1496 	struct osockaddr *kosa = (struct osockaddr *) &sa;
1497 	struct proc *p = l->l_proc;
1498 	socklen_t alloclen;
1499 #ifdef INET6
1500 	int oldv6size;
1501 	struct sockaddr_in6 *sin6;
1502 #endif
1503 
1504 	if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) {
1505 		DPRINTF(("bad osa=%p osalen=%d\n", osa, *osalen));
1506 		return (EINVAL);
1507 	}
1508 
1509 	alloclen = *osalen;
1510 #ifdef INET6
1511 	oldv6size = 0;
1512 	/*
1513 	 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
1514 	 * if it's a v4-mapped address, so reserve the proper space
1515 	 * for it.
1516 	 */
1517 	if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
1518 		alloclen = sizeof (struct sockaddr_in6);
1519 		oldv6size = 1;
1520 	}
1521 #endif
1522 
1523 	kosa = (struct osockaddr *) malloc(alloclen, M_TEMP, M_WAITOK);
1524 
1525 	if ((error = copyin(osa, (caddr_t) kosa, *osalen))) {
1526 		DPRINTF(("error copying osa %d\n", error));
1527 		goto out;
1528 	}
1529 
1530 	bdom = linux_to_bsd_domain(kosa->sa_family);
1531 	if (bdom == -1) {
1532 		DPRINTF(("bad linux family=%d\n", kosa->sa_family));
1533 		error = EINVAL;
1534 		goto out;
1535 	}
1536 
1537 #ifdef INET6
1538 	/*
1539 	 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
1540 	 * which lacks the scope id compared with RFC2553 one. If we detect
1541 	 * the situation, reject the address and write a message to system log.
1542 	 *
1543 	 * Still accept addresses for which the scope id is not used.
1544 	 */
1545 	if (oldv6size && bdom == AF_INET6) {
1546 		sin6 = (struct sockaddr_in6 *)kosa;
1547 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
1548 		    (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
1549 		     !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
1550 		     !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
1551 		     !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
1552 		     !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
1553 			sin6->sin6_scope_id = 0;
1554 		} else {
1555 			int uid = l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1;
1556 
1557 			log(LOG_DEBUG,
1558 			    "pid %d (%s), uid %d: obsolete pre-RFC2553 "
1559 			    "sockaddr_in6 rejected",
1560 			    p->p_pid, p->p_comm, uid);
1561 			error = EINVAL;
1562 			goto out;
1563 		}
1564 	}
1565 #endif
1566 
1567 	/*
1568 	 * If the family is unspecified, use address family of the
1569 	 * socket. This avoid triggering COMPAT_43 struct socket family check
1570 	 * in sockargs() on little-endian machines, and strict family checks
1571 	 * in netinet/in_pcb.c et.al.
1572 	 */
1573 	if (bdom == AF_UNSPEC) {
1574 		struct file *fp;
1575 		struct socket *so;
1576 
1577 		/* getsock() will use the descriptor for us */
1578 		if ((error = getsock(p->p_fd, s, &fp)) != 0)
1579 			goto out;
1580 
1581 		so = (struct socket *)fp->f_data;
1582 		bdom = so->so_proto->pr_domain->dom_family;
1583 
1584 		FILE_UNUSE(fp, l);
1585 
1586 		DPRINTF(("AF_UNSPEC family adjusted to %d\n", bdom));
1587 	}
1588 
1589 	if (bdom == AF_INET) {
1590 		alloclen = sizeof(struct sockaddr_in);
1591 	}
1592 
1593 	sa = (struct sockaddr *) kosa;
1594 	sa->sa_family = bdom;
1595 	sa->sa_len = alloclen;
1596 #ifdef DEBUG_LINUX
1597 	DPRINTF(("family %d, len = %d [ ", sa->sa_family, sa->sa_len));
1598 	for (bdom = 0; bdom < sizeof(sa->sa_data); bdom++)
1599 	    DPRINTF(("%02x ", (unsigned char) sa->sa_data[bdom]));
1600 	DPRINTF(("\n"));
1601 #endif
1602 
1603 	usa = (struct sockaddr *) stackgap_alloc(p, sgp, alloclen);
1604 	if (!usa) {
1605 		error = ENOMEM;
1606 		goto out;
1607 	}
1608 
1609 	if ((error = copyout(sa, usa, alloclen))) {
1610 		DPRINTF(("error copying out socket %d\n", error));
1611 		goto out;
1612 	}
1613 
1614 	*sap = usa;
1615 
1616     out:
1617 	*osalen = alloclen;
1618 	free(kosa, M_TEMP);
1619 	return (error);
1620 }
1621 
1622 static int
1623 linux_sa_put(osa)
1624 	struct osockaddr *osa;
1625 {
1626 	struct sockaddr sa;
1627 	struct osockaddr *kosa;
1628 	int error, bdom, len;
1629 
1630 	/*
1631 	 * Only read/write the sockaddr family and length part, the rest is
1632 	 * not changed.
1633 	 */
1634 	len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
1635 
1636 	error = copyin((caddr_t) osa, (caddr_t) &sa, len);
1637 	if (error)
1638 		return (error);
1639 
1640 	bdom = bsd_to_linux_domain(sa.sa_family);
1641 	if (bdom == -1)
1642 		return (EINVAL);
1643 
1644 	/* Note: we convert from sockaddr to osockaddr here, too */
1645 	kosa = (struct osockaddr *) &sa;
1646 	kosa->sa_family = bdom;
1647 	error = copyout(kosa, osa, len);
1648 	if (error)
1649 		return (error);
1650 
1651 	return (0);
1652 }
1653 
1654 #ifndef __amd64__
1655 int
1656 linux_sys_recv(l, v, retval)
1657 	struct lwp *l;
1658 	void *v;
1659 	register_t *retval;
1660 {
1661 	struct linux_sys_recv_args /* {
1662 		syscallarg(int) s;
1663 		syscallarg(void *) buf;
1664 		syscallarg(int) len;
1665 		syscallarg(int) flags;
1666 	} */ *uap = v;
1667 	struct sys_recvfrom_args bra;
1668 
1669 
1670 	SCARG(&bra, s) = SCARG(uap, s);
1671 	SCARG(&bra, buf) = SCARG(uap, buf);
1672 	SCARG(&bra, len) = (size_t) SCARG(uap, len);
1673 	SCARG(&bra, flags) = SCARG(uap, flags);
1674 	SCARG(&bra, from) = NULL;
1675 	SCARG(&bra, fromlenaddr) = NULL;
1676 
1677 	return (sys_recvfrom(l, &bra, retval));
1678 }
1679 
1680 int
1681 linux_sys_send(l, v, retval)
1682 	struct lwp *l;
1683 	void *v;
1684 	register_t *retval;
1685 {
1686 	struct linux_sys_send_args /* {
1687 		syscallarg(int) s;
1688 		syscallarg(caddr_t) buf;
1689 		syscallarg(int) len;
1690 		syscallarg(int) flags;
1691 	} */ *uap = v;
1692 	struct sys_sendto_args bsa;
1693 
1694 	SCARG(&bsa, s)		= SCARG(uap, s);
1695 	SCARG(&bsa, buf)	= SCARG(uap, buf);
1696 	SCARG(&bsa, len)	= SCARG(uap, len);
1697 	SCARG(&bsa, flags)	= SCARG(uap, flags);
1698 	SCARG(&bsa, to)		= NULL;
1699 	SCARG(&bsa, tolen)	= 0;
1700 
1701 	return (sys_sendto(l, &bsa, retval));
1702 }
1703 #endif
1704 
1705 int
1706 linux_sys_accept(l, v, retval)
1707 	struct lwp *l;
1708 	void *v;
1709 	register_t *retval;
1710 {
1711 	struct linux_sys_accept_args /* {
1712 		syscallarg(int) s;
1713 		syscallarg(struct osockaddr *) name;
1714 		syscallarg(int *) anamelen;
1715 	} */ *uap = v;
1716 	int error;
1717 	struct sys_accept_args baa;
1718 
1719 	SCARG(&baa, s)		= SCARG(uap, s);
1720 	SCARG(&baa, name)	= (struct sockaddr *) SCARG(uap, name);
1721 	SCARG(&baa, anamelen)	= (unsigned int *) SCARG(uap, anamelen);
1722 
1723 	if ((error = sys_accept(l, &baa, retval)))
1724 		return (error);
1725 
1726 	if (SCARG(uap, name) && (error = linux_sa_put(SCARG(uap, name))))
1727 		return (error);
1728 
1729 	return (0);
1730 }
1731