netsniff-ng: remove unnecessary zeroing of packet counters in init_ctx()
[netsniff-ng.git] / flowtop.c
blob1caae9e5d40a6805bd6fa7e19f3521c1ffb73a40
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 <sys/time.h>
21 #include <sys/fsuid.h>
22 #include <libgen.h>
23 #include <inttypes.h>
24 #include <poll.h>
25 #include <fcntl.h>
26 #include <arpa/inet.h>
28 #include <urcu.h>
29 #include <urcu/list.h>
30 #include <urcu/rculist.h>
32 #include "ui.h"
33 #include "die.h"
34 #include "xmalloc.h"
35 #include "conntrack.h"
36 #include "config.h"
37 #include "str.h"
38 #include "sig.h"
39 #include "lookup.h"
40 #include "geoip.h"
41 #include "built_in.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 proc_entry {
56 struct cds_list_head entry;
57 struct cds_list_head flows;
58 struct rcu_head rcu;
60 struct timeval last_update;
61 unsigned int pid;
62 char name[256];
63 uint64_t pkts_src, bytes_src;
64 uint64_t pkts_dst, bytes_dst;
65 double rate_bytes_src;
66 double rate_bytes_dst;
67 double rate_pkts_src;
68 double rate_pkts_dst;
69 int flows_count;
72 struct flow_entry {
73 struct cds_list_head proc_head;
74 struct cds_list_head entry;
75 struct rcu_head rcu;
77 uint32_t flow_id, use, status;
78 uint8_t l3_proto, l4_proto;
79 uint32_t ip4_src_addr, ip4_dst_addr;
80 uint32_t ip6_src_addr[4], ip6_dst_addr[4];
81 uint16_t port_src, port_dst;
82 uint8_t tcp_state, tcp_flags, sctp_state, dccp_state;
83 uint64_t pkts_src, bytes_src;
84 uint64_t pkts_dst, bytes_dst;
85 uint64_t timestamp_start, timestamp_stop;
86 char country_src[128], country_dst[128];
87 char country_code_src[4], country_code_dst[4];
88 char city_src[128], city_dst[128];
89 char rev_dns_src[256], rev_dns_dst[256];
90 struct proc_entry *proc;
91 int inode;
92 bool is_visible;
93 struct nf_conntrack *ct;
94 struct timeval last_update;
95 double rate_bytes_src;
96 double rate_bytes_dst;
97 double rate_pkts_src;
98 double rate_pkts_dst;
101 struct flow_list {
102 struct cds_list_head head;
105 struct proc_list {
106 struct cds_list_head head;
109 enum flow_direction {
110 FLOW_DIR_SRC,
111 FLOW_DIR_DST,
114 #ifndef ATTR_TIMESTAMP_START
115 # define ATTR_TIMESTAMP_START 63
116 #endif
117 #ifndef ATTR_TIMESTAMP_STOP
118 # define ATTR_TIMESTAMP_STOP 64
119 #endif
121 #define SCROLL_MAX 1000
123 #define INCLUDE_IPV4 (1 << 0)
124 #define INCLUDE_IPV6 (1 << 1)
125 #define INCLUDE_UDP (1 << 2)
126 #define INCLUDE_TCP (1 << 3)
127 #define INCLUDE_DCCP (1 << 4)
128 #define INCLUDE_ICMP (1 << 5)
129 #define INCLUDE_SCTP (1 << 6)
131 #define TOGGLE_FLAG(what, flag) \
132 do { \
133 if (what & flag) \
134 what &= ~flag; \
135 else \
136 what |= flag; \
137 } while (0)
139 struct sysctl_params_ctx {
140 int nfct_acct;
141 int nfct_tstamp;
144 enum rate_units {
145 RATE_BITS,
146 RATE_BYTES
149 static volatile bool do_reload_flows;
150 static volatile bool is_flow_collecting;
151 static volatile sig_atomic_t sigint = 0;
152 static int what = INCLUDE_IPV4 | INCLUDE_IPV6 | INCLUDE_TCP;
153 static struct proc_list proc_list;
154 static struct flow_list flow_list;
155 static struct sysctl_params_ctx sysctl = { -1, -1 };
157 static unsigned int cols, rows;
158 static WINDOW *screen;
159 static int skip_lines;
161 static unsigned int interval = 1;
162 static bool show_src = false;
163 static bool resolve_dns = true;
164 static bool resolve_geoip = true;
165 static enum rate_units rate_type = RATE_BYTES;
166 static bool show_active_only = false;
168 enum tbl_flow_col {
169 TBL_FLOW_PROCESS,
170 TBL_FLOW_PID,
171 TBL_FLOW_PROTO,
172 TBL_FLOW_STATE,
173 TBL_FLOW_TIME,
174 TBL_FLOW_ADDRESS,
175 TBL_FLOW_PORT,
176 TBL_FLOW_GEO,
177 TBL_FLOW_BYTES,
178 TBL_FLOW_RATE,
181 enum tbl_proc_col {
182 TBL_PROC_NAME,
183 TBL_PROC_PID,
184 TBL_PROC_FLOWS,
185 TBL_PROC_BYTES_SRC,
186 TBL_PROC_RATE_SRC,
187 TBL_PROC_BYTES_DST,
188 TBL_PROC_RATE_DST,
191 static struct ui_table flows_tbl;
192 static struct ui_table procs_tbl;
194 enum tab_entry {
195 TAB_FLOWS,
196 TAB_PROCS,
199 static const char *short_options = "vhTUsDIS46ut:nGb";
200 static const struct option long_options[] = {
201 {"ipv4", no_argument, NULL, '4'},
202 {"ipv6", no_argument, NULL, '6'},
203 {"tcp", no_argument, NULL, 'T'},
204 {"udp", no_argument, NULL, 'U'},
205 {"dccp", no_argument, NULL, 'D'},
206 {"icmp", no_argument, NULL, 'I'},
207 {"sctp", no_argument, NULL, 'S'},
208 {"no-dns", no_argument, NULL, 'n'},
209 {"no-geoip", no_argument, NULL, 'G'},
210 {"show-src", no_argument, NULL, 's'},
211 {"bits", no_argument, NULL, 'b'},
212 {"update", no_argument, NULL, 'u'},
213 {"interval", required_argument, NULL, 't'},
214 {"version", no_argument, NULL, 'v'},
215 {"help", no_argument, NULL, 'h'},
216 {NULL, 0, NULL, 0}
219 static const char *copyright = "Please report bugs to <netsniff-ng@googlegroups.com>\n"
220 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>\n"
221 "Copyright (C) 2011-2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>\n"
222 "Swiss federal institute of technology (ETH Zurich)\n"
223 "License: GNU GPL version 2.0\n"
224 "This is free software: you are free to change and redistribute it.\n"
225 "There is NO WARRANTY, to the extent permitted by law.";
227 static const char *const l4proto2str[IPPROTO_MAX] = {
228 [IPPROTO_TCP] = "tcp",
229 [IPPROTO_UDP] = "udp",
230 [IPPROTO_UDPLITE] = "udplite",
231 [IPPROTO_ICMP] = "icmp",
232 [IPPROTO_ICMPV6] = "icmpv6",
233 [IPPROTO_SCTP] = "sctp",
234 [IPPROTO_GRE] = "gre",
235 [IPPROTO_DCCP] = "dccp",
236 [IPPROTO_IGMP] = "igmp",
237 [IPPROTO_IPIP] = "ipip",
238 [IPPROTO_EGP] = "egp",
239 [IPPROTO_PUP] = "pup",
240 [IPPROTO_IDP] = "idp",
241 [IPPROTO_RSVP] = "rsvp",
242 [IPPROTO_IPV6] = "ip6tun",
243 [IPPROTO_ESP] = "esp",
244 [IPPROTO_AH] = "ah",
245 [IPPROTO_PIM] = "pim",
246 [IPPROTO_COMP] = "comp",
249 static const char *const tcp_state2str[TCP_CONNTRACK_MAX] = {
250 [TCP_CONNTRACK_NONE] = "NONE",
251 [TCP_CONNTRACK_SYN_SENT] = "SYN-SENT",
252 [TCP_CONNTRACK_SYN_RECV] = "SYN-RECV",
253 [TCP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
254 [TCP_CONNTRACK_FIN_WAIT] = "FIN-WAIT",
255 [TCP_CONNTRACK_CLOSE_WAIT] = "CLOSE-WAIT",
256 [TCP_CONNTRACK_LAST_ACK] = "LAST-ACK",
257 [TCP_CONNTRACK_TIME_WAIT] = "TIME-WAIT",
258 [TCP_CONNTRACK_CLOSE] = "CLOSE",
259 [TCP_CONNTRACK_SYN_SENT2] = "SYN-SENT2",
262 static const char *const dccp_state2str[DCCP_CONNTRACK_MAX] = {
263 [DCCP_CONNTRACK_NONE] = "NONE",
264 [DCCP_CONNTRACK_REQUEST] = "REQUEST",
265 [DCCP_CONNTRACK_RESPOND] = "RESPOND",
266 [DCCP_CONNTRACK_PARTOPEN] = "PARTOPEN",
267 [DCCP_CONNTRACK_OPEN] = "OPEN",
268 [DCCP_CONNTRACK_CLOSEREQ] = "CLOSE-REQ",
269 [DCCP_CONNTRACK_CLOSING] = "CLOSING",
270 [DCCP_CONNTRACK_TIMEWAIT] = "TIME-WAIT",
271 [DCCP_CONNTRACK_IGNORE] = "IGNORE",
272 [DCCP_CONNTRACK_INVALID] = "INVALID",
275 static const char *const sctp_state2str[SCTP_CONNTRACK_MAX] = {
276 [SCTP_CONNTRACK_NONE] = "NONE",
277 [SCTP_CONNTRACK_CLOSED] = "CLOSED",
278 [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE-WAIT",
279 [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE-ECHO",
280 [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
281 [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTD-SENT",
282 [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTD-RCVD",
283 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTD-ACK",
286 static const struct nfct_filter_ipv4 filter_ipv4 = {
287 .addr = __constant_htonl(INADDR_LOOPBACK),
288 .mask = 0xffffffff,
291 static const struct nfct_filter_ipv6 filter_ipv6 = {
292 .addr = { 0x0, 0x0, 0x0, 0x1 },
293 .mask = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
296 static int64_t time_after_us(struct timeval *tv)
298 struct timeval now;
300 bug_on(gettimeofday(&now, NULL));
302 now.tv_sec -= tv->tv_sec;
303 now.tv_usec -= tv->tv_usec;
305 return now.tv_sec * USEC_PER_SEC + now.tv_usec;
308 static void signal_handler(int number)
310 switch (number) {
311 case SIGINT:
312 case SIGQUIT:
313 case SIGTERM:
314 sigint = 1;
315 break;
316 case SIGHUP:
317 default:
318 break;
322 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct);
323 static void flow_entry_get_extended(struct flow_entry *n);
325 static void help(void)
327 printf("flowtop %s, top-like netfilter TCP/UDP/SCTP/.. flow tracking\n",
328 VERSION_STRING);
329 puts("http://www.netsniff-ng.org\n\n"
330 "Usage: flowtop [options]\n"
331 "Options:\n"
332 " -4|--ipv4 Show only IPv4 flows (default)\n"
333 " -6|--ipv6 Show only IPv6 flows (default)\n"
334 " -T|--tcp Show only TCP flows (default)\n"
335 " -U|--udp Show only UDP flows\n"
336 " -D|--dccp Show only DCCP flows\n"
337 " -I|--icmp Show only ICMP/ICMPv6 flows\n"
338 " -S|--sctp Show only SCTP flows\n"
339 " -n|--no-dns Don't perform hostname lookup\n"
340 " -G|--no-geoip Don't perform GeoIP lookup\n"
341 " -s|--show-src Also show source, not only dest\n"
342 " -b|--bits Show rates in bits/s instead of bytes/s\n"
343 " -u|--update Update GeoIP databases\n"
344 " -t|--interval <time> Refresh time in seconds (default 1s)\n"
345 " -v|--version Print version and exit\n"
346 " -h|--help Print this help and exit\n\n"
347 "Examples:\n"
348 " flowtop\n"
349 " flowtop -46UTDISs\n\n"
350 "Note:\n"
351 " If netfilter is not running, you can activate it with e.g.:\n"
352 " iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT\n"
353 " iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT\n");
354 puts(copyright);
355 die();
358 static void version(void)
360 printf("flowtop %s, Git id: %s\n", VERSION_LONG, GITVERSION);
361 puts("top-like netfilter TCP/UDP/SCTP/.. flow tracking\n"
362 "http://www.netsniff-ng.org\n");
363 puts(copyright);
364 die();
367 static void flow_entry_update_time(struct flow_entry *n)
369 bug_on(gettimeofday(&n->last_update, NULL));
372 #define CALC_RATE(fld) do { \
373 n->rate_##fld = (((fld) > n->fld) ? (((fld) - n->fld) / sec) : 0); \
374 } while (0)
376 static void flow_entry_calc_rate(struct flow_entry *n, const struct nf_conntrack *ct)
378 uint64_t bytes_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_BYTES);
379 uint64_t bytes_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_BYTES);
380 uint64_t pkts_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_PACKETS);
381 uint64_t pkts_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_PACKETS);
382 double sec = (double)time_after_us(&n->last_update) / USEC_PER_SEC;
384 if (sec < 1)
385 return;
387 CALC_RATE(bytes_src);
388 CALC_RATE(bytes_dst);
389 CALC_RATE(pkts_src);
390 CALC_RATE(pkts_dst);
393 static inline struct flow_entry *flow_entry_xalloc(void)
395 return xzmalloc(sizeof(struct flow_entry));
398 static inline void flow_entry_xfree(struct flow_entry *n)
400 if (n->ct)
401 nfct_destroy(n->ct);
403 xfree(n);
406 static void flow_entry_xfree_rcu(struct rcu_head *head)
408 struct flow_entry *n = container_of(head, struct flow_entry, rcu);
410 flow_entry_xfree(n);
413 static inline void flow_list_init(struct flow_list *fl)
415 CDS_INIT_LIST_HEAD(&fl->head);
418 static inline bool nfct_is_dns(const struct nf_conntrack *ct)
420 uint16_t port_src = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
421 uint16_t port_dst = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
423 return ntohs(port_src) == 53 || ntohs(port_dst) == 53;
426 static int flow_list_new_entry(struct flow_list *fl, struct nf_conntrack *ct)
428 struct flow_entry *n;
430 /* We don't want to analyze / display DNS itself, since we
431 * use it to resolve reverse dns.
433 if (nfct_is_dns(ct))
434 return NFCT_CB_CONTINUE;
436 n = flow_entry_xalloc();
438 n->ct = ct;
440 flow_entry_update_time(n);
441 flow_entry_from_ct(n, ct);
442 flow_entry_get_extended(n);
444 cds_list_add_rcu(&n->entry, &fl->head);
446 n->is_visible = true;
448 return NFCT_CB_STOLEN;
451 static struct flow_entry *flow_list_find_id(struct flow_list *fl, uint32_t id)
453 struct flow_entry *n;
455 cds_list_for_each_entry_rcu(n, &fl->head, entry) {
456 if (n->flow_id == id)
457 return n;
460 return NULL;
463 static int flow_list_del_entry(struct flow_list *fl, const struct nf_conntrack *ct)
465 struct flow_entry *n;
467 n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
468 if (n) {
469 if (n->proc) {
470 cds_list_del(&n->proc_head);
471 n->proc->flows_count--;
474 cds_list_del_rcu(&n->entry);
475 call_rcu(&n->rcu, flow_entry_xfree_rcu);
478 return NFCT_CB_CONTINUE;
481 static void flow_list_destroy(struct flow_list *fl)
483 struct flow_entry *n, *tmp;
485 cds_list_for_each_entry_safe(n, tmp, &fl->head, entry) {
486 cds_list_del_rcu(&n->entry);
487 call_rcu(&n->rcu, flow_entry_xfree_rcu);
491 static void proc_list_init(struct proc_list *proc_list)
493 CDS_INIT_LIST_HEAD(&proc_list->head);
496 static struct proc_entry *proc_list_new_entry(unsigned int pid)
498 struct proc_entry *proc;
500 cds_list_for_each_entry(proc, &proc_list.head, entry) {
501 if (proc->pid && proc->pid == pid)
502 return proc;
505 proc = xzmalloc(sizeof(*proc));
507 bug_on(gettimeofday(&proc->last_update, NULL));
508 CDS_INIT_LIST_HEAD(&proc->flows);
509 proc->pid = pid;
511 cds_list_add_tail(&proc->entry, &proc_list.head);
513 return proc;
516 static void proc_entry_xfree_rcu(struct rcu_head *head)
518 struct proc_entry *p = container_of(head, struct proc_entry, rcu);
520 xfree(p);
523 static void proc_list_destroy(struct proc_list *pl)
525 struct proc_entry *p, *tmp;
527 cds_list_for_each_entry_safe(p, tmp, &pl->head, entry) {
528 cds_list_del_rcu(&p->entry);
529 call_rcu(&p->rcu, proc_entry_xfree_rcu);
533 static void flow_entry_find_process(struct flow_entry *n)
535 struct proc_entry *p;
536 char cmdline[512];
537 pid_t pid;
538 int ret;
540 ret = proc_find_by_inode(n->inode, cmdline, sizeof(cmdline), &pid);
541 if (ret <= 0)
542 return;
544 p = proc_list_new_entry(pid);
546 if (snprintf(p->name, sizeof(p->name), "%s", basename(cmdline)) < 0)
547 p->name[0] = '\0';
549 p->pkts_src += n->pkts_src;
550 p->pkts_dst += n->pkts_dst;
551 p->bytes_src += n->bytes_src;
552 p->bytes_dst += n->bytes_dst;
553 p->flows_count++;
555 cds_list_add(&n->proc_head, &p->flows);
556 n->proc = p;
559 static int get_port_inode(uint16_t port, int proto, bool is_ip6)
561 int ret = -ENOENT;
562 char path[128], buff[1024];
563 FILE *proc;
565 memset(path, 0, sizeof(path));
566 snprintf(path, sizeof(path), "/proc/net/%s%s",
567 l4proto2str[proto], is_ip6 ? "6" : "");
569 proc = fopen(path, "r");
570 if (!proc)
571 return -EIO;
573 memset(buff, 0, sizeof(buff));
575 while (fgets(buff, sizeof(buff), proc) != NULL) {
576 int inode = 0;
577 unsigned int lport = 0;
579 buff[sizeof(buff) - 1] = 0;
580 if (sscanf(buff, "%*u: %*X:%X %*X:%*X %*X %*X:%*X %*X:%*X "
581 "%*X %*u %*u %u", &lport, &inode) == 2) {
582 if ((uint16_t) lport == port) {
583 ret = inode;
584 break;
588 memset(buff, 0, sizeof(buff));
591 fclose(proc);
592 return ret;
595 #define CP_NFCT(elem, attr, x) \
596 do { n->elem = nfct_get_attr_u##x(ct,(attr)); } while (0)
597 #define CP_NFCT_BUFF(elem, attr) do { \
598 const uint8_t *buff = nfct_get_attr(ct,(attr)); \
599 if (buff != NULL) \
600 memcpy(n->elem, buff, sizeof(n->elem)); \
601 } while (0)
603 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct)
605 uint64_t bytes_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_BYTES);
606 uint64_t bytes_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_BYTES);
607 uint64_t pkts_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_PACKETS);
608 uint64_t pkts_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_PACKETS);
610 /* Update stats diff to the related process entry */
611 if (n->proc) {
612 n->proc->pkts_src += pkts_src - n->pkts_src;
613 n->proc->pkts_dst += pkts_dst - n->pkts_dst;
614 n->proc->bytes_src += bytes_src - n->bytes_src;
615 n->proc->bytes_dst += bytes_dst - n->bytes_dst;
618 CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
619 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
621 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
622 CP_NFCT(ip4_dst_addr, ATTR_ORIG_IPV4_DST, 32);
624 CP_NFCT(port_src, ATTR_ORIG_PORT_SRC, 16);
625 CP_NFCT(port_dst, ATTR_ORIG_PORT_DST, 16);
627 CP_NFCT(status, ATTR_STATUS, 32);
629 CP_NFCT(tcp_state, ATTR_TCP_STATE, 8);
630 CP_NFCT(tcp_flags, ATTR_TCP_FLAGS_ORIG, 8);
631 CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
632 CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
634 CP_NFCT(pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
635 CP_NFCT(bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
637 CP_NFCT(pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
638 CP_NFCT(bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
640 CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
641 CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
643 CP_NFCT(flow_id, ATTR_ID, 32);
644 CP_NFCT(use, ATTR_USE, 32);
646 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
647 CP_NFCT_BUFF(ip6_dst_addr, ATTR_ORIG_IPV6_DST);
649 n->port_src = ntohs(n->port_src);
650 n->port_dst = ntohs(n->port_dst);
652 n->ip4_src_addr = ntohl(n->ip4_src_addr);
653 n->ip4_dst_addr = ntohl(n->ip4_dst_addr);
656 #define SELFLD(dir,src_member,dst_member) \
657 (((dir) == FLOW_DIR_SRC) ? n->src_member : n->dst_member)
659 static void flow_entry_get_sain4_obj(const struct flow_entry *n,
660 enum flow_direction dir,
661 struct sockaddr_in *sa)
663 memset(sa, 0, sizeof(*sa));
664 sa->sin_family = PF_INET;
665 sa->sin_addr.s_addr = htonl(SELFLD(dir, ip4_src_addr, ip4_dst_addr));
668 static void flow_entry_get_sain6_obj(const struct flow_entry *n,
669 enum flow_direction dir,
670 struct sockaddr_in6 *sa)
672 memset(sa, 0, sizeof(*sa));
673 sa->sin6_family = PF_INET6;
675 memcpy(&sa->sin6_addr, SELFLD(dir, ip6_src_addr, ip6_dst_addr),
676 sizeof(sa->sin6_addr));
679 static void
680 flow_entry_geo_city_lookup_generic(struct flow_entry *n,
681 enum flow_direction dir)
683 struct sockaddr_in sa4;
684 struct sockaddr_in6 sa6;
685 char *city = NULL;
687 switch (n->l3_proto) {
688 default:
689 bug();
691 case AF_INET:
692 flow_entry_get_sain4_obj(n, dir, &sa4);
693 city = geoip4_city_name(&sa4);
694 break;
696 case AF_INET6:
697 flow_entry_get_sain6_obj(n, dir, &sa6);
698 city = geoip6_city_name(&sa6);
699 break;
702 build_bug_on(sizeof(n->city_src) != sizeof(n->city_dst));
704 if (city)
705 strlcpy(SELFLD(dir, city_src, city_dst), city,
706 sizeof(n->city_src));
707 else
708 SELFLD(dir, city_src, city_dst)[0] = '\0';
710 free(city);
713 static void
714 flow_entry_geo_country_lookup_generic(struct flow_entry *n,
715 enum flow_direction dir)
717 struct sockaddr_in sa4;
718 struct sockaddr_in6 sa6;
719 const char *country = NULL;
720 const char *country_code = NULL;
722 switch (n->l3_proto) {
723 default:
724 bug();
726 case AF_INET:
727 flow_entry_get_sain4_obj(n, dir, &sa4);
728 country = geoip4_country_name(&sa4);
729 country_code = geoip4_country_code3_name(&sa4);
730 break;
732 case AF_INET6:
733 flow_entry_get_sain6_obj(n, dir, &sa6);
734 country = geoip6_country_name(&sa6);
735 country_code = geoip6_country_code3_name(&sa6);
736 break;
739 build_bug_on(sizeof(n->country_src) != sizeof(n->country_dst));
741 if (country)
742 strlcpy(SELFLD(dir, country_src, country_dst), country,
743 sizeof(n->country_src));
744 else
745 SELFLD(dir, country_src, country_dst)[0] = '\0';
747 build_bug_on(sizeof(n->country_code_src) != sizeof(n->country_code_dst));
749 if (country_code)
750 strlcpy(SELFLD(dir, country_code_src, country_code_dst),
751 country_code, sizeof(n->country_code_src));
752 else
753 SELFLD(dir, country_code_src, country_code_dst)[0] = '\0';
756 static void flow_entry_get_extended_geo(struct flow_entry *n,
757 enum flow_direction dir)
759 if (resolve_geoip) {
760 flow_entry_geo_city_lookup_generic(n, dir);
761 flow_entry_geo_country_lookup_generic(n, dir);
765 static void flow_entry_get_extended_revdns(struct flow_entry *n,
766 enum flow_direction dir)
768 size_t sa_len;
769 struct sockaddr_in sa4;
770 struct sockaddr_in6 sa6;
771 struct sockaddr *sa;
772 struct hostent *hent;
774 build_bug_on(sizeof(n->rev_dns_src) != sizeof(n->rev_dns_dst));
776 switch (n->l3_proto) {
777 default:
778 bug();
780 case AF_INET:
781 flow_entry_get_sain4_obj(n, dir, &sa4);
783 if (!resolve_dns) {
784 inet_ntop(AF_INET, &sa4.sin_addr,
785 SELFLD(dir, rev_dns_src, rev_dns_dst),
786 sizeof(n->rev_dns_src));
787 return;
790 sa = (struct sockaddr *) &sa4;
791 sa_len = sizeof(sa4);
792 hent = gethostbyaddr(&sa4.sin_addr, sizeof(sa4.sin_addr), AF_INET);
793 break;
795 case AF_INET6:
796 flow_entry_get_sain6_obj(n, dir, &sa6);
798 if (!resolve_dns) {
799 inet_ntop(AF_INET6, &sa6.sin6_addr,
800 SELFLD(dir, rev_dns_src, rev_dns_dst),
801 sizeof(n->rev_dns_src));
802 return;
805 sa = (struct sockaddr *) &sa6;
806 sa_len = sizeof(sa6);
807 hent = gethostbyaddr(&sa6.sin6_addr, sizeof(sa6.sin6_addr), AF_INET6);
808 break;
811 getnameinfo(sa, sa_len, SELFLD(dir, rev_dns_src, rev_dns_dst),
812 sizeof(n->rev_dns_src), NULL, 0, NI_NUMERICHOST);
814 if (hent)
815 strlcpy(SELFLD(dir, rev_dns_src, rev_dns_dst), hent->h_name,
816 sizeof(n->rev_dns_src));
819 static void flow_entry_get_extended(struct flow_entry *n)
821 if (n->flow_id == 0)
822 return;
824 flow_entry_get_extended_revdns(n, FLOW_DIR_SRC);
825 flow_entry_get_extended_geo(n, FLOW_DIR_SRC);
827 flow_entry_get_extended_revdns(n, FLOW_DIR_DST);
828 flow_entry_get_extended_geo(n, FLOW_DIR_DST);
830 /* Lookup application */
831 n->inode = get_port_inode(n->port_src, n->l4_proto,
832 n->l3_proto == AF_INET6);
833 if (n->inode > 0)
834 flow_entry_find_process(n);
837 static char *bandw2str(double bytes, char *buf, size_t len)
839 if (bytes <= 0) {
840 buf[0] = '\0';
841 return buf;
844 if (bytes > 1000000000.)
845 snprintf(buf, len, "%.1fGB", bytes / 1000000000.);
846 else if (bytes > 1000000.)
847 snprintf(buf, len, "%.1fMB", bytes / 1000000.);
848 else if (bytes > 1000.)
849 snprintf(buf, len, "%.1fkB", bytes / 1000.);
850 else
851 snprintf(buf, len, "%.0f", bytes);
853 return buf;
856 static char *rate2str(double rate, char *buf, size_t len)
858 const char * const unit_fmt[2][4] = {
859 { "%.1fGbit/s", "%.1fMbit/s", "%.1fkbit/s", "%.0fbit/s" },
860 { "%.1fGB/s", "%.1fMB/s", "%.1fkB/s", "%.0fB/s" }
863 if (rate <= 0) {
864 buf[0] = '\0';
865 return buf;
868 if (rate_type == RATE_BITS)
869 rate *= 8;
871 if (rate > 1000000000.)
872 snprintf(buf, len, unit_fmt[rate_type][0], rate / 1000000000.);
873 else if (rate > 1000000.)
874 snprintf(buf, len, unit_fmt[rate_type][1], rate / 1000000.);
875 else if (rate > 1000.)
876 snprintf(buf, len, unit_fmt[rate_type][2], rate / 1000.);
877 else
878 snprintf(buf, len, unit_fmt[rate_type][3], rate);
880 return buf;
883 static char *time2str(uint64_t tstamp, char *str, size_t len)
885 time_t now;
886 int v, s;
888 time(&now);
890 s = now - (tstamp ? (tstamp / NSEC_PER_SEC) : now);
891 if (s <= 0) {
892 str[0] = '\0';
893 return str;
896 v = s / (3600 * 24);
897 if (v > 0) {
898 slprintf(str, len, "%dd", v);
899 return str;
902 v = s / 3600;
903 if (v > 0) {
904 slprintf(str, len, "%dh", v);
905 return str;
908 v = s / 60;
909 if (v > 0) {
910 slprintf(str, len, "%dm", v);
911 return str;
914 slprintf(str, len, "%ds", s);
915 return str;
919 static const char *flow_state2str(const struct flow_entry *n)
921 switch (n->l4_proto) {
922 case IPPROTO_TCP:
923 return tcp_state2str[n->tcp_state];
924 case IPPROTO_SCTP:
925 return sctp_state2str[n->sctp_state];
926 case IPPROTO_DCCP:
927 return dccp_state2str[n->dccp_state];
929 case IPPROTO_UDP:
930 case IPPROTO_UDPLITE:
931 case IPPROTO_ICMP:
932 case IPPROTO_ICMPV6:
933 default:
934 return "";
938 static char *flow_port2str(const struct flow_entry *n, char *str, size_t len,
939 enum flow_direction dir)
941 const char *tmp = NULL;
942 uint16_t port = 0;
944 port = SELFLD(dir, port_src, port_dst);
945 tmp = NULL;
947 switch (n->l4_proto) {
948 case IPPROTO_TCP:
949 tmp = lookup_port_tcp(port);
950 break;
951 case IPPROTO_UDP:
952 case IPPROTO_UDPLITE:
953 tmp = lookup_port_udp(port);
954 break;
957 if (!tmp && port)
958 slprintf(str, len, "%d", port);
959 else
960 slprintf(str, len, "%s", tmp ? tmp : "");
962 return str;
965 static void print_flow_peer_info(const struct flow_entry *n, enum flow_direction dir)
967 int counters_color = COLOR(YELLOW, BLACK);
968 int src_color = COLOR(RED, BLACK);
969 int dst_color = COLOR(BLUE, BLACK);
970 int country_color = COLOR(GREEN, BLACK);
971 int addr_color = dst_color;
972 int port_color = A_BOLD;
973 char tmp[128];
975 if (show_src && dir == FLOW_DIR_SRC) {
976 country_color = src_color;
977 counters_color = src_color;
978 port_color |= src_color;
979 addr_color = src_color;
980 } else if (show_src && FLOW_DIR_DST) {
981 country_color = dst_color;
982 counters_color = dst_color;
983 port_color |= dst_color;
984 addr_color = dst_color;
987 ui_table_col_color_set(&flows_tbl, TBL_FLOW_ADDRESS, addr_color);
988 ui_table_col_color_set(&flows_tbl, TBL_FLOW_PORT, port_color);
989 ui_table_col_color_set(&flows_tbl, TBL_FLOW_GEO, country_color);
990 ui_table_col_color_set(&flows_tbl, TBL_FLOW_BYTES, counters_color);
991 ui_table_col_color_set(&flows_tbl, TBL_FLOW_RATE, counters_color);
993 /* Reverse DNS/IP */
994 ui_table_row_col_set(&flows_tbl, TBL_FLOW_ADDRESS,
995 SELFLD(dir, rev_dns_src, rev_dns_dst));
997 /* Application port */
998 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PORT,
999 flow_port2str(n, tmp, sizeof(tmp), dir));
1001 /* GEO */
1002 ui_table_row_col_set(&flows_tbl, TBL_FLOW_GEO,
1003 SELFLD(dir, country_code_src, country_code_dst));
1005 /* Bytes */
1006 ui_table_row_col_set(&flows_tbl, TBL_FLOW_BYTES,
1007 bandw2str(SELFLD(dir, bytes_src, bytes_dst),
1008 tmp, sizeof(tmp) - 1));
1010 /* Rate bytes */
1011 ui_table_row_col_set(&flows_tbl, TBL_FLOW_RATE,
1012 rate2str(SELFLD(dir, rate_bytes_src, rate_bytes_dst),
1013 tmp, sizeof(tmp) - 1));
1016 static void draw_flow_entry(const struct flow_entry *n)
1018 char tmp[128];
1020 ui_table_row_add(&flows_tbl);
1022 /* Application */
1023 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PROCESS,
1024 n->proc ? n->proc->name : "");
1026 /* PID */
1027 slprintf(tmp, sizeof(tmp), "%.d", n->proc ? n->proc->pid : 0);
1028 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PID, tmp);
1030 /* L4 protocol */
1031 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PROTO, l4proto2str[n->l4_proto]);
1033 /* L4 protocol state */
1034 ui_table_row_col_set(&flows_tbl, TBL_FLOW_STATE, flow_state2str(n));
1036 /* Time */
1037 time2str(n->timestamp_start, tmp, sizeof(tmp));
1038 ui_table_row_col_set(&flows_tbl, TBL_FLOW_TIME, tmp);
1040 print_flow_peer_info(n, show_src ? FLOW_DIR_SRC : FLOW_DIR_DST);
1042 ui_table_row_show(&flows_tbl);
1044 if (show_src) {
1045 ui_table_row_add(&flows_tbl);
1047 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PROCESS, "");
1048 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PID, "");
1049 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PROTO, "");
1050 ui_table_row_col_set(&flows_tbl, TBL_FLOW_STATE, "");
1051 ui_table_row_col_set(&flows_tbl, TBL_FLOW_TIME, "");
1053 print_flow_peer_info(n, FLOW_DIR_DST);
1054 ui_table_row_show(&flows_tbl);
1058 static inline bool presenter_flow_wrong_state(struct flow_entry *n)
1060 switch (n->l4_proto) {
1061 case IPPROTO_TCP:
1062 switch (n->tcp_state) {
1063 case TCP_CONNTRACK_SYN_SENT:
1064 case TCP_CONNTRACK_SYN_RECV:
1065 case TCP_CONNTRACK_ESTABLISHED:
1066 case TCP_CONNTRACK_FIN_WAIT:
1067 case TCP_CONNTRACK_CLOSE_WAIT:
1068 case TCP_CONNTRACK_LAST_ACK:
1069 case TCP_CONNTRACK_TIME_WAIT:
1070 case TCP_CONNTRACK_CLOSE:
1071 case TCP_CONNTRACK_SYN_SENT2:
1072 case TCP_CONNTRACK_NONE:
1073 return false;
1074 break;
1076 break;
1077 case IPPROTO_SCTP:
1078 switch (n->sctp_state) {
1079 case SCTP_CONNTRACK_NONE:
1080 case SCTP_CONNTRACK_CLOSED:
1081 case SCTP_CONNTRACK_COOKIE_WAIT:
1082 case SCTP_CONNTRACK_COOKIE_ECHOED:
1083 case SCTP_CONNTRACK_ESTABLISHED:
1084 case SCTP_CONNTRACK_SHUTDOWN_SENT:
1085 case SCTP_CONNTRACK_SHUTDOWN_RECD:
1086 case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT:
1087 return false;
1088 break;
1090 break;
1091 case IPPROTO_DCCP:
1092 switch (n->dccp_state) {
1093 case DCCP_CONNTRACK_NONE:
1094 case DCCP_CONNTRACK_REQUEST:
1095 case DCCP_CONNTRACK_RESPOND:
1096 case DCCP_CONNTRACK_PARTOPEN:
1097 case DCCP_CONNTRACK_OPEN:
1098 case DCCP_CONNTRACK_CLOSEREQ:
1099 case DCCP_CONNTRACK_CLOSING:
1100 case DCCP_CONNTRACK_TIMEWAIT:
1101 case DCCP_CONNTRACK_IGNORE:
1102 case DCCP_CONNTRACK_INVALID:
1103 return false;
1104 break;
1106 break;
1107 case IPPROTO_UDP:
1108 case IPPROTO_UDPLITE:
1109 case IPPROTO_ICMP:
1110 case IPPROTO_ICMPV6:
1111 return false;
1112 break;
1115 return true;
1118 static void draw_filter_status(char *title, int count, int skip_lines)
1120 mvwprintw(screen, 1, 0, "%*s", COLS - 1, " ");
1121 mvwprintw(screen, 1, 2, "%s(%u) for ", title, count);
1123 if (what & INCLUDE_IPV4)
1124 printw("IPv4,");
1125 if (what & INCLUDE_IPV6)
1126 printw("IPv6,");
1127 if (what & INCLUDE_TCP)
1128 printw("TCP,");
1129 if (what & INCLUDE_UDP)
1130 printw("UDP,");
1131 if (what & INCLUDE_SCTP)
1132 printw("SCTP,");
1133 if (what & INCLUDE_DCCP)
1134 printw("DCCP,");
1135 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1136 printw("ICMP,");
1137 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1138 printw("ICMP6,");
1139 if (show_active_only)
1140 printw("Active,");
1142 printw(" [+%d]", skip_lines);
1144 if (is_flow_collecting)
1145 printw(" [Collecting flows ...]");
1149 static void draw_flows(WINDOW *screen, struct flow_list *fl,
1150 int skip_lines)
1152 int row_width = show_src ? 2 : 1;
1153 unsigned int flows = 0;
1154 unsigned int line = 4;
1155 int skip = skip_lines;
1156 struct flow_entry *n;
1158 rcu_read_lock();
1160 if (cds_list_empty(&fl->head))
1161 mvwprintw(screen, line, 2, "(No sessions! "
1162 "Is netfilter running?)");
1164 ui_table_clear(&flows_tbl);
1165 ui_table_header_print(&flows_tbl);
1167 cds_list_for_each_entry_rcu(n, &fl->head, entry) {
1168 if (!n->is_visible)
1169 continue;
1170 if (presenter_flow_wrong_state(n))
1171 continue;
1173 /* count only flows which might be showed */
1174 flows++;
1176 if (line + row_width >= rows)
1177 continue;
1178 if (--skip >= 0)
1179 continue;
1181 draw_flow_entry(n);
1182 line += row_width;
1185 rcu_read_unlock();
1187 mvwprintw(screen, 1, 0, "%*s", COLS - 1, " ");
1188 mvwprintw(screen, 1, 2, "Kernel netfilter flows(%u) for ", flows);
1190 draw_filter_status("Kernel netfilter flows", flows, skip_lines);
1193 static void draw_proc_entry(struct proc_entry *p)
1195 struct ui_table *tbl = &procs_tbl;;
1196 char tmp[128];
1198 ui_table_row_add(tbl);
1200 /* Application */
1201 ui_table_row_col_set(tbl, TBL_PROC_NAME, p->name);
1203 /* PID */
1204 slprintf(tmp, sizeof(tmp), "%.d", p->pid);
1205 ui_table_row_col_set(tbl, TBL_PROC_PID, tmp);
1207 /* Flows */
1208 slprintf(tmp, sizeof(tmp), "%.d", p->flows_count);
1209 ui_table_row_col_set(tbl, TBL_PROC_FLOWS, tmp);
1211 /* Bytes Src */
1212 bandw2str(p->bytes_src, tmp, sizeof(tmp) - 1);
1213 ui_table_row_col_set(tbl, TBL_PROC_BYTES_SRC, tmp);
1215 /* Rate Src */
1216 rate2str(p->rate_bytes_src, tmp, sizeof(tmp) - 1);
1217 ui_table_row_col_set(tbl, TBL_PROC_RATE_SRC, tmp);
1219 /* Bytes Dest */
1220 bandw2str(p->bytes_dst, tmp, sizeof(tmp) - 1);
1221 ui_table_row_col_set(tbl, TBL_PROC_BYTES_DST, tmp);
1223 /* Rate Dest */
1224 rate2str(p->rate_bytes_dst, tmp, sizeof(tmp) - 1);
1225 ui_table_row_col_set(tbl, TBL_PROC_RATE_DST, tmp);
1227 ui_table_row_show(tbl);
1230 static void draw_procs(WINDOW *screen, struct flow_list *fl,
1231 int skip_lines)
1233 struct proc_entry *proc, *tmp;
1234 unsigned int line = 4;
1235 int skip = skip_lines;
1236 int procs = 0;
1238 rcu_read_lock();
1240 ui_table_clear(&procs_tbl);
1241 ui_table_header_print(&procs_tbl);
1243 cds_list_for_each_entry_safe(proc, tmp, &proc_list.head, entry) {
1244 if (line + 1 >= rows)
1245 continue;
1246 if (--skip >= 0)
1247 continue;
1249 draw_proc_entry(proc);
1250 procs++;
1251 line++;
1254 rcu_read_unlock();
1256 draw_filter_status("Processes", procs, skip_lines);
1259 static void draw_help(void)
1261 int col = 0;
1262 int row = 1;
1263 int i;
1265 mvaddch(row, col, ACS_ULCORNER);
1266 mvaddch(rows - row - 1, col, ACS_LLCORNER);
1268 mvaddch(row, cols - 1, ACS_URCORNER);
1269 mvaddch(rows - row - 1, cols - 1, ACS_LRCORNER);
1271 for (i = 1; i < rows - row - 2; i++) {
1272 mvaddch(row + i, 0, ACS_VLINE);
1273 mvaddch(row + i, cols - 1, ACS_VLINE);
1275 for (i = 1; i < cols - col - 1; i++) {
1276 mvaddch(row, col + i, ACS_HLINE);
1277 mvaddch(rows - row - 1, col + i, ACS_HLINE);
1280 attron(A_BOLD);
1281 mvaddnstr(row, cols / 2 - 2, "| Help |", -1);
1283 attron(A_UNDERLINE);
1284 mvaddnstr(row + 2, col + 2, "Navigation", -1);
1285 attroff(A_BOLD | A_UNDERLINE);
1287 mvaddnstr(row + 4, col + 3, "TAB Go to next tab panel", -1);
1288 mvaddnstr(row + 5, col + 3, "Up, u, k Move up", -1);
1289 mvaddnstr(row + 6, col + 3, "Down, d, j Move down", -1);
1290 mvaddnstr(row + 7, col + 3, "Left,l Scroll left", -1);
1291 mvaddnstr(row + 8, col + 3, "Right,h Scroll right", -1);
1292 mvaddnstr(row + 9, col + 3, "? Toggle help window", -1);
1293 mvaddnstr(row + 10, col + 3, "q, Ctrl+C Quit", -1);
1295 attron(A_BOLD | A_UNDERLINE);
1296 mvaddnstr(row + 12, col + 2, "Display Settings", -1);
1297 attroff(A_BOLD | A_UNDERLINE);
1299 mvaddnstr(row + 14, col + 3, "b Toggle rate units (bits/bytes)", -1);
1300 mvaddnstr(row + 15, col + 3, "a Toggle display of active flows (rate > 0) only", -1);
1301 mvaddnstr(row + 16, col + 3, "s Toggle show source peer info", -1);
1303 mvaddnstr(row + 18, col + 3, "T Toggle display TCP flows", -1);
1304 mvaddnstr(row + 19, col + 3, "U Toggle display UDP flows", -1);
1305 mvaddnstr(row + 20, col + 3, "D Toggle display DCCP flows", -1);
1306 mvaddnstr(row + 21, col + 3, "I Toggle display ICMP flows", -1);
1307 mvaddnstr(row + 22, col + 3, "S Toggle display SCTP flows", -1);
1310 static void draw_header(WINDOW *screen)
1312 int i;
1314 attron(A_STANDOUT);
1316 for (i = 0; i < cols; i++)
1317 mvaddch(0, i, ' ');
1319 mvwprintw(screen, 0, 2, "flowtop %s", VERSION_LONG);
1320 attroff(A_STANDOUT);
1323 static void draw_footer(void)
1325 int i;
1327 attron(A_STANDOUT);
1329 for (i = 0; i < cols; i++)
1330 mvaddch(rows - 1, i, ' ');
1332 mvaddnstr(rows - 1, 1, "Press '?' for help", -1);
1333 addch(ACS_VLINE);
1334 attroff(A_STANDOUT);
1337 static void show_option_toggle(int opt)
1339 switch (opt) {
1340 case 'T':
1341 TOGGLE_FLAG(what, INCLUDE_TCP);
1342 break;
1343 case 'U':
1344 TOGGLE_FLAG(what, INCLUDE_UDP);
1345 break;
1346 case 'D':
1347 TOGGLE_FLAG(what, INCLUDE_DCCP);
1348 break;
1349 case 'I':
1350 TOGGLE_FLAG(what, INCLUDE_ICMP);
1351 break;
1352 case 'S':
1353 TOGGLE_FLAG(what, INCLUDE_SCTP);
1354 break;
1358 static void flows_table_init(struct ui_table *tbl)
1360 ui_table_init(tbl);
1362 ui_table_pos_set(tbl, 3, 0);
1363 ui_table_height_set(tbl, LINES - 3);
1365 ui_table_col_add(tbl, TBL_FLOW_PROCESS, "PROCESS", 13);
1366 ui_table_col_add(tbl, TBL_FLOW_PID, "PID", 7);
1367 ui_table_col_add(tbl, TBL_FLOW_PROTO, "PROTO", 6);
1368 ui_table_col_add(tbl, TBL_FLOW_STATE, "STATE", 11);
1369 ui_table_col_add(tbl, TBL_FLOW_TIME, "TIME", 4);
1370 ui_table_col_add(tbl, TBL_FLOW_ADDRESS, "ADDRESS", 50);
1371 ui_table_col_add(tbl, TBL_FLOW_PORT, "PORT", 8);
1372 ui_table_col_add(tbl, TBL_FLOW_GEO, "GEO", 3);
1373 ui_table_col_add(tbl, TBL_FLOW_BYTES, "BYTES", 10);
1374 ui_table_col_add(tbl, TBL_FLOW_RATE, "RATE", 10);
1376 ui_table_col_align_set(tbl, TBL_FLOW_TIME, UI_ALIGN_RIGHT);
1377 ui_table_col_align_set(tbl, TBL_FLOW_BYTES, UI_ALIGN_RIGHT);
1378 ui_table_col_align_set(tbl, TBL_FLOW_RATE, UI_ALIGN_RIGHT);
1380 ui_table_col_color_set(tbl, TBL_FLOW_PROCESS, COLOR(YELLOW, BLACK));
1381 ui_table_col_color_set(tbl, TBL_FLOW_PID, A_BOLD);
1382 ui_table_col_color_set(tbl, TBL_FLOW_STATE, COLOR(YELLOW, BLACK));
1384 ui_table_header_color_set(&flows_tbl, COLOR(BLACK, GREEN));
1387 static void procs_table_init(struct ui_table *tbl)
1389 ui_table_init(tbl);
1391 ui_table_pos_set(tbl, 3, 0);
1392 ui_table_height_set(tbl, LINES - 3);
1394 ui_table_col_add(tbl, TBL_PROC_NAME, "NAME", 13);
1395 ui_table_col_add(tbl, TBL_PROC_PID, "PID", 7);
1396 ui_table_col_add(tbl, TBL_PROC_FLOWS, "FLOWS", 7);
1397 ui_table_col_add(tbl, TBL_PROC_BYTES_SRC, "BYTES_SRC", 10);
1398 ui_table_col_add(tbl, TBL_PROC_BYTES_DST, "BYTES_DST", 10);
1399 ui_table_col_add(tbl, TBL_PROC_RATE_SRC, "RATE_SRC", 14);
1400 ui_table_col_add(tbl, TBL_PROC_RATE_DST, "RATE_DST", 14);
1402 ui_table_col_align_set(tbl, TBL_PROC_BYTES_SRC, UI_ALIGN_RIGHT);
1403 ui_table_col_align_set(tbl, TBL_PROC_RATE_SRC, UI_ALIGN_RIGHT);
1404 ui_table_col_align_set(tbl, TBL_PROC_BYTES_DST, UI_ALIGN_RIGHT);
1405 ui_table_col_align_set(tbl, TBL_PROC_RATE_DST, UI_ALIGN_RIGHT);
1407 ui_table_col_color_set(tbl, TBL_PROC_NAME, COLOR(YELLOW, BLACK));
1408 ui_table_col_color_set(tbl, TBL_PROC_PID, A_BOLD);
1409 ui_table_col_color_set(tbl, TBL_PROC_FLOWS, COLOR(YELLOW, BLACK));
1410 ui_table_col_color_set(tbl, TBL_PROC_BYTES_SRC, COLOR(RED, BLACK));
1411 ui_table_col_color_set(tbl, TBL_PROC_RATE_SRC, COLOR(RED, BLACK));
1412 ui_table_col_color_set(tbl, TBL_PROC_BYTES_DST, COLOR(BLUE, BLACK));
1413 ui_table_col_color_set(tbl, TBL_PROC_RATE_DST, COLOR(BLUE, BLACK));
1415 ui_table_header_color_set(tbl, COLOR(BLACK, GREEN));
1418 static void tab_main_on_open(struct ui_tab *tab, enum ui_tab_event_t evt, uint32_t id)
1420 if (evt != UI_TAB_EVT_OPEN)
1421 return;
1423 if (id == TAB_FLOWS)
1424 draw_flows(screen, &flow_list, skip_lines);
1425 else if (id == TAB_PROCS)
1426 draw_procs(screen, &flow_list, skip_lines);
1429 static void presenter(void)
1431 bool show_help = false;
1432 struct ui_tab *tab_main;
1434 lookup_init(LT_PORTS_TCP);
1435 lookup_init(LT_PORTS_UDP);
1437 screen = screen_init(false);
1438 wclear(screen);
1439 halfdelay(1);
1441 start_color();
1442 INIT_COLOR(RED, BLACK);
1443 INIT_COLOR(BLUE, BLACK);
1444 INIT_COLOR(YELLOW, BLACK);
1445 INIT_COLOR(GREEN, BLACK);
1446 INIT_COLOR(BLACK, GREEN);
1448 flows_table_init(&flows_tbl);
1449 procs_table_init(&procs_tbl);
1451 tab_main = ui_tab_create();
1452 ui_tab_event_cb_set(tab_main, tab_main_on_open);
1453 ui_tab_pos_set(tab_main, 2, 0);
1454 ui_tab_active_color_set(tab_main, COLOR(BLACK, GREEN));
1455 ui_tab_entry_add(tab_main, TAB_FLOWS, "Flows");
1456 ui_tab_entry_add(tab_main, TAB_PROCS, "Process");
1458 rcu_register_thread();
1459 while (!sigint) {
1460 int ch;
1462 curs_set(0);
1463 getmaxyx(screen, rows, cols);
1465 ch = getch();
1466 switch (ch) {
1467 case 'q':
1468 sigint = 1;
1469 break;
1470 case KEY_UP:
1471 case 'u':
1472 case 'k':
1473 skip_lines--;
1474 if (skip_lines < 0)
1475 skip_lines = 0;
1476 break;
1477 case KEY_DOWN:
1478 case 'd':
1479 case 'j':
1480 skip_lines++;
1481 if (skip_lines > SCROLL_MAX)
1482 skip_lines = SCROLL_MAX;
1483 break;
1484 case KEY_LEFT:
1485 case 'h':
1486 ui_table_event_send(&flows_tbl, UI_EVT_SCROLL_LEFT);
1487 break;
1488 case KEY_RIGHT:
1489 case 'l':
1490 ui_table_event_send(&flows_tbl, UI_EVT_SCROLL_RIGHT);
1491 break;
1492 case 'b':
1493 if (rate_type == RATE_BYTES)
1494 rate_type = RATE_BITS;
1495 else
1496 rate_type = RATE_BYTES;
1497 break;
1498 case 'a':
1499 show_active_only = !show_active_only;
1500 break;
1501 case 's':
1502 show_src = !show_src;
1503 break;
1504 case '?':
1505 show_help = !show_help;
1506 wclear(screen);
1507 clear();
1508 break;
1509 case 'T':
1510 case 'U':
1511 case 'D':
1512 case 'I':
1513 case 'S':
1514 show_option_toggle(ch);
1515 do_reload_flows = true;
1516 break;
1517 case '\t':
1518 ui_tab_event_send(tab_main, UI_EVT_SELECT_NEXT);
1519 break;
1520 default:
1521 fflush(stdin);
1522 break;
1525 draw_header(screen);
1527 if (show_help)
1528 draw_help();
1529 else
1530 ui_tab_show(tab_main);
1532 draw_footer();
1534 rcu_unregister_thread();
1536 ui_table_uninit(&flows_tbl);
1537 ui_table_uninit(&procs_tbl);
1538 ui_tab_destroy(tab_main);
1540 screen_end();
1541 lookup_cleanup(LT_PORTS_UDP);
1542 lookup_cleanup(LT_PORTS_TCP);
1545 static void restore_sysctl(void *obj)
1547 struct sysctl_params_ctx *sysctl_ctx = obj;
1549 if (sysctl_ctx->nfct_acct == 0)
1550 sysctl_set_int("net/netfilter/nf_conntrack_acct",
1551 sysctl_ctx->nfct_acct);
1553 if (sysctl_ctx->nfct_tstamp == 0)
1554 sysctl_set_int("net/netfilter/nf_conntrack_timestamp",
1555 sysctl_ctx->nfct_tstamp);
1558 static void on_panic_handler(void *arg)
1560 restore_sysctl(arg);
1561 screen_end();
1564 static void conntrack_acct_enable(void)
1566 /* We can still work w/o traffic accounting so just warn about error */
1567 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &sysctl.nfct_acct)) {
1568 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1569 strerror(errno));
1570 return;
1573 if (sysctl.nfct_acct == 1)
1574 return;
1576 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1577 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1578 strerror(errno));
1582 static void conntrack_tstamp_enable(void)
1584 if (sysctl_get_int("net/netfilter/nf_conntrack_timestamp", &sysctl.nfct_tstamp)) {
1585 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_timestamp: %s\n",
1586 strerror(errno));
1587 return;
1590 if (sysctl.nfct_tstamp == 1)
1591 return;
1593 if (sysctl_set_int("net/netfilter/nf_conntrack_timestamp", 1)) {
1594 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_timestamp: %s\n",
1595 strerror(errno));
1599 static void flow_entry_filter(struct flow_entry *n)
1601 if (show_active_only && !n->rate_bytes_src && !n->rate_bytes_dst)
1602 n->is_visible = false;
1603 else
1604 n->is_visible = true;
1607 static int flow_list_update_entry(struct flow_list *fl, struct nf_conntrack *ct)
1609 struct flow_entry *n;
1611 n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
1612 if (!n)
1613 return NFCT_CB_CONTINUE;
1615 flow_entry_calc_rate(n, ct);
1616 flow_entry_update_time(n);
1617 flow_entry_from_ct(n, ct);
1618 flow_entry_filter(n);
1620 return NFCT_CB_CONTINUE;
1623 static int flow_event_cb(enum nf_conntrack_msg_type type,
1624 struct nf_conntrack *ct, void *data __maybe_unused)
1626 if (sigint)
1627 return NFCT_CB_STOP;
1629 switch (type) {
1630 case NFCT_T_NEW:
1631 return flow_list_new_entry(&flow_list, ct);
1632 case NFCT_T_UPDATE:
1633 return flow_list_update_entry(&flow_list, ct);
1634 case NFCT_T_DESTROY:
1635 return flow_list_del_entry(&flow_list, ct);
1636 default:
1637 return NFCT_CB_CONTINUE;
1641 static void collector_refresh_procs(void)
1643 struct proc_entry *p, *tmp;
1645 cds_list_for_each_entry_safe(p, tmp, &proc_list.head, entry) {
1646 double sec = (double)time_after_us(&p->last_update) / USEC_PER_SEC;
1647 struct flow_entry *n;
1649 if (sec < 1)
1650 continue;
1652 bug_on(gettimeofday(&p->last_update, NULL));
1654 if (!p->flows_count && !proc_exists(p->pid)) {
1655 cds_list_del_rcu(&p->entry);
1656 call_rcu(&p->rcu, proc_entry_xfree_rcu);
1657 continue;
1660 p->rate_bytes_src = 0;
1661 p->rate_bytes_dst = 0;
1662 p->rate_pkts_src = 0;
1663 p->rate_pkts_dst = 0;
1665 cds_list_for_each_entry_rcu(n, &p->flows, proc_head) {
1666 p->rate_bytes_src += n->rate_bytes_src;
1667 p->rate_bytes_dst += n->rate_bytes_dst;
1668 p->rate_pkts_src += n->rate_pkts_src;
1669 p->rate_pkts_dst += n->rate_pkts_dst;
1674 static void collector_refresh_flows(struct nfct_handle *handle)
1676 struct flow_entry *n;
1678 cds_list_for_each_entry_rcu(n, &flow_list.head, entry) {
1679 nfct_query(handle, NFCT_Q_GET, n->ct);
1683 static void collector_create_filter(struct nfct_handle *nfct)
1685 struct nfct_filter *filter;
1686 int ret;
1688 filter = nfct_filter_create();
1689 if (!filter)
1690 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1692 if (what & INCLUDE_UDP) {
1693 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1694 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1696 if (what & INCLUDE_TCP)
1697 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1698 if (what & INCLUDE_DCCP)
1699 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1700 if (what & INCLUDE_SCTP)
1701 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1702 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1703 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1704 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1705 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1706 if (what & INCLUDE_IPV4) {
1707 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1708 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1710 if (what & INCLUDE_IPV6) {
1711 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1712 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1715 ret = nfct_filter_attach(nfct_fd(nfct), filter);
1716 if (ret < 0)
1717 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1719 nfct_filter_destroy(filter);
1722 /* This hand-crafted filter looks ugly but it allows to do not
1723 * flush nfct connections & filter them by user specified filter.
1724 * May be it is better to replace this one by nfct_cmp. */
1725 static int flow_dump_cb(enum nf_conntrack_msg_type type __maybe_unused,
1726 struct nf_conntrack *ct, void *data __maybe_unused)
1728 struct flow_entry fl;
1729 struct flow_entry *n = &fl;
1731 if (sigint)
1732 return NFCT_CB_STOP;
1734 if (!(what & ~(INCLUDE_IPV4 | INCLUDE_IPV6)))
1735 goto check_addr;
1737 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
1739 if (what & INCLUDE_UDP) {
1740 if (n->l4_proto == IPPROTO_UDP)
1741 goto check_addr;
1743 if (n->l4_proto == IPPROTO_UDPLITE)
1744 goto check_addr;
1747 if ((what & INCLUDE_TCP) && n->l4_proto == IPPROTO_TCP)
1748 goto check_addr;
1750 if ((what & INCLUDE_DCCP) && n->l4_proto == IPPROTO_DCCP)
1751 goto check_addr;
1753 if ((what & INCLUDE_SCTP) && n->l4_proto == IPPROTO_SCTP)
1754 goto check_addr;
1756 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV4) &&
1757 n->l4_proto == IPPROTO_ICMP) {
1758 goto check_addr;
1761 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV6) &&
1762 n->l4_proto == IPPROTO_ICMPV6) {
1763 goto check_addr;
1766 goto skip_flow;
1768 check_addr:
1769 /* filter loopback addresses */
1770 if (what & INCLUDE_IPV4) {
1771 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
1773 if (n->ip4_src_addr == filter_ipv4.addr)
1774 goto skip_flow;
1776 if (what & INCLUDE_IPV6) {
1777 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
1779 if (n->ip6_src_addr[0] == 0x0 &&
1780 n->ip6_src_addr[1] == 0x0 &&
1781 n->ip6_src_addr[2] == 0x0 &&
1782 n->ip6_src_addr[3] == 0x1)
1783 goto skip_flow;
1786 return flow_list_new_entry(&flow_list, ct);
1788 skip_flow:
1789 return NFCT_CB_CONTINUE;
1792 static void collector_dump_flows(void)
1794 struct nfct_handle *nfct = nfct_open(CONNTRACK, 0);
1796 if (!nfct)
1797 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1799 nfct_callback_register(nfct, NFCT_T_ALL, flow_dump_cb, NULL);
1801 is_flow_collecting = true;
1802 if (what & INCLUDE_IPV4) {
1803 int family = AF_INET;
1804 nfct_query(nfct, NFCT_Q_DUMP, &family);
1806 if (what & INCLUDE_IPV6) {
1807 int family = AF_INET6;
1808 nfct_query(nfct, NFCT_Q_DUMP, &family);
1810 is_flow_collecting = false;
1812 nfct_close(nfct);
1815 static void *collector(void *null __maybe_unused)
1817 struct nfct_handle *ct_event;
1818 struct pollfd poll_fd[1];
1820 proc_list_init(&proc_list);
1821 flow_list_init(&flow_list);
1823 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1824 NF_NETLINK_CONNTRACK_UPDATE |
1825 NF_NETLINK_CONNTRACK_DESTROY);
1826 if (!ct_event)
1827 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1829 collector_create_filter(ct_event);
1831 nfct_callback_register(ct_event, NFCT_T_ALL, flow_event_cb, NULL);
1833 poll_fd[0].fd = nfct_fd(ct_event);
1834 poll_fd[0].events = POLLIN;
1836 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1837 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1838 strerror(errno));
1840 rcu_register_thread();
1842 collector_dump_flows();
1844 while (!sigint) {
1845 int status;
1847 if (!do_reload_flows) {
1848 usleep(USEC_PER_SEC * interval);
1849 } else {
1850 do_reload_flows = false;
1852 flow_list_destroy(&flow_list);
1854 collector_create_filter(ct_event);
1855 collector_dump_flows();
1858 collector_refresh_procs();
1859 collector_refresh_flows(ct_event);
1861 status = poll(poll_fd, 1, 0);
1862 if (status < 0) {
1863 if (errno == EAGAIN || errno == EINTR)
1864 continue;
1866 panic("Error while polling: %s\n", strerror(errno));
1867 } else if (status != 0) {
1868 if (poll_fd[0].revents & POLLIN)
1869 nfct_catch(ct_event);
1873 flow_list_destroy(&flow_list);
1874 proc_list_destroy(&proc_list);
1876 rcu_unregister_thread();
1878 nfct_close(ct_event);
1880 pthread_exit(NULL);
1883 int main(int argc, char **argv)
1885 pthread_t tid;
1886 int ret, c, what_cmd = 0;
1888 setfsuid(getuid());
1889 setfsgid(getgid());
1891 while ((c = getopt_long(argc, argv, short_options, long_options,
1892 NULL)) != EOF) {
1893 switch (c) {
1894 case '4':
1895 what_cmd |= INCLUDE_IPV4;
1896 break;
1897 case '6':
1898 what_cmd |= INCLUDE_IPV6;
1899 break;
1900 case 'T':
1901 what_cmd |= INCLUDE_TCP;
1902 break;
1903 case 'U':
1904 what_cmd |= INCLUDE_UDP;
1905 break;
1906 case 'D':
1907 what_cmd |= INCLUDE_DCCP;
1908 break;
1909 case 'I':
1910 what_cmd |= INCLUDE_ICMP;
1911 break;
1912 case 'S':
1913 what_cmd |= INCLUDE_SCTP;
1914 break;
1915 case 's':
1916 show_src = true;
1917 break;
1918 case 'b':
1919 rate_type = RATE_BITS;
1920 break;
1921 case 'u':
1922 update_geoip();
1923 die();
1924 break;
1925 case 't':
1926 interval = strtoul(optarg, NULL, 10);
1927 break;
1928 case 'n':
1929 resolve_dns = false;
1930 break;
1931 case 'G':
1932 resolve_geoip = false;
1933 break;
1934 case 'h':
1935 help();
1936 break;
1937 case 'v':
1938 version();
1939 break;
1940 default:
1941 break;
1945 if (what_cmd > 0) {
1946 what = what_cmd;
1948 if (!(what & (INCLUDE_IPV4 | INCLUDE_IPV6)))
1949 what |= INCLUDE_IPV4 | INCLUDE_IPV6;
1952 rcu_init();
1954 register_signal(SIGINT, signal_handler);
1955 register_signal(SIGQUIT, signal_handler);
1956 register_signal(SIGTERM, signal_handler);
1957 register_signal(SIGHUP, signal_handler);
1959 panic_handler_add(on_panic_handler, &sysctl);
1961 conntrack_acct_enable();
1962 conntrack_tstamp_enable();
1964 if (resolve_geoip)
1965 init_geoip(1);
1967 ret = pthread_create(&tid, NULL, collector, NULL);
1968 if (ret < 0)
1969 panic("Cannot create phthread!\n");
1971 presenter();
1973 if (resolve_geoip)
1974 destroy_geoip();
1976 restore_sysctl(&sysctl);
1978 return 0;