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