dhcp: rework DHCP options to not carry around option array

Previously, we would pass around the list of options. However,

- that isn't too nice to read. Also, usually when we want to treat
  IP address families generically, then we have an addr_family argument.
  Having to first resolve the addr_family to another set of variables
  is inconvenient.

- the option array itself doesn't have enough information. For example,
  we don't know how many elements there are, we don't know which address
  family it is (unless we compare it to one of the two well known
  lists).
  For example, I'd like to do a binary search for the option. But that's
  not immediately possible, because the length is unknown.

- in practice, there are only two address families: AF_INET and
  AF_INET6. It is extremely unlikely that we will require a third
  DHCP options list, and even if we had that, the addr_family argument
  still abstracts them nicely.
  We also don't need two different lists for one DHCP type. While that
  would currently be possible (and afterwards not anymore), it would
  be wrong to do.

- also add a new accessor nm_dhcp_option_find() to find the NMDhcpOption
  instance by option number.
This commit is contained in:
Thomas Haller
2021-02-11 10:21:46 +01:00
parent 53f137af6e
commit 1cbe926c20
5 changed files with 185 additions and 196 deletions

View File

@@ -231,30 +231,27 @@ lease_parse_address(NDhcp4ClientLease *lease,
a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask); a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask);
nm_dhcp_option_add_option_in_addr(options, nm_dhcp_option_add_option_in_addr(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS,
a_address.s_addr); a_address.s_addr);
nm_dhcp_option_add_option_in_addr(options, nm_dhcp_option_add_option_in_addr(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_SUBNET_MASK, NM_DHCP_OPTION_DHCP4_SUBNET_MASK,
a_netmask); a_netmask);
nm_dhcp_option_add_option_u64(options, nm_dhcp_option_add_option_u64(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME,
(guint64) a_lifetime); (guint64) a_lifetime);
if (a_expiry != G_MAXUINT64) { if (a_expiry != G_MAXUINT64) {
nm_dhcp_option_add_option_u64(options, nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_EXPIRY, a_expiry);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_NM_EXPIRY,
a_expiry);
} }
n_dhcp4_client_lease_get_siaddr(lease, &a_next_server); n_dhcp4_client_lease_get_siaddr(lease, &a_next_server);
if (a_next_server.s_addr != INADDR_ANY) { if (a_next_server.s_addr != INADDR_ANY) {
nm_dhcp_option_add_option_in_addr(options, nm_dhcp_option_add_option_in_addr(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER,
a_next_server.s_addr); a_next_server.s_addr);
} }
@@ -322,10 +319,7 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
} }
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, option, nm_str_buf_get_str(sbuf));
_nm_dhcp_option_dhcp4_options,
option,
nm_str_buf_get_str(sbuf));
} }
static void static void
@@ -391,7 +385,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE,
nm_str_buf_get_str(sbuf)); nm_str_buf_get_str(sbuf));
} }
@@ -436,7 +430,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE,
nm_str_buf_get_str(sbuf)); nm_str_buf_get_str(sbuf));
} }
@@ -482,7 +476,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_ROUTER, NM_DHCP_OPTION_DHCP4_ROUTER,
nm_str_buf_get_str(sbuf)); nm_str_buf_get_str(sbuf));
} }
@@ -510,7 +504,7 @@ lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GH
nm_ip4_config_add_search(ip4_config, domains[i]); nm_ip4_config_add_search(ip4_config, domains[i]);
nm_dhcp_option_take_option(options, nm_dhcp_option_take_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST,
g_strjoinv(" ", domains)); g_strjoinv(" ", domains));
} }
@@ -538,10 +532,7 @@ lease_parse_private_options(NDhcp4ClientLease *lease, GHashTable *options)
continue; continue;
option_string = nm_utils_bin2hexstr_full(l_data, l_data_len, ':', FALSE, NULL); option_string = nm_utils_bin2hexstr_full(l_data, l_data_len, ':', FALSE, NULL);
nm_dhcp_option_take_option(options, nm_dhcp_option_take_option(options, AF_INET, i, g_steal_pointer(&option_string));
_nm_dhcp_option_dhcp4_options,
i,
g_steal_pointer(&option_string));
} }
} }
@@ -578,7 +569,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s); r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s);
if (r == 0) { if (r == 0) {
nm_dhcp_option_add_option_in_addr(options, nm_dhcp_option_add_option_in_addr(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_SERVER_ID, NM_DHCP_OPTION_DHCP4_SERVER_ID,
v_inaddr_s.s_addr); v_inaddr_s.s_addr);
} }
@@ -586,7 +577,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_BROADCAST, &l_data, &l_data_len); r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_BROADCAST, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_in_addr(l_data, l_data_len, &v_inaddr)) { if (r == 0 && nm_dhcp_lease_data_parse_in_addr(l_data, l_data_len, &v_inaddr)) {
nm_dhcp_option_add_option_in_addr(options, nm_dhcp_option_add_option_in_addr(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_BROADCAST, NM_DHCP_OPTION_DHCP4_BROADCAST,
v_inaddr); v_inaddr);
} }
@@ -628,7 +619,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (sbuf.len > 0) { if (sbuf.len > 0) {
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME,
nm_str_buf_get_str(&sbuf)); nm_str_buf_get_str(&sbuf));
} }
@@ -638,10 +629,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &l_data, &l_data_len); r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_mtu(l_data, l_data_len, &v_u16)) { if (r == 0 && nm_dhcp_lease_data_parse_mtu(l_data, l_data_len, &v_u16)) {
nm_dhcp_option_add_option_u64(options, nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, v_u16);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_INTERFACE_MTU,
v_u16);
nm_ip4_config_set_mtu(ip4_config, v_u16, NM_IP_CONFIG_SOURCE_DHCP); nm_ip4_config_set_mtu(ip4_config, v_u16, NM_IP_CONFIG_SOURCE_DHCP);
} }
@@ -655,10 +643,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
gs_free char *s = NULL; gs_free char *s = NULL;
if (nm_dhcp_lease_data_parse_domain(l_data, l_data_len, &s)) { if (nm_dhcp_lease_data_parse_domain(l_data, l_data_len, &s)) {
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_HOST_NAME,
s);
} }
} }
@@ -676,7 +661,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
/* "Its minimum length is 1." */ /* "Its minimum length is 1." */
} else { } else {
nm_dhcp_option_add_option_utf8safe_escape(options, nm_dhcp_option_add_option_utf8safe_escape(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_ROOT_PATH, NM_DHCP_OPTION_DHCP4_ROOT_PATH,
l_data, l_data,
l_data_len); l_data_len);
@@ -694,7 +679,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* Otherwise, we allow any encoding and backslash-escape the result to * Otherwise, we allow any encoding and backslash-escape the result to
* UTF-8. */ * UTF-8. */
nm_dhcp_option_add_option_utf8safe_escape(options, nm_dhcp_option_add_option_utf8safe_escape(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
l_data, l_data,
l_data_len); l_data_len);
@@ -708,10 +693,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
v_str = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free); v_str = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_NIS_DOMAIN,
v_str);
nm_ip4_config_set_nis_domain(ip4_config, v_str); nm_ip4_config_set_nis_domain(ip4_config, v_str);
} }
@@ -781,7 +763,7 @@ bound4_handle(NMDhcpNettools *self, NDhcp4ClientLease *lease, gboolean extended)
return; return;
} }
nm_dhcp_option_add_requests_to_options(options, _nm_dhcp_option_dhcp4_options); nm_dhcp_option_add_requests_to_options(options, AF_INET);
lease_save(self, lease, priv->lease_file); lease_save(self, lease, priv->lease_file);
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
@@ -1107,7 +1089,7 @@ ip4_start(NMDhcpClient *client,
} }
/* Add requested options */ /* Add requested options */
for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options); i++) {
if (_nm_dhcp_option_dhcp4_options[i].include) { if (_nm_dhcp_option_dhcp4_options[i].include) {
nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255); nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255);
n_dhcp4_client_probe_config_request_option(config, n_dhcp4_client_probe_config_request_option(config,

View File

@@ -7,11 +7,11 @@
#include "nm-dhcp-options.h" #include "nm-dhcp-options.h"
#define REQPREFIX "requested_" /*****************************************************************************/
#define REQ(_num, _name, _include) \ #define REQ(_num, _name, _include) \
{ \ { \
.name = REQPREFIX ""_name, .option_num = _num, .include = _include, \ .name = NM_DHCP_OPTION_REQPREFIX ""_name, .option_num = _num, .include = _include, \
} }
const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = { const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = {
@@ -167,8 +167,7 @@ const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = {
REQ(NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, "ip_address", FALSE), REQ(NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, "ip_address", FALSE),
REQ(NM_DHCP_OPTION_DHCP4_NM_EXPIRY, "expiry", FALSE), REQ(NM_DHCP_OPTION_DHCP4_NM_EXPIRY, "expiry", FALSE),
REQ(NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, "next_server", FALSE), REQ(NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, "next_server", FALSE),
};
{0}};
const NMDhcpOption _nm_dhcp_option_dhcp6_options[] = { const NMDhcpOption _nm_dhcp_option_dhcp6_options[] = {
REQ(NM_DHCP_OPTION_DHCP6_CLIENTID, "dhcp6_client_id", FALSE), REQ(NM_DHCP_OPTION_DHCP6_CLIENTID, "dhcp6_client_id", FALSE),
@@ -194,103 +193,102 @@ const NMDhcpOption _nm_dhcp_option_dhcp6_options[] = {
REQ(NM_DHCP_OPTION_DHCP6_NM_RENEW, "renew", FALSE), REQ(NM_DHCP_OPTION_DHCP6_NM_RENEW, "renew", FALSE),
REQ(NM_DHCP_OPTION_DHCP6_NM_REBIND, "rebind", FALSE), REQ(NM_DHCP_OPTION_DHCP6_NM_REBIND, "rebind", FALSE),
REQ(NM_DHCP_OPTION_DHCP6_NM_IAID, "iaid", FALSE), REQ(NM_DHCP_OPTION_DHCP6_NM_IAID, "iaid", FALSE),
};
{0}}; #undef REQ
const char * const NMDhcpOption *
nm_dhcp_option_request_string(const NMDhcpOption *requests, guint option) nm_dhcp_option_find(int addr_family, guint option)
{ {
guint i = 0; const int IS_IPv4 = NM_IS_IPv4(addr_family);
const NMDhcpOption *const options =
IS_IPv4 ? _nm_dhcp_option_dhcp4_options : _nm_dhcp_option_dhcp6_options;
int n_options = IS_IPv4 ? G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options)
: G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options);
int i;
while (requests[i].name) { for (i = 0; i < n_options; i++) {
if (requests[i].option_num == option) const NMDhcpOption *opt = &options[i];
return requests[i].name + NM_STRLEN(REQPREFIX);
i++; if (opt->option_num == option)
return opt;
} }
/* Option should always be found */ /* Option should always be found */
nm_assert_not_reached(); return nm_assert_unreachable_val(NULL);
return NULL;
} }
void void
nm_dhcp_option_take_option(GHashTable * options, nm_dhcp_option_take_option(GHashTable *options, int addr_family, guint option, char *value)
const NMDhcpOption *requests,
guint option,
char * value)
{ {
nm_assert_addr_family(addr_family);
nm_assert(value);
nm_assert(g_utf8_validate(value, -1, NULL));
if (!options) { if (!options) {
nm_assert_not_reached(); nm_assert_not_reached();
g_free(value); g_free(value);
return; return;
} }
nm_assert(requests); g_hash_table_insert(options,
nm_assert(value); (gpointer) nm_dhcp_option_request_string(addr_family, option),
nm_assert(g_utf8_validate(value, -1, NULL)); value);
g_hash_table_insert(options, (gpointer) nm_dhcp_option_request_string(requests, option), value);
} }
void void
nm_dhcp_option_add_option(GHashTable * options, nm_dhcp_option_add_option(GHashTable *options, int addr_family, guint option, const char *value)
const NMDhcpOption *requests,
guint option,
const char * value)
{ {
nm_dhcp_option_take_option(options, requests, option, g_strdup(value)); nm_dhcp_option_take_option(options, addr_family, option, g_strdup(value));
} }
void void
nm_dhcp_option_add_option_utf8safe_escape(GHashTable * options, nm_dhcp_option_add_option_utf8safe_escape(GHashTable * options,
const NMDhcpOption *requests, int addr_family,
guint option, guint option,
const guint8 * data, const guint8 *data,
gsize n_data) gsize n_data)
{ {
gs_free char *to_free = NULL; gs_free char *to_free = NULL;
const char * escaped; const char * escaped;
escaped = nm_utils_buf_utf8safe_escape((char *) data, n_data, 0, &to_free); escaped = nm_utils_buf_utf8safe_escape((char *) data, n_data, 0, &to_free);
nm_dhcp_option_add_option(options, requests, option, escaped ?: ""); nm_dhcp_option_add_option(options, addr_family, option, escaped ?: "");
} }
void void
nm_dhcp_option_add_option_u64(GHashTable * options, nm_dhcp_option_add_option_u64(GHashTable *options, int addr_family, guint option, guint64 value)
const NMDhcpOption *requests,
guint option,
guint64 value)
{ {
nm_dhcp_option_take_option(options, nm_dhcp_option_take_option(options,
requests, addr_family,
option, option,
g_strdup_printf("%" G_GUINT64_FORMAT, value)); g_strdup_printf("%" G_GUINT64_FORMAT, value));
} }
void void
nm_dhcp_option_add_option_in_addr(GHashTable * options, nm_dhcp_option_add_option_in_addr(GHashTable *options,
const NMDhcpOption *requests, int addr_family,
guint option, guint option,
in_addr_t value) in_addr_t value)
{ {
char sbuf[NM_UTILS_INET_ADDRSTRLEN]; char sbuf[NM_UTILS_INET_ADDRSTRLEN];
nm_dhcp_option_add_option(options, requests, option, _nm_utils_inet4_ntop(value, sbuf)); nm_dhcp_option_add_option(options, addr_family, option, _nm_utils_inet4_ntop(value, sbuf));
} }
void void
nm_dhcp_option_add_requests_to_options(GHashTable *options, const NMDhcpOption *requests) nm_dhcp_option_add_requests_to_options(GHashTable *options, int addr_family)
{ {
guint i; const int IS_IPv4 = NM_IS_IPv4(addr_family);
const NMDhcpOption *const all_options =
IS_IPv4 ? _nm_dhcp_option_dhcp4_options : _nm_dhcp_option_dhcp6_options;
int n_options = IS_IPv4 ? G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options)
: G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options);
int i;
if (!options) { for (i = 0; i < n_options; i++) {
nm_assert_not_reached(); if (all_options[i].include)
return; g_hash_table_insert(options, (gpointer) all_options[i].name, g_strdup("1"));
}
for (i = 0; requests[i].name; i++) {
if (requests[i].include)
g_hash_table_insert(options, (gpointer) requests[i].name, g_strdup("1"));
} }
} }

View File

@@ -177,38 +177,50 @@ typedef enum {
} NMDhcpOptionDhcp6Options; } NMDhcpOptionDhcp6Options;
#define NM_DHCP_OPTION_REQPREFIX "requested_"
typedef struct { typedef struct {
const char *name; const char *name;
uint16_t option_num; uint16_t option_num;
bool include; bool include;
} NMDhcpOption; } NMDhcpOption;
extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[]; extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[142];
extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[]; extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[16];
const char *nm_dhcp_option_request_string(const NMDhcpOption *requests, guint option); static inline const char *
void nm_dhcp_option_take_option(GHashTable * options, nm_dhcp_option_get_name(const NMDhcpOption *option)
const NMDhcpOption *requests, {
guint option, nm_assert(option);
char * value); nm_assert(option->name);
void nm_dhcp_option_add_option(GHashTable * options, nm_assert(NM_STR_HAS_PREFIX(option->name, NM_DHCP_OPTION_REQPREFIX));
const NMDhcpOption *requests,
guint option, return &option->name[NM_STRLEN(NM_DHCP_OPTION_REQPREFIX)];
const char * value); }
void nm_dhcp_option_add_option_utf8safe_escape(GHashTable * options,
const NMDhcpOption *requests, const NMDhcpOption *nm_dhcp_option_find(int addr_family, guint option);
guint option,
const guint8 * data, static inline const char *
gsize n_data); nm_dhcp_option_request_string(int addr_family, guint option)
void nm_dhcp_option_add_option_in_addr(GHashTable * options, {
const NMDhcpOption *requests, return nm_dhcp_option_get_name(nm_dhcp_option_find(addr_family, option));
guint option, }
in_addr_t value);
void nm_dhcp_option_add_option_u64(GHashTable * options, void nm_dhcp_option_take_option(GHashTable *options, int addr_family, guint option, char *value);
const NMDhcpOption *requests, void
guint option, nm_dhcp_option_add_option(GHashTable *options, int addr_family, guint option, const char *value);
guint64 value); void nm_dhcp_option_add_option_utf8safe_escape(GHashTable * options,
void nm_dhcp_option_add_requests_to_options(GHashTable *options, const NMDhcpOption *requests); int addr_family,
guint option,
const guint8 *data,
gsize n_data);
void nm_dhcp_option_add_option_in_addr(GHashTable *options,
int addr_family,
guint option,
in_addr_t value);
void
nm_dhcp_option_add_option_u64(GHashTable *options, int addr_family, guint option, guint64 value);
void nm_dhcp_option_add_requests_to_options(GHashTable *options, int addr_family);
GHashTable *nm_dhcp_option_create_options_dict(void); GHashTable *nm_dhcp_option_create_options_dict(void);
#endif /* __NM_DHCP_OPTIONS_H__ */ #endif /* __NM_DHCP_OPTIONS_H__ */

