]> git.meshlink.io Git - catta/blobdiff - avahi-core/iface-linux.c
forgot to pull the publish_no_reverse change to the example.
[catta] / avahi-core / iface-linux.c
index bc871524cb4d93971202610b21a70e51f6d995d3..da497bc4dcbadb4816d5dc301acb25d3fd55e135 100644 (file)
@@ -1,18 +1,16 @@
-/* $Id$ */
-
 /***
   This file is part of avahi.
+
   avahi is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as
   published by the Free Software Foundation; either version 2.1 of the
   License, or (at your option) any later version.
+
   avahi 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 Lesser General
   Public License for more details.
+
   You should have received a copy of the GNU Lesser General Public
   License along with avahi; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 #include "iface.h"
 #include "iface-linux.h"
 
+#ifndef IFLA_RTA
+#include <linux/if_addr.h>
+#define IFLA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
+#endif
+
+#ifndef IFA_RTA
+#include <linux/if_addr.h>
+#define IFA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#endif
+
 static int netlink_list_items(AvahiNetlink *nl, uint16_t type, unsigned *ret_seq) {
     struct nlmsghdr *n;
     struct rtgenmsg *gen;
     uint8_t req[1024];
 
     /* Issue a wild dump NETLINK request */
-    
+
     memset(&req, 0, sizeof(req));
     n = (struct nlmsghdr*) req;
     n->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
     n->nlmsg_type = type;
-    n->nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST;
+    n->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
     n->nlmsg_pid = 0;
 
     gen = NLMSG_DATA(n);
@@ -59,7 +67,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
     AvahiInterfaceMonitor *m = userdata;
 
     /* This routine is called for every RTNETLINK response packet */
-    
+
     assert(m);
     assert(n);
     assert(m->osdep.netlink == nl);
@@ -67,7 +75,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
     if (n->nlmsg_type == RTM_NEWLINK) {
 
         /* A new interface appeared or an existing one has been modified */
-        
+
         struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
         AvahiHwInterface *hw;
         struct rtattr *a = NULL;
@@ -83,7 +91,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
          * interface appears, but when it changes, too */
 
         if (!(hw = avahi_interface_monitor_get_hw_interface(m, ifinfomsg->ifi_index)))
-            
+
             /* No object found, so let's create a new
              * one. avahi_hw_interface_new() will call
              * avahi_interface_new() internally twice for IPv4 and
@@ -98,7 +106,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
             (!m->server->config.use_iff_running || (ifinfomsg->ifi_flags & IFF_RUNNING)) &&
             !(ifinfomsg->ifi_flags & IFF_LOOPBACK) &&
             (ifinfomsg->ifi_flags & IFF_MULTICAST) &&
-            !(ifinfomsg->ifi_flags & IFF_POINTOPOINT);
+            (m->server->config.allow_point_to_point || !(ifinfomsg->ifi_flags & IFF_POINTOPOINT));
 
         /* Handle interface attributes */
         l = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg));
@@ -124,12 +132,12 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
 
                     /* Fill in hardware (MAC) address */
                     hw->mac_address_size = RTA_PAYLOAD(a);
-                    if (hw->mac_address_size > AVAHI_MAX_MAC_ADDRESS)
-                        hw->mac_address_size = AVAHI_MAX_MAC_ADDRESS;
-                    
+                    if (hw->mac_address_size > AVAHI_MAC_ADDRESS_MAX)
+                        hw->mac_address_size = AVAHI_MAC_ADDRESS_MAX;
+
                     memcpy(hw->mac_address, RTA_DATA(a), hw->mac_address_size);
                     break;
-                    
+
                 default:
                     ;
             }
@@ -146,7 +154,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
         /* Update any associated RRs of this interface. (i.e. the
          * _workstation._tcp record containing the MAC address) */
         avahi_hw_interface_update_rrs(hw, 0);
-        
+
     } else if (n->nlmsg_type == RTM_DELLINK) {
 
         /* An interface has been removed */
@@ -164,17 +172,17 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
 
         /* Free our object */
         avahi_hw_interface_free(hw, 0);
-        
+
     } else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
 
         /* An address has been added, modified or removed */
-        
+
         struct ifaddrmsg *ifaddrmsg = NLMSG_DATA(n);
         AvahiInterface *i;
         struct rtattr *a = NULL;
         size_t l;
-        AvahiAddress raddr;
-        int raddr_valid = 0;
+        AvahiAddress raddr, rlocal, *r;
+        int raddr_valid = 0, rlocal_valid = 0;
 
         /* We are only interested in IPv4 and IPv6 */
         if (ifaddrmsg->ifa_family != AF_INET && ifaddrmsg->ifa_family != AF_INET6)
@@ -187,7 +195,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
             return;
 
         /* Fill in address family for our new address */
-        raddr.proto = avahi_af_to_proto(ifaddrmsg->ifa_family);
+        rlocal.proto = raddr.proto = avahi_af_to_proto(ifaddrmsg->ifa_family);
 
         l = NLMSG_PAYLOAD(n, sizeof(struct ifaddrmsg));
         a = IFA_RTA(ifaddrmsg);
