static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp) { struct nl_cache *link_cache; char buf[128]; link_cache = nl_cache_mngt_require("route/link"); nl_dump(dp, "nexthop"); if (nh->ce_mask & NH_ATTR_GATEWAY) nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf))); if(nh->ce_mask & NH_ATTR_IFINDEX) { if (link_cache) { nl_dump(dp, " dev %s", rtnl_link_i2name(link_cache, nh->rtnh_ifindex, buf, sizeof(buf))); } else nl_dump(dp, " dev %d", nh->rtnh_ifindex); } if (nh->ce_mask & NH_ATTR_WEIGHT) nl_dump(dp, " weight %u", nh->rtnh_weight); if (nh->ce_mask & NH_ATTR_REALMS) nl_dump(dp, " realm %04x:%04x", RTNL_REALM_FROM(nh->rtnh_realms), RTNL_REALM_TO(nh->rtnh_realms)); if (nh->ce_mask & NH_ATTR_FLAGS) nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags, buf, sizeof(buf))); }
static int neigh_dump_brief(struct nl_cache *c, struct nl_common *a, FILE *fd, struct nl_dump_params *params) { char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5]; struct rtnl_neigh *n = (struct rtnl_neigh *) a; char state[128], flags[64]; dp_new_line(fd, params, 0); fprintf(fd, "%s dev %s lladdr %s ", nl_addr2str_r(&(n->n_dst), dst, sizeof(dst)), rtnl_link_i2name(nl_cache_lookup(RTNL_LINK), n->n_ifindex), nl_addr2str_r(&(n->n_lladdr), lladdr, sizeof(lladdr))); rtnl_neigh_state2str_r(n->n_state, state, sizeof(state)); rtnl_neigh_flags2str_r(n->n_flags, flags, sizeof(flags)); if (state[0]) fprintf(fd, "<%s", state); if (flags[0]) fprintf(fd, "%s%s", state[0] ? "," : "<", flags); if (state[0] || flags[0]) fprintf(fd, ">"); fprintf(fd, "\n"); return 1; }
int match_nl_table_cmd_to_type(FILE *fp, bool print, int valid, struct nlattr *tb[]) { unsigned int type, ifindex; int err; char iface[IFNAMSIZ]; struct nl_sock *fd = NULL; if (!tb[NET_MAT_IDENTIFIER_TYPE]) { MAT_LOG(ERR, "Warning: received rule msg without identifier type!\n"); return -EINVAL; } if (!tb[NET_MAT_IDENTIFIER]) { MAT_LOG(ERR, "Warning: received rule msg without identifier!\n"); return -EINVAL; } if (valid > 0 && !tb[valid]) { MAT_LOG(ERR, "Warning: received cmd without valid attribute expected %i\n", valid); return -ENOMSG; } if (nla_len(tb[NET_MAT_IDENTIFIER_TYPE]) < (int)sizeof(type)) { MAT_LOG(ERR, "Warning: invalid identifier type len\n"); return -EINVAL; } type = nla_get_u32(tb[NET_MAT_IDENTIFIER_TYPE]); switch (type) { case NET_MAT_IDENTIFIER_IFINDEX: fd = nl_socket_alloc(); err = nl_connect(fd, NETLINK_ROUTE); if (err < 0) { MAT_LOG(ERR,"Warning: Unable to connect socket\n"); break; } err = rtnl_link_alloc_cache(fd, AF_UNSPEC, &link_cache); if (err < 0) { MAT_LOG(ERR,"Warning: Unable to allocate cache\n"); break; } ifindex = nla_get_u32(tb[NET_MAT_IDENTIFIER]); rtnl_link_i2name(link_cache, (int)ifindex, iface, IFNAMSIZ); if (ifindex) pfprintf(fp, print, "%s (%u):\n", iface, ifindex); break; default: MAT_LOG(ERR, "Warning: unknown interface identifier type %i\n", type); break; } if (fd) { nl_close(fd); nl_socket_free(fd); } return 0; }
char * nm_netlink_index_to_iface (int idx) { NMNetlinkMonitor *self; NMNetlinkMonitorPrivate *priv; char *buf = NULL; g_return_val_if_fail (idx >= 0, NULL); self = nm_netlink_monitor_get (); priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); buf = g_malloc0 (MAX_IFACE_LEN); g_assert (buf); nl_cache_refill (priv->nlh_sync, priv->link_cache); if (!rtnl_link_i2name (priv->link_cache, idx, buf, MAX_IFACE_LEN - 1)) { nm_log_warn (LOGD_HW, "(%d) failed to find interface name for index", idx); g_free (buf); buf = NULL; } g_object_unref (self); return buf; }
static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp) { struct nl_cache *link_cache; char buf[128]; link_cache = nl_cache_mngt_require("route/link"); nl_dump(dp, "via"); if (nh->ce_mask & NH_ATTR_GATEWAY) nl_dump(dp, " %s", nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf))); if(nh->ce_mask & NH_ATTR_IFINDEX) { if (link_cache) { nl_dump(dp, " dev %s", rtnl_link_i2name(link_cache, nh->rtnh_ifindex, buf, sizeof(buf))); } else nl_dump(dp, " dev %d", nh->rtnh_ifindex); } nl_dump(dp, " "); }
static int route_dump_brief(struct nl_cache *c, struct nl_common *a, FILE *fd, struct nl_dump_params *params) { struct rtnl_route *r = (struct rtnl_route *) a; dp_new_line(fd, params, 0); if (r->rt_mask & ROUTE_HAS_DST) { char dst[INET6_ADDRSTRLEN+5]; fprintf(fd, "%s ", nl_addr2str_r(&r->rt_dst, dst, sizeof(dst))); } else if (r->rt_dst_len) fprintf(fd, "0/%u ", r->rt_dst_len); else fprintf(fd, "default "); if (r->rt_mask & ROUTE_HAS_GATEWAY) { char via[INET6_ADDRSTRLEN+5]; fprintf(fd, "via %s ", nl_addr2str_r(&r->rt_gateway, via, sizeof(via))); } if (r->rt_mask & ROUTE_HAS_OIF) { const char *dev = rtnl_link_i2name(nl_cache_lookup(RTNL_LINK), r->rt_oif); fprintf(fd, "dev %s ", dev); } if (r->rt_table != RT_TABLE_MAIN) fprintf(fd, "table %u ", r->rt_table); if (r->rt_mask & ROUTE_HAS_FLAGS && r->rt_flags) { int flags = r->rt_flags; fprintf(fd, "<"); #define PRINT_FLAG(f) if (flags & RTNH_F_##f) { \ flags &= ~RTNH_F_##f; fprintf(fd, #f "%s", flags ? "," : ""); } PRINT_FLAG(DEAD); PRINT_FLAG(ONLINK); PRINT_FLAG(PERVASIVE); #undef PRINT_FLAG #define PRINT_FLAG(f) if (flags & RTM_F_##f) { \ flags &= ~RTM_F_##f; fprintf(fd, #f "%s", flags ? "," : ""); } PRINT_FLAG(NOTIFY); PRINT_FLAG(CLONED); PRINT_FLAG(EQUALIZE); PRINT_FLAG(PREFIX); #undef PRINT_FLAG fprintf(fd, ">"); } fprintf(fd, "\n"); return 1; }
void tca_dump_line(struct rtnl_tc *g, const char *type, struct nl_dump_params *p) { char handle[32], parent[32]; struct nl_cache *link_cache; link_cache = nl_cache_mngt_require("route/link"); nl_dump_line(p, "%s %s ", type, g->tc_kind); if (link_cache) { char buf[32]; nl_dump(p, "dev %s ", rtnl_link_i2name(link_cache, g->tc_ifindex, buf, sizeof(buf))); } else nl_dump(p, "dev %u ", g->tc_ifindex); nl_dump(p, "id %s parent %s", rtnl_tc_handle2str(g->tc_handle, handle, sizeof(handle)), rtnl_tc_handle2str(g->tc_parent, parent, sizeof(parent))); }
static int addr_dump_brief(struct nl_object *obj, struct nl_dump_params *p) { struct rtnl_addr *addr = (struct rtnl_addr *) obj; struct nl_cache *link_cache; char buf[128]; link_cache = nl_cache_mngt_require("route/link"); if (addr->a_mask & ADDR_ATTR_LOCAL) dp_dump(p, "%s", nl_addr2str(addr->a_local, buf, sizeof(buf))); else dp_dump(p, "none"); if (addr->a_mask & ADDR_ATTR_PEER) dp_dump(p, " peer %s", nl_addr2str(addr->a_peer, buf, sizeof(buf))); dp_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf))); if (link_cache) dp_dump(p, "dev %s ", rtnl_link_i2name(link_cache, addr->a_ifindex, buf, sizeof(buf))); else dp_dump(p, "dev %d ", addr->a_ifindex); dp_dump(p, "scope %s", rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); if (buf[0]) dp_dump(p, " <%s>", buf); dp_dump(p, "\n"); return 1; }
int main(int argc, char *argv[]) { struct nl_sock *sock; struct nl_cache *link_cache; char name[IFNAMSIZ]; uint32_t ifindex; if (argc < 2) print_usage(); sock = nl_cli_alloc_socket(); nl_cli_connect(sock, NETLINK_ROUTE); link_cache = nl_cli_link_alloc_cache(sock); ifindex = nl_cli_parse_u32(argv[1]); if (!rtnl_link_i2name(link_cache, ifindex, name, sizeof(name))) nl_cli_fatal(ENOENT, "Interface index %d does not exist", ifindex); printf("%s\n", name); return 0; }
static void nh_dump_env(struct rtnl_nexthop *nh, struct nl_dump_params *dp) { struct nl_cache *link_cache; char buf[128]; link_cache = nl_cache_mngt_require("route/link"); if (nh->ce_mask & NH_ATTR_GATEWAY) nl_dump_line(dp, "ROUTE_NH%d_VIA=%s\n", dp->dp_ivar, nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf))); if(nh->ce_mask & NH_ATTR_IFINDEX) { if (link_cache) { nl_dump_line(dp, "ROUTE_NH%d_DEV=%s\n", dp->dp_ivar, rtnl_link_i2name(link_cache, nh->rtnh_ifindex, buf, sizeof(buf))); } else nl_dump_line(dp, "ROUTE_NH%d_DEV=%d\n", dp->dp_ivar, nh->rtnh_ifindex); } if (nh->ce_mask & NH_ATTR_WEIGHT) nl_dump_line(dp, "ROUTE_NH%d_WEIGHT=%u\n", dp->dp_ivar, nh->rtnh_weight); if (nh->ce_mask & NH_ATTR_REALMS) nl_dump_line(dp, "ROUTE_NH%d_REALM=%04x:%04x\n", dp->dp_ivar, RTNL_REALM_FROM(nh->rtnh_realms), RTNL_REALM_TO(nh->rtnh_realms)); if (nh->ce_mask & NH_ATTR_FLAGS) nl_dump_line(dp, "ROUTE_NH%d_FLAGS=<%s>\n", dp->dp_ivar, rtnl_route_nh_flags2str(nh->rtnh_flags, buf, sizeof(buf))); }
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; } }
static int addr_dump_xml(struct nl_object *obj, struct nl_dump_params *p) { struct rtnl_addr *addr = (struct rtnl_addr *) obj; struct nl_cache *link_cache; char buf[128]; int line = 0; dp_dump_line(p, line++, "<address>\n"); dp_dump_line(p, line++, " <family>%s</family>\n", nl_af2str(addr->a_family, buf, sizeof(buf))); if (addr->a_mask & ADDR_ATTR_LOCAL) dp_dump_line(p, line++, " <local>%s</local>\n", nl_addr2str(addr->a_local, buf, sizeof(buf))); if (addr->a_mask & ADDR_ATTR_PEER) dp_dump_line(p, line++, " <peer>%s</peer>\n", nl_addr2str(addr->a_peer, buf, sizeof(buf))); if (addr->a_mask & ADDR_ATTR_BROADCAST) dp_dump_line(p, line++, " <broadcast>%s</broadcast>\n", nl_addr2str(addr->a_bcast, buf, sizeof(buf))); if (addr->a_mask & ADDR_ATTR_ANYCAST) dp_dump_line(p, line++, " <anycast>%s</anycast>\n", nl_addr2str(addr->a_anycast, buf, sizeof(buf))); if (addr->a_mask & ADDR_ATTR_MULTICAST) dp_dump_line(p, line++, " <multicast>%s</multicast>\n", nl_addr2str(addr->a_multicast, buf, sizeof(buf))); if (addr->a_mask & ADDR_ATTR_PREFIXLEN) dp_dump_line(p, line++, " <prefixlen>%u</prefixlen>\n", addr->a_prefixlen); link_cache = nl_cache_mngt_require("route/link"); if (link_cache) dp_dump_line(p, line++, " <device>%s</device>\n", rtnl_link_i2name(link_cache, addr->a_ifindex, buf, sizeof(buf))); else dp_dump_line(p, line++, " <device>%u</device>\n", addr->a_ifindex); if (addr->a_mask & ADDR_ATTR_SCOPE) dp_dump_line(p, line++, " <scope>%s</scope>\n", rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); if (addr->a_mask & ADDR_ATTR_LABEL) dp_dump_line(p, line++, " <label>%s</label>\n", addr->a_label); rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); if (buf[0]) dp_dump_line(p, line++, " <flags>%s</flags>\n", buf); if (addr->a_mask & ADDR_ATTR_CACHEINFO) { struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; dp_dump_line(p, line++, " <cacheinfo>\n"); dp_dump_line(p, line++, " <valid>%s</valid>\n", ci->aci_valid == 0xFFFFFFFFU ? "forever" : nl_msec2str(ci->aci_valid * 1000, buf, sizeof(buf))); dp_dump_line(p, line++, " <prefered>%s</prefered>\n", ci->aci_prefered == 0xFFFFFFFFU ? "forever" : nl_msec2str(ci->aci_prefered * 1000, buf, sizeof(buf))); dp_dump_line(p, line++, " <created>%s</created>\n", nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, buf, sizeof(buf))); dp_dump_line(p, line++, " <last-update>%s</last-update>\n", nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, buf, sizeof(buf))); dp_dump_line(p, line++, " </cacheinfo>\n"); } dp_dump_line(p, line++, "</address>\n"); return line; }
static int netlink_msg_handler(struct nl_msg *msg, void *arg) { struct nlmsghdr *hdr; struct tcmsg *tcm; struct nlattr *attrs[TCA_MAX+1]; struct nlattr *stat_attrs[TCA_STATS_MAX+1]; struct qdisc_handler *h; char qdisc[IFNAMSIZ] = {0}; int qdisc_l = 0; char ifname[IFNAMSIZ] = {0}; int ifname_l = 0; struct timeval current_time = {0}; double time; char *ret = NULL; struct gnet_stats_basic *sb; struct gnet_stats_queue *q; struct options *opt = arg; struct recordset rset = {0}; hdr = nlmsg_hdr(msg); tcm = nlmsg_data(hdr); if(!has_iface(opt, tcm->tcm_ifindex)) return NL_SKIP; if((ret = rtnl_link_i2name(opt->cache, tcm->tcm_ifindex, ifname, IFNAMSIZ)) == NULL) return NL_SKIP; // No length checking in netlink library. if((ifname_l = 1 + strnlen(ifname, IFNAMSIZ)) >= IFNAMSIZ) { ifname[IFNAMSIZ-1] = '\0'; ifname_l = IFNAMSIZ; } gettimeofday(¤t_time, NULL); time = (double)current_time.tv_usec / 1000000 + (double) current_time.tv_sec; add_record_double(&rset, "time", sizeof("time"), time); add_record_str(&rset, "iface", sizeof("iface"), ifname, ifname_l); nlmsg_parse(hdr, sizeof(*tcm), attrs, TCA_MAX, tca_policy); if(attrs[TCA_KIND]) { qdisc_l = nla_len(attrs[TCA_KIND]); memcpy(qdisc, nla_get_string(attrs[TCA_KIND]), qdisc_l); add_record_str(&rset, "qdisc", sizeof("qdisc"), qdisc, qdisc_l); } add_record_hex(&rset, "handle", sizeof("handle"), tcm->tcm_handle >> 16); if(attrs[TCA_STATS2]) { nla_parse_nested(stat_attrs, TCA_STATS_MAX, attrs[TCA_STATS2], tca_stats_policy); if(stat_attrs[TCA_STATS_BASIC]) { sb = nla_data(stat_attrs[TCA_STATS_BASIC]); add_record_uint(&rset, "bytes", sizeof("bytes"), sb->bytes); add_record_uint(&rset, "packets", sizeof("packets"), sb->packets); } if(stat_attrs[TCA_STATS_QUEUE]) { q = nla_data(stat_attrs[TCA_STATS_QUEUE]); add_record_uint(&rset, "drops", sizeof("drops"), q->drops); add_record_uint(&rset, "qlen", sizeof("qlen"), q->qlen); add_record_uint(&rset, "backlog", sizeof("backlog"), q->backlog); add_record_uint(&rset, "overlimits", sizeof("overlimits"), q->overlimits); add_record_uint(&rset, "requeues", sizeof("requeues"), q->requeues); } if(stat_attrs[TCA_STATS_APP]) { h = find_qdisc_handler(qdisc); if(h) h->parse_stats(stat_attrs[TCA_STATS_APP], &rset); } } opt->formatter->format(opt->formatter, &rset); clear_records(&rset); if(!opt->run_length || current_time.tv_sec < opt->start_time.tv_sec + opt->run_length) return NL_OK; else return NL_STOP; }
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"); }
static void handle_class(struct nl_object *obj, void *arg) { struct rtnl_tc *tc = (struct rtnl_tc *) obj; struct element *e; struct rdata *rdata = arg; struct rdata ndata = { .level = rdata->level + 1, }; if (!(e = handle_tc_obj(tc, "class", rdata))) return; ndata.parent = e; if (!strcmp(rtnl_tc_get_kind(tc), "htb")) element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc)); find_classes(rtnl_tc_get_handle(tc), &ndata); find_qdiscs(rtnl_tc_get_handle(tc), &ndata); } static void find_qdiscs(uint32_t parent, struct rdata *rdata) { struct rtnl_qdisc *filter; if (!(filter = rtnl_qdisc_alloc())) return; rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter), handle_qdisc, rdata); rtnl_qdisc_put(filter); } static void find_cls(int ifindex, uint32_t parent, struct rdata *rdata) { struct nl_cache *cls_cache; if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) return; nl_cache_foreach(cls_cache, handle_cls, rdata); nl_cache_free(cls_cache); } static void find_classes(uint32_t parent, struct rdata *rdata) { struct rtnl_class *filter; if (!(filter = rtnl_class_alloc())) return; rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); nl_cache_foreach_filter(class_cache, OBJ_CAST(filter), handle_class, rdata); rtnl_class_put(filter); } static void handle_qdisc(struct nl_object *obj, void *arg) { struct rtnl_tc *tc = (struct rtnl_tc *) obj; struct element *e; struct rdata *rdata = arg; struct rdata ndata = { .level = rdata->level + 1, }; if (!(e = handle_tc_obj(tc, "qdisc", rdata))) return; ndata.parent = e; find_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata); if (rtnl_tc_get_parent(tc) == TC_H_ROOT) { find_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT, &ndata); find_classes(TC_H_ROOT, &ndata); } find_classes(rtnl_tc_get_handle(tc), &ndata); } static void handle_tc(struct element *e, struct rtnl_link *link) { struct rtnl_qdisc *qdisc; int ifindex = rtnl_link_get_ifindex(link); struct rdata rdata = { .level = 1, .parent = e, }; if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0) return; qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT); if (qdisc) { handle_qdisc(OBJ_CAST(qdisc), &rdata); rtnl_qdisc_put(qdisc); } qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0); if (qdisc) { handle_qdisc(OBJ_CAST(qdisc), &rdata); rtnl_qdisc_put(qdisc); } qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS); if (qdisc) { handle_qdisc(OBJ_CAST(qdisc), &rdata); rtnl_qdisc_put(qdisc); } nl_cache_free(class_cache); } static void update_link_infos(struct element *e, struct rtnl_link *link) { char buf[64]; snprintf(buf, sizeof(buf), "%u", rtnl_link_get_mtu(link)); element_update_info(e, "MTU", buf); rtnl_link_flags2str(rtnl_link_get_flags(link), buf, sizeof(buf)); element_update_info(e, "Flags", buf); rtnl_link_operstate2str(rtnl_link_get_operstate(link), buf, sizeof(buf)); element_update_info(e, "Operstate", buf); snprintf(buf, sizeof(buf), "%u", rtnl_link_get_ifindex(link)); element_update_info(e, "IfIndex", buf); nl_addr2str(rtnl_link_get_addr(link), buf, sizeof(buf)); element_update_info(e, "Address", buf); nl_addr2str(rtnl_link_get_broadcast(link), buf, sizeof(buf)); element_update_info(e, "Broadcast", buf); rtnl_link_mode2str(rtnl_link_get_linkmode(link), buf, sizeof(buf)); element_update_info(e, "Mode", buf); snprintf(buf, sizeof(buf), "%u", rtnl_link_get_txqlen(link)); element_update_info(e, "TXQlen", buf); nl_af2str(rtnl_link_get_family(link), buf, sizeof(buf)); element_update_info(e, "Family", buf); element_update_info(e, "Alias", rtnl_link_get_ifalias(link) ? : ""); element_update_info(e, "Qdisc", rtnl_link_get_qdisc(link) ? : ""); if (rtnl_link_get_link(link)) { snprintf(buf, sizeof(buf), "%u", rtnl_link_get_link(link)); element_update_info(e, "SlaveOfIndex", buf); } } static void do_link(struct nl_object *obj, void *arg) { struct rtnl_link *link = (struct rtnl_link *) obj; struct element *e, *e_parent = NULL; int i, master_ifindex; if (!cfg_show_all && !(rtnl_link_get_flags(link) & IFF_UP)) { /* FIXME: delete element */ return; } /* Check if the interface is a slave of another interface */ if ((master_ifindex = rtnl_link_get_link(link))) { char parent[IFNAMSIZ+1]; rtnl_link_i2name(link_cache, master_ifindex, parent, sizeof(parent)); e_parent = element_lookup(grp, parent, master_ifindex, NULL, 0); } if (!(e = element_lookup(grp, rtnl_link_get_name(link), rtnl_link_get_ifindex(link), e_parent, ELEMENT_CREAT))) return; if (e->e_flags & ELEMENT_FLAG_CREATED) { if (e->e_parent) e->e_level = e->e_parent->e_level + 1; if (element_set_key_attr(e, "bytes", "packets") || element_set_usage_attr(e, "bytes")) BUG(); /* FIXME: Update link infos every 1s or so */ update_link_infos(e, link); e->e_flags &= ~ELEMENT_FLAG_CREATED; } for (i = 0; i < ARRAY_SIZE(link_attrs); i++) { struct attr_map *m = &link_attrs[i]; uint64_t c_rx = 0, c_tx = 0; int flags = 0; if (m->rxid >= 0) { c_rx = rtnl_link_get_stat(link, m->rxid); flags |= UPDATE_FLAG_RX; } if (m->txid >= 0) { c_tx = rtnl_link_get_stat(link, m->txid); flags |= UPDATE_FLAG_TX; } attr_update(e, m->attrid, c_rx, c_tx, flags); } if (!c_notc) handle_tc(e, link); element_notify_update(e, NULL); element_lifesign(e, 1); } static void netlink_read(void) { int err; if ((err = nl_cache_resync(sock, link_cache, NULL, NULL)) < 0) { fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err)); goto disable; } if ((err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) { fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err)); goto disable; } nl_cache_foreach(link_cache, do_link, NULL); return; disable: netlink_ops.m_flags &= ~BMON_MODULE_ENABLED; } static void netlink_shutdown(void) { nl_cache_free(link_cache); nl_cache_free(qdisc_cache); nl_socket_free(sock); }
static void env_dump(struct nl_object *obj, void *arg) { struct nl_dump_params *p = arg; struct rtnl_addr *addr = (struct rtnl_addr *) obj; struct nl_cache *link_cache; struct nl_addr *a; static int index = 0; char buf[128], pfx[32], *s; snprintf(pfx, sizeof(pfx), "ADDR%d", index++); nl_dump_line(p, "%s_FAMILY=%s\n", pfx, nl_af2str(rtnl_addr_get_family(addr), buf, sizeof(buf))); nl_dump_line(p, "%s_LOCAL=%s\n", pfx, nl_addr2str(rtnl_addr_get_local(addr), buf, sizeof(buf))); nl_dump_line(p, "%s_IFINDEX=%u\n", pfx, rtnl_addr_get_ifindex(addr)); link_cache = nl_cache_mngt_require_safe("route/link"); if (link_cache) nl_dump_line(p, "%s_IFNAME=%s\n", pfx, rtnl_link_i2name(link_cache, rtnl_addr_get_ifindex(addr), buf, sizeof(buf))); if ((a = rtnl_addr_get_peer(addr))) nl_dump_line(p, "%s_PEER=%s\n", pfx, nl_addr2str(a, buf, sizeof(buf))); if ((a = rtnl_addr_get_broadcast(addr))) nl_dump_line(p, "%s_BROADCAST=%s\n", pfx, nl_addr2str(a, buf, sizeof(buf))); nl_dump_line(p, "%s_SCOPE=%s\n", pfx, rtnl_scope2str(rtnl_addr_get_scope(addr), buf, sizeof(buf))); if ((s = rtnl_addr_get_label(addr))) nl_dump_line(p, "%s_LABEL=%s\n", pfx, s); rtnl_addr_flags2str(rtnl_addr_get_flags(addr), buf, sizeof(buf)); if (buf[0]) nl_dump_line(p, "%s_FLAGS=%s\n", pfx, buf); nl_dump_line(p, "%s_CACHEINFO_VALID=%u\n", pfx, rtnl_addr_get_valid_lifetime(addr)); if (link_cache) nl_cache_put(link_cache); #if 0 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; nl_dump_line(p, "ADDR_CACHEINFO_PREFERRED=%u\n", ci->aci_prefered); nl_dump_line(p, "ADDR_CACHEINFO_CREATED=%u\n", ci->aci_cstamp); nl_dump_line(p, "ADDR_CACHEINFO_LASTUPDATE=%u\n", ci->aci_tstamp); } #endif }
const std::string NetLinkManager::getInterface(const int ifindex) const { char buf[256]; rtnl_link_i2name(_link_cache, ifindex, (char*)&buf, sizeof buf); return std::string((char*)&buf); }
static int addr_dump_env(struct nl_object *obj, struct nl_dump_params *p) { struct rtnl_addr *addr = (struct rtnl_addr *) obj; struct nl_cache *link_cache; char buf[128]; int line = 0; dp_dump_line(p, line++, "ADDR_FAMILY=%s\n", nl_af2str(addr->a_family, buf, sizeof(buf))); if (addr->ce_mask & ADDR_ATTR_LOCAL) dp_dump_line(p, line++, "ADDR_LOCAL=%s\n", nl_addr2str(addr->a_local, buf, sizeof(buf))); if (addr->ce_mask & ADDR_ATTR_PEER) dp_dump_line(p, line++, "ADDR_PEER=%s\n", nl_addr2str(addr->a_peer, buf, sizeof(buf))); if (addr->ce_mask & ADDR_ATTR_BROADCAST) dp_dump_line(p, line++, "ADDR_BROADCAST=%s\n", nl_addr2str(addr->a_bcast, buf, sizeof(buf))); if (addr->ce_mask & ADDR_ATTR_ANYCAST) dp_dump_line(p, line++, "ADDR_ANYCAST=%s\n", nl_addr2str(addr->a_anycast, buf, sizeof(buf))); if (addr->ce_mask & ADDR_ATTR_MULTICAST) dp_dump_line(p, line++, "ADDR_MULTICAST=%s\n", nl_addr2str(addr->a_multicast, buf, sizeof(buf))); if (addr->ce_mask & ADDR_ATTR_PREFIXLEN) dp_dump_line(p, line++, "ADDR_PREFIXLEN=%u\n", addr->a_prefixlen); link_cache = nl_cache_mngt_require("route/link"); dp_dump_line(p, line++, "ADDR_IFINDEX=%u\n", addr->a_ifindex); if (link_cache) dp_dump_line(p, line++, "ADDR_IFNAME=%s\n", rtnl_link_i2name(link_cache, addr->a_ifindex, buf, sizeof(buf))); if (addr->ce_mask & ADDR_ATTR_SCOPE) dp_dump_line(p, line++, "ADDR_SCOPE=%s\n", rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); if (addr->ce_mask & ADDR_ATTR_LABEL) dp_dump_line(p, line++, "ADDR_LABEL=%s\n", addr->a_label); rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); if (buf[0]) dp_dump_line(p, line++, "ADDR_FLAGS=%s\n", buf); if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; dp_dump_line(p, line++, "ADDR_CACHEINFO_VALID=%s\n", ci->aci_valid == 0xFFFFFFFFU ? "forever" : nl_msec2str(ci->aci_valid * 1000, buf, sizeof(buf))); dp_dump_line(p, line++, "ADDR_CACHEINFO_PREFERED=%s\n", ci->aci_prefered == 0xFFFFFFFFU ? "forever" : nl_msec2str(ci->aci_prefered * 1000, buf, sizeof(buf))); dp_dump_line(p, line++, "ADDR_CACHEINFO_CREATED=%s\n", nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, buf, sizeof(buf))); dp_dump_line(p, line++, "ADDR_CACHEINFO_LASTUPDATE=%s\n", nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, buf, sizeof(buf))); } return line; }