2 * Copyright (c) 2018 Rafael Zalamena
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #if defined(HAVE_NETLINK) && defined(NETLINK_DEBUG)
21 #include <sys/socket.h>
23 #include <linux/netconf.h>
24 #include <linux/netlink.h>
25 #include <linux/nexthop.h>
26 #include <linux/rtnetlink.h>
27 #include <net/if_arp.h>
28 #include <linux/fib_rules.h>
29 #include <linux/lwtunnel.h>
34 #include "zebra/rt_netlink.h"
35 #include "zebra/kernel_netlink.h"
36 #include "lib/vxlan.h"
38 const char *nlmsg_type2str(uint16_t type
)
104 return "RTM_NEWNETCONF";
106 return "RTM_DELNETCONF";
113 const char *af_type2str(int type
)
133 return "AF_BLUETOOTH";
145 const char *ifi_type2str(int type
)
164 case ARPHRD_APPLETLK
:
170 case ARPHRD_METRICOM
:
172 case ARPHRD_IEEE1394
:
176 case ARPHRD_INFINIBAND
:
212 case ARPHRD_LOOPBACK
:
214 case ARPHRD_LOCALTLK
:
242 case ARPHRD_FCFABRIC
:
244 case ARPHRD_IEEE802_TR
:
246 case ARPHRD_IEEE80211
:
248 case ARPHRD_IEEE80211_PRISM
:
249 return "IEEE80211_PRISM";
250 case ARPHRD_IEEE80211_RADIOTAP
:
251 return "IEEE80211_RADIOTAP";
252 case ARPHRD_IEEE802154
:
254 #ifdef ARPHRD_VSOCKMON
255 case ARPHRD_VSOCKMON
:
257 #endif /* ARPHRD_VSOCKMON */
267 const char *ifla_pdr_type2str(int type
)
270 case IFLA_PROTO_DOWN_REASON_UNSPEC
:
272 case IFLA_PROTO_DOWN_REASON_MASK
:
274 case IFLA_PROTO_DOWN_REASON_VALUE
:
281 const char *ifla_info_type2str(int type
)
284 case IFLA_INFO_UNSPEC
:
290 case IFLA_INFO_XSTATS
:
292 case IFLA_INFO_SLAVE_KIND
:
294 case IFLA_INFO_SLAVE_DATA
:
301 const char *rta_type2str(int type
)
342 case IFLA_NET_NS_PID
:
348 case IFLA_VFINFO_LIST
:
349 return "VFINFO_LIST";
364 case IFLA_PROMISCUITY
:
365 return "PROMISCUITY";
366 case IFLA_NUM_TX_QUEUES
:
367 return "NUM_TX_QUEUES";
368 case IFLA_NUM_RX_QUEUES
:
369 return "NUM_RX_QUEUES";
372 case IFLA_PHYS_PORT_ID
:
373 return "PHYS_PORT_ID";
374 case IFLA_CARRIER_CHANGES
:
375 return "CARRIER_CHANGES";
376 case IFLA_PHYS_SWITCH_ID
:
377 return "PHYS_SWITCH_ID";
378 case IFLA_LINK_NETNSID
:
379 return "LINK_NETNSID";
380 case IFLA_PHYS_PORT_NAME
:
381 return "PHYS_PORT_NAME";
382 case IFLA_PROTO_DOWN
:
384 #ifdef IFLA_GSO_MAX_SEGS
385 case IFLA_GSO_MAX_SEGS
:
386 return "GSO_MAX_SEGS";
387 #endif /* IFLA_GSO_MAX_SEGS */
388 #ifdef IFLA_GSO_MAX_SIZE
389 case IFLA_GSO_MAX_SIZE
:
390 return "GSO_MAX_SIZE";
391 #endif /* IFLA_GSO_MAX_SIZE */
395 #endif /* IFLA_PAD */
399 #endif /* IFLA_XDP */
403 #endif /* IFLA_EVENT */
404 case IFLA_PROTO_DOWN_REASON
:
405 return "PROTO_DOWN_REASON";
411 const char *rtm_type2str(int type
)
428 case RTN_UNREACHABLE
:
429 return "UNREACHABLE";
443 const char *rtm_protocol2str(int type
)
448 case RTPROT_REDIRECT
:
472 case RTPROT_DNROUTED
:
489 const char *rtm_scope2str(int type
)
492 case RT_SCOPE_UNIVERSE
:
500 case RT_SCOPE_NOWHERE
:
507 const char *rtm_rta2str(int type
)
553 const char *neigh_rta2str(int type
)
576 case NDA_LINK_NETNSID
:
577 return "LINK_NETNSID";
583 const char *ifa_rta2str(int type
)
609 const char *nhm_rta2str(int type
)
639 const char *frh_rta2str(int type
)
666 case FRA_SUPPRESS_IFGROUP
:
667 return "SUPPRESS_IFGROUP";
668 case FRA_SUPPRESS_PREFIXLEN
:
669 return "SUPPRESS_PREFIXLEN";
686 case FRA_SPORT_RANGE
:
687 return "SPORT_RANGE";
688 case FRA_DPORT_RANGE
:
689 return "DPORT_RANGE";
695 const char *frh_action2str(uint8_t action
)
708 case FR_ACT_BLACKHOLE
:
710 case FR_ACT_UNREACHABLE
:
711 return "UNREACHABLE";
712 case FR_ACT_PROHIBIT
:
719 static const char *ncm_rta2str(int type
)
722 case NETCONFA_UNSPEC
:
724 case NETCONFA_IFINDEX
:
726 case NETCONFA_FORWARDING
:
728 case NETCONFA_RP_FILTER
:
730 case NETCONFA_MC_FORWARDING
:
732 case NETCONFA_PROXY_NEIGH
:
733 return "PROXY_NEIGH";
734 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
735 return "IGNORE_LINKDOWN";
738 case NETCONFA_BC_FORWARDING
:
745 static void dump_on_off(uint32_t ival
, const char *prefix
)
747 zlog_debug("%s%s", prefix
, (ival
!= 0) ? "on" : "off");
750 static inline void flag_write(int flags
, int flag
, const char *flagstr
,
751 char *buf
, size_t buflen
)
753 if (CHECK_FLAG(flags
, flag
) == 0)
757 strlcat(buf
, ",", buflen
);
759 strlcat(buf
, flagstr
, buflen
);
762 const char *nlmsg_flags2str(uint16_t flags
, char *buf
, size_t buflen
)
764 const char *bufp
= buf
;
767 /* Specific flags. */
768 flag_write(flags
, NLM_F_REQUEST
, "REQUEST", buf
, buflen
);
769 flag_write(flags
, NLM_F_MULTI
, "MULTI", buf
, buflen
);
770 flag_write(flags
, NLM_F_ACK
, "ACK", buf
, buflen
);
771 flag_write(flags
, NLM_F_ECHO
, "ECHO", buf
, buflen
);
772 flag_write(flags
, NLM_F_DUMP
, "DUMP", buf
, buflen
);
774 /* Netlink family type dependent. */
775 flag_write(flags
, 0x0100, "(ROOT|REPLACE|CAPPED)", buf
, buflen
);
776 flag_write(flags
, 0x0200, "(MATCH|EXCLUDE|ACK_TLVS)", buf
, buflen
);
777 flag_write(flags
, 0x0400, "(ATOMIC|CREATE)", buf
, buflen
);
778 flag_write(flags
, 0x0800, "(DUMP|APPEND)", buf
, buflen
);
783 const char *if_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
785 const char *bufp
= buf
;
788 flag_write(flags
, IFF_UP
, "UP", buf
, buflen
);
789 flag_write(flags
, IFF_BROADCAST
, "BROADCAST", buf
, buflen
);
790 flag_write(flags
, IFF_DEBUG
, "DEBUG", buf
, buflen
);
791 flag_write(flags
, IFF_LOOPBACK
, "LOOPBACK", buf
, buflen
);
792 flag_write(flags
, IFF_POINTOPOINT
, "POINTOPOINT", buf
, buflen
);
793 flag_write(flags
, IFF_NOTRAILERS
, "NOTRAILERS", buf
, buflen
);
794 flag_write(flags
, IFF_RUNNING
, "RUNNING", buf
, buflen
);
795 flag_write(flags
, IFF_NOARP
, "NOARP", buf
, buflen
);
796 flag_write(flags
, IFF_PROMISC
, "PROMISC", buf
, buflen
);
797 flag_write(flags
, IFF_ALLMULTI
, "ALLMULTI", buf
, buflen
);
798 flag_write(flags
, IFF_MASTER
, "MASTER", buf
, buflen
);
799 flag_write(flags
, IFF_SLAVE
, "SLAVE", buf
, buflen
);
800 flag_write(flags
, IFF_MULTICAST
, "MULTICAST", buf
, buflen
);
801 flag_write(flags
, IFF_PORTSEL
, "PORTSEL", buf
, buflen
);
802 flag_write(flags
, IFF_AUTOMEDIA
, "AUTOMEDIA", buf
, buflen
);
803 flag_write(flags
, IFF_DYNAMIC
, "DYNAMIC", buf
, buflen
);
808 const char *rtm_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
810 const char *bufp
= buf
;
813 flag_write(flags
, RTM_F_NOTIFY
, "NOTIFY", buf
, buflen
);
814 flag_write(flags
, RTM_F_CLONED
, "CLONED", buf
, buflen
);
815 flag_write(flags
, RTM_F_EQUALIZE
, "EQUALIZE", buf
, buflen
);
820 const char *neigh_state2str(uint32_t flags
, char *buf
, size_t buflen
)
822 const char *bufp
= buf
;
825 flag_write(flags
, NUD_INCOMPLETE
, "INCOMPLETE", buf
, buflen
);
826 flag_write(flags
, NUD_REACHABLE
, "REACHABLE", buf
, buflen
);
827 flag_write(flags
, NUD_STALE
, "STALE", buf
, buflen
);
828 flag_write(flags
, NUD_DELAY
, "DELAY", buf
, buflen
);
829 flag_write(flags
, NUD_PROBE
, "PROBE", buf
, buflen
);
830 flag_write(flags
, NUD_FAILED
, "FAILED", buf
, buflen
);
831 flag_write(flags
, NUD_NOARP
, "NOARP", buf
, buflen
);
832 flag_write(flags
, NUD_PERMANENT
, "PERMANENT", buf
, buflen
);
837 const char *neigh_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
839 const char *bufp
= buf
;
842 flag_write(flags
, NTF_USE
, "USE", buf
, buflen
);
843 flag_write(flags
, NTF_SELF
, "SELF", buf
, buflen
);
844 flag_write(flags
, NTF_MASTER
, "MASTER", buf
, buflen
);
845 flag_write(flags
, NTF_PROXY
, "PROXY", buf
, buflen
);
846 flag_write(flags
, NTF_EXT_LEARNED
, "EXT_LEARNED", buf
, buflen
);
848 flag_write(flags
, NTF_OFFLOADED
, "OFFLOADED", buf
, buflen
);
849 #endif /* NTF_OFFLOADED */
850 flag_write(flags
, NTF_ROUTER
, "ROUTER", buf
, buflen
);
855 const char *ifa_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
857 const char *bufp
= buf
;
860 flag_write(flags
, IFA_F_SECONDARY
, "SECONDARY", buf
, buflen
);
861 flag_write(flags
, IFA_F_NODAD
, "NODAD", buf
, buflen
);
862 flag_write(flags
, IFA_F_OPTIMISTIC
, "OPTIMISTIC", buf
, buflen
);
863 flag_write(flags
, IFA_F_DADFAILED
, "DADFAILED", buf
, buflen
);
864 flag_write(flags
, IFA_F_HOMEADDRESS
, "HOMEADDRESS", buf
, buflen
);
865 flag_write(flags
, IFA_F_DEPRECATED
, "DEPRECATED", buf
, buflen
);
866 flag_write(flags
, IFA_F_TENTATIVE
, "TENTATIVE", buf
, buflen
);
867 flag_write(flags
, IFA_F_PERMANENT
, "PERMANENT", buf
, buflen
);
868 flag_write(flags
, IFA_F_MANAGETEMPADDR
, "MANAGETEMPADDR", buf
, buflen
);
869 flag_write(flags
, IFA_F_NOPREFIXROUTE
, "NOPREFIXROUTE", buf
, buflen
);
870 flag_write(flags
, IFA_F_MCAUTOJOIN
, "MCAUTOJOIN", buf
, buflen
);
871 flag_write(flags
, IFA_F_STABLE_PRIVACY
, "STABLE_PRIVACY", buf
, buflen
);
876 const char *nh_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
878 const char *bufp
= buf
;
881 flag_write(flags
, RTNH_F_DEAD
, "DEAD", buf
, buflen
);
882 flag_write(flags
, RTNH_F_PERVASIVE
, "PERVASIVE", buf
, buflen
);
883 flag_write(flags
, RTNH_F_ONLINK
, "ONLINK", buf
, buflen
);
884 flag_write(flags
, RTNH_F_OFFLOAD
, "OFFLOAD", buf
, buflen
);
885 flag_write(flags
, RTNH_F_LINKDOWN
, "LINKDOWN", buf
, buflen
);
886 flag_write(flags
, RTNH_F_UNRESOLVED
, "UNRESOLVED", buf
, buflen
);
892 * Netlink abstractions.
894 static void nllink_pdr_dump(struct rtattr
*rta
, size_t msglen
)
900 /* Check the header for valid length and for outbound access. */
901 if (RTA_OK(rta
, msglen
) == 0)
904 plen
= RTA_PAYLOAD(rta
);
905 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
906 rta
->rta_len
, plen
, rta
->rta_type
,
907 ifla_pdr_type2str(rta
->rta_type
));
908 switch (rta
->rta_type
) {
909 case IFLA_PROTO_DOWN_REASON_MASK
:
910 case IFLA_PROTO_DOWN_REASON_VALUE
:
911 if (plen
< sizeof(uint32_t)) {
912 zlog_debug(" invalid length");
916 u32v
= *(uint32_t *)RTA_DATA(rta
);
917 zlog_debug(" %u", u32v
);
921 /* NOTHING: unhandled. */
925 /* Get next pointer and start iteration again. */
926 rta
= RTA_NEXT(rta
, msglen
);
930 static void nllink_linkinfo_dump(struct rtattr
*rta
, size_t msglen
)
936 /* Check the header for valid length and for outbound access. */
937 if (RTA_OK(rta
, msglen
) == 0)
940 plen
= RTA_PAYLOAD(rta
);
941 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
942 rta
->rta_len
, plen
, rta
->rta_type
,
943 ifla_info_type2str(rta
->rta_type
));
944 switch (rta
->rta_type
) {
947 zlog_debug(" invalid length");
951 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
952 zlog_debug(" %s", dbuf
);
954 case IFLA_INFO_SLAVE_KIND
:
956 zlog_debug(" invalid length");
960 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
961 zlog_debug(" %s", dbuf
);
965 /* NOTHING: unhandled. */
969 /* Get next pointer and start iteration again. */
970 rta
= RTA_NEXT(rta
, msglen
);
974 static void nllink_dump(struct ifinfomsg
*ifi
, size_t msglen
)
983 unsigned short rta_type
;
985 /* Get the first attribute and go from there. */
988 /* Check the header for valid length and for outbound access. */
989 if (RTA_OK(rta
, msglen
) == 0)
992 plen
= RTA_PAYLOAD(rta
);
993 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
994 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
995 plen
, rta_type
, rta_type2str(rta_type
));
999 zlog_debug(" invalid length");
1003 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
1004 zlog_debug(" %s", dbuf
);
1009 case IFLA_NUM_TX_QUEUES
:
1010 case IFLA_NUM_RX_QUEUES
:
1012 case IFLA_PROMISCUITY
:
1013 #ifdef IFLA_GSO_MAX_SEGS
1014 case IFLA_GSO_MAX_SEGS
:
1015 #endif /* IFLA_GSO_MAX_SEGS */
1016 #ifdef IFLA_GSO_MAX_SIZE
1017 case IFLA_GSO_MAX_SIZE
:
1018 #endif /* IFLA_GSO_MAX_SIZE */
1019 case IFLA_CARRIER_CHANGES
:
1022 if (plen
< sizeof(uint32_t)) {
1023 zlog_debug(" invalid length");
1027 u32v
= *(uint32_t *)RTA_DATA(rta
);
1028 zlog_debug(" %u", u32v
);
1031 case IFLA_PROTO_DOWN
:
1032 if (plen
< sizeof(uint8_t)) {
1033 zlog_debug(" invalid length");
1037 u8v
= *(uint8_t *)RTA_DATA(rta
);
1038 zlog_debug(" %u", u8v
);
1041 datap
= RTA_DATA(rta
);
1043 for (it
= 0; it
< plen
; it
++) {
1044 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
1045 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
1048 /* Remove trailing ':'. */
1050 dbuf
[strlen(dbuf
) - 1] = 0;
1052 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
1056 nllink_linkinfo_dump(RTA_DATA(rta
), plen
);
1059 case IFLA_PROTO_DOWN_REASON
:
1060 nllink_pdr_dump(RTA_DATA(rta
), plen
);
1064 /* NOTHING: unhandled. */
1068 /* Get next pointer and start iteration again. */
1069 rta
= RTA_NEXT(rta
, msglen
);
1073 static void nlroute_dump(struct rtmsg
*rtm
, size_t msglen
)
1075 struct rta_mfc_stats
*mfc_stats
;
1081 /* Get the first attribute and go from there. */
1084 /* Check the header for valid length and for outbound access. */
1085 if (RTA_OK(rta
, msglen
) == 0)
1088 plen
= RTA_PAYLOAD(rta
);
1089 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1090 plen
, rta
->rta_type
& NLA_TYPE_MASK
,
1091 rtm_rta2str(rta
->rta_type
& NLA_TYPE_MASK
));
1092 switch (rta
->rta_type
& NLA_TYPE_MASK
) {
1098 u32v
= *(uint32_t *)RTA_DATA(rta
);
1099 zlog_debug(" %u", u32v
);
1103 u64v
= *(uint64_t *)RTA_DATA(rta
);
1104 zlog_debug(" %" PRIu64
, u64v
);
1112 case sizeof(struct in_addr
):
1114 (struct in_addr
*)RTA_DATA(rta
));
1116 case sizeof(struct in6_addr
):
1118 (struct in6_addr
*)RTA_DATA(rta
));
1126 mfc_stats
= (struct rta_mfc_stats
*)RTA_DATA(rta
);
1127 zlog_debug(" pkts=%ju bytes=%ju wrong_if=%ju",
1128 (uintmax_t)mfc_stats
->mfcs_packets
,
1129 (uintmax_t)mfc_stats
->mfcs_bytes
,
1130 (uintmax_t)mfc_stats
->mfcs_wrong_if
);
1134 /* NOTHING: unhandled. */
1138 /* Get next pointer and start iteration again. */
1139 rta
= RTA_NEXT(rta
, msglen
);
1143 static void nlneigh_dump(struct ndmsg
*ndm
, size_t msglen
)
1151 unsigned short rta_type
;
1154 #define NDA_RTA(ndm) \
1155 /* struct ndmsg *ndm; */ \
1156 ((struct rtattr *)(((uint8_t *)(ndm)) \
1157 + NLMSG_ALIGN(sizeof(struct ndmsg))))
1158 #endif /* NDA_RTA */
1160 /* Get the first attribute and go from there. */
1163 /* Check the header for valid length and for outbound access. */
1164 if (RTA_OK(rta
, msglen
) == 0)
1167 plen
= RTA_PAYLOAD(rta
);
1168 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
1169 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1170 plen
, rta
->rta_type
, neigh_rta2str(rta_type
));
1173 datap
= RTA_DATA(rta
);
1175 for (it
= 0; it
< plen
; it
++) {
1176 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
1177 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
1180 /* Remove trailing ':'. */
1182 dbuf
[strlen(dbuf
) - 1] = 0;
1184 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
1189 case sizeof(struct in_addr
):
1191 (struct in_addr
*)RTA_DATA(rta
));
1193 case sizeof(struct in6_addr
):
1195 (struct in6_addr
*)RTA_DATA(rta
));
1203 vid
= *(uint16_t *)RTA_DATA(rta
);
1204 zlog_debug(" %d", vid
);
1208 /* NOTHING: unhandled. */
1212 /* Get next pointer and start iteration again. */
1213 rta
= RTA_NEXT(rta
, msglen
);
1217 static void nlifa_dump(struct ifaddrmsg
*ifa
, size_t msglen
)
1223 /* Get the first attribute and go from there. */
1226 /* Check the header for valid length and for outbound access. */
1227 if (RTA_OK(rta
, msglen
) == 0)
1230 plen
= RTA_PAYLOAD(rta
);
1231 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1232 plen
, rta
->rta_type
, ifa_rta2str(rta
->rta_type
));
1233 switch (rta
->rta_type
) {
1235 u32v
= *(uint32_t *)RTA_DATA(rta
);
1236 zlog_debug(" %u", u32v
);
1240 zlog_debug(" %s", (const char *)RTA_DATA(rta
));
1249 (struct in_addr
*)RTA_DATA(rta
));
1253 (struct in6_addr
*)RTA_DATA(rta
));
1261 /* NOTHING: unhandled. */
1265 /* Get next pointer and start iteration again. */
1266 rta
= RTA_NEXT(rta
, msglen
);
1270 static void nltnl_dump(struct tunnel_msg
*tnlm
, size_t msglen
)
1272 struct rtattr
*attr
;
1273 vni_t vni_start
= 0, vni_end
= 0;
1274 struct rtattr
*ttb
[VXLAN_VNIFILTER_ENTRY_MAX
+ 1];
1277 attr
= TUNNEL_RTA(tnlm
);
1279 /* Check the header for valid length and for outbound access. */
1280 if (RTA_OK(attr
, msglen
) == 0)
1283 rta_type
= attr
->rta_type
& NLA_TYPE_MASK
;
1285 if (rta_type
!= VXLAN_VNIFILTER_ENTRY
) {
1286 attr
= RTA_NEXT(attr
, msglen
);
1290 memset(ttb
, 0, sizeof(ttb
));
1292 netlink_parse_rtattr_flags(ttb
, VXLAN_VNIFILTER_ENTRY_MAX
,
1293 RTA_DATA(attr
), RTA_PAYLOAD(attr
),
1296 if (ttb
[VXLAN_VNIFILTER_ENTRY_START
])
1298 *(uint32_t *)RTA_DATA(ttb
[VXLAN_VNIFILTER_ENTRY_START
]);
1300 if (ttb
[VXLAN_VNIFILTER_ENTRY_END
])
1301 vni_end
= *(uint32_t *)RTA_DATA(ttb
[VXLAN_VNIFILTER_ENTRY_END
]);
1302 zlog_debug(" vni_start %u, vni_end %u", vni_start
, vni_end
);
1304 attr
= RTA_NEXT(attr
, msglen
);
1308 static const char *lwt_type2str(uint16_t type
)
1311 case LWTUNNEL_ENCAP_NONE
:
1313 case LWTUNNEL_ENCAP_MPLS
:
1315 case LWTUNNEL_ENCAP_IP
:
1317 case LWTUNNEL_ENCAP_ILA
:
1319 case LWTUNNEL_ENCAP_IP6
:
1321 case LWTUNNEL_ENCAP_SEG6
:
1323 case LWTUNNEL_ENCAP_BPF
:
1325 case LWTUNNEL_ENCAP_SEG6_LOCAL
:
1326 return "SEG6_LOCAL";
1332 static const char *nhg_type2str(uint16_t type
)
1335 case NEXTHOP_GRP_TYPE_MPATH
:
1337 case NEXTHOP_GRP_TYPE_RES
:
1338 return "RESILIENT MULTIPATH";
1344 static void nlnh_dump(struct nhmsg
*nhm
, size_t msglen
)
1351 unsigned long count
, i
;
1352 struct nexthop_grp
*nhgrp
;
1353 unsigned short rta_type
;
1358 /* Check the header for valid length and for outbound access. */
1359 if (RTA_OK(rta
, msglen
) == 0)
1362 plen
= RTA_PAYLOAD(rta
);
1363 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
1364 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1365 plen
, rta
->rta_type
, nhm_rta2str(rta_type
));
1368 u32v
= *(uint32_t *)RTA_DATA(rta
);
1369 zlog_debug(" %u", u32v
);
1372 nhgrp
= (struct nexthop_grp
*)RTA_DATA(rta
);
1373 count
= (RTA_PAYLOAD(rta
) / sizeof(*nhgrp
));
1375 || (count
* sizeof(*nhgrp
)) != RTA_PAYLOAD(rta
)) {
1376 zlog_debug(" invalid nexthop group received");
1380 for (i
= 0; i
< count
; i
++)
1381 zlog_debug(" id %d weight %d", nhgrp
[i
].id
,
1384 case NHA_ENCAP_TYPE
:
1385 u16v
= *(uint16_t *)RTA_DATA(rta
);
1386 zlog_debug(" %s", lwt_type2str(u16v
));
1388 case NHA_GROUP_TYPE
:
1389 u16v
= *(uint16_t *)RTA_DATA(rta
);
1390 zlog_debug(" %s", nhg_type2str(u16v
));
1396 ifindex
= *(int *)RTA_DATA(rta
);
1397 zlog_debug(" %d", ifindex
);
1400 switch (nhm
->nh_family
) {
1403 (struct in_addr
*)RTA_DATA(rta
));
1407 (struct in6_addr
*)RTA_DATA(rta
));
1411 zlog_debug(" invalid family %d", nhm
->nh_family
);
1416 /* TODO: handle MPLS labels. */
1417 zlog_debug(" unparsed MPLS labels");
1420 /* TODO: handle this message. */
1421 zlog_debug(" unparsed GROUPS message");
1425 /* NOTHING: unhandled. */
1429 /* Get next pointer and start iteration again. */
1430 rta
= RTA_NEXT(rta
, msglen
);
1434 static void nlrule_dump(struct fib_rule_hdr
*frh
, size_t msglen
)
1443 struct fib_rule_uid_range
*u_range
;
1444 struct fib_rule_port_range
*p_range
;
1446 /* Get the first attribute and go from there. */
1449 /* Check the header for valid length and for outbound access. */
1450 if (RTA_OK(rta
, msglen
) == 0)
1453 plen
= RTA_PAYLOAD(rta
);
1454 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1455 plen
, rta
->rta_type
, frh_rta2str(rta
->rta_type
));
1456 switch (rta
->rta_type
) {
1460 case sizeof(struct in_addr
):
1462 (struct in_addr
*)RTA_DATA(rta
));
1464 case sizeof(struct in6_addr
):
1466 (struct in6_addr
*)RTA_DATA(rta
));
1475 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
1476 zlog_debug(" %s", dbuf
);
1489 u32v
= *(uint32_t *)RTA_DATA(rta
);
1490 zlog_debug(" %u", u32v
);
1493 case FRA_SUPPRESS_IFGROUP
:
1494 case FRA_SUPPRESS_PREFIXLEN
:
1495 s32v
= *(int32_t *)RTA_DATA(rta
);
1496 zlog_debug(" %d", s32v
);
1500 u64v
= *(uint64_t *)RTA_DATA(rta
);
1501 zlog_debug(" %" PRIu64
, u64v
);
1507 u8v
= *(uint8_t *)RTA_DATA(rta
);
1508 zlog_debug(" %u", u8v
);
1512 u_range
= (struct fib_rule_uid_range
*)RTA_DATA(rta
);
1513 if (u_range
->start
== u_range
->end
)
1514 zlog_debug(" %u", u_range
->start
);
1516 zlog_debug(" %u-%u", u_range
->start
, u_range
->end
);
1519 case FRA_SPORT_RANGE
:
1520 case FRA_DPORT_RANGE
:
1521 p_range
= (struct fib_rule_port_range
*)RTA_DATA(rta
);
1522 if (p_range
->start
== p_range
->end
)
1523 zlog_debug(" %u", p_range
->start
);
1525 zlog_debug(" %u-%u", p_range
->start
, p_range
->end
);
1528 case FRA_PAD
: /* fallthrough */
1530 /* NOTHING: unhandled. */
1534 /* Get next pointer and start iteration again. */
1535 rta
= RTA_NEXT(rta
, msglen
);
1539 static void nlncm_dump(const struct netconfmsg
*ncm
, size_t msglen
)
1541 const struct rtattr
*rta
;
1545 rta
= (void *)((const char *)ncm
+
1546 NLMSG_ALIGN(sizeof(struct netconfmsg
)));
1549 /* Check the attr header for valid length. */
1550 if (RTA_OK(rta
, msglen
) == 0)
1553 plen
= RTA_PAYLOAD(rta
);
1555 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1556 plen
, rta
->rta_type
, ncm_rta2str(rta
->rta_type
));
1558 switch (rta
->rta_type
) {
1559 case NETCONFA_IFINDEX
:
1560 ival
= *(uint32_t *)RTA_DATA(rta
);
1561 zlog_debug(" %d", (int32_t)ival
);
1564 /* Most attrs are just on/off. */
1565 case NETCONFA_FORWARDING
:
1566 case NETCONFA_RP_FILTER
:
1567 case NETCONFA_MC_FORWARDING
:
1568 case NETCONFA_PROXY_NEIGH
:
1569 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
1570 case NETCONFA_INPUT
:
1571 case NETCONFA_BC_FORWARDING
:
1572 ival
= *(uint32_t *)RTA_DATA(rta
);
1573 dump_on_off(ival
, " ");
1576 /* NOTHING: unhandled. */
1580 /* Get next pointer and start iteration again. */
1581 rta
= RTA_NEXT(rta
, msglen
);
1585 void nl_dump(void *msg
, size_t msglen
)
1587 struct nlmsghdr
*nlmsg
= msg
;
1588 struct nlmsgerr
*nlmsgerr
;
1589 struct rtgenmsg
*rtgen
;
1590 struct ifaddrmsg
*ifa
;
1594 struct netconfmsg
*ncm
;
1595 struct ifinfomsg
*ifi
;
1596 struct tunnel_msg
*tnlm
;
1597 struct fib_rule_hdr
*frh
;
1603 "nlmsghdr [len=%u type=(%d) %s flags=(0x%04x) {%s} seq=%u pid=%u]",
1604 nlmsg
->nlmsg_len
, nlmsg
->nlmsg_type
,
1605 nlmsg_type2str(nlmsg
->nlmsg_type
), nlmsg
->nlmsg_flags
,
1606 nlmsg_flags2str(nlmsg
->nlmsg_flags
, fbuf
, sizeof(fbuf
)),
1607 nlmsg
->nlmsg_seq
, nlmsg
->nlmsg_pid
);
1609 switch (nlmsg
->nlmsg_type
) {
1614 nlmsgerr
= NLMSG_DATA(nlmsg
);
1615 zlog_debug(" nlmsgerr [error=(%d) %s]", nlmsgerr
->error
,
1616 strerror(-nlmsgerr
->error
));
1627 ifi
= NLMSG_DATA(nlmsg
);
1629 " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]",
1630 ifi
->ifi_family
, ifi
->ifi_type
,
1631 ifi_type2str(ifi
->ifi_type
), ifi
->ifi_index
,
1633 if_flags2str(ifi
->ifi_flags
, ibuf
, sizeof(ibuf
)));
1634 nllink_dump(ifi
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
)));
1637 rtgen
= NLMSG_DATA(nlmsg
);
1638 zlog_debug(" rtgen [family=(%d) %s]", rtgen
->rtgen_family
,
1639 af_type2str(rtgen
->rtgen_family
));
1645 rtm
= NLMSG_DATA(nlmsg
);
1647 " 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}]",
1648 rtm
->rtm_family
, af_type2str(rtm
->rtm_family
),
1649 rtm
->rtm_dst_len
, rtm
->rtm_src_len
, rtm
->rtm_tos
,
1650 rtm
->rtm_table
, rtm
->rtm_protocol
,
1651 rtm_protocol2str(rtm
->rtm_protocol
), rtm
->rtm_scope
,
1652 rtm_scope2str(rtm
->rtm_scope
), rtm
->rtm_type
,
1653 rtm_type2str(rtm
->rtm_type
), rtm
->rtm_flags
,
1654 rtm_flags2str(rtm
->rtm_flags
, fbuf
, sizeof(fbuf
)));
1656 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*rtm
)));
1661 ndm
= NLMSG_DATA(nlmsg
);
1663 " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]",
1664 ndm
->ndm_family
, af_type2str(ndm
->ndm_family
),
1665 ndm
->ndm_ifindex
, ndm
->ndm_state
,
1666 neigh_state2str(ndm
->ndm_state
, ibuf
, sizeof(ibuf
)),
1668 neigh_flags2str(ndm
->ndm_flags
, fbuf
, sizeof(fbuf
)),
1669 ndm
->ndm_type
, rtm_type2str(ndm
->ndm_type
));
1671 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ndm
)));
1676 frh
= NLMSG_DATA(nlmsg
);
1678 " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]",
1679 frh
->family
, af_type2str(frh
->family
), frh
->dst_len
,
1680 frh
->src_len
, frh
->tos
, frh
->table
, frh
->res1
,
1681 frh
->res2
, frh
->action
, frh_action2str(frh
->action
),
1683 nlrule_dump(frh
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*frh
)));
1689 ifa
= NLMSG_DATA(nlmsg
);
1691 " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]",
1692 ifa
->ifa_family
, af_type2str(ifa
->ifa_family
),
1693 ifa
->ifa_prefixlen
, ifa
->ifa_flags
,
1694 if_flags2str(ifa
->ifa_flags
, fbuf
, sizeof(fbuf
)),
1695 ifa
->ifa_scope
, ifa
->ifa_index
);
1696 nlifa_dump(ifa
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifa
)));
1699 case RTM_NEWNEXTHOP
:
1700 case RTM_DELNEXTHOP
:
1701 case RTM_GETNEXTHOP
:
1702 nhm
= NLMSG_DATA(nlmsg
);
1704 " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]",
1705 nhm
->nh_family
, af_type2str(nhm
->nh_family
),
1706 nhm
->nh_scope
, rtm_scope2str(nhm
->nh_scope
),
1707 nhm
->nh_protocol
, rtm_protocol2str(nhm
->nh_protocol
),
1709 nh_flags2str(nhm
->nh_flags
, fbuf
, sizeof(fbuf
)));
1710 nlnh_dump(nhm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*nhm
)));
1716 tnlm
= NLMSG_DATA(nlmsg
);
1717 zlog_debug(" tnlm [family=(%d) %s ifindex=%d ", tnlm
->family
,
1718 af_type2str(tnlm
->family
), tnlm
->ifindex
);
1721 NLMSG_LENGTH(sizeof(struct tunnel_msg
)));
1725 case RTM_NEWNETCONF
:
1726 case RTM_DELNETCONF
:
1727 ncm
= NLMSG_DATA(nlmsg
);
1728 zlog_debug(" ncm [family=%s (%d)]",
1729 af_type2str(ncm
->ncm_family
), ncm
->ncm_family
);
1730 nlncm_dump(ncm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ncm
)));
1738 * Try to get the next header. There should only be more
1739 * messages if this header was flagged as MULTI, otherwise just
1742 nlmsg
= NLMSG_NEXT(nlmsg
, msglen
);
1743 if (NLMSG_OK(nlmsg
, msglen
) == 0)
1749 #endif /* NETLINK_DEBUG */