summaryrefslogtreecommitdiff
path: root/src/network/networkd-address.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-address.c')
-rw-r--r--src/network/networkd-address.c117
1 files changed, 83 insertions, 34 deletions
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 7f9a7268cc..367c340e08 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -27,6 +27,7 @@
#include "networkd.h"
#include "parse-util.h"
#include "set.h"
+#include "socket-util.h"
#include "string-util.h"
#include "utf8.h"
#include "util.h"
@@ -67,16 +68,15 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
if (r < 0)
return r;
- address->network = network;
-
- LIST_APPEND(addresses, network->static_addresses, address);
-
if (section) {
address->section = section;
hashmap_put(network->addresses_by_section,
UINT_TO_PTR(address->section), address);
}
+ address->network = network;
+ LIST_APPEND(addresses, network->static_addresses, address);
+
*ret = address;
address = NULL;
@@ -98,6 +98,9 @@ void address_free(Address *address) {
if (address->link) {
set_remove(address->link->addresses, address);
set_remove(address->link->addresses_foreign, address);
+
+ if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address))
+ memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr));
}
free(address);
@@ -331,6 +334,10 @@ int address_update(Address *address, unsigned char flags, unsigned char scope, s
assert(address);
assert(cinfo);
+ assert_return(address->link, 1);
+
+ if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
ready = address_is_ready(address);
@@ -338,19 +345,18 @@ int address_update(Address *address, unsigned char flags, unsigned char scope, s
address->scope = scope;
address->cinfo = *cinfo;
- if (address->link) {
- link_update_operstate(address->link);
-
- if (!ready && address_is_ready(address)) {
- link_check_ready(address->link);
-
- if (address->family == AF_INET6 &&
- in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
- in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
- r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
- if (r < 0)
- return r;
- }
+ link_update_operstate(address->link);
+
+ if (!ready && address_is_ready(address)) {
+ link_check_ready(address->link);
+
+ if (address->family == AF_INET6 &&
+ in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
+ in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
+
+ r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
+ if (r < 0)
+ return r;
}
}
@@ -404,8 +410,11 @@ int address_get(Link *link, int family, const union in_addr_union *in_addr, unsi
return 0;
}
-int address_remove(Address *address, Link *link,
- sd_netlink_message_handler_t callback) {
+int address_remove(
+ Address *address,
+ Link *link,
+ sd_netlink_message_handler_t callback) {
+
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
@@ -727,7 +736,8 @@ int config_parse_address(const char *unit,
return 0;
}
-int config_parse_label(const char *unit,
+int config_parse_label(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -737,9 +747,9 @@ int config_parse_label(const char *unit,
const char *rvalue,
void *data,
void *userdata) {
- Network *network = userdata;
+
_cleanup_address_free_ Address *n = NULL;
- char *label;
+ Network *network = userdata;
int r;
assert(filename);
@@ -752,25 +762,64 @@ int config_parse_label(const char *unit,
if (r < 0)
return r;
- label = strdup(rvalue);
- if (!label)
+ if (!ifname_valid(rvalue)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Interface label is not valid or too long, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ r = free_and_strdup(&n->label, rvalue);
+ if (r < 0)
return log_oom();
- if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Interface label is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
- free(label);
+ n = NULL;
+
+ return 0;
+}
+
+int config_parse_lifetime(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Network *network = userdata;
+ _cleanup_address_free_ Address *n = NULL;
+ unsigned k;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = address_new_static(network, section_line, &n);
+ if (r < 0)
+ return r;
+
+ if (STR_IN_SET(rvalue, "forever", "infinity")) {
+ n->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME;
+ n = NULL;
+
return 0;
}
- free(n->label);
- if (*label)
- n->label = label;
- else {
- free(label);
- n->label = NULL;
+ r = safe_atou(rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse PreferredLifetime, ignoring: %s", rvalue);
+ return 0;
}
- n = NULL;
+ if (k != 0)
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid PreferredLifetime value, ignoring: %d", k);
+ else {
+ n->cinfo.ifa_prefered = k;
+ n = NULL;
+ }
return 0;
}