diff options
-rw-r--r-- | include/ModemManager-enums.h | 16 | ||||
-rw-r--r-- | src/mm-bearer-mbim.c | 66 |
2 files changed, 54 insertions, 28 deletions
diff --git a/include/ModemManager-enums.h b/include/ModemManager-enums.h index 48c96817..57127d6c 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 baf419d7..02d27fee 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; |