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
, rtm_rta2str(rta
->rta_type
));
1087 switch (rta
->rta_type
) {
1093 u32v
= *(uint32_t *)RTA_DATA(rta
);
1094 zlog_debug(" %u", u32v
);
1102 case sizeof(struct in_addr
):
1104 (struct in_addr
*)RTA_DATA(rta
));
1106 case sizeof(struct in6_addr
):
1108 (struct in6_addr
*)RTA_DATA(rta
));
1116 /* NOTHING: unhandled. */
1120 /* Get next pointer and start iteration again. */
1121 rta
= RTA_NEXT(rta
, msglen
);
1125 static void nlneigh_dump(struct ndmsg
*ndm
, size_t msglen
)
1133 unsigned short rta_type
;
1136 #define NDA_RTA(ndm) \
1137 /* struct ndmsg *ndm; */ \
1138 ((struct rtattr *)(((uint8_t *)(ndm)) \
1139 + NLMSG_ALIGN(sizeof(struct ndmsg))))
1140 #endif /* NDA_RTA */
1142 /* Get the first attribute and go from there. */
1145 /* Check the header for valid length and for outbound access. */
1146 if (RTA_OK(rta
, msglen
) == 0)
1149 plen
= RTA_PAYLOAD(rta
);
1150 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
1151 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1152 plen
, rta
->rta_type
, neigh_rta2str(rta_type
));
1155 datap
= RTA_DATA(rta
);
1157 for (it
= 0; it
< plen
; it
++) {
1158 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
1159 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
1162 /* Remove trailing ':'. */
1164 dbuf
[strlen(dbuf
) - 1] = 0;
1166 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
1171 case sizeof(struct in_addr
):
1173 (struct in_addr
*)RTA_DATA(rta
));
1175 case sizeof(struct in6_addr
):
1177 (struct in6_addr
*)RTA_DATA(rta
));
1185 vid
= *(uint16_t *)RTA_DATA(rta
);
1186 zlog_debug(" %d", vid
);
1190 /* NOTHING: unhandled. */
1194 /* Get next pointer and start iteration again. */
1195 rta
= RTA_NEXT(rta
, msglen
);
1199 static void nlifa_dump(struct ifaddrmsg
*ifa
, size_t msglen
)
1205 /* Get the first attribute and go from there. */
1208 /* Check the header for valid length and for outbound access. */
1209 if (RTA_OK(rta
, msglen
) == 0)
1212 plen
= RTA_PAYLOAD(rta
);
1213 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1214 plen
, rta
->rta_type
, ifa_rta2str(rta
->rta_type
));
1215 switch (rta
->rta_type
) {
1217 u32v
= *(uint32_t *)RTA_DATA(rta
);
1218 zlog_debug(" %u", u32v
);
1222 zlog_debug(" %s", (const char *)RTA_DATA(rta
));
1231 (struct in_addr
*)RTA_DATA(rta
));
1235 (struct in6_addr
*)RTA_DATA(rta
));
1243 /* NOTHING: unhandled. */
1247 /* Get next pointer and start iteration again. */
1248 rta
= RTA_NEXT(rta
, msglen
);
1252 static void nltnl_dump(struct tunnel_msg
*tnlm
, size_t msglen
)
1254 struct rtattr
*attr
;
1255 vni_t vni_start
= 0, vni_end
= 0;
1256 struct rtattr
*ttb
[VXLAN_VNIFILTER_ENTRY_MAX
+ 1];
1259 attr
= TUNNEL_RTA(tnlm
);
1261 /* Check the header for valid length and for outbound access. */
1262 if (RTA_OK(attr
, msglen
) == 0)
1265 rta_type
= attr
->rta_type
& NLA_TYPE_MASK
;
1267 if (rta_type
!= VXLAN_VNIFILTER_ENTRY
) {
1268 attr
= RTA_NEXT(attr
, msglen
);
1272 memset(ttb
, 0, sizeof(ttb
));
1274 netlink_parse_rtattr_flags(ttb
, VXLAN_VNIFILTER_ENTRY_MAX
,
1275 RTA_DATA(attr
), RTA_PAYLOAD(attr
),
1278 if (ttb
[VXLAN_VNIFILTER_ENTRY_START
])
1280 *(uint32_t *)RTA_DATA(ttb
[VXLAN_VNIFILTER_ENTRY_START
]);
1282 if (ttb
[VXLAN_VNIFILTER_ENTRY_END
])
1283 vni_end
= *(uint32_t *)RTA_DATA(ttb
[VXLAN_VNIFILTER_ENTRY_END
]);
1284 zlog_debug(" vni_start %u, vni_end %u", vni_start
, vni_end
);
1286 attr
= RTA_NEXT(attr
, msglen
);
1290 static const char *lwt_type2str(uint16_t type
)
1293 case LWTUNNEL_ENCAP_NONE
:
1295 case LWTUNNEL_ENCAP_MPLS
:
1297 case LWTUNNEL_ENCAP_IP
:
1299 case LWTUNNEL_ENCAP_ILA
:
1301 case LWTUNNEL_ENCAP_IP6
:
1303 case LWTUNNEL_ENCAP_SEG6
:
1305 case LWTUNNEL_ENCAP_BPF
:
1307 case LWTUNNEL_ENCAP_SEG6_LOCAL
:
1308 return "SEG6_LOCAL";
1314 static const char *nhg_type2str(uint16_t type
)
1317 case NEXTHOP_GRP_TYPE_MPATH
:
1319 case NEXTHOP_GRP_TYPE_RES
:
1320 return "RESILIENT MULTIPATH";
1326 static void nlnh_dump(struct nhmsg
*nhm
, size_t msglen
)
1333 unsigned long count
, i
;
1334 struct nexthop_grp
*nhgrp
;
1335 unsigned short rta_type
;
1340 /* Check the header for valid length and for outbound access. */
1341 if (RTA_OK(rta
, msglen
) == 0)
1344 plen
= RTA_PAYLOAD(rta
);
1345 rta_type
= rta
->rta_type
& ~NLA_F_NESTED
;
1346 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1347 plen
, rta
->rta_type
, nhm_rta2str(rta_type
));
1350 u32v
= *(uint32_t *)RTA_DATA(rta
);
1351 zlog_debug(" %u", u32v
);
1354 nhgrp
= (struct nexthop_grp
*)RTA_DATA(rta
);
1355 count
= (RTA_PAYLOAD(rta
) / sizeof(*nhgrp
));
1357 || (count
* sizeof(*nhgrp
)) != RTA_PAYLOAD(rta
)) {
1358 zlog_debug(" invalid nexthop group received");
1362 for (i
= 0; i
< count
; i
++)
1363 zlog_debug(" id %d weight %d", nhgrp
[i
].id
,
1366 case NHA_ENCAP_TYPE
:
1367 u16v
= *(uint16_t *)RTA_DATA(rta
);
1368 zlog_debug(" %s", lwt_type2str(u16v
));
1370 case NHA_GROUP_TYPE
:
1371 u16v
= *(uint16_t *)RTA_DATA(rta
);
1372 zlog_debug(" %s", nhg_type2str(u16v
));
1378 ifindex
= *(int *)RTA_DATA(rta
);
1379 zlog_debug(" %d", ifindex
);
1382 switch (nhm
->nh_family
) {
1385 (struct in_addr
*)RTA_DATA(rta
));
1389 (struct in6_addr
*)RTA_DATA(rta
));
1393 zlog_debug(" invalid family %d", nhm
->nh_family
);
1398 /* TODO: handle MPLS labels. */
1399 zlog_debug(" unparsed MPLS labels");
1402 /* TODO: handle this message. */
1403 zlog_debug(" unparsed GROUPS message");
1407 /* NOTHING: unhandled. */
1411 /* Get next pointer and start iteration again. */
1412 rta
= RTA_NEXT(rta
, msglen
);
1416 static void nlrule_dump(struct fib_rule_hdr
*frh
, size_t msglen
)
1425 struct fib_rule_uid_range
*u_range
;
1426 struct fib_rule_port_range
*p_range
;
1428 /* Get the first attribute and go from there. */
1431 /* Check the header for valid length and for outbound access. */
1432 if (RTA_OK(rta
, msglen
) == 0)
1435 plen
= RTA_PAYLOAD(rta
);
1436 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1437 plen
, rta
->rta_type
, frh_rta2str(rta
->rta_type
));
1438 switch (rta
->rta_type
) {
1442 case sizeof(struct in_addr
):
1444 (struct in_addr
*)RTA_DATA(rta
));
1446 case sizeof(struct in6_addr
):
1448 (struct in6_addr
*)RTA_DATA(rta
));
1457 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
1458 zlog_debug(" %s", dbuf
);
1471 u32v
= *(uint32_t *)RTA_DATA(rta
);
1472 zlog_debug(" %u", u32v
);
1475 case FRA_SUPPRESS_IFGROUP
:
1476 case FRA_SUPPRESS_PREFIXLEN
:
1477 s32v
= *(int32_t *)RTA_DATA(rta
);
1478 zlog_debug(" %d", s32v
);
1482 u64v
= *(uint64_t *)RTA_DATA(rta
);
1483 zlog_debug(" %" PRIu64
, u64v
);
1489 u8v
= *(uint8_t *)RTA_DATA(rta
);
1490 zlog_debug(" %u", u8v
);
1494 u_range
= (struct fib_rule_uid_range
*)RTA_DATA(rta
);
1495 if (u_range
->start
== u_range
->end
)
1496 zlog_debug(" %u", u_range
->start
);
1498 zlog_debug(" %u-%u", u_range
->start
, u_range
->end
);
1501 case FRA_SPORT_RANGE
:
1502 case FRA_DPORT_RANGE
:
1503 p_range
= (struct fib_rule_port_range
*)RTA_DATA(rta
);
1504 if (p_range
->start
== p_range
->end
)
1505 zlog_debug(" %u", p_range
->start
);
1507 zlog_debug(" %u-%u", p_range
->start
, p_range
->end
);
1510 case FRA_PAD
: /* fallthrough */
1512 /* NOTHING: unhandled. */
1516 /* Get next pointer and start iteration again. */
1517 rta
= RTA_NEXT(rta
, msglen
);
1521 static void nlncm_dump(const struct netconfmsg
*ncm
, size_t msglen
)
1523 const struct rtattr
*rta
;
1527 rta
= (void *)((const char *)ncm
+
1528 NLMSG_ALIGN(sizeof(struct netconfmsg
)));
1531 /* Check the attr header for valid length. */
1532 if (RTA_OK(rta
, msglen
) == 0)
1535 plen
= RTA_PAYLOAD(rta
);
1537 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1538 plen
, rta
->rta_type
, ncm_rta2str(rta
->rta_type
));
1540 switch (rta
->rta_type
) {
1541 case NETCONFA_IFINDEX
:
1542 ival
= *(uint32_t *)RTA_DATA(rta
);
1543 zlog_debug(" %d", (int32_t)ival
);
1546 /* Most attrs are just on/off. */
1547 case NETCONFA_FORWARDING
:
1548 case NETCONFA_RP_FILTER
:
1549 case NETCONFA_MC_FORWARDING
:
1550 case NETCONFA_PROXY_NEIGH
:
1551 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
1552 case NETCONFA_INPUT
:
1553 case NETCONFA_BC_FORWARDING
:
1554 ival
= *(uint32_t *)RTA_DATA(rta
);
1555 dump_on_off(ival
, " ");
1558 /* NOTHING: unhandled. */
1562 /* Get next pointer and start iteration again. */
1563 rta
= RTA_NEXT(rta
, msglen
);
1567 void nl_dump(void *msg
, size_t msglen
)
1569 struct nlmsghdr
*nlmsg
= msg
;
1570 struct nlmsgerr
*nlmsgerr
;
1571 struct rtgenmsg
*rtgen
;
1572 struct ifaddrmsg
*ifa
;
1576 struct netconfmsg
*ncm
;
1577 struct ifinfomsg
*ifi
;
1578 struct tunnel_msg
*tnlm
;
1579 struct fib_rule_hdr
*frh
;
1585 "nlmsghdr [len=%u type=(%d) %s flags=(0x%04x) {%s} seq=%u pid=%u]",
1586 nlmsg
->nlmsg_len
, nlmsg
->nlmsg_type
,
1587 nlmsg_type2str(nlmsg
->nlmsg_type
), nlmsg
->nlmsg_flags
,
1588 nlmsg_flags2str(nlmsg
->nlmsg_flags
, fbuf
, sizeof(fbuf
)),
1589 nlmsg
->nlmsg_seq
, nlmsg
->nlmsg_pid
);
1591 switch (nlmsg
->nlmsg_type
) {
1596 nlmsgerr
= NLMSG_DATA(nlmsg
);
1597 zlog_debug(" nlmsgerr [error=(%d) %s]", nlmsgerr
->error
,
1598 strerror(-nlmsgerr
->error
));
1609 ifi
= NLMSG_DATA(nlmsg
);
1611 " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]",
1612 ifi
->ifi_family
, ifi
->ifi_type
,
1613 ifi_type2str(ifi
->ifi_type
), ifi
->ifi_index
,
1615 if_flags2str(ifi
->ifi_flags
, ibuf
, sizeof(ibuf
)));
1616 nllink_dump(ifi
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
)));
1619 rtgen
= NLMSG_DATA(nlmsg
);
1620 zlog_debug(" rtgen [family=(%d) %s]", rtgen
->rtgen_family
,
1621 af_type2str(rtgen
->rtgen_family
));
1627 rtm
= NLMSG_DATA(nlmsg
);
1629 " 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}]",
1630 rtm
->rtm_family
, af_type2str(rtm
->rtm_family
),
1631 rtm
->rtm_dst_len
, rtm
->rtm_src_len
, rtm
->rtm_tos
,
1632 rtm
->rtm_table
, rtm
->rtm_protocol
,
1633 rtm_protocol2str(rtm
->rtm_protocol
), rtm
->rtm_scope
,
1634 rtm_scope2str(rtm
->rtm_scope
), rtm
->rtm_type
,
1635 rtm_type2str(rtm
->rtm_type
), rtm
->rtm_flags
,
1636 rtm_flags2str(rtm
->rtm_flags
, fbuf
, sizeof(fbuf
)));
1638 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*rtm
)));
1643 ndm
= NLMSG_DATA(nlmsg
);
1645 " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]",
1646 ndm
->ndm_family
, af_type2str(ndm
->ndm_family
),
1647 ndm
->ndm_ifindex
, ndm
->ndm_state
,
1648 neigh_state2str(ndm
->ndm_state
, ibuf
, sizeof(ibuf
)),
1650 neigh_flags2str(ndm
->ndm_flags
, fbuf
, sizeof(fbuf
)),
1651 ndm
->ndm_type
, rtm_type2str(ndm
->ndm_type
));
1653 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ndm
)));
1658 frh
= NLMSG_DATA(nlmsg
);
1660 " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]",
1661 frh
->family
, af_type2str(frh
->family
), frh
->dst_len
,
1662 frh
->src_len
, frh
->tos
, frh
->table
, frh
->res1
,
1663 frh
->res2
, frh
->action
, frh_action2str(frh
->action
),
1665 nlrule_dump(frh
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*frh
)));
1671 ifa
= NLMSG_DATA(nlmsg
);
1673 " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]",
1674 ifa
->ifa_family
, af_type2str(ifa
->ifa_family
),
1675 ifa
->ifa_prefixlen
, ifa
->ifa_flags
,
1676 if_flags2str(ifa
->ifa_flags
, fbuf
, sizeof(fbuf
)),
1677 ifa
->ifa_scope
, ifa
->ifa_index
);
1678 nlifa_dump(ifa
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifa
)));
1681 case RTM_NEWNEXTHOP
:
1682 case RTM_DELNEXTHOP
:
1683 case RTM_GETNEXTHOP
:
1684 nhm
= NLMSG_DATA(nlmsg
);
1686 " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]",
1687 nhm
->nh_family
, af_type2str(nhm
->nh_family
),
1688 nhm
->nh_scope
, rtm_scope2str(nhm
->nh_scope
),
1689 nhm
->nh_protocol
, rtm_protocol2str(nhm
->nh_protocol
),
1691 nh_flags2str(nhm
->nh_flags
, fbuf
, sizeof(fbuf
)));
1692 nlnh_dump(nhm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*nhm
)));
1698 tnlm
= NLMSG_DATA(nlmsg
);
1699 zlog_debug(" tnlm [family=(%d) %s ifindex=%d ", tnlm
->family
,
1700 af_type2str(tnlm
->family
), tnlm
->ifindex
);
1703 NLMSG_LENGTH(sizeof(struct tunnel_msg
)));
1707 case RTM_NEWNETCONF
:
1708 case RTM_DELNETCONF
:
1709 ncm
= NLMSG_DATA(nlmsg
);
1710 zlog_debug(" ncm [family=%s (%d)]",
1711 af_type2str(ncm
->ncm_family
), ncm
->ncm_family
);
1712 nlncm_dump(ncm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ncm
)));
1720 * Try to get the next header. There should only be more
1721 * messages if this header was flagged as MULTI, otherwise just
1724 nlmsg
= NLMSG_NEXT(nlmsg
, msglen
);
1725 if (NLMSG_OK(nlmsg
, msglen
) == 0)
1731 #endif /* NETLINK_DEBUG */