make: Create containing directories for manpages if not existent
[netsniff-ng.git] / proto_nlmsg.c
blob44ef32825b2132cfeb53e654983e47715be3f6f5
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 "proto.h"
21 #include "protos.h"
22 #include "timer.h"
24 #define INFINITY 0xFFFFFFFFU
26 #define RTA_LEN(attr) RTA_PAYLOAD(attr)
27 #define RTA_INT(attr) (*(int *)RTA_DATA(attr))
28 #define RTA_UINT(attr) (*(unsigned int *)RTA_DATA(attr))
29 #define RTA_UINT8(attr) (*(uint8_t *)RTA_DATA(attr))
30 #define RTA_UINT32(attr) (*(uint32_t *)RTA_DATA(attr))
31 #define RTA_STR(attr) ((char *)RTA_DATA(attr))
33 #ifndef NDA_RTA
34 #define NDA_RTA(r) \
35 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
36 #endif
38 #ifndef NDA_PAYLOAD
39 #define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
40 #endif
42 #define attr_fmt(attr, fmt, ...) \
43 tprintf("\tA: "fmt, ##__VA_ARGS__); \
44 tprintf(", Len %lu\n", RTA_LEN(attr));
46 struct flag_name {
47 const char *name;
48 unsigned int flag;
51 static const char *flags2str(struct flag_name *tbl, unsigned int flags,
52 char *buf, int len)
54 int bits_stay = flags;
56 memset(buf, 0, len);
58 for (; tbl && tbl->name; tbl++) {
59 if (!(tbl->flag & flags))
60 continue;
62 bits_stay &= ~tbl->flag;
63 strncat(buf, tbl->name, len - strlen(buf) - 1);
65 if (bits_stay & flags)
66 strncat(buf, ",", len - strlen(buf) - 1);
69 return buf;
72 static const char *nlmsg_family2str(uint16_t family)
74 switch (family) {
75 case NETLINK_ROUTE: return "routing";
76 case NETLINK_UNUSED: return "unused";
77 case NETLINK_USERSOCK: return "user-mode socket";
78 case NETLINK_FIREWALL: return "unused, formerly ip_queue";
79 /* NETLINK_INET_DIAG was renamed to NETLINK_SOCK_DIAG in Linux kernel 3.10 */
80 #if defined(NETLINK_SOCK_DIAG)
81 case NETLINK_SOCK_DIAG: return "socket monitoring";
82 #elif defined(NETLINK_INET_DIAG)
83 case NETLINK_INET_DIAG: return "INET socket monitoring";
84 #endif
85 case NETLINK_NFLOG: return "netfilter ULOG";
86 case NETLINK_XFRM: return "IPsec";
87 case NETLINK_SELINUX: return "SELinux event notification";
88 case NETLINK_ISCSI: return "Open-iSCSI";
89 case NETLINK_AUDIT: return "auditing";
90 case NETLINK_FIB_LOOKUP: return "FIB lookup";
91 case NETLINK_CONNECTOR: return "Kernel connector";
92 case NETLINK_NETFILTER: return "Netfilter";
93 case NETLINK_IP6_FW: return "unused, formerly ip6_queue";
94 case NETLINK_DNRTMSG: return "DECnet routing";
95 case NETLINK_KOBJECT_UEVENT: return "Kernel messages";
96 case NETLINK_GENERIC: return "Generic";
97 case NETLINK_SCSITRANSPORT: return "SCSI transports";
98 case NETLINK_ECRYPTFS: return "ecryptfs";
99 case NETLINK_RDMA: return "RDMA";
100 case NETLINK_CRYPTO: return "Crypto layer";
101 default: return "Unknown";
105 static const char *nlmsg_rtnl_type2str(uint16_t type)
107 switch (type) {
108 case RTM_NEWLINK: return "new link";
109 case RTM_DELLINK: return "del link";
110 case RTM_GETLINK: return "get link";
111 case RTM_SETLINK: return "set link";
113 case RTM_NEWADDR: return "new addr";
114 case RTM_DELADDR: return "del addr";
115 case RTM_GETADDR: return "get addr";
117 case RTM_NEWROUTE: return "new route";
118 case RTM_DELROUTE: return "del route";
119 case RTM_GETROUTE: return "get route";
121 case RTM_NEWNEIGH: return "new neigh";
122 case RTM_DELNEIGH: return "del neigh";
123 case RTM_GETNEIGH: return "get neigh";
125 case RTM_NEWRULE: return "new rule";
126 case RTM_DELRULE: return "del rule";
127 case RTM_GETRULE: return "get rule";
129 case RTM_NEWQDISC: return "new tc qdisc";
130 case RTM_DELQDISC: return "del tc qdisc";
131 case RTM_GETQDISC: return "get tc qdisc";
133 case RTM_NEWTCLASS: return "new tc class";
134 case RTM_DELTCLASS: return "del tc class";
135 case RTM_GETTCLASS: return "get tc class";
137 case RTM_NEWTFILTER: return "new tc filter";
138 case RTM_DELTFILTER: return "del tc filter";
139 case RTM_GETTFILTER: return "get tc filter";
141 case RTM_NEWACTION: return "new tc action";
142 case RTM_DELACTION: return "del tc action";
143 case RTM_GETACTION: return "get tc action";
145 case RTM_NEWPREFIX: return "new prefix";
147 case RTM_GETMULTICAST: return "get mcast addr";
149 case RTM_GETANYCAST: return "get anycast addr";
151 case RTM_NEWNEIGHTBL: return "new neigh table";
152 case RTM_GETNEIGHTBL: return "get neigh table";
153 case RTM_SETNEIGHTBL: return "set neigh table";
155 case RTM_NEWNDUSEROPT: return "new ndisc user option";
157 case RTM_NEWADDRLABEL: return "new addr label";
158 case RTM_DELADDRLABEL: return "del addr label";
159 case RTM_GETADDRLABEL: return "get addr label";
161 case RTM_GETDCB: return "get data-center-bridge";
162 case RTM_SETDCB: return "set data-center-bridge";
164 #if defined(RTM_NEWNETCONF)
165 case RTM_NEWNETCONF: return "new netconf";
166 case RTM_GETNETCONF: return "get netconf";
167 #endif
169 #if defined(RTM_NEWMDB)
170 case RTM_NEWMDB: return "new bridge mdb";
171 case RTM_DELMDB: return "del bridge mdb";
172 case RTM_GETMDB: return "get bridge mdb";
173 #endif
174 default: return NULL;
178 static char *nlmsg_type2str(uint16_t proto, uint16_t type, char *buf, int len)
180 if (proto == NETLINK_ROUTE && type < RTM_MAX) {
181 const char *name = nlmsg_rtnl_type2str(type);
182 if (name) {
183 strncpy(buf, name, len);
184 return buf;
188 return nl_nlmsgtype2str(type, buf, len);
191 static const char *addr_family2str(uint16_t family)
193 switch (family) {
194 case AF_INET: return "ipv4";
195 case AF_INET6: return "ipv6";
196 case AF_DECnet: return "decnet";
197 case AF_IPX: return "ipx";
198 default: return "Unknown";
202 static const char *addr2str(uint16_t af, const void *addr, char *buf, int blen)
204 if (af == AF_INET || af == AF_INET6)
205 return inet_ntop(af, addr, buf, blen);
207 return "???";
210 static const char *scope2str(uint8_t scope)
212 switch (scope) {
213 case RT_SCOPE_UNIVERSE: return "global";
214 case RT_SCOPE_LINK: return "link";
215 case RT_SCOPE_HOST: return "host";
216 case RT_SCOPE_NOWHERE: return "nowhere";
218 default: return "Unknown";
222 static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
224 struct ifinfomsg *ifi = NLMSG_DATA(hdr);
225 struct rtattr *attr = IFLA_RTA(ifi);
226 uint32_t attrs_len = IFLA_PAYLOAD(hdr);
227 char flags[256];
228 char if_addr[64] = {};
229 char *af_link = "Unknown";
231 if (ifi->ifi_family == AF_UNSPEC)
232 af_link = "unspec";
233 else if (ifi->ifi_family == AF_BRIDGE)
234 af_link = "bridge";
236 tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
237 colorize_start(bold), af_link, colorize_end());
238 tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
239 colorize_start(bold),
240 device_type2str(ifi->ifi_type),
241 colorize_end());
242 tprintf(", Index %d", ifi->ifi_index);
243 tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
244 colorize_start(bold),
245 rtnl_link_flags2str(ifi->ifi_flags, flags,
246 sizeof(flags)),
247 colorize_end());
248 tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
249 colorize_start(bold),
250 rtnl_link_flags2str(ifi->ifi_change, flags,
251 sizeof(flags)),
252 colorize_end());
254 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
255 switch (attr->rta_type) {
256 case IFLA_ADDRESS:
257 attr_fmt(attr, "Address %s",
258 device_addr2str(RTA_DATA(attr),
259 RTA_LEN(attr), ifi->ifi_type,
260 if_addr, sizeof(if_addr)));
261 break;
262 case IFLA_BROADCAST:
263 attr_fmt(attr, "Broadcast %s",
264 device_addr2str(RTA_DATA(attr),
265 RTA_LEN(attr), ifi->ifi_type,
266 if_addr, sizeof(if_addr)));
267 break;
268 case IFLA_IFNAME:
269 attr_fmt(attr, "Name %s%s%s",
270 colorize_start(bold), RTA_STR(attr),
271 colorize_end());
272 break;
273 case IFLA_MTU:
274 attr_fmt(attr, "MTU %d", RTA_INT(attr));
275 break;
276 case IFLA_LINK:
277 attr_fmt(attr, "Link %d", RTA_INT(attr));
278 break;
279 case IFLA_QDISC:
280 attr_fmt(attr, "QDisc %s", RTA_STR(attr));
281 break;
282 case IFLA_OPERSTATE:
284 uint8_t st = RTA_UINT8(attr);
285 char states[256];
287 attr_fmt(attr, "Operation state 0x%x (%s%s%s)",
289 colorize_start(bold),
290 rtnl_link_operstate2str(st,
291 states, sizeof(states)),
292 colorize_end());
294 break;
295 case IFLA_LINKMODE:
297 uint8_t mode = RTA_UINT8(attr);
298 char str[32];
300 attr_fmt(attr, "Mode 0x%x (%s%s%s)", mode,
301 colorize_start(bold),
302 rtnl_link_mode2str(mode, str,
303 sizeof(str)),
304 colorize_end());
306 break;
307 case IFLA_GROUP:
308 attr_fmt(attr, "Group %d", RTA_INT(attr));
309 break;
310 case IFLA_TXQLEN:
311 attr_fmt(attr, "Tx queue len %d", RTA_INT(attr));
312 break;
313 case IFLA_NET_NS_PID:
314 attr_fmt(attr, "Network namespace pid %d",
315 RTA_INT(attr));
316 break;
317 case IFLA_NET_NS_FD:
318 attr_fmt(attr, "Network namespace fd %d",
319 RTA_INT(attr));
320 break;
325 static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
327 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
328 uint32_t attrs_len = IFA_PAYLOAD(hdr);
329 struct rtattr *attr = IFA_RTA(ifa);
330 struct ifa_cacheinfo *ci;
331 char addr_str[256];
332 char flags[256];
334 tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
335 colorize_start(bold),
336 addr_family2str(ifa->ifa_family),
337 colorize_end());
338 tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
339 tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
340 colorize_start(bold),
341 rtnl_addr_flags2str(ifa->ifa_flags, flags,
342 sizeof(flags)),
343 colorize_end());
344 tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
345 colorize_start(bold),
346 scope2str(ifa->ifa_scope),
347 colorize_end());
348 tprintf(", Link Index %d ]\n", ifa->ifa_index);
350 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
351 switch (attr->rta_type) {
352 case IFA_LOCAL:
353 attr_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
354 RTA_DATA(attr), addr_str, sizeof(addr_str)));
355 break;
356 case IFA_ADDRESS:
357 attr_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
358 RTA_DATA(attr), addr_str, sizeof(addr_str)));
359 break;
360 case IFA_BROADCAST:
361 attr_fmt(attr, "Broadcast %s",
362 addr2str(ifa->ifa_family,
363 RTA_DATA(attr), addr_str,
364 sizeof(addr_str)));
365 break;
366 case IFA_MULTICAST:
367 attr_fmt(attr, "Multicast %s",
368 addr2str(ifa->ifa_family,
369 RTA_DATA(attr), addr_str,
370 sizeof(addr_str)));
371 break;
372 case IFA_ANYCAST:
373 attr_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
374 RTA_DATA(attr), addr_str, sizeof(addr_str)));
375 break;
376 #ifdef IFA_FLAGS
377 case IFA_FLAGS:
378 attr_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
379 colorize_start(bold),
380 rtnl_addr_flags2str(RTA_INT(attr),
381 flags, sizeof(flags)),
382 colorize_end());
383 break;
384 #endif
385 case IFA_LABEL:
386 attr_fmt(attr, "Label %s", RTA_STR(attr));
387 break;
388 case IFA_CACHEINFO:
389 ci = RTA_DATA(attr);
390 tprintf("\tA: Cache (");
392 if (ci->ifa_valid == INFINITY)
393 tprintf("valid lft(forever)");
394 else
395 tprintf("valid lft(%us)", ci->ifa_valid);
397 if (ci->ifa_prefered == INFINITY)
398 tprintf(", prefrd lft(forever)");
399 else
400 tprintf(", prefrd lft(%us)", ci->ifa_prefered);
402 tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
403 tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
404 tprintf(", Len %lu\n", RTA_LEN(attr));
405 break;
410 static const char *route_table2str(uint8_t table)
412 switch (table) {
413 case RT_TABLE_UNSPEC: return "unspec";
414 case RT_TABLE_COMPAT: return "compat";
415 case RT_TABLE_DEFAULT: return "default";
416 case RT_TABLE_MAIN: return "main";
417 case RT_TABLE_LOCAL: return "local";
419 default: return "Unknown";
423 static const char *route_proto2str(uint8_t proto)
425 switch (proto) {
426 case RTPROT_UNSPEC: return "unspec";
427 case RTPROT_REDIRECT: return "redirect";
428 case RTPROT_KERNEL: return "kernel";
429 case RTPROT_BOOT: return "boot";
430 case RTPROT_STATIC: return "static";
431 case RTPROT_GATED: return "gated";
432 case RTPROT_RA: return "ra";
433 case RTPROT_MRT: return "mrt";
434 case RTPROT_ZEBRA: return "zebra";
435 case RTPROT_BIRD: return "bird";
436 case RTPROT_DNROUTED: return "DECnet";
437 case RTPROT_XORP: return "xorp";
438 case RTPROT_NTK: return "netsukuku";
439 case RTPROT_DHCP: return "dhcpc";
440 #ifdef RTPROT_MROUTED
441 case RTPROT_MROUTED: return "mrouted";
442 #endif
444 default: return "Unknown";
448 static const char *route_type2str(uint8_t type)
450 switch (type) {
451 case RTN_UNSPEC: return "unspec";
452 case RTN_UNICAST: return "unicast";
453 case RTN_LOCAL: return "local";
454 case RTN_BROADCAST: return "broadcast";
455 case RTN_ANYCAST: return "anycast";
456 case RTN_MULTICAST: return "multicast";
457 case RTN_BLACKHOLE: return "blackhole";
458 case RTN_UNREACHABLE: return "unreach";
459 case RTN_PROHIBIT: return "prohibit";
460 case RTN_THROW: return "throw";
461 case RTN_NAT: return "nat";
462 case RTN_XRESOLVE: return "xresolve";
464 default: return "Unknown";
468 static struct flag_name route_flags[] = {
469 { "notify", RTM_F_NOTIFY },
470 { "cloned", RTM_F_CLONED },
471 { "equalize", RTM_F_EQUALIZE },
472 { "prefix", RTM_F_PREFIX },
473 { "dead", RTNH_F_DEAD },
474 { "pervasive", RTNH_F_PERVASIVE },
475 { "onlink", RTNH_F_ONLINK },
476 { NULL, 0 },
479 static void rtnl_print_route(struct nlmsghdr *hdr)
481 struct rtmsg *rtm = NLMSG_DATA(hdr);
482 uint32_t attrs_len = RTM_PAYLOAD(hdr);
483 struct rtattr *attr = RTM_RTA(rtm);
484 struct rta_cacheinfo *ci;
485 int hz = get_user_hz();
486 char addr_str[256];
487 char flags[256];
489 tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
490 colorize_start(bold),
491 addr_family2str(rtm->rtm_family),
492 colorize_end());
493 tprintf(", Dst Len %d", rtm->rtm_dst_len);
494 tprintf(", Src Len %d", rtm->rtm_src_len);
495 tprintf(", ToS %d", rtm->rtm_tos);
496 tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
497 colorize_start(bold),
498 route_table2str(rtm->rtm_table),
499 colorize_end());
500 tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
501 colorize_start(bold),
502 route_proto2str(rtm->rtm_protocol),
503 colorize_end());
504 tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
505 colorize_start(bold),
506 scope2str(rtm->rtm_scope),
507 colorize_end());
508 tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
509 colorize_start(bold),
510 route_type2str(rtm->rtm_type),
511 colorize_end());
512 tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
513 colorize_start(bold),
514 flags2str(route_flags, rtm->rtm_flags, flags,
515 sizeof(flags)),
516 colorize_end());
518 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
519 switch (attr->rta_type) {
520 case RTA_DST:
521 attr_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
522 RTA_DATA(attr), addr_str, sizeof(addr_str)));
523 break;
524 case RTA_SRC:
525 attr_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
526 RTA_DATA(attr), addr_str, sizeof(addr_str)));
527 break;
528 case RTA_IIF:
529 attr_fmt(attr, "Iif %d", RTA_INT(attr));
530 break;
531 case RTA_OIF:
532 attr_fmt(attr, "Oif %d", RTA_INT(attr));
533 break;
534 case RTA_GATEWAY:
535 attr_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
536 RTA_DATA(attr), addr_str, sizeof(addr_str)));
537 break;
538 case RTA_PRIORITY:
539 attr_fmt(attr, "Priority %u", RTA_UINT32(attr));
540 break;
541 case RTA_PREFSRC:
542 attr_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
543 RTA_DATA(attr), addr_str, sizeof(addr_str)));
544 break;
545 case RTA_MARK:
546 attr_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
547 break;
548 case RTA_FLOW:
549 attr_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
550 break;
551 case RTA_TABLE:
552 attr_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
553 colorize_start(bold),
554 route_table2str(RTA_UINT32(attr)),
555 colorize_end());
556 break;
557 case RTA_CACHEINFO:
558 ci = RTA_DATA(attr);
559 tprintf("\tA: Cache (");
560 tprintf("expires(%ds)", ci->rta_expires / hz);
561 tprintf(", error(%d)", ci->rta_error);
562 tprintf(", users(%d)", ci->rta_clntref);
563 tprintf(", used(%d)", ci->rta_used);
564 tprintf(", last use(%ds)", ci->rta_lastuse / hz);
565 tprintf(", id(%d)", ci->rta_id);
566 tprintf(", ts(%d)", ci->rta_ts);
567 tprintf(", ts age(%ds))", ci->rta_tsage);
568 tprintf(", Len %lu\n", RTA_LEN(attr));
569 break;
574 static struct flag_name neigh_states[] = {
575 { "incomplete", NUD_INCOMPLETE },
576 { "reachable", NUD_REACHABLE },
577 { "stale", NUD_STALE },
578 { "delay", NUD_DELAY },
579 { "probe", NUD_PROBE },
580 { "failed", NUD_FAILED },
581 { "noarp", NUD_NOARP },
582 { "permanent", NUD_PERMANENT },
583 { "none", NUD_NONE },
584 { NULL, 0 },
587 static struct flag_name neigh_flags[] = {
588 { "use", NTF_USE },
589 { "self", NTF_SELF },
590 { "master", NTF_MASTER },
591 { "proxy", NTF_PROXY },
592 #ifdef NTF_EXT_LEARNED
593 { "ext learned", NTF_EXT_LEARNED },
594 #endif
595 { "router", NTF_ROUTER },
596 { NULL, 0 },
599 static void rtnl_print_neigh(struct nlmsghdr *hdr)
601 struct ndmsg *ndm = NLMSG_DATA(hdr);
602 uint32_t attrs_len = NDA_PAYLOAD(hdr);
603 struct rtattr *attr = NDA_RTA(ndm);
604 struct nda_cacheinfo *ci;
605 int hz = get_user_hz();
606 char addr_str[256];
607 char hw_addr[30];
608 char states[256];
609 char flags[256];
611 tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
612 colorize_start(bold),
613 addr_family2str(ndm->ndm_family),
614 colorize_end());
615 tprintf(", Link Index %d", ndm->ndm_ifindex);
616 tprintf(", State %d (%s%s%s)", ndm->ndm_state,
617 colorize_start(bold),
618 flags2str(neigh_states, ndm->ndm_state, states,
619 sizeof(states)),
620 colorize_end());
621 tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
622 colorize_start(bold),
623 flags2str(neigh_flags, ndm->ndm_flags, flags,
624 sizeof(flags)),
625 colorize_end());
626 tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
627 colorize_start(bold),
628 route_type2str(ndm->ndm_type),
629 colorize_end());
630 tprintf(" ]\n");
632 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
633 switch (attr->rta_type) {
634 case NDA_DST:
635 attr_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
636 RTA_DATA(attr), addr_str,
637 sizeof(addr_str)));
638 break;
639 case NDA_LLADDR:
640 attr_fmt(attr, "HW Address %s",
641 device_addr2str(RTA_DATA(attr),
642 RTA_LEN(attr), 0, hw_addr,
643 sizeof(hw_addr)));
644 break;
645 case NDA_PROBES:
646 attr_fmt(attr, "Probes %d", RTA_UINT32(attr));
647 break;
648 case NDA_CACHEINFO:
649 ci = RTA_DATA(attr);
650 tprintf("\tA: Cache (");
651 tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
652 tprintf(", used(%ds)", ci->ndm_used / hz);
653 tprintf(", updated(%ds)", ci->ndm_updated / hz);
654 tprintf(", refcnt(%d))", ci->ndm_refcnt);
655 tprintf(", Len %lu\n", RTA_LEN(attr));
656 break;
661 static void rtnl_msg_print(struct nlmsghdr *hdr)
663 switch (hdr->nlmsg_type) {
664 case RTM_NEWLINK:
665 case RTM_DELLINK:
666 case RTM_GETLINK:
667 case RTM_SETLINK:
668 rtnl_print_ifinfo(hdr);
669 break;
670 case RTM_NEWADDR:
671 case RTM_DELADDR:
672 case RTM_GETADDR:
673 rtnl_print_ifaddr(hdr);
674 break;
675 case RTM_NEWROUTE:
676 case RTM_DELROUTE:
677 case RTM_GETROUTE:
678 rtnl_print_route(hdr);
679 break;
680 case RTM_NEWNEIGH:
681 case RTM_DELNEIGH:
682 case RTM_GETNEIGH:
683 rtnl_print_neigh(hdr);
684 break;
688 static void nlmsg_print(uint16_t family, struct nlmsghdr *hdr)
690 char type[32];
691 char flags[128];
692 char procname[PATH_MAX];
694 /* Look up the process name if message is not coming from the kernel.
696 * Note that the port id is not necessarily equal to the PID of the
697 * receiving process (e.g. if the application is multithreaded or using
698 * multiple sockets). In these cases we're not able to find a matching
699 * PID and the information will not be printed.
701 if (hdr->nlmsg_pid != 0) {
702 char path[1024];
703 int ret;
705 snprintf(path, sizeof(path), "/proc/%u/exe", hdr->nlmsg_pid);
706 ret = readlink(path, procname, sizeof(procname) - 1);
707 if (ret < 0)
708 ret = 0;
709 procname[ret] = '\0';
710 } else
711 snprintf(procname, sizeof(procname), "kernel");
713 tprintf(" [ NLMSG ");
714 tprintf("Family %d (%s%s%s), ", family,
715 colorize_start(bold),
716 nlmsg_family2str(family),
717 colorize_end());
718 tprintf("Len %u, ", hdr->nlmsg_len);
719 tprintf("Type 0x%.4x (%s%s%s), ", hdr->nlmsg_type,
720 colorize_start(bold),
721 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
722 colorize_end());
723 tprintf("Flags 0x%.4x (%s%s%s), ", hdr->nlmsg_flags,
724 colorize_start(bold),
725 nl_nlmsg_flags2str(hdr->nlmsg_flags, flags, sizeof(flags)),
726 colorize_end());
727 tprintf("Seq-Nr %u, ", hdr->nlmsg_seq);
728 tprintf("PID %u", hdr->nlmsg_pid);
729 if (procname[0])
730 tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
731 colorize_end());
732 tprintf(" ]\n");
734 if (family == NETLINK_ROUTE)
735 rtnl_msg_print(hdr);
738 static void nlmsg(struct pkt_buff *pkt)
740 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, sizeof(*hdr));
742 while (hdr) {
743 nlmsg_print(ntohs(pkt->sll->sll_protocol), hdr);
745 if (!pkt_pull(pkt, NLMSG_PAYLOAD(hdr, 0)))
746 break;
748 hdr = (struct nlmsghdr *) pkt_pull(pkt, sizeof(*hdr));
749 if (hdr && hdr->nlmsg_type != NLMSG_DONE &&
750 (hdr->nlmsg_flags & NLM_F_MULTI))
751 tprintf("\n");
755 static void nlmsg_less(struct pkt_buff *pkt)
757 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, sizeof(*hdr));
758 uint16_t family = ntohs(pkt->sll->sll_protocol);
759 char type[32];
761 if (hdr == NULL)
762 return;
764 tprintf(" NLMSG Family %d (%s%s%s), ", family,
765 colorize_start(bold),
766 nlmsg_family2str(family),
767 colorize_end());
768 tprintf("Type %u (%s%s%s)", hdr->nlmsg_type,
769 colorize_start(bold),
770 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
771 colorize_end());
774 struct protocol nlmsg_ops = {
775 .print_full = nlmsg,
776 .print_less = nlmsg_less,