示例#1
0
void netlink_neigh_info::fill(struct rtnl_neigh* neigh)
{
	if (!neigh) 
		return;

	nl_addr* addr;
	char addr_str[ADDR_MAX_STR_LEN + 1];

	addr = rtnl_neigh_get_dst(neigh);
	if (addr) {
		dst_addr_str = nl_addr2str(addr, addr_str, ADDR_MAX_STR_LEN);
		dst_addr = (unsigned char*)nl_addr_get_binary_addr(addr);
		dst_addr_len = nl_addr_get_len(addr);
	}

	addr = rtnl_neigh_get_lladdr(neigh);
	if (addr) {
		lladdr_str = nl_addr2str(addr, addr_str, ADDR_MAX_STR_LEN);
		lladdr = (unsigned char*)nl_addr_get_binary_addr(addr);
		lladdr_len = nl_addr_get_len(addr);
	}
	//addr_family = rtnl_neigh_get_family(neigh);
	flags = rtnl_neigh_get_flags(neigh);
	ifindex = rtnl_neigh_get_ifindex(neigh);
	state = rtnl_neigh_get_state(neigh);
	type = rtnl_neigh_get_type(neigh);
}
示例#2
0
static int get_link_local_mac_ipv6(struct nl_addr *dst,
				   struct nl_addr **ll_addr)
{
	uint8_t mac_addr[6];

	memcpy(mac_addr + 3, (uint8_t *)nl_addr_get_binary_addr(dst) + 13, 3);
	memcpy(mac_addr, (uint8_t *)nl_addr_get_binary_addr(dst) + 8, 3);
	mac_addr[0] ^= 2;

	*ll_addr = nl_addr_build(AF_LLC, mac_addr, sizeof(mac_addr));
	return *ll_addr == NULL ? -EINVAL : 0;
}
示例#3
0
void nl_bridge::add_neigh_to_fdb(rtnl_neigh *neigh) {
  assert(sw);
  assert(neigh);

  uint32_t port = nl->get_port_id(rtnl_neigh_get_ifindex(neigh));
  if (port == 0) {
    VLOG(1) << __FUNCTION__ << ": unknown port for neigh " << OBJ_CAST(neigh);
    return;
  }

  nl_addr *mac = rtnl_neigh_get_lladdr(neigh);
  int vlan = rtnl_neigh_get_vlan(neigh);

  bool permanent = true;

  // for sure this is master (sw bridged)
  if (rtnl_neigh_get_master(neigh) &&
      !(rtnl_neigh_get_flags(neigh) & NTF_MASTER)) {
    rtnl_neigh_set_flags(neigh, NTF_MASTER);
  }

  // check if entry already exists in cache
  if (is_mac_in_l2_cache(neigh)) {
    permanent = false;
  }

  rofl::caddress_ll _mac((uint8_t *)nl_addr_get_binary_addr(mac),
                         nl_addr_get_len(mac));

  LOG(INFO) << __FUNCTION__ << ": add mac=" << _mac << " to bridge "
            << rtnl_link_get_name(bridge) << " on port=" << port
            << " vlan=" << (unsigned)vlan << ", permanent=" << permanent;
  LOG(INFO) << __FUNCTION__ << ": object: " << OBJ_CAST(neigh);
  sw->l2_addr_add(port, vlan, _mac, true, permanent);
}
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 */
	}
}
示例#5
0
/**
 *  libnl callback function.  Does the real parsing of a record returned by NETLINK.  This function
 *  parses LINK 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_link(struct nl_object *obj, void *arg)
{
	struct etherinfo *ethi = (struct etherinfo *) arg;
	struct rtnl_link *link = (struct rtnl_link *) obj;
	struct nl_addr *addr = rtnl_link_get_addr(link);
	unsigned int i, len;
	unsigned char *binaddr;
	char hwaddr[130], *ptr;

	if( (ethi == NULL) || (ethi->hwaddress != NULL) || (addr == NULL) ) {
		return;
	}

	binaddr = nl_addr_get_binary_addr(addr);
	memset(&hwaddr, 0, 130);
	len = 20;
	ptr = (char *)&hwaddr;
	for( i = 0; i < 6; i++ ) {
		if( i == 0 ) {
			snprintf(ptr, len, "%02X", *(binaddr+i));
			len -= 2;
			ptr += 2;
		} else {
			snprintf(ptr, len, ":%02X", *(binaddr+i));
			len -= 3;
			ptr += 3;
		}
	}
	SET_STR_VALUE(ethi->hwaddress, hwaddr);
}
示例#6
0
文件: libnl3.c 项目: exuuwen/study
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)));
}
示例#7
0
文件: libnl3.c 项目: exuuwen/study
static void get_route(struct nl_object *obj, void *arg)
{
	struct rtnl_route *route = (struct rtnl_route *) obj;
	struct rtnl_nexthop * nexthop = rtnl_route_nexthop_n(route, 0);
	struct nl_addr *naddr = rtnl_route_nh_get_gateway(nexthop);

	if (NULL != naddr)
		printf("gwip is 0x%x\n", *(uint32_t *) (nl_addr_get_binary_addr(naddr)));
	
}
static void
dump_route (struct rtnl_route *route)
{
	char buf6[INET6_ADDRSTRLEN];
	char buf4[INET_ADDRSTRLEN];
	struct nl_addr *nl;
	struct in6_addr *addr6 = NULL;
	struct in_addr *addr4 = NULL;
	int prefixlen = 0;
	const char *sf = "UNSPEC";
	int family = rtnl_route_get_family (route);
	guint32 log_level = LOGD_IP4 | LOGD_IP6;

	memset (buf6, 0, sizeof (buf6));
	memset (buf4, 0, sizeof (buf4));
	nl = rtnl_route_get_dst (route);
	if (nl) {
		if (nl_addr_get_family (nl) == AF_INET) {
			addr4 = nl_addr_get_binary_addr (nl);
			if (addr4)
				inet_ntop (AF_INET, addr4, &buf4[0], sizeof (buf4));
		} else if (nl_addr_get_family (nl) == AF_INET6) {
			addr6 = nl_addr_get_binary_addr (nl);
			if (addr6)
				inet_ntop (AF_INET6, addr6, &buf6[0], sizeof (buf6));
		}
		prefixlen = nl_addr_get_prefixlen (nl);
	}

	if (family == AF_INET) {
		sf = "INET";
		log_level = LOGD_IP4;
	} else if (family == AF_INET6) {
		sf = "INET6";
		log_level = LOGD_IP6;
	}

	nm_log_dbg (log_level, "  route idx %d family %s (%d) addr %s/%d",
	            rtnl_route_get_oif (route),
	            sf, family,
	            strlen (buf4) ? buf4 : (strlen (buf6) ? buf6 : "<unknown>"),
	            prefixlen);
}
示例#9
0
static int get_mcast_mac_ipv6(struct nl_addr *dst, struct nl_addr **ll_addr)
{
	uint8_t mac_addr[6] = {0x33, 0x33};

	memcpy(mac_addr + 2, (uint8_t *)nl_addr_get_binary_addr(dst) + 12, 4);

	*ll_addr = nl_addr_build(AF_LLC, mac_addr, sizeof(mac_addr));

	return *ll_addr == NULL ? -EINVAL : 0;
}
示例#10
0
static Option<net::IP> IP(nl_addr* _ip)
{
  Option<net::IP> result;
  if (_ip != NULL && nl_addr_get_len(_ip) != 0) {
    struct in_addr* addr = (struct in_addr*) nl_addr_get_binary_addr(_ip);
    result = net::IP(*addr);
  }

  return result;
}
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));
}
示例#12
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;
	}
}
示例#13
0
文件: inet6.c 项目: Domikk/libnl
/**
 * Set IPv6 tokenized interface identifier
 * @arg link		Link object
 * @arg token		Tokenized interface identifier
 *
 * Sets the link's IPv6 tokenized interface identifier.
 *
 * @return 0 on success
 * @return -NLE_NOMEM could not allocate inet6 data
 * @return -NLE_INVAL addr is not a valid inet6 address
 */
