示例#1
0
/*
 * Parse IPv6 route from strings to NMIP6Route stucture.
 * ip_str is the IPv6 route in the form address/prefix
 * next_hop_str is the next hop
 * metric_str is the route metric
 */
NMIP6Route *
nmc_parse_and_build_ip6_route (const char *ip_str, const char *next_hop_str, const char *metric_str, GError **error)
{
	NMIP6Route *route = NULL;
	struct in6_addr ip_addr, next_hop_addr;
	char *tmp;
	char *plen;
	long int prefix, metric;

	g_return_val_if_fail (ip_str != NULL, NULL);
	g_return_val_if_fail (error == NULL || *error == NULL, NULL);

	tmp = g_strdup (ip_str);
	plen = strchr (tmp, '/');  /* prefix delimiter */
	if (plen)
		*plen++ = '\0';

	if (inet_pton (AF_INET6, tmp, &ip_addr) < 1) {
		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
		             _("invalid IPv6 route '%s'"), tmp);
		goto finish;
	}

	prefix = 128;
	if (plen) {
		if (!nmc_string_to_int (plen, TRUE, 0, 128, &prefix)) {
			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
			             _("invalid prefix '%s'; <0-128> allowed"), plen);
			goto finish;
		}
	}

	if (inet_pton (AF_INET6, next_hop_str, &next_hop_addr) < 1) {
		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
		             _("invalid next hop address '%s'"), next_hop_str);
		goto finish;
	}

	metric = 0;
	if (metric_str) {
		if (!nmc_string_to_int (metric_str, TRUE, 0, G_MAXUINT32, &metric)) {
			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
			             _("invalid metric '%s'"), metric_str);
			goto finish;
		}
	}

	route = nm_ip6_route_new ();
	nm_ip6_route_set_dest (route, &ip_addr);
	nm_ip6_route_set_prefix (route, (guint32) prefix);
	nm_ip6_route_set_next_hop (route, &next_hop_addr);
	nm_ip6_route_set_metric (route, (guint32) metric);

