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