diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c index b40e814b3f..afce25593d 100644 --- a/libnm-util/nm-utils.c +++ b/libnm-util/nm-utils.c @@ -2430,12 +2430,22 @@ nm_utils_hwaddr_aton (const char *asc, int type, gpointer buffer) int left = nm_utils_hwaddr_len (type); while (left && *in) { - if (!isxdigit (in[0]) || !isxdigit (in[1])) + guint8 d1 = in[0], d2 = in[1]; + + if (!isxdigit (d1)) return NULL; - *out++ = (HEXVAL (in[0]) << 4) + HEXVAL (in[1]); + /* If there's no leading zero (ie "aa:b:cc") then fake it */ + if (d2 && isxdigit (d2)) { + *out++ = (HEXVAL (d1) << 4) + HEXVAL (d2); + in += 2; + } else { + /* Fake leading zero */ + *out++ = (HEXVAL ('0') << 4) + HEXVAL (d1); + in += 1; + } + left--; - in += 2; if (*in) { if (*in != ':') return NULL; diff --git a/libnm-util/tests/test-general.c b/libnm-util/tests/test-general.c index 10cda51a31..4504bd501d 100644 --- a/libnm-util/tests/test-general.c +++ b/libnm-util/tests/test-general.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "nm-test-helpers.h" #include @@ -1298,6 +1300,47 @@ test_setting_compare_vpn_secrets (NMSettingSecretFlags secret_flags, g_assert (success); } +static void +test_hwaddr_aton_ether_normal (void) +{ + guint8 buf[100]; + guint8 expected[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; + + g_assert (nm_utils_hwaddr_aton ("00:11:22:33:44:55", ARPHRD_ETHER, buf) != NULL); + g_assert (memcmp (buf, expected, sizeof (expected)) == 0); +} + +static void +test_hwaddr_aton_ib_normal (void) +{ + guint8 buf[100]; + const char *source = "00:11:22:33:44:55:66:77:88:99:01:12:23:34:45:56:67:78:89:90"; + guint8 expected[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, + 0x90 }; + + g_assert (nm_utils_hwaddr_aton (source, ARPHRD_INFINIBAND, buf) != NULL); + g_assert (memcmp (buf, expected, sizeof (expected)) == 0); +} + +static void +test_hwaddr_aton_no_leading_zeros (void) +{ + guint8 buf[100]; + guint8 expected[ETH_ALEN] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05 }; + + g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:44:5", ARPHRD_ETHER, buf) != NULL); + g_assert (memcmp (buf, expected, sizeof (expected)) == 0); +} + +static void +test_hwaddr_aton_malformed (void) +{ + guint8 buf[100]; + + g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:a@%%", ARPHRD_ETHER, buf) == NULL); +} + int main (int argc, char **argv) { GError *error = NULL; @@ -1339,6 +1382,11 @@ int main (int argc, char **argv) test_connection_good_base_types (); test_connection_bad_base_types (); + test_hwaddr_aton_ether_normal (); + test_hwaddr_aton_ib_normal (); + test_hwaddr_aton_no_leading_zeros (); + test_hwaddr_aton_malformed (); + base = g_path_get_basename (argv[0]); fprintf (stdout, "%s: SUCCESS\n", base); g_free (base);