summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-02-10 16:50:34 +0100
committerThomas Haller <thaller@redhat.com>2021-02-11 09:23:16 +0100
commit6e0d2e5850594b136b5da9ff2f337a85e8afd8c1 (patch)
tree378f54417fe57806bd5f6fffa0ddd11ca99a0755
parent67dd25a396588070d12d0ab1e975679833f49842 (diff)
downloadNetworkManager-6e0d2e5850594b136b5da9ff2f337a85e8afd8c1.tar.gz
dhcp/nettools: move nm_dhcp_lease_data_parse_search_list() to nm-dhcp-utils.c
-rw-r--r--src/core/dhcp/nm-dhcp-nettools.c155
-rw-r--r--src/core/dhcp/nm-dhcp-utils.c155
-rw-r--r--src/core/dhcp/nm-dhcp-utils.h15
-rw-r--r--src/core/dhcp/tests/test-dhcp-utils.c8
4 files changed, 173 insertions, 160 deletions
diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c
index 1381de47ae..0329030fac 100644
--- a/src/core/dhcp/nm-dhcp-nettools.c
+++ b/src/core/dhcp/nm-dhcp-nettools.c
@@ -159,130 +159,6 @@ lease_option_consume_route(uint8_t ** datap,
/*****************************************************************************/
static gboolean
-lease_option_print_label(GString *str, size_t n_label, uint8_t **datap, size_t *n_datap)
-{
- for (size_t i = 0; i < n_label; ++i) {
- uint8_t c;
-
- if (!lease_option_consume(datap, n_datap, &c, sizeof(c)))
- return FALSE;
-
- switch (c) {
- case 'a' ... 'z':
- case 'A' ... 'Z':
- case '0' ... '9':
- case '-':
- case '_':
- g_string_append_c(str, c);
- break;
- case '.':
- case '\\':
- g_string_append_printf(str, "\\%c", c);
- break;
- default:
- g_string_append_printf(str, "\\%3d", c);
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-lease_option_print_domain_name(GString * str,
- uint8_t * cache,
- size_t * n_cachep,
- uint8_t **datap,
- size_t * n_datap)
-{
- uint8_t * domain;
- size_t n_domain, n_cache = *n_cachep;
- uint8_t **domainp = datap;
- size_t * n_domainp = n_datap;
- gboolean first = TRUE;
- uint8_t c;
-
- /*
- * We are given two adjacent memory regions. The @cache contains alreday parsed
- * domain names, and the @datap contains the remaining data to parse.
- *
- * A domain name is formed from a sequence of labels. Each label start with
- * a length byte, where the two most significant bits are unset. A zero-length
- * label indicates the end of the domain name.
- *
- * Alternatively, a label can be followed by an offset (indicated by the two
- * most significant bits being set in the next byte that is read). The offset
- * is an offset into the cache, where the next label of the domain name can
- * be found.
- *
- * Note, that each time a jump to an offset is performed, the size of the
- * cache shrinks, so this is guaranteed to terminate.
- */
- if (cache + n_cache != *datap)
- return FALSE;
-
- for (;;) {
- if (!lease_option_consume(domainp, n_domainp, &c, sizeof(c)))
- return FALSE;
-
- switch (c & 0xC0) {
- case 0x00: /* label length */
- {
- size_t n_label = c;
-
- if (n_label == 0) {
- /*
- * We reached the final label of the domain name. Adjust
- * the cache to include the consumed data, and return.
- */
- *n_cachep = *datap - cache;
- return TRUE;
- }
-
- if (!first)
- g_string_append_c(str, '.');
- else
- first = FALSE;
-
- if (!lease_option_print_label(str, n_label, domainp, n_domainp))
- return FALSE;
-
- break;
- }
- case 0xC0: /* back pointer */
- {
- size_t offset = (c & 0x3F) << 16;
-
- /*
- * The offset is given as two bytes (in big endian), where the
- * two high bits are masked out.
- */
-
- if (!lease_option_consume(domainp, n_domainp, &c, sizeof(c)))
- return FALSE;
-
- offset += c;
-
- if (offset >= n_cache)
- return FALSE;
-
- domain = cache + offset;
- n_domain = n_cache - offset;
- n_cache = offset;
-
- domainp = &domain;
- n_domainp = &n_domain;
-
- break;
- }
- default:
- return FALSE;
- }
- }
-}
-
-/*****************************************************************************/
-
-static gboolean
lease_parse_address(NDhcp4ClientLease *lease,
NMIP4Config * ip4_config,
GHashTable * options,
@@ -623,35 +499,6 @@ lease_parse_routes(NDhcp4ClientLease *lease,
/*****************************************************************************/
-char **
-nm_dhcp_parse_search_list(guint8 *data, size_t n_data)
-{
- GPtrArray *array = NULL;
- guint8 * cache = data;
- size_t n_cache = 0;
-
- for (;;) {
- nm_auto_free_gstring GString *domain = NULL;
-
- nm_gstring_prepare(&domain);
-
- if (!lease_option_print_domain_name(domain, cache, &n_cache, &data, &n_data))
- break;
-
- if (!array)
- array = g_ptr_array_new();
-
- g_ptr_array_add(array, g_string_free(domain, FALSE));
- domain = NULL;
- }
-
- if (array) {
- g_ptr_array_add(array, NULL);
- return (char **) g_ptr_array_free(array, FALSE);
- } else
- return NULL;
-}
-
static void
lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options)
{
@@ -666,7 +513,7 @@ lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GH
if (r)
return;
- domains = nm_dhcp_parse_search_list(data, n_data);
+ domains = nm_dhcp_lease_data_parse_search_list(data, n_data);
nm_gstring_prepare(&str);
for (i = 0; domains && domains[i]; i++) {
diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c
index b3b0678dc8..6cddb2d5f1 100644
--- a/src/core/dhcp/nm-dhcp-utils.c
+++ b/src/core/dhcp/nm-dhcp-utils.c
@@ -964,3 +964,158 @@ nm_dhcp_lease_data_parse_in_addr(const guint8 *data, gsize n_data, in_addr_t *ou
*out_val = unaligned_read_ne32(data);
return TRUE;
}
+
+/*****************************************************************************/
+
+static gboolean
+lease_option_print_label(GString *str, size_t n_label, const uint8_t **datap, size_t *n_datap)
+{
+ gsize i;
+
+ for (i = 0; i < n_label; ++i) {
+ uint8_t c = 0;
+
+ if (!nm_dhcp_lease_data_consume(datap, n_datap, &c, sizeof(c)))
+ return FALSE;
+
+ switch (c) {
+ case 'a' ... 'z':
+ case 'A' ... 'Z':
+ case '0' ... '9':
+ case '-':
+ case '_':
+ g_string_append_c(str, c);
+ break;
+ case '.':
+ case '\\':
+ g_string_append_printf(str, "\\%c", c);
+ break;
+ default:
+ g_string_append_printf(str, "\\%3d", c);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+lease_option_print_domain_name(GString * str,
+ const uint8_t * cache,
+ size_t * n_cachep,
+ const uint8_t **datap,
+ size_t * n_datap)
+{
+ const uint8_t * domain;
+ size_t n_domain, n_cache = *n_cachep;
+ const uint8_t **domainp = datap;
+ size_t * n_domainp = n_datap;
+ gboolean first = TRUE;
+ uint8_t c;
+
+ /*
+ * We are given two adjacent memory regions. The @cache contains alreday parsed
+ * domain names, and the @datap contains the remaining data to parse.
+ *
+ * A domain name is formed from a sequence of labels. Each label start with
+ * a length byte, where the two most significant bits are unset. A zero-length
+ * label indicates the end of the domain name.
+ *
+ * Alternatively, a label can be followed by an offset (indicated by the two
+ * most significant bits being set in the next byte that is read). The offset
+ * is an offset into the cache, where the next label of the domain name can
+ * be found.
+ *
+ * Note, that each time a jump to an offset is performed, the size of the
+ * cache shrinks, so this is guaranteed to terminate.
+ */
+ if (cache + n_cache != *datap)
+ return FALSE;
+
+ for (;;) {
+ if (!nm_dhcp_lease_data_consume(domainp, n_domainp, &c, sizeof(c)))
+ return FALSE;
+
+ switch (c & 0xC0) {
+ case 0x00: /* label length */
+ {
+ size_t n_label = c;
+
+ if (n_label == 0) {
+ /*
+ * We reached the final label of the domain name. Adjust
+ * the cache to include the consumed data, and return.
+ */
+ *n_cachep = *datap - cache;
+ return TRUE;
+ }
+
+ if (!first)
+ g_string_append_c(str, '.');
+ else
+ first = FALSE;
+
+ if (!lease_option_print_label(str, n_label, domainp, n_domainp))
+ return FALSE;
+
+ break;
+ }
+ case 0xC0: /* back pointer */
+ {
+ size_t offset = (c & 0x3F) << 16;
+
+ /*
+ * The offset is given as two bytes (in big endian), where the
+ * two high bits are masked out.
+ */
+
+ if (!nm_dhcp_lease_data_consume(domainp, n_domainp, &c, sizeof(c)))
+ return FALSE;
+
+ offset += c;
+
+ if (offset >= n_cache)
+ return FALSE;
+
+ domain = cache + offset;
+ n_domain = n_cache - offset;
+ n_cache = offset;
+
+ domainp = &domain;
+ n_domainp = &n_domain;
+
+ break;
+ }
+ default:
+ return FALSE;
+ }
+ }
+}
+
+char **
+nm_dhcp_lease_data_parse_search_list(const guint8 *data, gsize n_data)
+{
+ GPtrArray * array = NULL;
+ const guint8 *cache = data;
+ gsize n_cache = 0;
+
+ for (;;) {
+ nm_auto_free_gstring GString *domain = NULL;
+
+ nm_gstring_prepare(&domain);
+
+ if (!lease_option_print_domain_name(domain, cache, &n_cache, &data, &n_data))
+ break;
+
+ if (!array)
+ array = g_ptr_array_new();
+
+ g_ptr_array_add(array, g_string_free(domain, FALSE));
+ domain = NULL;
+ }
+
+ if (array) {
+ g_ptr_array_add(array, NULL);
+ return (char **) g_ptr_array_free(array, FALSE);
+ } else
+ return NULL;
+}
diff --git a/src/core/dhcp/nm-dhcp-utils.h b/src/core/dhcp/nm-dhcp-utils.h
index 30f850ce1e..45f74b35d1 100644
--- a/src/core/dhcp/nm-dhcp-utils.h
+++ b/src/core/dhcp/nm-dhcp-utils.h
@@ -36,12 +36,22 @@ gboolean nm_dhcp_utils_get_leasefile_path(int addr_family,
const char *uuid,
char ** out_leasefile_path);
-char **nm_dhcp_parse_search_list(guint8 *data, size_t n_data);
-
char *nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease);
/*****************************************************************************/
+static inline gboolean
+nm_dhcp_lease_data_consume(const uint8_t **datap, size_t *n_datap, void *out, size_t n_out)
+{
+ if (*n_datap < n_out)
+ return FALSE;
+
+ memcpy(out, *datap, n_out);
+ *datap += n_out;
+ *n_datap -= n_out;
+ return TRUE;
+}
+
char *nm_dhcp_lease_data_parse_domain_validate(const char *str);
gboolean nm_dhcp_lease_data_parse_u16(const guint8 *data, gsize n_data, guint16 *out_val);
@@ -49,5 +59,6 @@ gboolean nm_dhcp_lease_data_parse_mtu(const guint8 *data, gsize n_data, guint16
gboolean nm_dhcp_lease_data_parse_cstr(const guint8 *data, gsize n_data, gsize *out_new_len);
gboolean nm_dhcp_lease_data_parse_domain(const guint8 *data, gsize n_data, char **out_val);
gboolean nm_dhcp_lease_data_parse_in_addr(const guint8 *data, gsize n_data, in_addr_t *out_val);
+char ** nm_dhcp_lease_data_parse_search_list(const guint8 *data, gsize n_data);
#endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */
diff --git a/src/core/dhcp/tests/test-dhcp-utils.c b/src/core/dhcp/tests/test-dhcp-utils.c
index 02fe640660..a45e7f118f 100644
--- a/src/core/dhcp/tests/test-dhcp-utils.c
+++ b/src/core/dhcp/tests/test-dhcp-utils.c
@@ -202,7 +202,7 @@ test_parse_search_list(void)
char ** domains;
data = (guint8[]){0x05, 'l', 'o', 'c', 'a', 'l', 0x00};
- domains = nm_dhcp_parse_search_list(data, 7);
+ domains = nm_dhcp_lease_data_parse_search_list(data, 7);
g_assert(domains);
g_assert_cmpint(g_strv_length(domains), ==, 1);
g_assert_cmpstr(domains[0], ==, "local");
@@ -211,7 +211,7 @@ test_parse_search_list(void)
data = (guint8[]){0x04, 't', 'e', 's', 't', 0x07, 'e', 'x', 'a', 'm', 'p', 'l',
'e', 0x03, 'c', 'o', 'm', 0x00, 0xc0, 0x05, 0x03, 'a', 'b', 'c',
0xc0, 0x0d, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x00};
- domains = nm_dhcp_parse_search_list(data, 34);
+ domains = nm_dhcp_lease_data_parse_search_list(data, 34);
g_assert(domains);
g_assert_cmpint(g_strv_length(domains), ==, 4);
g_assert_cmpstr(domains[0], ==, "test.example.com");
@@ -226,7 +226,7 @@ test_parse_search_list(void)
'a',
'd',
};
- domains = nm_dhcp_parse_search_list(data, 4);
+ domains = nm_dhcp_lease_data_parse_search_list(data, 4);
g_assert(!domains);
data = (guint8[]){
@@ -241,7 +241,7 @@ test_parse_search_list(void)
'a',
'd',
};
- domains = nm_dhcp_parse_search_list(data, 10);
+ domains = nm_dhcp_lease_data_parse_search_list(data, 10);
g_assert(domains);
g_assert_cmpint(g_strv_length(domains), ==, 1);
g_assert_cmpstr(domains[0], ==, "okay");