netsniff-ng: nlmsg: Print not dissected attribute type number
[netsniff-ng.git] / proto_nlmsg.c
blob04f261d4aeaf006ed7d4aa7b4ce117b0df61846d
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 #define attr_fmt(attr, fmt, ...) \
44 tprintf("\tA: "fmt, ##__VA_ARGS__); \
45 tprintf(", Len %d\n", RTA_LEN(attr));
47 struct flag_name {
48 const char *name;
49 unsigned int flag;
52 static const char *flags2str(struct flag_name *tbl, unsigned int flags,
53 char *buf, int len)
55 int bits_stay = flags;
57 memset(buf, 0, len);
59 for (; tbl && tbl->name; tbl++) {
60 if (!(tbl->flag & flags))
61 continue;
63 bits_stay &= ~tbl->flag;
64 strncat(buf, tbl->name, len - strlen(buf) - 1);
66 if (bits_stay & flags)
67 strncat(buf, ",", len - strlen(buf) - 1);
70 return buf;
73 static const char *nlmsg_family2str(uint16_t family)
75 switch (family) {
76 case NETLINK_ROUTE: return "routing";
77 case NETLINK_UNUSED: return "unused";
78 case NETLINK_USERSOCK: return "user-mode socket";
79 case NETLINK_FIREWALL: return "unused, formerly ip_queue";
80 /* NETLINK_INET_DIAG was renamed to NETLINK_SOCK_DIAG in Linux kernel 3.10 */
81 #if defined(NETLINK_SOCK_DIAG)
82 case NETLINK_SOCK_DIAG: return "socket monitoring";
83 #elif defined(NETLINK_INET_DIAG)
84 case NETLINK_INET_DIAG: return "INET socket monitoring";
85 #endif
86 case NETLINK_NFLOG: return "netfilter ULOG";
87 case NETLINK_XFRM: return "IPsec";
88 case NETLINK_SELINUX: return "SELinux event notification";
89 case NETLINK_ISCSI: return "Open-iSCSI";
90 case NETLINK_AUDIT: return "auditing";
91 case NETLINK_FIB_LOOKUP: return "FIB lookup";
92 case NETLINK_CONNECTOR: return "Kernel connector";
93 case NETLINK_NETFILTER: return "Netfilter";
94 case NETLINK_IP6_FW: return "unused, formerly ip6_queue";
95 case NETLINK_DNRTMSG: return "DECnet routing";
96 case NETLINK_KOBJECT_UEVENT: return "Kernel messages";
97 case NETLINK_GENERIC: return "Generic";
98 case NETLINK_SCSITRANSPORT: return "SCSI transports";
99 case NETLINK_ECRYPTFS: return "ecryptfs";
100 case NETLINK_RDMA: return "RDMA";
101 case NETLINK_CRYPTO: return "Crypto layer";
102 default: return "Unknown";
106 static const char *nlmsg_rtnl_type2str(uint16_t type)
108 switch (type) {
109 case RTM_NEWLINK: return "new link";
110 case RTM_DELLINK: return "del link";
111 case RTM_GETLINK: return "get link";
112 case RTM_SETLINK: return "set link";
114 case RTM_NEWADDR: return "new addr";
115 case RTM_DELADDR: return "del addr";
116 case RTM_GETADDR: return "get addr";
118 case RTM_NEWROUTE: return "new route";
119 case RTM_DELROUTE: return "del route";
120 case RTM_GETROUTE: return "get route";
122 case RTM_NEWNEIGH: return "new neigh";
123 case RTM_DELNEIGH: return "del neigh";
124 case RTM_GETNEIGH: return "get neigh";
126 case RTM_NEWRULE: return "new rule";
127 case RTM_DELRULE: return "del rule";
128 case RTM_GETRULE: return "get rule";
130 case RTM_NEWQDISC: return "new tc qdisc";
131 case RTM_DELQDISC: return "del tc qdisc";
132 case RTM_GETQDISC: return "get tc qdisc";
134 case RTM_NEWTCLASS: return "new tc class";
135 case RTM_DELTCLASS: return "del tc class";
136 case RTM_GETTCLASS: return "get tc class";
138 case RTM_NEWTFILTER: return "new tc filter";
139 case RTM_DELTFILTER: return "del tc filter";
140 case RTM_GETTFILTER: return "get tc filter";
142 case RTM_NEWACTION: return "new tc action";
143 case RTM_DELACTION: return "del tc action";
144 case RTM_GETACTION: return "get tc action";
146 case RTM_NEWPREFIX: return "new prefix";
148 case RTM_GETMULTICAST: return "get mcast addr";
150 case RTM_GETANYCAST: return "get anycast addr";
152 case RTM_NEWNEIGHTBL: return "new neigh table";
153 case RTM_GETNEIGHTBL: return "get neigh table";
154 case RTM_SETNEIGHTBL: return "set neigh table";
156 case RTM_NEWNDUSEROPT: return "new ndisc user option";
158 case RTM_NEWADDRLABEL: return "new addr label";
159 case RTM_DELADDRLABEL: return "del addr label";
160 case RTM_GETADDRLABEL: return "get addr label";
162 case RTM_GETDCB: return "get data-center-bridge";
163 case RTM_SETDCB: return "set data-center-bridge";
165 #if defined(RTM_NEWNETCONF)
166 case RTM_NEWNETCONF: return "new netconf";
167 case RTM_GETNETCONF: return "get netconf";
168 #endif
170 #if defined(RTM_NEWMDB)
171 case RTM_NEWMDB: return "new bridge mdb";
172 case RTM_DELMDB: return "del bridge mdb";
173 case RTM_GETMDB: return "get bridge mdb";
174 #endif
175 default: return NULL;
179 static char *nlmsg_type2str(uint16_t proto, uint16_t type, char *buf, int len)
181 if (proto == NETLINK_ROUTE && type < RTM_MAX) {
182 const char *name = nlmsg_rtnl_type2str(type);
183 if (name) {
184 strncpy(buf, name, len);
185 return buf;
189 return nl_nlmsgtype2str(type, buf, len);
192 static const char *addr_family2str(uint16_t family)
194 switch (family) {
195 case AF_INET: return "ipv4";
196 case AF_INET6: return "ipv6";
197 case AF_DECnet: return "decnet";
198 case AF_IPX: return "ipx";
199 default: return "Unknown";
203 static const char *addr2str(uint16_t af, const void *addr, char *buf, int blen)
205 if (af == AF_INET || af == AF_INET6)
206 return inet_ntop(af, addr, buf, blen);
208 return "???";
211 static const char *scope2str(uint8_t scope)
213 switch (scope) {
214 case RT_SCOPE_UNIVERSE: return "global";
215 case RT_SCOPE_LINK: return "link";
216 case RT_SCOPE_HOST: return "host";
217 case RT_SCOPE_NOWHERE: return "nowhere";
219 default: return "Unknown";
223 static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
225 struct ifinfomsg *ifi = NLMSG_DATA(hdr);
226 struct rtattr *attr = IFLA_RTA(ifi);
227 uint32_t attrs_len = IFLA_PAYLOAD(hdr);
228 char flags[256];
229 char if_addr[64] = {};
230 char *af_link = "unknown";
232 if (ifi->ifi_family == AF_UNSPEC)
233 af_link = "unspec";
234 else if (ifi->ifi_family == AF_BRIDGE)
235 af_link = "bridge";
237 tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
238 colorize_start(bold), af_link, colorize_end());
239 tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
240 colorize_start(bold),
241 device_type2str(ifi->ifi_type),
242 colorize_end());
243 tprintf(", Index %d", ifi->ifi_index);
244 tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
245 colorize_start(bold),
246 rtnl_link_flags2str(ifi->ifi_flags, flags,
247 sizeof(flags)),
248 colorize_end());
249 tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
250 colorize_start(bold),
251 rtnl_link_flags2str(ifi->ifi_change, flags,
252 sizeof(flags)),
253 colorize_end());
255 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
256 switch (attr->rta_type) {
257 case IFLA_ADDRESS:
258 attr_fmt(attr, "Address %s",
259 device_addr2str(RTA_DATA(attr),
260 RTA_LEN(attr), ifi->ifi_type,
261 if_addr, sizeof(if_addr)));
262 break;
263 case IFLA_BROADCAST:
264 attr_fmt(attr, "Broadcast %s",
265 device_addr2str(RTA_DATA(attr),
266 RTA_LEN(attr), ifi->ifi_type,
267 if_addr, sizeof(if_addr)));
268 break;
269 case IFLA_IFNAME:
270 attr_fmt(attr, "Name %s%s%s",
271 colorize_start(bold), RTA_STR(attr),
272 colorize_end());
273 break;
274 case IFLA_MTU:
275 attr_fmt(attr, "MTU %d", RTA_INT(attr));
276 break;
277 case IFLA_LINK:
278 attr_fmt(attr, "Link %d", RTA_INT(attr));
279 break;
280 case IFLA_QDISC:
281 attr_fmt(attr, "QDisc %s", RTA_STR(attr));
282 break;
283 case IFLA_OPERSTATE:
285 uint8_t st = RTA_UINT8(attr);
286 char states[256];
288 attr_fmt(attr, "Operation state 0x%x (%s%s%s)",
290 colorize_start(bold),
291 rtnl_link_operstate2str(st,
292 states, sizeof(states)),
293 colorize_end());
295 break;
296 case IFLA_LINKMODE:
298 uint8_t mode = RTA_UINT8(attr);
299 char str[32];
301 attr_fmt(attr, "Mode 0x%x (%s%s%s)", mode,
302 colorize_start(bold),
303 rtnl_link_mode2str(mode, str,
304 sizeof(str)),
305 colorize_end());
307 break;
308 case IFLA_GROUP:
309 attr_fmt(attr, "Group %d", RTA_INT(attr));
310 break;
311 case IFLA_TXQLEN:
312 attr_fmt(attr, "Tx queue len %d", RTA_INT(attr));
313 break;
314 case IFLA_NET_NS_PID:
315 attr_fmt(attr, "Network namespace pid %d",
316 RTA_INT(attr));
317 break;
318 case IFLA_NET_NS_FD:
319 attr_fmt(attr, "Network namespace fd %d",
320 RTA_INT(attr));
321 break;
322 default:
323 attr_fmt(attr, "0x%x", attr->rta_type);
324 break;
329 static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
331 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
332 uint32_t attrs_len = IFA_PAYLOAD(hdr);
333 struct rtattr *attr = IFA_RTA(ifa);
334 struct ifa_cacheinfo *ci;
335 char addr_str[256];
336 char flags[256];
338 tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
339 colorize_start(bold),
340 addr_family2str(ifa->ifa_family),
341 colorize_end());
342 tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
343 tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
344 colorize_start(bold),
345 rtnl_addr_flags2str(ifa->ifa_flags, flags,
346 sizeof(flags)),
347 colorize_end());
348 tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
349 colorize_start(bold),
350 scope2str(ifa->ifa_scope),
351 colorize_end());
352 tprintf(", Link Index %d ]\n", ifa->ifa_index);
354 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
355 switch (attr->rta_type) {
356 case IFA_LOCAL:
357 attr_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
358 RTA_DATA(attr), addr_str, sizeof(addr_str)));
359 break;
360 case IFA_ADDRESS:
361 attr_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
362 RTA_DATA(attr), addr_str, sizeof(addr_str)));
363 break;
364 case IFA_BROADCAST:
365 attr_fmt(attr, "Broadcast %s",
366 addr2str(ifa->ifa_family,
367 RTA_DATA(attr), addr_str,
368 sizeof(addr_str)));
369 break;
370 case IFA_MULTICAST:
371 attr_fmt(attr, "Multicast %s",
372 addr2str(ifa->ifa_family,
373 RTA_DATA(attr), addr_str,
374 sizeof(addr_str)));
375 break;
376 case IFA_ANYCAST:
377 attr_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
378 RTA_DATA(attr), addr_str, sizeof(addr_str)));
379 break;
380 #ifdef IFA_FLAGS
381 case IFA_FLAGS:
382 attr_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
383 colorize_start(bold),
384 rtnl_addr_flags2str(RTA_INT(attr),
385 flags, sizeof(flags)),
386 colorize_end());
387 break;
388 #endif
389 case IFA_LABEL:
390 attr_fmt(attr, "Label %s", RTA_STR(attr));
391 break;
392 case IFA_CACHEINFO:
393 ci = RTA_DATA(attr);
394 tprintf("\tA: Cache (");
396 if (ci->ifa_valid == INFINITY)
397 tprintf("valid lft(forever)");
398 else
399 tprintf("valid lft(%us)", ci->ifa_valid);
401 if (ci->ifa_prefered == INFINITY)
402 tprintf(", prefrd lft(forever)");
403 else
404 tprintf(", prefrd lft(%us)", ci->ifa_prefered);
406 tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
407 tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
408 tprintf(", Len %d\n", RTA_LEN(attr));
409 break;
410 default:
411 attr_fmt(attr, "0x%x", attr->rta_type);
412 break;
417 static const char *route_table2str(uint8_t table)
419 switch (table) {
420 case RT_TABLE_UNSPEC: return "unspec";
421 case RT_TABLE_COMPAT: return "compat";
422 case RT_TABLE_DEFAULT: return "default";
423 case RT_TABLE_MAIN: return "main";
424 case RT_TABLE_LOCAL: return "local";
426 default: return "Unknown";
430 static const char *route_proto2str(uint8_t proto)
432 switch (proto) {
433 case RTPROT_UNSPEC: return "unspec";
434 case RTPROT_REDIRECT: return "redirect";
435 case RTPROT_KERNEL: return "kernel";
436 case RTPROT_BOOT: return "boot";
437 case RTPROT_STATIC: return "static";
438 case RTPROT_GATED: return "gated";
439 case RTPROT_RA: return "ra";
440 case RTPROT_MRT: return "mrt";
441 case RTPROT_ZEBRA: return "zebra";
442 case RTPROT_BIRD: return "bird";
443 case RTPROT_DNROUTED: return "DECnet";
444 case RTPROT_XORP: return "xorp";
445 case RTPROT_NTK: return "netsukuku";
446 case RTPROT_DHCP: return "dhcpc";
447 #ifdef RTPROT_MROUTED
448 case RTPROT_MROUTED: return "mrouted";
449 #endif
451 default: return "Unknown";
455 static const char *route_type2str(uint8_t type)
457 switch (type) {
458 case RTN_UNSPEC: return "unspec";
459 case RTN_UNICAST: return "unicast";
460 case RTN_LOCAL: return "local";
461 case RTN_BROADCAST: return "broadcast";
462 case RTN_ANYCAST: return "anycast";
463 case RTN_MULTICAST: return "multicast";
464 case RTN_BLACKHOLE: return "blackhole";
465 case RTN_UNREACHABLE: return "unreach";
466 case RTN_PROHIBIT: return "prohibit";
467 case RTN_THROW: return "throw";
468 case RTN_NAT: return "nat";
469 case RTN_XRESOLVE: return "xresolve";
470 default: return "Unknown";
474 static struct flag_name route_flags[] = {
475 { "notify", RTM_F_NOTIFY },
476 { "cloned", RTM_F_CLONED },
477 { "equalize", RTM_F_EQUALIZE },
478 { "prefix", RTM_F_PREFIX },
479 { "dead", RTNH_F_DEAD },
480 { "pervasive", RTNH_F_PERVASIVE },
481 { "onlink", RTNH_F_ONLINK },
482 { NULL, 0 },
485 static void rtnl_print_route(struct nlmsghdr *hdr)
487 struct rtmsg *rtm = NLMSG_DATA(hdr);
488 uint32_t attrs_len = RTM_PAYLOAD(hdr);
489 struct rtattr *attr = RTM_RTA(rtm);
490 struct rta_cacheinfo *ci;
491 int hz = get_user_hz();
492 char addr_str[256];
493 char flags[256];
495 tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
496 colorize_start(bold),
497 addr_family2str(rtm->rtm_family),
498 colorize_end());
499 tprintf(", Dst Len %d", rtm->rtm_dst_len);
500 tprintf(", Src Len %d", rtm->rtm_src_len);
501 tprintf(", ToS %d", rtm->rtm_tos);
502 tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
503 colorize_start(bold),
504 route_table2str(rtm->rtm_table),
505 colorize_end());
506 tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
507 colorize_start(bold),
508 route_proto2str(rtm->rtm_protocol),
509 colorize_end());
510 tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
511 colorize_start(bold),
512 scope2str(rtm->rtm_scope),
513 colorize_end());
514 tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
515 colorize_start(bold),
516 route_type2str(rtm->rtm_type),
517 colorize_end());
518 tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
519 colorize_start(bold),
520 flags2str(route_flags, rtm->rtm_flags, flags,
521 sizeof(flags)),
522 colorize_end());
524 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
525 switch (attr->rta_type) {
526 case RTA_DST:
527 attr_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
528 RTA_DATA(attr), addr_str, sizeof(addr_str)));
529 break;
530 case RTA_SRC:
531 attr_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
532 RTA_DATA(attr), addr_str, sizeof(addr_str)));
533 break;
534 case RTA_IIF:
535 attr_fmt(attr, "Iif %d", RTA_INT(attr));
536 break;
537 case RTA_OIF:
538 attr_fmt(attr, "Oif %d", RTA_INT(attr));
539 break;
540 case RTA_GATEWAY:
541 attr_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
542 RTA_DATA(attr), addr_str, sizeof(addr_str)));
543 break;
544 case RTA_PRIORITY:
545 attr_fmt(attr, "Priority %u", RTA_UINT32(attr));
546 break;
547 case RTA_PREFSRC:
548 attr_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
549 RTA_DATA(attr), addr_str, sizeof(addr_str)));
550 break;
551 case RTA_MARK:
552 attr_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
553 break;
554 case RTA_FLOW:
555 attr_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
556 break;
557 case RTA_TABLE:
558 attr_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
559 colorize_start(bold),
560 route_table2str(RTA_UINT32(attr)),
561 colorize_end());
562 break;
563 case RTA_CACHEINFO:
564 ci = RTA_DATA(attr);
565 tprintf("\tA: Cache (");
566 tprintf("expires(%ds)", ci->rta_expires / hz);
567 tprintf(", error(%d)", ci->rta_error);
568 tprintf(", users(%d)", ci->rta_clntref);
569 tprintf(", used(%d)", ci->rta_used);
570 tprintf(", last use(%ds)", ci->rta_lastuse / hz);
571 tprintf(", id(%d)", ci->rta_id);
572 tprintf(", ts(%d)", ci->rta_ts);
573 tprintf(", ts age(%ds))", ci->rta_tsage);
574 tprintf(", Len %d\n", RTA_LEN(attr));
575 break;
576 default:
577 attr_fmt(attr, "0x%x", attr->rta_type);
578 break;
583 static struct flag_name neigh_states[] = {
584 { "incomplete", NUD_INCOMPLETE },
585 { "reachable", NUD_REACHABLE },
586 { "stale", NUD_STALE },
587 { "delay", NUD_DELAY },
588 { "probe", NUD_PROBE },
589 { "failed", NUD_FAILED },
590 { "noarp", NUD_NOARP },
591 { "permanent", NUD_PERMANENT },
592 { "none", NUD_NONE },
593 { NULL, 0 },
596 /* Copied from linux/neighbour.h */
597 #ifndef NTF_USE
598 # define NTF_USE 0x01
599 #endif
600 #ifndef NTF_SELF
601 # define NTF_SELF 0x02
602 #endif
603 #ifndef NTF_MASTER
604 # define NTF_MASTER 0x04
605 #endif
606 #ifndef NTF_PROXY
607 # define NTF_PROXY 0x08
608 #endif
609 #ifndef NTF_EXT_LEARNED
610 # define NTF_EXT_LEARNED 0x10
611 #endif
612 #ifndef NTF_ROUTER
613 # define NTF_ROUTER 0x80
614 #endif
616 static struct flag_name neigh_flags[] = {
617 { "use", NTF_USE },
618 { "self", NTF_SELF },
619 { "master", NTF_MASTER },
620 { "proxy", NTF_PROXY },
621 { "ext learned", NTF_EXT_LEARNED },
622 { "router", NTF_ROUTER },
623 { NULL, 0 },
626 static void rtnl_print_neigh(struct nlmsghdr *hdr)
628 struct ndmsg *ndm = NLMSG_DATA(hdr);
629 uint32_t attrs_len = NDA_PAYLOAD(hdr);
630 struct rtattr *attr = NDA_RTA(ndm);
631 struct nda_cacheinfo *ci;
632 int hz = get_user_hz();
633 char addr_str[256];
634 char hw_addr[30];
635 char states[256];
636 char flags[256];
638 tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
639 colorize_start(bold),
640 addr_family2str(ndm->ndm_family),
641 colorize_end());
642 tprintf(", Link Index %d", ndm->ndm_ifindex);
643 tprintf(", State %d (%s%s%s)", ndm->ndm_state,
644 colorize_start(bold),
645 flags2str(neigh_states, ndm->ndm_state, states,
646 sizeof(states)),
647 colorize_end());
648 tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
649 colorize_start(bold),
650 flags2str(neigh_flags, ndm->ndm_flags, flags,
651 sizeof(flags)),
652 colorize_end());
653 tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
654 colorize_start(bold),
655 route_type2str(ndm->ndm_type),
656 colorize_end());
657 tprintf(" ]\n");
659 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
660 switch (attr->rta_type) {
661 case NDA_DST:
662 attr_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
663 RTA_DATA(attr), addr_str,
664 sizeof(addr_str)));
665 break;
666 case NDA_LLADDR:
667 attr_fmt(attr, "HW Address %s",
668 device_addr2str(RTA_DATA(attr),
669 RTA_LEN(attr), 0, hw_addr,
670 sizeof(hw_addr)));
671 break;
672 case NDA_PROBES:
673 attr_fmt(attr, "Probes %d", RTA_UINT32(attr));
674 break;
675 case NDA_CACHEINFO:
676 ci = RTA_DATA(attr);
677 tprintf("\tA: Cache (");
678 tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
679 tprintf(", used(%ds)", ci->ndm_used / hz);
680 tprintf(", updated(%ds)", ci->ndm_updated / hz);
681 tprintf(", refcnt(%d))", ci->ndm_refcnt);
682 tprintf(", Len %d\n", RTA_LEN(attr));
683 break;
684 default:
685 attr_fmt(attr, "0x%x", attr->rta_type);
686 break;
691 static void rtnl_msg_print(struct nlmsghdr *hdr)
693 switch (hdr->nlmsg_type) {
694 case RTM_NEWLINK:
695 case RTM_DELLINK:
696 case RTM_GETLINK:
697 case RTM_SETLINK:
698 rtnl_print_ifinfo(hdr);
699 break;
700 case RTM_NEWADDR:
701 case RTM_DELADDR:
702 case RTM_GETADDR:
703 rtnl_print_ifaddr(hdr);
704 break;
705 case RTM_NEWROUTE:
706 case RTM_DELROUTE:
707 case RTM_GETROUTE:
708 rtnl_print_route(hdr);
709 break;
710 case RTM_NEWNEIGH:
711 case RTM_DELNEIGH:
712 case RTM_GETNEIGH:
713 rtnl_print_neigh(hdr);
714 break;
718 static void nlmsg_print_raw(struct nlmsghdr *hdr)
720 u32 len = hdr->nlmsg_len;
722 if (len) {
723 _ascii((uint8_t *) hdr + NLMSG_HDRLEN, len - NLMSG_HDRLEN);
724 _hex((uint8_t *) hdr + NLMSG_HDRLEN, len - NLMSG_HDRLEN);
728 static void nlmsg_print(uint16_t family, struct nlmsghdr *hdr)
730 u16 nlmsg_flags = hdr->nlmsg_flags;
731 char type[32];
732 char flags[128];
733 char procname[PATH_MAX];
735 /* Look up the process name if message is not coming from the kernel.
737 * Note that the port id is not necessarily equal to the PID of the
738 * receiving process (e.g. if the application is multithreaded or using
739 * multiple sockets). In these cases we're not able to find a matching
740 * PID and the information will not be printed.
742 if (hdr->nlmsg_pid != 0) {
743 if (proc_get_cmdline(hdr->nlmsg_pid, procname, sizeof(procname)) < 0)
744 snprintf(procname, sizeof(procname), "unknown process");
745 } else
746 snprintf(procname, sizeof(procname), "kernel");
748 tprintf(" [ NLMSG ");
749 tprintf("Family %d (%s%s%s), ", family,
750 colorize_start(bold),
751 nlmsg_family2str(family),
752 colorize_end());
753 tprintf("Len %u, ", hdr->nlmsg_len);
754 tprintf("Type 0x%.4x (%s%s%s), ", hdr->nlmsg_type,
755 colorize_start(bold),
756 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
757 colorize_end());
758 tprintf("Flags 0x%.4x (%s%s%s), ", nlmsg_flags,
759 colorize_start(bold),
760 nlmsg_flags ? nl_nlmsg_flags2str(nlmsg_flags, flags, sizeof(flags)) : "none",
761 colorize_end());
762 tprintf("Seq-Nr %u, ", hdr->nlmsg_seq);
763 tprintf("PID %u", hdr->nlmsg_pid);
764 if (procname[0])
765 tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
766 colorize_end());
767 tprintf(" ]\n");
769 if (family == NETLINK_ROUTE)
770 rtnl_msg_print(hdr);
771 else
772 nlmsg_print_raw(hdr);
775 static void nlmsg(struct pkt_buff *pkt)
777 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
778 unsigned int trim_len = pkt_len(pkt);
780 while (hdr) {
781 trim_len -= hdr->nlmsg_len;
782 nlmsg_print(ntohs(pkt->sll->sll_protocol), hdr);
784 if (!pkt_pull(pkt, NLMSG_ALIGN(hdr->nlmsg_len) - NLMSG_HDRLEN))
785 break;
787 hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
788 if (hdr == NULL)
789 break;
790 if (hdr->nlmsg_len == 0)
791 break;
793 if (hdr->nlmsg_type != NLMSG_DONE &&
794 (hdr->nlmsg_flags & NLM_F_MULTI))
795 tprintf("\n");
798 /* mmaped packet? */
799 if (hdr && hdr->nlmsg_len == 0)
800 pkt_trim(pkt, trim_len);
803 static void nlmsg_less(struct pkt_buff *pkt)
805 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
806 uint16_t family = ntohs(pkt->sll->sll_protocol);
807 char type[32];
809 if (hdr == NULL)
810 return;
812 tprintf(" NLMSG Family %d (%s%s%s), ", family,
813 colorize_start(bold),
814 nlmsg_family2str(family),
815 colorize_end());
816 tprintf("Type %u (%s%s%s)", hdr->nlmsg_type,
817 colorize_start(bold),
818 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
819 colorize_end());
822 struct protocol nlmsg_ops = {
823 .print_full = nlmsg,
824 .print_less = nlmsg_less,