flowtop: Move & refactor walk_processes() to proc.c
[netsniff-ng.git] / flowtop.c
blobf382d6c93b0d240ec4cb4e4195cd4584a555a424
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 <urcu.h>
23 #include <libgen.h>
24 #include <inttypes.h>
25 #include <poll.h>
26 #include <fcntl.h>
27 #include <arpa/inet.h>
29 #include "ui.h"
30 #include "die.h"
31 #include "xmalloc.h"
32 #include "conntrack.h"
33 #include "config.h"
34 #include "str.h"
35 #include "sig.h"
36 #include "lookup.h"
37 #include "geoip.h"
38 #include "built_in.h"
39 #include "locking.h"
40 #include "pkt_buff.h"
41 #include "screen.h"
42 #include "proc.h"
43 #include "sysctl.h"
45 #ifndef NSEC_PER_SEC
46 #define NSEC_PER_SEC 1000000000L
47 #endif
49 #ifndef USEC_PER_SEC
50 #define USEC_PER_SEC 1000000L
51 #endif
53 struct flow_entry {
54 uint32_t flow_id, use, status;
55 uint8_t l3_proto, l4_proto;
56 uint32_t ip4_src_addr, ip4_dst_addr;
57 uint32_t ip6_src_addr[4], ip6_dst_addr[4];
58 uint16_t port_src, port_dst;
59 uint8_t tcp_state, tcp_flags, sctp_state, dccp_state;
60 uint64_t pkts_src, bytes_src;
61 uint64_t pkts_dst, bytes_dst;
62 uint64_t timestamp_start, timestamp_stop;
63 char country_src[128], country_dst[128];
64 char country_code_src[4], country_code_dst[4];
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 enum tbl_flow_col {
142 TBL_FLOW_PROCESS,
143 TBL_FLOW_PID,
144 TBL_FLOW_PROTO,
145 TBL_FLOW_STATE,
146 TBL_FLOW_TIME,
147 TBL_FLOW_ADDRESS,
148 TBL_FLOW_PORT,
149 TBL_FLOW_GEO,
150 TBL_FLOW_BYTES,
151 TBL_FLOW_RATE,
154 static struct ui_table flows_tbl;
156 static const char *short_options = "vhTUsDIS46ut:nGb";
157 static const struct option long_options[] = {
158 {"ipv4", no_argument, NULL, '4'},
159 {"ipv6", no_argument, NULL, '6'},
160 {"tcp", no_argument, NULL, 'T'},
161 {"udp", no_argument, NULL, 'U'},
162 {"dccp", no_argument, NULL, 'D'},
163 {"icmp", no_argument, NULL, 'I'},
164 {"sctp", no_argument, NULL, 'S'},
165 {"no-dns", no_argument, NULL, 'n'},
166 {"no-geoip", no_argument, NULL, 'G'},
167 {"show-src", no_argument, NULL, 's'},
168 {"bits", no_argument, NULL, 'b'},
169 {"update", no_argument, NULL, 'u'},
170 {"interval", required_argument, NULL, 't'},
171 {"version", no_argument, NULL, 'v'},
172 {"help", no_argument, NULL, 'h'},
173 {NULL, 0, NULL, 0}
176 static const char *copyright = "Please report bugs to <netsniff-ng@googlegroups.com>\n"
177 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>\n"
178 "Copyright (C) 2011-2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>\n"
179 "Swiss federal institute of technology (ETH Zurich)\n"
180 "License: GNU GPL version 2.0\n"
181 "This is free software: you are free to change and redistribute it.\n"
182 "There is NO WARRANTY, to the extent permitted by law.";
184 static const char *const l4proto2str[IPPROTO_MAX] = {
185 [IPPROTO_TCP] = "tcp",
186 [IPPROTO_UDP] = "udp",
187 [IPPROTO_UDPLITE] = "udplite",
188 [IPPROTO_ICMP] = "icmp",
189 [IPPROTO_ICMPV6] = "icmpv6",
190 [IPPROTO_SCTP] = "sctp",
191 [IPPROTO_GRE] = "gre",
192 [IPPROTO_DCCP] = "dccp",
193 [IPPROTO_IGMP] = "igmp",
194 [IPPROTO_IPIP] = "ipip",
195 [IPPROTO_EGP] = "egp",
196 [IPPROTO_PUP] = "pup",
197 [IPPROTO_IDP] = "idp",
198 [IPPROTO_RSVP] = "rsvp",
199 [IPPROTO_IPV6] = "ip6tun",
200 [IPPROTO_ESP] = "esp",
201 [IPPROTO_AH] = "ah",
202 [IPPROTO_PIM] = "pim",
203 [IPPROTO_COMP] = "comp",
206 static const char *const tcp_state2str[TCP_CONNTRACK_MAX] = {
207 [TCP_CONNTRACK_NONE] = "NONE",
208 [TCP_CONNTRACK_SYN_SENT] = "SYN-SENT",
209 [TCP_CONNTRACK_SYN_RECV] = "SYN-RECV",
210 [TCP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
211 [TCP_CONNTRACK_FIN_WAIT] = "FIN-WAIT",
212 [TCP_CONNTRACK_CLOSE_WAIT] = "CLOSE-WAIT",
213 [TCP_CONNTRACK_LAST_ACK] = "LAST-ACK",
214 [TCP_CONNTRACK_TIME_WAIT] = "TIME-WAIT",
215 [TCP_CONNTRACK_CLOSE] = "CLOSE",
216 [TCP_CONNTRACK_SYN_SENT2] = "SYN-SENT2",
219 static const char *const dccp_state2str[DCCP_CONNTRACK_MAX] = {
220 [DCCP_CONNTRACK_NONE] = "NONE",
221 [DCCP_CONNTRACK_REQUEST] = "REQUEST",
222 [DCCP_CONNTRACK_RESPOND] = "RESPOND",
223 [DCCP_CONNTRACK_PARTOPEN] = "PARTOPEN",
224 [DCCP_CONNTRACK_OPEN] = "OPEN",
225 [DCCP_CONNTRACK_CLOSEREQ] = "CLOSE-REQ",
226 [DCCP_CONNTRACK_CLOSING] = "CLOSING",
227 [DCCP_CONNTRACK_TIMEWAIT] = "TIME-WAIT",
228 [DCCP_CONNTRACK_IGNORE] = "IGNORE",
229 [DCCP_CONNTRACK_INVALID] = "INVALID",
232 static const char *const sctp_state2str[SCTP_CONNTRACK_MAX] = {
233 [SCTP_CONNTRACK_NONE] = "NONE",
234 [SCTP_CONNTRACK_CLOSED] = "CLOSED",
235 [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE-WAIT",
236 [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE-ECHO",
237 [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
238 [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTD-SENT",
239 [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTD-RCVD",
240 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTD-ACK",
243 static const struct nfct_filter_ipv4 filter_ipv4 = {
244 .addr = __constant_htonl(INADDR_LOOPBACK),
245 .mask = 0xffffffff,
248 static const struct nfct_filter_ipv6 filter_ipv6 = {
249 .addr = { 0x0, 0x0, 0x0, 0x1 },
250 .mask = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
253 static int64_t time_after_us(struct timeval *tv)
255 struct timeval now;
257 bug_on(gettimeofday(&now, NULL));
259 now.tv_sec -= tv->tv_sec;
260 now.tv_usec -= tv->tv_usec;
262 return now.tv_sec * USEC_PER_SEC + now.tv_usec;
265 static void signal_handler(int number)
267 switch (number) {
268 case SIGINT:
269 case SIGQUIT:
270 case SIGTERM:
271 sigint = 1;
272 break;
273 case SIGHUP:
274 default:
275 break;
279 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct);
280 static void flow_entry_get_extended(struct flow_entry *n);
282 static void help(void)
284 printf("flowtop %s, top-like netfilter TCP/UDP/SCTP/.. flow tracking\n",
285 VERSION_STRING);
286 puts("http://www.netsniff-ng.org\n\n"
287 "Usage: flowtop [options]\n"
288 "Options:\n"
289 " -4|--ipv4 Show only IPv4 flows (default)\n"
290 " -6|--ipv6 Show only IPv6 flows (default)\n"
291 " -T|--tcp Show only TCP flows (default)\n"
292 " -U|--udp Show only UDP flows\n"
293 " -D|--dccp Show only DCCP flows\n"
294 " -I|--icmp Show only ICMP/ICMPv6 flows\n"
295 " -S|--sctp Show only SCTP flows\n"
296 " -n|--no-dns Don't perform hostname lookup\n"
297 " -G|--no-geoip Don't perform GeoIP lookup\n"
298 " -s|--show-src Also show source, not only dest\n"
299 " -b|--bits Show rates in bits/s instead of bytes/s\n"
300 " -u|--update Update GeoIP databases\n"
301 " -t|--interval <time> Refresh time in seconds (default 1s)\n"
302 " -v|--version Print version and exit\n"
303 " -h|--help Print this help and exit\n\n"
304 "Examples:\n"
305 " flowtop\n"
306 " flowtop -46UTDISs\n\n"
307 "Note:\n"
308 " If netfilter is not running, you can activate it with e.g.:\n"
309 " iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT\n"
310 " iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT\n");
311 puts(copyright);
312 die();
315 static void version(void)
317 printf("flowtop %s, Git id: %s\n", VERSION_LONG, GITVERSION);
318 puts("top-like netfilter TCP/UDP/SCTP/.. flow tracking\n"
319 "http://www.netsniff-ng.org\n");
320 puts(copyright);
321 die();
324 static void flow_entry_update_time(struct flow_entry *n)
326 bug_on(gettimeofday(&n->last_update, NULL));
329 #define CALC_RATE(fld) do { \
330 n->rate_##fld = (((fld) > n->fld) ? (((fld) - n->fld) / sec) : 0); \
331 } while (0)
333 static void flow_entry_calc_rate(struct flow_entry *n, const struct nf_conntrack *ct)
335 uint64_t bytes_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_BYTES);
336 uint64_t bytes_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_BYTES);
337 uint64_t pkts_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_PACKETS);
338 uint64_t pkts_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_PACKETS);
339 double sec = (double)time_after_us(&n->last_update) / USEC_PER_SEC;
341 if (sec < 1)
342 return;
344 CALC_RATE(bytes_src);
345 CALC_RATE(bytes_dst);
346 CALC_RATE(pkts_src);
347 CALC_RATE(pkts_dst);
350 static inline struct flow_entry *flow_entry_xalloc(void)
352 return xzmalloc(sizeof(struct flow_entry));
355 static inline void flow_entry_xfree(struct flow_entry *n)
357 if (n->ct)
358 nfct_destroy(n->ct);
360 xfree(n);
363 static inline void flow_list_init(struct flow_list *fl)
365 fl->head = NULL;
366 spinlock_init(&fl->lock);
369 static inline bool nfct_is_dns(const struct nf_conntrack *ct)
371 uint16_t port_src = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
372 uint16_t port_dst = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
374 return ntohs(port_src) == 53 || ntohs(port_dst) == 53;
377 static void flow_list_new_entry(struct flow_list *fl, const struct nf_conntrack *ct)
379 struct flow_entry *n;
381 /* We don't want to analyze / display DNS itself, since we
382 * use it to resolve reverse dns.
384 if (nfct_is_dns(ct))
385 return;
387 n = flow_entry_xalloc();
389 n->ct = nfct_clone(ct);
391 flow_entry_update_time(n);
392 flow_entry_from_ct(n, ct);
393 flow_entry_get_extended(n);
395 rcu_assign_pointer(n->next, fl->head);
396 rcu_assign_pointer(fl->head, n);
398 n->is_visible = true;
401 static struct flow_entry *flow_list_find_id(struct flow_list *fl,
402 uint32_t id)
404 struct flow_entry *n = rcu_dereference(fl->head);
406 while (n != NULL) {
407 if (n->flow_id == id)
408 return n;
410 n = rcu_dereference(n->next);
413 return NULL;
416 static struct flow_entry *flow_list_find_prev_id(const struct flow_list *fl,
417 uint32_t id)
419 struct flow_entry *prev = rcu_dereference(fl->head), *next;
421 if (prev->flow_id == id)
422 return NULL;
424 while ((next = rcu_dereference(prev->next)) != NULL) {
425 if (next->flow_id == id)
426 return prev;
428 prev = next;
431 return NULL;
434 static void flow_list_destroy_entry(struct flow_list *fl,
435 const struct nf_conntrack *ct)
437 struct flow_entry *n1, *n2;
438 uint32_t id = nfct_get_attr_u32(ct, ATTR_ID);
440 n1 = flow_list_find_id(fl, id);
441 if (n1) {
442 n2 = flow_list_find_prev_id(fl, id);
443 if (n2) {
444 rcu_assign_pointer(n2->next, n1->next);
445 n1->next = NULL;
447 flow_entry_xfree(n1);
448 } else {
449 struct flow_entry *next = fl->head->next;
451 flow_entry_xfree(fl->head);
452 fl->head = next;
457 static void flow_list_destroy(struct flow_list *fl)
459 struct flow_entry *n;
461 synchronize_rcu();
462 spinlock_lock(&flow_list.lock);
464 while (fl->head != NULL) {
465 n = rcu_dereference(fl->head->next);
466 fl->head->next = NULL;
468 flow_entry_xfree(fl->head);
469 rcu_assign_pointer(fl->head, n);
472 spinlock_unlock(&flow_list.lock);
475 static void flow_entry_find_process(struct flow_entry *n)
477 char cmdline[512];
478 pid_t pid;
479 int ret;
481 ret = proc_find_by_inode(n->inode, cmdline, sizeof(cmdline), &pid);
482 if (ret <= 0) {
483 n->procname[0] = '\0';
484 return;
487 if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0)
488 n->procname[0] = '\0';
490 n->procnum = pid;
493 static int get_port_inode(uint16_t port, int proto, bool is_ip6)
495 int ret = -ENOENT;
496 char path[128], buff[1024];
497 FILE *proc;
499 memset(path, 0, sizeof(path));
500 snprintf(path, sizeof(path), "/proc/net/%s%s",
501 l4proto2str[proto], is_ip6 ? "6" : "");
503 proc = fopen(path, "r");
504 if (!proc)
505 return -EIO;
507 memset(buff, 0, sizeof(buff));
509 while (fgets(buff, sizeof(buff), proc) != NULL) {
510 int inode = 0;
511 unsigned int lport = 0;
513 buff[sizeof(buff) - 1] = 0;
514 if (sscanf(buff, "%*u: %*X:%X %*X:%*X %*X %*X:%*X %*X:%*X "
515 "%*X %*u %*u %u", &lport, &inode) == 2) {
516 if ((uint16_t) lport == port) {
517 ret = inode;
518 break;
522 memset(buff, 0, sizeof(buff));
525 fclose(proc);
526 return ret;
529 #define CP_NFCT(elem, attr, x) \
530 do { n->elem = nfct_get_attr_u##x(ct,(attr)); } while (0)
531 #define CP_NFCT_BUFF(elem, attr) do { \
532 const uint8_t *buff = nfct_get_attr(ct,(attr)); \
533 if (buff != NULL) \
534 memcpy(n->elem, buff, sizeof(n->elem)); \
535 } while (0)
537 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct)
539 CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
540 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
542 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
543 CP_NFCT(ip4_dst_addr, ATTR_ORIG_IPV4_DST, 32);
545 CP_NFCT(port_src, ATTR_ORIG_PORT_SRC, 16);
546 CP_NFCT(port_dst, ATTR_ORIG_PORT_DST, 16);
548 CP_NFCT(status, ATTR_STATUS, 32);
550 CP_NFCT(tcp_state, ATTR_TCP_STATE, 8);
551 CP_NFCT(tcp_flags, ATTR_TCP_FLAGS_ORIG, 8);
552 CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
553 CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
555 CP_NFCT(pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
556 CP_NFCT(bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
558 CP_NFCT(pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
559 CP_NFCT(bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
561 CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
562 CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
564 CP_NFCT(flow_id, ATTR_ID, 32);
565 CP_NFCT(use, ATTR_USE, 32);
567 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
568 CP_NFCT_BUFF(ip6_dst_addr, ATTR_ORIG_IPV6_DST);
570 n->port_src = ntohs(n->port_src);
571 n->port_dst = ntohs(n->port_dst);
573 n->ip4_src_addr = ntohl(n->ip4_src_addr);
574 n->ip4_dst_addr = ntohl(n->ip4_dst_addr);
577 #define SELFLD(dir,src_member,dst_member) \
578 (((dir) == FLOW_DIR_SRC) ? n->src_member : n->dst_member)
580 static void flow_entry_get_sain4_obj(const struct flow_entry *n,
581 enum flow_direction dir,
582 struct sockaddr_in *sa)
584 memset(sa, 0, sizeof(*sa));
585 sa->sin_family = PF_INET;
586 sa->sin_addr.s_addr = htonl(SELFLD(dir, ip4_src_addr, ip4_dst_addr));
589 static void flow_entry_get_sain6_obj(const struct flow_entry *n,
590 enum flow_direction dir,
591 struct sockaddr_in6 *sa)
593 memset(sa, 0, sizeof(*sa));
594 sa->sin6_family = PF_INET6;
596 memcpy(&sa->sin6_addr, SELFLD(dir, ip6_src_addr, ip6_dst_addr),
597 sizeof(sa->sin6_addr));
600 static void
601 flow_entry_geo_city_lookup_generic(struct flow_entry *n,
602 enum flow_direction dir)
604 struct sockaddr_in sa4;
605 struct sockaddr_in6 sa6;
606 const char *city = NULL;
608 switch (n->l3_proto) {
609 default:
610 bug();
612 case AF_INET:
613 flow_entry_get_sain4_obj(n, dir, &sa4);
614 city = geoip4_city_name(&sa4);
615 break;
617 case AF_INET6:
618 flow_entry_get_sain6_obj(n, dir, &sa6);
619 city = geoip6_city_name(&sa6);
620 break;
623 build_bug_on(sizeof(n->city_src) != sizeof(n->city_dst));
625 if (city)
626 strlcpy(SELFLD(dir, city_src, city_dst), city,
627 sizeof(n->city_src));
628 else
629 SELFLD(dir, city_src, city_dst)[0] = '\0';
632 static void
633 flow_entry_geo_country_lookup_generic(struct flow_entry *n,
634 enum flow_direction dir)
636 struct sockaddr_in sa4;
637 struct sockaddr_in6 sa6;
638 const char *country = NULL;
639 const char *country_code = NULL;
641 switch (n->l3_proto) {
642 default:
643 bug();
645 case AF_INET:
646 flow_entry_get_sain4_obj(n, dir, &sa4);
647 country = geoip4_country_name(&sa4);
648 country_code = geoip4_country_code3_name(&sa4);
649 break;
651 case AF_INET6:
652 flow_entry_get_sain6_obj(n, dir, &sa6);
653 country = geoip6_country_name(&sa6);
654 country_code = geoip6_country_code3_name(&sa6);
655 break;
658 build_bug_on(sizeof(n->country_src) != sizeof(n->country_dst));
660 if (country)
661 strlcpy(SELFLD(dir, country_src, country_dst), country,
662 sizeof(n->country_src));
663 else
664 SELFLD(dir, country_src, country_dst)[0] = '\0';
666 build_bug_on(sizeof(n->country_code_src) != sizeof(n->country_code_dst));
668 if (country_code)
669 strlcpy(SELFLD(dir, country_code_src, country_code_dst),
670 country_code, sizeof(n->country_code_src));
671 else
672 SELFLD(dir, country_code_src, country_code_dst)[0] = '\0';
675 static void flow_entry_get_extended_geo(struct flow_entry *n,
676 enum flow_direction dir)
678 if (resolve_geoip) {
679 flow_entry_geo_city_lookup_generic(n, dir);
680 flow_entry_geo_country_lookup_generic(n, dir);
684 static void flow_entry_get_extended_revdns(struct flow_entry *n,
685 enum flow_direction dir)
687 size_t sa_len;
688 struct sockaddr_in sa4;
689 struct sockaddr_in6 sa6;
690 struct sockaddr *sa;
691 struct hostent *hent;
693 build_bug_on(sizeof(n->rev_dns_src) != sizeof(n->rev_dns_dst));
695 switch (n->l3_proto) {
696 default:
697 bug();
699 case AF_INET:
700 flow_entry_get_sain4_obj(n, dir, &sa4);
702 if (!resolve_dns) {
703 inet_ntop(AF_INET, &sa4.sin_addr,
704 SELFLD(dir, rev_dns_src, rev_dns_dst),
705 sizeof(n->rev_dns_src));
706 return;
709 sa = (struct sockaddr *) &sa4;
710 sa_len = sizeof(sa4);
711 hent = gethostbyaddr(&sa4.sin_addr, sizeof(sa4.sin_addr), AF_INET);
712 break;
714 case AF_INET6:
715 flow_entry_get_sain6_obj(n, dir, &sa6);
717 if (!resolve_dns) {
718 inet_ntop(AF_INET6, &sa6.sin6_addr,
719 SELFLD(dir, rev_dns_src, rev_dns_dst),
720 sizeof(n->rev_dns_src));
721 return;
724 sa = (struct sockaddr *) &sa6;
725 sa_len = sizeof(sa6);
726 hent = gethostbyaddr(&sa6.sin6_addr, sizeof(sa6.sin6_addr), AF_INET6);
727 break;
730 getnameinfo(sa, sa_len, SELFLD(dir, rev_dns_src, rev_dns_dst),
731 sizeof(n->rev_dns_src), NULL, 0, NI_NUMERICHOST);
733 if (hent)
734 strlcpy(SELFLD(dir, rev_dns_src, rev_dns_dst), hent->h_name,
735 sizeof(n->rev_dns_src));
738 static void flow_entry_get_extended(struct flow_entry *n)
740 if (n->flow_id == 0)
741 return;
743 flow_entry_get_extended_revdns(n, FLOW_DIR_SRC);
744 flow_entry_get_extended_geo(n, FLOW_DIR_SRC);
746 flow_entry_get_extended_revdns(n, FLOW_DIR_DST);
747 flow_entry_get_extended_geo(n, FLOW_DIR_DST);
749 /* Lookup application */
750 n->inode = get_port_inode(n->port_src, n->l4_proto,
751 n->l3_proto == AF_INET6);
752 if (n->inode > 0)
753 flow_entry_find_process(n);
756 static char *bandw2str(double bytes, char *buf, size_t len)
758 if (bytes <= 0) {
759 buf[0] = '\0';
760 return buf;
763 if (bytes > 1000000000.)
764 snprintf(buf, len, "%.1fGB", bytes / 1000000000.);
765 else if (bytes > 1000000.)
766 snprintf(buf, len, "%.1fMB", bytes / 1000000.);
767 else if (bytes > 1000.)
768 snprintf(buf, len, "%.1fkB", bytes / 1000.);
769 else
770 snprintf(buf, len, "%.0f", bytes);
772 return buf;
775 static char *rate2str(double rate, char *buf, size_t len)
777 const char * const unit_fmt[2][4] = {
778 { "%.1fGbit/s", "%.1fMbit/s", "%.1fkbit/s", "%.0fbit/s" },
779 { "%.1fGB/s", "%.1fMB/s", "%.1fkB/s", "%.0fB/s" }
782 if (rate <= 0) {
783 buf[0] = '\0';
784 return buf;
787 if (rate_type == RATE_BITS)
788 rate *= 8;
790 if (rate > 1000000000.)
791 snprintf(buf, len, unit_fmt[rate_type][0], rate / 1000000000.);
792 else if (rate > 1000000.)
793 snprintf(buf, len, unit_fmt[rate_type][1], rate / 1000000.);
794 else if (rate > 1000.)
795 snprintf(buf, len, unit_fmt[rate_type][2], rate / 1000.);
796 else
797 snprintf(buf, len, unit_fmt[rate_type][3], rate);
799 return buf;
802 static char *time2str(uint64_t tstamp, char *str, size_t len)
804 time_t now;
805 int v, s;
807 time(&now);
809 s = now - (tstamp ? (tstamp / NSEC_PER_SEC) : now);
810 if (s <= 0) {
811 str[0] = '\0';
812 return str;
815 v = s / (3600 * 24);
816 if (v > 0) {
817 slprintf(str, len, "%dd", v);
818 return str;
821 v = s / 3600;
822 if (v > 0) {
823 slprintf(str, len, "%dh", v);
824 return str;
827 v = s / 60;
828 if (v > 0) {
829 slprintf(str, len, "%dm", v);
830 return str;
833 slprintf(str, len, "%ds", s);
834 return str;
838 static const char *flow_state2str(const struct flow_entry *n)
840 switch (n->l4_proto) {
841 case IPPROTO_TCP:
842 return tcp_state2str[n->tcp_state];
843 case IPPROTO_SCTP:
844 return sctp_state2str[n->sctp_state];
845 case IPPROTO_DCCP:
846 return dccp_state2str[n->dccp_state];
848 case IPPROTO_UDP:
849 case IPPROTO_UDPLITE:
850 case IPPROTO_ICMP:
851 case IPPROTO_ICMPV6:
852 default:
853 return "";
857 static char *flow_port2str(const struct flow_entry *n, char *str, size_t len,
858 enum flow_direction dir)
860 const char *tmp = NULL;
861 uint16_t port = 0;
863 port = SELFLD(dir, port_src, port_dst);
864 tmp = NULL;
866 switch (n->l4_proto) {
867 case IPPROTO_TCP:
868 tmp = lookup_port_tcp(port);
869 break;
870 case IPPROTO_UDP:
871 case IPPROTO_UDPLITE:
872 tmp = lookup_port_udp(port);
873 break;
876 if (!tmp && port)
877 slprintf(str, len, "%d", port);
878 else
879 slprintf(str, len, "%s", tmp ? tmp : "");
881 return str;
884 static void print_flow_peer_info(const struct flow_entry *n, enum flow_direction dir)
886 int counters_color = COLOR(YELLOW, BLACK);
887 int src_color = COLOR(RED, BLACK);
888 int dst_color = COLOR(BLUE, BLACK);
889 int country_color = COLOR(GREEN, BLACK);
890 int addr_color = dst_color;
891 int port_color = A_BOLD;
892 char tmp[128];
894 if (show_src && dir == FLOW_DIR_SRC) {
895 country_color = src_color;
896 counters_color = src_color;
897 port_color |= src_color;
898 addr_color = src_color;
899 } else if (show_src && FLOW_DIR_DST) {
900 country_color = dst_color;
901 counters_color = dst_color;
902 port_color |= dst_color;
903 addr_color = dst_color;
906 ui_table_col_color_set(&flows_tbl, TBL_FLOW_ADDRESS, addr_color);
907 ui_table_col_color_set(&flows_tbl, TBL_FLOW_PORT, port_color);
908 ui_table_col_color_set(&flows_tbl, TBL_FLOW_GEO, country_color);
909 ui_table_col_color_set(&flows_tbl, TBL_FLOW_BYTES, counters_color);
910 ui_table_col_color_set(&flows_tbl, TBL_FLOW_RATE, counters_color);
912 /* Reverse DNS/IP */
913 ui_table_row_col_set(&flows_tbl, TBL_FLOW_ADDRESS,
914 SELFLD(dir, rev_dns_src, rev_dns_dst));
916 /* Application port */
917 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PORT,
918 flow_port2str(n, tmp, sizeof(tmp), dir));
920 /* GEO */
921 ui_table_row_col_set(&flows_tbl, TBL_FLOW_GEO,
922 SELFLD(dir, country_code_src, country_code_dst));
924 /* Bytes */
925 ui_table_row_col_set(&flows_tbl, TBL_FLOW_BYTES,
926 bandw2str(SELFLD(dir, bytes_src, bytes_dst),
927 tmp, sizeof(tmp) - 1));
929 /* Rate bytes */
930 ui_table_row_col_set(&flows_tbl, TBL_FLOW_RATE,
931 rate2str(SELFLD(dir, rate_bytes_src, rate_bytes_dst),
932 tmp, sizeof(tmp) - 1));
935 static void draw_flow_entry(const struct flow_entry *n)
937 char tmp[128];
939 ui_table_row_add(&flows_tbl);
941 /* Application */
942 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PROCESS, n->procname);
944 /* PID */
945 slprintf(tmp, sizeof(tmp), "%.d", n->procnum);
946 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PID, tmp);
948 /* L4 protocol */
949 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PROTO, l4proto2str[n->l4_proto]);
951 /* L4 protocol state */
952 ui_table_row_col_set(&flows_tbl, TBL_FLOW_STATE, flow_state2str(n));
954 /* Time */
955 time2str(n->timestamp_start, tmp, sizeof(tmp));
956 ui_table_row_col_set(&flows_tbl, TBL_FLOW_TIME, tmp);
958 print_flow_peer_info(n, show_src ? FLOW_DIR_SRC : FLOW_DIR_DST);
960 ui_table_row_show(&flows_tbl);
962 if (show_src) {
963 ui_table_row_add(&flows_tbl);
965 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PROCESS, "");
966 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PID, "");
967 ui_table_row_col_set(&flows_tbl, TBL_FLOW_PROTO, "");
968 ui_table_row_col_set(&flows_tbl, TBL_FLOW_STATE, "");
969 ui_table_row_col_set(&flows_tbl, TBL_FLOW_TIME, "");
971 print_flow_peer_info(n, FLOW_DIR_DST);
972 ui_table_row_show(&flows_tbl);
976 static inline bool presenter_flow_wrong_state(struct flow_entry *n)
978 switch (n->l4_proto) {
979 case IPPROTO_TCP:
980 switch (n->tcp_state) {
981 case TCP_CONNTRACK_SYN_SENT:
982 case TCP_CONNTRACK_SYN_RECV:
983 case TCP_CONNTRACK_ESTABLISHED:
984 case TCP_CONNTRACK_FIN_WAIT:
985 case TCP_CONNTRACK_CLOSE_WAIT:
986 case TCP_CONNTRACK_LAST_ACK:
987 case TCP_CONNTRACK_TIME_WAIT:
988 case TCP_CONNTRACK_CLOSE:
989 case TCP_CONNTRACK_SYN_SENT2:
990 case TCP_CONNTRACK_NONE:
991 return false;
992 break;
994 break;
995 case IPPROTO_SCTP:
996 switch (n->sctp_state) {
997 case SCTP_CONNTRACK_NONE:
998 case SCTP_CONNTRACK_CLOSED:
999 case SCTP_CONNTRACK_COOKIE_WAIT:
1000 case SCTP_CONNTRACK_COOKIE_ECHOED:
1001 case SCTP_CONNTRACK_ESTABLISHED:
1002 case SCTP_CONNTRACK_SHUTDOWN_SENT:
1003 case SCTP_CONNTRACK_SHUTDOWN_RECD:
1004 case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT:
1005 return false;
1006 break;
1008 break;
1009 case IPPROTO_DCCP:
1010 switch (n->dccp_state) {
1011 case DCCP_CONNTRACK_NONE:
1012 case DCCP_CONNTRACK_REQUEST:
1013 case DCCP_CONNTRACK_RESPOND:
1014 case DCCP_CONNTRACK_PARTOPEN:
1015 case DCCP_CONNTRACK_OPEN:
1016 case DCCP_CONNTRACK_CLOSEREQ:
1017 case DCCP_CONNTRACK_CLOSING:
1018 case DCCP_CONNTRACK_TIMEWAIT:
1019 case DCCP_CONNTRACK_IGNORE:
1020 case DCCP_CONNTRACK_INVALID:
1021 return false;
1022 break;
1024 break;
1025 case IPPROTO_UDP:
1026 case IPPROTO_UDPLITE:
1027 case IPPROTO_ICMP:
1028 case IPPROTO_ICMPV6:
1029 return false;
1030 break;
1033 return true;
1036 static void draw_flows(WINDOW *screen, struct flow_list *fl,
1037 int skip_lines)
1039 int row_width = show_src ? 2 : 1;
1040 unsigned int flows = 0;
1041 unsigned int line = 4;
1042 int skip = skip_lines;
1043 struct flow_entry *n;
1045 rcu_read_lock();
1047 n = rcu_dereference(fl->head);
1048 if (!n)
1049 mvwprintw(screen, line, 2, "(No sessions! "
1050 "Is netfilter running?)");
1052 ui_table_clear(&flows_tbl);
1053 ui_table_header_print(&flows_tbl);
1055 for (; n; n = rcu_dereference(n->next)) {
1056 if (!n->is_visible)
1057 continue;
1058 if (presenter_flow_wrong_state(n))
1059 continue;
1061 /* count only flows which might be showed */
1062 flows++;
1064 if (line + row_width >= rows)
1065 continue;
1066 if (--skip >= 0)
1067 continue;
1069 draw_flow_entry(n);
1070 line += row_width;
1073 mvwprintw(screen, 1, 0, "%*s", COLS - 1, " ");
1074 mvwprintw(screen, 1, 2, "Kernel netfilter flows(%u) for ", flows);
1076 if (what & INCLUDE_IPV4)
1077 printw("IPv4,");
1078 if (what & INCLUDE_IPV6)
1079 printw("IPv6,");
1080 if (what & INCLUDE_TCP)
1081 printw("TCP,");
1082 if (what & INCLUDE_UDP)
1083 printw("UDP,");
1084 if (what & INCLUDE_SCTP)
1085 printw("SCTP,");
1086 if (what & INCLUDE_DCCP)
1087 printw("DCCP,");
1088 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1089 printw("ICMP,");
1090 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1091 printw("ICMP6,");
1092 if (show_active_only)
1093 printw("Active,");
1095 printw(" [+%d]", skip_lines);
1097 if (is_flow_collecting)
1098 printw(" [Collecting flows ...]");
1100 rcu_read_unlock();
1103 static void draw_help(void)
1105 int col = 0;
1106 int row = 1;
1107 int i;
1109 mvaddch(row, col, ACS_ULCORNER);
1110 mvaddch(rows - row - 1, col, ACS_LLCORNER);
1112 mvaddch(row, cols - 1, ACS_URCORNER);
1113 mvaddch(rows - row - 1, cols - 1, ACS_LRCORNER);
1115 for (i = 1; i < rows - row - 2; i++) {
1116 mvaddch(row + i, 0, ACS_VLINE);
1117 mvaddch(row + i, cols - 1, ACS_VLINE);
1119 for (i = 1; i < cols - col - 1; i++) {
1120 mvaddch(row, col + i, ACS_HLINE);
1121 mvaddch(rows - row - 1, col + i, ACS_HLINE);
1124 attron(A_BOLD);
1125 mvaddnstr(row, cols / 2 - 2, "| Help |", -1);
1127 attron(A_UNDERLINE);
1128 mvaddnstr(row + 2, col + 2, "Navigation", -1);
1129 attroff(A_BOLD | A_UNDERLINE);
1131 mvaddnstr(row + 4, col + 3, "Up, u, k Move up", -1);
1132 mvaddnstr(row + 5, col + 3, "Down, d, j Move down", -1);
1133 mvaddnstr(row + 6, col + 3, "Left,l Scroll left", -1);
1134 mvaddnstr(row + 7, col + 3, "Right,h Scroll right", -1);
1135 mvaddnstr(row + 8, col + 3, "? Toggle help window", -1);
1136 mvaddnstr(row + 9, col + 3, "q, Ctrl+C Quit", -1);
1138 attron(A_BOLD | A_UNDERLINE);
1139 mvaddnstr(row + 11, col + 2, "Display Settings", -1);
1140 attroff(A_BOLD | A_UNDERLINE);
1142 mvaddnstr(row + 13, col + 3, "b Toggle rate units (bits/bytes)", -1);
1143 mvaddnstr(row + 14, col + 3, "a Toggle display of active flows (rate > 0) only", -1);
1144 mvaddnstr(row + 15, col + 3, "s Toggle show source peer info", -1);
1146 mvaddnstr(row + 17, col + 3, "T Toggle display TCP flows", -1);
1147 mvaddnstr(row + 18, col + 3, "U Toggle display UDP flows", -1);
1148 mvaddnstr(row + 19, col + 3, "D Toggle display DCCP flows", -1);
1149 mvaddnstr(row + 20, col + 3, "I Toggle display ICMP flows", -1);
1150 mvaddnstr(row + 21, col + 3, "S Toggle display SCTP flows", -1);
1153 static void draw_header(WINDOW *screen)
1155 int i;
1157 attron(A_STANDOUT);
1159 for (i = 0; i < cols; i++)
1160 mvaddch(0, i, ' ');
1162 mvwprintw(screen, 0, 2, "flowtop %s", VERSION_LONG);
1163 attroff(A_STANDOUT);
1166 static void draw_footer(void)
1168 int i;
1170 attron(A_STANDOUT);
1172 for (i = 0; i < cols; i++)
1173 mvaddch(rows - 1, i, ' ');
1175 mvaddnstr(rows - 1, 1, "Press '?' for help", -1);
1176 addch(ACS_VLINE);
1177 attroff(A_STANDOUT);
1180 static void show_option_toggle(int opt)
1182 switch (opt) {
1183 case 'T':
1184 TOGGLE_FLAG(what, INCLUDE_TCP);
1185 break;
1186 case 'U':
1187 TOGGLE_FLAG(what, INCLUDE_UDP);
1188 break;
1189 case 'D':
1190 TOGGLE_FLAG(what, INCLUDE_DCCP);
1191 break;
1192 case 'I':
1193 TOGGLE_FLAG(what, INCLUDE_ICMP);
1194 break;
1195 case 'S':
1196 TOGGLE_FLAG(what, INCLUDE_SCTP);
1197 break;
1201 static void flows_table_init(struct ui_table *tbl)
1203 ui_table_init(tbl);
1205 ui_table_pos_set(tbl, 3, 0);
1206 ui_table_height_set(tbl, LINES - 3);
1208 ui_table_col_add(tbl, TBL_FLOW_PROCESS, "PROCESS", 13);
1209 ui_table_col_add(tbl, TBL_FLOW_PID, "PID", 7);
1210 ui_table_col_add(tbl, TBL_FLOW_PROTO, "PROTO", 6);
1211 ui_table_col_add(tbl, TBL_FLOW_STATE, "STATE", 11);
1212 ui_table_col_add(tbl, TBL_FLOW_TIME, "TIME", 4);
1213 ui_table_col_add(tbl, TBL_FLOW_ADDRESS, "ADDRESS", 50);
1214 ui_table_col_add(tbl, TBL_FLOW_PORT, "PORT", 8);
1215 ui_table_col_add(tbl, TBL_FLOW_GEO, "GEO", 3);
1216 ui_table_col_add(tbl, TBL_FLOW_BYTES, "BYTES", 10);
1217 ui_table_col_add(tbl, TBL_FLOW_RATE, "RATE", 10);
1219 ui_table_col_align_set(tbl, TBL_FLOW_TIME, UI_ALIGN_RIGHT);
1220 ui_table_col_align_set(tbl, TBL_FLOW_BYTES, UI_ALIGN_RIGHT);
1221 ui_table_col_align_set(tbl, TBL_FLOW_RATE, UI_ALIGN_RIGHT);
1223 ui_table_col_color_set(tbl, TBL_FLOW_PROCESS, COLOR(YELLOW, BLACK));
1224 ui_table_col_color_set(tbl, TBL_FLOW_PID, A_BOLD);
1225 ui_table_col_color_set(tbl, TBL_FLOW_STATE, COLOR(YELLOW, BLACK));
1227 ui_table_header_color_set(&flows_tbl, COLOR(BLACK, GREEN));
1230 static void presenter(void)
1232 bool show_help = false;
1233 int skip_lines = 0;
1234 WINDOW *screen;
1236 lookup_init(LT_PORTS_TCP);
1237 lookup_init(LT_PORTS_UDP);
1239 screen = screen_init(false);
1240 wclear(screen);
1242 start_color();
1243 INIT_COLOR(RED, BLACK);
1244 INIT_COLOR(BLUE, BLACK);
1245 INIT_COLOR(YELLOW, BLACK);
1246 INIT_COLOR(GREEN, BLACK);
1247 INIT_COLOR(BLACK, GREEN);
1249 flows_table_init(&flows_tbl);
1251 rcu_register_thread();
1252 while (!sigint) {
1253 int ch;
1255 curs_set(0);
1256 getmaxyx(screen, rows, cols);
1258 ch = getch();
1259 switch (ch) {
1260 case 'q':
1261 sigint = 1;
1262 break;
1263 case KEY_UP:
1264 case 'u':
1265 case 'k':
1266 skip_lines--;
1267 if (skip_lines < 0)
1268 skip_lines = 0;
1269 break;
1270 case KEY_DOWN:
1271 case 'd':
1272 case 'j':
1273 skip_lines++;
1274 if (skip_lines > SCROLL_MAX)
1275 skip_lines = SCROLL_MAX;
1276 break;
1277 case KEY_LEFT:
1278 case 'h':
1279 ui_table_event_send(&flows_tbl, UI_EVT_SCROLL_LEFT);
1280 break;
1281 case KEY_RIGHT:
1282 case 'l':
1283 ui_table_event_send(&flows_tbl, UI_EVT_SCROLL_RIGHT);
1284 break;
1285 case 'b':
1286 if (rate_type == RATE_BYTES)
1287 rate_type = RATE_BITS;
1288 else
1289 rate_type = RATE_BYTES;
1290 break;
1291 case 'a':
1292 show_active_only = !show_active_only;
1293 break;
1294 case 's':
1295 show_src = !show_src;
1296 break;
1297 case '?':
1298 show_help = !show_help;
1299 wclear(screen);
1300 clear();
1301 break;
1302 case 'T':
1303 case 'U':
1304 case 'D':
1305 case 'I':
1306 case 'S':
1307 show_option_toggle(ch);
1308 do_reload_flows = true;
1309 break;
1310 default:
1311 fflush(stdin);
1312 break;
1315 draw_header(screen);
1317 if (show_help)
1318 draw_help();
1319 else
1320 draw_flows(screen, &flow_list, skip_lines);
1322 draw_footer();
1324 usleep(80000);
1326 rcu_unregister_thread();
1328 ui_table_uninit(&flows_tbl);
1330 screen_end();
1331 lookup_cleanup(LT_PORTS_UDP);
1332 lookup_cleanup(LT_PORTS_TCP);
1335 static void restore_sysctl(void *obj)
1337 struct sysctl_params_ctx *sysctl_ctx = obj;
1339 if (sysctl_ctx->nfct_acct == 0)
1340 sysctl_set_int("net/netfilter/nf_conntrack_acct",
1341 sysctl_ctx->nfct_acct);
1343 if (sysctl_ctx->nfct_tstamp == 0)
1344 sysctl_set_int("net/netfilter/nf_conntrack_timestamp",
1345 sysctl_ctx->nfct_tstamp);
1348 static void on_panic_handler(void *arg)
1350 restore_sysctl(arg);
1351 screen_end();
1354 static void conntrack_acct_enable(void)
1356 /* We can still work w/o traffic accounting so just warn about error */
1357 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &sysctl.nfct_acct)) {
1358 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1359 strerror(errno));
1360 return;
1363 if (sysctl.nfct_acct == 1)
1364 return;
1366 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1367 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1368 strerror(errno));
1372 static void conntrack_tstamp_enable(void)
1374 if (sysctl_get_int("net/netfilter/nf_conntrack_timestamp", &sysctl.nfct_tstamp)) {
1375 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_timestamp: %s\n",
1376 strerror(errno));
1377 return;
1380 if (sysctl.nfct_tstamp == 1)
1381 return;
1383 if (sysctl_set_int("net/netfilter/nf_conntrack_timestamp", 1)) {
1384 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_timestamp: %s\n",
1385 strerror(errno));
1389 static void flow_entry_filter(struct flow_entry *n)
1391 if (show_active_only && !n->rate_bytes_src && !n->rate_bytes_dst)
1392 n->is_visible = false;
1393 else
1394 n->is_visible = true;
1397 static int flow_list_update_entry(struct flow_list *fl, struct nf_conntrack *ct)
1399 struct flow_entry *n;
1401 n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
1402 if (!n)
1403 return NFCT_CB_CONTINUE;
1405 flow_entry_calc_rate(n, ct);
1406 flow_entry_update_time(n);
1407 flow_entry_from_ct(n, ct);
1408 flow_entry_filter(n);
1410 return NFCT_CB_CONTINUE;
1413 static int flow_event_cb(enum nf_conntrack_msg_type type,
1414 struct nf_conntrack *ct, void *data __maybe_unused)
1416 if (sigint)
1417 return NFCT_CB_STOP;
1419 synchronize_rcu();
1420 spinlock_lock(&flow_list.lock);
1422 switch (type) {
1423 case NFCT_T_NEW:
1424 flow_list_new_entry(&flow_list, ct);
1425 break;
1426 case NFCT_T_UPDATE:
1427 flow_list_update_entry(&flow_list, ct);
1428 break;
1429 case NFCT_T_DESTROY:
1430 flow_list_destroy_entry(&flow_list, ct);
1431 break;
1432 default:
1433 break;
1436 spinlock_unlock(&flow_list.lock);
1438 if (sigint)
1439 return NFCT_CB_STOP;
1441 return NFCT_CB_CONTINUE;
1444 static void collector_refresh_flows(struct nfct_handle *handle)
1446 struct flow_entry *n;
1448 n = rcu_dereference(flow_list.head);
1449 for (; n; n = rcu_dereference(n->next))
1450 nfct_query(handle, NFCT_Q_GET, n->ct);
1453 static void collector_create_filter(struct nfct_handle *nfct)
1455 struct nfct_filter *filter;
1456 int ret;
1458 filter = nfct_filter_create();
1459 if (!filter)
1460 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1462 if (what & INCLUDE_UDP) {
1463 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1464 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1466 if (what & INCLUDE_TCP)
1467 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1468 if (what & INCLUDE_DCCP)
1469 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1470 if (what & INCLUDE_SCTP)
1471 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1472 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1473 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1474 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1475 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1476 if (what & INCLUDE_IPV4) {
1477 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1478 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1480 if (what & INCLUDE_IPV6) {
1481 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1482 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1485 ret = nfct_filter_attach(nfct_fd(nfct), filter);
1486 if (ret < 0)
1487 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1489 nfct_filter_destroy(filter);
1492 /* This hand-crafted filter looks ugly but it allows to do not
1493 * flush nfct connections & filter them by user specified filter.
1494 * May be it is better to replace this one by nfct_cmp. */
1495 static int flow_dump_cb(enum nf_conntrack_msg_type type __maybe_unused,
1496 struct nf_conntrack *ct, void *data __maybe_unused)
1498 struct flow_entry fl;
1499 struct flow_entry *n = &fl;
1501 if (sigint)
1502 return NFCT_CB_STOP;
1504 synchronize_rcu();
1505 spinlock_lock(&flow_list.lock);
1507 if (!(what & ~(INCLUDE_IPV4 | INCLUDE_IPV6)))
1508 goto check_addr;
1510 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
1512 if (what & INCLUDE_UDP) {
1513 if (n->l4_proto == IPPROTO_UDP)
1514 goto check_addr;
1516 if (n->l4_proto == IPPROTO_UDPLITE)
1517 goto check_addr;
1520 if ((what & INCLUDE_TCP) && n->l4_proto == IPPROTO_TCP)
1521 goto check_addr;
1523 if ((what & INCLUDE_DCCP) && n->l4_proto == IPPROTO_DCCP)
1524 goto check_addr;
1526 if ((what & INCLUDE_SCTP) && n->l4_proto == IPPROTO_SCTP)
1527 goto check_addr;
1529 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV4) &&
1530 n->l4_proto == IPPROTO_ICMP) {
1531 goto check_addr;
1534 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV6) &&
1535 n->l4_proto == IPPROTO_ICMPV6) {
1536 goto check_addr;
1539 goto skip_flow;
1541 check_addr:
1542 /* filter loopback addresses */
1543 if (what & INCLUDE_IPV4) {
1544 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
1546 if (n->ip4_src_addr == filter_ipv4.addr)
1547 goto skip_flow;
1549 if (what & INCLUDE_IPV6) {
1550 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
1552 if (n->ip6_src_addr[0] == 0x0 &&
1553 n->ip6_src_addr[1] == 0x0 &&
1554 n->ip6_src_addr[2] == 0x0 &&
1555 n->ip6_src_addr[3] == 0x1)
1556 goto skip_flow;
1559 flow_list_new_entry(&flow_list, ct);
1561 skip_flow:
1562 spinlock_unlock(&flow_list.lock);
1563 return NFCT_CB_CONTINUE;
1566 static void collector_dump_flows(void)
1568 struct nfct_handle *nfct = nfct_open(CONNTRACK, 0);
1570 if (!nfct)
1571 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1573 nfct_callback_register(nfct, NFCT_T_ALL, flow_dump_cb, NULL);
1575 is_flow_collecting = true;
1576 if (what & INCLUDE_IPV4) {
1577 int family = AF_INET;
1578 nfct_query(nfct, NFCT_Q_DUMP, &family);
1580 if (what & INCLUDE_IPV6) {
1581 int family = AF_INET6;
1582 nfct_query(nfct, NFCT_Q_DUMP, &family);
1584 is_flow_collecting = false;
1586 nfct_close(nfct);
1589 static void *collector(void *null __maybe_unused)
1591 struct nfct_handle *ct_event;
1592 struct pollfd poll_fd[1];
1594 flow_list_init(&flow_list);
1596 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1597 NF_NETLINK_CONNTRACK_UPDATE |
1598 NF_NETLINK_CONNTRACK_DESTROY);
1599 if (!ct_event)
1600 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1602 collector_create_filter(ct_event);
1604 nfct_callback_register(ct_event, NFCT_T_ALL, flow_event_cb, NULL);
1606 poll_fd[0].fd = nfct_fd(ct_event);
1607 poll_fd[0].events = POLLIN;
1609 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1610 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1611 strerror(errno));
1613 rcu_register_thread();
1615 collector_dump_flows();
1617 while (!sigint) {
1618 int status;
1620 if (!do_reload_flows) {
1621 usleep(USEC_PER_SEC * interval);
1622 } else {
1623 do_reload_flows = false;
1625 flow_list_destroy(&flow_list);
1627 collector_create_filter(ct_event);
1628 collector_dump_flows();
1631 collector_refresh_flows(ct_event);
1633 status = poll(poll_fd, 1, 0);
1634 if (status < 0) {
1635 if (errno == EAGAIN || errno == EINTR)
1636 continue;
1638 panic("Error while polling: %s\n", strerror(errno));
1639 } else if (status == 0) {
1640 continue;
1643 if (poll_fd[0].revents & POLLIN)
1644 nfct_catch(ct_event);
1647 rcu_unregister_thread();
1649 flow_list_destroy(&flow_list);
1650 spinlock_destroy(&flow_list.lock);
1652 nfct_close(ct_event);
1654 pthread_exit(NULL);
1657 int main(int argc, char **argv)
1659 pthread_t tid;
1660 int ret, c, what_cmd = 0;
1662 setfsuid(getuid());
1663 setfsgid(getgid());
1665 while ((c = getopt_long(argc, argv, short_options, long_options,
1666 NULL)) != EOF) {
1667 switch (c) {
1668 case '4':
1669 what_cmd |= INCLUDE_IPV4;
1670 break;
1671 case '6':
1672 what_cmd |= INCLUDE_IPV6;
1673 break;
1674 case 'T':
1675 what_cmd |= INCLUDE_TCP;
1676 break;
1677 case 'U':
1678 what_cmd |= INCLUDE_UDP;
1679 break;
1680 case 'D':
1681 what_cmd |= INCLUDE_DCCP;
1682 break;
1683 case 'I':
1684 what_cmd |= INCLUDE_ICMP;
1685 break;
1686 case 'S':
1687 what_cmd |= INCLUDE_SCTP;
1688 break;
1689 case 's':
1690 show_src = true;
1691 break;
1692 case 'b':
1693 rate_type = RATE_BITS;
1694 break;
1695 case 'u':
1696 update_geoip();
1697 die();
1698 break;
1699 case 't':
1700 interval = strtoul(optarg, NULL, 10);
1701 break;
1702 case 'n':
1703 resolve_dns = false;
1704 break;
1705 case 'G':
1706 resolve_geoip = false;
1707 break;
1708 case 'h':
1709 help();
1710 break;
1711 case 'v':
1712 version();
1713 break;
1714 default:
1715 break;
1719 if (what_cmd > 0) {
1720 what = what_cmd;
1722 if (!(what & (INCLUDE_IPV4 | INCLUDE_IPV6)))
1723 what |= INCLUDE_IPV4 | INCLUDE_IPV6;
1726 rcu_init();
1728 register_signal(SIGINT, signal_handler);
1729 register_signal(SIGQUIT, signal_handler);
1730 register_signal(SIGTERM, signal_handler);
1731 register_signal(SIGHUP, signal_handler);
1733 panic_handler_add(on_panic_handler, &sysctl);
1735 conntrack_acct_enable();
1736 conntrack_tstamp_enable();
1738 if (resolve_geoip)
1739 init_geoip(1);
1741 ret = pthread_create(&tid, NULL, collector, NULL);
1742 if (ret < 0)
1743 panic("Cannot create phthread!\n");
1745 presenter();
1747 if (resolve_geoip)
1748 destroy_geoip();
1750 restore_sysctl(&sysctl);
1752 return 0;