summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-02-20 10:03:11 +0100
committerThomas Haller <thaller@redhat.com>2019-02-20 10:03:11 +0100
commit209ff015e26f295bdb7c396962a4e9b4199398fb (patch)
tree27ac1494a14ec88e84ad8bac9833202915fe36c1
parentc3f6356a39caf6bc7b159be81ebaa05b929b62f4 (diff)
parentc2b3b9b95582696c044d3d580e40570b6e96a0df (diff)
downloadNetworkManager-209ff015e26f295bdb7c396962a4e9b4199398fb.tar.gz
dhcp: merge branch 'th/dhcp-internal-mulitple-routers'
https://bugzilla.redhat.com/show_bug.cgi?id=1634657 https://github.com/NetworkManager/NetworkManager/pull/265
-rw-r--r--shared/nm-utils/nm-shared-utils.h6
-rw-r--r--shared/nm-utils/tests/test-shared-general.c14
-rw-r--r--shared/systemd/src/basic/in-addr-util.c8
-rw-r--r--shared/systemd/src/basic/in-addr-util.h2
-rw-r--r--src/dhcp/nm-dhcp-systemd.c141
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-lease-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c36
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h6
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c75
-rw-r--r--src/systemd/src/systemd/sd-dhcp-lease.h2
10 files changed, 178 insertions, 116 deletions
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index 4758c4a083..4d9f20d073 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -140,6 +140,12 @@ nm_ip_addr_set (int addr_family, gpointer dst, gconstpointer src)
: sizeof (struct in6_addr));
}
+static inline gboolean
+nm_ip4_addr_is_localhost (in_addr_t addr4)
+{
+ return (addr4 & htonl (0xFF000000u)) == htonl (0x7F000000u);
+}
+
/*****************************************************************************/
#define NM_CMP_RETURN(c) \
diff --git a/shared/nm-utils/tests/test-shared-general.c b/shared/nm-utils/tests/test-shared-general.c
index 7d22e56d99..b262757879 100644
--- a/shared/nm-utils/tests/test-shared-general.c
+++ b/shared/nm-utils/tests/test-shared-general.c
@@ -204,6 +204,19 @@ test_nm_strndup_a (void)
/*****************************************************************************/
+static void
+test_nm_ip4_addr_is_localhost (void)
+{
+ g_assert ( nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("127.0.0.0")));
+ g_assert ( nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("127.0.0.1")));
+ g_assert ( nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("127.5.0.1")));
+ g_assert (!nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("126.5.0.1")));
+ g_assert (!nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("128.5.0.1")));
+ g_assert (!nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("129.5.0.1")));
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -215,6 +228,7 @@ int main (int argc, char **argv)
g_test_add_func ("/general/test_nm_make_strv", test_make_strv);
g_test_add_func ("/general/test_nm_strdup_int", test_nm_strdup_int);
g_test_add_func ("/general/test_nm_strndup_a", test_nm_strndup_a);
+ g_test_add_func ("/general/test_nm_ip4_addr_is_localhost", test_nm_ip4_addr_is_localhost);
return g_test_run ();
}
diff --git a/shared/systemd/src/basic/in-addr-util.c b/shared/systemd/src/basic/in-addr-util.c
index 62b3147a59..5ced3501ac 100644
--- a/shared/systemd/src/basic/in-addr-util.c
+++ b/shared/systemd/src/basic/in-addr-util.c
@@ -70,6 +70,14 @@ bool in4_addr_is_localhost(const struct in_addr *a) {
return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
}
+bool in4_addr_is_non_local(const struct in_addr *a) {
+ /* Whether the address is not null and not localhost.
+ *
+ * As such, it is suitable to configure as DNS/NTP server from DHCP. */
+ return !in4_addr_is_null(a) &&
+ !in4_addr_is_localhost(a);
+}
+
int in_addr_is_localhost(int family, const union in_addr_union *u) {
assert(u);
diff --git a/shared/systemd/src/basic/in-addr-util.h b/shared/systemd/src/basic/in-addr-util.h
index 3069790519..c21567122c 100644
--- a/shared/systemd/src/basic/in-addr-util.h
+++ b/shared/systemd/src/basic/in-addr-util.h
@@ -30,6 +30,8 @@ int in_addr_is_link_local(int family, const union in_addr_union *u);
bool in4_addr_is_localhost(const struct in_addr *a);
int in_addr_is_localhost(int family, const union in_addr_union *u);
+bool in4_addr_is_non_local(const struct in_addr *a);
+
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c
index ddba34f392..70ed871503 100644
--- a/src/dhcp/nm-dhcp-systemd.c
+++ b/src/dhcp/nm-dhcp-systemd.c
@@ -267,28 +267,35 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
gint64 ts_time = time (NULL);
struct in_addr a_address;
struct in_addr a_netmask;
- struct in_addr a_router;
+ const struct in_addr *a_router;
guint32 a_plen;
guint32 a_lifetime;
g_return_val_if_fail (lease != NULL, NULL);
- ip4_config = nm_ip4_config_new (multi_idx, ifindex);
-
- options = out_options ? create_options_dict () : NULL;
-
if (sd_dhcp_lease_get_address (lease, &a_address) < 0) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get address from lease");
return NULL;
}
- nm_utils_inet4_ntop (a_address.s_addr, addr_str);
- LOG_LEASE (LOGD_DHCP4, "address %s", addr_str);
- add_option (options, dhcp4_requests, DHCP_OPTION_IP_ADDRESS, addr_str);
if (sd_dhcp_lease_get_netmask (lease, &a_netmask) < 0) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get netmask from lease");
return NULL;
}
+
+ if (sd_dhcp_lease_get_lifetime (lease, &a_lifetime) < 0) {
+ nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get lifetime from lease");
+ return NULL;
+ }
+
+ ip4_config = nm_ip4_config_new (multi_idx, ifindex);
+
+ options = out_options ? create_options_dict () : NULL;
+
+ nm_utils_inet4_ntop (a_address.s_addr, addr_str);
+ LOG_LEASE (LOGD_DHCP4, "address %s", addr_str);
+ add_option (options, dhcp4_requests, DHCP_OPTION_IP_ADDRESS, addr_str);
+
a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr);
LOG_LEASE (LOGD_DHCP4, "plen %u", (guint) a_plen);
add_option (options,
@@ -296,10 +303,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
SD_DHCP_OPTION_SUBNET_MASK,
nm_utils_inet4_ntop (a_netmask.s_addr, addr_str));
- if (sd_dhcp_lease_get_lifetime (lease, &a_lifetime) < 0) {
- nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get lifetime from lease");
- return NULL;
- }
LOG_LEASE (LOGD_DHCP4, "expires in %u seconds (at %lld)",
(guint) a_lifetime,
(long long) (ts_time + a_lifetime));
@@ -323,41 +326,44 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
if (num > 0) {
nm_gstring_prepare (&str);
for (i = 0; i < num; i++) {
- if (addr_list[i].s_addr) {
- nm_ip4_config_add_nameserver (ip4_config, addr_list[i].s_addr);
- s = nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str);
- LOG_LEASE (LOGD_DHCP4, "nameserver '%s'", s);
- g_string_append_printf (str, "%s%s", str->len ? " " : "", s);
+ nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str);
+ g_string_append (nm_gstring_add_space_delimiter (str), addr_str);
+
+ if ( addr_list[i].s_addr == 0
+ || nm_ip4_addr_is_localhost (addr_list[i].s_addr)) {
+ /* Skip localhost addresses, like also networkd does.
+ * See https://github.com/systemd/systemd/issues/4524. */
+ continue;
}
+ nm_ip4_config_add_nameserver (ip4_config, addr_list[i].s_addr);
}
- if (str->len)
- add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, str->str);
+ LOG_LEASE (LOGD_DHCP4, "nameserver '%s'", str->str);
+ add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, str->str);
}
num = sd_dhcp_lease_get_search_domains (lease, (char ***) &search_domains);
if (num > 0) {
nm_gstring_prepare (&str);
for (i = 0; i < num; i++) {
+ g_string_append (nm_gstring_add_space_delimiter (str), search_domains[i]);
nm_ip4_config_add_search (ip4_config, search_domains[i]);
- g_string_append_printf (str, "%s%s", str->len ? " " : "", search_domains[i]);
- LOG_LEASE (LOGD_DHCP4, "domain search '%s'", search_domains[i]);
}
+ LOG_LEASE (LOGD_DHCP4, "domain search '%s'", str->str);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST, str->str);
}
- if ( sd_dhcp_lease_get_domainname (lease, &s) >= 0
- && s) {
+ if (sd_dhcp_lease_get_domainname (lease, &s) >= 0) {
gs_strfreev char **domains = NULL;
char **d;
+ LOG_LEASE (LOGD_DHCP4, "domain name '%s'", s);
+ add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME, s);
+
/* Multiple domains sometimes stuffed into option 15 "Domain Name".
* As systemd escapes such characters, split them at \\032. */
domains = g_strsplit (s, "\\032", 0);
- for (d = domains; *d; d++) {
- LOG_LEASE (LOGD_DHCP4, "domain name '%s'", *d);
+ for (d = domains; *d; d++)
nm_ip4_config_add_domain (ip4_config, *d);
- }
- add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME, s);
}
if (sd_dhcp_lease_get_hostname (lease, &s) >= 0) {
@@ -477,45 +483,66 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
add_option (options, dhcp4_requests, SD_DHCP_OPTION_STATIC_ROUTE, str_static->str);
}
- /* FIXME: internal client only supports returning the first router. */
- if (sd_dhcp_lease_get_router (lease, &a_router) >= 0) {
- s = nm_utils_inet4_ntop (a_router.s_addr, addr_str);
- LOG_LEASE (LOGD_DHCP4, "gateway %s", s);
- add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, s);
-
- /* If the DHCP server returns both a Classless Static Routes option and a
- * Router option, the DHCP client MUST ignore the Router option [RFC 3442].
- *
- * Be more lenient and ignore the Router option only if Classless Static
- * Routes contain a default gateway (as other DHCP backends do).
- */
- if (!has_router_from_classless) {
+ num = sd_dhcp_lease_get_router (lease, &a_router);
+ if (num > 0) {
+ guint32 default_route_metric = route_metric;
+
+ nm_gstring_prepare (&str);
+ for (i = 0; i < num; i++) {
+ guint32 m;
+
+ s = nm_utils_inet4_ntop (a_router[i].s_addr, addr_str);
+ g_string_append (nm_gstring_add_space_delimiter (str), s);
+
+ if (a_router[i].s_addr == 0) {
+ /* silently skip 0.0.0.0 */
+ continue;
+ }
+
+ if (has_router_from_classless) {
+ /* If the DHCP server returns both a Classless Static Routes option and a
+ * Router option, the DHCP client MUST ignore the Router option [RFC 3442].
+ *
+ * Be more lenient and ignore the Router option only if Classless Static
+ * Routes contain a default gateway (as other DHCP backends do).
+ */
+ continue;
+ }
+
+ /* if there are multiple default routes, we add them with differing
+ * metrics. */
+ m = default_route_metric;
+ if (default_route_metric < G_MAXUINT32)
+ default_route_metric++;
+
nm_ip4_config_add_route (ip4_config,
&((const NMPlatformIP4Route) {
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = a_router.s_addr,
+ .gateway = a_router[i].s_addr,
.table_coerced = nm_platform_route_table_coerce (route_table),
- .metric = route_metric,
+ .metric = m,
}),
NULL);
}
+ LOG_LEASE (LOGD_DHCP4, "router %s", str->str);
+ add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str->str);
}
if ( sd_dhcp_lease_get_mtu (lease, &mtu) >= 0
&& mtu) {
- nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
- add_option_u64 (options, dhcp4_requests, SD_DHCP_OPTION_INTERFACE_MTU, mtu);
LOG_LEASE (LOGD_DHCP4, "mtu %u", mtu);
+ add_option_u64 (options, dhcp4_requests, SD_DHCP_OPTION_INTERFACE_MTU, mtu);
+ nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
}
num = sd_dhcp_lease_get_ntp (lease, &addr_list);
if (num > 0) {
nm_gstring_prepare (&str);
for (i = 0; i < num; i++) {
- s = nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str);
- LOG_LEASE (LOGD_DHCP4, "ntp server '%s'", s);
- g_string_append_printf (str, "%s%s", str->len ? " " : "", s);
+ nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str);
+ g_string_append (nm_gstring_add_space_delimiter (str), addr_str);
}
+ LOG_LEASE (LOGD_DHCP4, "ntp server '%s'", str->str);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_NTP_SERVER, str->str);
}
@@ -824,6 +851,7 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx,
sd_dhcp6_lease_reset_address_iter (lease);
nm_gstring_prepare (&str);
while (sd_dhcp6_lease_get_address (lease, &tmp_addr, &lft_pref, &lft_valid) >= 0) {
+ char sbuf[400];
const NMPlatformIP6Address address = {
.plen = 128,
.address = tmp_addr,
@@ -836,15 +864,12 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx,
nm_ip6_config_add_address (ip6_config, &address);
nm_utils_inet6_ntop (&tmp_addr, addr_str);
- if (str->len)
- g_string_append_c (str, ' ');
- g_string_append (str, addr_str);
+ g_string_append (nm_gstring_add_space_delimiter (str), addr_str);
LOG_LEASE (LOGD_DHCP6,
"address %s",
- nm_platform_ip6_address_to_string (&address, NULL, 0));
+ nm_platform_ip6_address_to_string (&address, sbuf, sizeof (sbuf)));
};
-
if (str->len)
add_option (options, dhcp6_requests, DHCP6_OPTION_IP_ADDRESS, str->str);
@@ -861,13 +886,11 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx,
if (num > 0) {
nm_gstring_prepare (&str);
for (i = 0; i < num; i++) {
- nm_ip6_config_add_nameserver (ip6_config, &dns[i]);
nm_utils_inet6_ntop (&dns[i], addr_str);
- if (str->len)
- g_string_append_c (str, ' ');
- g_string_append (str, addr_str);
- LOG_LEASE (LOGD_DHCP6, "nameserver %s", addr_str);
+ g_string_append (nm_gstring_add_space_delimiter (str), addr_str);
+ nm_ip6_config_add_nameserver (ip6_config, &dns[i]);
}
+ LOG_LEASE (LOGD_DHCP6, "nameserver %s", str->str);
add_option (options, dhcp6_requests, SD_DHCP6_OPTION_DNS_SERVERS, str->str);
}
@@ -875,10 +898,10 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx,
if (num > 0) {
nm_gstring_prepare (&str);
for (i = 0; i < num; i++) {
+ g_string_append (nm_gstring_add_space_delimiter (str), domains[i]);
nm_ip6_config_add_search (ip6_config, domains[i]);
- g_string_append_printf (str, "%s%s", str->len ? " " : "", domains[i]);
- LOG_LEASE (LOGD_DHCP6, "domain name '%s'", domains[i]);
}
+ LOG_LEASE (LOGD_DHCP6, "domain name '%s'", str->str);
add_option (options, dhcp6_requests, SD_DHCP6_OPTION_DOMAIN_LIST, str->str);
}
diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
index 9d245a9059..122042ab58 100644
--- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
@@ -41,7 +41,6 @@ struct sd_dhcp_lease {
/* each 0 if unset */
be32_t address;
be32_t server_address;
- be32_t router;
be32_t next_server;
bool have_subnet_mask;
@@ -50,6 +49,9 @@ struct sd_dhcp_lease {
bool have_broadcast;
be32_t broadcast;
+ struct in_addr *router;
+ size_t router_size;
+
struct in_addr *dns;
size_t dns_size;
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index f03a30f4b3..6e9888e804 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -413,16 +413,33 @@ int config_parse_bridge_port_priority(
}
#endif /* NM_IGNORED */
-void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
- unsigned i;
+size_t serialize_in_addrs(FILE *f,
+ const struct in_addr *addresses,
+ size_t size,
+ bool with_leading_space,
+ bool (*predicate)(const struct in_addr *addr)) {
+ size_t count;
+ size_t i;
assert(f);
assert(addresses);
- assert(size);
- for (i = 0; i < size; i++)
- fprintf(f, "%s%s", inet_ntoa(addresses[i]),
- (i < (size - 1)) ? " ": "");
+ count = 0;
+
+ for (i = 0; i < size; i++) {
+ char sbuf[INET_ADDRSTRLEN];
+
+ if (predicate && !predicate(&addresses[i]))
+ continue;
+ if (with_leading_space)
+ fputc(' ', f);
+ else
+ with_leading_space = true;
+ fputs(inet_ntop(AF_INET, &addresses[i], sbuf, sizeof(sbuf)), f);
+ count++;
+ }
+
+ return count;
}
int deserialize_in_addrs(struct in_addr **ret, const char *string) {
@@ -456,7 +473,7 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
size++;
}
- *ret = TAKE_PTR(addresses);
+ *ret = size > 0 ? TAKE_PTR(addresses) : NULL;
return size;
}
@@ -525,6 +542,7 @@ void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, siz
fprintf(f, "%s=", key);
for (i = 0; i < size; i++) {
+ char sbuf[INET_ADDRSTRLEN];
struct in_addr dest, gw;
uint8_t length;
@@ -532,8 +550,8 @@ void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, siz
assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0);
assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0);
- fprintf(f, "%s/%" PRIu8, inet_ntoa(dest), length);
- fprintf(f, ",%s%s", inet_ntoa(gw), (i < (size - 1)) ? " ": "");
+ fprintf(f, "%s/%" PRIu8, inet_ntop(AF_INET, &dest, sbuf, sizeof(sbuf)), length);
+ fprintf(f, ",%s%s", inet_ntop(AF_INET, &gw, sbuf, sizeof(sbuf)), (i < (size - 1)) ? " ": "");
}
fputs("\n", f);
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index dfe4c4244b..b54680f416 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -42,7 +42,11 @@ int net_get_unique_predictable_data(sd_device *device, uint64_t *result);
const char *net_get_name(sd_device *device);
#endif /* NM_IGNORED */
-void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size);
+size_t serialize_in_addrs(FILE *f,
+ const struct in_addr *addresses,
+ size_t size,
+ bool with_leading_space,
+ bool (*predicate)(const struct in_addr *addr));
int deserialize_in_addrs(struct in_addr **addresses, const char *string);
void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
size_t size);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index 8359d077ee..39d2a6d082 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -152,15 +152,15 @@ int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
return 0;
}
-int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {
+int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
- if (lease->router == 0)
+ if (lease->router_size <= 0)
return -ENODATA;
- addr->s_addr = lease->router;
- return 0;
+ *addr = lease->router;
+ return (int) lease->router_size;
}
int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
@@ -262,6 +262,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
}
free(lease->root_path);
+ free(lease->router);
free(lease->timezone);
free(lease->hostname);
free(lease->domainname);
@@ -371,23 +372,6 @@ static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
return 0;
}
-static void filter_bogus_addresses(struct in_addr *addresses, size_t *n) {
- size_t i, j;
-
- /* Silently filter DNS/NTP servers supplied to us that do not make outside of the local scope. */
-
- for (i = 0, j = 0; i < *n; i ++) {
-
- if (in4_addr_is_null(addresses+i) ||
- in4_addr_is_localhost(addresses+i))
- continue;
-
- addresses[j++] = addresses[i];
- }
-
- *n = j;
-}
-
static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
assert(option);
assert(ret);
@@ -409,8 +393,6 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add
if (!addresses)
return -ENOMEM;
- filter_bogus_addresses(addresses, &n_addresses);
-
free(*ret);
*ret = addresses;
*n_ret = n_addresses;
@@ -555,11 +537,9 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
break;
case SD_DHCP_OPTION_ROUTER:
- if (len >= 4) {
- r = lease_parse_be32(option, 4, &lease->router);
- if (r < 0)
- log_debug_errno(r, "Failed to parse router address, ignoring: %m");
- }
+ r = lease_parse_in_addrs(option, len, &lease->router, &lease->router_size);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse router addresses, ignoring: %m");
break;
case SD_DHCP_OPTION_DOMAIN_NAME_SERVER:
@@ -821,7 +801,6 @@ int dhcp_lease_new(sd_dhcp_lease **ret) {
if (!lease)
return -ENOMEM;
- lease->router = INADDR_ANY;
lease->n_ref = 1;
*ret = lease;
@@ -836,6 +815,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
const struct in_addr *addresses;
const void *client_id, *data;
size_t client_id_len, data_len;
+ char sbuf[INET_ADDRSTRLEN];
const char *string;
uint16_t mtu;
_cleanup_free_ sd_dhcp_route **routes = NULL;
@@ -858,27 +838,30 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
r = sd_dhcp_lease_get_address(lease, &address);
if (r >= 0)
- fprintf(f, "ADDRESS=%s\n", inet_ntoa(address));
+ fprintf(f, "ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
r = sd_dhcp_lease_get_netmask(lease, &address);
if (r >= 0)
- fprintf(f, "NETMASK=%s\n", inet_ntoa(address));
+ fprintf(f, "NETMASK=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
- r = sd_dhcp_lease_get_router(lease, &address);
- if (r >= 0)
- fprintf(f, "ROUTER=%s\n", inet_ntoa(address));
+ r = sd_dhcp_lease_get_router(lease, &addresses);
+ if (r > 0) {
+ fputs("ROUTER=", f);
+ serialize_in_addrs(f, addresses, r, false, NULL);
+ fputc('\n', f);
+ }
r = sd_dhcp_lease_get_server_identifier(lease, &address);
if (r >= 0)
- fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntoa(address));
+ fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
r = sd_dhcp_lease_get_next_server(lease, &address);
if (r >= 0)
- fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address));
+ fprintf(f, "NEXT_SERVER=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
r = sd_dhcp_lease_get_broadcast(lease, &address);
if (r >= 0)
- fprintf(f, "BROADCAST=%s\n", inet_ntoa(address));
+ fprintf(f, "BROADCAST=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
r = sd_dhcp_lease_get_mtu(lease, &mtu);
if (r >= 0)
@@ -899,15 +882,15 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
r = sd_dhcp_lease_get_dns(lease, &addresses);
if (r > 0) {
fputs("DNS=", f);
- serialize_in_addrs(f, addresses, r);
- fputs("\n", f);
+ serialize_in_addrs(f, addresses, r, false, NULL);
+ fputc('\n', f);
}
r = sd_dhcp_lease_get_ntp(lease, &addresses);
if (r > 0) {
fputs("NTP=", f);
- serialize_in_addrs(f, addresses, r);
- fputs("\n", f);
+ serialize_in_addrs(f, addresses, r, false, NULL);
+ fputc('\n', f);
}
r = sd_dhcp_lease_get_domainname(lease, &string);
@@ -918,7 +901,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
if (r > 0) {
fputs("DOMAIN_SEARCH_LIST=", f);
fputstrv(f, search_domains, NULL, NULL);
- fputs("\n", f);
+ fputc('\n', f);
}
r = sd_dhcp_lease_get_hostname(lease, &string);
@@ -1081,9 +1064,11 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
}
if (router) {
- r = inet_pton(AF_INET, router, &lease->router);
- if (r <= 0)
- log_debug("Failed to parse router %s, ignoring.", router);
+ r = deserialize_in_addrs(&lease->router, router);
+ if (r < 0)
+ log_debug_errno(r, "Failed to deserialize router addresses %s, ignoring: %m", router);
+ else
+ lease->router_size = r;
}
if (netmask) {
diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h
index 4875f10555..d299c79121 100644
--- a/src/systemd/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp-lease.h
@@ -39,7 +39,7 @@ int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1);
int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2);
int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr);
+int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);