static int rule_dump_xml(struct nl_object *obj, struct nl_dump_params *p) { struct rtnl_rule *rule = (struct rtnl_rule *) obj; char buf[128]; int line = 0; dp_dump_line(p, line++, "<rule>\n"); dp_dump_line(p, line++, " <priority>%u</priority>\n", rule->r_prio); dp_dump_line(p, line++, " <family>%s</family>\n", nl_af2str(rule->r_family, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_DST) dp_dump_line(p, line++, " <dst>%s</dst>\n", nl_addr2str(rule->r_dst, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_DST_LEN) dp_dump_line(p, line++, " <dstlen>%u</dstlen>\n", rule->r_dst_len); if (rule->ce_mask & RULE_ATTR_SRC) dp_dump_line(p, line++, " <src>%s</src>\n", nl_addr2str(rule->r_src, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_SRC_LEN) dp_dump_line(p, line++, " <srclen>%u</srclen>\n", rule->r_src_len); if (rule->ce_mask & RULE_ATTR_IIF) dp_dump_line(p, line++, " <iif>%s</iif>\n", rule->r_iif); if (rule->ce_mask & RULE_ATTR_TABLE) dp_dump_line(p, line++, " <table>%u</table>\n", rule->r_table); if (rule->ce_mask & RULE_ATTR_REALMS) dp_dump_line(p, line++, " <realms>%u</realms>\n", rule->r_realms); if (rule->ce_mask & RULE_ATTR_MARK) dp_dump_line(p, line++, " <mark>%" PRIx64 "</mark>\n", rule->r_mark); if (rule->ce_mask & RULE_ATTR_DSFIELD) dp_dump_line(p, line++, " <dsfield>%u</dsfield>\n", rule->r_dsfield); if (rule->ce_mask & RULE_ATTR_TYPE) dp_dump_line(p, line++, "<type>%s</type>\n", nl_rtntype2str(rule->r_type, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_SRCMAP) dp_dump_line(p, line++, "<srcmap>%s</srcmap>\n", nl_addr2str(rule->r_srcmap, buf, sizeof(buf))); dp_dump_line(p, line++, "</rule>\n"); return line; }
static void idiag_msg_dump_details(struct nl_object *a, struct nl_dump_params *p) { struct idiagnl_msg *msg = (struct idiagnl_msg *) a; char buf[64], buf2[64]; nl_dump(p, "\nfamily: %s\n", nl_af2str(msg->idiag_family, buf, sizeof(buf))); nl_dump(p, "state: %s\n", idiagnl_state2str(msg->idiag_state, buf, sizeof(buf))); nl_dump(p, "timer (%s, %s, retransmits: %d)\n", idiagnl_timer2str(msg->idiag_timer, buf, sizeof(buf)), nl_msec2str(msg->idiag_expires, buf2, sizeof(buf2)), msg->idiag_retrans); nl_dump(p, "source: %s:%d\n", nl_addr2str(msg->idiag_src, buf, sizeof(buf)), ntohs(msg->idiag_sport)); nl_dump(p, "destination: %s:%d\n", nl_addr2str(msg->idiag_dst, buf, sizeof(buf)), ntohs(msg->idiag_dport)); nl_dump(p, "ifindex: %d\n", msg->idiag_ifindex); nl_dump(p, "rqueue: %-6d wqueue: %-6d\n", msg->idiag_rqueue, msg->idiag_wqueue); nl_dump(p, "uid %d\n", msg->idiag_uid); nl_dump(p, "inode %d\n", msg->idiag_inode); if (msg->idiag_shutdown) { nl_dump(p, "socket shutdown: %s\n", idiagnl_shutdown2str(msg->idiag_shutdown, buf, sizeof(buf))); } nl_dump(p, "tos: 0x%x\n", msg->idiag_tos); nl_dump(p, "traffic class: %d\n", msg->idiag_tclass); nl_dump(p, "congestion algorithm: %s\n", msg->idiag_cong); }
static int rule_dump_env(struct nl_object *obj, struct nl_dump_params *p) { struct rtnl_rule *rule = (struct rtnl_rule *) obj; char buf[128]; int line = 0; dp_dump_line(p, line++, "RULE_PRIORITY=%u\n", rule->r_prio); dp_dump_line(p, line++, "RULE_FAMILY=%s\n", nl_af2str(rule->r_family, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_DST) dp_dump_line(p, line++, "RULE_DST=%s\n", nl_addr2str(rule->r_dst, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_DST_LEN) dp_dump_line(p, line++, "RULE_DSTLEN=%u\n", rule->r_dst_len); if (rule->ce_mask & RULE_ATTR_SRC) dp_dump_line(p, line++, "RULE_SRC=%s\n", nl_addr2str(rule->r_src, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_SRC_LEN) dp_dump_line(p, line++, "RULE_SRCLEN=%u\n", rule->r_src_len); if (rule->ce_mask & RULE_ATTR_IIF) dp_dump_line(p, line++, "RULE_IIF=%s\n", rule->r_iif); if (rule->ce_mask & RULE_ATTR_TABLE) dp_dump_line(p, line++, "RULE_TABLE=%u\n", rule->r_table); if (rule->ce_mask & RULE_ATTR_REALMS) dp_dump_line(p, line++, "RULE_REALM=%u\n", rule->r_realms); if (rule->ce_mask & RULE_ATTR_MARK) dp_dump_line(p, line++, "RULE_MARK=0x%" PRIx64 "\n", rule->r_mark); if (rule->ce_mask & RULE_ATTR_DSFIELD) dp_dump_line(p, line++, "RULE_DSFIELD=%u\n", rule->r_dsfield); if (rule->ce_mask & RULE_ATTR_TYPE) dp_dump_line(p, line++, "RULE_TYPE=%s\n", nl_rtntype2str(rule->r_type, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_SRCMAP) dp_dump_line(p, line++, "RULE_SRCMAP=%s\n", nl_addr2str(rule->r_srcmap, buf, sizeof(buf))); return line; }
static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p) { struct nfnl_ct *ct = (struct nfnl_ct *) a; char buf[64]; int fp = 0; ct_dump_line(a, p); nl_dump(p, " id 0x%x ", ct->ct_id); nl_dump_line(p, "family %s ", nl_af2str(ct->ct_family, buf, sizeof(buf))); if (nfnl_ct_test_use(ct)) nl_dump(p, "refcnt %u ", nfnl_ct_get_use(ct)); if (nfnl_ct_test_timeout(ct)) { uint64_t timeout_ms = nfnl_ct_get_timeout(ct) * 1000UL; nl_dump(p, "timeout %s ", nl_msec2str(timeout_ms, buf, sizeof(buf))); } if (ct->ct_status) nl_dump(p, "<"); #define PRINT_FLAG(str) \ { nl_dump(p, "%s%s", fp++ ? "," : "", (str)); } if (ct->ct_status & IPS_EXPECTED) PRINT_FLAG("EXPECTED"); if (!(ct->ct_status & IPS_SEEN_REPLY)) PRINT_FLAG("NOREPLY"); if (ct->ct_status & IPS_ASSURED) PRINT_FLAG("ASSURED"); if (!(ct->ct_status & IPS_CONFIRMED)) PRINT_FLAG("NOTSENT"); if (ct->ct_status & IPS_SRC_NAT) PRINT_FLAG("SNAT"); if (ct->ct_status & IPS_DST_NAT) PRINT_FLAG("DNAT"); if (ct->ct_status & IPS_SEQ_ADJUST) PRINT_FLAG("SEQADJUST"); if (!(ct->ct_status & IPS_SRC_NAT_DONE)) PRINT_FLAG("SNAT_INIT"); if (!(ct->ct_status & IPS_DST_NAT_DONE)) PRINT_FLAG("DNAT_INIT"); if (ct->ct_status & IPS_DYING) PRINT_FLAG("DYING"); if (ct->ct_status & IPS_FIXED_TIMEOUT) PRINT_FLAG("FIXED_TIMEOUT"); #undef PRINT_FLAG if (ct->ct_status) nl_dump(p, ">"); nl_dump(p, "\n"); }
static void idiag_msg_dump_line(struct nl_object *a, struct nl_dump_params *p) { struct idiagnl_msg *msg = (struct idiagnl_msg *) a; char buf[64] = { 0 }; nl_dump_line(p, "family: %s ", nl_af2str(msg->idiag_family, buf, sizeof(buf))); nl_dump(p, "src: %s:%d ", nl_addr2str(msg->idiag_src, buf, sizeof(buf)), ntohs(msg->idiag_sport)); nl_dump(p, "dst: %s:%d ", nl_addr2str(msg->idiag_dst, buf, sizeof(buf)), ntohs(msg->idiag_dport)); nl_dump(p, "iif: %d ", msg->idiag_ifindex); nl_dump(p, "\n"); }
static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p) { struct nfnl_exp *exp = (struct nfnl_exp *) a; char buf[64]; int fp = 0; exp_dump_line(a, p); nl_dump(p, " id 0x%x ", exp->exp_id); nl_dump_line(p, "family %s ", nl_af2str(exp->exp_family, buf, sizeof(buf))); if (nfnl_exp_test_timeout(exp)) { uint64_t timeout_ms = nfnl_exp_get_timeout(exp) * 1000UL; nl_dump(p, "timeout %s ", nl_msec2str(timeout_ms, buf, sizeof(buf))); } if (nfnl_exp_test_helper_name(exp)) nl_dump(p, "helper %s ", exp->exp_helper_name); if (nfnl_exp_test_fn(exp)) nl_dump(p, "fn %s ", exp->exp_fn); if (nfnl_exp_test_class(exp)) nl_dump(p, "class %u ", nfnl_exp_get_class(exp)); if (nfnl_exp_test_zone(exp)) nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp)); if (nfnl_exp_test_flags(exp)) nl_dump(p, "<"); #define PRINT_FLAG(str) \ { nl_dump(p, "%s%s", fp++ ? "," : "", (str)); } if (exp->exp_flags & NF_CT_EXPECT_PERMANENT) PRINT_FLAG("PERMANENT"); if (exp->exp_flags & NF_CT_EXPECT_INACTIVE) PRINT_FLAG("INACTIVE"); if (exp->exp_flags & NF_CT_EXPECT_USERSPACE) PRINT_FLAG("USERSPACE"); #undef PRINT_FLAG if (nfnl_exp_test_flags(exp)) nl_dump(p, ">"); nl_dump(p, "\n"); }
static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p) { struct rtnl_rule *r = (struct rtnl_rule *) o; char buf[128]; nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0); nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf))); if (r->ce_mask & RULE_ATTR_SRC) nl_dump(p, "from %s ", nl_addr2str(r->r_src, buf, sizeof(buf))); if (r->ce_mask & RULE_ATTR_DST) nl_dump(p, "to %s ", nl_addr2str(r->r_dst, buf, sizeof(buf))); if (r->ce_mask & RULE_ATTR_DSFIELD) nl_dump(p, "tos %u ", r->r_dsfield); if (r->ce_mask & (RULE_ATTR_MARK | RULE_ATTR_MASK)) nl_dump(p, "mark %#x/%#x", r->r_mark, r->r_mask); if (r->ce_mask & RULE_ATTR_IIFNAME) nl_dump(p, "iif %s ", r->r_iifname); if (r->ce_mask & RULE_ATTR_OIFNAME) nl_dump(p, "oif %s ", r->r_oifname); if (r->ce_mask & RULE_ATTR_TABLE) nl_dump(p, "lookup %s ", rtnl_route_table2str(r->r_table, buf, sizeof(buf))); if (r->ce_mask & RULE_ATTR_FLOW) nl_dump(p, "flow %s ", rtnl_realms2str(r->r_flow, buf, sizeof(buf))); if (r->ce_mask & RULE_ATTR_GOTO) nl_dump(p, "goto %u ", r->r_goto); if (r->ce_mask & RULE_ATTR_ACTION) nl_dump(p, "action %s", nl_rtntype2str(r->r_action, buf, sizeof(buf))); nl_dump(p, "\n"); }
static int rule_dump_full(struct nl_object *obj, struct nl_dump_params *p) { struct rtnl_rule *rule = (struct rtnl_rule *) obj; char buf[128]; int line; line = rule_dump_brief(obj, p); dp_dump_line(p, line++, " family %s", nl_af2str(rule->r_family, buf, sizeof(buf))); if (rule->ce_mask & RULE_ATTR_SRCMAP) dp_dump(p, " srcmap %s", nl_addr2str(rule->r_srcmap, buf, sizeof(buf))); dp_dump(p, "\n"); return line; }
static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p) { struct rtnl_rule *r = (struct rtnl_rule *) o; char buf[128]; nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0); nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf))); if (r->ce_mask & RULE_ATTR_SRC) nl_dump(p, "from %s ", nl_addr2str(r->r_src, buf, sizeof(buf))); else if (r->ce_mask & RULE_ATTR_SRC_LEN && r->r_src_len) nl_dump(p, "from 0/%d ", r->r_src_len); if (r->ce_mask & RULE_ATTR_DST) nl_dump(p, "to %s ", nl_addr2str(r->r_dst, buf, sizeof(buf))); else if (r->ce_mask & RULE_ATTR_DST_LEN && r->r_dst_len) nl_dump(p, "to 0/%d ", r->r_dst_len); if (r->ce_mask & RULE_ATTR_DSFIELD && r->r_dsfield) nl_dump(p, "tos %d ", r->r_dsfield); if (r->ce_mask & RULE_ATTR_MARK) nl_dump(p, "mark %" PRIx64 , r->r_mark); if (r->ce_mask & RULE_ATTR_IIF) nl_dump(p, "iif %s ", r->r_iif); if (r->ce_mask & RULE_ATTR_TABLE) nl_dump(p, "lookup %s ", rtnl_route_table2str(r->r_table, buf, sizeof(buf))); if (r->ce_mask & RULE_ATTR_REALMS) nl_dump(p, "realms %s ", rtnl_realms2str(r->r_realms, buf, sizeof(buf))); nl_dump(p, "action %s\n", nl_rtntype2str(r->r_type, buf, sizeof(buf))); }
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; }
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 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; }
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 }