summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2016-04-20 11:09:13 -0500
committerDan Williams <dcbw@redhat.com>2016-05-03 11:39:19 -0500
commitf5a061efbf29642521e3da6f5f6ff98129643143 (patch)
treebc10ebb528c19537deaad6a836c054031fcd0e3d
parentccc148fe9bc24a687ba868070014028d7ad0bb22 (diff)
downloadModemManager-f5a061efbf29642521e3da6f5f6ff98129643143.tar.gz
bearer-mbim: fine-tune bearer IP method reporting
v4: modems/providers may not return DNS servers and not all modems support DHCP, so lack of DNS servers should not indicate a bearer IP method of "DHCP". IP config daemon/scripts already have to handle missing DNS anyway. v6: IPv6 requires SLAAC or DHCPv6 as part of the specification, so for now we assume modems will support it. Provide all the info the modem sent, but if there is any missing information use an IP method of "DHCP" to indicate that info should be obtained via SLAAC/DHCPv6. Only use an IP method of "STATIC" when all basic properties are given by the modem.
-rw-r--r--include/ModemManager-enums.h16
-rw-r--r--src/mm-bearer-mbim.c66
2 files changed, 54 insertions, 28 deletions
diff --git a/include/ModemManager-enums.h b/include/ModemManager-enums.h
index 48c968178..57127d6cb 100644
--- a/include/ModemManager-enums.h
+++ b/include/ModemManager-enums.h
@@ -852,13 +852,19 @@ typedef enum { /*< underscore_name=mm_modem_contacts_storage >*/
/**
* MMBearerIpMethod:
* @MM_BEARER_IP_METHOD_UNKNOWN: Unknown method.
- * @MM_BEARER_IP_METHOD_PPP: Use PPP to get the address.
+ * @MM_BEARER_IP_METHOD_PPP: Use PPP to get IP addresses and DNS information.
+ * For IPv6, use PPP to retrieve the 64-bit Interface Identifier, use the IID to
+ * construct an IPv6 link-local address by following RFC 5072, and then run
+ * DHCP over the PPP link to retrieve DNS settings.
* @MM_BEARER_IP_METHOD_STATIC: Use the provided static IP configuration given
- * by the modem to configure the IP data interface.
+ * by the modem to configure the IP data interface. Note that DNS servers may
+ * not be provided by the network or modem firmware.
* @MM_BEARER_IP_METHOD_DHCP: Begin DHCP or IPv6 SLAAC on the data interface to
- * obtain necessary IP configuration details. For IPv4 bearers DHCP should
- * be used. For IPv6 bearers SLAAC should be used to determine the prefix and
- * any additional details.
+ * obtain any necessary IP configuration details that are not already provided
+ * by the IP configuration. For IPv4 bearers DHCP should be used. For IPv6
+ * bearers SLAAC should be used, and the IP configuration may already contain
+ * a link-local address that should be assigned to the interface before SLAAC
+ * is started to obtain the rest of the configuration.
*
* Type of IP method configuration to be used in a given Bearer.
*/
diff --git a/src/mm-bearer-mbim.c b/src/mm-bearer-mbim.c
index baf419d70..02d27feee 100644
--- a/src/mm-bearer-mbim.c
+++ b/src/mm-bearer-mbim.c
@@ -413,14 +413,13 @@ ip_configuration_query_ready (MbimDevice *device,
ctx->ip_type == MBIM_CONTEXT_IP_TYPE_IPV4_AND_IPV6) {
ipv4_config = mm_bearer_ip_config_new ();
- /* We assume that if we have IP and DNS, we can setup static */
+ /* We assume that if we have an IP we can use static configuration.
+ * Not all modems or providers will return DNS servers or even a
+ * gateway, and not all modems support DHCP either. The IP management
+ * daemon/script just has to deal with this...
+ */
if (ipv4configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS &&
- ipv4configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS &&
- ipv4addresscount > 0 &&
- ipv4dnsservercount > 0) {
- gchar **strarr;
- guint i, n;
-
+ ipv4addresscount > 0) {
mm_bearer_ip_config_set_method (ipv4_config, MM_BEARER_IP_METHOD_STATIC);
/* IP address, pick the first one */
@@ -441,8 +440,15 @@ ip_configuration_query_ready (MbimDevice *device,
g_free (str);
g_object_unref (addr);
}
+ } else
+ mm_bearer_ip_config_set_method (ipv4_config, MM_BEARER_IP_METHOD_DHCP);
+
+ /* DNS */
+ if (ipv4configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS &&
+ ipv4dnsservercount > 0) {
+ gchar **strarr;
+ guint i, n;
- /* DNS */
strarr = g_new0 (gchar *, ipv4dnsservercount + 1);
for (i = 0, n = 0; i < ipv4dnsservercount; i++) {
addr = g_inet_address_new_from_bytes ((guint8 *)&ipv4dnsserver[i], G_SOCKET_FAMILY_IPV4);
@@ -452,8 +458,7 @@ ip_configuration_query_ready (MbimDevice *device,
}
mm_bearer_ip_config_set_dns (ipv4_config, (const gchar **)strarr);
g_strfreev (strarr);
- } else
- mm_bearer_ip_config_set_method (ipv4_config, MM_BEARER_IP_METHOD_DHCP);
+ }
/* MTU */
if (ipv4configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)
@@ -465,30 +470,28 @@ ip_configuration_query_ready (MbimDevice *device,
if (ctx->ip_type == MBIM_CONTEXT_IP_TYPE_IPV6 ||
ctx->ip_type == MBIM_CONTEXT_IP_TYPE_IPV4V6 ||
ctx->ip_type == MBIM_CONTEXT_IP_TYPE_IPV4_AND_IPV6) {
+ gboolean address_set = FALSE;
+ gboolean gateway_set = FALSE;
+ gboolean dns_set = FALSE;
+
ipv6_config = mm_bearer_ip_config_new ();
- /* We assume that if we have IP and DNS, we can setup static */
if (ipv6configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS &&
- ipv6configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS &&
- ipv6addresscount > 0 &&
- ipv6dnsservercount > 0) {
- gchar **strarr;
- guint i, n;
-
- mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_STATIC);
+ ipv6addresscount > 0) {
/* IP address, pick the first one */
addr = g_inet_address_new_from_bytes ((guint8 *)&ipv6address[0]->ipv6_address, G_SOCKET_FAMILY_IPV6);
str = g_inet_address_to_string (addr);
mm_bearer_ip_config_set_address (ipv6_config, str);
g_free (str);
+ address_set = TRUE;
/* 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.
+ * to get the real prefix and address.
+ * FIXME: maybe the modem reported non-LL address in ipv6address[1] ?
*/
if (g_inet_address_get_is_link_local (addr))
- mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_DHCP);
+ address_set = FALSE;
g_object_unref (addr);
@@ -502,7 +505,14 @@ ip_configuration_query_ready (MbimDevice *device,
mm_bearer_ip_config_set_gateway (ipv6_config, str);
g_free (str);
g_object_unref (addr);
+ gateway_set = TRUE;
}
+ }
+
+ if (ipv6configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS &&
+ ipv6dnsservercount > 0) {
+ gchar **strarr;
+ guint i, n;
/* DNS */
strarr = g_new0 (gchar *, ipv6dnsservercount + 1);
@@ -514,12 +524,22 @@ ip_configuration_query_ready (MbimDevice *device,
}
mm_bearer_ip_config_set_dns (ipv6_config, (const gchar **)strarr);
g_strfreev (strarr);
- } else
- mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_DHCP);
+
+ dns_set = TRUE;
+ }
/* MTU */
if (ipv6configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)
mm_bearer_ip_config_set_mtu (ipv6_config, ipv6mtu);
+
+ /* Only use the static method if all basic properties are available,
+ * otherwise use DHCP to indicate the missing ones should be
+ * retrieved from SLAAC or DHCPv6.
+ */
+ if (address_set && gateway_set && dns_set)
+ mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_STATIC);
+ else
+ mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_DHCP);
} else
ipv6_config = NULL;