mausezahn: use getopt_long instead of getopt
[netsniff-ng.git] / proto_nlmsg.c
blob58bf7152505254602a7b178abf4795926dc9800d
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 <arpa/inet.h>
17 #include "dev.h"
18 #include "pkt_buff.h"
19 #include "proc.h"
20 #include "proto.h"
21 #include "protos.h"
22 #include "timer.h"
24 #define INFINITY 0xFFFFFFFFU
26 #define RTA_LEN(attr) ((int)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 #ifndef NLA_LENGTH
43 #define NLA_LENGTH(len) (NLA_ALIGN(sizeof(struct nlattr)) + (len))
44 #endif
46 #ifndef NLA_DATA
47 #define NLA_DATA(nla) ((void*)(((char*)(nla)) + NLA_LENGTH(0)))
48 #endif
50 #ifndef NLA_PAYLOAD
51 #define NLA_PAYLOAD(nla) ((int)((nla)->nla_len) - NLA_LENGTH(0))
52 #endif
54 #define NLA_LEN(attr) ((int)NLA_PAYLOAD(attr))
55 #define NLA_INT(attr) (*(int *)NLA_DATA(attr))
56 #define NLA_UINT(attr) (*(unsigned int *)NLA_DATA(attr))
57 #define NLA_UINT8(attr) (*(uint8_t *)NLA_DATA(attr))
58 #define NLA_UINT16(attr) (*(uint16_t *)NLA_DATA(attr))
59 #define NLA_UINT32(attr) (*(uint32_t *)NLA_DATA(attr))
60 #define NLA_STR(attr) ((char *)NLA_DATA(attr))
62 #ifndef GEN_NLA
63 #define GEN_NLA(n) ((struct nlattr*)(((char*)(n)) + GENL_HDRLEN))
64 #endif
66 #ifndef NLA_OK
67 #define NLA_OK(nla,len) \
68 ((len) >= (int)sizeof(struct nlattr) && \
69 (nla)->nla_len >= sizeof(struct nlattr) && \
70 (nla)->nla_len <= (len))
71 #endif
73 #ifndef NLA_NEXT
74 #define NLA_NEXT(nla,attrlen) \
75 ((attrlen) -= NLA_ALIGN((nla)->nla_len), \
76 (struct nlattr*)(((char*)(nla)) + NLA_ALIGN((nla)->nla_len)))
77 #endif
79 #define rta_fmt(attr, fmt, ...) \
80 tprintf("\tA: "fmt, ##__VA_ARGS__); \
81 tprintf(", Len %d\n", RTA_LEN(attr));
83 #define nla_fmt(attr, fmt, ...) \
84 tprintf("\tA: "fmt, ##__VA_ARGS__); \
85 tprintf(", Len %d\n", NLA_LEN(attr));
87 #define nla_fmt_nested(attr, fmt, ...) \
88 tprintf("[ "fmt, ##__VA_ARGS__); \
89 tprintf(", Len %d] ", NLA_LEN(attr));
91 #define nla_fmt_nested_start(attr, fmt, ...) \
92 tprintf("\t A: "fmt, ##__VA_ARGS__); \
93 tprintf(", Len %d ", NLA_LEN(attr));
95 #define nla_fmt_nested_end() tprintf("\n")
97 struct flag_name {
98 const char *name;
99 unsigned int flag;
102 static const char *flags2str(struct flag_name *tbl, unsigned int flags,
103 char *buf, int len)
105 int bits_stay = flags;
107 memset(buf, 0, len);
109 for (; tbl && tbl->name; tbl++) {
110 if (!(tbl->flag & flags))
111 continue;
113 bits_stay &= ~tbl->flag;
114 strncat(buf, tbl->name, len - strlen(buf) - 1);
116 if (bits_stay & flags)
117 strncat(buf, ",", len - strlen(buf) - 1);
120 return buf;
123 static void nlmsg_print_raw(struct nlmsghdr *hdr)
125 u32 len = hdr->nlmsg_len;
127 if (len) {
128 _ascii((uint8_t *) hdr + NLMSG_HDRLEN, len - NLMSG_HDRLEN);
129 _hex((uint8_t *) hdr + NLMSG_HDRLEN, len - NLMSG_HDRLEN);
133 static const char *nlmsg_family2str(uint16_t family)
135 switch (family) {
136 case NETLINK_ROUTE: return "routing";
137 case NETLINK_UNUSED: return "unused";
138 case NETLINK_USERSOCK: return "user-mode socket";
139 case NETLINK_FIREWALL: return "unused, formerly ip_queue";
140 /* NETLINK_INET_DIAG was renamed to NETLINK_SOCK_DIAG in Linux kernel 3.10 */
141 #if defined(NETLINK_SOCK_DIAG)
142 case NETLINK_SOCK_DIAG: return "socket monitoring";
143 #elif defined(NETLINK_INET_DIAG)
144 case NETLINK_INET_DIAG: return "INET socket monitoring";
145 #endif
146 case NETLINK_NFLOG: return "netfilter ULOG";
147 case NETLINK_XFRM: return "IPsec";
148 case NETLINK_SELINUX: return "SELinux event notification";
149 case NETLINK_ISCSI: return "Open-iSCSI";
150 case NETLINK_AUDIT: return "auditing";
151 case NETLINK_FIB_LOOKUP: return "FIB lookup";
152 case NETLINK_CONNECTOR: return "Kernel connector";
153 case NETLINK_NETFILTER: return "Netfilter";
154 case NETLINK_IP6_FW: return "unused, formerly ip6_queue";
155 case NETLINK_DNRTMSG: return "DECnet routing";
156 case NETLINK_KOBJECT_UEVENT: return "Kernel messages";
157 case NETLINK_GENERIC: return "Generic";
158 case NETLINK_SCSITRANSPORT: return "SCSI transports";
159 case NETLINK_ECRYPTFS: return "ecryptfs";
160 case NETLINK_RDMA: return "RDMA";
161 #if defined(NETLINK_CRYPTO)
162 case NETLINK_CRYPTO: return "Crypto layer";
163 #endif
164 default: return "Unknown";
168 static const char *nlmsg_rtnl_type2str(uint16_t type)
170 switch (type) {
171 case RTM_NEWLINK: return "new link";
172 case RTM_DELLINK: return "del link";
173 case RTM_GETLINK: return "get link";
174 case RTM_SETLINK: return "set link";
176 case RTM_NEWADDR: return "new addr";
177 case RTM_DELADDR: return "del addr";
178 case RTM_GETADDR: return "get addr";
180 case RTM_NEWROUTE: return "new route";
181 case RTM_DELROUTE: return "del route";
182 case RTM_GETROUTE: return "get route";
184 case RTM_NEWNEIGH: return "new neigh";
185 case RTM_DELNEIGH: return "del neigh";
186 case RTM_GETNEIGH: return "get neigh";
188 case RTM_NEWRULE: return "new rule";
189 case RTM_DELRULE: return "del rule";
190 case RTM_GETRULE: return "get rule";
192 case RTM_NEWQDISC: return "new tc qdisc";
193 case RTM_DELQDISC: return "del tc qdisc";
194 case RTM_GETQDISC: return "get tc qdisc";
196 case RTM_NEWTCLASS: return "new tc class";
197 case RTM_DELTCLASS: return "del tc class";
198 case RTM_GETTCLASS: return "get tc class";
200 case RTM_NEWTFILTER: return "new tc filter";
201 case RTM_DELTFILTER: return "del tc filter";
202 case RTM_GETTFILTER: return "get tc filter";
204 case RTM_NEWACTION: return "new tc action";
205 case RTM_DELACTION: return "del tc action";
206 case RTM_GETACTION: return "get tc action";
208 case RTM_NEWPREFIX: return "new prefix";
210 case RTM_GETMULTICAST: return "get mcast addr";
212 case RTM_GETANYCAST: return "get anycast addr";
214 case RTM_NEWNEIGHTBL: return "new neigh table";
215 case RTM_GETNEIGHTBL: return "get neigh table";
216 case RTM_SETNEIGHTBL: return "set neigh table";
218 case RTM_NEWNDUSEROPT: return "new ndisc user option";
220 case RTM_NEWADDRLABEL: return "new addr label";
221 case RTM_DELADDRLABEL: return "del addr label";
222 case RTM_GETADDRLABEL: return "get addr label";
224 case RTM_GETDCB: return "get data-center-bridge";
225 case RTM_SETDCB: return "set data-center-bridge";
227 #if defined(RTM_NEWNETCONF)
228 case RTM_NEWNETCONF: return "new netconf";
229 case RTM_GETNETCONF: return "get netconf";
230 #endif
232 #if defined(RTM_NEWMDB)
233 case RTM_NEWMDB: return "new bridge mdb";
234 case RTM_DELMDB: return "del bridge mdb";
235 case RTM_GETMDB: return "get bridge mdb";
236 #endif
237 default: return NULL;
241 static const char *nlmsg_genl_type2str(uint16_t type)
243 switch (type) {
244 case GENL_ID_CTRL: return "nlctrl";
245 #if defined(GENL_ID_PCMRAID)
246 case GENL_ID_PCMRAID: return "pcmraid";
247 #endif
248 #if defined(GENL_ID_VFS_DQUOT)
249 case GENL_ID_VFS_DQUOT: return "vfs dquot";
250 #endif
251 /* only dynamic family IDs should be used starting with Linux 4.10 */
252 default: return "dynamic";
256 static char *nlmsg_type2str(uint16_t proto, uint16_t type, char *buf, int len)
258 const char *name = NULL;
260 if (proto == NETLINK_ROUTE && type < RTM_MAX)
261 name = nlmsg_rtnl_type2str(type);
262 else if (proto == NETLINK_GENERIC)
263 name = nlmsg_genl_type2str(type);
265 if (name) {
266 strncpy(buf, name, len);
267 return buf;
270 return nl_nlmsgtype2str(type, buf, len);
273 static const char *addr_family2str(uint16_t family)
275 switch (family) {
276 case AF_INET: return "ipv4";
277 case AF_INET6: return "ipv6";
278 case AF_DECnet: return "decnet";
279 case AF_IPX: return "ipx";
280 default: return "Unknown";
284 static const char *addr2str(uint16_t af, const void *addr, char *buf, int blen)
286 if (af == AF_INET || af == AF_INET6)
287 return inet_ntop(af, addr, buf, blen);
289 return "???";
292 static const char *scope2str(uint8_t scope)
294 switch (scope) {
295 case RT_SCOPE_UNIVERSE: return "global";
296 case RT_SCOPE_LINK: return "link";
297 case RT_SCOPE_HOST: return "host";
298 case RT_SCOPE_NOWHERE: return "nowhere";
300 default: return "Unknown";
304 static void rtnl_print_ifinfo(struct nlmsghdr *hdr)
306 struct ifinfomsg *ifi = NLMSG_DATA(hdr);
307 struct rtattr *attr = IFLA_RTA(ifi);
308 uint32_t attrs_len = IFLA_PAYLOAD(hdr);
309 char flags[256];
310 char if_addr[64] = {};
311 char *af_link = "unknown";
313 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifi)))
314 return;
316 if (ifi->ifi_family == AF_UNSPEC)
317 af_link = "unspec";
318 else if (ifi->ifi_family == AF_BRIDGE)
319 af_link = "bridge";
321 tprintf(" [ Link Family %d (%s%s%s)", ifi->ifi_family,
322 colorize_start(bold), af_link, colorize_end());
323 tprintf(", Type %d (%s%s%s)", ifi->ifi_type,
324 colorize_start(bold),
325 device_type2str(ifi->ifi_type),
326 colorize_end());
327 tprintf(", Index %d", ifi->ifi_index);
328 tprintf(", Flags 0x%x (%s%s%s)", ifi->ifi_flags,
329 colorize_start(bold),
330 rtnl_link_flags2str(ifi->ifi_flags, flags,
331 sizeof(flags)),
332 colorize_end());
333 tprintf(", Change 0x%x (%s%s%s) ]\n", ifi->ifi_change,
334 colorize_start(bold),
335 rtnl_link_flags2str(ifi->ifi_change, flags,
336 sizeof(flags)),
337 colorize_end());
339 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
340 switch (attr->rta_type) {
341 case IFLA_ADDRESS:
342 rta_fmt(attr, "Address %s",
343 device_addr2str(RTA_DATA(attr),
344 RTA_LEN(attr), ifi->ifi_type,
345 if_addr, sizeof(if_addr)));
346 break;
347 case IFLA_BROADCAST:
348 rta_fmt(attr, "Broadcast %s",
349 device_addr2str(RTA_DATA(attr),
350 RTA_LEN(attr), ifi->ifi_type,
351 if_addr, sizeof(if_addr)));
352 break;
353 case IFLA_IFNAME:
354 rta_fmt(attr, "Name %s%s%s",
355 colorize_start(bold), RTA_STR(attr),
356 colorize_end());
357 break;
358 case IFLA_MTU:
359 rta_fmt(attr, "MTU %d", RTA_INT(attr));
360 break;
361 case IFLA_LINK:
362 rta_fmt(attr, "Link %d", RTA_INT(attr));
363 break;
364 case IFLA_QDISC:
365 rta_fmt(attr, "QDisc %s", RTA_STR(attr));
366 break;
367 case IFLA_OPERSTATE:
369 uint8_t st = RTA_UINT8(attr);
370 char states[256];
372 rta_fmt(attr, "Operation state 0x%x (%s%s%s)",
374 colorize_start(bold),
375 rtnl_link_operstate2str(st,
376 states, sizeof(states)),
377 colorize_end());
379 break;
380 case IFLA_LINKMODE:
382 uint8_t mode = RTA_UINT8(attr);
383 char str[32];
385 rta_fmt(attr, "Mode 0x%x (%s%s%s)", mode,
386 colorize_start(bold),
387 rtnl_link_mode2str(mode, str,
388 sizeof(str)),
389 colorize_end());
391 break;
392 case IFLA_GROUP:
393 rta_fmt(attr, "Group %d", RTA_INT(attr));
394 break;
395 case IFLA_TXQLEN:
396 rta_fmt(attr, "Tx queue len %d", RTA_INT(attr));
397 break;
398 case IFLA_NET_NS_PID:
399 rta_fmt(attr, "Network namespace pid %d",
400 RTA_INT(attr));
401 break;
402 case IFLA_NET_NS_FD:
403 rta_fmt(attr, "Network namespace fd %d", RTA_INT(attr));
404 break;
405 default:
406 rta_fmt(attr, "0x%x", attr->rta_type);
407 break;
412 static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
414 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
415 uint32_t attrs_len = IFA_PAYLOAD(hdr);
416 struct rtattr *attr = IFA_RTA(ifa);
417 struct ifa_cacheinfo *ci;
418 char addr_str[256];
419 char flags[256];
421 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifa)))
422 return;
424 tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
425 colorize_start(bold),
426 addr_family2str(ifa->ifa_family),
427 colorize_end());
428 tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
429 tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
430 colorize_start(bold),
431 rtnl_addr_flags2str(ifa->ifa_flags, flags,
432 sizeof(flags)),
433 colorize_end());
434 tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
435 colorize_start(bold),
436 scope2str(ifa->ifa_scope),
437 colorize_end());
438 tprintf(", Link Index %d ]\n", ifa->ifa_index);
440 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
441 switch (attr->rta_type) {
442 case IFA_LOCAL:
443 rta_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
444 RTA_DATA(attr), addr_str, sizeof(addr_str)));
445 break;
446 case IFA_ADDRESS:
447 rta_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
448 RTA_DATA(attr), addr_str, sizeof(addr_str)));
449 break;
450 case IFA_BROADCAST:
451 rta_fmt(attr, "Broadcast %s",
452 addr2str(ifa->ifa_family,
453 RTA_DATA(attr), addr_str,
454 sizeof(addr_str)));
455 break;
456 case IFA_MULTICAST:
457 rta_fmt(attr, "Multicast %s",
458 addr2str(ifa->ifa_family,
459 RTA_DATA(attr), addr_str,
460 sizeof(addr_str)));
461 break;
462 case IFA_ANYCAST:
463 rta_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
464 RTA_DATA(attr), addr_str, sizeof(addr_str)));
465 break;
466 #ifdef IFA_FLAGS
467 case IFA_FLAGS:
468 rta_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
469 colorize_start(bold),
470 rtnl_addr_flags2str(RTA_INT(attr),
471 flags, sizeof(flags)),
472 colorize_end());
473 break;
474 #endif
475 case IFA_LABEL:
476 rta_fmt(attr, "Label %s", RTA_STR(attr));
477 break;
478 case IFA_CACHEINFO:
479 ci = RTA_DATA(attr);
480 tprintf("\tA: Cache (");
482 if (ci->ifa_valid == INFINITY)
483 tprintf("valid lft(forever)");
484 else
485 tprintf("valid lft(%us)", ci->ifa_valid);
487 if (ci->ifa_prefered == INFINITY)
488 tprintf(", prefrd lft(forever)");
489 else
490 tprintf(", prefrd lft(%us)", ci->ifa_prefered);
492 tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
493 tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
494 tprintf(", Len %d\n", RTA_LEN(attr));
495 break;
496 default:
497 rta_fmt(attr, "0x%x", attr->rta_type);
498 break;
503 static const char *route_table2str(uint8_t table)
505 switch (table) {
506 case RT_TABLE_UNSPEC: return "unspec";
507 case RT_TABLE_COMPAT: return "compat";
508 case RT_TABLE_DEFAULT: return "default";
509 case RT_TABLE_MAIN: return "main";
510 case RT_TABLE_LOCAL: return "local";
512 default: return "Unknown";
516 static const char *route_proto2str(uint8_t proto)
518 switch (proto) {
519 case RTPROT_UNSPEC: return "unspec";
520 case RTPROT_REDIRECT: return "redirect";
521 case RTPROT_KERNEL: return "kernel";
522 case RTPROT_BOOT: return "boot";
523 case RTPROT_STATIC: return "static";
524 case RTPROT_GATED: return "gated";
525 case RTPROT_RA: return "ra";
526 case RTPROT_MRT: return "mrt";
527 case RTPROT_ZEBRA: return "zebra";
528 case RTPROT_BIRD: return "bird";
529 case RTPROT_DNROUTED: return "DECnet";
530 case RTPROT_XORP: return "xorp";
531 case RTPROT_NTK: return "netsukuku";
532 case RTPROT_DHCP: return "dhcpc";
533 #ifdef RTPROT_MROUTED
534 case RTPROT_MROUTED: return "mrouted";
535 #endif
537 default: return "Unknown";
541 static const char *route_type2str(uint8_t type)
543 switch (type) {
544 case RTN_UNSPEC: return "unspec";
545 case RTN_UNICAST: return "unicast";
546 case RTN_LOCAL: return "local";
547 case RTN_BROADCAST: return "broadcast";
548 case RTN_ANYCAST: return "anycast";
549 case RTN_MULTICAST: return "multicast";
550 case RTN_BLACKHOLE: return "blackhole";
551 case RTN_UNREACHABLE: return "unreach";
552 case RTN_PROHIBIT: return "prohibit";
553 case RTN_THROW: return "throw";
554 case RTN_NAT: return "nat";
555 case RTN_XRESOLVE: return "xresolve";
556 default: return "Unknown";
560 static struct flag_name route_flags[] = {
561 { "notify", RTM_F_NOTIFY },
562 { "cloned", RTM_F_CLONED },
563 { "equalize", RTM_F_EQUALIZE },
564 { "prefix", RTM_F_PREFIX },
565 { "dead", RTNH_F_DEAD },
566 { "pervasive", RTNH_F_PERVASIVE },
567 { "onlink", RTNH_F_ONLINK },
568 { NULL, 0 },
571 static void rtnl_print_route(struct nlmsghdr *hdr)
573 struct rtmsg *rtm = NLMSG_DATA(hdr);
574 uint32_t attrs_len = RTM_PAYLOAD(hdr);
575 struct rtattr *attr = RTM_RTA(rtm);
576 struct rta_cacheinfo *ci;
577 int hz = get_user_hz();
578 char addr_str[256];
579 char flags[256];
581 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*rtm)))
582 return;
584 tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
585 colorize_start(bold),
586 addr_family2str(rtm->rtm_family),
587 colorize_end());
588 tprintf(", Dst Len %d", rtm->rtm_dst_len);
589 tprintf(", Src Len %d", rtm->rtm_src_len);
590 tprintf(", ToS %d", rtm->rtm_tos);
591 tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
592 colorize_start(bold),
593 route_table2str(rtm->rtm_table),
594 colorize_end());
595 tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
596 colorize_start(bold),
597 route_proto2str(rtm->rtm_protocol),
598 colorize_end());
599 tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
600 colorize_start(bold),
601 scope2str(rtm->rtm_scope),
602 colorize_end());
603 tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
604 colorize_start(bold),
605 route_type2str(rtm->rtm_type),
606 colorize_end());
607 tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
608 colorize_start(bold),
609 flags2str(route_flags, rtm->rtm_flags, flags,
610 sizeof(flags)),
611 colorize_end());
613 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
614 switch (attr->rta_type) {
615 case RTA_DST:
616 rta_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
617 RTA_DATA(attr), addr_str, sizeof(addr_str)));
618 break;
619 case RTA_SRC:
620 rta_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
621 RTA_DATA(attr), addr_str, sizeof(addr_str)));
622 break;
623 case RTA_IIF:
624 rta_fmt(attr, "Iif %d", RTA_INT(attr));
625 break;
626 case RTA_OIF:
627 rta_fmt(attr, "Oif %d", RTA_INT(attr));
628 break;
629 case RTA_GATEWAY:
630 rta_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
631 RTA_DATA(attr), addr_str, sizeof(addr_str)));
632 break;
633 case RTA_PRIORITY:
634 rta_fmt(attr, "Priority %u", RTA_UINT32(attr));
635 break;
636 case RTA_PREFSRC:
637 rta_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
638 RTA_DATA(attr), addr_str, sizeof(addr_str)));
639 break;
640 #if defined(RTA_MARK)
641 case RTA_MARK:
642 rta_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
643 break;
644 #endif
645 case RTA_FLOW:
646 rta_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
647 break;
648 case RTA_TABLE:
649 rta_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
650 colorize_start(bold),
651 route_table2str(RTA_UINT32(attr)),
652 colorize_end());
653 break;
654 case RTA_CACHEINFO:
655 ci = RTA_DATA(attr);
656 tprintf("\tA: Cache (");
657 tprintf("expires(%ds)", ci->rta_expires / hz);
658 tprintf(", error(%d)", ci->rta_error);
659 tprintf(", users(%d)", ci->rta_clntref);
660 tprintf(", used(%d)", ci->rta_used);
661 tprintf(", last use(%ds)", ci->rta_lastuse / hz);
662 tprintf(", id(%d)", ci->rta_id);
663 tprintf(", ts(%d)", ci->rta_ts);
664 tprintf(", ts age(%ds))", ci->rta_tsage);
665 tprintf(", Len %d\n", RTA_LEN(attr));
666 break;
667 default:
668 rta_fmt(attr, "0x%x", attr->rta_type);
669 break;
674 static struct flag_name neigh_states[] = {
675 { "incomplete", NUD_INCOMPLETE },
676 { "reachable", NUD_REACHABLE },
677 { "stale", NUD_STALE },
678 { "delay", NUD_DELAY },
679 { "probe", NUD_PROBE },
680 { "failed", NUD_FAILED },
681 { "noarp", NUD_NOARP },
682 { "permanent", NUD_PERMANENT },
683 { "none", NUD_NONE },
684 { NULL, 0 },
687 /* Copied from linux/neighbour.h */
688 #ifndef NTF_USE
689 # define NTF_USE 0x01
690 #endif
691 #ifndef NTF_SELF
692 # define NTF_SELF 0x02
693 #endif
694 #ifndef NTF_MASTER
695 # define NTF_MASTER 0x04
696 #endif
697 #ifndef NTF_PROXY
698 # define NTF_PROXY 0x08
699 #endif
700 #ifndef NTF_EXT_LEARNED
701 # define NTF_EXT_LEARNED 0x10
702 #endif
703 #ifndef NTF_ROUTER
704 # define NTF_ROUTER 0x80
705 #endif
707 static struct flag_name neigh_flags[] = {
708 { "use", NTF_USE },
709 { "self", NTF_SELF },
710 { "master", NTF_MASTER },
711 { "proxy", NTF_PROXY },
712 { "ext learned", NTF_EXT_LEARNED },
713 { "router", NTF_ROUTER },
714 { NULL, 0 },
717 static void rtnl_print_neigh(struct nlmsghdr *hdr)
719 struct ndmsg *ndm = NLMSG_DATA(hdr);
720 uint32_t attrs_len = NDA_PAYLOAD(hdr);
721 struct rtattr *attr = NDA_RTA(ndm);
722 struct nda_cacheinfo *ci;
723 int hz = get_user_hz();
724 char addr_str[256];
725 char hw_addr[30];
726 char states[256];
727 char flags[256];
729 if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ndm)))
730 return;
732 tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
733 colorize_start(bold),
734 addr_family2str(ndm->ndm_family),
735 colorize_end());
736 tprintf(", Link Index %d", ndm->ndm_ifindex);
737 tprintf(", State %d (%s%s%s)", ndm->ndm_state,
738 colorize_start(bold),
739 flags2str(neigh_states, ndm->ndm_state, states,
740 sizeof(states)),
741 colorize_end());
742 tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
743 colorize_start(bold),
744 flags2str(neigh_flags, ndm->ndm_flags, flags,
745 sizeof(flags)),
746 colorize_end());
747 tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
748 colorize_start(bold),
749 route_type2str(ndm->ndm_type),
750 colorize_end());
751 tprintf(" ]\n");
753 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
754 switch (attr->rta_type) {
755 case NDA_DST:
756 rta_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
757 RTA_DATA(attr), addr_str,
758 sizeof(addr_str)));
759 break;
760 case NDA_LLADDR:
761 rta_fmt(attr, "HW Address %s",
762 device_addr2str(RTA_DATA(attr),
763 RTA_LEN(attr), 0, hw_addr,
764 sizeof(hw_addr)));
765 break;
766 case NDA_PROBES:
767 rta_fmt(attr, "Probes %d", RTA_UINT32(attr));
768 break;
769 case NDA_CACHEINFO:
770 ci = RTA_DATA(attr);
771 tprintf("\tA: Cache (");
772 tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
773 tprintf(", used(%ds)", ci->ndm_used / hz);
774 tprintf(", updated(%ds)", ci->ndm_updated / hz);
775 tprintf(", refcnt(%d))", ci->ndm_refcnt);
776 tprintf(", Len %d\n", RTA_LEN(attr));
777 break;
778 default:
779 rta_fmt(attr, "0x%x", attr->rta_type);
780 break;
785 static void rtnl_msg_print(struct nlmsghdr *hdr)
787 switch (hdr->nlmsg_type) {
788 case RTM_NEWLINK:
789 case RTM_DELLINK:
790 case RTM_GETLINK:
791 case RTM_SETLINK:
792 rtnl_print_ifinfo(hdr);
793 break;
794 case RTM_NEWADDR:
795 case RTM_DELADDR:
796 case RTM_GETADDR:
797 rtnl_print_ifaddr(hdr);
798 break;
799 case RTM_NEWROUTE:
800 case RTM_DELROUTE:
801 case RTM_GETROUTE:
802 rtnl_print_route(hdr);
803 break;
804 case RTM_NEWNEIGH:
805 case RTM_DELNEIGH:
806 case RTM_GETNEIGH:
807 rtnl_print_neigh(hdr);
808 break;
812 static const char *genl_cmd2str(uint8_t table)
814 switch (table) {
815 case CTRL_CMD_UNSPEC: return "unspec";
816 case CTRL_CMD_NEWFAMILY: return "new family";
817 case CTRL_CMD_DELFAMILY: return "del family";
818 case CTRL_CMD_GETFAMILY: return "get family";
819 case CTRL_CMD_NEWOPS: return "new ops";
820 case CTRL_CMD_DELOPS: return "del ops";
821 case CTRL_CMD_GETOPS: return "get ops";
822 case CTRL_CMD_NEWMCAST_GRP: return "new mcast group";
823 case CTRL_CMD_DELMCAST_GRP: return "del mcast group";
824 case CTRL_CMD_GETMCAST_GRP: return "get mcast group";
826 default: return "Unknown";
830 static struct flag_name genl_ops_flags[] = {
831 { "admin", GENL_ADMIN_PERM },
832 { "doit", GENL_CMD_CAP_DO },
833 { "dumpit", GENL_CMD_CAP_DUMP },
834 { "policy", GENL_CMD_CAP_HASPOL },
835 { NULL, 0 },
838 static void genl_print_ops_attr(struct nlattr *attr, uint32_t attr_len)
840 char str[256];
841 uint32_t flags;
843 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
844 switch (attr->nla_type) {
845 case CTRL_ATTR_OP_ID:
846 nla_fmt_nested(attr, "Id 0x%x", NLA_UINT32(attr));
847 break;
849 case CTRL_ATTR_OP_FLAGS:
850 flags = NLA_UINT32(attr);
852 nla_fmt_nested(attr, "Flags 0x%x (%s%s%s)", flags,
853 colorize_start(bold),
854 flags2str(genl_ops_flags, flags, str, sizeof(str)),
855 colorize_end());
856 break;
857 default:
858 nla_fmt_nested(attr, "0x%x", attr->nla_type);
859 break;
864 static void genl_print_ops_list(struct nlattr *attr, uint32_t attr_len)
866 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
867 nla_fmt_nested_start(attr, "0x%x", attr->nla_type);
868 genl_print_ops_attr(NLA_DATA(attr), NLA_LEN(attr));
869 nla_fmt_nested_end();
873 static void genl_print_mcast_group(struct nlattr *attr, uint32_t attr_len)
875 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
876 switch (attr->nla_type) {
877 case CTRL_ATTR_MCAST_GRP_ID:
878 nla_fmt_nested(attr, "Id 0x%x", NLA_UINT32(attr));
879 break;
881 case CTRL_ATTR_MCAST_GRP_NAME:
882 nla_fmt_nested(attr, "Name %s", NLA_STR(attr));
883 break;
884 default:
885 nla_fmt_nested(attr, "0x%x", attr->nla_type);
886 break;
891 static void genl_print_mc_groups(struct nlattr *attr, uint32_t attr_len)
893 for (; NLA_OK(attr, attr_len); attr = NLA_NEXT(attr, attr_len)) {
894 nla_fmt_nested_start(attr, "0x%x", attr->nla_type);
895 genl_print_mcast_group(NLA_DATA(attr), NLA_LEN(attr));
896 nla_fmt_nested_end();
900 static void genl_print_ctrl_attrs(struct nlmsghdr *hdr)
902 struct genlmsghdr *genl = NLMSG_DATA(hdr);
903 struct nlattr *attr = GEN_NLA(genl);
904 uint32_t attrs_len = NLMSG_PAYLOAD(hdr, sizeof(struct genlmsghdr));
906 for (; NLA_OK(attr, attrs_len); attr = NLA_NEXT(attr, attrs_len)) {
907 switch (attr->nla_type) {
908 case CTRL_ATTR_FAMILY_ID:
909 nla_fmt(attr, "Family Id 0x%x", NLA_UINT16(attr));
910 break;
911 case CTRL_ATTR_FAMILY_NAME:
912 nla_fmt(attr, "Family Name %s", NLA_STR(attr));
913 break;
914 case CTRL_ATTR_VERSION:
915 nla_fmt(attr, "Version %u", NLA_UINT32(attr));
916 break;
917 case CTRL_ATTR_HDRSIZE:
918 nla_fmt(attr, "Header size %u", NLA_UINT32(attr));
919 break;
920 case CTRL_ATTR_MAXATTR:
921 nla_fmt(attr, "Max attr value 0x%x", NLA_UINT32(attr));
922 break;
923 case CTRL_ATTR_OPS:
924 nla_fmt(attr, "Ops list");
925 genl_print_ops_list(NLA_DATA(attr), NLA_LEN(attr));
926 break;
927 case CTRL_ATTR_MCAST_GROUPS:
928 nla_fmt(attr, "Mcast groups");
929 genl_print_mc_groups(NLA_DATA(attr), NLA_LEN(attr));
930 break;
931 default:
932 nla_fmt(attr, "0x%x", attr->nla_type);
933 break;
938 static void genl_msg_print(struct nlmsghdr *hdr)
940 struct genlmsghdr *genl;
942 if (hdr->nlmsg_type != GENL_ID_CTRL) {
943 nlmsg_print_raw(hdr);
944 return;
947 genl = NLMSG_DATA(hdr);
949 tprintf(" [ Cmd %u (%s%s%s)", genl->cmd,
950 colorize_start(bold), genl_cmd2str(genl->cmd), colorize_end());
951 tprintf(", Version %u", genl->version);
952 tprintf(", Reserved %u", genl->reserved);
953 tprintf(" ]\n");
955 genl_print_ctrl_attrs(hdr);
958 static void nlmsg_print(uint16_t family, struct nlmsghdr *hdr)
960 u16 nlmsg_flags = hdr->nlmsg_flags;
961 char type[32];
962 char flags[128];
963 char procname[PATH_MAX];
965 /* Look up the process name if message is not coming from the kernel.
967 * Note that the port id is not necessarily equal to the PID of the
968 * receiving process (e.g. if the application is multithreaded or using
969 * multiple sockets). In these cases we're not able to find a matching
970 * PID and the information will not be printed.
972 if (hdr->nlmsg_pid != 0) {
973 if (proc_get_cmdline(hdr->nlmsg_pid, procname, sizeof(procname)) < 0)
974 snprintf(procname, sizeof(procname), "unknown process");
975 } else
976 snprintf(procname, sizeof(procname), "kernel");
978 tprintf(" [ NLMSG ");
979 tprintf("Family %d (%s%s%s), ", family,
980 colorize_start(bold),
981 nlmsg_family2str(family),
982 colorize_end());
983 tprintf("Len %u, ", hdr->nlmsg_len);
984 tprintf("Type 0x%.4x (%s%s%s), ", hdr->nlmsg_type,
985 colorize_start(bold),
986 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
987 colorize_end());
988 tprintf("Flags 0x%.4x (%s%s%s), ", nlmsg_flags,
989 colorize_start(bold),
990 nlmsg_flags ? nl_nlmsg_flags2str(nlmsg_flags, flags, sizeof(flags)) : "none",
991 colorize_end());
992 tprintf("Seq-Nr %u, ", hdr->nlmsg_seq);
993 tprintf("PID %u", hdr->nlmsg_pid);
994 if (procname[0])
995 tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
996 colorize_end());
997 tprintf(" ]\n");
999 switch (family) {
1000 case NETLINK_ROUTE:
1001 rtnl_msg_print(hdr);
1002 break;
1003 case NETLINK_GENERIC:
1004 genl_msg_print(hdr);
1005 break;
1006 default:
1007 nlmsg_print_raw(hdr);
1011 static void nlmsg(struct pkt_buff *pkt)
1013 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1014 unsigned int trim_len = pkt_len(pkt);
1016 while (hdr) {
1017 trim_len -= hdr->nlmsg_len;
1018 nlmsg_print(ntohs(pkt->sll->sll_protocol), hdr);
1020 if (!pkt_pull(pkt, NLMSG_ALIGN(hdr->nlmsg_len) - NLMSG_HDRLEN))
1021 break;
1023 hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1024 if (hdr == NULL)
1025 break;
1026 if (hdr->nlmsg_len == 0)
1027 break;
1029 if (hdr->nlmsg_type != NLMSG_DONE &&
1030 (hdr->nlmsg_flags & NLM_F_MULTI))
1031 tprintf("\n");
1034 /* mmaped packet? */
1035 if (hdr && hdr->nlmsg_len == 0)
1036 pkt_trim(pkt, trim_len);
1039 static void nlmsg_less(struct pkt_buff *pkt)
1041 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, NLMSG_HDRLEN);
1042 uint16_t family = ntohs(pkt->sll->sll_protocol);
1043 char type[32];
1045 if (hdr == NULL)
1046 return;
1048 tprintf(" NLMSG Family %d (%s%s%s), ", family,
1049 colorize_start(bold),
1050 nlmsg_family2str(family),
1051 colorize_end());
1052 tprintf("Type %u (%s%s%s)", hdr->nlmsg_type,
1053 colorize_start(bold),
1054 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
1055 colorize_end());
1058 struct protocol nlmsg_ops = {
1059 .print_full = nlmsg,
1060 .print_less = nlmsg_less,