initrd: merge branch 'th/initrd-parse-cleanup'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/282
This commit is contained in:
@@ -683,11 +683,80 @@ nm_utils_ip_is_site_local (int addr_family,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_parse_legacy_addr4 (const char *text, in_addr_t *out_addr)
|
||||
{
|
||||
gs_free char *s_free = NULL;
|
||||
struct in_addr a1;
|
||||
guint8 bin[sizeof (a1)];
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
if (inet_aton (text, &a1) != 1)
|
||||
return FALSE;
|
||||
|
||||
/* OK, inet_aton() accepted the format. That's good, because we want
|
||||
* to accept IPv4 addresses in octal format, like 255.255.000.000.
|
||||
* That's what "legacy" means here. inet_pton() doesn't accept those.
|
||||
*
|
||||
* But inet_aton() also ignores trailing garbage and formats with fewer than
|
||||
* 4 digits. That is just too crazy and we don't do that. Perform additional checks
|
||||
* and reject some forms that inet_aton() accepted.
|
||||
*
|
||||
* Note that we still should (of course) accept everything that inet_pton()
|
||||
* accepts. However this code never gets called if inet_pton() succeeds
|
||||
* (see below, aside the assertion code). */
|
||||
|
||||
if (NM_STRCHAR_ANY (text, ch, ( !(ch >= '0' && ch <= '9')
|
||||
&& !NM_IN_SET (ch, '.', 'x')))) {
|
||||
/* We only accepts '.', digits, and 'x' for "0x". */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s = nm_memdup_maybe_a (300, text, strlen (text) + 1, &s_free);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (bin); i++) {
|
||||
char *current_token = s;
|
||||
gint32 v;
|
||||
|
||||
s = strchr (s, '.');
|
||||
if (s) {
|
||||
s[0] = '\0';
|
||||
s++;
|
||||
}
|
||||
|
||||
if ((i == G_N_ELEMENTS (bin) - 1) != (s == NULL)) {
|
||||
/* Exactly for the last digit, we expect to have no more following token.
|
||||
* But this isn't the case. Abort. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
v = _nm_utils_ascii_str_to_int64 (current_token, 0, 0, 0xFF, -1);
|
||||
if (v == -1) {
|
||||
/* we do accept octal and hex (even with leading "0x"). But something
|
||||
* about this token is wrong. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bin[i] = v;
|
||||
}
|
||||
|
||||
if (memcmp (bin, &a1, sizeof (bin)) != 0) {
|
||||
/* our parsing did not agree with what inet_aton() gave. Something
|
||||
* is wrong. Abort. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*out_addr = a1.s_addr;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_utils_parse_inaddr_bin (int addr_family,
|
||||
const char *text,
|
||||
int *out_addr_family,
|
||||
gpointer out_addr)
|
||||
nm_utils_parse_inaddr_bin_full (int addr_family,
|
||||
gboolean accept_legacy,
|
||||
const char *text,
|
||||
int *out_addr_family,
|
||||
gpointer out_addr)
|
||||
{
|
||||
NMIPAddr addrbin;
|
||||
|
||||
@@ -699,8 +768,26 @@ nm_utils_parse_inaddr_bin (int addr_family,
|
||||
} else
|
||||
g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), FALSE);
|
||||
|
||||
if (inet_pton (addr_family, text, &addrbin) != 1)
|
||||
return FALSE;
|
||||
if (inet_pton (addr_family, text, &addrbin) != 1) {
|
||||
if ( accept_legacy
|
||||
&& addr_family == AF_INET
|
||||
&& _parse_legacy_addr4 (text, &addrbin.addr4)) {
|
||||
/* The address is in some legacy format which inet_aton() accepts, but not inet_pton().
|
||||
* Most likely octal digits (leading zeros). We accept the address. */
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if NM_MORE_ASSERTS > 10
|
||||
if (addr_family == AF_INET) {
|
||||
in_addr_t a;
|
||||
|
||||
/* The legacy parser should accept everything that inet_pton() accepts too. Meaning,
|
||||
* it should strictly parse *more* formats. And of course, parse it the same way. */
|
||||
nm_assert (_parse_legacy_addr4 (text, &a));
|
||||
nm_assert (addrbin.addr4 == a);
|
||||
}
|
||||
#endif
|
||||
|
||||
NM_SET_OUT (out_addr_family, addr_family);
|
||||
if (out_addr)
|
||||
|
@@ -89,6 +89,16 @@ nm_utils_addr_family_to_size (int addr_family)
|
||||
g_return_val_if_reached (0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
nm_utils_addr_family_from_size (gsize len)
|
||||
{
|
||||
switch (len) {
|
||||
case sizeof (in_addr_t): return AF_INET;
|
||||
case sizeof (struct in6_addr): return AF_INET6;
|
||||
}
|
||||
return AF_UNSPEC;
|
||||
}
|
||||
|
||||
#define nm_assert_addr_family(addr_family) \
|
||||
nm_assert (NM_IN_SET ((addr_family), AF_INET, AF_INET6))
|
||||
|
||||
@@ -532,10 +542,19 @@ gboolean nm_utils_ip_is_site_local (int addr_family,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nm_utils_parse_inaddr_bin (int addr_family,
|
||||
const char *text,
|
||||
int *out_addr_family,
|
||||
gpointer out_addr);
|
||||
gboolean nm_utils_parse_inaddr_bin_full (int addr_family,
|
||||
gboolean accept_legacy,
|
||||
const char *text,
|
||||
int *out_addr_family,
|
||||
gpointer out_addr);
|
||||
static inline gboolean
|
||||
nm_utils_parse_inaddr_bin (int addr_family,
|
||||
const char *text,
|
||||
int *out_addr_family,
|
||||
gpointer out_addr)
|
||||
{
|
||||
return nm_utils_parse_inaddr_bin_full (addr_family, FALSE, text, out_addr_family, out_addr);
|
||||
}
|
||||
|
||||
gboolean nm_utils_parse_inaddr (int addr_family,
|
||||
const char *text,
|
||||
|
@@ -51,40 +51,24 @@ dt_get_ipaddr_property (const char *base,
|
||||
const char *prop,
|
||||
int *family)
|
||||
{
|
||||
NMIPAddress *addr;
|
||||
gs_free char *buf = NULL;
|
||||
size_t len;
|
||||
gs_free_error GError *error = NULL;
|
||||
int f;
|
||||
|
||||
if (!dt_get_property (base, dev, prop, &buf, &len))
|
||||
return NULL;
|
||||
|
||||
switch (len) {
|
||||
case 4:
|
||||
if (*family == AF_UNSPEC)
|
||||
*family = AF_INET;
|
||||
break;
|
||||
case 16:
|
||||
if (*family == AF_UNSPEC)
|
||||
*family = AF_INET6;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (*family == AF_UNSPEC) {
|
||||
f = nm_utils_addr_family_from_size (len);
|
||||
if ( f == AF_UNSPEC
|
||||
|| ( *family != AF_UNSPEC
|
||||
&& *family != f)) {
|
||||
_LOGW (LOGD_CORE, "%s: Address %s has unrecognized length (%zd)",
|
||||
dev, prop, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
addr = nm_ip_address_new_binary (*family, buf, 0, &error);
|
||||
if (!addr) {
|
||||
_LOGW (LOGD_CORE, "%s: Address %s is malformed: %s",
|
||||
dev, prop, error->message);
|
||||
}
|
||||
|
||||
return addr;
|
||||
*family = f;
|
||||
return nm_ip_address_new_binary (f, buf, 0, NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -112,30 +96,23 @@ dt_get_hwaddr_property (const char *base,
|
||||
static NMIPAddress *
|
||||
str_addr (const char *str, int *family)
|
||||
{
|
||||
struct in_addr inp;
|
||||
NMIPAddr addr_bin;
|
||||
|
||||
if (*family == AF_UNSPEC)
|
||||
*family = guess_ip_address_family (str);
|
||||
|
||||
if (*family == AF_UNSPEC) {
|
||||
if (!nm_utils_parse_inaddr_bin_full (*family,
|
||||
TRUE,
|
||||
str,
|
||||
family,
|
||||
&addr_bin)) {
|
||||
_LOGW (LOGD_CORE, "Malformed IP address: '%s'", str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*family == AF_INET && inet_aton (str, &inp)) {
|
||||
/* For IPv4, we need to be more tolerant than
|
||||
* nm_ip_address_new(), to recognize things like
|
||||
* the extra zeroes in "255.255.255.000" */
|
||||
return nm_ip_address_new_binary (*family, &inp, 0, NULL);
|
||||
}
|
||||
|
||||
return nm_ip_address_new (*family, str, 0, NULL);
|
||||
return nm_ip_address_new_binary (*family, &addr_bin, 0, NULL);
|
||||
}
|
||||
|
||||
NMConnection *
|
||||
nmi_dt_reader_parse (const char *sysfs_dir)
|
||||
{
|
||||
NMConnection *connection;
|
||||
gs_unref_object NMConnection *connection = NULL;
|
||||
gs_free char *base = NULL;
|
||||
gs_free char *bootpath = NULL;
|
||||
gs_strfreev char **tokens = NULL;
|
||||
@@ -144,9 +121,8 @@ nmi_dt_reader_parse (const char *sysfs_dir)
|
||||
const char *s_ipaddr = NULL;
|
||||
const char *s_netmask = NULL;
|
||||
const char *s_gateway = NULL;
|
||||
NMIPAddress *ipaddr = NULL;
|
||||
NMIPAddress *netmask = NULL;
|
||||
NMIPAddress *gateway = NULL;
|
||||
nm_auto_unref_ip_address NMIPAddress *ipaddr = NULL;
|
||||
nm_auto_unref_ip_address NMIPAddress *gateway = NULL;
|
||||
const char *duplex = NULL;
|
||||
gs_free char *hwaddr = NULL;
|
||||
gs_free char *local_hwaddr = NULL;
|
||||
@@ -279,10 +255,10 @@ nmi_dt_reader_parse (const char *sysfs_dir)
|
||||
connection = nm_simple_connection_new ();
|
||||
|
||||
nm_connection_add_setting (connection,
|
||||
g_object_new (NM_TYPE_SETTING_CONNECTION,
|
||||
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
|
||||
NM_SETTING_CONNECTION_ID, "OpenFirmware Connection",
|
||||
NULL));
|
||||
g_object_new (NM_TYPE_SETTING_CONNECTION,
|
||||
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
|
||||
NM_SETTING_CONNECTION_ID, "OpenFirmware Connection",
|
||||
NULL));
|
||||
|
||||
s_ip4 = nm_setting_ip4_config_new ();
|
||||
nm_connection_add_setting (connection, s_ip4);
|
||||
@@ -298,6 +274,8 @@ nmi_dt_reader_parse (const char *sysfs_dir)
|
||||
bootp = TRUE;
|
||||
|
||||
if (!bootp) {
|
||||
nm_auto_unref_ip_address NMIPAddress *netmask = NULL;
|
||||
|
||||
netmask = dt_get_ipaddr_property (base, "chosen", "netmask-ip", &family);
|
||||
gateway = dt_get_ipaddr_property (base, "chosen", "gateway-ip", &family);
|
||||
if (gateway)
|
||||
@@ -305,9 +283,9 @@ nmi_dt_reader_parse (const char *sysfs_dir)
|
||||
ipaddr = dt_get_ipaddr_property (base, "chosen", "client-ip", &family);
|
||||
|
||||
if (family == AF_UNSPEC) {
|
||||
g_warn_if_fail (netmask == NULL);
|
||||
g_warn_if_fail (ipaddr == NULL);
|
||||
g_warn_if_fail (gateway == NULL);
|
||||
nm_assert (netmask == NULL);
|
||||
nm_assert (gateway == NULL);
|
||||
nm_assert (ipaddr == NULL);
|
||||
|
||||
netmask = str_addr (s_netmask, &family);
|
||||
ipaddr = str_addr (s_ipaddr, &family);
|
||||
@@ -326,11 +304,6 @@ nmi_dt_reader_parse (const char *sysfs_dir)
|
||||
_LOGW (LOGD_CORE, "Unable to determine the network prefix");
|
||||
else
|
||||
nm_ip_address_set_prefix (ipaddr, prefix);
|
||||
|
||||
if (netmask)
|
||||
nm_ip_address_unref (netmask);
|
||||
if (gateway)
|
||||
nm_ip_address_unref (gateway);
|
||||
}
|
||||
|
||||
if (!ipaddr) {
|
||||
@@ -375,9 +348,6 @@ nmi_dt_reader_parse (const char *sysfs_dir)
|
||||
g_object_set (s_ip, NM_SETTING_IP_CONFIG_GATEWAY, s_gateway, NULL);
|
||||
}
|
||||
|
||||
if (ipaddr)
|
||||
nm_ip_address_unref (ipaddr);
|
||||
|
||||
if (duplex || speed || hwaddr || local_hwaddr) {
|
||||
s_wired = nm_setting_wired_new ();
|
||||
nm_connection_add_setting (connection, s_wired);
|
||||
@@ -390,11 +360,11 @@ nmi_dt_reader_parse (const char *sysfs_dir)
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (!nm_connection_normalize (connection, NULL, NULL, &error)) {
|
||||
if (!nm_connection_normalize (connection, NULL, NULL, &error)) {
|
||||
_LOGW (LOGD_CORE, "Generated an invalid connection: %s",
|
||||
error->message);
|
||||
g_clear_pointer (&connection, g_object_unref);
|
||||
}
|
||||
|
||||
return connection;
|
||||
return g_steal_pointer (&connection);
|
||||
}
|
||||
|
Reference in New Issue
Block a user