curvetun: Fix issues detected by the Coverity scanner
[netsniff-ng.git] / proto_nlmsg.c
blob1dde5e1f38ee131eb6c26d3d3fbcf8410c8422bb
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) 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 %lu\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;
326 static void rtnl_print_ifaddr(struct nlmsghdr *hdr)
328 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
329 uint32_t attrs_len = IFA_PAYLOAD(hdr);
330 struct rtattr *attr = IFA_RTA(ifa);
331 struct ifa_cacheinfo *ci;
332 char addr_str[256];
333 char flags[256];
335 tprintf(" [ Address Family %d (%s%s%s)", ifa->ifa_family,
336 colorize_start(bold),
337 addr_family2str(ifa->ifa_family),
338 colorize_end());
339 tprintf(", Prefix Len %d", ifa->ifa_prefixlen);
340 tprintf(", Flags %d (%s%s%s)", ifa->ifa_flags,
341 colorize_start(bold),
342 rtnl_addr_flags2str(ifa->ifa_flags, flags,
343 sizeof(flags)),
344 colorize_end());
345 tprintf(", Scope %d (%s%s%s)", ifa->ifa_scope,
346 colorize_start(bold),
347 scope2str(ifa->ifa_scope),
348 colorize_end());
349 tprintf(", Link Index %d ]\n", ifa->ifa_index);
351 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
352 switch (attr->rta_type) {
353 case IFA_LOCAL:
354 attr_fmt(attr, "Local %s", addr2str(ifa->ifa_family,
355 RTA_DATA(attr), addr_str, sizeof(addr_str)));
356 break;
357 case IFA_ADDRESS:
358 attr_fmt(attr, "Address %s", addr2str(ifa->ifa_family,
359 RTA_DATA(attr), addr_str, sizeof(addr_str)));
360 break;
361 case IFA_BROADCAST:
362 attr_fmt(attr, "Broadcast %s",
363 addr2str(ifa->ifa_family,
364 RTA_DATA(attr), addr_str,
365 sizeof(addr_str)));
366 break;
367 case IFA_MULTICAST:
368 attr_fmt(attr, "Multicast %s",
369 addr2str(ifa->ifa_family,
370 RTA_DATA(attr), addr_str,
371 sizeof(addr_str)));
372 break;
373 case IFA_ANYCAST:
374 attr_fmt(attr, "Anycast %s", addr2str(ifa->ifa_family,
375 RTA_DATA(attr), addr_str, sizeof(addr_str)));
376 break;
377 #ifdef IFA_FLAGS
378 case IFA_FLAGS:
379 attr_fmt(attr, "Flags %d (%s%s%s)", RTA_INT(attr),
380 colorize_start(bold),
381 rtnl_addr_flags2str(RTA_INT(attr),
382 flags, sizeof(flags)),
383 colorize_end());
384 break;
385 #endif
386 case IFA_LABEL:
387 attr_fmt(attr, "Label %s", RTA_STR(attr));
388 break;
389 case IFA_CACHEINFO:
390 ci = RTA_DATA(attr);
391 tprintf("\tA: Cache (");
393 if (ci->ifa_valid == INFINITY)
394 tprintf("valid lft(forever)");
395 else
396 tprintf("valid lft(%us)", ci->ifa_valid);
398 if (ci->ifa_prefered == INFINITY)
399 tprintf(", prefrd lft(forever)");
400 else
401 tprintf(", prefrd lft(%us)", ci->ifa_prefered);
403 tprintf(", created on(%.2fs)", (double)ci->cstamp / 100);
404 tprintf(", updated on(%.2fs))", (double)ci->cstamp / 100);
405 tprintf(", Len %lu\n", RTA_LEN(attr));
406 break;
411 static const char *route_table2str(uint8_t table)
413 switch (table) {
414 case RT_TABLE_UNSPEC: return "unspec";
415 case RT_TABLE_COMPAT: return "compat";
416 case RT_TABLE_DEFAULT: return "default";
417 case RT_TABLE_MAIN: return "main";
418 case RT_TABLE_LOCAL: return "local";
420 default: return "Unknown";
424 static const char *route_proto2str(uint8_t proto)
426 switch (proto) {
427 case RTPROT_UNSPEC: return "unspec";
428 case RTPROT_REDIRECT: return "redirect";
429 case RTPROT_KERNEL: return "kernel";
430 case RTPROT_BOOT: return "boot";
431 case RTPROT_STATIC: return "static";
432 case RTPROT_GATED: return "gated";
433 case RTPROT_RA: return "ra";
434 case RTPROT_MRT: return "mrt";
435 case RTPROT_ZEBRA: return "zebra";
436 case RTPROT_BIRD: return "bird";
437 case RTPROT_DNROUTED: return "DECnet";
438 case RTPROT_XORP: return "xorp";
439 case RTPROT_NTK: return "netsukuku";
440 case RTPROT_DHCP: return "dhcpc";
441 #ifdef RTPROT_MROUTED
442 case RTPROT_MROUTED: return "mrouted";
443 #endif
445 default: return "Unknown";
449 static const char *route_type2str(uint8_t type)
451 switch (type) {
452 case RTN_UNSPEC: return "unspec";
453 case RTN_UNICAST: return "unicast";
454 case RTN_LOCAL: return "local";
455 case RTN_BROADCAST: return "broadcast";
456 case RTN_ANYCAST: return "anycast";
457 case RTN_MULTICAST: return "multicast";
458 case RTN_BLACKHOLE: return "blackhole";
459 case RTN_UNREACHABLE: return "unreach";
460 case RTN_PROHIBIT: return "prohibit";
461 case RTN_THROW: return "throw";
462 case RTN_NAT: return "nat";
463 case RTN_XRESOLVE: return "xresolve";
465 default: return "Unknown";
469 static struct flag_name route_flags[] = {
470 { "notify", RTM_F_NOTIFY },
471 { "cloned", RTM_F_CLONED },
472 { "equalize", RTM_F_EQUALIZE },
473 { "prefix", RTM_F_PREFIX },
474 { "dead", RTNH_F_DEAD },
475 { "pervasive", RTNH_F_PERVASIVE },
476 { "onlink", RTNH_F_ONLINK },
477 { NULL, 0 },
480 static void rtnl_print_route(struct nlmsghdr *hdr)
482 struct rtmsg *rtm = NLMSG_DATA(hdr);
483 uint32_t attrs_len = RTM_PAYLOAD(hdr);
484 struct rtattr *attr = RTM_RTA(rtm);
485 struct rta_cacheinfo *ci;
486 int hz = get_user_hz();
487 char addr_str[256];
488 char flags[256];
490 tprintf(" [ Route Family %d (%s%s%s)", rtm->rtm_family,
491 colorize_start(bold),
492 addr_family2str(rtm->rtm_family),
493 colorize_end());
494 tprintf(", Dst Len %d", rtm->rtm_dst_len);
495 tprintf(", Src Len %d", rtm->rtm_src_len);
496 tprintf(", ToS %d", rtm->rtm_tos);
497 tprintf(", Table %d (%s%s%s)", rtm->rtm_table,
498 colorize_start(bold),
499 route_table2str(rtm->rtm_table),
500 colorize_end());
501 tprintf(", Proto %d (%s%s%s)", rtm->rtm_protocol,
502 colorize_start(bold),
503 route_proto2str(rtm->rtm_protocol),
504 colorize_end());
505 tprintf(", Scope %d (%s%s%s)", rtm->rtm_scope,
506 colorize_start(bold),
507 scope2str(rtm->rtm_scope),
508 colorize_end());
509 tprintf(", Type %d (%s%s%s)", rtm->rtm_type,
510 colorize_start(bold),
511 route_type2str(rtm->rtm_type),
512 colorize_end());
513 tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm->rtm_flags,
514 colorize_start(bold),
515 flags2str(route_flags, rtm->rtm_flags, flags,
516 sizeof(flags)),
517 colorize_end());
519 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
520 switch (attr->rta_type) {
521 case RTA_DST:
522 attr_fmt(attr, "Dst %s", addr2str(rtm->rtm_family,
523 RTA_DATA(attr), addr_str, sizeof(addr_str)));
524 break;
525 case RTA_SRC:
526 attr_fmt(attr, "Src %s", addr2str(rtm->rtm_family,
527 RTA_DATA(attr), addr_str, sizeof(addr_str)));
528 break;
529 case RTA_IIF:
530 attr_fmt(attr, "Iif %d", RTA_INT(attr));
531 break;
532 case RTA_OIF:
533 attr_fmt(attr, "Oif %d", RTA_INT(attr));
534 break;
535 case RTA_GATEWAY:
536 attr_fmt(attr, "Gateway %s", addr2str(rtm->rtm_family,
537 RTA_DATA(attr), addr_str, sizeof(addr_str)));
538 break;
539 case RTA_PRIORITY:
540 attr_fmt(attr, "Priority %u", RTA_UINT32(attr));
541 break;
542 case RTA_PREFSRC:
543 attr_fmt(attr, "Pref Src %s", addr2str(rtm->rtm_family,
544 RTA_DATA(attr), addr_str, sizeof(addr_str)));
545 break;
546 case RTA_MARK:
547 attr_fmt(attr, "Mark 0x%x", RTA_UINT(attr));
548 break;
549 case RTA_FLOW:
550 attr_fmt(attr, "Flow 0x%x", RTA_UINT(attr));
551 break;
552 case RTA_TABLE:
553 attr_fmt(attr, "Table %d (%s%s%s)", RTA_UINT32(attr),
554 colorize_start(bold),
555 route_table2str(RTA_UINT32(attr)),
556 colorize_end());
557 break;
558 case RTA_CACHEINFO:
559 ci = RTA_DATA(attr);
560 tprintf("\tA: Cache (");
561 tprintf("expires(%ds)", ci->rta_expires / hz);
562 tprintf(", error(%d)", ci->rta_error);
563 tprintf(", users(%d)", ci->rta_clntref);
564 tprintf(", used(%d)", ci->rta_used);
565 tprintf(", last use(%ds)", ci->rta_lastuse / hz);
566 tprintf(", id(%d)", ci->rta_id);
567 tprintf(", ts(%d)", ci->rta_ts);
568 tprintf(", ts age(%ds))", ci->rta_tsage);
569 tprintf(", Len %lu\n", RTA_LEN(attr));
570 break;
575 static struct flag_name neigh_states[] = {
576 { "incomplete", NUD_INCOMPLETE },
577 { "reachable", NUD_REACHABLE },
578 { "stale", NUD_STALE },
579 { "delay", NUD_DELAY },
580 { "probe", NUD_PROBE },
581 { "failed", NUD_FAILED },
582 { "noarp", NUD_NOARP },
583 { "permanent", NUD_PERMANENT },
584 { "none", NUD_NONE },
585 { NULL, 0 },
588 /* Copied from linux/neighbour.h */
589 #ifndef NTF_USE
590 # define NTF_USE 0x01
591 #endif
592 #ifndef NTF_SELF
593 # define NTF_SELF 0x02
594 #endif
595 #ifndef NTF_MASTER
596 # define NTF_MASTER 0x04
597 #endif
598 #ifndef NTF_PROXY
599 # define NTF_PROXY 0x08
600 #endif
601 #ifndef NTF_EXT_LEARNED
602 # define NTF_EXT_LEARNED 0x10
603 #endif
604 #ifndef NTF_ROUTER
605 # define NTF_ROUTER 0x80
606 #endif
608 static struct flag_name neigh_flags[] = {
609 { "use", NTF_USE },
610 { "self", NTF_SELF },
611 { "master", NTF_MASTER },
612 { "proxy", NTF_PROXY },
613 { "ext learned", NTF_EXT_LEARNED },
614 { "router", NTF_ROUTER },
615 { NULL, 0 },
618 static void rtnl_print_neigh(struct nlmsghdr *hdr)
620 struct ndmsg *ndm = NLMSG_DATA(hdr);
621 uint32_t attrs_len = NDA_PAYLOAD(hdr);
622 struct rtattr *attr = NDA_RTA(ndm);
623 struct nda_cacheinfo *ci;
624 int hz = get_user_hz();
625 char addr_str[256];
626 char hw_addr[30];
627 char states[256];
628 char flags[256];
630 tprintf(" [ Neigh Family %d (%s%s%s)", ndm->ndm_family,
631 colorize_start(bold),
632 addr_family2str(ndm->ndm_family),
633 colorize_end());
634 tprintf(", Link Index %d", ndm->ndm_ifindex);
635 tprintf(", State %d (%s%s%s)", ndm->ndm_state,
636 colorize_start(bold),
637 flags2str(neigh_states, ndm->ndm_state, states,
638 sizeof(states)),
639 colorize_end());
640 tprintf(", Flags %d (%s%s%s)", ndm->ndm_flags,
641 colorize_start(bold),
642 flags2str(neigh_flags, ndm->ndm_flags, flags,
643 sizeof(flags)),
644 colorize_end());
645 tprintf(", Type %d (%s%s%s)", ndm->ndm_type,
646 colorize_start(bold),
647 route_type2str(ndm->ndm_type),
648 colorize_end());
649 tprintf(" ]\n");
651 for (; RTA_OK(attr, attrs_len); attr = RTA_NEXT(attr, attrs_len)) {
652 switch (attr->rta_type) {
653 case NDA_DST:
654 attr_fmt(attr, "Address %s", addr2str(ndm->ndm_family,
655 RTA_DATA(attr), addr_str,
656 sizeof(addr_str)));
657 break;
658 case NDA_LLADDR:
659 attr_fmt(attr, "HW Address %s",
660 device_addr2str(RTA_DATA(attr),
661 RTA_LEN(attr), 0, hw_addr,
662 sizeof(hw_addr)));
663 break;
664 case NDA_PROBES:
665 attr_fmt(attr, "Probes %d", RTA_UINT32(attr));
666 break;
667 case NDA_CACHEINFO:
668 ci = RTA_DATA(attr);
669 tprintf("\tA: Cache (");
670 tprintf("confirmed(%ds)", ci->ndm_confirmed / hz);
671 tprintf(", used(%ds)", ci->ndm_used / hz);
672 tprintf(", updated(%ds)", ci->ndm_updated / hz);
673 tprintf(", refcnt(%d))", ci->ndm_refcnt);
674 tprintf(", Len %lu\n", RTA_LEN(attr));
675 break;
680 static void rtnl_msg_print(struct nlmsghdr *hdr)
682 switch (hdr->nlmsg_type) {
683 case RTM_NEWLINK:
684 case RTM_DELLINK:
685 case RTM_GETLINK:
686 case RTM_SETLINK:
687 rtnl_print_ifinfo(hdr);
688 break;
689 case RTM_NEWADDR:
690 case RTM_DELADDR:
691 case RTM_GETADDR:
692 rtnl_print_ifaddr(hdr);
693 break;
694 case RTM_NEWROUTE:
695 case RTM_DELROUTE:
696 case RTM_GETROUTE:
697 rtnl_print_route(hdr);
698 break;
699 case RTM_NEWNEIGH:
700 case RTM_DELNEIGH:
701 case RTM_GETNEIGH:
702 rtnl_print_neigh(hdr);
703 break;
707 static void nlmsg_print(uint16_t family, struct nlmsghdr *hdr)
709 char type[32];
710 char flags[128];
711 char procname[PATH_MAX];
713 /* Look up the process name if message is not coming from the kernel.
715 * Note that the port id is not necessarily equal to the PID of the
716 * receiving process (e.g. if the application is multithreaded or using
717 * multiple sockets). In these cases we're not able to find a matching
718 * PID and the information will not be printed.
720 if (hdr->nlmsg_pid != 0) {
721 if (proc_get_cmdline(hdr->nlmsg_pid, procname, sizeof(procname)) < 0)
722 snprintf(procname, sizeof(procname), "unknown process");
723 } else
724 snprintf(procname, sizeof(procname), "kernel");
726 tprintf(" [ NLMSG ");
727 tprintf("Family %d (%s%s%s), ", family,
728 colorize_start(bold),
729 nlmsg_family2str(family),
730 colorize_end());
731 tprintf("Len %u, ", hdr->nlmsg_len);
732 tprintf("Type 0x%.4x (%s%s%s), ", hdr->nlmsg_type,
733 colorize_start(bold),
734 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
735 colorize_end());
736 tprintf("Flags 0x%.4x (%s%s%s), ", hdr->nlmsg_flags,
737 colorize_start(bold),
738 nl_nlmsg_flags2str(hdr->nlmsg_flags, flags, sizeof(flags)),
739 colorize_end());
740 tprintf("Seq-Nr %u, ", hdr->nlmsg_seq);
741 tprintf("PID %u", hdr->nlmsg_pid);
742 if (procname[0])
743 tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
744 colorize_end());
745 tprintf(" ]\n");
747 if (family == NETLINK_ROUTE)
748 rtnl_msg_print(hdr);
751 static void nlmsg(struct pkt_buff *pkt)
753 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, sizeof(*hdr));
755 while (hdr) {
756 nlmsg_print(ntohs(pkt->sll->sll_protocol), hdr);
758 if (!pkt_pull(pkt, NLMSG_PAYLOAD(hdr, 0)))
759 break;
761 hdr = (struct nlmsghdr *) pkt_pull(pkt, sizeof(*hdr));
762 if (hdr && hdr->nlmsg_type != NLMSG_DONE &&
763 (hdr->nlmsg_flags & NLM_F_MULTI))
764 tprintf("\n");
768 static void nlmsg_less(struct pkt_buff *pkt)
770 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, sizeof(*hdr));
771 uint16_t family = ntohs(pkt->sll->sll_protocol);
772 char type[32];
774 if (hdr == NULL)
775 return;
777 tprintf(" NLMSG Family %d (%s%s%s), ", family,
778 colorize_start(bold),
779 nlmsg_family2str(family),
780 colorize_end());
781 tprintf("Type %u (%s%s%s)", hdr->nlmsg_type,
782 colorize_start(bold),
783 nlmsg_type2str(family, hdr->nlmsg_type, type, sizeof(type)),
784 colorize_end());
787 struct protocol nlmsg_ops = {
788 .print_full = nlmsg,
789 .print_less = nlmsg_less,