sysctl: Add sysctl module with /proc/sys helpers
[netsniff-ng.git] / flowtop.c
blobbf2e585beb4c8544422cf9f0eb041d3467effde0
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 - 2013 Daniel Borkmann.
4 * Copyright 2011 Emmanuel Roullit.
5 * Subject to the GPL, version 2.
6 */
8 #define _LGPL_SOURCE
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <stdlib.h>
12 #include <signal.h>
13 #include <getopt.h>
14 #include <pthread.h>
15 #include <signal.h>
16 #include <netdb.h>
17 #include <ctype.h>
18 #include <netinet/in.h>
19 #include <curses.h>
20 #include <dirent.h>
21 #include <sys/stat.h>
22 #include <sys/fsuid.h>
23 #include <urcu.h>
24 #include <libgen.h>
25 #include <inttypes.h>
26 #include <poll.h>
27 #include <fcntl.h>
29 #include "die.h"
30 #include "xmalloc.h"
31 #include "conntrack.h"
32 #include "config.h"
33 #include "str.h"
34 #include "sig.h"
35 #include "lookup.h"
36 #include "geoip.h"
37 #include "built_in.h"
38 #include "locking.h"
39 #include "pkt_buff.h"
40 #include "screen.h"
41 #include "proc.h"
42 #include "sysctl.h"
44 struct flow_entry {
45 uint32_t flow_id, use, status;
46 uint8_t l3_proto, l4_proto;
47 uint32_t ip4_src_addr, ip4_dst_addr;
48 uint32_t ip6_src_addr[4], ip6_dst_addr[4];
49 uint16_t port_src, port_dst;
50 uint8_t tcp_state, tcp_flags, sctp_state, dccp_state;
51 uint64_t counter_pkts, counter_bytes;
52 uint64_t timestamp_start, timestamp_stop;
53 char country_src[128], country_dst[128];
54 char city_src[128], city_dst[128];
55 char rev_dns_src[256], rev_dns_dst[256];
56 char cmdline[256];
57 struct flow_entry *next;
58 int inode;
59 unsigned int procnum;
60 bool is_visible;
61 struct nf_conntrack *ct;
64 struct flow_list {
65 struct flow_entry *head;
66 struct spinlock lock;
69 #ifndef ATTR_TIMESTAMP_START
70 # define ATTR_TIMESTAMP_START 63
71 #endif
72 #ifndef ATTR_TIMESTAMP_STOP
73 # define ATTR_TIMESTAMP_STOP 64
74 #endif
76 #define SCROLL_MAX 1000
78 #define INCLUDE_IPV4 (1 << 0)
79 #define INCLUDE_IPV6 (1 << 1)
80 #define INCLUDE_UDP (1 << 2)
81 #define INCLUDE_TCP (1 << 3)
82 #define INCLUDE_DCCP (1 << 4)
83 #define INCLUDE_ICMP (1 << 5)
84 #define INCLUDE_SCTP (1 << 6)
86 static volatile sig_atomic_t sigint = 0;
87 static int what = INCLUDE_IPV4 | INCLUDE_IPV6 | INCLUDE_TCP, show_src = 0;
88 static struct flow_list flow_list;
89 static int nfct_acct_val = -1;
91 static const char *short_options = "vhTUsDIS46u";
92 static const struct option long_options[] = {
93 {"ipv4", no_argument, NULL, '4'},
94 {"ipv6", no_argument, NULL, '6'},
95 {"tcp", no_argument, NULL, 'T'},
96 {"udp", no_argument, NULL, 'U'},
97 {"dccp", no_argument, NULL, 'D'},
98 {"icmp", no_argument, NULL, 'I'},
99 {"sctp", no_argument, NULL, 'S'},
100 {"show-src", no_argument, NULL, 's'},
101 {"update", no_argument, NULL, 'u'},
102 {"version", no_argument, NULL, 'v'},
103 {"help", no_argument, NULL, 'h'},
104 {NULL, 0, NULL, 0}
107 static const char *copyright = "Please report bugs to <bugs@netsniff-ng.org>\n"
108 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>\n"
109 "Copyright (C) 2011-2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>\n"
110 "Swiss federal institute of technology (ETH Zurich)\n"
111 "License: GNU GPL version 2.0\n"
112 "This is free software: you are free to change and redistribute it.\n"
113 "There is NO WARRANTY, to the extent permitted by law.";
115 static const char *const l3proto2str[AF_MAX] = {
116 [AF_INET] = "ipv4",
117 [AF_INET6] = "ipv6",
120 static const char *const l4proto2str[IPPROTO_MAX] = {
121 [IPPROTO_TCP] = "tcp",
122 [IPPROTO_UDP] = "udp",
123 [IPPROTO_UDPLITE] = "udplite",
124 [IPPROTO_ICMP] = "icmp",
125 [IPPROTO_ICMPV6] = "icmpv6",
126 [IPPROTO_SCTP] = "sctp",
127 [IPPROTO_GRE] = "gre",
128 [IPPROTO_DCCP] = "dccp",
129 [IPPROTO_IGMP] = "igmp",
130 [IPPROTO_IPIP] = "ipip",
131 [IPPROTO_EGP] = "egp",
132 [IPPROTO_PUP] = "pup",
133 [IPPROTO_IDP] = "idp",
134 [IPPROTO_RSVP] = "rsvp",
135 [IPPROTO_IPV6] = "ip6tun",
136 [IPPROTO_ESP] = "esp",
137 [IPPROTO_AH] = "ah",
138 [IPPROTO_PIM] = "pim",
139 [IPPROTO_COMP] = "comp",
142 static const char *const tcp_state2str[TCP_CONNTRACK_MAX] = {
143 [TCP_CONNTRACK_NONE] = "NOSTATE",
144 [TCP_CONNTRACK_SYN_SENT] = "SYN_SENT",
145 [TCP_CONNTRACK_SYN_RECV] = "SYN_RECV",
146 [TCP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
147 [TCP_CONNTRACK_FIN_WAIT] = "FIN_WAIT",
148 [TCP_CONNTRACK_CLOSE_WAIT] = "CLOSE_WAIT",
149 [TCP_CONNTRACK_LAST_ACK] = "LAST_ACK",
150 [TCP_CONNTRACK_TIME_WAIT] = "TIME_WAIT",
151 [TCP_CONNTRACK_CLOSE] = "CLOSE",
152 [TCP_CONNTRACK_SYN_SENT2] = "SYN_SENT2",
155 static const bool tcp_states_show[TCP_CONNTRACK_MAX] = {
156 [TCP_CONNTRACK_SYN_SENT] = true,
157 [TCP_CONNTRACK_SYN_RECV] = true,
158 [TCP_CONNTRACK_ESTABLISHED] = true,
159 [TCP_CONNTRACK_FIN_WAIT] = true,
160 [TCP_CONNTRACK_CLOSE_WAIT] = true,
161 [TCP_CONNTRACK_LAST_ACK] = true,
162 [TCP_CONNTRACK_TIME_WAIT] = true,
163 [TCP_CONNTRACK_CLOSE] = true,
164 [TCP_CONNTRACK_SYN_SENT2] = true,
165 [TCP_CONNTRACK_NONE] = true,
168 static const char *const dccp_state2str[DCCP_CONNTRACK_MAX] = {
169 [DCCP_CONNTRACK_NONE] = "NOSTATE",
170 [DCCP_CONNTRACK_REQUEST] = "REQUEST",
171 [DCCP_CONNTRACK_RESPOND] = "RESPOND",
172 [DCCP_CONNTRACK_PARTOPEN] = "PARTOPEN",
173 [DCCP_CONNTRACK_OPEN] = "OPEN",
174 [DCCP_CONNTRACK_CLOSEREQ] = "CLOSEREQ",
175 [DCCP_CONNTRACK_CLOSING] = "CLOSING",
176 [DCCP_CONNTRACK_TIMEWAIT] = "TIMEWAIT",
177 [DCCP_CONNTRACK_IGNORE] = "IGNORE",
178 [DCCP_CONNTRACK_INVALID] = "INVALID",
181 static const uint8_t dccp_states_show[DCCP_CONNTRACK_MAX] = {
182 [DCCP_CONNTRACK_NONE] = true,
183 [DCCP_CONNTRACK_REQUEST] = true,
184 [DCCP_CONNTRACK_RESPOND] = true,
185 [DCCP_CONNTRACK_PARTOPEN] = true,
186 [DCCP_CONNTRACK_OPEN] = true,
187 [DCCP_CONNTRACK_CLOSEREQ] = true,
188 [DCCP_CONNTRACK_CLOSING] = true,
189 [DCCP_CONNTRACK_TIMEWAIT] = true,
190 [DCCP_CONNTRACK_IGNORE] = true,
191 [DCCP_CONNTRACK_INVALID] = true,
194 static const char *const sctp_state2str[SCTP_CONNTRACK_MAX] = {
195 [SCTP_CONNTRACK_NONE] = "NOSTATE",
196 [SCTP_CONNTRACK_CLOSED] = "CLOSED",
197 [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE_WAIT",
198 [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE_ECHOED",
199 [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
200 [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTDOWN_SENT",
201 [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTDOWN_RECD",
202 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTDOWN_ACK_SENT",
205 static const uint8_t sctp_states_show[SCTP_CONNTRACK_MAX] = {
206 [SCTP_CONNTRACK_NONE] = true,
207 [SCTP_CONNTRACK_CLOSED] = true,
208 [SCTP_CONNTRACK_COOKIE_WAIT] = true,
209 [SCTP_CONNTRACK_COOKIE_ECHOED] = true,
210 [SCTP_CONNTRACK_ESTABLISHED] = true,
211 [SCTP_CONNTRACK_SHUTDOWN_SENT] = true,
212 [SCTP_CONNTRACK_SHUTDOWN_RECD] = true,
213 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = true,
216 static const struct nfct_filter_ipv4 filter_ipv4 = {
217 .addr = __constant_htonl(INADDR_LOOPBACK),
218 .mask = 0xffffffff,
221 static const struct nfct_filter_ipv6 filter_ipv6 = {
222 .addr = { 0x0, 0x0, 0x0, 0x1 },
223 .mask = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
226 static void signal_handler(int number)
228 switch (number) {
229 case SIGINT:
230 case SIGQUIT:
231 case SIGTERM:
232 sigint = 1;
233 break;
234 case SIGHUP:
235 default:
236 break;
240 static void flow_entry_from_ct(struct flow_entry *n, struct nf_conntrack *ct);
241 static void flow_entry_get_extended(struct flow_entry *n);
243 static void help(void)
245 printf("flowtop %s, top-like netfilter TCP/UDP/SCTP/.. flow tracking\n",
246 VERSION_STRING);
247 puts("http://www.netsniff-ng.org\n\n"
248 "Usage: flowtop [options]\n"
249 "Options:\n"
250 " -4|--ipv4 Show only IPv4 flows (default)\n"
251 " -6|--ipv6 Show only IPv6 flows (default)\n"
252 " -T|--tcp Show only TCP flows (default)\n"
253 " -U|--udp Show only UDP flows\n"
254 " -D|--dccp Show only DCCP flows\n"
255 " -I|--icmp Show only ICMP/ICMPv6 flows\n"
256 " -S|--sctp Show only SCTP flows\n"
257 " -s|--show-src Also show source, not only dest\n"
258 " -u|--update Update GeoIP databases\n"
259 " -v|--version Print version and exit\n"
260 " -h|--help Print this help and exit\n\n"
261 "Examples:\n"
262 " flowtop\n"
263 " flowtop -46UTDISs\n\n"
264 "Note:\n"
265 " If netfilter is not running, you can activate it with e.g.:\n"
266 " iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT\n"
267 " iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT\n");
268 puts(copyright);
269 die();
272 static void version(void)
274 printf("flowtop %s, Git id: %s\n", VERSION_LONG, GITVERSION);
275 puts("top-like netfilter TCP/UDP/SCTP/.. flow tracking\n"
276 "http://www.netsniff-ng.org\n");
277 puts(copyright);
278 die();
281 static inline struct flow_entry *flow_entry_xalloc(void)
283 return xzmalloc(sizeof(struct flow_entry));
286 static inline void flow_entry_xfree(struct flow_entry *n)
288 if (n->ct)
289 nfct_destroy(n->ct);
291 xfree(n);
294 static inline void flow_list_init(struct flow_list *fl)
296 fl->head = NULL;
297 spinlock_init(&fl->lock);
300 static void flow_list_new_entry(struct flow_list *fl, struct nf_conntrack *ct)
302 struct flow_entry *n = flow_entry_xalloc();
304 n->ct = nfct_clone(ct);
306 flow_entry_from_ct(n, ct);
307 flow_entry_get_extended(n);
309 rcu_assign_pointer(n->next, fl->head);
310 rcu_assign_pointer(fl->head, n);
313 static struct flow_entry *flow_list_find_id(struct flow_list *fl,
314 uint32_t id)
316 struct flow_entry *n = rcu_dereference(fl->head);
318 while (n != NULL) {
319 if (n->flow_id == id)
320 return n;
322 n = rcu_dereference(n->next);
325 return NULL;
328 static struct flow_entry *flow_list_find_prev_id(struct flow_list *fl,
329 uint32_t id)
331 struct flow_entry *n = rcu_dereference(fl->head), *tmp;
333 if (n->flow_id == id)
334 return NULL;
336 while ((tmp = rcu_dereference(n->next)) != NULL) {
337 if (tmp->flow_id == id)
338 return n;
340 n = tmp;
343 return NULL;
346 static void flow_list_update_entry(struct flow_list *fl,
347 struct nf_conntrack *ct)
349 struct flow_entry *n;
351 n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
352 if (n == NULL) {
353 flow_list_new_entry(fl, ct);
354 return;
357 flow_entry_from_ct(n, ct);
360 static void flow_list_destroy_entry(struct flow_list *fl,
361 struct nf_conntrack *ct)
363 struct flow_entry *n1, *n2;
364 uint32_t id = nfct_get_attr_u32(ct, ATTR_ID);
366 n1 = flow_list_find_id(fl, id);
367 if (n1) {
368 n2 = flow_list_find_prev_id(fl, id);
369 if (n2) {
370 rcu_assign_pointer(n2->next, n1->next);
371 n1->next = NULL;
373 flow_entry_xfree(n1);
374 } else {
375 struct flow_entry *next = fl->head->next;
377 flow_entry_xfree(fl->head);
378 fl->head = next;
383 static void flow_list_destroy(struct flow_list *fl)
385 struct flow_entry *n;
387 while (fl->head != NULL) {
388 n = rcu_dereference(fl->head->next);
389 fl->head->next = NULL;
391 flow_entry_xfree(fl->head);
392 rcu_assign_pointer(fl->head, n);
395 synchronize_rcu();
396 spinlock_destroy(&fl->lock);
399 static int walk_process(unsigned int pid, struct flow_entry *n)
401 int ret;
402 DIR *dir;
403 struct dirent *ent;
404 char path[1024];
406 if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
407 panic("giant process name! %u\n", pid);
409 dir = opendir(path);
410 if (!dir)
411 return 0;
413 while ((ent = readdir(dir))) {
414 struct stat statbuf;
416 if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
417 pid, ent->d_name) < 0)
418 continue;
420 if (stat(path, &statbuf) < 0)
421 continue;
423 if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == statbuf.st_ino) {
424 ret = proc_get_cmdline(pid, n->cmdline, sizeof(n->cmdline));
425 if (ret < 0)
426 panic("Failed to get process cmdline: %s\n", strerror(errno));
428 n->procnum = pid;
429 closedir(dir);
430 return 1;
434 closedir(dir);
435 return 0;
438 static void walk_processes(struct flow_entry *n)
440 int ret;
441 DIR *dir;
442 struct dirent *ent;
444 /* n->inode must be set */
445 if (n->inode <= 0) {
446 n->cmdline[0] = '\0';
447 return;
450 dir = opendir("/proc");
451 if (!dir)
452 panic("Cannot open /proc: %s\n", strerror(errno));
454 while ((ent = readdir(dir))) {
455 const char *name = ent->d_name;
456 char *end;
457 unsigned int pid = strtoul(name, &end, 10);
459 /* not a PID */
460 if (pid == 0 && end == name)
461 continue;
463 ret = walk_process(pid, n);
464 if (ret > 0)
465 break;
468 closedir(dir);
471 static int get_port_inode(uint16_t port, int proto, int is_ip6)
473 int ret = -ENOENT;
474 char path[128], buff[1024];
475 FILE *proc;
477 memset(path, 0, sizeof(path));
478 snprintf(path, sizeof(path), "/proc/net/%s%s",
479 l4proto2str[proto], is_ip6 ? "6" : "");
481 proc = fopen(path, "r");
482 if (!proc)
483 return -EIO;
485 memset(buff, 0, sizeof(buff));
487 while (fgets(buff, sizeof(buff), proc) != NULL) {
488 int inode = 0;
489 unsigned int lport = 0;
491 buff[sizeof(buff) - 1] = 0;
492 if (sscanf(buff, "%*u: %*X:%X %*X:%*X %*X %*X:%*X %*X:%*X "
493 "%*X %*u %*u %u", &lport, &inode) == 2) {
494 if ((uint16_t) lport == port) {
495 ret = inode;
496 break;
500 memset(buff, 0, sizeof(buff));
503 fclose(proc);
504 return ret;
507 #define CP_NFCT(elem, attr, x) \
508 do { n->elem = nfct_get_attr_u##x(ct,(attr)); } while (0)
509 #define CP_NFCT_BUFF(elem, attr) do { \
510 const uint8_t *buff = nfct_get_attr(ct,(attr)); \
511 if (buff != NULL) \
512 memcpy(n->elem, buff, sizeof(n->elem)); \
513 } while (0)
515 static void flow_entry_from_ct(struct flow_entry *n, struct nf_conntrack *ct)
517 CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
518 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
520 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
521 CP_NFCT(ip4_dst_addr, ATTR_ORIG_IPV4_DST, 32);
523 CP_NFCT(port_src, ATTR_ORIG_PORT_SRC, 16);
524 CP_NFCT(port_dst, ATTR_ORIG_PORT_DST, 16);
526 CP_NFCT(status, ATTR_STATUS, 32);
528 CP_NFCT(tcp_state, ATTR_TCP_STATE, 8);
529 CP_NFCT(tcp_flags, ATTR_TCP_FLAGS_ORIG, 8);
530 CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
531 CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
533 CP_NFCT(counter_pkts, ATTR_ORIG_COUNTER_PACKETS, 64);
534 CP_NFCT(counter_bytes, ATTR_ORIG_COUNTER_BYTES, 64);
536 CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
537 CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
539 CP_NFCT(flow_id, ATTR_ID, 32);
540 CP_NFCT(use, ATTR_USE, 32);
542 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
543 CP_NFCT_BUFF(ip6_dst_addr, ATTR_ORIG_IPV6_DST);
545 n->port_src = ntohs(n->port_src);
546 n->port_dst = ntohs(n->port_dst);
548 n->ip4_src_addr = ntohl(n->ip4_src_addr);
549 n->ip4_dst_addr = ntohl(n->ip4_dst_addr);
552 enum flow_entry_direction {
553 flow_entry_src,
554 flow_entry_dst,
557 static inline int flow_entry_get_extended_is_dns(struct flow_entry *n)
559 /* We don't want to analyze / display DNS itself, since we
560 * use it to resolve reverse dns.
562 return n->port_src == 53 || n->port_dst == 53;
565 #define SELFLD(dir,src_member,dst_member) \
566 (((dir) == flow_entry_src) ? n->src_member : n->dst_member)
568 static void flow_entry_get_sain4_obj(struct flow_entry *n,
569 enum flow_entry_direction dir,
570 struct sockaddr_in *sa)
572 memset(sa, 0, sizeof(*sa));
573 sa->sin_family = PF_INET;
574 sa->sin_addr.s_addr = htonl(SELFLD(dir, ip4_src_addr, ip4_dst_addr));
577 static void flow_entry_get_sain6_obj(struct flow_entry *n,
578 enum flow_entry_direction dir,
579 struct sockaddr_in6 *sa)
581 memset(sa, 0, sizeof(*sa));
582 sa->sin6_family = PF_INET6;
584 memcpy(&sa->sin6_addr, SELFLD(dir, ip6_src_addr, ip6_dst_addr),
585 sizeof(sa->sin6_addr));
588 static void
589 flow_entry_geo_city_lookup_generic(struct flow_entry *n,
590 enum flow_entry_direction dir)
592 struct sockaddr_in sa4;
593 struct sockaddr_in6 sa6;
594 const char *city = NULL;
596 switch (n->l3_proto) {
597 default:
598 bug();
600 case AF_INET:
601 flow_entry_get_sain4_obj(n, dir, &sa4);
602 city = geoip4_city_name(&sa4);
603 break;
605 case AF_INET6:
606 flow_entry_get_sain6_obj(n, dir, &sa6);
607 city = geoip6_city_name(&sa6);
608 break;
611 bug_on(sizeof(n->city_src) != sizeof(n->city_dst));
613 if (city) {
614 memcpy(SELFLD(dir, city_src, city_dst), city,
615 min(sizeof(n->city_src), strlen(city)));
616 } else {
617 memset(SELFLD(dir, city_src, city_dst), 0,
618 sizeof(n->city_src));
622 static void
623 flow_entry_geo_country_lookup_generic(struct flow_entry *n,
624 enum flow_entry_direction dir)
626 struct sockaddr_in sa4;
627 struct sockaddr_in6 sa6;
628 const char *country = NULL;
630 switch (n->l3_proto) {
631 default:
632 bug();
634 case AF_INET:
635 flow_entry_get_sain4_obj(n, dir, &sa4);
636 country = geoip4_country_name(&sa4);
637 break;
639 case AF_INET6:
640 flow_entry_get_sain6_obj(n, dir, &sa6);
641 country = geoip6_country_name(&sa6);
642 break;
645 bug_on(sizeof(n->country_src) != sizeof(n->country_dst));
647 if (country) {
648 memcpy(SELFLD(dir, country_src, country_dst), country,
649 min(sizeof(n->country_src), strlen(country)));
650 } else {
651 memset(SELFLD(dir, country_src, country_dst), 0,
652 sizeof(n->country_src));
656 static void flow_entry_get_extended_geo(struct flow_entry *n,
657 enum flow_entry_direction dir)
659 flow_entry_geo_city_lookup_generic(n, dir);
660 flow_entry_geo_country_lookup_generic(n, dir);
663 static void flow_entry_get_extended_revdns(struct flow_entry *n,
664 enum flow_entry_direction dir)
666 size_t sa_len;
667 struct sockaddr_in sa4;
668 struct sockaddr_in6 sa6;
669 struct sockaddr *sa;
670 struct hostent *hent;
672 switch (n->l3_proto) {
673 default:
674 bug();
676 case AF_INET:
677 flow_entry_get_sain4_obj(n, dir, &sa4);
678 sa = (struct sockaddr *) &sa4;
679 sa_len = sizeof(sa4);
680 hent = gethostbyaddr(&sa4.sin_addr, sizeof(sa4.sin_addr), AF_INET);
681 break;
683 case AF_INET6:
684 flow_entry_get_sain6_obj(n, dir, &sa6);
685 sa = (struct sockaddr *) &sa6;
686 sa_len = sizeof(sa6);
687 hent = gethostbyaddr(&sa6.sin6_addr, sizeof(sa6.sin6_addr), AF_INET6);
688 break;
691 bug_on(sizeof(n->rev_dns_src) != sizeof(n->rev_dns_dst));
692 getnameinfo(sa, sa_len, SELFLD(dir, rev_dns_src, rev_dns_dst),
693 sizeof(n->rev_dns_src), NULL, 0, NI_NUMERICHOST);
695 if (hent) {
696 memset(n->rev_dns_dst, 0, sizeof(n->rev_dns_dst));
697 memcpy(SELFLD(dir, rev_dns_src, rev_dns_dst),
698 hent->h_name, min(sizeof(n->rev_dns_src),
699 strlen(hent->h_name)));
703 static void flow_entry_get_extended(struct flow_entry *n)
705 if (n->flow_id == 0 || flow_entry_get_extended_is_dns(n))
706 return;
708 flow_entry_get_extended_revdns(n, flow_entry_src);
709 flow_entry_get_extended_geo(n, flow_entry_src);
711 flow_entry_get_extended_revdns(n, flow_entry_dst);
712 flow_entry_get_extended_geo(n, flow_entry_dst);
714 /* Lookup application */
715 n->inode = get_port_inode(n->port_src, n->l4_proto,
716 n->l3_proto == AF_INET6);
717 if (n->inode > 0)
718 walk_processes(n);
721 static uint16_t presenter_get_port(uint16_t src, uint16_t dst, int tcp)
723 if (src < dst && src < 1024) {
724 return src;
725 } else if (dst < src && dst < 1024) {
726 return dst;
727 } else {
728 const char *tmp1, *tmp2;
729 if (tcp) {
730 tmp1 = lookup_port_tcp(src);
731 tmp2 = lookup_port_tcp(dst);
732 } else {
733 tmp1 = lookup_port_udp(src);
734 tmp2 = lookup_port_udp(dst);
736 if (tmp1 && !tmp2) {
737 return src;
738 } else if (!tmp1 && tmp2) {
739 return dst;
740 } else {
741 if (src < dst)
742 return src;
743 else
744 return dst;
749 static char *bandw2str(double bytes, char *buf, size_t len)
751 if (bytes > 1000000000.)
752 snprintf(buf, len, "%.1fG", bytes / 1000000000.);
753 if (bytes > 1000000.)
754 snprintf(buf, len, "%.1fM", bytes / 1000000.);
755 else if (bytes > 1000.)
756 snprintf(buf, len, "%.1fK", bytes / 1000.);
757 else
758 snprintf(buf, len, "%g", bytes);
760 return buf;
763 static void presenter_screen_do_line(WINDOW *screen, struct flow_entry *n,
764 unsigned int *line)
766 char tmp[128], *pname = NULL;
767 uint16_t port;
769 mvwprintw(screen, *line, 2, "");
771 /* PID, application name */
772 if (n->procnum > 0) {
773 slprintf(tmp, sizeof(tmp), "%s(%d)", basename(n->cmdline),
774 n->procnum);
776 printw("[");
777 attron(COLOR_PAIR(3));
778 printw("%s", tmp);
779 attroff(COLOR_PAIR(3));
780 printw("]:");
783 /* L3 protocol, L4 protocol, states */
784 printw("%s:%s", l3proto2str[n->l3_proto], l4proto2str[n->l4_proto]);
785 printw("[");
786 attron(COLOR_PAIR(3));
787 switch (n->l4_proto) {
788 case IPPROTO_TCP:
789 printw("%s", tcp_state2str[n->tcp_state]);
790 break;
791 case IPPROTO_SCTP:
792 printw("%s", sctp_state2str[n->sctp_state]);
793 break;
794 case IPPROTO_DCCP:
795 printw("%s", dccp_state2str[n->dccp_state]);
796 break;
797 case IPPROTO_UDP:
798 case IPPROTO_UDPLITE:
799 case IPPROTO_ICMP:
800 case IPPROTO_ICMPV6:
801 printw("NOSTATE");
802 break;
804 attroff(COLOR_PAIR(3));
805 printw("]");
807 /* Guess application port */
808 switch (n->l4_proto) {
809 case IPPROTO_TCP:
810 port = presenter_get_port(n->port_src, n->port_dst, 1);
811 pname = lookup_port_tcp(port);
812 break;
813 case IPPROTO_UDP:
814 case IPPROTO_UDPLITE:
815 port = presenter_get_port(n->port_src, n->port_dst, 0);
816 pname = lookup_port_udp(port);
817 break;
819 if (pname) {
820 attron(A_BOLD);
821 printw(":%s", pname);
822 attroff(A_BOLD);
824 printw(" ->");
826 /* Number packets, bytes */
827 if (n->counter_pkts > 0 && n->counter_bytes > 0) {
828 char bytes_str[64];
830 printw(" (%"PRIu64" pkts, %s bytes) ->", n->counter_pkts,
831 bandw2str(n->counter_bytes, bytes_str,
832 sizeof(bytes_str) - 1));
835 /* Show source information: reverse DNS, port, country, city */
836 if (show_src) {
837 attron(COLOR_PAIR(1));
838 mvwprintw(screen, ++(*line), 8, "src: %s", n->rev_dns_src);
839 attroff(COLOR_PAIR(1));
841 printw(":%"PRIu16, n->port_src);
843 if (n->country_src[0]) {
844 printw(" (");
846 attron(COLOR_PAIR(4));
847 printw("%s", n->country_src);
848 attroff(COLOR_PAIR(4));
850 if (n->city_src[0])
851 printw(", %s", n->city_src);
853 printw(")");
856 printw(" => ");
859 /* Show dest information: reverse DNS, port, country, city */
860 attron(COLOR_PAIR(2));
861 mvwprintw(screen, ++(*line), 8, "dst: %s", n->rev_dns_dst);
862 attroff(COLOR_PAIR(2));
864 printw(":%"PRIu16, n->port_dst);
866 if (n->country_dst[0]) {
867 printw(" (");
869 attron(COLOR_PAIR(4));
870 printw("%s", n->country_dst);
871 attroff(COLOR_PAIR(4));
873 if (n->city_dst[0])
874 printw(", %s", n->city_dst);
876 printw(")");
880 static inline int presenter_flow_wrong_state(struct flow_entry *n)
882 int ret = 1;
884 switch (n->l4_proto) {
885 case IPPROTO_TCP:
886 if (tcp_states_show[n->tcp_state])
887 ret = 0;
888 break;
889 case IPPROTO_SCTP:
890 if (sctp_states_show[n->sctp_state])
891 ret = 0;
892 break;
893 case IPPROTO_DCCP:
894 if (dccp_states_show[n->dccp_state])
895 ret = 0;
896 break;
897 case IPPROTO_UDP:
898 case IPPROTO_UDPLITE:
899 case IPPROTO_ICMP:
900 case IPPROTO_ICMPV6:
901 ret = 0;
902 break;
905 return ret;
908 static void presenter_screen_update(WINDOW *screen, struct flow_list *fl,
909 int skip_lines)
911 int maxy;
912 int skip_left = skip_lines;
913 unsigned int flows = 0;
914 unsigned int line = 3;
915 struct flow_entry *n;
917 curs_set(0);
919 maxy = getmaxy(screen);
920 maxy -= 6;
922 start_color();
923 init_pair(1, COLOR_RED, COLOR_BLACK);
924 init_pair(2, COLOR_BLUE, COLOR_BLACK);
925 init_pair(3, COLOR_YELLOW, COLOR_BLACK);
926 init_pair(4, COLOR_GREEN, COLOR_BLACK);
928 wclear(screen);
929 clear();
931 rcu_read_lock();
933 n = rcu_dereference(fl->head);
934 if (!n)
935 mvwprintw(screen, line, 2, "(No active sessions! "
936 "Is netfilter running?)");
938 for (; n; n = rcu_dereference(n->next)) {
939 if (presenter_get_port(n->port_src, n->port_dst, 0) == 53)
940 goto skip;
942 if (presenter_flow_wrong_state(n))
943 goto skip;
945 /* count only flows which might be showed */
946 flows++;
948 if (maxy <= 0)
949 goto skip;
951 if (skip_left > 0) {
952 skip_left--;
953 goto skip;
956 presenter_screen_do_line(screen, n, &line);
958 line++;
959 maxy -= (2 + 1 * show_src);
960 n->is_visible = true;
961 continue;
962 skip:
963 n->is_visible = false;
964 continue;
967 mvwprintw(screen, 1, 2, "Kernel netfilter flows(%u) for %s%s%s%s%s%s"
968 "[+%d]", flows, what & INCLUDE_TCP ? "TCP, " : "" ,
969 what & INCLUDE_UDP ? "UDP, " : "",
970 what & INCLUDE_SCTP ? "SCTP, " : "",
971 what & INCLUDE_DCCP ? "DCCP, " : "",
972 what & INCLUDE_ICMP && what & INCLUDE_IPV4 ? "ICMP, " : "",
973 what & INCLUDE_ICMP && what & INCLUDE_IPV6 ? "ICMP6, " : "",
974 skip_lines);
976 rcu_read_unlock();
978 wrefresh(screen);
979 refresh();
982 static void presenter(void)
984 int skip_lines = 0;
985 WINDOW *screen;
987 lookup_init_ports(PORTS_TCP);
988 lookup_init_ports(PORTS_UDP);
989 screen = screen_init(false);
991 rcu_register_thread();
992 while (!sigint) {
993 switch (getch()) {
994 case 'q':
995 sigint = 1;
996 break;
997 case KEY_UP:
998 case 'u':
999 case 'k':
1000 skip_lines--;
1001 if (skip_lines < 0)
1002 skip_lines = 0;
1003 break;
1004 case KEY_DOWN:
1005 case 'd':
1006 case 'j':
1007 skip_lines++;
1008 if (skip_lines > SCROLL_MAX)
1009 skip_lines = SCROLL_MAX;
1010 break;
1011 default:
1012 fflush(stdin);
1013 break;
1016 presenter_screen_update(screen, &flow_list, skip_lines);
1017 usleep(200000);
1019 rcu_unregister_thread();
1021 screen_end();
1022 lookup_cleanup_ports(PORTS_UDP);
1023 lookup_cleanup_ports(PORTS_TCP);
1026 static int collector_cb(enum nf_conntrack_msg_type type,
1027 struct nf_conntrack *ct, void *data __maybe_unused)
1029 if (sigint)
1030 return NFCT_CB_STOP;
1032 synchronize_rcu();
1033 spinlock_lock(&flow_list.lock);
1035 switch (type) {
1036 case NFCT_T_NEW:
1037 flow_list_new_entry(&flow_list, ct);
1038 break;
1039 case NFCT_T_UPDATE:
1040 flow_list_update_entry(&flow_list, ct);
1041 break;
1042 case NFCT_T_DESTROY:
1043 flow_list_destroy_entry(&flow_list, ct);
1044 break;
1045 default:
1046 break;
1049 spinlock_unlock(&flow_list.lock);
1051 return NFCT_CB_CONTINUE;
1054 static inline void collector_flush(struct nfct_handle *handle, uint8_t family)
1056 nfct_query(handle, NFCT_Q_FLUSH, &family);
1059 static void restore_sysctl(void *value)
1061 int int_val = *(int *)value;
1063 if (int_val == 0)
1064 sysctl_set_int("net/netfilter/nf_conntrack_acct", int_val);
1067 static void on_panic_handler(void *arg)
1069 restore_sysctl(arg);
1070 screen_end();
1073 static void conntrack_acct_enable(void)
1075 /* We can still work w/o traffic accounting so just warn about error */
1076 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &nfct_acct_val)) {
1077 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1078 strerror(errno));
1081 if (nfct_acct_val == 1)
1082 return;
1084 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1085 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1086 strerror(errno));
1090 static int dump_cb(enum nf_conntrack_msg_type type,
1091 struct nf_conntrack *ct, void *data __maybe_unused)
1093 struct flow_entry *n;
1095 if (type != NFCT_T_UPDATE)
1096 return NFCT_CB_CONTINUE;
1098 if (sigint)
1099 return NFCT_CB_STOP;
1101 n = flow_list_find_id(&flow_list, nfct_get_attr_u32(ct, ATTR_ID));
1102 if (!n)
1103 return NFCT_CB_CONTINUE;
1105 flow_entry_from_ct(n, ct);
1107 return NFCT_CB_CONTINUE;
1110 static void collector_refresh_flows(struct nfct_handle *handle)
1112 struct flow_entry *n;
1114 n = rcu_dereference(flow_list.head);
1115 for (; n; n = rcu_dereference(n->next)) {
1116 if (!n->is_visible)
1117 continue;
1119 nfct_query(handle, NFCT_Q_GET, n->ct);
1123 static void *collector(void *null __maybe_unused)
1125 struct nfct_handle *ct_event;
1126 struct nfct_handle *ct_dump;
1127 struct nfct_filter *filter;
1128 struct pollfd poll_fd[1];
1129 int ret;
1131 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1132 NF_NETLINK_CONNTRACK_UPDATE |
1133 NF_NETLINK_CONNTRACK_DESTROY);
1134 if (!ct_event)
1135 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1137 collector_flush(ct_event, AF_INET);
1138 collector_flush(ct_event, AF_INET6);
1140 filter = nfct_filter_create();
1141 if (!filter)
1142 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1144 ret = nfct_filter_attach(nfct_fd(ct_event), filter);
1145 if (ret < 0)
1146 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1148 if (what & INCLUDE_UDP) {
1149 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1150 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1152 if (what & INCLUDE_TCP)
1153 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1154 if (what & INCLUDE_DCCP)
1155 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1156 if (what & INCLUDE_SCTP)
1157 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1158 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1159 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1160 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1161 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1162 if (what & INCLUDE_IPV4) {
1163 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1164 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1166 if (what & INCLUDE_IPV6) {
1167 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1168 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1171 ret = nfct_filter_attach(nfct_fd(ct_event), filter);
1172 if (ret < 0)
1173 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1175 nfct_filter_destroy(filter);
1177 nfct_callback_register(ct_event, NFCT_T_ALL, collector_cb, NULL);
1178 flow_list_init(&flow_list);
1180 ct_dump = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_UPDATE);
1181 if (!ct_dump)
1182 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1184 nfct_callback_register(ct_dump, NFCT_T_ALL, dump_cb, NULL);
1186 poll_fd[0].fd = nfct_fd(ct_event);
1187 poll_fd[0].events = POLLIN;
1189 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1190 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1191 strerror(errno));
1193 if (fcntl(nfct_fd(ct_dump), F_SETFL, O_NONBLOCK) == -1)
1194 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1195 strerror(errno));
1197 rcu_register_thread();
1199 while (!sigint && ret >= 0) {
1200 int status;
1202 usleep(300000);
1204 collector_refresh_flows(ct_dump);
1206 status = poll(poll_fd, 1, 0);
1207 if (status < 0) {
1208 if (errno == EAGAIN || errno == EINTR)
1209 continue;
1211 panic("Error while polling: %s\n", strerror(errno));
1212 } else if (status == 0) {
1213 continue;
1216 if (poll_fd[0].revents & POLLIN)
1217 nfct_catch(ct_event);
1220 rcu_unregister_thread();
1222 flow_list_destroy(&flow_list);
1223 nfct_close(ct_event);
1224 nfct_close(ct_dump);
1226 pthread_exit(NULL);
1229 int main(int argc, char **argv)
1231 pthread_t tid;
1232 int ret, c, opt_index, what_cmd = 0;
1234 setfsuid(getuid());
1235 setfsgid(getgid());
1237 while ((c = getopt_long(argc, argv, short_options, long_options,
1238 &opt_index)) != EOF) {
1239 switch (c) {
1240 case '4':
1241 what_cmd |= INCLUDE_IPV4;
1242 break;
1243 case '6':
1244 what_cmd |= INCLUDE_IPV6;
1245 break;
1246 case 'T':
1247 what_cmd |= INCLUDE_TCP;
1248 break;
1249 case 'U':
1250 what_cmd |= INCLUDE_UDP;
1251 break;
1252 case 'D':
1253 what_cmd |= INCLUDE_DCCP;
1254 break;
1255 case 'I':
1256 what_cmd |= INCLUDE_ICMP;
1257 break;
1258 case 'S':
1259 what_cmd |= INCLUDE_SCTP;
1260 break;
1261 case 's':
1262 show_src = 1;
1263 break;
1264 case 'u':
1265 update_geoip();
1266 die();
1267 break;
1268 case 'h':
1269 help();
1270 break;
1271 case 'v':
1272 version();
1273 break;
1274 default:
1275 break;
1279 if (what_cmd > 0)
1280 what = what_cmd;
1282 rcu_init();
1284 register_signal(SIGINT, signal_handler);
1285 register_signal(SIGQUIT, signal_handler);
1286 register_signal(SIGTERM, signal_handler);
1287 register_signal(SIGHUP, signal_handler);
1289 panic_handler_add(on_panic_handler, &nfct_acct_val);
1291 conntrack_acct_enable();
1293 init_geoip(1);
1295 ret = pthread_create(&tid, NULL, collector, NULL);
1296 if (ret < 0)
1297 panic("Cannot create phthread!\n");
1299 presenter();
1301 destroy_geoip();
1303 restore_sysctl(&nfct_acct_val);
1305 return 0;