- strcpy(addr.sa_data, interface);
- if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)
- rv = 0;
-
- /* wait arp reply, and check it */
- tm.tv_usec = 0;
- prevTime = time(NULL);
- while (timeout > 0) {
- FD_ZERO(&fdset);
- FD_SET(s, &fdset);
- tm.tv_sec = timeout;
- if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {
- DEBUG(LOG_ERR, "Error on ARPING request: %m");
- if (errno != EINTR) rv = 0;
- } else if (FD_ISSET(s, &fdset)) {
- if (recv(s, &arp, sizeof(arp), 0) < 0 ) rv = 0;
- if (arp.operation == htons(ARPOP_REPLY) &&
- bcmp(arp.tHaddr, mac, 6) == 0 &&
- *((uint32_t *) arp.sInaddr) == yiaddr) {
- DEBUG(LOG_INFO, "Valid arp reply receved for this address");
+ safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data));
+ if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) {
+ // TODO: error message? caller didn't expect us to fail,
+ // just returning 1 "no reply received" misleads it.
+ goto ret;
+ }
+
+ /* wait for arp reply, and check it */
+ timeout_ms = 2000;
+ do {
+ int r;
+ unsigned prevTime = monotonic_us();
+
+ pfd[0].events = POLLIN;
+ r = safe_poll(pfd, 1, timeout_ms);
+ if (r < 0)
+ break;
+ if (r) {
+ r = read(s, &arp, sizeof(arp));
+ if (r < 0)
+ break;
+ if (r >= ARP_MSG_SIZE
+ && arp.operation == htons(ARPOP_REPLY)
+ /* don't check it: Linux doesn't return proper tHaddr (fixed in 2.6.24?) */
+ /* && memcmp(arp.tHaddr, from_mac, 6) == 0 */
+ && *((uint32_t *) arp.sInaddr) == test_ip
+ ) {