Exemplo n.º 1
0
static void
synchronize_device_config (Network *self,
                           Netinterface *iface,
                           NMDevice *device)
{
  NMConnection *connection;
  NMSettingIP4Config *ip4config;
  NMSettingIP6Config *ip6config;
  const char *ip4_method = "";
  const char *ip6_method = "";

  connection = device_find_connection (self->settings, device);

  if (!connection)
    return;

  ip4config = nm_connection_get_setting_ip4_config (connection);
  if (ip4config)
    ip4_method = nm_setting_ip4_config_get_method (ip4config);
  cockpit_network_netinterface_set_ip4_config_mode (COCKPIT_NETWORK_NETINTERFACE (iface),
                                                    ip4_method);

  ip6config = nm_connection_get_setting_ip6_config (connection);
  if (ip6config)
    ip6_method = nm_setting_ip6_config_get_method (ip6config);
  cockpit_network_netinterface_set_ip6_config_mode (COCKPIT_NETWORK_NETINTERFACE (iface),
                                                    ip6_method);
}
Exemplo n.º 2
0
void
nm_utils_complete_generic (NMConnection *connection,
                           const char *ctype,
                           const GSList *existing,
                           const char *format,
                           const char *preferred,
                           gboolean default_enable_ipv6)
{
	NMSettingConnection *s_con;
	NMSettingIP4Config *s_ip4;
	NMSettingIP6Config *s_ip6;
	const char *method;
	char *id, *uuid;

	s_con = nm_connection_get_setting_connection (connection);
	if (!s_con) {
		s_con = (NMSettingConnection *) nm_setting_connection_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_con));
	}
	g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_TYPE, ctype, NULL);

	if (!nm_setting_connection_get_uuid (s_con)) {
		uuid = nm_utils_uuid_generate ();
		g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_UUID, uuid, NULL);
		g_free (uuid);
	}

	/* Add a connection ID if absent */
	if (!nm_setting_connection_get_id (s_con)) {
		id = get_new_connection_name (existing, format, preferred);
		g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_ID, id, NULL);
		g_free (id);
	}

	/* Add an 'auto' IPv4 connection if present */
	s_ip4 = nm_connection_get_setting_ip4_config (connection);
	if (!s_ip4) {
		s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_ip4));
	}
	method = nm_setting_ip4_config_get_method (s_ip4);
	if (!method) {
		g_object_set (G_OBJECT (s_ip4),
		              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
		              NULL);
	}

	/* Add an 'auto' IPv6 setting if allowed and not preset */
	s_ip6 = nm_connection_get_setting_ip6_config (connection);
	if (!s_ip6 && default_enable_ipv6) {
		s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
		nm_connection_add_setting (connection, NM_SETTING (s_ip6));
	}
	if (s_ip6 && !nm_setting_ip6_config_get_method (s_ip6)) {
		g_object_set (G_OBJECT (s_ip6),
		              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
		              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
		              NULL);
	}
}
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;
}
const char *
nm_utils_get_ip_config_method (NMConnection *connection,
                               GType         ip_setting_type)
{
	NMSettingConnection *s_con;
	NMSettingIPConfig *s_ip4, *s_ip6;
	const char *method;

	s_con = nm_connection_get_setting_connection (connection);

	if (ip_setting_type == NM_TYPE_SETTING_IP4_CONFIG) {
		g_return_val_if_fail (s_con != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);

		if (nm_setting_connection_get_master (s_con))
			return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
		else {
			s_ip4 = nm_connection_get_setting_ip4_config (connection);
			if (!s_ip4)
				return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
			method = nm_setting_ip_config_get_method (s_ip4);
			g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);

			return method;
		}

	} else if (ip_setting_type == NM_TYPE_SETTING_IP6_CONFIG) {
		g_return_val_if_fail (s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);

		if (nm_setting_connection_get_master (s_con))
			return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
		else {
			s_ip6 = nm_connection_get_setting_ip6_config (connection);
			if (!s_ip6)
				return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
			method = nm_setting_ip_config_get_method (s_ip6);
			g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);

			return method;
		}

	} else
		g_assert_not_reached ();
}
Exemplo n.º 5
0
/**
 * 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;
}
Exemplo n.º 6
0
/**
 * 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;
}
static gboolean
nm_connection_editor_set_connection (NMConnectionEditor *editor,
                                     NMConnection *orig_connection,
                                     GError **error)
{
	NMSettingConnection *s_con;
	const char *connection_type;
	const char *slave_type;
	gboolean success = FALSE;
	GSList *iter, *copy;

	g_return_val_if_fail (NM_IS_CONNECTION_EDITOR (editor), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (orig_connection), FALSE);

	/* clean previous connection */
	if (editor->connection)
		g_object_unref (editor->connection);

	editor->connection = nm_simple_connection_new_clone (orig_connection);

	editor->orig_connection = g_object_ref (orig_connection);
	nm_connection_editor_update_title (editor);

	/* Handle CA cert ignore stuff */
	eap_method_ca_cert_ignore_load (editor->connection);

	s_con = nm_connection_get_setting_connection (editor->connection);
	g_assert (s_con);

	connection_type = nm_setting_connection_get_connection_type (s_con);
	if (!add_page (editor, ce_page_general_new, editor->connection, error))
		goto out;
	if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
		if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_8021x_security_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_dcb_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
		if (!add_page (editor, ce_page_wifi_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_wifi_security_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME)) {
		if (!add_page (editor, ce_page_vpn_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_IP_TUNNEL_SETTING_NAME)) {
		if (!add_page (editor, ce_page_ip_tunnel_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_dsl_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_GSM_SETTING_NAME) || 
	           !strcmp (connection_type, NM_SETTING_CDMA_SETTING_NAME)) {
		if (!add_page (editor, ce_page_mobile_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
		NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (editor->connection);
		const char *type = nm_setting_bluetooth_get_connection_type (s_bt);
		g_assert (type);

		if (!add_page (editor, ce_page_bluetooth_new, editor->connection, error))
			goto out;
		if (!g_strcmp0 (type, "dun")) {
			if (!add_page (editor, ce_page_mobile_new, editor->connection, error))
				goto out;
			if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
				goto out;
		}
	} else if (!strcmp (connection_type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
		if (!add_page (editor, ce_page_infiniband_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BOND_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bond_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_TEAM_SETTING_NAME)) {
		if (!add_page (editor, ce_page_team_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bridge_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_VLAN_SETTING_NAME)) {
		if (!add_page (editor, ce_page_vlan_new, editor->connection, error))
			goto out;
	} else {
		g_warning ("Unhandled setting type '%s'", connection_type);
	}

	slave_type = nm_setting_connection_get_slave_type (s_con);
	if (!g_strcmp0 (slave_type, NM_SETTING_TEAM_SETTING_NAME)) {
		if (!add_page (editor, ce_page_team_port_new, editor->connection, error))
			goto out;
	} else if (!g_strcmp0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bridge_port_new, editor->connection, error))
			goto out;
	}

	if (   nm_connection_get_setting_ip4_config (editor->connection)
	    && !add_page (editor, ce_page_ip4_new, editor->connection, error))
		goto out;
	if (   nm_connection_get_setting_ip6_config (editor->connection)
	    && !add_page (editor, ce_page_ip6_new, editor->connection, error))
		goto out;

	/* After all pages are created, then kick off secrets requests that any
	 * the pages may need to make; if they don't need any secrets, then let
	 * them finish initialization.  The list might get modified during the loop
	 * which is why copy the list here.
	 */
	copy = g_slist_copy (editor->initializing_pages);
	for (iter = copy; iter; iter = g_slist_next (iter)) {
		CEPage *page = CE_PAGE (iter->data);
		const char *setting_name = g_object_get_data (G_OBJECT (page), SECRETS_TAG);

		if (!setting_name) {
			/* page doesn't need any secrets */
			ce_page_complete_init (page, NULL, NULL, NULL);
		} else if (!NM_IS_REMOTE_CONNECTION (editor->orig_connection)) {
			/* We want to get secrets using ->orig_connection, since that's the
			 * remote connection which can actually respond to secrets requests.
			 * ->connection is a plain NMConnection copy of ->orig_connection
			 * which is what gets changed when users modify anything.  But when
			 * creating or importing, ->orig_connection will be an NMConnection
			 * since the new connection hasn't been added to NetworkManager yet.
			 * So basically, skip requesting secrets if the connection can't
			 * handle a secrets request.
			 */
			ce_page_complete_init (page, setting_name, NULL, NULL);
		} else {
			/* Page wants secrets, get them */
			get_secrets_for_page (editor, page, setting_name);
		}
		g_object_set_data (G_OBJECT (page), SECRETS_TAG, NULL);
	}
	g_slist_free (copy);

	/* set the UI */
	recheck_initialization (editor);
	success = TRUE;

out:
	return success;
}
Exemplo n.º 8
0
static void
nmt_page_ip6_constructed (GObject *object)
{
	NmtPageIP6 *ip6 = NMT_PAGE_IP6 (object);
	gboolean show_by_default;
	NmtEditorSection *section;
	NmtEditorGrid *grid;
	NMSettingIPConfig *s_ip6;
	NmtNewtWidget *widget, *button;
	NMConnection *conn;

	conn = nmt_editor_page_get_connection (NMT_EDITOR_PAGE (ip6));
	s_ip6 = nm_connection_get_setting_ip6_config (conn);
	if (!s_ip6) {
		s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
		g_object_set (G_OBJECT (s_ip6),
		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
		              NULL);
		nm_connection_add_setting (conn, (NMSetting *) s_ip6);
	}

	widget = nmt_newt_popup_new (ip6methods);
	g_object_bind_property (s_ip6, NM_SETTING_IP_CONFIG_METHOD,
	                        widget, "active-id",
	                        G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);

	if (!g_strcmp0 (nm_setting_ip_config_get_method (s_ip6), NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
		show_by_default = TRUE;
	else if (nm_setting_ip_config_get_num_addresses (s_ip6))
		show_by_default = TRUE;
	else
		show_by_default = FALSE;

	section = nmt_editor_section_new (_("IPv6 CONFIGURATION"), widget, show_by_default);
	grid = nmt_editor_section_get_body (section);

	widget = nmt_address_list_new (NMT_ADDRESS_LIST_IP6_WITH_PREFIX);
	nm_editor_bind_ip_addresses_with_prefix_to_strv (AF_INET6,
	                                                 s_ip6, NM_SETTING_IP_CONFIG_ADDRESSES,
	                                                 widget, "strings",
	                                                 G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
	nmt_editor_grid_append (grid, _("Addresses"), widget, NULL);

	widget = nmt_ip_entry_new (25, AF_INET6, FALSE, TRUE);
	nm_editor_bind_ip_gateway_to_string (AF_INET6,
	                                     s_ip6,
	                                     widget, "text", "sensitive",
	                                     G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
	nmt_editor_grid_append (grid, _("Gateway"), widget, NULL);

	widget = nmt_address_list_new (NMT_ADDRESS_LIST_IP6);
	nm_editor_bind_ip_addresses_to_strv (AF_INET6,
	                                     s_ip6, NM_SETTING_IP_CONFIG_DNS,
	                                     widget, "strings",
	                                     G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
	nmt_editor_grid_append (grid, _("DNS servers"), widget, NULL);

	widget = nmt_address_list_new (NMT_ADDRESS_LIST_HOSTNAME);
	g_object_bind_property (s_ip6, NM_SETTING_IP_CONFIG_DNS_SEARCH,
	                        widget, "strings",
	                        G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
	nmt_editor_grid_append (grid, _("Search domains"), widget, NULL);

	widget = g_object_new (NMT_TYPE_NEWT_LABEL,
	                       "text", "",
	                       "style", NMT_NEWT_LABEL_PLAIN,
	                       NULL);
	g_object_bind_property_full (s_ip6, NM_SETTING_IP_CONFIG_ROUTES,
	                             widget, "text",
	                             G_BINDING_SYNC_CREATE,
	                             ip6_routes_transform_to_description,
	                             NULL, NULL, NULL);
	button = nmt_newt_button_new (_("Edit..."));
	g_signal_connect (button, "clicked", G_CALLBACK (edit_routes), s_ip6);
	nmt_editor_grid_append (grid, _("Routing"), widget, button);

	widget = nmt_newt_checkbox_new (_("Never use this network for default route"));
	g_object_bind_property (s_ip6, NM_SETTING_IP_CONFIG_NEVER_DEFAULT,
	                        widget, "active",
	                        G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
	nmt_editor_grid_append (grid, NULL, widget, NULL);

	nmt_editor_grid_append (grid, NULL, nmt_newt_separator_new (), NULL);

	widget = nmt_newt_checkbox_new (_("Require IPv6 addressing for this connection"));
	g_object_bind_property (s_ip6, NM_SETTING_IP_CONFIG_MAY_FAIL,
	                        widget, "active",
	                        G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL |
	                        G_BINDING_INVERT_BOOLEAN);
	nmt_editor_grid_append (grid, NULL, widget, NULL);

	nmt_editor_page_add_section (NMT_EDITOR_PAGE (ip6), section);

	G_OBJECT_CLASS (nmt_page_ip6_parent_class)->constructed (object);
}