diff options
author | Thomas Haller <thaller@redhat.com> | 2019-02-20 10:03:11 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-02-20 10:03:11 +0100 |
commit | 209ff015e26f295bdb7c396962a4e9b4199398fb (patch) | |
tree | 27ac1494a14ec88e84ad8bac9833202915fe36c1 | |
parent | c3f6356a39caf6bc7b159be81ebaa05b929b62f4 (diff) | |
parent | c2b3b9b95582696c044d3d580e40570b6e96a0df (diff) | |
download | NetworkManager-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.h | 6 | ||||
-rw-r--r-- | shared/nm-utils/tests/test-shared-general.c | 14 | ||||
-rw-r--r-- | shared/systemd/src/basic/in-addr-util.c | 8 | ||||
-rw-r--r-- | shared/systemd/src/basic/in-addr-util.h | 2 | ||||
-rw-r--r-- | src/dhcp/nm-dhcp-systemd.c | 141 | ||||
-rw-r--r-- | src/systemd/src/libsystemd-network/dhcp-lease-internal.h | 4 | ||||
-rw-r--r-- | src/systemd/src/libsystemd-network/network-internal.c | 36 | ||||
-rw-r--r-- | src/systemd/src/libsystemd-network/network-internal.h | 6 | ||||
-rw-r--r-- | src/systemd/src/libsystemd-network/sd-dhcp-lease.c | 75 | ||||
-rw-r--r-- | src/systemd/src/systemd/sd-dhcp-lease.h | 2 |
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); |