summaryrefslogtreecommitdiff
path: root/mysys/my_gethwaddr.c
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2011-11-22 18:04:38 +0100
committerSergei Golubchik <sergii@pisem.net>2011-11-22 18:04:38 +0100
commitd2755a2c9c109ddb4e2e0c9feda89431a6c4fd50 (patch)
treec6e4678908c750d7f558e98cedc349aa1d350892 /mysys/my_gethwaddr.c
parentaf32b02c06f32a89dc9f52e556bc5dd3bf49c19e (diff)
parent42221abaed700f6dc5d280b462755851780e8487 (diff)
downloadmariadb-git-d2755a2c9c109ddb4e2e0c9feda89431a6c4fd50.tar.gz
5.3->5.5 merge
Diffstat (limited to 'mysys/my_gethwaddr.c')
-rw-r--r--mysys/my_gethwaddr.c182
1 files changed, 74 insertions, 108 deletions
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
index 54823a7c5ca..4360daca6f8 100644
--- a/mysys/my_gethwaddr.c
+++ b/mysys/my_gethwaddr.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2004, 2010, Oracle and/or its affiliates.
+ Copyright (c) 2011, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,8 +22,17 @@
#ifndef MAIN
-#ifdef __FreeBSD__
+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;
+}
+#if defined(__APPLE__) || defined(__FreeBSD__)
#include <net/ethernet.h>
#include <sys/sysctl.h>
#include <net/route.h>
@@ -32,11 +42,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 +61,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= (uchar *)LLADDR(sdl);
+ res= memcpy_and_test(to, addr, ETHER_ADDR_LEN);
}
}
@@ -62,140 +71,97 @@ err:
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;
}
-#elif defined(__WIN__)
-
-/*
- Workaround for BUG#32082 (Definition of VOID in my_global.h conflicts with
- windows headers)
-*/
-#ifdef VOID
-#undef VOID
-#define VOID void
-#endif
-
+#elif defined(_WIN32)
+#include <winsock2.h>
#include <iphlpapi.h>
-/*
- The following typedef is for dynamically loading iphlpapi.dll /
- GetAdaptersAddresses. Dynamic loading is used because
- GetAdaptersAddresses is not available on Windows 2000 which MySQL
- still supports. Static linking would cause an unresolved export.
-*/
-typedef DWORD (WINAPI *pfnGetAdaptersAddresses)(IN ULONG Family,
- IN DWORD Flags,IN PVOID Reserved,
- OUT PIP_ADAPTER_ADDRESSES pAdapterAddresses,
- IN OUT PULONG pOutBufLen);
+#define ETHER_ADDR_LEN 6
-/*
- my_gethwaddr - Windows version
+my_bool my_gethwaddr(uchar *to)
+{
+ my_bool res= 1;
- @brief Retrieve MAC address from network hardware
+ IP_ADAPTER_INFO *info= NULL;
+ ULONG info_len= 0;
- @param[out] to MAC address exactly six bytes
+ if (GetAdaptersInfo(info, &info_len) != ERROR_BUFFER_OVERFLOW)
+ goto err;
- @return Operation status
- @retval 0 OK
- @retval <>0 FAILED
-*/
-my_bool my_gethwaddr(uchar *to)
-{
- PIP_ADAPTER_ADDRESSES pAdapterAddresses;
- PIP_ADAPTER_ADDRESSES pCurrAddresses;
- IP_ADAPTER_ADDRESSES adapterAddresses;
- ULONG address_len;
- my_bool return_val= 1;
- static pfnGetAdaptersAddresses fnGetAdaptersAddresses=
- (pfnGetAdaptersAddresses)-1;
-
- if(fnGetAdaptersAddresses == (pfnGetAdaptersAddresses)-1)
- {
- /* Get the function from the DLL */
- fnGetAdaptersAddresses= (pfnGetAdaptersAddresses)
- GetProcAddress(LoadLibrary("iphlpapi.dll"),
- "GetAdaptersAddresses");
- }
- if (!fnGetAdaptersAddresses)
- return 1; /* failed to get function */
- address_len= sizeof (IP_ADAPTER_ADDRESSES);
+ info= alloca(info_len);
- /* Get the required size for the address data. */
- if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, &adapterAddresses, &address_len)
- == ERROR_BUFFER_OVERFLOW)
- {
- pAdapterAddresses= my_malloc(address_len, 0);
- if (!pAdapterAddresses)
- return 1; /* error, alloc failed */
- }
- else
- pAdapterAddresses= &adapterAddresses; /* one is enough don't alloc */
+ if (GetAdaptersInfo(info, &info_len) != NO_ERROR)
+ goto err;
- /* Get the hardware info. */
- if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &address_len)
- == NO_ERROR)
+ while (info && res)
{
- pCurrAddresses= pAdapterAddresses;
-
- while (pCurrAddresses)
+ if (info->Type == MIB_IF_TYPE_ETHERNET &&
+ info->AddressLength == ETHER_ADDR_LEN)
{
- /* Look for ethernet cards. */
- if (pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD)
- {
- /* check for a good address */
- if (pCurrAddresses->PhysicalAddressLength < 6)
- continue; /* bad address */
-
- /* save 6 bytes of the address in the 'to' parameter */
- memcpy(to, pCurrAddresses->PhysicalAddress, 6);
-
- /* Network card found, we're done. */
- return_val= 0;
- break;
- }
- pCurrAddresses= pCurrAddresses->Next;
+ res= memcpy_and_test(to, info->Address, ETHER_ADDR_LEN);
}
+ info = info->Next;
}
- /* Clean up memory allocation. */
- if (pAdapterAddresses != &adapterAddresses)
- my_free(pAdapterAddresses);
-
- return return_val;
+err:
+ return res;
}
-#else /* __FreeBSD__ || __linux__ || __WIN__ */
+#else /* unsupported system */
/* just fail */
my_bool my_gethwaddr(uchar *to __attribute__((unused)))
{
@@ -214,7 +180,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]);