static void
find_one_address (struct nl_object *object, void *user_data)
{
	FindAddrInfo *info = user_data;
	struct rtnl_addr *addr = (struct rtnl_addr *) object;
	struct nl_addr *local;
	void *binaddr;

	if (info->found)
		return;

	if (rtnl_addr_get_ifindex (addr) != info->ifindex)
		return;
	if (rtnl_addr_get_family (addr) != info->family)
		return;

	if (rtnl_addr_get_prefixlen (addr) != info->prefix)
		return;

	local = rtnl_addr_get_local (addr);
	if (nl_addr_get_family (local) != info->family)
		return;
	if (nl_addr_get_len (local) != info->addrlen)
		return;
	binaddr = nl_addr_get_binary_addr (local);
	if (binaddr) {
		if (memcmp (binaddr, info->addr, info->addrlen) == 0)
			info->found = TRUE; /* Yay, found it */
	}
}
Exemplo n.º 2
0
static void get_ip(struct nl_object *obj, void *arg)
{
	struct rtnl_addr * addr = (struct rtnl_addr *) obj;
	struct nl_addr *naddr = rtnl_addr_get_local(addr);
	int prefixlen = rtnl_addr_get_prefixlen(addr);
	if ((NULL != naddr) && (prefixlen == *(int*)(arg)))
		printf("ip is 0x%x\n", *(uint32_t *) (nl_addr_get_binary_addr(naddr)));
}
static void
check_addresses (NMIP6Device *device)
{
	NMIP6Manager *manager = device->manager;
	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
	struct rtnl_addr *rtnladdr;
	struct nl_addr *nladdr;
	struct in6_addr *addr;

	/* Reset address information */
	device->has_linklocal = FALSE;
	device->has_nonlinklocal = FALSE;

	/* Look for any IPv6 addresses the kernel may have set for the device */
	for (rtnladdr = (struct rtnl_addr *) nl_cache_get_first (priv->addr_cache);
		 rtnladdr;
		 rtnladdr = (struct rtnl_addr *) nl_cache_get_next ((struct nl_object *) rtnladdr)) {
		char buf[INET6_ADDRSTRLEN];

		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);

		if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0) {
			nm_log_dbg (LOGD_IP6, "(%s): netlink address: %s/%d",
			            device->iface, buf,
			            rtnl_addr_get_prefixlen (rtnladdr));
		}

		if (IN6_IS_ADDR_LINKLOCAL (addr)) {
			if (device->state == NM_IP6_DEVICE_UNCONFIGURED)
				device_set_state (device, NM_IP6_DEVICE_GOT_LINK_LOCAL);
			device->has_linklocal = TRUE;
		} else {
			if (device->state == NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT)
				device_set_state (device, NM_IP6_DEVICE_GOT_ADDRESS);
			device->has_nonlinklocal = TRUE;
		}
	}

	/* There might be a LL address hanging around on the interface from
	 * before in the initial run, but if it goes away later, make sure we
	 * regress from GOT_LINK_LOCAL back to UNCONFIGURED.
	 */
	if ((device->state == NM_IP6_DEVICE_GOT_LINK_LOCAL) && !device->has_linklocal)
		device_set_state (device, NM_IP6_DEVICE_UNCONFIGURED);

	nm_log_dbg (LOGD_IP6, "(%s): addresses checked (state %s)",
		    device->iface, state_to_string (device->state));
}
Exemplo n.º 4
0
/**
 *  libnl callback function.  Does the real parsing of a record returned by NETLINK.  This function
 *  parses ADDRESS related packets
 *
 * @param obj   Pointer to a struct nl_object response
 * @param arg   Pointer to a struct etherinfo element where the parse result will be saved
 */
static void callback_nl_address(struct nl_object *obj, void *arg)
{
	struct etherinfo *ethi = (struct etherinfo *) arg;
	struct nl_addr *addr;
	char ip_str[66];
	int family;

	if( ethi == NULL ) {
		return;
	}

	addr = rtnl_addr_get_local((struct rtnl_addr *)obj);
	family = nl_addr_get_family(addr);
	switch( family ) {
	case AF_INET:
	case AF_INET6:
		memset(&ip_str, 0, 66);
		inet_ntop(family, nl_addr_get_binary_addr(addr), (char *)&ip_str, 64);

		if( family == AF_INET ) {
			struct nl_addr *brdcst = rtnl_addr_get_broadcast((struct rtnl_addr *)obj);
			char brdcst_str[66];

			SET_STR_VALUE(ethi->ipv4_address, ip_str);
			ethi->ipv4_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*) obj);

			if( brdcst ) {
				memset(&brdcst_str, 0, 66);
				inet_ntop(family, nl_addr_get_binary_addr(brdcst), (char *)&brdcst_str, 64);
				SET_STR_VALUE(ethi->ipv4_broadcast, brdcst_str);
			}
		} else {
			ethi->ipv6_addresses = etherinfo_add_ipv6(ethi->ipv6_addresses,
								  ip_str,
								  rtnl_addr_get_prefixlen((struct rtnl_addr*) obj),
								  rtnl_addr_get_scope((struct rtnl_addr*) obj));
		}
		return;
	default:
		return;
	}
}
Exemplo n.º 5
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;
}