예제 #1
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;
}
예제 #2
0
static void route_proc_cb(struct nl_object *c, void *arg)
{
        struct ip_lookup_res *res = (struct ip_lookup_res*) arg;
	struct rtnl_route *route = (struct rtnl_route *) c;
	struct nl_cache *link_cache;
        struct nl_addr *addr;
        struct rtnl_nexthop *nh;
        int prefix_len;
        int oif;
	char buf[64];

	link_cache = nl_cache_mngt_require("route/link");

        addr = rtnl_route_get_dst(route);
        if (addr) {
		printf("%s", nl_addr2str(addr, buf, sizeof(buf)));
                res->dstaddr = *(uint32_t *) nl_addr_get_binary_addr(addr);
        }

        prefix_len = rtnl_route_get_dst_len(route);
        if (prefix_len)
                printf("/%d ", prefix_len);
        else
                printf("default ");

        addr = rtnl_route_get_src(route);
        if (addr) 
		printf("src %s ", nl_addr2str(addr, buf, sizeof(buf)));

        addr = rtnl_route_get_pref_src(route);
        if (addr)
		printf("preferred src %s ", nl_addr2str(addr, buf, sizeof(buf)));

        addr = rtnl_route_get_gateway(route);
        if (addr) { 
		printf("via %s ", nl_addr2str(addr, buf, sizeof(buf)));
                res->nh_addr = *(uint32_t*) nl_addr_get_binary_addr(addr);
        }
        else {
                res->nh_addr = 0;
        }

        oif = rtnl_route_get_oif(route);
        res->oif = oif;
        if (oif != RTNL_LINK_NOT_FOUND && link_cache) {
	        printf("dev %s ", rtnl_link_i2name(link_cache, oif,
						 buf, sizeof(buf)));
                rtnl_link_i2name(link_cache, oif, res->oifname, sizeof(res->oifname));
        }
        
        /* Declaration of rtnl_route_nh_get_gateway() is missing from 
         * include/netlink/route/nexthop.h, there is no way to inspect
         * each nexthop for gateway information, will just use gateway 
         * info stored in rtnl_route struct. The probem is only present
         * libnl 1 */
        /*
        nl_list_for_each_entry(nh, rtnl_route_get_nexthops(route), rtnh_list) {

        }
        */
                
        printf("\n");

}