Block in ethsock_add_ip on Windows
authorJoseph C. Lehner <joseph.c.lehner@gmail.com>
Sun, 13 Nov 2016 07:20:43 +0000 (08:20 +0100)
committerJoseph C. Lehner <joseph.c.lehner@gmail.com>
Sun, 13 Nov 2016 07:20:43 +0000 (08:20 +0100)
ethsock.c
tftp.c

index 75e166867047e8d9026fb06a688b05a655f45221..64a5058836c58a12f6d1c3d951d1b04d2ed62e17 100644 (file)
--- a/ethsock.c
+++ b/ethsock.c
@@ -644,7 +644,6 @@ int ethsock_for_each_ip(struct ethsock *sock, ethsock_ip_callback_t callback,
        return status <= 0 ? status : 0;
 }
 
-#ifndef NMRPFLASH_WINDOWS
 static inline void set_addr(void *p, uint32_t addr)
 {
        struct sockaddr_in* sin = p;
@@ -652,6 +651,7 @@ static inline void set_addr(void *p, uint32_t addr)
        sin->sin_addr.s_addr = addr;
 }
 
+#ifndef NMRPFLASH_WINDOWS
 static bool set_interface_up(int fd, const char *intf, bool up)
 {
        struct ifreq ifr;
@@ -685,22 +685,23 @@ int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struc
                return -1;
        }
 
-#ifndef NMRPFLASH_WINDOWS
-       int ret = -1;
        int fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (!fd) {
                perror("socket");
                return -1;
        }
 
+       int ret = -1;
+#ifndef NMRPFLASH_WINDOWS
+       // XXX: undo is non-zero only if we're adding an IP
+       bool add = undo;
 #ifdef NMRPFLASH_LINUX
        struct ifreq ifr;
        strncpy(ifr.ifr_name, sock->intf, IFNAMSIZ);
        // FIXME: automatically determine the next free alias
        strcat(ifr.ifr_name, ":42");
 
-       // XXX: undo is non-zero only if we're actually adding an ip
-       if (undo) {
+       if (add) {
                set_addr(&ifr.ifr_addr, ipaddr);
                if (ioctl(fd, SIOCSIFADDR, &ifr) != 0) {
                        perror("ioctl(SIOSIFADDR)");
@@ -717,7 +718,7 @@ int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struc
                (*undo)->ip[1] = ipmask;
        }
 
-       if (!set_interface_up(fd, ifr.ifr_name, undo ? true : false)) {
+       if (!set_interface_up(fd, ifr.ifr_name, add ? true : false)) {
                goto out;
        }
 #else // NMRPFLASH_OSX (or any other BSD)
@@ -729,38 +730,54 @@ int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struc
        //set_addr(&ifra.ifra_broadaddr, (ipaddr & ipmask) | ~ipmask);
        memset(&ifra.ifra_broadaddr, 0, sizeof(ifra.ifra_broadaddr));
 
-       // XXX: undo is non-zero only if we're actually adding an ip
-
-       if (ioctl(fd, undo ? SIOCAIFADDR : SIOCDIFADDR, &ifra) != 0) {
+       if (ioctl(fd, add ? SIOCAIFADDR : SIOCDIFADDR, &ifra) != 0) {
                perror("ioctl(SIOCAIFADDR)");
                goto out;
        }
 
-       if (undo) {
+       if (add) {
                (*undo)->ip[0] = ipaddr;
                (*undo)->ip[1] = ipmask;
                set_interface_up(fd, ifra.ifra_name, true);
        }
 
 #endif
-       ret = 0;
-
-out:
-       close(fd);
-       return ret;
 #else // NMRPFLASH_WINDOWS
+       struct sockaddr_in sin;
        ULONG instance;
 
        (*undo)->context = 0;
 
-       DWORD ret = AddIPAddress(ipaddr, ipmask, sock->index, &(*undo)->context, &instance);
-       if (ret != NO_ERROR && ret != ERROR_DUP_DOMAINNAME && ret != ERROR_OBJECT_ALREADY_EXISTS) {
-               win_perror2("AddIPAddress", ret);
-               return -1;
+       DWORD err = AddIPAddress(ipaddr, ipmask, sock->index, &(*undo)->context, &instance);
+       if (err != NO_ERROR && err != ERROR_DUP_DOMAINNAME && err != ERROR_OBJECT_ALREADY_EXISTS) {
+               win_perror2("AddIPAddress", err);
+               goto out;
        }
 
+       set_addr(&sin, ipaddr);
+       clock_t now = clock();
+
+       /* Wait until the new IP has actually been added */
+
+       while (bind(fd, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
+               if (((clock() - now) / CLOCKS_PER_SEC) >= 5) {
+                       fprintf(stderr, "Failed to bind after 5 seconds: ");
+                       sock_perror("bind");
+                       DeleteIPAddress((*undo)->context);
+                       goto out;
+               }
+       }
        return 0;
 #endif
+       ret = 0;
+
+out:
+#ifndef NMRPFLASH_WINDOWS
+       close(fd);
+#else
+       closesocket(fd);
+#endif
+       return ret;
 }
 
 int ethsock_ip_del(struct ethsock *sock, struct ethsock_ip_undo **undo)
diff --git a/tftp.c b/tftp.c
index ad02be72f48e49a736738f754d3c172e03501842..bb4d818d64e8594d672c1c336edf1230cf49cfd8 100644 (file)
--- a/tftp.c
+++ b/tftp.c
@@ -272,23 +272,9 @@ int tftp_put(struct nmrpd_args *args)
                        goto cleanup;
                }
 
-               int tries = 100;
-
-               while (1) {
-                       if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
-#ifdef NMRPFLASH_WINDOWS
-                               // Wait for AddIPAddress to update the IP tables
-                               if (WSAGetLastError() == WSAEADDRNOTAVAIL) {
-                                       if (--tries) {
-                                               continue;
-                                       }
-                               }
-#endif
-                               sock_perror("bind");
-                               goto cleanup;
-                       }
-
-                       break;
+               if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
+                       sock_perror("bind");
+                       goto cleanup;
                }
        }