View File

@@ -138,32 +138,26 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
options = out_options ? nm_dhcp_option_create_options_dict() : NULL; options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
_nm_utils_inet4_ntop(a_address.s_addr, addr_str); _nm_utils_inet4_ntop(a_address.s_addr, addr_str);
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS,
addr_str);
a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask.s_addr); a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask.s_addr);
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_SUBNET_MASK, NM_DHCP_OPTION_DHCP4_SUBNET_MASK,
_nm_utils_inet4_ntop(a_netmask.s_addr, addr_str)); _nm_utils_inet4_ntop(a_netmask.s_addr, addr_str));
nm_dhcp_option_add_option_u64(options, nm_dhcp_option_add_option_u64(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME,
a_lifetime); a_lifetime);
nm_dhcp_option_add_option_u64(options, nm_dhcp_option_add_option_u64(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_NM_EXPIRY, NM_DHCP_OPTION_DHCP4_NM_EXPIRY,
(guint64)(ts_time + a_lifetime)); (guint64)(ts_time + a_lifetime));
if (sd_dhcp_lease_get_next_server(lease, &a_next_server) == 0) { if (sd_dhcp_lease_get_next_server(lease, &a_next_server) == 0) {
_nm_utils_inet4_ntop(a_next_server.s_addr, addr_str); _nm_utils_inet4_ntop(a_next_server.s_addr, addr_str);
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER,
addr_str);
} }
nm_ip4_config_add_address(ip4_config, nm_ip4_config_add_address(ip4_config,
@@ -179,18 +173,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) { if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) {
_nm_utils_inet4_ntop(server_id.s_addr, addr_str); _nm_utils_inet4_ntop(server_id.s_addr, addr_str);
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_SERVER_ID, addr_str);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_SERVER_ID,
addr_str);
} }
if (sd_dhcp_lease_get_broadcast(lease, &broadcast) >= 0) { if (sd_dhcp_lease_get_broadcast(lease, &broadcast) >= 0) {
_nm_utils_inet4_ntop(broadcast.s_addr, addr_str); _nm_utils_inet4_ntop(broadcast.s_addr, addr_str);
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_BROADCAST, addr_str);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_BROADCAST,
addr_str);
} }
num = sd_dhcp_lease_get_dns(lease, &addr_list); num = sd_dhcp_lease_get_dns(lease, &addr_list);
@@ -208,7 +196,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr); nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr);
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
str->str); str->str);
} }
@@ -221,7 +209,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_ip4_config_add_search(ip4_config, search_domains[i]); nm_ip4_config_add_search(ip4_config, search_domains[i]);
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST,
str->str); str->str);
} }
@@ -230,10 +218,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
gs_strfreev char **domains = NULL; gs_strfreev char **domains = NULL;
char ** d; char ** d;
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, s);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME,
s);
/* Multiple domains sometimes stuffed into option 15 "Domain Name". /* Multiple domains sometimes stuffed into option 15 "Domain Name".
* As systemd escapes such characters, split them at \\032. */ * As systemd escapes such characters, split them at \\032. */
@@ -243,10 +228,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
} }
if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) { if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) {
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_HOST_NAME,
s);
} }
num = sd_dhcp_lease_get_routes(lease, &routes); num = sd_dhcp_lease_get_routes(lease, &routes);
@@ -348,12 +330,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (str_classless && str_classless->len > 0) if (str_classless && str_classless->len > 0)
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE,
str_classless->str); str_classless->str);
if (str_static && str_static->len > 0) if (str_static && str_static->len > 0)
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE,
str_static->str); str_static->str);
} }
@@ -400,17 +382,11 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
}), }),
NULL); NULL);
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROUTER, str->str);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_ROUTER,
str->str);
} }
if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) { if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) {
nm_dhcp_option_add_option_u64(options, nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, mtu);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_INTERFACE_MTU,
mtu);
nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
} }
@@ -421,38 +397,29 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
_nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str); _nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str);
g_string_append(nm_gstring_add_space_delimiter(str), addr_str); g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NTP_SERVER, str->str);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_NTP_SERVER,
str->str);
} }
if (sd_dhcp_lease_get_root_path(lease, &s) >= 0) { if (sd_dhcp_lease_get_root_path(lease, &s) >= 0) {
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROOT_PATH, s);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_ROOT_PATH,
s);
} }
if (sd_dhcp_lease_get_t1(lease, &renewal) >= 0) { if (sd_dhcp_lease_get_t1(lease, &renewal) >= 0) {
nm_dhcp_option_add_option_u64(options, nm_dhcp_option_add_option_u64(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME,
renewal); renewal);
} }
if (sd_dhcp_lease_get_t2(lease, &rebinding) >= 0) { if (sd_dhcp_lease_get_t2(lease, &rebinding) >= 0) {
nm_dhcp_option_add_option_u64(options, nm_dhcp_option_add_option_u64(options,
_nm_dhcp_option_dhcp4_options, AF_INET,
NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME,
rebinding); rebinding);
} }
if (sd_dhcp_lease_get_timezone(lease, &s) >= 0) { if (sd_dhcp_lease_get_timezone(lease, &s) >= 0) {
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, s);
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE,
s);
} }
if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0) if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0)
@@ -473,10 +440,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
g_free(option_string); g_free(option_string);
continue; continue;
} }
nm_dhcp_option_take_option(options, nm_dhcp_option_take_option(options, AF_INET, private_options[i].code, option_string);
_nm_dhcp_option_dhcp4_options,
private_options[i].code,
option_string);
} }
} }
NM_SET_OUT(out_options, g_steal_pointer(&options)); NM_SET_OUT(out_options, g_steal_pointer(&options));
@@ -518,7 +482,7 @@ bound4_handle(NMDhcpSystemd *self, gboolean extended)
return; return;
} }
nm_dhcp_option_add_requests_to_options(options, _nm_dhcp_option_dhcp4_options); nm_dhcp_option_add_requests_to_options(options, AF_INET);
dhcp_lease_save(lease, priv->lease_file); dhcp_lease_save(lease, priv->lease_file);
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
@@ -702,7 +666,7 @@ ip4_start(NMDhcpClient *client,
} }
/* Add requested options */ /* Add requested options */
for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options); i++) {
if (_nm_dhcp_option_dhcp4_options[i].include) { if (_nm_dhcp_option_dhcp4_options[i].include) {
nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255); nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255);
r = sd_dhcp_client_set_request_option(sd_client, r = sd_dhcp_client_set_request_option(sd_client,
@@ -821,10 +785,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
g_string_append(nm_gstring_add_space_delimiter(str), addr_str); g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
}; };
if (str->len) if (str->len)
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, str->str);
_nm_dhcp_option_dhcp6_options,
NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS,
str->str);
if (!info_only && nm_ip6_config_get_num_addresses(ip6_config) == 0) { if (!info_only && nm_ip6_config_get_num_addresses(ip6_config) == 0) {
g_set_error_literal(error, g_set_error_literal(error,
@@ -842,10 +803,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
g_string_append(nm_gstring_add_space_delimiter(str), addr_str); g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
nm_ip6_config_add_nameserver(ip6_config, &dns[i]); nm_ip6_config_add_nameserver(ip6_config, &dns[i]);
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, str->str);
_nm_dhcp_option_dhcp6_options,
NM_DHCP_OPTION_DHCP6_DNS_SERVERS,
str->str);
} }
num = sd_dhcp6_lease_get_domains(lease, &domains); num = sd_dhcp6_lease_get_domains(lease, &domains);
@@ -855,17 +813,11 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
g_string_append(nm_gstring_add_space_delimiter(str), domains[i]); g_string_append(nm_gstring_add_space_delimiter(str), domains[i]);
nm_ip6_config_add_search(ip6_config, domains[i]); nm_ip6_config_add_search(ip6_config, domains[i]);
} }
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, str->str);
_nm_dhcp_option_dhcp6_options,
NM_DHCP_OPTION_DHCP6_DOMAIN_LIST,
str->str);
} }
if (sd_dhcp6_lease_get_fqdn(lease, &s) >= 0) { if (sd_dhcp6_lease_get_fqdn(lease, &s) >= 0) {
nm_dhcp_option_add_option(options, nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_FQDN, s);
_nm_dhcp_option_dhcp6_options,
NM_DHCP_OPTION_DHCP6_FQDN,
s);
} }
NM_SET_OUT(out_options, g_steal_pointer(&options)); NM_SET_OUT(out_options, g_steal_pointer(&options));
@@ -1020,7 +972,7 @@ ip6_start(NMDhcpClient * client,
} }
/* Add requested options */ /* Add requested options */
for (i = 0; _nm_dhcp_option_dhcp6_options[i].name; i++) { for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options); i++) {
if (_nm_dhcp_option_dhcp6_options[i].include) { if (_nm_dhcp_option_dhcp6_options[i].include) {
r = sd_dhcp6_client_set_request_option(sd_client, r = sd_dhcp6_client_set_request_option(sd_client,
_nm_dhcp_option_dhcp6_options[i].option_num); _nm_dhcp_option_dhcp6_options[i].option_num);

View File

@@ -13,10 +13,13 @@
#include "nm-utils.h" #include "nm-utils.h"
#include "dhcp/nm-dhcp-utils.h" #include "dhcp/nm-dhcp-utils.h"
#include "dhcp/nm-dhcp-options.h"
#include "platform/nm-platform.h" #include "platform/nm-platform.h"
#include "nm-test-utils-core.h" #include "nm-test-utils-core.h"
/*****************************************************************************/
static NMIP4Config * static NMIP4Config *
_ip4_config_from_options(int ifindex, const char *iface, GHashTable *options, guint32 route_metric) _ip4_config_from_options(int ifindex, const char *iface, GHashTable *options, guint32 route_metric)
{ {
@@ -740,6 +743,46 @@ test_client_id_from_string(void)
COMPARE_ID(endcolon, TRUE, endcolon, strlen(endcolon)); COMPARE_ID(endcolon, TRUE, endcolon, strlen(endcolon));
} }
/*****************************************************************************/
static void
test_dhcp_opt_list(gconstpointer test_data)
{
const gboolean IS_IPv4 = (GPOINTER_TO_INT(test_data) == 0);
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
const NMDhcpOption *const options =
IS_IPv4 ? _nm_dhcp_option_dhcp4_options : _nm_dhcp_option_dhcp6_options;
const guint n = (IS_IPv4 ? G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options)
: G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options));
guint i;
guint j;
g_assert(options);
g_assert(n > 0);
for (i = 0; i < n; i++) {
const NMDhcpOption *const opt = &options[i];
g_assert_cmpstr(opt->name, !=, NULL);
g_assert(NM_STR_HAS_PREFIX(opt->name, NM_DHCP_OPTION_REQPREFIX));
for (j = 0; j < i; j++) {
const NMDhcpOption *const opt2 = &options[j];
g_assert_cmpstr(opt->name, !=, opt2->name);
g_assert_cmpint(opt->option_num, !=, opt2->option_num);
}
}
for (i = 0; i < n; i++) {
const NMDhcpOption *const opt = &options[i];
g_assert(opt == nm_dhcp_option_find(addr_family, opt->option_num));
}
}
/*****************************************************************************/
NMTST_DEFINE(); NMTST_DEFINE();
int int
@@ -776,6 +819,8 @@ main(int argc, char **argv)
g_test_add_func("/dhcp/client-id-from-string", test_client_id_from_string); g_test_add_func("/dhcp/client-id-from-string", test_client_id_from_string);
g_test_add_func("/dhcp/vendor-option-metered", test_vendor_option_metered); g_test_add_func("/dhcp/vendor-option-metered", test_vendor_option_metered);
g_test_add_func("/dhcp/parse-search-list", test_parse_search_list); g_test_add_func("/dhcp/parse-search-list", test_parse_search_list);
g_test_add_data_func("/dhcp/test_dhcp_opt_list/IPv4", GINT_TO_POINTER(0), test_dhcp_opt_list);
g_test_add_data_func("/dhcp/test_dhcp_opt_list/IPv6", GINT_TO_POINTER(1), test_dhcp_opt_list);
return g_test_run(); return g_test_run();
} }