flowtop: Remove unused parameters from draw_help() and draw_footer()
[netsniff-ng.git] / flowtop.c
blob848fd6a81d594fb739603fd5e603ea2c67b820ca
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 "ui.h"
32 #include "die.h"
33 #include "xmalloc.h"
34 #include "conntrack.h"
35 #include "config.h"
36 #include "str.h"
37 #include "sig.h"
38 #include "lookup.h"
39 #include "geoip.h"
40 #include "built_in.h"
41 #include "locking.h"
42 #include "pkt_buff.h"
43 #include "screen.h"
44 #include "proc.h"
45 #include "sysctl.h"
47 #ifndef NSEC_PER_SEC
48 #define NSEC_PER_SEC 1000000000L
49 #endif
51 #ifndef USEC_PER_SEC
52 #define USEC_PER_SEC 1000000L
53 #endif
55 struct flow_entry {
56 uint32_t flow_id, use, status;
57 uint8_t l3_proto, l4_proto;
58 uint32_t ip4_src_addr, ip4_dst_addr;
59 uint32_t ip6_src_addr[4], ip6_dst_addr[4];
60 uint16_t port_src, port_dst;
61 uint8_t tcp_state, tcp_flags, sctp_state, dccp_state;
62 uint64_t pkts_src, bytes_src;
63 uint64_t pkts_dst, bytes_dst;
64 uint64_t timestamp_start, timestamp_stop;
65 char country_src[128], country_dst[128];
66 char country_code_src[4], country_code_dst[4];
67 char city_src[128], city_dst[128];
68 char rev_dns_src[256], rev_dns_dst[256];
69 char procname[256];
70 struct flow_entry *next;
71 int inode;
72 unsigned int procnum;
73 bool is_visible;
74 struct nf_conntrack *ct;
75 struct timeval last_update;
76 double rate_bytes_src;
77 double rate_bytes_dst;
78 double rate_pkts_src;
79 double rate_pkts_dst;
82 struct flow_list {
83 struct flow_entry *head;
84 struct spinlock lock;
87 enum flow_direction {
88 FLOW_DIR_SRC,
89 FLOW_DIR_DST,
92 #ifndef ATTR_TIMESTAMP_START
93 # define ATTR_TIMESTAMP_START 63
94 #endif
95 #ifndef ATTR_TIMESTAMP_STOP
96 # define ATTR_TIMESTAMP_STOP 64
97 #endif
99 #define SCROLL_MAX 1000
101 #define INCLUDE_IPV4 (1 << 0)
102 #define INCLUDE_IPV6 (1 << 1)
103 #define INCLUDE_UDP (1 << 2)
104 #define INCLUDE_TCP (1 << 3)
105 #define INCLUDE_DCCP (1 << 4)
106 #define INCLUDE_ICMP (1 << 5)
107 #define INCLUDE_SCTP (1 << 6)
109 #define TOGGLE_FLAG(what, flag) \
110 do { \
111 if (what & flag) \
112 what &= ~flag; \
113 else \
114 what |= flag; \
115 } while (0)
117 struct sysctl_params_ctx {
118 int nfct_acct;
119 int nfct_tstamp;
122 enum rate_units {
123 RATE_BITS,
124 RATE_BYTES
127 static volatile bool do_reload_flows;
128 static volatile bool is_flow_collecting;
129 static volatile sig_atomic_t sigint = 0;
130 static int what = INCLUDE_IPV4 | INCLUDE_IPV6 | INCLUDE_TCP;
131 static struct flow_list flow_list;
132 static struct sysctl_params_ctx sysctl = { -1, -1 };
134 static unsigned int cols, rows;
136 static unsigned int interval = 1;
137 static bool show_src = false;
138 static bool resolve_dns = true;
139 static bool resolve_geoip = true;
140 static enum rate_units rate_type = RATE_BYTES;
141 static bool show_active_only = false;
143 enum tbl_flow_col {
144 TBL_FLOW_PROCESS,
145 TBL_FLOW_PID,
146 TBL_FLOW_PROTO,
147 TBL_FLOW_STATE,
148 TBL_FLOW_TIME,
149 TBL_FLOW_ADDRESS,
150 TBL_FLOW_PORT,
151 TBL_FLOW_GEO,
152 TBL_FLOW_BYTES,
153 TBL_FLOW_RATE,
156 static struct ui_table flows_tbl;
158 static const char *short_options = "vhTUsDIS46ut:nGb";
159 static const struct option long_options[] = {
160 {"ipv4", no_argument, NULL, '4'},
161 {"ipv6", no_argument, NULL, '6'},
162 {"tcp", no_argument, NULL, 'T'},
163 {"udp", no_argument, NULL, 'U'},
164 {"dccp", no_argument, NULL, 'D'},
165 {"icmp", no_argument, NULL, 'I'},
166 {"sctp", no_argument, NULL, 'S'},
167 {"no-dns", no_argument, NULL, 'n'},
168 {"no-geoip", no_argument, NULL, 'G'},
169 {"show-src", no_argument, NULL, 's'},
170 {"bits", no_argument, NULL, 'b'},
171 {"update", no_argument, NULL, 'u'},
172 {"interval", required_argument, NULL, 't'},
173 {"version", no_argument, NULL, 'v'},
174 {"help", no_argument, NULL, 'h'},
175 {NULL, 0, NULL, 0}
178 static const char *copyright = "Please report bugs to <netsniff-ng@googlegroups.com>\n"
179 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>\n"
180 "Copyright (C) 2011-2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>\n"
181 "Swiss federal institute of technology (ETH Zurich)\n"
182 "License: GNU GPL version 2.0\n"
183 "This is free software: you are free to change and redistribute it.\n"
184 "There is NO WARRANTY, to the extent permitted by law.";
186 static const char *const l4proto2str[IPPROTO_MAX] = {
187 [IPPROTO_TCP] = "tcp",
188 [IPPROTO_UDP] = "udp",
189 [IPPROTO_UDPLITE] = "udplite",
190 [IPPROTO_ICMP] = "icmp",
191 [IPPROTO_ICMPV6] = "icmpv6",
192 [IPPROTO_SCTP] = "sctp",
193 [IPPROTO_GRE] = "gre",
194 [IPPROTO_DCCP] = "dccp",
195 [IPPROTO_IGMP] = "igmp",
196 [IPPROTO_IPIP] = "ipip",
197 [IPPROTO_EGP] = "egp",
198 [IPPROTO_PUP] = "pup",
199 [IPPROTO_IDP] = "idp",
200 [IPPROTO_RSVP] = "rsvp",
201 [IPPROTO_IPV6] = "ip6tun",
202 [IPPROTO_ESP] = "esp",
203 [IPPROTO_AH] = "ah",
204 [IPPROTO_PIM] = "pim",
205 [IPPROTO_COMP] = "comp",
208 static const char *const tcp_state2str[TCP_CONNTRACK_MAX] = {
209 [TCP_CONNTRACK_NONE] = "NONE",
210 [TCP_CONNTRACK_SYN_SENT] = "SYN-SENT",
211 [TCP_CONNTRACK_SYN_RECV] = "SYN-RECV",
212 [TCP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
213 [TCP_CONNTRACK_FIN_WAIT] = "FIN-WAIT",
214 [TCP_CONNTRACK_CLOSE_WAIT] = "CLOSE-WAIT",
215 [TCP_CONNTRACK_LAST_ACK] = "LAST-ACK",
216 [TCP_CONNTRACK_TIME_WAIT] = "TIME-WAIT",
217 [TCP_CONNTRACK_CLOSE] = "CLOSE",
218 [TCP_CONNTRACK_SYN_SENT2] = "SYN-SENT2",
221 static const char *const dccp_state2str[DCCP_CONNTRACK_MAX] = {
222 [DCCP_CONNTRACK_NONE] = "NONE",
223 [DCCP_CONNTRACK_REQUEST] = "REQUEST",
224 [DCCP_CONNTRACK_RESPOND] = "RESPOND",
225 [DCCP_CONNTRACK_PARTOPEN] = "PARTOPEN",
226 [DCCP_CONNTRACK_OPEN] = "OPEN",
227 [DCCP_CONNTRACK_CLOSEREQ] = "CLOSE-REQ",
228 [DCCP_CONNTRACK_CLOSING] = "CLOSING",
229 [DCCP_CONNTRACK_TIMEWAIT] = "TIME-WAIT",
230 [DCCP_CONNTRACK_IGNORE] = "IGNORE",
231 [DCCP_CONNTRACK_INVALID] = "INVALID",
234 static const char *const sctp_state2str[SCTP_CONNTRACK_MAX] = {
235 [SCTP_CONNTRACK_NONE] = "NONE",
236 [SCTP_CONNTRACK_CLOSED] = "CLOSED",
237 [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE-WAIT",
238 [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE-ECHO",
239 [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
240 [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTD-SENT",
241 [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTD-RCVD",
242 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTD-ACK",
245 static const struct nfct_filter_ipv4 filter_ipv4 = {
246 .addr = __constant_htonl(INADDR_LOOPBACK),
247 .mask = 0xffffffff,
250 static const struct nfct_filter_ipv6 filter_ipv6 = {
251 .addr = { 0x0, 0x0, 0x0, 0x1 },
252 .mask = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
255 static int64_t time_after_us(struct timeval *tv)
257 struct timeval now;
259 bug_on(gettimeofday(&now, NULL));
261 now.tv_sec -= tv->tv_sec;
262 now.tv_usec -= tv->tv_usec;
264 return now.tv_sec * USEC_PER_SEC + now.tv_usec;
267 static void signal_handler(int number)
269 switch (number) {
270 case SIGINT:
271 case SIGQUIT:
272 case SIGTERM:
273 sigint = 1;
274 break;
275 case SIGHUP:
276 default:
277 break;
281 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct);
282 static void flow_entry_get_extended(struct flow_entry *n);
284 static void help(void)
286 printf("flowtop %s, top-like netfilter TCP/UDP/SCTP/.. flow tracking\n",
287 VERSION_STRING);
288 puts("http://www.netsniff-ng.org\n\n"
289 "Usage: flowtop [options]\n"
290 "Options:\n"
291 " -4|--ipv4 Show only IPv4 flows (default)\n"
292 " -6|--ipv6 Show only IPv6 flows (default)\n"
293 " -T|--tcp Show only TCP flows (default)\n"
294 " -U|--udp Show only UDP flows\n"
295 " -D|--dccp Show only DCCP flows\n"
296 " -I|--icmp Show only ICMP/ICMPv6 flows\n"
297 " -S|--sctp Show only SCTP flows\n"
298 " -n|--no-dns Don't perform hostname lookup\n"
299 " -G|--no-geoip Don't perform GeoIP lookup\n"
300 " -s|--show-src Also show source, not only dest\n"
301 " -b|--bits Show rates in bits/s instead of bytes/s\n"
302 " -u|--update Update GeoIP databases\n"
303 " -t|--interval <time> Refresh time in seconds (default 1s)\n"
304 " -v|--version Print version and exit\n"
305 " -h|--help Print this help and exit\n\n"
306 "Examples:\n"
307 " flowtop\n"
308 " flowtop -46UTDISs\n\n"
309 "Note:\n"
310 " If netfilter is not running, you can activate it with e.g.:\n"
311 " iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT\n"
312 " iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT\n");
313 puts(copyright);
314 die();
317 static void version(void)
319 printf("flowtop %s, Git id: %s\n", VERSION_LONG, GITVERSION);
320 puts("top-like netfilter TCP/UDP/SCTP/.. flow tracking\n"
321 "http://www.netsniff-ng.org\n");
322 puts(copyright);
323 die();
326 static void flow_entry_update_time(struct flow_entry *n)
328 bug_on(gettimeofday(&n->last_update, NULL));
331 #define CALC_RATE(fld) do { \
332 n->rate_##fld = (((fld) > n->fld) ? (((fld) - n->fld) / sec) : 0); \
333 } while (0)
335 static void flow_entry_calc_rate(struct flow_entry *n, const struct nf_conntrack *ct)
337 uint64_t bytes_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_BYTES);
338 uint64_t bytes_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_BYTES);
339 uint64_t pkts_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_PACKETS);
340 uint64_t pkts_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_PACKETS);
341 double sec = (double)time_after_us(&n->last_update) / USEC_PER_SEC;
343 if (sec < 1)
344 return;
346 CALC_RATE(bytes_src);
347 CALC_RATE(bytes_dst);
348 CALC_RATE(pkts_src);
349 CALC_RATE(pkts_dst);
352 static inline struct flow_entry *flow_entry_xalloc(void)
354 return xzmalloc(sizeof(struct flow_entry));
357 static inline void flow_entry_xfree(struct flow_entry *n)
359 if (n->ct)
360 nfct_destroy(n->ct);
362 xfree(n);
365 static inline void flow_list_init(struct flow_list *fl)
367 fl->head = NULL;
368 spinlock_init(&fl->lock);
371 static inline bool nfct_is_dns(const struct nf_conntrack *ct)
373 uint16_t port_src = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
374 uint16_t port_dst = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
376 return ntohs(port_src) == 53 || ntohs(port_dst) == 53;
379 static void flow_list_new_entry(struct flow_list *fl, const struct nf_conntrack *ct)
381 struct flow_entry *n;
383 /* We don't want to analyze / display DNS itself, since we
384 * use it to resolve reverse dns.
386 if (nfct_is_dns(ct))
387 return;
389 n = flow_entry_xalloc();
391 n->ct = nfct_clone(ct);
393 flow_entry_update_time(n);
394 flow_entry_from_ct(n, ct);
395 flow_entry_get_extended(n);
397 rcu_assign_pointer(n->next, fl->head);
398 rcu_assign_pointer(fl->head, n);
400 n->is_visible = true;
403 static struct flow_entry *flow_list_find_id(struct flow_list *fl,
404 uint32_t id)
406 struct flow_entry *n = rcu_dereference(fl->head);
408 while (n != NULL) {
409 if (n->flow_id == id)
410 return n;
412 n = rcu_dereference(n->next);
415 return NULL;
418 static struct flow_entry *flow_list_find_prev_id(const struct flow_list *fl,
419 uint32_t id)
421 struct flow_entry *prev = rcu_dereference(fl->head), *next;
423 if (prev->flow_id == id)
424 return NULL;
426 while ((next = rcu_dereference(prev->next)) != NULL) {
427 if (next->flow_id == id)
428 return prev;
430 prev = next;
433 return NULL;
436 static void flow_list_destroy_entry(struct flow_list *fl,
437 const struct nf_conntrack *ct)
439 struct flow_entry *n1, *n2;
440 uint32_t id = nfct_get_attr_u32(ct, ATTR_ID);
442 n1 = flow_list_find_id(fl, id);
443 if (n1) {
444 n2 = flow_list_find_prev_id(fl, id);
445 if (n2) {
446 rcu_assign_pointer(n2->next, n1->next);
447 n1->next = NULL;
449 flow_entry_xfree(n1);
450 } else {
451 struct flow_entry *next = fl->head->next;
453 flow_entry_xfree(fl->head);
454 fl->head = next;
459 static void flow_list_destroy(struct flow_list *fl)
461 struct flow_entry *n;
463 synchronize_rcu();
464 spinlock_lock(&flow_list.lock);
466 while (fl->head != NULL) {
467 n = rcu_dereference(fl->head->next);
468 fl->head->next = NULL;
470 flow_entry_xfree(fl->head);
471 rcu_assign_pointer(fl->head, n);
474 spinlock_unlock(&flow_list.lock);
477 static int walk_process(unsigned int pid, struct flow_entry *n)
479 int ret;
480 DIR *dir;
481 struct dirent *ent;
482 char path[1024];
484 if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
485 panic("giant process name! %u\n", pid);
487 dir = opendir(path);
488 if (!dir)
489 return 0;
491 while ((ent = readdir(dir))) {
492 struct stat statbuf;
494 if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
495 pid, ent->d_name) < 0)
496 continue;
498 if (stat(path, &statbuf) < 0)
499 continue;
501 if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == statbuf.st_ino) {
502 char cmdline[256];
504 ret = proc_get_cmdline(pid, cmdline, sizeof(cmdline));
505 if (ret < 0)
506 panic("Failed to get process cmdline: %s\n", strerror(errno));
508 if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0)
509 n->procname[0] = '\0';
510 n->procnum = pid;
511 closedir(dir);
512 return 1;
516 closedir(dir);
517 return 0;
520 static void walk_processes(struct flow_entry *n)
522 int ret;
523 DIR *dir;
524 struct dirent *ent;
526 /* n->inode must be set */
527 if (n->inode <= 0) {
528 n->procname[0] = '\0';
529 return;
532 dir = opendir("/proc");
533 if (!dir)
534 panic("Cannot open /proc: %s\n", strerror(errno));
536 while ((ent = readdir(dir))) {
537 const char *name = ent->d_name;
538 char *end;
539 unsigned int pid = strtoul(name, &end, 10);
541 /* not a PID */
542 if (pid == 0 && end == name)
543 continue;
545 ret = walk_process(pid, n);
546 if (ret > 0)
547 break;
550 closedir(dir);
553 static int get_port_inode(uint16_t port, int proto, bool is_ip6)
555 int ret = -ENOENT;
556 char path[128], buff[1024];
557 FILE *proc;
559 memset(path, 0, sizeof(path));
560 snprintf(path, sizeof(path), "/proc/net/%s%s",
561 l4proto2str[proto], is_ip6 ? "6" : "");
563 proc = fopen(path, "r");
564 if (!proc)
565 return -EIO;
567 memset(buff, 0, sizeof(buff));
569 while (fgets(buff, sizeof(buff), proc) != NULL) {
570 int inode = 0;
571 unsigned int lport = 0;
573 buff[sizeof(buff) - 1] = 0;
574 if (sscanf(buff, "%*u: %*X:%X %*X:%*X %*X %*X:%*X %*X:%*X "
575 "%*X %*u %*u %u", &lport, &inode) == 2) {
576 if ((uint16_t) lport == port) {
577 ret = inode;
578 break;
582 memset(buff, 0, sizeof(buff));
585 fclose(proc);
586 return ret;
589 #define CP_NFCT(elem, attr, x) \
590 do { n->elem = nfct_get_attr_u##x(ct,(attr)); } while (0)
591 #define CP_NFCT_BUFF(elem, attr) do { \
592 const uint8_t *buff = nfct_get_attr(ct,(attr)); \
593 if (buff != NULL) \
594 memcpy(n->elem, buff, sizeof(n->elem)); \
595 } while (0)
597 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct)
599 CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
600 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
602 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
603 CP_NFCT(ip4_dst_addr, ATTR_ORIG_IPV4_DST, 32);
605 CP_NFCT(port_src, ATTR_ORIG_PORT_SRC, 16);
606 CP_NFCT(port_dst, ATTR_ORIG_PORT_DST, 16);
608 CP_NFCT(status, ATTR_STATUS, 32);
610 CP_NFCT(tcp_state, ATTR_TCP_STATE, 8);
611 CP_NFCT(tcp_flags, ATTR_TCP_FLAGS_ORIG, 8);
612 CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
613 CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
615 CP_NFCT(pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
616 CP_NFCT(bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
618 CP_NFCT(pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
619 CP_NFCT(bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
621 CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
622 CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
624 CP_NFCT(flow_id, ATTR_ID, 32);
625 CP_NFCT(use, ATTR_USE, 32);
627 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
628 CP_NFCT_BUFF(ip6_dst_addr, ATTR_ORIG_IPV6_DST);
630 n->port_src = ntohs(n->port_src);
631 n->port_dst = ntohs(n->port_dst);
633 n->ip4_src_addr = ntohl(n->ip4_src_addr);
634 n->ip4_dst_addr = ntohl(n->ip4_dst_addr);
637 #define SELFLD(dir,src_member,dst_member) \
638 (((dir) == FLOW_DIR_SRC) ? n->src_member : n->dst_member)
640 static void flow_entry_get_sain4_obj(const struct flow_entry *n,
641 enum flow_direction dir,
642 struct sockaddr_in *sa)
644 memset(sa, 0, sizeof(*sa));
645 sa->sin_family = PF_INET;
646 sa->sin_addr.s_addr = htonl(SELFLD(dir, ip4_src_addr, ip4_dst_addr));
649 static void flow_entry_get_sain6_obj(const struct flow_entry *n,
650 enum flow_direction dir,
651 struct sockaddr_in6 *sa)
653 memset(sa, 0, sizeof(*sa));
654 sa->sin6_family = PF_INET6;
656 memcpy(&sa->sin6_addr, SELFLD(dir, ip6_src_addr, ip6_dst_addr),
657 sizeof(sa->sin6_addr));
660 static void
661 flow_entry_geo_city_lookup_generic(struct flow_entry *n,
662 enum flow_direction dir)
664 struct sockaddr_in sa4;
665 struct sockaddr_in6 sa6;
666 const char *city = NULL;
668 switch (n->l3_proto) {
669 default:
670 bug();
672 case AF_INET:
673 flow_entry_get_sain4_obj(n, dir, &sa4);
674 city = geoip4_city_name(&sa4);
675 break;
677 case AF_INET6:
678 flow_entry_get_sain6_obj(n, dir, &sa6);
679 city = geoip6_city_name(&sa6);
680 break;
683 build_bug_on(sizeof(n->city_src) != sizeof(n->city_dst));
685 if (city)
686 strlcpy(SELFLD(dir, city_src, city_dst), city,
687 sizeof(n->city_src));
688 else
689 SELFLD(dir, city_src, city_dst)[0] = '\0';
692 static void
693 flow_entry_geo_country_lookup_generic(struct flow_entry *n,
694 enum flow_direction dir)
696 struct sockaddr_in sa4;
697 struct sockaddr_in6 sa6;
698 const char *country = NULL;
699 const char *country_code = NULL;
701 switch (n->l3_proto) {
702 default:
703 bug();
705 case AF_INET:
706 flow_entry_get_sain4_obj(n, dir, &sa4);
707 country = geoip4_country_name(&sa4);
708 country_code = geoip4_country_code3_name(&sa4);
709 break;
711 case AF_INET6:
712 flow_entry_get_sain6_obj(n, dir, &sa6);
713 country = geoip6_country_name(&sa6);
714 country_code = geoip6_country_code3_name(&sa6);
715 break;
718 build_bug_on(sizeof(n->country_src) != sizeof(n->country_dst));
720 if (country)
721 strlcpy(SELFLD(dir, country_src, country_dst), country,
722 sizeof(n->country_src));
723 else
724 SELFLD(dir, country_src, country_dst)[0] = '\0';
726 build_bug_on(sizeof(n->country_code_src) != sizeof(n->country_code_dst));
728 if (country_code)
729 strlcpy(SELFLD(dir, country_code_src, country_code_dst),
730 country_code, sizeof(n->country_code_src));
731 else
732 SELFLD(dir, country_code_src, country_code_dst)[0] = '\0';
735 static void flow_entry_get_extended_geo(struct flow_entry *n,
736 enum flow_direction dir)
738 if (resolve_geoip) {
739 flow_entry_geo_city_lookup_generic(n, dir);
740 flow_entry_geo_country_lookup_generic(n, dir);
744 static void flow_entry_get_extended_revdns(struct flow_entry *n,
745 enum flow_direction dir)
747 size_t sa_len;
748 struct sockaddr_in sa4;
749 struct sockaddr_in6 sa6;
750 struct sockaddr *sa;
751 struct hostent *hent;
753 build_bug_on(sizeof(n->rev_dns_src) != sizeof(n->rev_dns_dst));
755 switch (n->l3_proto) {
756 default:
757 bug();
759 case AF_INET:
760 flow_entry_get_sain4_obj(n, dir, &sa4);
762 if (!resolve_dns) {
763 inet_ntop(AF_INET, &sa4.sin_addr,
764 SELFLD(dir, rev_dns_src, rev_dns_dst),
765 sizeof(n->rev_dns_src));
766 return;
769 sa = (struct sockaddr *) &sa4;
770 sa_len = sizeof(sa4);
771 hent = gethostbyaddr(&sa4.sin_addr, sizeof(sa4.sin_addr), AF_INET);
772 break;
774 case AF_INET6:
775 flow_entry_get_sain6_obj(n, dir, &sa6);
777 if (!resolve_dns) {
778 inet_ntop(AF_INET6, &sa6.sin6_addr,
779 SELFLD(dir, rev_dns_src, rev_dns_dst),
780 sizeof(n->rev_dns_src));
781 return;
784 sa = (struct sockaddr *) &sa6;
785 sa_len = sizeof(sa6);
786 hent = gethostbyaddr(&sa6.sin6_addr, sizeof(sa6.sin6_addr), AF_INET6);
787 break;
790 getnameinfo(sa, sa_len, SELFLD(dir, rev_dns_src, rev_dns_dst),
791 sizeof(n->rev_dns_src), NULL, 0, NI_NUMERICHOST);
793 if (hent)
794 strlcpy(SELFLD(dir, rev_dns_src, rev_dns_dst), hent->h_name,
795 sizeof(n->rev_dns_src));
798 static void flow_entry_get_extended(struct flow_entry *n)
800 if (n->flow_id == 0)
801 return;
803 flow_entry_get_extended_revdns(n, FLOW_DIR_SRC);
804 flow_entry_get_extended_geo(n, FLOW_DIR_SRC);
806 flow_entry_get_extended_revdns(n, FLOW_DIR_DST);
807 flow_entry_get_extended_geo(n, FLOW_DIR_DST);
809 /* Lookup application */
810 n->inode = get_port_inode(n->port_src, n->l4_proto,
811 n->l3_proto == AF_INET6);
812 if (n->inode > 0)
813 walk_processes(n);
816 static char *bandw2str(double bytes, char *buf, size_t len)
818 if (bytes <= 0) {
819 buf[0] = '\0';
820 return buf;
823 if (bytes > 1000000000.)
824 snprintf(buf, len, "%.1fGB", bytes / 1000000000.);
825 else if (bytes > 1000000.)
826 snprintf(buf, len, "%.1fMB", bytes / 1000000.);
827 else if (bytes > 1000.)
828 snprintf(buf, len, "%.1fkB", bytes / 1000.);
829 else
830 snprintf(buf, len, "%.0f", bytes);
832 return buf;
835 static char *rate2str(double rate, char *buf, size_t len)
837 const char * const unit_fmt[2][4] = {
838 { "%.1fGbit/s", "%.1fMbit/s", "%.1fkbit/s", "%.0fbit/s" },
839 { "%.1fGB/s", "%.1fMB/s", "%.1fkB/s", "%.0fB/s" }
842 if (rate <= 0) {
843 buf[0] = '\0';
844 return buf;
847 if (rate_type == RATE_BITS)
848 rate *= 8;
850 if (rate > 1000000000.)
851 snprintf(buf, len, unit_fmt[rate_type][0], rate / 1000000000.);
852 else if (rate > 1000000.)
853 snprintf(buf, len, unit_fmt[rate_type][1], rate / 1000000.);
854 else if (rate > 1000.)
855 snprintf(buf, len, unit_fmt[rate_type][2], rate / 1000.);
856 else
857 snprintf(buf, len, unit_fmt[rate_type][3], rate);
859 return buf;
862 static char *time2str(uint64_t tstamp, char *str, size_t len)
864 time_t now;
865 int v, s;
867 time(&now);
869 s = now - (tstamp ? (tstamp / NSEC_PER_SEC) : now);
870 if (s <= 0) {
871 str[0] = '\0';
872 return str;
875 v = s / (3600 * 24);
876 if (v > 0) {
877 slprintf(str, len, "%dd", v);
878 return str;
881 v = s / 3600;
882 if (v > 0) {
883 slprintf(str, len, "%dh", v);
884 return str;
887 v = s / 60;
888 if (v > 0) {
889 slprintf(str, len, "%dm", v);
890 return str;
893 slprintf(str, len, "%ds", s);
894 return str;
898 static const char *flow_state2str(const struct flow_entry *n)
900 switch (n->l4_proto) {
901 case IPPROTO_TCP:
902 return tcp_state2str[n->tcp_state];
903 case IPPROTO_SCTP:
904 return sctp_state2str[n->sctp_state];
905 case IPPROTO_DCCP:
906 return dccp_state2str[n->dccp_state];
908 case IPPROTO_UDP:
909 case IPPROTO_UDPLITE:
910 case IPPROTO_ICMP:
911 case IPPROTO_ICMPV6:
912 default:
913 return "";
917 static char *flow_port2str(const struct flow_entry *n, char *str, size_t len,
918 enum flow_direction dir)
920 const char *tmp = NULL;
921 uint16_t port = 0;
923 port = SELFLD(dir, port_src, port_dst);
924 tmp = NULL;
926 switch (n->l4_proto) {
927 case IPPROTO_TCP:
928 tmp = lookup_port_tcp(port);
929 break;
930 case IPPROTO_UDP:
931 case IPPROTO_UDPLITE:
932 tmp = lookup_port_udp(port);
933 break;
936 if (!tmp && port)
937 slprintf(str, len, "%d", port);
938 else
939 slprintf(str, len, "%s", tmp ? tmp : "");
941 return str;
944 static void print_flow_peer_info(const struct flow_entry *n, enum flow_direction dir)
946 int counters_color = COLOR(YELLOW, BLACK);
947 int src_color = COLOR(RED, BLACK);
948 int dst_color = COLOR(BLUE, BLACK);
949 int country_color = COLOR(GREEN, BLACK);
950 int addr_color = dst_color;
951 int port_color = A_BOLD;
952 char tmp[128];
954 if (show_src && dir == FLOW_DIR_SRC) {
955 country_color = src_color;
956 counters_color = src_color;
957 port_color |= src_color;
958 addr_color = src_color;
959 } else if (show_src && FLOW_DIR_DST) {
960 country_color = dst_color;
961 counters_color = dst_color;
962 port_color |= dst_color;
963 addr_color = dst_color;
966 ui_table_col_color_set(&flows_tbl, TBL_FLOW_ADDRESS, addr_color);
967 ui_table_col_color_set(&flows_tbl, TBL_FLOW_PORT, port_color);
968 ui_table_col_color_set(&flows_tbl, TBL_FLOW_GEO, country_color);
969 ui_table_col_color_set(&flows_tbl, TBL_FLOW_BYTES, counters_color);
970 ui_table_col_color_set(&flows_tbl, TBL_FLOW_RATE, counters_color);
972 /* Reverse DNS/IP */
973 ui_table_row_print(&flows_tbl, TBL_FLOW_ADDRESS,
974 SELFLD(dir, rev_dns_src, rev_dns_dst));
976 /* Application port */
977 ui_table_row_print(&flows_tbl, TBL_FLOW_PORT,
978 flow_port2str(n, tmp, sizeof(tmp), dir));
980 /* GEO */
981 ui_table_row_print(&flows_tbl, TBL_FLOW_GEO,
982 SELFLD(dir, country_code_src, country_code_dst));
984 /* Bytes */
985 ui_table_row_print(&flows_tbl, TBL_FLOW_BYTES,
986 bandw2str(SELFLD(dir, bytes_src, bytes_dst),
987 tmp, sizeof(tmp) - 1));
989 /* Rate bytes */
990 ui_table_row_print(&flows_tbl, TBL_FLOW_RATE,
991 rate2str(SELFLD(dir, rate_bytes_src, rate_bytes_dst),
992 tmp, sizeof(tmp) - 1));
995 static void draw_flow_entry(const struct flow_entry *n)
997 char tmp[128];
999 ui_table_row_add(&flows_tbl);
1001 /* Application */
1002 ui_table_row_print(&flows_tbl, TBL_FLOW_PROCESS, n->procname);
1004 /* PID */
1005 slprintf(tmp, sizeof(tmp), "%.d", n->procnum);
1006 ui_table_row_print(&flows_tbl, TBL_FLOW_PID, tmp);
1008 /* L4 protocol */
1009 ui_table_row_print(&flows_tbl, TBL_FLOW_PROTO, l4proto2str[n->l4_proto]);
1011 /* L4 protocol state */
1012 ui_table_row_print(&flows_tbl, TBL_FLOW_STATE, flow_state2str(n));
1014 /* Time */
1015 time2str(n->timestamp_start, tmp, sizeof(tmp));
1016 ui_table_row_print(&flows_tbl, TBL_FLOW_TIME, tmp);
1018 print_flow_peer_info(n, show_src ? FLOW_DIR_SRC : FLOW_DIR_DST);
1020 if (show_src) {
1021 ui_table_row_add(&flows_tbl);
1023 print_flow_peer_info(n, FLOW_DIR_DST);
1027 static inline bool presenter_flow_wrong_state(struct flow_entry *n)
1029 switch (n->l4_proto) {
1030 case IPPROTO_TCP:
1031 switch (n->tcp_state) {
1032 case TCP_CONNTRACK_SYN_SENT:
1033 case TCP_CONNTRACK_SYN_RECV:
1034 case TCP_CONNTRACK_ESTABLISHED:
1035 case TCP_CONNTRACK_FIN_WAIT:
1036 case TCP_CONNTRACK_CLOSE_WAIT:
1037 case TCP_CONNTRACK_LAST_ACK:
1038 case TCP_CONNTRACK_TIME_WAIT:
1039 case TCP_CONNTRACK_CLOSE:
1040 case TCP_CONNTRACK_SYN_SENT2:
1041 case TCP_CONNTRACK_NONE:
1042 return false;
1043 break;
1045 break;
1046 case IPPROTO_SCTP:
1047 switch (n->sctp_state) {
1048 case SCTP_CONNTRACK_NONE:
1049 case SCTP_CONNTRACK_CLOSED:
1050 case SCTP_CONNTRACK_COOKIE_WAIT:
1051 case SCTP_CONNTRACK_COOKIE_ECHOED:
1052 case SCTP_CONNTRACK_ESTABLISHED:
1053 case SCTP_CONNTRACK_SHUTDOWN_SENT:
1054 case SCTP_CONNTRACK_SHUTDOWN_RECD:
1055 case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT:
1056 return false;
1057 break;
1059 break;
1060 case IPPROTO_DCCP:
1061 switch (n->dccp_state) {
1062 case DCCP_CONNTRACK_NONE:
1063 case DCCP_CONNTRACK_REQUEST:
1064 case DCCP_CONNTRACK_RESPOND:
1065 case DCCP_CONNTRACK_PARTOPEN:
1066 case DCCP_CONNTRACK_OPEN:
1067 case DCCP_CONNTRACK_CLOSEREQ:
1068 case DCCP_CONNTRACK_CLOSING:
1069 case DCCP_CONNTRACK_TIMEWAIT:
1070 case DCCP_CONNTRACK_IGNORE:
1071 case DCCP_CONNTRACK_INVALID:
1072 return false;
1073 break;
1075 break;
1076 case IPPROTO_UDP:
1077 case IPPROTO_UDPLITE:
1078 case IPPROTO_ICMP:
1079 case IPPROTO_ICMPV6:
1080 return false;
1081 break;
1084 return true;
1087 static void draw_flows(WINDOW *screen, struct flow_list *fl,
1088 int skip_lines)
1090 int row_width = show_src ? 2 : 1;
1091 unsigned int flows = 0;
1092 unsigned int line = 4;
1093 int skip = skip_lines;
1094 struct flow_entry *n;
1096 rcu_read_lock();
1098 n = rcu_dereference(fl->head);
1099 if (!n)
1100 mvwprintw(screen, line, 2, "(No sessions! "
1101 "Is netfilter running?)");
1103 ui_table_clear(&flows_tbl);
1104 ui_table_header_print(&flows_tbl);
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(n);
1121 line += row_width;
1124 mvwprintw(screen, 1, 0, "%*s", COLS - 1, " ");
1125 mvwprintw(screen, 1, 2, "Kernel netfilter flows(%u) for ", flows);
1127 if (what & INCLUDE_IPV4)
1128 printw("IPv4,");
1129 if (what & INCLUDE_IPV6)
1130 printw("IPv6,");
1131 if (what & INCLUDE_TCP)
1132 printw("TCP,");
1133 if (what & INCLUDE_UDP)
1134 printw("UDP,");
1135 if (what & INCLUDE_SCTP)
1136 printw("SCTP,");
1137 if (what & INCLUDE_DCCP)
1138 printw("DCCP,");
1139 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1140 printw("ICMP,");
1141 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1142 printw("ICMP6,");
1143 if (show_active_only)
1144 printw("Active,");
1146 printw(" [+%d]", skip_lines);
1148 if (is_flow_collecting)
1149 printw(" [Collecting flows ...]");
1151 rcu_read_unlock();
1154 static void draw_help(void)
1156 int col = 0;
1157 int row = 1;
1158 int i;
1160 mvaddch(row, col, ACS_ULCORNER);
1161 mvaddch(rows - row - 1, col, ACS_LLCORNER);
1163 mvaddch(row, cols - 1, ACS_URCORNER);
1164 mvaddch(rows - row - 1, cols - 1, ACS_LRCORNER);
1166 for (i = 1; i < rows - row - 2; i++) {
1167 mvaddch(row + i, 0, ACS_VLINE);
1168 mvaddch(row + i, cols - 1, ACS_VLINE);
1170 for (i = 1; i < cols - col - 1; i++) {
1171 mvaddch(row, col + i, ACS_HLINE);
1172 mvaddch(rows - row - 1, col + i, ACS_HLINE);
1175 attron(A_BOLD);
1176 mvaddnstr(row, cols / 2 - 2, "| Help |", -1);
1178 attron(A_UNDERLINE);
1179 mvaddnstr(row + 2, col + 2, "Navigation", -1);
1180 attroff(A_BOLD | A_UNDERLINE);
1182 mvaddnstr(row + 4, col + 3, "Up, u, k Move up", -1);
1183 mvaddnstr(row + 5, col + 3, "Down, d, j Move down", -1);
1184 mvaddnstr(row + 6, col + 3, "? Toggle help window", -1);
1185 mvaddnstr(row + 7, col + 3, "q, Ctrl+C Quit", -1);
1187 attron(A_BOLD | A_UNDERLINE);
1188 mvaddnstr(row + 9, col + 2, "Display Settings", -1);
1189 attroff(A_BOLD | A_UNDERLINE);
1191 mvaddnstr(row + 11, col + 3, "b Toggle rate units (bits/bytes)", -1);
1192 mvaddnstr(row + 12, col + 3, "a Toggle display of active flows (rate > 0) only", -1);
1193 mvaddnstr(row + 13, col + 3, "s Toggle show source peer info", -1);
1195 mvaddnstr(row + 15, col + 3, "T Toggle display TCP flows", -1);
1196 mvaddnstr(row + 16, col + 3, "U Toggle display UDP flows", -1);
1197 mvaddnstr(row + 17, col + 3, "D Toggle display DCCP flows", -1);
1198 mvaddnstr(row + 18, col + 3, "I Toggle display ICMP flows", -1);
1199 mvaddnstr(row + 19, col + 3, "S Toggle display SCTP flows", -1);
1202 static void draw_header(WINDOW *screen)
1204 int i;
1206 attron(A_STANDOUT);
1208 for (i = 0; i < cols; i++)
1209 mvaddch(0, i, ' ');
1211 mvwprintw(screen, 0, 2, "flowtop %s", VERSION_LONG);
1212 attroff(A_STANDOUT);
1215 static void draw_footer(void)
1217 int i;
1219 attron(A_STANDOUT);
1221 for (i = 0; i < cols; i++)
1222 mvaddch(rows - 1, i, ' ');
1224 mvaddnstr(rows - 1, 1, "Press '?' for help", -1);
1225 addch(ACS_VLINE);
1226 attroff(A_STANDOUT);
1229 static void show_option_toggle(int opt)
1231 switch (opt) {
1232 case 'T':
1233 TOGGLE_FLAG(what, INCLUDE_TCP);
1234 break;
1235 case 'U':
1236 TOGGLE_FLAG(what, INCLUDE_UDP);
1237 break;
1238 case 'D':
1239 TOGGLE_FLAG(what, INCLUDE_DCCP);
1240 break;
1241 case 'I':
1242 TOGGLE_FLAG(what, INCLUDE_ICMP);
1243 break;
1244 case 'S':
1245 TOGGLE_FLAG(what, INCLUDE_SCTP);
1246 break;
1250 static void flows_table_init(struct ui_table *tbl)
1252 ui_table_init(tbl);
1254 ui_table_pos_set(tbl, 3, 0);
1255 ui_table_height_set(tbl, LINES - 3);
1257 ui_table_col_add(tbl, TBL_FLOW_PROCESS, "PROCESS", 13);
1258 ui_table_col_add(tbl, TBL_FLOW_PID, "PID", 7);
1259 ui_table_col_add(tbl, TBL_FLOW_PROTO, "PROTO", 6);
1260 ui_table_col_add(tbl, TBL_FLOW_STATE, "STATE", 11);
1261 ui_table_col_add(tbl, TBL_FLOW_TIME, "TIME", 4);
1262 ui_table_col_add(tbl, TBL_FLOW_ADDRESS, "ADDRESS", 50);
1263 ui_table_col_add(tbl, TBL_FLOW_PORT, "PORT", 8);
1264 ui_table_col_add(tbl, TBL_FLOW_GEO, "GEO", 3);
1265 ui_table_col_add(tbl, TBL_FLOW_BYTES, "BYTES", 10);
1266 ui_table_col_add(tbl, TBL_FLOW_RATE, "RATE", 10);
1268 ui_table_col_align_set(tbl, TBL_FLOW_TIME, UI_ALIGN_RIGHT);
1269 ui_table_col_align_set(tbl, TBL_FLOW_BYTES, UI_ALIGN_RIGHT);
1270 ui_table_col_align_set(tbl, TBL_FLOW_RATE, UI_ALIGN_RIGHT);
1272 ui_table_col_color_set(tbl, TBL_FLOW_PROCESS, COLOR(YELLOW, BLACK));
1273 ui_table_col_color_set(tbl, TBL_FLOW_PID, A_BOLD);
1274 ui_table_col_color_set(tbl, TBL_FLOW_STATE, COLOR(YELLOW, BLACK));
1276 ui_table_header_color_set(&flows_tbl, COLOR(BLACK, GREEN));
1279 static void presenter(void)
1281 bool show_help = false;
1282 int skip_lines = 0;
1283 WINDOW *screen;
1285 lookup_init(LT_PORTS_TCP);
1286 lookup_init(LT_PORTS_UDP);
1288 screen = screen_init(false);
1289 wclear(screen);
1291 start_color();
1292 INIT_COLOR(RED, BLACK);
1293 INIT_COLOR(BLUE, BLACK);
1294 INIT_COLOR(YELLOW, BLACK);
1295 INIT_COLOR(GREEN, BLACK);
1296 INIT_COLOR(BLACK, GREEN);
1298 flows_table_init(&flows_tbl);
1300 rcu_register_thread();
1301 while (!sigint) {
1302 int ch;
1304 curs_set(0);
1305 getmaxyx(screen, rows, cols);
1307 ch = getch();
1308 switch (ch) {
1309 case 'q':
1310 sigint = 1;
1311 break;
1312 case KEY_UP:
1313 case 'u':
1314 case 'k':
1315 skip_lines--;
1316 if (skip_lines < 0)
1317 skip_lines = 0;
1318 break;
1319 case KEY_DOWN:
1320 case 'd':
1321 case 'j':
1322 skip_lines++;
1323 if (skip_lines > SCROLL_MAX)
1324 skip_lines = SCROLL_MAX;
1325 break;
1326 case 'b':
1327 if (rate_type == RATE_BYTES)
1328 rate_type = RATE_BITS;
1329 else
1330 rate_type = RATE_BYTES;
1331 break;
1332 case 'a':
1333 show_active_only = !show_active_only;
1334 break;
1335 case 's':
1336 show_src = !show_src;
1337 break;
1338 case '?':
1339 show_help = !show_help;
1340 wclear(screen);
1341 clear();
1342 break;
1343 case 'T':
1344 case 'U':
1345 case 'D':
1346 case 'I':
1347 case 'S':
1348 show_option_toggle(ch);
1349 do_reload_flows = true;
1350 break;
1351 default:
1352 fflush(stdin);
1353 break;
1356 draw_header(screen);
1358 if (show_help)
1359 draw_help();
1360 else
1361 draw_flows(screen, &flow_list, skip_lines);
1363 draw_footer();
1365 usleep(80000);
1367 rcu_unregister_thread();
1369 ui_table_uninit(&flows_tbl);
1371 screen_end();
1372 lookup_cleanup(LT_PORTS_UDP);
1373 lookup_cleanup(LT_PORTS_TCP);
1376 static void restore_sysctl(void *obj)
1378 struct sysctl_params_ctx *sysctl_ctx = obj;
1380 if (sysctl_ctx->nfct_acct == 0)
1381 sysctl_set_int("net/netfilter/nf_conntrack_acct",
1382 sysctl_ctx->nfct_acct);
1384 if (sysctl_ctx->nfct_tstamp == 0)
1385 sysctl_set_int("net/netfilter/nf_conntrack_timestamp",
1386 sysctl_ctx->nfct_tstamp);
1389 static void on_panic_handler(void *arg)
1391 restore_sysctl(arg);
1392 screen_end();
1395 static void conntrack_acct_enable(void)
1397 /* We can still work w/o traffic accounting so just warn about error */
1398 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &sysctl.nfct_acct)) {
1399 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1400 strerror(errno));
1401 return;
1404 if (sysctl.nfct_acct == 1)
1405 return;
1407 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1408 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1409 strerror(errno));
1413 static void conntrack_tstamp_enable(void)
1415 if (sysctl_get_int("net/netfilter/nf_conntrack_timestamp", &sysctl.nfct_tstamp)) {
1416 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_timestamp: %s\n",
1417 strerror(errno));
1418 return;
1421 if (sysctl.nfct_tstamp == 1)
1422 return;
1424 if (sysctl_set_int("net/netfilter/nf_conntrack_timestamp", 1)) {
1425 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_timestamp: %s\n",
1426 strerror(errno));
1430 static void flow_entry_filter(struct flow_entry *n)
1432 if (show_active_only && !n->rate_bytes_src && !n->rate_bytes_dst)
1433 n->is_visible = false;
1434 else
1435 n->is_visible = true;
1438 static int flow_list_update_entry(struct flow_list *fl, struct nf_conntrack *ct)
1440 struct flow_entry *n;
1442 n = flow_list_find_id(&flow_list, nfct_get_attr_u32(ct, ATTR_ID));
1443 if (!n)
1444 return NFCT_CB_CONTINUE;
1446 flow_entry_calc_rate(n, ct);
1447 flow_entry_update_time(n);
1448 flow_entry_from_ct(n, ct);
1449 flow_entry_filter(n);
1451 return NFCT_CB_CONTINUE;
1454 static int flow_event_cb(enum nf_conntrack_msg_type type,
1455 struct nf_conntrack *ct, void *data __maybe_unused)
1457 if (sigint)
1458 return NFCT_CB_STOP;
1460 synchronize_rcu();
1461 spinlock_lock(&flow_list.lock);
1463 switch (type) {
1464 case NFCT_T_NEW:
1465 flow_list_new_entry(&flow_list, ct);
1466 break;
1467 case NFCT_T_UPDATE:
1468 flow_list_update_entry(&flow_list, ct);
1469 break;
1470 case NFCT_T_DESTROY:
1471 flow_list_destroy_entry(&flow_list, ct);
1472 break;
1473 default:
1474 break;
1477 spinlock_unlock(&flow_list.lock);
1479 if (sigint)
1480 return NFCT_CB_STOP;
1482 return NFCT_CB_CONTINUE;
1485 static void collector_refresh_flows(struct nfct_handle *handle)
1487 struct flow_entry *n;
1489 n = rcu_dereference(flow_list.head);
1490 for (; n; n = rcu_dereference(n->next))
1491 nfct_query(handle, NFCT_Q_GET, n->ct);
1494 static void collector_create_filter(struct nfct_handle *nfct)
1496 struct nfct_filter *filter;
1497 int ret;
1499 filter = nfct_filter_create();
1500 if (!filter)
1501 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1503 if (what & INCLUDE_UDP) {
1504 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1505 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1507 if (what & INCLUDE_TCP)
1508 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1509 if (what & INCLUDE_DCCP)
1510 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1511 if (what & INCLUDE_SCTP)
1512 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1513 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1514 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1515 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1516 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1517 if (what & INCLUDE_IPV4) {
1518 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1519 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1521 if (what & INCLUDE_IPV6) {
1522 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1523 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1526 ret = nfct_filter_attach(nfct_fd(nfct), filter);
1527 if (ret < 0)
1528 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1530 nfct_filter_destroy(filter);
1533 /* This hand-crafted filter looks ugly but it allows to do not
1534 * flush nfct connections & filter them by user specified filter.
1535 * May be it is better to replace this one by nfct_cmp. */
1536 static int flow_dump_cb(enum nf_conntrack_msg_type type,
1537 struct nf_conntrack *ct, void *data __maybe_unused)
1539 struct flow_entry fl;
1540 struct flow_entry *n = &fl;
1542 if (sigint)
1543 return NFCT_CB_STOP;
1545 synchronize_rcu();
1546 spinlock_lock(&flow_list.lock);
1548 if (!(what & ~(INCLUDE_IPV4 | INCLUDE_IPV6)))
1549 goto check_addr;
1551 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
1553 if (what & INCLUDE_UDP) {
1554 if (n->l4_proto == IPPROTO_UDP)
1555 goto check_addr;
1557 if (n->l4_proto == IPPROTO_UDPLITE)
1558 goto check_addr;
1561 if ((what & INCLUDE_TCP) && n->l4_proto == IPPROTO_TCP)
1562 goto check_addr;
1564 if ((what & INCLUDE_DCCP) && n->l4_proto == IPPROTO_DCCP)
1565 goto check_addr;
1567 if ((what & INCLUDE_SCTP) && n->l4_proto == IPPROTO_SCTP)
1568 goto check_addr;
1570 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV4) &&
1571 n->l4_proto == IPPROTO_ICMP) {
1572 goto check_addr;
1575 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV6) &&
1576 n->l4_proto == IPPROTO_ICMPV6) {
1577 goto check_addr;
1580 goto skip_flow;
1582 check_addr:
1583 /* filter loopback addresses */
1584 if (what & INCLUDE_IPV4) {
1585 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
1587 if (n->ip4_src_addr == filter_ipv4.addr)
1588 goto skip_flow;
1590 if (what & INCLUDE_IPV6) {
1591 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
1593 if (n->ip6_src_addr[0] == 0x0 &&
1594 n->ip6_src_addr[1] == 0x0 &&
1595 n->ip6_src_addr[2] == 0x0 &&
1596 n->ip6_src_addr[3] == 0x1)
1597 goto skip_flow;
1600 flow_list_new_entry(&flow_list, ct);
1602 skip_flow:
1603 spinlock_unlock(&flow_list.lock);
1604 return NFCT_CB_CONTINUE;
1607 static void collector_dump_flows(void)
1609 struct nfct_handle *nfct = nfct_open(CONNTRACK, 0);
1611 if (!nfct)
1612 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1614 nfct_callback_register(nfct, NFCT_T_ALL, flow_dump_cb, NULL);
1616 is_flow_collecting = true;
1617 if (what & INCLUDE_IPV4) {
1618 int family = AF_INET;
1619 nfct_query(nfct, NFCT_Q_DUMP, &family);
1621 if (what & INCLUDE_IPV6) {
1622 int family = AF_INET6;
1623 nfct_query(nfct, NFCT_Q_DUMP, &family);
1625 is_flow_collecting = false;
1627 nfct_close(nfct);
1630 static void *collector(void *null __maybe_unused)
1632 struct nfct_handle *ct_event;
1633 struct pollfd poll_fd[1];
1635 flow_list_init(&flow_list);
1637 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1638 NF_NETLINK_CONNTRACK_UPDATE |
1639 NF_NETLINK_CONNTRACK_DESTROY);
1640 if (!ct_event)
1641 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1643 collector_create_filter(ct_event);
1645 nfct_callback_register(ct_event, NFCT_T_ALL, flow_event_cb, NULL);
1647 poll_fd[0].fd = nfct_fd(ct_event);
1648 poll_fd[0].events = POLLIN;
1650 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1651 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1652 strerror(errno));
1654 rcu_register_thread();
1656 collector_dump_flows();
1658 while (!sigint) {
1659 int status;
1661 if (!do_reload_flows) {
1662 usleep(USEC_PER_SEC * interval);
1663 } else {
1664 do_reload_flows = false;
1666 flow_list_destroy(&flow_list);
1668 collector_create_filter(ct_event);
1669 collector_dump_flows();
1672 collector_refresh_flows(ct_event);
1674 status = poll(poll_fd, 1, 0);
1675 if (status < 0) {
1676 if (errno == EAGAIN || errno == EINTR)
1677 continue;
1679 panic("Error while polling: %s\n", strerror(errno));
1680 } else if (status == 0) {
1681 continue;
1684 if (poll_fd[0].revents & POLLIN)
1685 nfct_catch(ct_event);
1688 rcu_unregister_thread();
1690 flow_list_destroy(&flow_list);
1691 spinlock_destroy(&flow_list.lock);
1693 nfct_close(ct_event);
1695 pthread_exit(NULL);
1698 int main(int argc, char **argv)
1700 pthread_t tid;
1701 int ret, c, opt_index, what_cmd = 0;
1703 setfsuid(getuid());
1704 setfsgid(getgid());
1706 while ((c = getopt_long(argc, argv, short_options, long_options,
1707 &opt_index)) != EOF) {
1708 switch (c) {
1709 case '4':
1710 what_cmd |= INCLUDE_IPV4;
1711 break;
1712 case '6':
1713 what_cmd |= INCLUDE_IPV6;
1714 break;
1715 case 'T':
1716 what_cmd |= INCLUDE_TCP;
1717 break;
1718 case 'U':
1719 what_cmd |= INCLUDE_UDP;
1720 break;
1721 case 'D':
1722 what_cmd |= INCLUDE_DCCP;
1723 break;
1724 case 'I':
1725 what_cmd |= INCLUDE_ICMP;
1726 break;
1727 case 'S':
1728 what_cmd |= INCLUDE_SCTP;
1729 break;
1730 case 's':
1731 show_src = true;
1732 break;
1733 case 'b':
1734 rate_type = RATE_BITS;
1735 break;
1736 case 'u':
1737 update_geoip();
1738 die();
1739 break;
1740 case 't':
1741 interval = strtoul(optarg, NULL, 10);
1742 break;
1743 case 'n':
1744 resolve_dns = false;
1745 break;
1746 case 'G':
1747 resolve_geoip = false;
1748 break;
1749 case 'h':
1750 help();
1751 break;
1752 case 'v':
1753 version();
1754 break;
1755 default:
1756 break;
1760 if (what_cmd > 0) {
1761 what = what_cmd;
1763 if (!(what & (INCLUDE_IPV4 | INCLUDE_IPV6)))
1764 what |= INCLUDE_IPV4 | INCLUDE_IPV6;
1767 rcu_init();
1769 register_signal(SIGINT, signal_handler);
1770 register_signal(SIGQUIT, signal_handler);
1771 register_signal(SIGTERM, signal_handler);
1772 register_signal(SIGHUP, signal_handler);
1774 panic_handler_add(on_panic_handler, &sysctl);
1776 conntrack_acct_enable();
1777 conntrack_tstamp_enable();
1779 if (resolve_geoip)
1780 init_geoip(1);
1782 ret = pthread_create(&tid, NULL, collector, NULL);
1783 if (ret < 0)
1784 panic("Cannot create phthread!\n");
1786 presenter();
1788 if (resolve_geoip)
1789 destroy_geoip();
1791 restore_sysctl(&sysctl);
1793 return 0;