Repository navigation
Expand file tree
/
Copy pathnet_util.c
More file actions
254 lines (218 loc) · 7.89 KB
/
Copy pathnet_util.c
File metadata and controls
254 lines (218 loc) · 7.89 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#include "net_util.h"
#include "logging.h"
#include "misc.h"
#include "minieap_common.h"
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <ifaddrs.h>
#include <string.h>
#include <net/if.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <stdio.h>
static int ip_addr_family_cmpfunc(void* family, void* ip_addr) {
if (*(short*)family == ((IP_ADDR*)ip_addr)->family) {
return 0;
}
return 1;
}
IP_ADDR* find_ip_with_family(LIST_ELEMENT* list, short family) {
return (IP_ADDR*)lookup_data(list, &family, ip_addr_family_cmpfunc);
}
RESULT obtain_iface_mac(const char* ifname, uint8_t* adr_buf) {
struct ifreq ifreq;
int sockfd = -1;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
PR_ERRNO("套接字打开失败");
return FAILURE;
}
memset(&ifreq, 0, sizeof(struct ifreq));
strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
if (ioctl(sockfd, SIOCGIFHWADDR, &ifreq) < 0) {
PR_ERRNO("通过 ioctl 获取 MAC 地址失败");
close(sockfd);
return FAILURE;
}
memcpy(adr_buf, ifreq.ifr_hwaddr.sa_data, 6);
close(sockfd);
return SUCCESS;
}
RESULT obtain_iface_ip_mask(const char* ifname, LIST_ELEMENT** list) {
struct ifaddrs *ifaddrs, *if_curr;
IP_ADDR *addr;
if (getifaddrs(&ifaddrs) < 0) {
PR_ERRNO("通过 getifaddrs 获取 IP 地址失败");
return FAILURE;
}
if_curr = ifaddrs;
do {
if (strcmp(if_curr->ifa_name, ifname) == 0) {
addr = (IP_ADDR*)malloc(sizeof(IP_ADDR));
memset(addr, 0, sizeof(IP_ADDR));
addr->family = if_curr->ifa_addr->sa_family;
if (addr->family == AF_INET) {
memmove(addr->ip, &((struct sockaddr_in*)if_curr->ifa_addr)->sin_addr, 4);
if (if_curr->ifa_netmask) {
memmove(addr->mask, &((struct sockaddr_in*)if_curr->ifa_netmask)->sin_addr, 4);
}
} else if (addr->family == AF_INET6) {
memmove(addr->ip, &((struct sockaddr_in6*)if_curr->ifa_addr)->sin6_addr, 16);
if (if_curr->ifa_netmask) {
memmove(addr->mask, &((struct sockaddr_in6*)if_curr->ifa_netmask)->sin6_addr, 16);
}
}
insert_data(list, addr);
}
} while ((if_curr = if_curr->ifa_next));
freeifaddrs(ifaddrs);
return SUCCESS;
}
void free_ip_list(LIST_ELEMENT** list) {
list_destroy(list, TRUE);
}
RESULT obtain_dns_list(LIST_ELEMENT** list) {
FILE* _fp = fopen("/etc/resolv.conf", "r");
char _line_buf[MAX_LINE_LEN] = {0};
char* _line_buf_1;
if (_fp <= 0) {
PR_ERR("无法从 /etc/resolv.conf 获取 DNS 信息: %s", ferror(_fp));
return FAILURE;
}
while (fgets(_line_buf, MAX_LINE_LEN, _fp)) {
if (_line_buf[0] != '#') {
_line_buf_1 = strtok(_line_buf, " ");
if (_line_buf_1 == NULL || strcmp(_line_buf_1, "nameserver") != 0) continue;
_line_buf_1 = strtok(NULL, " ");
if (_line_buf_1 != NULL) {
int _len = strnlen(_line_buf_1, INET6_ADDRSTRLEN);
if (_line_buf_1[_len - 1] == '\n') {
_line_buf_1[_len - 1] = 0;
_len--;
}
insert_data(list, strndup(_line_buf_1, _len));
}
}
}
fclose(_fp);
return SUCCESS;
}
void free_dns_list(LIST_ELEMENT** list) {
list_destroy(list, TRUE);
}
/* http://stackoverflow.com/a/3288983/5701966 */
#define NL_BUFSIZE 8192
static int read_from_netlink_socket(int sockfd, uint8_t *buf, int seq, int pid) {
struct nlmsghdr *nlHdr;
int readLen = 0, msgLen = 0;
do {
/* Recieve response from the kernel */
if ((readLen = recv(sockfd, buf, NL_BUFSIZE - msgLen, 0)) < 0) {
PR_ERRNO("无法从 NETLINK 接收数据");
return -1;
}
nlHdr = (struct nlmsghdr *) buf;
/* Check if the header is valid */
if ((NLMSG_OK(nlHdr, readLen) == 0)
|| (nlHdr->nlmsg_type == NLMSG_ERROR)) {
struct nlmsgerr* _err = (struct nlmsgerr*) NLMSG_DATA(nlHdr);
8000
if (_err->error != 0) {
PR_ERR("NETLINK 报告了一个错误 (%d)", _err->error);
return -1;
}
}
/* Check if the its the last message */
if (nlHdr->nlmsg_type == NLMSG_DONE) {
break;
} else {
/* Else move the pointer to buffer appropriately */
buf += readLen;
msgLen += readLen;
}
/* Check if its a multi part message */
if ((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) {
/* return if its not */
break;
}
} while ((nlHdr->nlmsg_seq != seq) || (nlHdr->nlmsg_pid != pid));
return msgLen;
}
static RESULT retrive_if_gateway(const char* ifname, struct nlmsghdr* nl_hdr, struct in_addr* gateway) {
struct rtmsg *rtMsg;
struct rtattr *rtAttr;
struct in_addr dst_addr = {0}, this_gateway = {0};
int rtLen = 0;
char this_ifname[IFNAMSIZ] = {0};
rtMsg = (struct rtmsg *) NLMSG_DATA(nl_hdr);
/* If the route is not for AF_INET or does not belong to main routing table
then return. Do not care about IPv6 for now. */
if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
return FAILURE;
/* get the rtattr field */
rtAttr = (struct rtattr *) RTM_RTA(rtMsg);
rtLen = RTM_PAYLOAD(nl_hdr);
for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) {
switch (rtAttr->rta_type) {
case RTA_OIF:
if_indextoname(*(uint32_t *) RTA_DATA(rtAttr), this_ifname);
break;
case RTA_GATEWAY:
this_gateway.s_addr = *(uint32_t *) RTA_DATA(rtAttr);
break;
case RTA_DST:
dst_addr.s_addr = *(uint32_t *) RTA_DATA(rtAttr);
break;
}
}
#ifdef DEBUG
PR_DBG("%08X %08X %s", dst_addr.s_addr, this_gateway.s_addr, this_ifname);
#endif
if (dst_addr.s_addr == 0 && strncmp(this_ifname, ifname, IFNAMSIZ) == 0) {
gateway->s_addr = this_gateway.s_addr;
return SUCCESS;
}
return FAILURE;
}
RESULT obtain_iface_ipv4_gateway(const char* ifname, uint8_t* buf) {
struct nlmsghdr *nl_msg;
uint8_t msg_buf[NL_BUFSIZE];
int sockfd, len, msg_seq = 0, rand_pid = rand() % 65536;
if ((sockfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
PR_ERRNO("NETLINK 套接字打开失败");
return FAILURE;
}
memset(msg_buf, 0, sizeof(msg_buf));
/* Point the header and the msg structure pointers into the buffer */
nl_msg = (struct nlmsghdr *) msg_buf;
/* Fill in the nlmsg header*/
nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
nl_msg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table.
nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.
nl_msg->nlmsg_seq = msg_seq++; // Sequence of the message packet.
nl_msg->nlmsg_pid = rand_pid; // PID of process sending the request.
/* Send the request */
if (send(sockfd, nl_msg, nl_msg->nlmsg_len, 0) < 0) {
PR_ERRNO("无法向 NETLINK 发送请求");
goto err;
}
/* Read the response */
if ((len = read_from_netlink_socket(sockfd, msg_buf, msg_seq, rand_pid)) < 0) {
goto err;
}
/* Parse and print the response */
for (; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len)) {
struct in_addr addr;
memset(&addr, 0, sizeof(struct in_addr));
if (!IS_FAIL(retrive_if_gateway(ifname, nl_msg, &addr))) {
/* IPv4 Only */
memmove(buf, &addr.s_addr, 4);
close(sockfd);
return SUCCESS;
}
}
err:
close(sockfd);
return FAILURE;
}