static __u64 getattr_u64(struct rtattr *stat) { switch (RTA_PAYLOAD(stat)) { case sizeof(__u64): return rta_getattr_u64(stat); case sizeof(__u32): return rta_getattr_u32(stat); case sizeof(__u16): return rta_getattr_u16(stat); case sizeof(__u8): return rta_getattr_u8(stat); default: fprintf(stderr, "invalid attribute length %lu\n", RTA_PAYLOAD(stat)); exit(-1); } }
static void print_ila_locid(FILE *fp, int attr, struct rtattr *tb[], int space) { char abuf[256]; size_t blen; int i; if (tb[attr]) { blen = print_addr64(rta_getattr_u64(tb[attr]), abuf, sizeof(abuf)); fprintf(fp, "%s", abuf); } else { fprintf(fp, "-"); blen = 1; } for (i = 0; i < space - blen; i++) fprintf(fp, " "); }
static void _bridge_print_timer(FILE *f, const char *attr, struct rtattr *timer) { struct timeval tv; __jiffies_to_tv(&tv, rta_getattr_u64(timer)); if (is_json_context()) { json_writer_t *jw = get_json_writer(); jsonw_name(jw, attr); jsonw_printf(jw, "%i.%.2i", (int)tv.tv_sec, (int)tv.tv_usec / 10000); } else { fprintf(f, "%s %4i.%.2i ", attr, (int)tv.tv_sec, (int)tv.tv_usec / 10000); } }
static void print_rxsc_list(struct rtattr *sc) { int rem = RTA_PAYLOAD(sc); struct rtattr *c; open_json_array(PRINT_JSON, "rx_sc"); for (c = RTA_DATA(sc); RTA_OK(c, rem); c = RTA_NEXT(c, rem)) { struct rtattr *sc_attr[MACSEC_RXSC_ATTR_MAX + 1]; open_json_object(NULL); parse_rtattr_nested(sc_attr, MACSEC_RXSC_ATTR_MAX + 1, c); print_rx_sc(" ", rta_getattr_u64(sc_attr[MACSEC_RXSC_ATTR_SCI]), rta_getattr_u32(sc_attr[MACSEC_RXSC_ATTR_ACTIVE]), sc_attr[MACSEC_RXSC_ATTR_STATS], sc_attr[MACSEC_RXSC_ATTR_SA_LIST]); close_json_object(); } close_json_array(PRINT_JSON, NULL); }
static void print_attrs(struct rtattr *attrs[]) { print_flag(attrs, "protect", MACSEC_SECY_ATTR_PROTECT); if (attrs[MACSEC_SECY_ATTR_VALIDATE]) { __u8 val = rta_getattr_u8(attrs[MACSEC_SECY_ATTR_VALIDATE]); print_string(PRINT_ANY, "validate", "validate %s ", validate_str[val]); } print_flag(attrs, "sc", MACSEC_RXSC_ATTR_ACTIVE); print_flag(attrs, "sa", MACSEC_SA_ATTR_ACTIVE); print_flag(attrs, "encrypt", MACSEC_SECY_ATTR_ENCRYPT); print_flag(attrs, "send_sci", MACSEC_SECY_ATTR_INC_SCI); print_flag(attrs, "end_station", MACSEC_SECY_ATTR_ES); print_flag(attrs, "scb", MACSEC_SECY_ATTR_SCB); print_flag(attrs, "replay", MACSEC_SECY_ATTR_REPLAY); if (attrs[MACSEC_SECY_ATTR_WINDOW]) { __u32 win = rta_getattr_u32(attrs[MACSEC_SECY_ATTR_WINDOW]); print_uint(PRINT_ANY, "window", "window %u ", win); } if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]) { __u64 cid = rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]); print_string(PRINT_FP, NULL, "%s", _SL_); print_string(PRINT_ANY, "cipher_suite", " cipher suite: %s,", cs_id_to_name(cid)); } if (attrs[MACSEC_SECY_ATTR_ICV_LEN]) { __u8 icv_len = rta_getattr_u8(attrs[MACSEC_SECY_ATTR_ICV_LEN]); print_uint(PRINT_ANY, "icv_length", " using ICV length %u\n", icv_len); } }
static void print_encap_ip(FILE *fp, struct rtattr *encap) { struct rtattr *tb[LWTUNNEL_IP_MAX+1]; parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap); if (tb[LWTUNNEL_IP_ID]) fprintf(fp, "id %llu ", ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID]))); if (tb[LWTUNNEL_IP_SRC]) fprintf(fp, "src %s ", rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_SRC])); if (tb[LWTUNNEL_IP_DST]) fprintf(fp, "dst %s ", rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_DST])); if (tb[LWTUNNEL_IP_TTL]) fprintf(fp, "ttl %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL])); if (tb[LWTUNNEL_IP_TOS]) fprintf(fp, "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS])); }
static void print_encap_ip6(FILE *fp, struct rtattr *encap) { struct rtattr *tb[LWTUNNEL_IP6_MAX+1]; parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap); if (tb[LWTUNNEL_IP6_ID]) fprintf(fp, "id %llu ", ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID]))); if (tb[LWTUNNEL_IP6_SRC]) fprintf(fp, "src %s ", rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_SRC])); if (tb[LWTUNNEL_IP6_DST]) fprintf(fp, "dst %s ", rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_DST])); if (tb[LWTUNNEL_IP6_HOPLIMIT]) fprintf(fp, "hoplimit %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT])); if (tb[LWTUNNEL_IP6_TC]) fprintf(fp, "tc %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC])); }
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; }
static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { if (!tb) return; if (tb[IFLA_BR_FORWARD_DELAY]) fprintf(f, "forward_delay %u ", rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY])); if (tb[IFLA_BR_HELLO_TIME]) fprintf(f, "hello_time %u ", rta_getattr_u32(tb[IFLA_BR_HELLO_TIME])); if (tb[IFLA_BR_MAX_AGE]) fprintf(f, "max_age %u ", rta_getattr_u32(tb[IFLA_BR_MAX_AGE])); if (tb[IFLA_BR_AGEING_TIME]) fprintf(f, "ageing_time %u ", rta_getattr_u32(tb[IFLA_BR_AGEING_TIME])); if (tb[IFLA_BR_STP_STATE]) fprintf(f, "stp_state %u ", rta_getattr_u32(tb[IFLA_BR_STP_STATE])); if (tb[IFLA_BR_PRIORITY]) fprintf(f, "priority %u ", rta_getattr_u16(tb[IFLA_BR_PRIORITY])); if (tb[IFLA_BR_VLAN_FILTERING]) fprintf(f, "vlan_filtering %u ", rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING])); if (tb[IFLA_BR_VLAN_PROTOCOL]) { SPRINT_BUF(b1); fprintf(f, "vlan_protocol %s ", ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]), b1, sizeof(b1))); } if (tb[IFLA_BR_BRIDGE_ID]) { char bridge_id[32]; br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), bridge_id, sizeof(bridge_id)); fprintf(f, "bridge_id %s ", bridge_id); } if (tb[IFLA_BR_ROOT_ID]) { char root_id[32]; br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), root_id, sizeof(root_id)); fprintf(f, "designated_root %s ", root_id); } if (tb[IFLA_BR_ROOT_PORT]) fprintf(f, "root_port %u ", rta_getattr_u16(tb[IFLA_BR_ROOT_PORT])); if (tb[IFLA_BR_ROOT_PATH_COST]) fprintf(f, "root_path_cost %u ", rta_getattr_u32(tb[IFLA_BR_ROOT_PATH_COST])); if (tb[IFLA_BR_TOPOLOGY_CHANGE]) fprintf(f, "topology_change %u ", rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE])); if (tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED]) fprintf(f, "topology_change_detected %u ", rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED])); if (tb[IFLA_BR_HELLO_TIMER]) { struct timeval tv; __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_HELLO_TIMER])); fprintf(f, "hello_timer %4i.%.2i ", (int)tv.tv_sec, (int)tv.tv_usec/10000); } if (tb[IFLA_BR_TCN_TIMER]) { struct timeval tv; __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_TCN_TIMER])); fprintf(f, "tcn_timer %4i.%.2i ", (int)tv.tv_sec, (int)tv.tv_usec/10000); } if (tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]) { unsigned long jiffies; struct timeval tv; jiffies = rta_getattr_u64(tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]); __jiffies_to_tv(&tv, jiffies); fprintf(f, "topology_change_timer %4i.%.2i ", (int)tv.tv_sec, (int)tv.tv_usec/10000); } if (tb[IFLA_BR_GC_TIMER]) { struct timeval tv; __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_GC_TIMER])); fprintf(f, "gc_timer %4i.%.2i ", (int)tv.tv_sec, (int)tv.tv_usec/10000); } if (tb[IFLA_BR_VLAN_DEFAULT_PVID]) fprintf(f, "vlan_default_pvid %u ", rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID])); if (tb[IFLA_BR_GROUP_FWD_MASK]) fprintf(f, "group_fwd_mask %#x ", rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK])); if (tb[IFLA_BR_GROUP_ADDR]) { SPRINT_BUF(mac); fprintf(f, "group_address %s ", ll_addr_n2a(RTA_DATA(tb[IFLA_BR_GROUP_ADDR]), RTA_PAYLOAD(tb[IFLA_BR_GROUP_ADDR]), 1 /*ARPHDR_ETHER*/, mac, sizeof(mac))); } if (tb[IFLA_BR_MCAST_SNOOPING]) fprintf(f, "mcast_snooping %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING])); if (tb[IFLA_BR_MCAST_ROUTER]) fprintf(f, "mcast_router %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_ROUTER])); if (tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]) fprintf(f, "mcast_query_use_ifaddr %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR])); if (tb[IFLA_BR_MCAST_QUERIER]) fprintf(f, "mcast_querier %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_QUERIER])); if (tb[IFLA_BR_MCAST_HASH_ELASTICITY]) fprintf(f, "mcast_hash_elasticity %u ", rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_ELASTICITY])); if (tb[IFLA_BR_MCAST_HASH_MAX]) fprintf(f, "mcast_hash_max %u ", rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_MAX])); if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]) fprintf(f, "mcast_last_member_count %u ", rta_getattr_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT])); if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]) fprintf(f, "mcast_startup_query_count %u ", rta_getattr_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT])); if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]) fprintf(f, "mcast_last_member_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL])); if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]) fprintf(f, "mcast_membership_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL])); if (tb[IFLA_BR_MCAST_QUERIER_INTVL]) fprintf(f, "mcast_querier_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL])); if (tb[IFLA_BR_MCAST_QUERY_INTVL]) fprintf(f, "mcast_query_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_INTVL])); if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]) fprintf(f, "mcast_query_response_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL])); if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) fprintf(f, "mcast_startup_query_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL])); if (tb[IFLA_BR_NF_CALL_IPTABLES]) fprintf(f, "nf_call_iptables %u ", rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES])); if (tb[IFLA_BR_NF_CALL_IP6TABLES]) fprintf(f, "nf_call_ip6tables %u ", rta_getattr_u8(tb[IFLA_BR_NF_CALL_IP6TABLES])); if (tb[IFLA_BR_NF_CALL_ARPTABLES]) fprintf(f, "nf_call_arptables %u ", rta_getattr_u8(tb[IFLA_BR_NF_CALL_ARPTABLES])); }
void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, FILE *fp, const char *prefix) { if (tb[XFRMA_MARK]) { struct rtattr *rta = tb[XFRMA_MARK]; struct xfrm_mark *m = (struct xfrm_mark *) RTA_DATA(rta); fprintf(fp, "\tmark %d/0x%x\n", m->v, m->m); } if (tb[XFRMA_ALG_AUTH] && !tb[XFRMA_ALG_AUTH_TRUNC]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_AUTH_TRUNC]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH_TRUNC]; xfrm_auth_trunc_print((struct xfrm_algo_auth *) RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_AEAD]) { struct rtattr *rta = tb[XFRMA_ALG_AEAD]; xfrm_aead_print((struct xfrm_algo_aead *)RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_CRYPT]) { struct rtattr *rta = tb[XFRMA_ALG_CRYPT]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_COMP]) { struct rtattr *rta = tb[XFRMA_ALG_COMP]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ENCAP]) { struct xfrm_encap_tmpl *e; char abuf[256]; if (prefix) fputs(prefix, fp); fprintf(fp, "encap "); if (RTA_PAYLOAD(tb[XFRMA_ENCAP]) < sizeof(*e)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } e = (struct xfrm_encap_tmpl *) RTA_DATA(tb[XFRMA_ENCAP]); fprintf(fp, "type "); switch (e->encap_type) { case 1: fprintf(fp, "espinudp-nonike "); break; case 2: fprintf(fp, "espinudp "); break; default: fprintf(fp, "%u ", e->encap_type); break; } fprintf(fp, "sport %u ", ntohs(e->encap_sport)); fprintf(fp, "dport %u ", ntohs(e->encap_dport)); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "addr %s", rt_addr_n2a(family, sizeof(e->encap_oa), &e->encap_oa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_TMPL]) { struct rtattr *rta = tb[XFRMA_TMPL]; xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta), RTA_PAYLOAD(rta), family, fp, prefix); } if (tb[XFRMA_COADDR]) { char abuf[256]; xfrm_address_t *coa; if (prefix) fputs(prefix, fp); fprintf(fp, "coa "); coa = (xfrm_address_t *)RTA_DATA(tb[XFRMA_COADDR]); if (RTA_PAYLOAD(tb[XFRMA_COADDR]) < sizeof(*coa)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*coa), coa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_LASTUSED]) { __u64 lastused; if (prefix) fputs(prefix, fp); fprintf(fp, "lastused "); if (RTA_PAYLOAD(tb[XFRMA_LASTUSED]) < sizeof(lastused)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } lastused = rta_getattr_u64(tb[XFRMA_LASTUSED]); fprintf(fp, "%s", strxf_time(lastused)); fprintf(fp, "%s", _SL_); } }
static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE *) arg; struct genlmsghdr *ghdr; struct rtattr *attrs[TCP_METRICS_ATTR_MAX + 1], *a; int len = n->nlmsg_len; inet_prefix daddr, saddr; int family, i, atype, stype, dlen = 0, slen = 0; if (n->nlmsg_type != genl_family) return -1; len -= NLMSG_LENGTH(GENL_HDRLEN); if (len < 0) return -1; ghdr = NLMSG_DATA(n); if (ghdr->cmd != TCP_METRICS_CMD_GET) return 0; parse_rtattr(attrs, TCP_METRICS_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len); if (attrs[TCP_METRICS_ATTR_ADDR_IPV4]) { if (f.daddr.family && f.daddr.family != AF_INET) return 0; a = attrs[TCP_METRICS_ATTR_ADDR_IPV4]; memcpy(&daddr.data, RTA_DATA(a), 4); daddr.bytelen = 4; family = AF_INET; atype = TCP_METRICS_ATTR_ADDR_IPV4; dlen = RTA_PAYLOAD(a); } else if (attrs[TCP_METRICS_ATTR_ADDR_IPV6]) { if (f.daddr.family && f.daddr.family != AF_INET6) return 0; a = attrs[TCP_METRICS_ATTR_ADDR_IPV6]; memcpy(&daddr.data, RTA_DATA(a), 16); daddr.bytelen = 16; family = AF_INET6; atype = TCP_METRICS_ATTR_ADDR_IPV6; dlen = RTA_PAYLOAD(a); } else { return 0; } if (attrs[TCP_METRICS_ATTR_SADDR_IPV4]) { if (f.saddr.family && f.saddr.family != AF_INET) return 0; a = attrs[TCP_METRICS_ATTR_SADDR_IPV4]; memcpy(&saddr.data, RTA_DATA(a), 4); saddr.bytelen = 4; stype = TCP_METRICS_ATTR_SADDR_IPV4; slen = RTA_PAYLOAD(a); } else if (attrs[TCP_METRICS_ATTR_SADDR_IPV6]) { if (f.saddr.family && f.saddr.family != AF_INET6) return 0; a = attrs[TCP_METRICS_ATTR_SADDR_IPV6]; memcpy(&saddr.data, RTA_DATA(a), 16); saddr.bytelen = 16; stype = TCP_METRICS_ATTR_SADDR_IPV6; slen = RTA_PAYLOAD(a); } if (f.daddr.family && f.daddr.bitlen >= 0 && inet_addr_match(&daddr, &f.daddr, f.daddr.bitlen)) return 0; /* Only check for the source-address if the kernel supports it, * meaning slen != 0. */ if (slen && f.saddr.family && f.saddr.bitlen >= 0 && inet_addr_match(&saddr, &f.saddr, f.saddr.bitlen)) return 0; if (f.flushb) { struct nlmsghdr *fn; TCPM_REQUEST(req2, 128, TCP_METRICS_CMD_DEL, NLM_F_REQUEST); addattr_l(&req2.n, sizeof(req2), atype, &daddr.data, daddr.bytelen); if (slen) addattr_l(&req2.n, sizeof(req2), stype, &saddr.data, saddr.bytelen); if (NLMSG_ALIGN(f.flushp) + req2.n.nlmsg_len > f.flushe) { if (flush_update()) return -1; } fn = (struct nlmsghdr *) (f.flushb + NLMSG_ALIGN(f.flushp)); memcpy(fn, &req2.n, req2.n.nlmsg_len); fn->nlmsg_seq = ++grth.seq; f.flushp = (((char *) fn) + req2.n.nlmsg_len) - f.flushb; f.flushed++; if (show_stats < 2) return 0; } if (f.cmd & (CMD_DEL | CMD_FLUSH)) fprintf(fp, "Deleted "); fprintf(fp, "%s", format_host(family, dlen, &daddr.data)); a = attrs[TCP_METRICS_ATTR_AGE]; if (a) { unsigned long long val = rta_getattr_u64(a); fprintf(fp, " age %llu.%03llusec", val / 1000, val % 1000); } a = attrs[TCP_METRICS_ATTR_TW_TS_STAMP]; if (a) { __s32 val = (__s32) rta_getattr_u32(a); __u32 tsval; a = attrs[TCP_METRICS_ATTR_TW_TSVAL]; tsval = a ? rta_getattr_u32(a) : 0; fprintf(fp, " tw_ts %u/%dsec ago", tsval, val); } a = attrs[TCP_METRICS_ATTR_VALS]; if (a) { struct rtattr *m[TCP_METRIC_MAX + 1 + 1]; unsigned long rtt = 0, rttvar = 0; parse_rtattr_nested(m, TCP_METRIC_MAX + 1, a); for (i = 0; i < TCP_METRIC_MAX + 1; i++) { unsigned long val; a = m[i + 1]; if (!a) continue; if (i != TCP_METRIC_RTT && i != TCP_METRIC_RTT_US && i != TCP_METRIC_RTTVAR && i != TCP_METRIC_RTTVAR_US) { if (metric_name[i]) fprintf(fp, " %s ", metric_name[i]); else fprintf(fp, " metric_%d ", i); } val = rta_getattr_u32(a); switch (i) { case TCP_METRIC_RTT: if (!rtt) rtt = (val * 1000UL) >> 3; break; case TCP_METRIC_RTTVAR: if (!rttvar) rttvar = (val * 1000UL) >> 2; break; case TCP_METRIC_RTT_US: rtt = val >> 3; break; case TCP_METRIC_RTTVAR_US: rttvar = val >> 2; break; case TCP_METRIC_SSTHRESH: case TCP_METRIC_CWND: case TCP_METRIC_REORDERING: default: fprintf(fp, "%lu", val); break; } } if (rtt) fprintf(fp, " rtt %luus", rtt); if (rttvar) fprintf(fp, " rttvar %luus", rttvar); } a = attrs[TCP_METRICS_ATTR_FOPEN_MSS]; if (a) fprintf(fp, " fo_mss %u", rta_getattr_u16(a)); a = attrs[TCP_METRICS_ATTR_FOPEN_SYN_DROPS]; if (a) { __u16 syn_loss = rta_getattr_u16(a); unsigned long long ts; a = attrs[TCP_METRICS_ATTR_FOPEN_SYN_DROP_TS]; ts = a ? rta_getattr_u64(a) : 0; fprintf(fp, " fo_syn_drops %u/%llu.%03llusec ago", syn_loss, ts / 1000, ts % 1000); } a = attrs[TCP_METRICS_ATTR_FOPEN_COOKIE]; if (a) { char cookie[32 + 1]; unsigned char *ptr = RTA_DATA(a); int i, max = RTA_PAYLOAD(a); if (max > 16) max = 16; cookie[0] = 0; for (i = 0; i < max; i++) sprintf(cookie + i + i, "%02x", ptr[i]); fprintf(fp, " fo_cookie %s", cookie); } if (slen) { fprintf(fp, " source %s", format_host(family, slen, &saddr.data)); } fprintf(fp, "\n"); fflush(fp); return 0; }
static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { int dist_size = 0; struct rtattr *tail; struct tc_netem_qopt opt = { .limit = 1000 }; struct tc_netem_corr cor; struct tc_netem_reorder reorder; struct tc_netem_corrupt corrupt; struct tc_netem_gimodel gimodel; struct tc_netem_gemodel gemodel; struct tc_netem_rate rate; __s16 *dist_data = NULL; __u16 loss_type = NETEM_LOSS_UNSPEC; int present[__TCA_NETEM_MAX]; __u64 rate64 = 0; memset(&cor, 0, sizeof(cor)); memset(&reorder, 0, sizeof(reorder)); memset(&corrupt, 0, sizeof(corrupt)); memset(&rate, 0, sizeof(rate)); memset(present, 0, sizeof(present)); for( ; argc > 0; --argc, ++argv) { if (matches(*argv, "limit") == 0) { NEXT_ARG(); if (get_size(&opt.limit, *argv)) { explain1("limit"); return -1; } } else if (matches(*argv, "latency") == 0 || matches(*argv, "delay") == 0) { NEXT_ARG(); if (get_ticks(&opt.latency, *argv)) { explain1("latency"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); if (get_ticks(&opt.jitter, *argv)) { explain1("latency"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); ++present[TCA_NETEM_CORR]; if (get_percent(&cor.delay_corr, *argv)) { explain1("latency"); return -1; } } } } else if (matches(*argv, "loss") == 0 || matches(*argv, "drop") == 0) { if (opt.loss > 0 || loss_type != NETEM_LOSS_UNSPEC) { explain1("duplicate loss argument\n"); return -1; } NEXT_ARG(); /* Old (deprecated) random loss model syntax */ if (isdigit(argv[0][0])) goto random_loss_model; if (!strcmp(*argv, "random")) { NEXT_ARG(); random_loss_model: if (get_percent(&opt.loss, *argv)) { explain1("loss percent"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); ++present[TCA_NETEM_CORR]; if (get_percent(&cor.loss_corr, *argv)) { explain1("loss correllation"); return -1; } } } else if (!strcmp(*argv, "state")) { double p13; NEXT_ARG(); if (parse_percent(&p13, *argv)) { explain1("loss p13"); return -1; } /* set defaults */ set_percent(&gimodel.p13, p13); set_percent(&gimodel.p31, 1. - p13); set_percent(&gimodel.p32, 0); set_percent(&gimodel.p23, 1.); set_percent(&gimodel.p14, 0); loss_type = NETEM_LOSS_GI; if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gimodel.p31, *argv)) { explain1("loss p31"); return -1; } if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gimodel.p32, *argv)) { explain1("loss p32"); return -1; } if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gimodel.p23, *argv)) { explain1("loss p23"); return -1; } if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gimodel.p14, *argv)) { explain1("loss p14"); return -1; } } else if (!strcmp(*argv, "gemodel")) { NEXT_ARG(); if (get_percent(&gemodel.p, *argv)) { explain1("loss gemodel p"); return -1; } /* set defaults */ set_percent(&gemodel.r, 1.); set_percent(&gemodel.h, 0); set_percent(&gemodel.k1, 0); loss_type = NETEM_LOSS_GE; if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gemodel.r, *argv)) { explain1("loss gemodel r"); return -1; } if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gemodel.h, *argv)) { explain1("loss gemodel h"); return -1; } /* netem option is "1-h" but kernel * expects "h". */ gemodel.h = max_percent_value - gemodel.h; if (!NEXT_IS_NUMBER()) continue; NEXT_ARG(); if (get_percent(&gemodel.k1, *argv)) { explain1("loss gemodel k"); return -1; } } else { fprintf(stderr, "Unknown loss parameter: %s\n", *argv); return -1; } } else if (matches(*argv, "ecn") == 0) { present[TCA_NETEM_ECN] = 1; } else if (matches(*argv, "reorder") == 0) { NEXT_ARG(); present[TCA_NETEM_REORDER] = 1; if (get_percent(&reorder.probability, *argv)) { explain1("reorder"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); ++present[TCA_NETEM_CORR]; if (get_percent(&reorder.correlation, *argv)) { explain1("reorder"); return -1; } } } else if (matches(*argv, "corrupt") == 0) { NEXT_ARG(); present[TCA_NETEM_CORRUPT] = 1; if (get_percent(&corrupt.probability, *argv)) { explain1("corrupt"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); ++present[TCA_NETEM_CORR]; if (get_percent(&corrupt.correlation, *argv)) { explain1("corrupt"); return -1; } } } else if (matches(*argv, "gap") == 0) { NEXT_ARG(); if (get_u32(&opt.gap, *argv, 0)) { explain1("gap"); return -1; } } else if (matches(*argv, "duplicate") == 0) { NEXT_ARG(); if (get_percent(&opt.duplicate, *argv)) { explain1("duplicate"); return -1; } if (NEXT_IS_NUMBER()) { NEXT_ARG(); if (get_percent(&cor.dup_corr, *argv)) { explain1("duplicate"); return -1; } } } else if (matches(*argv, "distribution") == 0) { NEXT_ARG(); dist_data = calloc(sizeof(dist_data[0]), MAX_DIST); dist_size = get_distribution(*argv, dist_data, MAX_DIST); if (dist_size <= 0) { free(dist_data); return -1; } } else if (matches(*argv, "rate") == 0) { ++present[TCA_NETEM_RATE]; NEXT_ARG(); if (get_rate64(&rate64, *argv)) { explain1("rate"); return -1; } if (NEXT_IS_SIGNED_NUMBER()) { NEXT_ARG(); if (get_s32(&rate.packet_overhead, *argv, 0)) { explain1("rate"); return -1; } } if (NEXT_IS_NUMBER()) { NEXT_ARG(); if (get_u32(&rate.cell_size, *argv, 0)) { explain1("rate"); return -1; } } if (NEXT_IS_SIGNED_NUMBER()) { NEXT_ARG(); if (get_s32(&rate.cell_overhead, *argv, 0)) { explain1("rate"); return -1; } } } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } } tail = NLMSG_TAIL(n); if (reorder.probability) { if (opt.latency == 0) { fprintf(stderr, "reordering not possible without specifying some delay\n"); explain(); return -1; } if (opt.gap == 0) opt.gap = 1; } else if (opt.gap > 0) { fprintf(stderr, "gap specified without reorder probability\n"); explain(); return -1; } if (present[TCA_NETEM_ECN]) { if (opt.loss <= 0 && loss_type == NETEM_LOSS_UNSPEC) { fprintf(stderr, "ecn requested without loss model\n"); explain(); return -1; } } if (dist_data && (opt.latency == 0 || opt.jitter == 0)) { fprintf(stderr, "distribution specified but no latency and jitter values\n"); explain(); return -1; } if (addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)) < 0) return -1; if (present[TCA_NETEM_CORR] && addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor)) < 0) return -1; if (present[TCA_NETEM_REORDER] && addattr_l(n, 1024, TCA_NETEM_REORDER, &reorder, sizeof(reorder)) < 0) return -1; if (present[TCA_NETEM_ECN] && addattr_l(n, 1024, TCA_NETEM_ECN, &present[TCA_NETEM_ECN], sizeof(present[TCA_NETEM_ECN])) < 0) return -1; if (present[TCA_NETEM_CORRUPT] && addattr_l(n, 1024, TCA_NETEM_CORRUPT, &corrupt, sizeof(corrupt)) < 0) return -1; if (loss_type != NETEM_LOSS_UNSPEC) { struct rtattr *start; start = addattr_nest(n, 1024, TCA_NETEM_LOSS | NLA_F_NESTED); if (loss_type == NETEM_LOSS_GI) { if (addattr_l(n, 1024, NETEM_LOSS_GI, &gimodel, sizeof(gimodel)) < 0) return -1; } else if (loss_type == NETEM_LOSS_GE) { if (addattr_l(n, 1024, NETEM_LOSS_GE, &gemodel, sizeof(gemodel)) < 0) return -1; } else { fprintf(stderr, "loss in the weeds!\n"); return -1; } addattr_nest_end(n, start); } if (present[TCA_NETEM_RATE]) { if (rate64 >= (1ULL << 32)) { if (addattr_l(n, 1024, TCA_NETEM_RATE64, &rate64, sizeof(rate64)) < 0) return -1; rate.rate = ~0U; } else { rate.rate = rate64; } if (addattr_l(n, 1024, TCA_NETEM_RATE, &rate, sizeof(rate)) < 0) return -1; } if (dist_data) { if (addattr_l(n, MAX_DIST * sizeof(dist_data[0]), TCA_NETEM_DELAY_DIST, dist_data, dist_size * sizeof(dist_data[0])) < 0) return -1; free(dist_data); } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; } static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) { const struct tc_netem_corr *cor = NULL; const struct tc_netem_reorder *reorder = NULL; const struct tc_netem_corrupt *corrupt = NULL; const struct tc_netem_gimodel *gimodel = NULL; const struct tc_netem_gemodel *gemodel = NULL; int *ecn = NULL; struct tc_netem_qopt qopt; const struct tc_netem_rate *rate = NULL; int len = RTA_PAYLOAD(opt) - sizeof(qopt); __u64 rate64 = 0; SPRINT_BUF(b1); if (opt == NULL) return 0; if (len < 0) { fprintf(stderr, "options size error\n"); return -1; } memcpy(&qopt, RTA_DATA(opt), sizeof(qopt)); if (len > 0) { struct rtattr *tb[TCA_NETEM_MAX+1]; parse_rtattr(tb, TCA_NETEM_MAX, RTA_DATA(opt) + sizeof(qopt), len); if (tb[TCA_NETEM_CORR]) { if (RTA_PAYLOAD(tb[TCA_NETEM_CORR]) < sizeof(*cor)) return -1; cor = RTA_DATA(tb[TCA_NETEM_CORR]); } if (tb[TCA_NETEM_REORDER]) { if (RTA_PAYLOAD(tb[TCA_NETEM_REORDER]) < sizeof(*reorder)) return -1; reorder = RTA_DATA(tb[TCA_NETEM_REORDER]); } if (tb[TCA_NETEM_CORRUPT]) { if (RTA_PAYLOAD(tb[TCA_NETEM_CORRUPT]) < sizeof(*corrupt)) return -1; corrupt = RTA_DATA(tb[TCA_NETEM_CORRUPT]); } if (tb[TCA_NETEM_LOSS]) { struct rtattr *lb[NETEM_LOSS_MAX + 1]; parse_rtattr_nested(lb, NETEM_LOSS_MAX, tb[TCA_NETEM_LOSS]); if (lb[NETEM_LOSS_GI]) gimodel = RTA_DATA(lb[NETEM_LOSS_GI]); if (lb[NETEM_LOSS_GE]) gemodel = RTA_DATA(lb[NETEM_LOSS_GE]); } if (tb[TCA_NETEM_RATE]) { if (RTA_PAYLOAD(tb[TCA_NETEM_RATE]) < sizeof(*rate)) return -1; rate = RTA_DATA(tb[TCA_NETEM_RATE]); } if (tb[TCA_NETEM_ECN]) { if (RTA_PAYLOAD(tb[TCA_NETEM_ECN]) < sizeof(*ecn)) return -1; ecn = RTA_DATA(tb[TCA_NETEM_ECN]); } if (tb[TCA_NETEM_RATE64]) { if (RTA_PAYLOAD(tb[TCA_NETEM_RATE64]) < sizeof(rate64)) return -1; rate64 = rta_getattr_u64(tb[TCA_NETEM_RATE64]); } } fprintf(f, "limit %d", qopt.limit); if (qopt.latency) { fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1)); if (qopt.jitter) { fprintf(f, " %s", sprint_ticks(qopt.jitter, b1)); if (cor && cor->delay_corr) fprintf(f, " %s", sprint_percent(cor->delay_corr, b1)); } } if (qopt.loss) { fprintf(f, " loss %s", sprint_percent(qopt.loss, b1)); if (cor && cor->loss_corr) fprintf(f, " %s", sprint_percent(cor->loss_corr, b1)); } if (gimodel) { fprintf(f, " loss state p13 %s", sprint_percent(gimodel->p13, b1)); fprintf(f, " p31 %s", sprint_percent(gimodel->p31, b1)); fprintf(f, " p32 %s", sprint_percent(gimodel->p32, b1)); fprintf(f, " p23 %s", sprint_percent(gimodel->p23, b1)); fprintf(f, " p14 %s", sprint_percent(gimodel->p14, b1)); } if (gemodel) { fprintf(f, " loss gemodel p %s", sprint_percent(gemodel->p, b1)); fprintf(f, " r %s", sprint_percent(gemodel->r, b1)); fprintf(f, " 1-h %s", sprint_percent(max_percent_value - gemodel->h, b1)); fprintf(f, " 1-k %s", sprint_percent(gemodel->k1, b1)); } if (qopt.duplicate) { fprintf(f, " duplicate %s", sprint_percent(qopt.duplicate, b1)); if (cor && cor->dup_corr) fprintf(f, " %s", sprint_percent(cor->dup_corr, b1)); } if (reorder && reorder->probability) { fprintf(f, " reorder %s", sprint_percent(reorder->probability, b1)); if (reorder->correlation) fprintf(f, " %s", sprint_percent(reorder->correlation, b1)); } if (corrupt && corrupt->probability) { fprintf(f, " corrupt %s", sprint_percent(corrupt->probability, b1)); if (corrupt->correlation) fprintf(f, " %s", sprint_percent(corrupt->correlation, b1)); } if (rate && rate->rate) { if (rate64) fprintf(f, " rate %s", sprint_rate(rate64, b1)); else fprintf(f, " rate %s", sprint_rate(rate->rate, b1)); if (rate->packet_overhead) fprintf(f, " packetoverhead %d", rate->packet_overhead); if (rate->cell_size) fprintf(f, " cellsize %u", rate->cell_size); if (rate->cell_overhead) fprintf(f, " celloverhead %d", rate->cell_overhead); } if (ecn) fprintf(f, " ecn "); if (qopt.gap) fprintf(f, " gap %lu", (unsigned long)qopt.gap); return 0; } struct qdisc_util netem_qdisc_util = { .id = "netem", .parse_qopt = netem_parse_opt, .print_qopt = netem_print_opt, };
static int process(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct genlmsghdr *ghdr; struct rtattr *attrs[MACSEC_ATTR_MAX + 1]; struct rtattr *attrs_secy[MACSEC_SECY_ATTR_MAX + 1]; int len = n->nlmsg_len; int ifindex; __u64 sci; __u8 encoding_sa; if (n->nlmsg_type != genl_family) return -1; len -= NLMSG_LENGTH(GENL_HDRLEN); if (len < 0) return -1; ghdr = NLMSG_DATA(n); if (ghdr->cmd != MACSEC_CMD_GET_TXSC) return 0; parse_rtattr(attrs, MACSEC_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len); if (!validate_dump(attrs)) { fprintf(stderr, "incomplete dump message\n"); return -1; } ifindex = rta_getattr_u32(attrs[MACSEC_ATTR_IFINDEX]); parse_rtattr_nested(attrs_secy, MACSEC_SECY_ATTR_MAX + 1, attrs[MACSEC_ATTR_SECY]); if (!validate_secy_dump(attrs_secy)) { fprintf(stderr, "incomplete dump message\n"); return -1; } sci = rta_getattr_u64(attrs_secy[MACSEC_SECY_ATTR_SCI]); encoding_sa = rta_getattr_u8(attrs_secy[MACSEC_SECY_ATTR_ENCODING_SA]); if (filter.ifindex && ifindex != filter.ifindex) return 0; if (filter.sci && sci != filter.sci) return 0; open_json_object(NULL); print_uint(PRINT_ANY, "ifindex", "%u: ", ifindex); print_color_string(PRINT_ANY, COLOR_IFNAME, "ifname", "%s: ", ll_index_to_name(ifindex)); print_attrs(attrs_secy); print_tx_sc(" ", sci, encoding_sa, attrs[MACSEC_ATTR_TXSC_STATS], attrs[MACSEC_ATTR_SECY_STATS], attrs[MACSEC_ATTR_TXSA_LIST]); if (attrs[MACSEC_ATTR_RXSC_LIST]) print_rxsc_list(attrs[MACSEC_ATTR_RXSC_LIST]); close_json_object(); return 0; }
static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { if (!tb) return; if (tb[IFLA_BR_FORWARD_DELAY]) print_uint(PRINT_ANY, "forward_delay", "forward_delay %u ", rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY])); if (tb[IFLA_BR_HELLO_TIME]) print_uint(PRINT_ANY, "hello_time", "hello_time %u ", rta_getattr_u32(tb[IFLA_BR_HELLO_TIME])); if (tb[IFLA_BR_MAX_AGE]) print_uint(PRINT_ANY, "max_age", "max_age %u ", rta_getattr_u32(tb[IFLA_BR_MAX_AGE])); if (tb[IFLA_BR_AGEING_TIME]) print_uint(PRINT_ANY, "ageing_time", "ageing_time %u ", rta_getattr_u32(tb[IFLA_BR_AGEING_TIME])); if (tb[IFLA_BR_STP_STATE]) print_uint(PRINT_ANY, "stp_state", "stp_state %u ", rta_getattr_u32(tb[IFLA_BR_STP_STATE])); if (tb[IFLA_BR_PRIORITY]) print_uint(PRINT_ANY, "priority", "priority %u ", rta_getattr_u16(tb[IFLA_BR_PRIORITY])); if (tb[IFLA_BR_VLAN_FILTERING]) print_uint(PRINT_ANY, "vlan_filtering", "vlan_filtering %u ", rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING])); if (tb[IFLA_BR_VLAN_PROTOCOL]) { SPRINT_BUF(b1); print_string(PRINT_ANY, "vlan_protocol", "vlan_protocol %s ", ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]), b1, sizeof(b1))); } if (tb[IFLA_BR_BRIDGE_ID]) { char bridge_id[32]; br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), bridge_id, sizeof(bridge_id)); print_string(PRINT_ANY, "bridge_id", "bridge_id %s ", bridge_id); } if (tb[IFLA_BR_ROOT_ID]) { char root_id[32]; br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), root_id, sizeof(root_id)); print_string(PRINT_ANY, "root_id", "designated_root %s ", root_id); } if (tb[IFLA_BR_ROOT_PORT]) print_uint(PRINT_ANY, "root_port", "root_port %u ", rta_getattr_u16(tb[IFLA_BR_ROOT_PORT])); if (tb[IFLA_BR_ROOT_PATH_COST]) print_uint(PRINT_ANY, "root_path_cost", "root_path_cost %u ", rta_getattr_u32(tb[IFLA_BR_ROOT_PATH_COST])); if (tb[IFLA_BR_TOPOLOGY_CHANGE]) print_uint(PRINT_ANY, "topology_change", "topology_change %u ", rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE])); if (tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED]) print_uint(PRINT_ANY, "topology_change_detected", "topology_change_detected %u ", rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED])); if (tb[IFLA_BR_HELLO_TIMER]) _bridge_print_timer(f, "hello_timer", tb[IFLA_BR_HELLO_TIMER]); if (tb[IFLA_BR_TCN_TIMER]) _bridge_print_timer(f, "tcn_timer", tb[IFLA_BR_TCN_TIMER]); if (tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]) _bridge_print_timer(f, "topology_change_timer", tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]); if (tb[IFLA_BR_GC_TIMER]) _bridge_print_timer(f, "gc_timer", tb[IFLA_BR_GC_TIMER]); if (tb[IFLA_BR_VLAN_DEFAULT_PVID]) print_uint(PRINT_ANY, "vlan_default_pvid", "vlan_default_pvid %u ", rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID])); if (tb[IFLA_BR_VLAN_STATS_ENABLED]) print_uint(PRINT_ANY, "vlan_stats_enabled", "vlan_stats_enabled %u ", rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_ENABLED])); if (tb[IFLA_BR_GROUP_FWD_MASK]) print_0xhex(PRINT_ANY, "group_fwd_mask", "group_fwd_mask %#llx ", rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK])); if (tb[IFLA_BR_GROUP_ADDR]) { SPRINT_BUF(mac); print_string(PRINT_ANY, "group_addr", "group_address %s ", ll_addr_n2a(RTA_DATA(tb[IFLA_BR_GROUP_ADDR]), RTA_PAYLOAD(tb[IFLA_BR_GROUP_ADDR]), 1 /*ARPHDR_ETHER*/, mac, sizeof(mac))); } if (tb[IFLA_BR_MCAST_SNOOPING]) print_uint(PRINT_ANY, "mcast_snooping", "mcast_snooping %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING])); if (tb[IFLA_BR_MCAST_ROUTER]) print_uint(PRINT_ANY, "mcast_router", "mcast_router %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_ROUTER])); if (tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]) print_uint(PRINT_ANY, "mcast_query_use_ifaddr", "mcast_query_use_ifaddr %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR])); if (tb[IFLA_BR_MCAST_QUERIER]) print_uint(PRINT_ANY, "mcast_querier", "mcast_querier %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_QUERIER])); if (tb[IFLA_BR_MCAST_HASH_ELASTICITY]) print_uint(PRINT_ANY, "mcast_hash_elasticity", "mcast_hash_elasticity %u ", rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_ELASTICITY])); if (tb[IFLA_BR_MCAST_HASH_MAX]) print_uint(PRINT_ANY, "mcast_hash_max", "mcast_hash_max %u ", rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_MAX])); if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]) print_uint(PRINT_ANY, "mcast_last_member_cnt", "mcast_last_member_count %u ", rta_getattr_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT])); if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]) print_uint(PRINT_ANY, "mcast_startup_query_cnt", "mcast_startup_query_count %u ", rta_getattr_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT])); if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]) print_lluint(PRINT_ANY, "mcast_last_member_intvl", "mcast_last_member_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL])); if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]) print_lluint(PRINT_ANY, "mcast_membership_intvl", "mcast_membership_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL])); if (tb[IFLA_BR_MCAST_QUERIER_INTVL]) print_lluint(PRINT_ANY, "mcast_querier_intvl", "mcast_querier_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL])); if (tb[IFLA_BR_MCAST_QUERY_INTVL]) print_lluint(PRINT_ANY, "mcast_query_intvl", "mcast_query_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_INTVL])); if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]) print_lluint(PRINT_ANY, "mcast_query_response_intvl", "mcast_query_response_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL])); if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) print_lluint(PRINT_ANY, "mcast_startup_query_intvl", "mcast_startup_query_interval %llu ", rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL])); if (tb[IFLA_BR_MCAST_STATS_ENABLED]) print_uint(PRINT_ANY, "mcast_stats_enabled", "mcast_stats_enabled %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED])); if (tb[IFLA_BR_MCAST_IGMP_VERSION]) print_uint(PRINT_ANY, "mcast_igmp_version", "mcast_igmp_version %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION])); if (tb[IFLA_BR_MCAST_MLD_VERSION]) print_uint(PRINT_ANY, "mcast_mld_version", "mcast_mld_version %u ", rta_getattr_u8(tb[IFLA_BR_MCAST_MLD_VERSION])); if (tb[IFLA_BR_NF_CALL_IPTABLES]) print_uint(PRINT_ANY, "nf_call_iptables", "nf_call_iptables %u ", rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES])); if (tb[IFLA_BR_NF_CALL_IP6TABLES]) print_uint(PRINT_ANY, "nf_call_ip6tables", "nf_call_ip6tables %u ", rta_getattr_u8(tb[IFLA_BR_NF_CALL_IP6TABLES])); if (tb[IFLA_BR_NF_CALL_ARPTABLES]) print_uint(PRINT_ANY, "nf_call_arptables", "nf_call_arptables %u ", rta_getattr_u8(tb[IFLA_BR_NF_CALL_ARPTABLES])); }
static int gre_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); struct { struct nlmsghdr n; struct ifinfomsg i; char buf[16384]; } req = { .n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)), .n.nlmsg_flags = NLM_F_REQUEST, .n.nlmsg_type = RTM_GETLINK, .i.ifi_family = preferred_family, .i.ifi_index = ifi->ifi_index, }; struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *greinfo[IFLA_GRE_MAX + 1]; __u16 iflags = 0; __u16 oflags = 0; unsigned int ikey = 0; unsigned int okey = 0; unsigned int saddr = 0; unsigned int daddr = 0; unsigned int link = 0; __u8 pmtudisc = 1; __u8 ttl = 0; __u8 tos = 0; int len; __u16 encaptype = 0; __u16 encapflags = 0; __u16 encapsport = 0; __u16 encapdport = 0; __u8 metadata = 0; __u8 ignore_df = 0; __u32 fwmark = 0; __u32 erspan_idx = 0; __u8 keepalive_ret = 0; __u32 keepalive_interv = 0; if (!(n->nlmsg_flags & NLM_F_CREATE)) { if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); return -1; } len = req.n.nlmsg_len; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) goto get_failed; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); if (!tb[IFLA_LINKINFO]) goto get_failed; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); if (!linkinfo[IFLA_INFO_DATA]) goto get_failed; parse_rtattr_nested(greinfo, IFLA_GRE_MAX, linkinfo[IFLA_INFO_DATA]); if (greinfo[IFLA_GRE_IKEY]) ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]); if (greinfo[IFLA_GRE_OKEY]) okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]); if (greinfo[IFLA_GRE_IFLAGS]) iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]); if (greinfo[IFLA_GRE_OFLAGS]) oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]); if (greinfo[IFLA_GRE_LOCAL]) saddr = rta_getattr_u32(greinfo[IFLA_GRE_LOCAL]); if (greinfo[IFLA_GRE_REMOTE]) daddr = rta_getattr_u32(greinfo[IFLA_GRE_REMOTE]); if (greinfo[IFLA_GRE_PMTUDISC]) pmtudisc = rta_getattr_u8( greinfo[IFLA_GRE_PMTUDISC]); if (greinfo[IFLA_GRE_TTL]) ttl = rta_getattr_u8(greinfo[IFLA_GRE_TTL]); if (greinfo[IFLA_GRE_TOS]) tos = rta_getattr_u8(greinfo[IFLA_GRE_TOS]); if (greinfo[IFLA_GRE_LINK]) link = rta_getattr_u8(greinfo[IFLA_GRE_LINK]); if (greinfo[IFLA_GRE_ENCAP_TYPE]) encaptype = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_TYPE]); if (greinfo[IFLA_GRE_ENCAP_FLAGS]) encapflags = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_FLAGS]); if (greinfo[IFLA_GRE_ENCAP_SPORT]) encapsport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_SPORT]); if (greinfo[IFLA_GRE_ENCAP_DPORT]) encapdport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_DPORT]); if (greinfo[IFLA_GRE_COLLECT_METADATA]) metadata = 1; if (greinfo[IFLA_GRE_IGNORE_DF]) ignore_df = !!rta_getattr_u8(greinfo[IFLA_GRE_IGNORE_DF]); if (greinfo[IFLA_GRE_FWMARK]) fwmark = rta_getattr_u32(greinfo[IFLA_GRE_FWMARK]); if (greinfo[IFLA_GRE_ERSPAN_INDEX]) erspan_idx = rta_getattr_u32(greinfo[IFLA_GRE_ERSPAN_INDEX]); } while (argc > 0) { if (!matches(*argv, "key")) { unsigned int uval; NEXT_ARG(); iflags |= GRE_KEY; oflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0) < 0) { fprintf(stderr, "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } uval = htonl(uval); } ikey = okey = uval; } else if (!matches(*argv, "ikey")) { unsigned int uval; NEXT_ARG(); iflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0) < 0) { fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } uval = htonl(uval); } ikey = uval; } else if (!matches(*argv, "okey")) { unsigned int uval; NEXT_ARG(); oflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0) < 0) { fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } uval = htonl(uval); } okey = uval; } else if (!matches(*argv, "seq")) { iflags |= GRE_SEQ; oflags |= GRE_SEQ; } else if (!matches(*argv, "iseq")) { iflags |= GRE_SEQ; } else if (!matches(*argv, "oseq")) { oflags |= GRE_SEQ; } else if (!matches(*argv, "csum")) { iflags |= GRE_CSUM; oflags |= GRE_CSUM; } else if (!matches(*argv, "icsum")) { iflags |= GRE_CSUM; } else if (!matches(*argv, "ocsum")) { oflags |= GRE_CSUM; } else if (!matches(*argv, "nopmtudisc")) { pmtudisc = 0; } else if (!matches(*argv, "pmtudisc")) { pmtudisc = 1; } else if (!matches(*argv, "remote")) { NEXT_ARG(); if (strcmp(*argv, "any")) daddr = get_addr32(*argv); } else if (!matches(*argv, "local")) { NEXT_ARG(); if (strcmp(*argv, "any")) saddr = get_addr32(*argv); } else if (!matches(*argv, "dev")) { NEXT_ARG(); link = if_nametoindex(*argv); if (link == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", *argv); exit(-1); } } else if (!matches(*argv, "ttl") || !matches(*argv, "hoplimit")) { unsigned int uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL\n", *argv); if (uval > 255) invarg("TTL must be <= 255\n", *argv); ttl = uval; } } else if (!matches(*argv, "tos") || !matches(*argv, "tclass") || !matches(*argv, "dsfield")) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); tos = uval; } else tos = 1; } else if (strcmp(*argv, "noencap") == 0) { encaptype = TUNNEL_ENCAP_NONE; } else if (strcmp(*argv, "encap") == 0) { NEXT_ARG(); if (strcmp(*argv, "fou") == 0) encaptype = TUNNEL_ENCAP_FOU; else if (strcmp(*argv, "gue") == 0) encaptype = TUNNEL_ENCAP_GUE; else if (strcmp(*argv, "none") == 0) encaptype = TUNNEL_ENCAP_NONE; else invarg("Invalid encap type.", *argv); } else if (strcmp(*argv, "encap-sport") == 0) { NEXT_ARG(); if (strcmp(*argv, "auto") == 0) encapsport = 0; else if (get_u16(&encapsport, *argv, 0)) invarg("Invalid source port.", *argv); } else if (strcmp(*argv, "encap-dport") == 0) { NEXT_ARG(); if (get_u16(&encapdport, *argv, 0)) invarg("Invalid destination port.", *argv); } else if (strcmp(*argv, "encap-csum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_CSUM; } else if (strcmp(*argv, "noencap-csum") == 0) { encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM; } else if (strcmp(*argv, "encap-udp6-csum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_CSUM6; } else if (strcmp(*argv, "noencap-udp6-csum") == 0) { encapflags |= ~TUNNEL_ENCAP_FLAG_CSUM6; } else if (strcmp(*argv, "encap-remcsum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM; } else if (strcmp(*argv, "noencap-remcsum") == 0) { encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM; } else if (strcmp(*argv, "external") == 0) { metadata = 1; } else if (strcmp(*argv, "ignore-df") == 0) { ignore_df = 1; } else if (strcmp(*argv, "noignore-df") == 0) { /* *only the lsb is significant, use 2 for presence */ ignore_df = 2; } else if (strcmp(*argv, "fwmark") == 0) { NEXT_ARG(); if (get_u32(&fwmark, *argv, 0)) invarg("invalid fwmark\n", *argv); } else if (strcmp(*argv, "erspan") == 0) { NEXT_ARG(); if (get_u32(&erspan_idx, *argv, 0)) invarg("invalid erspan index\n", *argv); if (erspan_idx & ~((1<<20) - 1) || erspan_idx == 0) invarg("erspan index must be > 0 and <= 20-bit\n", *argv); } else if (!matches(*argv, "keepalive")) { __u64 interv; __u32 ret; NEXT_ARG(); if (strcmp(*argv, "auto") != 0) { if (get_u32(&interv, *argv, 0)) invarg("invalid KeepAlive time interval\n", *argv); keepalive_interv = interv; } NEXT_ARG(); if (strcmp(*argv, "auto") != 0) { if (get_unsigned(&ret, *argv, 0)) invarg("invalid KeepAlive retries\n", *argv); if (ret > 255) invarg("KeepAlive retries must be <= 255\n", *argv); keepalive_ret = ret; } } else usage(); argc--; argv++; } if (!ikey && IN_MULTICAST(ntohl(daddr))) { ikey = daddr; iflags |= GRE_KEY; } if (!okey && IN_MULTICAST(ntohl(daddr))) { okey = daddr; oflags |= GRE_KEY; } if (IN_MULTICAST(ntohl(daddr)) && !saddr) { fprintf(stderr, "A broadcast tunnel requires a source address.\n"); return -1; } if (!metadata) { addattr32(n, 1024, IFLA_GRE_IKEY, ikey); addattr32(n, 1024, IFLA_GRE_OKEY, okey); addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4); addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4); addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1); if (link) addattr32(n, 1024, IFLA_GRE_LINK, link); addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1); addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1); addattr32(n, 1024, IFLA_GRE_FWMARK, fwmark); if (erspan_idx != 0) addattr32(n, 1024, IFLA_GRE_ERSPAN_INDEX, erspan_idx); if (keepalive_interv) { addattr32(n, 1024, IFLA_GRE_KEEPALIVE_INTERVAL, keepalive_interv); addattr8(n, 1024, IFLA_GRE_KEEPALIVE_RETRIES, keepalive_ret); } } else { addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0); } addattr16(n, 1024, IFLA_GRE_ENCAP_TYPE, encaptype); addattr16(n, 1024, IFLA_GRE_ENCAP_FLAGS, encapflags); addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport)); addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport)); if (ignore_df) addattr8(n, 1024, IFLA_GRE_IGNORE_DF, ignore_df & 1); return 0; } static void gre_print_direct_opt(FILE *f, struct rtattr *tb[]) { char s2[64]; const char *local = "any"; const char *remote = "any"; unsigned int iflags = 0; unsigned int oflags = 0; if (tb[IFLA_GRE_REMOTE]) { unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]); if (addr) remote = format_host(AF_INET, 4, &addr); } print_string(PRINT_ANY, "remote", "remote %s ", remote); if (tb[IFLA_GRE_LOCAL]) { unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]); if (addr) local = format_host(AF_INET, 4, &addr); } print_string(PRINT_ANY, "local", "local %s ", local); if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) { unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]); const char *n = if_indextoname(link, s2); if (n) print_string(PRINT_ANY, "link", "dev %s ", n); else print_uint(PRINT_ANY, "link_index", "dev %u ", link); } if (tb[IFLA_GRE_TTL]) { __u8 ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]); if (ttl) print_int(PRINT_ANY, "ttl", "ttl %d ", ttl); else print_int(PRINT_JSON, "ttl", NULL, ttl); } else { print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); } if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) { int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]); if (is_json_context()) { SPRINT_BUF(b1); snprintf(b1, sizeof(b1), "0x%x", tos); print_string(PRINT_JSON, "tos", NULL, b1); } else { fputs("tos ", f); if (tos == 1) fputs("inherit ", f); else fprintf(f, "0x%x ", tos); } } if (tb[IFLA_GRE_KEEPALIVE_INTERVAL]) { unsigned long interval; unsigned int retries; interval = rta_getattr_u64(tb[IFLA_GRE_KEEPALIVE_INTERVAL]); retries = rta_getattr_u8(tb[IFLA_GRE_KEEPALIVE_RETRIES]); if (interval) { print_int(PRINT_ANY, "keepalive", "keepalive interval %d ", interval); print_int(PRINT_ANY, "keepalive", "retries %d ", retries); } else { print_int(PRINT_JSON, "keepalive", NULL, interval); } } else { print_string(PRINT_FP, NULL, "keepalive %s ", "auto"); } if (tb[IFLA_GRE_PMTUDISC]) { if (!rta_getattr_u8(tb[IFLA_GRE_PMTUDISC])) print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false); else print_bool(PRINT_JSON, "pmtudisc", NULL, true); } if (tb[IFLA_GRE_IFLAGS]) iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]); if (tb[IFLA_GRE_OFLAGS]) oflags = rta_getattr_u16(tb[IFLA_GRE_OFLAGS]); if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) { inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2)); print_string(PRINT_ANY, "ikey", "ikey %s ", s2); } if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) { inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2)); print_string(PRINT_ANY, "okey", "okey %s ", s2); } if (iflags & GRE_SEQ) print_bool(PRINT_ANY, "iseq", "iseq ", true); if (oflags & GRE_SEQ) print_bool(PRINT_ANY, "oseq", "oseq ", true); if (iflags & GRE_CSUM) print_bool(PRINT_ANY, "icsum", "icsum ", true); if (oflags & GRE_CSUM) print_bool(PRINT_ANY, "ocsum", "ocsum ", true); if (tb[IFLA_GRE_FWMARK]) { __u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]); if (fwmark) { snprintf(s2, sizeof(s2), "0x%x", fwmark); print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2); } } }
/* device creation */ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { if (!tb) return; if (tb[IFLA_MACSEC_SCI]) { if (is_json_context()) { SPRINT_BUF(b1); snprintf(b1, sizeof(b1), "%016llx", ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI]))); print_string(PRINT_JSON, "sci", NULL, b1); } else { fprintf(f, "sci %016llx ", ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI]))); } } print_flag(tb, "protect", IFLA_MACSEC_PROTECT); if (tb[IFLA_MACSEC_CIPHER_SUITE]) { __u64 csid = rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]); print_string(PRINT_ANY, "cipher_suite", "cipher %s ", cs_id_to_name(csid)); } if (tb[IFLA_MACSEC_ICV_LEN]) { if (is_json_context()) { char b2[4]; snprintf(b2, sizeof(b2), "%hhu", rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN])); print_uint(PRINT_JSON, "icv_len", NULL, atoi(b2)); } else { fprintf(f, "icvlen %hhu ", rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN])); } } if (tb[IFLA_MACSEC_ENCODING_SA]) { if (is_json_context()) { char b2[4]; snprintf(b2, sizeof(b2), "%hhu", rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA])); print_uint(PRINT_JSON, "encoding_sa", NULL, atoi(b2)); } else { fprintf(f, "encodingsa %hhu ", rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA])); } } if (tb[IFLA_MACSEC_VALIDATION]) { __u8 val = rta_getattr_u8(tb[IFLA_MACSEC_VALIDATION]); print_string(PRINT_ANY, "validation", "validate %s ", validate_str[val]); } const char *inc_sci, *es, *replay; if (is_json_context()) { inc_sci = "inc_sci"; replay = "replay_protect"; es = "es"; } else { inc_sci = "send_sci"; es = "end_station"; replay = "replay"; } print_flag(tb, "encrypt", IFLA_MACSEC_ENCRYPT); print_flag(tb, inc_sci, IFLA_MACSEC_INC_SCI); print_flag(tb, es, IFLA_MACSEC_ES); print_flag(tb, "scb", IFLA_MACSEC_SCB); print_flag(tb, replay, IFLA_MACSEC_REPLAY_PROTECT); if (tb[IFLA_MACSEC_WINDOW]) print_int(PRINT_ANY, "window", "window %d ", rta_getattr_u32(tb[IFLA_MACSEC_WINDOW])); }
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; }
void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, FILE *fp, const char *prefix) { if (tb[XFRMA_MARK]) { struct rtattr *rta = tb[XFRMA_MARK]; struct xfrm_mark *m = (struct xfrm_mark *) RTA_DATA(rta); fprintf(fp, "\tmark %#x/%#x", m->v, m->m); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_ALG_AUTH] && !tb[XFRMA_ALG_AUTH_TRUNC]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_AUTH_TRUNC]) { struct rtattr *rta = tb[XFRMA_ALG_AUTH_TRUNC]; xfrm_auth_trunc_print((struct xfrm_algo_auth *) RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_AEAD]) { struct rtattr *rta = tb[XFRMA_ALG_AEAD]; xfrm_aead_print((struct xfrm_algo_aead *)RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_CRYPT]) { struct rtattr *rta = tb[XFRMA_ALG_CRYPT]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ALG_COMP]) { struct rtattr *rta = tb[XFRMA_ALG_COMP]; xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta), XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_ENCAP]) { struct xfrm_encap_tmpl *e; char abuf[256]; if (prefix) fputs(prefix, fp); fprintf(fp, "encap "); if (RTA_PAYLOAD(tb[XFRMA_ENCAP]) < sizeof(*e)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } e = (struct xfrm_encap_tmpl *) RTA_DATA(tb[XFRMA_ENCAP]); fprintf(fp, "type "); switch (e->encap_type) { case 1: fprintf(fp, "espinudp-nonike "); break; case 2: fprintf(fp, "espinudp "); break; default: fprintf(fp, "%u ", e->encap_type); break; } fprintf(fp, "sport %u ", ntohs(e->encap_sport)); fprintf(fp, "dport %u ", ntohs(e->encap_dport)); memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "addr %s", rt_addr_n2a(family, sizeof(e->encap_oa), &e->encap_oa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_TMPL]) { struct rtattr *rta = tb[XFRMA_TMPL]; xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix); } if (tb[XFRMA_COADDR]) { char abuf[256]; xfrm_address_t *coa; if (prefix) fputs(prefix, fp); fprintf(fp, "coa "); coa = (xfrm_address_t *)RTA_DATA(tb[XFRMA_COADDR]); if (RTA_PAYLOAD(tb[XFRMA_COADDR]) < sizeof(*coa)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } memset(abuf, '\0', sizeof(abuf)); fprintf(fp, "%s", rt_addr_n2a(family, sizeof(*coa), coa, abuf, sizeof(abuf))); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_LASTUSED]) { __u64 lastused; if (prefix) fputs(prefix, fp); fprintf(fp, "lastused "); if (RTA_PAYLOAD(tb[XFRMA_LASTUSED]) < sizeof(lastused)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } lastused = rta_getattr_u64(tb[XFRMA_LASTUSED]); fprintf(fp, "%s", strxf_time(lastused)); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_REPLAY_VAL]) { struct xfrm_replay_state *replay; if (prefix) fputs(prefix, fp); fprintf(fp, "anti-replay context: "); if (RTA_PAYLOAD(tb[XFRMA_REPLAY_VAL]) < sizeof(*replay)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } replay = (struct xfrm_replay_state *)RTA_DATA(tb[XFRMA_REPLAY_VAL]); fprintf(fp, "seq 0x%x, oseq 0x%x, bitmap 0x%08x", replay->seq, replay->oseq, replay->bitmap); fprintf(fp, "%s", _SL_); } if (tb[XFRMA_REPLAY_ESN_VAL]) { struct xfrm_replay_state_esn *replay; unsigned int i, j; if (prefix) fputs(prefix, fp); fprintf(fp, "anti-replay esn context:"); if (RTA_PAYLOAD(tb[XFRMA_REPLAY_ESN_VAL]) < sizeof(*replay)) { fprintf(fp, "(ERROR truncated)"); fprintf(fp, "%s", _SL_); return; } fprintf(fp, "%s", _SL_); replay = (struct xfrm_replay_state_esn *)RTA_DATA(tb[XFRMA_REPLAY_ESN_VAL]); if (prefix) fputs(prefix, fp); fprintf(fp, " seq-hi 0x%x, seq 0x%x, oseq-hi 0x%0x, oseq 0x%0x", replay->seq_hi, replay->seq, replay->oseq_hi, replay->oseq); fprintf(fp, "%s", _SL_); if (prefix) fputs(prefix, fp); fprintf(fp, " replay_window %u, bitmap-length %u", replay->replay_window, replay->bmp_len); for (i = replay->bmp_len, j = 0; i; i--) { if (j++ % 8 == 0) { fprintf(fp, "%s", _SL_); if (prefix) fputs(prefix, fp); fprintf(fp, " "); } fprintf(fp, "%08x ", replay->bmp[i - 1]); } fprintf(fp, "%s", _SL_); } }
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 void print_ndtparams(struct rtattr *tpb[]) { if (tpb[NDTPA_IFINDEX]) { __u32 ifindex = rta_getattr_u32(tpb[NDTPA_IFINDEX]); print_string(PRINT_FP, NULL, " dev ", NULL); print_color_string(PRINT_ANY, COLOR_IFNAME, "dev", "%s ", ll_index_to_name(ifindex)); print_nl(); } print_string(PRINT_FP, NULL, " ", NULL); if (tpb[NDTPA_REFCNT]) { __u32 refcnt = rta_getattr_u32(tpb[NDTPA_REFCNT]); print_uint(PRINT_ANY, "refcnt", "refcnt %u ", refcnt); } if (tpb[NDTPA_REACHABLE_TIME]) { __u64 reachable = rta_getattr_u64(tpb[NDTPA_REACHABLE_TIME]); print_u64(PRINT_ANY, "reachable", "reachable %llu ", reachable); } if (tpb[NDTPA_BASE_REACHABLE_TIME]) { __u64 breachable = rta_getattr_u64(tpb[NDTPA_BASE_REACHABLE_TIME]); print_u64(PRINT_ANY, "base_reachable", "base_reachable %llu ", breachable); } if (tpb[NDTPA_RETRANS_TIME]) { __u64 retrans = rta_getattr_u64(tpb[NDTPA_RETRANS_TIME]); print_u64(PRINT_ANY, "retrans", "retrans %llu ", retrans); } print_string(PRINT_FP, NULL, "%s ", _SL_); if (tpb[NDTPA_GC_STALETIME]) { __u64 gc_stale = rta_getattr_u64(tpb[NDTPA_GC_STALETIME]); print_u64(PRINT_ANY, "gc_stale", "gc_stale %llu ", gc_stale); } if (tpb[NDTPA_DELAY_PROBE_TIME]) { __u64 delay_probe = rta_getattr_u64(tpb[NDTPA_DELAY_PROBE_TIME]); print_u64(PRINT_ANY, "delay_probe", "delay_probe %llu ", delay_probe); } if (tpb[NDTPA_QUEUE_LEN]) { __u32 queue = rta_getattr_u32(tpb[NDTPA_QUEUE_LEN]); print_uint(PRINT_ANY, "queue", "queue %u ", queue); } print_string(PRINT_FP, NULL, "%s ", _SL_); if (tpb[NDTPA_APP_PROBES]) { __u32 aprobe = rta_getattr_u32(tpb[NDTPA_APP_PROBES]); print_uint(PRINT_ANY, "app_probes", "app_probes %u ", aprobe); } if (tpb[NDTPA_UCAST_PROBES]) { __u32 uprobe = rta_getattr_u32(tpb[NDTPA_UCAST_PROBES]); print_uint(PRINT_ANY, "ucast_probes", "ucast_probes %u ", uprobe); } if (tpb[NDTPA_MCAST_PROBES]) { __u32 mprobe = rta_getattr_u32(tpb[NDTPA_MCAST_PROBES]); print_uint(PRINT_ANY, "mcast_probes", "mcast_probes %u ", mprobe); } print_string(PRINT_FP, NULL, "%s ", _SL_); if (tpb[NDTPA_ANYCAST_DELAY]) { __u64 anycast_delay = rta_getattr_u64(tpb[NDTPA_ANYCAST_DELAY]); print_u64(PRINT_ANY, "anycast_delay", "anycast_delay %llu ", anycast_delay); } if (tpb[NDTPA_PROXY_DELAY]) { __u64 proxy_delay = rta_getattr_u64(tpb[NDTPA_PROXY_DELAY]); print_u64(PRINT_ANY, "proxy_delay", "proxy_delay %llu ", proxy_delay); } if (tpb[NDTPA_PROXY_QLEN]) { __u32 pqueue = rta_getattr_u32(tpb[NDTPA_PROXY_QLEN]); print_uint(PRINT_ANY, "proxy_queue", "proxy_queue %u ", pqueue); } if (tpb[NDTPA_LOCKTIME]) { __u64 locktime = rta_getattr_u64(tpb[NDTPA_LOCKTIME]); print_u64(PRINT_ANY, "locktime", "locktime %llu ", locktime); } print_nl(); }