2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2014 Tobias Klauser.
4 * Subject to the GPL, version 2.
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>
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))
36 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
40 #define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
43 #define attr_fmt(attr, fmt, ...) \
44 tprintf("\tA: "fmt, ##__VA_ARGS__); \
45 tprintf(", Len %lu\n", RTA_LEN(attr));
52 static const char *flags2str(struct flag_name
*tbl
, unsigned int flags
,
55 int bits_stay
= flags
;
59 for (; tbl
&& tbl
->name
; tbl
++) {
60 if (!(tbl
->flag
& flags
))
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);
73 static const char *nlmsg_family2str(uint16_t 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";
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
)
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";
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";
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
);
184 strncpy(buf
, name
, len
);
189 return nl_nlmsgtype2str(type
, buf
, len
);
192 static const char *addr_family2str(uint16_t 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
);
211 static const char *scope2str(uint8_t 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
);
229 char if_addr
[64] = {};
230 char *af_link
= "unknown";
232 if (ifi
->ifi_family
== AF_UNSPEC
)
234 else if (ifi
->ifi_family
== AF_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
),
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
,
249 tprintf(", Change 0x%x (%s%s%s) ]\n", ifi
->ifi_change
,
250 colorize_start(bold
),
251 rtnl_link_flags2str(ifi
->ifi_change
, flags
,
255 for (; RTA_OK(attr
, attrs_len
); attr
= RTA_NEXT(attr
, attrs_len
)) {
256 switch (attr
->rta_type
) {
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
)));
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
)));
270 attr_fmt(attr
, "Name %s%s%s",
271 colorize_start(bold
), RTA_STR(attr
),
275 attr_fmt(attr
, "MTU %d", RTA_INT(attr
));
278 attr_fmt(attr
, "Link %d", RTA_INT(attr
));
281 attr_fmt(attr
, "QDisc %s", RTA_STR(attr
));
285 uint8_t st
= RTA_UINT8(attr
);
288 attr_fmt(attr
, "Operation state 0x%x (%s%s%s)",
290 colorize_start(bold
),
291 rtnl_link_operstate2str(st
,
292 states
, sizeof(states
)),
298 uint8_t mode
= RTA_UINT8(attr
);
301 attr_fmt(attr
, "Mode 0x%x (%s%s%s)", mode
,
302 colorize_start(bold
),
303 rtnl_link_mode2str(mode
, str
,
309 attr_fmt(attr
, "Group %d", RTA_INT(attr
));
312 attr_fmt(attr
, "Tx queue len %d", RTA_INT(attr
));
314 case IFLA_NET_NS_PID
:
315 attr_fmt(attr
, "Network namespace pid %d",
319 attr_fmt(attr
, "Network namespace fd %d",
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
;
335 tprintf(" [ Address Family %d (%s%s%s)", ifa
->ifa_family
,
336 colorize_start(bold
),
337 addr_family2str(ifa
->ifa_family
),
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
,
345 tprintf(", Scope %d (%s%s%s)", ifa
->ifa_scope
,
346 colorize_start(bold
),
347 scope2str(ifa
->ifa_scope
),
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
) {
354 attr_fmt(attr
, "Local %s", addr2str(ifa
->ifa_family
,
355 RTA_DATA(attr
), addr_str
, sizeof(addr_str
)));
358 attr_fmt(attr
, "Address %s", addr2str(ifa
->ifa_family
,
359 RTA_DATA(attr
), addr_str
, sizeof(addr_str
)));
362 attr_fmt(attr
, "Broadcast %s",
363 addr2str(ifa
->ifa_family
,
364 RTA_DATA(attr
), addr_str
,
368 attr_fmt(attr
, "Multicast %s",
369 addr2str(ifa
->ifa_family
,
370 RTA_DATA(attr
), addr_str
,
374 attr_fmt(attr
, "Anycast %s", addr2str(ifa
->ifa_family
,
375 RTA_DATA(attr
), addr_str
, sizeof(addr_str
)));
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
)),
387 attr_fmt(attr
, "Label %s", RTA_STR(attr
));
391 tprintf("\tA: Cache (");
393 if (ci
->ifa_valid
== INFINITY
)
394 tprintf("valid lft(forever)");
396 tprintf("valid lft(%us)", ci
->ifa_valid
);
398 if (ci
->ifa_prefered
== INFINITY
)
399 tprintf(", prefrd lft(forever)");
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
));
411 static const char *route_table2str(uint8_t 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
)
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";
445 default: return "Unknown";
449 static const char *route_type2str(uint8_t 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
},
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();
490 tprintf(" [ Route Family %d (%s%s%s)", rtm
->rtm_family
,
491 colorize_start(bold
),
492 addr_family2str(rtm
->rtm_family
),
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
),
501 tprintf(", Proto %d (%s%s%s)", rtm
->rtm_protocol
,
502 colorize_start(bold
),
503 route_proto2str(rtm
->rtm_protocol
),
505 tprintf(", Scope %d (%s%s%s)", rtm
->rtm_scope
,
506 colorize_start(bold
),
507 scope2str(rtm
->rtm_scope
),
509 tprintf(", Type %d (%s%s%s)", rtm
->rtm_type
,
510 colorize_start(bold
),
511 route_type2str(rtm
->rtm_type
),
513 tprintf(", Flags 0x%x (%s%s%s) ]\n", rtm
->rtm_flags
,
514 colorize_start(bold
),
515 flags2str(route_flags
, rtm
->rtm_flags
, flags
,
519 for (; RTA_OK(attr
, attrs_len
); attr
= RTA_NEXT(attr
, attrs_len
)) {
520 switch (attr
->rta_type
) {
522 attr_fmt(attr
, "Dst %s", addr2str(rtm
->rtm_family
,
523 RTA_DATA(attr
), addr_str
, sizeof(addr_str
)));
526 attr_fmt(attr
, "Src %s", addr2str(rtm
->rtm_family
,
527 RTA_DATA(attr
), addr_str
, sizeof(addr_str
)));
530 attr_fmt(attr
, "Iif %d", RTA_INT(attr
));
533 attr_fmt(attr
, "Oif %d", RTA_INT(attr
));
536 attr_fmt(attr
, "Gateway %s", addr2str(rtm
->rtm_family
,
537 RTA_DATA(attr
), addr_str
, sizeof(addr_str
)));
540 attr_fmt(attr
, "Priority %u", RTA_UINT32(attr
));
543 attr_fmt(attr
, "Pref Src %s", addr2str(rtm
->rtm_family
,
544 RTA_DATA(attr
), addr_str
, sizeof(addr_str
)));
547 attr_fmt(attr
, "Mark 0x%x", RTA_UINT(attr
));
550 attr_fmt(attr
, "Flow 0x%x", RTA_UINT(attr
));
553 attr_fmt(attr
, "Table %d (%s%s%s)", RTA_UINT32(attr
),
554 colorize_start(bold
),
555 route_table2str(RTA_UINT32(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
));
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
},
588 /* Copied from linux/neighbour.h */
590 # define NTF_USE 0x01
593 # define NTF_SELF 0x02
596 # define NTF_MASTER 0x04
599 # define NTF_PROXY 0x08
601 #ifndef NTF_EXT_LEARNED
602 # define NTF_EXT_LEARNED 0x10
605 # define NTF_ROUTER 0x80
608 static struct flag_name neigh_flags
[] = {
610 { "self", NTF_SELF
},
611 { "master", NTF_MASTER
},
612 { "proxy", NTF_PROXY
},
613 { "ext learned", NTF_EXT_LEARNED
},
614 { "router", NTF_ROUTER
},
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();
630 tprintf(" [ Neigh Family %d (%s%s%s)", ndm
->ndm_family
,
631 colorize_start(bold
),
632 addr_family2str(ndm
->ndm_family
),
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
,
640 tprintf(", Flags %d (%s%s%s)", ndm
->ndm_flags
,
641 colorize_start(bold
),
642 flags2str(neigh_flags
, ndm
->ndm_flags
, flags
,
645 tprintf(", Type %d (%s%s%s)", ndm
->ndm_type
,
646 colorize_start(bold
),
647 route_type2str(ndm
->ndm_type
),
651 for (; RTA_OK(attr
, attrs_len
); attr
= RTA_NEXT(attr
, attrs_len
)) {
652 switch (attr
->rta_type
) {
654 attr_fmt(attr
, "Address %s", addr2str(ndm
->ndm_family
,
655 RTA_DATA(attr
), addr_str
,
659 attr_fmt(attr
, "HW Address %s",
660 device_addr2str(RTA_DATA(attr
),
661 RTA_LEN(attr
), 0, hw_addr
,
665 attr_fmt(attr
, "Probes %d", RTA_UINT32(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
));
680 static void rtnl_msg_print(struct nlmsghdr
*hdr
)
682 switch (hdr
->nlmsg_type
) {
687 rtnl_print_ifinfo(hdr
);
692 rtnl_print_ifaddr(hdr
);
697 rtnl_print_route(hdr
);
702 rtnl_print_neigh(hdr
);
707 static void nlmsg_print(uint16_t family
, struct nlmsghdr
*hdr
)
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");
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
),
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
)),
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
)),
740 tprintf("Seq-Nr %u, ", hdr
->nlmsg_seq
);
741 tprintf("PID %u", hdr
->nlmsg_pid
);
743 tprintf(" (%s%s%s)", colorize_start(bold
), basename(procname
),
747 if (family
== NETLINK_ROUTE
)
751 static void nlmsg(struct pkt_buff
*pkt
)
753 struct nlmsghdr
*hdr
= (struct nlmsghdr
*) pkt_pull(pkt
, sizeof(*hdr
));
756 nlmsg_print(ntohs(pkt
->sll
->sll_protocol
), hdr
);
758 if (!pkt_pull(pkt
, NLMSG_PAYLOAD(hdr
, 0)))
761 hdr
= (struct nlmsghdr
*) pkt_pull(pkt
, sizeof(*hdr
));
762 if (hdr
&& hdr
->nlmsg_type
!= NLMSG_DONE
&&
763 (hdr
->nlmsg_flags
& NLM_F_MULTI
))
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
);
777 tprintf(" NLMSG Family %d (%s%s%s), ", family
,
778 colorize_start(bold
),
779 nlmsg_family2str(family
),
781 tprintf("Type %u (%s%s%s)", hdr
->nlmsg_type
,
782 colorize_start(bold
),
783 nlmsg_type2str(family
, hdr
->nlmsg_type
, type
, sizeof(type
)),
787 struct protocol nlmsg_ops
= {
789 .print_less
= nlmsg_less
,