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