diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-22 00:58:49 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-22 00:58:49 +0000 |
commit | 223bc97f61f2fd5efbccede0837a374c1669e864 (patch) | |
tree | 0105a1f02dbc344ede7cca99565b6c556e7cab96 /networking/udhcp/arpping.c | |
parent | c881c733bb05286f7147d0ca49ad238b86f6d848 (diff) | |
download | busybox-w32-223bc97f61f2fd5efbccede0837a374c1669e864.tar.gz busybox-w32-223bc97f61f2fd5efbccede0837a374c1669e864.tar.bz2 busybox-w32-223bc97f61f2fd5efbccede0837a374c1669e864.zip |
udhcpc: an option to perform ARP check (Jonas Danielsson <jonas.danielsson@axis.com>)
configurable, ~+300 bytes when on.
Diffstat (limited to 'networking/udhcp/arpping.c')
-rw-r--r-- | networking/udhcp/arpping.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c index 7b702d8f3..45597c04b 100644 --- a/networking/udhcp/arpping.c +++ b/networking/udhcp/arpping.c | |||
@@ -32,12 +32,16 @@ struct arpMsg { | |||
32 | uint8_t pad[18]; /* 2a 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 | enum { | ||
36 | ARP_MSG_SIZE = 0x2a | ||
37 | }; | ||
38 | |||
35 | 39 | ||
36 | /* Returns 1 if no reply received */ | 40 | /* Returns 1 if no reply received */ |
37 | 41 | ||
38 | int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface) | 42 | int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface) |
39 | { | 43 | { |
40 | int timeout_ms = 2000; | 44 | int timeout_ms; |
41 | struct pollfd pfd[1]; | 45 | struct pollfd pfd[1]; |
42 | #define s (pfd[0].fd) /* socket */ | 46 | #define s (pfd[0].fd) /* socket */ |
43 | int rv = 1; /* "no reply received" yet */ | 47 | int rv = 1; /* "no reply received" yet */ |
@@ -51,7 +55,7 @@ int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *i | |||
51 | } | 55 | } |
52 | 56 | ||
53 | if (setsockopt_broadcast(s) == -1) { | 57 | if (setsockopt_broadcast(s) == -1) { |
54 | bb_perror_msg("cannot setsocketopt on raw socket"); | 58 | bb_perror_msg("cannot enable bcast on raw socket"); |
55 | goto ret; | 59 | goto ret; |
56 | } | 60 | } |
57 | 61 | ||
@@ -67,28 +71,35 @@ int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *i | |||
67 | arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ | 71 | arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ |
68 | memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */ | 72 | memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */ |
69 | memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */ | 73 | memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */ |
70 | /* tHaddr */ /* target hardware address */ | 74 | /* tHaddr is zero-fiiled */ /* target hardware address */ |
71 | memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */ | 75 | memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */ |
72 | 76 | ||
73 | memset(&addr, 0, sizeof(addr)); | 77 | memset(&addr, 0, sizeof(addr)); |
74 | safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data)); | 78 | safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data)); |
75 | if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) | 79 | if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) { |
80 | // TODO: error message? caller didn't expect us to fail, | ||
81 | // just returning 1 "no reply received" misleads it. | ||
76 | goto ret; | 82 | goto ret; |
83 | } | ||
77 | 84 | ||
78 | /* wait for arp reply, and check it */ | 85 | /* wait for arp reply, and check it */ |
86 | timeout_ms = 2000; | ||
79 | do { | 87 | do { |
80 | int r; | 88 | int r; |
81 | unsigned prevTime = monotonic_us(); | 89 | unsigned prevTime = monotonic_us(); |
82 | 90 | ||
83 | pfd[0].events = POLLIN; | 91 | pfd[0].events = POLLIN; |
84 | r = safe_poll(pfd, 1, timeout_ms); | 92 | r = safe_poll(pfd, 1, timeout_ms); |
85 | if (r < 0) { | 93 | if (r < 0) |
86 | break; | 94 | break; |
87 | } else if (r) { | 95 | if (r) { |
88 | if (read(s, &arp, sizeof(arp)) < 0) | 96 | r = read(s, &arp, sizeof(arp)); |
97 | if (r < 0) | ||
89 | break; | 98 | break; |
90 | if (arp.operation == htons(ARPOP_REPLY) | 99 | if (r >= ARP_MSG_SIZE |
91 | && memcmp(arp.tHaddr, from_mac, 6) == 0 | 100 | && arp.operation == htons(ARPOP_REPLY) |
101 | /* don't check it: Linux doesn't return proper tHaddr (fixed in 2.6.24?) */ | ||
102 | /* && memcmp(arp.tHaddr, from_mac, 6) == 0 */ | ||
92 | && *((uint32_t *) arp.sInaddr) == test_ip | 103 | && *((uint32_t *) arp.sInaddr) == test_ip |
93 | ) { | 104 | ) { |
94 | rv = 0; | 105 | rv = 0; |