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
This commit is contained in:
Aleksander Morgado
2014-12-03 19:02:00 +01:00
parent 71a1b64b3b
commit fd28a4d5cd
2 changed files with 60 additions and 36 deletions
+37 -28
View File
@@ -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);
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))
/* 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;
}
+23 -8
View File
@@ -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);