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); } }
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; }
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); }
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); }
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; } }
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)); } }
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; }
/** * 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; }
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; }
/* 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; }
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_); }
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; }
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); }
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; }
/* 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; }
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; }
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; }
/* 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; }
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); }
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 }
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; }
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); } }
/* 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; }
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; }
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; }
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); } } }
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 }
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; }
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; }