merge branch 'jk/keyfile-mac-fix' (bgo #730514)

https://bugzilla.gnome.org/show_bug.cgi?id=730514
This commit is contained in:
Thomas Haller 2014-05-29 19:01:35 +02:00
commit b5a94ae479
8 changed files with 184 additions and 44 deletions

View file

@ -880,8 +880,8 @@ vpn_data_item (const char *key, const char *value, gpointer user_data)
g_value_init (&val, DBUS_TYPE_G_UCHAR_ARRAY); \
g_object_get_property (G_OBJECT (setting), property_name, &val); \
array = g_value_get_boxed (&val); \
if (array) \
hwaddr = nm_utils_hwaddr_ntoa (array->data, nm_utils_hwaddr_type (array->len)); \
if (array && array->len) \
hwaddr = nm_utils_hwaddr_ntoa_len (array->data, array->len); \
g_value_unset (&val); \
return hwaddr; \
}

View file

@ -1946,10 +1946,7 @@ nm_utils_wifi_is_channel_valid (guint32 channel, const char *band)
*
* Returns the length in octets of a hardware address of type @type.
*
* Note that this only accepts %ARPHRD_ETHER and %ARPHRD_INFINIBAND,
* not other types.
*
* Return value: the length
* Return value: the positive length, or -1 if the type is unknown/unsupported.
*/
int
nm_utils_hwaddr_len (int type)
@ -1959,7 +1956,7 @@ nm_utils_hwaddr_len (int type)
else if (type == ARPHRD_INFINIBAND)
return INFINIBAND_ALEN;
else
g_return_val_if_reached (-1);
return -1;
}
/**
@ -1970,6 +1967,7 @@ nm_utils_hwaddr_len (int type)
* the raw address given its length.
*
* Return value: the type, either %ARPHRD_ETHER or %ARPHRD_INFINIBAND.
* If the length is unexpected, return -1 (unsupported type/length).
*
* Deprecated: This could not be extended to cover other types, since
* there is not a one-to-one mapping between types and lengths. This
@ -1986,7 +1984,7 @@ nm_utils_hwaddr_type (int len)
else if (len == INFINIBAND_ALEN)
return ARPHRD_INFINIBAND;
else
g_return_val_if_reached (-1);
return -1;
}
#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
@ -2009,7 +2007,13 @@ nm_utils_hwaddr_type (int len)
guint8 *
nm_utils_hwaddr_aton (const char *asc, int type, gpointer buffer)
{
return nm_utils_hwaddr_aton_len (asc, buffer, nm_utils_hwaddr_len (type));
int len = nm_utils_hwaddr_len (type);
if (len <= 0) {
g_return_val_if_reached (NULL);
return NULL;
}
return nm_utils_hwaddr_aton_len (asc, buffer, len);
}
/**
@ -2029,9 +2033,14 @@ nm_utils_hwaddr_atoba (const char *asc, int type)
GByteArray *ba;
int len = nm_utils_hwaddr_len (type);
if (len <= 0) {
g_return_val_if_reached (NULL);
return NULL;
}
ba = g_byte_array_sized_new (len);
ba->len = len;
if (!nm_utils_hwaddr_aton (asc, type, ba->data)) {
g_byte_array_set_size (ba, len);
if (!nm_utils_hwaddr_aton_len (asc, ba->data, len)) {
g_byte_array_unref (ba);
return NULL;
}
@ -2054,14 +2063,22 @@ nm_utils_hwaddr_atoba (const char *asc, int type)
char *
nm_utils_hwaddr_ntoa (gconstpointer addr, int type)
{
return nm_utils_hwaddr_ntoa_len (addr, nm_utils_hwaddr_len (type));
int len = nm_utils_hwaddr_len (type);
if (len <= 0) {
g_return_val_if_reached (NULL);
return NULL;
}
return nm_utils_hwaddr_ntoa_len (addr, len);
}
/**
* nm_utils_hwaddr_aton_len:
* @asc: the ASCII representation of a hardware address
* @buffer: buffer to store the result into
* @length: the expected length in bytes of the result
* @length: the expected length in bytes of the result and
* the size of the buffer in bytes.
*
* Parses @asc and converts it to binary form in @buffer.
* Bytes in @asc can be sepatared by colons (:), or hyphens (-), but not mixed.
@ -2078,6 +2095,13 @@ nm_utils_hwaddr_aton_len (const char *asc, gpointer buffer, gsize length)
guint8 *out = (guint8 *)buffer;
char delimiter = '\0';
if (!asc) {
g_return_val_if_reached (NULL);
return NULL;
}
g_return_val_if_fail (buffer, NULL);
g_return_val_if_fail (length, NULL);
while (length && *in) {
guint8 d1 = in[0], d2 = in[1];
@ -2130,8 +2154,11 @@ char *
nm_utils_hwaddr_ntoa_len (gconstpointer addr, gsize length)
{
const guint8 *in = addr;
GString *out = g_string_new (NULL);
GString *out;
g_return_val_if_fail (addr && length, g_strdup (""));
out = g_string_new (NULL);
while (length--) {
if (out->len)
g_string_append_c (out, ':');
@ -2156,8 +2183,11 @@ gboolean
nm_utils_hwaddr_valid (const char *asc)
{
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
int in_len = strlen (asc), out_len;
gsize in_len, out_len;
if (!asc && !*asc)
return FALSE;
in_len = strlen (asc);
if ((in_len + 1) % 3 != 0)
return FALSE;
out_len = (in_len + 1) / 3;

View file

@ -534,37 +534,43 @@ ip6_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const ch
}
static void
mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path, gsize enforce_length)
{
const char *setting_name = nm_setting_get_name (setting);
char *tmp_string = NULL, *p;
gint *tmp_list;
GByteArray *array = NULL;
gsize length;
int i, type;
p = tmp_string = nm_keyfile_plugin_kf_get_string (keyfile, setting_name, key, NULL);
if (tmp_string) {
if (tmp_string && tmp_string[0]) {
/* Look for enough ':' characters to signify a MAC address */
i = 0;
guint i = 0;
while (*p) {
if (*p == ':')
i++;
p++;
}
/* If we found enough it's probably a string-format MAC address */
type = nm_utils_hwaddr_type (i + 1);
if (type > 0)
array = nm_utils_hwaddr_atoba (tmp_string, type);
if (enforce_length == 0 || enforce_length == i+1) {
/* If we found enough it's probably a string-format MAC address */
array = g_byte_array_sized_new (i+1);
g_byte_array_set_size (array, i+1);
if (!nm_utils_hwaddr_aton_len (tmp_string, array->data, array->len)) {
g_byte_array_unref (array);
array = NULL;
}
}
}
g_free (tmp_string);
if (array == NULL) {
/* Old format; list of ints */
tmp_list = nm_keyfile_plugin_kf_get_integer_list (keyfile, setting_name, key, &length, NULL);
type = nm_utils_hwaddr_type (length);
if (type < 0) {
if (length > 0 && (enforce_length == 0 || enforce_length == length)) {
gsize i;
array = g_byte_array_sized_new (length);
for (i = 0; i < length; i++) {
int val = tmp_list[i];
@ -593,6 +599,18 @@ mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, cons
}
}
static void
mac_address_parser_ETHER (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
{
mac_address_parser (setting, key, keyfile, keyfile_path, ETH_ALEN);
}
static void
mac_address_parser_INFINIBAND (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
{
mac_address_parser (setting, key, keyfile, keyfile_path, INFINIBAND_ALEN);
}
static void
read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key)
{
@ -910,35 +928,35 @@ static KeyParser key_parsers[] = {
{ NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS,
TRUE,
mac_address_parser },
mac_address_parser_ETHER },
{ NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
TRUE,
mac_address_parser },
mac_address_parser_ETHER },
{ NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_MAC_ADDRESS,
TRUE,
mac_address_parser },
mac_address_parser_ETHER },
{ NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
TRUE,
mac_address_parser },
mac_address_parser_ETHER },
{ NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_BSSID,
TRUE,
mac_address_parser },
mac_address_parser_ETHER },
{ NM_SETTING_BLUETOOTH_SETTING_NAME,
NM_SETTING_BLUETOOTH_BDADDR,
TRUE,
mac_address_parser },
mac_address_parser_ETHER },
{ NM_SETTING_INFINIBAND_SETTING_NAME,
NM_SETTING_INFINIBAND_MAC_ADDRESS,
TRUE,
mac_address_parser },
mac_address_parser_INFINIBAND },
{ NM_SETTING_WIMAX_SETTING_NAME,
NM_SETTING_WIMAX_MAC_ADDRESS,
TRUE,
mac_address_parser },
mac_address_parser_ETHER },
{ NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SSID,
TRUE,

View file

@ -3,6 +3,8 @@ KEYFILES = \
Test_GSM_Connection \
Test_Wireless_Connection \
Test_Wired_Connection_MAC_Case \
Test_MAC_Old_Format \
Test_MAC_IB_Old_Format \
Test_Wired_Connection_IP6 \
ATT_Data_Connect_BT \
ATT_Data_Connect_Plain \

View file

@ -0,0 +1,13 @@
[connection]
id=Test InfiniBand Connection
uuid=5680a56d-c99f-45ad-a6dd-b44d5c398c12
type=infiniband
[infiniband]
mac-address=0;17;34;51;68;85;102;119;136;153;1;18;35;52;69;86;103;120;137;144;
transport-mode=datagram
mtu=1400
[ipv4]
method=auto

View file

@ -0,0 +1,10 @@
[connection]
id=Test MAC Old Format
uuid=8980a26d-c99f-4aad-a6bd-b439bc348ca4
type=802-3-ethernet
[802-3-ethernet]
mac-address=00:11:aa:BB:CC:55
cloned-mac-address=00;22;170;187;204;254;
mtu=1400

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 - 2011 Red Hat, Inc.
* Copyright (C) 2008 - 2014 Red Hat, Inc.
*/
#include <stdio.h>
@ -968,6 +968,79 @@ test_read_wired_mac_case (void)
g_object_unref (connection);
}
#define TEST_MAC_OLD_FORMAT_FILE TEST_KEYFILES_DIR"/Test_MAC_Old_Format"
static void
test_read_mac_old_format (void)
{
NMConnection *connection;
NMSettingWired *s_wired;
GError *error = NULL;
gboolean success;
const GByteArray *array;
char expected_mac[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 };
char expected_cloned_mac[ETH_ALEN] = { 0x00, 0x16, 0xaa, 0xbb, 0xcc, 0xfe };
connection = nm_keyfile_plugin_connection_from_file (TEST_MAC_OLD_FORMAT_FILE, &error);
g_assert_no_error (error);
g_assert (connection);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
s_wired = nm_connection_get_setting_wired (connection);
g_assert (s_wired);
/* MAC address */
array = nm_setting_wired_get_mac_address (s_wired);
g_assert (array);
g_assert_cmpint (array->len, ==, ETH_ALEN);
g_assert (memcmp (array->data, expected_mac, ETH_ALEN) == 0);
/* Cloned MAC address */
array = nm_setting_wired_get_cloned_mac_address (s_wired);
g_assert (array);
g_assert_cmpint (array->len, ==, ETH_ALEN);
g_assert (memcmp (array->data, expected_cloned_mac, ETH_ALEN) == 0);
g_object_unref (connection);
}
#define TEST_MAC_IB_OLD_FORMAT_FILE TEST_KEYFILES_DIR"/Test_MAC_IB_Old_Format"
static void
test_read_mac_ib_old_format (void)
{
NMConnection *connection;
NMSettingInfiniband *s_ib;
GError *error = NULL;
gboolean success;
const GByteArray *array;
guint8 expected_mac[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
0x90 };
connection = nm_keyfile_plugin_connection_from_file (TEST_MAC_IB_OLD_FORMAT_FILE, &error);
g_assert_no_error (error);
g_assert (connection);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
s_ib = nm_connection_get_setting_infiniband (connection);
g_assert (s_ib);
/* MAC address */
array = nm_setting_infiniband_get_mac_address (s_ib);
g_assert (array);
g_assert_cmpint (array->len, ==, INFINIBAND_ALEN);
g_assert_cmpint (memcmp (array->data, expected_mac, sizeof (expected_mac)), ==, 0);
g_object_unref (connection);
}
static void
test_read_valid_wireless_connection (void)
{
@ -3359,6 +3432,8 @@ int main (int argc, char **argv)
test_write_ip6_wired_connection ();
test_read_wired_mac_case ();
test_read_mac_old_format ();
test_read_mac_ib_old_format ();
test_read_valid_wireless_connection ();
test_write_wireless_connection ();

View file

@ -414,22 +414,14 @@ mac_address_writer (GKeyFile *file,
GByteArray *array;
const char *setting_name = nm_setting_get_name (setting);
char *mac;
int type;
g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY));
array = (GByteArray *) g_value_get_boxed (value);
if (!array)
if (!array || !array->len)
return;
type = nm_utils_hwaddr_type (array->len);
if (type < 0) {
nm_log_warn (LOGD_SETTINGS, "%s: invalid %s / %s MAC address length %d",
__func__, setting_name, key, array->len);
return;
}
mac = nm_utils_hwaddr_ntoa (array->data, type);
mac = nm_utils_hwaddr_ntoa_len (array->data, array->len);
nm_keyfile_plugin_kf_set_string (file, setting_name, key, mac);
g_free (mac);
}