Block in ethsock_add_ip on Windows

This commit is contained in:
Joseph C. Lehner 2016-11-13 08:20:43 +01:00
parent 482b03db23
commit 644a9ce55f
2 changed files with 39 additions and 36 deletions

View file

@ -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)

20
tftp.c
View file

@ -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;
}
}