@@ -195,9 +203,26 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
         while (RTA_OK(a, l)) {
 
             switch(a->rta_type) {
+
                 case IFA_ADDRESS:
-                    /* Fill in address data */
-                    
+
+                    if ((rlocal.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) ||
+                        (rlocal.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4))
+                        return;
+
+                    memcpy(rlocal.data.data, RTA_DATA(a), RTA_PAYLOAD(a));
+                    rlocal_valid = 1;
+
+                    break;
+
+                case IFA_LOCAL:
+
+                    /* Fill in local address data. Usually this is
+                     * preferable over IFA_ADDRESS if both are set,
+                     * since this refers to the local address of a PPP
+                     * link while IFA_ADDRESS refers to the other
+                     * end. */
+
                     if ((raddr.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) ||
                         (raddr.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4))
                         return;
@@ -210,32 +235,37 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
                 default:
                     ;
             }
-            
+
             a = RTA_NEXT(a, l);
         }
 
         /* If there was no adress attached to this message, let's quit. */
-        if (!raddr_valid)
+        if (rlocal_valid)
+            r = &rlocal;
+        else if (raddr_valid)
+            r = &raddr;
+        else
             return;
 
         if (n->nlmsg_type == RTM_NEWADDR) {
             AvahiInterfaceAddress *addr;
 
             /* This address is new or has been modified, so let's get an object for it */
-            if (!(addr = avahi_interface_monitor_get_address(m, i, &raddr)))
+            if (!(addr = avahi_interface_monitor_get_address(m, i, r)))
 
                 /* Mmm, no object existing yet, so let's create a new one */
-                if (!(addr = avahi_interface_address_new(m, i, &raddr, ifaddrmsg->ifa_prefixlen)))
+                if (!(addr = avahi_interface_address_new(m, i, r, ifaddrmsg->ifa_prefixlen)))
                     return; /* OOM */
 
             /* Update the scope field for the address */
             addr->global_scope = ifaddrmsg->ifa_scope == RT_SCOPE_UNIVERSE || ifaddrmsg->ifa_scope == RT_SCOPE_SITE;
+            addr->deprecated = !!(ifaddrmsg->ifa_flags & IFA_F_DEPRECATED);
         } else {
             AvahiInterfaceAddress *addr;
             assert(n->nlmsg_type == RTM_DELADDR);
 
             /* Try to get a reference to our AvahiInterfaceAddress object for this address */
-            if (!(addr = avahi_interface_monitor_get_address(m, i, &raddr)))
+            if (!(addr = avahi_interface_monitor_get_address(m, i, r)))
                 return;
 
             /* And free it */
@@ -250,16 +280,16 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
 
         /* Update any associated RRs, like A or AAAA for our new/removed address */
         avahi_interface_update_rrs(i, 0);
-        
+
     } else if (n->nlmsg_type == NLMSG_DONE) {
 
         /* This wild dump request ended, so let's see what we do next */
-        
+
         if (m->osdep.list == LIST_IFACE) {
 
             /* Mmmm, interfaces have been wild dumped already, so
              * let's go on with wild dumping the addresses */
-            
+
             if (netlink_list_items(m->osdep.netlink, RTM_GETADDR, &m->osdep.query_addr_seq) < 0) {
                 avahi_log_warn("NETLINK: Failed to list addrs: %s", strerror(errno));
                 m->osdep.list = LIST_DONE;
@@ -290,14 +320,14 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
             /* Tell the user that the wild dump is complete */
             avahi_log_info("Network interface enumeration completed.");
         }
-        
+
     } else if (n->nlmsg_type == NLMSG_ERROR &&
                (n->nlmsg_seq == m->osdep.query_link_seq || n->nlmsg_seq == m->osdep.query_addr_seq)) {
         struct nlmsgerr *e = NLMSG_DATA (n);
 
         /* Some kind of error happened. Let's just tell the user and
          * ignore it otherwise */
-        
+
         if (e->error)
             avahi_log_warn("NETLINK: Failed to browse: %s", strerror(-e->error));
     }
@@ -307,7 +337,7 @@ int avahi_interface_monitor_init_osdep(AvahiInterfaceMonitor *m) {
     assert(m);
 
     /* Initialize our own data */
-    
+
     m->osdep.netlink = NULL;
     m->osdep.query_addr_seq = m->osdep.query_link_seq = 0;
 
@@ -351,11 +381,10 @@ void avahi_interface_monitor_sync(AvahiInterfaceMonitor *m) {
 
     /* Let's handle netlink events until we are done with wild
      * dumping */
-    
-    while (m->osdep.list != LIST_DONE) {
+
+    while (!m->list_complete)
         if (!avahi_netlink_work(m->osdep.netlink, 1) == 0)
             break;
-    }
 
     /* At this point Avahi knows about all local interfaces and
      * addresses in existance. */