diff options
author | Umut Tezduyar Lindskog <umut.tezduyar@axis.com> | 2014-04-02 21:31:12 +0200 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2014-04-03 16:00:25 +0200 |
commit | aba496a58acf9d9c61314de71353550e579f85ee (patch) | |
tree | e554123004bba327c3114539142047d4c124f40a /src/network/networkd-address.c | |
parent | 3e790eae01ce74f94a5233adeab12c64508916e0 (diff) |
networkd: smooth transition from ipv4ll to dhcp address
Currently when both ipv4ll and dhcp are enabled, ipv4ll
address (if one has been claimed) is removed when dhcp
address is aquired. This is not the best thing to do
since there might be clients unaware of the removal
trying to communicate.
This patch provides a smooth transition between ipv4ll
and dhcp. If ipv4ll address was claimed [1] before dhcp,
address is marked as deprecated. Deprecated address is still
a valid address and packets can be received on it but address
cannot be selected as a source address. If dhcp lease cannot
be extended, then ipv4ll address is marked as valid again.
[1] If there is no collision, claiming IPv4LL takes between 4 to
7 seconds.
Diffstat (limited to 'src/network/networkd-address.c')
-rw-r--r-- | src/network/networkd-address.c | 96 |
1 files changed, 92 insertions, 4 deletions
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index dd4c822c67..87688a5ae6 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -28,6 +28,15 @@ #include "conf-parser.h" #include "network-internal.h" +static void address_init(Address *address) { + assert(address); + + address->family = AF_UNSPEC; + address->scope = RT_SCOPE_UNIVERSE; + address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME; + address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME; +} + int address_new_static(Network *network, unsigned section, Address **ret) { _cleanup_address_free_ Address *address = NULL; @@ -46,8 +55,7 @@ int address_new_static(Network *network, unsigned section, Address **ret) { if (!address) return -ENOMEM; - address->family = AF_UNSPEC; - address->scope = RT_SCOPE_UNIVERSE; + address_init(address); address->network = network; @@ -71,8 +79,7 @@ int address_new_dynamic(Address **ret) { if (!address) return -ENOMEM; - address->family = AF_UNSPEC; - address->scope = RT_SCOPE_UNIVERSE; + address_init(address); *ret = address; address = NULL; @@ -140,6 +147,87 @@ int address_drop(Address *address, Link *link, return 0; } +int address_update(Address *address, Link *link, + sd_rtnl_message_handler_t callback) { + _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL; + int r; + + assert(address); + assert(address->family == AF_INET || address->family == AF_INET6); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req, + link->ifindex, address->family); + if (r < 0) { + log_error("Could not allocate RTM_NEWADDR message: %s", + strerror(-r)); + return r; + } + + r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); + if (r < 0) { + log_error("Could not set prefixlen: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT); + if (r < 0) { + log_error("Could not set flags: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_addr_set_scope(req, address->scope); + if (r < 0) { + log_error("Could not set scope: %s", strerror(-r)); + return r; + } + + if (address->family == AF_INET) + r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in); + else if (address->family == AF_INET6) + r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6); + if (r < 0) { + log_error("Could not append IFA_LOCAL attribute: %s", + strerror(-r)); + return r; + } + + if (address->family == AF_INET) { + r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); + if (r < 0) { + log_error("Could not append IFA_BROADCAST attribute: %s", + strerror(-r)); + return r; + } + } + + if (address->label) { + r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label); + if (r < 0) { + log_error("Could not append IFA_LABEL attribute: %s", + strerror(-r)); + return r; + } + } + + r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo); + if (r < 0) { + log_error("Could not append IFA_CACHEINFO attribute: %s", + strerror(-r)); + return r; + } + + r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL); + if (r < 0) { + log_error("Could not send rtnetlink message: %s", strerror(-r)); + return r; + } + + return 0; +} + int address_configure(Address *address, Link *link, sd_rtnl_message_handler_t callback) { _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL; |