Esempio n. 1
0
void linux_unicast_router::handle_intf_event(bool isnew, nlmsghdr *hdr) {
    ifinfomsg *ifi = (ifinfomsg *)NLMSG_DATA(hdr);

    if (isnew) {
        rtattr *tb[IFLA_MAX + 1];
        memset(tb, 0, sizeof(tb));

        netlink_msg::parse_rtatable(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(hdr));

        if (tb[IFLA_IFNAME] && tb[IFLA_MTU]) {
            interface_desc desc;

            desc.index = ifi->ifi_index;
            desc.name = (const char *)RTA_DATA(tb[IFLA_IFNAME]);
            desc.mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
            desc.flags = ifi->ifi_flags;
            desc.type = _conv_intf(ifi->ifi_type, ifi->ifi_flags);
            desc.up = ((ifi->ifi_flags & IFF_UP) == IFF_UP);

            if (rt_dumping) {
                _interfaces.push_back(desc);
            } else {
                _install_interface(desc);
            }
        }
    } else {
        g_mrd->lost_interface(ifi->ifi_index);
    }
}
Esempio n. 2
0
int TunManager::getLinkRespParser(const struct sockaddr_nl *who,
                                  struct nlmsghdr *n,
                                  void *arg) {
  // only cares about RTM_NEWLINK
  if (n->nlmsg_type != RTM_NEWLINK) {
    return 0;
  }

  struct ifinfomsg *ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(n));
  struct rtattr *tb[IFLA_MAX + 1];
  int len = n->nlmsg_len;
  len -= NLMSG_LENGTH(sizeof(*ifi));
  if (len < 0) {
    throw FbossError("Wrong length for RTM_GETLINK response ", len, " vs ",
                     NLMSG_LENGTH(sizeof(*ifi)));
  }
  parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
  if (tb[IFLA_IFNAME] == nullptr) {
    throw FbossError("Device @ index ", static_cast<int>(ifi->ifi_index),
                     " does not have a nmae");
  }
  const auto name = rta_getattr_str(tb[IFLA_IFNAME]);
  // match the interface name against intfPrefix
  if (!TunIntf::isTunIntf(name)) {
    VLOG(3) << "Ignore interface " << name
            << " because it is not a tun interface";
    return 0;
  }
  // base on the name, get the router ID
  auto rid = TunIntf::getRidFromName(name);

  TunManager *mgr = static_cast<TunManager *>(arg);
  mgr->addIntf(rid, std::string(name), ifi->ifi_index);
  return 0;
}
Esempio n. 3
0
static void getlink_callback(unsigned int error, uint16_t type, const void *data,
						uint32_t len, void *user_data)
{
	const struct ifinfomsg *ifi = data;
	struct rtattr *rta;
	int bytes;
	char ifname[IF_NAMESIZE];
	uint32_t index, flags;

	g_assert_cmpuint(error, ==, 0);

	bytes = len - NLMSG_ALIGN(sizeof(struct ifinfomsg));

	memset(ifname, 0, sizeof(ifname));

	index = ifi->ifi_index;
	flags = ifi->ifi_flags;

	for (rta = IFLA_RTA(ifi); RTA_OK(rta, bytes);
					rta = RTA_NEXT(rta, bytes)) {
		switch (rta->rta_type) {
		case IFLA_IFNAME:
			if (RTA_PAYLOAD(rta) <= IF_NAMESIZE)
				strcpy(ifname, RTA_DATA(rta));
			break;
		}
	}

	printf("index=%d flags=0x%08x name=%s\n", index, flags, ifname);

	g_main_loop_quit(mainloop);
}
Esempio n. 4
0
static void nl_parse_addr_msg(struct nlmsghdr *nlp, struct nl_cb *cb)
{
	struct ifaddrmsg *ifaddr;
	struct rtattr *rtap;
	nl_addr_cb addr_cb;
	size_t len;
	in_addr_t *addr;
	struct nl_addr nl_addr;

	addr = NULL;
	ifaddr = NLMSG_DATA(nlp);
	rtap = IFLA_RTA(ifaddr);
	len = IFLA_PAYLOAD(nlp);

	for (; RTA_OK(rtap, len); rtap = RTA_NEXT(rtap, len)) {
		switch (rtap->rta_type) {
		case IFA_LOCAL:
			addr = (in_addr_t*)RTA_DATA(rtap);
			break;
		default:
			break;
		}
	}

	if (!addr) {
		XLOG_ERR("could not get addr for link %u", ifaddr->ifa_index);
		return;
	}

	addr_cb = (nl_addr_cb) cb->parse_cb;
	nl_addr.ifindex = ifaddr->ifa_index;
	nl_addr.ifaddr = *addr;
	addr_cb(&nl_addr , cb->aux);
}
Esempio n. 5
0
static void test_container(void) {
        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
        uint16_t type;
        uint32_t u32_data;
        void *data;
        int r;
        struct ifinfomsg *ifi;

        assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);

        assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
        assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
        assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
        assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
        assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
        assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
        assert_se(sd_rtnl_message_close_container(m) >= 0);
        assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
        assert_se(sd_rtnl_message_close_container(m) >= 0);
        assert_se(sd_rtnl_message_close_container(m) == -EINVAL);

        assert_se(rtnl_message_seal(NULL, m) >= 0);

        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_LINKINFO);
        assert_se(data == NULL);
