netsniff-ng: nlmsg: Rename attr_fmt to rta_fmt
[netsniff-ng.git] / proto_nlmsg.c
blob93c52b96bc90273ceb01e3310584217b516c6c07
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 struct flag_name {
89 const char *name;
90 unsigned int flag;
93 static const char *flags2str(struct flag_name *tbl, unsigned int flags,
94 char *buf, int len)
96 int bits_stay = flags;
98 memset(buf, 0, len);
100 for (; tbl && tbl->name; tbl++) {
101 if (!(tbl->flag & flags))
102 continue;
104 bits_stay &= ~tbl->flag;
105 strncat(buf, tbl->name, len - strlen(buf) - 1);
107 if (bits_stay & flags)
108 strncat(buf, ",", len - strlen(buf) - 1);
111 return buf;
114 static void nlmsg_print_raw(struct nlmsghdr *hdr)
116 u32 len = hdr->nlmsg_len;
118 if (len) {
119 _ascii((uint8_t *) hdr + NLMSG_HDRLEN, len - NLMSG_HDRLEN);
120 _hex((uint8_t *) hdr + NLMSG_HDRLEN, len - NLMSG_HDRLEN);
124 static const char *nlmsg_family2str(uint16_t family)
126 switch (family) {
127 case NETLINK_ROUTE: return "routing";
128 case NETLINK_UNUSED: return "unused";
129 case NETLINK_USERSOCK: return "user-mode socket";
130 case NETLINK_FIREWALL: return "unused, formerly ip_queue";
131 /* NETLINK_INET_DIAG was renamed to NETLINK_SOCK_DIAG in Linux kernel 3.10 */
132 #if defined(NETLINK_SOCK_DIAG)
133 case NETLINK_SOCK_DIAG: return "socket monitoring";
134 #elif defined(NETLINK_INET_DIAG)
135 case NETLINK_INET_DIAG: return "INET socket monitoring";
136 #endif
137 case NETLINK_NFLOG: return "netfilter ULOG";
138 case NETLINK_XFRM: return "IPsec";
139 case NETLINK_SELINUX: return "SELinux event notification";
140 case NETLINK_ISCSI: return "Open-iSCSI";
141 case NETLINK_AUDIT: return "auditing";
142 case NETLINK_FIB_LOOKUP: return "FIB lookup";
143 case NETLINK_CONNECTOR: return "Kernel connector";
144 case NETLINK_NETFILTER: return "Netfilter";
145 case NETLINK_IP6_FW: return "unused, formerly ip6_queue";
146 case NETLINK_DNRTMSG: return "DECnet routing";
147 case NETLINK_KOBJECT_UEVENT: return "Kernel messages";
148 case NETLINK_GENERIC: return "Generic";
149 case NETLINK_SCSITRANSPORT: return "SCSI transports";
150 case NETLINK_ECRYPTFS: return "ecryptfs";
151 case NETLINK_RDMA: return "RDMA";
152 case NETLINK_CRYPTO: return "Crypto layer";
153 default: return "Unknown";
157 static const char *nlmsg_rtnl_type2str(uint16_t type)
159 switch (type) {
160 case RTM_NEWLINK: return "new link";
161 case RTM_DELLINK: return "del link";
162 case RTM_GETLINK: return "get link";
163 case RTM_SETLINK: return "set link";
165 case RTM_NEWADDR: return "new addr";
166 case RTM_DELADDR: return "del addr";
167 case RTM_GETADDR: return "get addr";
169 case RTM_NEWROUTE: return "new route";
170 case RTM_DELROUTE: return "del route";
171 case RTM_GETROUTE: return "get route";
173 case RTM_NEWNEIGH: return "new neigh";
174 case RTM_DELNEIGH: return "del neigh";
175 case RTM_GETNEIGH: return "get neigh";
177 case RTM_NEWRULE: return "new rule";
178 case RTM_DELRULE: return "del rule";
179 case RTM_GETRULE: return "get rule";
181 case RTM_NEWQDISC: return "new tc qdisc";
182 case RTM_DELQDISC: return "del tc qdisc";
183 case RTM_GETQDISC: return "get tc qdisc";
185 case RTM_NEWTCLASS: return "new tc class";
186 case RTM_DELTCLASS: return "del tc class";
187 case RTM_GETTCLASS: return "get tc class";
189 case RTM_NEWTFILTER: return "new tc filter";
190 case RTM_DELTFILTER: return "del tc filter";
191 case RTM_GETTFILTER: return "get tc filter";
193 case RTM_NEWACTION: return "new tc action";
194 case RTM_DELACTION: return "del tc action";
195 case RTM_GETACTION: return "get tc action";
197 case RTM_NEWPREFIX: return "new prefix";
199 case RTM_GETMULTICAST: return "get mcast addr";
201 case RTM_GETANYCAST: return "get anycast addr";
203 case RTM_NEWNEIGHTBL: return "new neigh table";
204 case RTM_GETNEIGHTBL: return "get neigh table";
205 case RTM_SETNEIGHTBL: return "set neigh table";
207 case RTM_NEWNDUSEROPT: return "new ndisc user option";
209 case RTM_NEWADDRLABEL: return "new addr label";
210 case RTM_DELADDRLABEL: return "del addr label";
211 case RTM_GETADDRLABEL: return "get addr label";
213 case RTM_GETDCB: return "get data-center-bridge";
214 case RTM_SETDCB: return "set data-center-bridge";
216 #if defined(RTM_NEWNETCONF)
217 case RTM_NEWNETCONF: return "new netconf";
218 case RTM_GETNETCONF: return "get netconf";
219 #endif
221 #if defined(RTM_NEWMDB)
222 case RTM_NEWMDB: return "new bridge mdb";
223 case RTM_DELMDB: return "del bridge mdb";
224 case RTM_GETMDB: return "get bridge mdb";
225 #endif
226 default: return NULL;
230 static const char *nlmsg_genl_type2str(uint16_t type)
232 switch (type) {
233 case GENL_ID_GENERATE: return "id gen";
234 case GENL_ID_CTRL: return "id ctrl";
235 default: return NULL;
239 static char *nlmsg_type2str(uint16_t proto, uint16_t type, char *buf, int len)
241 const char *name = NULL;
243 if (proto == NETLINK_ROUTE && type < RTM_MAX)
244 name = nlmsg_rtnl_type2str(type);
245 else if (proto == NETLINK_GENERIC)
246 name = nlmsg_genl_type2str(type);
248 if (name) {
249 strncpy(buf, name, len);
250 return buf;
253 return nl_nlmsgtype2str(type, buf, len);
256 static const char *addr_family2str(uint16_t family)
258 switch (family) {
259 case AF_INET: return "ipv4";
260 case AF_INET6: return "ipv6";
261 case AF_DECnet: return "decnet";
262 case AF_IPX: return "ipx";
263 default: return "Unknown";
267 static const char *addr2str(uint16_t af, const void *addr, char *buf, int blen)
269 if (af == AF_INET || af == AF_INET6)
270 return inet_ntop(af, addr, buf, blen);
272 return "???";
275 static const char *scope2str(uint8_t scope)
277 switch (scope) {
278 case RT_SCOPE_UNIVERSE: return "global";
279 case RT_SCOPE_LINK: return "link";
280 case RT_SCOPE_HOST: return "host";
281 case RT_SCOPE_NOWHERE: return "nowhere";
283 default: return "Unknown";
287 static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
289 struct ifinfomsg *ifi = NLMSG_DATA(hdr);
290 struct rtattr *attr = IFLA_RTA(ifi);
291 uint32_t attrs_len = IFLA_PAYLOAD(hdr);
292 char flags[256];
293 char if_addr[64] = {};
294 char *af_link = "unknown";
296 if (ifi->ifi_family == AF_UNSPEC)
297 af_link = "unspec";
298 else if (ifi->ifi_family == AF_BRIDGE)
299 af_link = "bridge";
301 tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
302 colorize_start(bold), af_link, colorize_end());
303 tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
304 colorize_start(bold),
305 device_type2str(ifi->ifi_type),
306 colorize_end());
307 tprintf(", Index %d", ifi->ifi_index);
308 tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
309 colorize_start(bold),
310 rtnl_link_flags2str(ifi->ifi_flags, flags,
311 sizeof(flags)),
312 colorize_end());
313 tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
314 colorize_start(bold),
315 rtnl_link_flags2str(ifi->ifi_change, flags,
316 sizeof(flags)),
317 colorize_end());
319 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
320 switch (attr->rta_type) {
321 case IFLA_ADDRESS:
322 rta_fmt(attr, "Address %s",
323 device_addr2str(RTA_DATA(attr),
324 RTA_LEN(attr), ifi->ifi_type,
325 if_addr, sizeof(if_addr)));
326 break;
327 case IFLA_BROADCAST:
328 rta_fmt(attr, "Broadcast %s",
329 device_addr2str(RTA_DATA(attr),
330 RTA_LEN(attr), ifi->ifi_type,
331 if_addr, sizeof(if_addr)));
332 break;
333 case IFLA_IFNAME:
334 rta_fmt(attr, "Name %s%s%s",
335 colorize_start(bold), RTA_STR(attr),
336 colorize_end());
337 break;
338 case IFLA_MTU:
339 rta_fmt(attr, "MTU %d", RTA_INT(attr));
340 break;
341 case IFLA_LINK:
342 rta_fmt(attr, "Link %d", RTA_INT(attr));
343 break;
344 case IFLA_QDISC:
345 rta_fmt(attr, "QDisc %s", RTA_STR(attr));
346 break;
347 case IFLA_OPERSTATE:
349 uint8_t st = RTA_UINT8(attr);
350 char states[256];
352 rta_fmt(attr, "Operation state 0x%x (%s%s%s)",
354 colorize_start(bold),
355 rtnl_link_operstate2str(st,
356 states, sizeof(states)),
357 colorize_end());
359 break;
360 case IFLA_LINKMODE:
362 uint8_t mode = RTA_UINT8(attr);
363 char str[32];
365 rta_fmt(attr, "Mode 0x%x (%s%s%s)", mode,
366 colorize_start(bold),
367 rtnl_link_mode2str(mode, str,
368 sizeof(str)),
369 colorize_end());
371 break;
372 case IFLA_GROUP:
373 rta_fmt(attr, "Group %d", RTA_INT(attr));
374 break;
375 case IFLA_TXQLEN:
376 rta_fmt(attr, "Tx queue len %d", RTA_INT(attr));
377 break;
378 case IFLA_NET_NS_PID:
379 rta_fmt(attr, "Network namespace pid %d",
380 RTA_INT(attr));
381 break;
382 case IFLA_NET_NS_FD:
383 rta_fmt(attr, "Network namespace fd %d", RTA_INT(attr));
384 break;
385 default:
386 rta_fmt(attr, "0x%x", attr->rta_type);
387 break;
392 static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
394 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
395 uint32_t attrs_len = IFA_PAYLOAD(hdr);
396 struct rtattr *attr = IFA_RTA(ifa);
397 struct ifa_cacheinfo *ci;
398 char addr_str[256];
399 char flags[256];
401 tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
402 colorize_start(bold),
403 addr_family2str(ifa->ifa_family),
404 colorize_end());
405 tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
406 tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
407 colorize_start(bold),
408 rtnl_addr_flags2str(ifa->ifa_flags, flags,
409 sizeof(flags)),
410 colorize_end());
411 tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
412 colorize_start(bold),
413 scope2str(ifa->ifa_scope),
414 colorize_end());
415 tprintf(", Link Index %d ]\n", ifa->ifa_index);
417 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
418 switch (attr->rta_type) {
419 case IFA_LOCAL:
420 rta_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
421 RTA_DATA(attr), addr_str, sizeof(addr_str)));
422 break;
423 case IFA_ADDRESS:
424 rta_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
425 RTA_DATA(attr), addr_str, sizeof(addr_str)));
426 break;
427 case IFA_BROADCAST:
428 rta_fmt(attr, "Broadcast %s",
429 addr2str(ifa->ifa_family,
430 RTA_DATA(attr), addr_str,
431 sizeof(addr_str)));
432 break;
433 case IFA_MULTICAST:
434 rta_fmt(attr, "Multicast %s",
435 addr2str(ifa->ifa_family,
436 RTA_DATA(attr), addr_str,
437 sizeof(addr_str)));
438 break;
439 case IFA_ANYCAST:
440 rta_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
441 RTA_DATA(attr), addr_str, sizeof(addr_str)));
442 break;
443 #ifdef IFA_FLAGS
444 case IFA_FLAGS:
445 rta_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
446 colorize_start(bold),
447 rtnl_addr_flags2str(RTA_INT(attr),
448 flags, sizeof(flags)),
449 colorize_end());
450 break;
451 #endif
452 case IFA_LABEL:
453 rta_fmt(attr, "Label %s", RTA_STR(attr));
454 break;
455 case IFA_CACHEINFO:
456 ci = RTA_DATA(attr);
457 tprintf("\tA: Cache (");
459 if (ci->ifa_valid == INFINITY)
460 tprintf("valid lft(forever)");
461 else
462 tprintf("valid lft(%us)", ci->ifa_valid);
464 if (ci->ifa_prefered == INFINITY)
465 tprintf(", prefrd lft(forever)");
466 else
467 tprintf(", prefrd lft(%us)", ci->ifa_prefered);
469 tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
470 tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
471 tprintf(", Len %d\n", RTA_LEN(attr));
472 break;
473 default:
474 rta_fmt(attr, "0x%x", attr->rta_type);
475 break;
480 static const char *route_table2str(uint8_t table)
482 switch (table) {
483 case RT_TABLE_UNSPEC: return "unspec";
484 case RT_TABLE_COMPAT: return "compat";
485 case RT_TABLE_DEFAULT: return "default";
486 case RT_TABLE_MAIN: return "main";
487 case RT_TABLE_LOCAL: return "local";
489 default: return "Unknown";
493 static const char *route_proto2str(uint8_t proto)
495 switch (proto) {
496 case RTPROT_UNSPEC: return "unspec";
497 case RTPROT_REDIRECT: return "redirect";
498 case RTPROT_KERNEL: return "kernel";
499 case RTPROT_BOOT: return "boot";
500 case RTPROT_STATIC: return "static";
501 case RTPROT_GATED: return "gated";
502 case RTPROT_RA: return "ra";
503 case RTPROT_MRT: return "mrt";
504 case RTPROT_ZEBRA: return "zebra";
505 case RTPROT_BIRD: return "bird";
506 case RTPROT_DNROUTED: return "DECnet";
507 case RTPROT_XORP: return "xorp";
508 case RTPROT_NTK: return "netsukuku";
509 case RTPROT_DHCP: return "dhcpc";
510 #ifdef RTPROT_MROUTED
511 case RTPROT_MROUTED: return "mrouted";
512 #endif
514 default: return "Unknown";
518 static const char *route_type2str(uint8_t type)
520 switch (type) {
521 case RTN_UNSPEC: return "unspec";
522 case RTN_UNICAST: return "unicast";
523 case RTN_LOCAL: return "local";
524 case RTN_BROADCAST: return "broadcast";
525 case RTN_ANYCAST: return "anycast";
526 case RTN_MULTICAST: return "multicast";
527 case RTN_BLACKHOLE: return "blackhole";
528 case RTN_UNREACHABLE: return "unreach";
529 case RTN_PROHIBIT: return "prohibit";
530 case RTN_THROW: return "throw";
531 case RTN_NAT: return "nat";
532 case RTN_XRESOLVE: return "xresolve";
533 default: return "Unknown";
537 static struct flag_name route_flags[] = {
538 { "notify", RTM_F_NOTIFY },
539 { "cloned", RTM_F_CLONED },
540 { "equalize", RTM_F_EQUALIZE },
541 { "prefix", RTM_F_PREFIX },
542 { "dead", RTNH_F_DEAD },
543 { "pervasive", RTNH_F_PERVASIVE },
544 { "onlink", RTNH_F_ONLINK },
545 { NULL, 0 },
548 static void rtnl_print_route(struct nlmsghdr *hdr)
550 struct rtmsg *rtm = NLMSG_DATA(hdr);
551 uint32_t attrs_len = RTM_PAYLOAD(hdr);
552 struct rtattr *attr = RTM_RTA(rtm);
553 struct rta_cacheinfo *ci;
554 int hz = get_user_hz();
555 char addr_str[256];
556 char flags[256];
558 tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
559 colorize_start(bold),
560 addr_family2str(rtm->rtm_family),
561 colorize_end());
562 tprintf(", Dst Len %d", rtm->rtm_dst_len);
563 tprintf(", Src Len %d", rtm->rtm_src_len);
564 tprintf(", ToS %d", rtm->rtm_tos);
565 tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
566 colorize_start(bold),
567 route_table2str(rtm->rtm_table),
568 colorize_end());
569 tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
570 colorize_start(bold),
571 route_proto2str(rtm->rtm_protocol),
572 colorize_end());
573 tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
574 colorize_start(bold),
575 scope2str(rtm->rtm_scope),
576 colorize_end());
577 tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
578 colorize_start(bold),
579 route_type2str(rtm->rtm_type),
580 colorize_end());
581 tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
582 colorize_start(bold),
583 flags2str(route_flags, rtm->rtm_flags, flags,
584 sizeof(flags)),
585 colorize_end());
587 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
588 switch (attr->rta_type) {
589 case RTA_DST:
590 rta_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
591 RTA_DATA(attr), addr_str, sizeof(addr_str)));
592 break;
593 case RTA_SRC:
594 rta_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
595 RTA_DATA(attr), addr_str, sizeof(addr_str)));
596 break;
597 case RTA_IIF:
598 rta_fmt(attr, "Iif %d", RTA_INT(attr));
599 break;
600 case RTA_OIF:
601 rta_fmt(attr, "Oif %d", RTA_INT(attr));
602 break;
603 case RTA_GATEWAY:
604 rta_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
605 RTA_DATA(attr), addr_str, sizeof(addr_str)));
606 break;
607 case RTA_PRIORITY:
608 rta_fmt(attr, "Priority %u", RTA_UINT32(attr));
609 break;
610 case RTA_PREFSRC:
611 rta_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
612 RTA_DATA(attr), addr_str, sizeof(addr_str)));
613 break;
614 case RTA_MARK:
615 rta_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
616 break;
617 case RTA_FLOW:
618 rta_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
619 break;
620 case RTA_TABLE:
621 rta_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
622 colorize_start(bold),
623 route_table2str(RTA_UINT32(attr)),
624 colorize_end());
625 break;
626 case RTA_CACHEINFO:
627 ci = RTA_DATA(attr);
628 tprintf("\tA: Cache (");
629 tprintf("expires(%ds)", ci->rta_expires / hz);
630 tprintf(", error(%d)", ci->rta_error);
631 tprintf(", users(%d)", ci->rta_clntref);
632 tprintf(", used(%d)", ci->rta_used);
633 tprintf(", last use(%ds)", ci->rta_lastuse / hz);
634 tprintf(", id(%d)", ci->rta_id);
635 tprintf(", ts(%d)", ci->rta_ts);
636 tprintf(", ts age(%ds))", ci->rta_tsage);
637 tprintf(", Len %d\n", RTA_LEN(attr));
638 break;
639 default:
640 rta_fmt(attr, "0x%x", attr->rta_type);
641 break;
646 static struct flag_name neigh_states[] = {
647 { "incomplete", NUD_INCOMPLETE },
648 { "reachable", NUD_REACHABLE },
649 { "stale", NUD_STALE },
650 { "delay", NUD_DELAY },
651 { "probe", NUD_PROBE },
652 { "failed", NUD_FAILED },
653 { "noarp", NUD_NOARP },
654 { "permanent", NUD_PERMANENT },
655 { "none", NUD_NONE },
656 { NULL, 0 },
659 /* Copied from linux/neighbour.h */
660 #ifndef NTF_USE
661 # define NTF_USE 0x01
662 #endif
663 #ifndef NTF_SELF
664 # define NTF_SELF 0x02
665 #endif
666 #ifndef NTF_MASTER
667 # define NTF_MASTER 0x04
668 #endif
669 #ifndef NTF_PROXY
670 # define NTF_PROXY 0x08
671 #endif
672 #ifndef NTF_EXT_LEARNED
673 # define NTF_EXT_LEARNED 0x10
674 #endif
675 #ifndef NTF_ROUTER
676 # define NTF_ROUTER 0x80
677 #endif
679 static struct flag_name neigh_flags[] = {
680 { "use", NTF_USE },
681 { "self", NTF_SELF },
682 { "master", NTF_MASTER },
683 { "proxy", NTF_PROXY },
684 { "ext learned", NTF_EXT_LEARNED },
685 { "router", NTF_ROUTER },
686 { NULL, 0 },
689 static void rtnl_print_neigh(struct nlmsghdr *hdr)
691 struct ndmsg *ndm = NLMSG_DATA(hdr);
692 uint32_t attrs_len = NDA_PAYLOAD(hdr);
693 struct rtattr *attr = NDA_RTA(ndm);
694 struct nda_cacheinfo *ci;
695 int hz = get_user_hz();
696 char addr_str[256];
697 char hw_addr[30];
698 char states[256];
699 char flags[256];
701 tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
702 colorize_start(bold),
703 addr_family2str(ndm->ndm_family),
704 colorize_end());
705 tprintf(", Link Index %d", ndm->ndm_ifindex);
706 tprintf(", State %d (%s%s%s)", ndm->ndm_state,
707 colorize_start(bold),
708 flags2str(neigh_states, ndm->ndm_state, states,
709 sizeof(states)),
710 colorize_end());
711 tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
712 colorize_start(bold),
713 flags2str(neigh_flags, ndm->ndm_flags, flags,
714 sizeof(flags)),
715 colorize_end());
716 tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
717 colorize_start(bold),
718 route_type2str(ndm->ndm_type),
719 colorize_end());
720 tprintf(" ]\n");
722 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
723 switch (attr->rta_type) {
724 case NDA_DST:
725 rta_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
726 RTA_DATA(attr), addr_str,
727 sizeof(addr_str)));
728 break;
729 case NDA_LLADDR:
730 rta_fmt(attr, "HW Address %s",
731 device_addr2str(RTA_DATA(attr),
732 RTA_LEN(attr), 0, hw_addr,
733 sizeof(hw_addr)));
734 break;
735 case NDA_PROBES:
736 rta_fmt(attr, "Probes %d", RTA_UINT32(attr));
737 break;
738 case NDA_CACHEINFO:
739 ci = RTA_DATA(attr);
740 tprintf("\tA: Cache (");
741 tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
742 tprintf(", used(%ds)", ci->ndm_used / hz);
743 tprintf(", updated(%ds)", ci->ndm_updated / hz);
744 tprintf(", refcnt(%d))", ci->ndm_refcnt);
745 tprintf(", Len %d\n", RTA_LEN(attr));
746 break;
747 default:
748 rta_fmt(attr, "0x%x", attr->rta_type);
749 break;
754 static void rtnl_msg_print(struct nlmsghdr *hdr)
756 switch (hdr->nlmsg_type) {
757 case RTM_NEWLINK:
758 case RTM_DELLINK:
759 case RTM_GETLINK:
760 case RTM_SETLINK:
761 rtnl_print_ifinfo(hdr);
762 break;
763 case RTM_NEWADDR:
764 case RTM_DELADDR:
765 case RTM_GETADDR:
766 rtnl_print_ifaddr(hdr);
767 break;
768 case RTM_NEWROUTE:
769 case RTM_DELROUTE:
770 case RTM_GETROUTE:
771 rtnl_print_route(hdr);
772 break;
773 case RTM_NEWNEIGH:
774 case RTM_DELNEIGH:
775 case RTM_GETNEIGH:
776 rtnl_print_neigh(hdr);
777 break;
781 static const char *genl_cmd2str(uint8_t table)
783 switch (table) {
784 case CTRL_CMD_UNSPEC: return "unspec";
785 case CTRL_CMD_NEWFAMILY: return "new family";
786 case CTRL_CMD_DELFAMILY: return "del family";
787 case CTRL_CMD_GETFAMILY: return "get family";
788 case CTRL_CMD_NEWOPS: return "new ops";
789 case CTRL_CMD_DELOPS: return "del ops";
790 case CTRL_CMD_GETOPS: return "get ops";
791 case CTRL_CMD_NEWMCAST_GRP: return "new mcast group";
792 case CTRL_CMD_DELMCAST_GRP: return "del mcast group";
793 case CTRL_CMD_GETMCAST_GRP: return "get mcast group";
795 default: return "Unknown";
799 static void genl_print_ctrl_family(struct nlmsghdr *hdr)
801 struct genlmsghdr *genl = NLMSG_DATA(hdr);
802 struct nlattr *attr = GEN_NLA(genl);
803 uint32_t attrs_len = NLMSG_PAYLOAD(hdr, sizeof(struct genlmsghdr));
805 for (; NLA_OK(attr, attrs_len); attr = NLA_NEXT(attr, attrs_len)) {
806 switch (attr->nla_type) {
807 case CTRL_ATTR_FAMILY_ID:
808 nla_fmt(attr, "Family Id 0x%x", NLA_UINT16(attr));
809 break;
811 case CTRL_ATTR_FAMILY_NAME:
812 nla_fmt(attr, "Family Name %s", NLA_STR(attr));
813 break;
815 case CTRL_ATTR_VERSION:
816 nla_fmt(attr, "Version %u", NLA_UINT32(attr));
817 break;
819 case CTRL_ATTR_HDRSIZE:
820 nla_fmt(attr, "Header size %u", NLA_UINT32(attr));
821 break;
823 case CTRL_ATTR_MAXATTR:
824 nla_fmt(attr, "Max attr value 0x%x", NLA_UINT32(attr));
825 break;
827 default:
828 nla_fmt(attr, "0x%x", attr->nla_type);
829 break;
834 static void genl_print_ctrl(struct nlmsghdr *hdr)
836 struct genlmsghdr *genl = NLMSG_DATA(hdr);
838 switch (genl->cmd) {
839 case CTRL_CMD_NEWFAMILY:
840 case CTRL_CMD_DELFAMILY:
841 case CTRL_CMD_GETFAMILY:
842 genl_print_ctrl_family(hdr);
846 static void genl_msg_print(struct nlmsghdr *hdr)
848 struct genlmsghdr *genl;
850 if (hdr->nlmsg_type != GENL_ID_CTRL) {
851 nlmsg_print_raw(hdr);
852 return;
855 genl = NLMSG_DATA(hdr);
857 tprintf(" [ Cmd %u (%s%s%s)", genl->cmd,
858 colorize_start(bold), genl_cmd2str(genl->cmd), colorize_end());
859 tprintf(", Version %u", genl->version);
860 tprintf(", Reserved %u", genl->reserved);
861 tprintf(" ]\n");
863 genl_print_ctrl(hdr);
866 static void nlmsg_print(uint16_t family, struct nlmsghdr *hdr)
868 u16 nlmsg_flags = hdr->nlmsg_flags;
869 char type[32];
870 char flags[128];
871 char procname[PATH_MAX];
873 /* Look up the process name if message is not coming from the kernel.
875 * Note that the port id is not necessarily equal to the PID of the
876 * receiving process (e.g. if the application is multithreaded or using
877 * multiple sockets). In these cases we're not able to find a matching
878 * PID and the information will not be printed.
880 if (hdr->nlmsg_pid != 0) {
881 if (proc_get_cmdline(hdr->nlmsg_pid, procname, sizeof(procname)) < 0)
882 snprintf(procname, sizeof(procname), "unknown process");
883 } else
884 snprintf(procname, sizeof(procname), "kernel");
886 tprintf(" [ NLMSG ");
887 tprintf("Family %d (%s%s%s), ", family,
888 colorize_start(bold),
889 nlmsg_family2str(family),
890 colorize_end());
891 tprintf("Len %u, ", hdr->nlmsg_len);
892 tprintf("Type 0x%.4x (%s%s%s), ", hdr->nlmsg_type,
893 colorize_start(bold),
894 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
895 colorize_end());
896 tprintf("Flags 0x%.4x (%s%s%s), ", nlmsg_flags,
897 colorize_start(bold),
898 nlmsg_flags ? nl_nlmsg_flags2str(nlmsg_flags, flags, sizeof(flags)) : "none",
899 colorize_end());
900 tprintf("Seq-Nr %u, ", hdr->nlmsg_seq);
901 tprintf("PID %u", hdr->nlmsg_pid);
902 if (procname[0])
903 tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
904 colorize_end());
905 tprintf(" ]\n");
907 switch (family) {
908 case NETLINK_ROUTE:
909 rtnl_msg_print(hdr);
910 break;
911 case NETLINK_GENERIC:
912 genl_msg_print(hdr);
913 break;
914 default:
915 nlmsg_print_raw(hdr);
919 static void nlmsg(struct pkt_buff *pkt)
921 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
922 unsigned int trim_len = pkt_len(pkt);
924 while (hdr) {
925 trim_len -= hdr->nlmsg_len;
926 nlmsg_print(ntohs(pkt->sll->sll_protocol), hdr);
928 if (!pkt_pull(pkt, NLMSG_ALIGN(hdr->nlmsg_len) - NLMSG_HDRLEN))
929 break;
931 hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
932 if (hdr == NULL)
933 break;
934 if (hdr->nlmsg_len == 0)
935 break;
937 if (hdr->nlmsg_type != NLMSG_DONE &&
938 (hdr->nlmsg_flags & NLM_F_MULTI))
939 tprintf("\n");
942 /* mmaped packet? */
943 if (hdr && hdr->nlmsg_len == 0)
944 pkt_trim(pkt, trim_len);
947 static void nlmsg_less(struct pkt_buff *pkt)
949 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
950 uint16_t family = ntohs(pkt->sll->sll_protocol);
951 char type[32];
953 if (hdr == NULL)
954 return;
956 tprintf(" NLMSG Family %d (%s%s%s), ", family,
957 colorize_start(bold),
958 nlmsg_family2str(family),
959 colorize_end());
960 tprintf("Type %u (%s%s%s)", hdr->nlmsg_type,
961 colorize_start(bold),
962 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
963 colorize_end());
966 struct protocol nlmsg_ops = {
967 .print_full = nlmsg,
968 .print_less = nlmsg_less,