summaryrefslogtreecommitdiff
path: root/src/dhcp-manager/nm-dhcp-dhclient-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dhcp-manager/nm-dhcp-dhclient-utils.c')
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient-utils.c133
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");