flowtop: Use new colors naming & helpers
[netsniff-ng.git] / flowtop.c
blob402d4bc3f0918cb5497337762f6cabf3cf69a9c1
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/time.h>
23 #include <sys/fsuid.h>
24 #include <urcu.h>
25 #include <libgen.h>
26 #include <inttypes.h>
27 #include <poll.h>
28 #include <fcntl.h>
29 #include <arpa/inet.h>
31 #include "die.h"
32 #include "xmalloc.h"
33 #include "conntrack.h"
34 #include "config.h"
35 #include "str.h"
36 #include "sig.h"
37 #include "lookup.h"
38 #include "geoip.h"
39 #include "built_in.h"
40 #include "locking.h"
41 #include "pkt_buff.h"
42 #include "screen.h"
43 #include "proc.h"
44 #include "sysctl.h"
46 #ifndef NSEC_PER_SEC
47 #define NSEC_PER_SEC 1000000000L
48 #endif
50 #ifndef USEC_PER_SEC
51 #define USEC_PER_SEC 1000000L
52 #endif
54 struct flow_entry {
55 uint32_t flow_id, use, status;
56 uint8_t l3_proto, l4_proto;
57 uint32_t ip4_src_addr, ip4_dst_addr;
58 uint32_t ip6_src_addr[4], ip6_dst_addr[4];
59 uint16_t port_src, port_dst;
60 uint8_t tcp_state, tcp_flags, sctp_state, dccp_state;
61 uint64_t pkts_src, bytes_src;
62 uint64_t pkts_dst, bytes_dst;
63 uint64_t timestamp_start, timestamp_stop;
64 char country_src[128], country_dst[128];
65 char country_code_src[4], country_code_dst[4];
66 char city_src[128], city_dst[128];
67 char rev_dns_src[256], rev_dns_dst[256];
68 char procname[256];
69 struct flow_entry *next;
70 int inode;
71 unsigned int procnum;
72 bool is_visible;
73 struct nf_conntrack *ct;
74 struct timeval last_update;
75 double rate_bytes_src;
76 double rate_bytes_dst;
77 double rate_pkts_src;
78 double rate_pkts_dst;
81 struct flow_list {
82 struct flow_entry *head;
83 struct spinlock lock;
86 enum flow_direction {
87 FLOW_DIR_SRC,
88 FLOW_DIR_DST,
91 #ifndef ATTR_TIMESTAMP_START
92 # define ATTR_TIMESTAMP_START 63
93 #endif
94 #ifndef ATTR_TIMESTAMP_STOP
95 # define ATTR_TIMESTAMP_STOP 64
96 #endif
98 #define SCROLL_MAX 1000
100 #define INCLUDE_IPV4 (1 << 0)
101 #define INCLUDE_IPV6 (1 << 1)
102 #define INCLUDE_UDP (1 << 2)
103 #define INCLUDE_TCP (1 << 3)
104 #define INCLUDE_DCCP (1 << 4)
105 #define INCLUDE_ICMP (1 << 5)
106 #define INCLUDE_SCTP (1 << 6)
108 #define TOGGLE_FLAG(what, flag) \
109 do { \
110 if (what & flag) \
111 what &= ~flag; \
112 else \
113 what |= flag; \
114 } while (0)
116 struct sysctl_params_ctx {
117 int nfct_acct;
118 int nfct_tstamp;
121 enum rate_units {
122 RATE_BITS,
123 RATE_BYTES
126 static volatile bool do_reload_flows;
127 static volatile bool is_flow_collecting;
128 static volatile sig_atomic_t sigint = 0;
129 static int what = INCLUDE_IPV4 | INCLUDE_IPV6 | INCLUDE_TCP;
130 static struct flow_list flow_list;
131 static struct sysctl_params_ctx sysctl = { -1, -1 };
133 static unsigned int cols, rows;
135 static unsigned int interval = 1;
136 static bool show_src = false;
137 static bool resolve_dns = true;
138 static bool resolve_geoip = true;
139 static enum rate_units rate_type = RATE_BYTES;
140 static bool show_active_only = false;
142 static const char *short_options = "vhTUsDIS46ut:nGb";
143 static const struct option long_options[] = {
144 {"ipv4", no_argument, NULL, '4'},
145 {"ipv6", no_argument, NULL, '6'},
146 {"tcp", no_argument, NULL, 'T'},
147 {"udp", no_argument, NULL, 'U'},
148 {"dccp", no_argument, NULL, 'D'},
149 {"icmp", no_argument, NULL, 'I'},
150 {"sctp", no_argument, NULL, 'S'},
151 {"no-dns", no_argument, NULL, 'n'},
152 {"no-geoip", no_argument, NULL, 'G'},
153 {"show-src", no_argument, NULL, 's'},
154 {"bits", no_argument, NULL, 'b'},
155 {"update", no_argument, NULL, 'u'},
156 {"interval", required_argument, NULL, 't'},
157 {"version", no_argument, NULL, 'v'},
158 {"help", no_argument, NULL, 'h'},
159 {NULL, 0, NULL, 0}
162 static const char *copyright = "Please report bugs to <netsniff-ng@googlegroups.com>\n"
163 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>\n"
164 "Copyright (C) 2011-2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>\n"
165 "Swiss federal institute of technology (ETH Zurich)\n"
166 "License: GNU GPL version 2.0\n"
167 "This is free software: you are free to change and redistribute it.\n"
168 "There is NO WARRANTY, to the extent permitted by law.";
170 static const char *const l4proto2str[IPPROTO_MAX] = {
171 [IPPROTO_TCP] = "tcp",
172 [IPPROTO_UDP] = "udp",
173 [IPPROTO_UDPLITE] = "udplite",
174 [IPPROTO_ICMP] = "icmp",
175 [IPPROTO_ICMPV6] = "icmpv6",
176 [IPPROTO_SCTP] = "sctp",
177 [IPPROTO_GRE] = "gre",
178 [IPPROTO_DCCP] = "dccp",
179 [IPPROTO_IGMP] = "igmp",
180 [IPPROTO_IPIP] = "ipip",
181 [IPPROTO_EGP] = "egp",
182 [IPPROTO_PUP] = "pup",
183 [IPPROTO_IDP] = "idp",
184 [IPPROTO_RSVP] = "rsvp",
185 [IPPROTO_IPV6] = "ip6tun",
186 [IPPROTO_ESP] = "esp",
187 [IPPROTO_AH] = "ah",
188 [IPPROTO_PIM] = "pim",
189 [IPPROTO_COMP] = "comp",
192 static const char *const tcp_state2str[TCP_CONNTRACK_MAX] = {
193 [TCP_CONNTRACK_NONE] = "NONE",
194 [TCP_CONNTRACK_SYN_SENT] = "SYN-SENT",
195 [TCP_CONNTRACK_SYN_RECV] = "SYN-RECV",
196 [TCP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
197 [TCP_CONNTRACK_FIN_WAIT] = "FIN-WAIT",
198 [TCP_CONNTRACK_CLOSE_WAIT] = "CLOSE-WAIT",
199 [TCP_CONNTRACK_LAST_ACK] = "LAST-ACK",
200 [TCP_CONNTRACK_TIME_WAIT] = "TIME-WAIT",
201 [TCP_CONNTRACK_CLOSE] = "CLOSE",
202 [TCP_CONNTRACK_SYN_SENT2] = "SYN-SENT2",
205 static const char *const dccp_state2str[DCCP_CONNTRACK_MAX] = {
206 [DCCP_CONNTRACK_NONE] = "NONE",
207 [DCCP_CONNTRACK_REQUEST] = "REQUEST",
208 [DCCP_CONNTRACK_RESPOND] = "RESPOND",
209 [DCCP_CONNTRACK_PARTOPEN] = "PARTOPEN",
210 [DCCP_CONNTRACK_OPEN] = "OPEN",
211 [DCCP_CONNTRACK_CLOSEREQ] = "CLOSE-REQ",
212 [DCCP_CONNTRACK_CLOSING] = "CLOSING",
213 [DCCP_CONNTRACK_TIMEWAIT] = "TIME-WAIT",
214 [DCCP_CONNTRACK_IGNORE] = "IGNORE",
215 [DCCP_CONNTRACK_INVALID] = "INVALID",
218 static const char *const sctp_state2str[SCTP_CONNTRACK_MAX] = {
219 [SCTP_CONNTRACK_NONE] = "NONE",
220 [SCTP_CONNTRACK_CLOSED] = "CLOSED",
221 [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE-WAIT",
222 [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE-ECHO",
223 [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
224 [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTD-SENT",
225 [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTD-RCVD",
226 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTD-ACK",
229 static const struct nfct_filter_ipv4 filter_ipv4 = {
230 .addr = __constant_htonl(INADDR_LOOPBACK),
231 .mask = 0xffffffff,
234 static const struct nfct_filter_ipv6 filter_ipv6 = {
235 .addr = { 0x0, 0x0, 0x0, 0x1 },
236 .mask = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
239 static int64_t time_after_us(struct timeval *tv)
241 struct timeval now;
243 bug_on(gettimeofday(&now, NULL));
245 now.tv_sec -= tv->tv_sec;
246 now.tv_usec -= tv->tv_usec;
248 return now.tv_sec * USEC_PER_SEC + now.tv_usec;
251 static void signal_handler(int number)
253 switch (number) {
254 case SIGINT:
255 case SIGQUIT:
256 case SIGTERM:
257 sigint = 1;
258 break;
259 case SIGHUP:
260 default:
261 break;
265 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct);
266 static void flow_entry_get_extended(struct flow_entry *n);
268 static void help(void)
270 printf("flowtop %s, top-like netfilter TCP/UDP/SCTP/.. flow tracking\n",
271 VERSION_STRING);
272 puts("http://www.netsniff-ng.org\n\n"
273 "Usage: flowtop [options]\n"
274 "Options:\n"
275 " -4|--ipv4 Show only IPv4 flows (default)\n"
276 " -6|--ipv6 Show only IPv6 flows (default)\n"
277 " -T|--tcp Show only TCP flows (default)\n"
278 " -U|--udp Show only UDP flows\n"
279 " -D|--dccp Show only DCCP flows\n"
280 " -I|--icmp Show only ICMP/ICMPv6 flows\n"
281 " -S|--sctp Show only SCTP flows\n"
282 " -n|--no-dns Don't perform hostname lookup\n"
283 " -G|--no-geoip Don't perform GeoIP lookup\n"
284 " -s|--show-src Also show source, not only dest\n"
285 " -b|--bits Show rates in bits/s instead of bytes/s\n"
286 " -u|--update Update GeoIP databases\n"
287 " -t|--interval <time> Refresh time in seconds (default 1s)\n"
288 " -v|--version Print version and exit\n"
289 " -h|--help Print this help and exit\n\n"
290 "Examples:\n"
291 " flowtop\n"
292 " flowtop -46UTDISs\n\n"
293 "Note:\n"
294 " If netfilter is not running, you can activate it with e.g.:\n"
295 " iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT\n"
296 " iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT\n");
297 puts(copyright);
298 die();
301 static void version(void)
303 printf("flowtop %s, Git id: %s\n", VERSION_LONG, GITVERSION);
304 puts("top-like netfilter TCP/UDP/SCTP/.. flow tracking\n"
305 "http://www.netsniff-ng.org\n");
306 puts(copyright);
307 die();
310 static void flow_entry_update_time(struct flow_entry *n)
312 bug_on(gettimeofday(&n->last_update, NULL));
315 #define CALC_RATE(fld) do { \
316 n->rate_##fld = (((fld) > n->fld) ? (((fld) - n->fld) / sec) : 0); \
317 } while (0)
319 static void flow_entry_calc_rate(struct flow_entry *n, const struct nf_conntrack *ct)
321 uint64_t bytes_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_BYTES);
322 uint64_t bytes_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_BYTES);
323 uint64_t pkts_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_PACKETS);
324 uint64_t pkts_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_PACKETS);
325 double sec = (double)time_after_us(&n->last_update) / USEC_PER_SEC;
327 if (sec < 1)
328 return;
330 CALC_RATE(bytes_src);
331 CALC_RATE(bytes_dst);
332 CALC_RATE(pkts_src);
333 CALC_RATE(pkts_dst);
336 static inline struct flow_entry *flow_entry_xalloc(void)
338 return xzmalloc(sizeof(struct flow_entry));
341 static inline void flow_entry_xfree(struct flow_entry *n)
343 if (n->ct)
344 nfct_destroy(n->ct);
346 xfree(n);
349 static inline void flow_list_init(struct flow_list *fl)
351 fl->head = NULL;
352 spinlock_init(&fl->lock);
355 static inline bool nfct_is_dns(const struct nf_conntrack *ct)
357 uint16_t port_src = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
358 uint16_t port_dst = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
360 return ntohs(port_src) == 53 || ntohs(port_dst) == 53;
363 static void flow_list_new_entry(struct flow_list *fl, const struct nf_conntrack *ct)
365 struct flow_entry *n;
367 /* We don't want to analyze / display DNS itself, since we
368 * use it to resolve reverse dns.
370 if (nfct_is_dns(ct))
371 return;
373 n = flow_entry_xalloc();
375 n->ct = nfct_clone(ct);
377 flow_entry_update_time(n);
378 flow_entry_from_ct(n, ct);
379 flow_entry_get_extended(n);
381 rcu_assign_pointer(n->next, fl->head);
382 rcu_assign_pointer(fl->head, n);
384 n->is_visible = true;
387 static struct flow_entry *flow_list_find_id(struct flow_list *fl,
388 uint32_t id)
390 struct flow_entry *n = rcu_dereference(fl->head);
392 while (n != NULL) {
393 if (n->flow_id == id)
394 return n;
396 n = rcu_dereference(n->next);
399 return NULL;
402 static struct flow_entry *flow_list_find_prev_id(const struct flow_list *fl,
403 uint32_t id)
405 struct flow_entry *prev = rcu_dereference(fl->head), *next;
407 if (prev->flow_id == id)
408 return NULL;
410 while ((next = rcu_dereference(prev->next)) != NULL) {
411 if (next->flow_id == id)
412 return prev;
414 prev = next;
417 return NULL;
420 static void flow_list_destroy_entry(struct flow_list *fl,
421 const struct nf_conntrack *ct)
423 struct flow_entry *n1, *n2;
424 uint32_t id = nfct_get_attr_u32(ct, ATTR_ID);
426 n1 = flow_list_find_id(fl, id);
427 if (n1) {
428 n2 = flow_list_find_prev_id(fl, id);
429 if (n2) {
430 rcu_assign_pointer(n2->next, n1->next);
431 n1->next = NULL;
433 flow_entry_xfree(n1);
434 } else {
435 struct flow_entry *next = fl->head->next;
437 flow_entry_xfree(fl->head);
438 fl->head = next;
443 static void flow_list_destroy(struct flow_list *fl)
445 struct flow_entry *n;
447 synchronize_rcu();
448 spinlock_lock(&flow_list.lock);
450 while (fl->head != NULL) {
451 n = rcu_dereference(fl->head->next);
452 fl->head->next = NULL;
454 flow_entry_xfree(fl->head);
455 rcu_assign_pointer(fl->head, n);
458 spinlock_unlock(&flow_list.lock);
461 static int walk_process(unsigned int pid, struct flow_entry *n)
463 int ret;
464 DIR *dir;
465 struct dirent *ent;
466 char path[1024];
468 if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
469 panic("giant process name! %u\n", pid);
471 dir = opendir(path);
472 if (!dir)
473 return 0;
475 while ((ent = readdir(dir))) {
476 struct stat statbuf;
478 if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
479 pid, ent->d_name) < 0)
480 continue;
482 if (stat(path, &statbuf) < 0)
483 continue;
485 if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == statbuf.st_ino) {
486 char cmdline[256];
488 ret = proc_get_cmdline(pid, cmdline, sizeof(cmdline));
489 if (ret < 0)
490 panic("Failed to get process cmdline: %s\n", strerror(errno));
492 if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0)
493 n->procname[0] = '\0';
494 n->procnum = pid;
495 closedir(dir);
496 return 1;
500 closedir(dir);
501 return 0;
504 static void walk_processes(struct flow_entry *n)
506 int ret;
507 DIR *dir;
508 struct dirent *ent;
510 /* n->inode must be set */
511 if (n->inode <= 0) {
512 n->procname[0] = '\0';
513 return;
516 dir = opendir("/proc");
517 if (!dir)
518 panic("Cannot open /proc: %s\n", strerror(errno));
520 while ((ent = readdir(dir))) {
521 const char *name = ent->d_name;
522 char *end;
523 unsigned int pid = strtoul(name, &end, 10);
525 /* not a PID */
526 if (pid == 0 && end == name)
527 continue;
529 ret = walk_process(pid, n);
530 if (ret > 0)
531 break;
534 closedir(dir);
537 static int get_port_inode(uint16_t port, int proto, bool is_ip6)
539 int ret = -ENOENT;
540 char path[128], buff[1024];
541 FILE *proc;
543 memset(path, 0, sizeof(path));
544 snprintf(path, sizeof(path), "/proc/net/%s%s",
545 l4proto2str[proto], is_ip6 ? "6" : "");
547 proc = fopen(path, "r");
548 if (!proc)
549 return -EIO;
551 memset(buff, 0, sizeof(buff));
553 while (fgets(buff, sizeof(buff), proc) != NULL) {
554 int inode = 0;
555 unsigned int lport = 0;
557 buff[sizeof(buff) - 1] = 0;
558 if (sscanf(buff, "%*u: %*X:%X %*X:%*X %*X %*X:%*X %*X:%*X "
559 "%*X %*u %*u %u", &lport, &inode) == 2) {
560 if ((uint16_t) lport == port) {
561 ret = inode;
562 break;
566 memset(buff, 0, sizeof(buff));
569 fclose(proc);
570 return ret;
573 #define CP_NFCT(elem, attr, x) \
574 do { n->elem = nfct_get_attr_u##x(ct,(attr)); } while (0)
575 #define CP_NFCT_BUFF(elem, attr) do { \
576 const uint8_t *buff = nfct_get_attr(ct,(attr)); \
577 if (buff != NULL) \
578 memcpy(n->elem, buff, sizeof(n->elem)); \
579 } while (0)
581 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct)
583 CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
584 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
586 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
587 CP_NFCT(ip4_dst_addr, ATTR_ORIG_IPV4_DST, 32);
589 CP_NFCT(port_src, ATTR_ORIG_PORT_SRC, 16);
590 CP_NFCT(port_dst, ATTR_ORIG_PORT_DST, 16);
592 CP_NFCT(status, ATTR_STATUS, 32);
594 CP_NFCT(tcp_state, ATTR_TCP_STATE, 8);
595 CP_NFCT(tcp_flags, ATTR_TCP_FLAGS_ORIG, 8);
596 CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
597 CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
599 CP_NFCT(pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
600 CP_NFCT(bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
602 CP_NFCT(pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
603 CP_NFCT(bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
605 CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
606 CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
608 CP_NFCT(flow_id, ATTR_ID, 32);
609 CP_NFCT(use, ATTR_USE, 32);
611 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
612 CP_NFCT_BUFF(ip6_dst_addr, ATTR_ORIG_IPV6_DST);
614 n->port_src = ntohs(n->port_src);
615 n->port_dst = ntohs(n->port_dst);
617 n->ip4_src_addr = ntohl(n->ip4_src_addr);
618 n->ip4_dst_addr = ntohl(n->ip4_dst_addr);
621 #define SELFLD(dir,src_member,dst_member) \
622 (((dir) == FLOW_DIR_SRC) ? n->src_member : n->dst_member)
624 static void flow_entry_get_sain4_obj(const struct flow_entry *n,
625 enum flow_direction dir,
626 struct sockaddr_in *sa)
628 memset(sa, 0, sizeof(*sa));
629 sa->sin_family = PF_INET;
630 sa->sin_addr.s_addr = htonl(SELFLD(dir, ip4_src_addr, ip4_dst_addr));
633 static void flow_entry_get_sain6_obj(const struct flow_entry *n,
634 enum flow_direction dir,
635 struct sockaddr_in6 *sa)
637 memset(sa, 0, sizeof(*sa));
638 sa->sin6_family = PF_INET6;
640 memcpy(&sa->sin6_addr, SELFLD(dir, ip6_src_addr, ip6_dst_addr),
641 sizeof(sa->sin6_addr));
644 static void
645 flow_entry_geo_city_lookup_generic(struct flow_entry *n,
646 enum flow_direction dir)
648 struct sockaddr_in sa4;
649 struct sockaddr_in6 sa6;
650 const char *city = NULL;
652 switch (n->l3_proto) {
653 default:
654 bug();
656 case AF_INET:
657 flow_entry_get_sain4_obj(n, dir, &sa4);
658 city = geoip4_city_name(&sa4);
659 break;
661 case AF_INET6:
662 flow_entry_get_sain6_obj(n, dir, &sa6);
663 city = geoip6_city_name(&sa6);
664 break;
667 build_bug_on(sizeof(n->city_src) != sizeof(n->city_dst));
669 if (city)
670 strlcpy(SELFLD(dir, city_src, city_dst), city,
671 sizeof(n->city_src));
672 else
673 SELFLD(dir, city_src, city_dst)[0] = '\0';
676 static void
677 flow_entry_geo_country_lookup_generic(struct flow_entry *n,
678 enum flow_direction dir)
680 struct sockaddr_in sa4;
681 struct sockaddr_in6 sa6;
682 const char *country = NULL;
683 const char *country_code = NULL;
685 switch (n->l3_proto) {
686 default:
687 bug();
689 case AF_INET:
690 flow_entry_get_sain4_obj(n, dir, &sa4);
691 country = geoip4_country_name(&sa4);
692 country_code = geoip4_country_code3_name(&sa4);
693 break;
695 case AF_INET6:
696 flow_entry_get_sain6_obj(n, dir, &sa6);
697 country = geoip6_country_name(&sa6);
698 country_code = geoip6_country_code3_name(&sa6);
699 break;
702 build_bug_on(sizeof(n->country_src) != sizeof(n->country_dst));
704 if (country)
705 strlcpy(SELFLD(dir, country_src, country_dst), country,
706 sizeof(n->country_src));
707 else
708 SELFLD(dir, country_src, country_dst)[0] = '\0';
710 build_bug_on(sizeof(n->country_code_src) != sizeof(n->country_code_dst));
712 if (country_code)
713 strlcpy(SELFLD(dir, country_code_src, country_code_dst),
714 country_code, sizeof(n->country_code_src));
715 else
716 SELFLD(dir, country_code_src, country_code_dst)[0] = '\0';
719 static void flow_entry_get_extended_geo(struct flow_entry *n,
720 enum flow_direction dir)
722 if (resolve_geoip) {
723 flow_entry_geo_city_lookup_generic(n, dir);
724 flow_entry_geo_country_lookup_generic(n, dir);
728 static void flow_entry_get_extended_revdns(struct flow_entry *n,
729 enum flow_direction dir)
731 size_t sa_len;
732 struct sockaddr_in sa4;
733 struct sockaddr_in6 sa6;
734 struct sockaddr *sa;
735 struct hostent *hent;
737 build_bug_on(sizeof(n->rev_dns_src) != sizeof(n->rev_dns_dst));
739 switch (n->l3_proto) {
740 default:
741 bug();
743 case AF_INET:
744 flow_entry_get_sain4_obj(n, dir, &sa4);
746 if (!resolve_dns) {
747 inet_ntop(AF_INET, &sa4.sin_addr,
748 SELFLD(dir, rev_dns_src, rev_dns_dst),
749 sizeof(n->rev_dns_src));
750 return;
753 sa = (struct sockaddr *) &sa4;
754 sa_len = sizeof(sa4);
755 hent = gethostbyaddr(&sa4.sin_addr, sizeof(sa4.sin_addr), AF_INET);
756 break;
758 case AF_INET6:
759 flow_entry_get_sain6_obj(n, dir, &sa6);
761 if (!resolve_dns) {
762 inet_ntop(AF_INET6, &sa6.sin6_addr,
763 SELFLD(dir, rev_dns_src, rev_dns_dst),
764 sizeof(n->rev_dns_src));
765 return;
768 sa = (struct sockaddr *) &sa6;
769 sa_len = sizeof(sa6);
770 hent = gethostbyaddr(&sa6.sin6_addr, sizeof(sa6.sin6_addr), AF_INET6);
771 break;
774 getnameinfo(sa, sa_len, SELFLD(dir, rev_dns_src, rev_dns_dst),
775 sizeof(n->rev_dns_src), NULL, 0, NI_NUMERICHOST);
777 if (hent)
778 strlcpy(SELFLD(dir, rev_dns_src, rev_dns_dst), hent->h_name,
779 sizeof(n->rev_dns_src));
782 static void flow_entry_get_extended(struct flow_entry *n)
784 if (n->flow_id == 0)
785 return;
787 flow_entry_get_extended_revdns(n, FLOW_DIR_SRC);
788 flow_entry_get_extended_geo(n, FLOW_DIR_SRC);
790 flow_entry_get_extended_revdns(n, FLOW_DIR_DST);
791 flow_entry_get_extended_geo(n, FLOW_DIR_DST);
793 /* Lookup application */
794 n->inode = get_port_inode(n->port_src, n->l4_proto,
795 n->l3_proto == AF_INET6);
796 if (n->inode > 0)
797 walk_processes(n);
800 static char *bandw2str(double bytes, char *buf, size_t len)
802 if (bytes <= 0) {
803 buf[0] = '\0';
804 return buf;
807 if (bytes > 1000000000.)
808 snprintf(buf, len, "%.1fGB", bytes / 1000000000.);
809 else if (bytes > 1000000.)
810 snprintf(buf, len, "%.1fMB", bytes / 1000000.);
811 else if (bytes > 1000.)
812 snprintf(buf, len, "%.1fkB", bytes / 1000.);
813 else
814 snprintf(buf, len, "%.0f", bytes);
816 return buf;
819 static char *rate2str(double rate, char *buf, size_t len)
821 const char * const unit_fmt[2][4] = {
822 { "%.1fGbit/s", "%.1fMbit/s", "%.1fkbit/s", "%.0fbit/s" },
823 { "%.1fGB/s", "%.1fMB/s", "%.1fkB/s", "%.0fB/s" }
826 if (rate <= 0) {
827 buf[0] = '\0';
828 return buf;
831 if (rate_type == RATE_BITS)
832 rate *= 8;
834 if (rate > 1000000000.)
835 snprintf(buf, len, unit_fmt[rate_type][0], rate / 1000000000.);
836 else if (rate > 1000000.)
837 snprintf(buf, len, unit_fmt[rate_type][1], rate / 1000000.);
838 else if (rate > 1000.)
839 snprintf(buf, len, unit_fmt[rate_type][2], rate / 1000.);
840 else
841 snprintf(buf, len, unit_fmt[rate_type][3], rate);
843 return buf;
846 static char *time2str(uint64_t tstamp, char *str, size_t len)
848 time_t now;
849 int v, s;
851 time(&now);
853 s = now - (tstamp ? (tstamp / NSEC_PER_SEC) : now);
854 if (s <= 0) {
855 str[0] = '\0';
856 return str;
859 v = s / (3600 * 24);
860 if (v > 0) {
861 slprintf(str, len, "%dd", v);
862 return str;
865 v = s / 3600;
866 if (v > 0) {
867 slprintf(str, len, "%dh", v);
868 return str;
871 v = s / 60;
872 if (v > 0) {
873 slprintf(str, len, "%dm", v);
874 return str;
877 slprintf(str, len, "%ds", s);
878 return str;
881 static void print_flow_peer_info(const struct flow_entry *n, int y, int x,
882 enum flow_direction dir)
884 int counters_color = COLOR(YELLOW, BLACK);
885 int src_color = COLOR(RED, BLACK);
886 int dst_color = COLOR(BLUE, BLACK);
887 int country_color = COLOR(GREEN, BLACK);
888 int port_color = A_BOLD;
889 const char *str = NULL;
890 uint16_t port = 0;
891 char tmp[128];
893 if (show_src && dir == FLOW_DIR_SRC) {
894 country_color = counters_color = src_color;
895 port_color |= src_color;
896 } else if (show_src && FLOW_DIR_DST) {
897 country_color = counters_color = dst_color;
898 port_color |= dst_color;
901 mvprintw(y, x, "");
903 /* Reverse DNS/IP */
904 attron(dir == FLOW_DIR_SRC ? src_color : dst_color);
905 printw(" %-*.*s", 50, 50, SELFLD(dir, rev_dns_src, rev_dns_dst));
906 attroff(dir == FLOW_DIR_SRC ? src_color : dst_color);
908 /* Application port */
909 port = SELFLD(dir, port_src, port_dst);
910 str = NULL;
912 switch (n->l4_proto) {
913 case IPPROTO_TCP:
914 str = lookup_port_tcp(port);
915 break;
916 case IPPROTO_UDP:
917 case IPPROTO_UDPLITE:
918 str = lookup_port_udp(port);
919 break;
922 if (!str && port)
923 slprintf(tmp, sizeof(tmp), "%d", port);
924 else
925 slprintf(tmp, sizeof(tmp), "%s", str ? str : "");
927 attron(port_color);
928 printw(" %-*.*s", 8, 8, tmp);
929 attroff(port_color);
931 /* Country code */
932 attron(country_color);
933 printw(" %-*.*s", 3, 3, SELFLD(dir, country_code_src, country_code_dst));
934 attroff(country_color);
936 /* Bytes */
937 attron(counters_color);
938 printw(" %*.*s", 10, 10,
939 bandw2str(SELFLD(dir, bytes_src, bytes_dst),
940 tmp, sizeof(tmp) - 1));
941 attroff(counters_color);
943 /* Rate */
944 attron(counters_color);
945 printw(" %*.*s", 10, 10,
946 rate2str(SELFLD(dir, rate_bytes_src, rate_bytes_dst),
947 tmp, sizeof(tmp) - 1));
948 attroff(counters_color);
951 static void draw_flow_entry(WINDOW *scr, const struct flow_entry *n, int line)
953 const char *str = NULL;
954 char tmp[128];
956 mvwprintw(scr, line, 0, "");
958 /* Application */
959 COLOR_ON(YELLOW, BLACK);
960 printw("%-*.*s", 10, 10, n->procname);
961 COLOR_OFF(YELLOW, BLACK);
963 /* PID */
964 slprintf(tmp, sizeof(tmp), "%.d", n->procnum);
965 attron(A_BOLD);
966 printw("%-*.*s", 7, 7, tmp);
967 attroff(A_BOLD);
969 /* L4 protocol */
970 printw(" %-*.*s", 6, 6, l4proto2str[n->l4_proto]);
972 /* L4 protocol state */
973 COLOR_ON(YELLOW, BLACK);
974 switch (n->l4_proto) {
975 case IPPROTO_TCP:
976 str = tcp_state2str[n->tcp_state];
977 break;
978 case IPPROTO_SCTP:
979 str = sctp_state2str[n->sctp_state];
980 break;
981 case IPPROTO_DCCP:
982 str = dccp_state2str[n->dccp_state];
983 break;
984 case IPPROTO_UDP:
985 case IPPROTO_UDPLITE:
986 case IPPROTO_ICMP:
987 case IPPROTO_ICMPV6:
988 str = "";
989 break;
991 COLOR_OFF(YELLOW, BLACK);
992 printw(" %-*.*s", 11, 11, str);
993 attroff(COLOR_PAIR(3));
994 COLOR_OFF(YELLOW, BLACK);
996 /* Time */
997 printw(" %*.*s", 4, 4, time2str(n->timestamp_start, tmp, sizeof(tmp)));
999 print_flow_peer_info(n, line, 41, show_src ? FLOW_DIR_SRC : FLOW_DIR_DST);
1000 if (show_src)
1001 print_flow_peer_info(n, line + 1, 41, FLOW_DIR_DST);
1004 static inline bool presenter_flow_wrong_state(struct flow_entry *n)
1006 switch (n->l4_proto) {
1007 case IPPROTO_TCP:
1008 switch (n->tcp_state) {
1009 case TCP_CONNTRACK_SYN_SENT:
1010 case TCP_CONNTRACK_SYN_RECV:
1011 case TCP_CONNTRACK_ESTABLISHED:
1012 case TCP_CONNTRACK_FIN_WAIT:
1013 case TCP_CONNTRACK_CLOSE_WAIT:
1014 case TCP_CONNTRACK_LAST_ACK:
1015 case TCP_CONNTRACK_TIME_WAIT:
1016 case TCP_CONNTRACK_CLOSE:
1017 case TCP_CONNTRACK_SYN_SENT2:
1018 case TCP_CONNTRACK_NONE:
1019 return false;
1020 break;
1022 break;
1023 case IPPROTO_SCTP:
1024 switch (n->sctp_state) {
1025 case SCTP_CONNTRACK_NONE:
1026 case SCTP_CONNTRACK_CLOSED:
1027 case SCTP_CONNTRACK_COOKIE_WAIT:
1028 case SCTP_CONNTRACK_COOKIE_ECHOED:
1029 case SCTP_CONNTRACK_ESTABLISHED:
1030 case SCTP_CONNTRACK_SHUTDOWN_SENT:
1031 case SCTP_CONNTRACK_SHUTDOWN_RECD:
1032 case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT:
1033 return false;
1034 break;
1036 break;
1037 case IPPROTO_DCCP:
1038 switch (n->dccp_state) {
1039 case DCCP_CONNTRACK_NONE:
1040 case DCCP_CONNTRACK_REQUEST:
1041 case DCCP_CONNTRACK_RESPOND:
1042 case DCCP_CONNTRACK_PARTOPEN:
1043 case DCCP_CONNTRACK_OPEN:
1044 case DCCP_CONNTRACK_CLOSEREQ:
1045 case DCCP_CONNTRACK_CLOSING:
1046 case DCCP_CONNTRACK_TIMEWAIT:
1047 case DCCP_CONNTRACK_IGNORE:
1048 case DCCP_CONNTRACK_INVALID:
1049 return false;
1050 break;
1052 break;
1053 case IPPROTO_UDP:
1054 case IPPROTO_UDPLITE:
1055 case IPPROTO_ICMP:
1056 case IPPROTO_ICMPV6:
1057 return false;
1058 break;
1061 return true;
1064 static void draw_flows_header(WINDOW *scr, int line)
1066 COLOR_ON(BLACK, GREEN);
1068 mvwprintw(scr, line, 0, "%-*.*s", cols, cols, "");
1069 mvwprintw(scr, line, 0, "");
1071 wprintw(scr, "%-*.*s", 10, 10, "PROCESS");
1072 wprintw(scr, "%-*.*s", 7, 7, "PID");
1073 wprintw(scr, " %-*.*s", 6, 6, "PROTO");
1074 wprintw(scr, " %-*.*s", 11, 11, "STATE");
1075 wprintw(scr, " %*.*s", 4, 4, "TIME");
1076 wprintw(scr, " %-*.*s", 50, 50, "ADDRESS");
1077 wprintw(scr, " %-*.*s", 8, 8, "PORT");
1078 wprintw(scr, " %-*.*s", 3, 3, "GEO");
1079 wprintw(scr, " %*.*s", 10, 10, "BYTES");
1080 wprintw(scr, " %*.*s", 10, 10, "RATE");
1082 COLOR_OFF(BLACK, GREEN);
1085 static void draw_flows(WINDOW *screen, struct flow_list *fl,
1086 int skip_lines)
1088 int row_width = show_src ? 2 : 1;
1089 unsigned int flows = 0;
1090 unsigned int line = 4;
1091 int skip = skip_lines;
1092 struct flow_entry *n;
1094 wclear(screen);
1095 clear();
1097 rcu_read_lock();
1099 n = rcu_dereference(fl->head);
1100 if (!n)
1101 mvwprintw(screen, line, 2, "(No sessions! "
1102 "Is netfilter running?)");
1104 draw_flows_header(screen, line - 1);
1106 for (; n; n = rcu_dereference(n->next)) {
1107 if (!n->is_visible)
1108 continue;
1109 if (presenter_flow_wrong_state(n))
1110 continue;
1112 /* count only flows which might be showed */
1113 flows++;
1115 if (line + row_width >= rows)
1116 continue;
1117 if (--skip >= 0)
1118 continue;
1120 draw_flow_entry(screen, n, line);
1121 line += row_width;
1124 mvwprintw(screen, 1, 2, "Kernel netfilter flows(%u) for ", flows);
1126 if (what & INCLUDE_IPV4)
1127 printw("IPv4,");
1128 if (what & INCLUDE_IPV6)
1129 printw("IPv6,");
1130 if (what & INCLUDE_TCP)
1131 printw("TCP,");
1132 if (what & INCLUDE_UDP)
1133 printw("UDP,");
1134 if (what & INCLUDE_SCTP)
1135 printw("SCTP,");
1136 if (what & INCLUDE_DCCP)
1137 printw("DCCP,");
1138 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1139 printw("ICMP,");
1140 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1141 printw("ICMP6,");
1142 if (show_active_only)
1143 printw("Active,");
1145 printw(" [+%d]", skip_lines);
1147 if (is_flow_collecting)
1148 printw(" [Collecting flows ...]");
1150 rcu_read_unlock();
1153 static void draw_help(WINDOW *screen)
1155 int col = 0;
1156 int row = 1;
1157 int i;
1159 mvaddch(row, col, ACS_ULCORNER);
1160 mvaddch(rows - row - 1, col, ACS_LLCORNER);
1162 mvaddch(row, cols - 1, ACS_URCORNER);
1163 mvaddch(rows - row - 1, cols - 1, ACS_LRCORNER);
1165 for (i = 1; i < rows - row - 2; i++) {
1166 mvaddch(row + i, 0, ACS_VLINE);
1167 mvaddch(row + i, cols - 1, ACS_VLINE);
1169 for (i = 1; i < cols - col - 1; i++) {
1170 mvaddch(row, col + i, ACS_HLINE);
1171 mvaddch(rows - row - 1, col + i, ACS_HLINE);
1174 attron(A_BOLD);
1175 mvaddnstr(row, cols / 2 - 2, "| Help |", -1);
1177 attron(A_UNDERLINE);
1178 mvaddnstr(row + 2, col + 2, "Navigation", -1);
1179 attroff(A_BOLD | A_UNDERLINE);
1181 mvaddnstr(row + 4, col + 3, "Up, u, k Move up", -1);
1182 mvaddnstr(row + 5, col + 3, "Down, d, j Move down", -1);
1183 mvaddnstr(row + 6, col + 3, "? Toggle help window", -1);
1184 mvaddnstr(row + 7, col + 3, "q, Ctrl+C Quit", -1);
1186 attron(A_BOLD | A_UNDERLINE);
1187 mvaddnstr(row + 9, col + 2, "Display Settings", -1);
1188 attroff(A_BOLD | A_UNDERLINE);
1190 mvaddnstr(row + 11, col + 3, "b Toggle rate units (bits/bytes)", -1);
1191 mvaddnstr(row + 12, col + 3, "a Toggle display of active flows (rate > 0) only", -1);
1192 mvaddnstr(row + 13, col + 3, "s Toggle show source peer info", -1);
1194 mvaddnstr(row + 15, col + 3, "T Toggle display TCP flows", -1);
1195 mvaddnstr(row + 16, col + 3, "U Toggle display UDP flows", -1);
1196 mvaddnstr(row + 17, col + 3, "D Toggle display DCCP flows", -1);
1197 mvaddnstr(row + 18, col + 3, "I Toggle display ICMP flows", -1);
1198 mvaddnstr(row + 19, col + 3, "S Toggle display SCTP flows", -1);
1201 static void draw_header(WINDOW *screen)
1203 int i;
1205 attron(A_STANDOUT);
1207 for (i = 0; i < cols; i++)
1208 mvaddch(0, i, ' ');
1210 mvwprintw(screen, 0, 2, "flowtop %s", VERSION_LONG);
1211 attroff(A_STANDOUT);
1214 static void draw_footer(WINDOW *screen)
1216 int i;
1218 attron(A_STANDOUT);
1220 for (i = 0; i < cols; i++)
1221 mvaddch(rows - 1, i, ' ');
1223 mvaddnstr(rows - 1, 1, "Press '?' for help", -1);
1224 addch(ACS_VLINE);
1225 attroff(A_STANDOUT);
1228 static void show_option_toggle(int opt)
1230 switch (opt) {
1231 case 'T':
1232 TOGGLE_FLAG(what, INCLUDE_TCP);
1233 break;
1234 case 'U':
1235 TOGGLE_FLAG(what, INCLUDE_UDP);
1236 break;
1237 case 'D':
1238 TOGGLE_FLAG(what, INCLUDE_DCCP);
1239 break;
1240 case 'I':
1241 TOGGLE_FLAG(what, INCLUDE_ICMP);
1242 break;
1243 case 'S':
1244 TOGGLE_FLAG(what, INCLUDE_SCTP);
1245 break;
1249 static void presenter(void)
1251 int time_sleep_us = 200000;
1252 int time_passed_us = 0;
1253 bool show_help = false;
1254 int skip_lines = 0;
1255 WINDOW *screen;
1257 lookup_init(LT_PORTS_TCP);
1258 lookup_init(LT_PORTS_UDP);
1259 screen = screen_init(false);
1261 start_color();
1262 INIT_COLOR(RED, BLACK);
1263 INIT_COLOR(BLUE, BLACK);
1264 INIT_COLOR(YELLOW, BLACK);
1265 INIT_COLOR(GREEN, BLACK);
1266 INIT_COLOR(BLACK, GREEN);
1268 rcu_register_thread();
1269 while (!sigint) {
1270 bool redraw_flows = true;
1271 int ch;
1273 curs_set(0);
1274 getmaxyx(screen, rows, cols);
1276 ch = getch();
1277 switch (ch) {
1278 case 'q':
1279 sigint = 1;
1280 break;
1281 case KEY_UP:
1282 case 'u':
1283 case 'k':
1284 skip_lines--;
1285 if (skip_lines < 0)
1286 skip_lines = 0;
1287 break;
1288 case KEY_DOWN:
1289 case 'd':
1290 case 'j':
1291 skip_lines++;
1292 if (skip_lines > SCROLL_MAX)
1293 skip_lines = SCROLL_MAX;
1294 break;
1295 case 'b':
1296 if (rate_type == RATE_BYTES)
1297 rate_type = RATE_BITS;
1298 else
1299 rate_type = RATE_BYTES;
1300 break;
1301 case 'a':
1302 show_active_only = !show_active_only;
1303 break;
1304 case 's':
1305 show_src = !show_src;
1306 break;
1307 case '?':
1308 show_help = !show_help;
1309 wclear(screen);
1310 clear();
1311 break;
1312 case 'T':
1313 case 'U':
1314 case 'D':
1315 case 'I':
1316 case 'S':
1317 show_option_toggle(ch);
1318 do_reload_flows = true;
1319 break;
1320 default:
1321 fflush(stdin);
1322 redraw_flows = false;
1323 break;
1326 if (!redraw_flows)
1327 redraw_flows = time_passed_us >= 1 * USEC_PER_SEC;
1329 if (show_help)
1330 redraw_flows = false;
1332 if (redraw_flows) {
1333 draw_flows(screen, &flow_list, skip_lines);
1334 time_passed_us = 0;
1335 } else {
1336 time_passed_us += time_sleep_us;
1339 draw_header(screen);
1341 if (show_help)
1342 draw_help(screen);
1344 draw_footer(screen);
1346 wrefresh(screen);
1347 refresh();
1348 usleep(time_sleep_us);
1350 rcu_unregister_thread();
1352 screen_end();
1353 lookup_cleanup(LT_PORTS_UDP);
1354 lookup_cleanup(LT_PORTS_TCP);
1357 static void restore_sysctl(void *obj)
1359 struct sysctl_params_ctx *sysctl_ctx = obj;
1361 if (sysctl_ctx->nfct_acct == 0)
1362 sysctl_set_int("net/netfilter/nf_conntrack_acct",
1363 sysctl_ctx->nfct_acct);
1365 if (sysctl_ctx->nfct_tstamp == 0)
1366 sysctl_set_int("net/netfilter/nf_conntrack_timestamp",
1367 sysctl_ctx->nfct_tstamp);
1370 static void on_panic_handler(void *arg)
1372 restore_sysctl(arg);
1373 screen_end();
1376 static void conntrack_acct_enable(void)
1378 /* We can still work w/o traffic accounting so just warn about error */
1379 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &sysctl.nfct_acct)) {
1380 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1381 strerror(errno));
1382 return;
1385 if (sysctl.nfct_acct == 1)
1386 return;
1388 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1389 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1390 strerror(errno));
1394 static void conntrack_tstamp_enable(void)
1396 if (sysctl_get_int("net/netfilter/nf_conntrack_timestamp", &sysctl.nfct_tstamp)) {
1397 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_timestamp: %s\n",
1398 strerror(errno));
1399 return;
1402 if (sysctl.nfct_tstamp == 1)
1403 return;
1405 if (sysctl_set_int("net/netfilter/nf_conntrack_timestamp", 1)) {
1406 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_timestamp: %s\n",
1407 strerror(errno));
1411 static void flow_entry_filter(struct flow_entry *n)
1413 if (show_active_only && !n->rate_bytes_src && !n->rate_bytes_dst)
1414 n->is_visible = false;
1415 else
1416 n->is_visible = true;
1419 static int flow_list_update_entry(struct flow_list *fl, struct nf_conntrack *ct)
1421 struct flow_entry *n;
1423 n = flow_list_find_id(&flow_list, nfct_get_attr_u32(ct, ATTR_ID));
1424 if (!n)
1425 return NFCT_CB_CONTINUE;
1427 flow_entry_calc_rate(n, ct);
1428 flow_entry_update_time(n);
1429 flow_entry_from_ct(n, ct);
1430 flow_entry_filter(n);
1432 return NFCT_CB_CONTINUE;
1435 static int flow_event_cb(enum nf_conntrack_msg_type type,
1436 struct nf_conntrack *ct, void *data __maybe_unused)
1438 if (sigint)
1439 return NFCT_CB_STOP;
1441 synchronize_rcu();
1442 spinlock_lock(&flow_list.lock);
1444 switch (type) {
1445 case NFCT_T_NEW:
1446 flow_list_new_entry(&flow_list, ct);
1447 break;
1448 case NFCT_T_UPDATE:
1449 flow_list_update_entry(&flow_list, ct);
1450 break;
1451 case NFCT_T_DESTROY:
1452 flow_list_destroy_entry(&flow_list, ct);
1453 break;
1454 default:
1455 break;
1458 spinlock_unlock(&flow_list.lock);
1460 if (sigint)
1461 return NFCT_CB_STOP;
1463 return NFCT_CB_CONTINUE;
1466 static void collector_refresh_flows(struct nfct_handle *handle)
1468 struct flow_entry *n;
1470 n = rcu_dereference(flow_list.head);
1471 for (; n; n = rcu_dereference(n->next))
1472 nfct_query(handle, NFCT_Q_GET, n->ct);
1475 static void collector_create_filter(struct nfct_handle *nfct)
1477 struct nfct_filter *filter;
1478 int ret;
1480 filter = nfct_filter_create();
1481 if (!filter)
1482 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1484 if (what & INCLUDE_UDP) {
1485 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1486 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1488 if (what & INCLUDE_TCP)
1489 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1490 if (what & INCLUDE_DCCP)
1491 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1492 if (what & INCLUDE_SCTP)
1493 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1494 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1495 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1496 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1497 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1498 if (what & INCLUDE_IPV4) {
1499 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1500 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1502 if (what & INCLUDE_IPV6) {
1503 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1504 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1507 ret = nfct_filter_attach(nfct_fd(nfct), filter);
1508 if (ret < 0)
1509 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1511 nfct_filter_destroy(filter);
1514 /* This hand-crafted filter looks ugly but it allows to do not
1515 * flush nfct connections & filter them by user specified filter.
1516 * May be it is better to replace this one by nfct_cmp. */
1517 static int flow_dump_cb(enum nf_conntrack_msg_type type,
1518 struct nf_conntrack *ct, void *data __maybe_unused)
1520 struct flow_entry fl;
1521 struct flow_entry *n = &fl;
1523 if (sigint)
1524 return NFCT_CB_STOP;
1526 synchronize_rcu();
1527 spinlock_lock(&flow_list.lock);
1529 if (!(what & ~(INCLUDE_IPV4 | INCLUDE_IPV6)))
1530 goto check_addr;
1532 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
1534 if (what & INCLUDE_UDP) {
1535 if (n->l4_proto == IPPROTO_UDP)
1536 goto check_addr;
1538 if (n->l4_proto == IPPROTO_UDPLITE)
1539 goto check_addr;
1542 if ((what & INCLUDE_TCP) && n->l4_proto == IPPROTO_TCP)
1543 goto check_addr;
1545 if ((what & INCLUDE_DCCP) && n->l4_proto == IPPROTO_DCCP)
1546 goto check_addr;
1548 if ((what & INCLUDE_SCTP) && n->l4_proto == IPPROTO_SCTP)
1549 goto check_addr;
1551 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV4) &&
1552 n->l4_proto == IPPROTO_ICMP) {
1553 goto check_addr;
1556 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV6) &&
1557 n->l4_proto == IPPROTO_ICMPV6) {
1558 goto check_addr;
1561 goto skip_flow;
1563 check_addr:
1564 /* filter loopback addresses */
1565 if (what & INCLUDE_IPV4) {
1566 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
1568 if (n->ip4_src_addr == filter_ipv4.addr)
1569 goto skip_flow;
1571 if (what & INCLUDE_IPV6) {
1572 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
1574 if (n->ip6_src_addr[0] == 0x0 &&
1575 n->ip6_src_addr[1] == 0x0 &&
1576 n->ip6_src_addr[2] == 0x0 &&
1577 n->ip6_src_addr[3] == 0x1)
1578 goto skip_flow;
1581 flow_list_new_entry(&flow_list, ct);
1583 skip_flow:
1584 spinlock_unlock(&flow_list.lock);
1585 return NFCT_CB_CONTINUE;
1588 static void collector_dump_flows(void)
1590 struct nfct_handle *nfct = nfct_open(CONNTRACK, 0);
1592 if (!nfct)
1593 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1595 nfct_callback_register(nfct, NFCT_T_ALL, flow_dump_cb, NULL);
1597 is_flow_collecting = true;
1598 if (what & INCLUDE_IPV4) {
1599 int family = AF_INET;
1600 nfct_query(nfct, NFCT_Q_DUMP, &family);
1602 if (what & INCLUDE_IPV6) {
1603 int family = AF_INET6;
1604 nfct_query(nfct, NFCT_Q_DUMP, &family);
1606 is_flow_collecting = false;
1608 nfct_close(nfct);
1611 static void *collector(void *null __maybe_unused)
1613 struct nfct_handle *ct_event;
1614 struct pollfd poll_fd[1];
1616 flow_list_init(&flow_list);
1618 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1619 NF_NETLINK_CONNTRACK_UPDATE |
1620 NF_NETLINK_CONNTRACK_DESTROY);
1621 if (!ct_event)
1622 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1624 collector_create_filter(ct_event);
1626 nfct_callback_register(ct_event, NFCT_T_ALL, flow_event_cb, NULL);
1628 poll_fd[0].fd = nfct_fd(ct_event);
1629 poll_fd[0].events = POLLIN;
1631 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1632 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1633 strerror(errno));
1635 rcu_register_thread();
1637 collector_dump_flows();
1639 while (!sigint) {
1640 int status;
1642 if (!do_reload_flows) {
1643 usleep(USEC_PER_SEC * interval);
1644 } else {
1645 do_reload_flows = false;
1647 flow_list_destroy(&flow_list);
1649 collector_create_filter(ct_event);
1650 collector_dump_flows();
1653 collector_refresh_flows(ct_event);
1655 status = poll(poll_fd, 1, 0);
1656 if (status < 0) {
1657 if (errno == EAGAIN || errno == EINTR)
1658 continue;
1660 panic("Error while polling: %s\n", strerror(errno));
1661 } else if (status == 0) {
1662 continue;
1665 if (poll_fd[0].revents & POLLIN)
1666 nfct_catch(ct_event);
1669 rcu_unregister_thread();
1671 flow_list_destroy(&flow_list);
1672 spinlock_destroy(&flow_list.lock);
1674 nfct_close(ct_event);
1676 pthread_exit(NULL);
1679 int main(int argc, char **argv)
1681 pthread_t tid;
1682 int ret, c, opt_index, what_cmd = 0;
1684 setfsuid(getuid());
1685 setfsgid(getgid());
1687 while ((c = getopt_long(argc, argv, short_options, long_options,
1688 &opt_index)) != EOF) {
1689 switch (c) {
1690 case '4':
1691 what_cmd |= INCLUDE_IPV4;
1692 break;
1693 case '6':
1694 what_cmd |= INCLUDE_IPV6;
1695 break;
1696 case 'T':
1697 what_cmd |= INCLUDE_TCP;
1698 break;
1699 case 'U':
1700 what_cmd |= INCLUDE_UDP;
1701 break;
1702 case 'D':
1703 what_cmd |= INCLUDE_DCCP;
1704 break;
1705 case 'I':
1706 what_cmd |= INCLUDE_ICMP;
1707 break;
1708 case 'S':
1709 what_cmd |= INCLUDE_SCTP;
1710 break;
1711 case 's':
1712 show_src = true;
1713 break;
1714 case 'b':
1715 rate_type = RATE_BITS;
1716 break;
1717 case 'u':
1718 update_geoip();
1719 die();
1720 break;
1721 case 't':
1722 interval = strtoul(optarg, NULL, 10);
1723 break;
1724 case 'n':
1725 resolve_dns = false;
1726 break;
1727 case 'G':
1728 resolve_geoip = false;
1729 break;
1730 case 'h':
1731 help();
1732 break;
1733 case 'v':
1734 version();
1735 break;
1736 default:
1737 break;
1741 if (what_cmd > 0) {
1742 what = what_cmd;
1744 if (!(what & (INCLUDE_IPV4 | INCLUDE_IPV6)))
1745 what |= INCLUDE_IPV4 | INCLUDE_IPV6;
1748 rcu_init();
1750 register_signal(SIGINT, signal_handler);
1751 register_signal(SIGQUIT, signal_handler);
1752 register_signal(SIGTERM, signal_handler);
1753 register_signal(SIGHUP, signal_handler);
1755 panic_handler_add(on_panic_handler, &sysctl);
1757 conntrack_acct_enable();
1758 conntrack_tstamp_enable();
1760 if (resolve_geoip)
1761 init_geoip(1);
1763 ret = pthread_create(&tid, NULL, collector, NULL);
1764 if (ret < 0)
1765 panic("Cannot create phthread!\n");
1767 presenter();
1769 if (resolve_geoip)
1770 destroy_geoip();
1772 restore_sysctl(&sysctl);
1774 return 0;