xref: /netbsd-src/sys/compat/linux/common/linux_socket.c (revision c4a72b64362cdaf56b20ef58a2b9eb3d98492c47)
1 /*	$NetBSD: linux_socket.c,v 1.42 2002/11/29 14:32:27 fvdl 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  * XXX Note: Linux CMSG_ALIGN() uses (sizeof(long)-1). For architectures
44  * where our CMSG_ALIGN() differs (like powerpc, sparc, sparc64), the passed
45  * control structure would need to be adjusted accordingly in sendmsg() and
46  * recvmsg().
47  */
48 
49 #include <sys/cdefs.h>
50 __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.42 2002/11/29 14:32:27 fvdl Exp $");
51 
52 #if defined(_KERNEL_OPT)
53 #include "opt_inet.h"
54 #endif
55 
56 #include <sys/param.h>
57 #include <sys/kernel.h>
58 #include <sys/systm.h>
59 #include <sys/buf.h>
60 #include <sys/malloc.h>
61 #include <sys/ioctl.h>
62 #include <sys/tty.h>
63 #include <sys/file.h>
64 #include <sys/filedesc.h>
65 #include <sys/select.h>
66 #include <sys/socket.h>
67 #include <sys/socketvar.h>
68 #include <net/if.h>
69 #include <net/if_dl.h>
70 #include <net/if_types.h>
71 #include <netinet/in.h>
72 #include <netinet/tcp.h>
73 #include <sys/mount.h>
74 #include <sys/proc.h>
75 #include <sys/vnode.h>
76 #include <sys/device.h>
77 #include <sys/protosw.h>
78 #include <sys/mbuf.h>
79 #include <sys/syslog.h>
80 
81 #include <sys/syscallargs.h>
82 
83 #ifdef INET6
84 #include <netinet/ip6.h>
85 #include <netinet6/ip6_var.h>
86 #endif
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 #include <compat/linux/common/linux_socketcall.h>
94 #include <compat/linux/common/linux_sockio.h>
95 
96 #include <compat/linux/linux_syscallargs.h>
97 
98 #ifdef DEBUG_LINUX
99 #define DPRINTF(a) uprintf a
100 #else
101 #define DPRINTF(a)
102 #endif
103 
104 /*
105  * The calls in this file are entered either via the linux_socketcall()
106  * interface or, on the Alpha, as individual syscalls.  The
107  * linux_socketcall function does any massaging of arguments so that all
108  * the calls in here need not think that they are anything other
109  * than a normal syscall.
110  */
111 
112 static int linux_to_bsd_domain __P((int));
113 static int bsd_to_linux_domain __P((int));
114 int linux_to_bsd_sopt_level __P((int));
115 int linux_to_bsd_so_sockopt __P((int));
116 int linux_to_bsd_ip_sockopt __P((int));
117 int linux_to_bsd_tcp_sockopt __P((int));
118 int linux_to_bsd_udp_sockopt __P((int));
119 int linux_getifhwaddr __P((struct proc *, register_t *, u_int, void *));
120 static int linux_sa_get __P((struct proc *, caddr_t *sgp, struct sockaddr **sap,
121 		const struct osockaddr *osa, int *osalen));
122 static int linux_sa_put __P((struct osockaddr *osa));
123 
124 static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
125 	AF_UNSPEC,
126 	AF_UNIX,
127 	AF_INET,
128 	AF_CCITT,	/* LINUX_AF_AX25 */
129 	AF_IPX,
130 	AF_APPLETALK,
131 	-1,		/* LINUX_AF_NETROM */
132 	-1,		/* LINUX_AF_BRIDGE */
133 	-1,		/* LINUX_AF_ATMPVC */
134 	AF_CCITT,	/* LINUX_AF_X25 */
135 	AF_INET6,
136 	-1,		/* LINUX_AF_ROSE */
137 	AF_DECnet,
138 	-1,		/* LINUX_AF_NETBEUI */
139 	-1,		/* LINUX_AF_SECURITY */
140 	pseudo_AF_KEY,
141 	AF_ROUTE,	/* LINUX_AF_NETLINK */
142 	-1,		/* LINUX_AF_PACKET */
143 	-1,		/* LINUX_AF_ASH */
144 	-1,		/* LINUX_AF_ECONET */
145 	-1,		/* LINUX_AF_ATMSVC */
146 	AF_SNA,
147 	/* rest up to LINUX_AF_MAX-1 is not allocated */
148 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
149 };
150 
151 static const int bsd_to_linux_domain_[AF_MAX] = {
152 	LINUX_AF_UNSPEC,
153 	LINUX_AF_UNIX,
154 	LINUX_AF_INET,
155 	-1,		/* AF_IMPLINK */
156 	-1,		/* AF_PUP */
157 	-1,		/* AF_CHAOS */
158 	-1,		/* AF_NS */
159 	-1,		/* AF_ISO */
160 	-1,		/* AF_ECMA */
161 	-1,		/* AF_DATAKIT */
162 	LINUX_AF_AX25,	/* AF_CCITT */
163 	LINUX_AF_SNA,
164 	LINUX_AF_DECnet,
165 	-1,		/* AF_DLI */
166 	-1,		/* AF_LAT */
167 	-1,		/* AF_HYLINK */
168 	LINUX_AF_APPLETALK,
169 	LINUX_AF_NETLINK,
170 	-1,		/* AF_LINK */
171 	-1,		/* AF_XTP */
172 	-1,		/* AF_COIP */
173 	-1,		/* AF_CNT */
174 	-1,		/* pseudo_AF_RTIP */
175 	LINUX_AF_IPX,
176 	LINUX_AF_INET6,
177 	-1,		/* pseudo_AF_PIP */
178 	-1,		/* AF_ISDN */
179 	-1,		/* AF_NATM */
180 	-1,		/* AF_ARP */
181 	LINUX_pseudo_AF_KEY,
182 	-1,		/* pseudo_AF_HDRCMPLT */
183 };
184 
185 /*
186  * Convert between Linux and BSD socket domain values
187  */
188 static int
189 linux_to_bsd_domain(ldom)
190 	int ldom;
191 {
192 	if (ldom < 0 || ldom >= LINUX_AF_MAX)
193 		return (-1);
194 
195 	return linux_to_bsd_domain_[ldom];
196 }
197 
198 /*
199  * Convert between BSD and Linux socket domain values
200  */
201 static int
202 bsd_to_linux_domain(bdom)
203 	int bdom;
204 {
205 	if (bdom < 0 || bdom >= AF_MAX)
206 		return (-1);
207 
208 	return bsd_to_linux_domain_[bdom];
209 }
210 
211 int
212 linux_sys_socket(p, v, retval)
213 	struct proc *p;
214 	void *v;
215 	register_t *retval;
216 {
217 	struct linux_sys_socket_args /* {
218 		syscallarg(int)	domain;
219 		syscallarg(int)	type;
220 		syscallarg(int) protocol;
221 	} */ *uap = v;
222 	struct sys_socket_args bsa;
223 	int error;
224 
225 	SCARG(&bsa, protocol) = SCARG(uap, protocol);
226 	SCARG(&bsa, type) = SCARG(uap, type);
227 	SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
228 	if (SCARG(&bsa, domain) == -1)
229 		return EINVAL;
230 	error = sys_socket(p, &bsa, retval);
231 
232 #ifdef INET6
233 	/*
234 	 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by
235 	 * default and some apps depend on this. So, set V6ONLY to 0
236 	 * for Linux apps if the sysctl value is set to 1.
237 	 */
238 	if (!error && ip6_v6only && SCARG(&bsa, domain) == PF_INET6) {
239 		struct file *fp;
240 
241 		if (getsock(p->p_fd, *retval, &fp) == 0) {
242 			struct mbuf *m;
243 
244 			m = m_get(M_WAIT, MT_SOOPTS);
245 			m->m_len = sizeof(int);
246 			*mtod(m, int *) = 0;
247 
248 			/* ignore error */
249 			(void) sosetopt((struct socket *)fp->f_data,
250 				IPPROTO_IPV6, IPV6_V6ONLY, m);
251 
252 			FILE_UNUSE(fp, p);
253 		}
254 	}
255 #endif
256 
257 	return (error);
258 }
259 
260 int
261 linux_sys_socketpair(p, v, retval)
262 	struct proc *p;
263 	void *v;
264 	register_t *retval;
265 {
266 	struct linux_sys_socketpair_args /* {
267 		syscallarg(int) domain;
268 		syscallarg(int) type;
269 		syscallarg(int) protocol;
270 		syscallarg(int *) rsv;
271 	} */ *uap = v;
272 	struct sys_socketpair_args bsa;
273 
274 	SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
275 	if (SCARG(&bsa, domain) == -1)
276 		return EINVAL;
277 	SCARG(&bsa, type) = SCARG(uap, type);
278 	SCARG(&bsa, protocol) = SCARG(uap, protocol);
279 	SCARG(&bsa, rsv) = SCARG(uap, rsv);
280 
281 	return sys_socketpair(p, &bsa, retval);
282 }
283 
284 int
285 linux_sys_sendto(p, v, retval)
286 	struct proc *p;
287 	void *v;
288 	register_t *retval;
289 {
290 	struct linux_sys_sendto_args /* {
291 		syscallarg(int)				s;
292 		syscallarg(void *)			msg;
293 		syscallarg(int)				len;
294 		syscallarg(int)				flags;
295 		syscallarg(struct osockaddr *)		to;
296 		syscallarg(int)				tolen;
297 	} */ *uap = v;
298 	struct sys_sendto_args bsa;
299 	int tolen;
300 
301 	SCARG(&bsa, s) = SCARG(uap, s);
302 	SCARG(&bsa, buf) = SCARG(uap, msg);
303 	SCARG(&bsa, len) = (size_t) SCARG(uap, len);
304 	SCARG(&bsa, flags) = SCARG(uap, flags);
305 	tolen = SCARG(uap, tolen);
306 	if (SCARG(uap, to)) {
307 		struct sockaddr *sa;
308 		int error;
309 		caddr_t sg = stackgap_init(p, 0);
310 
311 		if ((error = linux_sa_get(p, &sg, &sa, SCARG(uap, to), &tolen)))
312 			return (error);
313 
314 		SCARG(&bsa, to) = sa;
315 	} else
316 		SCARG(&bsa, to) = NULL;
317 	SCARG(&bsa, tolen) = tolen;
318 
319 	return (sys_sendto(p, &bsa, retval));
320 }
321 
322 int
323 linux_sys_sendmsg(p, v, retval)
324 	struct proc *p;
325 	void *v;
326 	register_t *retval;
327 {
328 	struct linux_sys_sendmsg_args /* {
329 		syscallarg(int) s;
330 		syscallarg(struct msghdr *) msg;
331 		syscallarg(u_int) flags;
332 	} */ *uap = v;
333 	struct msghdr	msg;
334 	int		error;
335 	struct sys_sendmsg_args bsa;
336 	struct msghdr *nmsg = NULL;
337 
338 	error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
339 	if (error)
340 		return (error);
341 
342 	if (msg.msg_name) {
343 		struct sockaddr *sa;
344 		caddr_t sg = stackgap_init(p, 0);
345 
346 		nmsg = (struct msghdr *) stackgap_alloc(p, &sg,
347 		    sizeof(struct msghdr));
348 		if (!nmsg)
349 			return (ENOMEM);
350 
351 		error = linux_sa_get(p, &sg, &sa,
352 		    (struct osockaddr *) msg.msg_name, &msg.msg_namelen);
353 		if (error)
354 			return (error);
355 
356 		msg.msg_name = (struct sockaddr *) sa;
357 		if ((error = copyout(&msg, nmsg, sizeof(struct msghdr))))
358 			return (error);
359 	}
360 
361 	/*
362 	 * XXX handle different alignment of cmsg data on architectures where
363 	 * the Linux alignment is different (powerpc, sparc, sparc64).
364 	 */
365 
366 	SCARG(&bsa, s) = SCARG(uap, s);
367 	SCARG(&bsa, msg) = nmsg;
368 	SCARG(&bsa, flags) = SCARG(uap, flags);
369 
370 	if ((error = sys_sendmsg(p, &bsa, retval)))
371 		return (error);
372 
373 	return (0);
374 }
375 
376 
377 int
378 linux_sys_recvfrom(p, v, retval)
379 	struct proc *p;
380 	void *v;
381 	register_t *retval;
382 {
383 	struct linux_sys_recvfrom_args /* {
384 		syscallarg(int) s;
385 		syscallarg(void *) buf;
386 		syscallarg(int) len;
387 		syscallarg(int) flags;
388 		syscallarg(struct osockaddr *) from;
389 		syscallarg(int *) fromlenaddr;
390 	} */ *uap = v;
391 	int		error;
392 	struct sys_recvfrom_args bra;
393 
394 	SCARG(&bra, s) = SCARG(uap, s);
395 	SCARG(&bra, buf) = SCARG(uap, buf);
396 	SCARG(&bra, len) = SCARG(uap, len);
397 	SCARG(&bra, flags) = SCARG(uap, flags);
398 	SCARG(&bra, from) = (struct sockaddr *) SCARG(uap, from);
399 	SCARG(&bra, fromlenaddr) = SCARG(uap, fromlenaddr);
400 
401 	if ((error = sys_recvfrom(p, &bra, retval)))
402 		return (error);
403 
404 	if (SCARG(uap, from) && (error = linux_sa_put(SCARG(uap, from))))
405 		return (error);
406 
407 	return (0);
408 }
409 
410 int
411 linux_sys_recvmsg(p, v, retval)
412 	struct proc *p;
413 	void *v;
414 	register_t *retval;
415 {
416 	struct linux_sys_recvmsg_args /* {
417 		syscallarg(int) s;
418 		syscallarg(struct msghdr *) msg;
419 		syscallarg(u_int) flags;
420 	} */ *uap = v;
421 	struct msghdr	msg;
422 	int		error;
423 
424 	if ((error = sys_recvmsg(p, v, retval)))
425 		return (error);
426 
427 	error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
428 		       sizeof(msg));
429 
430 	if (!error && msg.msg_name && msg.msg_namelen > 2)
431 		error = linux_sa_put(msg.msg_name);
432 
433 	/*
434 	 * XXX handle different alignment of cmsg data on architectures where
435 	 * the Linux alignment is different (powerpc, sparc, sparc64).
436 	 */
437 
438 	return (error);
439 }
440 
441 /*
442  * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
443  * is different, the rest matches IPPROTO_* on both systems.
444  */
445 int
446 linux_to_bsd_sopt_level(llevel)
447 	int llevel;
448 {
449 
450 	switch (llevel) {
451 	case LINUX_SOL_SOCKET:
452 		return SOL_SOCKET;
453 	case LINUX_SOL_IP:
454 		return IPPROTO_IP;
455 	case LINUX_SOL_TCP:
456 		return IPPROTO_TCP;
457 	case LINUX_SOL_UDP:
458 		return IPPROTO_UDP;
459 	default:
460 		return -1;
461 	}
462 }
463 
464 /*
465  * Convert Linux socket level socket option numbers to NetBSD values.
466  */
467 int
468 linux_to_bsd_so_sockopt(lopt)
469 	int lopt;
470 {
471 
472 	switch (lopt) {
473 	case LINUX_SO_DEBUG:
474 		return SO_DEBUG;
475 	case LINUX_SO_REUSEADDR:
476 		/*
477 		 * Linux does not implement SO_REUSEPORT, but allows reuse of a
478 		 * host:port pair through SO_REUSEADDR even if the address is not a
479 		 * multicast-address.  Effectively, this means that we should use
480 		 * SO_REUSEPORT to allow Linux applications to not exit with
481 		 * EADDRINUSE
482 		 */
483 		return SO_REUSEPORT;
484 	case LINUX_SO_TYPE:
485 		return SO_TYPE;
486 	case LINUX_SO_ERROR:
487 		return SO_ERROR;
488 	case LINUX_SO_DONTROUTE:
489 		return SO_DONTROUTE;
490 	case LINUX_SO_BROADCAST:
491 		return SO_BROADCAST;
492 	case LINUX_SO_SNDBUF:
493 		return SO_SNDBUF;
494 	case LINUX_SO_RCVBUF:
495 		return SO_RCVBUF;
496 	case LINUX_SO_KEEPALIVE:
497 		return SO_KEEPALIVE;
498 	case LINUX_SO_OOBINLINE:
499 		return SO_OOBINLINE;
500 	case LINUX_SO_LINGER:
501 		return SO_LINGER;
502 	case LINUX_SO_PRIORITY:
503 	case LINUX_SO_NO_CHECK:
504 	default:
505 		return -1;
506 	}
507 }
508 
509 /*
510  * Convert Linux IP level socket option number to NetBSD values.
511  */
512 int
513 linux_to_bsd_ip_sockopt(lopt)
514 	int lopt;
515 {
516 
517 	switch (lopt) {
518 	case LINUX_IP_TOS:
519 		return IP_TOS;
520 	case LINUX_IP_TTL:
521 		return IP_TTL;
522 	case LINUX_IP_MULTICAST_TTL:
523 		return IP_MULTICAST_TTL;
524 	case LINUX_IP_MULTICAST_LOOP:
525 		return IP_MULTICAST_LOOP;
526 	case LINUX_IP_MULTICAST_IF:
527 		return IP_MULTICAST_IF;
528 	case LINUX_IP_ADD_MEMBERSHIP:
529 		return IP_ADD_MEMBERSHIP;
530 	case LINUX_IP_DROP_MEMBERSHIP:
531 		return IP_DROP_MEMBERSHIP;
532 	default:
533 		return -1;
534 	}
535 }
536 
537 /*
538  * Convert Linux TCP level socket option number to NetBSD values.
539  */
540 int
541 linux_to_bsd_tcp_sockopt(lopt)
542 	int lopt;
543 {
544 
545 	switch (lopt) {
546 	case LINUX_TCP_NODELAY:
547 		return TCP_NODELAY;
548 	case LINUX_TCP_MAXSEG:
549 		return TCP_MAXSEG;
550 	default:
551 		return -1;
552 	}
553 }
554 
555 /*
556  * Convert Linux UDP level socket option number to NetBSD values.
557  */
558 int
559 linux_to_bsd_udp_sockopt(lopt)
560 	int lopt;
561 {
562 
563 	switch (lopt) {
564 	default:
565 		return -1;
566 	}
567 }
568 
569 /*
570  * Another reasonably straightforward function: setsockopt(2).
571  * The level and option numbers are converted; the values passed
572  * are not (yet) converted, the ones currently implemented don't
573  * need conversion, as they are the same on both systems.
574  */
575 int
576 linux_sys_setsockopt(p, v, retval)
577 	struct proc *p;
578 	void *v;
579 	register_t *retval;
580 {
581 	struct linux_sys_setsockopt_args /* {
582 		syscallarg(int) s;
583 		syscallarg(int) level;
584 		syscallarg(int) optname;
585 		syscallarg(void *) optval;
586 		syscallarg(int) optlen;
587 	} */ *uap = v;
588 	struct sys_setsockopt_args bsa;
589 	int name;
590 
591 	SCARG(&bsa, s) = SCARG(uap, s);
592 	SCARG(&bsa, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
593 	SCARG(&bsa, val) = SCARG(uap, optval);
594 	SCARG(&bsa, valsize) = SCARG(uap, optlen);
595 
596 	switch (SCARG(&bsa, level)) {
597 	case SOL_SOCKET:
598 		name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
599 		break;
600 	case IPPROTO_IP:
601 		name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
602 		break;
603 	case IPPROTO_TCP:
604 		name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
605 		break;
606 	case IPPROTO_UDP:
607 		name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
608 		break;
609 	default:
610 		return EINVAL;
611 	}
612 
613 	if (name == -1)
614 		return EINVAL;
615 	SCARG(&bsa, name) = name;
616 
617 	return sys_setsockopt(p, &bsa, retval);
618 }
619 
620 /*
621  * getsockopt(2) is very much the same as setsockopt(2) (see above)
622  */
623 int
624 linux_sys_getsockopt(p, v, retval)
625 	struct proc *p;
626 	void *v;
627 	register_t *retval;
628 {
629 	struct linux_sys_getsockopt_args /* {
630 		syscallarg(int) s;
631 		syscallarg(int) level;
632 		syscallarg(int) optname;
633 		syscallarg(void *) optval;
634 		syscallarg(int *) optlen;
635 	} */ *uap = v;
636 	struct sys_getsockopt_args bga;
637 	int name;
638 
639 	SCARG(&bga, s) = SCARG(uap, s);
640 	SCARG(&bga, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
641 	SCARG(&bga, val) = SCARG(uap, optval);
642 	SCARG(&bga, avalsize) = SCARG(uap, optlen);
643 
644 	switch (SCARG(&bga, level)) {
645 	case SOL_SOCKET:
646 		name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
647 		break;
648 	case IPPROTO_IP:
649 		name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
650 		break;
651 	case IPPROTO_TCP:
652 		name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
653 		break;
654 	case IPPROTO_UDP:
655 		name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
656 		break;
657 	default:
658 		return EINVAL;
659 	}
660 
661 	if (name == -1)
662 		return EINVAL;
663 	SCARG(&bga, name) = name;
664 
665 	return sys_getsockopt(p, &bga, retval);
666 }
667 
668 #define IF_NAME_LEN 16
669 
670 int
671 linux_getifhwaddr(p, retval, fd, data)
672 	struct proc *p;
673 	register_t *retval;
674 	u_int fd;
675 	void *data;
676 {
677 	/* Not the full structure, just enough to map what we do here */
678 	struct linux_ifreq {
679 		char if_name[IF_NAME_LEN];
680 		struct osockaddr hwaddr;
681 	} lreq;
682 	struct filedesc *fdp;
683 	struct file *fp;
684 	struct ifaddr *ifa;
685 	struct ifnet *ifp;
686 	struct sockaddr_dl *sadl;
687 	int error, found;
688 	int index, ifnum;
689 
690 	/*
691 	 * We can't emulate this ioctl by calling sys_ioctl() to run
692 	 * SIOCGIFCONF, because the user buffer is not of the right
693 	 * type to take those results.  We can't use kernel buffers to
694 	 * receive the results, as the implementation of sys_ioctl()
695 	 * and ifconf() [which implements SIOCGIFCONF] use
696 	 * copyin()/copyout() which will fail on kernel addresses.
697 	 *
698 	 * So, we must duplicate code from sys_ioctl() and ifconf().  Ugh.
699 	 */
700 
701 	fdp = p->p_fd;
702 	if ((fp = fd_getfile(fdp, fd)) == NULL)
703 		return (EBADF);
704 
705 	FILE_USE(fp);
706 	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
707 		error = EBADF;
708 		goto out;
709 	}
710 
711 	error = copyin(data, (caddr_t)&lreq, sizeof(lreq));
712 	if (error)
713 		goto out;
714 	lreq.if_name[IF_NAME_LEN-1] = '\0';		/* just in case */
715 
716 	/*
717 	 * Try real interface name first, then fake "ethX"
718 	 */
719 	for (ifp = ifnet.tqh_first, found = 0;
720 	     ifp != 0 && !found;
721 	     ifp = ifp->if_list.tqe_next) {
722 		if (strcmp(lreq.if_name, ifp->if_xname))
723 			/* not this interface */
724 			continue;
725 		found=1;
726 		if ((ifa = ifp->if_addrlist.tqh_first) != 0) {
727 			for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
728 				sadl = (struct sockaddr_dl *)ifa->ifa_addr;
729 				/* only return ethernet addresses */
730 				/* XXX what about FDDI, etc. ? */
731 				if (sadl->sdl_family != AF_LINK ||
732 				    sadl->sdl_type != IFT_ETHER)
733 					continue;
734 				memcpy((caddr_t)&lreq.hwaddr.sa_data,
735 				       LLADDR(sadl),
736 				       MIN(sadl->sdl_alen,
737 					   sizeof(lreq.hwaddr.sa_data)));
738 				lreq.hwaddr.sa_family =
739 					sadl->sdl_family;
740 				error = copyout((caddr_t)&lreq, data,
741 						sizeof(lreq));
742 				goto out;
743 			}
744 		} else {
745 			error = ENODEV;
746 			goto out;
747 		}
748 	}
749 
750 	if (strncmp(lreq.if_name, "eth", 3) == 0) {
751 		for (ifnum = 0, index = 3;
752 		     lreq.if_name[index] != '\0' && index < IF_NAME_LEN;
753 		     index++) {
754 			ifnum *= 10;
755 			ifnum += lreq.if_name[index] - '0';
756 		}
757 
758 		error = EINVAL;			/* in case we don't find one */
759 		for (ifp = ifnet.tqh_first, found = 0;
760 		     ifp != 0 && !found;
761 		     ifp = ifp->if_list.tqe_next) {
762 			memcpy(lreq.if_name, ifp->if_xname,
763 			       MIN(IF_NAME_LEN, IFNAMSIZ));
764 			if ((ifa = ifp->if_addrlist.tqh_first) == 0)
765 				/* no addresses on this interface */
766 				continue;
767 			else
768 				for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
769 					sadl = (struct sockaddr_dl *)ifa->ifa_addr;
770 					/* only return ethernet addresses */
771 					/* XXX what about FDDI, etc. ? */
772 					if (sadl->sdl_family != AF_LINK ||
773 					    sadl->sdl_type != IFT_ETHER)
774 						continue;
775 					if (ifnum--)
776 						/* not the reqested iface */
777 						continue;
778 					memcpy((caddr_t)&lreq.hwaddr.sa_data,
779 					       LLADDR(sadl),
780 					       MIN(sadl->sdl_alen,
781 						   sizeof(lreq.hwaddr.sa_data)));
782 					lreq.hwaddr.sa_family =
783 						sadl->sdl_family;
784 					error = copyout((caddr_t)&lreq, data,
785 							sizeof(lreq));
786 					found = 1;
787 					break;
788 				}
789 		}
790 	} else {
791 		/* unknown interface, not even an "eth*" name */
792 		error = ENODEV;
793 	}
794 
795 out:
796 	FILE_UNUSE(fp, p);
797 	return error;
798 }
799 #undef IF_NAME_LEN
800 
801 int
802 linux_ioctl_socket(p, uap, retval)
803 	struct proc *p;
804 	struct linux_sys_ioctl_args /* {
805 		syscallarg(int) fd;
806 		syscallarg(u_long) com;
807 		syscallarg(caddr_t) data;
808 	} */ *uap;
809 	register_t *retval;
810 {
811 	u_long com;
812 	int error = 0, isdev = 0, dosys = 1;
813 	struct sys_ioctl_args ia;
814 	struct file *fp;
815 	struct filedesc *fdp;
816 	struct vnode *vp;
817 	int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *));
818 	struct ioctl_pt pt;
819 
820         fdp = p->p_fd;
821 	if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
822 		return (EBADF);
823 
824 	FILE_USE(fp);
825 
826 	if (fp->f_type == DTYPE_VNODE) {
827 		vp = (struct vnode *)fp->f_data;
828 		isdev = vp->v_type == VCHR;
829 	}
830 
831 	/*
832 	 * Don't try to interpret socket ioctl calls that are done
833 	 * on a device filedescriptor, just pass them through, to
834 	 * emulate Linux behaviour. Use PTIOCLINUX so that the
835 	 * device will only handle these if it's prepared to do
836 	 * so, to avoid unexpected things from happening.
837 	 */
838 	if (isdev) {
839 		dosys = 0;
840 		ioctlf = fp->f_ops->fo_ioctl;
841 		pt.com = SCARG(uap, com);
842 		pt.data = SCARG(uap, data);
843 		error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
844 		/*
845 		 * XXX hack: if the function returns EJUSTRETURN,
846 		 * it has stuffed a sysctl return value in pt.data.
847 		 */
848 		if (error == EJUSTRETURN) {
849 			retval[0] = (register_t)pt.data;
850 			error = 0;
851 		}
852 		goto out;
853 	}
854 
855 	com = SCARG(uap, com);
856 	retval[0] = 0;
857 
858 	switch (com) {
859 	case LINUX_SIOCGIFCONF:
860 		SCARG(&ia, com) = OSIOCGIFCONF;
861 		break;
862 	case LINUX_SIOCGIFFLAGS:
863 		SCARG(&ia, com) = SIOCGIFFLAGS;
864 		break;
865 	case LINUX_SIOCSIFFLAGS:
866 		SCARG(&ia, com) = SIOCSIFFLAGS;
867 		break;
868 	case LINUX_SIOCGIFADDR:
869 		SCARG(&ia, com) = OSIOCGIFADDR;
870 		break;
871 	case LINUX_SIOCGIFDSTADDR:
872 		SCARG(&ia, com) = OSIOCGIFDSTADDR;
873 		break;
874 	case LINUX_SIOCGIFBRDADDR:
875 		SCARG(&ia, com) = OSIOCGIFBRDADDR;
876 		break;
877 	case LINUX_SIOCGIFNETMASK:
878 		SCARG(&ia, com) = OSIOCGIFNETMASK;
879 		break;
880 	case LINUX_SIOCADDMULTI:
881 		SCARG(&ia, com) = SIOCADDMULTI;
882 		break;
883 	case LINUX_SIOCDELMULTI:
884 		SCARG(&ia, com) = SIOCDELMULTI;
885 		break;
886 	case LINUX_SIOCGIFHWADDR:
887 	        error = linux_getifhwaddr(p, retval, SCARG(uap, fd),
888 					 SCARG(uap, data));
889 		dosys = 0;
890 		break;
891 	default:
892 		error = EINVAL;
893 	}
894 
895 out:
896 	FILE_UNUSE(fp, p);
897 
898 	if (error ==0 && dosys) {
899 		SCARG(&ia, fd) = SCARG(uap, fd);
900 		SCARG(&ia, data) = SCARG(uap, data);
901 		error = sys_ioctl(p, &ia, retval);
902 	}
903 
904 	return error;
905 }
906 
907 int
908 linux_sys_connect(p, v, retval)
909 	struct proc *p;
910 	void *v;
911 	register_t *retval;
912 {
913 	struct linux_sys_connect_args /* {
914 		syscallarg(int) s;
915 		syscallarg(const struct sockaddr *) name;
916 		syscallarg(int) namelen;
917 	} */ *uap = v;
918 	int		error;
919 	struct sockaddr *sa;
920 	struct sys_connect_args bca;
921 	caddr_t sg = stackgap_init(p, 0);
922 	int namlen;
923 
924 	namlen = SCARG(uap, namelen);
925 	error = linux_sa_get(p, &sg, &sa, SCARG(uap, name), &namlen);
926 	if (error)
927 		return (error);
928 
929 	SCARG(&bca, s) = SCARG(uap, s);
930 	SCARG(&bca, name) = sa;
931 	SCARG(&bca, namelen) = (unsigned int) namlen;
932 
933 	error = sys_connect(p, &bca, retval);
934 
935 	if (error == EISCONN) {
936 		struct file *fp;
937 		struct socket *so;
938 		int s, state, prflags;
939 
940 		/* getsock() will use the descriptor for us */
941 	    	if (getsock(p->p_fd, SCARG(uap, s), &fp) != 0)
942 		    	return EISCONN;
943 
944 		s = splsoftnet();
945 		so = (struct socket *)fp->f_data;
946 		state = so->so_state;
947 		prflags = so->so_proto->pr_flags;
948 		splx(s);
949 		FILE_UNUSE(fp, p);
950 		/*
951 		 * We should only let this call succeed once per
952 		 * non-blocking connect; however we don't have
953 		 * a convenient place to keep that state..
954 		 */
955 		if ((state & SS_NBIO) && (state & SS_ISCONNECTED) &&
956 		    (prflags & PR_CONNREQUIRED))
957 			return 0;
958 	}
959 
960 	return (error);
961 }
962 
963 int
964 linux_sys_bind(p, v, retval)
965 	struct proc *p;
966 	void *v;
967 	register_t *retval;
968 {
969 	struct linux_sys_bind_args /* {
970 		syscallarg(int) s;
971 		syscallarg(const struct osockaddr *) name;
972 		syscallarg(int) namelen;
973 	} */ *uap = v;
974 	int		error, namlen;
975 	struct sys_bind_args bsa;
976 
977 	namlen = SCARG(uap, namelen);
978 	SCARG(&bsa, s) = SCARG(uap, s);
979 	if (SCARG(uap, name)) {
980 		struct sockaddr *sa;
981 		caddr_t sg = stackgap_init(p, 0);
982 
983 		error = linux_sa_get(p, &sg, &sa, SCARG(uap, name), &namlen);
984 		if (error)
985 			return (error);
986 
987 		SCARG(&bsa, name) = sa;
988 	} else
989 		SCARG(&bsa, name) = NULL;
990 	SCARG(&bsa, namelen) = namlen;
991 
992 	return (sys_bind(p, &bsa, retval));
993 }
994 
995 int
996 linux_sys_getsockname(p, v, retval)
997 	struct proc *p;
998 	void *v;
999 	register_t *retval;
1000 {
1001 	struct linux_sys_getsockname_args /* {
1002 		syscallarg(int) fdes;
1003 		syscallarg(caddr_t) asa;
1004 		syscallarg(int *) alen;
1005 	} */ *uap = v;
1006 	int error;
1007 
1008 	if ((error = sys_getsockname(p, uap, retval)) != 0)
1009 		return (error);
1010 
1011 	if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
1012 		return (error);
1013 
1014 	return (0);
1015 }
1016 
1017 int
1018 linux_sys_getpeername(p, v, retval)
1019 	struct proc *p;
1020 	void *v;
1021 	register_t *retval;
1022 {
1023 	struct sys_getpeername_args /* {
1024 		syscallarg(int) fdes;
1025 		syscallarg(caddr_t) asa;
1026 		syscallarg(int *) alen;
1027 	} */ *uap = v;
1028 	int error;
1029 
1030 	if ((error = sys_getpeername(p, uap, retval)) != 0)
1031 		return (error);
1032 
1033 	if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
1034 		return (error);
1035 
1036 	return (0);
1037 }
1038 
1039 /*
1040  * Copy the osockaddr structure pointed to by osa to kernel, adjust
1041  * family and convert to sockaddr, allocate stackgap and put the
1042  * the converted structure there, address on stackgap returned in sap.
1043  */
1044 static int
1045 linux_sa_get(p, sgp, sap, osa, osalen)
1046 	struct proc *p;
1047 	caddr_t *sgp;
1048 	struct sockaddr **sap;
1049 	const struct osockaddr *osa;
1050 	int *osalen;
1051 {
1052 	int error=0, bdom;
1053 	struct sockaddr *sa, *usa;
1054 	struct osockaddr *kosa = (struct osockaddr *) &sa;
1055 	int alloclen;
1056 #ifdef INET6
1057 	int oldv6size;
1058 	struct sockaddr_in6 *sin6;
1059 #endif
1060 
1061 	if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) {
1062 		DPRINTF(("bad osa=%p osalen=%d\n", osa, *osalen));
1063 		return (EINVAL);
1064 	}
1065 
1066 	alloclen = *osalen;
1067 #ifdef INET6
1068 	oldv6size = 0;
1069 	/*
1070 	 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
1071 	 * if it's a v4-mapped address, so reserve the proper space
1072 	 * for it.
1073 	 */
1074 	if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
1075 		alloclen = sizeof (struct sockaddr_in6);
1076 		oldv6size = 1;
1077 	}
1078 #endif
1079 
1080 	kosa = (struct osockaddr *) malloc(alloclen, M_TEMP, M_WAITOK);
1081 
1082 	if ((error = copyin(osa, (caddr_t) kosa, *osalen))) {
1083 		DPRINTF(("error copying osa %d\n", error));
1084 		goto out;
1085 	}
1086 
1087 	bdom = linux_to_bsd_domain(kosa->sa_family);
1088 	if (bdom == -1) {
1089 		DPRINTF(("bad linux family=%d\n", kosa->sa_family));
1090 		error = EINVAL;
1091 		goto out;
1092 	}
1093 
1094 #ifdef INET6
1095 	/*
1096 	 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
1097 	 * which lacks the scope id compared with RFC2553 one. If we detect
1098 	 * the situation, reject the address and write a message to system log.
1099 	 *
1100 	 * Still accept addresses for which the scope id is not used.
1101 	 */
1102 	if (oldv6size && bdom == AF_INET6) {
1103 		sin6 = (struct sockaddr_in6 *)kosa;
1104 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
1105 		    (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
1106 		     !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
1107 		     !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
1108 		     !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
1109 		     !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
1110 			sin6->sin6_scope_id = 0;
1111 		} else {
1112 			struct proc *p = curproc;	/* XXX */
1113 			int uid = p->p_cred && p->p_ucred ?
1114 					p->p_ucred->cr_uid : -1;
1115 
1116 			log(LOG_DEBUG,
1117 			    "pid %d (%s), uid %d: obsolete pre-RFC2553 "
1118 			    "sockaddr_in6 rejected",
1119 			    p->p_pid, p->p_comm, uid);
1120 			error = EINVAL;
1121 			goto out;
1122 		}
1123 	} else
1124 #endif
1125 	if (bdom == AF_INET) {
1126 		alloclen = sizeof(struct sockaddr_in);
1127 	}
1128 
1129 	sa = (struct sockaddr *) kosa;
1130 	sa->sa_family = bdom;
1131 	sa->sa_len = alloclen;
1132 #ifdef DEBUG_LINUX
1133 	DPRINTF(("family %d, len = %d [ ", sa->sa_family, sa->sa_len));
1134 	for (bdom = 0; bdom < sizeof(sa->sa_data); bdom++)
1135 	    DPRINTF(("%02x ", sa->sa_data[bdom]));
1136 	DPRINTF(("\n"));
1137 #endif
1138 
1139 	usa = (struct sockaddr *) stackgap_alloc(p, sgp, alloclen);
1140 	if (!usa) {
1141 		error = ENOMEM;
1142 		goto out;
1143 	}
1144 
1145 	if ((error = copyout(sa, usa, alloclen))) {
1146 		DPRINTF(("error copying out socket %d\n", error));
1147 		goto out;
1148 	}
1149 
1150 	*sap = usa;
1151 
1152     out:
1153 	*osalen = alloclen;
1154 	free(kosa, M_TEMP);
1155 	return (error);
1156 }
1157 
1158 static int
1159 linux_sa_put(osa)
1160 	struct osockaddr *osa;
1161 {
1162 	struct sockaddr sa;
1163 	struct osockaddr *kosa;
1164 	int error, bdom, len;
1165 
1166 	/*
1167 	 * Only read/write the sockaddr family and length part, the rest is
1168 	 * not changed.
1169 	 */
1170 	len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
1171 
1172 	error = copyin((caddr_t) osa, (caddr_t) &sa, len);
1173 	if (error)
1174 		return (error);
1175 
1176 	bdom = bsd_to_linux_domain(sa.sa_family);
1177 	if (bdom == -1)
1178 		return (EINVAL);
1179 
1180 	/* Note: we convert from sockaddr to osockaddr here, too */
1181 	kosa = (struct osockaddr *) &sa;
1182 	kosa->sa_family = bdom;
1183 	error = copyout(kosa, osa, len);
1184 	if (error)
1185 		return (error);
1186 
1187 	return (0);
1188 }
1189 
1190 int
1191 linux_sys_recv(p, v, retval)
1192 	struct proc *p;
1193 	void *v;
1194 	register_t *retval;
1195 {
1196 	struct linux_sys_recv_args /* {
1197 		syscallarg(int) s;
1198 		syscallarg(void *) buf;
1199 		syscallarg(int) len;
1200 		syscallarg(int) flags;
1201 	} */ *uap = v;
1202 	struct sys_recvfrom_args bra;
1203 
1204 
1205 	SCARG(&bra, s) = SCARG(uap, s);
1206 	SCARG(&bra, buf) = SCARG(uap, buf);
1207 	SCARG(&bra, len) = (size_t) SCARG(uap, len);
1208 	SCARG(&bra, flags) = SCARG(uap, flags);
1209 	SCARG(&bra, from) = NULL;
1210 	SCARG(&bra, fromlenaddr) = NULL;
1211 
1212 	return (sys_recvfrom(p, &bra, retval));
1213 }
1214 
1215 int
1216 linux_sys_send(p, v, retval)
1217 	struct proc *p;
1218 	void *v;
1219 	register_t *retval;
1220 {
1221 	struct linux_sys_send_args /* {
1222 		syscallarg(int) s;
1223 		syscallarg(caddr_t) buf;
1224 		syscallarg(int) len;
1225 		syscallarg(int) flags;
1226 	} */ *uap = v;
1227 	struct sys_sendto_args bsa;
1228 
1229 	SCARG(&bsa, s)		= SCARG(uap, s);
1230 	SCARG(&bsa, buf)	= SCARG(uap, buf);
1231 	SCARG(&bsa, len)	= SCARG(uap, len);
1232 	SCARG(&bsa, flags)	= SCARG(uap, flags);
1233 	SCARG(&bsa, to)		= NULL;
1234 	SCARG(&bsa, tolen)	= 0;
1235 
1236 	return (sys_sendto(p, &bsa, retval));
1237 }
1238 
1239 int
1240 linux_sys_accept(p, v, retval)
1241 	struct proc *p;
1242 	void *v;
1243 	register_t *retval;
1244 {
1245 	struct linux_sys_accept_args /* {
1246 		syscallarg(int) s;
1247 		syscallarg(struct osockaddr *) name;
1248 		syscallarg(int *) anamelen;
1249 	} */ *uap = v;
1250 	int error;
1251 	struct sys_accept_args baa;
1252 
1253 	SCARG(&baa, s)		= SCARG(uap, s);
1254 	SCARG(&baa, name)	= (struct sockaddr *) SCARG(uap, name);
1255 	SCARG(&baa, anamelen)	= (unsigned int *) SCARG(uap, anamelen);
1256 
1257 	if ((error = sys_accept(p, &baa, retval)))
1258 		return (error);
1259 
1260 	if (SCARG(uap, name) && (error = linux_sa_put(SCARG(uap, name))))
1261 		return (error);
1262 
1263 	return (0);
1264 }
1265