finish:
	g_free (tmp);
	return route;
}
示例#2
0
NMIP6Config *
nm_ip6_config_new_for_interface (int ifindex)
{
	NMIP6Config *ip6;
	GArray *addrs_array, *routes_array;
	NMPlatformIP6Address *addrs;
	NMPlatformIP6Route *routes;
	NMIP6Address *addr;
	NMIP6Route *route;
	int i;

	addrs_array = nm_platform_ip6_address_get_all (ifindex);
	if (addrs_array->len == 0) {
		g_array_unref (addrs_array);
		return NULL;
	}

	ip6 = nm_ip6_config_new ();

	addrs = (NMPlatformIP6Address *)addrs_array->data;
	for (i = 0; i < addrs_array->len; i++) {
		addr = nm_ip6_address_new ();
		nm_ip6_address_set_address (addr, &addrs[i].address);
		nm_ip6_address_set_prefix (addr, addrs[i].plen);
		nm_ip6_config_take_address (ip6, addr);
	}
	g_array_unref (addrs_array);

	routes_array = nm_platform_ip6_route_get_all (ifindex);
	routes = (NMPlatformIP6Route *)routes_array->data;
	for (i = 0; i < routes_array->len; i++) {
		/* Default route ignored; it's handled internally by NM and not
		* tracked in the device's IP config.
		*/
		if (routes[i].plen == 0)
			continue;

		route = nm_ip6_route_new ();
		nm_ip6_route_set_dest (route, &routes[i].network);
		nm_ip6_route_set_prefix (route, routes[i].plen);
		nm_ip6_route_set_next_hop (route, &routes[i].gateway);
		nm_ip6_route_set_metric (route, routes[i].metric);
		nm_ip6_config_take_route (ip6, route);
	}
	g_array_unref (routes_array);

	return ip6;
}
示例#3
0
NMIP6Config *
nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
{
	NMIP6ManagerPrivate *priv;
	NMIP6Device *device;
	NMIP6Config *config;
	struct rtnl_addr *rtnladdr;
	struct nl_addr *nladdr;
	struct in6_addr *addr;
	NMIP6Address *ip6addr;
	struct rtnl_route *rtnlroute;
	struct nl_addr *nldest, *nlgateway;
	struct in6_addr *dest, *gateway;
	gboolean defgw_set = FALSE;
	struct in6_addr defgw;
	uint32_t metric;
	NMIP6Route *ip6route;
	int i;

	g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), NULL);
	g_return_val_if_fail (ifindex > 0, NULL);

	priv = NM_IP6_MANAGER_GET_PRIVATE (manager);

	device = (NMIP6Device *) g_hash_table_lookup (priv->devices,
	                                              GINT_TO_POINTER (ifindex));
	if (!device) {
		nm_log_warn (LOGD_IP6, "(%d): addrconf not started.", ifindex);
		return NULL;
	}

	config = nm_ip6_config_new ();
	if (!config) {
		nm_log_err (LOGD_IP6, "(%s): out of memory creating IP6 config object.",
		            device->iface);
		return NULL;
	}

	/* Make sure we refill the route and address caches, otherwise we won't get
	 * up-to-date information here since the netlink route/addr change messages
	 * may be lagging a bit.
	 */
	nl_cache_refill (priv->nlh, priv->route_cache);
	nl_cache_refill (priv->nlh, priv->addr_cache);

	/* Add routes */
	for (rtnlroute = FIRST_ROUTE (priv->route_cache); rtnlroute; rtnlroute = NEXT_ROUTE (rtnlroute)) {
		/* Make sure it's an IPv6 route for this device */
		if (rtnl_route_get_oif (rtnlroute) != device->ifindex)
			continue;
		if (rtnl_route_get_family (rtnlroute) != AF_INET6)
			continue;

		nldest = rtnl_route_get_dst (rtnlroute);
		if (!nldest || nl_addr_get_family (nldest) != AF_INET6)
			continue;
		dest = nl_addr_get_binary_addr (nldest);

		nlgateway = rtnl_route_get_gateway (rtnlroute);
		if (!nlgateway || nl_addr_get_family (nlgateway) != AF_INET6)
			continue;
		gateway = nl_addr_get_binary_addr (nlgateway);

		if (rtnl_route_get_dst_len (rtnlroute) == 0) {
			/* Default gateway route; don't add to normal routes but to each address */
			if (!defgw_set) {
				memcpy (&defgw, gateway, sizeof (defgw));
				defgw_set = TRUE;
			}
			continue;
		}

		/* Also ignore link-local routes where the destination and gateway are
		 * the same, which apparently get added by the kernel but return -EINVAL
		 * when we try to add them via netlink.
		 */
		if (gateway && IN6_ARE_ADDR_EQUAL (dest, gateway))
			continue;

		ip6route = nm_ip6_route_new ();
		nm_ip6_route_set_dest (ip6route, dest);
		nm_ip6_route_set_prefix (ip6route, rtnl_route_get_dst_len (rtnlroute));
		nm_ip6_route_set_next_hop (ip6route, gateway);
		rtnl_route_get_metric(rtnlroute, 1, &metric);
		if (metric != UINT_MAX)
			nm_ip6_route_set_metric (ip6route, metric);
		nm_ip6_config_take_route (config, ip6route);
	}

	/* Add addresses */
	for (rtnladdr = FIRST_ADDR (priv->addr_cache); rtnladdr; rtnladdr = NEXT_ADDR (rtnladdr)) {
		if (rtnl_addr_get_ifindex (rtnladdr) != device->ifindex)
			continue;

		nladdr = rtnl_addr_get_local (rtnladdr);
		if (!nladdr || nl_addr_get_family (nladdr) != AF_INET6)
			continue;

		addr = nl_addr_get_binary_addr (nladdr);
		ip6addr = nm_ip6_address_new ();
		nm_ip6_address_set_prefix (ip6addr, rtnl_addr_get_prefixlen (rtnladdr));
		nm_ip6_address_set_address (ip6addr, addr);
		nm_ip6_config_take_address (config, ip6addr);
		if (defgw_set)
			nm_ip6_address_set_gateway (ip6addr, &defgw);
	}

	/* Add DNS servers */
	if (device->rdnss_servers) {
		NMIP6RDNSS *rdnss = (NMIP6RDNSS *)(device->rdnss_servers->data);

		for (i = 0; i < device->rdnss_servers->len; i++)
			nm_ip6_config_add_nameserver (config, &rdnss[i].addr);
	}

	/* Add DNS domains */
	if (device->dnssl_domains) {
		NMIP6DNSSL *dnssl = (NMIP6DNSSL *)(device->dnssl_domains->data);

		for (i = 0; i < device->dnssl_domains->len; i++)
			nm_ip6_config_add_domain (config, dnssl[i].domain);
	}

	return config;
}
示例#4
0
static gboolean
ui_to_setting (CEPageIP6 *page)
{
        gboolean valid = FALSE;
        const gchar *method;
        gboolean ignore_auto_dns;
        gboolean ignore_auto_routes;
        gboolean never_default;
        GList *children, *l;

        if (!gtk_switch_get_active (page->enabled)) {
                method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
        } else {
                switch (gtk_combo_box_get_active (page->method)) {
                case IP6_METHOD_MANUAL:
                        method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
                        break;
                case IP6_METHOD_LINK_LOCAL:
                        method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
                        break;
                case IP6_METHOD_DHCP:
                        method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
                        break;
                default:
                case IP6_METHOD_AUTO:
                        method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
                        break;
                }
        }

        nm_setting_ip6_config_clear_addresses (page->setting);
        children = gtk_container_get_children (GTK_CONTAINER (page->address_list));
        for (l = children; l; l = l->next) {
                GtkWidget *row = l->data;
                GtkEntry *entry;
                const gchar *text_address;
                const gchar *text_prefix;
                const gchar *text_gateway;
                struct in6_addr tmp_addr;
                struct in6_addr tmp_gateway;
                guint32 prefix;
                gchar *end;
                NMIP6Address *addr;
                gboolean have_gateway = FALSE;

                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
                if (!entry)
                        continue;

                text_address = gtk_entry_get_text (entry);
                text_prefix = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "prefix")));
                text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));

                if (!*text_address && !*text_prefix && !*text_gateway) {
                        /* ignore empty rows */
                        continue;
                }

                if (inet_pton (AF_INET6, text_address, &tmp_addr) <= 0) {
                        g_warning ("IPv6 address %s missing or invalid", text_address);
                        goto out;
                }

                prefix = strtoul (text_prefix, &end, 10);
                if (!end || *end || prefix == 0 || prefix > 128) {
                        g_warning ("IPv6 prefix %s is invalid", text_prefix);
                        goto out;
                }

                if (text_gateway && *text_gateway) {
                        if (inet_pton (AF_INET6, text_gateway, &tmp_gateway) <= 0) {
                                g_warning ("IPv6 gateway %s is invalid", text_gateway);
                                goto out;
                        }
                        if (!IN6_IS_ADDR_UNSPECIFIED (&tmp_gateway))
                                have_gateway = TRUE;
                }

                addr = nm_ip6_address_new ();
                nm_ip6_address_set_address (addr, &tmp_addr);
                nm_ip6_address_set_prefix (addr, prefix);
                if (have_gateway)
                        nm_ip6_address_set_gateway (addr, &tmp_gateway);
                nm_setting_ip6_config_add_address (page->setting, addr);
        }
        g_list_free (children);

        nm_setting_ip6_config_clear_dns (page->setting);
        children = gtk_container_get_children (GTK_CONTAINER (page->dns_list));
        for (l = children; l; l = l->next) {
                GtkWidget *row = l->data;
                GtkEntry *entry;
                const gchar *text;
                struct in6_addr tmp_addr;

                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
                if (!entry)
                        continue;

                text = gtk_entry_get_text (entry);
                if (!*text) {
                        /* ignore empty rows */
                        continue;
                }

                if (inet_pton (AF_INET6, text, &tmp_addr) <= 0) {
                        g_warning ("IPv6 dns server %s invalid", text);
                        goto out;
                }

                nm_setting_ip6_config_add_dns (page->setting, &tmp_addr);
        }
        g_list_free (children);

        nm_setting_ip6_config_clear_routes (page->setting);
        children = gtk_container_get_children (GTK_CONTAINER (page->routes_list));
        for (l = children; l; l = l->next) {
                GtkWidget *row = l->data;
                GtkEntry *entry;
                const gchar *text_address;
                const gchar *text_prefix;
                const gchar *text_gateway;
                const gchar *text_metric;
                struct in6_addr dest, gateway;
                guint32 prefix, metric;
                gchar *end;
                NMIP6Route *route;

                entry = GTK_ENTRY (g_object_get_data (G_OBJECT (row), "address"));
                if (!entry)
                        continue;

                text_address = gtk_entry_get_text (entry);
                text_prefix = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "prefix")));
                text_gateway = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "gateway")));
                text_metric = gtk_entry_get_text (GTK_ENTRY (g_object_get_data (G_OBJECT (row), "metric")));

                if (!*text_address && !*text_prefix && !*text_gateway && !*text_metric) {
                        /* ignore empty rows */
                        continue;
                }

                if (inet_pton (AF_INET6, text_address, &dest) <= 0) {
                        g_warning ("IPv6 route address %s invalid", text_address);
                        goto out;
                }

                prefix = strtoul (text_prefix, &end, 10);
                if (!end || *end || prefix == 0 || prefix > 128) {
                        g_warning ("IPv6 route prefix %s invalid", text_prefix);
                        goto out;
                }

                if (inet_pton (AF_INET6, text_gateway, &gateway) <= 0) {
                        g_warning ("IPv6 route gateway %s invalid", text_gateway);
                        goto out;
                }

                metric = 0;
                if (*text_metric) {
                        errno = 0;
                        metric = strtoul (text_metric, NULL, 10);
                        if (errno) {
                                g_warning ("IPv6 route metric %s invalid", text_metric);
                                goto out;
                        }
                }

                route = nm_ip6_route_new ();
                nm_ip6_route_set_dest (route, &dest);
                nm_ip6_route_set_prefix (route, prefix);
                nm_ip6_route_set_next_hop (route, &gateway);
                nm_ip6_route_set_metric (route, metric);
                nm_setting_ip6_config_add_route (page->setting, route);
                nm_ip6_route_unref (route);
        }
        g_list_free (children);

        ignore_auto_dns = !gtk_switch_get_active (page->auto_dns);
        ignore_auto_routes = !gtk_switch_get_active (page->auto_routes);
        never_default = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (page->never_default));

        g_object_set (page->setting,
                      NM_SETTING_IP6_CONFIG_METHOD, method,
                      NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, ignore_auto_dns,
                      NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, ignore_auto_routes,
                      NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, never_default,
                      NULL);

        valid = TRUE;

