From 0c4970336a40ebb435664a9691254ea5807bcd38 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sun, 29 Oct 2023 19:29:32 -0400 Subject: [PATCH] iiod: Make sure network is alive before poking avahi In the past, we were only checking hostname, as a way to see if the network was ready, but unfortunately - that doesn't work. The kernel really only needs to have a hostname set for uname() to work, which is what glibc and uclibc implement in gethostname(). So - now we check there is a working, configured ethernet card, that supports mdns (ie. multicast) that is up before moving on to making sure there is a hostname. We also don't allow "none" or "(none)" to be the hostname until after things time out (3 min). This fixes #1072 and turns: 192.168.2.1:5353 : answer _iio._tcp.local. PTR "iiod on (none)._iio._tcp.local." rclass 0x1 ttl 10 length 17 into: 192.168.2.1:5353 : answer _iio._tcp.local. PTR "iiod on pluto._iio._tcp.local." rclass 0x1 ttl 10 length 16 Signed-off-by: Robin Getz --- iiod/dns-sd.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/iiod/dns-sd.c b/iiod/dns-sd.c index 75bb27d04..f976975eb 100644 --- a/iiod/dns-sd.c +++ b/iiod/dns-sd.c @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -242,21 +244,53 @@ static void create_services(AvahiClient *c) } #define IIOD_ON "iiod on " +#define TIMEOUT 20 static void start_avahi_thd(struct thread_pool *pool, void *d) { - char label[AVAHI_LABEL_MAX]; char host[AVAHI_LABEL_MAX - sizeof(IIOD_ON)]; struct timespec ts; - int ret; + int ret, net = 0; ts.tv_nsec = 0; ts.tv_sec = 1; while(true) { + struct ifaddrs *ifaddr = 0; + struct ifaddrs *ifa = 0; + + if (!net) { + /* Ensure networking is alive */ + ret = getifaddrs(&ifaddr); + if (ret) + goto again; + + /* Make sure at least one practical interface is up and ready */ + for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { + /* no address */ + if (!ifa->ifa_addr) + continue; + /* or not up */ + if (!(ifa->ifa_flags & IFF_UP)) + continue; + /* or not multicast (doesn't support MDNS) */ + if (!(ifa->ifa_flags & IFF_MULTICAST)) + continue; + /* or is loopback */ + if ((ifa->ifa_flags & IFF_LOOPBACK)) + continue; + net++; + } + freeifaddrs(ifaddr); + if (!net) + goto again; + } + + /* Get the hostname, which on uClibc, can return (none) + * rather than fail/zero length string, like on glibc */ ret = gethostname(host, sizeof(host)); - if (ret || !strcmp(host, "none")) + if (ret || (ts.tv_sec <= TIMEOUT && (!strcmp(host, "none") || !strcmp(host, "(none)")))) goto again; snprintf(label, sizeof(label), "%s%s", IIOD_ON, host); @@ -277,13 +311,13 @@ static void start_avahi_thd(struct thread_pool *pool, void *d) if (avahi.client) break; again: - IIO_INFO("Avahi didn't start, try again later\n"); + IIO_INFO("Avahi didn't start, try again in %d seconds later\n", ts.tv_sec); nanosleep(&ts, NULL); ts.tv_sec++; - /* If it hasn't started in 10 times over 60 seconds, + /* If it hasn't started in 20 times over 210 seconds (3.5 min), * it is not going to, so stop */ - if (ts.tv_sec >= 11) + if (ts.tv_sec >= TIMEOUT + 1) break; }