summaryrefslogtreecommitdiff
path: root/networking/udhcp/arpping.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/udhcp/arpping.c')
-rw-r--r--networking/udhcp/arpping.c121
1 files changed, 58 insertions, 63 deletions
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c
index 615a91172..4ac52c640 100644
--- a/networking/udhcp/arpping.c
+++ b/networking/udhcp/arpping.c
@@ -15,44 +15,36 @@
15 15
16struct arpMsg { 16struct arpMsg {
17 /* Ethernet header */ 17 /* Ethernet header */
18 uint8_t h_dest[6]; /* destination ether addr */ 18 uint8_t h_dest[6]; /* 00 destination ether addr */
19 uint8_t h_source[6]; /* source ether addr */ 19 uint8_t h_source[6]; /* 06 source ether addr */
20 uint16_t h_proto; /* packet type ID field */ 20 uint16_t h_proto; /* 0c packet type ID field */
21 21
22 /* ARP packet */ 22 /* ARP packet */
23 uint16_t htype; /* hardware type (must be ARPHRD_ETHER) */ 23 uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */
24 uint16_t ptype; /* protocol type (must be ETH_P_IP) */ 24 uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */
25 uint8_t hlen; /* hardware address length (must be 6) */ 25 uint8_t hlen; /* 12 hardware address length (must be 6) */
26 uint8_t plen; /* protocol address length (must be 4) */ 26 uint8_t plen; /* 13 protocol address length (must be 4) */
27 uint16_t operation; /* ARP opcode */ 27 uint16_t operation; /* 14 ARP opcode */
28 uint8_t sHaddr[6]; /* sender's hardware address */ 28 uint8_t sHaddr[6]; /* 16 sender's hardware address */
29 uint8_t sInaddr[4]; /* sender's IP address */ 29 uint8_t sInaddr[4]; /* 1c sender's IP address */
30 uint8_t tHaddr[6]; /* target's hardware address */ 30 uint8_t tHaddr[6]; /* 20 target's hardware address */
31 uint8_t tInaddr[4]; /* target's IP address */ 31 uint8_t tInaddr[4]; /* 26 target's IP address */
32 uint8_t pad[18]; /* pad for min. Ethernet payload (60 bytes) */ 32 uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */
33} ATTRIBUTE_PACKED; 33} ATTRIBUTE_PACKED;
34 34
35/* args: yiaddr - what IP to ping
36 * ip - our ip
37 * mac - our arp address
38 * interface - interface to use
39 * retn: 1 addr free
40 * 0 addr used
41 * -1 error
42 */
43 35
44/* FIXME: match response against chaddr */ 36/* Returns 1 if no reply received */
45int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)
46{
47 int timeout = 2;
48 int s; /* socket */
49 int rv = 1; /* return value */
50 struct sockaddr addr; /* for interface name */
51 struct arpMsg arp;
52 fd_set fdset;
53 struct timeval tm;
54 time_t prevTime;
55 37
38int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface)
39{
40 int timeout = 2;
41 int s; /* socket */
42 int rv = 1; /* "no reply received" yet */
43 struct sockaddr addr; /* for interface name */
44 struct arpMsg arp;
45 fd_set fdset;
46 struct timeval tm;
47 unsigned prevTime;
56 48
57 s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); 49 s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
58 if (s == -1) { 50 if (s == -1) {
@@ -62,55 +54,58 @@ int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)
62 54
63 if (setsockopt_broadcast(s) == -1) { 55 if (setsockopt_broadcast(s) == -1) {
64 bb_perror_msg("cannot setsocketopt on raw socket"); 56 bb_perror_msg("cannot setsocketopt on raw socket");
65 close(s); 57 goto ret;
66 return -1;
67 } 58 }
68 59
69 /* send arp request */ 60 /* send arp request */
70 memset(&arp, 0, sizeof(arp)); 61 memset(&arp, 0, sizeof(arp));
71 memcpy(arp.h_dest, MAC_BCAST_ADDR, 6); /* MAC DA */ 62 memset(arp.h_dest, 0xff, 6); /* MAC DA */
72 memcpy(arp.h_source, mac, 6); /* MAC SA */ 63 memcpy(arp.h_source, from_mac, 6); /* MAC SA */
73 arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */ 64 arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
74 arp.htype = htons(ARPHRD_ETHER); /* hardware type */ 65 arp.htype = htons(ARPHRD_ETHER); /* hardware type */
75 arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */ 66 arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */
76 arp.hlen = 6; /* hardware address length */ 67 arp.hlen = 6; /* hardware address length */
77 arp.plen = 4; /* protocol address length */ 68 arp.plen = 4; /* protocol address length */
78 arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ 69 arp.operation = htons(ARPOP_REQUEST); /* ARP op code */
79 memcpy(arp.sInaddr, &ip, sizeof(ip)); /* source IP address */ 70 memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */
80 memcpy(arp.sHaddr, mac, 6); /* source hardware address */ 71 memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */
81 memcpy(arp.tInaddr, &yiaddr, sizeof(yiaddr)); /* target IP address */ 72 /* tHaddr */ /* target hardware address */
73 memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */
82 74
83 memset(&addr, 0, sizeof(addr)); 75 memset(&addr, 0, sizeof(addr));
84 strcpy(addr.sa_data, interface); 76 safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data));
85 if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) 77 if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)
86 rv = 0; 78 goto ret;
87 79
88 /* wait arp reply, and check it */ 80 /* wait for arp reply, and check it */
89 tm.tv_usec = 0; 81 do {
90 prevTime = uptime(); 82 int r;
91 while (timeout > 0) { 83 prevTime = monotonic_sec();
92 FD_ZERO(&fdset); 84 FD_ZERO(&fdset);
93 FD_SET(s, &fdset); 85 FD_SET(s, &fdset);
94 tm.tv_sec = timeout; 86 tm.tv_sec = timeout;
95 if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) { 87 tm.tv_usec = 0;
88 r = select(s + 1, &fdset, NULL, NULL, &tm);
89 if (r < 0) {
96 bb_perror_msg("error on ARPING request"); 90 bb_perror_msg("error on ARPING request");
97 if (errno != EINTR) 91 if (errno != EINTR)
98 rv = 0; 92 break;
99 } else if (FD_ISSET(s, &fdset)) { 93 } else if (r) {
100 if (recv(s, &arp, sizeof(arp), 0) < 0) 94 if (recv(s, &arp, sizeof(arp), 0) < 0)
101 rv = 0; 95 break;
102 if (arp.operation == htons(ARPOP_REPLY) && 96 if (arp.operation == htons(ARPOP_REPLY)
103 memcmp(arp.tHaddr, mac, 6) == 0 && 97 && memcmp(arp.tHaddr, from_mac, 6) == 0
104 *((uint32_t *) arp.sInaddr) == yiaddr) { 98 && *((uint32_t *) arp.sInaddr) == test_ip
105 DEBUG("Valid arp reply received for this address"); 99 ) {
106 rv = 0; 100 rv = 0;
107 break; 101 break;
108 } 102 }
109 } 103 }
110 timeout -= uptime() - prevTime; 104 timeout -= monotonic_sec() - prevTime;
111 prevTime = uptime(); 105 } while (timeout > 0);
112 } 106
107 ret:
113 close(s); 108 close(s);
114 DEBUG("%salid arp replies for this address", rv ? "No v" : "V"); 109 DEBUG("%srp reply received for this address", rv ? "No a" : "A");
115 return rv; 110 return rv;
116} 111}