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