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