flowtop: Remove unused parameters from draw_help() and draw_footer()
[netsniff-ng.git] / proto_nlmsg.c
blob6b43335f72089fc10290ccaa6995069f0c7e37f8
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2014 Tobias Klauser.
4 * Subject to the GPL, version 2.
5 */
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <limits.h>
11 #include <libgen.h>
12 #include <netlink/msg.h>
13 #include <netlink/route/link.h>
14 #include <netlink/route/addr.h>
15 #include <linux/if_arp.h>
16 #include <arpa/inet.h>
18 #include "dev.h"
19 #include "pkt_buff.h"
20 #include "proc.h"
21 #include "proto.h"
22 #include "protos.h"
23 #include "timer.h"
25 #define INFINITY 0xFFFFFFFFU
27 #define RTA_LEN(attr) ((int)RTA_PAYLOAD(attr))
28 #define RTA_INT(attr) (*(int *)RTA_DATA(attr))
29 #define RTA_UINT(attr) (*(unsigned int *)RTA_DATA(attr))
30 #define RTA_UINT8(attr) (*(uint8_t *)RTA_DATA(attr))
31 #define RTA_UINT32(attr) (*(uint32_t *)RTA_DATA(attr))
32 #define RTA_STR(attr) ((char *)RTA_DATA(attr))
34 #ifndef NDA_RTA
35 #define NDA_RTA(r) \
36 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
37 #endif
39 #ifndef NDA_PAYLOAD
40 #define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
41 #endif
43 #ifndef NLA_LENGTH
44 #define NLA_LENGTH(len) (NLA_ALIGN(sizeof(struct nlattr)) + (len))
45 #endif
47 #ifndef NLA_DATA
48 #define NLA_DATA(nla) ((void*)(((char*)(nla)) + NLA_LENGTH(0)))
49 #endif
51 #ifndef NLA_PAYLOAD
52 #define NLA_PAYLOAD(nla) ((int)((nla)->nla_len) - NLA_LENGTH(0))
53 #endif
55 #define NLA_LEN(attr) ((int)NLA_PAYLOAD(attr))
56 #define NLA_INT(attr) (*(int *)NLA_DATA(attr))
57 #define NLA_UINT(attr) (*(unsigned int *)NLA_DATA(attr))
58 #define NLA_UINT8(attr) (*(uint8_t *)NLA_DATA(attr))
59 #define NLA_UINT16(attr) (*(uint16_t *)NLA_DATA(attr))
60 #define NLA_UINT32(attr) (*(uint32_t *)NLA_DATA(attr))
61 #define NLA_STR(attr) ((char *)NLA_DATA(attr))
63 #ifndef GEN_NLA
64 #define GEN_NLA(n) ((struct nlattr*)(((char*)(n)) + GENL_HDRLEN))
65 #endif
67 #ifndef NLA_OK
68 #define NLA_OK(nla,len) \
69 ((len) >= (int)sizeof(struct nlattr) && \
70 (nla)->nla_len >= sizeof(struct nlattr) && \
71 (nla)->nla_len <= (len))
72 #endif
74 #ifndef NLA_NEXT
75 #define NLA_NEXT(nla,attrlen) \
76 ((attrlen) -= NLA_ALIGN((nla)->nla_len), \
77 (struct nlattr*)(((char*)(nla)) + NLA_ALIGN((nla)->nla_len)))
78 #endif
80 #define rta_fmt(attr, fmt, ...) \
81 tprintf("\tA: "fmt, ##__VA_ARGS__); \
82 tprintf(", Len %d\n", RTA_LEN(attr));
84 #define nla_fmt(attr, fmt, ...) \
85 tprintf("\tA: "fmt, ##__VA_ARGS__); \
86 tprintf(", Len %d\n", NLA_LEN(attr));
88 #define nla_fmt_nested(attr, fmt, ...) \
89 tprintf("[ "fmt, ##__VA_ARGS__); \
90 tprintf(", Len %d] ", NLA_LEN(attr));
92 #define nla_fmt_nested_start(attr, fmt, ...) \
93 tprintf("\t A: "fmt, ##__VA_ARGS__); \
94 tprintf(", Len %d ", NLA_LEN(attr));
96 #define nla_fmt_nested_end() tprintf("\n")
98 struct flag_name {
99 const char *name;
100 unsigned int flag;
103 static const char *flags2str(struct flag_name *tbl, unsigned int flags,
104 char *buf, int len)
106 int bits_stay = flags;
108 memset(buf, 0, len);
110 for (; tbl && tbl->name; tbl++) {
111 if (!(tbl->flag & flags))
112 continue;
114 bits_stay &= ~tbl->flag;
115 strncat(buf, tbl->name, len - strlen(buf) - 1);
117 if (bits_stay & flags)
118 strncat(buf, ",", len - strlen(buf) - 1);
121 return buf;
124 static void nlmsg_print_raw(struct nlmsghdr *hdr)
126 u32 len = hdr->nlmsg_len;
128 if (len) {
129 _ascii((uint8_t *) hdr + NLMSG_HDRLEN, len - NLMSG_HDRLEN);
130 _hex((uint8_t *) hdr + NLMSG_HDRLEN, len - NLMSG_HDRLEN);
134 static const char *nlmsg_family2str(uint16_t family)
136 switch (family) {
137 case NETLINK_ROUTE: return "routing";
138 case NETLINK_UNUSED: return "unused";
139 case NETLINK_USERSOCK: return "user-mode socket";
140 case NETLINK_FIREWALL: return "unused, formerly ip_queue";
141 /* NETLINK_INET_DIAG was renamed to NETLINK_SOCK_DIAG in Linux kernel 3.10 */
142 #if defined(NETLINK_SOCK_DIAG)
143 case NETLINK_SOCK_DIAG: return "socket monitoring";
144 #elif defined(NETLINK_INET_DIAG)
145 case NETLINK_INET_DIAG: return "INET socket monitoring";
146 #endif
147 case NETLINK_NFLOG: return "netfilter ULOG";
148 case NETLINK_XFRM: return "IPsec";
149 case NETLINK_SELINUX: return "SELinux event notification";
150 case NETLINK_ISCSI: return "Open-iSCSI";
151 case NETLINK_AUDIT: return "auditing";
152 case NETLINK_FIB_LOOKUP: return "FIB lookup";
153 case NETLINK_CONNECTOR: return "Kernel connector";
154 case NETLINK_NETFILTER: return "Netfilter";
155 case NETLINK_IP6_FW: return "unused, formerly ip6_queue";
156 case NETLINK_DNRTMSG: return "DECnet routing";
157 case NETLINK_KOBJECT_UEVENT: return "Kernel messages";
158 case NETLINK_GENERIC: return "Generic";
159 case NETLINK_SCSITRANSPORT: return "SCSI transports";
160 case NETLINK_ECRYPTFS: return "ecryptfs";
161 case NETLINK_RDMA: return "RDMA";
162 case NETLINK_CRYPTO: return "Crypto layer";
163 default: return "Unknown";
167 static const char *nlmsg_rtnl_type2str(uint16_t type)
169 switch (type) {
170 case RTM_NEWLINK: return "new link";
171 case RTM_DELLINK: return "del link";
172 case RTM_GETLINK: return "get link";
173 case RTM_SETLINK: return "set link";
175 case RTM_NEWADDR: return "new addr";
176 case RTM_DELADDR: return "del addr";
177 case RTM_GETADDR: return "get addr";
179 case RTM_NEWROUTE: return "new route";
180 case RTM_DELROUTE: return "del route";
181 case RTM_GETROUTE: return "get route";
183 case RTM_NEWNEIGH: return "new neigh";
184 case RTM_DELNEIGH: return "del neigh";
185 case RTM_GETNEIGH: return "get neigh";
187 case RTM_NEWRULE: return "new rule";
188 case RTM_DELRULE: return "del rule";
189 case RTM_GETRULE: return "get rule";
191 case RTM_NEWQDISC: return "new tc qdisc";
192 case RTM_DELQDISC: return "del tc qdisc";
193 case RTM_GETQDISC: return "get tc qdisc";
195 case RTM_NEWTCLASS: return "new tc class";
196 case RTM_DELTCLASS: return "del tc class";
197 case RTM_GETTCLASS: return "get tc class";
199 case RTM_NEWTFILTER: return "new tc filter";
200 case RTM_DELTFILTER: return "del tc filter";
201 case RTM_GETTFILTER: return "get tc filter";
203 case RTM_NEWACTION: return "new tc action";
204 case RTM_DELACTION: return "del tc action";
205 case RTM_GETACTION: return "get tc action";
207 case RTM_NEWPREFIX: return "new prefix";
209 case RTM_GETMULTICAST: return "get mcast addr";
211 case RTM_GETANYCAST: return "get anycast addr";
213 case RTM_NEWNEIGHTBL: return "new neigh table";
214 case RTM_GETNEIGHTBL: return "get neigh table";
215 case RTM_SETNEIGHTBL: return "set neigh table";
217 case RTM_NEWNDUSEROPT: return "new ndisc user option";
219 case RTM_NEWADDRLABEL: return "new addr label";
220 case RTM_DELADDRLABEL: return "del addr label";
221 case RTM_GETADDRLABEL: return "get addr label";
223 case RTM_GETDCB: return "get data-center-bridge";
224 case RTM_SETDCB: return "set data-center-bridge";
226 #if defined(RTM_NEWNETCONF)
227 case RTM_NEWNETCONF: return "new netconf";
228 case RTM_GETNETCONF: return "get netconf";
229 #endif
231 #if defined(RTM_NEWMDB)
232 case RTM_NEWMDB: return "new bridge mdb";
233 case RTM_DELMDB: return "del bridge mdb";
234 case RTM_GETMDB: return "get bridge mdb";
235 #endif
236 default: return NULL;
240 static const char *nlmsg_genl_type2str(uint16_t type)
242 switch (type) {
243 case GENL_ID_GENERATE: return "id gen";
244 case GENL_ID_CTRL: return "id ctrl";
245 default: return NULL;
249 static char *nlmsg_type2str(uint16_t proto, uint16_t type, char *buf, int len)
251 const char *name = NULL;
253 if (proto == NETLINK_ROUTE && type < RTM_MAX)
254 name = nlmsg_rtnl_type2str(type);
255 else if (proto == NETLINK_GENERIC)
256 name = nlmsg_genl_type2str(type);
258 if (name) {
259 strncpy(buf, name, len);
260 return buf;
263 return nl_nlmsgtype2str(type, buf, len);
266 static const char *addr_family2str(uint16_t family)
268 switch (family) {
269 case AF_INET: return "ipv4";
270 case AF_INET6: return "ipv6";
271 case AF_DECnet: return "decnet";
272 case AF_IPX: return "ipx";
273 default: return "Unknown";
277 static const char *addr2str(uint16_t af, const void *addr, char *buf, int blen)
279 if (af == AF_INET || af == AF_INET6)
280 return inet_ntop(af, addr, buf, blen);
282 return "???";
285 static const char *scope2str(uint8_t scope)
287 switch (scope) {
288 case RT_SCOPE_UNIVERSE: return "global";
289 case RT_SCOPE_LINK: return "link";
290 case RT_SCOPE_HOST: return "host";
291 case RT_SCOPE_NOWHERE: return "nowhere";
293 default: return "Unknown";
297 static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
299 struct ifinfomsg *ifi = NLMSG_DATA(hdr);
300 struct rtattr *attr = IFLA_RTA(ifi);
301 uint32_t attrs_len = IFLA_PAYLOAD(hdr);
302 char flags[256];
303 char if_addr[64] = {};
304 char *af_link = "unknown";
306 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifi)))
307 return;
309 if (ifi->ifi_family == AF_UNSPEC)
310 af_link = "unspec";
311 else if (ifi->ifi_family == AF_BRIDGE)
312 af_link = "bridge";
314 tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
315 colorize_start(bold), af_link, colorize_end());
316 tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
317 colorize_start(bold),
318 device_type2str(ifi->ifi_type),
319 colorize_end());
320 tprintf(", Index %d", ifi->ifi_index);
321 tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
322 colorize_start(bold),
323 rtnl_link_flags2str(ifi->ifi_flags, flags,
324 sizeof(flags)),
325 colorize_end());
326 tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
327 colorize_start(bold),
328 rtnl_link_flags2str(ifi->ifi_change, flags,
329 sizeof(flags)),
330 colorize_end());
332 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
333 switch (attr->rta_type) {
334 case IFLA_ADDRESS:
335 rta_fmt(attr, "Address %s",
336 device_addr2str(RTA_DATA(attr),
337 RTA_LEN(attr), ifi->ifi_type,
338 if_addr, sizeof(if_addr)));
339 break;
340 case IFLA_BROADCAST:
341 rta_fmt(attr, "Broadcast %s",
342 device_addr2str(RTA_DATA(attr),
343 RTA_LEN(attr), ifi->ifi_type,
344 if_addr, sizeof(if_addr)));
345 break;
346 case IFLA_IFNAME:
347 rta_fmt(attr, "Name %s%s%s",
348 colorize_start(bold), RTA_STR(attr),
349 colorize_end());
350 break;
351 case IFLA_MTU:
352 rta_fmt(attr, "MTU %d", RTA_INT(attr));
353 break;
354 case IFLA_LINK:
355 rta_fmt(attr, "Link %d", RTA_INT(attr));
356 break;
357 case IFLA_QDISC:
358 rta_fmt(attr, "QDisc %s", RTA_STR(attr));
359 break;
360 case IFLA_OPERSTATE:
362 uint8_t st = RTA_UINT8(attr);
363 char states[256];
365 rta_fmt(attr, "Operation state 0x%x (%s%s%s)",
367 colorize_start(bold),
368 rtnl_link_operstate2str(st,
369 states, sizeof(states)),
370 colorize_end());
372 break;
373 case IFLA_LINKMODE:
375 uint8_t mode = RTA_UINT8(attr);
376 char str[32];
378 rta_fmt(attr, "Mode 0x%x (%s%s%s)", mode,
379 colorize_start(bold),
380 rtnl_link_mode2str(mode, str,
381 sizeof(str)),
382 colorize_end());
384 break;
385 case IFLA_GROUP:
386 rta_fmt(attr, "Group %d", RTA_INT(attr));
387 break;
388 case IFLA_TXQLEN:
389 rta_fmt(attr, "Tx queue len %d", RTA_INT(attr));
390 break;
391 case IFLA_NET_NS_PID:
392 rta_fmt(attr, "Network namespace pid %d",
393 RTA_INT(attr));
394 break;
395 case IFLA_NET_NS_FD:
396 rta_fmt(attr, "Network namespace fd %d", RTA_INT(attr));
397 break;
398 default:
399 rta_fmt(attr, "0x%x", attr->rta_type);
400 break;
405 static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
407 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
408 uint32_t attrs_len = IFA_PAYLOAD(hdr);
409 struct rtattr *attr = IFA_RTA(ifa);
410 struct ifa_cacheinfo *ci;
411 char addr_str[256];
412 char flags[256];
414 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifa)))
415 return;
417 tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
418 colorize_start(bold),
419 addr_family2str(ifa->ifa_family),
420 colorize_end());
421 tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
422 tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
423 colorize_start(bold),
424 rtnl_addr_flags2str(ifa->ifa_flags, flags,
425 sizeof(flags)),
426 colorize_end());
427 tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
428 colorize_start(bold),
429 scope2str(ifa->ifa_scope),
430 colorize_end());
431 tprintf(", Link Index %d ]\n", ifa->ifa_index);
433 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
434 switch (attr->rta_type) {
435 case IFA_LOCAL:
436 rta_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
437 RTA_DATA(attr), addr_str, sizeof(addr_str)));
438 break;
439 case IFA_ADDRESS:
440 rta_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
441 RTA_DATA(attr), addr_str, sizeof(addr_str)));
442 break;
443 case IFA_BROADCAST:
444 rta_fmt(attr, "Broadcast %s",
445 addr2str(ifa->ifa_family,
446 RTA_DATA(attr), addr_str,
447 sizeof(addr_str)));
448 break;
449 case IFA_MULTICAST:
450 rta_fmt(attr, "Multicast %s",
451 addr2str(ifa->ifa_family,
452 RTA_DATA(attr), addr_str,
453 sizeof(addr_str)));
454 break;
455 case IFA_ANYCAST:
456 rta_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
457 RTA_DATA(attr), addr_str, sizeof(addr_str)));
458 break;
459 #ifdef IFA_FLAGS
460 case IFA_FLAGS:
461 rta_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
462 colorize_start(bold),
463 rtnl_addr_flags2str(RTA_INT(attr),
464 flags, sizeof(flags)),
465 colorize_end());
466 break;
467 #endif
468 case IFA_LABEL:
469 rta_fmt(attr, "Label %s", RTA_STR(attr));
470 break;
471 case IFA_CACHEINFO:
472 ci = RTA_DATA(attr);
473 tprintf("\tA: Cache (");
475 if (ci->ifa_valid == INFINITY)
476 tprintf("valid lft(forever)");
477 else
478 tprintf("valid lft(%us)", ci->ifa_valid);
480 if (ci->ifa_prefered == INFINITY)
481 tprintf(", prefrd lft(forever)");
482 else
483 tprintf(", prefrd lft(%us)", ci->ifa_prefered);
485 tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
486 tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
487 tprintf(", Len %d\n", RTA_LEN(attr));
488 break;
489 default:
490 rta_fmt(attr, "0x%x", attr->rta_type);
491 break;
496 static const char *route_table2str(uint8_t table)
498 switch (table) {
499 case RT_TABLE_UNSPEC: return "unspec";
500 case RT_TABLE_COMPAT: return "compat";
501 case RT_TABLE_DEFAULT: return "default";
502 case RT_TABLE_MAIN: return "main";
503 case RT_TABLE_LOCAL: return "local";
505 default: return "Unknown";
509 static const char *route_proto2str(uint8_t proto)
511 switch (proto) {
512 case RTPROT_UNSPEC: return "unspec";
513 case RTPROT_REDIRECT: return "redirect";
514 case RTPROT_KERNEL: return "kernel";
515 case RTPROT_BOOT: return "boot";
516 case RTPROT_STATIC: return "static";
517 case RTPROT_GATED: return "gated";
518 case RTPROT_RA: return "ra";
519 case RTPROT_MRT: return "mrt";
520 case RTPROT_ZEBRA: return "zebra";
521 case RTPROT_BIRD: return "bird";
522 case RTPROT_DNROUTED: return "DECnet";
523 case RTPROT_XORP: return "xorp";
524 case RTPROT_NTK: return "netsukuku";
525 case RTPROT_DHCP: return "dhcpc";
526 #ifdef RTPROT_MROUTED
527 case RTPROT_MROUTED: return "mrouted";
528 #endif
530 default: return "Unknown";
534 static const char *route_type2str(uint8_t type)
536 switch (type) {
537 case RTN_UNSPEC: return "unspec";
538 case RTN_UNICAST: return "unicast";
539 case RTN_LOCAL: return "local";
540 case RTN_BROADCAST: return "broadcast";
541 case RTN_ANYCAST: return "anycast";
542 case RTN_MULTICAST: return "multicast";
543 case RTN_BLACKHOLE: return "blackhole";
544 case RTN_UNREACHABLE: return "unreach";
545 case RTN_PROHIBIT: return "prohibit";
546 case RTN_THROW: return "throw";
547 case RTN_NAT: return "nat";
548 case RTN_XRESOLVE: return "xresolve";
549 default: return "Unknown";
553 static struct flag_name route_flags[] = {
554 { "notify", RTM_F_NOTIFY },
555 { "cloned", RTM_F_CLONED },
556 { "equalize", RTM_F_EQUALIZE },
557 { "prefix", RTM_F_PREFIX },
558 { "dead", RTNH_F_DEAD },
559 { "pervasive", RTNH_F_PERVASIVE },
560 { "onlink", RTNH_F_ONLINK },
561 { NULL, 0 },
564 static void rtnl_print_route(struct nlmsghdr *hdr)
566 struct rtmsg *rtm = NLMSG_DATA(hdr);
567 uint32_t attrs_len = RTM_PAYLOAD(hdr);
568 struct rtattr *attr = RTM_RTA(rtm);
569 struct rta_cacheinfo *ci;
570 int hz = get_user_hz();
571 char addr_str[256];
572 char flags[256];
574 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*rtm)))
575 return;
577 tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
578 colorize_start(bold),
579 addr_family2str(rtm->rtm_family),
580 colorize_end());
581 tprintf(", Dst Len %d", rtm->rtm_dst_len);
582 tprintf(", Src Len %d", rtm->rtm_src_len);
583 tprintf(", ToS %d", rtm->rtm_tos);
584 tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
585 colorize_start(bold),
586 route_table2str(rtm->rtm_table),
587 colorize_end());
588 tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
589 colorize_start(bold),
590 route_proto2str(rtm->rtm_protocol),
591 colorize_end());
592 tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
593 colorize_start(bold),
594 scope2str(rtm->rtm_scope),
595 colorize_end());
596 tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
597 colorize_start(bold),
598 route_type2str(rtm->rtm_type),
599 colorize_end());
600 tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
601 colorize_start(bold),
602 flags2str(route_flags, rtm->rtm_flags, flags,
603 sizeof(flags)),
604 colorize_end());
606 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
607 switch (attr->rta_type) {
608 case RTA_DST:
609 rta_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
610 RTA_DATA(attr), addr_str, sizeof(addr_str)));
611 break;
612 case RTA_SRC:
613 rta_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
614 RTA_DATA(attr), addr_str, sizeof(addr_str)));
615 break;
616 case RTA_IIF:
617 rta_fmt(attr, "Iif %d", RTA_INT(attr));
618 break;
619 case RTA_OIF:
620 rta_fmt(attr, "Oif %d", RTA_INT(attr));
621 break;
622 case RTA_GATEWAY:
623 rta_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
624 RTA_DATA(attr), addr_str, sizeof(addr_str)));
625 break;
626 case RTA_PRIORITY:
627 rta_fmt(attr, "Priority %u", RTA_UINT32(attr));
628 break;
629 case RTA_PREFSRC:
630 rta_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
631 RTA_DATA(attr), addr_str, sizeof(addr_str)));
632 break;
633 case RTA_MARK:
634 rta_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
635 break;
636 case RTA_FLOW:
637 rta_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
638 break;
639 case RTA_TABLE:
640 rta_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
641 colorize_start(bold),
642 route_table2str(RTA_UINT32(attr)),
643 colorize_end());
644 break;
645 case RTA_CACHEINFO:
646 ci = RTA_DATA(attr);
647 tprintf("\tA: Cache (");
648 tprintf("expires(%ds)", ci->rta_expires / hz);
649 tprintf(", error(%d)", ci->rta_error);
650 tprintf(", users(%d)", ci->rta_clntref);
651 tprintf(", used(%d)", ci->rta_used);
652 tprintf(", last use(%ds)", ci->rta_lastuse / hz);
653 tprintf(", id(%d)", ci->rta_id);
654 tprintf(", ts(%d)", ci->rta_ts);
655 tprintf(", ts age(%ds))", ci->rta_tsage);
656 tprintf(", Len %d\n", RTA_LEN(attr));
657 break;
658 default:
659 rta_fmt(attr, "0x%x", attr->rta_type);
660 break;
665 static struct flag_name neigh_states[] = {
666 { "incomplete", NUD_INCOMPLETE },
667 { "reachable", NUD_REACHABLE },
668 { "stale", NUD_STALE },
669 { "delay", NUD_DELAY },
670 { "probe", NUD_PROBE },
671 { "failed", NUD_FAILED },
672 { "noarp", NUD_NOARP },
673 { "permanent", NUD_PERMANENT },
674 { "none", NUD_NONE },
675 { NULL, 0 },
678 /* Copied from linux/neighbour.h */
679 #ifndef NTF_USE
680 # define NTF_USE 0x01
681 #endif
682 #ifndef NTF_SELF
683 # define NTF_SELF 0x02
684 #endif
685 #ifndef NTF_MASTER
686 # define NTF_MASTER 0x04
687 #endif
688 #ifndef NTF_PROXY
689 # define NTF_PROXY 0x08
690 #endif
691 #ifndef NTF_EXT_LEARNED
692 # define NTF_EXT_LEARNED 0x10
693 #endif
694 #ifndef NTF_ROUTER
695 # define NTF_ROUTER 0x80
696 #endif
698 static struct flag_name neigh_flags[] = {
699 { "use", NTF_USE },
700 { "self", NTF_SELF },
701 { "master", NTF_MASTER },
702 { "proxy", NTF_PROXY },
703 { "ext learned", NTF_EXT_LEARNED },
704 { "router", NTF_ROUTER },
705 { NULL, 0 },
708 static void rtnl_print_neigh(struct nlmsghdr *hdr)
710 struct ndmsg *ndm = NLMSG_DATA(hdr);
711 uint32_t attrs_len = NDA_PAYLOAD(hdr);
712 struct rtattr *attr = NDA_RTA(ndm);
713 struct nda_cacheinfo *ci;
714 int hz = get_user_hz();
715 char addr_str[256];
716 char hw_addr[30];
717 char states[256];
718 char flags[256];
720 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ndm)))
721 return;
723 tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
724 colorize_start(bold),
725 addr_family2str(ndm->ndm_family),
726 colorize_end());
727 tprintf(", Link Index %d", ndm->ndm_ifindex);
728 tprintf(", State %d (%s%s%s)", ndm->ndm_state,
729 colorize_start(bold),
730 flags2str(neigh_states, ndm->ndm_state, states,
731 sizeof(states)),
732 colorize_end());
733 tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
734 colorize_start(bold),
735 flags2str(neigh_flags, ndm->ndm_flags, flags,
736 sizeof(flags)),
737 colorize_end());
738 tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
739 colorize_start(bold),
740 route_type2str(ndm->ndm_type),
741 colorize_end());
742 tprintf(" ]\n");
744 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
745 switch (attr->rta_type) {
746 case NDA_DST:
747 rta_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
748 RTA_DATA(attr), addr_str,
749 sizeof(addr_str)));
750 break;
751 case NDA_LLADDR:
752 rta_fmt(attr, "HW Address %s",
753 device_addr2str(RTA_DATA(attr),
754 RTA_LEN(attr), 0, hw_addr,
755 sizeof(hw_addr)));
756 break;
757 case NDA_PROBES:
758 rta_fmt(attr, "Probes %d", RTA_UINT32(attr));
759 break;
760 case NDA_CACHEINFO:
761 ci = RTA_DATA(attr);
762 tprintf("\tA: Cache (");
763 tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
764 tprintf(", used(%ds)", ci->ndm_used / hz);
765 tprintf(", updated(%ds)", ci->ndm_updated / hz);
766 tprintf(", refcnt(%d))", ci->ndm_refcnt);
767 tprintf(", Len %d\n", RTA_LEN(attr));
768 break;
769 default:
770 rta_fmt(attr, "0x%x", attr->rta_type);
771 break;
776 static void rtnl_msg_print(struct nlmsghdr *hdr)
778 switch (hdr->nlmsg_type) {
779 case RTM_NEWLINK:
780 case RTM_DELLINK:
781 case RTM_GETLINK:
782 case RTM_SETLINK:
783 rtnl_print_ifinfo(hdr);
784 break;
785 case RTM_NEWADDR:
786 case RTM_DELADDR:
787 case RTM_GETADDR:
788 rtnl_print_ifaddr(hdr);
789 break;
790 case RTM_NEWROUTE:
791 case RTM_DELROUTE:
792 case RTM_GETROUTE:
793 rtnl_print_route(hdr);
794 break;
795 case RTM_NEWNEIGH:
796 case RTM_DELNEIGH:
797 case RTM_GETNEIGH:
798 rtnl_print_neigh(hdr);
799 break;
803 static const char *genl_cmd2str(uint8_t table)
805 switch (table) {
806 case CTRL_CMD_UNSPEC: return "unspec";
807 case CTRL_CMD_NEWFAMILY: return "new family";
808 case CTRL_CMD_DELFAMILY: return "del family";
809 case CTRL_CMD_GETFAMILY: return "get family";
810 case CTRL_CMD_NEWOPS: return "new ops";
811 case CTRL_CMD_DELOPS: return "del ops";
812 case CTRL_CMD_GETOPS: return "get ops";
813 case CTRL_CMD_NEWMCAST_GRP: return "new mcast group";
814 case CTRL_CMD_DELMCAST_GRP: return "del mcast group";
815 case CTRL_CMD_GETMCAST_GRP: return "get mcast group";
817 default: return "Unknown";
821 static struct flag_name genl_ops_flags[] = {
822 { "admin", GENL_ADMIN_PERM },
823 { "doit", GENL_CMD_CAP_DO },
824 { "dumpit", GENL_CMD_CAP_DUMP },
825 { "policy", GENL_CMD_CAP_HASPOL },
826 { NULL, 0 },
829 static void genl_print_ops_attr(struct nlattr *attr, uint32_t attr_len)
831 char str[256];
832 uint32_t flags;
834 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
835 switch (attr->nla_type) {
836 case CTRL_ATTR_OP_ID:
837 nla_fmt_nested(attr, "Id 0x%x", NLA_UINT32(attr));
838 break;
840 case CTRL_ATTR_OP_FLAGS:
841 flags = NLA_UINT32(attr);
843 nla_fmt_nested(attr, "Flags 0x%x (%s%s%s)", flags,
844 colorize_start(bold),
845 flags2str(genl_ops_flags, flags, str, sizeof(str)),
846 colorize_end());
847 break;
848 default:
849 nla_fmt_nested(attr, "0x%x", attr->nla_type);
850 break;
855 static void genl_print_ops_list(struct nlattr *attr, uint32_t attr_len)
857 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
858 nla_fmt_nested_start(attr, "0x%x", attr->nla_type);
859 genl_print_ops_attr(NLA_DATA(attr), NLA_LEN(attr));
860 nla_fmt_nested_end();
864 static void genl_print_mcast_group(struct nlattr *attr, uint32_t attr_len)
866 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
867 switch (attr->nla_type) {
868 case CTRL_ATTR_MCAST_GRP_ID:
869 nla_fmt_nested(attr, "Id 0x%x", NLA_UINT32(attr));
870 break;
872 case CTRL_ATTR_MCAST_GRP_NAME:
873 nla_fmt_nested(attr, "Name %s", NLA_STR(attr));
874 break;
875 default:
876 nla_fmt_nested(attr, "0x%x", attr->nla_type);
877 break;
882 static void genl_print_mc_groups(struct nlattr *attr, uint32_t attr_len)
884 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
885 nla_fmt_nested_start(attr, "0x%x", attr->nla_type);
886 genl_print_mcast_group(NLA_DATA(attr), NLA_LEN(attr));
887 nla_fmt_nested_end();
891 static void genl_print_ctrl_attrs(struct nlmsghdr *hdr)
893 struct genlmsghdr *genl = NLMSG_DATA(hdr);
894 struct nlattr *attr = GEN_NLA(genl);
895 uint32_t attrs_len = NLMSG_PAYLOAD(hdr, sizeof(struct genlmsghdr));
897 for (; NLA_OK(attr, attrs_len); attr = NLA_NEXT(attr, attrs_len)) {
898 switch (attr->nla_type) {
899 case CTRL_ATTR_FAMILY_ID:
900 nla_fmt(attr, "Family Id 0x%x", NLA_UINT16(attr));
901 break;
902 case CTRL_ATTR_FAMILY_NAME:
903 nla_fmt(attr, "Family Name %s", NLA_STR(attr));
904 break;
905 case CTRL_ATTR_VERSION:
906 nla_fmt(attr, "Version %u", NLA_UINT32(attr));
907 break;
908 case CTRL_ATTR_HDRSIZE:
909 nla_fmt(attr, "Header size %u", NLA_UINT32(attr));
910 break;
911 case CTRL_ATTR_MAXATTR:
912 nla_fmt(attr, "Max attr value 0x%x", NLA_UINT32(attr));
913 break;
914 case CTRL_ATTR_OPS:
915 nla_fmt(attr, "Ops list");
916 genl_print_ops_list(NLA_DATA(attr), NLA_LEN(attr));
917 break;
918 case CTRL_ATTR_MCAST_GROUPS:
919 nla_fmt(attr, "Mcast groups");
920 genl_print_mc_groups(NLA_DATA(attr), NLA_LEN(attr));
921 break;
922 default:
923 nla_fmt(attr, "0x%x", attr->nla_type);
924 break;
929 static void genl_msg_print(struct nlmsghdr *hdr)
931 struct genlmsghdr *genl;
933 if (hdr->nlmsg_type != GENL_ID_CTRL) {
934 nlmsg_print_raw(hdr);
935 return;
938 genl = NLMSG_DATA(hdr);
940 tprintf(" [ Cmd %u (%s%s%s)", genl->cmd,
941 colorize_start(bold), genl_cmd2str(genl->cmd), colorize_end());
942 tprintf(", Version %u", genl->version);
943 tprintf(", Reserved %u", genl->reserved);
944 tprintf(" ]\n");
946 genl_print_ctrl_attrs(hdr);
949 static void nlmsg_print(uint16_t family, struct nlmsghdr *hdr)
951 u16 nlmsg_flags = hdr->nlmsg_flags;
952 char type[32];
953 char flags[128];
954 char procname[PATH_MAX];
956 /* Look up the process name if message is not coming from the kernel.
958 * Note that the port id is not necessarily equal to the PID of the
959 * receiving process (e.g. if the application is multithreaded or using
960 * multiple sockets). In these cases we're not able to find a matching
961 * PID and the information will not be printed.
963 if (hdr->nlmsg_pid != 0) {
964 if (proc_get_cmdline(hdr->nlmsg_pid, procname, sizeof(procname)) < 0)
965 snprintf(procname, sizeof(procname), "unknown process");
966 } else
967 snprintf(procname, sizeof(procname), "kernel");
969 tprintf(" [ NLMSG ");
970 tprintf("Family %d (%s%s%s), ", family,
971 colorize_start(bold),
972 nlmsg_family2str(family),
973 colorize_end());
974 tprintf("Len %u, ", hdr->nlmsg_len);
975 tprintf("Type 0x%.4x (%s%s%s), ", hdr->nlmsg_type,
976 colorize_start(bold),
977 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
978 colorize_end());
979 tprintf("Flags 0x%.4x (%s%s%s), ", nlmsg_flags,
980 colorize_start(bold),
981 nlmsg_flags ? nl_nlmsg_flags2str(nlmsg_flags, flags, sizeof(flags)) : "none",
982 colorize_end());
983 tprintf("Seq-Nr %u, ", hdr->nlmsg_seq);
984 tprintf("PID %u", hdr->nlmsg_pid);
985 if (procname[0])
986 tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
987 colorize_end());
988 tprintf(" ]\n");
990 switch (family) {
991 case NETLINK_ROUTE:
992 rtnl_msg_print(hdr);
993 break;
994 case NETLINK_GENERIC:
995 genl_msg_print(hdr);
996 break;
997 default:
998 nlmsg_print_raw(hdr);
1002 static void nlmsg(struct pkt_buff *pkt)
1004 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1005 unsigned int trim_len = pkt_len(pkt);
1007 while (hdr) {
1008 trim_len -= hdr->nlmsg_len;
1009 nlmsg_print(ntohs(pkt->sll->sll_protocol), hdr);
1011 if (!pkt_pull(pkt, NLMSG_ALIGN(hdr->nlmsg_len) - NLMSG_HDRLEN))
1012 break;
1014 hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1015 if (hdr == NULL)
1016 break;
1017 if (hdr->nlmsg_len == 0)
1018 break;
1020 if (hdr->nlmsg_type != NLMSG_DONE &&
1021 (hdr->nlmsg_flags & NLM_F_MULTI))
1022 tprintf("\n");
1025 /* mmaped packet? */
1026 if (hdr && hdr->nlmsg_len == 0)
1027 pkt_trim(pkt, trim_len);
1030 static void nlmsg_less(struct pkt_buff *pkt)
1032 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1033 uint16_t family = ntohs(pkt->sll->sll_protocol);
1034 char type[32];
1036 if (hdr == NULL)
1037 return;
1039 tprintf(" NLMSG Family %d (%s%s%s), ", family,
1040 colorize_start(bold),
1041 nlmsg_family2str(family),
1042 colorize_end());
1043 tprintf("Type %u (%s%s%s)", hdr->nlmsg_type,
1044 colorize_start(bold),
1045 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
1046 colorize_end());
1049 struct protocol nlmsg_ops = {
1050 .print_full = nlmsg,
1051 .print_less = nlmsg_less,