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 int rtnl_linkinfo_parse(struct rtattr *rta) { int index = -1; const char *kind; struct rtattr *linkinfo[IFLA_INFO_MAX]; struct rtattr *bond[IFLA_BOND_MAX]; if (rtnl_nested_rtattr_parse(linkinfo, IFLA_INFO_MAX, rta) < 0) return -1; if (linkinfo[IFLA_INFO_KIND]) { kind = rta_getattr_str(linkinfo[IFLA_INFO_KIND]); if (kind && !strncmp(kind, "bond", 4) && linkinfo[IFLA_INFO_DATA]) { if (rtnl_nested_rtattr_parse(bond, IFLA_BOND_MAX, linkinfo[IFLA_INFO_DATA]) < 0) return -1; if (bond[IFLA_BOND_ACTIVE_SLAVE]) { index = rta_getattr_u32(bond[IFLA_BOND_ACTIVE_SLAVE]); } } } return index; }
static void print_queuelen(FILE *f, struct rtattr *tb[IFLA_MAX + 1]) { int qlen; if (tb[IFLA_TXQLEN]) qlen = *(int *)RTA_DATA(tb[IFLA_TXQLEN]); else { struct ifreq ifr; int s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) return; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, rta_getattr_str(tb[IFLA_IFNAME])); if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) { fprintf(f, "ioctl(SIOCGIFTXQLEN) failed: %s\n", strerror(errno)); close(s); return; } close(s); qlen = ifr.ifr_qlen; } if (qlen) fprintf(f, "qlen %d", qlen); }
static int bpf_print_opt(struct action_util *au, FILE *f, struct rtattr *arg) { struct rtattr *tb[TCA_ACT_BPF_MAX + 1]; struct tc_act_bpf *parm; SPRINT_BUF(action_buf); if (arg == NULL) return -1; parse_rtattr_nested(tb, TCA_ACT_BPF_MAX, arg); if (!tb[TCA_ACT_BPF_PARMS]) { fprintf(f, "[NULL bpf parameters]"); return -1; } parm = RTA_DATA(tb[TCA_ACT_BPF_PARMS]); fprintf(f, "bpf "); if (tb[TCA_ACT_BPF_NAME]) fprintf(f, "%s ", rta_getattr_str(tb[TCA_ACT_BPF_NAME])); else if (tb[TCA_ACT_BPF_FD]) fprintf(f, "pfd %u ", rta_getattr_u32(tb[TCA_ACT_BPF_FD])); if (tb[TCA_ACT_BPF_OPS] && tb[TCA_ACT_BPF_OPS_LEN]) { bpf_print_ops(f, tb[TCA_ACT_BPF_OPS], rta_getattr_u16(tb[TCA_ACT_BPF_OPS_LEN])); fprintf(f, " "); } fprintf(f, "default-action %s\n", action_n2a(parm->action, action_buf, sizeof(action_buf))); fprintf(f, "\tindex %d ref %d bind %d", parm->index, parm->refcnt, parm->bindcnt); if (show_stats) { if (tb[TCA_ACT_BPF_TM]) { struct tcf_t *tm = RTA_DATA(tb[TCA_ACT_BPF_TM]); print_tm(f, tm); } } fprintf(f, "\n "); return 0; }
const char *get_ifname_rta(int ifindex, const struct rtattr *rta) { const char *name; if (rta) { name = rta_getattr_str(rta); } else { fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifindex); name = ll_idx_n2a(ifindex); } if (check_ifname(name)) return NULL; return name; }
static int fw_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle) { struct rtattr *tb[TCA_FW_MAX+1]; if (opt == NULL) return 0; parse_rtattr_nested(tb, TCA_FW_MAX, opt); if (handle || tb[TCA_FW_MASK]) { __u32 mark = 0, mask = 0; if(handle) mark = handle; if(tb[TCA_FW_MASK] && (mask = rta_getattr_u32(tb[TCA_FW_MASK])) != 0xFFFFFFFF) fprintf(f, "handle 0x%x/0x%x ", mark, mask); else fprintf(f, "handle 0x%x ", handle); } if (tb[TCA_FW_CLASSID]) { SPRINT_BUF(b1); fprintf(f, "classid %s ", sprint_tc_classid(rta_getattr_u32(tb[TCA_FW_CLASSID]), b1)); } if (tb[TCA_FW_POLICE]) tc_print_police(f, tb[TCA_FW_POLICE]); if (tb[TCA_FW_INDEV]) { struct rtattr *idev = tb[TCA_FW_INDEV]; fprintf(f, "input dev %s ",rta_getattr_str(idev)); } if (tb[TCA_FW_ACT]) { fprintf(f, "\n"); tc_print_action(f, tb[TCA_FW_ACT]); } return 0; }
static int get_response(struct nlmsghdr *n, void *arg) { struct genlmsghdr *ghdr; struct l2tp_data *data = arg; struct l2tp_parm *p = &data->config; struct rtattr *attrs[L2TP_ATTR_MAX + 1]; struct rtattr *nla_stats; int len; /* Validate message and parse attributes */ if (n->nlmsg_type == NLMSG_ERROR) return -EBADMSG; ghdr = NLMSG_DATA(n); len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ghdr)); if (len < 0) return -1; parse_rtattr(attrs, L2TP_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len); if (attrs[L2TP_ATTR_PW_TYPE]) p->pw_type = rta_getattr_u16(attrs[L2TP_ATTR_PW_TYPE]); if (attrs[L2TP_ATTR_ENCAP_TYPE]) p->encap = rta_getattr_u16(attrs[L2TP_ATTR_ENCAP_TYPE]); if (attrs[L2TP_ATTR_OFFSET]) p->offset = rta_getattr_u16(attrs[L2TP_ATTR_OFFSET]); if (attrs[L2TP_ATTR_DATA_SEQ]) p->data_seq = rta_getattr_u16(attrs[L2TP_ATTR_DATA_SEQ]); if (attrs[L2TP_ATTR_CONN_ID]) p->tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_CONN_ID]); if (attrs[L2TP_ATTR_PEER_CONN_ID]) p->peer_tunnel_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_CONN_ID]); if (attrs[L2TP_ATTR_SESSION_ID]) p->session_id = rta_getattr_u32(attrs[L2TP_ATTR_SESSION_ID]); if (attrs[L2TP_ATTR_PEER_SESSION_ID]) p->peer_session_id = rta_getattr_u32(attrs[L2TP_ATTR_PEER_SESSION_ID]); if (attrs[L2TP_ATTR_L2SPEC_TYPE]) p->l2spec_type = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_TYPE]); if (attrs[L2TP_ATTR_L2SPEC_LEN]) p->l2spec_len = rta_getattr_u8(attrs[L2TP_ATTR_L2SPEC_LEN]); p->udp_csum = !!attrs[L2TP_ATTR_UDP_CSUM]; if (attrs[L2TP_ATTR_COOKIE]) memcpy(p->cookie, RTA_DATA(attrs[L2TP_ATTR_COOKIE]), p->cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_COOKIE])); if (attrs[L2TP_ATTR_PEER_COOKIE]) memcpy(p->peer_cookie, RTA_DATA(attrs[L2TP_ATTR_PEER_COOKIE]), p->peer_cookie_len = RTA_PAYLOAD(attrs[L2TP_ATTR_PEER_COOKIE])); p->recv_seq = !!attrs[L2TP_ATTR_RECV_SEQ]; p->send_seq = !!attrs[L2TP_ATTR_SEND_SEQ]; if (attrs[L2TP_ATTR_RECV_TIMEOUT]) p->reorder_timeout = rta_getattr_u64(attrs[L2TP_ATTR_RECV_TIMEOUT]); if (attrs[L2TP_ATTR_IP_SADDR]) { p->local_ip.family = AF_INET; p->local_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_SADDR]); p->local_ip.bytelen = 4; p->local_ip.bitlen = -1; } if (attrs[L2TP_ATTR_IP_DADDR]) { p->peer_ip.family = AF_INET; p->peer_ip.data[0] = rta_getattr_u32(attrs[L2TP_ATTR_IP_DADDR]); p->peer_ip.bytelen = 4; p->peer_ip.bitlen = -1; } if (attrs[L2TP_ATTR_IP6_SADDR]) { p->local_ip.family = AF_INET6; memcpy(&p->local_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_SADDR]), p->local_ip.bytelen = 16); p->local_ip.bitlen = -1; } if (attrs[L2TP_ATTR_IP6_DADDR]) { p->peer_ip.family = AF_INET6; memcpy(&p->peer_ip.data, RTA_DATA(attrs[L2TP_ATTR_IP6_DADDR]), p->peer_ip.bytelen = 16); p->peer_ip.bitlen = -1; } if (attrs[L2TP_ATTR_UDP_SPORT]) p->local_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_SPORT]); if (attrs[L2TP_ATTR_UDP_DPORT]) p->peer_udp_port = rta_getattr_u16(attrs[L2TP_ATTR_UDP_DPORT]); if (attrs[L2TP_ATTR_MTU]) p->mtu = rta_getattr_u16(attrs[L2TP_ATTR_MTU]); if (attrs[L2TP_ATTR_IFNAME]) p->ifname = rta_getattr_str(attrs[L2TP_ATTR_IFNAME]); nla_stats = attrs[L2TP_ATTR_STATS]; if (nla_stats) { struct rtattr *tb[L2TP_ATTR_STATS_MAX + 1]; parse_rtattr_nested(tb, L2TP_ATTR_STATS_MAX, nla_stats); if (tb[L2TP_ATTR_TX_PACKETS]) data->stats.data_tx_packets = rta_getattr_u64(tb[L2TP_ATTR_TX_PACKETS]); if (tb[L2TP_ATTR_TX_BYTES]) data->stats.data_tx_bytes = rta_getattr_u64(tb[L2TP_ATTR_TX_BYTES]); if (tb[L2TP_ATTR_TX_ERRORS]) data->stats.data_tx_errors = rta_getattr_u64(tb[L2TP_ATTR_TX_ERRORS]); if (tb[L2TP_ATTR_RX_PACKETS]) data->stats.data_rx_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_PACKETS]); if (tb[L2TP_ATTR_RX_BYTES]) data->stats.data_rx_bytes = rta_getattr_u64(tb[L2TP_ATTR_RX_BYTES]); if (tb[L2TP_ATTR_RX_ERRORS]) data->stats.data_rx_errors = rta_getattr_u64(tb[L2TP_ATTR_RX_ERRORS]); if (tb[L2TP_ATTR_RX_SEQ_DISCARDS]) data->stats.data_rx_oos_discards = rta_getattr_u64(tb[L2TP_ATTR_RX_SEQ_DISCARDS]); if (tb[L2TP_ATTR_RX_OOS_PACKETS]) data->stats.data_rx_oos_packets = rta_getattr_u64(tb[L2TP_ATTR_RX_OOS_PACKETS]); } return 0; }
int print_link(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct ndmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *ifattr[IFLA_MAX+1]; struct rtattr *ifinfo[IFLA_INFO_MAX+1]; struct rtattr *ifgreo[IFLA_GRE_MAX+1]; const char *ifname; const char *kind; int link=0; int tunid=0; struct in_addr sip,dip; uint8_t ttl=0,tos=0; struct ifinfomsg *ifi; sip.s_addr=dip.s_addr=htonl(0); if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) { fprintf(stderr, "Not RTM_xxxLINK: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } ifi=(void *)r; parse_rtattr(ifattr, IFLA_MAX, IFLA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); if (ifattr[IFLA_IFNAME]) ifname=rta_getattr_str(ifattr[IFLA_IFNAME]); else ifname=""; if (ifattr[IFLA_LINKINFO]) parse_rtattr(ifinfo, IFLA_INFO_MAX, (void *)rta_getattr_str(ifattr[IFLA_LINKINFO]), ifattr[IFLA_LINKINFO]->rta_len); else memset(ifinfo,0,sizeof ifinfo); if (ifinfo[IFLA_INFO_KIND]) kind=rta_getattr_str(ifinfo[IFLA_INFO_KIND]); else kind=""; if (!strcmp(kind,"eoip") && ifinfo[IFLA_INFO_DATA]) { char ts[IFNAMSIZ],td[IFNAMSIZ]; parse_rtattr(ifgreo, IFLA_GRE_MAX, (void *)rta_getattr_str(ifinfo[IFLA_INFO_DATA]), ifinfo[IFLA_INFO_DATA]->rta_len); if (ifgreo[IFLA_GRE_LINK]) link=rta_getattr_u32(ifgreo[IFLA_GRE_LINK]); if (ifgreo[IFLA_GRE_TOS]) tos=rta_getattr_u8(ifgreo[IFLA_GRE_TOS]); if (ifgreo[IFLA_GRE_TTL]) ttl=rta_getattr_u8(ifgreo[IFLA_GRE_TTL]); if (ifgreo[IFLA_GRE_LOCAL]) sip.s_addr=rta_getattr_u32(ifgreo[IFLA_GRE_LOCAL]); if (ifgreo[IFLA_GRE_REMOTE]) dip.s_addr=rta_getattr_u32(ifgreo[IFLA_GRE_REMOTE]); if (ifgreo[IFLA_GRE_IKEY]) tunid=rta_getattr_u32(ifgreo[IFLA_GRE_IKEY]); strcpy(ts,inet_ntoa(sip)); strcpy(td,inet_ntoa(dip)); printf("%d: %s@%d: link/%s %s remote %s tunnel-id %d ttl %d tos %d\n",ifi->ifi_index,ifname,link,kind,ts,td,tunid,ttl,tos); } return 0; }
int print_qdisc(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE *)arg; struct tcmsg *t = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[TCA_MAX+1]; struct qdisc_util *q; char abuf[256]; if (n->nlmsg_type != RTM_NEWQDISC && n->nlmsg_type != RTM_DELQDISC) { fprintf(stderr, "Not a qdisc\n"); return 0; } len -= NLMSG_LENGTH(sizeof(*t)); if (len < 0) { fprintf(stderr, "Wrong len %d\n", len); return -1; } if (filter_ifindex && filter_ifindex != t->tcm_ifindex) return 0; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len); if (tb[TCA_KIND] == NULL) { fprintf(stderr, "print_qdisc: NULL kind\n"); return -1; } if (n->nlmsg_type == RTM_DELQDISC) fprintf(fp, "deleted "); fprintf(fp, "qdisc %s %x: ", rta_getattr_str(tb[TCA_KIND]), t->tcm_handle>>16); if (filter_ifindex == 0) fprintf(fp, "dev %s ", ll_index_to_name(t->tcm_ifindex)); if (t->tcm_parent == TC_H_ROOT) fprintf(fp, "root "); else if (t->tcm_parent) { print_tc_classid(abuf, sizeof(abuf), t->tcm_parent); fprintf(fp, "parent %s ", abuf); } if (t->tcm_info != 1) { fprintf(fp, "refcnt %d ", t->tcm_info); } /* pfifo_fast is generic enough to warrant the hardcoding --JHS */ if (0 == strcmp("pfifo_fast", RTA_DATA(tb[TCA_KIND]))) q = get_qdisc_kind("prio"); else q = get_qdisc_kind(RTA_DATA(tb[TCA_KIND])); if (tb[TCA_OPTIONS]) { if (q) q->print_qopt(q, fp, tb[TCA_OPTIONS]); else fprintf(fp, "[cannot parse qdisc parameters]"); } fprintf(fp, "\n"); if (show_details && tb[TCA_STAB]) { print_size_table(fp, " ", tb[TCA_STAB]); fprintf(fp, "\n"); } if (show_stats) { struct rtattr *xstats = NULL; if (tb[TCA_STATS] || tb[TCA_STATS2] || tb[TCA_XSTATS]) { print_tcstats_attr(fp, tb, " ", &xstats); fprintf(fp, "\n"); } if (q && xstats && q->print_xstats) { q->print_xstats(q, fp, xstats); fprintf(fp, "\n"); } } fflush(fp); return 0; }
static int netl_handler(struct netl_handle *h, pktj_unused(struct sockaddr_nl *nladdr), struct nlmsghdr *hdr, void *args) { int len = hdr->nlmsg_len; switch (hdr->nlmsg_type) { // TODO RTM_SETLINK case RTM_NEWLINK: case RTM_DELLINK: { struct ifinfomsg *ifi = NLMSG_DATA(hdr); struct rtattr *rta_tb[IFLA_MAX + 1]; struct ether_addr lladdr; int ifid = ifi->ifi_index; int mtu = -1; const char *ifname = ""; uint16_t vlanid = 0; oper_state_t state = LINK_UNKNOWN; link_action_t action = LINK_ADD; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) { // incomplete message return -1; } parse_rtattr_flags(rta_tb, IFLA_MAX, IFLA_RTA(ifi), len, 0); if (ifi->ifi_type != ARPHRD_ETHER) return 0; // This is not ethernet if (rta_tb[IFLA_IFNAME] == NULL) return -1; // There should be a name, this is a bug if (hdr->nlmsg_type == RTM_DELLINK) action = LINK_DELETE; if (rta_tb[IFLA_MTU]) mtu = *(int *) RTA_DATA(rta_tb[IFLA_MTU]); if (rta_tb[IFLA_IFNAME]) ifname = rta_getattr_str(rta_tb[IFLA_IFNAME]); if (rta_tb[IFLA_OPERSTATE]) state = rta_getattr_u8(rta_tb[IFLA_OPERSTATE]); if (rta_tb[IFLA_ADDRESS]) memcpy(&lladdr.addr_bytes, RTA_DATA(rta_tb[IFLA_ADDRESS]), sizeof(lladdr.addr_bytes)); if (rta_tb[IFLA_LINKINFO]) { struct rtattr *linkinfo[IFLA_INFO_MAX + 1]; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, rta_tb[IFLA_LINKINFO]); if (linkinfo[IFLA_INFO_KIND]) { char *kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); //XXX only handle vlan type for now if (!strcmp(kind, "vlan")) { vlanid = get_vlan_id(linkinfo); } else { //TODO receive an IF without vlan id } } } if (h->cb.link != NULL) { h->cb.link(action, ifid, &lladdr, mtu, ifname, state, vlanid, args); } } break; } if (hdr->nlmsg_type == RTM_NEWADDR || hdr->nlmsg_type == RTM_DELADDR) { //struct if_rtattrs attrs; struct rtattr *rta_tb[IFA_MAX + 1]; struct ifaddrmsg *ifa = NLMSG_DATA(hdr); //unsigned int ifa_flags; unsigned char buf_addr[sizeof(struct in6_addr)]; addr_action_t action; len -= NLMSG_LENGTH(sizeof(*ifa)); if (len < 0) { // incomplete message return -1; } if (hdr->nlmsg_type == RTM_NEWADDR) action = ADDR_ADD; else if (hdr->nlmsg_type == RTM_DELADDR) action = ADDR_DELETE; else return -1; parse_rtattr_flags(rta_tb, IFA_MAX, IFA_RTA(ifa), len, 0); //ifa_flags = get_ifa_flags(ifa, rta_tb[IFA_FLAGS]); if (!rta_tb[IFA_LOCAL]) rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; if (!rta_tb[IFA_ADDRESS]) rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL]; if (rta_tb[IFA_LOCAL]) { //we may optimize by passing directly RTA_DATA(rta_tb[IFA_LOCAL]) to the cb memcpy(buf_addr, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL])); } switch (ifa->ifa_family) { case AF_INET: if (h->cb.addr4 != NULL) { h->cb.addr4(action, ifa->ifa_index, (struct in_addr *) buf_addr, ifa->ifa_prefixlen, args); } break; case AF_INET6: if (h->cb.addr6 != NULL) { h->cb.addr6(action, ifa->ifa_index, (struct in6_addr *) buf_addr, ifa->ifa_prefixlen, args); } break; default: //only handling IP return -1; } } if (hdr->nlmsg_type == RTM_NEWROUTE || hdr->nlmsg_type == RTM_DELROUTE) { struct rtattr *tb[RTA_MAX + 1]; struct rtmsg *r = NLMSG_DATA(hdr); //__u32 table; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) { // incomplete message return -1; } if (r->rtm_family != RTNL_FAMILY_IPMR && r->rtm_family != RTNL_FAMILY_IP6MR) { // This is an unicast route, no interest for multicast route_action_t action; if (hdr->nlmsg_type == RTM_NEWROUTE) action = ROUTE_ADD; else action = ROUTE_DELETE; parse_rtattr_flags(tb, RTA_MAX, RTM_RTA(r), len, 0); //table = rtm_get_table(r, tb); switch(r->rtm_type) { case RTN_UNICAST: if (!tb[RTA_DST]) return 0; if (!tb[RTA_GATEWAY]) return 0; case RTN_BLACKHOLE: break; default: return 0; } switch (r->rtm_family) { case AF_INET: if (h->cb.route4 != NULL) { h->cb.route4(r, action, RTA_DATA(tb[RTA_DST]), r->rtm_dst_len, RTA_DATA(tb[RTA_GATEWAY]), r->rtm_type, args); } break; case AF_INET6: if (h->cb.route6 != NULL) { h->cb.route6(r, action, RTA_DATA(tb[RTA_DST]), r->rtm_dst_len, RTA_DATA(tb[RTA_GATEWAY]), r->rtm_type, args); } break; default: //only handling IP return 0; } } } if (hdr->nlmsg_type == RTM_NEWNEIGH || hdr->nlmsg_type == RTM_DELNEIGH) { struct ndmsg *neighbor = NLMSG_DATA(hdr); struct rtattr *tb[NDA_MAX + 1]; uint16_t vlanid = 0; len -= NLMSG_LENGTH(sizeof(*neighbor)); if (len < 0) { // incomplete message return -1; } // Ignore non-ip if (neighbor->ndm_family != AF_INET && neighbor->ndm_family != AF_INET6) return 0; parse_rtattr_flags(tb, NDA_MAX, RTM_RTA(neighbor), len, 0); neighbor_action_t action; if (hdr->nlmsg_type == RTM_NEWNEIGH) action = NEIGHBOR_ADD; else action = NEIGHBOR_DELETE; if (tb[NDA_VLAN]) vlanid = rta_getattr_u16(tb[NDA_VLAN]); switch (neighbor->ndm_family) { case AF_INET: if (h->cb.neighbor4 != NULL) { if (tb[NDA_LLADDR]) { h->cb.neighbor4(action, neighbor->ndm_ifindex, RTA_DATA(tb[NDA_DST]), RTA_DATA(tb[NDA_LLADDR]), neighbor->ndm_state, vlanid, args); } else { h->cb.neighbor4(action, neighbor->ndm_ifindex, RTA_DATA(tb[NDA_DST]), &invalid_mac, neighbor->ndm_state, vlanid, args); } } break; case AF_INET6: if (h->cb.neighbor6 != NULL) { if (tb[NDA_LLADDR]) { h->cb.neighbor6(action, neighbor->ndm_ifindex, RTA_DATA(tb[NDA_DST]), RTA_DATA(tb[NDA_LLADDR]), neighbor->ndm_state, vlanid, args); } else { h->cb.neighbor6(action, neighbor->ndm_ifindex, RTA_DATA(tb[NDA_DST]), &invalid_mac, neighbor->ndm_state, vlanid, args); } } break; default: //only handling IP return 0; } } return 0; }
int print_linkinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct ifinfomsg *ifi = NLMSG_DATA(n); struct rtattr * tb[IFLA_MAX+1]; int len = n->nlmsg_len; unsigned m_flag = 0; if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) return 0; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) return -1; if (filter.ifindex && ifi->ifi_index != filter.ifindex) return 0; if (filter.up && !(ifi->ifi_flags&IFF_UP)) return 0; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL) { fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index); } if (filter.label && (!filter.family || filter.family == AF_PACKET) && fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)) return 0; if (tb[IFLA_GROUP]) { int group = *(int*)RTA_DATA(tb[IFLA_GROUP]); if (filter.group != -1 && group != filter.group) return -1; } if (tb[IFLA_MASTER]) { int master = *(int*)RTA_DATA(tb[IFLA_MASTER]); if (filter.master > 0 && master != filter.master) return -1; } else if (filter.master > 0) return -1; if (filter.kind) { if (tb[IFLA_LINKINFO]) { char *kind = parse_link_kind(tb[IFLA_LINKINFO]); if (strcmp(kind, filter.kind)) return -1; } else { return -1; } } if (n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); fprintf(fp, "%d: ", ifi->ifi_index); color_fprintf(fp, COLOR_IFNAME, "%s", tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>"); if (tb[IFLA_LINK]) { SPRINT_BUF(b1); int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); if (iflink == 0) fprintf(fp, "@NONE: "); else { if (tb[IFLA_LINK_NETNSID]) fprintf(fp, "@if%d: ", iflink); else { fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1)); m_flag = ll_index_to_flags(iflink); m_flag = !(m_flag & IFF_UP); } } } else { fprintf(fp, ": "); } print_link_flags(fp, ifi->ifi_flags, m_flag); if (tb[IFLA_MTU]) fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); if (tb[IFLA_QDISC]) fprintf(fp, "qdisc %s ", rta_getattr_str(tb[IFLA_QDISC])); if (tb[IFLA_MASTER]) { SPRINT_BUF(b1); fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); } if (tb[IFLA_PHYS_PORT_ID]) { SPRINT_BUF(b1); fprintf(fp, "portid %s ", hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_PORT_ID]), RTA_PAYLOAD(tb[IFLA_PHYS_PORT_ID]), b1, sizeof(b1))); } if (tb[IFLA_OPERSTATE]) print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); if (do_link && tb[IFLA_LINKMODE]) print_linkmode(fp, tb[IFLA_LINKMODE]); if (tb[IFLA_GROUP]) { SPRINT_BUF(b1); int group = *(int*)RTA_DATA(tb[IFLA_GROUP]); fprintf(fp, "group %s ", rtnl_group_n2a(group, b1, sizeof(b1))); } if (filter.showqueue) print_queuelen(fp, tb); if (!filter.family || filter.family == AF_PACKET || show_details) { SPRINT_BUF(b1); fprintf(fp, "%s", _SL_); fprintf(fp, " link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1))); if (tb[IFLA_ADDRESS]) { color_fprintf(fp, COLOR_MAC, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]), RTA_PAYLOAD(tb[IFLA_ADDRESS]), ifi->ifi_type, b1, sizeof(b1))); } if (tb[IFLA_BROADCAST]) { if (ifi->ifi_flags&IFF_POINTOPOINT) fprintf(fp, " peer "); else fprintf(fp, " brd "); fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]), RTA_PAYLOAD(tb[IFLA_BROADCAST]), ifi->ifi_type, b1, sizeof(b1))); } } if (tb[IFLA_LINK_NETNSID]) { int id = *(int*)RTA_DATA(tb[IFLA_LINK_NETNSID]); if (id >= 0) fprintf(fp, " link-netnsid %d", id); else fprintf(fp, " link-netnsid unknown"); } if (tb[IFLA_PROMISCUITY] && show_details) fprintf(fp, " promiscuity %u ", *(int*)RTA_DATA(tb[IFLA_PROMISCUITY])); if (tb[IFLA_LINKINFO] && show_details) print_linktype(fp, tb[IFLA_LINKINFO]); if (do_link && tb[IFLA_AF_SPEC] && show_details) print_af_spec(fp, tb[IFLA_AF_SPEC]); if ((do_link || show_details) && tb[IFLA_IFALIAS]) { fprintf(fp, "%s alias %s", _SL_, rta_getattr_str(tb[IFLA_IFALIAS])); } if (do_link && show_stats) { fprintf(fp, "%s", _SL_); __print_link_stats(fp, tb); } if ((do_link || show_details) && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) { struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST]; int rem = RTA_PAYLOAD(vflist); for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) print_vfinfo(fp, i); } fprintf(fp, "\n"); fflush(fp); return 1; }
int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; int host_len = -1; __u32 table; struct rtattr * tb[FRA_MAX+1]; char abuf[256]; SPRINT_BUF(b1); if (n->nlmsg_type != RTM_NEWRULE && n->nlmsg_type != RTM_DELRULE) return 0; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) return -1; parse_rtattr(tb, FRA_MAX, RTM_RTA(r), len); if (r->rtm_family == AF_INET) host_len = 32; else if (r->rtm_family == AF_INET6) host_len = 128; else if (r->rtm_family == AF_DECnet) host_len = 16; else if (r->rtm_family == AF_IPX) host_len = 80; if (n->nlmsg_type == RTM_DELRULE) fprintf(fp, "Deleted "); if (tb[FRA_PRIORITY]) fprintf(fp, "%u:\t", *(unsigned*)RTA_DATA(tb[FRA_PRIORITY])); else fprintf(fp, "0:\t"); if (r->rtm_flags & FIB_RULE_INVERT) fprintf(fp, "not "); if (tb[FRA_SRC]) { if (r->rtm_src_len != host_len) { fprintf(fp, "from %s/%u ", rt_addr_n2a(r->rtm_family, RTA_PAYLOAD(tb[FRA_SRC]), RTA_DATA(tb[FRA_SRC]), abuf, sizeof(abuf)), r->rtm_src_len ); } else { fprintf(fp, "from %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[FRA_SRC]), RTA_DATA(tb[FRA_SRC]), abuf, sizeof(abuf)) ); } } else if (r->rtm_src_len) { fprintf(fp, "from 0/%d ", r->rtm_src_len); } else { fprintf(fp, "from all "); } if (tb[FRA_DST]) { if (r->rtm_dst_len != host_len) { fprintf(fp, "to %s/%u ", rt_addr_n2a(r->rtm_family, RTA_PAYLOAD(tb[FRA_DST]), RTA_DATA(tb[FRA_DST]), abuf, sizeof(abuf)), r->rtm_dst_len ); } else { fprintf(fp, "to %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[FRA_DST]), RTA_DATA(tb[FRA_DST]), abuf, sizeof(abuf))); } } else if (r->rtm_dst_len) { fprintf(fp, "to 0/%d ", r->rtm_dst_len); } if (r->rtm_tos) { SPRINT_BUF(b1); fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1))); } if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) { __u32 mark = 0, mask = 0; if (tb[FRA_FWMARK]) mark = rta_getattr_u32(tb[FRA_FWMARK]); if (tb[FRA_FWMASK] && (mask = rta_getattr_u32(tb[FRA_FWMASK])) != 0xFFFFFFFF) fprintf(fp, "fwmark 0x%x/0x%x ", mark, mask); else fprintf(fp, "fwmark 0x%x ", mark); } if (tb[FRA_IFNAME]) { fprintf(fp, "iif %s ", rta_getattr_str(tb[FRA_IFNAME])); if (r->rtm_flags & FIB_RULE_IIF_DETACHED) fprintf(fp, "[detached] "); } if (tb[FRA_OIFNAME]) { fprintf(fp, "oif %s ", rta_getattr_str(tb[FRA_OIFNAME])); if (r->rtm_flags & FIB_RULE_OIF_DETACHED) fprintf(fp, "[detached] "); } table = rtm_get_table(r, tb); if (table) fprintf(fp, "lookup %s ", rtnl_rttable_n2a(table, b1, sizeof(b1))); if (tb[FRA_FLOW]) { __u32 to = rta_getattr_u32(tb[FRA_FLOW]); __u32 from = to>>16; to &= 0xFFFF; if (from) { fprintf(fp, "realms %s/", rtnl_rtrealm_n2a(from, b1, sizeof(b1))); } fprintf(fp, "%s ", rtnl_rtrealm_n2a(to, b1, sizeof(b1))); } if (r->rtm_type == RTN_NAT) { if (tb[RTA_GATEWAY]) { fprintf(fp, "map-to %s ", format_host(r->rtm_family, RTA_PAYLOAD(tb[RTA_GATEWAY]), RTA_DATA(tb[RTA_GATEWAY]), abuf, sizeof(abuf))); } else fprintf(fp, "masquerade"); } else if (r->rtm_type == FR_ACT_GOTO) { fprintf(fp, "goto "); if (tb[FRA_GOTO]) fprintf(fp, "%u", rta_getattr_u32(tb[FRA_GOTO])); else fprintf(fp, "none"); if (r->rtm_flags & FIB_RULE_UNRESOLVED) fprintf(fp, " [unresolved]"); } else if (r->rtm_type == FR_ACT_NOP) fprintf(fp, "nop"); else if (r->rtm_type != RTN_UNICAST) fprintf(fp, "%s", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); fprintf(fp, "\n"); fflush(fp); return 0; }
static int print_ntable(struct nlmsghdr *n, void *arg) { FILE *fp = (FILE *)arg; struct ndtmsg *ndtm = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[NDTA_MAX+1]; struct rtattr *tpb[NDTPA_MAX+1]; int ret; if (n->nlmsg_type != RTM_NEWNEIGHTBL) { fprintf(stderr, "Not NEIGHTBL: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*ndtm)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (preferred_family && preferred_family != ndtm->ndtm_family) return 0; parse_rtattr(tb, NDTA_MAX, NDTA_RTA(ndtm), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ndtm))); if (tb[NDTA_NAME]) { const char *name = rta_getattr_str(tb[NDTA_NAME]); if (filter.name && strcmp(filter.name, name)) return 0; } if (tb[NDTA_PARMS]) { parse_rtattr(tpb, NDTPA_MAX, RTA_DATA(tb[NDTA_PARMS]), RTA_PAYLOAD(tb[NDTA_PARMS])); if (tpb[NDTPA_IFINDEX]) { __u32 ifindex = rta_getattr_u32(tpb[NDTPA_IFINDEX]); if (filter.index && filter.index != ifindex) return 0; } else { if (filter.index && filter.index != NONE_DEV) return 0; } } open_json_object(NULL); print_string(PRINT_ANY, "family", "%s ", family_name(ndtm->ndtm_family)); if (tb[NDTA_NAME]) { const char *name = rta_getattr_str(tb[NDTA_NAME]); print_string(PRINT_ANY, "name", "%s ", name); } print_nl(); ret = (tb[NDTA_THRESH1] || tb[NDTA_THRESH2] || tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]); if (ret) print_string(PRINT_FP, NULL, " ", NULL); if (tb[NDTA_THRESH1]) { __u32 thresh1 = rta_getattr_u32(tb[NDTA_THRESH1]); print_uint(PRINT_ANY, "thresh1", "thresh1 %u ", thresh1); } if (tb[NDTA_THRESH2]) { __u32 thresh2 = rta_getattr_u32(tb[NDTA_THRESH2]); print_uint(PRINT_ANY, "thresh2", "thresh2 %u ", thresh2); } if (tb[NDTA_THRESH3]) { __u32 thresh3 = rta_getattr_u32(tb[NDTA_THRESH3]); print_uint(PRINT_ANY, "thresh3", "thresh3 %u ", thresh3); } if (tb[NDTA_GC_INTERVAL]) { __u64 gc_int = rta_getattr_u64(tb[NDTA_GC_INTERVAL]); print_u64(PRINT_ANY, "gc_interval", "gc_int %llu ", gc_int); } if (ret) print_nl(); if (tb[NDTA_CONFIG] && show_stats) print_ndtconfig(RTA_DATA(tb[NDTA_CONFIG])); if (tb[NDTA_PARMS]) print_ndtparams(tpb); if (tb[NDTA_STATS] && show_stats) print_ndtstats(RTA_DATA(tb[NDTA_STATS])); print_string(PRINT_FP, NULL, "\n", ""); close_json_object(); fflush(fp); return 0; }
static int print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) { struct rtattr *tb[TCA_IPT_MAX + 1]; struct xt_entry_target *t = NULL; if (arg == NULL) return -1; xtables_init_all(&tcipt_globals, NFPROTO_IPV4); set_lib_dir(); parse_rtattr_nested(tb, TCA_IPT_MAX, arg); if (tb[TCA_IPT_TABLE] == NULL) { fprintf(f, "[NULL ipt table name ] assuming mangle "); } else { fprintf(f, "tablename: %s ", rta_getattr_str(tb[TCA_IPT_TABLE])); } if (tb[TCA_IPT_HOOK] == NULL) { fprintf(f, "[NULL ipt hook name ]\n "); return -1; } else { __u32 hook; hook = rta_getattr_u32(tb[TCA_IPT_HOOK]); fprintf(f, " hook: %s \n", ipthooks[hook]); } if (tb[TCA_IPT_TARG] == NULL) { fprintf(f, "\t[NULL ipt target parameters ] \n"); return -1; } else { struct xtables_target *m = NULL; t = RTA_DATA(tb[TCA_IPT_TARG]); m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD); if (NULL != m) { if (0 > build_st(m, t)) { fprintf(stderr, " %s error \n", m->name); return -1; } tcipt_globals.opts = xtables_merge_options( #if (XTABLES_VERSION_CODE >= 6) tcipt_globals.orig_opts, #endif tcipt_globals.opts, m->extra_opts, &m->option_offset); } else { fprintf(stderr, " failed to find target %s\n\n", t->u.user.name); return -1; } fprintf(f, "\ttarget "); m->print(NULL, m->t, 0); if (tb[TCA_IPT_INDEX] == NULL) { fprintf(f, " [NULL ipt target index ]\n"); } else { __u32 index; index = rta_getattr_u32(tb[TCA_IPT_INDEX]); fprintf(f, " \n\tindex %d", index); } if (tb[TCA_IPT_CNT]) { struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);; fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt); } if (show_stats) { if (tb[TCA_IPT_TM]) { struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]); print_tm(f,tm); } } fprintf(f, " \n"); } xtables_free_opts(1); return 0; }
int print_linkinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct ifinfomsg *ifi = NLMSG_DATA(n); struct rtattr * tb[IFLA_MAX+1]; int len = n->nlmsg_len; unsigned m_flag = 0; if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) return 0; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) return -1; if (filter.ifindex && ifi->ifi_index != filter.ifindex) return 0; if (filter.up && !(ifi->ifi_flags&IFF_UP)) return 0; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL) { fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index); } if (filter.label && (!filter.family || filter.family == AF_PACKET) && fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0)) return 0; if (tb[IFLA_GROUP]) { int group = *(int*)RTA_DATA(tb[IFLA_GROUP]); if (group != filter.group) return -1; } if (n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); fprintf(fp, "%d: %s", ifi->ifi_index, tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>"); if (tb[IFLA_LINK]) { SPRINT_BUF(b1); int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]); if (iflink == 0) fprintf(fp, "@NONE: "); else { fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1)); m_flag = ll_index_to_flags(iflink); m_flag = !(m_flag & IFF_UP); } } else { fprintf(fp, ": "); } print_link_flags(fp, ifi->ifi_flags, m_flag); if (tb[IFLA_MTU]) fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); if (tb[IFLA_QDISC]) fprintf(fp, "qdisc %s ", rta_getattr_str(tb[IFLA_QDISC])); if (tb[IFLA_MASTER]) { SPRINT_BUF(b1); fprintf(fp, "master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); } if (tb[IFLA_OPERSTATE]) print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); if (do_link && tb[IFLA_LINKMODE]) print_linkmode(fp, tb[IFLA_LINKMODE]); if (filter.showqueue) print_queuelen(fp, tb); if (!filter.family || filter.family == AF_PACKET) { SPRINT_BUF(b1); fprintf(fp, "%s", _SL_); fprintf(fp, " link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1))); if (tb[IFLA_ADDRESS]) { fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]), RTA_PAYLOAD(tb[IFLA_ADDRESS]), ifi->ifi_type, b1, sizeof(b1))); } if (tb[IFLA_BROADCAST]) { if (ifi->ifi_flags&IFF_POINTOPOINT) fprintf(fp, " peer "); else fprintf(fp, " brd "); fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]), RTA_PAYLOAD(tb[IFLA_BROADCAST]), ifi->ifi_type, b1, sizeof(b1))); } } if (do_link && tb[IFLA_LINKINFO] && show_details) print_linktype(fp, tb[IFLA_LINKINFO]); if (do_link && tb[IFLA_IFALIAS]) fprintf(fp,"\n alias %s", rta_getattr_str(tb[IFLA_IFALIAS])); if (do_link && show_stats) { if (tb[IFLA_STATS64]) print_link_stats64(fp, RTA_DATA(tb[IFLA_STATS64])); else if (tb[IFLA_STATS]) print_link_stats(fp, RTA_DATA(tb[IFLA_STATS])); } if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) { struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST]; int rem = RTA_PAYLOAD(vflist); for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) print_vfinfo(fp, i); } fprintf(fp, "\n"); fflush(fp); return 0; }
static int print_ipt(struct action_util *au, FILE * f, struct rtattr *arg) { struct rtattr *tb[TCA_IPT_MAX + 1]; struct xt_entry_target *t = NULL; if (arg == NULL) return -1; set_lib_dir(); parse_rtattr_nested(tb, TCA_IPT_MAX, arg); if (tb[TCA_IPT_TABLE] == NULL) { fprintf(f, "[NULL ipt table name ] assuming mangle "); } else { fprintf(f, "tablename: %s ", rta_getattr_str(tb[TCA_IPT_TABLE])); } if (tb[TCA_IPT_HOOK] == NULL) { fprintf(f, "[NULL ipt hook name ]\n "); return -1; } else { __u32 hook; hook = rta_getattr_u32(tb[TCA_IPT_HOOK]); fprintf(f, " hook: %s\n", ipthooks[hook]); } if (tb[TCA_IPT_TARG] == NULL) { fprintf(f, "\t[NULL ipt target parameters ]\n"); return -1; } else { struct xtables_target *m = NULL; t = RTA_DATA(tb[TCA_IPT_TARG]); m = find_target(t->u.user.name, TRY_LOAD); if (m != NULL) { if (build_st(m, t) < 0) { fprintf(stderr, " %s error\n", m->name); return -1; } opts = merge_options(opts, m->extra_opts, &m->option_offset); } else { fprintf(stderr, " failed to find target %s\n\n", t->u.user.name); return -1; } fprintf(f, "\ttarget "); m->print(NULL, m->t, 0); if (tb[TCA_IPT_INDEX] == NULL) { fprintf(f, " [NULL ipt target index ]\n"); } else { __u32 index; index = rta_getattr_u32(tb[TCA_IPT_INDEX]); fprintf(f, "\n\tindex %u", index); } if (tb[TCA_IPT_CNT]) { struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]); fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt); } if (show_stats) { if (tb[TCA_IPT_TM]) { struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]); print_tm(f, tm); } } fprintf(f, "\n"); } free_opts(opts); return 0; }
int print_ntable(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; struct ndtmsg *ndtm = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[NDTA_MAX+1]; struct rtattr *tpb[NDTPA_MAX+1]; int ret; if (n->nlmsg_type != RTM_NEWNEIGHTBL) { fprintf(stderr, "Not NEIGHTBL: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } len -= NLMSG_LENGTH(sizeof(*ndtm)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (preferred_family && preferred_family != ndtm->ndtm_family) return 0; parse_rtattr(tb, NDTA_MAX, NDTA_RTA(ndtm), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ndtm))); if (tb[NDTA_NAME]) { const char *name = rta_getattr_str(tb[NDTA_NAME]); if (strlen(filter.name) > 0 && strcmp(filter.name, name)) return 0; } if (tb[NDTA_PARMS]) { parse_rtattr(tpb, NDTPA_MAX, RTA_DATA(tb[NDTA_PARMS]), RTA_PAYLOAD(tb[NDTA_PARMS])); if (tpb[NDTPA_IFINDEX]) { __u32 ifindex = rta_getattr_u32(tpb[NDTPA_IFINDEX]); if (filter.index && filter.index != ifindex) return 0; } else { if (filter.index && filter.index != NONE_DEV) return 0; } } if (ndtm->ndtm_family == AF_INET) fprintf(fp, "inet "); else if (ndtm->ndtm_family == AF_INET6) fprintf(fp, "inet6 "); else if (ndtm->ndtm_family == AF_DECnet) fprintf(fp, "dnet "); else fprintf(fp, "(%d) ", ndtm->ndtm_family); if (tb[NDTA_NAME]) { const char *name = rta_getattr_str(tb[NDTA_NAME]); fprintf(fp, "%s ", name); } fprintf(fp, "%s", _SL_); ret = (tb[NDTA_THRESH1] || tb[NDTA_THRESH2] || tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]); if (ret) fprintf(fp, " "); if (tb[NDTA_THRESH1]) { __u32 thresh1 = rta_getattr_u32(tb[NDTA_THRESH1]); fprintf(fp, "thresh1 %u ", thresh1); } if (tb[NDTA_THRESH2]) { __u32 thresh2 = rta_getattr_u32(tb[NDTA_THRESH2]); fprintf(fp, "thresh2 %u ", thresh2); } if (tb[NDTA_THRESH3]) { __u32 thresh3 = rta_getattr_u32(tb[NDTA_THRESH3]); fprintf(fp, "thresh3 %u ", thresh3); } if (tb[NDTA_GC_INTERVAL]) { unsigned long long gc_int = rta_getattr_u64(tb[NDTA_GC_INTERVAL]); fprintf(fp, "gc_int %llu ", gc_int); } if (ret) fprintf(fp, "%s", _SL_); if (tb[NDTA_CONFIG] && show_stats) { struct ndt_config *ndtc = RTA_DATA(tb[NDTA_CONFIG]); fprintf(fp, " "); fprintf(fp, "config "); fprintf(fp, "key_len %u ", ndtc->ndtc_key_len); fprintf(fp, "entry_size %u ", ndtc->ndtc_entry_size); fprintf(fp, "entries %u ", ndtc->ndtc_entries); fprintf(fp, "%s", _SL_); fprintf(fp, " "); fprintf(fp, "last_flush %s ", ntable_strtime_delta(ndtc->ndtc_last_flush)); fprintf(fp, "last_rand %s ", ntable_strtime_delta(ndtc->ndtc_last_rand)); fprintf(fp, "%s", _SL_); fprintf(fp, " "); fprintf(fp, "hash_rnd %u ", ndtc->ndtc_hash_rnd); fprintf(fp, "hash_mask %08x ", ndtc->ndtc_hash_mask); fprintf(fp, "hash_chain_gc %u ", ndtc->ndtc_hash_chain_gc); fprintf(fp, "proxy_qlen %u ", ndtc->ndtc_proxy_qlen); fprintf(fp, "%s", _SL_); } if (tb[NDTA_PARMS]) { if (tpb[NDTPA_IFINDEX]) { __u32 ifindex = rta_getattr_u32(tpb[NDTPA_IFINDEX]); fprintf(fp, " "); fprintf(fp, "dev %s ", ll_index_to_name(ifindex)); fprintf(fp, "%s", _SL_); } fprintf(fp, " "); if (tpb[NDTPA_REFCNT]) { __u32 refcnt = rta_getattr_u32(tpb[NDTPA_REFCNT]); fprintf(fp, "refcnt %u ", refcnt); } if (tpb[NDTPA_REACHABLE_TIME]) { unsigned long long reachable = rta_getattr_u64(tpb[NDTPA_REACHABLE_TIME]); fprintf(fp, "reachable %llu ", reachable); } if (tpb[NDTPA_BASE_REACHABLE_TIME]) { unsigned long long breachable = rta_getattr_u64(tpb[NDTPA_BASE_REACHABLE_TIME]); fprintf(fp, "base_reachable %llu ", breachable); } if (tpb[NDTPA_RETRANS_TIME]) { unsigned long long retrans = rta_getattr_u64(tpb[NDTPA_RETRANS_TIME]); fprintf(fp, "retrans %llu ", retrans); } fprintf(fp, "%s", _SL_); fprintf(fp, " "); if (tpb[NDTPA_GC_STALETIME]) { unsigned long long gc_stale = rta_getattr_u64(tpb[NDTPA_GC_STALETIME]); fprintf(fp, "gc_stale %llu ", gc_stale); } if (tpb[NDTPA_DELAY_PROBE_TIME]) { unsigned long long delay_probe = rta_getattr_u64(tpb[NDTPA_DELAY_PROBE_TIME]); fprintf(fp, "delay_probe %llu ", delay_probe); } if (tpb[NDTPA_QUEUE_LEN]) { __u32 queue = rta_getattr_u32(tpb[NDTPA_QUEUE_LEN]); fprintf(fp, "queue %u ", queue); } fprintf(fp, "%s", _SL_); fprintf(fp, " "); if (tpb[NDTPA_APP_PROBES]) { __u32 aprobe = rta_getattr_u32(tpb[NDTPA_APP_PROBES]); fprintf(fp, "app_probes %u ", aprobe); } if (tpb[NDTPA_UCAST_PROBES]) { __u32 uprobe = rta_getattr_u32(tpb[NDTPA_UCAST_PROBES]); fprintf(fp, "ucast_probes %u ", uprobe); } if (tpb[NDTPA_MCAST_PROBES]) { __u32 mprobe = rta_getattr_u32(tpb[NDTPA_MCAST_PROBES]); fprintf(fp, "mcast_probes %u ", mprobe); } fprintf(fp, "%s", _SL_); fprintf(fp, " "); if (tpb[NDTPA_ANYCAST_DELAY]) { unsigned long long anycast_delay = rta_getattr_u64(tpb[NDTPA_ANYCAST_DELAY]); fprintf(fp, "anycast_delay %llu ", anycast_delay); } if (tpb[NDTPA_PROXY_DELAY]) { unsigned long long proxy_delay = rta_getattr_u64(tpb[NDTPA_PROXY_DELAY]); fprintf(fp, "proxy_delay %llu ", proxy_delay); } if (tpb[NDTPA_PROXY_QLEN]) { __u32 pqueue = rta_getattr_u32(tpb[NDTPA_PROXY_QLEN]); fprintf(fp, "proxy_queue %u ", pqueue); } if (tpb[NDTPA_LOCKTIME]) { unsigned long long locktime = rta_getattr_u64(tpb[NDTPA_LOCKTIME]); fprintf(fp, "locktime %llu ", locktime); } fprintf(fp, "%s", _SL_); } if (tb[NDTA_STATS] && show_stats) { struct ndt_stats *ndts = RTA_DATA(tb[NDTA_STATS]); fprintf(fp, " "); fprintf(fp, "stats "); fprintf(fp, "allocs %llu ", (unsigned long long) ndts->ndts_allocs); fprintf(fp, "destroys %llu ", (unsigned long long) ndts->ndts_destroys); fprintf(fp, "hash_grows %llu ", (unsigned long long) ndts->ndts_hash_grows); fprintf(fp, "%s", _SL_); fprintf(fp, " "); fprintf(fp, "res_failed %llu ", (unsigned long long) ndts->ndts_res_failed); fprintf(fp, "lookups %llu ", (unsigned long long) ndts->ndts_lookups); fprintf(fp, "hits %llu ", (unsigned long long) ndts->ndts_hits); fprintf(fp, "%s", _SL_); fprintf(fp, " "); fprintf(fp, "rcv_probes_mcast %llu ", (unsigned long long) ndts->ndts_rcv_probes_mcast); fprintf(fp, "rcv_probes_ucast %llu ", (unsigned long long) ndts->ndts_rcv_probes_ucast); fprintf(fp, "%s", _SL_); fprintf(fp, " "); fprintf(fp, "periodic_gc_runs %llu ", (unsigned long long) ndts->ndts_periodic_gc_runs); fprintf(fp, "forced_gc_runs %llu ", (unsigned long long) ndts->ndts_forced_gc_runs); fprintf(fp, "%s", _SL_); } fprintf(fp, "\n"); fflush(fp); return 0; }
static int parse_ipt(struct action_util *a,int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { struct xtables_target *m = NULL; struct ipt_entry fw; struct rtattr *tail; int c; int rargc = *argc_p; char **argv = *argv_p; int argc = 0, iargc = 0; char k[16]; int size = 0; int iok = 0, ok = 0; __u32 hook = 0, index = 0; struct option *opts = NULL; xtables_init_all(&tcipt_globals, NFPROTO_IPV4); set_lib_dir(); { int i; for (i = 0; i < rargc; i++) { if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) { break; } } iargc = argc = i; } if (argc <= 2) { fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc); return -1; } while (1) { c = getopt_long(argc, argv, "j:", tcipt_globals.opts, NULL); if (c == -1) break; switch (c) { case 'j': m = xtables_find_target(optarg, XTF_TRY_LOAD); if (NULL != m) { if (0 > build_st(m, NULL)) { printf(" %s error \n", m->name); return -1; } #if (XTABLES_VERSION_CODE >= 6) opts = xtables_options_xfrm(tcipt_globals.orig_opts, tcipt_globals.opts, m->x6_options, &m->option_offset); #else opts = xtables_merge_options(tcipt_globals.orig_opts, tcipt_globals.opts, m->extra_opts, &m->option_offset); #endif if (opts == NULL) { fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); return -1; } else tcipt_globals.opts = opts; } else { fprintf(stderr," failed to find target %s\n\n", optarg); return -1; } ok++; break; default: memset(&fw, 0, sizeof (fw)); #if (XTABLES_VERSION_CODE >= 6) if (m != NULL && m->x6_parse != NULL ) { xtables_option_tpcall(c, argv, 0 , m, NULL); #else if (m != NULL && m->parse != NULL ) { m->parse(c - m->option_offset, argv, 0, &m->tflags, NULL, &m->t); #endif } else { fprintf(stderr,"failed to find target %s\n\n", optarg); return -1; } ok++; break; } } if (iargc > optind) { if (matches(argv[optind], "index") == 0) { if (get_u32(&index, argv[optind + 1], 10)) { fprintf(stderr, "Illegal \"index\"\n"); xtables_free_opts(1); return -1; } iok++; optind += 2; } } if (!ok && !iok) { fprintf(stderr," ipt Parser BAD!! (%s)\n", *argv); return -1; } /* check that we passed the correct parameters to the target */ #if (XTABLES_VERSION_CODE >= 6) if (m) xtables_option_tfcall(m); #else if (m && m->final_check) m->final_check(m->tflags); #endif { struct tcmsg *t = NLMSG_DATA(n); if (t->tcm_parent != TC_H_ROOT && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) { hook = NF_IP_PRE_ROUTING; } else { hook = NF_IP_POST_ROUTING; } } tail = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, tca_id, NULL, 0); fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]); fprintf(stdout, "\ttarget: "); if (m) m->print(NULL, m->t, 0); fprintf(stdout, " index %d\n", index); if (strlen(tname) > 16) { size = 16; k[15] = 0; } else { size = 1 + strlen(tname); } strncpy(k, tname, size); addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size); addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4); addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4); if (m) addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; argc -= optind; argv += optind; *argc_p = rargc - iargc; *argv_p = argv; optind = 0; xtables_free_opts(1); if (m) { /* Clear flags if target will be used again */ m->tflags = 0; m->used = 0; /* Free allocated memory */ if (m->t) free(m->t); } return 0; } static int print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) { struct rtattr *tb[TCA_IPT_MAX + 1]; struct xt_entry_target *t = NULL; struct option *opts = NULL; if (arg == NULL) return -1; xtables_init_all(&tcipt_globals, NFPROTO_IPV4); set_lib_dir(); parse_rtattr_nested(tb, TCA_IPT_MAX, arg); if (tb[TCA_IPT_TABLE] == NULL) { fprintf(f, "[NULL ipt table name ] assuming mangle "); } else { fprintf(f, "tablename: %s ", rta_getattr_str(tb[TCA_IPT_TABLE])); } if (tb[TCA_IPT_HOOK] == NULL) { fprintf(f, "[NULL ipt hook name ]\n "); return -1; } else { __u32 hook; hook = rta_getattr_u32(tb[TCA_IPT_HOOK]); fprintf(f, " hook: %s \n", ipthooks[hook]); } if (tb[TCA_IPT_TARG] == NULL) { fprintf(f, "\t[NULL ipt target parameters ] \n"); return -1; } else { struct xtables_target *m = NULL; t = RTA_DATA(tb[TCA_IPT_TARG]); m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD); if (NULL != m) { if (0 > build_st(m, t)) { fprintf(stderr, " %s error \n", m->name); return -1; } #if (XTABLES_VERSION_CODE >= 6) opts = xtables_options_xfrm(tcipt_globals.orig_opts, tcipt_globals.opts, m->x6_options, &m->option_offset); #else opts = xtables_merge_options(tcipt_globals.orig_opts, tcipt_globals.opts, m->extra_opts, &m->option_offset); #endif if (opts == NULL) { fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); return -1; } else tcipt_globals.opts = opts; } else { fprintf(stderr, " failed to find target %s\n\n", t->u.user.name); return -1; } fprintf(f, "\ttarget "); m->print(NULL, m->t, 0); if (tb[TCA_IPT_INDEX] == NULL) { fprintf(f, " [NULL ipt target index ]\n"); } else { __u32 index; index = rta_getattr_u32(tb[TCA_IPT_INDEX]); fprintf(f, " \n\tindex %d", index); } if (tb[TCA_IPT_CNT]) { struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);; fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt); } if (show_stats) { if (tb[TCA_IPT_TM]) { struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]); print_tm(f,tm); } } fprintf(f, " \n"); } xtables_free_opts(1); return 0; } struct action_util xt_action_util = { .id = "xt", .parse_aopt = parse_ipt, .print_aopt = print_ipt, };
int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = arg; struct ifaddrmsg *ifa = NLMSG_DATA(n); int len = n->nlmsg_len; int deprecated = 0; /* Use local copy of ifa_flags to not interfere with filtering code */ unsigned int ifa_flags; struct rtattr * rta_tb[IFA_MAX+1]; char abuf[256]; SPRINT_BUF(b1); if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) return 0; len -= NLMSG_LENGTH(sizeof(*ifa)); if (len < 0) { fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } if (filter.flushb && n->nlmsg_type != RTM_NEWADDR) return 0; parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); ifa_flags = get_ifa_flags(ifa, rta_tb[IFA_FLAGS]); if (!rta_tb[IFA_LOCAL]) rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; if (!rta_tb[IFA_ADDRESS]) rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL]; if (filter.ifindex && filter.ifindex != ifa->ifa_index) return 0; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) return 0; if ((filter.flags ^ ifa_flags) & filter.flagmask) return 0; if (filter.label) { SPRINT_BUF(b1); const char *label; if (rta_tb[IFA_LABEL]) label = RTA_DATA(rta_tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) return 0; } if (filter.pfx.family) { if (rta_tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) return 0; } } if (filter.family && filter.family != ifa->ifa_family) return 0; if (filter.flushb) { struct nlmsghdr *fn; if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) { if (flush_update()) return -1; } fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp)); memcpy(fn, n, n->nlmsg_len); fn->nlmsg_type = RTM_DELADDR; fn->nlmsg_flags = NLM_F_REQUEST; fn->nlmsg_seq = ++rth.seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; if (show_stats < 2) return 0; } if (n->nlmsg_type == RTM_DELADDR) fprintf(fp, "Deleted "); if (filter.oneline || filter.flushb) fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index)); if (ifa->ifa_family == AF_INET) fprintf(fp, " inet "); else if (ifa->ifa_family == AF_INET6) fprintf(fp, " inet6 "); else if (ifa->ifa_family == AF_DECnet) fprintf(fp, " dnet "); else if (ifa->ifa_family == AF_IPX) fprintf(fp, " ipx "); else fprintf(fp, " family %d ", ifa->ifa_family); if (rta_tb[IFA_LOCAL]) { if (ifa->ifa_family == AF_INET) color_fprintf(fp, COLOR_INET, "%s", format_host(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_LOCAL]), RTA_DATA(rta_tb[IFA_LOCAL]), abuf, sizeof(abuf))); else if (ifa->ifa_family == AF_INET6) color_fprintf(fp, COLOR_INET6, "%s", format_host(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_LOCAL]), RTA_DATA(rta_tb[IFA_LOCAL]), abuf, sizeof(abuf))); else fprintf(fp, "%s", format_host(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_LOCAL]), RTA_DATA(rta_tb[IFA_LOCAL]), abuf, sizeof(abuf))); if (rta_tb[IFA_ADDRESS] == NULL || memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), ifa->ifa_family == AF_INET ? 4 : 16) == 0) { fprintf(fp, "/%d ", ifa->ifa_prefixlen); } else { fprintf(fp, " peer %s/%d ", format_host(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_ADDRESS]), abuf, sizeof(abuf)), ifa->ifa_prefixlen); } } if (rta_tb[IFA_BROADCAST]) { fprintf(fp, "brd %s ", format_host(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_BROADCAST]), RTA_DATA(rta_tb[IFA_BROADCAST]), abuf, sizeof(abuf))); } if (rta_tb[IFA_ANYCAST]) { fprintf(fp, "any %s ", format_host(ifa->ifa_family, RTA_PAYLOAD(rta_tb[IFA_ANYCAST]), RTA_DATA(rta_tb[IFA_ANYCAST]), abuf, sizeof(abuf))); } fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1))); if (ifa_flags & IFA_F_SECONDARY) { ifa_flags &= ~IFA_F_SECONDARY; if (ifa->ifa_family == AF_INET6) fprintf(fp, "temporary "); else fprintf(fp, "secondary "); } if (ifa_flags & IFA_F_TENTATIVE) { ifa_flags &= ~IFA_F_TENTATIVE; fprintf(fp, "tentative "); } if (ifa_flags & IFA_F_DEPRECATED) { ifa_flags &= ~IFA_F_DEPRECATED; deprecated = 1; fprintf(fp, "deprecated "); } if (ifa_flags & IFA_F_HOMEADDRESS) { ifa_flags &= ~IFA_F_HOMEADDRESS; fprintf(fp, "home "); } if (ifa_flags & IFA_F_NODAD) { ifa_flags &= ~IFA_F_NODAD; fprintf(fp, "nodad "); } if (ifa_flags & IFA_F_MANAGETEMPADDR) { ifa_flags &= ~IFA_F_MANAGETEMPADDR; fprintf(fp, "mngtmpaddr "); } if (ifa_flags & IFA_F_NOPREFIXROUTE) { ifa_flags &= ~IFA_F_NOPREFIXROUTE; fprintf(fp, "noprefixroute "); } if (ifa_flags & IFA_F_MCAUTOJOIN) { ifa_flags &= ~IFA_F_MCAUTOJOIN; fprintf(fp, "autojoin "); } if (!(ifa_flags & IFA_F_PERMANENT)) { fprintf(fp, "dynamic "); } else ifa_flags &= ~IFA_F_PERMANENT; if (ifa_flags & IFA_F_DADFAILED) { ifa_flags &= ~IFA_F_DADFAILED; fprintf(fp, "dadfailed "); } if (ifa_flags) fprintf(fp, "flags %02x ", ifa_flags); if (rta_tb[IFA_LABEL]) fprintf(fp, "%s", rta_getattr_str(rta_tb[IFA_LABEL])); if (rta_tb[IFA_CACHEINFO]) { struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]); fprintf(fp, "%s", _SL_); fprintf(fp, " valid_lft "); if (ci->ifa_valid == INFINITY_LIFE_TIME) fprintf(fp, "forever"); else fprintf(fp, "%usec", ci->ifa_valid); fprintf(fp, " preferred_lft "); if (ci->ifa_prefered == INFINITY_LIFE_TIME) fprintf(fp, "forever"); else { if (deprecated) fprintf(fp, "%dsec", ci->ifa_prefered); else fprintf(fp, "%usec", ci->ifa_prefered); } } fprintf(fp, "\n"); fflush(fp); return 0; }
int print_linkinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = arg; int len = n->nlmsg_len; struct ifinfomsg *ifi = NLMSG_DATA(n); struct rtattr * tb[IFLA_MAX+1]; char b1[IFNAMSIZ]; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) { fprintf(stderr, "Message too short!\n"); return -1; } if (!(ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_UNSPEC)) return 0; if (filter_index && filter_index != ifi->ifi_index) return 0; parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, NLA_F_NESTED); if (tb[IFLA_IFNAME] == NULL) { fprintf(stderr, "BUG: nil ifname\n"); return -1; } if (n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); fprintf(fp, "%d: %s ", ifi->ifi_index, tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>"); if (tb[IFLA_OPERSTATE]) print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); if (tb[IFLA_LINK]) { SPRINT_BUF(b1); int iflink = rta_getattr_u32(tb[IFLA_LINK]); if (iflink == 0) fprintf(fp, "@NONE: "); else fprintf(fp, "@%s: ", if_indextoname(iflink, b1)); } else fprintf(fp, ": "); print_link_flags(fp, ifi->ifi_flags); if (tb[IFLA_MTU]) fprintf(fp, "mtu %u ", rta_getattr_u32(tb[IFLA_MTU])); if (tb[IFLA_MASTER]) fprintf(fp, "master %s ", if_indextoname(rta_getattr_u32(tb[IFLA_MASTER]), b1)); if (tb[IFLA_PROTINFO]) { if (tb[IFLA_PROTINFO]->rta_type & NLA_F_NESTED) { struct rtattr *prtb[IFLA_BRPORT_MAX+1]; parse_rtattr_nested(prtb, IFLA_BRPORT_MAX, tb[IFLA_PROTINFO]); if (prtb[IFLA_BRPORT_STATE]) print_portstate(fp, rta_getattr_u8(prtb[IFLA_BRPORT_STATE])); if (prtb[IFLA_BRPORT_PRIORITY]) fprintf(fp, "priority %hu ", rta_getattr_u16(prtb[IFLA_BRPORT_PRIORITY])); if (prtb[IFLA_BRPORT_COST]) fprintf(fp, "cost %u ", rta_getattr_u32(prtb[IFLA_BRPORT_COST])); if (show_details) { fprintf(fp, "%s ", _SL_); if (prtb[IFLA_BRPORT_MODE]) print_onoff(fp, "hairpin", rta_getattr_u8(prtb[IFLA_BRPORT_MODE])); if (prtb[IFLA_BRPORT_GUARD]) print_onoff(fp, "guard", rta_getattr_u8(prtb[IFLA_BRPORT_GUARD])); if (prtb[IFLA_BRPORT_PROTECT]) print_onoff(fp, "root_block", rta_getattr_u8(prtb[IFLA_BRPORT_PROTECT])); if (prtb[IFLA_BRPORT_FAST_LEAVE]) print_onoff(fp, "fastleave", rta_getattr_u8(prtb[IFLA_BRPORT_FAST_LEAVE])); if (prtb[IFLA_BRPORT_LEARNING]) print_onoff(fp, "learning", rta_getattr_u8(prtb[IFLA_BRPORT_LEARNING])); if (prtb[IFLA_BRPORT_LEARNING_SYNC]) print_onoff(fp, "learning_sync", rta_getattr_u8(prtb[IFLA_BRPORT_LEARNING_SYNC])); if (prtb[IFLA_BRPORT_UNICAST_FLOOD]) print_onoff(fp, "flood", rta_getattr_u8(prtb[IFLA_BRPORT_UNICAST_FLOOD])); } } else print_portstate(fp, rta_getattr_u8(tb[IFLA_PROTINFO])); } if (tb[IFLA_AF_SPEC]) { /* This is reported by HW devices that have some bridging * capabilities. */ struct rtattr *aftb[IFLA_BRIDGE_MAX+1]; parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]); if (aftb[IFLA_BRIDGE_MODE]) print_hwmode(fp, rta_getattr_u16(aftb[IFLA_BRIDGE_MODE])); } fprintf(fp, "\n"); fflush(fp); return 0; }