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