MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_gethwaddr.c
1 /* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /* get hardware address for an interface */
17 /* if there are many available, any non-zero one can be used */
18 
19 #include "mysys_priv.h"
20 #include <m_string.h>
21 
22 #ifndef MAIN
23 
24 #ifdef __FreeBSD__
25 
26 #include <net/ethernet.h>
27 #include <sys/sysctl.h>
28 #include <net/route.h>
29 #include <net/if.h>
30 #include <net/if_dl.h>
31 
32 my_bool my_gethwaddr(uchar *to)
33 {
34  size_t len;
35  char *buf, *next, *end;
36  struct if_msghdr *ifm;
37  struct sockaddr_dl *sdl;
38  int res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0};
39  char zero_array[ETHER_ADDR_LEN] = {0};
40 
41  if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
42  goto err;
43  if (!(buf = alloca(len)))
44  goto err;
45  if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
46  goto err;
47 
48  end = buf + len;
49 
50  for (next = buf ; res && next < end ; next += ifm->ifm_msglen)
51  {
52  ifm = (struct if_msghdr *)next;
53  if (ifm->ifm_type == RTM_IFINFO)
54  {
55  sdl= (struct sockaddr_dl *)(ifm + 1);
56  memcpy(to, LLADDR(sdl), ETHER_ADDR_LEN);
57  res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1;
58  }
59  }
60 
61 err:
62  return res;
63 }
64 
65 #elif __linux__
66 
67 #include <net/if.h>
68 #include <sys/ioctl.h>
69 #include <net/ethernet.h>
70 
71 my_bool my_gethwaddr(uchar *to)
72 {
73  int fd, res= 1;
74  struct ifreq ifr;
75  char zero_array[ETHER_ADDR_LEN] = {0};
76 
77  fd = socket(AF_INET, SOCK_DGRAM, 0);
78  if (fd < 0)
79  goto err;
80 
81  memset(&ifr, 0, sizeof(ifr));
82  strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
83 
84  do
85  {
86  if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0)
87  {
88  memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
89  res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1;
90  }
91  } while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6');
92 
93  close(fd);
94 err:
95  return res;
96 }
97 
98 #elif defined(__WIN__)
99 
100 /*
101  Workaround for BUG#32082 (Definition of VOID in my_global.h conflicts with
102  windows headers)
103 */
104 #ifdef VOID
105 #undef VOID
106 #define VOID void
107 #endif
108 
109 #include <iphlpapi.h>
110 
111 /*
112  The following typedef is for dynamically loading iphlpapi.dll /
113  GetAdaptersAddresses. Dynamic loading is used because
114  GetAdaptersAddresses is not available on Windows 2000 which MySQL
115  still supports. Static linking would cause an unresolved export.
116 */
117 typedef DWORD (WINAPI *pfnGetAdaptersAddresses)(IN ULONG Family,
118  IN DWORD Flags,IN PVOID Reserved,
119  OUT PIP_ADAPTER_ADDRESSES pAdapterAddresses,
120  IN OUT PULONG pOutBufLen);
121 
122 /*
123  my_gethwaddr - Windows version
124 
125  @brief Retrieve MAC address from network hardware
126 
127  @param[out] to MAC address exactly six bytes
128 
129  @return Operation status
130  @retval 0 OK
131  @retval <>0 FAILED
132 */
133 my_bool my_gethwaddr(uchar *to)
134 {
135  PIP_ADAPTER_ADDRESSES pAdapterAddresses;
136  PIP_ADAPTER_ADDRESSES pCurrAddresses;
137  IP_ADAPTER_ADDRESSES adapterAddresses;
138  ULONG address_len;
139  my_bool return_val= 1;
140  static pfnGetAdaptersAddresses fnGetAdaptersAddresses=
141  (pfnGetAdaptersAddresses)-1;
142 
143  if(fnGetAdaptersAddresses == (pfnGetAdaptersAddresses)-1)
144  {
145  /* Get the function from the DLL */
146  fnGetAdaptersAddresses= (pfnGetAdaptersAddresses)
147  GetProcAddress(LoadLibrary("iphlpapi.dll"),
148  "GetAdaptersAddresses");
149  }
150  if (!fnGetAdaptersAddresses)
151  return 1; /* failed to get function */
152  address_len= sizeof (IP_ADAPTER_ADDRESSES);
153 
154  /* Get the required size for the address data. */
155  if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, &adapterAddresses, &address_len)
156  == ERROR_BUFFER_OVERFLOW)
157  {
158  pAdapterAddresses= my_malloc(address_len, 0);
159  if (!pAdapterAddresses)
160  return 1; /* error, alloc failed */
161  }
162  else
163  pAdapterAddresses= &adapterAddresses; /* one is enough don't alloc */
164 
165  /* Get the hardware info. */
166  if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &address_len)
167  == NO_ERROR)
168  {
169  pCurrAddresses= pAdapterAddresses;
170 
171  while (pCurrAddresses)
172  {
173  /* Look for ethernet cards. */
174  if (pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD)
175  {
176  /* check for a good address */
177  if (pCurrAddresses->PhysicalAddressLength < 6)
178  continue; /* bad address */
179 
180  /* save 6 bytes of the address in the 'to' parameter */
181  memcpy(to, pCurrAddresses->PhysicalAddress, 6);
182 
183  /* Network card found, we're done. */
184  return_val= 0;
185  break;
186  }
187  pCurrAddresses= pCurrAddresses->Next;
188  }
189  }
190 
191  /* Clean up memory allocation. */
192  if (pAdapterAddresses != &adapterAddresses)
193  my_free(pAdapterAddresses);
194 
195  return return_val;
196 }
197 
198 #else /* __FreeBSD__ || __linux__ || __WIN__ */
199 /* just fail */
200 my_bool my_gethwaddr(uchar *to __attribute__((unused)))
201 {
202  return 1;
203 }
204 #endif
205 
206 #else /* MAIN */
207 int main(int argc __attribute__((unused)),char **argv)
208 {
209  uchar mac[6];
210  uint i;
211  MY_INIT(argv[0]);
212  if (my_gethwaddr(mac))
213  {
214  printf("my_gethwaddr failed with errno %d\n", errno);
215  exit(1);
216  }
217  for (i=0; i < sizeof(mac); i++)
218  {
219  if (i) printf(":");
220  printf("%02x", mac[i]);
221  }
222  printf("\n");
223  return 0;
224 }
225 #endif
226