diff options
author | Thomas Haller <thaller@redhat.com> | 2021-02-10 16:50:34 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2021-02-11 09:23:16 +0100 |
commit | 6e0d2e5850594b136b5da9ff2f337a85e8afd8c1 (patch) | |
tree | 378f54417fe57806bd5f6fffa0ddd11ca99a0755 | |
parent | 67dd25a396588070d12d0ab1e975679833f49842 (diff) | |
download | NetworkManager-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.c | 155 | ||||
-rw-r--r-- | src/core/dhcp/nm-dhcp-utils.c | 155 | ||||
-rw-r--r-- | src/core/dhcp/nm-dhcp-utils.h | 15 | ||||
-rw-r--r-- | src/core/dhcp/tests/test-dhcp-utils.c | 8 |
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"); |