/*
        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_INFO_KIND);
        assert_se(streq("kind", (char *)data));
        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_INFO_DATA);
        assert_se(data == NULL);
        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_VLAN_ID);
        assert_se(*(uint16_t *)data == 100);
        assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
        assert_se(sd_rtnl_message_exit_container(m) >= 0);
        assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
        assert_se(type == IFLA_INFO_KIND);
        assert_se(streq("kind", (char *)data));
        assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
        assert_se(sd_rtnl_message_exit_container(m) >= 0);
*/

        ifi = NLMSG_DATA(m->hdr);
        r = rtnl_message_parse(m,
                               &m->rta_offset_tb,
                               &m->rta_tb_size,
                               IFLA_MAX,
                               IFLA_RTA(ifi),
                               IFLA_PAYLOAD(m->hdr));
        if(r < 0)
                return;

        assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0);

        assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
}
boost::asio::ip::address_v6 get_ipv6_address(const nlmsghdr *in, const nlmsghdr *an)
{
	boost::asio::ip::address_v6 unspec;
	if (in->nlmsg_type != RTM_NEWLINK)
		return unspec;
	if (an->nlmsg_type != RTM_NEWADDR)
		return unspec;

	ifinfomsg* ifi = (ifinfomsg*)NLMSG_DATA(in);
	ifaddrmsg* ifa = (ifaddrmsg*)NLMSG_DATA(an);

	__u32 ilen = in->nlmsg_len;
	if (ilen < NLMSG_LENGTH(sizeof(*ifi)))
		return unspec;
	ilen -= NLMSG_LENGTH(sizeof(*ifi));

	__u32 alen = an->nlmsg_len;
	if (alen < NLMSG_LENGTH(sizeof(*ifa)))
		return unspec;
	alen -= NLMSG_LENGTH(sizeof(*ifa));

	/* NOTE: ifi_index and ifa_index should have the same type (int), but for
	 * some reason they are not... So instead of a normal (in)equality comparison
	 * we do a bit-wise compare.
	 */
	if (ifi->ifi_index ^ ifa->ifa_index)
		return unspec;

	if (ifi->ifi_family != AF_INET6 || ifa->ifa_family != AF_INET6)
		return unspec;

	rtattr* tbi[IFLA_MAX+1];
	memset(tbi, 0, sizeof(tbi));
	parse_rtattr(tbi, IFLA_MAX, IFLA_RTA(ifi), ilen);

	if (tbi[IFLA_IFNAME] == NULL)
		return unspec;

	rtattr* tba[IFA_MAX+1];
	memset(tba, 0, sizeof(tba));
	parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), alen);

	char abuf[256];
	rt_addr_n2a(ifa->ifa_family,
			RTA_PAYLOAD(tba[IFA_ADDRESS]),
			RTA_DATA(tba[IFA_ADDRESS]),
			abuf, sizeof(abuf));
	std::string ipaddr = abuf;

	try {
		boost::asio::ip::address_v6 addr(boost::asio::ip::address_v6::from_string(ipaddr));
		addr.scope_id(ifi->ifi_index);
		return addr;
	} catch(...) {
		return unspec;
	}
}
Esempio n. 7
0
static void ril_mtu_watch_handle_ifinfomsg(struct ril_mtu_watch *self,
					const struct ifinfomsg *ifi, int len)
{
	if (ifi->ifi_flags & IFF_UP) {
		const struct rtattr *rta = IFLA_RTA(ifi);
		ril_mtu_watch_handle_rtattr(self, rta,
					len - ((char*)rta - (char*)ifi));
	}
}
Esempio n. 8
0
int if_info_save_interface(struct nlmsghdr *hdr, void *arg)
{
    struct rtattr *attrs[IFLA_MAX + 1];
    struct ifinfomsg *info = NLMSG_DATA(hdr);

    parse_rtattrs(attrs, IFLA_MAX, IFLA_RTA(info), IFLA_PAYLOAD(hdr));

    return if_info_update_interface(hdr, attrs) ? 0 : -1;
}
Esempio n. 9
0
/**
 * vlan_get_link_parse - parse a get_link rtnl message and extract the important
 *  data
 * @nh: the reply header
 * @iface: pointer to the buffer where the link interface has to be stored (it
 *  is allocated by this function)
 *
 * Return the vid in case of success or -1 otherwise
 */
