+ if(fd == -1) {
+ logger(mesh, MESHLINK_ERROR, "Error creating IPv6 socket: %s", strerror(errno));
+ }
+
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
+ 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));
+ setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
+
+ if(bind(fd, &sa6.sa, SALEN(sa6.sa)) == -1) {
+ logger(mesh, MESHLINK_ERROR, "Error binding to IPv4 multicast socket: %s", strerror(errno));
+ } else {
+ io_add(&mesh->loop, &mesh->discovery.sockets[1], mdns_io_handler, &mesh->discovery.sockets[1], fd, IO_READ);
+ }
+
+#if defined(__linux)
+ int sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+
+ if(sock != -1) {
+ struct sockaddr_nl sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.nl_family = AF_NETLINK;
+ sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
+
+ if(bind(sock, (struct sockaddr *)&sa, sizeof(sa)) != -1) {
+ io_add(&mesh->loop, &mesh->discovery.pfroute_io, netlink_io_handler, NULL, sock, IO_READ);
+ 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__)
+ pthread_create(&mesh->discovery.thread, NULL, network_change_handler, mesh);
+ // TODO: Do we need to wait for the thread to start succesfully?
+ scan_ifaddrs(mesh);
+#elif defined(RTM_NEWADDR)
+ int sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
+
+ if(sock != -1) {
+ io_add(&mesh->loop, &mesh->discovery.pfroute_io, pfroute_io_handler, NULL, sock, IO_READ);
+ } else {
+ logger(mesh, MESHLINK_WARNING, "Could not open PF_ROUTE socket: %s", strerror(errno));
+ }
+
+ scan_ifaddrs(mesh);
+#endif