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>
33 #include "zebra/rt_netlink.h"
34 #include "zebra/kernel_netlink.h"
36 const char *nlmsg_type2str(uint16_t type
)
95 return "RTM_NEWNETCONF";
97 return "RTM_DELNETCONF";
104 const char *af_type2str(int type
)
124 return "AF_BLUETOOTH";
136 const char *ifi_type2str(int type
)
155 case ARPHRD_APPLETLK
:
161 case ARPHRD_METRICOM
:
163 case ARPHRD_IEEE1394
:
167 case ARPHRD_INFINIBAND
:
203 case ARPHRD_LOOPBACK
:
205 case ARPHRD_LOCALTLK
:
233 case ARPHRD_FCFABRIC
:
235 case ARPHRD_IEEE802_TR
:
237 case ARPHRD_IEEE80211
:
239 case ARPHRD_IEEE80211_PRISM
:
240 return "IEEE80211_PRISM";
241 case ARPHRD_IEEE80211_RADIOTAP
:
242 return "IEEE80211_RADIOTAP";
243 case ARPHRD_IEEE802154
:
245 #ifdef ARPHRD_VSOCKMON
246 case ARPHRD_VSOCKMON
:
248 #endif /* ARPHRD_VSOCKMON */
258 const char *rta_type2str(int type
)
299 case IFLA_NET_NS_PID
:
305 case IFLA_VFINFO_LIST
:
306 return "VFINFO_LIST";
321 case IFLA_PROMISCUITY
:
322 return "PROMISCUITY";
323 case IFLA_NUM_TX_QUEUES
:
324 return "NUM_TX_QUEUES";
325 case IFLA_NUM_RX_QUEUES
:
326 return "NUM_RX_QUEUES";
329 case IFLA_PHYS_PORT_ID
:
330 return "PHYS_PORT_ID";
331 case IFLA_CARRIER_CHANGES
:
332 return "CARRIER_CHANGES";
333 case IFLA_PHYS_SWITCH_ID
:
334 return "PHYS_SWITCH_ID";
335 case IFLA_LINK_NETNSID
:
336 return "LINK_NETNSID";
337 case IFLA_PHYS_PORT_NAME
:
338 return "PHYS_PORT_NAME";
339 case IFLA_PROTO_DOWN
:
341 #ifdef IFLA_GSO_MAX_SEGS
342 case IFLA_GSO_MAX_SEGS
:
343 return "GSO_MAX_SEGS";
344 #endif /* IFLA_GSO_MAX_SEGS */
345 #ifdef IFLA_GSO_MAX_SIZE
346 case IFLA_GSO_MAX_SIZE
:
347 return "GSO_MAX_SIZE";
348 #endif /* IFLA_GSO_MAX_SIZE */
352 #endif /* IFLA_PAD */
356 #endif /* IFLA_XDP */
360 #endif /* IFLA_EVENT */
366 const char *rtm_type2str(int type
)
383 case RTN_UNREACHABLE
:
384 return "UNREACHABLE";
398 const char *rtm_protocol2str(int type
)
403 case RTPROT_REDIRECT
:
421 case RTPROT_DNROUTED
:
438 const char *rtm_scope2str(int type
)
441 case RT_SCOPE_UNIVERSE
:
449 case RT_SCOPE_NOWHERE
:
456 const char *rtm_rta2str(int type
)
500 const char *neigh_rta2str(int type
)
523 case NDA_LINK_NETNSID
:
524 return "LINK_NETNSID";
530 const char *ifa_rta2str(int type
)
556 const char *nhm_rta2str(int type
)
586 const char *frh_rta2str(int type
)
613 case FRA_SUPPRESS_IFGROUP
:
614 return "SUPPRESS_IFGROUP";
615 case FRA_SUPPRESS_PREFIXLEN
:
616 return "SUPPRESS_PREFIXLEN";
633 case FRA_SPORT_RANGE
:
634 return "SPORT_RANGE";
635 case FRA_DPORT_RANGE
:
636 return "DPORT_RANGE";
642 const char *frh_action2str(uint8_t action
)
655 case FR_ACT_BLACKHOLE
:
657 case FR_ACT_UNREACHABLE
:
658 return "UNREACHABLE";
659 case FR_ACT_PROHIBIT
:
666 static const char *ncm_rta2str(int type
)
669 case NETCONFA_UNSPEC
:
671 case NETCONFA_IFINDEX
:
673 case NETCONFA_FORWARDING
:
675 case NETCONFA_RP_FILTER
:
677 case NETCONFA_MC_FORWARDING
:
679 case NETCONFA_PROXY_NEIGH
:
680 return "PROXY_NEIGH";
681 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
682 return "IGNORE_LINKDOWN";
685 case NETCONFA_BC_FORWARDING
:
692 static void dump_on_off(uint32_t ival
, const char *prefix
)
694 zlog_debug("%s%s", prefix
, (ival
!= 0) ? "on" : "off");
697 static inline void flag_write(int flags
, int flag
, const char *flagstr
,
698 char *buf
, size_t buflen
)
700 if (CHECK_FLAG(flags
, flag
) == 0)
704 strlcat(buf
, ",", buflen
);
706 strlcat(buf
, flagstr
, buflen
);
709 const char *nlmsg_flags2str(uint16_t flags
, char *buf
, size_t buflen
)
711 const char *bufp
= buf
;
714 /* Specific flags. */
715 flag_write(flags
, NLM_F_REQUEST
, "REQUEST", buf
, buflen
);
716 flag_write(flags
, NLM_F_MULTI
, "MULTI", buf
, buflen
);
717 flag_write(flags
, NLM_F_ACK
, "ACK", buf
, buflen
);
718 flag_write(flags
, NLM_F_ECHO
, "ECHO", buf
, buflen
);
719 flag_write(flags
, NLM_F_DUMP
, "DUMP", buf
, buflen
);
721 /* Netlink family type dependent. */
722 flag_write(flags
, 0x0100, "(ROOT|REPLACE|CAPPED)", buf
, buflen
);
723 flag_write(flags
, 0x0200, "(MATCH|EXCLUDE|ACK_TLVS)", buf
, buflen
);
724 flag_write(flags
, 0x0400, "(ATOMIC|CREATE)", buf
, buflen
);
725 flag_write(flags
, 0x0800, "(DUMP|APPEND)", buf
, buflen
);
730 const char *if_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
732 const char *bufp
= buf
;
735 flag_write(flags
, IFF_UP
, "UP", buf
, buflen
);
736 flag_write(flags
, IFF_BROADCAST
, "BROADCAST", buf
, buflen
);
737 flag_write(flags
, IFF_DEBUG
, "DEBUG", buf
, buflen
);
738 flag_write(flags
, IFF_LOOPBACK
, "LOOPBACK", buf
, buflen
);
739 flag_write(flags
, IFF_POINTOPOINT
, "POINTOPOINT", buf
, buflen
);
740 flag_write(flags
, IFF_NOTRAILERS
, "NOTRAILERS", buf
, buflen
);
741 flag_write(flags
, IFF_RUNNING
, "RUNNING", buf
, buflen
);
742 flag_write(flags
, IFF_NOARP
, "NOARP", buf
, buflen
);
743 flag_write(flags
, IFF_PROMISC
, "PROMISC", buf
, buflen
);
744 flag_write(flags
, IFF_ALLMULTI
, "ALLMULTI", buf
, buflen
);
745 flag_write(flags
, IFF_MASTER
, "MASTER", buf
, buflen
);
746 flag_write(flags
, IFF_SLAVE
, "SLAVE", buf
, buflen
);
747 flag_write(flags
, IFF_MULTICAST
, "MULTICAST", buf
, buflen
);
748 flag_write(flags
, IFF_PORTSEL
, "PORTSEL", buf
, buflen
);
749 flag_write(flags
, IFF_AUTOMEDIA
, "AUTOMEDIA", buf
, buflen
);
750 flag_write(flags
, IFF_DYNAMIC
, "DYNAMIC", buf
, buflen
);
755 const char *rtm_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
757 const char *bufp
= buf
;
760 flag_write(flags
, RTM_F_NOTIFY
, "NOTIFY", buf
, buflen
);
761 flag_write(flags
, RTM_F_CLONED
, "CLONED", buf
, buflen
);
762 flag_write(flags
, RTM_F_EQUALIZE
, "EQUALIZE", buf
, buflen
);
767 const char *neigh_state2str(uint32_t flags
, char *buf
, size_t buflen
)
769 const char *bufp
= buf
;
772 flag_write(flags
, NUD_INCOMPLETE
, "INCOMPLETE", buf
, buflen
);
773 flag_write(flags
, NUD_REACHABLE
, "REACHABLE", buf
, buflen
);
774 flag_write(flags
, NUD_STALE
, "STALE", buf
, buflen
);
775 flag_write(flags
, NUD_DELAY
, "DELAY", buf
, buflen
);
776 flag_write(flags
, NUD_PROBE
, "PROBE", buf
, buflen
);
777 flag_write(flags
, NUD_FAILED
, "FAILED", buf
, buflen
);
778 flag_write(flags
, NUD_NOARP
, "NOARP", buf
, buflen
);
779 flag_write(flags
, NUD_PERMANENT
, "PERMANENT", buf
, buflen
);
784 const char *neigh_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
786 const char *bufp
= buf
;
789 flag_write(flags
, NTF_USE
, "USE", buf
, buflen
);
790 flag_write(flags
, NTF_SELF
, "SELF", buf
, buflen
);
791 flag_write(flags
, NTF_MASTER
, "MASTER", buf
, buflen
);
792 flag_write(flags
, NTF_PROXY
, "PROXY", buf
, buflen
);
793 flag_write(flags
, NTF_EXT_LEARNED
, "EXT_LEARNED", buf
, buflen
);
795 flag_write(flags
, NTF_OFFLOADED
, "OFFLOADED", buf
, buflen
);
796 #endif /* NTF_OFFLOADED */
797 flag_write(flags
, NTF_ROUTER
, "ROUTER", buf
, buflen
);
802 const char *ifa_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
804 const char *bufp
= buf
;
807 flag_write(flags
, IFA_F_SECONDARY
, "SECONDARY", buf
, buflen
);
808 flag_write(flags
, IFA_F_NODAD
, "NODAD", buf
, buflen
);
809 flag_write(flags
, IFA_F_OPTIMISTIC
, "OPTIMISTIC", buf
, buflen
);
810 flag_write(flags
, IFA_F_DADFAILED
, "DADFAILED", buf
, buflen
);
811 flag_write(flags
, IFA_F_HOMEADDRESS
, "HOMEADDRESS", buf
, buflen
);
812 flag_write(flags
, IFA_F_DEPRECATED
, "DEPRECATED", buf
, buflen
);
813 flag_write(flags
, IFA_F_TENTATIVE
, "TENTATIVE", buf
, buflen
);
814 flag_write(flags
, IFA_F_PERMANENT
, "PERMANENT", buf
, buflen
);
815 flag_write(flags
, IFA_F_MANAGETEMPADDR
, "MANAGETEMPADDR", buf
, buflen
);
816 flag_write(flags
, IFA_F_NOPREFIXROUTE
, "NOPREFIXROUTE", buf
, buflen
);
817 flag_write(flags
, IFA_F_MCAUTOJOIN
, "MCAUTOJOIN", buf
, buflen
);
818 flag_write(flags
, IFA_F_STABLE_PRIVACY
, "STABLE_PRIVACY", buf
, buflen
);
823 const char *nh_flags2str(uint32_t flags
, char *buf
, size_t buflen
)
825 const char *bufp
= buf
;
828 flag_write(flags
, RTNH_F_DEAD
, "DEAD", buf
, buflen
);
829 flag_write(flags
, RTNH_F_PERVASIVE
, "PERVASIVE", buf
, buflen
);
830 flag_write(flags
, RTNH_F_ONLINK
, "ONLINK", buf
, buflen
);
831 flag_write(flags
, RTNH_F_OFFLOAD
, "OFFLOAD", buf
, buflen
);
832 flag_write(flags
, RTNH_F_LINKDOWN
, "LINKDOWN", buf
, buflen
);
833 flag_write(flags
, RTNH_F_UNRESOLVED
, "UNRESOLVED", buf
, buflen
);
839 * Netlink abstractions.
841 static void nllink_linkinfo_dump(struct rtattr
*rta
, size_t msglen
)
847 /* Check the header for valid length and for outbound access. */
848 if (RTA_OK(rta
, msglen
) == 0)
851 plen
= RTA_PAYLOAD(rta
);
852 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
853 rta
->rta_len
, plen
, rta
->rta_type
,
854 rta_type2str(rta
->rta_type
));
855 switch (rta
->rta_type
) {
858 zlog_debug(" invalid length");
862 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
863 zlog_debug(" %s", dbuf
);
865 case IFLA_INFO_SLAVE_KIND
:
867 zlog_debug(" invalid length");
871 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
872 zlog_debug(" %s", dbuf
);
876 /* NOTHING: unhandled. */
880 /* Get next pointer and start iteration again. */
881 rta
= RTA_NEXT(rta
, msglen
);
885 static void nllink_dump(struct ifinfomsg
*ifi
, size_t msglen
)
894 /* Get the first attribute and go from there. */
897 /* Check the header for valid length and for outbound access. */
898 if (RTA_OK(rta
, msglen
) == 0)
901 plen
= RTA_PAYLOAD(rta
);
902 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
903 plen
, rta
->rta_type
, rta_type2str(rta
->rta_type
));
904 switch (rta
->rta_type
) {
908 zlog_debug(" invalid length");
912 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
913 zlog_debug(" %s", dbuf
);
918 case IFLA_NUM_TX_QUEUES
:
919 case IFLA_NUM_RX_QUEUES
:
921 case IFLA_PROMISCUITY
:
922 #ifdef IFLA_GSO_MAX_SEGS
923 case IFLA_GSO_MAX_SEGS
:
924 #endif /* IFLA_GSO_MAX_SEGS */
925 #ifdef IFLA_GSO_MAX_SIZE
926 case IFLA_GSO_MAX_SIZE
:
927 #endif /* IFLA_GSO_MAX_SIZE */
928 case IFLA_CARRIER_CHANGES
:
930 if (plen
< sizeof(uint32_t)) {
931 zlog_debug(" invalid length");
935 u32v
= *(uint32_t *)RTA_DATA(rta
);
936 zlog_debug(" %u", u32v
);
940 datap
= RTA_DATA(rta
);
942 for (it
= 0; it
< plen
; it
++) {
943 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
944 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
947 /* Remove trailing ':'. */
949 dbuf
[strlen(dbuf
) - 1] = 0;
951 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
955 nllink_linkinfo_dump(RTA_DATA(rta
), msglen
);
959 /* NOTHING: unhandled. */
963 /* Get next pointer and start iteration again. */
964 rta
= RTA_NEXT(rta
, msglen
);
968 static void nlroute_dump(struct rtmsg
*rtm
, size_t msglen
)
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 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
983 plen
, rta
->rta_type
, rtm_rta2str(rta
->rta_type
));
984 switch (rta
->rta_type
) {
990 u32v
= *(uint32_t *)RTA_DATA(rta
);
991 zlog_debug(" %u", u32v
);
999 case sizeof(struct in_addr
):
1001 (struct in_addr
*)RTA_DATA(rta
));
1003 case sizeof(struct in6_addr
):
1005 (struct in6_addr
*)RTA_DATA(rta
));
1013 /* NOTHING: unhandled. */
1017 /* Get next pointer and start iteration again. */
1018 rta
= RTA_NEXT(rta
, msglen
);
1022 static void nlneigh_dump(struct ndmsg
*ndm
, size_t msglen
)
1032 #define NDA_RTA(ndm) \
1033 /* struct ndmsg *ndm; */ \
1034 ((struct rtattr *)(((uint8_t *)(ndm)) \
1035 + NLMSG_ALIGN(sizeof(struct ndmsg))))
1036 #endif /* NDA_RTA */
1038 /* Get the first attribute and go from there. */
1041 /* Check the header for valid length and for outbound access. */
1042 if (RTA_OK(rta
, msglen
) == 0)
1045 plen
= RTA_PAYLOAD(rta
);
1046 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1047 plen
, rta
->rta_type
, neigh_rta2str(rta
->rta_type
));
1048 switch (rta
->rta_type
& ~ NLA_F_NESTED
) {
1050 datap
= RTA_DATA(rta
);
1052 for (it
= 0; it
< plen
; it
++) {
1053 snprintf(bytestr
, sizeof(bytestr
), "%02X:", *datap
);
1054 strlcat(dbuf
, bytestr
, sizeof(dbuf
));
1057 /* Remove trailing ':'. */
1059 dbuf
[strlen(dbuf
) - 1] = 0;
1061 zlog_debug(" %s", dbuf
[0] ? dbuf
: "<empty>");
1066 case sizeof(struct in_addr
):
1068 (struct in_addr
*)RTA_DATA(rta
));
1070 case sizeof(struct in6_addr
):
1072 (struct in6_addr
*)RTA_DATA(rta
));
1080 vid
= *(uint16_t *)RTA_DATA(rta
);
1081 zlog_debug(" %d", vid
);
1085 /* NOTHING: unhandled. */
1089 /* Get next pointer and start iteration again. */
1090 rta
= RTA_NEXT(rta
, msglen
);
1094 static void nlifa_dump(struct ifaddrmsg
*ifa
, size_t msglen
)
1100 /* Get the first attribute and go from there. */
1103 /* Check the header for valid length and for outbound access. */
1104 if (RTA_OK(rta
, msglen
) == 0)
1107 plen
= RTA_PAYLOAD(rta
);
1108 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1109 plen
, rta
->rta_type
, ifa_rta2str(rta
->rta_type
));
1110 switch (rta
->rta_type
) {
1112 u32v
= *(uint32_t *)RTA_DATA(rta
);
1113 zlog_debug(" %u", u32v
);
1117 zlog_debug(" %s", (const char *)RTA_DATA(rta
));
1126 (struct in_addr
*)RTA_DATA(rta
));
1130 (struct in6_addr
*)RTA_DATA(rta
));
1138 /* NOTHING: unhandled. */
1142 /* Get next pointer and start iteration again. */
1143 rta
= RTA_NEXT(rta
, msglen
);
1147 static void nlnh_dump(struct nhmsg
*nhm
, size_t msglen
)
1154 unsigned long count
, i
;
1155 struct nexthop_grp
*nhgrp
;
1160 /* Check the header for valid length and for outbound access. */
1161 if (RTA_OK(rta
, msglen
) == 0)
1164 plen
= RTA_PAYLOAD(rta
);
1165 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1166 plen
, rta
->rta_type
, nhm_rta2str(rta
->rta_type
));
1167 switch (rta
->rta_type
& ~NLA_F_NESTED
) {
1169 u32v
= *(uint32_t *)RTA_DATA(rta
);
1170 zlog_debug(" %u", u32v
);
1173 nhgrp
= (struct nexthop_grp
*)RTA_DATA(rta
);
1174 count
= (RTA_PAYLOAD(rta
) / sizeof(*nhgrp
));
1176 || (count
* sizeof(*nhgrp
)) != RTA_PAYLOAD(rta
)) {
1177 zlog_debug(" invalid nexthop group received");
1181 for (i
= 0; i
< count
; i
++)
1182 zlog_debug(" id %d weight %d", nhgrp
[i
].id
,
1185 case NHA_ENCAP_TYPE
:
1186 case NHA_GROUP_TYPE
:
1187 u16v
= *(uint16_t *)RTA_DATA(rta
);
1188 zlog_debug(" %d", u16v
);
1194 ifindex
= *(int *)RTA_DATA(rta
);
1195 zlog_debug(" %d", ifindex
);
1198 switch (nhm
->nh_family
) {
1201 (struct in_addr
*)RTA_DATA(rta
));
1205 (struct in6_addr
*)RTA_DATA(rta
));
1209 zlog_debug(" invalid family %d", nhm
->nh_family
);
1214 /* TODO: handle MPLS labels. */
1215 zlog_debug(" unparsed MPLS labels");
1218 /* TODO: handle this message. */
1219 zlog_debug(" unparsed GROUPS message");
1223 /* NOTHING: unhandled. */
1227 /* Get next pointer and start iteration again. */
1228 rta
= RTA_NEXT(rta
, msglen
);
1232 static void nlrule_dump(struct fib_rule_hdr
*frh
, size_t msglen
)
1241 struct fib_rule_uid_range
*u_range
;
1242 struct fib_rule_port_range
*p_range
;
1244 /* Get the first attribute and go from there. */
1247 /* Check the header for valid length and for outbound access. */
1248 if (RTA_OK(rta
, msglen
) == 0)
1251 plen
= RTA_PAYLOAD(rta
);
1252 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1253 plen
, rta
->rta_type
, frh_rta2str(rta
->rta_type
));
1254 switch (rta
->rta_type
) {
1258 case sizeof(struct in_addr
):
1260 (struct in_addr
*)RTA_DATA(rta
));
1262 case sizeof(struct in6_addr
):
1264 (struct in6_addr
*)RTA_DATA(rta
));
1273 snprintf(dbuf
, sizeof(dbuf
), "%s", (char *)RTA_DATA(rta
));
1274 zlog_debug(" %s", dbuf
);
1287 u32v
= *(uint32_t *)RTA_DATA(rta
);
1288 zlog_debug(" %u", u32v
);
1291 case FRA_SUPPRESS_IFGROUP
:
1292 case FRA_SUPPRESS_PREFIXLEN
:
1293 s32v
= *(int32_t *)RTA_DATA(rta
);
1294 zlog_debug(" %d", s32v
);
1298 u64v
= *(uint64_t *)RTA_DATA(rta
);
1299 zlog_debug(" %" PRIu64
, u64v
);
1305 u8v
= *(uint8_t *)RTA_DATA(rta
);
1306 zlog_debug(" %u", u8v
);
1310 u_range
= (struct fib_rule_uid_range
*)RTA_DATA(rta
);
1311 if (u_range
->start
== u_range
->end
)
1312 zlog_debug(" %u", u_range
->start
);
1314 zlog_debug(" %u-%u", u_range
->start
, u_range
->end
);
1317 case FRA_SPORT_RANGE
:
1318 case FRA_DPORT_RANGE
:
1319 p_range
= (struct fib_rule_port_range
*)RTA_DATA(rta
);
1320 if (p_range
->start
== p_range
->end
)
1321 zlog_debug(" %u", p_range
->start
);
1323 zlog_debug(" %u-%u", p_range
->start
, p_range
->end
);
1326 case FRA_PAD
: /* fallthrough */
1328 /* NOTHING: unhandled. */
1332 /* Get next pointer and start iteration again. */
1333 rta
= RTA_NEXT(rta
, msglen
);
1337 static void nlncm_dump(const struct netconfmsg
*ncm
, size_t msglen
)
1339 const struct rtattr
*rta
;
1343 rta
= (void *)((const char *)ncm
+
1344 NLMSG_ALIGN(sizeof(struct netconfmsg
)));
1347 /* Check the attr header for valid length. */
1348 if (RTA_OK(rta
, msglen
) == 0)
1351 plen
= RTA_PAYLOAD(rta
);
1353 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta
->rta_len
,
1354 plen
, rta
->rta_type
, ncm_rta2str(rta
->rta_type
));
1356 switch (rta
->rta_type
) {
1357 case NETCONFA_IFINDEX
:
1358 ival
= *(uint32_t *)RTA_DATA(rta
);
1359 zlog_debug(" %d", (int32_t)ival
);
1362 /* Most attrs are just on/off. */
1363 case NETCONFA_FORWARDING
:
1364 case NETCONFA_RP_FILTER
:
1365 case NETCONFA_MC_FORWARDING
:
1366 case NETCONFA_PROXY_NEIGH
:
1367 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
:
1368 case NETCONFA_INPUT
:
1369 case NETCONFA_BC_FORWARDING
:
1370 ival
= *(uint32_t *)RTA_DATA(rta
);
1371 dump_on_off(ival
, " ");
1374 /* NOTHING: unhandled. */
1378 /* Get next pointer and start iteration again. */
1379 rta
= RTA_NEXT(rta
, msglen
);
1383 void nl_dump(void *msg
, size_t msglen
)
1385 struct nlmsghdr
*nlmsg
= msg
;
1386 struct nlmsgerr
*nlmsgerr
;
1387 struct rtgenmsg
*rtgen
;
1388 struct ifaddrmsg
*ifa
;
1392 struct netconfmsg
*ncm
;
1393 struct ifinfomsg
*ifi
;
1394 struct fib_rule_hdr
*frh
;
1400 "nlmsghdr [len=%u type=(%d) %s flags=(0x%04x) {%s} seq=%u pid=%u]",
1401 nlmsg
->nlmsg_len
, nlmsg
->nlmsg_type
,
1402 nlmsg_type2str(nlmsg
->nlmsg_type
), nlmsg
->nlmsg_flags
,
1403 nlmsg_flags2str(nlmsg
->nlmsg_flags
, fbuf
, sizeof(fbuf
)),
1404 nlmsg
->nlmsg_seq
, nlmsg
->nlmsg_pid
);
1406 switch (nlmsg
->nlmsg_type
) {
1411 nlmsgerr
= NLMSG_DATA(nlmsg
);
1412 zlog_debug(" nlmsgerr [error=(%d) %s]", nlmsgerr
->error
,
1413 strerror(-nlmsgerr
->error
));
1424 ifi
= NLMSG_DATA(nlmsg
);
1426 " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]",
1427 ifi
->ifi_family
, ifi
->ifi_type
,
1428 ifi_type2str(ifi
->ifi_type
), ifi
->ifi_index
,
1430 if_flags2str(ifi
->ifi_flags
, ibuf
, sizeof(ibuf
)));
1431 nllink_dump(ifi
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifi
)));
1434 rtgen
= NLMSG_DATA(nlmsg
);
1435 zlog_debug(" rtgen [family=(%d) %s]", rtgen
->rtgen_family
,
1436 af_type2str(rtgen
->rtgen_family
));
1442 rtm
= NLMSG_DATA(nlmsg
);
1444 " 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}]",
1445 rtm
->rtm_family
, af_type2str(rtm
->rtm_family
),
1446 rtm
->rtm_dst_len
, rtm
->rtm_src_len
, rtm
->rtm_tos
,
1447 rtm
->rtm_table
, rtm
->rtm_protocol
,
1448 rtm_protocol2str(rtm
->rtm_protocol
), rtm
->rtm_scope
,
1449 rtm_scope2str(rtm
->rtm_scope
), rtm
->rtm_type
,
1450 rtm_type2str(rtm
->rtm_type
), rtm
->rtm_flags
,
1451 rtm_flags2str(rtm
->rtm_flags
, fbuf
, sizeof(fbuf
)));
1453 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*rtm
)));
1458 ndm
= NLMSG_DATA(nlmsg
);
1460 " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]",
1461 ndm
->ndm_family
, af_type2str(ndm
->ndm_family
),
1462 ndm
->ndm_ifindex
, ndm
->ndm_state
,
1463 neigh_state2str(ndm
->ndm_state
, ibuf
, sizeof(ibuf
)),
1465 neigh_flags2str(ndm
->ndm_flags
, fbuf
, sizeof(fbuf
)),
1466 ndm
->ndm_type
, rtm_type2str(ndm
->ndm_type
));
1468 nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ndm
)));
1473 frh
= NLMSG_DATA(nlmsg
);
1475 " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]",
1476 frh
->family
, af_type2str(frh
->family
), frh
->dst_len
,
1477 frh
->src_len
, frh
->tos
, frh
->table
, frh
->res1
,
1478 frh
->res2
, frh
->action
, frh_action2str(frh
->action
),
1480 nlrule_dump(frh
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*frh
)));
1486 ifa
= NLMSG_DATA(nlmsg
);
1488 " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]",
1489 ifa
->ifa_family
, af_type2str(ifa
->ifa_family
),
1490 ifa
->ifa_prefixlen
, ifa
->ifa_flags
,
1491 if_flags2str(ifa
->ifa_flags
, fbuf
, sizeof(fbuf
)),
1492 ifa
->ifa_scope
, ifa
->ifa_index
);
1493 nlifa_dump(ifa
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifa
)));
1496 case RTM_NEWNEXTHOP
:
1497 case RTM_DELNEXTHOP
:
1498 case RTM_GETNEXTHOP
:
1499 nhm
= NLMSG_DATA(nlmsg
);
1501 " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]",
1502 nhm
->nh_family
, af_type2str(nhm
->nh_family
),
1503 nhm
->nh_scope
, rtm_scope2str(nhm
->nh_scope
),
1504 nhm
->nh_protocol
, rtm_protocol2str(nhm
->nh_protocol
),
1506 nh_flags2str(nhm
->nh_flags
, fbuf
, sizeof(fbuf
)));
1507 nlnh_dump(nhm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*nhm
)));
1510 case RTM_NEWNETCONF
:
1511 case RTM_DELNETCONF
:
1512 ncm
= NLMSG_DATA(nlmsg
);
1513 zlog_debug(" ncm [family=%s (%d)]",
1514 af_type2str(ncm
->ncm_family
), ncm
->ncm_family
);
1515 nlncm_dump(ncm
, nlmsg
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ncm
)));
1523 * Try to get the next header. There should only be more
1524 * messages if this header was flagged as MULTI, otherwise just
1527 nlmsg
= NLMSG_NEXT(nlmsg
, msglen
);
1528 if (NLMSG_OK(nlmsg
, msglen
) == 0)
1534 #endif /* NETLINK_DEBUG */