43ff24c
From f49887cbe75da56dc8555d56c66daad78400b2b3 Mon Sep 17 00:00:00 2001
43ff24c
From: Tom Gundersen <teg@jklm.no>
43ff24c
Date: Thu, 3 Jul 2014 22:47:51 +0200
43ff24c
Subject: [PATCH] networkd: properly track addresses when first added
43ff24c
43ff24c
When doing a NEWADDR, the reply we get back is the NEWADDR itself, rather
43ff24c
than just an empty ack (unlike how NEWLINK works). For this reason, the
43ff24c
process that did the NEWADDR does not get the broadcast message.
43ff24c
43ff24c
We were only listening for broadcast messages, and hence not tracking the
43ff24c
addresses we added ourselves. This went unnoticed as the kernel will usually
43ff24c
send NEWADDR messages from time to time anyway, so things would mostly work,
43ff24c
but in the worst case we would not notice that a routable address was available
43ff24c
and consider ourselves offline.
43ff24c
43ff24c
(cherry picked from commit 4958aee4977f325be19f0e1e4b424922c3cada5f)
43ff24c
---
43ff24c
 src/network/networkd-link.c | 54 +++++++++++++++++++++++++--------------------
43ff24c
 1 file changed, 30 insertions(+), 24 deletions(-)
43ff24c
43ff24c
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
43ff24c
index 961c1ab8ad..6257372ffd 100644
43ff24c
--- a/src/network/networkd-link.c
43ff24c
+++ b/src/network/networkd-link.c
43ff24c
@@ -599,10 +599,35 @@ static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata)
43ff24c
         return 0;
43ff24c
 }
43ff24c
 
43ff24c
+static int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
43ff24c
+        _cleanup_link_unref_ Link *link = userdata;
43ff24c
+        int r;
43ff24c
+
43ff24c
+        assert(rtnl);
43ff24c
+        assert(m);
43ff24c
+        assert(link);
43ff24c
+        assert(link->manager);
43ff24c
+
43ff24c
+        for (; m; m = sd_rtnl_message_next(m)) {
43ff24c
+                r = sd_rtnl_message_get_errno(m);
43ff24c
+                if (r < 0) {
43ff24c
+                        log_debug_link(link, "getting address failed: %s", strerror(-r));
43ff24c
+                        continue;
43ff24c
+                }
43ff24c
+
43ff24c
+                r = link_rtnl_process_address(rtnl, m, link->manager);
43ff24c
+                if (r < 0)
43ff24c
+                        log_warning_link(link, "could not process address: %s", strerror(-r));
43ff24c
+        }
43ff24c
+
43ff24c
+        return 1;
43ff24c
+}
43ff24c
+
43ff24c
 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
43ff24c
         _cleanup_link_unref_ Link *link = userdata;
43ff24c
         int r;
43ff24c
 
43ff24c
+        assert(rtnl);
43ff24c
         assert(m);
43ff24c
         assert(link);
43ff24c
         assert(link->ifname);
43ff24c
@@ -623,6 +648,11 @@ static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
43ff24c
                                 link->ifname, strerror(-r),
43ff24c
                                 "ERRNO=%d", -r,
43ff24c
                                 NULL);
43ff24c
+        if (r >= 0) {
43ff24c
+                /* calling handler directly so take a ref */
43ff24c
+                link_ref(link);
43ff24c
+                link_get_address_handler(rtnl, m, link);
43ff24c
+        }
43ff24c
 
43ff24c
         if (link->addr_messages == 0) {
43ff24c
                 log_debug_link(link, "addresses set");
43ff24c
@@ -2233,30 +2263,6 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use
43ff24c
         return 1;
43ff24c
 }
43ff24c
 
43ff24c
-static int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
43ff24c
-        _cleanup_link_unref_ Link *link = userdata;
43ff24c
-        int r;
43ff24c
-
43ff24c
-        assert(rtnl);
43ff24c
-        assert(m);
43ff24c
-        assert(link);
43ff24c
-        assert(link->manager);
43ff24c
-
43ff24c
-        for (; m; m = sd_rtnl_message_next(m)) {
43ff24c
-                r = sd_rtnl_message_get_errno(m);
43ff24c
-                if (r < 0) {
43ff24c
-                        log_debug_link(link, "getting address failed: %s", strerror(-r));
43ff24c
-                        continue;
43ff24c
-                }
43ff24c
-
43ff24c
-                r = link_rtnl_process_address(rtnl, m, link->manager);
43ff24c
-                if (r < 0)
43ff24c
-                        log_warning_link(link, "could not process address: %s", strerror(-r));
43ff24c
-        }
43ff24c
-
43ff24c
-        return 1;
43ff24c
-}
43ff24c
-
43ff24c
 int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
43ff24c
         Link *link;
43ff24c
         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;