int rtnl_link_inet6_set_token(struct rtnl_link *link, struct nl_addr *addr)
{
	struct inet6_data *id;

	if ((nl_addr_get_family(addr) != AF_INET6) ||
	    (nl_addr_get_len(addr) != sizeof(id->i6_token)))
		return -NLE_INVAL;

	if (!(id = rtnl_link_af_alloc(link, &inet6_ops)))
		return -NLE_NOMEM;

	memcpy(&id->i6_token, nl_addr_get_binary_addr(addr),
	       sizeof(id->i6_token));
	return 0;
}
示例#14
0
static int get_mcast_mac_ipv4(struct nl_addr *dst, struct nl_addr **ll_addr)
{
	uint8_t mac_addr[6] = {0x01, 0x00, 0x5E};
	uint32_t addr = be32toh(*(__be32 *)nl_addr_get_binary_addr(dst));

	mac_addr[5] = addr & 0xFF;
	addr >>= 8;
	mac_addr[4] = addr & 0xFF;
	addr >>= 8;
	mac_addr[3] = addr & 0x7F;

	*ll_addr = nl_addr_build(AF_LLC, mac_addr, sizeof(mac_addr));

	return *ll_addr == NULL ? -EINVAL : 0;
}
static void
foreach_route_cb (struct nl_object *object, void *user_data)
{
	ForeachRouteInfo *info = user_data;
	struct rtnl_route *route = (struct rtnl_route *) object;
	struct nl_addr *dst;

	if (info->out_route)
		return;

	if (nm_logging_level_enabled (LOGL_DEBUG))
		dump_route (route);

	if (   info->ifindex > 0
	    && rtnl_route_get_oif (route) != info->ifindex)
		return;

	if (   info->scope != RT_SCOPE_UNIVERSE
	    && rtnl_route_get_scope (route) != info->scope)
		return;

	if (   info->family != AF_UNSPEC
	    && rtnl_route_get_family (route) != info->family)
		return;

	dst = rtnl_route_get_dst (route);

	/* Check for IPv6 LL and MC routes that might need to be ignored */
	if (   (info->family == AF_INET6 || info->family == AF_UNSPEC)
	    && (rtnl_route_get_family (route) == AF_INET6)) {
		struct in6_addr *addr = NULL;

		if (dst)
			addr = nl_addr_get_binary_addr (dst);
		if (addr) {
			if (   IN6_IS_ADDR_LINKLOCAL (addr)
			    || IN6_IS_ADDR_MC_LINKLOCAL (addr)
			    || (IN6_IS_ADDR_MULTICAST (addr) && (nl_addr_get_prefixlen (dst) == 8)))
				return;
		}
	}

	info->out_route = info->callback (route, dst, info->iface, info->user_data);
	if (info->out_route) {
		/* Ref the route so it sticks around after the cache is cleared */
		rtnl_route_get (info->out_route);
	}
}
static int
get_hwaddr (int ifindex, guint8 *buf)
{
	struct rtnl_link *lk;
	struct nl_addr *addr;
	int len;

	lk = nm_netlink_index_to_rtnl_link (ifindex);
	if (!lk)
		return -1;

	addr = rtnl_link_get_addr (lk);
	len = nl_addr_get_len (addr);
	if (len > NM_UTILS_HWADDR_LEN_MAX)
		len = -1;
	else
		memcpy (buf, nl_addr_get_binary_addr (addr), len);

	rtnl_link_put (lk);
	return len;
}
示例#17
0
文件: lookup.c 项目: Alenevod/libnl
/**
 * Builds a netlink request message to do a lookup
 * @arg req		Requested match.
 * @arg flags		additional netlink message flags
 * @arg result		Result pointer
 *
 * Builds a new netlink message requesting a change of link attributes.
 * The netlink message header isn't fully equipped with all relevant
 * fields and must be sent out via nl_send_auto_complete() or
 * supplemented as needed.
 * \a old must point to a link currently configured in the kernel
 * and \a tmpl must contain the attributes to be changed set via
 * \c rtnl_link_set_* functions.
 *
 * @return 0 on success or a negative error code.
 */
int flnl_lookup_build_request(struct flnl_request *req, int flags,
			      struct nl_msg **result)
{
	struct nl_msg *msg;
	struct nl_addr *addr;
	uint64_t fwmark;
	int tos, scope, table;
	struct fib_result_nl fr = {0};

	fwmark = flnl_request_get_fwmark(req);
	tos = flnl_request_get_tos(req);
	scope = flnl_request_get_scope(req);
	table = flnl_request_get_table(req);

	fr.fl_fwmark = fwmark != UINT_LEAST64_MAX ? fwmark : 0;
	fr.fl_tos = tos >= 0 ? tos : 0;
	fr.fl_scope = scope >= 0 ? scope : RT_SCOPE_UNIVERSE;
	fr.tb_id_in = table >= 0 ? table : RT_TABLE_UNSPEC;

	addr = flnl_request_get_addr(req);
	if (!addr)
		return -NLE_MISSING_ATTR;

	fr.fl_addr = *(uint32_t *) nl_addr_get_binary_addr(addr);

	msg = nlmsg_alloc_simple(0, flags);
	if (!msg)
		return -NLE_NOMEM;

	if (nlmsg_append(msg, &fr, sizeof(fr), NLMSG_ALIGNTO) < 0)
		goto errout;

