]> git.meshlink.io Git - catta/blobdiff - avahi-core/iface-linux.c
netlink: fix wrong use of netlink flags for dump operations
[catta] / avahi-core / iface-linux.c
index 4fc4addfd49cf6e37f4e48314a7f891ae6765ee3..4d12f73504193d00332f56debdcdd8581f00bab7 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,11 +172,11 @@ 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;
@@ -197,7 +205,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
             switch(a->rta_type) {
                 case IFA_ADDRESS:
                     /* Fill in address data */
-                    
+
                     if ((raddr.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) ||
                         (raddr.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4))
                         return;
@@ -210,7 +218,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
                 default:
                     ;
             }
-            
+
             a = RTA_NEXT(a, l);
         }
 
@@ -230,6 +238,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat
 
             /* 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);
@@ -250,16 +259,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 +299,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 +316,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,7 +360,7 @@ void avahi_interface_monitor_sync(AvahiInterfaceMonitor *m) {
 
     /* Let's handle netlink events until we are done with wild
      * dumping */
-    
+
     while (!m->list_complete)
         if (!avahi_netlink_work(m->osdep.netlink, 1) == 0)
             break;