flowtop: Refresh flows if filter was changed while flows loading
[netsniff-ng.git] / flowtop.c
blob1d438ba48b4fc1e1918f383495737195a35336e7
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 - 2013 Daniel Borkmann.
4 * Copyright 2011 Emmanuel Roullit.
5 * Subject to the GPL, version 2.
6 */
8 #define _LGPL_SOURCE
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <stdlib.h>
12 #include <signal.h>
13 #include <getopt.h>
14 #include <pthread.h>
15 #include <signal.h>
16 #include <netdb.h>
17 #include <ctype.h>
18 #include <netinet/in.h>
19 #include <curses.h>
20 #include <dirent.h>
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <sys/fsuid.h>
24 #include <urcu.h>
25 #include <libgen.h>
26 #include <inttypes.h>
27 #include <poll.h>
28 #include <fcntl.h>
29 #include <arpa/inet.h>
31 #include "die.h"
32 #include "xmalloc.h"
33 #include "conntrack.h"
34 #include "config.h"
35 #include "str.h"
36 #include "sig.h"
37 #include "lookup.h"
38 #include "geoip.h"
39 #include "built_in.h"
40 #include "locking.h"
41 #include "pkt_buff.h"
42 #include "screen.h"
43 #include "proc.h"
44 #include "sysctl.h"
46 #ifndef NSEC_PER_SEC
47 #define NSEC_PER_SEC 1000000000L
48 #endif
50 #ifndef USEC_PER_SEC
51 #define USEC_PER_SEC 1000000L
52 #endif
54 struct flow_entry {
55 uint32_t flow_id, use, status;
56 uint8_t l3_proto, l4_proto;
57 uint32_t ip4_src_addr, ip4_dst_addr;
58 uint32_t ip6_src_addr[4], ip6_dst_addr[4];
59 uint16_t port_src, port_dst;
60 uint8_t tcp_state, tcp_flags, sctp_state, dccp_state;
61 uint64_t pkts_src, bytes_src;
62 uint64_t pkts_dst, bytes_dst;
63 uint64_t timestamp_start, timestamp_stop;
64 char country_src[128], country_dst[128];
65 char city_src[128], city_dst[128];
66 char rev_dns_src[256], rev_dns_dst[256];
67 char procname[256];
68 struct flow_entry *next;
69 int inode;
70 unsigned int procnum;
71 bool is_visible;
72 struct nf_conntrack *ct;
73 struct timeval last_update;
74 double rate_bytes_src;
75 double rate_bytes_dst;
76 double rate_pkts_src;
77 double rate_pkts_dst;
80 struct flow_list {
81 struct flow_entry *head;
82 struct spinlock lock;
85 enum flow_direction {
86 FLOW_DIR_SRC,
87 FLOW_DIR_DST,
90 #ifndef ATTR_TIMESTAMP_START
91 # define ATTR_TIMESTAMP_START 63
92 #endif
93 #ifndef ATTR_TIMESTAMP_STOP
94 # define ATTR_TIMESTAMP_STOP 64
95 #endif
97 #define SCROLL_MAX 1000
99 #define INCLUDE_IPV4 (1 << 0)
100 #define INCLUDE_IPV6 (1 << 1)
101 #define INCLUDE_UDP (1 << 2)
102 #define INCLUDE_TCP (1 << 3)
103 #define INCLUDE_DCCP (1 << 4)
104 #define INCLUDE_ICMP (1 << 5)
105 #define INCLUDE_SCTP (1 << 6)
107 #define TOGGLE_FLAG(what, flag) \
108 do { \
109 if (what & flag) \
110 what &= ~flag; \
111 else \
112 what |= flag; \
113 } while (0)
115 struct sysctl_params_ctx {
116 int nfct_acct;
117 int nfct_tstamp;
120 enum rate_units {
121 RATE_BITS,
122 RATE_BYTES
125 static volatile bool do_reload_flows;
126 static volatile bool is_flow_collecting;
127 static volatile sig_atomic_t sigint = 0;
128 static int what = INCLUDE_IPV4 | INCLUDE_IPV6 | INCLUDE_TCP;
129 static struct flow_list flow_list;
130 static struct sysctl_params_ctx sysctl = { -1, -1 };
132 static unsigned int cols, rows;
134 static unsigned int interval = 1;
135 static bool show_src = false;
136 static bool resolve_dns = true;
137 static bool resolve_geoip = true;
138 static enum rate_units rate_type = RATE_BYTES;
139 static bool show_active_only = false;
141 static const char *short_options = "vhTUsDIS46ut:nGb";
142 static const struct option long_options[] = {
143 {"ipv4", no_argument, NULL, '4'},
144 {"ipv6", no_argument, NULL, '6'},
145 {"tcp", no_argument, NULL, 'T'},
146 {"udp", no_argument, NULL, 'U'},
147 {"dccp", no_argument, NULL, 'D'},
148 {"icmp", no_argument, NULL, 'I'},
149 {"sctp", no_argument, NULL, 'S'},
150 {"no-dns", no_argument, NULL, 'n'},
151 {"no-geoip", no_argument, NULL, 'G'},
152 {"show-src", no_argument, NULL, 's'},
153 {"bits", no_argument, NULL, 'b'},
154 {"update", no_argument, NULL, 'u'},
155 {"interval", required_argument, NULL, 't'},
156 {"version", no_argument, NULL, 'v'},
157 {"help", no_argument, NULL, 'h'},
158 {NULL, 0, NULL, 0}
161 static const char *copyright = "Please report bugs to <netsniff-ng@googlegroups.com>\n"
162 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>\n"
163 "Copyright (C) 2011-2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>\n"
164 "Swiss federal institute of technology (ETH Zurich)\n"
165 "License: GNU GPL version 2.0\n"
166 "This is free software: you are free to change and redistribute it.\n"
167 "There is NO WARRANTY, to the extent permitted by law.";
169 static const char *const l3proto2str[AF_MAX] = {
170 [AF_INET] = "ipv4",
171 [AF_INET6] = "ipv6",
174 static const char *const l4proto2str[IPPROTO_MAX] = {
175 [IPPROTO_TCP] = "tcp",
176 [IPPROTO_UDP] = "udp",
177 [IPPROTO_UDPLITE] = "udplite",
178 [IPPROTO_ICMP] = "icmp",
179 [IPPROTO_ICMPV6] = "icmpv6",
180 [IPPROTO_SCTP] = "sctp",
181 [IPPROTO_GRE] = "gre",
182 [IPPROTO_DCCP] = "dccp",
183 [IPPROTO_IGMP] = "igmp",
184 [IPPROTO_IPIP] = "ipip",
185 [IPPROTO_EGP] = "egp",
186 [IPPROTO_PUP] = "pup",
187 [IPPROTO_IDP] = "idp",
188 [IPPROTO_RSVP] = "rsvp",
189 [IPPROTO_IPV6] = "ip6tun",
190 [IPPROTO_ESP] = "esp",
191 [IPPROTO_AH] = "ah",
192 [IPPROTO_PIM] = "pim",
193 [IPPROTO_COMP] = "comp",
196 static const char *const tcp_state2str[TCP_CONNTRACK_MAX] = {
197 [TCP_CONNTRACK_NONE] = "NOSTATE",
198 [TCP_CONNTRACK_SYN_SENT] = "SYN_SENT",
199 [TCP_CONNTRACK_SYN_RECV] = "SYN_RECV",
200 [TCP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
201 [TCP_CONNTRACK_FIN_WAIT] = "FIN_WAIT",
202 [TCP_CONNTRACK_CLOSE_WAIT] = "CLOSE_WAIT",
203 [TCP_CONNTRACK_LAST_ACK] = "LAST_ACK",
204 [TCP_CONNTRACK_TIME_WAIT] = "TIME_WAIT",
205 [TCP_CONNTRACK_CLOSE] = "CLOSE",
206 [TCP_CONNTRACK_SYN_SENT2] = "SYN_SENT2",
209 static const char *const dccp_state2str[DCCP_CONNTRACK_MAX] = {
210 [DCCP_CONNTRACK_NONE] = "NOSTATE",
211 [DCCP_CONNTRACK_REQUEST] = "REQUEST",
212 [DCCP_CONNTRACK_RESPOND] = "RESPOND",
213 [DCCP_CONNTRACK_PARTOPEN] = "PARTOPEN",
214 [DCCP_CONNTRACK_OPEN] = "OPEN",
215 [DCCP_CONNTRACK_CLOSEREQ] = "CLOSEREQ",
216 [DCCP_CONNTRACK_CLOSING] = "CLOSING",
217 [DCCP_CONNTRACK_TIMEWAIT] = "TIMEWAIT",
218 [DCCP_CONNTRACK_IGNORE] = "IGNORE",
219 [DCCP_CONNTRACK_INVALID] = "INVALID",
222 static const char *const sctp_state2str[SCTP_CONNTRACK_MAX] = {
223 [SCTP_CONNTRACK_NONE] = "NOSTATE",
224 [SCTP_CONNTRACK_CLOSED] = "CLOSED",
225 [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE_WAIT",
226 [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE_ECHOED",
227 [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
228 [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTDOWN_SENT",
229 [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTDOWN_RECD",
230 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTDOWN_ACK_SENT",
233 static const struct nfct_filter_ipv4 filter_ipv4 = {
234 .addr = __constant_htonl(INADDR_LOOPBACK),
235 .mask = 0xffffffff,
238 static const struct nfct_filter_ipv6 filter_ipv6 = {
239 .addr = { 0x0, 0x0, 0x0, 0x1 },
240 .mask = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
243 static int64_t time_after_us(struct timeval *tv)
245 struct timeval now;
247 bug_on(gettimeofday(&now, NULL));
249 now.tv_sec -= tv->tv_sec;
250 now.tv_usec -= tv->tv_usec;
252 return now.tv_sec * USEC_PER_SEC + now.tv_usec;
255 static void signal_handler(int number)
257 switch (number) {
258 case SIGINT:
259 case SIGQUIT:
260 case SIGTERM:
261 sigint = 1;
262 break;
263 case SIGHUP:
264 default:
265 break;
269 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct);
270 static void flow_entry_get_extended(struct flow_entry *n);
272 static void help(void)
274 printf("flowtop %s, top-like netfilter TCP/UDP/SCTP/.. flow tracking\n",
275 VERSION_STRING);
276 puts("http://www.netsniff-ng.org\n\n"
277 "Usage: flowtop [options]\n"
278 "Options:\n"
279 " -4|--ipv4 Show only IPv4 flows (default)\n"
280 " -6|--ipv6 Show only IPv6 flows (default)\n"
281 " -T|--tcp Show only TCP flows (default)\n"
282 " -U|--udp Show only UDP flows\n"
283 " -D|--dccp Show only DCCP flows\n"
284 " -I|--icmp Show only ICMP/ICMPv6 flows\n"
285 " -S|--sctp Show only SCTP flows\n"
286 " -n|--no-dns Don't perform hostname lookup\n"
287 " -G|--no-geoip Don't perform GeoIP lookup\n"
288 " -s|--show-src Also show source, not only dest\n"
289 " -b|--bits Show rates in bits/s instead of bytes/s\n"
290 " -u|--update Update GeoIP databases\n"
291 " -t|--interval <time> Refresh time in seconds (default 1s)\n"
292 " -v|--version Print version and exit\n"
293 " -h|--help Print this help and exit\n\n"
294 "Examples:\n"
295 " flowtop\n"
296 " flowtop -46UTDISs\n\n"
297 "Note:\n"
298 " If netfilter is not running, you can activate it with e.g.:\n"
299 " iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT\n"
300 " iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT\n");
301 puts(copyright);
302 die();
305 static void version(void)
307 printf("flowtop %s, Git id: %s\n", VERSION_LONG, GITVERSION);
308 puts("top-like netfilter TCP/UDP/SCTP/.. flow tracking\n"
309 "http://www.netsniff-ng.org\n");
310 puts(copyright);
311 die();
314 static void flow_entry_update_time(struct flow_entry *n)
316 bug_on(gettimeofday(&n->last_update, NULL));
319 #define CALC_RATE(fld) do { \
320 n->rate_##fld = (((fld) > n->fld) ? (((fld) - n->fld) / sec) : 0); \
321 } while (0)
323 static void flow_entry_calc_rate(struct flow_entry *n, const struct nf_conntrack *ct)
325 uint64_t bytes_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_BYTES);
326 uint64_t bytes_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_BYTES);
327 uint64_t pkts_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_PACKETS);
328 uint64_t pkts_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_PACKETS);
329 double sec = (double)time_after_us(&n->last_update) / USEC_PER_SEC;
331 if (sec < 1)
332 return;
334 CALC_RATE(bytes_src);
335 CALC_RATE(bytes_dst);
336 CALC_RATE(pkts_src);
337 CALC_RATE(pkts_dst);
340 static inline struct flow_entry *flow_entry_xalloc(void)
342 return xzmalloc(sizeof(struct flow_entry));
345 static inline void flow_entry_xfree(struct flow_entry *n)
347 if (n->ct)
348 nfct_destroy(n->ct);
350 xfree(n);
353 static inline void flow_list_init(struct flow_list *fl)
355 fl->head = NULL;
356 spinlock_init(&fl->lock);
359 static inline bool nfct_is_dns(const struct nf_conntrack *ct)
361 uint16_t port_src = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
362 uint16_t port_dst = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
364 return ntohs(port_src) == 53 || ntohs(port_dst) == 53;
367 static void flow_list_new_entry(struct flow_list *fl, const struct nf_conntrack *ct)
369 struct flow_entry *n;
371 /* We don't want to analyze / display DNS itself, since we
372 * use it to resolve reverse dns.
374 if (nfct_is_dns(ct))
375 return;
377 n = flow_entry_xalloc();
379 n->ct = nfct_clone(ct);
381 flow_entry_update_time(n);
382 flow_entry_from_ct(n, ct);
383 flow_entry_get_extended(n);
385 rcu_assign_pointer(n->next, fl->head);
386 rcu_assign_pointer(fl->head, n);
388 n->is_visible = true;
391 static struct flow_entry *flow_list_find_id(struct flow_list *fl,
392 uint32_t id)
394 struct flow_entry *n = rcu_dereference(fl->head);
396 while (n != NULL) {
397 if (n->flow_id == id)
398 return n;
400 n = rcu_dereference(n->next);
403 return NULL;
406 static struct flow_entry *flow_list_find_prev_id(const struct flow_list *fl,
407 uint32_t id)
409 struct flow_entry *prev = rcu_dereference(fl->head), *next;
411 if (prev->flow_id == id)
412 return NULL;
414 while ((next = rcu_dereference(prev->next)) != NULL) {
415 if (next->flow_id == id)
416 return prev;
418 prev = next;
421 return NULL;
424 static void flow_list_update_entry(struct flow_list *fl,
425 const struct nf_conntrack *ct)
427 struct flow_entry *n;
429 n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
430 if (n == NULL) {
431 flow_list_new_entry(fl, ct);
432 return;
435 flow_entry_from_ct(n, ct);
438 static void flow_list_destroy_entry(struct flow_list *fl,
439 const struct nf_conntrack *ct)
441 struct flow_entry *n1, *n2;
442 uint32_t id = nfct_get_attr_u32(ct, ATTR_ID);
444 n1 = flow_list_find_id(fl, id);
445 if (n1) {
446 n2 = flow_list_find_prev_id(fl, id);
447 if (n2) {
448 rcu_assign_pointer(n2->next, n1->next);
449 n1->next = NULL;
451 flow_entry_xfree(n1);
452 } else {
453 struct flow_entry *next = fl->head->next;
455 flow_entry_xfree(fl->head);
456 fl->head = next;
461 static void flow_list_destroy(struct flow_list *fl)
463 struct flow_entry *n;
465 synchronize_rcu();
466 spinlock_lock(&flow_list.lock);
468 while (fl->head != NULL) {
469 n = rcu_dereference(fl->head->next);
470 fl->head->next = NULL;
472 flow_entry_xfree(fl->head);
473 rcu_assign_pointer(fl->head, n);
476 spinlock_unlock(&flow_list.lock);
479 static int walk_process(unsigned int pid, struct flow_entry *n)
481 int ret;
482 DIR *dir;
483 struct dirent *ent;
484 char path[1024];
486 if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
487 panic("giant process name! %u\n", pid);
489 dir = opendir(path);
490 if (!dir)
491 return 0;
493 while ((ent = readdir(dir))) {
494 struct stat statbuf;
496 if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
497 pid, ent->d_name) < 0)
498 continue;
500 if (stat(path, &statbuf) < 0)
501 continue;
503 if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == statbuf.st_ino) {
504 char cmdline[256];
506 ret = proc_get_cmdline(pid, cmdline, sizeof(cmdline));
507 if (ret < 0)
508 panic("Failed to get process cmdline: %s\n", strerror(errno));
510 if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0)
511 n->procname[0] = '\0';
512 n->procnum = pid;
513 closedir(dir);
514 return 1;
518 closedir(dir);
519 return 0;
522 static void walk_processes(struct flow_entry *n)
524 int ret;
525 DIR *dir;
526 struct dirent *ent;
528 /* n->inode must be set */
529 if (n->inode <= 0) {
530 n->procname[0] = '\0';
531 return;
534 dir = opendir("/proc");
535 if (!dir)
536 panic("Cannot open /proc: %s\n", strerror(errno));
538 while ((ent = readdir(dir))) {
539 const char *name = ent->d_name;
540 char *end;
541 unsigned int pid = strtoul(name, &end, 10);
543 /* not a PID */
544 if (pid == 0 && end == name)
545 continue;
547 ret = walk_process(pid, n);
548 if (ret > 0)
549 break;
552 closedir(dir);
555 static int get_port_inode(uint16_t port, int proto, bool is_ip6)
557 int ret = -ENOENT;
558 char path[128], buff[1024];
559 FILE *proc;
561 memset(path, 0, sizeof(path));
562 snprintf(path, sizeof(path), "/proc/net/%s%s",
563 l4proto2str[proto], is_ip6 ? "6" : "");
565 proc = fopen(path, "r");
566 if (!proc)
567 return -EIO;
569 memset(buff, 0, sizeof(buff));
571 while (fgets(buff, sizeof(buff), proc) != NULL) {
572 int inode = 0;
573 unsigned int lport = 0;
575 buff[sizeof(buff) - 1] = 0;
576 if (sscanf(buff, "%*u: %*X:%X %*X:%*X %*X %*X:%*X %*X:%*X "
577 "%*X %*u %*u %u", &lport, &inode) == 2) {
578 if ((uint16_t) lport == port) {
579 ret = inode;
580 break;
584 memset(buff, 0, sizeof(buff));
587 fclose(proc);
588 return ret;
591 #define CP_NFCT(elem, attr, x) \
592 do { n->elem = nfct_get_attr_u##x(ct,(attr)); } while (0)
593 #define CP_NFCT_BUFF(elem, attr) do { \
594 const uint8_t *buff = nfct_get_attr(ct,(attr)); \
595 if (buff != NULL) \
596 memcpy(n->elem, buff, sizeof(n->elem)); \
597 } while (0)
599 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct)
601 CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
602 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
604 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
605 CP_NFCT(ip4_dst_addr, ATTR_ORIG_IPV4_DST, 32);
607 CP_NFCT(port_src, ATTR_ORIG_PORT_SRC, 16);
608 CP_NFCT(port_dst, ATTR_ORIG_PORT_DST, 16);
610 CP_NFCT(status, ATTR_STATUS, 32);
612 CP_NFCT(tcp_state, ATTR_TCP_STATE, 8);
613 CP_NFCT(tcp_flags, ATTR_TCP_FLAGS_ORIG, 8);
614 CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
615 CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
617 CP_NFCT(pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
618 CP_NFCT(bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
620 CP_NFCT(pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
621 CP_NFCT(bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
623 CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
624 CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
626 CP_NFCT(flow_id, ATTR_ID, 32);
627 CP_NFCT(use, ATTR_USE, 32);
629 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
630 CP_NFCT_BUFF(ip6_dst_addr, ATTR_ORIG_IPV6_DST);
632 n->port_src = ntohs(n->port_src);
633 n->port_dst = ntohs(n->port_dst);
635 n->ip4_src_addr = ntohl(n->ip4_src_addr);
636 n->ip4_dst_addr = ntohl(n->ip4_dst_addr);
639 #define SELFLD(dir,src_member,dst_member) \
640 (((dir) == FLOW_DIR_SRC) ? n->src_member : n->dst_member)
642 static void flow_entry_get_sain4_obj(const struct flow_entry *n,
643 enum flow_direction dir,
644 struct sockaddr_in *sa)
646 memset(sa, 0, sizeof(*sa));
647 sa->sin_family = PF_INET;
648 sa->sin_addr.s_addr = htonl(SELFLD(dir, ip4_src_addr, ip4_dst_addr));
651 static void flow_entry_get_sain6_obj(const struct flow_entry *n,
652 enum flow_direction dir,
653 struct sockaddr_in6 *sa)
655 memset(sa, 0, sizeof(*sa));
656 sa->sin6_family = PF_INET6;
658 memcpy(&sa->sin6_addr, SELFLD(dir, ip6_src_addr, ip6_dst_addr),
659 sizeof(sa->sin6_addr));
662 static void
663 flow_entry_geo_city_lookup_generic(struct flow_entry *n,
664 enum flow_direction dir)
666 struct sockaddr_in sa4;
667 struct sockaddr_in6 sa6;
668 const char *city = NULL;
670 switch (n->l3_proto) {
671 default:
672 bug();
674 case AF_INET:
675 flow_entry_get_sain4_obj(n, dir, &sa4);
676 city = geoip4_city_name(&sa4);
677 break;
679 case AF_INET6:
680 flow_entry_get_sain6_obj(n, dir, &sa6);
681 city = geoip6_city_name(&sa6);
682 break;
685 build_bug_on(sizeof(n->city_src) != sizeof(n->city_dst));
687 if (city)
688 strlcpy(SELFLD(dir, city_src, city_dst), city,
689 sizeof(n->city_src));
690 else
691 SELFLD(dir, city_src, city_dst)[0] = '\0';
694 static void
695 flow_entry_geo_country_lookup_generic(struct flow_entry *n,
696 enum flow_direction dir)
698 struct sockaddr_in sa4;
699 struct sockaddr_in6 sa6;
700 const char *country = NULL;
702 switch (n->l3_proto) {
703 default:
704 bug();
706 case AF_INET:
707 flow_entry_get_sain4_obj(n, dir, &sa4);
708 country = geoip4_country_name(&sa4);
709 break;
711 case AF_INET6:
712 flow_entry_get_sain6_obj(n, dir, &sa6);
713 country = geoip6_country_name(&sa6);
714 break;
717 build_bug_on(sizeof(n->country_src) != sizeof(n->country_dst));
719 if (country)
720 strlcpy(SELFLD(dir, country_src, country_dst), country,
721 sizeof(n->country_src));
722 else
723 SELFLD(dir, country_src, country_dst)[0] = '\0';
726 static void flow_entry_get_extended_geo(struct flow_entry *n,
727 enum flow_direction dir)
729 if (resolve_geoip) {
730 flow_entry_geo_city_lookup_generic(n, dir);
731 flow_entry_geo_country_lookup_generic(n, dir);
735 static void flow_entry_get_extended_revdns(struct flow_entry *n,
736 enum flow_direction dir)
738 size_t sa_len;
739 struct sockaddr_in sa4;
740 struct sockaddr_in6 sa6;
741 struct sockaddr *sa;
742 struct hostent *hent;
744 build_bug_on(sizeof(n->rev_dns_src) != sizeof(n->rev_dns_dst));
746 switch (n->l3_proto) {
747 default:
748 bug();
750 case AF_INET:
751 flow_entry_get_sain4_obj(n, dir, &sa4);
753 if (!resolve_dns) {
754 inet_ntop(AF_INET, &sa4.sin_addr,
755 SELFLD(dir, rev_dns_src, rev_dns_dst),
756 sizeof(n->rev_dns_src));
757 return;
760 sa = (struct sockaddr *) &sa4;
761 sa_len = sizeof(sa4);
762 hent = gethostbyaddr(&sa4.sin_addr, sizeof(sa4.sin_addr), AF_INET);
763 break;
765 case AF_INET6:
766 flow_entry_get_sain6_obj(n, dir, &sa6);
768 if (!resolve_dns) {
769 inet_ntop(AF_INET6, &sa6.sin6_addr,
770 SELFLD(dir, rev_dns_src, rev_dns_dst),
771 sizeof(n->rev_dns_src));
772 return;
775 sa = (struct sockaddr *) &sa6;
776 sa_len = sizeof(sa6);
777 hent = gethostbyaddr(&sa6.sin6_addr, sizeof(sa6.sin6_addr), AF_INET6);
778 break;
781 getnameinfo(sa, sa_len, SELFLD(dir, rev_dns_src, rev_dns_dst),
782 sizeof(n->rev_dns_src), NULL, 0, NI_NUMERICHOST);
784 if (hent)
785 strlcpy(SELFLD(dir, rev_dns_src, rev_dns_dst), hent->h_name,
786 sizeof(n->rev_dns_src));
789 static void flow_entry_get_extended(struct flow_entry *n)
791 if (n->flow_id == 0)
792 return;
794 if (show_src) {
795 flow_entry_get_extended_revdns(n, FLOW_DIR_SRC);
796 flow_entry_get_extended_geo(n, FLOW_DIR_SRC);
799 flow_entry_get_extended_revdns(n, FLOW_DIR_DST);
800 flow_entry_get_extended_geo(n, FLOW_DIR_DST);
802 /* Lookup application */
803 n->inode = get_port_inode(n->port_src, n->l4_proto,
804 n->l3_proto == AF_INET6);
805 if (n->inode > 0)
806 walk_processes(n);
809 static uint16_t presenter_get_port(uint16_t src, uint16_t dst, bool is_tcp)
811 if (src < dst && src < 1024) {
812 return src;
813 } else if (dst < src && dst < 1024) {
814 return dst;
815 } else {
816 const char *tmp1, *tmp2;
817 if (is_tcp) {
818 tmp1 = lookup_port_tcp(src);
819 tmp2 = lookup_port_tcp(dst);
820 } else {
821 tmp1 = lookup_port_udp(src);
822 tmp2 = lookup_port_udp(dst);
824 if (tmp1 && !tmp2) {
825 return src;
826 } else if (!tmp1 && tmp2) {
827 return dst;
828 } else {
829 if (src < dst)
830 return src;
831 else
832 return dst;
837 static char *bandw2str(double bytes, char *buf, size_t len)
839 if (bytes > 1000000000.)
840 snprintf(buf, len, "%.1fGB", bytes / 1000000000.);
841 else if (bytes > 1000000.)
842 snprintf(buf, len, "%.1fMB", bytes / 1000000.);
843 else if (bytes > 1000.)
844 snprintf(buf, len, "%.1fkB", bytes / 1000.);
845 else
846 snprintf(buf, len, "%g bytes", bytes);
848 return buf;
851 static char *rate2str(double rate, char *buf, size_t len)
853 const char * const unit_fmt[2][4] = {
854 { "%.1fGbit/s", "%.1fMbit/s", "%.1fkbit/s", "%gbit/s" },
855 { "%.1fGB/s", "%.1fMB/s", "%.1fkB/s", "%gB/s" }
858 if (rate_type == RATE_BITS)
859 rate *= 8;
861 if (rate > 1000000000.)
862 snprintf(buf, len, unit_fmt[rate_type][0], rate / 1000000000.);
863 else if (rate > 1000000.)
864 snprintf(buf, len, unit_fmt[rate_type][1], rate / 1000000.);
865 else if (rate > 1000.)
866 snprintf(buf, len, unit_fmt[rate_type][2], rate / 1000.);
867 else
868 snprintf(buf, len, unit_fmt[rate_type][3], rate);
870 return buf;
873 static void presenter_print_counters(uint64_t bytes, uint64_t pkts,
874 double rate_bytes, double rate_pkts,
875 int color)
877 char bytes_str[64];
879 printw(" -> (");
880 attron(COLOR_PAIR(color));
881 printw("%"PRIu64" pkts", pkts);
882 if (rate_pkts) {
883 attron(COLOR_PAIR(3));
884 printw("(%.1fpps)", rate_pkts);
885 attron(COLOR_PAIR(color));
888 printw(", %s", bandw2str(bytes, bytes_str, sizeof(bytes_str) - 1));
889 if (rate_bytes) {
890 attron(COLOR_PAIR(3));
891 printw("(%s)", rate2str(rate_bytes, bytes_str,
892 sizeof(bytes_str) - 1));
893 attron(COLOR_PAIR(color));
895 attroff(COLOR_PAIR(color));
896 printw(")");
899 static void presenter_print_flow_entry_time(const struct flow_entry *n)
901 int h, m, s;
902 time_t now;
904 time(&now);
906 s = now - (n->timestamp_start / NSEC_PER_SEC);
907 if (s <= 0)
908 return;
910 h = s / 3600;
911 s -= h * 3600;
912 m = s / 60;
913 s -= m * 60;
915 printw(" [ time");
916 if (h > 0)
917 printw(" %dh", h);
918 if (m > 0)
919 printw(" %dm", m);
920 if (s > 0)
921 printw(" %ds", s);
922 printw(" ]");
925 static void draw_flow_entry(WINDOW *screen, const struct flow_entry *n,
926 unsigned int *line)
928 char tmp[128];
929 const char *pname = NULL;
930 uint16_t port;
932 mvwprintw(screen, *line, 2, "");
934 /* PID, application name */
935 if (n->procnum > 0) {
936 slprintf(tmp, sizeof(tmp), "%s(%d)", n->procname, n->procnum);
938 printw("[");
939 attron(COLOR_PAIR(3));
940 printw("%s", tmp);
941 attroff(COLOR_PAIR(3));
942 printw("]:");
945 /* L3 protocol, L4 protocol, states */
946 printw("%s:%s", l3proto2str[n->l3_proto], l4proto2str[n->l4_proto]);
947 printw("[");
948 attron(COLOR_PAIR(3));
949 switch (n->l4_proto) {
950 case IPPROTO_TCP:
951 printw("%s", tcp_state2str[n->tcp_state]);
952 break;
953 case IPPROTO_SCTP:
954 printw("%s", sctp_state2str[n->sctp_state]);
955 break;
956 case IPPROTO_DCCP:
957 printw("%s", dccp_state2str[n->dccp_state]);
958 break;
959 case IPPROTO_UDP:
960 case IPPROTO_UDPLITE:
961 case IPPROTO_ICMP:
962 case IPPROTO_ICMPV6:
963 printw("NOSTATE");
964 break;
966 attroff(COLOR_PAIR(3));
967 printw("]");
969 /* Guess application port */
970 switch (n->l4_proto) {
971 case IPPROTO_TCP:
972 port = presenter_get_port(n->port_src, n->port_dst, true);
973 pname = lookup_port_tcp(port);
974 break;
975 case IPPROTO_UDP:
976 case IPPROTO_UDPLITE:
977 port = presenter_get_port(n->port_src, n->port_dst, false);
978 pname = lookup_port_udp(port);
979 break;
981 if (pname) {
982 attron(A_BOLD);
983 printw(":%s", pname);
984 attroff(A_BOLD);
987 if (n->timestamp_start > 0)
988 presenter_print_flow_entry_time(n);
990 /* Show source information: reverse DNS, port, country, city, counters */
991 if (show_src) {
992 attron(COLOR_PAIR(1));
993 mvwprintw(screen, ++(*line), 8, "src: %s", n->rev_dns_src);
994 attroff(COLOR_PAIR(1));
996 printw(":%"PRIu16, n->port_src);
998 if (n->country_src[0]) {
999 printw(" (");
1001 attron(COLOR_PAIR(4));
1002 printw("%s", n->country_src);
1003 attroff(COLOR_PAIR(4));
1005 if (n->city_src[0])
1006 printw(", %s", n->city_src);
1008 printw(")");
1011 if (n->pkts_src > 0 && n->bytes_src > 0)
1012 presenter_print_counters(n->bytes_src, n->pkts_src,
1013 n->rate_bytes_src,
1014 n->rate_pkts_src, 1);
1016 printw(" => ");
1019 /* Show dest information: reverse DNS, port, country, city, counters */
1020 attron(COLOR_PAIR(2));
1021 mvwprintw(screen, ++(*line), 8, "dst: %s", n->rev_dns_dst);
1022 attroff(COLOR_PAIR(2));
1024 printw(":%"PRIu16, n->port_dst);
1026 if (n->country_dst[0]) {
1027 printw(" (");
1029 attron(COLOR_PAIR(4));
1030 printw("%s", n->country_dst);
1031 attroff(COLOR_PAIR(4));
1033 if (n->city_dst[0])
1034 printw(", %s", n->city_dst);
1036 printw(")");
1039 if (n->pkts_dst > 0 && n->bytes_dst > 0)
1040 presenter_print_counters(n->bytes_dst, n->pkts_dst,
1041 n->rate_bytes_dst,
1042 n->rate_pkts_dst, 2);
1045 static inline bool presenter_flow_wrong_state(struct flow_entry *n)
1047 switch (n->l4_proto) {
1048 case IPPROTO_TCP:
1049 switch (n->tcp_state) {
1050 case TCP_CONNTRACK_SYN_SENT:
1051 case TCP_CONNTRACK_SYN_RECV:
1052 case TCP_CONNTRACK_ESTABLISHED:
1053 case TCP_CONNTRACK_FIN_WAIT:
1054 case TCP_CONNTRACK_CLOSE_WAIT:
1055 case TCP_CONNTRACK_LAST_ACK:
1056 case TCP_CONNTRACK_TIME_WAIT:
1057 case TCP_CONNTRACK_CLOSE:
1058 case TCP_CONNTRACK_SYN_SENT2:
1059 case TCP_CONNTRACK_NONE:
1060 return false;
1061 break;
1063 break;
1064 case IPPROTO_SCTP:
1065 switch (n->sctp_state) {
1066 case SCTP_CONNTRACK_NONE:
1067 case SCTP_CONNTRACK_CLOSED:
1068 case SCTP_CONNTRACK_COOKIE_WAIT:
1069 case SCTP_CONNTRACK_COOKIE_ECHOED:
1070 case SCTP_CONNTRACK_ESTABLISHED:
1071 case SCTP_CONNTRACK_SHUTDOWN_SENT:
1072 case SCTP_CONNTRACK_SHUTDOWN_RECD:
1073 case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT:
1074 return false;
1075 break;
1077 break;
1078 case IPPROTO_DCCP:
1079 switch (n->dccp_state) {
1080 case DCCP_CONNTRACK_NONE:
1081 case DCCP_CONNTRACK_REQUEST:
1082 case DCCP_CONNTRACK_RESPOND:
1083 case DCCP_CONNTRACK_PARTOPEN:
1084 case DCCP_CONNTRACK_OPEN:
1085 case DCCP_CONNTRACK_CLOSEREQ:
1086 case DCCP_CONNTRACK_CLOSING:
1087 case DCCP_CONNTRACK_TIMEWAIT:
1088 case DCCP_CONNTRACK_IGNORE:
1089 case DCCP_CONNTRACK_INVALID:
1090 return false;
1091 break;
1093 break;
1094 case IPPROTO_UDP:
1095 case IPPROTO_UDPLITE:
1096 case IPPROTO_ICMP:
1097 case IPPROTO_ICMPV6:
1098 return false;
1099 break;
1102 return true;
1105 static void draw_flows(WINDOW *screen, struct flow_list *fl,
1106 int skip_lines)
1108 int skip_left = skip_lines;
1109 unsigned int flows = 0;
1110 unsigned int line = 3;
1111 struct flow_entry *n;
1112 int maxy = rows - 6;
1114 wclear(screen);
1115 clear();
1117 rcu_read_lock();
1119 n = rcu_dereference(fl->head);
1120 if (!n)
1121 mvwprintw(screen, line, 2, "(No sessions! "
1122 "Is netfilter running?)");
1124 for (; n; n = rcu_dereference(n->next)) {
1125 if (!n->is_visible)
1126 continue;
1128 if (presenter_flow_wrong_state(n))
1129 continue;
1131 /* count only flows which might be showed */
1132 flows++;
1134 if (maxy <= 0)
1135 continue;
1137 if (skip_left > 0) {
1138 skip_left--;
1139 continue;
1142 draw_flow_entry(screen, n, &line);
1144 line++;
1145 maxy -= (2 + (show_src ? 1 : 0));
1148 mvwprintw(screen, 1, 2, "Kernel netfilter flows(%u) for ", flows);
1150 if (what & INCLUDE_IPV4)
1151 printw("IPv4,");
1152 if (what & INCLUDE_IPV6)
1153 printw("IPv6,");
1154 if (what & INCLUDE_TCP)
1155 printw("TCP,");
1156 if (what & INCLUDE_UDP)
1157 printw("UDP,");
1158 if (what & INCLUDE_SCTP)
1159 printw("SCTP,");
1160 if (what & INCLUDE_DCCP)
1161 printw("DCCP,");
1162 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1163 printw("ICMP,");
1164 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1165 printw("ICMP6,");
1166 if (show_active_only)
1167 printw("Active,");
1169 printw(" [+%d]", skip_lines);
1171 if (is_flow_collecting)
1172 printw(" [Collecting flows ...]");
1174 rcu_read_unlock();
1177 static void draw_help(WINDOW *screen)
1179 int col = 0;
1180 int row = 1;
1181 int i;
1183 mvaddch(row, col, ACS_ULCORNER);
1184 mvaddch(rows - row - 1, col, ACS_LLCORNER);
1186 mvaddch(row, cols - 1, ACS_URCORNER);
1187 mvaddch(rows - row - 1, cols - 1, ACS_LRCORNER);
1189 for (i = 1; i < rows - row - 2; i++) {
1190 mvaddch(row + i, 0, ACS_VLINE);
1191 mvaddch(row + i, cols - 1, ACS_VLINE);
1193 for (i = 1; i < cols - col - 1; i++) {
1194 mvaddch(row, col + i, ACS_HLINE);
1195 mvaddch(rows - row - 1, col + i, ACS_HLINE);
1198 attron(A_BOLD);
1199 mvaddnstr(row, cols / 2 - 2, "| Help |", -1);
1201 attron(A_UNDERLINE);
1202 mvaddnstr(row + 2, col + 2, "Navigation", -1);
1203 attroff(A_BOLD | A_UNDERLINE);
1205 mvaddnstr(row + 4, col + 3, "Up, u, k Move up", -1);
1206 mvaddnstr(row + 5, col + 3, "Down, d, j Move down", -1);
1207 mvaddnstr(row + 6, col + 3, "? Toggle help window", -1);
1208 mvaddnstr(row + 7, col + 3, "q, Ctrl+C Quit", -1);
1210 attron(A_BOLD | A_UNDERLINE);
1211 mvaddnstr(row + 9, col + 2, "Display Settings", -1);
1212 attroff(A_BOLD | A_UNDERLINE);
1214 mvaddnstr(row + 11, col + 3, "b Toggle rate units (bits/bytes)", -1);
1215 mvaddnstr(row + 12, col + 3, "a Toggle display of active flows (rate > 0) only", -1);
1217 mvaddnstr(row + 14, col + 3, "T Toggle display TCP flows", -1);
1218 mvaddnstr(row + 15, col + 3, "U Toggle display UDP flows", -1);
1219 mvaddnstr(row + 16, col + 3, "D Toggle display DCCP flows", -1);
1220 mvaddnstr(row + 17, col + 3, "I Toggle display ICMP flows", -1);
1221 mvaddnstr(row + 18, col + 3, "S Toggle display SCTP flows", -1);
1224 static void draw_header(WINDOW *screen)
1226 int i;
1228 attron(A_STANDOUT);
1230 for (i = 0; i < cols; i++)
1231 mvaddch(0, i, ' ');
1233 mvwprintw(screen, 0, 2, "flowtop %s", VERSION_LONG);
1234 attroff(A_STANDOUT);
1237 static void draw_footer(WINDOW *screen)
1239 int i;
1241 attron(A_STANDOUT);
1243 for (i = 0; i < cols; i++)
1244 mvaddch(rows - 1, i, ' ');
1246 mvaddnstr(rows - 1, 1, "Press '?' for help", -1);
1247 addch(ACS_VLINE);
1248 attroff(A_STANDOUT);
1251 static void show_option_toggle(int opt)
1253 switch (opt) {
1254 case 'T':
1255 TOGGLE_FLAG(what, INCLUDE_TCP);
1256 break;
1257 case 'U':
1258 TOGGLE_FLAG(what, INCLUDE_UDP);
1259 break;
1260 case 'D':
1261 TOGGLE_FLAG(what, INCLUDE_DCCP);
1262 break;
1263 case 'I':
1264 TOGGLE_FLAG(what, INCLUDE_ICMP);
1265 break;
1266 case 'S':
1267 TOGGLE_FLAG(what, INCLUDE_SCTP);
1268 break;
1272 static void presenter(void)
1274 int time_sleep_us = 200000;
1275 int time_passed_us = 0;
1276 bool show_help = false;
1277 int skip_lines = 0;
1278 WINDOW *screen;
1280 lookup_init(LT_PORTS_TCP);
1281 lookup_init(LT_PORTS_UDP);
1282 screen = screen_init(false);
1284 start_color();
1285 init_pair(1, COLOR_RED, COLOR_BLACK);
1286 init_pair(2, COLOR_BLUE, COLOR_BLACK);
1287 init_pair(3, COLOR_YELLOW, COLOR_BLACK);
1288 init_pair(4, COLOR_GREEN, COLOR_BLACK);
1290 rcu_register_thread();
1291 while (!sigint) {
1292 bool redraw_flows = true;
1293 int ch;
1295 curs_set(0);
1296 getmaxyx(screen, rows, cols);
1298 ch = getch();
1299 switch (ch) {
1300 case 'q':
1301 sigint = 1;
1302 break;
1303 case KEY_UP:
1304 case 'u':
1305 case 'k':
1306 skip_lines--;
1307 if (skip_lines < 0)
1308 skip_lines = 0;
1309 break;
1310 case KEY_DOWN:
1311 case 'd':
1312 case 'j':
1313 skip_lines++;
1314 if (skip_lines > SCROLL_MAX)
1315 skip_lines = SCROLL_MAX;
1316 break;
1317 case 'b':
1318 if (rate_type == RATE_BYTES)
1319 rate_type = RATE_BITS;
1320 else
1321 rate_type = RATE_BYTES;
1322 break;
1323 case 'a':
1324 show_active_only = !show_active_only;
1325 break;
1326 case '?':
1327 show_help = !show_help;
1328 wclear(screen);
1329 clear();
1330 break;
1331 case 'T':
1332 case 'U':
1333 case 'D':
1334 case 'I':
1335 case 'S':
1336 show_option_toggle(ch);
1337 do_reload_flows = true;
1338 break;
1339 default:
1340 fflush(stdin);
1341 redraw_flows = false;
1342 break;
1345 if (!redraw_flows)
1346 redraw_flows = time_passed_us >= 1 * USEC_PER_SEC;
1348 if (show_help)
1349 redraw_flows = false;
1351 if (redraw_flows) {
1352 draw_flows(screen, &flow_list, skip_lines);
1353 time_passed_us = 0;
1354 } else {
1355 time_passed_us += time_sleep_us;
1358 draw_header(screen);
1360 if (show_help)
1361 draw_help(screen);
1363 draw_footer(screen);
1365 wrefresh(screen);
1366 refresh();
1367 usleep(time_sleep_us);
1369 rcu_unregister_thread();
1371 screen_end();
1372 lookup_cleanup(LT_PORTS_UDP);
1373 lookup_cleanup(LT_PORTS_TCP);
1376 static int flow_event_cb(enum nf_conntrack_msg_type type,
1377 struct nf_conntrack *ct, void *data __maybe_unused)
1379 if (sigint)
1380 return NFCT_CB_STOP;
1382 synchronize_rcu();
1383 spinlock_lock(&flow_list.lock);
1385 switch (type) {
1386 case NFCT_T_NEW:
1387 flow_list_new_entry(&flow_list, ct);
1388 break;
1389 case NFCT_T_UPDATE:
1390 flow_list_update_entry(&flow_list, ct);
1391 break;
1392 case NFCT_T_DESTROY:
1393 flow_list_destroy_entry(&flow_list, ct);
1394 break;
1395 default:
1396 break;
1399 spinlock_unlock(&flow_list.lock);
1401 return NFCT_CB_CONTINUE;
1404 static void restore_sysctl(void *obj)
1406 struct sysctl_params_ctx *sysctl_ctx = obj;
1408 if (sysctl_ctx->nfct_acct == 0)
1409 sysctl_set_int("net/netfilter/nf_conntrack_acct",
1410 sysctl_ctx->nfct_acct);
1412 if (sysctl_ctx->nfct_tstamp == 0)
1413 sysctl_set_int("net/netfilter/nf_conntrack_timestamp",
1414 sysctl_ctx->nfct_tstamp);
1417 static void on_panic_handler(void *arg)
1419 restore_sysctl(arg);
1420 screen_end();
1423 static void conntrack_acct_enable(void)
1425 /* We can still work w/o traffic accounting so just warn about error */
1426 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &sysctl.nfct_acct)) {
1427 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1428 strerror(errno));
1429 return;
1432 if (sysctl.nfct_acct == 1)
1433 return;
1435 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1436 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1437 strerror(errno));
1441 static void conntrack_tstamp_enable(void)
1443 if (sysctl_get_int("net/netfilter/nf_conntrack_timestamp", &sysctl.nfct_tstamp)) {
1444 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_timestamp: %s\n",
1445 strerror(errno));
1446 return;
1449 if (sysctl.nfct_tstamp == 1)
1450 return;
1452 if (sysctl_set_int("net/netfilter/nf_conntrack_timestamp", 1)) {
1453 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_timestamp: %s\n",
1454 strerror(errno));
1458 static void flow_entry_filter(struct flow_entry *n)
1460 if (show_active_only && !n->rate_bytes_src && !n->rate_bytes_dst)
1461 n->is_visible = false;
1462 else
1463 n->is_visible = true;
1466 static int flow_update_cb(enum nf_conntrack_msg_type type,
1467 struct nf_conntrack *ct, void *data __maybe_unused)
1469 struct flow_entry *n;
1471 if (type != NFCT_T_UPDATE)
1472 return NFCT_CB_CONTINUE;
1474 if (sigint)
1475 return NFCT_CB_STOP;
1477 n = flow_list_find_id(&flow_list, nfct_get_attr_u32(ct, ATTR_ID));
1478 if (!n)
1479 return NFCT_CB_CONTINUE;
1481 flow_entry_calc_rate(n, ct);
1482 flow_entry_update_time(n);
1483 flow_entry_from_ct(n, ct);
1484 flow_entry_filter(n);
1486 return NFCT_CB_CONTINUE;
1489 static void collector_refresh_flows(struct nfct_handle *handle)
1491 struct flow_entry *n;
1493 n = rcu_dereference(flow_list.head);
1494 for (; n; n = rcu_dereference(n->next))
1495 nfct_query(handle, NFCT_Q_GET, n->ct);
1498 static void collector_create_filter(struct nfct_handle *nfct)
1500 struct nfct_filter *filter;
1501 int ret;
1503 filter = nfct_filter_create();
1504 if (!filter)
1505 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1507 if (what & INCLUDE_UDP) {
1508 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1509 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1511 if (what & INCLUDE_TCP)
1512 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1513 if (what & INCLUDE_DCCP)
1514 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1515 if (what & INCLUDE_SCTP)
1516 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1517 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1518 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1519 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1520 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1521 if (what & INCLUDE_IPV4) {
1522 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1523 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1525 if (what & INCLUDE_IPV6) {
1526 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1527 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1530 ret = nfct_filter_attach(nfct_fd(nfct), filter);
1531 if (ret < 0)
1532 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1534 nfct_filter_destroy(filter);
1537 /* This hand-crafted filter looks ugly but it allows to do not
1538 * flush nfct connections & filter them by user specified filter.
1539 * May be it is better to replace this one by nfct_cmp. */
1540 static int flow_dump_cb(enum nf_conntrack_msg_type type,
1541 struct nf_conntrack *ct, void *data __maybe_unused)
1543 struct flow_entry fl;
1544 struct flow_entry *n = &fl;
1546 if (sigint)
1547 return NFCT_CB_STOP;
1549 synchronize_rcu();
1550 spinlock_lock(&flow_list.lock);
1552 if (!(what & ~(INCLUDE_IPV4 | INCLUDE_IPV6)))
1553 goto check_addr;
1555 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
1557 if (what & INCLUDE_UDP) {
1558 if (n->l4_proto == IPPROTO_UDP)
1559 goto check_addr;
1561 if (n->l4_proto == IPPROTO_UDPLITE)
1562 goto check_addr;
1565 if ((what & INCLUDE_TCP) && n->l4_proto == IPPROTO_TCP)
1566 goto check_addr;
1568 if ((what & INCLUDE_DCCP) && n->l4_proto == IPPROTO_DCCP)
1569 goto check_addr;
1571 if ((what & INCLUDE_SCTP) && n->l4_proto == IPPROTO_SCTP)
1572 goto check_addr;
1574 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV4) &&
1575 n->l4_proto == IPPROTO_ICMP) {
1576 goto check_addr;
1579 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV6) &&
1580 n->l4_proto == IPPROTO_ICMPV6) {
1581 goto check_addr;
1584 goto skip_flow;
1586 check_addr:
1587 /* filter loopback addresses */
1588 if (what & INCLUDE_IPV4) {
1589 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
1591 if (n->ip4_src_addr == filter_ipv4.addr)
1592 goto skip_flow;
1594 if (what & INCLUDE_IPV6) {
1595 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
1597 if (n->ip6_src_addr[0] == 0x0 &&
1598 n->ip6_src_addr[1] == 0x0 &&
1599 n->ip6_src_addr[2] == 0x0 &&
1600 n->ip6_src_addr[3] == 0x1)
1601 goto skip_flow;
1604 flow_list_new_entry(&flow_list, ct);
1606 skip_flow:
1607 spinlock_unlock(&flow_list.lock);
1608 return NFCT_CB_CONTINUE;
1611 static void collector_dump_flows(void)
1613 struct nfct_handle *nfct = nfct_open(CONNTRACK, 0);
1615 if (!nfct)
1616 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1618 nfct_callback_register(nfct, NFCT_T_ALL, flow_dump_cb, NULL);
1620 is_flow_collecting = true;
1621 if (what & INCLUDE_IPV4) {
1622 int family = AF_INET;
1623 nfct_query(nfct, NFCT_Q_DUMP, &family);
1625 if (what & INCLUDE_IPV6) {
1626 int family = AF_INET6;
1627 nfct_query(nfct, NFCT_Q_DUMP, &family);
1629 is_flow_collecting = false;
1631 nfct_close(nfct);
1634 static void *collector(void *null __maybe_unused)
1636 struct nfct_handle *ct_update;
1637 struct nfct_handle *ct_event;
1638 struct pollfd poll_fd[1];
1640 flow_list_init(&flow_list);
1642 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1643 NF_NETLINK_CONNTRACK_UPDATE |
1644 NF_NETLINK_CONNTRACK_DESTROY);
1645 if (!ct_event)
1646 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1648 collector_create_filter(ct_event);
1650 nfct_callback_register(ct_event, NFCT_T_ALL, flow_event_cb, NULL);
1652 ct_update = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_UPDATE);
1653 if (!ct_update)
1654 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1656 nfct_callback_register(ct_update, NFCT_T_ALL, flow_update_cb, NULL);
1658 poll_fd[0].fd = nfct_fd(ct_event);
1659 poll_fd[0].events = POLLIN;
1661 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1662 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1663 strerror(errno));
1665 if (fcntl(nfct_fd(ct_update), F_SETFL, O_NONBLOCK) == -1)
1666 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1667 strerror(errno));
1669 rcu_register_thread();
1671 collector_dump_flows();
1673 while (!sigint) {
1674 int status;
1676 if (!do_reload_flows) {
1677 usleep(USEC_PER_SEC * interval);
1678 } else {
1679 do_reload_flows = false;
1681 flow_list_destroy(&flow_list);
1683 collector_create_filter(ct_event);
1684 collector_dump_flows();
1687 collector_refresh_flows(ct_update);
1689 status = poll(poll_fd, 1, 0);
1690 if (status < 0) {
1691 if (errno == EAGAIN || errno == EINTR)
1692 continue;
1694 panic("Error while polling: %s\n", strerror(errno));
1695 } else if (status == 0) {
1696 continue;
1699 if (poll_fd[0].revents & POLLIN)
1700 nfct_catch(ct_event);
1703 rcu_unregister_thread();
1705 flow_list_destroy(&flow_list);
1706 spinlock_destroy(&flow_list.lock);
1708 nfct_close(ct_event);
1709 nfct_close(ct_update);
1711 pthread_exit(NULL);
1714 int main(int argc, char **argv)
1716 pthread_t tid;
1717 int ret, c, opt_index, what_cmd = 0;
1719 setfsuid(getuid());
1720 setfsgid(getgid());
1722 while ((c = getopt_long(argc, argv, short_options, long_options,
1723 &opt_index)) != EOF) {
1724 switch (c) {
1725 case '4':
1726 what_cmd |= INCLUDE_IPV4;
1727 break;
1728 case '6':
1729 what_cmd |= INCLUDE_IPV6;
1730 break;
1731 case 'T':
1732 what_cmd |= INCLUDE_TCP;
1733 break;
1734 case 'U':
1735 what_cmd |= INCLUDE_UDP;
1736 break;
1737 case 'D':
1738 what_cmd |= INCLUDE_DCCP;
1739 break;
1740 case 'I':
1741 what_cmd |= INCLUDE_ICMP;
1742 break;
1743 case 'S':
1744 what_cmd |= INCLUDE_SCTP;
1745 break;
1746 case 's':
1747 show_src = true;
1748 break;
1749 case 'b':
1750 rate_type = RATE_BITS;
1751 break;
1752 case 'u':
1753 update_geoip();
1754 die();
1755 break;
1756 case 't':
1757 interval = strtoul(optarg, NULL, 10);
1758 break;
1759 case 'n':
1760 resolve_dns = false;
1761 break;
1762 case 'G':
1763 resolve_geoip = false;
1764 break;
1765 case 'h':
1766 help();
1767 break;
1768 case 'v':
1769 version();
1770 break;
1771 default:
1772 break;
1776 if (what_cmd > 0) {
1777 what = what_cmd;
1779 if (!(what & (INCLUDE_IPV4 | INCLUDE_IPV6)))
1780 what |= INCLUDE_IPV4 | INCLUDE_IPV6;
1783 rcu_init();
1785 register_signal(SIGINT, signal_handler);
1786 register_signal(SIGQUIT, signal_handler);
1787 register_signal(SIGTERM, signal_handler);
1788 register_signal(SIGHUP, signal_handler);
1790 panic_handler_add(on_panic_handler, &sysctl);
1792 conntrack_acct_enable();
1793 conntrack_tstamp_enable();
1795 if (resolve_geoip)
1796 init_geoip(1);
1798 ret = pthread_create(&tid, NULL, collector, NULL);
1799 if (ret < 0)
1800 panic("Cannot create phthread!\n");
1802 presenter();
1804 if (resolve_geoip)
1805 destroy_geoip();
1807 restore_sysctl(&sysctl);
1809 return 0;