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