	*result = msg;
	return 0;

errout:
	nlmsg_free(msg);
	return -NLE_MSGSIZE;
}
示例#18
0
文件: lookup.c 项目: 62gs8ha/batphone
/**
 * Builds a netlink request message to do a lookup
 * @arg req		Requested match.
 * @arg flags		additional netlink message flags
 *
 * Builds a new netlink message requesting a change of link attributes.
 * The netlink message header isn't fully equipped with all relevant
 * fields and must be sent out via nl_send_auto_complete() or
 * supplemented as needed.
 * \a old must point to a link currently configured in the kernel
 * and \a tmpl must contain the attributes to be changed set via
 * \c rtnl_link_set_* functions.
 *
 * @return New netlink message
 * @note Not all attributes can be changed, see
 *       \ref link_changeable "Changeable Attributes" for more details.
 */
struct nl_msg *flnl_lookup_build_request(struct flnl_request *req, int flags)
{
	struct nl_msg *msg;
	struct nl_addr *addr;
	uint64_t fwmark;
	int tos, scope, table;
	struct fib_result_nl fr = {0};

	fwmark = flnl_request_get_fwmark(req);
	tos = flnl_request_get_tos(req);
	scope = flnl_request_get_scope(req);
	table = flnl_request_get_table(req);

	fr.fl_fwmark = fwmark != UINT_LEAST64_MAX ? fwmark : 0;
	fr.fl_tos = tos >= 0 ? tos : 0;
	fr.fl_scope = scope >= 0 ? scope : RT_SCOPE_UNIVERSE;
	fr.tb_id_in = table >= 0 ? table : RT_TABLE_UNSPEC;

	addr = flnl_request_get_addr(req);
	if (!addr) {
		nl_error(EINVAL, "Request must specify the address");
		return NULL;
	}

	fr.fl_addr = *(uint32_t *) nl_addr_get_binary_addr(addr);

	msg = nlmsg_alloc_simple(0, flags);
	if (!msg)
		goto errout;

	if (nlmsg_append(msg, &fr, sizeof(fr), NLMSG_ALIGNTO) < 0)
		goto errout;

	return msg;

errout:
	nlmsg_free(msg);
	return NULL;
}
示例#19
0
文件: ae.c 项目: Domikk/libnl
int xfrmnl_ae_build_get_request(struct nl_addr* daddr, unsigned int spi, unsigned int protocol,
                                unsigned int mark_mask, unsigned int mark_value, struct nl_msg **result)
{
	struct nl_msg *msg;
	struct xfrm_aevent_id   ae_id;
	struct xfrmnl_mark   mark;

	if (!daddr || !spi)
	{
		fprintf(stderr, "APPLICATION BUG: %s:%d:%s: A valid destination address, spi must be specified\n",
				__FILE__, __LINE__, __PRETTY_FUNCTION__);
		assert(0);
		return -NLE_MISSING_ATTR;
	}

	memset(&ae_id, 0, sizeof(ae_id));
	memcpy (&ae_id.sa_id.daddr, nl_addr_get_binary_addr (daddr), sizeof (uint8_t) * nl_addr_get_len (daddr));
	ae_id.sa_id.spi    = htonl(spi);
	ae_id.sa_id.family = nl_addr_get_family (daddr);
	ae_id.sa_id.proto  = protocol;

	if (!(msg = nlmsg_alloc_simple(XFRM_MSG_GETAE, 0)))
		return -NLE_NOMEM;

	if (nlmsg_append(msg, &ae_id, sizeof(ae_id), NLMSG_ALIGNTO) < 0)
		goto nla_put_failure;

	mark.m  =   mark_mask;
	mark.v  =   mark_value;
	NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrmnl_mark), &mark);

	*result = msg;
	return 0;

nla_put_failure:
	nlmsg_free(msg);
	return -NLE_MSGSIZE;
}
static void
update_hw_address (NMDevice *dev)
{
	NMDeviceWired *self = NM_DEVICE_WIRED (dev);
	NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
	struct rtnl_link *rtnl;
	struct nl_addr *addr;

	rtnl = nm_netlink_index_to_rtnl_link (nm_device_get_ip_ifindex (dev));
	if (!rtnl) {
		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
		            "(%s) failed to read hardware address (error %d)",
		            nm_device_get_iface (dev), errno);
		return;
	}

	addr = rtnl_link_get_addr (rtnl);
	if (!addr) {
		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
		            "(%s) no hardware address?",
		            nm_device_get_iface (dev));
		rtnl_link_put (rtnl);
		return;
	}

	if (nl_addr_get_len (addr) != priv->hw_addr_len) {
		nm_log_err (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (dev),
		            "(%s) hardware address is wrong length (expected %d got %d)",
		            nm_device_get_iface (dev),
		            priv->hw_addr_len, nl_addr_get_len (addr));
	} else {
		memcpy (&priv->hw_addr, nl_addr_get_binary_addr (addr),
				priv->hw_addr_len);
	}

	rtnl_link_put (rtnl);
}
示例#21
0
void nl_bridge::remove_neigh_from_fdb(rtnl_neigh *neigh) {
  assert(sw);
  nl_addr *addr = rtnl_neigh_get_lladdr(neigh);

  if (nl_addr_cmp(rtnl_link_get_addr(bridge), addr) == 0) {
    // ignore ll addr of bridge on slave
    return;
  }

  // lookup l2_cache as well
  std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n_lookup(
      NEIGH_CAST(nl_cache_search(l2_cache.get(), OBJ_CAST(neigh))),
      rtnl_neigh_put);

  if (n_lookup) {
    nl_cache_remove(OBJ_CAST(n_lookup.get()));
  }

  const uint32_t port = nl->get_port_id(rtnl_neigh_get_ifindex(neigh));
  rofl::caddress_ll mac((uint8_t *)nl_addr_get_binary_addr(addr),
                        nl_addr_get_len(addr));

  sw->l2_addr_remove(port, rtnl_neigh_get_vlan(neigh), mac);
}
示例#22
0
文件: addr.c 项目: artisdom/mipv6
static struct nl_msg *build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags)
{
	struct nl_msg *msg;
	struct ifaddrmsg am = {
		.ifa_family = tmpl->a_family,
		.ifa_index = tmpl->a_ifindex,
		.ifa_prefixlen = tmpl->a_prefixlen,
	};

	if (tmpl->a_mask & ADDR_ATTR_FLAGS)
		am.ifa_flags = tmpl->a_flags;

	if (tmpl->a_mask & ADDR_ATTR_SCOPE)
		am.ifa_scope = tmpl->a_scope;
	else {
		/* compatibility hack */
		if (tmpl->a_family == AF_INET &&
		    tmpl->a_mask & ADDR_ATTR_LOCAL &&
		    *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127)
			am.ifa_scope = RT_SCOPE_HOST;
		else
			am.ifa_scope = RT_SCOPE_UNIVERSE;
	}

	msg = nlmsg_build_simple(cmd, flags);
	if (!msg)
		goto nla_put_failure;

	if (nlmsg_append(msg, &am, sizeof(am), 1) < 0)
		goto nla_put_failure;

