]> git.meshlink.io Git - catta/commitdiff
* Import fixes to multicast code to IP_ADD_MEMBERSHIP per interface,
authorTrent Lloyd <lathiat@bur.st>
Mon, 25 Apr 2005 18:48:57 +0000 (18:48 +0000)
committerTrent Lloyd <lathiat@bur.st>
Mon, 25 Apr 2005 18:48:57 +0000 (18:48 +0000)
rather than a 'global' one, which didn't really work.

-- Trent Lloyd  <lathiat@bur.st>

git-svn-id: file:///home/lennart/svn/public/avahi/trunk@31 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

iface.c
socket.c
socket.h

diff --git a/iface.c b/iface.c
index 0afdb7094e3c83c7be94a8cfdf6c2d4f1e552262..c1dec19acc3a75c9c596169fee6f786f59eb8aad 100644 (file)
--- a/iface.c
+++ b/iface.c
@@ -155,6 +155,7 @@ static void new_interface(flxInterfaceMonitor *m, flxHwInterface *hw, guchar pro
 
 static void check_interface_relevant(flxInterfaceMonitor *m, flxInterface *i) {
     gboolean b;
+
     g_assert(m);
     g_assert(i);
 
@@ -163,13 +164,24 @@ static void check_interface_relevant(flxInterfaceMonitor *m, flxInterface *i) {
     if (b && !i->announcing) {
         g_message("New relevant interface %s.%i", i->hardware->name, i->protocol);
 
+        if (i->protocol == AF_INET)
+            flx_mdns_mcast_join_ipv4 (i->hardware->index, m->server->fd_ipv4);
+        if (i->protocol == AF_INET6)
+            flx_mdns_mcast_join_ipv6 (i->hardware->index, m->server->fd_ipv6);
+
         i->announcing = TRUE;
         flx_announce_interface(m->server, i);
     } else if (!b && i->announcing) {
         g_message("Interface %s.%i no longer relevant", i->hardware->name, i->protocol);
 
-        i->announcing = FALSE;
         flx_goodbye_interface(m->server, i, FALSE);
+
+        if (i->protocol == AF_INET)
+            flx_mdns_mcast_leave_ipv4 (i->hardware->index, m->server->fd_ipv4);
+        if (i->protocol == AF_INET6)
+            flx_mdns_mcast_leave_ipv6 (i->hardware->index, m->server->fd_ipv6);
+
+        i->announcing = FALSE;
     }
 }
 
index 54433d6e026042fd54cbf3561dacc73c1913cb43..e6cf40f4e5b909f7da94145b4608bc25dd49ba13 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -26,12 +26,97 @@ static void mdns_mcast_group_ipv4(struct sockaddr_in *ret_sa) {
     inet_pton(AF_INET, "224.0.0.251", &ret_sa->sin_addr);
 }
 
+static void mdns_mcast_group_ipv6(struct sockaddr_in6 *ret_sa) {
+
+    g_assert(ret_sa);
+
+    memset(ret_sa, 0, sizeof(struct sockaddr_in6));
+    
+    ret_sa->sin6_family = AF_INET6;
+    ret_sa->sin6_port = htons(MDNS_PORT);
+    inet_pton(AF_INET6, "ff02::fb", &ret_sa->sin6_addr);
+}
+
+int flx_mdns_mcast_join_ipv4 (int index, int fd)
+{
+    struct ip_mreqn mreq; 
+    struct sockaddr_in sa;
+
+    mdns_mcast_group_ipv4 (&sa);
+    memset(&mreq, 0, sizeof(mreq));
+    mreq.imr_multiaddr = sa.sin_addr;
+    mreq.imr_ifindex = index;
+    if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
+        g_warning("IP_ADD_MEMBERSHIP failed: %s\n", strerror(errno));
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int flx_mdns_mcast_join_ipv6 (int index, int fd)
+{
+    struct ipv6_mreq mreq6; 
+    struct sockaddr_in6 sa6;
+
+
+    mdns_mcast_group_ipv6 (&sa6);
+
+    memset(&mreq6, 0, sizeof(mreq6));
+    mreq6.ipv6mr_multiaddr = sa6.sin6_addr;
+    mreq6.ipv6mr_interface = index;
+
+    if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
+        g_warning("IPV6_ADD_MEMBERSHIP failed: %s\n", strerror(errno));
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int flx_mdns_mcast_leave_ipv4 (int index, int fd)
+{
+    struct ip_mreqn mreq; 
+    struct sockaddr_in sa;
+    
+    mdns_mcast_group_ipv4 (&sa);
+    memset(&mreq, 0, sizeof(mreq));
+    mreq.imr_multiaddr = sa.sin_addr;
+    mreq.imr_ifindex = index;
+    if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
+        g_warning("IP_DROP_MEMBERSHIP failed: %s\n", strerror(errno));
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int flx_mdns_mcast_leave_ipv6 (int index, int fd)
+{
+    struct ipv6_mreq mreq6; 
+    struct sockaddr_in6 sa6;
+
+    mdns_mcast_group_ipv6 (&sa6);
+
+    memset(&mreq6, 0, sizeof(mreq6));
+    mreq6.ipv6mr_multiaddr = sa6.sin6_addr;
+    mreq6.ipv6mr_interface = index;
+
+    if (setsockopt(fd, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
+        g_warning("IPV6_DROP_MEMBERSHIP failed: %s\n", strerror(errno));
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
 gint flx_open_socket_ipv4(void) {
-    struct ip_mreqn mreq;
     struct sockaddr_in sa, local;
     int fd = -1, ttl, yes;
-
-    mdns_mcast_group_ipv4(&sa);
         
     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         g_warning("socket() failed: %s\n", strerror(errno));
@@ -72,16 +157,6 @@ gint flx_open_socket_ipv4(void) {
         goto fail;
     }
 
-    memset(&mreq, 0, sizeof(mreq));
-    mreq.imr_multiaddr = sa.sin_addr;
-    mreq.imr_address.s_addr = htonl(INADDR_ANY);
-    mreq.imr_ifindex = 0;
-    
-    if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
-        g_warning("IP_ADD_MEMBERSHIP failed: %s\n", strerror(errno));
-        goto fail;
-    }
-
     yes = 1;
     if (setsockopt(fd, SOL_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) {
         g_warning("IP_RECVTTL failed: %s\n", strerror(errno));
@@ -113,19 +188,7 @@ fail:
     return -1;
 }
 
-static void mdns_mcast_group_ipv6(struct sockaddr_in6 *ret_sa) {
-    g_assert(ret_sa);
-
-    memset(ret_sa, 0, sizeof(struct sockaddr_in6));
-    
-    ret_sa->sin6_family = AF_INET6;
-    ret_sa->sin6_port = htons(MDNS_PORT);
-    inet_pton(AF_INET6, "ff02::fb", &ret_sa->sin6_addr);
-}
-
-
 gint flx_open_socket_ipv6(void) {
-    struct ipv6_mreq mreq;
     struct sockaddr_in6 sa, local;
     int fd = -1, ttl, yes;
 
@@ -175,15 +238,6 @@ gint flx_open_socket_ipv6(void) {
         goto fail;
     }
 
-    memset(&mreq, 0, sizeof(mreq));
-    mreq.ipv6mr_multiaddr = sa.sin6_addr;
-    mreq.ipv6mr_interface = 0;
-    
-    if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
-        g_warning("IPV6_ADD_MEMBERSHIP failed: %s\n", strerror(errno));
-        goto fail;
-    }
-
     yes = 1;
     if (setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) {
         g_warning("IPV6_HOPLIMIT failed: %s\n", strerror(errno));
index eb7013a07152c7981d34c2e5191088a2d7c979c0..61d17a532f966ac22aa2bfcef980637aaade72a8 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -14,4 +14,10 @@ gint flx_send_dns_packet_ipv6(gint fd, gint iface, flxDnsPacket *p);
 flxDnsPacket *flx_recv_dns_packet_ipv4(gint fd, struct sockaddr_in*ret_sa, gint *ret_iface, guint8 *ret_ttl);
 flxDnsPacket *flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6*ret_sa, gint *ret_iface, guint8 *ret_ttl);
 
+int flx_mdns_mcast_join_ipv4(int index, int fd);
+int flx_mdns_mcast_join_ipv6(int index, int fd);
+
+int flx_mdns_mcast_leave_ipv4(int index, int fd);
+int flx_mdns_mcast_leave_ipv6(int index, int fd);
+
 #endif