static int vlan_get_link_parse(struct nlmsghdr *nh, char **iface)
{
	struct ifinfomsg *ifi = NLMSG_DATA(nh);
	size_t vlan_len, info_len, len = nh->nlmsg_len;
	struct rtattr *rta, *info, *vlan;
	int idx = -1, vid = -1;

	*iface = NULL;

	rta = IFLA_RTA(ifi);
	while (RTA_OK(rta, len)) {
		/* check if the interface is a vlan */
		if (rta->rta_type == IFLA_LINKINFO) {
			info = RTA_DATA(rta);
			info_len = RTA_PAYLOAD(rta);

			while (RTA_OK(info, info_len)) {
				if (info->rta_type == IFLA_INFO_KIND &&
				    strcmp(RTA_DATA(info), "vlan"))
					goto err;

				if (info->rta_type == IFLA_INFO_DATA) {
					vlan = RTA_DATA(info);
					vlan_len = RTA_PAYLOAD(info);

					while (RTA_OK(vlan, vlan_len)) {
						if (vlan->rta_type == IFLA_VLAN_ID)
							vid = *(int *)RTA_DATA(vlan);
						vlan = RTA_NEXT(vlan, vlan_len);
					}
				}
				info = RTA_NEXT(info, info_len);
			}
		}

		/* extract the name of the "link" interface */
		if (rta->rta_type == IFLA_LINK) {
			idx = *(int *)RTA_DATA(rta);

			*iface = malloc(IFNAMSIZ + 1);
			if (!if_indextoname(idx, *iface))
				goto err;
		}
		rta = RTA_NEXT(rta, len);
	}

	if (vid == -1)
		goto err;

	if (idx <= 0)
		goto err;

	return vid;
err:
	free(*iface);
	return -1;
}
Esempio n. 10
0
static int print_vlan(const struct sockaddr_nl *who,
                      struct nlmsghdr *n,
                      void *arg)
{
    FILE *fp = arg;
    struct ifinfomsg *ifm = NLMSG_DATA(n);
    int len = n->nlmsg_len;
    struct rtattr * tb[IFLA_MAX+1];

    if (n->nlmsg_type != RTM_NEWLINK) {
        fprintf(stderr, "Not RTM_NEWLINK: %08x %08x %08x\n",
                n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
        return 0;
    }

    len -= NLMSG_LENGTH(sizeof(*ifm));
    if (len < 0) {
        fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
        return -1;
    }

    if (ifm->ifi_family != AF_BRIDGE)
        return 0;

    if (filter_index && filter_index != ifm->ifi_index)
        return 0;

    parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len);

    /* if AF_SPEC isn't there, vlan table is not preset for this port */
    if (!tb[IFLA_AF_SPEC]) {
        fprintf(fp, "%s\tNone\n", ll_index_to_name(ifm->ifi_index));
        return 0;
    } else {
        struct rtattr *i, *list = tb[IFLA_AF_SPEC];
        int rem = RTA_PAYLOAD(list);

        fprintf(fp, "%s", ll_index_to_name(ifm->ifi_index));
        for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
            struct bridge_vlan_info *vinfo;

            if (i->rta_type != IFLA_BRIDGE_VLAN_INFO)
                continue;

            vinfo = RTA_DATA(i);
            fprintf(fp, "\t %hu", vinfo->vid);
            if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
                fprintf(fp, " PVID");
            if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
                fprintf(fp, " Egress Untagged");
            fprintf(fp, "\n");
        }
    }
    fprintf(fp, "\n");
    fflush(fp);
    return 0;
}
Esempio n. 11
0
/* Netlink interface link lookup filter */
static int
netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
{
	struct ifinfomsg *ifi;
	struct rtattr *tb[IFLA_MAX + 1];
	interface_t *ifp;
	int len, status;
	char *name;

	ifi = NLMSG_DATA(h);

	if (h->nlmsg_type != RTM_NEWLINK)
		return 0;

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg));
	if (len < 0)
		return -1;

	/* Interface name lookup */
	memset(tb, 0, sizeof (tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL)
		return -1;
	name = (char *) RTA_DATA(tb[IFLA_IFNAME]);

	/* Return if loopback */
	if (ifi->ifi_type == ARPHRD_LOOPBACK)
		return 0;

	/* Skip it if already exist */
	ifp = if_get_by_ifname(name);
	if (ifp) {
#ifdef _HAVE_VRRP_VMAC_
		if (!ifp->vmac)
#endif
		{
#ifdef _HAVE_VRRP_VMAC_
			if_vmac_reflect_flags(ifi->ifi_index, ifi->ifi_flags);
#endif
			ifp->flags = ifi->ifi_flags;
		}
		return 0;
	}

	/* Fill the interface structure */
	ifp = (interface_t *) MALLOC(sizeof(interface_t));

	status = netlink_if_link_populate(ifp, tb, ifi);
	if (status < 0) {
		FREE(ifp);
		return -1;
	}
	/* Queue this new interface_t */
	if_add_queue(ifp);
	return 0;
}
Esempio n. 12
0
static void print_link_stats(FILE *fp, struct nlmsghdr *n)
{
	struct ifinfomsg *ifi = NLMSG_DATA(n);
	struct rtattr * tb[IFLA_MAX+1];

	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi),
		     n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
	__print_link_stats(fp, tb);
	fprintf(fp, "%s", _SL_);
}
Esempio n. 13
0
static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id,
				    int startup)
{
	char *name = NULL;
	struct ifinfomsg *ifi;
	struct rtattr *tb[IFLA_MAX + 1];
	struct interface *ifp;
	struct rtattr *aftb[IFLA_BRIDGE_MAX + 1];
	struct {
		uint16_t flags;
		uint16_t vid;
	} * vinfo;
	vlanid_t access_vlan;

	/* Fetch name and ifindex */
	ifi = NLMSG_DATA(h);
	memset(tb, 0, sizeof tb);
	netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);

	if (tb[IFLA_IFNAME] == NULL)
		return -1;
	name = (char *)RTA_DATA(tb[IFLA_IFNAME]);

	/* The interface should already be known, if not discard. */
	ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifi->ifi_index);
	if (!ifp) {
		zlog_warn("Cannot find bridge IF %s(%u)", name, ifi->ifi_index);
		return 0;
	}
	if (!IS_ZEBRA_IF_VXLAN(ifp))
		return 0;

	/* We are only interested in the access VLAN i.e., AF_SPEC */
	if (!tb[IFLA_AF_SPEC])
		return 0;

	/* There is a 1-to-1 mapping of VLAN to VxLAN - hence
	 * only 1 access VLAN is accepted.
	 */
	memset(aftb, 0, sizeof aftb);
	parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]);
	if (!aftb[IFLA_BRIDGE_VLAN_INFO])
		return 0;

	vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]);
	if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID))
		return 0;

	access_vlan = (vlanid_t)vinfo->vid;
	if (IS_ZEBRA_DEBUG_KERNEL)
		zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", access_vlan,
			   name, ifi->ifi_index);
	zebra_l2_vxlanif_update_access_vlan(ifp, access_vlan);
	return 0;
}
Esempio n. 14
0
static int rtnl_iface_get(struct nlmsghdr *h,
			  int (*if_callback)(struct iface *))
{
	struct rtattr *tb[IFLA_MAX + 1];
	struct ifinfomsg *ifi;
	int len;

	struct iface iface;

	if (h->nlmsg_type != RTM_NEWLINK)
		return 0;

	ifi = NLMSG_DATA(h);
	
	len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
	if (len < 0)
		return -1;
		
	netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);

	if (!tb[IFLA_IFNAME] || !tb[IFLA_ADDRESS]) {
		DEBUGP("Error: getting interface info");
		return -1;
	}

	iface.haddr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
	
	if (iface.haddr_len < MAX_ADDR_LEN) {
		memcpy(iface.haddr, RTA_DATA(tb[IFLA_ADDRESS]),
		       iface.haddr_len);
	} else {
		DEBUGP("Warning: Hardware address is too large: %d", 
			iface.haddr_len);
		return -1;
	}

	strcpy(iface.name, (char *)RTA_DATA(tb[IFLA_IFNAME]));
	strcpy(iface.qdisc, (char *)RTA_DATA(tb[IFLA_QDISC]));

	iface.index = ifi->ifi_index;
	iface.type  = ifi->ifi_type;
	iface.flags = ifi->ifi_flags & 0x0000fffff;

	iface.mtu 	 = (tb[IFLA_MTU]) ? *(int *)RTA_DATA(tb[IFLA_MTU]) : 0;
	iface.weight	 = (tb[IFLA_WEIGHT]) ? *(int *)RTA_DATA(tb[IFLA_WEIGHT]) : 0;
	iface.txqueuelen = *(int *)RTA_DATA(tb[IFLA_TXQLEN]);
	
	iface.stats = *(struct net_device_stats *)RTA_DATA(tb[IFLA_STATS]);

	return if_callback(&iface);
}
Esempio n. 15
0
int ll_remember_index(const struct sockaddr_nl *who,
		      struct nlmsghdr *n, void *arg)
{
	int h;
	struct ifinfomsg *ifi = NLMSG_DATA(n);
	struct ll_cache *im, **imp;
	struct rtattr *tb[IFLA_MAX+1];

