From 1675ab017d7899ddecb7d7fd85dc401374f5d10d Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Fri, 14 Nov 2014 12:32:10 +0100 Subject: [PATCH] icera: IPv6 '::' is a placeholder for 'no IPv6', so don't error out if found Also, allow IPDPADDR returns where only DNS IPv6 is given (i.e. no IPv6 address to set), and in that case default to DHCP method in the bearer. https://bugs.freedesktop.org/show_bug.cgi?id=85012 --- plugins/icera/mm-modem-helpers-icera.c | 67 +++++++++++++++----------- plugins/icera/tests/test-modem-helpers-icera.c | 31 +++++++++--- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/plugins/icera/mm-modem-helpers-icera.c b/plugins/icera/mm-modem-helpers-icera.c index f9aa612..1b64d63 100644 --- a/plugins/icera/mm-modem-helpers-icera.c +++ b/plugins/icera/mm-modem-helpers-icera.c @@ -145,43 +145,53 @@ parse_ipdpaddr_v6 (const gchar **items, guint num_items, GError **error) if (num_items < 12) return NULL; + /* No IPv6 IP and no IPv6 DNS, return NULL without error. */ + if (g_strcmp0 (items[9], "::") == 0 && g_strcmp0 (items[11], "::") == 0) + return NULL; + + config = mm_bearer_ip_config_new (); + /* It appears that for IPv6 %IPDPADDR returns only the expected * link-local address and a DNS address, and that to retrieve the * default router, extra DNS, and search domains, the host must listen * for IPv6 Router Advertisements on the net port. */ - - config = mm_bearer_ip_config_new (); - mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_STATIC); - - /* IP address and prefix */ - if (inet_pton (AF_INET6, items[9], &tmp6) != 1 || + if (g_strcmp0 (items[9], "::") != 0) { + mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_STATIC); + /* IP address and prefix */ + if (inet_pton (AF_INET6, items[9], &tmp6) != 1 || IN6_IS_ADDR_UNSPECIFIED (&tmp6)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse IPv6 address '%s'", items[9]); - goto error; - } - mm_bearer_ip_config_set_address (config, items[9]); - mm_bearer_ip_config_set_prefix (config, 64); - - /* If the address is a link-local one, then SLAAC or DHCP must be used - * to get the real prefix and address. Change the method to DHCP to - * indicate this to clients. - */ - if (IN6_IS_ADDR_LINKLOCAL (&tmp6)) + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't parse IPv6 address '%s'", items[9]); + goto error; + } + mm_bearer_ip_config_set_address (config, items[9]); + mm_bearer_ip_config_set_prefix (config, 64); + + /* If the address is a link-local one, then SLAAC or DHCP must be used + * to get the real prefix and address. Change the method to DHCP to + * indicate this to clients. + */ + if (IN6_IS_ADDR_LINKLOCAL (&tmp6)) + mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); + } else { + /* No IPv6 given, but DNS will be available, try with DHCP */ mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP); + } /* DNS server */ - memset (&tmp6, 0, sizeof (tmp6)); - if (inet_pton (AF_INET6, items[11], &tmp6) == 1 && + if (g_strcmp0 (items[11], "::") != 0) { + memset (&tmp6, 0, sizeof (tmp6)); + if (inet_pton (AF_INET6, items[11], &tmp6) == 1 && !IN6_IS_ADDR_UNSPECIFIED (&tmp6)) { - dns[0] = items[11]; - dns[1] = NULL; - mm_bearer_ip_config_set_dns (config, (const gchar **) dns); - } else { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't parse DNS address '%s'", items[11]); - goto error; + dns[0] = items[11]; + dns[1] = NULL; + mm_bearer_ip_config_set_dns (config, (const gchar **) dns); + } else { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't parse DNS address '%s'", items[11]); + goto error; + } } return config; @@ -223,7 +233,7 @@ mm_icera_parse_ipdpaddr_response (const gchar *response, * Sierra USB305: %IPDPADDR: 2, 21.93.217.11, 21.93.217.10, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0 * K3805-Z: %IPDPADDR: 2, 21.93.217.11, 21.93.217.10, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0, 255.0.0.0, 255.255.255.0, 21.93.217.10, * Nokia 21M: %IPDPADDR: 2, 33.196.7.127, 33.196.7.128, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0, 255.0.0.0, 33.196.7.128, fe80::f:9135:5901, ::, fd00:976a::9, ::, ::, ::, ::, :: - * Nokia 21M: %IPDPADDR: 3, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, fe80::2e:437b:7901, ::, fd00:976a::9, ::, ::, ::, ::, :: + * Nokia 21M: %IPDPADDR: 3, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, fe80::2e:437b:7901, ::, fd00:976a::9, ::, ::, ::, ::, :: */ response = mm_strip_tag (response, IPDPADDR_TAG); items = g_strsplit_set (response, ",", 0); @@ -274,4 +284,3 @@ out: *out_ip6_config = ip6_config; return success; } - diff --git a/plugins/icera/tests/test-modem-helpers-icera.c b/plugins/icera/tests/test-modem-helpers-icera.c index 8eaff4c..e7d1645 100644 --- a/plugins/icera/tests/test-modem-helpers-icera.c +++ b/plugins/icera/tests/test-modem-helpers-icera.c @@ -49,7 +49,7 @@ typedef struct { static const IpdpaddrTest ipdpaddr_tests[] = { /* Sierra USB305 */ - { "%IPDPADDR: 2, 21.93.217.11, 21.93.217.10, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0\r\n", + { "%IPDPADDR: 2, 21.93.217.11, 21.93.217.10, 10.177.0.34, 10.161.171.220, 0.0.0.0, 0.0.0.0\r\n", 2, "21.93.217.11", 32, "21.93.217.10", "10.177.0.34", "10.161.171.220", NULL, NULL }, @@ -87,6 +87,18 @@ static const IpdpaddrTest ipdpaddr_tests[] = { 2, "188.150.116.13", 16, "188.150.116.14", "188.149.250.16", NULL, "fe80::1:e414:eb01", "2a00:e18:0:3::6" }, + { "%IPDPADDR: 1, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, fe80::1f:fad1:4c01, ::, 2001:4600:4:fff::54, 2001:4600:4:1fff::54, ::, ::, ::, ::\r\n", + 1, NULL, 0, NULL, NULL, NULL, + "fe80::1f:fad1:4c01", "2001:4600:4:fff::54" }, + + { "%IPDPADDR: 1, 46.157.76.179, 46.157.76.180, 193.213.112.4, 130.67.15.198, 0.0.0.0, 0.0.0.0, 255.0.0.0, 46.157.76.180, ::, ::, ::, ::, ::, ::, ::, ::\r\n", + 1, "46.157.76.179", 32, "46.157.76.180", "193.213.112.4", "130.67.15.198", + NULL, NULL }, + + { "%IPDPADDR: 1, 0.0.0.0, 0.0.0.0, 193.213.112.4, 130.67.15.198, 0.0.0.0, 0.0.0.0, 0.0.0.0, 0.0.0.0, ::, ::, 2001:4600:4:fff::52, 2001:4600:4:1fff::52, ::, ::, ::, ::", + 1, NULL, 0, NULL, NULL, NULL, + NULL, "2001:4600:4:fff::52" }, + { NULL } }; @@ -133,18 +145,21 @@ test_ipdpaddr (void) g_assert (ipv4 == NULL); /* IPv6 */ - if (ipdpaddr_tests[i].ipv6_addr) { + if (ipdpaddr_tests[i].ipv6_addr || ipdpaddr_tests[i].ipv6_dns1) { struct in6_addr a6; g_assert (ipv6); - g_assert_cmpstr (mm_bearer_ip_config_get_address (ipv6), ==, ipdpaddr_tests[i].ipv6_addr); - g_assert_cmpint (mm_bearer_ip_config_get_prefix (ipv6), ==, 64); + if (ipdpaddr_tests[i].ipv6_addr) { + g_assert_cmpstr (mm_bearer_ip_config_get_address (ipv6), ==, ipdpaddr_tests[i].ipv6_addr); + g_assert_cmpint (mm_bearer_ip_config_get_prefix (ipv6), ==, 64); - g_assert (inet_pton (AF_INET6, mm_bearer_ip_config_get_address (ipv6), &a6)); - if (IN6_IS_ADDR_LINKLOCAL (&a6)) + g_assert (inet_pton (AF_INET6, mm_bearer_ip_config_get_address (ipv6), &a6)); + if (IN6_IS_ADDR_LINKLOCAL (&a6)) + g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_DHCP); + else + g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_STATIC); + } else g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_DHCP); - else - g_assert_cmpint (mm_bearer_ip_config_get_method (ipv6), ==, MM_BEARER_IP_METHOD_STATIC); dns = mm_bearer_ip_config_get_dns (ipv6); g_assert (dns); -- 2.1.3