Fix/change comment format about port 5353
[project/mdnsd.git] / interface.c
index 2b09ad3..463335a 100644 (file)
@@ -38,6 +38,7 @@
 #include "util.h"
 #include "dns.h"
 #include "announce.h"
+#include "service.h"
 
 static int
 interface_send_packet4(struct interface *iface, struct iovec *iov, int iov_len)
@@ -110,6 +111,11 @@ interface_send_packet6(struct interface *iface, struct iovec *iov, int iov_len)
 int
 interface_send_packet(struct interface *iface, struct iovec *iov, int iov_len)
 {
+       if (debug > 1) {
+               fprintf(stderr, "TX ipv%d: %s\n", iface->v6 * 2 + 4, iface->name);
+               fprintf(stderr, "  multicast: %d\n", iface->multicast);
+       }
+
        if (iface->v6)
                return interface_send_packet6(iface, iov, iov_len);
 
@@ -133,6 +139,25 @@ static void interface_free(struct interface *iface)
        free(iface);
 }
 
+static int
+interface_valid_src(void *ip1, void *mask, void *ip2, int len)
+{
+       uint8_t *i1 = ip1;
+       uint8_t *i2 = ip2;
+       uint8_t *m = mask;
+       int i;
+
+       if (cfg_no_subnet)
+               return 0;
+
+       for (i = 0; i < len; i++, i1++, i2++, m++) {
+               if ((*i1 & *m) != (*i2 & *m))
+                       return -1;
+       }
+
+       return 0;
+}
+
 static void
 read_socket4(struct uloop_fd *u, unsigned int events)
 {
@@ -194,8 +219,7 @@ read_socket4(struct uloop_fd *u, unsigned int events)
        if (debug > 1) {
                char buf[256];
 
-               fprintf(stderr, "iface: %s\n", iface->name);
-               fprintf(stderr, "  v6: %d\n", iface->v6);
+               fprintf(stderr, "RX ipv4: %s\n", iface->name);
                fprintf(stderr, "  multicast: %d\n", iface->multicast);
                inet_ntop(AF_INET, &from.sin_addr, buf, 256);
                fprintf(stderr, "  src %s:%d\n", buf, from.sin_port);
@@ -207,8 +231,8 @@ read_socket4(struct uloop_fd *u, unsigned int events)
 
        if (inp->ipi_ifindex != iface->ifindex)
                fprintf(stderr, "invalid iface index %d != %d\n", ifindex, iface->ifindex);
-       else
-               dns_handle_packet(iface, buffer, len, 0);
+       else if (!interface_valid_src((void *) &iface->v4_addr, (void *) &iface->v4_netmask, (void *) &from.sin_addr, 4))
+               dns_handle_packet(iface, (struct sockaddr *) &from, from.sin_port, buffer, len);
 }
 
 static void
@@ -272,8 +296,7 @@ read_socket6(struct uloop_fd *u, unsigned int events)
        if (debug > 1) {
                char buf[256];
 
-               fprintf(stderr, "iface: %s\n", iface->name);
-               fprintf(stderr, "  v6: %d\n", iface->v6);
+               fprintf(stderr, "RX ipv6: %s\n", iface->name);
                fprintf(stderr, "  multicast: %d\n", iface->multicast);
                inet_ntop(AF_INET6, &from.sin6_addr, buf, 256);
                fprintf(stderr, "  src %s:%d\n", buf, from.sin6_port);
@@ -283,8 +306,8 @@ read_socket6(struct uloop_fd *u, unsigned int events)
 
        if (inp->ipi6_ifindex != iface->ifindex)
                fprintf(stderr, "invalid iface index %d != %d\n", ifindex, iface->ifindex);
-       else
-               dns_handle_packet(iface, buffer, len, 0);
+       else if (!interface_valid_src((void *) &iface->v6_addr, (void *) &iface->v6_netmask, (void *) &from.sin6_addr, 16))
+               dns_handle_packet(iface, (struct sockaddr *) &from, from.sin6_port, buffer, len);
 }
 
 static int
@@ -375,6 +398,9 @@ reconnect_socket4(struct uloop_timeout *timeout)
                goto retry;
        }
 
