Once I call socket()
; bind()
(with a specific IP address, not INADDR_ANY
); listen()
, there seems to be no way of determining if the IP address is still a valid address of one of the system's interfaces.
What I looked into using:
getsockopt(SO_ERROR)
;epoll()
-ing on some EPOLLERR
, EPOLL{,RD}HUP
events;accept()
would return an error if the IP address is deleted when process is blocked on this syscall;Non of those above seem to detect the IP address vanishing and/or change of interface state at all.
bind()
in some timer callback to periodically check if the IP address may be bound, but this requires another socket has to be created it is not feasible.I did not test these:
Setting SO_BINDTODEVICE
in the hope that this will change behavior of the facilities from the first triple in case interface goes down/IP address is removed.
Calling some ioctl()
like SIOCSPGRP
or FIOASYNC
since they promise to signal process about asynchronous events that hopefully include disappearance of an IP address.
Using netlink
to get routing table events, but this is very Linux-specific.
I'm hopping for a more portable way.
What I needing is some event similar to RDMA_CM_EVENT_DEVICE_REMOVAL
, but with AF_INET
sockets that would notify me when there is no bound interface with that IP address. Even this may be impossible to fulfill, because even bind()
completes without error if the interface is down.
You do not need to close a socket when the link goes down with BSD sockets.
This other questions shows how to listen for network routing changes mentioned by Remy.
A simpler way may be to check if the IP is currently bound before using the socket. This is a way to verify that 127.0.0.1
is still valid:
% cat checksocket.c && cc -o checksocket checksocket.c ; ./checksocket
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <net/if.h>
int main (void)
{
struct ifaddrs *ifa, *i;
char host[NI_MAXHOST];
int ret = getifaddrs(&ifa);
if (ret) {
perror("getifaddrs:");
exit(EXIT_FAILURE);
}
for (i = ifa; i != NULL; i = i->ifa_next) {
ret = getnameinfo(i->ifa_addr, sizeof(*(i->ifa_addr)),
host, sizeof(host), NULL, 0, NI_NUMERICHOST);
char find[] = "127.0.0.1";
int len = strlen(host);
if (!ret && len && !strncmp(host, find, len)) {
printf("Still valid: %s %s\n", i->ifa_name, ret ? "" : host);
}
}
freeifaddrs(ifa);
return 0;
}
Still valid: lo0 127.0.0.1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With