mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-10 15:10:22 +01:00
dhcp: log messages about invalid DHCP options
Log messages when invalid DHCP options are found. For example: <info> dhcp4 (eth0): error parsing DHCP option 6 (domain_name_servers): address 0.0.0.0 is ignored <info> dhcp4 (eth0): error parsing DHCP option 12 (host_name): '.example.com' is not a valid DNS domain <info> dhcp4 (eth0): error parsing DHCP option 26 (interface_mtu): value 60 is smaller than 68 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1225
This commit is contained in:
parent
d9d72c6ea1
commit
7a3774f62d
4 changed files with 283 additions and 55 deletions
|
|
@ -155,6 +155,7 @@ lease_option_consume_route(const uint8_t **datap,
|
|||
static gboolean
|
||||
lease_parse_address(NDhcp4ClientLease *lease,
|
||||
NML3ConfigData *l3cd,
|
||||
const char *iface,
|
||||
GHashTable *options,
|
||||
in_addr_t *out_address,
|
||||
GError **error)
|
||||
|
|
@ -225,7 +226,12 @@ lease_parse_address(NDhcp4ClientLease *lease,
|
|||
}
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, &l_data, &l_data_len);
|
||||
if (r != 0 || !nm_dhcp_lease_data_parse_in_addr(l_data, l_data_len, &a_netmask)) {
|
||||
if (r != 0
|
||||
|| !nm_dhcp_lease_data_parse_in_addr(l_data,
|
||||
l_data_len,
|
||||
&a_netmask,
|
||||
iface,
|
||||
NM_DHCP_OPTION_DHCP4_SUBNET_MASK)) {
|
||||
nm_utils_error_set_literal(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"could not get netmask from lease");
|
||||
|
|
@ -279,6 +285,7 @@ lease_parse_address(NDhcp4ClientLease *lease,
|
|||
static void
|
||||
lease_parse_address_list(NDhcp4ClientLease *lease,
|
||||
NML3ConfigData *l3cd,
|
||||
const char *iface,
|
||||
NMDhcpOptionDhcp4Options option,
|
||||
GHashTable *options,
|
||||
NMStrBuf *sbuf)
|
||||
|
|
@ -291,8 +298,14 @@ lease_parse_address_list(NDhcp4ClientLease *lease,
|
|||
if (r != 0)
|
||||
return;
|
||||
|
||||
if (l_data_len == 0 || l_data_len % 4 != 0)
|
||||
if (l_data_len == 0 || l_data_len % 4 != 0) {
|
||||
nm_dhcp_lease_log_invalid_option(iface,
|
||||
AF_INET,
|
||||
option,
|
||||
"wrong option length %lu",
|
||||
(unsigned long) l_data_len);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_str_buf_reset(sbuf);
|
||||
|
||||
|
|
@ -308,6 +321,11 @@ lease_parse_address_list(NDhcp4ClientLease *lease,
|
|||
if (addr == 0 || nm_ip4_addr_is_localhost(addr)) {
|
||||
/* Skip localhost addresses, like also networkd does.
|
||||
* See https://github.com/systemd/systemd/issues/4524. */
|
||||
nm_dhcp_lease_log_invalid_option(iface,
|
||||
AF_INET,
|
||||
option,
|
||||
"address %s is ignored",
|
||||
_nm_utils_inet4_ntop(addr, addr_str));
|
||||
continue;
|
||||
}
|
||||
nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr);
|
||||
|
|
@ -499,7 +517,10 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
|||
}
|
||||
|
||||
static void
|
||||
lease_parse_search_domains(NDhcp4ClientLease *lease, NML3ConfigData *l3cd, GHashTable *options)
|
||||
lease_parse_search_domains(NDhcp4ClientLease *lease,
|
||||
NML3ConfigData *l3cd,
|
||||
const char *iface,
|
||||
GHashTable *options)
|
||||
{
|
||||
gs_strfreev char **domains = NULL;
|
||||
const guint8 *l_data;
|
||||
|
|
@ -511,7 +532,11 @@ lease_parse_search_domains(NDhcp4ClientLease *lease, NML3ConfigData *l3cd, GHash
|
|||
if (r != 0)
|
||||
return;
|
||||
|
||||
domains = nm_dhcp_lease_data_parse_search_list(l_data, l_data_len);
|
||||
domains = nm_dhcp_lease_data_parse_search_list(l_data,
|
||||
l_data_len,
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST);
|
||||
|
||||
if (!domains || !domains[0])
|
||||
return;
|
||||
|
|
@ -577,7 +602,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
options = nm_dhcp_option_create_options_dict();
|
||||
|
||||
if (!lease_parse_address(lease, l3cd, options, &lease_address, error))
|
||||
if (!lease_parse_address(lease, l3cd, iface, options, &lease_address, error))
|
||||
return NULL;
|
||||
|
||||
r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s);
|
||||
|
|
@ -589,7 +614,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_BROADCAST, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_in_addr(l_data, l_data_len, &v_inaddr)) {
|
||||
if (r == 0
|
||||
&& nm_dhcp_lease_data_parse_in_addr(l_data,
|
||||
l_data_len,
|
||||
&v_inaddr,
|
||||
iface,
|
||||
NM_DHCP_OPTION_DHCP4_BROADCAST)) {
|
||||
nm_dhcp_option_add_option_in_addr(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_BROADCAST,
|
||||
|
|
@ -598,10 +628,21 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
lease_parse_routes(lease, l3cd, lease_address, options, &sbuf);
|
||||
|
||||
lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options, &sbuf);
|
||||
lease_parse_address_list(lease,
|
||||
l3cd,
|
||||
iface,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
|
||||
options,
|
||||
&sbuf);
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
if (r == 0
|
||||
&& nm_dhcp_lease_data_parse_cstr(l_data,
|
||||
l_data_len,
|
||||
&l_data_len,
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME)) {
|
||||
gs_free const char **domains = NULL;
|
||||
|
||||
nm_str_buf_reset(&sbuf);
|
||||
|
|
@ -617,7 +658,10 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
for (i = 0; domains[i]; i++) {
|
||||
gs_free char *s = NULL;
|
||||
|
||||
s = nm_dhcp_lease_data_parse_domain_validate(domains[i]);
|
||||
s = nm_dhcp_lease_data_parse_domain_validate(domains[i],
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME);
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
|
|
@ -635,10 +679,16 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
}
|
||||
|
||||
lease_parse_search_domains(lease, l3cd, options);
|
||||
lease_parse_search_domains(lease, l3cd, iface, options);
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_mtu(l_data, l_data_len, &v_u16)) {
|
||||
if (r == 0
|
||||
&& nm_dhcp_lease_data_parse_mtu(l_data,
|
||||
l_data_len,
|
||||
&v_u16,
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_INTERFACE_MTU)) {
|
||||
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, v_u16);
|
||||
nm_l3_config_data_set_mtu(l3cd, v_u16);
|
||||
}
|
||||
|
|
@ -651,15 +701,26 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
if (r == 0) {
|
||||
gs_free char *s = NULL;
|
||||
|
||||
if (nm_dhcp_lease_data_parse_domain(l_data, l_data_len, &s)) {
|
||||
if (nm_dhcp_lease_data_parse_domain(l_data,
|
||||
l_data_len,
|
||||
&s,
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_HOST_NAME)) {
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s);
|
||||
}
|
||||
}
|
||||
|
||||
lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
|
||||
lease_parse_address_list(lease, l3cd, iface, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROOT_PATH, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
if (r == 0
|
||||
&& nm_dhcp_lease_data_parse_cstr(l_data,
|
||||
l_data_len,
|
||||
&l_data_len,
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_ROOT_PATH)) {
|
||||
/* https://tools.ietf.org/html/rfc2132#section-3.19
|
||||
*
|
||||
* The path is formatted as a character string consisting of
|
||||
|
|
@ -681,7 +742,13 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
|
||||
&l_data,
|
||||
&l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
if (r == 0
|
||||
&& nm_dhcp_lease_data_parse_cstr(l_data,
|
||||
l_data_len,
|
||||
&l_data_len,
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY)) {
|
||||
/* https://tools.ietf.org/html/draft-ietf-wrec-wpad-01#section-4.4.1
|
||||
*
|
||||
* We reject NUL characters inside the string (except trailing NULs).
|
||||
|
|
@ -701,7 +768,13 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
if (r == 0
|
||||
&& nm_dhcp_lease_data_parse_cstr(l_data,
|
||||
l_data_len,
|
||||
&l_data_len,
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_NIS_DOMAIN)) {
|
||||
gs_free char *to_free = NULL;
|
||||
|
||||
/* https://tools.ietf.org/html/rfc2132#section-8.1 */
|
||||
|
|
@ -727,7 +800,13 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
if (r == 0
|
||||
&& nm_dhcp_lease_data_parse_cstr(l_data,
|
||||
l_data_len,
|
||||
&l_data_len,
|
||||
iface,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME)) {
|
||||
gs_free char *to_free = NULL;
|
||||
|
||||
v_str = nm_utils_buf_utf8safe_escape((char *) l_data,
|
||||
|
|
@ -740,9 +819,14 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
v_str ?: "");
|
||||
}
|
||||
|
||||
lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
|
||||
lease_parse_address_list(lease, l3cd, iface, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
|
||||
|
||||
lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, options, &sbuf);
|
||||
lease_parse_address_list(lease,
|
||||
l3cd,
|
||||
iface,
|
||||
NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER,
|
||||
options,
|
||||
&sbuf);
|
||||
|
||||
lease_parse_private_options(lease, options);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
|
||||
|
||||
#include "nm-dhcp-utils.h"
|
||||
#include "nm-dhcp-options.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-config.h"
|
||||
|
|
@ -884,28 +885,75 @@ nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData *l3cd_old,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nm_dhcp_lease_data_parse_u16(const guint8 *data, gsize n_data, uint16_t *out_val)
|
||||
void
|
||||
nm_dhcp_lease_log_invalid_option(const char *iface,
|
||||
int addr_family,
|
||||
guint option,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
if (n_data != 2)
|
||||
const char *option_name;
|
||||
gs_free char *msg = NULL;
|
||||
va_list ap;
|
||||
|
||||
option_name = nm_dhcp_option_request_string(addr_family, option);
|
||||
|
||||
va_start(ap, fmt);
|
||||
msg = g_strdup_vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
_LOG2I(NM_IS_IPv4(addr_family) ? LOGD_DHCP4 : LOGD_DHCP6,
|
||||
iface,
|
||||
"error parsing DHCP option %d (%s)%s%s",
|
||||
option,
|
||||
option_name,
|
||||
msg ? ": " : "",
|
||||
msg ?: "");
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dhcp_lease_data_parse_u16(const guint8 *data,
|
||||
gsize n_data,
|
||||
uint16_t *out_val,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option)
|
||||
{
|
||||
if (n_data != 2) {
|
||||
nm_dhcp_lease_log_invalid_option(iface,
|
||||
addr_family,
|
||||
option,
|
||||
"invalid option length %lu",
|
||||
(unsigned long) n_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*out_val = unaligned_read_be16(data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dhcp_lease_data_parse_mtu(const guint8 *data, gsize n_data, uint16_t *out_val)
|
||||
nm_dhcp_lease_data_parse_mtu(const guint8 *data,
|
||||
gsize n_data,
|
||||
uint16_t *out_val,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option)
|
||||
{
|
||||
uint16_t mtu;
|
||||
|
||||
if (!nm_dhcp_lease_data_parse_u16(data, n_data, &mtu))
|
||||
if (!nm_dhcp_lease_data_parse_u16(data, n_data, &mtu, iface, addr_family, option))
|
||||
return FALSE;
|
||||
|
||||
if (mtu < 68) {
|
||||
/* https://tools.ietf.org/html/rfc2132#section-5.1:
|
||||
*
|
||||
* The minimum legal value for the MTU is 68. */
|
||||
nm_dhcp_lease_log_invalid_option(iface,
|
||||
addr_family,
|
||||
option,
|
||||
"value %u is smaller than 68",
|
||||
mtu);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -914,7 +962,12 @@ nm_dhcp_lease_data_parse_mtu(const guint8 *data, gsize n_data, uint16_t *out_val
|
|||
}
|
||||
|
||||
gboolean
|
||||
nm_dhcp_lease_data_parse_cstr(const guint8 *data, gsize n_data, gsize *out_new_len)
|
||||
nm_dhcp_lease_data_parse_cstr(const guint8 *data,
|
||||
gsize n_data,
|
||||
gsize *out_new_len,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option)
|
||||
{
|
||||
/* WARNING: this function only validates that the string does not contain
|
||||
* NUL characters (and ignores trailing NULs). It does not check character
|
||||
|
|
@ -929,6 +982,10 @@ nm_dhcp_lease_data_parse_cstr(const guint8 *data, gsize n_data, gsize *out_new_l
|
|||
*
|
||||
* https://tools.ietf.org/html/rfc2132#section-2
|
||||
* https://github.com/systemd/systemd/issues/1337 */
|
||||
nm_dhcp_lease_log_invalid_option(iface,
|
||||
addr_family,
|
||||
option,
|
||||
"string contains embedded NUL");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -938,32 +995,47 @@ nm_dhcp_lease_data_parse_cstr(const guint8 *data, gsize n_data, gsize *out_new_l
|
|||
}
|
||||
|
||||
char *
|
||||
nm_dhcp_lease_data_parse_domain_validate(const char *str)
|
||||
nm_dhcp_lease_data_parse_domain_validate(const char *str,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option)
|
||||
{
|
||||
gs_free char *s = NULL;
|
||||
|
||||
s = nm_sd_dns_name_normalize(str);
|
||||
if (!s)
|
||||
return NULL;
|
||||
goto err;
|
||||
|
||||
if (nm_str_is_empty(s) || (s[0] == '.' && s[1] == '\0')) {
|
||||
/* root domains are not allowed. */
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (nm_utils_is_localhost(s))
|
||||
return NULL;
|
||||
goto err;
|
||||
|
||||
if (!g_utf8_validate(s, -1, NULL)) {
|
||||
/* the result must be valid UTF-8. */
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return g_steal_pointer(&s);
|
||||
err:
|
||||
nm_dhcp_lease_log_invalid_option(iface,
|
||||
addr_family,
|
||||
option,
|
||||
"'%s' is not a valid DNS domain",
|
||||
str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dhcp_lease_data_parse_domain(const guint8 *data, gsize n_data, char **out_val)
|
||||
nm_dhcp_lease_data_parse_domain(const guint8 *data,
|
||||
gsize n_data,
|
||||
char **out_val,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option)
|
||||
{
|
||||
gs_free char *str1_free = NULL;
|
||||
const char *str1;
|
||||
|
|
@ -971,7 +1043,7 @@ nm_dhcp_lease_data_parse_domain(const guint8 *data, gsize n_data, char **out_val
|
|||
|
||||
/* this is mostly the same as systemd's lease_parse_domain(). */
|
||||
|
||||
if (!nm_dhcp_lease_data_parse_cstr(data, n_data, &n_data))
|
||||
if (!nm_dhcp_lease_data_parse_cstr(data, n_data, &n_data, iface, addr_family, option))
|
||||
return FALSE;
|
||||
|
||||
if (n_data == 0) {
|
||||
|
|
@ -983,12 +1055,13 @@ nm_dhcp_lease_data_parse_domain(const guint8 *data, gsize n_data, char **out_val
|
|||
*
|
||||
* Note that this is *after* we potentially stripped trailing NULs.
|
||||
*/
|
||||
nm_dhcp_lease_log_invalid_option(iface, addr_family, option, "empty value");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
str1 = nm_strndup_a(300, (char *) data, n_data, &str1_free);
|
||||
|
||||
s = nm_dhcp_lease_data_parse_domain_validate(str1);
|
||||
s = nm_dhcp_lease_data_parse_domain_validate(str1, iface, addr_family, option);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -997,7 +1070,11 @@ 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)
|
||||
nm_dhcp_lease_data_parse_in_addr(const guint8 *data,
|
||||
gsize n_data,
|
||||
in_addr_t *out_val,
|
||||
const char *iface,
|
||||
guint option)
|
||||
{
|
||||
/* - option 1, https://tools.ietf.org/html/rfc2132#section-3.3
|
||||
* - option 28, https://tools.ietf.org/html/rfc2132#section-5.3
|
||||
|
|
@ -1007,8 +1084,14 @@ nm_dhcp_lease_data_parse_in_addr(const guint8 *data, gsize n_data, in_addr_t *ou
|
|||
* according to RFC 3396 section 7. Therefore, it's possible that a
|
||||
* option carrying a IPv4 address has a length > 4.
|
||||
*/
|
||||
if (n_data < 4)
|
||||
if (n_data < 4) {
|
||||
nm_dhcp_lease_log_invalid_option(iface,
|
||||
AF_INET,
|
||||
option,
|
||||
"invalid address length %lu",
|
||||
(unsigned long) n_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*out_val = unaligned_read_ne32(data);
|
||||
return TRUE;
|
||||
|
|
@ -1051,7 +1134,8 @@ static char *
|
|||
lease_option_print_domain_name(const uint8_t *cache,
|
||||
size_t *n_cachep,
|
||||
const uint8_t **datap,
|
||||
size_t *n_datap)
|
||||
size_t *n_datap,
|
||||
gboolean *invalid)
|
||||
{
|
||||
nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_40, FALSE);
|
||||
const uint8_t *domain;
|
||||
|
|
@ -1062,6 +1146,8 @@ lease_option_print_domain_name(const uint8_t *cache,
|
|||
gboolean first = TRUE;
|
||||
uint8_t c;
|
||||
|
||||
NM_SET_OUT(invalid, FALSE);
|
||||
|
||||
/*
|
||||
* We are given two adjacent memory regions. The @cache contains alreday parsed
|
||||
* domain names, and the @datap contains the remaining data to parse.
|
||||
|
|
@ -1078,8 +1164,10 @@ lease_option_print_domain_name(const uint8_t *cache,
|
|||
* 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)
|
||||
if (cache + n_cache != *datap) {
|
||||
NM_SET_OUT(invalid, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!nm_dhcp_lease_data_consume(domainp, n_domainp, &c, sizeof(c)))
|
||||
|
|
@ -1104,8 +1192,10 @@ lease_option_print_domain_name(const uint8_t *cache,
|
|||
else
|
||||
first = FALSE;
|
||||
|
||||
if (!lease_option_print_label(&sbuf, n_label, domainp, n_domainp))
|
||||
if (!lease_option_print_label(&sbuf, n_label, domainp, n_domainp)) {
|
||||
NM_SET_OUT(invalid, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -1118,13 +1208,17 @@ lease_option_print_domain_name(const uint8_t *cache,
|
|||
* two high bits are masked out.
|
||||
*/
|
||||
|
||||
if (!nm_dhcp_lease_data_consume(domainp, n_domainp, &c, sizeof(c)))
|
||||
if (!nm_dhcp_lease_data_consume(domainp, n_domainp, &c, sizeof(c))) {
|
||||
NM_SET_OUT(invalid, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offset += c;
|
||||
|
||||
if (offset >= n_cache)
|
||||
if (offset >= n_cache) {
|
||||
NM_SET_OUT(invalid, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
domain = cache + offset;
|
||||
n_domain = n_cache - offset;
|
||||
|
|
@ -1136,29 +1230,44 @@ lease_option_print_domain_name(const uint8_t *cache,
|
|||
break;
|
||||
}
|
||||
default:
|
||||
NM_SET_OUT(invalid, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char **
|
||||
nm_dhcp_lease_data_parse_search_list(const guint8 *data, gsize n_data)
|
||||
nm_dhcp_lease_data_parse_search_list(const guint8 *data,
|
||||
gsize n_data,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option)
|
||||
{
|
||||
GPtrArray *array = NULL;
|
||||
const guint8 *cache = data;
|
||||
gsize n_cache = 0;
|
||||
guint i = 0;
|
||||
|
||||
for (;;) {
|
||||
gs_free char *s = NULL;
|
||||
gboolean invalid;
|
||||
|
||||
s = lease_option_print_domain_name(cache, &n_cache, &data, &n_data);
|
||||
if (!s)
|
||||
s = lease_option_print_domain_name(cache, &n_cache, &data, &n_data, &invalid);
|
||||
if (!s) {
|
||||
if (iface && invalid)
|
||||
nm_dhcp_lease_log_invalid_option(iface,
|
||||
addr_family,
|
||||
option,
|
||||
"search domain #%u is invalid",
|
||||
i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!array)
|
||||
array = g_ptr_array_new();
|
||||
|
||||
g_ptr_array_add(array, g_steal_pointer(&s));
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!array)
|
||||
|
|
|
|||
|
|
@ -59,13 +59,48 @@ nm_dhcp_lease_data_consume_in_addr(const uint8_t **datap, size_t *n_datap, in_ad
|
|||
return nm_dhcp_lease_data_consume(datap, n_datap, addrp, sizeof(struct in_addr));
|
||||
}
|
||||
|
||||
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);
|
||||
gboolean nm_dhcp_lease_data_parse_mtu(const guint8 *data, gsize n_data, guint16 *out_val);
|
||||
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);
|
||||
void nm_dhcp_lease_log_invalid_option(const char *iface,
|
||||
int addr_family,
|
||||
guint option,
|
||||
const char *fmt,
|
||||
...) G_GNUC_PRINTF(4, 5);
|
||||
char *nm_dhcp_lease_data_parse_domain_validate(const char *str,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option);
|
||||
gboolean nm_dhcp_lease_data_parse_u16(const guint8 *data,
|
||||
gsize n_data,
|
||||
guint16 *out_val,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option);
|
||||
gboolean nm_dhcp_lease_data_parse_mtu(const guint8 *data,
|
||||
gsize n_data,
|
||||
guint16 *out_val,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option);
|
||||
gboolean nm_dhcp_lease_data_parse_cstr(const guint8 *data,
|
||||
gsize n_data,
|
||||
gsize *out_new_len,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option);
|
||||
gboolean nm_dhcp_lease_data_parse_domain(const guint8 *data,
|
||||
gsize n_data,
|
||||
char **out_val,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option);
|
||||
gboolean nm_dhcp_lease_data_parse_in_addr(const guint8 *data,
|
||||
gsize n_data,
|
||||
in_addr_t *out_val,
|
||||
const char *iface,
|
||||
guint option);
|
||||
char **nm_dhcp_lease_data_parse_search_list(const guint8 *data,
|
||||
gsize n_data,
|
||||
const char *iface,
|
||||
int addr_family,
|
||||
guint option);
|
||||
|
||||
#endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ test_parse_search_list(void)
|
|||
char **domains;
|
||||
|
||||
data = (guint8[]){0x05, 'l', 'o', 'c', 'a', 'l', 0x00};
|
||||
domains = nm_dhcp_lease_data_parse_search_list(data, 7);
|
||||
domains = nm_dhcp_lease_data_parse_search_list(data, 7, NULL, 0, 0);
|
||||
g_assert(domains);
|
||||
g_assert_cmpint(g_strv_length(domains), ==, 1);
|
||||
g_assert_cmpstr(domains[0], ==, "local");
|
||||
|
|
@ -205,7 +205,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_lease_data_parse_search_list(data, 34);
|
||||
domains = nm_dhcp_lease_data_parse_search_list(data, 34, NULL, 0, 0);
|
||||
g_assert(domains);
|
||||
g_assert_cmpint(g_strv_length(domains), ==, 4);
|
||||
g_assert_cmpstr(domains[0], ==, "test.example.com");
|
||||
|
|
@ -220,7 +220,7 @@ test_parse_search_list(void)
|
|||
'a',
|
||||
'd',
|
||||
};
|
||||
domains = nm_dhcp_lease_data_parse_search_list(data, 4);
|
||||
domains = nm_dhcp_lease_data_parse_search_list(data, 4, NULL, 0, 0);
|
||||
g_assert(!domains);
|
||||
|
||||
data = (guint8[]){
|
||||
|
|
@ -235,7 +235,7 @@ test_parse_search_list(void)
|
|||
'a',
|
||||
'd',
|
||||
};
|
||||
domains = nm_dhcp_lease_data_parse_search_list(data, 10);
|
||||
domains = nm_dhcp_lease_data_parse_search_list(data, 10, NULL, 0, 0);
|
||||
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