+       if (setsockopt(iface->fd.fd, SOL_SOCKET, SO_BINDTODEVICE, iface->name, strlen(iface->name) < 0))
+               fprintf(stderr, "ioctl failed: SO_BINDTODEVICE\n");
+
        if (setsockopt(iface->fd.fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
                fprintf(stderr, "ioctl failed: SO_REUSEADDR\n");
 
@@ -391,7 +417,7 @@ reconnect_socket4(struct uloop_timeout *timeout)
 
        uloop_fd_add(&iface->fd, ULOOP_READ);
        if (iface->multicast) {
-               dns_send_question(iface, "_services._dns-sd._udp.local", TYPE_PTR, 1);
+               dns_send_question(iface, "_services._dns-sd._udp.local", TYPE_PTR, 0);
                announce_init(iface);
        }
 
@@ -416,6 +442,9 @@ reconnect_socket6(struct uloop_timeout *timeout)
                goto retry;
        }
 
+       if (setsockopt(iface->fd.fd, SOL_SOCKET, SO_BINDTODEVICE, iface->name, strlen(iface->name) < 0))
+               fprintf(stderr, "ioctl failed: SO_BINDTODEVICE\n");
+
        if (setsockopt(iface->fd.fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0)
                fprintf(stderr, "ioctl failed: IPV6_UNICAST_HOPS\n");
 
@@ -436,7 +465,7 @@ reconnect_socket6(struct uloop_timeout *timeout)
        uloop_fd_add(&iface->fd, ULOOP_READ);
 
        if (iface->multicast) {
-               dns_send_question(iface, "_services._dns-sd._udp.local", TYPE_PTR, 1);
+               dns_send_question(iface, "_services._dns-sd._udp.local", TYPE_PTR, 0);
                announce_init(iface);
        }
 
@@ -528,15 +557,20 @@ int interface_add(const char *name)
                        unicast = _interface_add(name, 0, 0);
                        if (!unicast)
                                continue;
-                       sa = (struct sockaddr_in *) ifa->ifa_addr;
-                       memcpy(&unicast->v4_addr, &sa->sin_addr, sizeof(unicast->v4_addr));
-                       inet_ntop(AF_INET, &sa->sin_addr, unicast->v4_addrs, sizeof(unicast->v4_addrs));
-
                        v4 = _interface_add(name, 1, 0);
                        if (!v4)
                                continue;
+
+                       sa = (struct sockaddr_in *) ifa->ifa_addr;
                        memcpy(&v4->v4_addr, &sa->sin_addr, sizeof(v4->v4_addr));
+                       memcpy(&unicast->v4_addr, &sa->sin_addr, sizeof(unicast->v4_addr));
+
                        inet_ntop(AF_INET, &sa->sin_addr, v4->v4_addrs, sizeof(v4->v4_addrs));
+                       inet_ntop(AF_INET, &sa->sin_addr, unicast->v4_addrs, sizeof(unicast->v4_addrs));
+
+                       sa = (struct sockaddr_in *) ifa->ifa_netmask;
+                       memcpy(&unicast->v4_netmask, &sa->sin_addr, sizeof(unicast->v4_netmask));
+                       memcpy(&v4->v4_netmask, &sa->sin_addr, sizeof(v4->v4_netmask));
 
                        v4->peer = unicast;
                        unicast->peer = v4;
@@ -556,14 +590,19 @@ int interface_add(const char *name)
                        unicast = _interface_add(name, 0, 1);
                        if (!unicast)
                                continue;
-                       memcpy(&unicast->v6_addr, &sa6->sin6_addr, sizeof(unicast->v6_addr));
-                       inet_ntop(AF_INET6, &sa6->sin6_addr, unicast->v6_addrs, sizeof(unicast->v6_addrs));
-
                        v6 = _interface_add(name, 1, 1);
                        if (!v6)
                                continue;
+
                        memcpy(&v6->v6_addr, &sa6->sin6_addr, sizeof(v6->v6_addr));
+                       memcpy(&unicast->v6_addr, &sa6->sin6_addr, sizeof(unicast->v6_addr));
+
                        inet_ntop(AF_INET6, &sa6->sin6_addr, v6->v6_addrs, sizeof(v6->v6_addrs));
+                       inet_ntop(AF_INET6, &sa6->sin6_addr, unicast->v6_addrs, sizeof(unicast->v6_addrs));
+
+                       sa6 = (struct sockaddr_in6 *) ifa->ifa_netmask;
+                       memcpy(&v6->v6_netmask, &sa6->sin6_addr, sizeof(v6->v6_netmask));
+                       memcpy(&unicast->v6_netmask, &sa6->sin6_addr, sizeof(unicast->v6_netmask));
 
                        v6->peer = unicast;
                        unicast->peer = v6;
@@ -575,4 +614,26 @@ int interface_add(const char *name)
        return !v4 && !v6;
 }
 
+void interface_shutdown(void)
+{
+       struct interface *iface;
+
+       vlist_for_each_element(&interfaces, iface, node)
+               if (iface->fd.fd > 0 && iface->multicast) {
+                       service_announce(iface, 0);
+                       dns_reply_a(iface, 0);
+               }
+       vlist_for_each_element(&interfaces, iface, node)
+               interface_close(iface);
+}
+
+struct interface*
+interface_get(const char *name, int v6, int multicast)
+{
+       char id_buf[32];
+       snprintf(id_buf, sizeof(id_buf), "%d_%d_%s", multicast, v6, name);
+       struct interface *iface = vlist_find(&interfaces, id_buf, iface, node);
+       return iface;
+}
+
 VLIST_TREE(interfaces, avl_strcmp, iface_update_cb, false, false);