out:

        return valid;
}
void
ip6_routes_dialog_update_setting (GtkWidget *dialog, NMSettingIP6Config *s_ip6)
{
	GtkBuilder *builder;
	GtkWidget *widget;
	GtkTreeModel *model;
	GtkTreeIter tree_iter;
	gboolean iter_valid;

	g_return_if_fail (dialog != NULL);
	g_return_if_fail (s_ip6 != NULL);

	builder = g_object_get_data (G_OBJECT (dialog), "builder");
	g_return_if_fail (builder != NULL);
	g_return_if_fail (GTK_IS_BUILDER (builder));

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_routes"));
	model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
	iter_valid = gtk_tree_model_get_iter_first (model, &tree_iter);

	nm_setting_ip6_config_clear_routes (s_ip6);

	while (iter_valid) {
		struct in6_addr dest, next_hop;
		guint prefix = 0, metric = 0;
		NMIP6Route *route;

		/* Address */
		if (!get_one_addr (model, &tree_iter, COL_ADDRESS, TRUE, &dest)) {
			g_warning ("%s: IPv6 address missing or invalid!", __func__);
			goto next;
		}

		/* Prefix */
		if (!get_one_int (model, &tree_iter, COL_PREFIX, 128, TRUE, &prefix)) {
			g_warning ("%s: IPv6 prefix missing or invalid!", __func__);
			goto next;
		}

		/* Next hop (optional) */
		memset (&next_hop, 0, sizeof (struct in6_addr));
		if (!get_one_addr (model, &tree_iter, COL_NEXT_HOP, FALSE, &next_hop)) {
			g_warning ("%s: IPv6 next hop invalid!", __func__);
			goto next;
		}

		/* Metric (optional) */
		if (!get_one_int (model, &tree_iter, COL_METRIC, G_MAXUINT32, FALSE, &metric)) {
			g_warning ("%s: IPv6 metric invalid!", __func__);
			goto next;
		}

		route = nm_ip6_route_new ();
		nm_ip6_route_set_dest (route, &dest);
		nm_ip6_route_set_prefix (route, prefix);
		nm_ip6_route_set_next_hop (route, &next_hop);
		nm_ip6_route_set_metric (route, metric);
		nm_setting_ip6_config_add_route (s_ip6, route);
		nm_ip6_route_unref (route);

	next:
		iter_valid = gtk_tree_model_iter_next (model, &tree_iter);
	}

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_ignore_auto_routes"));
	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
	              gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)),
	              NULL);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "ip6_never_default"));
	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_NEVER_DEFAULT,
	              gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)),
	              NULL);
}