-
Notifications
You must be signed in to change notification settings - Fork 0
/
api.c
84 lines (71 loc) · 2.31 KB
/
api.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
#include "api.h"
int areq(struct sockaddr *ipa, socklen_t len, struct hwaddr *hwa) {
int sock, rv;
struct sockaddr_un arpaddr;
struct areq req;
fd_set rset;
struct timeval tv;
info("AREQ for IP: %s\n", inet_ntoa(((struct sockaddr_in *)ipa)->sin_addr));
if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
error("failed to create unix socket: %s\n", strerror(errno));
return 0;
}
/* Init the ARP address */
memset(&arpaddr, 0, sizeof(arpaddr));
arpaddr.sun_family = AF_UNIX;
strcpy(arpaddr.sun_path, ARP_WELL_KNOWN_PATH);
/* Connect to ARP */
if(connect(sock, (struct sockaddr *)&arpaddr, SUN_LEN(&arpaddr)) < 0) {
error("failed to connect to ARP: %s\n", strerror(errno));
goto CLOSE_SOCK;
}
/* Init ARP request */
memcpy(&req.addr, ipa, sizeof(struct sockaddr));
req.addrlen = len;
/* Send the ARP request */
if(send(sock, &req, sizeof(req), 0) < 0) {
error("failed to connect to ARP: %s\n", strerror(errno));
goto CLOSE_SOCK;
}
/* Wait 2 seconds for ARP response */
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&rset);
FD_SET(sock, &rset);
rv = select(sock + 1, &rset, NULL, NULL, &tv);
if(rv < 0) {
error("select failed: %s\n", strerror(errno));
goto CLOSE_SOCK;
} else if(rv == 0) {
error("ARP request timed out.\n");
goto CLOSE_SOCK;
} else {
int nread;
/* The socket is readable */
if((nread = recv(sock, hwa, sizeof(struct hwaddr), 0)) < 0) {
error("failed to recv from ARP: %s\n", strerror(errno));
goto CLOSE_SOCK;
} else if(nread < sizeof(struct hwaddr)) {
errno = EPROTO;
error("ARP failed: %s\n", strerror(errno));
goto CLOSE_SOCK;
}
info("AREQ returned <IP: %s, ETH: ", inet_ntoa(((struct
sockaddr_in *)ipa)->sin_addr));
print_hwa(hwa);
printf(">\n");
}
close(sock);
return 1;
CLOSE_SOCK:
warn("AREQ for IP: %s failed\n", inet_ntoa(((struct sockaddr_in *)ipa)->sin_addr));
close(sock);
return 0;
}
void print_hwa(struct hwaddr *hwa) {
int i;
for(i = 0; i < hwa->sll_halen - 1; ++i) {
printf("%02hhX:", hwa->sll_addr[i]);
}
printf("%02hhX", hwa->sll_addr[i]);
}