1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
--- src/netinfo.c 2014-01-01 19:10:25.000000000 +0200
+++ src/netinfo.c 2014-10-22 05:49:50.129320393 +0300
@@ -23,14 +23,31 @@
* USA
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/socket.h>
#include <sys/ioctl.h>
-#include <linux/ethtool.h>
-#include <linux/sockios.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <net/ethernet.h>
+
+#if defined(HAVE_IF_PACKET)
+# include <linux/if_packet.h>
+#elif defined(HAVE_IF_DL)
+# include <net/if_dl.h>
+#endif
+
+#if defined(HAVE_ETHTOOL)
+# include <linux/ethtool.h>
+# include <linux/sockios.h>
+#endif
#include "netinfo.h"
@@ -49,7 +66,7 @@
strncpy (new->dev.ifr_name, device, sizeof(new->dev.ifr_name));
new->dev.ifr_name[sizeof(new->dev.ifr_name)-1] = '\0';
- if (ioctl(new->sock, SIOCGIFHWADDR, &new->dev) < 0) {
+ if (if_nametoindex(device) == 0) {
perror ("[ERROR] Set device name");
free(new);
return NULL;
@@ -66,29 +83,55 @@
free(net);
}
-
mac_t *
mc_net_info_get_mac (const net_info_t *net)
{
- int i;
- mac_t *new = (mac_t *) malloc (sizeof(mac_t));
+ int i;
+ mac_t *mac = (mac_t *) malloc (sizeof(mac_t));
+ u_char *lladr;
- for (i=0; i<6; i++) {
- new->byte[i] = net->dev.ifr_hwaddr.sa_data[i] & 0xFF;
- }
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_ll *sdl;
- return new;
-}
+ if (getifaddrs(&ifap) == 0) {
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+
+ sdl = (struct sockaddr_ll *) ifa->ifa_addr;
+
+ if (strcmp(ifa->ifa_name, net->dev.ifr_name) != 0)
+ continue;
+ if (!sdl && sdl->sll_family != AF_PACKET)
+ continue;
+
+ lladr = (u_char *) LLADDR(sdl);
+ for (i=0; i<6; i++)
+ mac->byte[i] = lladr[i] & 0xFF;
+ break;
+ }
+ freeifaddrs(ifap);
+ } else
+ perror("getifaddrs");
+
+ return mac;
+}
int
mc_net_info_set_mac (net_info_t *net, const mac_t *mac)
{
int i;
+#if defined(HAVE_ETHTOOL)
+ if (ioctl(net->sock, SIOCGIFHWADDR, &net->dev) < 0) {
+ perror ("[ERROR] Set ifreq structure");
+ return -1;
+ }
+#elif defined(HAVE_SOCKADDR_SA_LEN)
+ net->dev.ifr_addr.sa_family = AF_PACKET;
+ net->dev.ifr_addr.sa_len = ETHER_ADDR_LEN;
+#endif
- for (i=0; i<6; i++) {
+ for (i=0; i<6; i++)
net->dev.ifr_hwaddr.sa_data[i] = mac->byte[i];
- }
if (ioctl(net->sock, SIOCSIFHWADDR, &net->dev) < 0) {
perror ("[ERROR] Could not change MAC: interface up or insufficient permissions");
@@ -98,6 +141,7 @@
return 0;
}
+#if defined(HAVE_ETHTOOL)
mac_t *
mc_net_info_get_permanent_mac (const net_info_t *net)
{
@@ -126,3 +170,4 @@
free(epa);
return newmac;
}
+#endif
|