]> git.proxmox.com Git - mirror_frr.git/blob - zebra/debug_nl.c
Merge pull request #11175 from louis-6wind/ip-vrf-exec
[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, rtm_rta2str(rta->rta_type));
1087 switch (rta->rta_type) {
1088 case RTA_IIF:
1089 case RTA_OIF:
1090 case RTA_PRIORITY:
1091 case RTA_TABLE:
1092 case RTA_NH_ID:
1093 u32v = *(uint32_t *)RTA_DATA(rta);
1094 zlog_debug(" %u", u32v);
1095 break;
1096
1097 case RTA_GATEWAY:
1098 case RTA_DST:
1099 case RTA_SRC:
1100 case RTA_PREFSRC:
1101 switch (plen) {
1102 case sizeof(struct in_addr):
1103 zlog_debug(" %pI4",
1104 (struct in_addr *)RTA_DATA(rta));
1105 break;
1106 case sizeof(struct in6_addr):
1107 zlog_debug(" %pI6",
1108 (struct in6_addr *)RTA_DATA(rta));
1109 break;
1110 default:
1111 break;
1112 }
1113 break;
1114
1115 default:
1116 /* NOTHING: unhandled. */
1117 break;
1118 }
1119
1120 /* Get next pointer and start iteration again. */
1121 rta = RTA_NEXT(rta, msglen);
1122 goto next_rta;
1123 }
1124
1125 static void nlneigh_dump(struct ndmsg *ndm, size_t msglen)
1126 {
1127 struct rtattr *rta;
1128 uint8_t *datap;
1129 size_t plen, it;
1130 uint16_t vid;
1131 char bytestr[16];
1132 char dbuf[128];
1133 unsigned short rta_type;
1134
1135 #ifndef NDA_RTA
1136 #define NDA_RTA(ndm) \
1137 /* struct ndmsg *ndm; */ \
1138 ((struct rtattr *)(((uint8_t *)(ndm)) \
1139 + NLMSG_ALIGN(sizeof(struct ndmsg))))
1140 #endif /* NDA_RTA */
1141
1142 /* Get the first attribute and go from there. */
1143 rta = NDA_RTA(ndm);
1144 next_rta:
1145 /* Check the header for valid length and for outbound access. */
1146 if (RTA_OK(rta, msglen) == 0)
1147 return;
1148
1149 plen = RTA_PAYLOAD(rta);
1150 rta_type = rta->rta_type & ~NLA_F_NESTED;
1151 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
1152 plen, rta->rta_type, neigh_rta2str(rta_type));
1153 switch (rta_type) {
1154 case NDA_LLADDR:
1155 datap = RTA_DATA(rta);
1156 dbuf[0] = 0;
1157 for (it = 0; it < plen; it++) {
1158 snprintf(bytestr, sizeof(bytestr), "%02X:", *datap);
1159 strlcat(dbuf, bytestr, sizeof(dbuf));
1160 datap++;
1161 }
1162 /* Remove trailing ':'. */
1163 if (dbuf[0])
1164 dbuf[strlen(dbuf) - 1] = 0;
1165
1166 zlog_debug(" %s", dbuf[0] ? dbuf : "<empty>");
1167 break;
1168
1169 case NDA_DST:
1170 switch (plen) {
1171 case sizeof(struct in_addr):
1172 zlog_debug(" %pI4",
1173 (struct in_addr *)RTA_DATA(rta));
1174 break;
1175 case sizeof(struct in6_addr):
1176 zlog_debug(" %pI6",
1177 (struct in6_addr *)RTA_DATA(rta));
1178 break;
1179 default:
1180 break;
1181 }
1182 break;
1183
1184 case NDA_VLAN:
1185 vid = *(uint16_t *)RTA_DATA(rta);
1186 zlog_debug(" %d", vid);
1187 break;
1188
1189 default:
1190 /* NOTHING: unhandled. */
1191 break;
1192 }
1193
1194 /* Get next pointer and start iteration again. */
1195 rta = RTA_NEXT(rta, msglen);
1196 goto next_rta;
1197 }
1198
1199 static void nlifa_dump(struct ifaddrmsg *ifa, size_t msglen)
1200 {
1201 struct rtattr *rta;
1202 size_t plen;
1203 uint32_t u32v;
1204
1205 /* Get the first attribute and go from there. */
1206 rta = IFA_RTA(ifa);
1207 next_rta:
1208 /* Check the header for valid length and for outbound access. */
1209 if (RTA_OK(rta, msglen) == 0)
1210 return;
1211
1212 plen = RTA_PAYLOAD(rta);
1213 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
1214 plen, rta->rta_type, ifa_rta2str(rta->rta_type));
1215 switch (rta->rta_type) {
1216 case IFA_UNSPEC:
1217 u32v = *(uint32_t *)RTA_DATA(rta);
1218 zlog_debug(" %u", u32v);
1219 break;
1220
1221 case IFA_LABEL:
1222 zlog_debug(" %s", (const char *)RTA_DATA(rta));
1223 break;
1224
1225 case IFA_ADDRESS:
1226 case IFA_LOCAL:
1227 case IFA_BROADCAST:
1228 switch (plen) {
1229 case 4:
1230 zlog_debug(" %pI4",
1231 (struct in_addr *)RTA_DATA(rta));
1232 break;
1233 case 16:
1234 zlog_debug(" %pI6",
1235 (struct in6_addr *)RTA_DATA(rta));
1236 break;
1237 default:
1238 break;
1239 }
1240 break;
1241
1242 default:
1243 /* NOTHING: unhandled. */
1244 break;
1245 }
1246
1247 /* Get next pointer and start iteration again. */
1248 rta = RTA_NEXT(rta, msglen);
1249 goto next_rta;
1250 }
1251
1252 static void nltnl_dump(struct tunnel_msg *tnlm, size_t msglen)
1253 {
1254 struct rtattr *attr;
1255 vni_t vni_start = 0, vni_end = 0;
1256 struct rtattr *ttb[VXLAN_VNIFILTER_ENTRY_MAX + 1];
1257 uint8_t rta_type;
1258
1259 attr = TUNNEL_RTA(tnlm);
1260 next_attr:
1261 /* Check the header for valid length and for outbound access. */
1262 if (RTA_OK(attr, msglen) == 0)
1263 return;
1264
1265 rta_type = attr->rta_type & NLA_TYPE_MASK;
1266
1267 if (rta_type != VXLAN_VNIFILTER_ENTRY) {
1268 attr = RTA_NEXT(attr, msglen);
1269 goto next_attr;
1270 }
1271
1272 memset(ttb, 0, sizeof(ttb));
1273
1274 netlink_parse_rtattr_flags(ttb, VXLAN_VNIFILTER_ENTRY_MAX,
1275 RTA_DATA(attr), RTA_PAYLOAD(attr),
1276 NLA_F_NESTED);
1277
1278 if (ttb[VXLAN_VNIFILTER_ENTRY_START])
1279 vni_start =
1280 *(uint32_t *)RTA_DATA(ttb[VXLAN_VNIFILTER_ENTRY_START]);
1281
1282 if (ttb[VXLAN_VNIFILTER_ENTRY_END])
1283 vni_end = *(uint32_t *)RTA_DATA(ttb[VXLAN_VNIFILTER_ENTRY_END]);
1284 zlog_debug(" vni_start %u, vni_end %u", vni_start, vni_end);
1285
1286 attr = RTA_NEXT(attr, msglen);
1287 goto next_attr;
1288 }
1289
1290 static const char *lwt_type2str(uint16_t type)
1291 {
1292 switch (type) {
1293 case LWTUNNEL_ENCAP_NONE:
1294 return "NONE";
1295 case LWTUNNEL_ENCAP_MPLS:
1296 return "MPLS";
1297 case LWTUNNEL_ENCAP_IP:
1298 return "IPv4";
1299 case LWTUNNEL_ENCAP_ILA:
1300 return "ILA";
1301 case LWTUNNEL_ENCAP_IP6:
1302 return "IPv6";
1303 case LWTUNNEL_ENCAP_SEG6:
1304 return "SEG6";
1305 case LWTUNNEL_ENCAP_BPF:
1306 return "BPF";
1307 case LWTUNNEL_ENCAP_SEG6_LOCAL:
1308 return "SEG6_LOCAL";
1309 default:
1310 return "UNKNOWN";
1311 }
1312 }
1313
1314 static const char *nhg_type2str(uint16_t type)
1315 {
1316 switch (type) {
1317 case NEXTHOP_GRP_TYPE_MPATH:
1318 return "MULTIPATH";
1319 case NEXTHOP_GRP_TYPE_RES:
1320 return "RESILIENT MULTIPATH";
1321 default:
1322 return "UNKNOWN";
1323 }
1324 }
1325
1326 static void nlnh_dump(struct nhmsg *nhm, size_t msglen)
1327 {
1328 struct rtattr *rta;
1329 int ifindex;
1330 size_t plen;
1331 uint16_t u16v;
1332 uint32_t u32v;
1333 unsigned long count, i;
1334 struct nexthop_grp *nhgrp;
1335 unsigned short rta_type;
1336
1337 rta = RTM_NHA(nhm);
1338
1339 next_rta:
1340 /* Check the header for valid length and for outbound access. */
1341 if (RTA_OK(rta, msglen) == 0)
1342 return;
1343
1344 plen = RTA_PAYLOAD(rta);
1345 rta_type = rta->rta_type & ~NLA_F_NESTED;
1346 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
1347 plen, rta->rta_type, nhm_rta2str(rta_type));
1348 switch (rta_type) {
1349 case NHA_ID:
1350 u32v = *(uint32_t *)RTA_DATA(rta);
1351 zlog_debug(" %u", u32v);
1352 break;
1353 case NHA_GROUP:
1354 nhgrp = (struct nexthop_grp *)RTA_DATA(rta);
1355 count = (RTA_PAYLOAD(rta) / sizeof(*nhgrp));
1356 if (count == 0
1357 || (count * sizeof(*nhgrp)) != RTA_PAYLOAD(rta)) {
1358 zlog_debug(" invalid nexthop group received");
1359 return;
1360 }
1361
1362 for (i = 0; i < count; i++)
1363 zlog_debug(" id %d weight %d", nhgrp[i].id,
1364 nhgrp[i].weight);
1365 break;
1366 case NHA_ENCAP_TYPE:
1367 u16v = *(uint16_t *)RTA_DATA(rta);
1368 zlog_debug(" %s", lwt_type2str(u16v));
1369 break;
1370 case NHA_GROUP_TYPE:
1371 u16v = *(uint16_t *)RTA_DATA(rta);
1372 zlog_debug(" %s", nhg_type2str(u16v));
1373 break;
1374 case NHA_BLACKHOLE:
1375 /* NOTHING */
1376 break;
1377 case NHA_OIF:
1378 ifindex = *(int *)RTA_DATA(rta);
1379 zlog_debug(" %d", ifindex);
1380 break;
1381 case NHA_GATEWAY:
1382 switch (nhm->nh_family) {
1383 case AF_INET:
1384 zlog_debug(" %pI4",
1385 (struct in_addr *)RTA_DATA(rta));
1386 break;
1387 case AF_INET6:
1388 zlog_debug(" %pI6",
1389 (struct in6_addr *)RTA_DATA(rta));
1390 break;
1391
1392 default:
1393 zlog_debug(" invalid family %d", nhm->nh_family);
1394 break;
1395 }
1396 break;
1397 case NHA_ENCAP:
1398 /* TODO: handle MPLS labels. */
1399 zlog_debug(" unparsed MPLS labels");
1400 break;
1401 case NHA_GROUPS:
1402 /* TODO: handle this message. */
1403 zlog_debug(" unparsed GROUPS message");
1404 break;
1405
1406 default:
1407 /* NOTHING: unhandled. */
1408 break;
1409 }
1410
1411 /* Get next pointer and start iteration again. */
1412 rta = RTA_NEXT(rta, msglen);
1413 goto next_rta;
1414 }
1415
1416 static void nlrule_dump(struct fib_rule_hdr *frh, size_t msglen)
1417 {
1418 struct rtattr *rta;
1419 size_t plen;
1420 uint8_t u8v;
1421 uint32_t u32v;
1422 int32_t s32v;
1423 uint64_t u64v;
1424 char dbuf[128];
1425 struct fib_rule_uid_range *u_range;
1426 struct fib_rule_port_range *p_range;
1427
1428 /* Get the first attribute and go from there. */
1429 rta = RTM_RTA(frh);
1430 next_rta:
1431 /* Check the header for valid length and for outbound access. */
1432 if (RTA_OK(rta, msglen) == 0)
1433 return;
1434
1435 plen = RTA_PAYLOAD(rta);
1436 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
1437 plen, rta->rta_type, frh_rta2str(rta->rta_type));
1438 switch (rta->rta_type) {
1439 case FRA_DST:
1440 case FRA_SRC:
1441 switch (plen) {
1442 case sizeof(struct in_addr):
1443 zlog_debug(" %pI4",
1444 (struct in_addr *)RTA_DATA(rta));
1445 break;
1446 case sizeof(struct in6_addr):
1447 zlog_debug(" %pI6",
1448 (struct in6_addr *)RTA_DATA(rta));
1449 break;
1450 default:
1451 break;
1452 }
1453 break;
1454
1455 case FRA_IIFNAME:
1456 case FRA_OIFNAME:
1457 snprintf(dbuf, sizeof(dbuf), "%s", (char *)RTA_DATA(rta));
1458 zlog_debug(" %s", dbuf);
1459 break;
1460
1461 case FRA_GOTO:
1462 case FRA_UNUSED2:
1463 case FRA_PRIORITY:
1464 case FRA_UNUSED3:
1465 case FRA_UNUSED4:
1466 case FRA_UNUSED5:
1467 case FRA_FWMARK:
1468 case FRA_FLOW:
1469 case FRA_TABLE:
1470 case FRA_FWMASK:
1471 u32v = *(uint32_t *)RTA_DATA(rta);
1472 zlog_debug(" %u", u32v);
1473 break;
1474
1475 case FRA_SUPPRESS_IFGROUP:
1476 case FRA_SUPPRESS_PREFIXLEN:
1477 s32v = *(int32_t *)RTA_DATA(rta);
1478 zlog_debug(" %d", s32v);
1479 break;
1480
1481 case FRA_TUN_ID:
1482 u64v = *(uint64_t *)RTA_DATA(rta);
1483 zlog_debug(" %" PRIu64, u64v);
1484 break;
1485
1486 case FRA_L3MDEV:
1487 case FRA_PROTOCOL:
1488 case FRA_IP_PROTO:
1489 u8v = *(uint8_t *)RTA_DATA(rta);
1490 zlog_debug(" %u", u8v);
1491 break;
1492
1493 case FRA_UID_RANGE:
1494 u_range = (struct fib_rule_uid_range *)RTA_DATA(rta);
1495 if (u_range->start == u_range->end)
1496 zlog_debug(" %u", u_range->start);
1497 else
1498 zlog_debug(" %u-%u", u_range->start, u_range->end);
1499 break;
1500
1501 case FRA_SPORT_RANGE:
1502 case FRA_DPORT_RANGE:
1503 p_range = (struct fib_rule_port_range *)RTA_DATA(rta);
1504 if (p_range->start == p_range->end)
1505 zlog_debug(" %u", p_range->start);
1506 else
1507 zlog_debug(" %u-%u", p_range->start, p_range->end);
1508 break;
1509
1510 case FRA_PAD: /* fallthrough */
1511 default:
1512 /* NOTHING: unhandled. */
1513 break;
1514 }
1515
1516 /* Get next pointer and start iteration again. */
1517 rta = RTA_NEXT(rta, msglen);
1518 goto next_rta;
1519 }
1520
1521 static void nlncm_dump(const struct netconfmsg *ncm, size_t msglen)
1522 {
1523 const struct rtattr *rta;
1524 size_t plen;
1525 uint32_t ival;
1526
1527 rta = (void *)((const char *)ncm +
1528 NLMSG_ALIGN(sizeof(struct netconfmsg)));
1529
1530 next_rta:
1531 /* Check the attr header for valid length. */
1532 if (RTA_OK(rta, msglen) == 0)
1533 return;
1534
1535 plen = RTA_PAYLOAD(rta);
1536
1537 zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
1538 plen, rta->rta_type, ncm_rta2str(rta->rta_type));
1539
1540 switch (rta->rta_type) {
1541 case NETCONFA_IFINDEX:
1542 ival = *(uint32_t *)RTA_DATA(rta);
1543 zlog_debug(" %d", (int32_t)ival);
1544 break;
1545
1546 /* Most attrs are just on/off. */
1547 case NETCONFA_FORWARDING:
1548 case NETCONFA_RP_FILTER:
1549 case NETCONFA_MC_FORWARDING:
1550 case NETCONFA_PROXY_NEIGH:
1551 case NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN:
1552 case NETCONFA_INPUT:
1553 case NETCONFA_BC_FORWARDING:
1554 ival = *(uint32_t *)RTA_DATA(rta);
1555 dump_on_off(ival, " ");
1556 break;
1557 default:
1558 /* NOTHING: unhandled. */
1559 break;
1560 }
1561
1562 /* Get next pointer and start iteration again. */
1563 rta = RTA_NEXT(rta, msglen);
1564 goto next_rta;
1565 }
1566
1567 void nl_dump(void *msg, size_t msglen)
1568 {
1569 struct nlmsghdr *nlmsg = msg;
1570 struct nlmsgerr *nlmsgerr;
1571 struct rtgenmsg *rtgen;
1572 struct ifaddrmsg *ifa;
1573 struct ndmsg *ndm;
1574 struct rtmsg *rtm;
1575 struct nhmsg *nhm;
1576 struct netconfmsg *ncm;
1577 struct ifinfomsg *ifi;
1578 struct tunnel_msg *tnlm;
1579 struct fib_rule_hdr *frh;
1580 char fbuf[128];
1581 char ibuf[128];
1582
1583 next_header:
1584 zlog_debug(
1585 "nlmsghdr [len=%u type=(%d) %s flags=(0x%04x) {%s} seq=%u pid=%u]",
1586 nlmsg->nlmsg_len, nlmsg->nlmsg_type,
1587 nlmsg_type2str(nlmsg->nlmsg_type), nlmsg->nlmsg_flags,
1588 nlmsg_flags2str(nlmsg->nlmsg_flags, fbuf, sizeof(fbuf)),
1589 nlmsg->nlmsg_seq, nlmsg->nlmsg_pid);
1590
1591 switch (nlmsg->nlmsg_type) {
1592 /* Generic. */
1593 case NLMSG_NOOP:
1594 break;
1595 case NLMSG_ERROR:
1596 nlmsgerr = NLMSG_DATA(nlmsg);
1597 zlog_debug(" nlmsgerr [error=(%d) %s]", nlmsgerr->error,
1598 strerror(-nlmsgerr->error));
1599 break;
1600 case NLMSG_DONE:
1601 return;
1602 case NLMSG_OVERRUN:
1603 break;
1604
1605 /* RTM. */
1606 case RTM_NEWLINK:
1607 case RTM_DELLINK:
1608 case RTM_SETLINK:
1609 ifi = NLMSG_DATA(nlmsg);
1610 zlog_debug(
1611 " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]",
1612 ifi->ifi_family, ifi->ifi_type,
1613 ifi_type2str(ifi->ifi_type), ifi->ifi_index,
1614 ifi->ifi_flags,
1615 if_flags2str(ifi->ifi_flags, ibuf, sizeof(ibuf)));
1616 nllink_dump(ifi, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
1617 break;
1618 case RTM_GETLINK:
1619 rtgen = NLMSG_DATA(nlmsg);
1620 zlog_debug(" rtgen [family=(%d) %s]", rtgen->rtgen_family,
1621 af_type2str(rtgen->rtgen_family));
1622 break;
1623
1624 case RTM_NEWROUTE:
1625 case RTM_DELROUTE:
1626 case RTM_GETROUTE:
1627 rtm = NLMSG_DATA(nlmsg);
1628 zlog_debug(
1629 " rtmsg [family=(%d) %s dstlen=%d srclen=%d tos=%d table=%d protocol=(%d) %s scope=(%d) %s type=(%d) %s flags=0x%04x {%s}]",
1630 rtm->rtm_family, af_type2str(rtm->rtm_family),
1631 rtm->rtm_dst_len, rtm->rtm_src_len, rtm->rtm_tos,
1632 rtm->rtm_table, rtm->rtm_protocol,
1633 rtm_protocol2str(rtm->rtm_protocol), rtm->rtm_scope,
1634 rtm_scope2str(rtm->rtm_scope), rtm->rtm_type,
1635 rtm_type2str(rtm->rtm_type), rtm->rtm_flags,
1636 rtm_flags2str(rtm->rtm_flags, fbuf, sizeof(fbuf)));
1637 nlroute_dump(rtm,
1638 nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*rtm)));
1639 break;
1640
1641 case RTM_NEWNEIGH:
1642 case RTM_DELNEIGH:
1643 ndm = NLMSG_DATA(nlmsg);
1644 zlog_debug(
1645 " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]",
1646 ndm->ndm_family, af_type2str(ndm->ndm_family),
1647 ndm->ndm_ifindex, ndm->ndm_state,
1648 neigh_state2str(ndm->ndm_state, ibuf, sizeof(ibuf)),
1649 ndm->ndm_flags,
1650 neigh_flags2str(ndm->ndm_flags, fbuf, sizeof(fbuf)),
1651 ndm->ndm_type, rtm_type2str(ndm->ndm_type));
1652 nlneigh_dump(ndm,
1653 nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ndm)));
1654 break;
1655
1656 case RTM_NEWRULE:
1657 case RTM_DELRULE:
1658 frh = NLMSG_DATA(nlmsg);
1659 zlog_debug(
1660 " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]",
1661 frh->family, af_type2str(frh->family), frh->dst_len,
1662 frh->src_len, frh->tos, frh->table, frh->res1,
1663 frh->res2, frh->action, frh_action2str(frh->action),
1664 frh->flags);
1665 nlrule_dump(frh, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*frh)));
1666 break;
1667
1668
1669 case RTM_NEWADDR:
1670 case RTM_DELADDR:
1671 ifa = NLMSG_DATA(nlmsg);
1672 zlog_debug(
1673 " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]",
1674 ifa->ifa_family, af_type2str(ifa->ifa_family),
1675 ifa->ifa_prefixlen, ifa->ifa_flags,
1676 if_flags2str(ifa->ifa_flags, fbuf, sizeof(fbuf)),
1677 ifa->ifa_scope, ifa->ifa_index);
1678 nlifa_dump(ifa, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
1679 break;
1680
1681 case RTM_NEWNEXTHOP:
1682 case RTM_DELNEXTHOP:
1683 case RTM_GETNEXTHOP:
1684 nhm = NLMSG_DATA(nlmsg);
1685 zlog_debug(
1686 " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]",
1687 nhm->nh_family, af_type2str(nhm->nh_family),
1688 nhm->nh_scope, rtm_scope2str(nhm->nh_scope),
1689 nhm->nh_protocol, rtm_protocol2str(nhm->nh_protocol),
1690 nhm->nh_flags,
1691 nh_flags2str(nhm->nh_flags, fbuf, sizeof(fbuf)));
1692 nlnh_dump(nhm, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*nhm)));
1693 break;
1694
1695 case RTM_NEWTUNNEL:
1696 case RTM_DELTUNNEL:
1697 case RTM_GETTUNNEL:
1698 tnlm = NLMSG_DATA(nlmsg);
1699 zlog_debug(" tnlm [family=(%d) %s ifindex=%d ", tnlm->family,
1700 af_type2str(tnlm->family), tnlm->ifindex);
1701 nltnl_dump(tnlm,
1702 nlmsg->nlmsg_len -
1703 NLMSG_LENGTH(sizeof(struct tunnel_msg)));
1704 break;
1705
1706
1707 case RTM_NEWNETCONF:
1708 case RTM_DELNETCONF:
1709 ncm = NLMSG_DATA(nlmsg);
1710 zlog_debug(" ncm [family=%s (%d)]",
1711 af_type2str(ncm->ncm_family), ncm->ncm_family);
1712 nlncm_dump(ncm, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ncm)));
1713 break;
1714
1715 default:
1716 break;
1717 }
1718
1719 /*
1720 * Try to get the next header. There should only be more
1721 * messages if this header was flagged as MULTI, otherwise just
1722 * end it here.
1723 */
1724 nlmsg = NLMSG_NEXT(nlmsg, msglen);
1725 if (NLMSG_OK(nlmsg, msglen) == 0)
1726 return;
1727
1728 goto next_header;
1729 }
1730
1731 #endif /* NETLINK_DEBUG */