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
)
551 const char *neigh_rta2str(int type
)
574 case NDA_LINK_NETNSID
:
575 return "LINK_NETNSID";
581 const char *ifa_rta2str(int type
)
607 const char *nhm_rta2str(int type
)
637 const char *frh_rta2str(int type
)
664 case FRA_SUPPRESS_IFGROUP
:
665 return "SUPPRESS_IFGROUP";
666 case FRA_SUPPRESS_PREFIXLEN
:
667 return "SUPPRESS_PREFIXLEN";
684 case FRA_SPORT_RANGE
:
685 return "SPORT_RANGE";
686 case FRA_DPORT_RANGE
:
687 return "DPORT_RANGE";
693 const char *frh_action2str(uint8_t action
)
706 case FR_ACT_BLACKHOLE
:
708 case FR_ACT_UNREACHABLE
:
709 return "UNREACHABLE";
710 case FR_ACT_PROHIBIT
:
717 static const char *ncm_rta2str(int type
)
720 case NETCONFA_UNSPEC
:
722 case NETCONFA_IFINDEX
:
724 case NETCONFA_FORWARDING
:
726 case NETCONFA_RP_FILTER
:
728 case NETCONFA_MC_FORWARDING
:
730 case NETCONFA_PROXY_NEIGH
:
731 return "PROXY_NEIGH";
732 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
733 return "IGNORE_LINKDOWN";
736 case NETCONFA_BC_FORWARDING
:
743 static void dump_on_off(uint32_t ival
, const char *prefix
)
745 zlog_debug("%s%s", prefix
, (ival
!= 0) ? "on" : "off");
748 static inline void flag_write(int flags
, int flag
, const char *flagstr
,
749 char *buf
, size_t buflen
)
751 if (CHECK_FLAG(flags
, flag
) == 0)
755 strlcat(buf
, ",", buflen
);
757 strlcat(buf
, flagstr
, buflen
);
760 const char *nlmsg_flags2str(uint16_t flags
, char *buf
, size_t buflen
)
762 const char *bufp
= buf
;
765 /* Specific flags. */
766 flag_write(flags
, NLM_F_REQUEST
, "REQUEST", buf
, buflen
);
767 flag_write(flags
, NLM_F_MULTI
, "MULTI", buf
, buflen
);
768 flag_write(flags
, NLM_F_ACK
, "ACK", buf
, buflen
);
769 flag_write(flags
, NLM_F_ECHO
, "ECHO", buf
, buflen
);
770 flag_write(flags
, NLM_F_DUMP
, "DUMP", buf
, buflen
);
772 /* Netlink family type dependent. */
773 flag_write(flags
, 0x0100, "(ROOT|REPLACE|CAPPED)", buf
, buflen
);
774 flag_write(flags
, 0x0200, "(MATCH|EXCLUDE|ACK_TLVS)", buf
, buflen
);
775 flag_write(flags
, 0x0400, "(ATOMIC|CREATE)", buf
, buflen
);
776 flag_write(flags
, 0x0800, "(DUMP|APPEND)", buf
, buflen
);
781 const char *if_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
783 const char *bufp
= buf
;
786 flag_write(flags
, IFF_UP
, "UP", buf
, buflen
);
787 flag_write(flags
, IFF_BROADCAST
, "BROADCAST", buf
, buflen
);
788 flag_write(flags
, IFF_DEBUG
, "DEBUG", buf
, buflen
);
789 flag_write(flags
, IFF_LOOPBACK
, "LOOPBACK", buf
, buflen
);
790 flag_write(flags
, IFF_POINTOPOINT
, "POINTOPOINT", buf
, buflen
);
791 flag_write(flags
, IFF_NOTRAILERS
, "NOTRAILERS", buf
, buflen
);
792 flag_write(flags
, IFF_RUNNING
, "RUNNING", buf
, buflen
);
793 flag_write(flags
, IFF_NOARP
, "NOARP", buf
, buflen
);
794 flag_write(flags
, IFF_PROMISC
, "PROMISC", buf
, buflen
);
795 flag_write(flags
, IFF_ALLMULTI
, "ALLMULTI", buf
, buflen
);
796 flag_write(flags
, IFF_MASTER
, "MASTER", buf
, buflen
);
797 flag_write(flags
, IFF_SLAVE
, "SLAVE", buf
, buflen
);
798 flag_write(flags
, IFF_MULTICAST
, "MULTICAST", buf
, buflen
);
799 flag_write(flags
, IFF_PORTSEL
, "PORTSEL", buf
, buflen
);
800 flag_write(flags
, IFF_AUTOMEDIA
, "AUTOMEDIA", buf
, buflen
);
801 flag_write(flags
, IFF_DYNAMIC
, "DYNAMIC", buf
, buflen
);
806 const char *rtm_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
808 const char *bufp
= buf
;
811 flag_write(flags
, RTM_F_NOTIFY
, "NOTIFY", buf
, buflen
);
812 flag_write(flags
, RTM_F_CLONED
, "CLONED", buf
, buflen
);
813 flag_write(flags
, RTM_F_EQUALIZE
, "EQUALIZE", buf
, buflen
);
818 const char *neigh_state2str(uint32_t flags
, char *buf
, size_t buflen
)
820 const char *bufp
= buf
;
823 flag_write(flags
, NUD_INCOMPLETE
, "INCOMPLETE", buf
, buflen
);
824 flag_write(flags
, NUD_REACHABLE
, "REACHABLE", buf
, buflen
);
825 flag_write(flags
, NUD_STALE
, "STALE", buf
, buflen
);
826 flag_write(flags
, NUD_DELAY
, "DELAY", buf
, buflen
);
827 flag_write(flags
, NUD_PROBE
, "PROBE", buf
, buflen
);
828 flag_write(flags
, NUD_FAILED
, "FAILED", buf
, buflen
);
829 flag_write(flags
, NUD_NOARP
, "NOARP", buf
, buflen
);
830 flag_write(flags
, NUD_PERMANENT
, "PERMANENT", buf
, buflen
);
835 const char *neigh_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
837 const char *bufp
= buf
;
840 flag_write(flags
, NTF_USE
, "USE", buf
, buflen
);
841 flag_write(flags
, NTF_SELF
, "SELF", buf
, buflen
);
842 flag_write(flags
, NTF_MASTER
, "MASTER", buf
, buflen
);
843 flag_write(flags
, NTF_PROXY
, "PROXY", buf
, buflen
);
844 flag_write(flags
, NTF_EXT_LEARNED
, "EXT_LEARNED", buf
, buflen
);
846 flag_write(flags
, NTF_OFFLOADED
, "OFFLOADED", buf
, buflen
);
847 #endif /* NTF_OFFLOADED */
848 flag_write(flags
, NTF_ROUTER
, "ROUTER", buf
, buflen
);
853 const char *ifa_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
855 const char *bufp
= buf
;
858 flag_write(flags
, IFA_F_SECONDARY
, "SECONDARY", buf
, buflen
);
859 flag_write(flags
, IFA_F_NODAD
, "NODAD", buf
, buflen
);
860 flag_write(flags
, IFA_F_OPTIMISTIC
, "OPTIMISTIC", buf
, buflen
);
861 flag_write(flags
, IFA_F_DADFAILED
, "DADFAILED", buf
, buflen
);
862 flag_write(flags
, IFA_F_HOMEADDRESS
, "HOMEADDRESS", buf
, buflen
);
863 flag_write(flags
, IFA_F_DEPRECATED
, "DEPRECATED", buf
, buflen
);
864 flag_write(flags
, IFA_F_TENTATIVE
, "TENTATIVE", buf
, buflen
);
865 flag_write(flags
, IFA_F_PERMANENT
, "PERMANENT", buf
, buflen
);
866 flag_write(flags
, IFA_F_MANAGETEMPADDR
, "MANAGETEMPADDR", buf
, buflen
);
867 flag_write(flags
, IFA_F_NOPREFIXROUTE
, "NOPREFIXROUTE", buf
, buflen
);
868 flag_write(flags
, IFA_F_MCAUTOJOIN
, "MCAUTOJOIN", buf
, buflen
);
869 flag_write(flags
, IFA_F_STABLE_PRIVACY
, "STABLE_PRIVACY", buf
, buflen
);
874 const char *nh_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
876 const char *bufp
= buf
;
879 flag_write(flags
, RTNH_F_DEAD
, "DEAD", buf
, buflen
);
880 flag_write(flags
, RTNH_F_PERVASIVE
, "PERVASIVE", buf
, buflen
);
881 flag_write(flags
, RTNH_F_ONLINK
, "ONLINK", buf
, buflen
);
882 flag_write(flags
, RTNH_F_OFFLOAD
, "OFFLOAD", buf
, buflen
);
883 flag_write(flags
, RTNH_F_LINKDOWN
, "LINKDOWN", buf
, buflen
);
884 flag_write(flags
, RTNH_F_UNRESOLVED
, "UNRESOLVED", buf
, buflen
);
890 * Netlink abstractions.
892 static void nllink_pdr_dump(struct rtattr
*rta
, size_t msglen
)
898 /* Check the header for valid length and for outbound access. */
899 if (RTA_OK(rta
, msglen
) == 0)
902 plen
= RTA_PAYLOAD(rta
);
903 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
904 rta
->rta_len
, plen
, rta
->rta_type
,
905 ifla_pdr_type2str(rta
->rta_type
));
906 switch (rta
->rta_type
) {
907 case IFLA_PROTO_DOWN_REASON_MASK
:
908 case IFLA_PROTO_DOWN_REASON_VALUE
:
909 if (plen
< sizeof(uint32_t)) {
910 zlog_debug(" invalid length");
914 u32v
= *(uint32_t *)RTA_DATA(rta
);
915 zlog_debug(" %u", u32v
);
919 /* NOTHING: unhandled. */
923 /* Get next pointer and start iteration again. */
924 rta
= RTA_NEXT(rta
, msglen
);
928 static void nllink_linkinfo_dump(struct rtattr
*rta
, size_t msglen
)
934 /* Check the header for valid length and for outbound access. */
935 if (RTA_OK(rta
, msglen
) == 0)
938 plen
= RTA_PAYLOAD(rta
);
939 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
940 rta
->rta_len
, plen
, rta
->rta_type
,
941 ifla_info_type2str(rta
->rta_type
));
942 switch (rta
->rta_type
) {
945 zlog_debug(" invalid length");
949 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
950 zlog_debug(" %s", dbuf
);
952 case IFLA_INFO_SLAVE_KIND
:
954 zlog_debug(" invalid length");
958 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
959 zlog_debug(" %s", dbuf
);
963 /* NOTHING: unhandled. */
967 /* Get next pointer and start iteration again. */
968 rta
= RTA_NEXT(rta
, msglen
);
972 static void nllink_dump(struct ifinfomsg
*ifi
, size_t msglen
)
981 unsigned short rta_type
;
983 /* Get the first attribute and go from there. */
986 /* Check the header for valid length and for outbound access. */
987 if (RTA_OK(rta
, msglen
) == 0)
990 plen
= RTA_PAYLOAD(rta
);
991 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
992 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
993 plen
, rta_type
, rta_type2str(rta_type
));
997 zlog_debug(" invalid length");
1001 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
1002 zlog_debug(" %s", dbuf
);
1007 case IFLA_NUM_TX_QUEUES
:
1008 case IFLA_NUM_RX_QUEUES
:
1010 case IFLA_PROMISCUITY
:
1011 #ifdef IFLA_GSO_MAX_SEGS
1012 case IFLA_GSO_MAX_SEGS
:
1013 #endif /* IFLA_GSO_MAX_SEGS */
1014 #ifdef IFLA_GSO_MAX_SIZE
1015 case IFLA_GSO_MAX_SIZE
:
1016 #endif /* IFLA_GSO_MAX_SIZE */
1017 case IFLA_CARRIER_CHANGES
:
1020 if (plen
< sizeof(uint32_t)) {
1021 zlog_debug(" invalid length");
1025 u32v
= *(uint32_t *)RTA_DATA(rta
);
1026 zlog_debug(" %u", u32v
);
1029 case IFLA_PROTO_DOWN
:
1030 if (plen
< sizeof(uint8_t)) {
1031 zlog_debug(" invalid length");
1035 u8v
= *(uint8_t *)RTA_DATA(rta
);
1036 zlog_debug(" %u", u8v
);
1039 datap
= RTA_DATA(rta
);
1041 for (it
= 0; it
< plen
; it
++) {
1042 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
1043 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
1046 /* Remove trailing ':'. */
1048 dbuf
[strlen(dbuf
) - 1] = 0;
1050 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
1054 nllink_linkinfo_dump(RTA_DATA(rta
), plen
);
1057 case IFLA_PROTO_DOWN_REASON
:
1058 nllink_pdr_dump(RTA_DATA(rta
), plen
);
1062 /* NOTHING: unhandled. */
1066 /* Get next pointer and start iteration again. */
1067 rta
= RTA_NEXT(rta
, msglen
);
1071 static void nlroute_dump(struct rtmsg
*rtm
, size_t msglen
)
1077 /* Get the first attribute and go from there. */
1080 /* Check the header for valid length and for outbound access. */
1081 if (RTA_OK(rta
, msglen
) == 0)
1084 plen
= RTA_PAYLOAD(rta
);
1085 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1086 plen
, rta
->rta_type
& NLA_TYPE_MASK
,
1087 rtm_rta2str(rta
->rta_type
& NLA_TYPE_MASK
));
1088 switch (rta
->rta_type
& NLA_TYPE_MASK
) {
1094 u32v
= *(uint32_t *)RTA_DATA(rta
);
1095 zlog_debug(" %u", u32v
);
1103 case sizeof(struct in_addr
):
1105 (struct in_addr
*)RTA_DATA(rta
));
1107 case sizeof(struct in6_addr
):
1109 (struct in6_addr
*)RTA_DATA(rta
));
1117 /* NOTHING: unhandled. */
1121 /* Get next pointer and start iteration again. */
1122 rta
= RTA_NEXT(rta
, msglen
);
1126 static void nlneigh_dump(struct ndmsg
*ndm
, size_t msglen
)
1134 unsigned short rta_type
;
1137 #define NDA_RTA(ndm) \
1138 /* struct ndmsg *ndm; */ \
1139 ((struct rtattr *)(((uint8_t *)(ndm)) \
1140 + NLMSG_ALIGN(sizeof(struct ndmsg))))
1141 #endif /* NDA_RTA */
1143 /* Get the first attribute and go from there. */
1146 /* Check the header for valid length and for outbound access. */
1147 if (RTA_OK(rta
, msglen
) == 0)
1150 plen
= RTA_PAYLOAD(rta
);
1151 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
1152 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1153 plen
, rta
->rta_type
, neigh_rta2str(rta_type
));
1156 datap
= RTA_DATA(rta
);
1158 for (it
= 0; it
< plen
; it
++) {
1159 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
1160 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
1163 /* Remove trailing ':'. */
1165 dbuf
[strlen(dbuf
) - 1] = 0;
1167 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
1172 case sizeof(struct in_addr
):
1174 (struct in_addr
*)RTA_DATA(rta
));
1176 case sizeof(struct in6_addr
):
1178 (struct in6_addr
*)RTA_DATA(rta
));
1186 vid
= *(uint16_t *)RTA_DATA(rta
);
1187 zlog_debug(" %d", vid
);
1191 /* NOTHING: unhandled. */
1195 /* Get next pointer and start iteration again. */
1196 rta
= RTA_NEXT(rta
, msglen
);
1200 static void nlifa_dump(struct ifaddrmsg
*ifa
, size_t msglen
)
1206 /* Get the first attribute and go from there. */
1209 /* Check the header for valid length and for outbound access. */
1210 if (RTA_OK(rta
, msglen
) == 0)
1213 plen
= RTA_PAYLOAD(rta
);
1214 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1215 plen
, rta
->rta_type
, ifa_rta2str(rta
->rta_type
));
1216 switch (rta
->rta_type
) {
1218 u32v
= *(uint32_t *)RTA_DATA(rta
);
1219 zlog_debug(" %u", u32v
);
1223 zlog_debug(" %s", (const char *)RTA_DATA(rta
));
1232 (struct in_addr
*)RTA_DATA(rta
));
1236 (struct in6_addr
*)RTA_DATA(rta
));
1244 /* NOTHING: unhandled. */
1248 /* Get next pointer and start iteration again. */
1249 rta
= RTA_NEXT(rta
, msglen
);
1253 static void nltnl_dump(struct tunnel_msg
*tnlm
, size_t msglen
)
1255 struct rtattr
*attr
;
1256 vni_t vni_start
= 0, vni_end
= 0;
1257 struct rtattr
*ttb
[VXLAN_VNIFILTER_ENTRY_MAX
+ 1];
1260 attr
= TUNNEL_RTA(tnlm
);
1262 /* Check the header for valid length and for outbound access. */
1263 if (RTA_OK(attr
, msglen
) == 0)
1266 rta_type
= attr
->rta_type
& NLA_TYPE_MASK
;
1268 if (rta_type
!= VXLAN_VNIFILTER_ENTRY
) {
1269 attr
= RTA_NEXT(attr
, msglen
);
1273 memset(ttb
, 0, sizeof(ttb
));
1275 netlink_parse_rtattr_flags(ttb
, VXLAN_VNIFILTER_ENTRY_MAX
,
1276 RTA_DATA(attr
), RTA_PAYLOAD(attr
),
1279 if (ttb
[VXLAN_VNIFILTER_ENTRY_START
])
1281 *(uint32_t *)RTA_DATA(ttb
[VXLAN_VNIFILTER_ENTRY_START
]);
1283 if (ttb
[VXLAN_VNIFILTER_ENTRY_END
])
1284 vni_end
= *(uint32_t *)RTA_DATA(ttb
[VXLAN_VNIFILTER_ENTRY_END
]);
1285 zlog_debug(" vni_start %u, vni_end %u", vni_start
, vni_end
);
1287 attr
= RTA_NEXT(attr
, msglen
);
1291 static const char *lwt_type2str(uint16_t type
)
1294 case LWTUNNEL_ENCAP_NONE
:
1296 case LWTUNNEL_ENCAP_MPLS
:
1298 case LWTUNNEL_ENCAP_IP
:
1300 case LWTUNNEL_ENCAP_ILA
:
1302 case LWTUNNEL_ENCAP_IP6
:
1304 case LWTUNNEL_ENCAP_SEG6
:
1306 case LWTUNNEL_ENCAP_BPF
:
1308 case LWTUNNEL_ENCAP_SEG6_LOCAL
:
1309 return "SEG6_LOCAL";
1315 static const char *nhg_type2str(uint16_t type
)
1318 case NEXTHOP_GRP_TYPE_MPATH
:
1320 case NEXTHOP_GRP_TYPE_RES
:
1321 return "RESILIENT MULTIPATH";
1327 static void nlnh_dump(struct nhmsg
*nhm
, size_t msglen
)
1334 unsigned long count
, i
;
1335 struct nexthop_grp
*nhgrp
;
1336 unsigned short rta_type
;
1341 /* Check the header for valid length and for outbound access. */
1342 if (RTA_OK(rta
, msglen
) == 0)
1345 plen
= RTA_PAYLOAD(rta
);
1346 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
1347 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1348 plen
, rta
->rta_type
, nhm_rta2str(rta_type
));
1351 u32v
= *(uint32_t *)RTA_DATA(rta
);
1352 zlog_debug(" %u", u32v
);
1355 nhgrp
= (struct nexthop_grp
*)RTA_DATA(rta
);
1356 count
= (RTA_PAYLOAD(rta
) / sizeof(*nhgrp
));
1358 || (count
* sizeof(*nhgrp
)) != RTA_PAYLOAD(rta
)) {
1359 zlog_debug(" invalid nexthop group received");
1363 for (i
= 0; i
< count
; i
++)
1364 zlog_debug(" id %d weight %d", nhgrp
[i
].id
,
1367 case NHA_ENCAP_TYPE
:
1368 u16v
= *(uint16_t *)RTA_DATA(rta
);
1369 zlog_debug(" %s", lwt_type2str(u16v
));
1371 case NHA_GROUP_TYPE
:
1372 u16v
= *(uint16_t *)RTA_DATA(rta
);
1373 zlog_debug(" %s", nhg_type2str(u16v
));
1379 ifindex
= *(int *)RTA_DATA(rta
);
1380 zlog_debug(" %d", ifindex
);
1383 switch (nhm
->nh_family
) {
1386 (struct in_addr
*)RTA_DATA(rta
));
1390 (struct in6_addr
*)RTA_DATA(rta
));
1394 zlog_debug(" invalid family %d", nhm
->nh_family
);
1399 /* TODO: handle MPLS labels. */
1400 zlog_debug(" unparsed MPLS labels");
1403 /* TODO: handle this message. */
1404 zlog_debug(" unparsed GROUPS message");
1408 /* NOTHING: unhandled. */
1412 /* Get next pointer and start iteration again. */
1413 rta
= RTA_NEXT(rta
, msglen
);
1417 static void nlrule_dump(struct fib_rule_hdr
*frh
, size_t msglen
)
1426 struct fib_rule_uid_range
*u_range
;
1427 struct fib_rule_port_range
*p_range
;
1429 /* Get the first attribute and go from there. */
1432 /* Check the header for valid length and for outbound access. */
1433 if (RTA_OK(rta
, msglen
) == 0)
1436 plen
= RTA_PAYLOAD(rta
);
1437 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1438 plen
, rta
->rta_type
, frh_rta2str(rta
->rta_type
));
1439 switch (rta
->rta_type
) {
1443 case sizeof(struct in_addr
):
1445 (struct in_addr
*)RTA_DATA(rta
));
1447 case sizeof(struct in6_addr
):
1449 (struct in6_addr
*)RTA_DATA(rta
));
1458 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
1459 zlog_debug(" %s", dbuf
);
1472 u32v
= *(uint32_t *)RTA_DATA(rta
);
1473 zlog_debug(" %u", u32v
);
1476 case FRA_SUPPRESS_IFGROUP
:
1477 case FRA_SUPPRESS_PREFIXLEN
:
1478 s32v
= *(int32_t *)RTA_DATA(rta
);
1479 zlog_debug(" %d", s32v
);
1483 u64v
= *(uint64_t *)RTA_DATA(rta
);
1484 zlog_debug(" %" PRIu64
, u64v
);
1490 u8v
= *(uint8_t *)RTA_DATA(rta
);
1491 zlog_debug(" %u", u8v
);
1495 u_range
= (struct fib_rule_uid_range
*)RTA_DATA(rta
);
1496 if (u_range
->start
== u_range
->end
)
1497 zlog_debug(" %u", u_range
->start
);
1499 zlog_debug(" %u-%u", u_range
->start
, u_range
->end
);
1502 case FRA_SPORT_RANGE
:
1503 case FRA_DPORT_RANGE
:
1504 p_range
= (struct fib_rule_port_range
*)RTA_DATA(rta
);
1505 if (p_range
->start
== p_range
->end
)
1506 zlog_debug(" %u", p_range
->start
);
1508 zlog_debug(" %u-%u", p_range
->start
, p_range
->end
);
1511 case FRA_PAD
: /* fallthrough */
1513 /* NOTHING: unhandled. */
1517 /* Get next pointer and start iteration again. */
1518 rta
= RTA_NEXT(rta
, msglen
);
1522 static void nlncm_dump(const struct netconfmsg
*ncm
, size_t msglen
)
1524 const struct rtattr
*rta
;
1528 rta
= (void *)((const char *)ncm
+
1529 NLMSG_ALIGN(sizeof(struct netconfmsg
)));
1532 /* Check the attr header for valid length. */
1533 if (RTA_OK(rta
, msglen
) == 0)
1536 plen
= RTA_PAYLOAD(rta
);
1538 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1539 plen
, rta
->rta_type
, ncm_rta2str(rta
->rta_type
));
1541 switch (rta
->rta_type
) {
1542 case NETCONFA_IFINDEX
:
1543 ival
= *(uint32_t *)RTA_DATA(rta
);
1544 zlog_debug(" %d", (int32_t)ival
);
1547 /* Most attrs are just on/off. */
1548 case NETCONFA_FORWARDING
:
1549 case NETCONFA_RP_FILTER
:
1550 case NETCONFA_MC_FORWARDING
:
1551 case NETCONFA_PROXY_NEIGH
:
1552 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
1553 case NETCONFA_INPUT
:
1554 case NETCONFA_BC_FORWARDING
:
1555 ival
= *(uint32_t *)RTA_DATA(rta
);
1556 dump_on_off(ival
, " ");
1559 /* NOTHING: unhandled. */
1563 /* Get next pointer and start iteration again. */
1564 rta
= RTA_NEXT(rta
, msglen
);
1568 void nl_dump(void *msg
, size_t msglen
)
1570 struct nlmsghdr
*nlmsg
= msg
;
1571 struct nlmsgerr
*nlmsgerr
;
1572 struct rtgenmsg
*rtgen
;
1573 struct ifaddrmsg
*ifa
;
1577 struct netconfmsg
*ncm
;
1578 struct ifinfomsg
*ifi
;
1579 struct tunnel_msg
*tnlm
;
1580 struct fib_rule_hdr
*frh
;
1586 "nlmsghdr [len=%u type=(%d) %s flags=(0x%04x) {%s} seq=%u pid=%u]",
1587 nlmsg
->nlmsg_len
, nlmsg
->nlmsg_type
,
1588 nlmsg_type2str(nlmsg
->nlmsg_type
), nlmsg
->nlmsg_flags
,
1589 nlmsg_flags2str(nlmsg
->nlmsg_flags
, fbuf
, sizeof(fbuf
)),
1590 nlmsg
->nlmsg_seq
, nlmsg
->nlmsg_pid
);
1592 switch (nlmsg
->nlmsg_type
) {
1597 nlmsgerr
= NLMSG_DATA(nlmsg
);
1598 zlog_debug(" nlmsgerr [error=(%d) %s]", nlmsgerr
->error
,
1599 strerror(-nlmsgerr
->error
));
1610 ifi
= NLMSG_DATA(nlmsg
);
1612 " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]",
1613 ifi
->ifi_family
, ifi
->ifi_type
,
1614 ifi_type2str(ifi
->ifi_type
), ifi
->ifi_index
,
1616 if_flags2str(ifi
->ifi_flags
, ibuf
, sizeof(ibuf
)));
1617 nllink_dump(ifi
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
)));
1620 rtgen
= NLMSG_DATA(nlmsg
);
1621 zlog_debug(" rtgen [family=(%d) %s]", rtgen
->rtgen_family
,
1622 af_type2str(rtgen
->rtgen_family
));
1628 rtm
= NLMSG_DATA(nlmsg
);
1630 " 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}]",
1631 rtm
->rtm_family
, af_type2str(rtm
->rtm_family
),
1632 rtm
->rtm_dst_len
, rtm
->rtm_src_len
, rtm
->rtm_tos
,
1633 rtm
->rtm_table
, rtm
->rtm_protocol
,
1634 rtm_protocol2str(rtm
->rtm_protocol
), rtm
->rtm_scope
,
1635 rtm_scope2str(rtm
->rtm_scope
), rtm
->rtm_type
,
1636 rtm_type2str(rtm
->rtm_type
), rtm
->rtm_flags
,
1637 rtm_flags2str(rtm
->rtm_flags
, fbuf
, sizeof(fbuf
)));
1639 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*rtm
)));
1644 ndm
= NLMSG_DATA(nlmsg
);
1646 " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]",
1647 ndm
->ndm_family
, af_type2str(ndm
->ndm_family
),
1648 ndm
->ndm_ifindex
, ndm
->ndm_state
,
1649 neigh_state2str(ndm
->ndm_state
, ibuf
, sizeof(ibuf
)),
1651 neigh_flags2str(ndm
->ndm_flags
, fbuf
, sizeof(fbuf
)),
1652 ndm
->ndm_type
, rtm_type2str(ndm
->ndm_type
));
1654 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ndm
)));
1659 frh
= NLMSG_DATA(nlmsg
);
1661 " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]",
1662 frh
->family
, af_type2str(frh
->family
), frh
->dst_len
,
1663 frh
->src_len
, frh
->tos
, frh
->table
, frh
->res1
,
1664 frh
->res2
, frh
->action
, frh_action2str(frh
->action
),
1666 nlrule_dump(frh
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*frh
)));
1672 ifa
= NLMSG_DATA(nlmsg
);
1674 " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]",
1675 ifa
->ifa_family
, af_type2str(ifa
->ifa_family
),
1676 ifa
->ifa_prefixlen
, ifa
->ifa_flags
,
1677 if_flags2str(ifa
->ifa_flags
, fbuf
, sizeof(fbuf
)),
1678 ifa
->ifa_scope
, ifa
->ifa_index
);
1679 nlifa_dump(ifa
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifa
)));
1682 case RTM_NEWNEXTHOP
:
1683 case RTM_DELNEXTHOP
:
1684 case RTM_GETNEXTHOP
:
1685 nhm
= NLMSG_DATA(nlmsg
);
1687 " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]",
1688 nhm
->nh_family
, af_type2str(nhm
->nh_family
),
1689 nhm
->nh_scope
, rtm_scope2str(nhm
->nh_scope
),
1690 nhm
->nh_protocol
, rtm_protocol2str(nhm
->nh_protocol
),
1692 nh_flags2str(nhm
->nh_flags
, fbuf
, sizeof(fbuf
)));
1693 nlnh_dump(nhm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*nhm
)));
1699 tnlm
= NLMSG_DATA(nlmsg
);
1700 zlog_debug(" tnlm [family=(%d) %s ifindex=%d ", tnlm
->family
,
1701 af_type2str(tnlm
->family
), tnlm
->ifindex
);
1704 NLMSG_LENGTH(sizeof(struct tunnel_msg
)));
1708 case RTM_NEWNETCONF
:
1709 case RTM_DELNETCONF
:
1710 ncm
= NLMSG_DATA(nlmsg
);
1711 zlog_debug(" ncm [family=%s (%d)]",
1712 af_type2str(ncm
->ncm_family
), ncm
->ncm_family
);
1713 nlncm_dump(ncm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ncm
)));
1721 * Try to get the next header. There should only be more
1722 * messages if this header was flagged as MULTI, otherwise just
1725 nlmsg
= NLMSG_NEXT(nlmsg
, msglen
);
1726 if (NLMSG_OK(nlmsg
, msglen
) == 0)
1732 #endif /* NETLINK_DEBUG */