]> git.proxmox.com Git - mirror_frr.git/blame - zebra/debug_nl.c
Merge pull request #13395 from LabNConsulting/chopps/mgmtd-debug-flags
[mirror_frr.git] / zebra / debug_nl.c
CommitLineData
47a3a827 1// SPDX-License-Identifier: ISC
eead0bc4
RZ
2/*
3 * Copyright (c) 2018 Rafael Zalamena
eead0bc4
RZ
4 */
5
6#include <zebra.h>
7
8#if defined(HAVE_NETLINK) && defined(NETLINK_DEBUG)
9
10#include <sys/socket.h>
11
777f9650 12#include <linux/netconf.h>
eead0bc4
RZ
13#include <linux/netlink.h>
14#include <linux/nexthop.h>
15#include <linux/rtnetlink.h>
16#include <net/if_arp.h>
95fe3288 17#include <linux/fib_rules.h>
c30c6070 18#include <linux/lwtunnel.h>
eead0bc4
RZ
19
20#include <stdio.h>
21#include <stdint.h>
22
23#include "zebra/rt_netlink.h"
73b8a68e 24#include "zebra/kernel_netlink.h"
42ed3bd7 25#include "lib/vxlan.h"
eead0bc4
RZ
26
27const char *nlmsg_type2str(uint16_t type)
28{
29 switch (type) {
30 /* Generic */
31 case NLMSG_NOOP:
32 return "NOOP";
33 case NLMSG_ERROR:
34 return "ERROR";
35 case NLMSG_DONE:
36 return "DONE";
37 case NLMSG_OVERRUN:
38 return "OVERRUN";
39
40 /* RTM */
41 case RTM_NEWLINK:
42 return "NEWLINK";
43 case RTM_DELLINK:
44 return "DELLINK";
45 case RTM_GETLINK:
46 return "GETLINK";
47 case RTM_SETLINK:
48 return "SETLINK";
49
50 case RTM_NEWADDR:
51 return "NEWADDR";
52 case RTM_DELADDR:
53 return "DELADDR";
54 case RTM_GETADDR:
55 return "GETADDR";
56
57 case RTM_NEWROUTE:
58 return "NEWROUTE";
59 case RTM_DELROUTE:
60 return "DELROUTE";
61 case RTM_GETROUTE:
62 return "GETROUTE";
63
64 case RTM_NEWNEIGH:
65 return "NEWNEIGH";
66 case RTM_DELNEIGH:
67 return "DELNEIGH";
68 case RTM_GETNEIGH:
69 return "GETNEIGH";
70
71 case RTM_NEWRULE:
72 return "NEWRULE";
73 case RTM_DELRULE:
74 return "DELRULE";
75 case RTM_GETRULE:
76 return "GETRULE";
77
78 case RTM_NEWNEXTHOP:
79 return "NEWNEXTHOP";
80 case RTM_DELNEXTHOP:
81 return "DELNEXTHOP";
82 case RTM_GETNEXTHOP:
83 return "GETNEXTHOP";
84
42ed3bd7
CS
85 case RTM_NEWTUNNEL:
86 return "NEWTUNNEL";
87 case RTM_DELTUNNEL:
88 return "DELTUNNEL";
89 case RTM_GETTUNNEL:
90 return "GETTUNNEL";
91
777f9650
MS
92 case RTM_NEWNETCONF:
93 return "RTM_NEWNETCONF";
94 case RTM_DELNETCONF:
95 return "RTM_DELNETCONF";
96
eead0bc4
RZ
97 default:
98 return "UNKNOWN";
99 }
100}
101
102const char *af_type2str(int type)
103{
104 switch (type) {
105 case AF_UNSPEC:
106 return "AF_UNSPEC";
107 case AF_UNIX:
108 return "AF_UNIX";
109 case AF_INET:
110 return "AF_INET";
111 case AF_INET6:
112 return "AF_INET6";
113 case AF_BRIDGE:
114 return "AF_BRIDGE";
115 case AF_NETLINK:
116 return "AF_NETLINK";
117#ifdef AF_MPLS
118 case AF_MPLS:
119 return "AF_MPLS";
120#endif /* AF_MPLS */
121 case AF_BLUETOOTH:
122 return "AF_BLUETOOTH";
123 case AF_VSOCK:
124 return "AF_VSOCK";
125 case AF_KEY:
126 return "AF_KEY";
127 case AF_PACKET:
128 return "AF_PACKET";
129 default:
130 return "UNKNOWN";
131 }
132}
133
134const char *ifi_type2str(int type)
135{
136 switch (type) {
137 case ARPHRD_ETHER:
138 return "ETHER";
139 case ARPHRD_EETHER:
140 return "EETHER";
141 case ARPHRD_NETROM:
142 return "NETROM";
143 case ARPHRD_AX25:
144 return "AX25";
145 case ARPHRD_PRONET:
146 return "PRONET";
147 case ARPHRD_CHAOS:
148 return "CHAOS";
149 case ARPHRD_IEEE802:
150 return "IEEE802";
151 case ARPHRD_ARCNET:
152 return "ARCNET";
153 case ARPHRD_APPLETLK:
154 return "APPLETLK";
155 case ARPHRD_DLCI:
156 return "DLCI";
157 case ARPHRD_ATM:
158 return "ATM";
159 case ARPHRD_METRICOM:
160 return "METRICOM";
161 case ARPHRD_IEEE1394:
162 return "IEEE1394";
163 case ARPHRD_EUI64:
164 return "EUI64";
165 case ARPHRD_INFINIBAND:
166 return "INFINIBAND";
167 case ARPHRD_SLIP:
168 return "SLIP";
169 case ARPHRD_CSLIP:
170 return "CSLIP";
171 case ARPHRD_SLIP6:
172 return "SLIP6";
173 case ARPHRD_CSLIP6:
174 return "CSLIP6";
175 case ARPHRD_RSRVD:
176 return "RSRVD";
177 case ARPHRD_ADAPT:
178 return "ADAPT";
179 case ARPHRD_ROSE:
180 return "ROSE";
181 case ARPHRD_X25:
182 return "X25";
183 case ARPHRD_PPP:
184 return "PPP";
185 case ARPHRD_HDLC:
186 return "HDLC";
187 case ARPHRD_LAPB:
188 return "LAPB";
189 case ARPHRD_DDCMP:
190 return "DDCMP";
191 case ARPHRD_RAWHDLC:
192 return "RAWHDLC";
193 case ARPHRD_TUNNEL:
194 return "TUNNEL";
195 case ARPHRD_TUNNEL6:
196 return "TUNNEL6";
197 case ARPHRD_FRAD:
198 return "FRAD";
199 case ARPHRD_SKIP:
200 return "SKIP";
201 case ARPHRD_LOOPBACK:
202 return "LOOPBACK";
203 case ARPHRD_LOCALTLK:
204 return "LOCALTLK";
205 case ARPHRD_FDDI:
206 return "FDDI";
207 case ARPHRD_BIF:
208 return "BIF";
209 case ARPHRD_SIT:
210 return "SIT";
211 case ARPHRD_IPDDP:
212 return "IPDDP";
213 case ARPHRD_IPGRE:
214 return "IPGRE";
215 case ARPHRD_PIMREG:
216 return "PIMREG";
217 case ARPHRD_HIPPI:
218 return "HIPPI";
219 case ARPHRD_ASH:
220 return "ASH";
221 case ARPHRD_ECONET:
222 return "ECONET";
223 case ARPHRD_IRDA:
224 return "IRDA";
225 case ARPHRD_FCPP:
226 return "FCPP";
227 case ARPHRD_FCAL:
228 return "FCAL";
229 case ARPHRD_FCPL:
230 return "FCPL";
231 case ARPHRD_FCFABRIC:
232 return "FCFABRIC";
233 case ARPHRD_IEEE802_TR:
234 return "IEEE802_TR";
235 case ARPHRD_IEEE80211:
236 return "IEEE80211";
237 case ARPHRD_IEEE80211_PRISM:
238 return "IEEE80211_PRISM";
239 case ARPHRD_IEEE80211_RADIOTAP:
240 return "IEEE80211_RADIOTAP";
241 case ARPHRD_IEEE802154:
242 return "IEEE802154";
243#ifdef ARPHRD_VSOCKMON
244 case ARPHRD_VSOCKMON:
245 return "VSOCKMON";
246#endif /* ARPHRD_VSOCKMON */
247 case ARPHRD_VOID:
248 return "VOID";
249 case ARPHRD_NONE:
250 return "NONE";
251 default:
252 return "UNKNOWN";
253 }
254}
255
5d414138
SW
256const char *ifla_pdr_type2str(int type)
257{
258 switch (type) {
259 case IFLA_PROTO_DOWN_REASON_UNSPEC:
260 return "UNSPEC";
261 case IFLA_PROTO_DOWN_REASON_MASK:
262 return "MASK";
263 case IFLA_PROTO_DOWN_REASON_VALUE:
264 return "VALUE";
265 default:
266 return "UNKNOWN";
267 }
268}
269
270const char *ifla_info_type2str(int type)
271{
272 switch (type) {
273 case IFLA_INFO_UNSPEC:
274 return "UNSPEC";
275 case IFLA_INFO_KIND:
276 return "KIND";
277 case IFLA_INFO_DATA:
278 return "DATA";
279 case IFLA_INFO_XSTATS:
280 return "XSTATS";
281 case IFLA_INFO_SLAVE_KIND:
282 return "SLAVE_KIND";
283 case IFLA_INFO_SLAVE_DATA:
284 return "SLAVE_DATA";
285 default:
286 return "UNKNOWN";
287 }
288}
289
eead0bc4
RZ
290const char *rta_type2str(int type)
291{
292 switch (type) {
293 case IFLA_UNSPEC:
294 return "UNSPEC";
295 case IFLA_ADDRESS:
296 return "ADDRESS";
297 case IFLA_BROADCAST:
298 return "BROADCAST";
299 case IFLA_IFNAME:
300 return "IFNAME";
301 case IFLA_MTU:
302 return "MTU";
303 case IFLA_LINK:
304 return "LINK";
305 case IFLA_QDISC:
306 return "QDISC";
307 case IFLA_STATS:
308 return "STATS";
309 case IFLA_COST:
310 return "COST";
311 case IFLA_PRIORITY:
312 return "PRIORITY";
313 case IFLA_MASTER:
314 return "MASTER";
315 case IFLA_WIRELESS:
316 return "WIRELESS";
317 case IFLA_PROTINFO:
318 return "PROTINFO";
319 case IFLA_TXQLEN:
320 return "TXQLEN";
321 case IFLA_MAP:
322 return "MAP";
323 case IFLA_WEIGHT:
324 return "WEIGHT";
325 case IFLA_OPERSTATE:
326 return "OPERSTATE";
327 case IFLA_LINKMODE:
328 return "LINKMODE";
329 case IFLA_LINKINFO:
330 return "LINKINFO";
331 case IFLA_NET_NS_PID:
332 return "NET_NS_PID";
333 case IFLA_IFALIAS:
334 return "IFALIAS";
335 case IFLA_NUM_VF:
336 return "NUM_VF";
337 case IFLA_VFINFO_LIST:
338 return "VFINFO_LIST";
339 case IFLA_STATS64:
340 return "STATS64";
341 case IFLA_VF_PORTS:
342 return "VF_PORTS";
343 case IFLA_PORT_SELF:
344 return "PORT_SELF";
345 case IFLA_AF_SPEC:
346 return "AF_SPEC";
347 case IFLA_GROUP:
348 return "GROUP";
349 case IFLA_NET_NS_FD:
350 return "NET_NS_FD";
351 case IFLA_EXT_MASK:
352 return "EXT_MASK";
353 case IFLA_PROMISCUITY:
354 return "PROMISCUITY";
355 case IFLA_NUM_TX_QUEUES:
356 return "NUM_TX_QUEUES";
357 case IFLA_NUM_RX_QUEUES:
358 return "NUM_RX_QUEUES";
359 case IFLA_CARRIER:
360 return "CARRIER";
361 case IFLA_PHYS_PORT_ID:
362 return "PHYS_PORT_ID";
363 case IFLA_CARRIER_CHANGES:
364 return "CARRIER_CHANGES";
365 case IFLA_PHYS_SWITCH_ID:
366 return "PHYS_SWITCH_ID";
367 case IFLA_LINK_NETNSID:
368 return "LINK_NETNSID";
369 case IFLA_PHYS_PORT_NAME:
370 return "PHYS_PORT_NAME";
371 case IFLA_PROTO_DOWN:
372 return "PROTO_DOWN";
373#ifdef IFLA_GSO_MAX_SEGS
374 case IFLA_GSO_MAX_SEGS:
375 return "GSO_MAX_SEGS";
376#endif /* IFLA_GSO_MAX_SEGS */
377#ifdef IFLA_GSO_MAX_SIZE
378 case IFLA_GSO_MAX_SIZE:
379 return "GSO_MAX_SIZE";
380#endif /* IFLA_GSO_MAX_SIZE */
381#ifdef IFLA_PAD
382 case IFLA_PAD:
383 return "PAD";
384#endif /* IFLA_PAD */
385#ifdef IFLA_XDP
386 case IFLA_XDP:
387 return "XDP";
388#endif /* IFLA_XDP */
389#ifdef IFLA_EVENT
390 case IFLA_EVENT:
391 return "EVENT";
392#endif /* IFLA_EVENT */
5d414138
SW
393 case IFLA_PROTO_DOWN_REASON:
394 return "PROTO_DOWN_REASON";
eead0bc4
RZ
395 default:
396 return "UNKNOWN";
397 }
398}
399
400const char *rtm_type2str(int type)
401{
402 switch (type) {
403 case RTN_UNSPEC:
404 return "UNSPEC";
405 case RTN_UNICAST:
406 return "UNICAST";
407 case RTN_LOCAL:
408 return "LOCAL";
409 case RTN_BROADCAST:
410 return "BROADCAST";
411 case RTN_ANYCAST:
412 return "ANYCAST";
413 case RTN_MULTICAST:
414 return "MULTICAST";
415 case RTN_BLACKHOLE:
416 return "BLACKHOLE";
417 case RTN_UNREACHABLE:
418 return "UNREACHABLE";
419 case RTN_PROHIBIT:
420 return "PROHIBIT";
421 case RTN_THROW:
422 return "THROW";
423 case RTN_NAT:
424 return "NAT";
425 case RTN_XRESOLVE:
426 return "XRESOLVE";
427 default:
428 return "UNKNOWN";
429 }
430}
431
432const char *rtm_protocol2str(int type)
433{
434 switch (type) {
435 case RTPROT_UNSPEC:
436 return "UNSPEC";
437 case RTPROT_REDIRECT:
438 return "REDIRECT";
439 case RTPROT_KERNEL:
440 return "KERNEL";
441 case RTPROT_BOOT:
442 return "BOOT";
443 case RTPROT_STATIC:
444 return "STATIC";
445 case RTPROT_GATED:
446 return "GATED";
447 case RTPROT_RA:
448 return "RA";
449 case RTPROT_MRT:
450 return "MRT";
451 case RTPROT_ZEBRA:
452 return "ZEBRA";
865c12e1
CS
453 case RTPROT_BGP:
454 return "BGP";
455 case RTPROT_ISIS:
456 return "ISIS";
457 case RTPROT_OSPF:
458 return "OSPF";
eead0bc4
RZ
459 case RTPROT_BIRD:
460 return "BIRD";
461 case RTPROT_DNROUTED:
462 return "DNROUTED";
463 case RTPROT_XORP:
464 return "XORP";
465 case RTPROT_NTK:
466 return "NTK";
467 case RTPROT_DHCP:
468 return "DHCP";
469 case RTPROT_MROUTED:
470 return "MROUTED";
471 case RTPROT_BABEL:
472 return "BABEL";
473 default:
474 return "UNKNOWN";
475 }
476}
477
478const char *rtm_scope2str(int type)
479{
480 switch (type) {
481 case RT_SCOPE_UNIVERSE:
482 return "UNIVERSE";
483 case RT_SCOPE_SITE:
484 return "SITE";
485 case RT_SCOPE_LINK:
486 return "LINK";
487 case RT_SCOPE_HOST:
488 return "HOST";
489 case RT_SCOPE_NOWHERE:
490 return "NOWHERE";
491 default:
492 return "UNKNOWN";
493 }
494}
495
496const char *rtm_rta2str(int type)
497{
498 switch (type) {
499 case RTA_UNSPEC:
500 return "UNSPEC";
501 case RTA_DST:
502 return "DST";
503 case RTA_SRC:
504 return "SRC";
505 case RTA_IIF:
506 return "IIF";
507 case RTA_OIF:
508 return "OIF";
509 case RTA_GATEWAY:
510 return "GATEWAY";
511 case RTA_PRIORITY:
512 return "PRIORITY";
513 case RTA_PREF:
514 return "PREF";
515 case RTA_PREFSRC:
516 return "PREFSRC";
517 case RTA_MARK:
518 return "MARK";
519 case RTA_METRICS:
520 return "METRICS";
521 case RTA_MULTIPATH:
522 return "MULTIPATH";
523 case RTA_PROTOINFO:
524 return "PROTOINFO";
525 case RTA_FLOW:
526 return "FLOW";
527 case RTA_CACHEINFO:
528 return "CACHEINFO";
529 case RTA_TABLE:
530 return "TABLE";
531 case RTA_MFC_STATS:
532 return "MFC_STATS";
533 case RTA_NH_ID:
534 return "NH_ID";
ca8a395d
DL
535 case RTA_EXPIRES:
536 return "EXPIRES";
eead0bc4
RZ
537 default:
538 return "UNKNOWN";
539 }
540}
541
542const char *neigh_rta2str(int type)
543{
544 switch (type) {
545 case NDA_UNSPEC:
546 return "UNSPEC";
547 case NDA_DST:
548 return "DST";
549 case NDA_LLADDR:
550 return "LLADDR";
551 case NDA_CACHEINFO:
552 return "CACHEINFO";
553 case NDA_PROBES:
554 return "PROBES";
555 case NDA_VLAN:
556 return "VLAN";
557 case NDA_PORT:
558 return "PORT";
559 case NDA_VNI:
560 return "VNI";
561 case NDA_IFINDEX:
562 return "IFINDEX";
563 case NDA_MASTER:
564 return "MASTER";
565 case NDA_LINK_NETNSID:
566 return "LINK_NETNSID";
567 default:
568 return "UNKNOWN";
569 }
570}
571
572const char *ifa_rta2str(int type)
573{
574 switch (type) {
575 case IFA_UNSPEC:
576 return "UNSPEC";
577 case IFA_ADDRESS:
578 return "ADDRESS";
579 case IFA_LOCAL:
580 return "LOCAL";
581 case IFA_LABEL:
582 return "LABEL";
583 case IFA_BROADCAST:
584 return "BROADCAST";
585 case IFA_ANYCAST:
586 return "ANYCAST";
587 case IFA_CACHEINFO:
588 return "CACHEINFO";
589 case IFA_MULTICAST:
590 return "MULTICAST";
591 case IFA_FLAGS:
592 return "FLAGS";
593 default:
594 return "UNKNOWN";
595 }
596}
597
598const char *nhm_rta2str(int type)
599{
600 switch (type) {
601 case NHA_UNSPEC:
602 return "UNSPEC";
603 case NHA_ID:
604 return "ID";
605 case NHA_GROUP:
606 return "GROUP";
607 case NHA_GROUP_TYPE:
608 return "GROUP_TYPE";
609 case NHA_BLACKHOLE:
610 return "BLACKHOLE";
611 case NHA_OIF:
612 return "OIF";
613 case NHA_GATEWAY:
614 return "GATEWAY";
615 case NHA_ENCAP_TYPE:
616 return "ENCAP_TYPE";
617 case NHA_ENCAP:
618 return "ENCAP";
619 case NHA_GROUPS:
620 return "GROUPS";
621 case NHA_MASTER:
622 return "MASTER";
623 default:
624 return "UNKNOWN";
625 }
626}
627
95fe3288
TA
628const char *frh_rta2str(int type)
629{
630 switch (type) {
631 case FRA_DST:
632 return "DST";
633 case FRA_SRC:
634 return "SRC";
635 case FRA_IIFNAME:
636 return "IIFNAME";
637 case FRA_GOTO:
638 return "GOTO";
639 case FRA_UNUSED2:
640 return "UNUSED2";
641 case FRA_PRIORITY:
642 return "PRIORITY";
643 case FRA_UNUSED3:
644 return "UNUSED3";
645 case FRA_UNUSED4:
646 return "UNUSED4";
647 case FRA_UNUSED5:
648 return "UNUSED5";
649 case FRA_FWMARK:
650 return "FWMARK";
651 case FRA_FLOW:
652 return "FLOW";
653 case FRA_TUN_ID:
654 return "TUN_ID";
655 case FRA_SUPPRESS_IFGROUP:
656 return "SUPPRESS_IFGROUP";
657 case FRA_SUPPRESS_PREFIXLEN:
658 return "SUPPRESS_PREFIXLEN";
659 case FRA_TABLE:
660 return "TABLE";
661 case FRA_FWMASK:
662 return "FWMASK";
663 case FRA_OIFNAME:
664 return "OIFNAME";
665 case FRA_PAD:
666 return "PAD";
667 case FRA_L3MDEV:
668 return "L3MDEV";
669 case FRA_UID_RANGE:
670 return "UID_RANGE";
671 case FRA_PROTOCOL:
672 return "PROTOCOL";
673 case FRA_IP_PROTO:
674 return "IP_PROTO";
675 case FRA_SPORT_RANGE:
676 return "SPORT_RANGE";
677 case FRA_DPORT_RANGE:
678 return "DPORT_RANGE";
679 default:
680 return "UNKNOWN";
681 }
682}
683
684const char *frh_action2str(uint8_t action)
685{
686 switch (action) {
687 case FR_ACT_TO_TBL:
688 return "TO_TBL";
689 case FR_ACT_GOTO:
690 return "GOTO";
691 case FR_ACT_NOP:
692 return "NOP";
693 case FR_ACT_RES3:
694 return "RES3";
695 case FR_ACT_RES4:
696 return "RES4";
697 case FR_ACT_BLACKHOLE:
698 return "BLACKHOLE";
699 case FR_ACT_UNREACHABLE:
700 return "UNREACHABLE";
701 case FR_ACT_PROHIBIT:
702 return "PROHIBIT";
703 default:
704 return "UNKNOWN";
705 }
706}
707
777f9650
MS
708static const char *ncm_rta2str(int type)
709{
710 switch (type) {
711 case NETCONFA_UNSPEC:
712 return "UNSPEC";
713 case NETCONFA_IFINDEX:
714 return "IFINDEX";
715 case NETCONFA_FORWARDING:
716 return "FORWARDING";
717 case NETCONFA_RP_FILTER:
718 return "RP_FILTER";
719 case NETCONFA_MC_FORWARDING:
720 return "MCAST";
721 case NETCONFA_PROXY_NEIGH:
722 return "PROXY_NEIGH";
723 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN:
724 return "IGNORE_LINKDOWN";
725 case NETCONFA_INPUT:
726 return "MPLS";
727 case NETCONFA_BC_FORWARDING:
728 return "BCAST";
729 default:
730 return "UNKNOWN";
731 }
732}
733
734static void dump_on_off(uint32_t ival, const char *prefix)
735{
736 zlog_debug("%s%s", prefix, (ival != 0) ? "on" : "off");
737}
738
eead0bc4
RZ
739static inline void flag_write(int flags, int flag, const char *flagstr,
740 char *buf, size_t buflen)
741{
742 if (CHECK_FLAG(flags, flag) == 0)
743 return;
744
745 if (buf[0])
746 strlcat(buf, ",", buflen);
747
748 strlcat(buf, flagstr, buflen);
749}
750
751const char *nlmsg_flags2str(uint16_t flags, char *buf, size_t buflen)
752{
753 const char *bufp = buf;
754
755 *buf = 0;
756 /* Specific flags. */
757 flag_write(flags, NLM_F_REQUEST, "REQUEST", buf, buflen);
758 flag_write(flags, NLM_F_MULTI, "MULTI", buf, buflen);
759 flag_write(flags, NLM_F_ACK, "ACK", buf, buflen);
760 flag_write(flags, NLM_F_ECHO, "ECHO", buf, buflen);
761 flag_write(flags, NLM_F_DUMP, "DUMP", buf, buflen);
762
763 /* Netlink family type dependent. */
764 flag_write(flags, 0x0100, "(ROOT|REPLACE|CAPPED)", buf, buflen);
765 flag_write(flags, 0x0200, "(MATCH|EXCLUDE|ACK_TLVS)", buf, buflen);
766 flag_write(flags, 0x0400, "(ATOMIC|CREATE)", buf, buflen);
767 flag_write(flags, 0x0800, "(DUMP|APPEND)", buf, buflen);
768
769 return (bufp);
770}
771
772const char *if_flags2str(uint32_t flags, char *buf, size_t buflen)
773{
774 const char *bufp = buf;
775
776 *buf = 0;
777 flag_write(flags, IFF_UP, "UP", buf, buflen);
778 flag_write(flags, IFF_BROADCAST, "BROADCAST", buf, buflen);
779 flag_write(flags, IFF_DEBUG, "DEBUG", buf, buflen);
780 flag_write(flags, IFF_LOOPBACK, "LOOPBACK", buf, buflen);
781 flag_write(flags, IFF_POINTOPOINT, "POINTOPOINT", buf, buflen);
782 flag_write(flags, IFF_NOTRAILERS, "NOTRAILERS", buf, buflen);
783 flag_write(flags, IFF_RUNNING, "RUNNING", buf, buflen);
784 flag_write(flags, IFF_NOARP, "NOARP", buf, buflen);
785 flag_write(flags, IFF_PROMISC, "PROMISC", buf, buflen);
786 flag_write(flags, IFF_ALLMULTI, "ALLMULTI", buf, buflen);
787 flag_write(flags, IFF_MASTER, "MASTER", buf, buflen);
788 flag_write(flags, IFF_SLAVE, "SLAVE", buf, buflen);
789 flag_write(flags, IFF_MULTICAST, "MULTICAST", buf, buflen);
790 flag_write(flags, IFF_PORTSEL, "PORTSEL", buf, buflen);
791 flag_write(flags, IFF_AUTOMEDIA, "AUTOMEDIA", buf, buflen);
792 flag_write(flags, IFF_DYNAMIC, "DYNAMIC", buf, buflen);
793
794 return (bufp);
795}
796
797const char *rtm_flags2str(uint32_t flags, char *buf, size_t buflen)
798{
799 const char *bufp = buf;
800
801 *buf = 0;
802 flag_write(flags, RTM_F_NOTIFY, "NOTIFY", buf, buflen);
803 flag_write(flags, RTM_F_CLONED, "CLONED", buf, buflen);
804 flag_write(flags, RTM_F_EQUALIZE, "EQUALIZE", buf, buflen);
805
806 return (bufp);
807}
808
809const char *neigh_state2str(uint32_t flags, char *buf, size_t buflen)
810{
811 const char *bufp = buf;
812
813 *buf = 0;
814 flag_write(flags, NUD_INCOMPLETE, "INCOMPLETE", buf, buflen);
815 flag_write(flags, NUD_REACHABLE, "REACHABLE", buf, buflen);
816 flag_write(flags, NUD_STALE, "STALE", buf, buflen);
817 flag_write(flags, NUD_DELAY, "DELAY", buf, buflen);
818 flag_write(flags, NUD_PROBE, "PROBE", buf, buflen);
819 flag_write(flags, NUD_FAILED, "FAILED", buf, buflen);
820 flag_write(flags, NUD_NOARP, "NOARP", buf, buflen);
821 flag_write(flags, NUD_PERMANENT, "PERMANENT", buf, buflen);
822
823 return (bufp);
824}
825
826const char *neigh_flags2str(uint32_t flags, char *buf, size_t buflen)
827{
828 const char *bufp = buf;
829
830 *buf = 0;
831 flag_write(flags, NTF_USE, "USE", buf, buflen);
832 flag_write(flags, NTF_SELF, "SELF", buf, buflen);
833 flag_write(flags, NTF_MASTER, "MASTER", buf, buflen);
834 flag_write(flags, NTF_PROXY, "PROXY", buf, buflen);
835 flag_write(flags, NTF_EXT_LEARNED, "EXT_LEARNED", buf, buflen);
836#ifdef NTF_OFFLOADED
837 flag_write(flags, NTF_OFFLOADED, "OFFLOADED", buf, buflen);
838#endif /* NTF_OFFLOADED */
839 flag_write(flags, NTF_ROUTER, "ROUTER", buf, buflen);
840
841 return (bufp);
842}
843
844const char *ifa_flags2str(uint32_t flags, char *buf, size_t buflen)
845{
846 const char *bufp = buf;
847
848 *buf = 0;
849 flag_write(flags, IFA_F_SECONDARY, "SECONDARY", buf, buflen);
850 flag_write(flags, IFA_F_NODAD, "NODAD", buf, buflen);
851 flag_write(flags, IFA_F_OPTIMISTIC, "OPTIMISTIC", buf, buflen);
852 flag_write(flags, IFA_F_DADFAILED, "DADFAILED", buf, buflen);
853 flag_write(flags, IFA_F_HOMEADDRESS, "HOMEADDRESS", buf, buflen);
854 flag_write(flags, IFA_F_DEPRECATED, "DEPRECATED", buf, buflen);
855 flag_write(flags, IFA_F_TENTATIVE, "TENTATIVE", buf, buflen);
856 flag_write(flags, IFA_F_PERMANENT, "PERMANENT", buf, buflen);
857 flag_write(flags, IFA_F_MANAGETEMPADDR, "MANAGETEMPADDR", buf, buflen);
858 flag_write(flags, IFA_F_NOPREFIXROUTE, "NOPREFIXROUTE", buf, buflen);
859 flag_write(flags, IFA_F_MCAUTOJOIN, "MCAUTOJOIN", buf, buflen);
860 flag_write(flags, IFA_F_STABLE_PRIVACY, "STABLE_PRIVACY", buf, buflen);
861
862 return (bufp);
863}
864
865const char *nh_flags2str(uint32_t flags, char *buf, size_t buflen)
866{
867 const char *bufp = buf;
868
869 *buf = 0;
870 flag_write(flags, RTNH_F_DEAD, "DEAD", buf, buflen);
871 flag_write(flags, RTNH_F_PERVASIVE, "PERVASIVE", buf, buflen);
872 flag_write(flags, RTNH_F_ONLINK, "ONLINK", buf, buflen);
873 flag_write(flags, RTNH_F_OFFLOAD, "OFFLOAD", buf, buflen);
874 flag_write(flags, RTNH_F_LINKDOWN, "LINKDOWN", buf, buflen);
875 flag_write(flags, RTNH_F_UNRESOLVED, "UNRESOLVED", buf, buflen);
876
877 return (bufp);
878}
879
880/*
881 * Netlink abstractions.
882 */
5d414138
SW
883static void nllink_pdr_dump(struct rtattr *rta, size_t msglen)
884{
885 size_t plen;
886 uint32_t u32v;
887
888next_rta:
889 /* Check the header for valid length and for outbound access. */
890 if (RTA_OK(rta, msglen) == 0)
891 return;
892
893 plen = RTA_PAYLOAD(rta);
894 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
895 rta->rta_len, plen, rta->rta_type,
896 ifla_pdr_type2str(rta->rta_type));
897 switch (rta->rta_type) {
898 case IFLA_PROTO_DOWN_REASON_MASK:
899 case IFLA_PROTO_DOWN_REASON_VALUE:
900 if (plen < sizeof(uint32_t)) {
901 zlog_debug(" invalid length");
902 break;
903 }
904
905 u32v = *(uint32_t *)RTA_DATA(rta);
906 zlog_debug(" %u", u32v);
907 break;
908
909 default:
910 /* NOTHING: unhandled. */
911 break;
912 }
913
914 /* Get next pointer and start iteration again. */
915 rta = RTA_NEXT(rta, msglen);
916 goto next_rta;
917}
918
eead0bc4
RZ
919static void nllink_linkinfo_dump(struct rtattr *rta, size_t msglen)
920{
921 size_t plen;
922 char dbuf[128];
923
924next_rta:
925 /* Check the header for valid length and for outbound access. */
926 if (RTA_OK(rta, msglen) == 0)
927 return;
928
929 plen = RTA_PAYLOAD(rta);
930 zlog_debug(" linkinfo [len=%d (payload=%zu) type=(%d) %s]",
931 rta->rta_len, plen, rta->rta_type,
5d414138 932 ifla_info_type2str(rta->rta_type));
eead0bc4
RZ
933 switch (rta->rta_type) {
934 case IFLA_INFO_KIND:
935 if (plen == 0) {
936 zlog_debug(" invalid length");
937 break;
938 }
939
940 snprintf(dbuf, sizeof(dbuf), "%s", (char *)RTA_DATA(rta));
941 zlog_debug(" %s", dbuf);
942 break;
943 case IFLA_INFO_SLAVE_KIND:
944 if (plen == 0) {
945 zlog_debug(" invalid length");
946 break;
947 }
948
949 snprintf(dbuf, sizeof(dbuf), "%s", (char *)RTA_DATA(rta));
950 zlog_debug(" %s", dbuf);
951 break;
952
953 default:
954 /* NOTHING: unhandled. */
955 break;
956 }
957
958 /* Get next pointer and start iteration again. */
959 rta = RTA_NEXT(rta, msglen);
960 goto next_rta;
961}
962
963static void nllink_dump(struct ifinfomsg *ifi, size_t msglen)
964{
965 uint8_t *datap;
966 struct rtattr *rta;
967 size_t plen, it;
968 uint32_t u32v;
5d414138 969 uint8_t u8v;
eead0bc4
RZ
970 char bytestr[16];
971 char dbuf[128];
5d414138 972 unsigned short rta_type;
eead0bc4
RZ
973
974 /* Get the first attribute and go from there. */
975 rta = IFLA_RTA(ifi);
976next_rta:
977 /* Check the header for valid length and for outbound access. */
978 if (RTA_OK(rta, msglen) == 0)
979 return;
980
981 plen = RTA_PAYLOAD(rta);
5d414138 982 rta_type = rta->rta_type & ~NLA_F_NESTED;
eead0bc4 983 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
5d414138
SW
984 plen, rta_type, rta_type2str(rta_type));
985 switch (rta_type) {
eead0bc4
RZ
986 case IFLA_IFALIAS:
987 if (plen == 0) {
988 zlog_debug(" invalid length");
989 break;
990 }
991
992 snprintf(dbuf, sizeof(dbuf), "%s", (char *)RTA_DATA(rta));
993 zlog_debug(" %s", dbuf);
994 break;
995
996 case IFLA_MTU:
997 case IFLA_TXQLEN:
998 case IFLA_NUM_TX_QUEUES:
999 case IFLA_NUM_RX_QUEUES:
1000 case IFLA_GROUP:
1001 case IFLA_PROMISCUITY:
1002#ifdef IFLA_GSO_MAX_SEGS
1003 case IFLA_GSO_MAX_SEGS:
1004#endif /* IFLA_GSO_MAX_SEGS */
1005#ifdef IFLA_GSO_MAX_SIZE
1006 case IFLA_GSO_MAX_SIZE:
1007#endif /* IFLA_GSO_MAX_SIZE */
1008 case IFLA_CARRIER_CHANGES:
1009 case IFLA_MASTER:
5d414138 1010 case IFLA_LINK:
eead0bc4
RZ
1011 if (plen < sizeof(uint32_t)) {
1012 zlog_debug(" invalid length");
1013 break;
1014 }
1015
1016 u32v = *(uint32_t *)RTA_DATA(rta);
1017 zlog_debug(" %u", u32v);
1018 break;
1019
5d414138
SW
1020 case IFLA_PROTO_DOWN:
1021 if (plen < sizeof(uint8_t)) {
1022 zlog_debug(" invalid length");
1023 break;
1024 }
1025
1026 u8v = *(uint8_t *)RTA_DATA(rta);
1027 zlog_debug(" %u", u8v);
1028 break;
eead0bc4
RZ
1029 case IFLA_ADDRESS:
1030 datap = RTA_DATA(rta);
1031 dbuf[0] = 0;
1032 for (it = 0; it < plen; it++) {
1033 snprintf(bytestr, sizeof(bytestr), "%02X:", *datap);
1034 strlcat(dbuf, bytestr, sizeof(dbuf));
1035 datap++;
1036 }
1037 /* Remove trailing ':'. */
1038 if (dbuf[0])
1039 dbuf[strlen(dbuf) - 1] = 0;
1040
1041 zlog_debug(" %s", dbuf[0] ? dbuf : "<empty>");
1042 break;
1043
1044 case IFLA_LINKINFO:
5d414138
SW
1045 nllink_linkinfo_dump(RTA_DATA(rta), plen);
1046 break;
1047
1048 case IFLA_PROTO_DOWN_REASON:
1049 nllink_pdr_dump(RTA_DATA(rta), plen);
eead0bc4
RZ
1050 break;
1051
1052 default:
1053 /* NOTHING: unhandled. */
1054 break;
1055 }
1056
1057 /* Get next pointer and start iteration again. */
1058 rta = RTA_NEXT(rta, msglen);
1059 goto next_rta;
1060}
1061
1062static void nlroute_dump(struct rtmsg *rtm, size_t msglen)
1063{
ca8a395d 1064 struct rta_mfc_stats *mfc_stats;
eead0bc4
RZ
1065 struct rtattr *rta;
1066 size_t plen;
1067 uint32_t u32v;
ca8a395d 1068 uint64_t u64v;
eead0bc4
RZ
1069
1070 /* Get the first attribute and go from there. */
1071 rta = RTM_RTA(rtm);
1072next_rta:
1073 /* Check the header for valid length and for outbound access. */
1074 if (RTA_OK(rta, msglen) == 0)
1075 return;
1076
1077 plen = RTA_PAYLOAD(rta);
1078 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
63eaefa8
R
1079 plen, rta->rta_type & NLA_TYPE_MASK,
1080 rtm_rta2str(rta->rta_type & NLA_TYPE_MASK));
1081 switch (rta->rta_type & NLA_TYPE_MASK) {
eead0bc4
RZ
1082 case RTA_IIF:
1083 case RTA_OIF:
1084 case RTA_PRIORITY:
1085 case RTA_TABLE:
1086 case RTA_NH_ID:
1087 u32v = *(uint32_t *)RTA_DATA(rta);
1088 zlog_debug(" %u", u32v);
1089 break;
1090
ca8a395d
DL
1091 case RTA_EXPIRES:
1092 u64v = *(uint64_t *)RTA_DATA(rta);
1093 zlog_debug(" %" PRIu64, u64v);
1094 break;
1095
eead0bc4
RZ
1096 case RTA_GATEWAY:
1097 case RTA_DST:
1098 case RTA_SRC:
1099 case RTA_PREFSRC:
1100 switch (plen) {
1101 case sizeof(struct in_addr):
1102 zlog_debug(" %pI4",
1103 (struct in_addr *)RTA_DATA(rta));
1104 break;
1105 case sizeof(struct in6_addr):
1106 zlog_debug(" %pI6",
1107 (struct in6_addr *)RTA_DATA(rta));
1108 break;
1109 default:
1110 break;
1111 }
1112 break;
1113
ca8a395d
DL
1114 case RTA_MFC_STATS:
1115 mfc_stats = (struct rta_mfc_stats *)RTA_DATA(rta);
1116 zlog_debug(" pkts=%ju bytes=%ju wrong_if=%ju",
1117 (uintmax_t)mfc_stats->mfcs_packets,
1118 (uintmax_t)mfc_stats->mfcs_bytes,
1119 (uintmax_t)mfc_stats->mfcs_wrong_if);
1120 break;
1121
eead0bc4
RZ
1122 default:
1123 /* NOTHING: unhandled. */
1124 break;
1125 }
1126
1127 /* Get next pointer and start iteration again. */
1128 rta = RTA_NEXT(rta, msglen);
1129 goto next_rta;
1130}
1131
1132static void nlneigh_dump(struct ndmsg *ndm, size_t msglen)
1133{
1134 struct rtattr *rta;
1135 uint8_t *datap;
1136 size_t plen, it;
1137 uint16_t vid;
1138 char bytestr[16];
1139 char dbuf[128];
5d414138 1140 unsigned short rta_type;
eead0bc4
RZ
1141
1142#ifndef NDA_RTA
1143#define NDA_RTA(ndm) \
1144 /* struct ndmsg *ndm; */ \
1145 ((struct rtattr *)(((uint8_t *)(ndm)) \
1146 + NLMSG_ALIGN(sizeof(struct ndmsg))))
1147#endif /* NDA_RTA */
1148
1149 /* Get the first attribute and go from there. */
1150 rta = NDA_RTA(ndm);
1151next_rta:
1152 /* Check the header for valid length and for outbound access. */
1153 if (RTA_OK(rta, msglen) == 0)
1154 return;
1155
1156 plen = RTA_PAYLOAD(rta);
5d414138 1157 rta_type = rta->rta_type & ~NLA_F_NESTED;
eead0bc4 1158 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
5d414138
SW
1159 plen, rta->rta_type, neigh_rta2str(rta_type));
1160 switch (rta_type) {
eead0bc4
RZ
1161 case NDA_LLADDR:
1162 datap = RTA_DATA(rta);
1163 dbuf[0] = 0;
1164 for (it = 0; it < plen; it++) {
1165 snprintf(bytestr, sizeof(bytestr), "%02X:", *datap);
1166 strlcat(dbuf, bytestr, sizeof(dbuf));
1167 datap++;
1168 }
1169 /* Remove trailing ':'. */
1170 if (dbuf[0])
1171 dbuf[strlen(dbuf) - 1] = 0;
1172
1173 zlog_debug(" %s", dbuf[0] ? dbuf : "<empty>");
1174 break;
1175
1176 case NDA_DST:
1177 switch (plen) {
1178 case sizeof(struct in_addr):
1179 zlog_debug(" %pI4",
1180 (struct in_addr *)RTA_DATA(rta));
1181 break;
1182 case sizeof(struct in6_addr):
1183 zlog_debug(" %pI6",
1184 (struct in6_addr *)RTA_DATA(rta));
1185 break;
1186 default:
1187 break;
1188 }
1189 break;
1190
1191 case NDA_VLAN:
1192 vid = *(uint16_t *)RTA_DATA(rta);
1193 zlog_debug(" %d", vid);
1194 break;
1195
1196 default:
1197 /* NOTHING: unhandled. */
1198 break;
1199 }
1200
1201 /* Get next pointer and start iteration again. */
1202 rta = RTA_NEXT(rta, msglen);
1203 goto next_rta;
1204}
1205
1206static void nlifa_dump(struct ifaddrmsg *ifa, size_t msglen)
1207{
1208 struct rtattr *rta;
1209 size_t plen;
1210 uint32_t u32v;
1211
1212 /* Get the first attribute and go from there. */
1213 rta = IFA_RTA(ifa);
1214next_rta:
1215 /* Check the header for valid length and for outbound access. */
1216 if (RTA_OK(rta, msglen) == 0)
1217 return;
1218
1219 plen = RTA_PAYLOAD(rta);
1220 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
1221 plen, rta->rta_type, ifa_rta2str(rta->rta_type));
1222 switch (rta->rta_type) {
1223 case IFA_UNSPEC:
1224 u32v = *(uint32_t *)RTA_DATA(rta);
1225 zlog_debug(" %u", u32v);
1226 break;
1227
1228 case IFA_LABEL:
1229 zlog_debug(" %s", (const char *)RTA_DATA(rta));
1230 break;
1231
1232 case IFA_ADDRESS:
1233 case IFA_LOCAL:
1234 case IFA_BROADCAST:
1235 switch (plen) {
1236 case 4:
1237 zlog_debug(" %pI4",
1238 (struct in_addr *)RTA_DATA(rta));
1239 break;
1240 case 16:
1241 zlog_debug(" %pI6",
1242 (struct in6_addr *)RTA_DATA(rta));
1243 break;
1244 default:
1245 break;
1246 }
1247 break;
1248
1249 default:
1250 /* NOTHING: unhandled. */
1251 break;
1252 }
1253
1254 /* Get next pointer and start iteration again. */
1255 rta = RTA_NEXT(rta, msglen);
1256 goto next_rta;
1257}
1258
42ed3bd7
CS
1259static void nltnl_dump(struct tunnel_msg *tnlm, size_t msglen)
1260{
1261 struct rtattr *attr;
1262 vni_t vni_start = 0, vni_end = 0;
1263 struct rtattr *ttb[VXLAN_VNIFILTER_ENTRY_MAX + 1];
1264 uint8_t rta_type;
1265
1266 attr = TUNNEL_RTA(tnlm);
1267next_attr:
1268 /* Check the header for valid length and for outbound access. */
1269 if (RTA_OK(attr, msglen) == 0)
1270 return;
1271
1272 rta_type = attr->rta_type & NLA_TYPE_MASK;
1273
1274 if (rta_type != VXLAN_VNIFILTER_ENTRY) {
1275 attr = RTA_NEXT(attr, msglen);
1276 goto next_attr;
1277 }
1278
1279 memset(ttb, 0, sizeof(ttb));
1280
1281 netlink_parse_rtattr_flags(ttb, VXLAN_VNIFILTER_ENTRY_MAX,
1282 RTA_DATA(attr), RTA_PAYLOAD(attr),
1283 NLA_F_NESTED);
1284
1285 if (ttb[VXLAN_VNIFILTER_ENTRY_START])
1286 vni_start =
1287 *(uint32_t *)RTA_DATA(ttb[VXLAN_VNIFILTER_ENTRY_START]);
1288
1289 if (ttb[VXLAN_VNIFILTER_ENTRY_END])
1290 vni_end = *(uint32_t *)RTA_DATA(ttb[VXLAN_VNIFILTER_ENTRY_END]);
1291 zlog_debug(" vni_start %u, vni_end %u", vni_start, vni_end);
1292
1293 attr = RTA_NEXT(attr, msglen);
1294 goto next_attr;
1295}
1296
c30c6070
DS
1297static const char *lwt_type2str(uint16_t type)
1298{
1299 switch (type) {
1300 case LWTUNNEL_ENCAP_NONE:
1301 return "NONE";
1302 case LWTUNNEL_ENCAP_MPLS:
1303 return "MPLS";
1304 case LWTUNNEL_ENCAP_IP:
1305 return "IPv4";
1306 case LWTUNNEL_ENCAP_ILA:
1307 return "ILA";
1308 case LWTUNNEL_ENCAP_IP6:
1309 return "IPv6";
1310 case LWTUNNEL_ENCAP_SEG6:
1311 return "SEG6";
1312 case LWTUNNEL_ENCAP_BPF:
1313 return "BPF";
1314 case LWTUNNEL_ENCAP_SEG6_LOCAL:
1315 return "SEG6_LOCAL";
1316 default:
1317 return "UNKNOWN";
1318 }
1319}
1320
1321static const char *nhg_type2str(uint16_t type)
1322{
1323 switch (type) {
1324 case NEXTHOP_GRP_TYPE_MPATH:
1325 return "MULTIPATH";
1326 case NEXTHOP_GRP_TYPE_RES:
1327 return "RESILIENT MULTIPATH";
1328 default:
1329 return "UNKNOWN";
1330 }
1331}
1332
eead0bc4
RZ
1333static void nlnh_dump(struct nhmsg *nhm, size_t msglen)
1334{
1335 struct rtattr *rta;
1336 int ifindex;
1337 size_t plen;
1338 uint16_t u16v;
1339 uint32_t u32v;
1340 unsigned long count, i;
1341 struct nexthop_grp *nhgrp;
5d414138 1342 unsigned short rta_type;
eead0bc4
RZ
1343
1344 rta = RTM_NHA(nhm);
777f9650 1345
eead0bc4
RZ
1346next_rta:
1347 /* Check the header for valid length and for outbound access. */
1348 if (RTA_OK(rta, msglen) == 0)
1349 return;
1350
1351 plen = RTA_PAYLOAD(rta);
5d414138 1352 rta_type = rta->rta_type & ~NLA_F_NESTED;
eead0bc4 1353 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
5d414138
SW
1354 plen, rta->rta_type, nhm_rta2str(rta_type));
1355 switch (rta_type) {
eead0bc4
RZ
1356 case NHA_ID:
1357 u32v = *(uint32_t *)RTA_DATA(rta);
1358 zlog_debug(" %u", u32v);
1359 break;
1360 case NHA_GROUP:
1361 nhgrp = (struct nexthop_grp *)RTA_DATA(rta);
1362 count = (RTA_PAYLOAD(rta) / sizeof(*nhgrp));
1363 if (count == 0
1364 || (count * sizeof(*nhgrp)) != RTA_PAYLOAD(rta)) {
1365 zlog_debug(" invalid nexthop group received");
1366 return;
1367 }
1368
1369 for (i = 0; i < count; i++)
1370 zlog_debug(" id %d weight %d", nhgrp[i].id,
1371 nhgrp[i].weight);
1372 break;
1373 case NHA_ENCAP_TYPE:
c30c6070
DS
1374 u16v = *(uint16_t *)RTA_DATA(rta);
1375 zlog_debug(" %s", lwt_type2str(u16v));
1376 break;
eead0bc4
RZ
1377 case NHA_GROUP_TYPE:
1378 u16v = *(uint16_t *)RTA_DATA(rta);
c30c6070 1379 zlog_debug(" %s", nhg_type2str(u16v));
eead0bc4
RZ
1380 break;
1381 case NHA_BLACKHOLE:
1382 /* NOTHING */
1383 break;
1384 case NHA_OIF:
1385 ifindex = *(int *)RTA_DATA(rta);
1386 zlog_debug(" %d", ifindex);
1387 break;
1388 case NHA_GATEWAY:
1389 switch (nhm->nh_family) {
1390 case AF_INET:
1391 zlog_debug(" %pI4",
1392 (struct in_addr *)RTA_DATA(rta));
1393 break;
1394 case AF_INET6:
1395 zlog_debug(" %pI6",
1396 (struct in6_addr *)RTA_DATA(rta));
1397 break;
1398
1399 default:
1400 zlog_debug(" invalid family %d", nhm->nh_family);
1401 break;
1402 }
1403 break;
1404 case NHA_ENCAP:
1405 /* TODO: handle MPLS labels. */
1406 zlog_debug(" unparsed MPLS labels");
1407 break;
1408 case NHA_GROUPS:
1409 /* TODO: handle this message. */
1410 zlog_debug(" unparsed GROUPS message");
1411 break;
1412
1413 default:
1414 /* NOTHING: unhandled. */
1415 break;
1416 }
1417
1418 /* Get next pointer and start iteration again. */
1419 rta = RTA_NEXT(rta, msglen);
1420 goto next_rta;
1421}
1422
95fe3288
TA
1423static void nlrule_dump(struct fib_rule_hdr *frh, size_t msglen)
1424{
1425 struct rtattr *rta;
1426 size_t plen;
1427 uint8_t u8v;
1428 uint32_t u32v;
1429 int32_t s32v;
1430 uint64_t u64v;
1431 char dbuf[128];
1432 struct fib_rule_uid_range *u_range;
1433 struct fib_rule_port_range *p_range;
1434
1435 /* Get the first attribute and go from there. */
1436 rta = RTM_RTA(frh);
1437next_rta:
1438 /* Check the header for valid length and for outbound access. */
1439 if (RTA_OK(rta, msglen) == 0)
1440 return;
1441
1442 plen = RTA_PAYLOAD(rta);
1443 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
1444 plen, rta->rta_type, frh_rta2str(rta->rta_type));
1445 switch (rta->rta_type) {
1446 case FRA_DST:
1447 case FRA_SRC:
1448 switch (plen) {
1449 case sizeof(struct in_addr):
1450 zlog_debug(" %pI4",
1451 (struct in_addr *)RTA_DATA(rta));
1452 break;
1453 case sizeof(struct in6_addr):
1454 zlog_debug(" %pI6",
1455 (struct in6_addr *)RTA_DATA(rta));
1456 break;
1457 default:
1458 break;
1459 }
1460 break;
1461
1462 case FRA_IIFNAME:
1463 case FRA_OIFNAME:
1464 snprintf(dbuf, sizeof(dbuf), "%s", (char *)RTA_DATA(rta));
1465 zlog_debug(" %s", dbuf);
1466 break;
1467
1468 case FRA_GOTO:
1469 case FRA_UNUSED2:
1470 case FRA_PRIORITY:
1471 case FRA_UNUSED3:
1472 case FRA_UNUSED4:
1473 case FRA_UNUSED5:
1474 case FRA_FWMARK:
1475 case FRA_FLOW:
1476 case FRA_TABLE:
1477 case FRA_FWMASK:
1478 u32v = *(uint32_t *)RTA_DATA(rta);
1479 zlog_debug(" %u", u32v);
1480 break;
1481
1482 case FRA_SUPPRESS_IFGROUP:
1483 case FRA_SUPPRESS_PREFIXLEN:
1484 s32v = *(int32_t *)RTA_DATA(rta);
1485 zlog_debug(" %d", s32v);
1486 break;
1487
1488 case FRA_TUN_ID:
1489 u64v = *(uint64_t *)RTA_DATA(rta);
1490 zlog_debug(" %" PRIu64, u64v);
1491 break;
1492
1493 case FRA_L3MDEV:
1494 case FRA_PROTOCOL:
1495 case FRA_IP_PROTO:
1496 u8v = *(uint8_t *)RTA_DATA(rta);
1497 zlog_debug(" %u", u8v);
1498 break;
1499
1500 case FRA_UID_RANGE:
1501 u_range = (struct fib_rule_uid_range *)RTA_DATA(rta);
1502 if (u_range->start == u_range->end)
1503 zlog_debug(" %u", u_range->start);
1504 else
1505 zlog_debug(" %u-%u", u_range->start, u_range->end);
1506 break;
1507
1508 case FRA_SPORT_RANGE:
1509 case FRA_DPORT_RANGE:
1510 p_range = (struct fib_rule_port_range *)RTA_DATA(rta);
1511 if (p_range->start == p_range->end)
1512 zlog_debug(" %u", p_range->start);
1513 else
1514 zlog_debug(" %u-%u", p_range->start, p_range->end);
1515 break;
1516
1517 case FRA_PAD: /* fallthrough */
1518 default:
1519 /* NOTHING: unhandled. */
1520 break;
1521 }
1522
1523 /* Get next pointer and start iteration again. */
1524 rta = RTA_NEXT(rta, msglen);
1525 goto next_rta;
1526}
1527
449a30ed
SY
1528static const char *tcm_nltype2str(int nltype)
1529{
1530 switch (nltype) {
1531 case RTM_NEWQDISC:
1532 case RTM_DELQDISC:
1533 return "qdisc";
1534 case RTM_NEWTCLASS:
1535 case RTM_DELTCLASS:
1536 return "tclass";
1537 case RTM_NEWTFILTER:
1538 case RTM_DELTFILTER:
1539 return "tfilter";
1540 default:
1541 /* should never hit */
1542 return "unknown";
1543 }
1544}
1545
777f9650
MS
1546static void nlncm_dump(const struct netconfmsg *ncm, size_t msglen)
1547{
1548 const struct rtattr *rta;
1549 size_t plen;
1550 uint32_t ival;
1551
1552 rta = (void *)((const char *)ncm +
1553 NLMSG_ALIGN(sizeof(struct netconfmsg)));
1554
1555next_rta:
1556 /* Check the attr header for valid length. */
1557 if (RTA_OK(rta, msglen) == 0)
1558 return;
1559
1560 plen = RTA_PAYLOAD(rta);
1561
1562 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
1563 plen, rta->rta_type, ncm_rta2str(rta->rta_type));
1564
1565 switch (rta->rta_type) {
1566 case NETCONFA_IFINDEX:
1567 ival = *(uint32_t *)RTA_DATA(rta);
1568 zlog_debug(" %d", (int32_t)ival);
1569 break;
1570
1571 /* Most attrs are just on/off. */
1572 case NETCONFA_FORWARDING:
1573 case NETCONFA_RP_FILTER:
1574 case NETCONFA_MC_FORWARDING:
1575 case NETCONFA_PROXY_NEIGH:
1576 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN:
1577 case NETCONFA_INPUT:
1578 case NETCONFA_BC_FORWARDING:
1579 ival = *(uint32_t *)RTA_DATA(rta);
1580 dump_on_off(ival, " ");
1581 break;
1582 default:
1583 /* NOTHING: unhandled. */
1584 break;
1585 }
1586
1587 /* Get next pointer and start iteration again. */
1588 rta = RTA_NEXT(rta, msglen);
1589 goto next_rta;
1590}
1591
eead0bc4
RZ
1592void nl_dump(void *msg, size_t msglen)
1593{
1594 struct nlmsghdr *nlmsg = msg;
1595 struct nlmsgerr *nlmsgerr;
1596 struct rtgenmsg *rtgen;
1597 struct ifaddrmsg *ifa;
1598 struct ndmsg *ndm;
1599 struct rtmsg *rtm;
1600 struct nhmsg *nhm;
777f9650 1601 struct netconfmsg *ncm;
eead0bc4 1602 struct ifinfomsg *ifi;
42ed3bd7 1603 struct tunnel_msg *tnlm;
95fe3288 1604 struct fib_rule_hdr *frh;
449a30ed
SY
1605 struct tcmsg *tcm;
1606
eead0bc4
RZ
1607 char fbuf[128];
1608 char ibuf[128];
1609
1610next_header:
1611 zlog_debug(
1612 "nlmsghdr [len=%u type=(%d) %s flags=(0x%04x) {%s} seq=%u pid=%u]",
1613 nlmsg->nlmsg_len, nlmsg->nlmsg_type,
1614 nlmsg_type2str(nlmsg->nlmsg_type), nlmsg->nlmsg_flags,
1615 nlmsg_flags2str(nlmsg->nlmsg_flags, fbuf, sizeof(fbuf)),
1616 nlmsg->nlmsg_seq, nlmsg->nlmsg_pid);
1617
1618 switch (nlmsg->nlmsg_type) {
1619 /* Generic. */
1620 case NLMSG_NOOP:
1621 break;
1622 case NLMSG_ERROR:
1623 nlmsgerr = NLMSG_DATA(nlmsg);
1624 zlog_debug(" nlmsgerr [error=(%d) %s]", nlmsgerr->error,
1625 strerror(-nlmsgerr->error));
1626 break;
1627 case NLMSG_DONE:
1628 return;
1629 case NLMSG_OVERRUN:
1630 break;
1631
1632 /* RTM. */
1633 case RTM_NEWLINK:
1634 case RTM_DELLINK:
1635 case RTM_SETLINK:
1636 ifi = NLMSG_DATA(nlmsg);
1637 zlog_debug(
e54cd978 1638 " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]",
eead0bc4
RZ
1639 ifi->ifi_family, ifi->ifi_type,
1640 ifi_type2str(ifi->ifi_type), ifi->ifi_index,
1641 ifi->ifi_flags,
1642 if_flags2str(ifi->ifi_flags, ibuf, sizeof(ibuf)));
1643 nllink_dump(ifi, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
1644 break;
1645 case RTM_GETLINK:
1646 rtgen = NLMSG_DATA(nlmsg);
1647 zlog_debug(" rtgen [family=(%d) %s]", rtgen->rtgen_family,
1648 af_type2str(rtgen->rtgen_family));
1649 break;
1650
1651 case RTM_NEWROUTE:
1652 case RTM_DELROUTE:
1653 case RTM_GETROUTE:
1654 rtm = NLMSG_DATA(nlmsg);
1655 zlog_debug(
e54cd978 1656 " rtmsg [family=(%d) %s dstlen=%d srclen=%d tos=%d table=%d protocol=(%d) %s scope=(%d) %s type=(%d) %s flags=0x%04x {%s}]",
eead0bc4
RZ
1657 rtm->rtm_family, af_type2str(rtm->rtm_family),
1658 rtm->rtm_dst_len, rtm->rtm_src_len, rtm->rtm_tos,
1659 rtm->rtm_table, rtm->rtm_protocol,
1660 rtm_protocol2str(rtm->rtm_protocol), rtm->rtm_scope,
1661 rtm_scope2str(rtm->rtm_scope), rtm->rtm_type,
1662 rtm_type2str(rtm->rtm_type), rtm->rtm_flags,
1663 rtm_flags2str(rtm->rtm_flags, fbuf, sizeof(fbuf)));
1664 nlroute_dump(rtm,
1665 nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*rtm)));
1666 break;
1667
1668 case RTM_NEWNEIGH:
1669 case RTM_DELNEIGH:
1670 ndm = NLMSG_DATA(nlmsg);
1671 zlog_debug(
e54cd978 1672 " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]",
eead0bc4
RZ
1673 ndm->ndm_family, af_type2str(ndm->ndm_family),
1674 ndm->ndm_ifindex, ndm->ndm_state,
1675 neigh_state2str(ndm->ndm_state, ibuf, sizeof(ibuf)),
1676 ndm->ndm_flags,
1677 neigh_flags2str(ndm->ndm_flags, fbuf, sizeof(fbuf)),
1678 ndm->ndm_type, rtm_type2str(ndm->ndm_type));
1679 nlneigh_dump(ndm,
1680 nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ndm)));
1681 break;
1682
95fe3288
TA
1683 case RTM_NEWRULE:
1684 case RTM_DELRULE:
1685 frh = NLMSG_DATA(nlmsg);
1686 zlog_debug(
e54cd978 1687 " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]",
95fe3288
TA
1688 frh->family, af_type2str(frh->family), frh->dst_len,
1689 frh->src_len, frh->tos, frh->table, frh->res1,
1690 frh->res2, frh->action, frh_action2str(frh->action),
1691 frh->flags);
1692 nlrule_dump(frh, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*frh)));
1693 break;
1694
1695
eead0bc4
RZ
1696 case RTM_NEWADDR:
1697 case RTM_DELADDR:
1698 ifa = NLMSG_DATA(nlmsg);
1699 zlog_debug(
e54cd978 1700 " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]",
eead0bc4
RZ
1701 ifa->ifa_family, af_type2str(ifa->ifa_family),
1702 ifa->ifa_prefixlen, ifa->ifa_flags,
1703 if_flags2str(ifa->ifa_flags, fbuf, sizeof(fbuf)),
1704 ifa->ifa_scope, ifa->ifa_index);
1705 nlifa_dump(ifa, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
1706 break;
1707
1708 case RTM_NEWNEXTHOP:
1709 case RTM_DELNEXTHOP:
1710 case RTM_GETNEXTHOP:
1711 nhm = NLMSG_DATA(nlmsg);
1712 zlog_debug(
e54cd978 1713 " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]",
eead0bc4
RZ
1714 nhm->nh_family, af_type2str(nhm->nh_family),
1715 nhm->nh_scope, rtm_scope2str(nhm->nh_scope),
1716 nhm->nh_protocol, rtm_protocol2str(nhm->nh_protocol),
1717 nhm->nh_flags,
1718 nh_flags2str(nhm->nh_flags, fbuf, sizeof(fbuf)));
1719 nlnh_dump(nhm, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*nhm)));
1720 break;
1721
42ed3bd7
CS
1722 case RTM_NEWTUNNEL:
1723 case RTM_DELTUNNEL:
1724 case RTM_GETTUNNEL:
1725 tnlm = NLMSG_DATA(nlmsg);
1726 zlog_debug(" tnlm [family=(%d) %s ifindex=%d ", tnlm->family,
1727 af_type2str(tnlm->family), tnlm->ifindex);
1728 nltnl_dump(tnlm,
1729 nlmsg->nlmsg_len -
1730 NLMSG_LENGTH(sizeof(struct tunnel_msg)));
1731 break;
1732
1733
777f9650
MS
1734 case RTM_NEWNETCONF:
1735 case RTM_DELNETCONF:
1736 ncm = NLMSG_DATA(nlmsg);
1737 zlog_debug(" ncm [family=%s (%d)]",
1738 af_type2str(ncm->ncm_family), ncm->ncm_family);
1739 nlncm_dump(ncm, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ncm)));
1740 break;
1741
449a30ed
SY
1742 case RTM_NEWQDISC:
1743 case RTM_DELQDISC:
1744 case RTM_NEWTCLASS:
1745 case RTM_DELTCLASS:
1746 case RTM_NEWTFILTER:
1747 case RTM_DELTFILTER:
1748 tcm = NLMSG_DATA(nlmsg);
1749 zlog_debug(
1750 " tcm [type=%s family=%s (%d) ifindex=%d handle=%04x:%04x]",
1751 tcm_nltype2str(nlmsg->nlmsg_type),
1752 af_type2str(tcm->tcm_family), tcm->tcm_family,
1753 tcm->tcm_ifindex, tcm->tcm_handle >> 16,
1754 tcm->tcm_handle & 0xffff);
1755 break;
1756
eead0bc4
RZ
1757 default:
1758 break;
1759 }
1760
1761 /*
1762 * Try to get the next header. There should only be more
1763 * messages if this header was flagged as MULTI, otherwise just
1764 * end it here.
1765 */
1766 nlmsg = NLMSG_NEXT(nlmsg, msglen);
1767 if (NLMSG_OK(nlmsg, msglen) == 0)
1768 return;
1769
1770 goto next_header;
1771}
1772
1773#endif /* NETLINK_DEBUG */