1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2018 Rafael Zalamena
8 #if defined(HAVE_NETLINK) && defined(NETLINK_DEBUG)
10 #include <sys/socket.h>
12 #include <linux/netconf.h>
13 #include <linux/netlink.h>
14 #include <linux/nexthop.h>
15 #include <linux/rtnetlink.h>
16 #include <net/if_arp.h>
17 #include <linux/fib_rules.h>
18 #include <linux/lwtunnel.h>
23 #include "zebra/rt_netlink.h"
24 #include "zebra/kernel_netlink.h"
25 #include "lib/vxlan.h"
27 const char *nlmsg_type2str(uint16_t type
)
93 return "RTM_NEWNETCONF";
95 return "RTM_DELNETCONF";
102 const char *af_type2str(int type
)
122 return "AF_BLUETOOTH";
134 const char *ifi_type2str(int type
)
153 case ARPHRD_APPLETLK
:
159 case ARPHRD_METRICOM
:
161 case ARPHRD_IEEE1394
:
165 case ARPHRD_INFINIBAND
:
201 case ARPHRD_LOOPBACK
:
203 case ARPHRD_LOCALTLK
:
231 case ARPHRD_FCFABRIC
:
233 case ARPHRD_IEEE802_TR
:
235 case ARPHRD_IEEE80211
:
237 case ARPHRD_IEEE80211_PRISM
:
238 return "IEEE80211_PRISM";
239 case ARPHRD_IEEE80211_RADIOTAP
:
240 return "IEEE80211_RADIOTAP";
241 case ARPHRD_IEEE802154
:
243 #ifdef ARPHRD_VSOCKMON
244 case ARPHRD_VSOCKMON
:
246 #endif /* ARPHRD_VSOCKMON */
256 const char *ifla_pdr_type2str(int type
)
259 case IFLA_PROTO_DOWN_REASON_UNSPEC
:
261 case IFLA_PROTO_DOWN_REASON_MASK
:
263 case IFLA_PROTO_DOWN_REASON_VALUE
:
270 const char *ifla_info_type2str(int type
)
273 case IFLA_INFO_UNSPEC
:
279 case IFLA_INFO_XSTATS
:
281 case IFLA_INFO_SLAVE_KIND
:
283 case IFLA_INFO_SLAVE_DATA
:
290 const char *rta_type2str(int type
)
331 case IFLA_NET_NS_PID
:
337 case IFLA_VFINFO_LIST
:
338 return "VFINFO_LIST";
353 case IFLA_PROMISCUITY
:
354 return "PROMISCUITY";
355 case IFLA_NUM_TX_QUEUES
:
356 return "NUM_TX_QUEUES";
357 case IFLA_NUM_RX_QUEUES
:
358 return "NUM_RX_QUEUES";
361 case IFLA_PHYS_PORT_ID
:
362 return "PHYS_PORT_ID";
363 case IFLA_CARRIER_CHANGES
:
364 return "CARRIER_CHANGES";
365 case IFLA_PHYS_SWITCH_ID
:
366 return "PHYS_SWITCH_ID";
367 case IFLA_LINK_NETNSID
:
368 return "LINK_NETNSID";
369 case IFLA_PHYS_PORT_NAME
:
370 return "PHYS_PORT_NAME";
371 case IFLA_PROTO_DOWN
:
373 #ifdef IFLA_GSO_MAX_SEGS
374 case IFLA_GSO_MAX_SEGS
:
375 return "GSO_MAX_SEGS";
376 #endif /* IFLA_GSO_MAX_SEGS */
377 #ifdef IFLA_GSO_MAX_SIZE
378 case IFLA_GSO_MAX_SIZE
:
379 return "GSO_MAX_SIZE";
380 #endif /* IFLA_GSO_MAX_SIZE */
384 #endif /* IFLA_PAD */
388 #endif /* IFLA_XDP */
392 #endif /* IFLA_EVENT */
393 case IFLA_PROTO_DOWN_REASON
:
394 return "PROTO_DOWN_REASON";
400 const char *rtm_type2str(int type
)
417 case RTN_UNREACHABLE
:
418 return "UNREACHABLE";
432 const char *rtm_protocol2str(int type
)
437 case RTPROT_REDIRECT
:
461 case RTPROT_DNROUTED
:
478 const char *rtm_scope2str(int type
)
481 case RT_SCOPE_UNIVERSE
:
489 case RT_SCOPE_NOWHERE
:
496 const char *rtm_rta2str(int type
)
542 const char *neigh_rta2str(int type
)
565 case NDA_LINK_NETNSID
:
566 return "LINK_NETNSID";
572 const char *ifa_rta2str(int type
)
598 const char *nhm_rta2str(int type
)
628 const char *frh_rta2str(int type
)
655 case FRA_SUPPRESS_IFGROUP
:
656 return "SUPPRESS_IFGROUP";
657 case FRA_SUPPRESS_PREFIXLEN
:
658 return "SUPPRESS_PREFIXLEN";
675 case FRA_SPORT_RANGE
:
676 return "SPORT_RANGE";
677 case FRA_DPORT_RANGE
:
678 return "DPORT_RANGE";
684 const char *frh_action2str(uint8_t action
)
697 case FR_ACT_BLACKHOLE
:
699 case FR_ACT_UNREACHABLE
:
700 return "UNREACHABLE";
701 case FR_ACT_PROHIBIT
:
708 static const char *ncm_rta2str(int type
)
711 case NETCONFA_UNSPEC
:
713 case NETCONFA_IFINDEX
:
715 case NETCONFA_FORWARDING
:
717 case NETCONFA_RP_FILTER
:
719 case NETCONFA_MC_FORWARDING
:
721 case NETCONFA_PROXY_NEIGH
:
722 return "PROXY_NEIGH";
723 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
724 return "IGNORE_LINKDOWN";
727 case NETCONFA_BC_FORWARDING
:
734 static void dump_on_off(uint32_t ival
, const char *prefix
)
736 zlog_debug("%s%s", prefix
, (ival
!= 0) ? "on" : "off");
739 static inline void flag_write(int flags
, int flag
, const char *flagstr
,
740 char *buf
, size_t buflen
)
742 if (CHECK_FLAG(flags
, flag
) == 0)
746 strlcat(buf
, ",", buflen
);
748 strlcat(buf
, flagstr
, buflen
);
751 const char *nlmsg_flags2str(uint16_t flags
, char *buf
, size_t buflen
)
753 const char *bufp
= buf
;
756 /* Specific flags. */
757 flag_write(flags
, NLM_F_REQUEST
, "REQUEST", buf
, buflen
);
758 flag_write(flags
, NLM_F_MULTI
, "MULTI", buf
, buflen
);
759 flag_write(flags
, NLM_F_ACK
, "ACK", buf
, buflen
);
760 flag_write(flags
, NLM_F_ECHO
, "ECHO", buf
, buflen
);
761 flag_write(flags
, NLM_F_DUMP
, "DUMP", buf
, buflen
);
763 /* Netlink family type dependent. */
764 flag_write(flags
, 0x0100, "(ROOT|REPLACE|CAPPED)", buf
, buflen
);
765 flag_write(flags
, 0x0200, "(MATCH|EXCLUDE|ACK_TLVS)", buf
, buflen
);
766 flag_write(flags
, 0x0400, "(ATOMIC|CREATE)", buf
, buflen
);
767 flag_write(flags
, 0x0800, "(DUMP|APPEND)", buf
, buflen
);
772 const char *if_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
774 const char *bufp
= buf
;
777 flag_write(flags
, IFF_UP
, "UP", buf
, buflen
);
778 flag_write(flags
, IFF_BROADCAST
, "BROADCAST", buf
, buflen
);
779 flag_write(flags
, IFF_DEBUG
, "DEBUG", buf
, buflen
);
780 flag_write(flags
, IFF_LOOPBACK
, "LOOPBACK", buf
, buflen
);
781 flag_write(flags
, IFF_POINTOPOINT
, "POINTOPOINT", buf
, buflen
);
782 flag_write(flags
, IFF_NOTRAILERS
, "NOTRAILERS", buf
, buflen
);
783 flag_write(flags
, IFF_RUNNING
, "RUNNING", buf
, buflen
);
784 flag_write(flags
, IFF_NOARP
, "NOARP", buf
, buflen
);
785 flag_write(flags
, IFF_PROMISC
, "PROMISC", buf
, buflen
);
786 flag_write(flags
, IFF_ALLMULTI
, "ALLMULTI", buf
, buflen
);
787 flag_write(flags
, IFF_MASTER
, "MASTER", buf
, buflen
);
788 flag_write(flags
, IFF_SLAVE
, "SLAVE", buf
, buflen
);
789 flag_write(flags
, IFF_MULTICAST
, "MULTICAST", buf
, buflen
);
790 flag_write(flags
, IFF_PORTSEL
, "PORTSEL", buf
, buflen
);
791 flag_write(flags
, IFF_AUTOMEDIA
, "AUTOMEDIA", buf
, buflen
);
792 flag_write(flags
, IFF_DYNAMIC
, "DYNAMIC", buf
, buflen
);
797 const char *rtm_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
799 const char *bufp
= buf
;
802 flag_write(flags
, RTM_F_NOTIFY
, "NOTIFY", buf
, buflen
);
803 flag_write(flags
, RTM_F_CLONED
, "CLONED", buf
, buflen
);
804 flag_write(flags
, RTM_F_EQUALIZE
, "EQUALIZE", buf
, buflen
);
809 const char *neigh_state2str(uint32_t flags
, char *buf
, size_t buflen
)
811 const char *bufp
= buf
;
814 flag_write(flags
, NUD_INCOMPLETE
, "INCOMPLETE", buf
, buflen
);
815 flag_write(flags
, NUD_REACHABLE
, "REACHABLE", buf
, buflen
);
816 flag_write(flags
, NUD_STALE
, "STALE", buf
, buflen
);
817 flag_write(flags
, NUD_DELAY
, "DELAY", buf
, buflen
);
818 flag_write(flags
, NUD_PROBE
, "PROBE", buf
, buflen
);
819 flag_write(flags
, NUD_FAILED
, "FAILED", buf
, buflen
);
820 flag_write(flags
, NUD_NOARP
, "NOARP", buf
, buflen
);
821 flag_write(flags
, NUD_PERMANENT
, "PERMANENT", buf
, buflen
);
826 const char *neigh_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
828 const char *bufp
= buf
;
831 flag_write(flags
, NTF_USE
, "USE", buf
, buflen
);
832 flag_write(flags
, NTF_SELF
, "SELF", buf
, buflen
);
833 flag_write(flags
, NTF_MASTER
, "MASTER", buf
, buflen
);
834 flag_write(flags
, NTF_PROXY
, "PROXY", buf
, buflen
);
835 flag_write(flags
, NTF_EXT_LEARNED
, "EXT_LEARNED", buf
, buflen
);
837 flag_write(flags
, NTF_OFFLOADED
, "OFFLOADED", buf
, buflen
);
838 #endif /* NTF_OFFLOADED */
839 flag_write(flags
, NTF_ROUTER
, "ROUTER", buf
, buflen
);
844 const char *ifa_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
846 const char *bufp
= buf
;
849 flag_write(flags
, IFA_F_SECONDARY
, "SECONDARY", buf
, buflen
);
850 flag_write(flags
, IFA_F_NODAD
, "NODAD", buf
, buflen
);
851 flag_write(flags
, IFA_F_OPTIMISTIC
, "OPTIMISTIC", buf
, buflen
);
852 flag_write(flags
, IFA_F_DADFAILED
, "DADFAILED", buf
, buflen
);
853 flag_write(flags
, IFA_F_HOMEADDRESS
, "HOMEADDRESS", buf
, buflen
);
854 flag_write(flags
, IFA_F_DEPRECATED
, "DEPRECATED", buf
, buflen
);
855 flag_write(flags
, IFA_F_TENTATIVE
, "TENTATIVE", buf
, buflen
);
856 flag_write(flags
, IFA_F_PERMANENT
, "PERMANENT", buf
, buflen
);
857 flag_write(flags
, IFA_F_MANAGETEMPADDR
, "MANAGETEMPADDR", buf
, buflen
);
858 flag_write(flags
, IFA_F_NOPREFIXROUTE
, "NOPREFIXROUTE", buf
, buflen
);
859 flag_write(flags
, IFA_F_MCAUTOJOIN
, "MCAUTOJOIN", buf
, buflen
);
860 flag_write(flags
, IFA_F_STABLE_PRIVACY
, "STABLE_PRIVACY", buf
, buflen
);
865 const char *nh_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
867 const char *bufp
= buf
;
870 flag_write(flags
, RTNH_F_DEAD
, "DEAD", buf
, buflen
);
871 flag_write(flags
, RTNH_F_PERVASIVE
, "PERVASIVE", buf
, buflen
);
872 flag_write(flags
, RTNH_F_ONLINK
, "ONLINK", buf
, buflen
);
873 flag_write(flags
, RTNH_F_OFFLOAD
, "OFFLOAD", buf
, buflen
);
874 flag_write(flags
, RTNH_F_LINKDOWN
, "LINKDOWN", buf
, buflen
);
875 flag_write(flags
, RTNH_F_UNRESOLVED
, "UNRESOLVED", buf
, buflen
);
881 * Netlink abstractions.
883 static void nllink_pdr_dump(struct rtattr
*rta
, size_t msglen
)
889 /* Check the header for valid length and for outbound access. */
890 if (RTA_OK(rta
, msglen
) == 0)
893 plen
= RTA_PAYLOAD(rta
);
894 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
895 rta
->rta_len
, plen
, rta
->rta_type
,
896 ifla_pdr_type2str(rta
->rta_type
));
897 switch (rta
->rta_type
) {
898 case IFLA_PROTO_DOWN_REASON_MASK
:
899 case IFLA_PROTO_DOWN_REASON_VALUE
:
900 if (plen
< sizeof(uint32_t)) {
901 zlog_debug(" invalid length");
905 u32v
= *(uint32_t *)RTA_DATA(rta
);
906 zlog_debug(" %u", u32v
);
910 /* NOTHING: unhandled. */
914 /* Get next pointer and start iteration again. */
915 rta
= RTA_NEXT(rta
, msglen
);
919 static void nllink_linkinfo_dump(struct rtattr
*rta
, size_t msglen
)
925 /* Check the header for valid length and for outbound access. */
926 if (RTA_OK(rta
, msglen
) == 0)
929 plen
= RTA_PAYLOAD(rta
);
930 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
931 rta
->rta_len
, plen
, rta
->rta_type
,
932 ifla_info_type2str(rta
->rta_type
));
933 switch (rta
->rta_type
) {
936 zlog_debug(" invalid length");
940 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
941 zlog_debug(" %s", dbuf
);
943 case IFLA_INFO_SLAVE_KIND
:
945 zlog_debug(" invalid length");
949 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
950 zlog_debug(" %s", dbuf
);
954 /* NOTHING: unhandled. */
958 /* Get next pointer and start iteration again. */
959 rta
= RTA_NEXT(rta
, msglen
);
963 static void nllink_dump(struct ifinfomsg
*ifi
, size_t msglen
)
972 unsigned short rta_type
;
974 /* Get the first attribute and go from there. */
977 /* Check the header for valid length and for outbound access. */
978 if (RTA_OK(rta
, msglen
) == 0)
981 plen
= RTA_PAYLOAD(rta
);
982 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
983 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
984 plen
, rta_type
, rta_type2str(rta_type
));
988 zlog_debug(" invalid length");
992 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
993 zlog_debug(" %s", dbuf
);
998 case IFLA_NUM_TX_QUEUES
:
999 case IFLA_NUM_RX_QUEUES
:
1001 case IFLA_PROMISCUITY
:
1002 #ifdef IFLA_GSO_MAX_SEGS
1003 case IFLA_GSO_MAX_SEGS
:
1004 #endif /* IFLA_GSO_MAX_SEGS */
1005 #ifdef IFLA_GSO_MAX_SIZE
1006 case IFLA_GSO_MAX_SIZE
:
1007 #endif /* IFLA_GSO_MAX_SIZE */
1008 case IFLA_CARRIER_CHANGES
:
1011 if (plen
< sizeof(uint32_t)) {
1012 zlog_debug(" invalid length");
1016 u32v
= *(uint32_t *)RTA_DATA(rta
);
1017 zlog_debug(" %u", u32v
);
1020 case IFLA_PROTO_DOWN
:
1021 if (plen
< sizeof(uint8_t)) {
1022 zlog_debug(" invalid length");
1026 u8v
= *(uint8_t *)RTA_DATA(rta
);
1027 zlog_debug(" %u", u8v
);
1030 datap
= RTA_DATA(rta
);
1032 for (it
= 0; it
< plen
; it
++) {
1033 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
1034 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
1037 /* Remove trailing ':'. */
1039 dbuf
[strlen(dbuf
) - 1] = 0;
1041 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
1045 nllink_linkinfo_dump(RTA_DATA(rta
), plen
);
1048 case IFLA_PROTO_DOWN_REASON
:
1049 nllink_pdr_dump(RTA_DATA(rta
), plen
);
1053 /* NOTHING: unhandled. */
1057 /* Get next pointer and start iteration again. */
1058 rta
= RTA_NEXT(rta
, msglen
);
1062 static void nlroute_dump(struct rtmsg
*rtm
, size_t msglen
)
1064 struct rta_mfc_stats
*mfc_stats
;
1070 /* Get the first attribute and go from there. */
1073 /* Check the header for valid length and for outbound access. */
1074 if (RTA_OK(rta
, msglen
) == 0)
1077 plen
= RTA_PAYLOAD(rta
);
1078 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1079 plen
, rta
->rta_type
& NLA_TYPE_MASK
,
1080 rtm_rta2str(rta
->rta_type
& NLA_TYPE_MASK
));
1081 switch (rta
->rta_type
& NLA_TYPE_MASK
) {
1087 u32v
= *(uint32_t *)RTA_DATA(rta
);
1088 zlog_debug(" %u", u32v
);
1092 u64v
= *(uint64_t *)RTA_DATA(rta
);
1093 zlog_debug(" %" PRIu64
, u64v
);
1101 case sizeof(struct in_addr
):
1103 (struct in_addr
*)RTA_DATA(rta
));
1105 case sizeof(struct in6_addr
):
1107 (struct in6_addr
*)RTA_DATA(rta
));
1115 mfc_stats
= (struct rta_mfc_stats
*)RTA_DATA(rta
);
1116 zlog_debug(" pkts=%ju bytes=%ju wrong_if=%ju",
1117 (uintmax_t)mfc_stats
->mfcs_packets
,
1118 (uintmax_t)mfc_stats
->mfcs_bytes
,
1119 (uintmax_t)mfc_stats
->mfcs_wrong_if
);
1123 /* NOTHING: unhandled. */
1127 /* Get next pointer and start iteration again. */
1128 rta
= RTA_NEXT(rta
, msglen
);
1132 static void nlneigh_dump(struct ndmsg
*ndm
, size_t msglen
)
1140 unsigned short rta_type
;
1143 #define NDA_RTA(ndm) \
1144 /* struct ndmsg *ndm; */ \
1145 ((struct rtattr *)(((uint8_t *)(ndm)) \
1146 + NLMSG_ALIGN(sizeof(struct ndmsg))))
1147 #endif /* NDA_RTA */
1149 /* Get the first attribute and go from there. */
1152 /* Check the header for valid length and for outbound access. */
1153 if (RTA_OK(rta
, msglen
) == 0)
1156 plen
= RTA_PAYLOAD(rta
);
1157 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
1158 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1159 plen
, rta
->rta_type
, neigh_rta2str(rta_type
));
1162 datap
= RTA_DATA(rta
);
1164 for (it
= 0; it
< plen
; it
++) {
1165 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
1166 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
1169 /* Remove trailing ':'. */
1171 dbuf
[strlen(dbuf
) - 1] = 0;
1173 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
1178 case sizeof(struct in_addr
):
1180 (struct in_addr
*)RTA_DATA(rta
));
1182 case sizeof(struct in6_addr
):
1184 (struct in6_addr
*)RTA_DATA(rta
));
1192 vid
= *(uint16_t *)RTA_DATA(rta
);
1193 zlog_debug(" %d", vid
);
1197 /* NOTHING: unhandled. */
1201 /* Get next pointer and start iteration again. */
1202 rta
= RTA_NEXT(rta
, msglen
);
1206 static void nlifa_dump(struct ifaddrmsg
*ifa
, size_t msglen
)
1212 /* Get the first attribute and go from there. */
1215 /* Check the header for valid length and for outbound access. */
1216 if (RTA_OK(rta
, msglen
) == 0)
1219 plen
= RTA_PAYLOAD(rta
);
1220 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1221 plen
, rta
->rta_type
, ifa_rta2str(rta
->rta_type
));
1222 switch (rta
->rta_type
) {
1224 u32v
= *(uint32_t *)RTA_DATA(rta
);
1225 zlog_debug(" %u", u32v
);
1229 zlog_debug(" %s", (const char *)RTA_DATA(rta
));
1238 (struct in_addr
*)RTA_DATA(rta
));
1242 (struct in6_addr
*)RTA_DATA(rta
));
1250 /* NOTHING: unhandled. */
1254 /* Get next pointer and start iteration again. */
1255 rta
= RTA_NEXT(rta
, msglen
);
1259 static void nltnl_dump(struct tunnel_msg
*tnlm
, size_t msglen
)
1261 struct rtattr
*attr
;
1262 vni_t vni_start
= 0, vni_end
= 0;
1263 struct rtattr
*ttb
[VXLAN_VNIFILTER_ENTRY_MAX
+ 1];
1266 attr
= TUNNEL_RTA(tnlm
);
1268 /* Check the header for valid length and for outbound access. */
1269 if (RTA_OK(attr
, msglen
) == 0)
1272 rta_type
= attr
->rta_type
& NLA_TYPE_MASK
;
1274 if (rta_type
!= VXLAN_VNIFILTER_ENTRY
) {
1275 attr
= RTA_NEXT(attr
, msglen
);
1279 memset(ttb
, 0, sizeof(ttb
));
1281 netlink_parse_rtattr_flags(ttb
, VXLAN_VNIFILTER_ENTRY_MAX
,
1282 RTA_DATA(attr
), RTA_PAYLOAD(attr
),
1285 if (ttb
[VXLAN_VNIFILTER_ENTRY_START
])
1287 *(uint32_t *)RTA_DATA(ttb
[VXLAN_VNIFILTER_ENTRY_START
]);
1289 if (ttb
[VXLAN_VNIFILTER_ENTRY_END
])
1290 vni_end
= *(uint32_t *)RTA_DATA(ttb
[VXLAN_VNIFILTER_ENTRY_END
]);
1291 zlog_debug(" vni_start %u, vni_end %u", vni_start
, vni_end
);
1293 attr
= RTA_NEXT(attr
, msglen
);
1297 static const char *lwt_type2str(uint16_t type
)
1300 case LWTUNNEL_ENCAP_NONE
:
1302 case LWTUNNEL_ENCAP_MPLS
:
1304 case LWTUNNEL_ENCAP_IP
:
1306 case LWTUNNEL_ENCAP_ILA
:
1308 case LWTUNNEL_ENCAP_IP6
:
1310 case LWTUNNEL_ENCAP_SEG6
:
1312 case LWTUNNEL_ENCAP_BPF
:
1314 case LWTUNNEL_ENCAP_SEG6_LOCAL
:
1315 return "SEG6_LOCAL";
1321 static const char *nhg_type2str(uint16_t type
)
1324 case NEXTHOP_GRP_TYPE_MPATH
:
1326 case NEXTHOP_GRP_TYPE_RES
:
1327 return "RESILIENT MULTIPATH";
1333 static void nlnh_dump(struct nhmsg
*nhm
, size_t msglen
)
1340 unsigned long count
, i
;
1341 struct nexthop_grp
*nhgrp
;
1342 unsigned short rta_type
;
1347 /* Check the header for valid length and for outbound access. */
1348 if (RTA_OK(rta
, msglen
) == 0)
1351 plen
= RTA_PAYLOAD(rta
);
1352 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
1353 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1354 plen
, rta
->rta_type
, nhm_rta2str(rta_type
));
1357 u32v
= *(uint32_t *)RTA_DATA(rta
);
1358 zlog_debug(" %u", u32v
);
1361 nhgrp
= (struct nexthop_grp
*)RTA_DATA(rta
);
1362 count
= (RTA_PAYLOAD(rta
) / sizeof(*nhgrp
));
1364 || (count
* sizeof(*nhgrp
)) != RTA_PAYLOAD(rta
)) {
1365 zlog_debug(" invalid nexthop group received");
1369 for (i
= 0; i
< count
; i
++)
1370 zlog_debug(" id %d weight %d", nhgrp
[i
].id
,
1373 case NHA_ENCAP_TYPE
:
1374 u16v
= *(uint16_t *)RTA_DATA(rta
);
1375 zlog_debug(" %s", lwt_type2str(u16v
));
1377 case NHA_GROUP_TYPE
:
1378 u16v
= *(uint16_t *)RTA_DATA(rta
);
1379 zlog_debug(" %s", nhg_type2str(u16v
));
1385 ifindex
= *(int *)RTA_DATA(rta
);
1386 zlog_debug(" %d", ifindex
);
1389 switch (nhm
->nh_family
) {
1392 (struct in_addr
*)RTA_DATA(rta
));
1396 (struct in6_addr
*)RTA_DATA(rta
));
1400 zlog_debug(" invalid family %d", nhm
->nh_family
);
1405 /* TODO: handle MPLS labels. */
1406 zlog_debug(" unparsed MPLS labels");
1409 /* TODO: handle this message. */
1410 zlog_debug(" unparsed GROUPS message");
1414 /* NOTHING: unhandled. */
1418 /* Get next pointer and start iteration again. */
1419 rta
= RTA_NEXT(rta
, msglen
);
1423 static void nlrule_dump(struct fib_rule_hdr
*frh
, size_t msglen
)
1432 struct fib_rule_uid_range
*u_range
;
1433 struct fib_rule_port_range
*p_range
;
1435 /* Get the first attribute and go from there. */
1438 /* Check the header for valid length and for outbound access. */
1439 if (RTA_OK(rta
, msglen
) == 0)
1442 plen
= RTA_PAYLOAD(rta
);
1443 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1444 plen
, rta
->rta_type
, frh_rta2str(rta
->rta_type
));
1445 switch (rta
->rta_type
) {
1449 case sizeof(struct in_addr
):
1451 (struct in_addr
*)RTA_DATA(rta
));
1453 case sizeof(struct in6_addr
):
1455 (struct in6_addr
*)RTA_DATA(rta
));
1464 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
1465 zlog_debug(" %s", dbuf
);
1478 u32v
= *(uint32_t *)RTA_DATA(rta
);
1479 zlog_debug(" %u", u32v
);
1482 case FRA_SUPPRESS_IFGROUP
:
1483 case FRA_SUPPRESS_PREFIXLEN
:
1484 s32v
= *(int32_t *)RTA_DATA(rta
);
1485 zlog_debug(" %d", s32v
);
1489 u64v
= *(uint64_t *)RTA_DATA(rta
);
1490 zlog_debug(" %" PRIu64
, u64v
);
1496 u8v
= *(uint8_t *)RTA_DATA(rta
);
1497 zlog_debug(" %u", u8v
);
1501 u_range
= (struct fib_rule_uid_range
*)RTA_DATA(rta
);
1502 if (u_range
->start
== u_range
->end
)
1503 zlog_debug(" %u", u_range
->start
);
1505 zlog_debug(" %u-%u", u_range
->start
, u_range
->end
);
1508 case FRA_SPORT_RANGE
:
1509 case FRA_DPORT_RANGE
:
1510 p_range
= (struct fib_rule_port_range
*)RTA_DATA(rta
);
1511 if (p_range
->start
== p_range
->end
)
1512 zlog_debug(" %u", p_range
->start
);
1514 zlog_debug(" %u-%u", p_range
->start
, p_range
->end
);
1517 case FRA_PAD
: /* fallthrough */
1519 /* NOTHING: unhandled. */
1523 /* Get next pointer and start iteration again. */
1524 rta
= RTA_NEXT(rta
, msglen
);
1528 static const char *tcm_nltype2str(int nltype
)
1537 case RTM_NEWTFILTER
:
1538 case RTM_DELTFILTER
:
1541 /* should never hit */
1546 static void nlncm_dump(const struct netconfmsg
*ncm
, size_t msglen
)
1548 const struct rtattr
*rta
;
1552 rta
= (void *)((const char *)ncm
+
1553 NLMSG_ALIGN(sizeof(struct netconfmsg
)));
1556 /* Check the attr header for valid length. */
1557 if (RTA_OK(rta
, msglen
) == 0)
1560 plen
= RTA_PAYLOAD(rta
);
1562 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1563 plen
, rta
->rta_type
, ncm_rta2str(rta
->rta_type
));
1565 switch (rta
->rta_type
) {
1566 case NETCONFA_IFINDEX
:
1567 ival
= *(uint32_t *)RTA_DATA(rta
);
1568 zlog_debug(" %d", (int32_t)ival
);
1571 /* Most attrs are just on/off. */
1572 case NETCONFA_FORWARDING
:
1573 case NETCONFA_RP_FILTER
:
1574 case NETCONFA_MC_FORWARDING
:
1575 case NETCONFA_PROXY_NEIGH
:
1576 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
1577 case NETCONFA_INPUT
:
1578 case NETCONFA_BC_FORWARDING
:
1579 ival
= *(uint32_t *)RTA_DATA(rta
);
1580 dump_on_off(ival
, " ");
1583 /* NOTHING: unhandled. */
1587 /* Get next pointer and start iteration again. */
1588 rta
= RTA_NEXT(rta
, msglen
);
1592 void nl_dump(void *msg
, size_t msglen
)
1594 struct nlmsghdr
*nlmsg
= msg
;
1595 struct nlmsgerr
*nlmsgerr
;
1596 struct rtgenmsg
*rtgen
;
1597 struct ifaddrmsg
*ifa
;
1601 struct netconfmsg
*ncm
;
1602 struct ifinfomsg
*ifi
;
1603 struct tunnel_msg
*tnlm
;
1604 struct fib_rule_hdr
*frh
;
1612 "nlmsghdr [len=%u type=(%d) %s flags=(0x%04x) {%s} seq=%u pid=%u]",
1613 nlmsg
->nlmsg_len
, nlmsg
->nlmsg_type
,
1614 nlmsg_type2str(nlmsg
->nlmsg_type
), nlmsg
->nlmsg_flags
,
1615 nlmsg_flags2str(nlmsg
->nlmsg_flags
, fbuf
, sizeof(fbuf
)),
1616 nlmsg
->nlmsg_seq
, nlmsg
->nlmsg_pid
);
1618 switch (nlmsg
->nlmsg_type
) {
1623 nlmsgerr
= NLMSG_DATA(nlmsg
);
1624 zlog_debug(" nlmsgerr [error=(%d) %s]", nlmsgerr
->error
,
1625 strerror(-nlmsgerr
->error
));
1636 ifi
= NLMSG_DATA(nlmsg
);
1638 " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]",
1639 ifi
->ifi_family
, ifi
->ifi_type
,
1640 ifi_type2str(ifi
->ifi_type
), ifi
->ifi_index
,
1642 if_flags2str(ifi
->ifi_flags
, ibuf
, sizeof(ibuf
)));
1643 nllink_dump(ifi
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
)));
1646 rtgen
= NLMSG_DATA(nlmsg
);
1647 zlog_debug(" rtgen [family=(%d) %s]", rtgen
->rtgen_family
,
1648 af_type2str(rtgen
->rtgen_family
));
1654 rtm
= NLMSG_DATA(nlmsg
);
1656 " 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}]",
1657 rtm
->rtm_family
, af_type2str(rtm
->rtm_family
),
1658 rtm
->rtm_dst_len
, rtm
->rtm_src_len
, rtm
->rtm_tos
,
1659 rtm
->rtm_table
, rtm
->rtm_protocol
,
1660 rtm_protocol2str(rtm
->rtm_protocol
), rtm
->rtm_scope
,
1661 rtm_scope2str(rtm
->rtm_scope
), rtm
->rtm_type
,
1662 rtm_type2str(rtm
->rtm_type
), rtm
->rtm_flags
,
1663 rtm_flags2str(rtm
->rtm_flags
, fbuf
, sizeof(fbuf
)));
1665 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*rtm
)));
1670 ndm
= NLMSG_DATA(nlmsg
);
1672 " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]",
1673 ndm
->ndm_family
, af_type2str(ndm
->ndm_family
),
1674 ndm
->ndm_ifindex
, ndm
->ndm_state
,
1675 neigh_state2str(ndm
->ndm_state
, ibuf
, sizeof(ibuf
)),
1677 neigh_flags2str(ndm
->ndm_flags
, fbuf
, sizeof(fbuf
)),
1678 ndm
->ndm_type
, rtm_type2str(ndm
->ndm_type
));
1680 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ndm
)));
1685 frh
= NLMSG_DATA(nlmsg
);
1687 " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]",
1688 frh
->family
, af_type2str(frh
->family
), frh
->dst_len
,
1689 frh
->src_len
, frh
->tos
, frh
->table
, frh
->res1
,
1690 frh
->res2
, frh
->action
, frh_action2str(frh
->action
),
1692 nlrule_dump(frh
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*frh
)));
1698 ifa
= NLMSG_DATA(nlmsg
);
1700 " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]",
1701 ifa
->ifa_family
, af_type2str(ifa
->ifa_family
),
1702 ifa
->ifa_prefixlen
, ifa
->ifa_flags
,
1703 if_flags2str(ifa
->ifa_flags
, fbuf
, sizeof(fbuf
)),
1704 ifa
->ifa_scope
, ifa
->ifa_index
);
1705 nlifa_dump(ifa
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifa
)));
1708 case RTM_NEWNEXTHOP
:
1709 case RTM_DELNEXTHOP
:
1710 case RTM_GETNEXTHOP
:
1711 nhm
= NLMSG_DATA(nlmsg
);
1713 " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]",
1714 nhm
->nh_family
, af_type2str(nhm
->nh_family
),
1715 nhm
->nh_scope
, rtm_scope2str(nhm
->nh_scope
),
1716 nhm
->nh_protocol
, rtm_protocol2str(nhm
->nh_protocol
),
1718 nh_flags2str(nhm
->nh_flags
, fbuf
, sizeof(fbuf
)));
1719 nlnh_dump(nhm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*nhm
)));
1725 tnlm
= NLMSG_DATA(nlmsg
);
1726 zlog_debug(" tnlm [family=(%d) %s ifindex=%d ", tnlm
->family
,
1727 af_type2str(tnlm
->family
), tnlm
->ifindex
);
1730 NLMSG_LENGTH(sizeof(struct tunnel_msg
)));
1734 case RTM_NEWNETCONF
:
1735 case RTM_DELNETCONF
:
1736 ncm
= NLMSG_DATA(nlmsg
);
1737 zlog_debug(" ncm [family=%s (%d)]",
1738 af_type2str(ncm
->ncm_family
), ncm
->ncm_family
);
1739 nlncm_dump(ncm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ncm
)));
1746 case RTM_NEWTFILTER
:
1747 case RTM_DELTFILTER
:
1748 tcm
= NLMSG_DATA(nlmsg
);
1750 " tcm [type=%s family=%s (%d) ifindex=%d handle=%04x:%04x]",
1751 tcm_nltype2str(nlmsg
->nlmsg_type
),
1752 af_type2str(tcm
->tcm_family
), tcm
->tcm_family
,
1753 tcm
->tcm_ifindex
, tcm
->tcm_handle
>> 16,
1754 tcm
->tcm_handle
& 0xffff);
1762 * Try to get the next header. There should only be more
1763 * messages if this header was flagged as MULTI, otherwise just
1766 nlmsg
= NLMSG_NEXT(nlmsg
, msglen
);
1767 if (NLMSG_OK(nlmsg
, msglen
) == 0)
1773 #endif /* NETLINK_DEBUG */