build: Explicitly mention last release in announcement message
[netsniff-ng.git] / proto_nlmsg.c
blob136cec6ff4dcec821861ed7075a7830ff6ac960d
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 <unistd.h>
9 #include <limits.h>
10 #include <libgen.h>
11 #include <netlink/msg.h>
13 #include "pkt_buff.h"
14 #include "proto.h"
15 #include "protos.h"
17 static const char *nlmsg_family2str(uint16_t family)
19 switch (family) {
20 case NETLINK_ROUTE: return "routing";
21 case NETLINK_UNUSED: return "unused";
22 case NETLINK_USERSOCK: return "user-mode socket";
23 case NETLINK_FIREWALL: return "unused, formerly ip_queue";
24 /* NETLINK_INET_DIAG was renamed to NETLINK_SOCK_DIAG in Linux kernel 3.10 */
25 #if defined(NETLINK_SOCK_DIAG)
26 case NETLINK_SOCK_DIAG: return "socket monitoring";
27 #elif defined(NETLINK_INET_DIAG)
28 case NETLINK_INET_DIAG: return "INET socket monitoring";
29 #endif
30 case NETLINK_NFLOG: return "netfilter ULOG";
31 case NETLINK_XFRM: return "IPsec";
32 case NETLINK_SELINUX: return "SELinux event notification";
33 case NETLINK_ISCSI: return "Open-iSCSI";
34 case NETLINK_AUDIT: return "auditing";
35 case NETLINK_FIB_LOOKUP: return "FIB lookup";
36 case NETLINK_CONNECTOR: return "Kernel connector";
37 case NETLINK_NETFILTER: return "Netfilter";
38 case NETLINK_IP6_FW: return "unused, formerly ip6_queue";
39 case NETLINK_DNRTMSG: return "DECnet routing";
40 case NETLINK_KOBJECT_UEVENT: return "Kernel messages";
41 case NETLINK_GENERIC: return "Generic";
42 case NETLINK_SCSITRANSPORT: return "SCSI transports";
43 case NETLINK_ECRYPTFS: return "ecryptfs";
44 case NETLINK_RDMA: return "RDMA";
45 case NETLINK_CRYPTO: return "Crypto layer";
46 default: return "Unknown";
50 static const char *nlmsg_rtnl_type2str(uint16_t type)
52 switch (type) {
53 case RTM_NEWLINK: return "new link";
54 case RTM_DELLINK: return "del link";
55 case RTM_GETLINK: return "get link";
56 case RTM_SETLINK: return "set link";
58 case RTM_NEWADDR: return "new addr";
59 case RTM_DELADDR: return "del addr";
60 case RTM_GETADDR: return "get addr";
62 case RTM_NEWROUTE: return "new route";
63 case RTM_DELROUTE: return "del route";
64 case RTM_GETROUTE: return "get route";
66 case RTM_NEWNEIGH: return "new neigh";
67 case RTM_DELNEIGH: return "del neigh";
68 case RTM_GETNEIGH: return "get neigh";
70 case RTM_NEWRULE: return "new rule";
71 case RTM_DELRULE: return "del rule";
72 case RTM_GETRULE: return "get rule";
74 case RTM_NEWQDISC: return "new tc qdisc";
75 case RTM_DELQDISC: return "del tc qdisc";
76 case RTM_GETQDISC: return "get tc qdisc";
78 case RTM_NEWTCLASS: return "new tc class";
79 case RTM_DELTCLASS: return "del tc class";
80 case RTM_GETTCLASS: return "get tc class";
82 case RTM_NEWTFILTER: return "new tc filter";
83 case RTM_DELTFILTER: return "del tc filter";
84 case RTM_GETTFILTER: return "get tc filter";
86 case RTM_NEWACTION: return "new tc action";
87 case RTM_DELACTION: return "del tc action";
88 case RTM_GETACTION: return "get tc action";
90 case RTM_NEWPREFIX: return "new prefix";
92 case RTM_GETMULTICAST: return "get mcast addr";
94 case RTM_GETANYCAST: return "get anycast addr";
96 case RTM_NEWNEIGHTBL: return "new neigh table";
97 case RTM_GETNEIGHTBL: return "get neigh table";
98 case RTM_SETNEIGHTBL: return "set neigh table";
100 case RTM_NEWNDUSEROPT: return "new ndisc user option";
102 case RTM_NEWADDRLABEL: return "new addr label";
103 case RTM_DELADDRLABEL: return "del addr label";
104 case RTM_GETADDRLABEL: return "get addr label";
106 case RTM_GETDCB: return "get data-center-bridge";
107 case RTM_SETDCB: return "set data-center-bridge";
109 #if defined(RTM_NEWNETCONF)
110 case RTM_NEWNETCONF: return "new netconf";
111 case RTM_GETNETCONF: return "get netconf";
112 #endif
114 #if defined(RTM_NEWMDB)
115 case RTM_NEWMDB: return "new bridge mdb";
116 case RTM_DELMDB: return "del bridge mdb";
117 case RTM_GETMDB: return "get bridge mdb";
118 #endif
119 default: return NULL;
123 static char *nlmsg_type2str(uint16_t proto, uint16_t type, char *buf, int len)
125 if (proto == NETLINK_ROUTE && type < RTM_MAX) {
126 const char *name = nlmsg_rtnl_type2str(type);
127 if (name) {
128 strncpy(buf, name, len);
129 return buf;
133 return nl_nlmsgtype2str(type, buf, len);
136 static void nlmsg(struct pkt_buff *pkt)
138 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, sizeof(*hdr));
139 char type[32];
140 char flags[128];
141 char procname[PATH_MAX];
143 if (hdr == NULL)
144 return;
146 /* Look up the process name if message is not coming from the kernel.
148 * Note that the port id is not necessarily equal to the PID of the
149 * receiving process (e.g. if the application is multithreaded or using
150 * multiple sockets). In these cases we're not able to find a matching
151 * PID and the information will not be printed.
153 if (hdr->nlmsg_pid != 0) {
154 char path[1024];
155 int ret;
157 snprintf(path, sizeof(path), "/proc/%u/exe", hdr->nlmsg_pid);
158 ret = readlink(path, procname, sizeof(procname) - 1);
159 if (ret < 0)
160 ret = 0;
161 procname[ret] = '\0';
162 } else
163 snprintf(procname, sizeof(procname), "kernel");
165 tprintf(" [ NLMSG ");
166 tprintf("Family %d (%s%s%s), ", ntohs(pkt->proto), colorize_start(bold),
167 nlmsg_family2str(ntohs(pkt->proto)), colorize_end());
168 tprintf("Len %u, ", hdr->nlmsg_len);
169 tprintf("Type 0x%.4x (%s%s%s), ", hdr->nlmsg_type,
170 colorize_start(bold),
171 nlmsg_type2str(ntohs(pkt->proto), hdr->nlmsg_type, type,
172 sizeof(type)), colorize_end());
173 tprintf("Flags 0x%.4x (%s%s%s), ", hdr->nlmsg_flags,
174 colorize_start(bold),
175 nl_nlmsg_flags2str(hdr->nlmsg_flags, flags, sizeof(flags)),
176 colorize_end());
177 tprintf("Seq-Nr %u, ", hdr->nlmsg_seq);
178 tprintf("PID %u", hdr->nlmsg_pid);
179 if (procname[0])
180 tprintf(" (%s%s%s)", colorize_start(bold), basename(procname),
181 colorize_end());
182 tprintf(" ]\n");
185 static void nlmsg_less(struct pkt_buff *pkt)
187 struct nlmsghdr *hdr = (struct nlmsghdr *) pkt_pull(pkt, sizeof(*hdr));
188 char type[32];
190 if (hdr == NULL)
191 return;
193 tprintf(" NLMSG Family %d (%s%s%s), ", ntohs(pkt->proto), colorize_start(bold),
194 nlmsg_family2str(ntohs(pkt->proto)), colorize_end());
195 tprintf("Type %u (%s%s%s)", hdr->nlmsg_type, colorize_start(bold),
196 nlmsg_type2str(ntohs(pkt->proto), hdr->nlmsg_type, type,
197 sizeof(type)), colorize_end());
200 struct protocol nlmsg_ops = {
201 .print_full = nlmsg,
202 .print_less = nlmsg_less,