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