	if (tmpl->a_mask & ADDR_ATTR_LOCAL)
		NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local);

	if (tmpl->a_mask & ADDR_ATTR_PEER)
		NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer);
	else
		NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local);

	if (tmpl->a_mask & ADDR_ATTR_LABEL)
		NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label);

	if (tmpl->a_mask & ADDR_ATTR_BROADCAST)
		NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast);

	if (tmpl->a_mask & ADDR_ATTR_ANYCAST)
		NLA_PUT_ADDR(msg, IFA_ANYCAST, tmpl->a_anycast);

	return msg;

nla_put_failure:
	nlmsg_free(msg);
	return NULL;
}

/**
 * @name Address Addition
 * @{
 */

/**
 * Build netlink request message to request addition of new address
 * @arg addr		Address object representing the new address.
 * @arg flags		Additional netlink message flags.
 *
 * Builds a new netlink message requesting the addition of a new
 * address. The netlink message header isn't fully equipped with
 * all relevant fields and must thus be sent out via nl_send_auto_complete()
 * or supplemented as needed.
 *
 * Minimal required attributes:
 *   - interface index (rtnl_addr_set_ifindex())
 *   - local address (rtnl_addr_set_local())
 *
 * The scope will default to universe except for loopback addresses in
 * which case a host scope is used if not specified otherwise.
 *
 * @note Free the memory after usage using nlmsg_free().
 * @return Newly allocated netlink message or NULL if an error occured.
 */
struct nl_msg *rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags)
{
	int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY |
		       ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL;

	if ((addr->a_mask & required) != required) {
		nl_error(EINVAL, "Missing mandatory attributes, required are: "
				 "ifindex, family, prefixlen, local address.");
		return NULL;
	}
	
	return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags);
}
示例#23
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");

}
示例#24
0
文件: ae.c 项目: Domikk/libnl
static int build_xfrm_ae_message(struct xfrmnl_ae *tmpl, int cmd, int flags,
			   struct nl_msg **result)
{
	struct nl_msg*          msg;
	struct xfrm_aevent_id   ae_id;

	if (!(tmpl->ce_mask & XFRM_AE_ATTR_DADDR) ||
		!(tmpl->ce_mask & XFRM_AE_ATTR_SPI) ||
		!(tmpl->ce_mask & XFRM_AE_ATTR_PROTO))
		return -NLE_MISSING_ATTR;

	memcpy (&ae_id.sa_id.daddr, nl_addr_get_binary_addr (tmpl->sa_id.daddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->sa_id.daddr));
	ae_id.sa_id.spi    = htonl(tmpl->sa_id.spi);
	ae_id.sa_id.family = tmpl->sa_id.family;
	ae_id.sa_id.proto  = tmpl->sa_id.proto;

	if (tmpl->ce_mask & XFRM_AE_ATTR_SADDR)
		memcpy (&ae_id.saddr, nl_addr_get_binary_addr (tmpl->saddr), sizeof (uint8_t) * nl_addr_get_len (tmpl->saddr));

	if (tmpl->ce_mask & XFRM_AE_ATTR_FLAGS)
		ae_id.flags    = tmpl->flags;

	if (tmpl->ce_mask & XFRM_AE_ATTR_REQID)
		ae_id.reqid    = tmpl->reqid;

	msg = nlmsg_alloc_simple(cmd, flags);
	if (!msg)
		return -NLE_NOMEM;

	if (nlmsg_append(msg, &ae_id, sizeof(ae_id), NLMSG_ALIGNTO) < 0)
		goto nla_put_failure;

	if (tmpl->ce_mask & XFRM_AE_ATTR_MARK)
		NLA_PUT (msg, XFRMA_MARK, sizeof (struct xfrmnl_mark), &tmpl->mark);

	if (tmpl->ce_mask & XFRM_AE_ATTR_LIFETIME)
		NLA_PUT (msg, XFRMA_LTIME_VAL, sizeof (struct xfrmnl_lifetime_cur), &tmpl->lifetime_cur);

	if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_MAXAGE)
		NLA_PUT_U32 (msg, XFRMA_ETIMER_THRESH, tmpl->replay_maxage);

	if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_MAXDIFF)
		NLA_PUT_U32 (msg, XFRMA_REPLAY_THRESH, tmpl->replay_maxdiff);

	if (tmpl->ce_mask & XFRM_AE_ATTR_REPLAY_STATE) {
		if (tmpl->replay_state_esn) {
			uint32_t len = sizeof (struct xfrm_replay_state_esn) + (sizeof (uint32_t) * tmpl->replay_state_esn->bmp_len);
			NLA_PUT (msg, XFRMA_REPLAY_ESN_VAL, len, tmpl->replay_state_esn);
		}
		else {
			NLA_PUT (msg, XFRMA_REPLAY_VAL, sizeof (struct xfrmnl_replay_state), &tmpl->replay_state);
		}
	}

	*result = msg;
	return 0;