	UNUSED(who);
	UNUSED(arg);

	if (n->nlmsg_type != RTM_NEWLINK)
		return 0;

	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
		return -1;

	memset(tb, 0, sizeof(tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
	if (tb[IFLA_IFNAME] == NULL)
		return 0;

	h = ifi->ifi_index & (IDXMAP_SIZE - 1);
	for (imp = &idx_head[h]; (im=*imp)!=NULL; imp = &im->idx_next)
		if (im->index == ifi->ifi_index)
			break;

	if (im == NULL) {
		im = malloc(sizeof(*im));
		if (im == NULL)
			return 0;
		im->idx_next = *imp;
		im->index = ifi->ifi_index;
		*imp = im;
	}

	im->type = ifi->ifi_type;
	im->flags = ifi->ifi_flags;
	if (tb[IFLA_ADDRESS]) {
		size_t alen;
		im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
		if (alen > sizeof(im->addr))
			alen = sizeof(im->addr);
		memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
	} else {
		im->alen = 0;
		memset(im->addr, 0, sizeof(im->addr));
	}
	strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]));
	return 0;
}
Esempio n. 16
0
/* Called from interface_lookup_netlink().  This function is only used
   during bootstrap. */
static int
netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
  int len;
  struct ifinfomsg *ifi;
  struct rtattr *tb[IFLA_MAX + 1];
  struct interface *ifp;
  char *name;

  ifi = NLMSG_DATA (h);

  if (h->nlmsg_type != RTM_NEWLINK)
    return 0;

  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
  if (len < 0)
    return -1;

  /* Looking up interface name. */
  memset (tb, 0, sizeof tb);
  netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
  
