-
Notifications
You must be signed in to change notification settings - Fork 0
/
get_hw_addrs.c
117 lines (105 loc) · 3.76 KB
/
get_hw_addrs.c
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
#include "get_hw_addrs.h"
struct hwa_info *get_hw_addrs(void) {
struct hwa_info *hwa, *hwahead, **hwapnext;
int sockfd, len, lastlen, alias, nInterfaces, i;
char *buf, lastname[IFNAMSIZ], *cptr;
struct ifconf ifc;
struct ifreq *ifr, *item, ifrcopy;
struct sockaddr *sinptr;
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
return NULL;
}
lastlen = 0;
len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
for ( ; ; ) {
if((buf = malloc(len)) == NULL) {
goto CLOSE_SOCK;
}
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
if (errno != EINVAL || lastlen != 0) {
error("ioctl error: %s\n", strerror(errno));
goto FREE_BUF;
}
} else {
if (ifc.ifc_len == lastlen) {
break; /* success, len has not changed */
}
lastlen = ifc.ifc_len;
}
len += 10 * sizeof(struct ifreq); /* increment */
free(buf);
}
hwahead = NULL;
hwapnext = &hwahead;
lastname[0] = 0;
ifr = ifc.ifc_req;
nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
for(i = 0; i < nInterfaces; i++) {
item = &ifr[i];
if(strcmp(item->ifr_name, "eth0") != 0) {
// Skip over the interfaces we dont care about.
info("Skipping hardware device %s\n", item->ifr_name);
continue;
}
alias = 0;
if((hwa = calloc(1, sizeof(struct hwa_info))) == NULL) {
goto FREE_HWA;
}
memcpy(hwa->if_name, item->ifr_name, IFNAMSIZ); /* interface name */
hwa->if_name[IFNAMSIZ-1] = '\0';
/* start to check if alias address */
if ( (cptr = (char *) strchr(item->ifr_name, ':')) != NULL)
*cptr = 0; /* replace colon will null */
if (strncmp(lastname, item->ifr_name, IFNAMSIZ) == 0) {
alias = IP_ALIAS;
}
memcpy(lastname, item->ifr_name, IFNAMSIZ);
ifrcopy = *item;
*hwapnext = hwa; /* prev points to this new one */
hwapnext = &hwa->hwa_next; /* pointer to next one goes here */
hwa->ip_alias = alias; /* alias IP address flag: 0 if no; 1 if yes */
sinptr = &item->ifr_addr;
if((hwa->ip_addr = calloc(1, sizeof(struct sockaddr))) == NULL) {
goto FREE_BUF;
}
memcpy(hwa->ip_addr, sinptr, sizeof(struct sockaddr)); /* IP address */
/* get hw address */
if (ioctl(sockfd, SIOCGIFHWADDR, &ifrcopy) < 0) {
error("ioctl SIOCGIFHWADDR failed: %s", strerror(errno));
}
memcpy(hwa->if_haddr, ifrcopy.ifr_hwaddr.sa_data, IFHWADDRLEN);
/* get interface index */
if (ioctl(sockfd, SIOCGIFINDEX, &ifrcopy) < 0) {
error("ioctl SIOCGIFINDEX failed: %s", strerror(errno));
}
memcpy(&hwa->if_index, &ifrcopy.ifr_ifindex, sizeof(int));
}
free(buf);
return(hwahead); /* pointer to first structure in linked list */
FREE_HWA:
free_hwa_info(hwahead);
FREE_BUF:
free(buf);
CLOSE_SOCK:
close(sockfd);
return NULL;
}
void free_hwa_info(struct hwa_info *hwahead) {
struct hwa_info *hwa, *hwanext;
for (hwa = hwahead; hwa != NULL; hwa = hwanext) {
free(hwa->ip_addr);
hwanext = hwa->hwa_next; /* can't fetch hwa_next after free() */
free(hwa); /* the hwa_info{} itself */
}
}
struct hwa_info *hwa_searchbyindex(struct hwa_info *head, int index) {
struct hwa_info *tmp;
for(tmp = head; tmp != NULL; tmp = tmp->hwa_next) {
if(tmp->if_index == index) {
return tmp;
}
}
return NULL;
}