X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fdiscovery.c;h=4d05f7bc98e0373b4e2afc5685291c1025a639a4;hb=325d837df2ec867c668b6a911b97e719f196ba0e;hp=65c197409808acbc65469f6139dc164b4fdba735;hpb=c68c5ebd8abf7a91f3d0ea3d05aa872b6a40d78e;p=meshlink diff --git a/src/discovery.c b/src/discovery.c index 65c19740..4d05f7bc 100644 --- a/src/discovery.c +++ b/src/discovery.c @@ -1,3 +1,22 @@ +/* + discovery.c -- local network discovery + Copyright (C) 2014-2021 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + #define __APPLE_USE_RFC_3542 #include "system.h" @@ -102,6 +121,8 @@ static void send_mdns_packet_ipv4(meshlink_handle_t *mesh, int fd, int index, co struct cmsghdr align; } u; + memset(&u, 0, sizeof(u)); + struct msghdr msg = { .msg_name = (struct sockaddr *) &dest->sa, .msg_namelen = SALEN(dest->sa), @@ -111,7 +132,6 @@ static void send_mdns_packet_ipv4(meshlink_handle_t *mesh, int fd, int index, co .msg_controllen = sizeof(u.buf), }; - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_PKTINFO; @@ -413,8 +433,8 @@ static void addr_del(meshlink_handle_t *mesh, const discovery_address_t *addr) { memmove(p, p + 1, (mesh->discovery.addresses + --mesh->discovery.address_count - p) * sizeof(*p)); } -#if !defined(__linux) && (defined(RTM_NEWADDR) || defined(__APPLE__)) -static void scan_ifaddrs(meshlink_handle_t *mesh) { +void scan_ifaddrs(meshlink_handle_t *mesh) { +#ifdef HAVE_GETIFADDRS struct ifaddrs *ifa = NULL; if(getifaddrs(&ifa) == -1) { @@ -512,8 +532,10 @@ static void scan_ifaddrs(meshlink_handle_t *mesh) { } freeifaddrs(ifa); -} +#else + (void)mesh; #endif +} #if defined(__linux) static void netlink_getlink(int fd) { @@ -662,26 +684,26 @@ static void netlink_io_handler(event_loop_t *loop, void *data, int flags) { if(loop->now.tv_sec > mesh->discovery.last_update + 5) { mesh->discovery.last_update = loop->now.tv_sec; - handle_network_change(mesh, 1); + handle_network_change(mesh, true); } } } } #elif defined(__APPLE__) -static void network_change_callback(SCDynamicStoreRef store, CFArrayRef keys, void *info) { - (void)store; - (void)keys; +static void reachability_change_callback(SCNetworkReachabilityRef reachability, SCNetworkReachabilityFlags flags, void *info) { + (void)reachability; + (void)flags; meshlink_handle_t *mesh = info; pthread_mutex_lock(&mesh->mutex); - logger(mesh, MESHLINK_ERROR, "Network change detected!"); scan_ifaddrs(mesh); if(mesh->loop.now.tv_sec > mesh->discovery.last_update + 5) { + logger(mesh, MESHLINK_INFO, "Network change detected"); mesh->discovery.last_update = mesh->loop.now.tv_sec; - handle_network_change(mesh, 1); + handle_network_change(mesh, true); } pthread_mutex_unlock(&mesh->mutex); @@ -692,78 +714,42 @@ static void *network_change_handler(void *arg) { mesh->discovery.runloop = CFRunLoopGetCurrent(); - SCDynamicStoreContext context = {0, mesh, NULL, NULL, NULL}; - SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("network_change_handler"), network_change_callback, &context); - CFStringRef interfaces = SCDynamicStoreKeyCreate(NULL, CFSTR("State:/Network/Interface"), kCFStringEncodingUTF8); - CFStringRef ipv4 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); - CFStringRef ipv6 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); - CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFRunLoopSourceRef runloop_source = NULL; - - if(!store) { - logger(mesh, MESHLINK_ERROR, "Error setting up network change handler: %s\n", SCErrorString(SCError())); - goto exit; - } - - if(!interfaces || !ipv4 || !ipv6 || !keys || !patterns) { - logger(mesh, MESHLINK_ERROR, "Error setting up network change handler: %s\n", SCErrorString(SCError())); - goto exit; - } + SCNetworkReachabilityRef reach_v4 = SCNetworkReachabilityCreateWithName(NULL, "93.184.216.34"); + SCNetworkReachabilityRef reach_v6 = SCNetworkReachabilityCreateWithName(NULL, "2606:2800:220:1:248:1893:25c8:1946"); - CFArrayAppendValue(keys, interfaces); - CFArrayAppendValue(patterns, ipv4); - CFArrayAppendValue(patterns, ipv6); + SCNetworkReachabilityContext context; + memset(&context, 0, sizeof(context)); + context.info = mesh; - if(!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) { - logger(mesh, MESHLINK_ERROR, "Error setting up network change handler: %s\n", SCErrorString(SCError())); - goto exit; + if(reach_v4) { + SCNetworkReachabilitySetCallback(reach_v4, reachability_change_callback, &context); + SCNetworkReachabilityScheduleWithRunLoop(reach_v4, mesh->discovery.runloop, kCFRunLoopDefaultMode); + } else { + logger(mesh, MESHLINK_ERROR, "Could not create IPv4 network reachability watcher"); } - runloop_source = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); - - if(!runloop_source) { - logger(mesh, MESHLINK_ERROR, "Error setting up network change handler: %s\n", SCErrorString(SCError())); - goto exit; + if(reach_v6) { + SCNetworkReachabilitySetCallback(reach_v6, reachability_change_callback, &context); + SCNetworkReachabilityScheduleWithRunLoop(reach_v6, mesh->discovery.runloop, kCFRunLoopDefaultMode); + } else { + logger(mesh, MESHLINK_ERROR, "Could not create IPv6 network reachability watcher"); } - CFRunLoopAddSource(CFRunLoopGetCurrent(), runloop_source, kCFRunLoopDefaultMode); CFRunLoopRun(); -exit: - - if(runloop_source) { - CFRelease(runloop_source); - } - - if(interfaces) { - CFRelease(interfaces); - } - - if(ipv4) { - CFRelease(ipv4); - } - - if(ipv6) { - CFRelease(ipv6); - } - - if(keys) { - CFRelease(keys); - } + mesh->discovery.runloop = NULL; - if(patterns) { - CFRelease(patterns); + if(reach_v4) { + SCNetworkReachabilityUnscheduleFromRunLoop(reach_v4, mesh->discovery.runloop, kCFRunLoopDefaultMode); + CFRelease(reach_v4); } - if(store) { - CFRelease(store); + if(reach_v6) { + SCNetworkReachabilityUnscheduleFromRunLoop(reach_v6, mesh->discovery.runloop, kCFRunLoopDefaultMode); + CFRelease(reach_v6); } - mesh->discovery.runloop = NULL; - return NULL; - } #elif defined(RTM_NEWADDR) static void pfroute_parse_iface(meshlink_handle_t *mesh, const struct rt_msghdr *rtm) { @@ -885,7 +871,9 @@ bool discovery_start(meshlink_handle_t *mesh) { .in.sin_port = ntohs(5353), }; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); +#ifdef SO_REUSEPORT setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); +#endif setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one8, sizeof(one8)); setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl8, sizeof(ttl8)); @@ -906,7 +894,9 @@ bool discovery_start(meshlink_handle_t *mesh) { } setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); +#ifdef SO_REUSEPORT setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); +#endif setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one)); setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); @@ -932,9 +922,11 @@ bool discovery_start(meshlink_handle_t *mesh) { netlink_getlink(sock); } else { logger(mesh, MESHLINK_WARNING, "Could not bind AF_NETLINK socket: %s", strerror(errno)); + scan_ifaddrs(mesh); } } else { logger(mesh, MESHLINK_WARNING, "Could not open AF_NETLINK socket: %s", strerror(errno)); + scan_ifaddrs(mesh); } #elif defined(__APPLE__)