nla_put_failure:
	nlmsg_free(msg);
	return -NLE_MSGSIZE;
}
示例#25
0
CAMLprim value
ocaml_get_routing_table(value unit) {
    CAMLparam1(unit);
    CAMLlocal3( ret, tmp, entry );

    struct nl_sock *fd;
    struct nl_cache *res, *links;
    struct rtnl_route *it;
    uint32 i_ip, netmask = 0, mask_len, gw;
    int i;
    struct nl_addr *ip;
    char device_name[IFNAMSIZ];
    struct rtnl_nexthop *to;
    fd = nl_socket_alloc();
    if (!fd) {
        fprintf(stderr, "error nl_socket_alloc\n");
        exit(1);
    }

    if(nl_connect(fd, NETLINK_ROUTE) < 0) {
        fprintf(stderr, "error nl_connect\n");
        exit(1);
    }

    ret = Val_emptylist;

    if(rtnl_route_alloc_cache(fd, AF_UNSPEC, 0, &res) < 0) {
        fprintf(stderr, "error rtnl_route_alloc_cache");
        exit(1);
    }

    if(rtnl_link_alloc_cache (fd, AF_UNSPEC, &links) < 0) {
        fprintf(stderr, "error rtnl_link_alloc_cache");
        exit(1);
    }

    it = (struct rtnl_route *)nl_cache_get_first(res);
    for(; it != NULL; it = (struct rtnl_route *)
                           nl_cache_get_next((struct nl_object *)it) ) {
        if(rtnl_route_get_family (it) == AF_INET) {
            ip = rtnl_route_get_dst(it);
            i_ip = ntohl(*(int *)nl_addr_get_binary_addr(ip));
            mask_len = nl_addr_get_prefixlen(ip);
            for(i = 0; i < 32; i++)
                netmask = (netmask << 1) + (i< mask_len?1:0);
            to = rtnl_route_nexthop_n(it, 0);
            rtnl_link_i2name(links, rtnl_route_nh_get_ifindex(to),
                             device_name, IFNAMSIZ);
            if ( rtnl_route_nh_get_gateway (to) != NULL)
                gw = ntohl(*(int *)nl_addr_get_binary_addr(
                               rtnl_route_nh_get_gateway (to)));
            else
                gw = 0;
            /*printf("src ip:%x mask:%x gw:%x dev:%s\n", i_ip, netmask, */
            /*gw, device_name);*/

            entry = caml_alloc(7,0);
            Store_field(entry, 0, Val_int(i_ip & 0xFFFF));
            Store_field(entry, 1, Val_int(i_ip >> 16));
            Store_field(entry, 2, Val_int(netmask & 0xFFFF));
            Store_field(entry, 3, Val_int(netmask >> 16));
            Store_field(entry, 4, Val_int(gw & 0xFFFF));
            Store_field(entry, 5, Val_int(gw >> 16));
            Store_field(entry, 6, caml_copy_string(device_name));

            // store in list
            tmp =  caml_alloc(2, 0);
            Store_field( tmp, 0, entry);  // head
            Store_field( tmp, 1, ret);  // tail
            ret = tmp;
        }
    }
示例#26
0
int main(int argc, char *argv[])
{
    char *unikernel;
    enum {
        QEMU,
        KVM,
        UKVM,
        UNIX
    } hypervisor;

    if (argc < 3) {
        fprintf(stderr, "usage: runner HYPERVISOR UNIKERNEL [ ARGS... ]\n");
        fprintf(stderr, "HYPERVISOR: qemu | kvm | ukvm | unix\n");
        return 1;
    }
    if (strcmp(argv[1], "qemu") == 0)
        hypervisor = QEMU;
    else if (strcmp(argv[1], "kvm") == 0)
        hypervisor = KVM;
    else if (strcmp(argv[1], "ukvm") == 0)
        hypervisor = UKVM;
    else if (strcmp(argv[1], "unix") == 0)
        hypervisor = UNIX;
    else {
        warnx("error: Invalid hypervisor: %s", argv[1]);
        return 1;
    }
    unikernel = argv[2];
    /*
     * Remaining arguments are to be passed on to the unikernel.
     */
    argv += 3;
    argc -= 3;

    /*
     * Check we have CAP_NET_ADMIN.
     */
    if (capng_get_caps_process() != 0) {
        warnx("error: capng_get_caps_process() failed");
        return 1;
    }
    if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_ADMIN)) {
        warnx("error: CAP_NET_ADMIN is required");
        return 1;
    }

    /*
     * Connect to netlink, load link cache from kernel.
     */
    struct nl_sock *sk;
    struct nl_cache *link_cache;
    int err;
 
    sk = nl_socket_alloc();
    assert(sk);
    err = nl_connect(sk, NETLINK_ROUTE);
    if (err < 0) {
        warnx("nl_connect() failed: %s", nl_geterror(err));
        return 1;
    }
    err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache);
    if (err < 0) {
        warnx("rtnl_link_alloc_cache() failed: %s", nl_geterror(err));
        return 1;
    }
   
    /*
     * Retrieve container network configuration -- IP address and
     * default gateway.
     */
    struct rtnl_link *l_veth;
    l_veth = rtnl_link_get_by_name(link_cache, VETH_LINK_NAME);
    if (l_veth == NULL) {
        warnx("error: Could not get link information for %s", VETH_LINK_NAME);
        return 1;
    }
    struct nl_addr *veth_addr;
    err = get_link_inet_addr(sk, l_veth, &veth_addr);
    if (err) {
        warnx("error: Unable to determine IP address of %s",
                VETH_LINK_NAME);
        return 1;
    }
    struct nl_addr *gw_addr;
    err = get_default_gw_inet_addr(sk, &gw_addr);
    if (err) {
        warnx("error: get_deGfault_gw_inet_addr() failed");
        return 1;
    }
    if (gw_addr == NULL) {
        warnx("error: No default gateway found. This is currently "
                "not supported");
        return 1;
    }

    /*
     * Create bridge and tap interface, enslave veth and tap interfaces to
     * bridge.
     */
    err = create_bridge_link(sk, BRIDGE_LINK_NAME);
    if (err < 0) {
        warnx("create_bridge_link(%s) failed: %s", BRIDGE_LINK_NAME,
                nl_geterror(err));
        return 1;
    }
    int tap_fd;

    if (hypervisor == UKVM)
        err = create_tap_link(TAP_LINK_NAME, &tap_fd);
    else
        err = create_tap_link(TAP_LINK_NAME, NULL);
    if (err != 0) {
        warnx("create_tap_link(%s) failed: %s", TAP_LINK_NAME, strerror(err));
        return 1;
    }

    /* Refill link cache with newly-created interfaces */
    nl_cache_refill(sk, link_cache);

    struct rtnl_link *l_bridge;
    l_bridge = rtnl_link_get_by_name(link_cache, BRIDGE_LINK_NAME);
    if (l_bridge == NULL) {
        warnx("error: Could not get link information for %s", BRIDGE_LINK_NAME);
        return 1;
    }
    struct rtnl_link *l_tap;
    l_tap = rtnl_link_get_by_name(link_cache, TAP_LINK_NAME);
    if (l_tap == NULL) {
        warnx("error: Could not get link information for %s", TAP_LINK_NAME);
        return 1;
    }
    err = rtnl_link_enslave(sk, l_bridge, l_veth);
    if (err < 0) {
        warnx("error: Unable to enslave %s to %s: %s", VETH_LINK_NAME,
                BRIDGE_LINK_NAME, nl_geterror(err));
        return 1;
    }
    err = rtnl_link_enslave(sk, l_bridge, l_tap);
    if (err < 0) {
        warnx("error: Unable to enslave %s to %s: %s", TAP_LINK_NAME,
                BRIDGE_LINK_NAME, nl_geterror(err));
        return 1;
    }

    /*
     * Flush all IPv4 addresses from the veth interface. This is now safe
     * as we are good to commit and have retrieved the existing configuration.
     */
    struct rtnl_addr *flush_addr;
    flush_addr = rtnl_addr_alloc();
    assert(flush_addr);
    rtnl_addr_set_ifindex(flush_addr, rtnl_link_get_ifindex(l_veth));
    rtnl_addr_set_family(flush_addr, AF_INET);
    rtnl_addr_set_local(flush_addr, veth_addr);
    err = rtnl_addr_delete(sk, flush_addr, 0);
    if (err < 0) {
        warnx("error: Could not flush addresses on %s: %s", VETH_LINK_NAME,
                nl_geterror(err));
        return 1;
    }
    rtnl_addr_put(flush_addr);

    /* 
     * Bring up the tap and bridge interfaces.
     */
    struct rtnl_link *l_up;
    l_up = rtnl_link_alloc();
    assert(l_up);
    /* You'd think set_operstate was the thing to do here. It's not. */
    rtnl_link_set_flags(l_up, IFF_UP);
    err = rtnl_link_change(sk, l_tap, l_up, 0);
    if (err < 0) {
        warnx("error: rtnl_link_change(%s, UP) failed: %s", TAP_LINK_NAME,
                nl_geterror(err));
        return 1;
    }
    err = rtnl_link_change(sk, l_bridge, l_up, 0);
    if (err < 0) {
        warnx("error: rtnl_link_change(%s, UP) failed: %s", BRIDGE_LINK_NAME,
                nl_geterror(err));
        return 1;
    }
    rtnl_link_put(l_up);

    /*
     * Collect network configuration data.
     */
    char ip[AF_INET_BUFSIZE];
    if (inet_ntop(AF_INET, nl_addr_get_binary_addr(veth_addr), ip,
            sizeof ip) == NULL) {
        perror("inet_ntop()");
        return 1;
    }
    char uarg_ip[AF_INET_BUFSIZE];
    unsigned int prefixlen = nl_addr_get_prefixlen(veth_addr);
    snprintf(uarg_ip, sizeof uarg_ip, "%s/%u", ip, prefixlen);

    char uarg_gw[AF_INET_BUFSIZE];
    if (inet_ntop(AF_INET, nl_addr_get_binary_addr(gw_addr), uarg_gw,
            sizeof uarg_gw) == NULL) {
        perror("inet_ntop()");
        return 1;
    }

    /*
     * Build unikernel and hypervisor arguments.
     */
    ptrvec* uargpv = pvnew();
    char *uarg_buf;
    /*
     * QEMU/KVM:
     * /usr/bin/qemu-system-x86_64 <qemu args> -kernel <unikernel> -append "<unikernel args>"
     */
    if (hypervisor == QEMU || hypervisor == KVM) {
        pvadd(uargpv, "/usr/bin/qemu-system-x86_64");
        pvadd(uargpv, "-nodefaults");
        pvadd(uargpv, "-no-acpi");
        pvadd(uargpv, "-display");
        pvadd(uargpv, "none");
        pvadd(uargpv, "-serial");
        pvadd(uargpv, "stdio");
        pvadd(uargpv, "-m");
        pvadd(uargpv, "512");
        if (hypervisor == KVM) {
            pvadd(uargpv, "-enable-kvm");
            pvadd(uargpv, "-cpu");
            pvadd(uargpv, "host");
        }
        else {
            /*
             * Required for AESNI use in Mirage.
             */
            pvadd(uargpv, "-cpu");
            pvadd(uargpv, "Westmere");
        }
        pvadd(uargpv, "-device");
        char *guest_mac = generate_mac();
        assert(guest_mac);
        err = asprintf(&uarg_buf, "virtio-net-pci,netdev=n0,mac=%s", guest_mac);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        pvadd(uargpv, "-netdev");
        err = asprintf(&uarg_buf, "tap,id=n0,ifname=%s,script=no,downscript=no",
            TAP_LINK_NAME);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        pvadd(uargpv, "-kernel");
        pvadd(uargpv, unikernel);
        pvadd(uargpv, "-append");
        /*
         * TODO: Replace any occurences of ',' with ',,' in -append, because
         * QEMU arguments are insane.
         */
        char cmdline[1024];
        char *cmdline_p = cmdline;
        size_t cmdline_free = sizeof cmdline;
        for (; *argv; argc--, argv++) {
            size_t alen = snprintf(cmdline_p, cmdline_free, "%s%s", *argv,
                    (argc > 1) ? " " : "");
            if (alen >= cmdline_free) {
                warnx("error: Command line too long");
                return 1;
            }
            cmdline_free -= alen;
            cmdline_p += alen;
        }
        size_t alen = snprintf(cmdline_p, cmdline_free,
                "--ipv4=%s --ipv4-gateway=%s", uarg_ip, uarg_gw);
        if (alen >= cmdline_free) {
            warnx("error: Command line too long");
            return 1;
        }
        pvadd(uargpv, cmdline);
    }
    /*
     * UKVM:
     * /unikernel/ukvm <ukvm args> <unikernel> -- <unikernel args>
     */
    else if (hypervisor == UKVM) {
        pvadd(uargpv, "/unikernel/ukvm");
        err = asprintf(&uarg_buf, "--net=@%d", tap_fd);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        pvadd(uargpv, "--");
        pvadd(uargpv, unikernel);
        for (; *argv; argc--, argv++) {
            pvadd(uargpv, *argv);
        }
        err = asprintf(&uarg_buf, "--ipv4=%s", uarg_ip);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        err = asprintf(&uarg_buf, "--ipv4-gateway=%s", uarg_gw);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
    }
    /*
     * UNIX:
     * <unikernel> <unikernel args>
     */
    else if (hypervisor == UNIX) {
        pvadd(uargpv, unikernel);
        err = asprintf(&uarg_buf, "--interface=%s", TAP_LINK_NAME);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        for (; *argv; argc--, argv++) {
            pvadd(uargpv, *argv);
        }
        err = asprintf(&uarg_buf, "--ipv4=%s", uarg_ip);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        err = asprintf(&uarg_buf, "--ipv4-gateway=%s", uarg_gw);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
    }
    char **uargv = (char **)pvfinal(uargpv);

    /*
     * Done with netlink, free all resources and close socket.
     */
    rtnl_link_put(l_veth);
    rtnl_link_put(l_bridge);
    rtnl_link_put(l_tap);
    nl_addr_put(veth_addr);
    nl_addr_put(gw_addr);

    nl_cache_free(link_cache);
    nl_close(sk);
    nl_socket_free(sk);

    /*
     * Drop all capabilities except CAP_NET_BIND_SERVICE.
     */
    capng_clear(CAPNG_SELECT_BOTH);
    capng_update(CAPNG_ADD,
            CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_INHERITABLE,
            CAP_NET_BIND_SERVICE);
    if (capng_apply(CAPNG_SELECT_BOTH) != 0) {
        warnx("error: Could not drop capabilities");
        return 1;
    }

    /*
     * Run the unikernel.
     */
    err = execv(uargv[0], uargv);
    warn("error: execv() of %s failed", uargv[0]);
    return 1;
}
示例#27
0
文件: libnl3.c 项目: exuuwen/study
int main(int argc, char *argv[])
{
	struct nl_sock *nl_sock;
	struct nl_cache *link_cache;
	int ifindex;
	int ret = 0;
	int err = 0;

	if (argc < 2)
	{
		printf("%s ip gw on/off tip\n", argv[0]);
		return -1;
	}

//link
	if (err = rtnl_route_read_table_names(ROUTE_TABLE)) {
		printf("failed to read %s. err = %s\n", ROUTE_TABLE, nl_geterror(err));
		return -1;;
	}

	nl_sock = nl_socket_alloc();
	if (NULL == nl_sock) {
		printf("failed to alloc netlink handler.\n");
		return -1;
	}

	if (err = nl_connect(nl_sock, NETLINK_ROUTE)) {
		printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}

	if (err = rtnl_link_alloc_cache(nl_sock, AF_INET, &link_cache))
	{
		printf("failed to allocate link cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}

	ifindex = rtnl_link_name2i(link_cache, NAME);
	if (0 == ifindex) {
		printf("%s - failed to find.\n", NAME);
		ret = -1;
		goto release_link_cache;
	}

	struct rtnl_link * link = rtnl_link_get(link_cache, ifindex);
	if (link == NULL)
	{
		printf("can't get link.\n");
		ret = -1;
		goto release_link_cache;
	}
	//rtnl_link_get_by_name

	struct nl_addr *lladdr = rtnl_link_get_addr(link);
	if (NULL == lladdr || AF_LLC != nl_addr_get_family(lladdr)) {
		printf("failed to get MAC\n");
		ret = -1;
		goto release_link;
	}

	uint8_t mac_address[ETHER_ADDR_LEN];
	memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN);
	printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
		 mac_address[0],
		 mac_address[1],
		 mac_address[2],
		 mac_address[3],
		 mac_address[4],
		 mac_address[5]);

//addr 
	struct nl_cache * addr_cache;
	if (err  = rtnl_addr_alloc_cache(nl_sock, &addr_cache))
	{
		printf("fail to get addr_cache\n");
		ret = -1;
		goto release_link;
	}
	struct rtnl_addr *addr = rtnl_addr_alloc();
	rtnl_addr_set_ifindex(addr, ifindex);
	rtnl_addr_set_family(addr, AF_INET);
	int prefixlen = 16;
	nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, get_ip, &prefixlen);
	nl_cache_free(addr_cache);

	uint32_t ipaddr = inet_addr(argv[1]);
	struct nl_addr * local = nl_addr_build(AF_INET, &ipaddr, sizeof(ipaddr));
	rtnl_addr_set_local(addr, local);
	rtnl_addr_set_ifindex(addr, ifindex);
	rtnl_addr_set_family(addr, AF_INET);
	rtnl_addr_set_prefixlen(addr, 32);

	if (!strcmp(argv[2], "on"))
	{
		if (err = rtnl_addr_add(nl_sock, addr, 0))
		{
			printf("fail to add addr %s\n", nl_geterror(err));
			ret = -1;
			goto release_addr;
		}
	}
	else
	{
		if (err = rtnl_addr_delete(nl_sock, addr, 0))
		{
			printf("fail to del addr %s\n", nl_geterror(err));
			ret = -1;
			goto release_addr;
		}
		
	}
