static gboolean check_ip6_method (NMConnection *orig, NMConnection *candidate, GHashTable *settings) { GHashTable *props; const char *orig_ip6_method, *candidate_ip6_method; NMSettingIPConfig *candidate_ip6; gboolean allow = FALSE; props = check_property_in_hash (settings, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD); if (!props) return TRUE; /* If the generated connection is 'link-local' and the candidate is both 'auto' * and may-fail=TRUE, then the candidate is OK to use. may-fail is included * in the decision because if the candidate is 'auto' but may-fail=FALSE, then * the connection could not possibly have been previously activated on the * device if the device has no non-link-local IPv6 address. */ orig_ip6_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP6_CONFIG); candidate_ip6_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP6_CONFIG); candidate_ip6 = nm_connection_get_setting_ip6_config (candidate); if ( strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0 && strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 && (!candidate_ip6 || nm_setting_ip_config_get_may_fail (candidate_ip6))) { allow = TRUE; } /* If the generated connection method is 'link-local' or 'auto' and the candidate * method is 'ignore' we can take the connection, because NM didn't simply take care * of IPv6. */ if ( ( strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0 || strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) && strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) { allow = TRUE; } if (allow) { remove_from_hash (settings, props, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD); } return allow; }
static gboolean check_ip4_method (NMConnection *orig, NMConnection *candidate, GHashTable *settings, gboolean device_has_carrier) { GHashTable *props; const char *orig_ip4_method, *candidate_ip4_method; NMSettingIPConfig *candidate_ip4; props = check_property_in_hash (settings, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD); if (!props) return TRUE; /* If the generated connection is 'disabled' (device had no IP addresses) * but it has no carrier, that most likely means that IP addressing could * not complete and thus no IP addresses were assigned. In that case, allow * matching to the "auto" method. */ orig_ip4_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP4_CONFIG); candidate_ip4_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP4_CONFIG); candidate_ip4 = nm_connection_get_setting_ip4_config (candidate); if ( strcmp (orig_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0 && strcmp (candidate_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0 && (!candidate_ip4 || nm_setting_ip_config_get_may_fail (candidate_ip4)) && (device_has_carrier == FALSE)) { remove_from_hash (settings, props, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD); return TRUE; } return FALSE; }
static void populate_ui (CEPageIP4 *self) { CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); NMSettingIPConfig *setting = priv->setting; GtkListStore *store; GtkTreeIter model_iter; int method = IP4_METHOD_AUTO; GString *string = NULL; SetMethodInfo info; const char *str_method; int i; /* Method */ gtk_combo_box_set_active (priv->method, 0); str_method = nm_setting_ip_config_get_method (setting); if (str_method) { if (!strcmp (str_method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) method = IP4_METHOD_LINK_LOCAL; else if (!strcmp (str_method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) method = IP4_METHOD_MANUAL; else if (!strcmp (str_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) method = IP4_METHOD_SHARED; else if (!strcmp (str_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) method = IP4_METHOD_DISABLED; } if (method == IP4_METHOD_AUTO && nm_setting_ip_config_get_ignore_auto_dns (setting)) method = IP4_METHOD_AUTO_ADDRESSES; info.method = method; info.combo = priv->method; gtk_tree_model_foreach (GTK_TREE_MODEL (priv->method_store), set_method, &info); /* Addresses */ store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); for (i = 0; i < nm_setting_ip_config_get_num_addresses (setting); i++) { NMIPAddress *addr = nm_setting_ip_config_get_address (setting, i); char buf[32]; if (!addr) { g_warning ("%s: empty IP4 Address structure!", __func__); continue; } snprintf (buf, sizeof (buf), "%u", nm_ip_address_get_prefix (addr)); gtk_list_store_append (store, &model_iter); gtk_list_store_set (store, &model_iter, COL_ADDRESS, nm_ip_address_get_address (addr), COL_PREFIX, buf, /* FIXME */ COL_GATEWAY, i == 0 ? nm_setting_ip_config_get_gateway (setting) : NULL, -1); } gtk_tree_view_set_model (priv->addr_list, GTK_TREE_MODEL (store)); g_signal_connect_swapped (store, "row-inserted", G_CALLBACK (ce_page_changed), self); g_signal_connect_swapped (store, "row-deleted", G_CALLBACK (ce_page_changed), self); g_object_unref (store); /* DNS servers */ string = g_string_new (""); for (i = 0; i < nm_setting_ip_config_get_num_dns (setting); i++) { const char *dns; dns = nm_setting_ip_config_get_dns (setting, i); if (!dns) continue; if (string->len) g_string_append (string, ", "); g_string_append (string, dns); } gtk_entry_set_text (priv->dns_servers, string->str); g_string_free (string, TRUE); /* DNS searches */ string = g_string_new (""); for (i = 0; i < nm_setting_ip_config_get_num_dns_searches (setting); i++) { if (string->len) g_string_append (string, ", "); g_string_append (string, nm_setting_ip_config_get_dns_search (setting, i)); } gtk_entry_set_text (priv->dns_searches, string->str); g_string_free (string, TRUE); if ((method == IP4_METHOD_AUTO) || (method == IP4_METHOD_AUTO_ADDRESSES)) { if (nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (setting))) { gtk_entry_set_text (priv->dhcp_client_id, nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (setting))); } } /* IPv4 required */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->ip4_required), !nm_setting_ip_config_get_may_fail (setting)); }
/** * nm_modem_get_connection_ip_type: * @self: the #NMModem * @connection: the #NMConnection to determine IP type to use * * Given a modem and a connection, determine which #NMModemIPTypes to use * when connecting. * * Returns: an array of #NMModemIpType values, in the order in which they * should be tried. */ GArray * nm_modem_get_connection_ip_type (NMModem *self, NMConnection *connection, GError **error) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); NMSettingIPConfig *s_ip4, *s_ip6; const char *method; gboolean ip4 = TRUE, ip6 = TRUE; gboolean ip4_may_fail = TRUE, ip6_may_fail = TRUE; s_ip4 = nm_connection_get_setting_ip4_config (connection); if (s_ip4) { method = nm_setting_ip_config_get_method (s_ip4); if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) ip4 = FALSE; ip4_may_fail = nm_setting_ip_config_get_may_fail (s_ip4); } s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) { method = nm_setting_ip_config_get_method (s_ip6); if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) ip6 = FALSE; ip6_may_fail = nm_setting_ip_config_get_may_fail (s_ip6); } if (ip4 && !ip6) { if (!(priv->ip_types & NM_MODEM_IP_TYPE_IPV4)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection requested IPv4 but IPv4 is " "unsupported by the modem."); return NULL; } return build_single_ip_type_array (NM_MODEM_IP_TYPE_IPV4); } if (ip6 && !ip4) { if (!(priv->ip_types & NM_MODEM_IP_TYPE_IPV6)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection requested IPv6 but IPv6 is " "unsupported by the modem."); return NULL; } return build_single_ip_type_array (NM_MODEM_IP_TYPE_IPV6); } if (ip4 && ip6) { NMModemIPType type; GArray *out; out = g_array_sized_new (FALSE, FALSE, sizeof (NMModemIPType), 3); /* Modem supports dual-stack? */ if (priv->ip_types & NM_MODEM_IP_TYPE_IPV4V6) { type = NM_MODEM_IP_TYPE_IPV4V6; g_array_append_val (out, type); } /* If IPv6 may-fail=false, we should NOT try IPv4 as fallback */ if ((priv->ip_types & NM_MODEM_IP_TYPE_IPV4) && ip6_may_fail) { type = NM_MODEM_IP_TYPE_IPV4; g_array_append_val (out, type); } /* If IPv4 may-fail=false, we should NOT try IPv6 as fallback */ if ((priv->ip_types & NM_MODEM_IP_TYPE_IPV6) && ip4_may_fail) { type = NM_MODEM_IP_TYPE_IPV6; g_array_append_val (out, type); } if (out->len > 0) return out; /* Error... */ g_array_unref (out); g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection requested both IPv4 and IPv6 " "but dual-stack addressing is unsupported " "by the modem."); return NULL; } g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection specified no IP configuration!"); return NULL; }
/** * nm_modem_get_connection_ip_type: * @self: the #NMModem * @connection: the #NMConnection to determine IP type to use * * Given a modem and a connection, determine which NMModemIpType to use * when connecting. * * Returns: a single %NMModemIpType value */ NMModemIPType nm_modem_get_connection_ip_type (NMModem *self, NMConnection *connection, GError **error) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); NMSettingIPConfig *s_ip4, *s_ip6; const char *method; gboolean ip4 = TRUE, ip6 = TRUE; gboolean ip4_may_fail = TRUE, ip6_may_fail = TRUE; s_ip4 = nm_connection_get_setting_ip4_config (connection); if (s_ip4) { method = nm_setting_ip_config_get_method (s_ip4); if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) ip4 = FALSE; ip4_may_fail = nm_setting_ip_config_get_may_fail (s_ip4); } s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) { method = nm_setting_ip_config_get_method (s_ip6); if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) ip6 = FALSE; ip6_may_fail = nm_setting_ip_config_get_may_fail (s_ip6); } if (ip4 && !ip6) { if (!(priv->ip_types & NM_MODEM_IP_TYPE_IPV4)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection requested IPv4 but IPv4 is " "unsuported by the modem."); return NM_MODEM_IP_TYPE_UNKNOWN; } return NM_MODEM_IP_TYPE_IPV4; } if (ip6 && !ip4) { if (!(priv->ip_types & NM_MODEM_IP_TYPE_IPV6)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection requested IPv6 but IPv6 is " "unsuported by the modem."); return NM_MODEM_IP_TYPE_UNKNOWN; } return NM_MODEM_IP_TYPE_IPV6; } if (ip4 && ip6) { /* Modem supports dual-stack */ if (priv->ip_types & NM_MODEM_IP_TYPE_IPV4V6) return NM_MODEM_IP_TYPE_IPV4V6; /* Both IPv4 and IPv6 requested, but modem doesn't support dual-stack; * if one method is marked "may-fail" then use the other. */ if (ip6_may_fail) return NM_MODEM_IP_TYPE_IPV4; else if (ip4_may_fail) return NM_MODEM_IP_TYPE_IPV6; g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection requested both IPv4 and IPv6 " "but dual-stack addressing is unsupported " "by the modem."); return NM_MODEM_IP_TYPE_UNKNOWN; } g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection specified no IP configuration!"); return NM_MODEM_IP_TYPE_UNKNOWN; }