dhcp: let users override FQDN dhclient options

When the ipv4.dhcp-fqdn property is set, NM adds the following options
to dhclient.conf:

  send fqdn.fqdn "foo.bar";
  send fqdn.encoded on;
  send fqdn.server-update on;

which enable the S (server-update) and E (encoded) flags in DHCP
option 81, since they are sensible default values and dhclient
requires a "send fqdn.server-update [on|off]" directive in order to
send the option.

Users may want to change these flags according to their server's
configuration, but this is not possible at the moment since NM options
are placed after user's ones, overriding them.

To fix this, collect user's fqdn options and add them after NM
configuration; note that the fqdn.fqdn option still can't be
overridden by users, as NM must control the FQDN sent to server.

Fixes: c3573ebf2b
This commit is contained in:
Beniamino Galvani 2016-05-27 13:33:50 +02:00
parent d43a0459bc
commit f940428c65
2 changed files with 64 additions and 3 deletions

View file

@ -36,8 +36,9 @@
#define HOSTNAME4_TAG "send host-name"
#define HOSTNAME4_FORMAT HOSTNAME4_TAG " \"%s\"; # added by NetworkManager"
#define FQDN_TAG "send fqdn.fqdn"
#define FQDN_FORMAT FQDN_TAG " \"%s\"; # added by NetworkManager"
#define FQDN_TAG_PREFIX "send fqdn."
#define FQDN_TAG FQDN_TAG_PREFIX "fqdn"
#define FQDN_FORMAT FQDN_TAG " \"%s\"; # added by NetworkManager"
#define ALSOREQ_TAG "also request "
@ -205,13 +206,14 @@ nm_dhcp_dhclient_create_config (const char *interface,
GBytes **out_new_client_id)
{
GString *new_contents;
GPtrArray *alsoreq;
GPtrArray *alsoreq, *fqdn_opts;
int i;
g_return_val_if_fail (!anycast_addr || nm_utils_hwaddr_valid (anycast_addr, ETH_ALEN), NULL);
new_contents = g_string_new (_("# Created by NetworkManager\n"));
alsoreq = g_ptr_array_sized_new (5);
fqdn_opts = g_ptr_array_sized_new (5);
if (orig_contents) {
char **lines, **line;
@ -244,6 +246,14 @@ nm_dhcp_dhclient_create_config (const char *interface,
continue;
}
/* To let user's FQDN options (except "fqdn.fqdn") override the
* default ones set by NM, add them later
*/
if (!strncmp (p, FQDN_TAG_PREFIX, NM_STRLEN (FQDN_TAG_PREFIX))) {
g_ptr_array_add (fqdn_opts, g_strdup (p + NM_STRLEN (FQDN_TAG_PREFIX)));
continue;
}
/* Ignore 'script' since we pass our own */
if (g_str_has_prefix (p, "script "))
continue;
@ -320,6 +330,16 @@ nm_dhcp_dhclient_create_config (const char *interface,
}
g_ptr_array_free (alsoreq, TRUE);
for (i = 0; i < fqdn_opts->len; i++) {
char *t = g_ptr_array_index (fqdn_opts, i);
if (i == 0)
g_string_append_printf (new_contents, "\n# FQDN options from %s\n", orig_path);
g_string_append_printf (new_contents, FQDN_TAG_PREFIX "%s\n", t);
g_free (t);
}
g_ptr_array_free (fqdn_opts, TRUE);
g_string_append_c (new_contents, '\n');
if (anycast_addr) {

View file

@ -334,6 +334,46 @@ test_fqdn (void)
NULL);
}
static const char *fqdn_options_override_orig = \
"\n"
"send fqdn.fqdn \"foobar.com\"\n" /* NM must ignore this ... */
"send fqdn.encoded off;\n" /* ... and honor these */
"send fqdn.server-update off;\n";
static const char *fqdn_options_override_expected = \
"# Created by NetworkManager\n"
"# Merged from /path/to/dhclient.conf\n"
"\n"
"send fqdn.fqdn \"example2.com\"; # added by NetworkManager\n"
"send fqdn.encoded on;\n"
"send fqdn.server-update on;\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"
"option wpad code 252 = string;\n"
"\n"
"also request rfc3442-classless-static-routes;\n"
"also request ms-classless-static-routes;\n"
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
"\n"
"# FQDN options from /path/to/dhclient.conf\n"
"send fqdn.encoded off;\n"
"send fqdn.server-update off;\n\n";
static void
test_fqdn_options_override (void)
{
test_config (fqdn_options_override_orig,
fqdn_options_override_expected,
FALSE, NULL,
"example2.com", NULL,
NULL,
"eth0",
NULL);
}
/*******************************************/
static const char *override_hostname_orig = \
@ -804,6 +844,7 @@ main (int argc, char **argv)
g_test_add_func ("/dhcp/dhclient/existing-hex-client-id", test_existing_hex_client_id);
g_test_add_func ("/dhcp/dhclient/existing-ascii-client-id", test_existing_ascii_client_id);
g_test_add_func ("/dhcp/dhclient/fqdn", test_fqdn);
g_test_add_func ("/dhcp/dhclient/fqdn_options_override", test_fqdn_options_override);
g_test_add_func ("/dhcp/dhclient/override_hostname", test_override_hostname);
g_test_add_func ("/dhcp/dhclient/override_hostname6", test_override_hostname6);
g_test_add_func ("/dhcp/dhclient/nonfqdn_hostname6", test_nonfqdn_hostname6);