From 38483f31be391af66b35542f733e569febe13d3a 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 and when you have multiple on network (with same name): 192.168.1.110:5353 : answer _iio._tcp.local. PTR "iiod on pluto._iio._tcp.local." rclass 0x1 ttl 10 length 16 192.168.1.110:5353 : answer pluto.local. A 192.168.1.110 192.168.1.115:5353 : answer _iio._tcp.local. PTR "iiod on pluto #2._iio._tcp.local." rclass 0x1 ttl 10 length 19 192.168.1.115:5353 : answer pluto-2.local. A 192.168.1.115 Signed-off-by: Robin Getz [pcercuei: change %d to %ld in print format string] Signed-off-by: Paul Cercueil --- iiod/dns-sd.c | 55 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/iiod/dns-sd.c b/iiod/dns-sd.c index 724f33cf2..d4a89ee1a 100644 --- a/iiod/dns-sd.c +++ b/iiod/dns-sd.c @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -242,21 +244,62 @@ 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; + /* + * Try to make sure the network is up before letting avahi + * know we are here, and advertising on the network. + * However, if we are on the last try before we timeout, + * ignore some prerequisites, and just assume it will be + * OK later (if someone boots, and later plugs in USB <-> ethernet). + */ while(true) { + struct ifaddrs *ifaddr = 0; + struct ifaddrs *ifa = 0; + + if (!net && ts.tv_sec < TIMEOUT) { + /* 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; + /* Interface is running, think ifup */ + if (!(ifa->ifa_flags & IFF_UP)) + continue; + /* supports multicast (i.e. MDNS) */ + if (!(ifa->ifa_flags & IFF_MULTICAST)) + continue; + /* Interface is not a loopback interface */ + if ((ifa->ifa_flags & IFF_LOOPBACK)) + continue; + IIO_INFO("found applicable network for mdns on %s\n", ifa->ifa_name); + 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 || !host[0] || (ts.tv_sec < TIMEOUT && (!strcmp(host, "none") || + !strcmp(host, "(none)")))) goto again; snprintf(label, sizeof(label), "%s%s", IIOD_ON, host); @@ -277,13 +320,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 %ld 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) break; }