2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2014 Tobias Klauser.
4 * Subject to the GPL, version 2.
11 #include <netlink/msg.h>
12 #include <netlink/route/link.h>
13 #include <linux/if_arp.h>
14 #include <arpa/inet.h>
20 static const char *nlmsg_family2str(uint16_t family
)
23 case NETLINK_ROUTE
: return "routing";
24 case NETLINK_UNUSED
: return "unused";
25 case NETLINK_USERSOCK
: return "user-mode socket";
26 case NETLINK_FIREWALL
: return "unused, formerly ip_queue";
27 /* NETLINK_INET_DIAG was renamed to NETLINK_SOCK_DIAG in Linux kernel 3.10 */
28 #if defined(NETLINK_SOCK_DIAG)
29 case NETLINK_SOCK_DIAG
: return "socket monitoring";
30 #elif defined(NETLINK_INET_DIAG)
31 case NETLINK_INET_DIAG
: return "INET socket monitoring";
33 case NETLINK_NFLOG
: return "netfilter ULOG";
34 case NETLINK_XFRM
: return "IPsec";
35 case NETLINK_SELINUX
: return "SELinux event notification";
36 case NETLINK_ISCSI
: return "Open-iSCSI";
37 case NETLINK_AUDIT
: return "auditing";
38 case NETLINK_FIB_LOOKUP
: return "FIB lookup";
39 case NETLINK_CONNECTOR
: return "Kernel connector";
40 case NETLINK_NETFILTER
: return "Netfilter";
41 case NETLINK_IP6_FW
: return "unused, formerly ip6_queue";
42 case NETLINK_DNRTMSG
: return "DECnet routing";
43 case NETLINK_KOBJECT_UEVENT
: return "Kernel messages";
44 case NETLINK_GENERIC
: return "Generic";
45 case NETLINK_SCSITRANSPORT
: return "SCSI transports";
46 case NETLINK_ECRYPTFS
: return "ecryptfs";
47 case NETLINK_RDMA
: return "RDMA";
48 case NETLINK_CRYPTO
: return "Crypto layer";
49 default: return "Unknown";
53 static const char *nlmsg_rtnl_type2str(uint16_t type
)
56 case RTM_NEWLINK
: return "new link";
57 case RTM_DELLINK
: return "del link";
58 case RTM_GETLINK
: return "get link";
59 case RTM_SETLINK
: return "set link";
61 case RTM_NEWADDR
: return "new addr";
62 case RTM_DELADDR
: return "del addr";
63 case RTM_GETADDR
: return "get addr";
65 case RTM_NEWROUTE
: return "new route";
66 case RTM_DELROUTE
: return "del route";
67 case RTM_GETROUTE
: return "get route";
69 case RTM_NEWNEIGH
: return "new neigh";
70 case RTM_DELNEIGH
: return "del neigh";
71 case RTM_GETNEIGH
: return "get neigh";
73 case RTM_NEWRULE
: return "new rule";
74 case RTM_DELRULE
: return "del rule";
75 case RTM_GETRULE
: return "get rule";
77 case RTM_NEWQDISC
: return "new tc qdisc";
78 case RTM_DELQDISC
: return "del tc qdisc";
79 case RTM_GETQDISC
: return "get tc qdisc";
81 case RTM_NEWTCLASS
: return "new tc class";
82 case RTM_DELTCLASS
: return "del tc class";
83 case RTM_GETTCLASS
: return "get tc class";
85 case RTM_NEWTFILTER
: return "new tc filter";
86 case RTM_DELTFILTER
: return "del tc filter";
87 case RTM_GETTFILTER
: return "get tc filter";
89 case RTM_NEWACTION
: return "new tc action";
90 case RTM_DELACTION
: return "del tc action";
91 case RTM_GETACTION
: return "get tc action";
93 case RTM_NEWPREFIX
: return "new prefix";
95 case RTM_GETMULTICAST
: return "get mcast addr";
97 case RTM_GETANYCAST
: return "get anycast addr";
99 case RTM_NEWNEIGHTBL
: return "new neigh table";
100 case RTM_GETNEIGHTBL
: return "get neigh table";
101 case RTM_SETNEIGHTBL
: return "set neigh table";
103 case RTM_NEWNDUSEROPT
: return "new ndisc user option";
105 case RTM_NEWADDRLABEL
: return "new addr label";
106 case RTM_DELADDRLABEL
: return "del addr label";
107 case RTM_GETADDRLABEL
: return "get addr label";
109 case RTM_GETDCB
: return "get data-center-bridge";
110 case RTM_SETDCB
: return "set data-center-bridge";
112 #if defined(RTM_NEWNETCONF)
113 case RTM_NEWNETCONF
: return "new netconf";
114 case RTM_GETNETCONF
: return "get netconf";
117 #if defined(RTM_NEWMDB)
118 case RTM_NEWMDB
: return "new bridge mdb";
119 case RTM_DELMDB
: return "del bridge mdb";
120 case RTM_GETMDB
: return "get bridge mdb";
122 default: return NULL
;
126 static char *if_type2str(uint16_t type
)
129 case ARPHRD_ETHER
: return "ether";
130 case ARPHRD_EETHER
: return "eether";
131 case ARPHRD_AX25
: return "ax25";
132 case ARPHRD_PRONET
: return "pronet";
133 case ARPHRD_CHAOS
: return "chaos";
134 case ARPHRD_IEEE802
: return "ieee802";
135 case ARPHRD_ARCNET
: return "arcnet";
136 case ARPHRD_APPLETLK
: return "appletlk";
137 case ARPHRD_DLCI
: return "dlci";
138 case ARPHRD_ATM
: return "atm";
139 case ARPHRD_METRICOM
: return "metricom";
140 case ARPHRD_IEEE1394
: return "ieee1394";
141 case ARPHRD_INFINIBAND
: return "infiniband";
142 case ARPHRD_SLIP
: return "slip";
143 case ARPHRD_CSLIP
: return "cslip";
144 case ARPHRD_SLIP6
: return "slip6";
145 case ARPHRD_CSLIP6
: return "cslip6";
146 case ARPHRD_RSRVD
: return "RSRVD";
147 case ARPHRD_ADAPT
: return "adapt";
148 case ARPHRD_ROSE
: return "rose";
149 case ARPHRD_X25
: return "x25";
150 case ARPHRD_HWX25
: return "hwx25";
151 case ARPHRD_CAN
: return "can";
152 case ARPHRD_PPP
: return "ppp";
153 case ARPHRD_HDLC
: return "hdlc";
154 case ARPHRD_LAPB
: return "lapb";
155 case ARPHRD_DDCMP
: return "ddcmp";
156 case ARPHRD_RAWHDLC
: return "rawhdlc";
157 case ARPHRD_TUNNEL
: return "tunnel";
158 case ARPHRD_TUNNEL6
: return "tunnel6";
159 case ARPHRD_FRAD
: return "frad";
160 case ARPHRD_SKIP
: return "skip";
161 case ARPHRD_LOOPBACK
: return "loopback";
162 case ARPHRD_LOCALTLK
: return "localtlk";
163 case ARPHRD_FDDI
: return "fddi";
164 case ARPHRD_BIF
: return "bif";
165 case ARPHRD_SIT
: return "sit";
166 case ARPHRD_IPDDP
: return "ipddp";
167 case ARPHRD_IPGRE
: return "ipgre";
168 case ARPHRD_PIMREG
: return "pimreg";
169 case ARPHRD_HIPPI
: return "hippi";
170 case ARPHRD_ASH
: return "ash";
171 case ARPHRD_ECONET
: return "econet";
172 case ARPHRD_IRDA
: return "irda";
173 case ARPHRD_FCPP
: return "fcpp";
174 case ARPHRD_FCAL
: return "fcal";
175 case ARPHRD_FCPL
: return "fcpl";
176 case ARPHRD_FCFABRIC
: return "fcfb0";
177 case ARPHRD_FCFABRIC
+ 1: return "fcfb1";
178 case ARPHRD_FCFABRIC
+ 2: return "fcfb2";
179 case ARPHRD_FCFABRIC
+ 3: return "fcfb3";
180 case ARPHRD_FCFABRIC
+ 4: return "fcfb4";
181 case ARPHRD_FCFABRIC
+ 5: return "fcfb5";
182 case ARPHRD_FCFABRIC
+ 6: return "fcfb6";
183 case ARPHRD_FCFABRIC
+ 7: return "fcfb7";
184 case ARPHRD_FCFABRIC
+ 8: return "fcfb8";
185 case ARPHRD_FCFABRIC
+ 9: return "fcfb9";
186 case ARPHRD_FCFABRIC
+ 10: return "fcfb10";
187 case ARPHRD_FCFABRIC
+ 11: return "fcfb11";
188 case ARPHRD_FCFABRIC
+ 12: return "fcfb12";
189 case ARPHRD_IEEE802_TR
: return "ieee802_tr";
190 case ARPHRD_IEEE80211
: return "ieee80211";
191 case ARPHRD_IEEE80211_PRISM
: return "ieee80211_prism";
192 case ARPHRD_IEEE80211_RADIOTAP
: return "ieee80211_radiotap";
193 case ARPHRD_IEEE802154
: return "ieee802154";
194 case ARPHRD_PHONET
: return "phonet";
195 case ARPHRD_PHONET_PIPE
: return "phonet_pipe";
196 case ARPHRD_CAIF
: return "caif";
197 case ARPHRD_IP6GRE
: return "ip6gre";
198 case ARPHRD_NETLINK
: return "netlink";
199 case ARPHRD_NONE
: return "none";
200 case ARPHRD_VOID
: return "void";
202 default: return "Unknown";
206 /* Taken from iproute2 */
207 static const char *ll_addr_n2a(const unsigned char *addr
, int alen
, int type
,
214 (type
== ARPHRD_TUNNEL
|| type
== ARPHRD_SIT
|| type
== ARPHRD_IPGRE
)) {
215 return inet_ntop(AF_INET
, addr
, buf
, blen
);
217 if (alen
== 16 && type
== ARPHRD_TUNNEL6
) {
218 return inet_ntop(AF_INET6
, addr
, buf
, blen
);
221 for (i
=0; i
<alen
; i
++) {
223 snprintf(buf
+l
, blen
, "%02x", addr
[i
]);
227 snprintf(buf
+l
, blen
, ":%02x", addr
[i
]);
235 static char *nlmsg_type2str(uint16_t proto
, uint16_t type
, char *buf
, int len
)
237 if (proto
== NETLINK_ROUTE
&& type
< RTM_MAX
) {
238 const char *name
= nlmsg_rtnl_type2str(type
);
240 strncpy(buf
, name
, len
);
245 return nl_nlmsgtype2str(type
, buf
, len
);
248 static void rtnl_print_ifinfo(struct nlmsghdr
*hdr
)
250 struct ifinfomsg
*ifi
= NLMSG_DATA(hdr
);
251 struct rtattr
*attr
= IFLA_RTA(ifi
);
252 uint32_t attrs_len
= IFLA_PAYLOAD(hdr
);
254 char if_addr
[64] = {};
255 char *af_link
= "Unknown";
257 if (ifi
->ifi_family
== AF_UNSPEC
)
259 else if (ifi
->ifi_family
== AF_BRIDGE
)
262 tprintf(" [ Link Family %d (%s%s%s)", ifi
->ifi_family
,
263 colorize_start(bold
), af_link
, colorize_end());
264 tprintf(", Type %d (%s%s%s)", ifi
->ifi_type
,
265 colorize_start(bold
),
266 if_type2str(ifi
->ifi_type
),
268 tprintf(", Index %d", ifi
->ifi_index
);
269 tprintf(", Flags 0x%x (%s%s%s)", ifi
->ifi_flags
,
270 colorize_start(bold
),
271 rtnl_link_flags2str(ifi
->ifi_flags
, flags
,
274 tprintf(", Change 0x%x (%s%s%s) ]\n", ifi
->ifi_change
,
275 colorize_start(bold
),
276 rtnl_link_flags2str(ifi
->ifi_change
, flags
,
280 for (; RTA_OK(attr
, attrs_len
); attr
= RTA_NEXT(attr
, attrs_len
)) {
281 switch (attr
->rta_type
) {
283 tprintf("\tA: Address %s\n",
284 ll_addr_n2a(RTA_DATA(attr
),
286 ifi
->ifi_type
, if_addr
,
290 tprintf("\tA: Broadcast %s\n",
291 ll_addr_n2a(RTA_DATA(attr
),
293 ifi
->ifi_type
, if_addr
,
297 tprintf("\tA: Name %s%s%s\n",
298 colorize_start(bold
),
299 (char *)(RTA_DATA(attr
)),
303 tprintf("\tA: MTU %d\n", *(int *)(RTA_DATA(attr
)));
306 tprintf("\tA: Link %d\n", *(int *)(RTA_DATA(attr
)));
309 tprintf("\tA: QDisc %s\n", (char *)(RTA_DATA(attr
)));
313 uint8_t st
= *(uint8_t *)(RTA_DATA(attr
));
316 tprintf("\tA: Operation state 0x%x (%s%s%s)\n",
318 colorize_start(bold
),
319 rtnl_link_operstate2str(st
,
320 states
, sizeof(states
)),
326 uint8_t mode
= *(uint8_t *)(RTA_DATA(attr
));
329 tprintf("\tA: Mode 0x%x (%s%s%s)\n", mode
,
330 colorize_start(bold
),
331 rtnl_link_mode2str(mode
, str
,
337 tprintf("\tA: Group %d\n", *(int *)(RTA_DATA(attr
)));
340 tprintf("\tA: Tx queue len %d\n",
341 *(int *)(RTA_DATA(attr
)));
343 case IFLA_NET_NS_PID
:
344 tprintf("\tA: Network namespace pid %d\n",
345 *(int *)(RTA_DATA(attr
)));
348 tprintf("\tA: Network namespace fd %d\n",
349 *(int *)(RTA_DATA(attr
)));
355 static void rtnl_msg_print(struct nlmsghdr
*hdr
)
357 switch (hdr
->nlmsg_type
) {
362 rtnl_print_ifinfo(hdr
);
366 static void nlmsg_print(uint16_t family
, struct nlmsghdr
*hdr
)
370 char procname
[PATH_MAX
];
372 /* Look up the process name if message is not coming from the kernel.
374 * Note that the port id is not necessarily equal to the PID of the
375 * receiving process (e.g. if the application is multithreaded or using
376 * multiple sockets). In these cases we're not able to find a matching
377 * PID and the information will not be printed.
379 if (hdr
->nlmsg_pid
!= 0) {
383 snprintf(path
, sizeof(path
), "/proc/%u/exe", hdr
->nlmsg_pid
);
384 ret
= readlink(path
, procname
, sizeof(procname
) - 1);
387 procname
[ret
] = '\0';
389 snprintf(procname
, sizeof(procname
), "kernel");
391 tprintf(" [ NLMSG ");
392 tprintf("Family %d (%s%s%s), ", family
,
393 colorize_start(bold
),
394 nlmsg_family2str(family
),
396 tprintf("Len %u, ", hdr
->nlmsg_len
);
397 tprintf("Type 0x%.4x (%s%s%s), ", hdr
->nlmsg_type
,
398 colorize_start(bold
),
399 nlmsg_type2str(family
, hdr
->nlmsg_type
, type
, sizeof(type
)),
401 tprintf("Flags 0x%.4x (%s%s%s), ", hdr
->nlmsg_flags
,
402 colorize_start(bold
),
403 nl_nlmsg_flags2str(hdr
->nlmsg_flags
, flags
, sizeof(flags
)),
405 tprintf("Seq-Nr %u, ", hdr
->nlmsg_seq
);
406 tprintf("PID %u", hdr
->nlmsg_pid
);
408 tprintf(" (%s%s%s)", colorize_start(bold
), basename(procname
),
412 if (family
== NETLINK_ROUTE
)
416 static void nlmsg(struct pkt_buff
*pkt
)
418 struct nlmsghdr
*hdr
= (struct nlmsghdr
*) pkt_pull(pkt
, sizeof(*hdr
));
421 nlmsg_print(ntohs(pkt
->proto
), hdr
);
423 if (!pkt_pull(pkt
, NLMSG_PAYLOAD(hdr
, 0)))
426 hdr
= (struct nlmsghdr
*) pkt_pull(pkt
, sizeof(*hdr
));
430 static void nlmsg_less(struct pkt_buff
*pkt
)
432 struct nlmsghdr
*hdr
= (struct nlmsghdr
*) pkt_pull(pkt
, sizeof(*hdr
));
433 uint16_t family
= ntohs(pkt
->proto
);
439 tprintf(" NLMSG Family %d (%s%s%s), ", family
,
440 colorize_start(bold
),
441 nlmsg_family2str(family
),
443 tprintf("Type %u (%s%s%s)", hdr
->nlmsg_type
,
444 colorize_start(bold
),
445 nlmsg_type2str(family
, hdr
->nlmsg_type
, type
, sizeof(type
)),
449 struct protocol nlmsg_ops
= {
451 .print_less
= nlmsg_less
,