#ifdef IFLA_WIRELESS
  /* check for wireless messages to ignore */
  if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
    {
      if (IS_DEBUG_HA(kroute, KROUTE))
        zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
      return 0;
    }
#endif /* IFLA_WIRELESS */

  if (tb[IFLA_IFNAME] == NULL)
    return -1;
  name = (char *) RTA_DATA (tb[IFLA_IFNAME]);

  /* Add interface. */
  ifp = if_get_by_name (name);
  set_ifindex(ifp, ifi->ifi_index);
  ifp->flags = ifi->ifi_flags & 0x0000fffff;
  ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
  ifp->metric = 1;

  /* Hardware type and address. */
  ifp->hw_type = ifi->ifi_type;
  netlink_interface_update_hw_addr (tb, ifp);

  if_add_update (ifp);

  return 0;
}
Esempio n. 17
0
static int handle_link_msg(struct nlmsghdr *nlh, int n)
{
	struct ifinfomsg *ifla_msg = NLMSG_DATA(nlh);
	struct rtattr *tb[IFLA_MAX];


	int atts = parse_rt_attrs(tb, IFLA_MAX, IFLA_RTA(ifla_msg), IFLA_PAYLOAD(nlh));

	parse_ifinfomsg(ifla_msg);

	handle_link_attrs(ifla_msg, tb, nlh->nlmsg_type);

	return 0;
}
Esempio n. 18
0
rtnetlink::if_addr& rtnetlink::if_addr::operator=(message& msg)
{
	static_cast<data&>(*this) = msg;

	std::pair<const void*, size_t> pl = msg.payload();

	if (msg.type() < 20 || msg.type() > 23 || pl.second < sizeof(::ifaddrmsg))
		throw "bad msg type";

	const ::ifaddrmsg* ifa = reinterpret_cast<const ifaddrmsg*>(pl.first);

	_family = ifa->ifa_family;
	_prefixlen = ifa->ifa_prefixlen;
	_scope = ifa->ifa_scope;
	_flags = ifa->ifa_flags;
	_index = ifa->ifa_index;

	const ::rtattr* rta = IFLA_RTA(ifa);
	size_t attrlen = IFLA_PAYLOAD(reinterpret_cast<const ::nlmsghdr*>(_msg->header()));

	for (; RTA_OK(rta, attrlen); rta = RTA_NEXT(rta, attrlen)) {
		switch (rta->rta_type) {
		case IFA_ADDRESS:
			_address = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFA_LOCAL:
			_local = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFA_LABEL:
			_label = attr<char>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFA_BROADCAST:
			_broadcast = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		case IFA_ANYCAST:
			_anycast = attr<void>(RTA_DATA(rta), RTA_PAYLOAD(rta));
			break;

		default:
			std::cout << "IFA_UNSPEC(" << rta->rta_type << ", " << RTA_PAYLOAD(rta) << ")\n";
		}
	}

	return *this;
}
Esempio n. 19
0
/* Netlink flag Link update */
static int
netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
{
	struct ifinfomsg *ifi;
	struct rtattr *tb[IFLA_MAX + 1];
	interface_t *ifp;
	int len;

	ifi = NLMSG_DATA(h);
	if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
		return 0;

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg));
	if (len < 0)
		return -1;

	/* Interface name lookup */
	memset(tb, 0, sizeof (tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL)
		return -1;

	/* ignore loopback device */
	if (ifi->ifi_type == ARPHRD_LOOPBACK)
		return 0;

	/* find the VMAC interface (if any) */
	ifp = if_get_by_vmac_base_ifindex(ifi->ifi_index);

	/* if found, reflect base interface flags on VMAC interface */
	if (ifp)
		ifp->flags = ifi->ifi_flags;

	/* find the interface_t */
	ifp = if_get_by_ifindex(ifi->ifi_index);
	if (!ifp)
		return -1;

	/*
	 * Update flags.
	 * VMAC interfaces should never update it own flags, only be reflected
	 * by the base interface flags, see above.
	 */
	if (!ifp->vmac)
		ifp->flags = ifi->ifi_flags;

	return 0;
}
Esempio n. 20
0
static void nl_parse_link_msg(struct nlmsghdr *nlp, struct nl_cb *cb)
{
	nl_link_cb link_cb;
	struct ifinfomsg *ifinfo;
	struct rtattr *rtap;
	struct nl_link link;
	size_t len;

	memset(&link, 0, sizeof(struct nl_link));
	ifinfo = NLMSG_DATA(nlp);
	rtap = IFLA_RTA(ifinfo);
	len = IFLA_PAYLOAD(nlp);

	for (; RTA_OK(rtap, len); rtap = RTA_NEXT(rtap, len)) {
		switch (rtap->rta_type) {
		case IFLA_IFNAME:
			link.ifname = (char *)RTA_DATA(rtap);
			break;
		case IFLA_ADDRESS:
			if (RTA_PAYLOAD(rtap) != sizeof(struct ether_addr)) {
				XLOG_ERR("invalid ll address for %u", ifinfo->ifi_index);
				return;
			}
			link.ifaddr = (struct ether_addr *)RTA_DATA(rtap);
			break;
		default:
			/* XLOG_DEBUG("attr: %u", rtap->rta_type); */
			break;
		}
	}

	if (!link.ifname) {
		XLOG_ERR("could not get name for link %u", ifinfo->ifi_index);
		return;
	}

	if (!link.ifaddr) {
		XLOG_ERR("could not get ll addr for link %u", ifinfo->ifi_index);
		return;
	}

	link.ifindex = ifinfo->ifi_index;
	link.iftype = ifinfo->ifi_type;
	link.ifflags = ifinfo->ifi_flags;

	link_cb = (nl_link_cb) cb->parse_cb;
	link_cb(&link, cb->aux);
}
Esempio n. 21
0
int get_rtstat_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *m, void *arg)
{
#ifndef IFLA_RTSTATS
		return -1;
#else
	struct ifinfomsg *ifi = NLMSG_DATA(m);
	struct rtattr * tb[IFLA_MAX+1];
	int len = m->nlmsg_len;
	struct rtstat_ent *n;
	unsigned long ival[RTMAXS];
	int i;

	if (m->nlmsg_type != RTM_NEWLINK)
		return 0;

	len -= NLMSG_LENGTH(sizeof(*ifi));
	if (len < 0)
		return -1;

	if (!(ifi->ifi_flags&IFF_UP))
		return 0;


	memset(tb, 0, sizeof(tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL || tb[IFLA_RTSTATS] == NULL)
		return 0;

	n = malloc(sizeof(*n));
	if (!n)
		abort();
	n->ifindex = ifi->ifi_index;
	n->name = strdup(RTA_DATA(tb[IFLA_IFNAME]));

	memcpy(&ival, RTA_DATA(tb[IFLA_RTSTATS]), sizeof(ival));

	for (i=0; i<RTMAXS; i++) {
		n->ival[i] = ival[i];
	}

	n->next = rtstat_db;
	rtstat_db = n;


	return 0;
#endif
}
Esempio n. 22
0
static gboolean
is_wireless_status_message (struct nlmsghdr *header)
{
        int rt_attr_len;
        struct rtattr *rt_attr;

        rt_attr = IFLA_RTA (NLMSG_DATA (header));
        rt_attr_len = IFLA_PAYLOAD (header);
        while (RT_ATTR_OK (rt_attr, rt_attr_len)) {
                if (rt_attr->rta_type == IFLA_WIRELESS)
                        return TRUE;

                rt_attr = RTA_NEXT (rt_attr, rt_attr_len);
        }

        return FALSE;
}
Esempio n. 23
0
static void
extract_info (struct nlmsghdr *header, char **label)
{
        int rt_attr_len;
        struct rtattr *rt_attr;

        rt_attr = IFLA_RTA (NLMSG_DATA (header));
        rt_attr_len = IFLA_PAYLOAD (header);
        while (RT_ATTR_OK (rt_attr, rt_attr_len)) {
                if (rt_attr->rta_type == IFA_LABEL) {
                        *label = g_strdup ((char *) RTA_DATA (rt_attr));

                        break;
                }
                rt_attr = RTA_NEXT (rt_attr, rt_attr_len);
        }
}
Esempio n. 24
0
/* iftable_del - Delete an entry from the interface table
 * @n:		netlink message header of a RTM_DELLINK nlmsg
 * @arg:	not used
 *
 * Delete an entry from the interface table.  
 * Returns -1 on error, 0 if no matching entry was found or 1 on success.
 */
static int iftable_del(struct nlmsghdr *n, void *arg)
{
	struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
	struct rtattr *cb[IFLA_MAX+1];
	struct nlif_handle *nlif_handle = (struct nlif_handle *)arg;
	struct ifindex_map *im, *ima, **imp;
	unsigned int hash;

	if (n->nlmsg_type != RTM_DELLINK) {
		iftb_log(LOG_ERROR,
			 "called with wrong nlmsg_type %u", n->nlmsg_type);
		return -1;
	}

	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi_msg))) {
		iftb_log(LOG_ERROR, "short message (%u < %u)",
			 n->nlmsg_len, NLMSG_LENGTH(sizeof(ifi_msg)));
		return -1;
	}

	memset(&cb, 0, sizeof(cb));
	rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));

	/* \todo Really suppress entry */
	hash = ifi_msg->ifi_index&0xF;
	for (ima = NULL, imp = &((nlif_handle->ifindex_map)[hash]); 
	     (im=*imp)!=NULL; imp = &im->next, ima=im) {
		if (im->index == ifi_msg->ifi_index) {
			iftb_log(LOG_DEBUG,
				 "deleting iftable (ifindex=%u)", im->index);
			break;
		}
	}

	if (!im)
		return 0;

	if (ima)
		ima->next = *imp;
	else
		(nlif_handle->ifindex_map)[hash] = *imp;
	free(im);

	return 1;
}
Esempio n. 25
0
static int get_netstat_nlmsg(struct sockaddr_nl *who, struct nlmsghdr *m, void *arg)
{
	struct ifinfomsg *ifi = NLMSG_DATA(m);
	struct rtattr * tb[IFLA_MAX+1];
	int len = m->nlmsg_len;
	struct ifstat_ent *n;
	uint64_t ival[MAXS];
	int i;

	if (m->nlmsg_type != RTM_NEWLINK)
		return 0;

	len -= NLMSG_LENGTH(sizeof(*ifi));
	if (len < 0)
		return -1;

	if (!(ifi->ifi_flags&IFF_UP))
		return 0;

	memset(tb, 0, sizeof(tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL || tb[IFLA_STATS64] == NULL)
		return 0;

	n = malloc(sizeof(*n));
	if (!n)
		abort();
	n->ifindex = ifi->ifi_index;
	n->name = strdup(RTA_DATA(tb[IFLA_IFNAME]));
	memcpy(&ival, RTA_DATA(tb[IFLA_STATS64]), sizeof(ival));
	for (i=0; i<MAXS; i++) {

#undef DO_L2_STATS
#ifdef DO_L2_STATS

		if(i == 2) n->ival[i] = n->ival[i]+4; /* RX CRC */
		if(i == 3) n->ival[i] = n->ival[i]+18; /* TX 14+4 E-hdr + CRC */
#endif
		n->val[i] = ival[i];
	}
	n->next = kern_db;
	kern_db = n;
	return 0;
}
Esempio n. 26
0
static char *
parse_ifname_rta(struct ifinfomsg *info, int len)
{
    struct rtattr *rta = IFLA_RTA(info);
    char *ifname = NULL;

    len -= NLMSG_ALIGN(sizeof(*info));

    while(RTA_OK(rta, len)) {
        switch (rta->rta_type) {
        case IFLA_IFNAME:
            ifname = RTA_DATA(rta);
            break;
        default:
            break;
        }
        rta = RTA_NEXT(rta, len);
    }
    return ifname;
}
Esempio n. 27
0
static void __if_nameindex_callback(void* context, nlmsghdr* hdr) {
  if_list** list = reinterpret_cast<if_list**>(context);
  if (hdr->nlmsg_type == RTM_NEWLINK) {
    ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));

    // Create a new entry and set the interface index.
    if_list* new_link = new if_list(list);
    new_link->data.if_index = ifi->ifi_index;

    // Go through the various bits of information and find the name.
    rtattr* rta = IFLA_RTA(ifi);
    size_t rta_len = IFLA_PAYLOAD(hdr);
    while (RTA_OK(rta, rta_len)) {
      if (rta->rta_type == IFLA_IFNAME) {
        new_link->data.if_name = strndup(reinterpret_cast<char*>(RTA_DATA(rta)), RTA_PAYLOAD(rta));
      }
      rta = RTA_NEXT(rta, rta_len);
    }
  }
}
Esempio n. 28
0
static void g_pn_nl_link(GPhonetNetlink *self, struct nlmsghdr *nlh)
{
	const struct ifinfomsg *ifi;
	const struct rtattr *rta;
	int len;
	const char *ifname = NULL;
	GIsiModem *idx = NULL;
	GPhonetLinkState st;

	ifi = NLMSG_DATA(nlh);
	len = IFA_PAYLOAD(nlh);

	if (ifi->ifi_type != ARPHRD_PHONET)
		return;

	if (self->interface != 0 && self->interface != (unsigned)ifi->ifi_index)
		return;

	idx = make_modem(ifi->ifi_index);

#define UP (IFF_UP | IFF_LOWER_UP | IFF_RUNNING)

	if (nlh->nlmsg_type == RTM_DELLINK)
		st = PN_LINK_REMOVED;
	else if ((ifi->ifi_flags & UP) != UP)
		st = PN_LINK_DOWN;
	else
		st = PN_LINK_UP;

	for (rta = IFLA_RTA(ifi); RTA_OK(rta, len);
		rta = RTA_NEXT(rta, len)) {

		if (rta->rta_type == IFLA_IFNAME)
			ifname = RTA_DATA(rta);
	}

	if (ifname && idx)
		self->callback(idx, st, ifname, self->opaque);

#undef UP
}
Esempio n. 29
0
static inline
bt_address * parse_address ( void * ctx, struct ifaddrmsg * message, size_t length )
{
    bt_address * address = talloc ( ctx, sizeof ( bt_address ) );
    if ( address == NULL ) {
        return NULL;
    }

    struct rtattr * attribute;
    size_t          payload;
    char *          label;

    bool found_label   = false;
    bool found_address = false;
    for ( attribute = IFLA_RTA ( message ) ; RTA_OK ( attribute, length ); attribute = RTA_NEXT ( attribute, length ) ) {
        switch ( attribute->rta_type ) {
        case IFA_ADDRESS:
        case IFA_LOCAL:
            memcpy ( &address->addr, RTA_DATA ( attribute ), RTA_PAYLOAD ( attribute ) );
            found_address = true;
            break;
        case IFA_LABEL:
            payload = RTA_PAYLOAD ( attribute );
            label = talloc ( address, sizeof ( char ) * payload );
            if ( label == NULL ) {
                talloc_free ( address );
                return NULL;
            }
            memcpy ( label, RTA_DATA ( attribute ), payload );
            address->label = label;
            found_label    = true;
            break;
        }
    }

    if ( found_label && found_address ) {
        return address;
    }
    talloc_free ( address );
    return NULL;
}
Esempio n. 30
0
static bool extract_link(struct ifinfomsg *msg, int bytes,
				struct ether_addr *address, const char **ifname,
				unsigned int *mtu, unsigned char *operstate,
				struct rtnl_link_stats *stats)
{
	struct rtattr *attr;

	for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
					attr = RTA_NEXT(attr, bytes)) {
		switch (attr->rta_type) {
		case IFLA_ADDRESS:
			if (address)
				memcpy(address, RTA_DATA(attr), ETH_ALEN);
			break;
		case IFLA_IFNAME:
			if (ifname)
				*ifname = RTA_DATA(attr);
			break;
		case IFLA_MTU:
			if (mtu)
				*mtu = *((unsigned int *) RTA_DATA(attr));
			break;
		case IFLA_STATS:
			if (stats)
				memcpy(stats, RTA_DATA(attr),
					sizeof(struct rtnl_link_stats));
			break;
		case IFLA_OPERSTATE:
			if (operstate)
				*operstate = *((unsigned char *) RTA_DATA(attr));
			break;
		case IFLA_LINKMODE:
			break;
		case IFLA_WIRELESS:
			return false;
		}
	}

	return true;
}