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