Commit b3e0991b authored by Sergei Golubchik's avatar Sergei Golubchik

my_gethwaddr() on Solaris and Windows

parent c7b7c5d6
......@@ -864,7 +864,7 @@ AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h fpu_control.h \
ieeefp.h limits.h memory.h pwd.h select.h fnmatch.h \
stdlib.h stddef.h sys/stat.h \
stdlib.h stddef.h sys/stat.h sys/sockio.h \
strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \
sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \
......
......@@ -48,6 +48,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_
IF(NOT SOURCE_SUBLIBS)
ADD_LIBRARY(mysys ${MYSYS_SOURCES})
TARGET_LINK_LIBRARIES(mysys IPHLPAPI)
INSTALL(TARGETS mysys DESTINATION lib/opt COMPONENT runtime) # TODO: Component?
ENDIF(NOT SOURCE_SUBLIBS)
......@@ -16,11 +16,22 @@
/* get hardware address for an interface */
/* if there are many available, any non-zero one can be used */
#define DONT_DEFINE_VOID /* windows includes break if we do */
#include "mysys_priv.h"
#include <m_string.h>
#ifndef MAIN
static my_bool memcpy_and_test(uchar *to, uchar *from, uint len)
{
uint i, res= 1;
for (i= 0; i < len; i++)
if ((*to++= *from++))
res= 0;
return res;
}
#ifdef __FreeBSD__
#include <net/ethernet.h>
......@@ -32,11 +43,10 @@
my_bool my_gethwaddr(uchar *to)
{
size_t len;
char *buf, *next, *end;
uchar *buf, *next, *end, *addr;
struct if_msghdr *ifm;
struct sockaddr_dl *sdl;
int res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0};
char zero_array[ETHER_ADDR_LEN] = {0};
int res= 1, mib[6]= {CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0};
if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
goto err;
......@@ -52,9 +62,9 @@ my_bool my_gethwaddr(uchar *to)
ifm = (struct if_msghdr *)next;
if (ifm->ifm_type == RTM_IFINFO)
{
sdl= (struct sockaddr_dl *)(ifm + 1);
memcpy(to, LLADDR(sdl), ETHER_ADDR_LEN);
res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1;
sdl = (struct sockaddr_dl *)(ifm + 1);
addr= LLADDR(sdl);
res= memcpy_and_test(to, addr, ETHER_ADDR_LEN);
}
}
......@@ -62,40 +72,94 @@ my_bool my_gethwaddr(uchar *to)
return res;
}
#elif __linux__
#elif defined(__linux__) || defined(__sun__)
#include <net/if.h>
#include <sys/ioctl.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#define ETHER_ADDR_LEN 6
my_bool my_gethwaddr(uchar *to)
{
int fd, res= 1;
struct ifreq ifr;
char zero_array[ETHER_ADDR_LEN] = {0};
struct ifreq ifr[32];
struct ifconf ifc;
ifc.ifc_req= ifr;
ifc.ifc_len= sizeof(ifr);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
goto err;
bzero(&ifr, sizeof(ifr));
strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
do
if (ioctl(fd, SIOCGIFCONF, (char*)&ifc) >= 0)
{
if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0)
uint i;
for (i= 0; res && i < ifc.ifc_len / sizeof(ifr[0]); i++)
{
memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1;
#ifdef SIOCGIFHWADDR
if (ioctl(fd, SIOCGIFHWADDR, &ifr[i]) >= 0)
res= memcpy_and_test(to, (uchar *)&ifr[i].ifr_hwaddr.sa_data,
ETHER_ADDR_LEN);
#else
/*
A bug in OpenSolaris prevents non-root from getting a mac address:
http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=4720634
Thus, we'll use an alternative method and extract the address from the
arp table.
*/
struct arpreq arpr;
arpr.arp_pa= ifr[i].ifr_addr;
if (ioctl(fd, SIOCGARP, (char*)&arpr) >= 0)
res= memcpy_and_test(to, (uchar *)&arpr.arp_ha.sa_data,
ETHER_ADDR_LEN);
#endif
}
} while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6');
}
close(fd);
err:
return res;
}
#else /* FreeBSD elif linux */
#elif defined(_WIN32)
#include <winsock2.h>
#include <iphlpapi.h>
#define ETHER_ADDR_LEN 6
my_bool my_gethwaddr(uchar *to)
{
my_bool res= 1;
IP_ADAPTER_INFO *info= NULL;
ULONG info_len= 0;
if (GetAdaptersInfo(info, &info_len) != ERROR_BUFFER_OVERFLOW)
goto err;
info= alloca(info_len);
if (GetAdaptersInfo(info, &info_len) != NO_ERROR)
goto err;
while (info && res)
{
if (info->Type == MIB_IF_TYPE_ETHERNET &&
info->AddressLength == ETHER_ADDR_LEN)
res= memcpy_and_test(to, info->Address, ETHER_ADDR_LEN);
}
err:
return res;
}
#else /* neither FreeBSD nor linux not Windows */
/* just fail */
my_bool my_gethwaddr(uchar *to __attribute__((unused)))
{
......@@ -114,7 +178,7 @@ int main(int argc __attribute__((unused)),char **argv)
printf("my_gethwaddr failed with errno %d\n", errno);
exit(1);
}
for (i=0; i < sizeof(mac); i++)
for (i= 0; i < sizeof(mac); i++)
{
if (i) printf(":");
printf("%02x", mac[i]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment