示例#1
0
static void
connect_ip6_page (CEPageIP6 *page)
{
        GtkWidget *content;
        const gchar *str_method;
        gboolean disabled;
        GtkListStore *store;
        GtkTreeIter iter;
        guint method;

        add_address_section (page);
        add_dns_section (page);
        add_routes_section (page);

        page->enabled = GTK_SWITCH (gtk_builder_get_object (CE_PAGE (page)->builder, "switch_enable"));
        g_signal_connect (page->enabled, "notify::active", G_CALLBACK (switch_toggled), page);

        str_method = nm_setting_ip6_config_get_method (page->setting);
        disabled = g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0;
        gtk_switch_set_active (page->enabled, !disabled);
        g_signal_connect_swapped (page->enabled, "notify::active", G_CALLBACK (ce_page_changed), page);
        content = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "page_content"));
        g_object_bind_property (page->enabled, "active",
                                content, "sensitive",
                                G_BINDING_SYNC_CREATE);

        page->method = GTK_COMBO_BOX (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_addresses"));

        store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_UINT);
        gtk_list_store_insert_with_values (store, &iter, -1,
                                           METHOD_COL_NAME, _("Automatic"),
                                           METHOD_COL_METHOD, IP6_METHOD_AUTO,
                                           -1);
        gtk_list_store_insert_with_values (store, &iter, -1,
                                           METHOD_COL_NAME, _("Automatic, DHCP only"),
                                           METHOD_COL_METHOD, IP6_METHOD_DHCP,
                                           -1);
        gtk_list_store_insert_with_values (store, &iter, -1,
                                           METHOD_COL_NAME, _("Manual"),
                                           METHOD_COL_METHOD, IP6_METHOD_MANUAL,
                                           -1);
        gtk_list_store_insert_with_values (store, &iter, -1,
                                           METHOD_COL_NAME, _("Link-Local Only"),
                                           METHOD_COL_METHOD, IP6_METHOD_LINK_LOCAL,
                                           -1);

        gtk_combo_box_set_model (page->method, GTK_TREE_MODEL (store));

        method = IP6_METHOD_AUTO;
        if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
                method = IP6_METHOD_DHCP;
        } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
                method = IP6_METHOD_LINK_LOCAL;
        } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) {
                method = IP6_METHOD_MANUAL;
        } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
                method = IP6_METHOD_SHARED;
        } else if (g_strcmp0 (str_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) {
                method = IP6_METHOD_IGNORE;
        }

        page->never_default = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "never_default_check"));
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->never_default),
                                      nm_setting_ip6_config_get_never_default (page->setting));

        g_signal_connect (page->method, "changed", G_CALLBACK (method_changed), page);
        if (method != IP6_METHOD_SHARED && method != IP6_METHOD_IGNORE)
                gtk_combo_box_set_active (page->method, method);
}
示例#2
0
static void
update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update)
{
	NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
	NMDevice *best = NULL;
	NMActRequest *best_req = NULL;
	NMDnsManager *dns_mgr;
	GSList *devices = NULL, *iter;
#if NOT_YET
	GSList *vpns;
#endif
	NMIP6Config *ip6_config = NULL;
	NMIP6Address *addr;
	const char *ip_iface = NULL;
	NMConnection *connection = NULL;
	NMSettingConnection *s_con = NULL;
	const char *connection_id;

	best = get_best_ip6_device (policy->manager, &best_req);
	if (!best)
		goto out;
	if (!force_update && (best == policy->default_device6))
		goto out;

#if NOT_YET
	/* If a VPN connection is active, it is preferred */
	vpns = nm_vpn_manager_get_active_connections (policy->vpn_manager);
	for (iter = vpns; iter; iter = g_slist_next (iter)) {
		NMVPNConnection *candidate = NM_VPN_CONNECTION (iter->data);
		NMConnection *vpn_connection;
		NMSettingIP6Config *s_ip6;
		gboolean can_default = TRUE;
		NMVPNConnectionState vpn_state;

		/* If it's marked 'never-default', don't make it default */
		vpn_connection = nm_vpn_connection_get_connection (candidate);
		g_assert (vpn_connection);
		s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (vpn_connection, NM_TYPE_SETTING_IP6_CONFIG);
		if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6))
			can_default = FALSE;

		vpn_state = nm_vpn_connection_get_vpn_state (candidate);
		if (can_default && (vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED)) {
			NMIP6Config *parent_ip6;
			NMDevice *parent;

			ip_iface = nm_vpn_connection_get_ip_iface (candidate);
			connection = nm_vpn_connection_get_connection (candidate);
			ip6_config = nm_vpn_connection_get_ip6_config (candidate);
			addr = nm_ip6_config_get_address (ip6_config, 0);

			parent = nm_vpn_connection_get_parent_device (candidate);
			parent_ip6 = nm_device_get_ip6_config (parent);

			nm_system_replace_default_ip6_route_vpn (ip_iface,
			                                         nm_ip6_address_get_gateway (addr),
			                                         nm_vpn_connection_get_ip4_internal_gateway (candidate),
			                                         nm_ip6_config_get_mss (ip4_config),
			                                         nm_device_get_ip_iface (parent),
			                                         nm_ip6_config_get_mss (parent_ip4));

			dns_type = NM_DNS_IP_CONFIG_TYPE_VPN;
		}
		g_object_unref (candidate);
	}
	g_slist_free (vpns);
#endif

	/* The best device gets the default route if a VPN connection didn't */
	if (!ip_iface || !ip6_config) {
		connection = nm_act_request_get_connection (best_req);
		ip_iface = nm_device_get_ip_iface (best);
		ip6_config = nm_device_get_ip6_config (best);
		g_assert (ip6_config);
		addr = nm_ip6_config_get_address (ip6_config, 0);

		nm_system_replace_default_ip6_route (ip_iface, nm_ip6_address_get_gateway (addr));

		dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
	}

	if (!ip_iface || !ip6_config) {
		nm_log_warn (LOGD_CORE, "couldn't determine IP interface (%p) or IPv6 config (%p)!",
		             ip_iface, ip6_config);
		goto out;
	}

	/* Update the default active connection.  Only mark the new default
	 * active connection after setting default = FALSE on all other connections
	 * first.  The order is important, we don't want two connections marked
	 * default at the same time ever.
	 */
	devices = nm_manager_get_devices (policy->manager);
	for (iter = devices; iter; iter = g_slist_next (iter)) {
		NMDevice *dev = NM_DEVICE (iter->data);
		NMActRequest *req;

		req = nm_device_get_act_request (dev);
		if (req && (req != best_req))
			nm_act_request_set_default6 (req, FALSE);
	}

	dns_mgr = nm_dns_manager_get (NULL);
	nm_dns_manager_add_ip6_config (dns_mgr, ip_iface, ip6_config, dns_type);
	g_object_unref (dns_mgr);

	/* Now set new default active connection _after_ updating DNS info, so that
	 * if the connection is shared dnsmasq picks up the right stuff.
	 */
	if (best_req)
		nm_act_request_set_default6 (best_req, TRUE);

	if (connection)
		s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);

	connection_id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
	if (connection_id) {
		nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv6 routing and DNS.", connection_id, ip_iface);
	} else {
		nm_log_info (LOGD_CORE, "Policy set (%s) as default for IPv6 routing and DNS.", ip_iface);
	}

out:
	policy->default_device6 = best;
}
/* This is exactly identical to nm_utils_merge_ip4_config, with s/4/6/,
 * except that we can't compare addresses with ==.
 */
void
nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting)
{
	int i, j;

	if (!setting)
		return; /* Defaults are just fine */

	if (nm_setting_ip6_config_get_ignore_auto_dns (setting)) {
		nm_ip6_config_reset_nameservers (ip6_config);
		nm_ip6_config_reset_domains (ip6_config);
		nm_ip6_config_reset_searches (ip6_config);
	}

	if (nm_setting_ip6_config_get_ignore_auto_routes (setting))
		nm_ip6_config_reset_routes (ip6_config);

	for (i = 0; i < nm_setting_ip6_config_get_num_dns (setting); i++) {
		const struct in6_addr *ns;
		gboolean found = FALSE;

		/* Avoid dupes */
		ns = nm_setting_ip6_config_get_dns (setting, i);
		for (j = 0; j < nm_ip6_config_get_num_nameservers (ip6_config); j++) {
			if (ip6_addresses_equal (nm_ip6_config_get_nameserver (ip6_config, j), ns)) {
				found = TRUE;
				break;
			}
		}

		if (!found)
			nm_ip6_config_add_nameserver (ip6_config, ns);
	}

	/* DNS search domains */
	for (i = 0; i < nm_setting_ip6_config_get_num_dns_searches (setting); i++) {
		const char *search = nm_setting_ip6_config_get_dns_search (setting, i);
		gboolean found = FALSE;

		/* Avoid dupes */
		for (j = 0; j < nm_ip6_config_get_num_searches (ip6_config); j++) {
			if (!strcmp (search, nm_ip6_config_get_search (ip6_config, j))) {
				found = TRUE;
				break;
			}
		}

		if (!found)
			nm_ip6_config_add_search (ip6_config, search);
	}

	/* IPv6 addresses */
	for (i = 0; i < nm_setting_ip6_config_get_num_addresses (setting); i++) {
		NMIP6Address *setting_addr = nm_setting_ip6_config_get_address (setting, i);
		guint32 num;

		num = nm_ip6_config_get_num_addresses (ip6_config);
		for (j = 0; j < num; j++) {
			NMIP6Address *cfg_addr = nm_ip6_config_get_address (ip6_config, j);

			/* Dupe, override with user-specified address */
			if (ip6_addresses_equal (nm_ip6_address_get_address (cfg_addr), nm_ip6_address_get_address (setting_addr))) {
				nm_ip6_config_replace_address (ip6_config, j, setting_addr);
				break;
			}
		}

		if (j == num)
			nm_ip6_config_add_address (ip6_config, setting_addr);
	}

	/* IPv6 routes */
	for (i = 0; i < nm_setting_ip6_config_get_num_routes (setting); i++) {
		NMIP6Route *setting_route = nm_setting_ip6_config_get_route (setting, i);
		guint32 num;

		num = nm_ip6_config_get_num_routes (ip6_config);
		for (j = 0; j < num; j++) {
			NMIP6Route *cfg_route = nm_ip6_config_get_route (ip6_config, j);

			/* Dupe, override with user-specified route */
			if (   ip6_addresses_equal (nm_ip6_route_get_dest (cfg_route), nm_ip6_route_get_dest (setting_route))
			    && (nm_ip6_route_get_prefix (cfg_route) == nm_ip6_route_get_prefix (setting_route))
				&& ip6_addresses_equal (nm_ip6_route_get_next_hop (cfg_route), nm_ip6_route_get_next_hop (setting_route))) {
				nm_ip6_config_replace_route (ip6_config, j, setting_route);
				break;
			}
		}

		if (j == num)
			nm_ip6_config_add_route (ip6_config, setting_route);
	}

	if (nm_setting_ip6_config_get_never_default (setting))
		nm_ip6_config_set_never_default (ip6_config, TRUE);
}
示例#4
0
static NMDevice *
get_best_ip6_device (NMManager *manager, NMActRequest **out_req)
{
	GSList *devices, *iter;
	NMDevice *best = NULL;
	int best_prio = G_MAXINT;

	g_return_val_if_fail (manager != NULL, NULL);
	g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
	g_return_val_if_fail (out_req != NULL, NULL);
	g_return_val_if_fail (*out_req == NULL, NULL);

	devices = nm_manager_get_devices (manager);
	for (iter = devices; iter; iter = g_slist_next (iter)) {
		NMDevice *dev = NM_DEVICE (iter->data);
		NMActRequest *req;
		NMConnection *connection;
		NMIP6Config *ip6_config;
		NMSettingIP6Config *s_ip6;
		int prio;
		guint i;
		gboolean can_default = FALSE;
		const char *method = NULL;

		if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED)
			continue;

		ip6_config = nm_device_get_ip6_config (dev);
		if (!ip6_config)
			continue;

		req = nm_device_get_act_request (dev);
		g_assert (req);
		connection = nm_act_request_get_connection (req);
		g_assert (connection);

		/* Never set the default route through an IPv4LL-addressed device */
		s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
		if (s_ip6)
			method = nm_setting_ip6_config_get_method (s_ip6);

		if (method && !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
			continue;

		/* Make sure at least one of this device's IP addresses has a gateway */
		for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) {
			NMIP6Address *addr;

			addr = nm_ip6_config_get_address (ip6_config, i);
			if (nm_ip6_address_get_gateway (addr)) {
				can_default = TRUE;
				break;
			}
		}

		if (!can_default && !NM_IS_DEVICE_MODEM (dev))
			continue;

		/* 'never-default' devices can't ever be the default */
		if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6))
			continue;

		prio = nm_device_get_priority (dev);
		if (prio > 0 && prio < best_prio) {
			best = dev;
			best_prio = prio;
			*out_req = req;
		}
	}

	return best;
}
GtkWidget *
ip6_routes_dialog_new (NMSettingIP6Config *s_ip6, gboolean automatic)
{
	GtkBuilder *builder;
	GtkWidget *dialog, *widget, *ok_button;
	GtkListStore *store;
	GtkTreeIter model_iter;
	GtkTreeSelection *selection;
	gint offset;
	GtkTreeViewColumn *column;
	GtkCellRenderer *renderer;
	int i;
	GSList *renderers = NULL;
	GError* error = NULL;

	/* Initialize temporary storage vars */
	g_free (last_edited);
	last_edited = NULL;
	last_path = NULL;
	g_free (last_path);
	last_column = -1;

	builder = gtk_builder_new ();

	if (!gtk_builder_add_from_file (builder, UIDIR "/ce-ip6-routes.ui", &error)) {
		g_warning ("Couldn't load builder file: %s", error->message);
		g_error_free (error);
		return NULL;
	}

	dialog = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_routes_dialog"));
	if (!dialog) {
		g_warning ("%s: Couldn't load ip6 routes dialog from .ui file.", __func__);
		g_object_unref (builder);
		return NULL;
	}

	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);

	g_object_set_data_full (G_OBJECT (dialog), "builder",
	                        builder, (GDestroyNotify) g_object_unref);

	ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button"));

	store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);

	/* Add existing routes */
	for (i = 0; i < nm_setting_ip6_config_get_num_routes (s_ip6); i++) {
		NMIP6Route *route = nm_setting_ip6_config_get_route (s_ip6, i);
		const struct in6_addr *tmp_addr;
		char ip_string[INET6_ADDRSTRLEN];
		char *tmp;

		if (!route) {
			g_warning ("%s: empty IP6 route structure!", __func__);
			continue;
		}

		gtk_list_store_append (store, &model_iter);

		tmp_addr = nm_ip6_route_get_dest (route);
		if (inet_ntop (AF_INET6, tmp_addr, ip_string, sizeof (ip_string)))
			gtk_list_store_set (store, &model_iter, COL_ADDRESS, ip_string, -1);

		tmp = g_strdup_printf ("%u", nm_ip6_route_get_prefix (route));
		gtk_list_store_set (store, &model_iter, COL_PREFIX, tmp, -1);
		g_free (tmp);

		tmp_addr = nm_ip6_route_get_next_hop (route);
		if (tmp_addr && !IN6_IS_ADDR_UNSPECIFIED (tmp_addr) &&
			inet_ntop (AF_INET6, tmp_addr, ip_string, sizeof (ip_string)))
			gtk_list_store_set (store, &model_iter, COL_NEXT_HOP, ip_string, -1);

		if (nm_ip6_route_get_metric (route)) {
			tmp = g_strdup_printf ("%u", nm_ip6_route_get_metric (route));
			gtk_list_store_set (store, &model_iter, COL_METRIC, tmp, -1);
			g_free (tmp);
		}
	}

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_routes"));
	gtk_tree_view_set_model (GTK_TREE_VIEW (widget), GTK_TREE_MODEL (store));
	g_object_unref (store);

	/* IP Address column */
	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "editable", TRUE, NULL);
	g_signal_connect (renderer, "edited", G_CALLBACK (cell_edited), builder);
	g_object_set_data (G_OBJECT (renderer), "column", GUINT_TO_POINTER (COL_ADDRESS));
	g_signal_connect (renderer, "editing-started", G_CALLBACK (ip6_cell_editing_started), ok_button);
	g_signal_connect (renderer, "editing-canceled", G_CALLBACK (cell_editing_canceled), builder);
	renderers = g_slist_append (renderers, renderer);

	offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
	                                                      -1, _("Address"), renderer,
	                                                      "text", COL_ADDRESS,
	                                                      NULL);
	column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
	gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
	gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);

	/* Prefix column */
	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "editable", TRUE, NULL);
	g_signal_connect (renderer, "edited", G_CALLBACK (cell_edited), builder);
	g_object_set_data (G_OBJECT (renderer), "column", GUINT_TO_POINTER (COL_PREFIX));
	g_signal_connect (renderer, "editing-started", G_CALLBACK (uint_cell_editing_started), ok_button);
	g_signal_connect (renderer, "editing-canceled", G_CALLBACK (cell_editing_canceled), builder);
	renderers = g_slist_append (renderers, renderer);

	offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
	                                                      -1, _("Prefix"), renderer,
	                                                      "text", COL_PREFIX,
	                                                      NULL);
	column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
	gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
	gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);

	/* Gateway column */
	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "editable", TRUE, NULL);
	g_signal_connect (renderer, "edited", G_CALLBACK (cell_edited), builder);
	g_object_set_data (G_OBJECT (renderer), "column", GUINT_TO_POINTER (COL_NEXT_HOP));
	g_signal_connect (renderer, "editing-started", G_CALLBACK (ip6_cell_editing_started), ok_button);
	g_signal_connect (renderer, "editing-canceled", G_CALLBACK (cell_editing_canceled), builder);
	renderers = g_slist_append (renderers, renderer);

	offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
	                                                      -1, _("Gateway"), renderer,
	                                                      "text", COL_NEXT_HOP,
	                                                      NULL);
	column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
	gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
	gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);

	/* Metric column */
	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "editable", TRUE, NULL);
	g_signal_connect (renderer, "edited", G_CALLBACK (cell_edited), builder);
	g_object_set_data (G_OBJECT (renderer), "column", GUINT_TO_POINTER (COL_METRIC));
	g_signal_connect (renderer, "editing-started", G_CALLBACK (uint_cell_editing_started), ok_button);
	g_signal_connect (renderer, "editing-canceled", G_CALLBACK (cell_editing_canceled), builder);
	renderers = g_slist_append (renderers, renderer);

	offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (widget),
	                                                      -1, _("Metric"), renderer,
	                                                      "text", COL_METRIC,
	                                                      NULL);
	column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), offset - 1);
	gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
	gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);

	g_object_set_data_full (G_OBJECT (dialog), "renderers", renderers, (GDestroyNotify) g_slist_free);

	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
	g_signal_connect (selection, "changed",
	                  G_CALLBACK (list_selection_changed),
	                  GTK_WIDGET (gtk_builder_get_object (builder, "ip6_route_delete_button")));
	g_signal_connect (widget, "button-press-event", G_CALLBACK (tree_view_button_pressed_cb), builder);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_route_add_button"));
	gtk_widget_set_sensitive (widget, TRUE);
	g_signal_connect (widget, "clicked", G_CALLBACK (route_add_clicked), builder);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_route_delete_button"));
	gtk_widget_set_sensitive (widget, FALSE);
	g_signal_connect (widget, "clicked", G_CALLBACK (route_delete_clicked), builder);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_ignore_auto_routes"));
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
	                              nm_setting_ip6_config_get_ignore_auto_routes (s_ip6));
	gtk_widget_set_sensitive (widget, automatic);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_never_default"));
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
	                              nm_setting_ip6_config_get_never_default (s_ip6));

	/* Update initial validity */
	validate (dialog);

	return dialog;
}