xref: /netbsd-src/sys/compat/linux/common/linux_socket.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
1 /*	$NetBSD: linux_socket.c,v 1.33 2001/07/04 10:24:18 jdolecek 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 
258 	SCARG(&bsa, s) = SCARG(uap, s);
259 	SCARG(&bsa, buf) = SCARG(uap, msg);
260 	SCARG(&bsa, len) = (size_t) SCARG(uap, len);
261 	SCARG(&bsa, flags) = SCARG(uap, flags);
262 	if (SCARG(uap, to)) {
263 		struct sockaddr *sa;
264 		int error;
265 		caddr_t sg = stackgap_init(p->p_emul);
266 
267 		if ((error = linux_sa_get(&sg, &sa, SCARG(uap, to),
268 		    SCARG(uap, tolen))))
269 			return (error);
270 
271 		SCARG(&bsa, to) = sa;
272 	} else
273 		SCARG(&bsa, to) = NULL;
274 	SCARG(&bsa, tolen) = SCARG(uap, tolen);
275 
276 	return (sys_sendto(p, &bsa, retval));
277 }
278 
279 int
280 linux_sys_sendmsg(p, v, retval)
281 	struct proc *p;
282 	void *v;
283 	register_t *retval;
284 {
285 	struct linux_sys_sendmsg_args /* {
286 		syscallarg(int) s;
287 		syscallarg(struct msghdr *) msg;
288 		syscallarg(u_int) flags;
289 	} */ *uap = v;
290 	struct msghdr	msg;
291 	int		error;
292 	struct sys_sendmsg_args bsa;
293 	struct msghdr *nmsg = NULL;
294 
295 	error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
296 	if (error)
297 		return (error);
298 
299 	if (msg.msg_name) {
300 		struct sockaddr *sa;
301 		caddr_t sg = stackgap_init(p->p_emul);
302 
303 		nmsg = (struct msghdr *) stackgap_alloc(&sg,
304 		    sizeof(struct msghdr));
305 		if (!nmsg)
306 			return (ENOMEM);
307 
308 		error = linux_sa_get(&sg, &sa,
309 		    (struct osockaddr *) msg.msg_name, msg.msg_namelen);
310 		if (error)
311 			return (error);
312 
313 		msg.msg_name = (struct sockaddr *) sa;
314 		if ((error = copyout(&msg, nmsg, sizeof(struct msghdr))))
315 			return (error);
316 	}
317 
318 	/*
319 	 * XXX handle different alignment of cmsg data on architectures where
320 	 * the Linux alignment is different (powerpc, sparc, sparc64).
321 	 */
322 
323 	SCARG(&bsa, s) = SCARG(uap, s);
324 	SCARG(&bsa, msg) = nmsg;
325 	SCARG(&bsa, flags) = SCARG(uap, flags);
326 
327 	if ((error = sys_sendmsg(p, &bsa, retval)))
328 		return (error);
329 
330 	return (0);
331 }
332 
333 
334 int
335 linux_sys_recvfrom(p, v, retval)
336 	struct proc *p;
337 	void *v;
338 	register_t *retval;
339 {
340 	struct linux_sys_recvfrom_args /* {
341 		syscallarg(int) s;
342 		syscallarg(void *) buf;
343 		syscallarg(int) len;
344 		syscallarg(int) flags;
345 		syscallarg(struct osockaddr *) from;
346 		syscallarg(int *) fromlenaddr;
347 	} */ *uap = v;
348 	int		error;
349 	struct sys_recvfrom_args bra;
350 
351 	SCARG(&bra, s) = SCARG(uap, s);
352 	SCARG(&bra, buf) = SCARG(uap, buf);
353 	SCARG(&bra, len) = SCARG(uap, len);
354 	SCARG(&bra, flags) = SCARG(uap, flags);
355 	SCARG(&bra, from) = (struct sockaddr *) SCARG(uap, from);
356 	SCARG(&bra, fromlenaddr) = SCARG(uap, fromlenaddr);
357 
358 	if ((error = sys_recvfrom(p, &bra, retval)))
359 		return (error);
360 
361 	if (SCARG(uap, from) && (error = linux_sa_put(SCARG(uap, from))))
362 		return (error);
363 
364 	return (0);
365 }
366 
367 int
368 linux_sys_recvmsg(p, v, retval)
369 	struct proc *p;
370 	void *v;
371 	register_t *retval;
372 {
373 	struct linux_sys_recvmsg_args /* {
374 		syscallarg(int) s;
375 		syscallarg(struct msghdr *) msg;
376 		syscallarg(u_int) flags;
377 	} */ *uap = v;
378 	struct msghdr	msg;
379 	int		error;
380 
381 	if ((error = sys_recvmsg(p, v, retval)))
382 		return (error);
383 
384 	error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
385 		       sizeof(msg));
386 
387 	if (!error && msg.msg_name && msg.msg_namelen > 2)
388 		error = linux_sa_put(msg.msg_name);
389 
390 	/*
391 	 * XXX handle different alignment of cmsg data on architectures where
392 	 * the Linux alignment is different (powerpc, sparc, sparc64).
393 	 */
394 
395 	return (error);
396 }
397 
398 /*
399  * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
400  * is different, the rest matches IPPROTO_* on both systems.
401  */
402 int
403 linux_to_bsd_sopt_level(llevel)
404 	int llevel;
405 {
406 
407 	switch (llevel) {
408 	case LINUX_SOL_SOCKET:
409 		return SOL_SOCKET;
410 	case LINUX_SOL_IP:
411 		return IPPROTO_IP;
412 	case LINUX_SOL_TCP:
413 		return IPPROTO_TCP;
414 	case LINUX_SOL_UDP:
415 		return IPPROTO_UDP;
416 	default:
417 		return -1;
418 	}
419 }
420 
421 /*
422  * Convert Linux socket level socket option numbers to NetBSD values.
423  */
424 int
425 linux_to_bsd_so_sockopt(lopt)
426 	int lopt;
427 {
428 
429 	switch (lopt) {
430 	case LINUX_SO_DEBUG:
431 		return SO_DEBUG;
432 	case LINUX_SO_REUSEADDR:
433 		return SO_REUSEADDR;
434 	case LINUX_SO_TYPE:
435 		return SO_TYPE;
436 	case LINUX_SO_ERROR:
437 		return SO_ERROR;
438 	case LINUX_SO_DONTROUTE:
439 		return SO_DONTROUTE;
440 	case LINUX_SO_BROADCAST:
441 		return SO_BROADCAST;
442 	case LINUX_SO_SNDBUF:
443 		return SO_SNDBUF;
444 	case LINUX_SO_RCVBUF:
445 		return SO_RCVBUF;
446 	case LINUX_SO_KEEPALIVE:
447 		return SO_KEEPALIVE;
448 	case LINUX_SO_OOBINLINE:
449 		return SO_OOBINLINE;
450 	case LINUX_SO_LINGER:
451 		return SO_LINGER;
452 	case LINUX_SO_PRIORITY:
453 	case LINUX_SO_NO_CHECK:
454 	default:
455 		return -1;
456 	}
457 }
458 
459 /*
460  * Convert Linux IP level socket option number to NetBSD values.
461  */
462 int
463 linux_to_bsd_ip_sockopt(lopt)
464 	int lopt;
465 {
466 
467 	switch (lopt) {
468 	case LINUX_IP_TOS:
469 		return IP_TOS;
470 	case LINUX_IP_TTL:
471 		return IP_TTL;
472 	case LINUX_IP_MULTICAST_TTL:
473 		return IP_MULTICAST_TTL;
474 	case LINUX_IP_MULTICAST_LOOP:
475 		return IP_MULTICAST_LOOP;
476 	case LINUX_IP_MULTICAST_IF:
477 		return IP_MULTICAST_IF;
478 	case LINUX_IP_ADD_MEMBERSHIP:
479 		return IP_ADD_MEMBERSHIP;
480 	case LINUX_IP_DROP_MEMBERSHIP:
481 		return IP_DROP_MEMBERSHIP;
482 	default:
483 		return -1;
484 	}
485 }
486 
487 /*
488  * Convert Linux TCP level socket option number to NetBSD values.
489  */
490 int
491 linux_to_bsd_tcp_sockopt(lopt)
492 	int lopt;
493 {
494 
495 	switch (lopt) {
496 	case LINUX_TCP_NODELAY:
497 		return TCP_NODELAY;
498 	case LINUX_TCP_MAXSEG:
499 		return TCP_MAXSEG;
500 	default:
501 		return -1;
502 	}
503 }
504 
505 /*
506  * Convert Linux UDP level socket option number to NetBSD values.
507  */
508 int
509 linux_to_bsd_udp_sockopt(lopt)
510 	int lopt;
511 {
512 
513 	switch (lopt) {
514 	default:
515 		return -1;
516 	}
517 }
518 
519 /*
520  * Another reasonably straightforward function: setsockopt(2).
521  * The level and option numbers are converted; the values passed
522  * are not (yet) converted, the ones currently implemented don't
523  * need conversion, as they are the same on both systems.
524  */
525 int
526 linux_sys_setsockopt(p, v, retval)
527 	struct proc *p;
528 	void *v;
529 	register_t *retval;
530 {
531 	struct linux_sys_setsockopt_args /* {
532 		syscallarg(int) s;
533 		syscallarg(int) level;
534 		syscallarg(int) optname;
535 		syscallarg(void *) optval;
536 		syscallarg(int) optlen;
537 	} */ *uap = v;
538 	struct sys_setsockopt_args bsa;
539 	int name;
540 
541 	SCARG(&bsa, s) = SCARG(uap, s);
542 	SCARG(&bsa, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
543 	SCARG(&bsa, val) = SCARG(uap, optval);
544 	SCARG(&bsa, valsize) = SCARG(uap, optlen);
545 
546 	switch (SCARG(&bsa, level)) {
547 		case SOL_SOCKET:
548 			name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
549 			break;
550 		case IPPROTO_IP:
551 			name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
552 			break;
553 		case IPPROTO_TCP:
554 			name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
555 			break;
556 		case IPPROTO_UDP:
557 			name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
558 			break;
559 		default:
560 			return EINVAL;
561 	}
562 
563 	if (name == -1)
564 		return EINVAL;
565 	SCARG(&bsa, name) = name;
566 
567 	return sys_setsockopt(p, &bsa, retval);
568 }
569 
570 /*
571  * getsockopt(2) is very much the same as setsockopt(2) (see above)
572  */
573 int
574 linux_sys_getsockopt(p, v, retval)
575 	struct proc *p;
576 	void *v;
577 	register_t *retval;
578 {
579 	struct linux_sys_getsockopt_args /* {
580 		syscallarg(int) s;
581 		syscallarg(int) level;
582 		syscallarg(int) optname;
583 		syscallarg(void *) optval;
584 		syscallarg(int *) optlen;
585 	} */ *uap = v;
586 	struct sys_getsockopt_args bga;
587 	int name;
588 
589 	SCARG(&bga, s) = SCARG(uap, s);
590 	SCARG(&bga, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
591 	SCARG(&bga, val) = SCARG(uap, optval);
592 	SCARG(&bga, avalsize) = SCARG(uap, optlen);
593 
594 	switch (SCARG(&bga, level)) {
595 		case SOL_SOCKET:
596 			name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
597 			break;
598 		case IPPROTO_IP:
599 			name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
600 			break;
601 		case IPPROTO_TCP:
602 			name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
603 			break;
604 		case IPPROTO_UDP:
605 			name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
606 			break;
607 		default:
608 			return EINVAL;
609 	}
610 
611 	if (name == -1)
612 		return EINVAL;
613 	SCARG(&bga, name) = name;
614 
615 	return sys_getsockopt(p, &bga, retval);
616 }
617 
618 #define IF_NAME_LEN 16
619 
620 int
621 linux_getifhwaddr(p, retval, fd, data)
622 	struct proc *p;
623 	register_t *retval;
624 	u_int fd;
625 	void *data;
626 {
627 	/* Not the full structure, just enough to map what we do here */
628 	struct linux_ifreq {
629 		char if_name[IF_NAME_LEN];
630 		struct osockaddr hwaddr;
631 	} lreq;
632 	struct filedesc *fdp;
633 	struct file *fp;
634 	struct ifaddr *ifa;
635 	struct ifnet *ifp;
636 	struct sockaddr_dl *sadl;
637 	int error, found;
638 	int index, ifnum;
639 
640 	/*
641 	 * We can't emulate this ioctl by calling sys_ioctl() to run
642 	 * SIOCGIFCONF, because the user buffer is not of the right
643 	 * type to take those results.  We can't use kernel buffers to
644 	 * receive the results, as the implementation of sys_ioctl()
645 	 * and ifconf() [which implements SIOCGIFCONF] use
646 	 * copyin()/copyout() which will fail on kernel addresses.
647 	 *
648 	 * So, we must duplicate code from sys_ioctl() and ifconf().  Ugh.
649 	 */
650 
651 	fdp = p->p_fd;
652 	if ((fp = fd_getfile(fdp, fd)) == NULL)
653 		return (EBADF);
654 
655 	FILE_USE(fp);
656 	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
657 		error = EBADF;
658 		goto out;
659 	}
660 
661 	error = copyin(data, (caddr_t)&lreq, sizeof(lreq));
662 	if (error)
663 		goto out;
664 	lreq.if_name[IF_NAME_LEN-1] = '\0';		/* just in case */
665 
666 	/*
667 	 * Try real interface name first, then fake "ethX"
668 	 */
669 	for (ifp = ifnet.tqh_first, found = 0;
670 	     ifp != 0 && !found;
671 	     ifp = ifp->if_list.tqe_next) {
672 		if (strcmp(lreq.if_name, ifp->if_xname))
673 			/* not this interface */
674 			continue;
675 		found=1;
676 		if ((ifa = ifp->if_addrlist.tqh_first) != 0) {
677 			for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
678 				sadl = (struct sockaddr_dl *)ifa->ifa_addr;
679 				/* only return ethernet addresses */
680 				/* XXX what about FDDI, etc. ? */
681 				if (sadl->sdl_family != AF_LINK ||
682 				    sadl->sdl_type != IFT_ETHER)
683 					continue;
684 				memcpy((caddr_t)&lreq.hwaddr.sa_data,
685 				       LLADDR(sadl),
686 				       MIN(sadl->sdl_alen,
687 					   sizeof(lreq.hwaddr.sa_data)));
688 				lreq.hwaddr.sa_family =
689 					sadl->sdl_family;
690 				error = copyout((caddr_t)&lreq, data,
691 						sizeof(lreq));
692 				goto out;
693 			}
694 		} else {
695 			error = ENODEV;
696 			goto out;
697 		}
698 	}
699 
700 	if (strncmp(lreq.if_name, "eth", 3) == 0) {
701 		for (ifnum = 0, index = 3;
702 		     lreq.if_name[index] != '\0' && index < IF_NAME_LEN;
703 		     index++) {
704 			ifnum *= 10;
705 			ifnum += lreq.if_name[index] - '0';
706 		}
707 
708 		error = EINVAL;			/* in case we don't find one */
709 		for (ifp = ifnet.tqh_first, found = 0;
710 		     ifp != 0 && !found;
711 		     ifp = ifp->if_list.tqe_next) {
712 			memcpy(lreq.if_name, ifp->if_xname,
713 			       MIN(IF_NAME_LEN, IFNAMSIZ));
714 			if ((ifa = ifp->if_addrlist.tqh_first) == 0)
715 				/* no addresses on this interface */
716 				continue;
717 			else
718 				for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
719 					sadl = (struct sockaddr_dl *)ifa->ifa_addr;
720 					/* only return ethernet addresses */
721 					/* XXX what about FDDI, etc. ? */
722 					if (sadl->sdl_family != AF_LINK ||
723 					    sadl->sdl_type != IFT_ETHER)
724 						continue;
725 					if (ifnum--)
726 						/* not the reqested iface */
727 						continue;
728 					memcpy((caddr_t)&lreq.hwaddr.sa_data,
729 					       LLADDR(sadl),
730 					       MIN(sadl->sdl_alen,
731 						   sizeof(lreq.hwaddr.sa_data)));
732 					lreq.hwaddr.sa_family =
733 						sadl->sdl_family;
734 					error = copyout((caddr_t)&lreq, data,
735 							sizeof(lreq));
736 					found = 1;
737 					break;
738 				}
739 		}
740 	} else {
741 		/* unknown interface, not even an "eth*" name */
742 		error = ENODEV;
743 	}
744 
745 out:
746 	FILE_UNUSE(fp, p);
747 	return error;
748 }
749 #undef IF_NAME_LEN
750 
751 int
752 linux_ioctl_socket(p, uap, retval)
753 	struct proc *p;
754 	struct linux_sys_ioctl_args /* {
755 		syscallarg(int) fd;
756 		syscallarg(u_long) com;
757 		syscallarg(caddr_t) data;
758 	} */ *uap;
759 	register_t *retval;
760 {
761 	u_long com;
762 	int error = 0, isdev = 0, dosys = 1;
763 	struct sys_ioctl_args ia;
764 	struct file *fp;
765 	struct filedesc *fdp;
766 	struct vnode *vp;
767 	int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *));
768 	struct ioctl_pt pt;
769 
770         fdp = p->p_fd;
771 	if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
772 		return (EBADF);
773 
774 	FILE_USE(fp);
775 
776 	if (fp->f_type == DTYPE_VNODE) {
777 		vp = (struct vnode *)fp->f_data;
778 		isdev = vp->v_type == VCHR;
779 	}
780 
781 	/*
782 	 * Don't try to interpret socket ioctl calls that are done
783 	 * on a device filedescriptor, just pass them through, to
784 	 * emulate Linux behaviour. Use PTIOCLINUX so that the
785 	 * device will only handle these if it's prepared to do
786 	 * so, to avoid unexpected things from happening.
787 	 */
788 	if (isdev) {
789 		dosys = 0;
790 		ioctlf = fp->f_ops->fo_ioctl;
791 		pt.com = SCARG(uap, com);
792 		pt.data = SCARG(uap, data);
793 		error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
794 		/*
795 		 * XXX hack: if the function returns EJUSTRETURN,
796 		 * it has stuffed a sysctl return value in pt.data.
797 		 */
798 		if (error == EJUSTRETURN) {
799 			retval[0] = (register_t)pt.data;
800 			error = 0;
801 		}
802 		goto out;
803 	}
804 
805 	com = SCARG(uap, com);
806 	retval[0] = 0;
807 
808 	switch (com) {
809 	case LINUX_SIOCGIFCONF:
810 		SCARG(&ia, com) = OSIOCGIFCONF;
811 		break;
812 	case LINUX_SIOCGIFFLAGS:
813 		SCARG(&ia, com) = SIOCGIFFLAGS;
814 		break;
815 	case LINUX_SIOCSIFFLAGS:
816 		SCARG(&ia, com) = SIOCSIFFLAGS;
817 		break;
818 	case LINUX_SIOCGIFADDR:
819 		SCARG(&ia, com) = OSIOCGIFADDR;
820 		break;
821 	case LINUX_SIOCGIFDSTADDR:
822 		SCARG(&ia, com) = OSIOCGIFDSTADDR;
823 		break;
824 	case LINUX_SIOCGIFBRDADDR:
825 		SCARG(&ia, com) = OSIOCGIFBRDADDR;
826 		break;
827 	case LINUX_SIOCGIFNETMASK:
828 		SCARG(&ia, com) = OSIOCGIFNETMASK;
829 		break;
830 	case LINUX_SIOCADDMULTI:
831 		SCARG(&ia, com) = SIOCADDMULTI;
832 		break;
833 	case LINUX_SIOCDELMULTI:
834 		SCARG(&ia, com) = SIOCDELMULTI;
835 		break;
836 	case LINUX_SIOCGIFHWADDR:
837 	        error = linux_getifhwaddr(p, retval, SCARG(uap, fd),
838 					 SCARG(uap, data));
839 		dosys = 0;
840 		break;
841 	default:
842 		error = EINVAL;
843 	}
844 
845 out:
846 	FILE_UNUSE(fp, p);
847 
848 	if (error ==0 && dosys) {
849 		SCARG(&ia, fd) = SCARG(uap, fd);
850 		SCARG(&ia, data) = SCARG(uap, data);
851 		error = sys_ioctl(p, &ia, retval);
852 	}
853 
854 	return error;
855 }
856 
857 int
858 linux_sys_connect(p, v, retval)
859 	struct proc *p;
860 	void *v;
861 	register_t *retval;
862 {
863 	struct linux_sys_connect_args /* {
864 		syscallarg(int) s;
865 		syscallarg(const struct sockaddr *) name;
866 		syscallarg(int) namelen;
867 	} */ *uap = v;
868 	int		error;
869 	struct sockaddr *sa;
870 	struct sys_connect_args bca;
871 	caddr_t sg = stackgap_init(p->p_emul);
872 
873 	error = linux_sa_get(&sg, &sa, SCARG(uap, name), SCARG(uap, namelen));
874 	if (error)
875 		return (error);
876 
877 	SCARG(&bca, s) = SCARG(uap, s);
878 	SCARG(&bca, name) = sa;
879 	SCARG(&bca, namelen) = (unsigned int) SCARG(uap, namelen);
880 
881 	error = sys_connect(p, &bca, retval);
882 
883 	if (error == EISCONN) {
884 		struct file *fp;
885 		struct socket *so;
886 		int s, state, prflags;
887 
888 		/* getsock() will use the descriptor for us */
889 	    	if (getsock(p->p_fd, SCARG(uap, s), &fp) != 0)
890 		    	return EISCONN;
891 
892 		s = splsoftnet();
893 		so = (struct socket *)fp->f_data;
894 		state = so->so_state;
895 		prflags = so->so_proto->pr_flags;
896 		splx(s);
897 		FILE_UNUSE(fp, p);
898 		/*
899 		 * We should only let this call succeed once per
900 		 * non-blocking connect; however we don't have
901 		 * a convenient place to keep that state..
902 		 */
903 		if ((state & SS_NBIO) && (state & SS_ISCONNECTED) &&
904 		    (prflags & PR_CONNREQUIRED))
905 			return 0;
906 	}
907 
908 	return (error);
909 }
910 
911 int
912 linux_sys_bind(p, v, retval)
913 	struct proc *p;
914 	void *v;
915 	register_t *retval;
916 {
917 	struct linux_sys_bind_args /* {
918 		syscallarg(int) s;
919 		syscallarg(const struct osockaddr *) name;
920 		syscallarg(int) namelen;
921 	} */ *uap = v;
922 	int		error;
923 	struct sys_bind_args bsa;
924 
925 	SCARG(&bsa, s) = SCARG(uap, s);
926 	if (SCARG(uap, name)) {
927 		struct sockaddr *sa;
928 		caddr_t sg = stackgap_init(p->p_emul);
929 
930 		error = linux_sa_get(&sg, &sa, SCARG(uap, name),
931 		    SCARG(uap, namelen));
932 		if (error)
933 			return (error);
934 
935 		SCARG(&bsa, name) = sa;
936 	} else
937 		SCARG(&bsa, name) = NULL;
938 	SCARG(&bsa, namelen) = SCARG(uap, namelen);
939 
940 	return (sys_bind(p, &bsa, retval));
941 }
942 
943 int
944 linux_sys_getsockname(p, v, retval)
945 	struct proc *p;
946 	void *v;
947 	register_t *retval;
948 {
949 	struct linux_sys_getsockname_args /* {
950 		syscallarg(int) fdes;
951 		syscallarg(caddr_t) asa;
952 		syscallarg(int *) alen;
953 	} */ *uap = v;
954 	int error;
955 
956 	if ((error = sys_getsockname(p, uap, retval)) != 0)
957 		return (error);
958 
959 	if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
960 		return (error);
961 
962 	return (0);
963 }
964 
965 int
966 linux_sys_getpeername(p, v, retval)
967 	struct proc *p;
968 	void *v;
969 	register_t *retval;
970 {
971 	struct sys_getpeername_args /* {
972 		syscallarg(int) fdes;
973 		syscallarg(caddr_t) asa;
974 		syscallarg(int *) alen;
975 	} */ *uap = v;
976 	int error;
977 
978 	if ((error = sys_getpeername(p, uap, retval)) != 0)
979 		return (error);
980 
981 	if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
982 		return (error);
983 
984 	return (0);
985 }
986 
987 /*
988  * Copy the osockaddr structure pointed to by osa to kernel, adjust
989  * family and convert to sockaddr, allocate stackgap and put the
990  * the converted structure there, address on stackgap returned in sap.
991  */
992 static int
993 linux_sa_get(sgp, sap, osa, osalen)
994 	caddr_t *sgp;
995 	struct sockaddr **sap;
996 	const struct osockaddr *osa;
997 	int osalen;
998 {
999 	int error=0, bdom;
1000 	struct sockaddr *sa, *usa;
1001 	struct osockaddr *kosa = (struct osockaddr *) &sa;
1002 
1003 	if (osalen < 0 || osalen > UCHAR_MAX || !osa)
1004 		return (EINVAL);
1005 
1006 	kosa = (struct osockaddr *) malloc(osalen, M_TEMP, M_WAITOK);
1007 
1008 	if ((error = copyin(osa, (caddr_t) kosa, osalen)))
1009 		goto out;
1010 
1011 	bdom = linux_to_bsd_domain(kosa->sa_family);
1012 	if (bdom == -1) {
1013 		error = EINVAL;
1014 		goto out;
1015 	}
1016 
1017 #ifdef INET6
1018 	/*
1019 	 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
1020 	 * which lacks the scope id compared with RFC2553 one. If we detect
1021 	 * the situation, reject the address and write a message to system log.
1022 	 */
1023 	if (bdom == AF_INET6 && osalen < sizeof(struct sockaddr_in6)) {
1024 		struct proc *p = curproc;	/* XXX */
1025 		int uid = p->p_cred && p->p_ucred ?
1026 				p->p_ucred->cr_uid : -1;
1027 
1028 		log(LOG_DEBUG,
1029 		    "pid %d (%s), uid %d: obsolete pre-RFC2553 sockaddr_in6 rejected",
1030 		    p->p_pid, p->p_comm, uid);
1031 		error = EINVAL;
1032 		goto out;
1033 	}
1034 #endif
1035 
1036 	sa = (struct sockaddr *) kosa;
1037 	sa->sa_family = bdom;
1038 	sa->sa_len = osalen;
1039 
1040 	usa = (struct sockaddr *) stackgap_alloc(sgp, osalen);
1041 	if (!usa) {
1042 		error = ENOMEM;
1043 		goto out;
1044 	}
1045 
1046 	if ((error = copyout(sa, usa, osalen)))
1047 		goto out;
1048 
1049 	*sap = usa;
1050 
1051     out:
1052 	free(kosa, M_TEMP);
1053 	return (error);
1054 }
1055 
1056 static int
1057 linux_sa_put(osa)
1058 	struct osockaddr *osa;
1059 {
1060 	struct sockaddr sa;
1061 	struct osockaddr *kosa;
1062 	int error, bdom, len;
1063 
1064 	/*
1065 	 * Only read/write the sockaddr family and length part, the rest is
1066 	 * not changed.
1067 	 */
1068 	len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
1069 
1070 	error = copyin((caddr_t) osa, (caddr_t) &sa, len);
1071 	if (error)
1072 		return (error);
1073 
1074 	bdom = bsd_to_linux_domain(sa.sa_family);
1075 	if (bdom == -1)
1076 		return (EINVAL);
1077 
1078 	/* Note: we convert from sockaddr to osockaddr here, too */
1079 	kosa = (struct osockaddr *) &sa;
1080 	kosa->sa_family = bdom;
1081 	error = copyout(kosa, osa, len);
1082 	if (error)
1083 		return (error);
1084 
1085 	return (0);
1086 }
1087 
1088 int
1089 linux_sys_recv(p, v, retval)
1090 	struct proc *p;
1091 	void *v;
1092 	register_t *retval;
1093 {
1094 	struct linux_sys_recv_args /* {
1095 		syscallarg(int) s;
1096 		syscallarg(void *) buf;
1097 		syscallarg(int) len;
1098 		syscallarg(int) flags;
1099 	} */ *uap = v;
1100 	struct sys_recvfrom_args bra;
1101 
1102 
1103 	SCARG(&bra, s) = SCARG(uap, s);
1104 	SCARG(&bra, buf) = SCARG(uap, buf);
1105 	SCARG(&bra, len) = (size_t) SCARG(uap, len);
1106 	SCARG(&bra, flags) = SCARG(uap, flags);
1107 	SCARG(&bra, from) = NULL;
1108 	SCARG(&bra, fromlenaddr) = NULL;
1109 
1110 	return (sys_recvfrom(p, &bra, retval));
1111 }
1112 
1113 int
1114 linux_sys_send(p, v, retval)
1115 	struct proc *p;
1116 	void *v;
1117 	register_t *retval;
1118 {
1119 	struct linux_sys_send_args /* {
1120 		syscallarg(int) s;
1121 		syscallarg(caddr_t) buf;
1122 		syscallarg(int) len;
1123 		syscallarg(int) flags;
1124 	} */ *uap = v;
1125 	struct sys_sendto_args bsa;
1126 
1127 	SCARG(&bsa, s)		= SCARG(uap, s);
1128 	SCARG(&bsa, buf)	= SCARG(uap, buf);
1129 	SCARG(&bsa, len)	= SCARG(uap, len);
1130 	SCARG(&bsa, flags)	= SCARG(uap, flags);
1131 	SCARG(&bsa, to)		= NULL;
1132 	SCARG(&bsa, tolen)	= 0;
1133 
1134 	return (sys_sendto(p, &bsa, retval));
1135 }
1136 
1137 int
1138 linux_sys_accept(p, v, retval)
1139 	struct proc *p;
1140 	void *v;
1141 	register_t *retval;
1142 {
1143 	struct linux_sys_accept_args /* {
1144 		syscallarg(int) s;
1145 		syscallarg(struct osockaddr *) name;
1146 		syscallarg(int *) anamelen;
1147 	} */ *uap = v;
1148 	int error;
1149 	struct sys_accept_args baa;
1150 
1151 	SCARG(&baa, s)		= SCARG(uap, s);
1152 	SCARG(&baa, name)	= (struct sockaddr *) SCARG(uap, name);
1153 	SCARG(&baa, anamelen)	= (unsigned int *) SCARG(uap, anamelen);
1154 
1155 	if ((error = sys_accept(p, &baa, retval)))
1156 		return (error);
1157 
1158 	if (SCARG(uap, name) && (error = linux_sa_put(SCARG(uap, name))))
1159 		return (error);
1160 
1161 	return (0);
1162 }
1163