diff options
Diffstat (limited to 'src/dhcp-manager/nm-dhcp-dhclient-utils.c')
-rw-r--r-- | src/dhcp-manager/nm-dhcp-dhclient-utils.c | 133 |
1 files changed, 94 insertions, 39 deletions
diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c index a53e95b009..0a5f6ce4a6 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient-utils.c +++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c @@ -26,14 +26,13 @@ #include <arpa/inet.h> #include "nm-dhcp-dhclient-utils.h" +#include "nm-dhcp-utils.h" #include "nm-ip4-config.h" #include "nm-utils.h" #include "nm-platform.h" #include "NetworkManagerUtils.h" #define CLIENTID_TAG "send dhcp-client-identifier" -#define CLIENTID_FORMAT CLIENTID_TAG " \"%s\"; # added by NetworkManager" -#define CLIENTID_FORMAT_OCTETS CLIENTID_TAG " %s; # added by NetworkManager" #define HOSTNAME4_TAG "send host-name" #define HOSTNAME4_FORMAT HOSTNAME4_TAG " \"%s\"; # added by NetworkManager" @@ -73,40 +72,39 @@ add_hostname (GString *str, const char *format, const char *hostname) } static void -add_ip4_config (GString *str, const char *dhcp_client_id, const char *hostname) +add_ip4_config (GString *str, GBytes *client_id, const char *hostname) { - if (dhcp_client_id && *dhcp_client_id) { - gboolean is_octets = TRUE; - int i = 0; + if (client_id) { + const char *p; + gsize l; + guint i; - while (dhcp_client_id[i]) { - if (!g_ascii_isxdigit (dhcp_client_id[i])) { - is_octets = FALSE; - break; - } - i++; - if (!dhcp_client_id[i]) - break; - if (g_ascii_isxdigit (dhcp_client_id[i])) { - i++; - if (!dhcp_client_id[i]) - break; - } - if (dhcp_client_id[i] != ':') { - is_octets = FALSE; + p = g_bytes_get_data (client_id, &l); + g_assert (p); + + /* Allow type 0 (non-hardware address) to be represented as a string + * as long as all the characters are printable. + */ + for (i = 1; (p[0] == 0) && i < l; i++) { + if (!g_ascii_isprint (p[i])) break; - } - i++; } - /* If the client ID is just hex digits and : then don't use quotes, - * because dhclient expects either a quoted ASCII string, or a byte - * array formated as hex octets separated by : - */ - if (is_octets) - g_string_append_printf (str, CLIENTID_FORMAT_OCTETS "\n", dhcp_client_id); - else - g_string_append_printf (str, CLIENTID_FORMAT "\n", dhcp_client_id); + g_string_append (str, CLIENTID_TAG " "); + if (i < l) { + /* Unprintable; convert to a hex string */ + for (i = 0; i < l; i++) { + if (i > 0) + g_string_append_c (str, ':'); + g_string_append_printf (str, "%02x", (guint8) p[i]); + } + } else { + /* Printable; just add to the line minus the 'type' */ + g_string_append_c (str, '"'); + g_string_append_len (str, p + 1, l - 1); + g_string_append_c (str, '"'); + } + g_string_append (str, "; # added by NetworkManager\n"); } add_hostname (str, HOSTNAME4_FORMAT "\n", hostname); @@ -134,14 +132,67 @@ add_ip6_config (GString *str, const char *hostname) "send fqdn.server-update on;\n"); } +static GBytes * +read_client_id (const char *str) +{ + gs_free char *s = NULL; + char *p; + + g_assert (!strncmp (str, CLIENTID_TAG, STRLEN (CLIENTID_TAG))); + + str += STRLEN (CLIENTID_TAG); + while (g_ascii_isspace (*str)) + str++; + + if (*str == '"') { + s = g_strdup (str + 1); + p = strrchr (s, '"'); + if (p) + *p = '\0'; + else + return NULL; + } else + s = g_strdup (str); + + g_strchomp (s); + if (s[strlen (s) - 1] == ';') + s[strlen (s) - 1] = '\0'; + + return nm_dhcp_utils_client_id_string_to_bytes (s); +} + +GBytes * +nm_dhcp_dhclient_get_client_id_from_config_file (const char *path) +{ + gs_free char *contents = NULL; + gs_strfreev char **lines = NULL; + char **line; + + g_return_val_if_fail (path != NULL, NULL); + + if (!g_file_test (path, G_FILE_TEST_EXISTS)) + return NULL; + + if (!g_file_get_contents (path, &contents, NULL, NULL)) + return NULL; + + lines = g_strsplit_set (contents, "\n\r", 0); + for (line = lines; lines && *line; line++) { + if (!strncmp (*line, CLIENTID_TAG, STRLEN (CLIENTID_TAG))) + return read_client_id (*line); + } + return NULL; +} + char * nm_dhcp_dhclient_create_config (const char *interface, gboolean is_ip6, - const char *dhcp_client_id, + GBytes *client_id, const char *anycast_addr, const char *hostname, const char *orig_path, - const char *orig_contents) + const char *orig_contents, + GBytes **out_new_client_id) { GString *new_contents; GPtrArray *alsoreq; @@ -165,11 +216,15 @@ nm_dhcp_dhclient_create_config (const char *interface, if (!strlen (g_strstrip (p))) continue; - /* Override config file "dhcp-client-id" and use one from the - * connection. - */ - if (dhcp_client_id && !strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) - continue; + if (!strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) { + /* Override config file "dhcp-client-id" and use one from the connection */ + if (client_id) + continue; + + /* Otherwise capture and return the existing client id */ + if (out_new_client_id) + *out_new_client_id = read_client_id (p); + } /* Override config file hostname and use one from the connection */ if (hostname) { @@ -238,7 +293,7 @@ nm_dhcp_dhclient_create_config (const char *interface, add_also_request (alsoreq, "dhcp6.domain-search"); add_also_request (alsoreq, "dhcp6.client-id"); } else { - add_ip4_config (new_contents, dhcp_client_id, hostname); + add_ip4_config (new_contents, client_id, hostname); add_also_request (alsoreq, "rfc3442-classless-static-routes"); add_also_request (alsoreq, "ms-classless-static-routes"); add_also_request (alsoreq, "static-routes"); |