mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-04-20 16:31:41 +02:00
dhcp/nettools: move nm_dhcp_lease_data_parse_search_list() to nm-dhcp-utils.c
This commit is contained in:
parent
67dd25a396
commit
6e0d2e5850
4 changed files with 173 additions and 160 deletions
|
|
@ -158,130 +158,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,
|
||||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue