1/*
2 Copyright (c) 2004, 2010, Oracle and/or its affiliates
3 Copyright (c) 2011, Monty Program Ab
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
17
18/* get hardware address for an interface */
19/* if there are many available, any non-zero one can be used */
20
21#include "mysys_priv.h"
22#include <m_string.h>
23
24#ifndef MAIN
25
26static my_bool memcpy_and_test(uchar *to, uchar *from, uint len)
27{
28 uint i, res= 1;
29
30 for (i= 0; i < len; i++)
31 if ((*to++= *from++))
32 res= 0;
33 return res;
34}
35
36#if defined(__APPLE__) || defined(__FreeBSD__)
37#include <net/ethernet.h>
38#include <sys/sysctl.h>
39#include <net/route.h>
40#include <net/if.h>
41#include <net/if_dl.h>
42
43my_bool my_gethwaddr(uchar *to)
44{
45 size_t len;
46 uchar *buf, *next, *end, *addr;
47 struct if_msghdr *ifm;
48 struct sockaddr_dl *sdl;
49 int res= 1, mib[6]= {CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0};
50
51 if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
52 goto err;
53 if (!(buf = alloca(len)))
54 goto err;
55 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
56 goto err;
57
58 end = buf + len;
59
60 for (next = buf ; res && next < end ; next += ifm->ifm_msglen)
61 {
62 ifm = (struct if_msghdr *)next;
63 if (ifm->ifm_type == RTM_IFINFO)
64 {
65 sdl = (struct sockaddr_dl *)(ifm + 1);
66 addr= (uchar *)LLADDR(sdl);
67 res= memcpy_and_test(to, addr, ETHER_ADDR_LEN);
68 }
69 }
70
71err:
72 return res;
73}
74
75#elif defined(__linux__) || defined(__sun)
76#include <net/if.h>
77#include <sys/ioctl.h>
78#include <net/if_arp.h>
79#ifdef HAVE_SYS_SOCKIO_H
80#include <sys/sockio.h>
81#endif
82
83#define ETHER_ADDR_LEN 6
84
85my_bool my_gethwaddr(uchar *to)
86{
87 int fd, res= 1;
88 struct ifreq ifr[32];
89 struct ifconf ifc;
90 DBUG_ENTER("my_gethwaddr");
91
92 ifc.ifc_req= ifr;
93 ifc.ifc_len= sizeof(ifr);
94
95 fd = socket(AF_INET, SOCK_DGRAM, 0);
96 if (fd < 0)
97 {
98 DBUG_PRINT("error", ("socket() call failed with %d", errno));
99 goto err;
100 }
101
102 if (ioctl(fd, SIOCGIFCONF, (char*)&ifc) >= 0)
103 {
104 uint i;
105 for (i= 0; res && i < ifc.ifc_len / sizeof(ifr[0]); i++)
106 {
107#ifdef __linux__
108 if (ioctl(fd, SIOCGIFHWADDR, &ifr[i]) >= 0)
109 res= memcpy_and_test(to, (uchar *)&ifr[i].ifr_hwaddr.sa_data,
110 ETHER_ADDR_LEN);
111#else
112 /*
113 A bug in OpenSolaris used to prevent non-root from getting a mac
114 address: {no url. Oracle killed the old OpenSolaris bug database}
115
116 Thus, we'll use an alternative method and extract the address from the
117 arp table.
118 */
119 struct arpreq arpr;
120 arpr.arp_pa= ifr[i].ifr_addr;
121
122 if (ioctl(fd, SIOCGARP, (char*)&arpr) >= 0)
123 res= memcpy_and_test(to, (uchar *)&arpr.arp_ha.sa_data,
124 ETHER_ADDR_LEN);
125#endif
126 }
127 }
128
129 close(fd);
130err:
131 DBUG_RETURN(res);
132}
133
134#elif defined(_WIN32)
135#include <winsock2.h>
136#include <iphlpapi.h>
137#pragma comment(lib, "iphlpapi.lib")
138
139#define ETHER_ADDR_LEN 6
140
141my_bool my_gethwaddr(uchar *to)
142{
143 my_bool res= 1;
144
145 IP_ADAPTER_INFO *info= NULL;
146 ULONG info_len= 0;
147
148 if (GetAdaptersInfo(info, &info_len) != ERROR_BUFFER_OVERFLOW)
149 goto err;
150
151 info= (IP_ADAPTER_INFO *)alloca(info_len);
152
153 if (GetAdaptersInfo(info, &info_len) != NO_ERROR)
154 goto err;
155
156 while (info && res)
157 {
158 if (info->Type == MIB_IF_TYPE_ETHERNET &&
159 info->AddressLength == ETHER_ADDR_LEN)
160 {
161 res= memcpy_and_test(to, info->Address, ETHER_ADDR_LEN);
162 }
163 info = info->Next;
164 }
165
166err:
167 return res;
168}
169
170#else /* unsupported system */
171/* just fail */
172my_bool my_gethwaddr(uchar *to __attribute__((unused)))
173{
174 return 1;
175}
176#endif
177
178#else /* MAIN */
179int main(int argc __attribute__((unused)),char **argv)
180{
181 uchar mac[6];
182 uint i;
183 MY_INIT(argv[0]);
184 if (my_gethwaddr(mac))
185 {
186 printf("my_gethwaddr failed with errno %d\n", errno);
187 exit(1);
188 }
189 for (i= 0; i < sizeof(mac); i++)
190 {
191 if (i) printf(":");
192 printf("%02x", mac[i]);
193 }
194 printf("\n");
195 return 0;
196}
197#endif
198
199