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