diff options
| -rw-r--r-- | avahi-core/iface.c | 116 | ||||
| -rw-r--r-- | avahi-core/iface.h | 2 | ||||
| -rw-r--r-- | avahi-core/socket.c | 23 | ||||
| -rw-r--r-- | avahi-core/socket.h | 9 | 
4 files changed, 108 insertions, 42 deletions
diff --git a/avahi-core/iface.c b/avahi-core/iface.c index 6a92b8e..6fc66d3 100644 --- a/avahi-core/iface.c +++ b/avahi-core/iface.c @@ -172,6 +172,88 @@ void avahi_interface_monitor_update_rrs(AvahiInterfaceMonitor *m, int remove_rrs          avahi_hw_interface_update_rrs(hw, remove_rrs);  } +static int interface_mdns_mcast_join(AvahiInterface *i, int join) { +    char at[AVAHI_ADDRESS_STR_MAX]; +    assert(i); + +    assert((join && !i->mcast_joined) || (!join && i->mcast_joined)); +     +    if (join) { +        AvahiInterfaceAddress *a; + +        /* Look if there's an address with global scope */ +        for (a = i->addresses; a; a = a->address_next) +            if (a->global_scope) +                break; + +        /* No address with a global scope has been found, so let's use +         * any. */ +        if (!a) +            a = i->addresses; + +        /* Hmm, there is no address available. */ +        if (!a) { +            avahi_log_warn(__FILE__": interface_mdns_mcast_join() called but no local address available.");  +            return -1; +        } + +        i->local_mcast_address = a->address; +    } + +    avahi_log_info("%s mDNS multicast group on interface %s.%s with address %s", +                   join ? "Joining" : "Leaving", +                   i->hardware->name, +                   avahi_proto_to_string(i->protocol), +                   avahi_address_snprint(at, sizeof(at), &i->local_mcast_address)); + +    if (i->protocol == AVAHI_PROTO_INET6) { +        if (avahi_mdns_mcast_join_ipv6(i->monitor->server->fd_ipv6, &i->local_mcast_address.data.ipv6, i->hardware->index, join) < 0) +            return -1; +         +    } else { +        assert(i->protocol == AVAHI_PROTO_INET); +             +        if (avahi_mdns_mcast_join_ipv4(i->monitor->server->fd_ipv4, &i->local_mcast_address.data.ipv4, i->hardware->index, join) < 0) +            return -1; +    } + +    i->mcast_joined = join; +    return 0; +} + +static int interface_mdns_mcast_rejoin(AvahiInterface *i) { +    AvahiInterfaceAddress *a, *usable = NULL, *found = NULL; +    assert(i); + +    if (!i->mcast_joined) +        return 0; + +    /* Check whether old address we joined with is still available. If +     * not, rejoin using an other address. */ +     +    for (a = i->addresses; a; a = a->address_next) { +        if (a->global_scope && !usable) +            usable = a; +         +        if (avahi_address_cmp(&a->address, &i->local_mcast_address) == 0) { + +            if (a->global_scope) +                /* No action necessary: the address still exists and +                 * has global scope. */ +                return 0; + +            found = a; +        } +    } + +    if (found && !usable) +        /* No action necessary: the address still exists and no better one has been found */ +        return 0; +     +    interface_mdns_mcast_join(i, 0); +    return interface_mdns_mcast_join(i, 1); +} +  void avahi_interface_address_free(AvahiInterfaceAddress *a) {      assert(a);      assert(a->interface); @@ -181,6 +263,8 @@ void avahi_interface_address_free(AvahiInterfaceAddress *a) {      if (a->entry_group)          avahi_s_entry_group_free(a->entry_group); + +    interface_mdns_mcast_rejoin(a->interface);      avahi_free(a);  } @@ -193,6 +277,9 @@ void avahi_interface_free(AvahiInterface *i, int send_goodbye) {      avahi_response_scheduler_force(i->response_scheduler);      assert(!i->announcers); +    if (i->mcast_joined) +        interface_mdns_mcast_join(i, 0); +          /* Remove queriers */      avahi_querier_free_all(i);      avahi_hashmap_free(i->queriers_by_key); @@ -246,6 +333,7 @@ AvahiInterface* avahi_interface_new(AvahiInterfaceMonitor *m, AvahiHwInterface *      i->hardware = hw;      i->protocol = protocol;      i->announcing = 0; +    i->mcast_joined = 0;      AVAHI_LLIST_HEAD_INIT(AvahiInterfaceAddress, i->addresses);      AVAHI_LLIST_HEAD_INIT(AvahiAnnouncer, i->announcers); @@ -333,30 +421,6 @@ AvahiInterfaceAddress *avahi_interface_address_new(AvahiInterfaceMonitor *m, Ava      return a;  } -static int interface_mdns_mcast_join(AvahiInterface *i, int join) { - -    if (i->protocol == AVAHI_PROTO_INET6) -        return avahi_mdns_mcast_join_ipv6(i->monitor->server->fd_ipv6, i->hardware->index, join); -    else if (i->protocol == AVAHI_PROTO_INET) { - -#ifdef HAVE_STRUCT_IP_MREQN -        return avahi_mdns_mcast_join_ipv4(i->monitor->server->fd_ipv4, i->hardware->index, join); - -#else -        AvahiInterfaceAddress *ia; -        int r = 0; - -        for (ia = i->addresses; ia; ia = ia->address_next) -            r  |= avahi_mdns_mcast_join_ipv4(i->monitor->server->fd_ipv4, &ia->address, join); - -        return r; -#endif -    } - -    abort(); -} - -  void avahi_interface_check_relevant(AvahiInterface *i) {      int b;      AvahiInterfaceMonitor *m; @@ -388,7 +452,9 @@ void avahi_interface_check_relevant(AvahiInterface *i) {          avahi_cache_flush(i->cache);          i->announcing = 0; -    } +         +    } else +        interface_mdns_mcast_rejoin(i);  }  void avahi_hw_interface_check_relevant(AvahiHwInterface *hw) { diff --git a/avahi-core/iface.h b/avahi-core/iface.h index 24da316..e7c2298 100644 --- a/avahi-core/iface.h +++ b/avahi-core/iface.h @@ -99,6 +99,8 @@ struct AvahiInterface {      AvahiProtocol protocol;      int announcing; +    AvahiAddress local_mcast_address; +    int mcast_joined;      AvahiCache *cache; diff --git a/avahi-core/socket.c b/avahi-core/socket.c index c03cc34..728bea5 100644 --- a/avahi-core/socket.c +++ b/avahi-core/socket.c @@ -102,25 +102,25 @@ static void ipv6_address_to_sockaddr(struct sockaddr_in6 *ret_sa, const AvahiIPv      memcpy(&ret_sa->sin6_addr, a, sizeof(AvahiIPv6Address));  } +int avahi_mdns_mcast_join_ipv4(int fd, const AvahiIPv4Address *a, int idx, int join) {  #ifdef HAVE_STRUCT_IP_MREQN -int avahi_mdns_mcast_join_ipv4(int fd, int idx, int join) {      struct ip_mreqn mreq;  #else -int avahi_mdns_mcast_join_ipv4(int fd, const AvahiAddress *a, int join) {      struct ip_mreq mreq;  #endif -              struct sockaddr_in sa; -    memset(&mreq, 0, sizeof(mreq)); +    assert(fd >= 0); +    assert(idx >= 0); +    assert(a); + +    memset(&mreq, 0, sizeof(mreq));  #ifdef HAVE_STRUCT_IP_MREQN      mreq.imr_ifindex = idx; +    mreq.imr_address.s_addr = a->address;  #else -    assert(a); -    assert(a->proto == AVAHI_PROTO_INET); -    mreq.imr_interface.s_addr = a->data.ipv4.address; +    mreq.imr_interface.s_addr = a->address;  #endif -          mdns_mcast_group_ipv4(&sa);      mreq.imr_multiaddr = sa.sin_addr; @@ -132,13 +132,16 @@ int avahi_mdns_mcast_join_ipv4(int fd, const AvahiAddress *a, int join) {      return 0;  } -int avahi_mdns_mcast_join_ipv6(int fd, int idx, int join) { +int avahi_mdns_mcast_join_ipv6(int fd, const AvahiIPv6Address *a, int idx, int join) {      struct ipv6_mreq mreq6;       struct sockaddr_in6 sa6; -    mdns_mcast_group_ipv6 (&sa6); +    assert(fd >= 0); +    assert(idx >= 0); +    assert(a);      memset(&mreq6, 0, sizeof(mreq6)); +    mdns_mcast_group_ipv6 (&sa6);      mreq6.ipv6mr_multiaddr = sa6.sin6_addr;      mreq6.ipv6mr_interface = idx; diff --git a/avahi-core/socket.h b/avahi-core/socket.h index 02990b7..57f9153 100644 --- a/avahi-core/socket.h +++ b/avahi-core/socket.h @@ -44,12 +44,7 @@ int avahi_send_dns_packet_ipv6(int fd, int iface, AvahiDnsPacket *p, const Avahi  AvahiDnsPacket *avahi_recv_dns_packet_ipv4(int fd, struct sockaddr_in*ret_sa, AvahiIPv4Address *ret_dest_address, int *ret_iface, uint8_t *ret_ttl);  AvahiDnsPacket *avahi_recv_dns_packet_ipv6(int fd, struct sockaddr_in6*ret_sa, AvahiIPv6Address *ret_dest_address, int *ret_iface, uint8_t *ret_ttl); -#ifdef HAVE_STRUCT_IP_MREQN -int avahi_mdns_mcast_join_ipv4(int fd, int idx, int join); -#else -int avahi_mdns_mcast_join_ipv4(int fd, const AvahiAddress *a, int join); -#endif - -int avahi_mdns_mcast_join_ipv6(int fd, int idx, int join); +int avahi_mdns_mcast_join_ipv4(int fd, const AvahiIPv4Address *a, int iface, int join); +int avahi_mdns_mcast_join_ipv6(int fd, const AvahiIPv6Address *a, int iface, int join);  #endif  | 
