diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c index 0e0ccccb6a..825497fff3 100644 --- a/zebra/debug_nl.c +++ b/zebra/debug_nl.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -576,6 +577,86 @@ const char *nhm_rta2str(int type) } } +const char *frh_rta2str(int type) +{ + switch (type) { + case FRA_DST: + return "DST"; + case FRA_SRC: + return "SRC"; + case FRA_IIFNAME: + return "IIFNAME"; + case FRA_GOTO: + return "GOTO"; + case FRA_UNUSED2: + return "UNUSED2"; + case FRA_PRIORITY: + return "PRIORITY"; + case FRA_UNUSED3: + return "UNUSED3"; + case FRA_UNUSED4: + return "UNUSED4"; + case FRA_UNUSED5: + return "UNUSED5"; + case FRA_FWMARK: + return "FWMARK"; + case FRA_FLOW: + return "FLOW"; + case FRA_TUN_ID: + return "TUN_ID"; + case FRA_SUPPRESS_IFGROUP: + return "SUPPRESS_IFGROUP"; + case FRA_SUPPRESS_PREFIXLEN: + return "SUPPRESS_PREFIXLEN"; + case FRA_TABLE: + return "TABLE"; + case FRA_FWMASK: + return "FWMASK"; + case FRA_OIFNAME: + return "OIFNAME"; + case FRA_PAD: + return "PAD"; + case FRA_L3MDEV: + return "L3MDEV"; + case FRA_UID_RANGE: + return "UID_RANGE"; + case FRA_PROTOCOL: + return "PROTOCOL"; + case FRA_IP_PROTO: + return "IP_PROTO"; + case FRA_SPORT_RANGE: + return "SPORT_RANGE"; + case FRA_DPORT_RANGE: + return "DPORT_RANGE"; + default: + return "UNKNOWN"; + } +} + +const char *frh_action2str(uint8_t action) +{ + switch (action) { + case FR_ACT_TO_TBL: + return "TO_TBL"; + case FR_ACT_GOTO: + return "GOTO"; + case FR_ACT_NOP: + return "NOP"; + case FR_ACT_RES3: + return "RES3"; + case FR_ACT_RES4: + return "RES4"; + case FR_ACT_BLACKHOLE: + return "BLACKHOLE"; + case FR_ACT_UNREACHABLE: + return "UNREACHABLE"; + case FR_ACT_PROHIBIT: + return "PROHIBIT"; + default: + return "UNKNOWN"; + } +} + static inline void flag_write(int flags, int flag, const char *flagstr, char *buf, size_t buflen) { @@ -1110,6 +1191,111 @@ next_rta: goto next_rta; } +static void nlrule_dump(struct fib_rule_hdr *frh, size_t msglen) +{ + struct rtattr *rta; + size_t plen; + uint8_t u8v; + uint32_t u32v; + int32_t s32v; + uint64_t u64v; + char dbuf[128]; + struct fib_rule_uid_range *u_range; + struct fib_rule_port_range *p_range; + + /* Get the first attribute and go from there. */ + rta = RTM_RTA(frh); +next_rta: + /* Check the header for valid length and for outbound access. */ + if (RTA_OK(rta, msglen) == 0) + return; + + plen = RTA_PAYLOAD(rta); + zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len, + plen, rta->rta_type, frh_rta2str(rta->rta_type)); + switch (rta->rta_type) { + case FRA_DST: + case FRA_SRC: + switch (plen) { + case sizeof(struct in_addr): + zlog_debug(" %pI4", + (struct in_addr *)RTA_DATA(rta)); + break; + case sizeof(struct in6_addr): + zlog_debug(" %pI6", + (struct in6_addr *)RTA_DATA(rta)); + break; + default: + break; + } + break; + + case FRA_IIFNAME: + case FRA_OIFNAME: + snprintf(dbuf, sizeof(dbuf), "%s", (char *)RTA_DATA(rta)); + zlog_debug(" %s", dbuf); + break; + + case FRA_GOTO: + case FRA_UNUSED2: + case FRA_PRIORITY: + case FRA_UNUSED3: + case FRA_UNUSED4: + case FRA_UNUSED5: + case FRA_FWMARK: + case FRA_FLOW: + case FRA_TABLE: + case FRA_FWMASK: + u32v = *(uint32_t *)RTA_DATA(rta); + zlog_debug(" %u", u32v); + break; + + case FRA_SUPPRESS_IFGROUP: + case FRA_SUPPRESS_PREFIXLEN: + s32v = *(int32_t *)RTA_DATA(rta); + zlog_debug(" %d", s32v); + break; + + case FRA_TUN_ID: + u64v = *(uint64_t *)RTA_DATA(rta); + zlog_debug(" %" PRIu64, u64v); + break; + + case FRA_L3MDEV: + case FRA_PROTOCOL: + case FRA_IP_PROTO: + u8v = *(uint8_t *)RTA_DATA(rta); + zlog_debug(" %u", u8v); + break; + + case FRA_UID_RANGE: + u_range = (struct fib_rule_uid_range *)RTA_DATA(rta); + if (u_range->start == u_range->end) + zlog_debug(" %u", u_range->start); + else + zlog_debug(" %u-%u", u_range->start, u_range->end); + break; + + case FRA_SPORT_RANGE: + case FRA_DPORT_RANGE: + p_range = (struct fib_rule_port_range *)RTA_DATA(rta); + if (p_range->start == p_range->end) + zlog_debug(" %u", p_range->start); + else + zlog_debug(" %u-%u", p_range->start, p_range->end); + break; + + case FRA_PAD: /* fallthrough */ + default: + /* NOTHING: unhandled. */ + break; + } + + /* Get next pointer and start iteration again. */ + rta = RTA_NEXT(rta, msglen); + goto next_rta; +} + void nl_dump(void *msg, size_t msglen) { struct nlmsghdr *nlmsg = msg; @@ -1120,6 +1306,7 @@ void nl_dump(void *msg, size_t msglen) struct rtmsg *rtm; struct nhmsg *nhm; struct ifinfomsg *ifi; + struct fib_rule_hdr *frh; char fbuf[128]; char ibuf[128]; @@ -1151,8 +1338,7 @@ next_header: case RTM_SETLINK: ifi = NLMSG_DATA(nlmsg); zlog_debug( - " ifinfomsg [family=%d type=(%d) %s " - "index=%d flags=0x%04x {%s}]", + " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]", ifi->ifi_family, ifi->ifi_type, ifi_type2str(ifi->ifi_type), ifi->ifi_index, ifi->ifi_flags, @@ -1170,9 +1356,7 @@ next_header: case RTM_GETROUTE: rtm = NLMSG_DATA(nlmsg); zlog_debug( - " rtmsg [family=(%d) %s dstlen=%d srclen=%d tos=%d " - "table=%d protocol=(%d) %s scope=(%d) %s " - "type=(%d) %s flags=0x%04x {%s}]", + " rtmsg [family=(%d) %s dstlen=%d srclen=%d tos=%d table=%d protocol=(%d) %s scope=(%d) %s type=(%d) %s flags=0x%04x {%s}]", rtm->rtm_family, af_type2str(rtm->rtm_family), rtm->rtm_dst_len, rtm->rtm_src_len, rtm->rtm_tos, rtm->rtm_table, rtm->rtm_protocol, @@ -1188,8 +1372,7 @@ next_header: case RTM_DELNEIGH: ndm = NLMSG_DATA(nlmsg); zlog_debug( - " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} " - "flags=0x%04x {%s} type=%d (%s)]", + " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]", ndm->ndm_family, af_type2str(ndm->ndm_family), ndm->ndm_ifindex, ndm->ndm_state, neigh_state2str(ndm->ndm_state, ibuf, sizeof(ibuf)), @@ -1200,12 +1383,24 @@ next_header: nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ndm))); break; + case RTM_NEWRULE: + case RTM_DELRULE: + frh = NLMSG_DATA(nlmsg); + zlog_debug( + " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]", + frh->family, af_type2str(frh->family), frh->dst_len, + frh->src_len, frh->tos, frh->table, frh->res1, + frh->res2, frh->action, frh_action2str(frh->action), + frh->flags); + nlrule_dump(frh, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*frh))); + break; + + case RTM_NEWADDR: case RTM_DELADDR: ifa = NLMSG_DATA(nlmsg); zlog_debug( - " ifa [family=(%d) %s prefixlen=%d " - "flags=0x%04x {%s} scope=%d index=%u]", + " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]", ifa->ifa_family, af_type2str(ifa->ifa_family), ifa->ifa_prefixlen, ifa->ifa_flags, if_flags2str(ifa->ifa_flags, fbuf, sizeof(fbuf)), @@ -1218,8 +1413,7 @@ next_header: case RTM_GETNEXTHOP: nhm = NLMSG_DATA(nlmsg); zlog_debug( - " nhm [family=(%d) %s scope=(%d) %s " - "protocol=(%d) %s flags=0x%08x {%s}]", + " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]", nhm->nh_family, af_type2str(nhm->nh_family), nhm->nh_scope, rtm_scope2str(nhm->nh_scope), nhm->nh_protocol, rtm_protocol2str(nhm->nh_protocol), diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 93c06e555b..0a79771708 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -134,6 +134,8 @@ const char *rtm_rta2str(int type); const char *neigh_rta2str(int type); const char *ifa_rta2str(int type); const char *nhm_rta2str(int type); +const char *frh_rta2str(int type); +const char *frh_action2str(uint8_t action); const char *nlmsg_flags2str(uint16_t flags, char *buf, size_t buflen); const char *if_flags2str(uint32_t flags, char *buf, size_t buflen); const char *rtm_flags2str(uint32_t flags, char *buf, size_t buflen);