parent
c82e679e68
commit
9084eed1a8
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux32_socket.c,v 1.7 2008/06/24 09:00:04 njoly Exp $ */
|
||||
/* $NetBSD: linux32_socket.c,v 1.8 2008/06/27 12:38:25 njoly Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.7 2008/06/24 09:00:04 njoly Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.8 2008/06/27 12:38:25 njoly Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -53,6 +53,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.7 2008/06/24 09:00:04 njoly Exp
|
|||
#include <machine/types.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
@ -64,6 +66,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.7 2008/06/24 09:00:04 njoly Exp
|
|||
#include <compat/netbsd32/netbsd32_ioctl.h>
|
||||
#include <compat/netbsd32/netbsd32_conv.h>
|
||||
#include <compat/netbsd32/netbsd32_syscallargs.h>
|
||||
|
||||
#include <compat/sys/socket.h>
|
||||
#include <compat/sys/sockio.h>
|
||||
|
||||
#include <compat/linux/common/linux_types.h>
|
||||
|
@ -81,9 +85,12 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.7 2008/06/24 09:00:04 njoly Exp
|
|||
#include <compat/linux32/common/linux32_machdep.h>
|
||||
#include <compat/linux32/common/linux32_sysctl.h>
|
||||
#include <compat/linux32/common/linux32_socketcall.h>
|
||||
#include <compat/linux32/common/linux32_sockio.h>
|
||||
#include <compat/linux32/common/linux32_ioctl.h>
|
||||
#include <compat/linux32/linux32_syscallargs.h>
|
||||
|
||||
int linux32_getifhwaddr(struct lwp *, register_t *, u_int, void *);
|
||||
|
||||
int
|
||||
linux32_sys_socketpair(struct lwp *l, const struct linux32_sys_socketpair_args *uap, register_t *retval)
|
||||
{
|
||||
|
@ -376,6 +383,123 @@ linux32_sys_recv(struct lwp *l, const struct linux32_sys_recv_args *uap, registe
|
|||
return sys_recvfrom(l, &ua, retval);
|
||||
}
|
||||
|
||||
int
|
||||
linux32_getifhwaddr(struct lwp *l, register_t *retval, u_int fd,
|
||||
void *data)
|
||||
{
|
||||
struct linux32_ifreq lreq;
|
||||
file_t *fp;
|
||||
struct ifaddr *ifa;
|
||||
struct ifnet *ifp;
|
||||
struct sockaddr_dl *sadl;
|
||||
int error, found;
|
||||
int index, ifnum;
|
||||
|
||||
/*
|
||||
* We can't emulate this ioctl by calling sys_ioctl() to run
|
||||
* SIOCGIFCONF, because the user buffer is not of the right
|
||||
* type to take those results. We can't use kernel buffers to
|
||||
* receive the results, as the implementation of sys_ioctl()
|
||||
* and ifconf() [which implements SIOCGIFCONF] use
|
||||
* copyin()/copyout() which will fail on kernel addresses.
|
||||
*
|
||||
* So, we must duplicate code from sys_ioctl() and ifconf(). Ugh.
|
||||
*/
|
||||
|
||||
if ((fp = fd_getfile(fd)) == NULL)
|
||||
return (EBADF);
|
||||
|
||||
KERNEL_LOCK(1, NULL);
|
||||
|
||||
if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
|
||||
error = EBADF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = copyin(data, &lreq, sizeof(lreq));
|
||||
if (error)
|
||||
goto out;
|
||||
lreq.ifr_name[LINUX32_IFNAMSIZ-1] = '\0'; /* just in case */
|
||||
|
||||
/*
|
||||
* Try real interface name first, then fake "ethX"
|
||||
*/
|
||||
found = 0;
|
||||
IFNET_FOREACH(ifp) {
|
||||
if (found)
|
||||
break;
|
||||
if (strcmp(lreq.ifr_name, ifp->if_xname))
|
||||
/* not this interface */
|
||||
continue;
|
||||
found=1;
|
||||
if (IFADDR_EMPTY(ifp)) {
|
||||
error = ENODEV;
|
||||
goto out;
|
||||
}
|
||||
IFADDR_FOREACH(ifa, ifp) {
|
||||
sadl = satosdl(ifa->ifa_addr);
|
||||
/* only return ethernet addresses */
|
||||
/* XXX what about FDDI, etc. ? */
|
||||
if (sadl->sdl_family != AF_LINK ||
|
||||
sadl->sdl_type != IFT_ETHER)
|
||||
continue;
|
||||
memcpy(&lreq.ifr_hwaddr.sa_data, CLLADDR(sadl),
|
||||
MIN(sadl->sdl_alen,
|
||||
sizeof(lreq.ifr_hwaddr.sa_data)));
|
||||
lreq.ifr_hwaddr.sa_family =
|
||||
sadl->sdl_family;
|
||||
error = copyout(&lreq, data, sizeof(lreq));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(lreq.ifr_name, "eth", 3) == 0) {
|
||||
for (ifnum = 0, index = 3;
|
||||
lreq.ifr_name[index] != '\0' && index < LINUX32_IFNAMSIZ;
|
||||
index++) {
|
||||
ifnum *= 10;
|
||||
ifnum += lreq.ifr_name[index] - '0';
|
||||
}
|
||||
|
||||
error = EINVAL; /* in case we don't find one */
|
||||
found = 0;
|
||||
IFNET_FOREACH(ifp) {
|
||||
if (found)
|
||||
break;
|
||||
memcpy(lreq.ifr_name, ifp->if_xname,
|
||||
MIN(LINUX32_IFNAMSIZ, IFNAMSIZ));
|
||||
IFADDR_FOREACH(ifa, ifp) {
|
||||
sadl = satosdl(ifa->ifa_addr);
|
||||
/* only return ethernet addresses */
|
||||
/* XXX what about FDDI, etc. ? */
|
||||
if (sadl->sdl_family != AF_LINK ||
|
||||
sadl->sdl_type != IFT_ETHER)
|
||||
continue;
|
||||
if (ifnum--)
|
||||
/* not the reqested iface */
|
||||
continue;
|
||||
memcpy(&lreq.ifr_hwaddr.sa_data,
|
||||
CLLADDR(sadl),
|
||||
MIN(sadl->sdl_alen,
|
||||
sizeof(lreq.ifr_hwaddr.sa_data)));
|
||||
lreq.ifr_hwaddr.sa_family =
|
||||
sadl->sdl_family;
|
||||
error = copyout(&lreq, data, sizeof(lreq));
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* unknown interface, not even an "eth*" name */
|
||||
error = ENODEV;
|
||||
}
|
||||
|
||||
out:
|
||||
KERNEL_UNLOCK_ONE(NULL);
|
||||
fd_putfile(fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
linux32_ioctl_socket(struct lwp *l, const struct linux32_sys_ioctl_args *uap, register_t *retval)
|
||||
{
|
||||
|
@ -455,13 +579,11 @@ linux32_ioctl_socket(struct lwp *l, const struct linux32_sys_ioctl_args *uap, re
|
|||
case LINUX_SIOCDELMULTI:
|
||||
SCARG(&ia, com) = OSIOCDELMULTI;
|
||||
break;
|
||||
#ifdef notyet
|
||||
case LINUX_SIOCGIFHWADDR:
|
||||
error = linux_getifhwaddr(l, retval, SCARG(uap, fd),
|
||||
SCARG(uap, data));
|
||||
error = linux32_getifhwaddr(l, retval, SCARG(uap, fd),
|
||||
SCARG_P32(uap, data));
|
||||
dosys = 0;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error = EINVAL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* $NetBSD: linux32_sockio.h,v 1.1 2008/06/27 12:38:25 njoly Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicolas Joly
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX32_SOCKIO_H
|
||||
#define _LINUX32_SOCKIO_H
|
||||
|
||||
#define LINUX32_IFNAMSIZ 16
|
||||
|
||||
struct linux32_ifmap {
|
||||
netbsd32_u_long mem_start;
|
||||
netbsd32_u_long mem_end;
|
||||
unsigned short base_addr;
|
||||
unsigned char irq;
|
||||
unsigned char dma;
|
||||
unsigned char port;
|
||||
};
|
||||
|
||||
struct linux32_ifreq {
|
||||
union {
|
||||
char ifrn_name[LINUX32_IFNAMSIZ];
|
||||
} ifr_ifrn;
|
||||
union {
|
||||
struct osockaddr ifru_hwaddr;
|
||||
struct linux32_ifmap ifru_map;
|
||||
} ifr_ifru;
|
||||
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
|
||||
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
|
||||
#define ifr_map ifr_ifru.ifru_map /* device map */
|
||||
};
|
||||
|
||||
#endif /* !_LINUX32_SOCKIO_H */
|
Loading…
Reference in New Issue