dhcp: include conditionals from existing dhclient configuration

Since commit 159ff23268 ('dhcp/dhclient-utils: skip over
dhclient.conf blocks') we skip blocks enclosed in lines containing '{'
and '}' because NM should ignore 'lease', 'alias' and other
declarations. However, conditional statements seem useful and should
not be skipped.

https://bugzilla.redhat.com/show_bug.cgi?id=1758550
This commit is contained in:
Beniamino Galvani 2019-10-06 08:27:18 +02:00
parent 724113c144
commit b58e4d311d
2 changed files with 50 additions and 12 deletions

View file

@ -291,11 +291,13 @@ nm_dhcp_dhclient_create_config (const char *interface,
if (orig_contents) {
gs_free const char **lines = NULL;
gsize line_i;
int nest = 0;
nm_auto_free_gstring GString *blocks_stack = NULL;
guint blocks_skip = 0;
gboolean in_alsoreq = FALSE;
gboolean in_req = FALSE;
char intf[IFNAMSIZ];
blocks_stack = g_string_new (NULL);
g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path);
intf[0] = '\0';
@ -313,19 +315,38 @@ nm_dhcp_dhclient_create_config (const char *interface,
if (in_req) {
/* pass */
} else if (strchr (p, '{')) {
nest++;
if ( !intf[0]
&& NM_STR_HAS_PREFIX (p, "interface"))
if (read_interface (p, intf, sizeof (intf)))
continue;
if ( NM_STR_HAS_PREFIX (p, "lease")
|| NM_STR_HAS_PREFIX (p, "alias")
|| NM_STR_HAS_PREFIX (p, "interface")
|| NM_STR_HAS_PREFIX (p, "pseudo")) {
/* skip over these blocks, except 'interface' when it
* matches the current interface */
blocks_skip++;
g_string_append_c (blocks_stack, 'b');
if ( !intf[0]
&& NM_STR_HAS_PREFIX (p, "interface")) {
if (read_interface (p, intf, sizeof (intf)))
continue;
}
} else {
/* allow other blocks (conditionals) */
if (!strchr (p, '}')) /* '} else {' */
g_string_append_c (blocks_stack, 'c');
}
} else if (strchr (p, '}')) {
if (nest)
nest--;
intf[0] = '\0';
continue;
if (blocks_stack->len > 0) {
if (blocks_stack->str[blocks_stack->len - 1] == 'b') {
g_string_truncate (blocks_stack, blocks_stack->len - 1);
nm_assert(blocks_skip > 0);
blocks_skip--;
intf[0] = '\0';
continue;
}
g_string_truncate (blocks_stack, blocks_stack->len - 1);
}
}
if (nest && !intf[0])
if (blocks_skip > 0 && !intf[0])
continue;
if (intf[0] && !nm_streq (intf, interface))

View file

@ -982,6 +982,11 @@ test_structured (void)
" request subnet-mask, broadcast-address, time-offset, routers,\n"
" domain-search, domain-name, domain-name-servers, host-name;\n"
" require subnet-mask, domain-name-servers;\n"
" if not option domain-name = \"example.org\" {\n"
" prepend domain-name-servers 127.0.0.1;\n"
" } else {\n"
" prepend domain-name-servers 127.0.0.2;\n"
" } \n"
" } \n"
"\n"
"pseudo \"secondary\" \"eth0\" { \n"
@ -1008,7 +1013,13 @@ test_structured (void)
" interface \"eth0\";\n"
" fixed-address 192.0.2.2;\n"
" option subnet-mask 255.255.255.0;\n"
" } \n";
" } \n"
"if not option domain-name = \"example.org\" {\n"
" prepend domain-name-servers 127.0.0.1;\n"
" if not option domain-name = \"useless.example.com\" {\n"
" prepend domain-name-servers 127.0.0.2;\n"
" }\n"
"}\n";
static const char *const expected = \
"# Created by NetworkManager\n"
@ -1019,6 +1030,12 @@ test_structured (void)
"send dhcp-client-identifier \"sad-and-useless\";\n"
"send dhcp-lease-time 8086;\n"
"require subnet-mask;\n"
"if not option domain-name = \"example.org\" {\n"
"prepend domain-name-servers 127.0.0.1;\n"
"if not option domain-name = \"useless.example.com\" {\n"
"prepend domain-name-servers 127.0.0.2;\n"
"}\n"
"}\n"
"\n"
"option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"
"option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"