//neigh
	struct nl_cache * neigh_cache;
	if (err = rtnl_neigh_alloc_cache(nl_sock, &neigh_cache))
	{
		printf("failed to allocate neighbor cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_neigh_cache;
	}

	uint32_t gw = inet_addr(argv[3]);
	struct nl_addr * gw_addr = nl_addr_build(AF_INET, &gw, sizeof(gw));

	struct rtnl_neigh * neigh = rtnl_neigh_get(neigh_cache, ifindex, gw_addr);
	if (neigh) {
		// It's optional
		struct nl_addr * lladdr = rtnl_neigh_get_lladdr(neigh);
		if (lladdr) {
			uint8_t mac_address[ETHER_ADDR_LEN];
			memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN);
			printf("gw  %02X:%02X:%02X:%02X:%02X:%02X\n",
		 		mac_address[0],
		 		mac_address[1],
		 		mac_address[2],
		 		mac_address[3],
		 		mac_address[4],
		 		mac_address[5]);
		}
	}

	nl_addr_put(gw_addr);

//route
	struct nl_cache *route_cache;
	if (err = rtnl_route_alloc_cache(nl_sock, AF_INET, 0, &route_cache))
	{
		printf("failed to allocate route cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_neigh_cache;
	}

	struct rtnl_route *route = rtnl_route_alloc();
	struct nl_addr * taddr;
	err = nl_addr_parse(argv[4], AF_INET, &taddr);
        if (err)
        {
                printf("failed to get taddr. err = %s\n", nl_geterror(err));
                ret = -1;
                goto release_route_cache;
                
        }

	nl_cache_foreach_filter(route_cache, OBJ_CAST(route), get_route, NULL);
/*
	struct nl_sock *nl_fib_sock;
	nl_fib_sock = nl_socket_alloc();
	if (err = nl_connect(nl_fib_sock, NETLINK_FIB_LOOKUP)) {
		printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}
	struct nl_dump_params params = {
		.dp_fd = stdout,
		.dp_type = NL_DUMP_DETAILS,
	};

	struct nl_cache *route_cache = flnl_result_alloc_cache();

        struct flnl_request *req = flnl_request_alloc();
        struct nl_addr * taddr;
	err = nl_addr_parse(argv[4], AF_INET, &taddr);
	if (err)
	{
		printf("failed to get taddr. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_route;
		
	}
	int table = RT_TABLE_UNSPEC, scope = RT_SCOPE_UNIVERSE;
        flnl_request_set_addr(req, taddr);
	flnl_request_set_table(req, table);
	flnl_request_set_scope(req, scope);
        err = flnl_lookup(nl_fib_sock, req, route_cache);
	if (err)
	{
		printf("failed to fib lookup. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_route_addr;
	}
	
	nl_cache_dump(route_cache, &params);

release_route_addr:
	nl_addr_put(taddr);	

release_route:
        nl_cache_free(route_cache);
	nl_object_put(OBJ_CAST(req));

	nl_close(nl_fib_sock);
	nl_socket_free(nl_fib_sock);
*/
release_route_cache:
	nl_cache_free(route_cache);
release_neigh_cache:
	nl_cache_free(neigh_cache);
release_addr:
	nl_addr_put(local);
	rtnl_addr_put(addr);
release_link:
	rtnl_link_put(link);
release_link_cache:
	nl_cache_free(link_cache);
release_nl:
	nl_close(nl_sock);
	nl_socket_free(nl_sock);

	return ret;
}
示例#28
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;
}
示例#29
0
static void
nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed)
{
	NMIP6Manager *manager = device->manager;
	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
	struct rtnl_addr *rtnladdr;
	struct nl_addr *nladdr;
	struct in6_addr *addr;
	CallbackInfo *info;
	guint dhcp_opts = IP6_DHCP_OPT_NONE;
	gboolean found_linklocal = FALSE, found_other = FALSE;

	nm_log_dbg (LOGD_IP6, "(%s): syncing with netlink (ra_flags 0x%X) (state/target '%s'/'%s')",
	            device->iface, device->ra_flags,
	            state_to_string (device->state),
	            state_to_string (device->target_state));

	/* 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",
			            device->iface, buf);
		}

		if (IN6_IS_ADDR_LINKLOCAL (addr)) {
			if (device->state == NM_IP6_DEVICE_UNCONFIGURED)
				device->state = NM_IP6_DEVICE_GOT_LINK_LOCAL;
			found_linklocal = TRUE;
		} else {
			if (device->state < NM_IP6_DEVICE_GOT_ADDRESS)
				device->state = NM_IP6_DEVICE_GOT_ADDRESS;
			found_other = 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) && !found_linklocal)
		device->state = NM_IP6_DEVICE_UNCONFIGURED;

	nm_log_dbg (LOGD_IP6, "(%s): addresses synced (state %s)",
	            device->iface, state_to_string (device->state));

	/* We only care about router advertisements if we want a real IPv6 address */
	if (   (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS)
	    && (device->ra_flags & IF_RA_RCVD)) {

		if (device->state < NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT)
			device->state = NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT;

		if (device->ra_flags & IF_RA_MANAGED) {
			dhcp_opts = IP6_DHCP_OPT_MANAGED;
			nm_log_dbg (LOGD_IP6, "router advertisement deferred to DHCPv6");
		} else if (device->ra_flags & IF_RA_OTHERCONF) {
			dhcp_opts = IP6_DHCP_OPT_OTHERCONF;
			nm_log_dbg (LOGD_IP6, "router advertisement requests parallel DHCPv6");
		}
	}

	if (!device->addrconf_complete) {
		/* Managed mode (ie DHCP only) short-circuits automatic addrconf, so
		 * we don't bother waiting for the device's target state to be reached
		 * when the RA requests managed mode.
		 */
		if (   (device->state >= device->target_state)
		    || (dhcp_opts == IP6_DHCP_OPT_MANAGED)) {
			/* device->finish_addrconf_id may currently be a timeout
			 * rather than an idle, so we remove the existing source.
			 */
			if (device->finish_addrconf_id)
				g_source_remove (device->finish_addrconf_id);

			nm_log_dbg (LOGD_IP6, "(%s): reached target state or Managed-mode requested (state '%s') (dhcp opts 0x%X)",
			            device->iface, state_to_string (device->state),
			            dhcp_opts);

			info = callback_info_new (device, dhcp_opts, TRUE);
			device->finish_addrconf_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
			                                              finish_addrconf,
			                                              info,
			                                              (GDestroyNotify) g_free);
		}
	} else if (config_changed) {
		if (!device->config_changed_id) {
			gboolean success = TRUE;

			/* If for some reason an RA-provided address disappeared, we need
			 * to make sure we fail the connection as it's no longer valid.
			 */
			if (   (device->state == NM_IP6_DEVICE_GOT_ADDRESS)
			    && (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS)
			    && !found_other) {
				nm_log_dbg (LOGD_IP6, "(%s): RA-provided address no longer valid",
				            device->iface);
				success = FALSE;
			}

			info = callback_info_new (device, dhcp_opts, success);
			device->config_changed_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
			                                             emit_config_changed,
			                                             info,
			                                             (GDestroyNotify) g_free);
		}
	}
}
示例#30
0
TError TNlLink::AddXVlan(const std::string &vlantype,
                         const std::string &master,
                         uint32_t type,
                         const std::string &hw,
                         int mtu) {
    TError error = TError::Success();
    int ret;
    uint32_t masterIdx;
    struct nl_msg *msg;
    struct nlattr *linkinfo, *infodata;
    struct ifinfomsg ifi = { 0 };
    struct ether_addr *ea = nullptr;
    auto Name = GetName();

    if (hw.length()) {
        // FIXME THREADS
        ea = ether_aton(hw.c_str());
        if (!ea)
            return TError(EError::Unknown, "Invalid " + vlantype + " mac address " + hw);
    }

    TNlLink masterLink(Nl, master);
    error = masterLink.Load();
    if (error)
        return error;
    masterIdx = masterLink.GetIndex();

    msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_CREATE);
    if (!msg)
        return TError(EError::Unknown, "Unable to add " + vlantype + ": no memory");

    ret = nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO);
    if (ret < 0) {
        error = TError(EError::Unknown, "Unable to add " + vlantype + ": " + nl_geterror(ret));
        goto free_msg;
    }

    /* link configuration */
    ret = nla_put(msg, IFLA_LINK, sizeof(uint32_t), &masterIdx);
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to put IFLA_LINK: ") + nl_geterror(ret));
        goto free_msg;
    }
    ret = nla_put(msg, IFLA_IFNAME, Name.length() + 1, Name.c_str());
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to put IFLA_IFNAME: ") + nl_geterror(ret));
        goto free_msg;
    }

    if (mtu > 0) {
        ret = nla_put(msg, IFLA_MTU, sizeof(int), &mtu);
        if (ret < 0) {
            error = TError(EError::Unknown, std::string("Unable to put IFLA_MTU: ") + nl_geterror(ret));
            goto free_msg;
        }
    }

    if (ea) {
        struct nl_addr *addr = nl_addr_build(AF_LLC, ea, ETH_ALEN);
        ret = nla_put(msg, IFLA_ADDRESS, nl_addr_get_len(addr), nl_addr_get_binary_addr(addr));
        if (ret < 0) {
            error = TError(EError::Unknown, std::string("Unable to put IFLA_ADDRESS: ") + nl_geterror(ret));
            goto free_msg;
        }
        nl_addr_put(addr);
    }

    /* link type */
    linkinfo = nla_nest_start(msg, IFLA_LINKINFO);
    if (!linkinfo) {
        error = TError(EError::Unknown, "Unable to add " + vlantype + ": can't nest IFLA_LINKINFO");
        goto free_msg;
    }
    ret = nla_put(msg, IFLA_INFO_KIND, vlantype.length() + 1, vlantype.c_str());
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to put IFLA_INFO_KIND: ") + nl_geterror(ret));
        goto free_msg;
    }

    /* xvlan specific */
    infodata = nla_nest_start(msg, IFLA_INFO_DATA);
    if (!infodata) {
        error = TError(EError::Unknown, "Unable to add " + vlantype + ": can't nest IFLA_INFO_DATA");
        goto free_msg;
    }

    if (vlantype == "macvlan") {
        ret = nla_put(msg, IFLA_MACVLAN_MODE, sizeof(uint32_t), &type);
        if (ret < 0) {
            error = TError(EError::Unknown, std::string("Unable to put IFLA_MACVLAN_MODE: ") + nl_geterror(ret));
            goto free_msg;
        }
#ifdef IFLA_IPVLAN_MAX
    } else if (vlantype == "ipvlan") {
        uint16_t mode = type;
        ret = nla_put(msg, IFLA_IPVLAN_MODE, sizeof(uint16_t), &mode);
        if (ret < 0) {
            error = TError(EError::Unknown, std::string("Unable to put IFLA_IPVLAN_MODE: ") + nl_geterror(ret));
            goto free_msg;
        }
#endif
    }
    nla_nest_end(msg, infodata);
    nla_nest_end(msg, linkinfo);

    L() << "netlink: add " << vlantype << " " << Name << " master " << master
        << " type " << type << " hw " << hw << " mtu " << mtu << std::endl;

    ret = nl_send_sync(GetSock(), msg);
    if (ret)
        return Error(ret, "Cannot add " + vlantype);

    return Load();

free_msg:
    nlmsg_free(msg);
    return error;

}