예제 #1
0
static void
get_property (GObject *object,
              guint prop_id,
              GValue *value,
              GParamSpec *pspec)
{
	NMIP6Config *self = NM_IP6_CONFIG (object);
	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);

	_nm_object_ensure_inited (NM_OBJECT (object));

	switch (prop_id) {
	case PROP_GATEWAY:
		g_value_set_string (value, nm_ip6_config_get_gateway (self));
		break;
	case PROP_ADDRESSES:
		nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
		break;
	case PROP_ROUTES:
		nm_utils_ip6_routes_to_gvalue (priv->routes, value);
		break;
	case PROP_NAMESERVERS:
		g_value_set_boxed (value, nm_ip6_config_get_nameservers (self));
		break;
	case PROP_DOMAINS:
		g_value_set_boxed (value, nm_ip6_config_get_domains (self));
		break;
	case PROP_SEARCHES:
		g_value_set_boxed (value, nm_ip6_config_get_searches (self));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
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;
	const struct in6_addr *dest, *gateway;
	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;

		/* And ignore cache/cloned routes as they aren't part of the interface's
		 * permanent routing configuration.
		 */
		if (rtnl_route_get_flags (rtnlroute) & RTM_F_CLONED)
			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; cache the router's address for later */
			if (!nm_ip6_config_get_gateway (config))
				nm_ip6_config_set_gateway (config, gateway);
			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);
		gateway = nm_ip6_config_get_gateway (config);
		if (gateway)
			nm_ip6_address_set_gateway (ip6addr, gateway);
	}

	/* 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;
}
예제 #3
0
static void
dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder)
{
	GVariantBuilder int_builder;
	guint n, i;
	const NMPlatformIP6Address *addr;
	const struct in6_addr *gw_bytes;
	const NMPlatformIP6Route *route;
	GVariant *ip, *gw;

	/* Addresses */
	g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuay)"));
	n = nm_ip6_config_get_num_addresses (ip6);
	for (i = 0; i < n; i++) {
		addr = nm_ip6_config_get_address (ip6, i);
		gw_bytes = nm_ip6_config_get_gateway (ip6);
		ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
		                                &addr->address,
		                                sizeof (struct in6_addr), 1);
		gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
		                                (i == 0 && gw_bytes) ? gw_bytes : &in6addr_any,
		                                sizeof (struct in6_addr), 1);
		g_variant_builder_add (&int_builder, "(@ayu@ay)", ip, addr->plen, gw);
	}
	g_variant_builder_add (builder, "{sv}",
	                       "addresses",
	                       g_variant_builder_end (&int_builder));

	/* DNS servers */
	g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aay"));
	n = nm_ip6_config_get_num_nameservers (ip6);
	for (i = 0; i < n; i++) {
		ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
		                                nm_ip6_config_get_nameserver (ip6, i),
		                                sizeof (struct in6_addr), 1);
		g_variant_builder_add (&int_builder, "@ay", ip);
	}
	g_variant_builder_add (builder, "{sv}",
	                       "nameservers",
	                       g_variant_builder_end (&int_builder));

	/* Search domains */
	g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("as"));
	n = nm_ip6_config_get_num_domains (ip6);
	for (i = 0; i < n; i++)
		g_variant_builder_add (&int_builder, "s", nm_ip6_config_get_domain (ip6, i));
	g_variant_builder_add (builder, "{sv}",
	                       "domains",
	                       g_variant_builder_end (&int_builder));

	/* Static routes */
	g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuayu)"));
	n = nm_ip6_config_get_num_routes (ip6);
	for (i = 0; i < n; i++) {
		route = nm_ip6_config_get_route (ip6, i);
		ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
		                                &route->network,
		                                sizeof (struct in6_addr), 1);
		gw = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
		                                &route->gateway,
		                                sizeof (struct in6_addr), 1);
		g_variant_builder_add (&int_builder, "(@ayu@ayu)", ip, route->plen, gw, route->metric);
	}
	g_variant_builder_add (builder, "{sv}",
	                       "routes",
	                       g_variant_builder_end (&int_builder));
}