netsniff-ng: remove unnecessary zeroing of packet counters in init_ctx()
[netsniff-ng.git] / proto_nlmsg.c
blobf2064059be08329f20b63d811d5753f2292dfdca
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 #if defined(NETLINK_CRYPTO)
163 case NETLINK_CRYPTO: return "Crypto layer";
164 #endif
165 default: return "Unknown";
169 static const char *nlmsg_rtnl_type2str(uint16_t type)
171 switch (type) {
172 case RTM_NEWLINK: return "new link";
173 case RTM_DELLINK: return "del link";
174 case RTM_GETLINK: return "get link";
175 case RTM_SETLINK: return "set link";
177 case RTM_NEWADDR: return "new addr";
178 case RTM_DELADDR: return "del addr";
179 case RTM_GETADDR: return "get addr";
181 case RTM_NEWROUTE: return "new route";
182 case RTM_DELROUTE: return "del route";
183 case RTM_GETROUTE: return "get route";
185 case RTM_NEWNEIGH: return "new neigh";
186 case RTM_DELNEIGH: return "del neigh";
187 case RTM_GETNEIGH: return "get neigh";
189 case RTM_NEWRULE: return "new rule";
190 case RTM_DELRULE: return "del rule";
191 case RTM_GETRULE: return "get rule";
193 case RTM_NEWQDISC: return "new tc qdisc";
194 case RTM_DELQDISC: return "del tc qdisc";
195 case RTM_GETQDISC: return "get tc qdisc";
197 case RTM_NEWTCLASS: return "new tc class";
198 case RTM_DELTCLASS: return "del tc class";
199 case RTM_GETTCLASS: return "get tc class";
201 case RTM_NEWTFILTER: return "new tc filter";
202 case RTM_DELTFILTER: return "del tc filter";
203 case RTM_GETTFILTER: return "get tc filter";
205 case RTM_NEWACTION: return "new tc action";
206 case RTM_DELACTION: return "del tc action";
207 case RTM_GETACTION: return "get tc action";
209 case RTM_NEWPREFIX: return "new prefix";
211 case RTM_GETMULTICAST: return "get mcast addr";
213 case RTM_GETANYCAST: return "get anycast addr";
215 case RTM_NEWNEIGHTBL: return "new neigh table";
216 case RTM_GETNEIGHTBL: return "get neigh table";
217 case RTM_SETNEIGHTBL: return "set neigh table";
219 case RTM_NEWNDUSEROPT: return "new ndisc user option";
221 case RTM_NEWADDRLABEL: return "new addr label";
222 case RTM_DELADDRLABEL: return "del addr label";
223 case RTM_GETADDRLABEL: return "get addr label";
225 case RTM_GETDCB: return "get data-center-bridge";
226 case RTM_SETDCB: return "set data-center-bridge";
228 #if defined(RTM_NEWNETCONF)
229 case RTM_NEWNETCONF: return "new netconf";
230 case RTM_GETNETCONF: return "get netconf";
231 #endif
233 #if defined(RTM_NEWMDB)
234 case RTM_NEWMDB: return "new bridge mdb";
235 case RTM_DELMDB: return "del bridge mdb";
236 case RTM_GETMDB: return "get bridge mdb";
237 #endif
238 default: return NULL;
242 static const char *nlmsg_genl_type2str(uint16_t type)
244 switch (type) {
245 case GENL_ID_CTRL: return "nlctrl";
246 #if defined(GENL_ID_PCMRAID)
247 case GENL_ID_PCMRAID: return "pcmraid";
248 #endif
249 #if defined(GENL_ID_VFS_DQUOT)
250 case GENL_ID_VFS_DQUOT: return "vfs dquot";
251 #endif
252 /* only dynamic family IDs should be used starting with Linux 4.10 */
253 default: return "dynamic";
257 static char *nlmsg_type2str(uint16_t proto, uint16_t type, char *buf, int len)
259 const char *name = NULL;
261 if (proto == NETLINK_ROUTE && type < RTM_MAX)
262 name = nlmsg_rtnl_type2str(type);
263 else if (proto == NETLINK_GENERIC)
264 name = nlmsg_genl_type2str(type);
266 if (name) {
267 strncpy(buf, name, len);
268 return buf;
271 return nl_nlmsgtype2str(type, buf, len);
274 static const char *addr_family2str(uint16_t family)
276 switch (family) {
277 case AF_INET: return "ipv4";
278 case AF_INET6: return "ipv6";
279 case AF_DECnet: return "decnet";
280 case AF_IPX: return "ipx";
281 default: return "Unknown";
285 static const char *addr2str(uint16_t af, const void *addr, char *buf, int blen)
287 if (af == AF_INET || af == AF_INET6)
288 return inet_ntop(af, addr, buf, blen);
290 return "???";
293 static const char *scope2str(uint8_t scope)
295 switch (scope) {
296 case RT_SCOPE_UNIVERSE: return "global";
297 case RT_SCOPE_LINK: return "link";
298 case RT_SCOPE_HOST: return "host";
299 case RT_SCOPE_NOWHERE: return "nowhere";
301 default: return "Unknown";
305 static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
307 struct ifinfomsg *ifi = NLMSG_DATA(hdr);
308 struct rtattr *attr = IFLA_RTA(ifi);
309 uint32_t attrs_len = IFLA_PAYLOAD(hdr);
310 char flags[256];
311 char if_addr[64] = {};
312 char *af_link = "unknown";
314 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifi)))
315 return;
317 if (ifi->ifi_family == AF_UNSPEC)
318 af_link = "unspec";
319 else if (ifi->ifi_family == AF_BRIDGE)
320 af_link = "bridge";
322 tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
323 colorize_start(bold), af_link, colorize_end());
324 tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
325 colorize_start(bold),
326 device_type2str(ifi->ifi_type),
327 colorize_end());
328 tprintf(", Index %d", ifi->ifi_index);
329 tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
330 colorize_start(bold),
331 rtnl_link_flags2str(ifi->ifi_flags, flags,
332 sizeof(flags)),
333 colorize_end());
334 tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
335 colorize_start(bold),
336 rtnl_link_flags2str(ifi->ifi_change, flags,
337 sizeof(flags)),
338 colorize_end());
340 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
341 switch (attr->rta_type) {
342 case IFLA_ADDRESS:
343 rta_fmt(attr, "Address %s",
344 device_addr2str(RTA_DATA(attr),
345 RTA_LEN(attr), ifi->ifi_type,
346 if_addr, sizeof(if_addr)));
347 break;
348 case IFLA_BROADCAST:
349 rta_fmt(attr, "Broadcast %s",
350 device_addr2str(RTA_DATA(attr),
351 RTA_LEN(attr), ifi->ifi_type,
352 if_addr, sizeof(if_addr)));
353 break;
354 case IFLA_IFNAME:
355 rta_fmt(attr, "Name %s%s%s",
356 colorize_start(bold), RTA_STR(attr),
357 colorize_end());
358 break;
359 case IFLA_MTU:
360 rta_fmt(attr, "MTU %d", RTA_INT(attr));
361 break;
362 case IFLA_LINK:
363 rta_fmt(attr, "Link %d", RTA_INT(attr));
364 break;
365 case IFLA_QDISC:
366 rta_fmt(attr, "QDisc %s", RTA_STR(attr));
367 break;
368 case IFLA_OPERSTATE:
370 uint8_t st = RTA_UINT8(attr);
371 char states[256];
373 rta_fmt(attr, "Operation state 0x%x (%s%s%s)",
375 colorize_start(bold),
376 rtnl_link_operstate2str(st,
377 states, sizeof(states)),
378 colorize_end());
380 break;
381 case IFLA_LINKMODE:
383 uint8_t mode = RTA_UINT8(attr);
384 char str[32];
386 rta_fmt(attr, "Mode 0x%x (%s%s%s)", mode,
387 colorize_start(bold),
388 rtnl_link_mode2str(mode, str,
389 sizeof(str)),
390 colorize_end());
392 break;
393 case IFLA_GROUP:
394 rta_fmt(attr, "Group %d", RTA_INT(attr));
395 break;
396 case IFLA_TXQLEN:
397 rta_fmt(attr, "Tx queue len %d", RTA_INT(attr));
398 break;
399 case IFLA_NET_NS_PID:
400 rta_fmt(attr, "Network namespace pid %d",
401 RTA_INT(attr));
402 break;
403 case IFLA_NET_NS_FD:
404 rta_fmt(attr, "Network namespace fd %d", RTA_INT(attr));
405 break;
406 default:
407 rta_fmt(attr, "0x%x", attr->rta_type);
408 break;
413 static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
415 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
416 uint32_t attrs_len = IFA_PAYLOAD(hdr);
417 struct rtattr *attr = IFA_RTA(ifa);
418 struct ifa_cacheinfo *ci;
419 char addr_str[256];
420 char flags[256];
422 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifa)))
423 return;
425 tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
426 colorize_start(bold),
427 addr_family2str(ifa->ifa_family),
428 colorize_end());
429 tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
430 tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
431 colorize_start(bold),
432 rtnl_addr_flags2str(ifa->ifa_flags, flags,
433 sizeof(flags)),
434 colorize_end());
435 tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
436 colorize_start(bold),
437 scope2str(ifa->ifa_scope),
438 colorize_end());
439 tprintf(", Link Index %d ]\n", ifa->ifa_index);
441 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
442 switch (attr->rta_type) {
443 case IFA_LOCAL:
444 rta_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
445 RTA_DATA(attr), addr_str, sizeof(addr_str)));
446 break;
447 case IFA_ADDRESS:
448 rta_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
449 RTA_DATA(attr), addr_str, sizeof(addr_str)));
450 break;
451 case IFA_BROADCAST:
452 rta_fmt(attr, "Broadcast %s",
453 addr2str(ifa->ifa_family,
454 RTA_DATA(attr), addr_str,
455 sizeof(addr_str)));
456 break;
457 case IFA_MULTICAST:
458 rta_fmt(attr, "Multicast %s",
459 addr2str(ifa->ifa_family,
460 RTA_DATA(attr), addr_str,
461 sizeof(addr_str)));
462 break;
463 case IFA_ANYCAST:
464 rta_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
465 RTA_DATA(attr), addr_str, sizeof(addr_str)));
466 break;
467 #ifdef IFA_FLAGS
468 case IFA_FLAGS:
469 rta_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
470 colorize_start(bold),
471 rtnl_addr_flags2str(RTA_INT(attr),
472 flags, sizeof(flags)),
473 colorize_end());
474 break;
475 #endif
476 case IFA_LABEL:
477 rta_fmt(attr, "Label %s", RTA_STR(attr));
478 break;
479 case IFA_CACHEINFO:
480 ci = RTA_DATA(attr);
481 tprintf("\tA: Cache (");
483 if (ci->ifa_valid == INFINITY)
484 tprintf("valid lft(forever)");
485 else
486 tprintf("valid lft(%us)", ci->ifa_valid);
488 if (ci->ifa_prefered == INFINITY)
489 tprintf(", prefrd lft(forever)");
490 else
491 tprintf(", prefrd lft(%us)", ci->ifa_prefered);
493 tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
494 tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
495 tprintf(", Len %d\n", RTA_LEN(attr));
496 break;
497 default:
498 rta_fmt(attr, "0x%x", attr->rta_type);
499 break;
504 static const char *route_table2str(uint8_t table)
506 switch (table) {
507 case RT_TABLE_UNSPEC: return "unspec";
508 case RT_TABLE_COMPAT: return "compat";
509 case RT_TABLE_DEFAULT: return "default";
510 case RT_TABLE_MAIN: return "main";
511 case RT_TABLE_LOCAL: return "local";
513 default: return "Unknown";
517 static const char *route_proto2str(uint8_t proto)
519 switch (proto) {
520 case RTPROT_UNSPEC: return "unspec";
521 case RTPROT_REDIRECT: return "redirect";
522 case RTPROT_KERNEL: return "kernel";
523 case RTPROT_BOOT: return "boot";
524 case RTPROT_STATIC: return "static";
525 case RTPROT_GATED: return "gated";
526 case RTPROT_RA: return "ra";
527 case RTPROT_MRT: return "mrt";
528 case RTPROT_ZEBRA: return "zebra";
529 case RTPROT_BIRD: return "bird";
530 case RTPROT_DNROUTED: return "DECnet";
531 case RTPROT_XORP: return "xorp";
532 case RTPROT_NTK: return "netsukuku";
533 case RTPROT_DHCP: return "dhcpc";
534 #ifdef RTPROT_MROUTED
535 case RTPROT_MROUTED: return "mrouted";
536 #endif
538 default: return "Unknown";
542 static const char *route_type2str(uint8_t type)
544 switch (type) {
545 case RTN_UNSPEC: return "unspec";
546 case RTN_UNICAST: return "unicast";
547 case RTN_LOCAL: return "local";
548 case RTN_BROADCAST: return "broadcast";
549 case RTN_ANYCAST: return "anycast";
550 case RTN_MULTICAST: return "multicast";
551 case RTN_BLACKHOLE: return "blackhole";
552 case RTN_UNREACHABLE: return "unreach";
553 case RTN_PROHIBIT: return "prohibit";
554 case RTN_THROW: return "throw";
555 case RTN_NAT: return "nat";
556 case RTN_XRESOLVE: return "xresolve";
557 default: return "Unknown";
561 static struct flag_name route_flags[] = {
562 { "notify", RTM_F_NOTIFY },
563 { "cloned", RTM_F_CLONED },
564 { "equalize", RTM_F_EQUALIZE },
565 { "prefix", RTM_F_PREFIX },
566 { "dead", RTNH_F_DEAD },
567 { "pervasive", RTNH_F_PERVASIVE },
568 { "onlink", RTNH_F_ONLINK },
569 { NULL, 0 },
572 static void rtnl_print_route(struct nlmsghdr *hdr)
574 struct rtmsg *rtm = NLMSG_DATA(hdr);
575 uint32_t attrs_len = RTM_PAYLOAD(hdr);
576 struct rtattr *attr = RTM_RTA(rtm);
577 struct rta_cacheinfo *ci;
578 int hz = get_user_hz();
579 char addr_str[256];
580 char flags[256];
582 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*rtm)))
583 return;
585 tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
586 colorize_start(bold),
587 addr_family2str(rtm->rtm_family),
588 colorize_end());
589 tprintf(", Dst Len %d", rtm->rtm_dst_len);
590 tprintf(", Src Len %d", rtm->rtm_src_len);
591 tprintf(", ToS %d", rtm->rtm_tos);
592 tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
593 colorize_start(bold),
594 route_table2str(rtm->rtm_table),
595 colorize_end());
596 tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
597 colorize_start(bold),
598 route_proto2str(rtm->rtm_protocol),
599 colorize_end());
600 tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
601 colorize_start(bold),
602 scope2str(rtm->rtm_scope),
603 colorize_end());
604 tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
605 colorize_start(bold),
606 route_type2str(rtm->rtm_type),
607 colorize_end());
608 tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
609 colorize_start(bold),
610 flags2str(route_flags, rtm->rtm_flags, flags,
611 sizeof(flags)),
612 colorize_end());
614 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
615 switch (attr->rta_type) {
616 case RTA_DST:
617 rta_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
618 RTA_DATA(attr), addr_str, sizeof(addr_str)));
619 break;
620 case RTA_SRC:
621 rta_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
622 RTA_DATA(attr), addr_str, sizeof(addr_str)));
623 break;
624 case RTA_IIF:
625 rta_fmt(attr, "Iif %d", RTA_INT(attr));
626 break;
627 case RTA_OIF:
628 rta_fmt(attr, "Oif %d", RTA_INT(attr));
629 break;
630 case RTA_GATEWAY:
631 rta_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
632 RTA_DATA(attr), addr_str, sizeof(addr_str)));
633 break;
634 case RTA_PRIORITY:
635 rta_fmt(attr, "Priority %u", RTA_UINT32(attr));
636 break;
637 case RTA_PREFSRC:
638 rta_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
639 RTA_DATA(attr), addr_str, sizeof(addr_str)));
640 break;
641 #if defined(RTA_MARK)
642 case RTA_MARK:
643 rta_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
644 break;
645 #endif
646 case RTA_FLOW:
647 rta_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
648 break;
649 case RTA_TABLE:
650 rta_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
651 colorize_start(bold),
652 route_table2str(RTA_UINT32(attr)),
653 colorize_end());
654 break;
655 case RTA_CACHEINFO:
656 ci = RTA_DATA(attr);
657 tprintf("\tA: Cache (");
658 tprintf("expires(%ds)", ci->rta_expires / hz);
659 tprintf(", error(%d)", ci->rta_error);
660 tprintf(", users(%d)", ci->rta_clntref);
661 tprintf(", used(%d)", ci->rta_used);
662 tprintf(", last use(%ds)", ci->rta_lastuse / hz);
663 tprintf(", id(%d)", ci->rta_id);
664 tprintf(", ts(%d)", ci->rta_ts);
665 tprintf(", ts age(%ds))", ci->rta_tsage);
666 tprintf(", Len %d\n", RTA_LEN(attr));
667 break;
668 default:
669 rta_fmt(attr, "0x%x", attr->rta_type);
670 break;
675 static struct flag_name neigh_states[] = {
676 { "incomplete", NUD_INCOMPLETE },
677 { "reachable", NUD_REACHABLE },
678 { "stale", NUD_STALE },
679 { "delay", NUD_DELAY },
680 { "probe", NUD_PROBE },
681 { "failed", NUD_FAILED },
682 { "noarp", NUD_NOARP },
683 { "permanent", NUD_PERMANENT },
684 { "none", NUD_NONE },
685 { NULL, 0 },
688 /* Copied from linux/neighbour.h */
689 #ifndef NTF_USE
690 # define NTF_USE 0x01
691 #endif
692 #ifndef NTF_SELF
693 # define NTF_SELF 0x02
694 #endif
695 #ifndef NTF_MASTER
696 # define NTF_MASTER 0x04
697 #endif
698 #ifndef NTF_PROXY
699 # define NTF_PROXY 0x08
700 #endif
701 #ifndef NTF_EXT_LEARNED
702 # define NTF_EXT_LEARNED 0x10
703 #endif
704 #ifndef NTF_ROUTER
705 # define NTF_ROUTER 0x80
706 #endif
708 static struct flag_name neigh_flags[] = {
709 { "use", NTF_USE },
710 { "self", NTF_SELF },
711 { "master", NTF_MASTER },
712 { "proxy", NTF_PROXY },
713 { "ext learned", NTF_EXT_LEARNED },
714 { "router", NTF_ROUTER },
715 { NULL, 0 },
718 static void rtnl_print_neigh(struct nlmsghdr *hdr)
720 struct ndmsg *ndm = NLMSG_DATA(hdr);
721 uint32_t attrs_len = NDA_PAYLOAD(hdr);
722 struct rtattr *attr = NDA_RTA(ndm);
723 struct nda_cacheinfo *ci;
724 int hz = get_user_hz();
725 char addr_str[256];
726 char hw_addr[30];
727 char states[256];
728 char flags[256];
730 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ndm)))
731 return;
733 tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
734 colorize_start(bold),
735 addr_family2str(ndm->ndm_family),
736 colorize_end());
737 tprintf(", Link Index %d", ndm->ndm_ifindex);
738 tprintf(", State %d (%s%s%s)", ndm->ndm_state,
739 colorize_start(bold),
740 flags2str(neigh_states, ndm->ndm_state, states,
741 sizeof(states)),
742 colorize_end());
743 tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
744 colorize_start(bold),
745 flags2str(neigh_flags, ndm->ndm_flags, flags,
746 sizeof(flags)),
747 colorize_end());
748 tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
749 colorize_start(bold),
750 route_type2str(ndm->ndm_type),
751 colorize_end());
752 tprintf(" ]\n");
754 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
755 switch (attr->rta_type) {
756 case NDA_DST:
757 rta_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
758 RTA_DATA(attr), addr_str,
759 sizeof(addr_str)));
760 break;
761 case NDA_LLADDR:
762 rta_fmt(attr, "HW Address %s",
763 device_addr2str(RTA_DATA(attr),
764 RTA_LEN(attr), 0, hw_addr,
765 sizeof(hw_addr)));
766 break;
767 case NDA_PROBES:
768 rta_fmt(attr, "Probes %d", RTA_UINT32(attr));
769 break;
770 case NDA_CACHEINFO:
771 ci = RTA_DATA(attr);
772 tprintf("\tA: Cache (");
773 tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
774 tprintf(", used(%ds)", ci->ndm_used / hz);
775 tprintf(", updated(%ds)", ci->ndm_updated / hz);
776 tprintf(", refcnt(%d))", ci->ndm_refcnt);
777 tprintf(", Len %d\n", RTA_LEN(attr));
778 break;
779 default:
780 rta_fmt(attr, "0x%x", attr->rta_type);
781 break;
786 static void rtnl_msg_print(struct nlmsghdr *hdr)
788 switch (hdr->nlmsg_type) {
789 case RTM_NEWLINK:
790 case RTM_DELLINK:
791 case RTM_GETLINK:
792 case RTM_SETLINK:
793 rtnl_print_ifinfo(hdr);
794 break;
795 case RTM_NEWADDR:
796 case RTM_DELADDR:
797 case RTM_GETADDR:
798 rtnl_print_ifaddr(hdr);
799 break;
800 case RTM_NEWROUTE:
801 case RTM_DELROUTE:
802 case RTM_GETROUTE:
803 rtnl_print_route(hdr);
804 break;
805 case RTM_NEWNEIGH:
806 case RTM_DELNEIGH:
807 case RTM_GETNEIGH:
808 rtnl_print_neigh(hdr);
809 break;
813 static const char *genl_cmd2str(uint8_t table)
815 switch (table) {
816 case CTRL_CMD_UNSPEC: return "unspec";
817 case CTRL_CMD_NEWFAMILY: return "new family";
818 case CTRL_CMD_DELFAMILY: return "del family";
819 case CTRL_CMD_GETFAMILY: return "get family";
820 case CTRL_CMD_NEWOPS: return "new ops";
821 case CTRL_CMD_DELOPS: return "del ops";
822 case CTRL_CMD_GETOPS: return "get ops";
823 case CTRL_CMD_NEWMCAST_GRP: return "new mcast group";
824 case CTRL_CMD_DELMCAST_GRP: return "del mcast group";
825 case CTRL_CMD_GETMCAST_GRP: return "get mcast group";
827 default: return "Unknown";
831 static struct flag_name genl_ops_flags[] = {
832 { "admin", GENL_ADMIN_PERM },
833 { "doit", GENL_CMD_CAP_DO },
834 { "dumpit", GENL_CMD_CAP_DUMP },
835 { "policy", GENL_CMD_CAP_HASPOL },
836 { NULL, 0 },
839 static void genl_print_ops_attr(struct nlattr *attr, uint32_t attr_len)
841 char str[256];
842 uint32_t flags;
844 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
845 switch (attr->nla_type) {
846 case CTRL_ATTR_OP_ID:
847 nla_fmt_nested(attr, "Id 0x%x", NLA_UINT32(attr));
848 break;
850 case CTRL_ATTR_OP_FLAGS:
851 flags = NLA_UINT32(attr);
853 nla_fmt_nested(attr, "Flags 0x%x (%s%s%s)", flags,
854 colorize_start(bold),
855 flags2str(genl_ops_flags, flags, str, sizeof(str)),
856 colorize_end());
857 break;
858 default:
859 nla_fmt_nested(attr, "0x%x", attr->nla_type);
860 break;
865 static void genl_print_ops_list(struct nlattr *attr, uint32_t attr_len)
867 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
868 nla_fmt_nested_start(attr, "0x%x", attr->nla_type);
869 genl_print_ops_attr(NLA_DATA(attr), NLA_LEN(attr));
870 nla_fmt_nested_end();
874 static void genl_print_mcast_group(struct nlattr *attr, uint32_t attr_len)
876 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
877 switch (attr->nla_type) {
878 case CTRL_ATTR_MCAST_GRP_ID:
879 nla_fmt_nested(attr, "Id 0x%x", NLA_UINT32(attr));
880 break;
882 case CTRL_ATTR_MCAST_GRP_NAME:
883 nla_fmt_nested(attr, "Name %s", NLA_STR(attr));
884 break;
885 default:
886 nla_fmt_nested(attr, "0x%x", attr->nla_type);
887 break;
892 static void genl_print_mc_groups(struct nlattr *attr, uint32_t attr_len)
894 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
895 nla_fmt_nested_start(attr, "0x%x", attr->nla_type);
896 genl_print_mcast_group(NLA_DATA(attr), NLA_LEN(attr));
897 nla_fmt_nested_end();
901 static void genl_print_ctrl_attrs(struct nlmsghdr *hdr)
903 struct genlmsghdr *genl = NLMSG_DATA(hdr);
904 struct nlattr *attr = GEN_NLA(genl);
905 uint32_t attrs_len = NLMSG_PAYLOAD(hdr, sizeof(struct genlmsghdr));
907 for (; NLA_OK(attr, attrs_len); attr = NLA_NEXT(attr, attrs_len)) {
908 switch (attr->nla_type) {
909 case CTRL_ATTR_FAMILY_ID:
910 nla_fmt(attr, "Family Id 0x%x", NLA_UINT16(attr));
911 break;
912 case CTRL_ATTR_FAMILY_NAME:
913 nla_fmt(attr, "Family Name %s", NLA_STR(attr));
914 break;
915 case CTRL_ATTR_VERSION:
916 nla_fmt(attr, "Version %u", NLA_UINT32(attr));
917 break;
918 case CTRL_ATTR_HDRSIZE:
919 nla_fmt(attr, "Header size %u", NLA_UINT32(attr));
920 break;
921 case CTRL_ATTR_MAXATTR:
922 nla_fmt(attr, "Max attr value 0x%x", NLA_UINT32(attr));
923 break;
924 case CTRL_ATTR_OPS:
925 nla_fmt(attr, "Ops list");
926 genl_print_ops_list(NLA_DATA(attr), NLA_LEN(attr));
927 break;
928 case CTRL_ATTR_MCAST_GROUPS:
929 nla_fmt(attr, "Mcast groups");
930 genl_print_mc_groups(NLA_DATA(attr), NLA_LEN(attr));
931 break;
932 default:
933 nla_fmt(attr, "0x%x", attr->nla_type);
934 break;
939 static void genl_msg_print(struct nlmsghdr *hdr)
941 struct genlmsghdr *genl;
943 if (hdr->nlmsg_type != GENL_ID_CTRL) {
944 nlmsg_print_raw(hdr);
945 return;
948 genl = NLMSG_DATA(hdr);
950 tprintf(" [ Cmd %u (%s%s%s)", genl->cmd,
951 colorize_start(bold), genl_cmd2str(genl->cmd), colorize_end());
952 tprintf(", Version %u", genl->version);
953 tprintf(", Reserved %u", genl->reserved);
954 tprintf(" ]\n");
956 genl_print_ctrl_attrs(hdr);
959 static void nlmsg_print(uint16_t family, struct nlmsghdr *hdr)
961 u16 nlmsg_flags = hdr->nlmsg_flags;
962 char type[32];
963 char flags[128];
964 char procname[PATH_MAX];
966 /* Look up the process name if message is not coming from the kernel.
968 * Note that the port id is not necessarily equal to the PID of the
969 * receiving process (e.g. if the application is multithreaded or using
970 * multiple sockets). In these cases we're not able to find a matching
971 * PID and the information will not be printed.
973 if (hdr->nlmsg_pid != 0) {
974 if (proc_get_cmdline(hdr->nlmsg_pid, procname, sizeof(procname)) < 0)
975 snprintf(procname, sizeof(procname), "unknown process");
976 } else
977 snprintf(procname, sizeof(procname), "kernel");
979 tprintf(" [ NLMSG ");
980 tprintf("Family %d (%s%s%s), ", family,
981 colorize_start(bold),
982 nlmsg_family2str(family),
983 colorize_end());
984 tprintf("Len %u, ", hdr->nlmsg_len);
985 tprintf("Type 0x%.4x (%s%s%s), ", hdr->nlmsg_type,
986 colorize_start(bold),
987 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
988 colorize_end());
989 tprintf("Flags 0x%.4x (%s%s%s), ", nlmsg_flags,
990 colorize_start(bold),
991 nlmsg_flags ? nl_nlmsg_flags2str(nlmsg_flags, flags, sizeof(flags)) : "none",
992 colorize_end());
993 tprintf("Seq-Nr %u, ", hdr->nlmsg_seq);
994 tprintf("PID %u", hdr->nlmsg_pid);
995 if (procname[0])
996 tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
997 colorize_end());
998 tprintf(" ]\n");
1000 switch (family) {
1001 case NETLINK_ROUTE:
1002 rtnl_msg_print(hdr);
1003 break;
1004 case NETLINK_GENERIC:
1005 genl_msg_print(hdr);
1006 break;
1007 default:
1008 nlmsg_print_raw(hdr);
1012 static void nlmsg(struct pkt_buff *pkt)
1014 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1015 unsigned int trim_len = pkt_len(pkt);
1017 while (hdr) {
1018 trim_len -= hdr->nlmsg_len;
1019 nlmsg_print(ntohs(pkt->sll->sll_protocol), hdr);
1021 if (!pkt_pull(pkt, NLMSG_ALIGN(hdr->nlmsg_len) - NLMSG_HDRLEN))
1022 break;
1024 hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1025 if (hdr == NULL)
1026 break;
1027 if (hdr->nlmsg_len == 0)
1028 break;
1030 if (hdr->nlmsg_type != NLMSG_DONE &&
1031 (hdr->nlmsg_flags & NLM_F_MULTI))
1032 tprintf("\n");
1035 /* mmaped packet? */
1036 if (hdr && hdr->nlmsg_len == 0)
1037 pkt_trim(pkt, trim_len);
1040 static void nlmsg_less(struct pkt_buff *pkt)
1042 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1043 uint16_t family = ntohs(pkt->sll->sll_protocol);
1044 char type[32];
1046 if (hdr == NULL)
1047 return;
1049 tprintf(" NLMSG Family %d (%s%s%s), ", family,
1050 colorize_start(bold),
1051 nlmsg_family2str(family),
1052 colorize_end());
1053 tprintf("Type %u (%s%s%s)", hdr->nlmsg_type,
1054 colorize_start(bold),
1055 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
1056 colorize_end());
1059 struct protocol nlmsg_ops = {
1060 .print_full = nlmsg,
1061 .print_less = nlmsg_less,