static int dsmark_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) { struct rtattr *tb[TCA_DSMARK_MAX+1]; if (!opt) return 0; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, TCA_DSMARK_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)); if (tb[TCA_DSMARK_MASK]) { if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK])) fprintf(stderr,"dsmark: empty mask\n"); else fprintf(f,"mask 0x%02x ", rta_getattr_u8(tb[TCA_DSMARK_MASK])); } if (tb[TCA_DSMARK_VALUE]) { if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE])) fprintf(stderr,"dsmark: empty value\n"); else fprintf(f,"value 0x%02x ", rta_getattr_u8(tb[TCA_DSMARK_VALUE])); } if (tb[TCA_DSMARK_INDICES]) { if (RTA_PAYLOAD(tb[TCA_DSMARK_INDICES]) < sizeof(__u16)) fprintf(stderr,"dsmark: indices too short\n"); else fprintf(f,"indices 0x%04x ", rta_getattr_u16(tb[TCA_DSMARK_INDICES])); } if (tb[TCA_DSMARK_DEFAULT_INDEX]) { if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX]) < sizeof(__u16)) fprintf(stderr,"dsmark: default_index too short\n"); else fprintf(f,"default_index 0x%04x ", rta_getattr_u16(tb[TCA_DSMARK_DEFAULT_INDEX])); } if (tb[TCA_DSMARK_SET_TC_INDEX]) fprintf(f,"set_tc_index "); return 0; }
static int print_ila_mapping(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE *)arg; struct genlmsghdr *ghdr; struct rtattr *tb[ILA_ATTR_MAX + 1]; int len = n->nlmsg_len; if (n->nlmsg_type != genl_family) return 0; len -= NLMSG_LENGTH(GENL_HDRLEN); if (len < 0) return -1; ghdr = NLMSG_DATA(n); parse_rtattr(tb, ILA_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len); print_ila_locid(fp, ILA_ATTR_LOCATOR_MATCH, tb, ADDR_BUF_SIZE); print_ila_locid(fp, ILA_ATTR_LOCATOR, tb, ADDR_BUF_SIZE); if (tb[ILA_ATTR_IFINDEX]) fprintf(fp, "%-16s", ll_index_to_name(rta_getattr_u32( tb[ILA_ATTR_IFINDEX]))); else fprintf(fp, "%-10s ", "-"); if (tb[ILA_ATTR_CSUM_MODE]) fprintf(fp, "%s", ila_csum_mode2name(rta_getattr_u8( tb[ILA_ATTR_CSUM_MODE]))); else fprintf(fp, "%-10s ", "-"); if (tb[ILA_ATTR_IDENT_TYPE]) fprintf(fp, "%s", ila_ident_type2name(rta_getattr_u8( tb[ILA_ATTR_IDENT_TYPE]))); else fprintf(fp, "-"); fprintf(fp, "\n"); return 0; }
static void print_slave_state(FILE *f, struct rtattr *tb) { unsigned int state = rta_getattr_u8(tb); if (state >= sizeof(slave_states) / sizeof(slave_states[0])) fprintf(f, "state %d ", state); else fprintf(f, "state %s ", slave_states[state]); }
static void print_slave_mii_status(FILE *f, struct rtattr *tb) { unsigned int status = rta_getattr_u8(tb); if (status >= sizeof(slave_mii_status) / sizeof(slave_mii_status[0])) fprintf(f, "mii_status %d ", status); else fprintf(f, "mii_status %s ", slave_mii_status[status]); }
static void print_linkmode(FILE *f, struct rtattr *tb) { unsigned int mode = rta_getattr_u8(tb); if (mode >= sizeof(link_modes) / sizeof(link_modes[0])) fprintf(f, "mode %d ", mode); else fprintf(f, "mode %s ", link_modes[mode]); }
static void print_tx_sc(const char *prefix, __u64 sci, __u8 encoding_sa, struct rtattr *txsc_stats, struct rtattr *secy_stats, struct rtattr *sa) { struct rtattr *sa_attr[MACSEC_SA_ATTR_MAX + 1]; struct rtattr *a; int rem; print_string(PRINT_FP, NULL, "%s", prefix); print_0xhex(PRINT_ANY, "sci", "TXSC: %016llx", ntohll(sci)); print_uint(PRINT_ANY, "encoding_sa", " on SA %d\n", encoding_sa); print_secy_stats(prefix, secy_stats); print_txsc_stats(prefix, txsc_stats); open_json_array(PRINT_JSON, "sa_list"); rem = RTA_PAYLOAD(sa); for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) { bool state; open_json_object(NULL); parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]); print_string(PRINT_FP, NULL, "%s", prefix); print_string(PRINT_FP, NULL, "%s", prefix); print_uint(PRINT_ANY, "an", "%d:", rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN])); print_uint(PRINT_ANY, "pn", " PN %u,", rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN])); print_bool(PRINT_JSON, "active", NULL, state); print_string(PRINT_FP, NULL, " state %s,", state ? "on" : "off"); print_key(sa_attr[MACSEC_SA_ATTR_KEYID]); print_txsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]); close_json_object(); } close_json_array(PRINT_JSON, NULL); }
static void print_slave_state(FILE *f, struct rtattr *tb) { unsigned int state = rta_getattr_u8(tb); if (state >= ARRAY_SIZE(slave_states)) print_int(PRINT_ANY, "state_index", "state %d ", state); else print_string(PRINT_ANY, "state", "state %s ", slave_states[state]); }
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_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 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 bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { SPRINT_BUF(b1); if (!tb) return; if (tb[IFLA_BOND_SLAVE_STATE]) print_slave_state(f, tb[IFLA_BOND_SLAVE_STATE]); if (tb[IFLA_BOND_SLAVE_MII_STATUS]) print_slave_mii_status(f, tb[IFLA_BOND_SLAVE_MII_STATUS]); if (tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT]) print_int(PRINT_ANY, "link_failure_count", "link_failure_count %d ", rta_getattr_u32(tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT])); if (tb[IFLA_BOND_SLAVE_PERM_HWADDR]) print_string(PRINT_ANY, "perm_hwaddr", "perm_hwaddr %s ", ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_SLAVE_PERM_HWADDR]), RTA_PAYLOAD(tb[IFLA_BOND_SLAVE_PERM_HWADDR]), 0, b1, sizeof(b1))); if (tb[IFLA_BOND_SLAVE_QUEUE_ID]) print_int(PRINT_ANY, "queue_id", "queue_id %d ", rta_getattr_u16(tb[IFLA_BOND_SLAVE_QUEUE_ID])); if (tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]) print_int(PRINT_ANY, "ad_aggregator_id", "ad_aggregator_id %d ", rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])); if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]) print_int(PRINT_ANY, "ad_actor_oper_port_state", "ad_actor_oper_port_state %d ", rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE])); if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]) print_int(PRINT_ANY, "ad_partner_oper_port_state", "ad_partner_oper_port_state %d ", rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE])); }
static void print_slave_mii_status(FILE *f, struct rtattr *tb) { unsigned int status = rta_getattr_u8(tb); if (status >= ARRAY_SIZE(slave_mii_status)) print_int(PRINT_ANY, "mii_status_index", "mii_status %d ", status); else print_string(PRINT_ANY, "mii_status", "mii_status %s ", slave_mii_status[status]); }
static void print_flag(struct rtattr *attrs[], const char *desc, int field) { __u8 flag; if (!attrs[field]) return; flag = rta_getattr_u8(attrs[field]); if (is_json_context()) print_bool(PRINT_JSON, desc, NULL, flag); else { print_string(PRINT_FP, NULL, "%s ", desc); print_string(PRINT_FP, NULL, "%s ", flag ? "on" : "off"); } }
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_encap_ila(FILE *fp, struct rtattr *encap) { struct rtattr *tb[ILA_ATTR_MAX+1]; parse_rtattr_nested(tb, ILA_ATTR_MAX, encap); if (tb[ILA_ATTR_LOCATOR]) { char abuf[ADDR64_BUF_SIZE]; addr64_n2a(*(__u64 *)RTA_DATA(tb[ILA_ATTR_LOCATOR]), abuf, sizeof(abuf)); fprintf(fp, " %s ", abuf); } if (tb[ILA_ATTR_CSUM_MODE]) fprintf(fp, " csum-mode %s ", ila_csum_mode2name(rta_getattr_u8(tb[ILA_ATTR_CSUM_MODE]))); }
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))); } }
static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr) { struct rtattr *inet6_attr; struct rtattr *tb[IFLA_INET6_MAX + 1]; inet6_attr = parse_rtattr_one_nested(AF_INET6, af_spec_attr); if (!inet6_attr) return; parse_rtattr_nested(tb, IFLA_INET6_MAX, inet6_attr); if (tb[IFLA_INET6_ADDR_GEN_MODE]) { switch (rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE])) { case IN6_ADDR_GEN_MODE_EUI64: fprintf(fp, "addrgenmode eui64 "); break; case IN6_ADDR_GEN_MODE_NONE: fprintf(fp, "addrgenmode none "); break; } } }
int prio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) { int i; struct tc_prio_qopt *qopt; struct rtattr *tb[TCA_PRIO_MAX+1]; if (opt == NULL) return 0; if (parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt))) return -1; fprintf(f, "bands %u priomap ", qopt->bands); for (i = 0; i <= TC_PRIO_MAX; i++) fprintf(f, " %d", qopt->priomap[i]); if (tb[TCA_PRIO_MQ]) fprintf(f, " multiqueue: %s ", rta_getattr_u8(tb[TCA_PRIO_MQ]) ? "on" : "off"); 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; }
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])); }
static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct { struct nlmsghdr n; struct ifinfomsg i; char buf[2048]; } req; struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1]; int len; __u32 link = 0; __u32 laddr = 0; __u32 raddr = 0; __u8 ttl = 0; __u8 tos = 0; __u8 pmtudisc = 1; __u16 iflags = 0; __u8 proto = 0; struct in6_addr ip6rdprefix; __u16 ip6rdprefixlen = 0; __u32 ip6rdrelayprefix = 0; __u16 ip6rdrelayprefixlen = 0; memset(&ip6rdprefix, 0, sizeof(ip6rdprefix)); if (!(n->nlmsg_flags & NLM_F_CREATE)) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETLINK; req.i.ifi_family = preferred_family; req.i.ifi_index = ifi->ifi_index; if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 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(iptuninfo, IFLA_IPTUN_MAX, linkinfo[IFLA_INFO_DATA]); if (iptuninfo[IFLA_IPTUN_LOCAL]) laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]); if (iptuninfo[IFLA_IPTUN_REMOTE]) raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]); if (iptuninfo[IFLA_IPTUN_TTL]) ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]); if (iptuninfo[IFLA_IPTUN_TOS]) tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]); if (iptuninfo[IFLA_IPTUN_PMTUDISC]) pmtudisc = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]); if (iptuninfo[IFLA_IPTUN_FLAGS]) iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]); if (iptuninfo[IFLA_IPTUN_LINK]) link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]); if (iptuninfo[IFLA_IPTUN_PROTO]) proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]); if (iptuninfo[IFLA_IPTUN_6RD_PREFIX]) memcpy(&ip6rdprefix, RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]), sizeof(laddr)); if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]) ip6rdprefixlen = rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]); if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]) ip6rdrelayprefix = rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]); if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) ip6rdrelayprefixlen = rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); } while (argc > 0) { if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) raddr = get_addr32(*argv); else raddr = 0; } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) laddr = get_addr32(*argv); else laddr = 0; } else if (matches(*argv, "dev") == 0) { NEXT_ARG(); link = if_nametoindex(*argv); if (link == 0) invarg("\"dev\" is invalid", *argv); } else if (strcmp(*argv, "ttl") == 0 || strcmp(*argv, "hoplimit") == 0) { NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_u8(&ttl, *argv, 0)) invarg("invalid TTL\n", *argv); } else ttl = 0; } else if (strcmp(*argv, "tos") == 0 || strcmp(*argv, "tclass") == 0 || matches(*argv, "dsfield") == 0) { __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, "nopmtudisc") == 0) { pmtudisc = 0; } else if (strcmp(*argv, "pmtudisc") == 0) { pmtudisc = 1; } else if (strcmp(lu->id, "sit") == 0 && strcmp(*argv, "isatap") == 0) { iflags |= SIT_ISATAP; } else if (strcmp(lu->id, "sit") == 0 && strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipv6/ipv4") == 0 || strcmp(*argv, "ip6ip") == 0) proto = IPPROTO_IPV6; else if (strcmp(*argv, "ipv4/ipv4") == 0 || strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip4ip4") == 0) proto = IPPROTO_IPIP; else if (strcmp(*argv, "any/ipv4") == 0 || strcmp(*argv, "any") == 0) proto = 0; else invarg("Cannot guess tunnel mode.", *argv); } else if (strcmp(*argv, "6rd-prefix") == 0) { inet_prefix prefix; NEXT_ARG(); if (get_prefix(&prefix, *argv, AF_INET6)) invarg("invalid 6rd_prefix\n", *argv); memcpy(&ip6rdprefix, prefix.data, 16); ip6rdprefixlen = prefix.bitlen; } else if (strcmp(*argv, "6rd-relay_prefix") == 0) { inet_prefix prefix; NEXT_ARG(); if (get_prefix(&prefix, *argv, AF_INET)) invarg("invalid 6rd-relay_prefix\n", *argv); memcpy(&ip6rdrelayprefix, prefix.data, 4); ip6rdrelayprefixlen = prefix.bitlen; } else if (strcmp(*argv, "6rd-reset") == 0) { inet_prefix prefix; get_prefix(&prefix, "2002::", AF_INET6); memcpy(&ip6rdprefix, prefix.data, 16); ip6rdprefixlen = 16; ip6rdrelayprefix = 0; ip6rdrelayprefixlen = 0; } else usage(strcmp(lu->id, "sit") == 0); argc--, argv++; } if (ttl && pmtudisc == 0) { fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n"); exit(-1); } addattr32(n, 1024, IFLA_IPTUN_LINK, link); addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr); addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr); addattr8(n, 1024, IFLA_IPTUN_TTL, ttl); addattr8(n, 1024, IFLA_IPTUN_TOS, tos); addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc); if (strcmp(lu->id, "sit") == 0) { addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags); addattr8(n, 1024, IFLA_IPTUN_PROTO, proto); if (ip6rdprefixlen) { addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX, &ip6rdprefix, sizeof(ip6rdprefix)); addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN, ip6rdprefixlen); addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX, ip6rdrelayprefix); addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, ip6rdrelayprefixlen); } } return 0; }
static int gre_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct { struct nlmsghdr n; struct ifinfomsg i; char buf[1024]; } req; struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); 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 ikey = 0; unsigned okey = 0; struct in6_addr raddr = IN6ADDR_ANY_INIT; struct in6_addr laddr = IN6ADDR_ANY_INIT; unsigned link = 0; unsigned flowinfo = 0; unsigned flags = 0; __u8 hop_limit = DEFAULT_TNL_HOP_LIMIT; __u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; int len; if (!(n->nlmsg_flags & NLM_F_CREATE)) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETLINK; req.i.ifi_family = preferred_family; req.i.ifi_index = ifi->ifi_index; if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 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]) memcpy(&laddr, RTA_DATA(greinfo[IFLA_GRE_LOCAL]), sizeof(laddr)); if (greinfo[IFLA_GRE_REMOTE]) memcpy(&raddr, RTA_DATA(greinfo[IFLA_GRE_REMOTE]), sizeof(raddr)); if (greinfo[IFLA_GRE_TTL]) hop_limit = rta_getattr_u8(greinfo[IFLA_GRE_TTL]); if (greinfo[IFLA_GRE_LINK]) link = rta_getattr_u32(greinfo[IFLA_GRE_LINK]); if (greinfo[IFLA_GRE_ENCAP_LIMIT]) encap_limit = rta_getattr_u8(greinfo[IFLA_GRE_ENCAP_LIMIT]); if (greinfo[IFLA_GRE_FLOWINFO]) flowinfo = rta_getattr_u32(greinfo[IFLA_GRE_FLOWINFO]); if (greinfo[IFLA_GRE_FLAGS]) flags = rta_getattr_u32(greinfo[IFLA_GRE_FLAGS]); } while (argc > 0) { if (!matches(*argv, "key")) { unsigned 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\"\n"); exit(-1); } uval = htonl(uval); } ikey = okey = uval; } else if (!matches(*argv, "ikey")) { unsigned 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 of \"ikey\"\n"); exit(-1); } uval = htonl(uval); } ikey = uval; } else if (!matches(*argv, "okey")) { unsigned 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 of \"okey\"\n"); 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, "remote")) { inet_prefix addr; NEXT_ARG(); get_prefix(&addr, *argv, preferred_family); if (addr.family == AF_UNSPEC) invarg("\"remote\" address family is AF_UNSPEC", *argv); memcpy(&raddr, &addr.data, sizeof(raddr)); } else if (!matches(*argv, "local")) { inet_prefix addr; NEXT_ARG(); get_prefix(&addr, *argv, preferred_family); if (addr.family == AF_UNSPEC) invarg("\"local\" address family is AF_UNSPEC", *argv); memcpy(&laddr, &addr.data, sizeof(laddr)); } 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")) { __u8 uval; NEXT_ARG(); if (get_u8(&uval, *argv, 0)) invarg("invalid TTL", *argv); hop_limit = uval; } else if (!matches(*argv, "tos") || !matches(*argv, "tclass") || !matches(*argv, "dsfield")) { __u8 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") == 0) flags |= IP6_TNL_F_USE_ORIG_TCLASS; else { if (get_u8(&uval, *argv, 16)) invarg("invalid TClass", *argv); flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS; flags &= ~IP6_TNL_F_USE_ORIG_TCLASS; } } else if (strcmp(*argv, "flowlabel") == 0 || strcmp(*argv, "fl") == 0) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") == 0) flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; else { if (get_u32(&uval, *argv, 16)) invarg("invalid Flowlabel", *argv); if (uval > 0xFFFFF) invarg("invalid Flowlabel", *argv); flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL; flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; } } else if (strcmp(*argv, "dscp") == 0) { NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) invarg("not inherit", *argv); flags |= IP6_TNL_F_RCV_DSCP_COPY; } else usage(); argc--; argv++; } 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, &laddr, sizeof(laddr)); addattr_l(n, 1024, IFLA_GRE_REMOTE, &raddr, sizeof(raddr)); if (link) addattr32(n, 1024, IFLA_GRE_LINK, link); addattr_l(n, 1024, IFLA_GRE_TTL, &hop_limit, 1); addattr_l(n, 1024, IFLA_GRE_ENCAP_LIMIT, &encap_limit, 1); addattr_l(n, 1024, IFLA_GRE_FLOWINFO, &flowinfo, 4); addattr_l(n, 1024, IFLA_GRE_FLAGS, &flowinfo, 4); 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; }
static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { char s1[1024]; char s2[64]; const char *local = "any"; const char *remote = "any"; unsigned iflags = 0; unsigned oflags = 0; if (!tb) return; if (tb[IFLA_GRE_REMOTE]) { unsigned addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]); if (addr) remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); } fprintf(f, "remote %s ", remote); if (tb[IFLA_GRE_LOCAL]) { unsigned addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]); if (addr) local = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); } fprintf(f, "local %s ", local); if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) { unsigned link = rta_getattr_u32(tb[IFLA_GRE_LINK]); const char *n = if_indextoname(link, s2); if (n) fprintf(f, "dev %s ", n); else fprintf(f, "dev %u ", link); } if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL])) fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_GRE_TTL])); else fprintf(f, "ttl inherit "); if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) { int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]); fputs("tos ", f); if (tos == 1) fputs("inherit ", f); else fprintf(f, "0x%x ", tos); } if (tb[IFLA_GRE_PMTUDISC] && !rta_getattr_u8(tb[IFLA_GRE_PMTUDISC])) fputs("nopmtudisc ", f); 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)); fprintf(f, "ikey %s ", s2); } if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) { inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2)); fprintf(f, "okey %s ", s2); } if (iflags & GRE_SEQ) fputs("iseq ", f); if (oflags & GRE_SEQ) fputs("oseq ", f); if (iflags & GRE_CSUM) fputs("icsum ", f); if (oflags & GRE_CSUM) fputs("ocsum ", f); if (tb[IFLA_GRE_ENCAP_TYPE] && *(__u16 *)RTA_DATA(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) { __u16 type = rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]); __u16 flags = rta_getattr_u16(tb[IFLA_GRE_ENCAP_FLAGS]); __u16 sport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_SPORT]); __u16 dport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_DPORT]); fputs("encap ", f); switch (type) { case TUNNEL_ENCAP_FOU: fputs("fou ", f); break; case TUNNEL_ENCAP_GUE: fputs("gue ", f); break; default: fputs("unknown ", f); break; } if (sport == 0) fputs("encap-sport auto ", f); else fprintf(f, "encap-sport %u", ntohs(sport)); fprintf(f, "encap-dport %u ", ntohs(dport)); if (flags & TUNNEL_ENCAP_FLAG_CSUM) fputs("encap-csum ", f); else fputs("noencap-csum ", f); if (flags & TUNNEL_ENCAP_FLAG_CSUM6) fputs("encap-csum6 ", f); else fputs("noencap-csum6 ", f); if (flags & TUNNEL_ENCAP_FLAG_REMCSUM) fputs("encap-remcsum ", f); else fputs("noencap-remcsum ", f); } }
static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { char s1[1024]; char s2[64]; const char *local = "any"; const char *remote = "any"; unsigned iflags = 0; unsigned oflags = 0; unsigned flags = 0; unsigned flowinfo = 0; struct in6_addr in6_addr_any = IN6ADDR_ANY_INIT; if (!tb) return; if (tb[IFLA_GRE_FLAGS]) flags = rta_getattr_u32(tb[IFLA_GRE_FLAGS]); if (tb[IFLA_GRE_FLOWINFO]) flags = rta_getattr_u32(tb[IFLA_GRE_FLOWINFO]); if (tb[IFLA_GRE_REMOTE]) { struct in6_addr addr; memcpy(&addr, RTA_DATA(tb[IFLA_GRE_REMOTE]), sizeof(addr)); if (memcmp(&addr, &in6_addr_any, sizeof(addr))) remote = format_host(AF_INET6, sizeof(addr), &addr, s1, sizeof(s1)); } fprintf(f, "remote %s ", remote); if (tb[IFLA_GRE_LOCAL]) { struct in6_addr addr; memcpy(&addr, RTA_DATA(tb[IFLA_GRE_LOCAL]), sizeof(addr)); if (memcmp(&addr, &in6_addr_any, sizeof(addr))) local = format_host(AF_INET6, sizeof(addr), &addr, s1, sizeof(s1)); } fprintf(f, "local %s ", local); if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) { unsigned link = rta_getattr_u32(tb[IFLA_GRE_LINK]); const char *n = if_indextoname(link, s2); if (n) fprintf(f, "dev %s ", n); else fprintf(f, "dev %u ", link); } if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL])) fprintf(f, "hoplimit %d ", rta_getattr_u8(tb[IFLA_GRE_TTL])); if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) fprintf(f, "encaplimit none "); else if (tb[IFLA_GRE_ENCAP_LIMIT]) { int encap_limit = rta_getattr_u8(tb[IFLA_GRE_ENCAP_LIMIT]); fprintf(f, "encaplimit %d ", encap_limit); } if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) fprintf(f, "flowlabel inherit "); else fprintf(f, "flowlabel 0x%05x ", ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL)); if (flags & IP6_TNL_F_RCV_DSCP_COPY) fprintf(f, "dscp inherit "); 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)); fprintf(f, "ikey %s ", s2); } if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) { inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2)); fprintf(f, "okey %s ", s2); } if (iflags & GRE_SEQ) fputs("iseq ", f); if (oflags & GRE_SEQ) fputs("oseq ", f); if (iflags & GRE_CSUM) fputs("icsum ", f); if (oflags & GRE_CSUM) fputs("ocsum ", f); }
static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { unsigned ifindex; if (!tb) return; if (tb[IFLA_BOND_MODE]) { const char *mode = get_name(mode_tbl, rta_getattr_u8(tb[IFLA_BOND_MODE])); fprintf(f, "mode %s ", mode); } if (tb[IFLA_BOND_ACTIVE_SLAVE] && (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) { char buf[IFNAMSIZ]; const char *n = if_indextoname(ifindex, buf); if (n) fprintf(f, "active_slave %s ", n); else fprintf(f, "active_slave %u ", ifindex); } if (tb[IFLA_BOND_MIIMON]) fprintf(f, "miimon %u ", rta_getattr_u32(tb[IFLA_BOND_MIIMON])); if (tb[IFLA_BOND_UPDELAY]) fprintf(f, "updelay %u ", rta_getattr_u32(tb[IFLA_BOND_UPDELAY])); if (tb[IFLA_BOND_DOWNDELAY]) fprintf(f, "downdelay %u ", rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY])); if (tb[IFLA_BOND_USE_CARRIER]) fprintf(f, "use_carrier %u ", rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER])); if (tb[IFLA_BOND_ARP_INTERVAL]) fprintf(f, "arp_interval %u ", rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL])); if (tb[IFLA_BOND_ARP_IP_TARGET]) { struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1]; char buf[INET_ADDRSTRLEN]; int i; parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS, tb[IFLA_BOND_ARP_IP_TARGET]); if (iptb[0]) fprintf(f, "arp_ip_target "); for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { if (iptb[i]) fprintf(f, "%s", rt_addr_n2a(AF_INET, RTA_PAYLOAD(iptb[i]), RTA_DATA(iptb[i]), buf, INET_ADDRSTRLEN)); if (i < BOND_MAX_ARP_TARGETS-1 && iptb[i+1]) fprintf(f, ","); } if (iptb[0]) fprintf(f, " "); } if (tb[IFLA_BOND_ARP_VALIDATE]) { const char *arp_validate = get_name(arp_validate_tbl, rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE])); fprintf(f, "arp_validate %s ", arp_validate); } if (tb[IFLA_BOND_ARP_ALL_TARGETS]) { const char *arp_all_targets = get_name(arp_all_targets_tbl, rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS])); fprintf(f, "arp_all_targets %s ", arp_all_targets); } if (tb[IFLA_BOND_PRIMARY] && (ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]))) { char buf[IFNAMSIZ]; const char *n = if_indextoname(ifindex, buf); if (n) fprintf(f, "primary %s ", n); else fprintf(f, "primary %u ", ifindex); } if (tb[IFLA_BOND_PRIMARY_RESELECT]) { const char *primary_reselect = get_name(primary_reselect_tbl, rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT])); fprintf(f, "primary_reselect %s ", primary_reselect); } if (tb[IFLA_BOND_FAIL_OVER_MAC]) { const char *fail_over_mac = get_name(fail_over_mac_tbl, rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC])); fprintf(f, "fail_over_mac %s ", fail_over_mac); } if (tb[IFLA_BOND_XMIT_HASH_POLICY]) { const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl, rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY])); fprintf(f, "xmit_hash_policy %s ", xmit_hash_policy); } if (tb[IFLA_BOND_RESEND_IGMP]) fprintf(f, "resend_igmp %u ", rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP])); if (tb[IFLA_BOND_NUM_PEER_NOTIF]) fprintf(f, "num_grat_arp %u ", rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF])); if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE]) fprintf(f, "all_slaves_active %u ", rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE])); if (tb[IFLA_BOND_MIN_LINKS]) fprintf(f, "min_links %u ", rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS])); if (tb[IFLA_BOND_LP_INTERVAL]) fprintf(f, "lp_interval %u ", rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL])); if (tb[IFLA_BOND_PACKETS_PER_SLAVE]) fprintf(f, "packets_per_slave %u ", rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE])); if (tb[IFLA_BOND_AD_LACP_RATE]) { const char *lacp_rate = get_name(lacp_rate_tbl, rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE])); fprintf(f, "lacp_rate %s ", lacp_rate); } if (tb[IFLA_BOND_AD_SELECT]) { const char *ad_select = get_name(ad_select_tbl, rta_getattr_u8(tb[IFLA_BOND_AD_SELECT])); fprintf(f, "ad_select %s ", ad_select); } if (tb[IFLA_BOND_AD_INFO]) { struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1]; parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX, tb[IFLA_BOND_AD_INFO]); if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR]) fprintf(f, "ad_aggregator %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR])); if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS]) fprintf(f, "ad_num_ports %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS])); if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]) fprintf(f, "ad_actor_key %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])); if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]) fprintf(f, "ad_partner_key %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])); if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) { unsigned char *p = RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]); SPRINT_BUF(b); fprintf(f, "ad_partner_mac %s ", ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b))); } } if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) { fprintf(f, "ad_actor_sys_prio %u ", rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO])); } if (tb[IFLA_BOND_AD_USER_PORT_KEY]) { fprintf(f, "ad_user_port_key %u ", rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY])); } if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) { /* We assume the l2 address is an Ethernet MAC address */ SPRINT_BUF(b1); fprintf(f, "ad_actor_system %s ", ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), 1 /*ARPHDR_ETHER*/, b1, sizeof(b1))); } if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) { fprintf(f, "tlb_dynamic_lb %u ", rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB])); } }
static int gre_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct { struct nlmsghdr n; struct ifinfomsg i; char buf[16384]; } req; struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); 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 ikey = 0; unsigned okey = 0; unsigned saddr = 0; unsigned daddr = 0; unsigned 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; if (!(n->nlmsg_flags & NLM_F_CREATE)) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETLINK; req.i.ifi_family = preferred_family; req.i.ifi_index = ifi->ifi_index; 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]); } while (argc > 0) { if (!matches(*argv, "key")) { unsigned 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 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 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 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 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; } 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); 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)); return 0; }
static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { char s1[1024]; char s2[64]; const char *local = "any"; const char *remote = "any"; if (!tb) return; if (tb[IFLA_IPTUN_REMOTE]) { unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]); if (addr) remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); } fprintf(f, "remote %s ", remote); if (tb[IFLA_IPTUN_LOCAL]) { unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]); if (addr) local = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); } fprintf(f, "local %s ", local); if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) { unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); const char *n = if_indextoname(link, s2); if (n) fprintf(f, "dev %s ", n); else fprintf(f, "dev %u ", link); } if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL])) fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL])); else fprintf(f, "ttl inherit "); if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) { int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]); fputs("tos ", f); if (tos == 1) fputs("inherit ", f); else fprintf(f, "0x%x ", tos); } if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC])) fprintf(f, "pmtudisc "); else fprintf(f, "nopmtudisc "); if (tb[IFLA_IPTUN_FLAGS]) { __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]); if (iflags & SIT_ISATAP) fprintf(f, "isatap "); } if (tb[IFLA_IPTUN_6RD_PREFIXLEN] && *(__u16 *)RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIXLEN])) { __u16 prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]); __u16 relayprefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); __u32 relayprefix = rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]); printf("6rd-prefix %s/%u ", inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]), s1, sizeof(s1)), prefixlen); if (relayprefix) { printf("6rd-relay_prefix %s/%u ", format_host(AF_INET, 4, &relayprefix, s1, sizeof(s1)), relayprefixlen); } } }
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_neigh(struct nlmsghdr *n, void *arg) { FILE *fp = (FILE *)arg; struct ndmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[NDA_MAX+1]; static int logit = 1; __u8 protocol = 0; if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH && n->nlmsg_type != RTM_GETNEIGH) { fprintf(stderr, "Not RTM_NEWNEIGH: %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; } if (filter.flushb && n->nlmsg_type != RTM_NEWNEIGH) return 0; if (filter.family && filter.family != r->ndm_family) return 0; if (filter.index && filter.index != r->ndm_ifindex) return 0; if (!(filter.state&r->ndm_state) && !(r->ndm_flags & NTF_PROXY) && !(r->ndm_flags & NTF_EXT_LEARNED) && (r->ndm_state || !(filter.state&0x100)) && (r->ndm_family != AF_DECnet)) return 0; if (filter.master && !(n->nlmsg_flags & NLM_F_DUMP_FILTERED)) { if (logit) { logit = 0; fprintf(fp, "\nWARNING: Kernel does not support filtering by master device\n\n"); } } parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); if (inet_addr_match_rta(&filter.pfx, tb[NDA_DST])) return 0; if (tb[NDA_PROTOCOL]) protocol = rta_getattr_u8(tb[NDA_PROTOCOL]); if (filter.protocol && filter.protocol != protocol) return 0; if (filter.unused_only && tb[NDA_CACHEINFO]) { struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]); if (ci->ndm_refcnt) 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_DELNEIGH; 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; } open_json_object(NULL); if (n->nlmsg_type == RTM_DELNEIGH) print_bool(PRINT_ANY, "deleted", "Deleted ", true); else if (n->nlmsg_type == RTM_GETNEIGH) print_null(PRINT_ANY, "miss", "%s ", "miss"); if (tb[NDA_DST]) { const char *dst; int family = r->ndm_family; if (family == AF_BRIDGE) { if (RTA_PAYLOAD(tb[NDA_DST]) == sizeof(struct in6_addr)) family = AF_INET6; else family = AF_INET; } dst = format_host_rta(family, tb[NDA_DST]); print_color_string(PRINT_ANY, ifa_family_color(family), "dst", "%s ", dst); } if (!filter.index && r->ndm_ifindex) { if (!is_json_context()) fprintf(fp, "dev "); print_color_string(PRINT_ANY, COLOR_IFNAME, "dev", "%s ", ll_index_to_name(r->ndm_ifindex)); } if (tb[NDA_LLADDR]) { const char *lladdr; SPRINT_BUF(b1); lladdr = ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR]), ll_index_to_type(r->ndm_ifindex), b1, sizeof(b1)); if (!is_json_context()) fprintf(fp, "lladdr "); print_color_string(PRINT_ANY, COLOR_MAC, "lladdr", "%s", lladdr); } if (r->ndm_flags & NTF_ROUTER) print_null(PRINT_ANY, "router", " %s", "router"); if (r->ndm_flags & NTF_PROXY) print_null(PRINT_ANY, "proxy", " %s", "proxy"); if (r->ndm_flags & NTF_EXT_LEARNED) print_null(PRINT_ANY, "extern_learn", " %s ", "extern_learn"); if (show_stats) { if (tb[NDA_CACHEINFO]) print_cacheinfo(RTA_DATA(tb[NDA_CACHEINFO])); if (tb[NDA_PROBES]) print_uint(PRINT_ANY, "probes", " probes %u", rta_getattr_u32(tb[NDA_PROBES])); } if (r->ndm_state) print_neigh_state(r->ndm_state); if (protocol) { SPRINT_BUF(b1); print_string(PRINT_ANY, "protocol", " proto %s ", rtnl_rtprot_n2a(protocol, b1, sizeof(b1))); } print_string(PRINT_FP, NULL, "\n", ""); close_json_object(); fflush(stdout); return 0; }