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