trafgen: proto: Simplify getting lower protocol after init
[netsniff-ng-new.git] / flowtop.c
blob4c15c064e0053b92d68d528cd86352dd5405c96c
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_destroy_entry(struct flow_list *fl,
425 const struct nf_conntrack *ct)
427 struct flow_entry *n1, *n2;
428 uint32_t id = nfct_get_attr_u32(ct, ATTR_ID);
430 n1 = flow_list_find_id(fl, id);
431 if (n1) {
432 n2 = flow_list_find_prev_id(fl, id);
433 if (n2) {
434 rcu_assign_pointer(n2->next, n1->next);
435 n1->next = NULL;
437 flow_entry_xfree(n1);
438 } else {
439 struct flow_entry *next = fl->head->next;
441 flow_entry_xfree(fl->head);
442 fl->head = next;
447 static void flow_list_destroy(struct flow_list *fl)
449 struct flow_entry *n;
451 synchronize_rcu();
452 spinlock_lock(&flow_list.lock);
454 while (fl->head != NULL) {
455 n = rcu_dereference(fl->head->next);
456 fl->head->next = NULL;
458 flow_entry_xfree(fl->head);
459 rcu_assign_pointer(fl->head, n);
462 spinlock_unlock(&flow_list.lock);
465 static int walk_process(unsigned int pid, struct flow_entry *n)
467 int ret;
468 DIR *dir;
469 struct dirent *ent;
470 char path[1024];
472 if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
473 panic("giant process name! %u\n", pid);
475 dir = opendir(path);
476 if (!dir)
477 return 0;
479 while ((ent = readdir(dir))) {
480 struct stat statbuf;
482 if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
483 pid, ent->d_name) < 0)
484 continue;
486 if (stat(path, &statbuf) < 0)
487 continue;
489 if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == statbuf.st_ino) {
490 char cmdline[256];
492 ret = proc_get_cmdline(pid, cmdline, sizeof(cmdline));
493 if (ret < 0)
494 panic("Failed to get process cmdline: %s\n", strerror(errno));
496 if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0)
497 n->procname[0] = '\0';
498 n->procnum = pid;
499 closedir(dir);
500 return 1;
504 closedir(dir);
505 return 0;
508 static void walk_processes(struct flow_entry *n)
510 int ret;
511 DIR *dir;
512 struct dirent *ent;
514 /* n->inode must be set */
515 if (n->inode <= 0) {
516 n->procname[0] = '\0';
517 return;
520 dir = opendir("/proc");
521 if (!dir)
522 panic("Cannot open /proc: %s\n", strerror(errno));
524 while ((ent = readdir(dir))) {
525 const char *name = ent->d_name;
526 char *end;
527 unsigned int pid = strtoul(name, &end, 10);
529 /* not a PID */
530 if (pid == 0 && end == name)
531 continue;
533 ret = walk_process(pid, n);
534 if (ret > 0)
535 break;
538 closedir(dir);
541 static int get_port_inode(uint16_t port, int proto, bool is_ip6)
543 int ret = -ENOENT;
544 char path[128], buff[1024];
545 FILE *proc;
547 memset(path, 0, sizeof(path));
548 snprintf(path, sizeof(path), "/proc/net/%s%s",
549 l4proto2str[proto], is_ip6 ? "6" : "");
551 proc = fopen(path, "r");
552 if (!proc)
553 return -EIO;
555 memset(buff, 0, sizeof(buff));
557 while (fgets(buff, sizeof(buff), proc) != NULL) {
558 int inode = 0;
559 unsigned int lport = 0;
561 buff[sizeof(buff) - 1] = 0;
562 if (sscanf(buff, "%*u: %*X:%X %*X:%*X %*X %*X:%*X %*X:%*X "
563 "%*X %*u %*u %u", &lport, &inode) == 2) {
564 if ((uint16_t) lport == port) {
565 ret = inode;
566 break;
570 memset(buff, 0, sizeof(buff));
573 fclose(proc);
574 return ret;
577 #define CP_NFCT(elem, attr, x) \
578 do { n->elem = nfct_get_attr_u##x(ct,(attr)); } while (0)
579 #define CP_NFCT_BUFF(elem, attr) do { \
580 const uint8_t *buff = nfct_get_attr(ct,(attr)); \
581 if (buff != NULL) \
582 memcpy(n->elem, buff, sizeof(n->elem)); \
583 } while (0)
585 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct)
587 CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
588 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
590 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
591 CP_NFCT(ip4_dst_addr, ATTR_ORIG_IPV4_DST, 32);
593 CP_NFCT(port_src, ATTR_ORIG_PORT_SRC, 16);
594 CP_NFCT(port_dst, ATTR_ORIG_PORT_DST, 16);
596 CP_NFCT(status, ATTR_STATUS, 32);
598 CP_NFCT(tcp_state, ATTR_TCP_STATE, 8);
599 CP_NFCT(tcp_flags, ATTR_TCP_FLAGS_ORIG, 8);
600 CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
601 CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
603 CP_NFCT(pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
604 CP_NFCT(bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
606 CP_NFCT(pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
607 CP_NFCT(bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
609 CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
610 CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
612 CP_NFCT(flow_id, ATTR_ID, 32);
613 CP_NFCT(use, ATTR_USE, 32);
615 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
616 CP_NFCT_BUFF(ip6_dst_addr, ATTR_ORIG_IPV6_DST);
618 n->port_src = ntohs(n->port_src);
619 n->port_dst = ntohs(n->port_dst);
621 n->ip4_src_addr = ntohl(n->ip4_src_addr);
622 n->ip4_dst_addr = ntohl(n->ip4_dst_addr);
625 #define SELFLD(dir,src_member,dst_member) \
626 (((dir) == FLOW_DIR_SRC) ? n->src_member : n->dst_member)
628 static void flow_entry_get_sain4_obj(const struct flow_entry *n,
629 enum flow_direction dir,
630 struct sockaddr_in *sa)
632 memset(sa, 0, sizeof(*sa));
633 sa->sin_family = PF_INET;
634 sa->sin_addr.s_addr = htonl(SELFLD(dir, ip4_src_addr, ip4_dst_addr));
637 static void flow_entry_get_sain6_obj(const struct flow_entry *n,
638 enum flow_direction dir,
639 struct sockaddr_in6 *sa)
641 memset(sa, 0, sizeof(*sa));
642 sa->sin6_family = PF_INET6;
644 memcpy(&sa->sin6_addr, SELFLD(dir, ip6_src_addr, ip6_dst_addr),
645 sizeof(sa->sin6_addr));
648 static void
649 flow_entry_geo_city_lookup_generic(struct flow_entry *n,
650 enum flow_direction dir)
652 struct sockaddr_in sa4;
653 struct sockaddr_in6 sa6;
654 const char *city = NULL;
656 switch (n->l3_proto) {
657 default:
658 bug();
660 case AF_INET:
661 flow_entry_get_sain4_obj(n, dir, &sa4);
662 city = geoip4_city_name(&sa4);
663 break;
665 case AF_INET6:
666 flow_entry_get_sain6_obj(n, dir, &sa6);
667 city = geoip6_city_name(&sa6);
668 break;
671 build_bug_on(sizeof(n->city_src) != sizeof(n->city_dst));
673 if (city)
674 strlcpy(SELFLD(dir, city_src, city_dst), city,
675 sizeof(n->city_src));
676 else
677 SELFLD(dir, city_src, city_dst)[0] = '\0';
680 static void
681 flow_entry_geo_country_lookup_generic(struct flow_entry *n,
682 enum flow_direction dir)
684 struct sockaddr_in sa4;
685 struct sockaddr_in6 sa6;
686 const char *country = NULL;
688 switch (n->l3_proto) {
689 default:
690 bug();
692 case AF_INET:
693 flow_entry_get_sain4_obj(n, dir, &sa4);
694 country = geoip4_country_name(&sa4);
695 break;
697 case AF_INET6:
698 flow_entry_get_sain6_obj(n, dir, &sa6);
699 country = geoip6_country_name(&sa6);
700 break;
703 build_bug_on(sizeof(n->country_src) != sizeof(n->country_dst));
705 if (country)
706 strlcpy(SELFLD(dir, country_src, country_dst), country,
707 sizeof(n->country_src));
708 else
709 SELFLD(dir, country_src, country_dst)[0] = '\0';
712 static void flow_entry_get_extended_geo(struct flow_entry *n,
713 enum flow_direction dir)
715 if (resolve_geoip) {
716 flow_entry_geo_city_lookup_generic(n, dir);
717 flow_entry_geo_country_lookup_generic(n, dir);
721 static void flow_entry_get_extended_revdns(struct flow_entry *n,
722 enum flow_direction dir)
724 size_t sa_len;
725 struct sockaddr_in sa4;
726 struct sockaddr_in6 sa6;
727 struct sockaddr *sa;
728 struct hostent *hent;
730 build_bug_on(sizeof(n->rev_dns_src) != sizeof(n->rev_dns_dst));
732 switch (n->l3_proto) {
733 default:
734 bug();
736 case AF_INET:
737 flow_entry_get_sain4_obj(n, dir, &sa4);
739 if (!resolve_dns) {
740 inet_ntop(AF_INET, &sa4.sin_addr,
741 SELFLD(dir, rev_dns_src, rev_dns_dst),
742 sizeof(n->rev_dns_src));
743 return;
746 sa = (struct sockaddr *) &sa4;
747 sa_len = sizeof(sa4);
748 hent = gethostbyaddr(&sa4.sin_addr, sizeof(sa4.sin_addr), AF_INET);
749 break;
751 case AF_INET6:
752 flow_entry_get_sain6_obj(n, dir, &sa6);
754 if (!resolve_dns) {
755 inet_ntop(AF_INET6, &sa6.sin6_addr,
756 SELFLD(dir, rev_dns_src, rev_dns_dst),
757 sizeof(n->rev_dns_src));
758 return;
761 sa = (struct sockaddr *) &sa6;
762 sa_len = sizeof(sa6);
763 hent = gethostbyaddr(&sa6.sin6_addr, sizeof(sa6.sin6_addr), AF_INET6);
764 break;
767 getnameinfo(sa, sa_len, SELFLD(dir, rev_dns_src, rev_dns_dst),
768 sizeof(n->rev_dns_src), NULL, 0, NI_NUMERICHOST);
770 if (hent)
771 strlcpy(SELFLD(dir, rev_dns_src, rev_dns_dst), hent->h_name,
772 sizeof(n->rev_dns_src));
775 static void flow_entry_get_extended(struct flow_entry *n)
777 if (n->flow_id == 0)
778 return;
780 if (show_src) {
781 flow_entry_get_extended_revdns(n, FLOW_DIR_SRC);
782 flow_entry_get_extended_geo(n, FLOW_DIR_SRC);
785 flow_entry_get_extended_revdns(n, FLOW_DIR_DST);
786 flow_entry_get_extended_geo(n, FLOW_DIR_DST);
788 /* Lookup application */
789 n->inode = get_port_inode(n->port_src, n->l4_proto,
790 n->l3_proto == AF_INET6);
791 if (n->inode > 0)
792 walk_processes(n);
795 static uint16_t presenter_get_port(uint16_t src, uint16_t dst, bool is_tcp)
797 if (src < dst && src < 1024) {
798 return src;
799 } else if (dst < src && dst < 1024) {
800 return dst;
801 } else {
802 const char *tmp1, *tmp2;
803 if (is_tcp) {
804 tmp1 = lookup_port_tcp(src);
805 tmp2 = lookup_port_tcp(dst);
806 } else {
807 tmp1 = lookup_port_udp(src);
808 tmp2 = lookup_port_udp(dst);
810 if (tmp1 && !tmp2) {
811 return src;
812 } else if (!tmp1 && tmp2) {
813 return dst;
814 } else {
815 if (src < dst)
816 return src;
817 else
818 return dst;
823 static char *bandw2str(double bytes, char *buf, size_t len)
825 if (bytes > 1000000000.)
826 snprintf(buf, len, "%.1fGB", bytes / 1000000000.);
827 else if (bytes > 1000000.)
828 snprintf(buf, len, "%.1fMB", bytes / 1000000.);
829 else if (bytes > 1000.)
830 snprintf(buf, len, "%.1fkB", bytes / 1000.);
831 else
832 snprintf(buf, len, "%g bytes", bytes);
834 return buf;
837 static char *rate2str(double rate, char *buf, size_t len)
839 const char * const unit_fmt[2][4] = {
840 { "%.1fGbit/s", "%.1fMbit/s", "%.1fkbit/s", "%gbit/s" },
841 { "%.1fGB/s", "%.1fMB/s", "%.1fkB/s", "%gB/s" }
844 if (rate_type == RATE_BITS)
845 rate *= 8;
847 if (rate > 1000000000.)
848 snprintf(buf, len, unit_fmt[rate_type][0], rate / 1000000000.);
849 else if (rate > 1000000.)
850 snprintf(buf, len, unit_fmt[rate_type][1], rate / 1000000.);
851 else if (rate > 1000.)
852 snprintf(buf, len, unit_fmt[rate_type][2], rate / 1000.);
853 else
854 snprintf(buf, len, unit_fmt[rate_type][3], rate);
856 return buf;
859 static void presenter_print_counters(uint64_t bytes, uint64_t pkts,
860 double rate_bytes, double rate_pkts,
861 int color)
863 char bytes_str[64];
865 printw(" -> (");
866 attron(COLOR_PAIR(color));
867 printw("%"PRIu64" pkts", pkts);
868 if (rate_pkts) {
869 attron(COLOR_PAIR(3));
870 printw("(%.1fpps)", rate_pkts);
871 attron(COLOR_PAIR(color));
874 printw(", %s", bandw2str(bytes, bytes_str, sizeof(bytes_str) - 1));
875 if (rate_bytes) {
876 attron(COLOR_PAIR(3));
877 printw("(%s)", rate2str(rate_bytes, bytes_str,
878 sizeof(bytes_str) - 1));
879 attron(COLOR_PAIR(color));
881 attroff(COLOR_PAIR(color));
882 printw(")");
885 static void presenter_print_flow_entry_time(const struct flow_entry *n)
887 int h, m, s;
888 time_t now;
890 time(&now);
892 s = now - (n->timestamp_start / NSEC_PER_SEC);
893 if (s <= 0)
894 return;
896 h = s / 3600;
897 s -= h * 3600;
898 m = s / 60;
899 s -= m * 60;
901 printw(" [ time");
902 if (h > 0)
903 printw(" %dh", h);
904 if (m > 0)
905 printw(" %dm", m);
906 if (s > 0)
907 printw(" %ds", s);
908 printw(" ]");
911 static void draw_flow_entry(WINDOW *screen, const struct flow_entry *n,
912 unsigned int *line)
914 char tmp[128];
915 const char *pname = NULL;
916 uint16_t port;
918 mvwprintw(screen, *line, 2, "");
920 /* PID, application name */
921 if (n->procnum > 0) {
922 slprintf(tmp, sizeof(tmp), "%s(%d)", n->procname, n->procnum);
924 printw("[");
925 attron(COLOR_PAIR(3));
926 printw("%s", tmp);
927 attroff(COLOR_PAIR(3));
928 printw("]:");
931 /* L3 protocol, L4 protocol, states */
932 printw("%s:%s", l3proto2str[n->l3_proto], l4proto2str[n->l4_proto]);
933 printw("[");
934 attron(COLOR_PAIR(3));
935 switch (n->l4_proto) {
936 case IPPROTO_TCP:
937 printw("%s", tcp_state2str[n->tcp_state]);
938 break;
939 case IPPROTO_SCTP:
940 printw("%s", sctp_state2str[n->sctp_state]);
941 break;
942 case IPPROTO_DCCP:
943 printw("%s", dccp_state2str[n->dccp_state]);
944 break;
945 case IPPROTO_UDP:
946 case IPPROTO_UDPLITE:
947 case IPPROTO_ICMP:
948 case IPPROTO_ICMPV6:
949 printw("NOSTATE");
950 break;
952 attroff(COLOR_PAIR(3));
953 printw("]");
955 /* Guess application port */
956 switch (n->l4_proto) {
957 case IPPROTO_TCP:
958 port = presenter_get_port(n->port_src, n->port_dst, true);
959 pname = lookup_port_tcp(port);
960 break;
961 case IPPROTO_UDP:
962 case IPPROTO_UDPLITE:
963 port = presenter_get_port(n->port_src, n->port_dst, false);
964 pname = lookup_port_udp(port);
965 break;
967 if (pname) {
968 attron(A_BOLD);
969 printw(":%s", pname);
970 attroff(A_BOLD);
973 if (n->timestamp_start > 0)
974 presenter_print_flow_entry_time(n);
976 /* Show source information: reverse DNS, port, country, city, counters */
977 if (show_src) {
978 attron(COLOR_PAIR(1));
979 mvwprintw(screen, ++(*line), 8, "src: %s", n->rev_dns_src);
980 attroff(COLOR_PAIR(1));
982 printw(":%"PRIu16, n->port_src);
984 if (n->country_src[0]) {
985 printw(" (");
987 attron(COLOR_PAIR(4));
988 printw("%s", n->country_src);
989 attroff(COLOR_PAIR(4));
991 if (n->city_src[0])
992 printw(", %s", n->city_src);
994 printw(")");
997 if (n->pkts_src > 0 && n->bytes_src > 0)
998 presenter_print_counters(n->bytes_src, n->pkts_src,
999 n->rate_bytes_src,
1000 n->rate_pkts_src, 1);
1002 printw(" => ");
1005 /* Show dest information: reverse DNS, port, country, city, counters */
1006 attron(COLOR_PAIR(2));
1007 mvwprintw(screen, ++(*line), 8, "dst: %s", n->rev_dns_dst);
1008 attroff(COLOR_PAIR(2));
1010 printw(":%"PRIu16, n->port_dst);
1012 if (n->country_dst[0]) {
1013 printw(" (");
1015 attron(COLOR_PAIR(4));
1016 printw("%s", n->country_dst);
1017 attroff(COLOR_PAIR(4));
1019 if (n->city_dst[0])
1020 printw(", %s", n->city_dst);
1022 printw(")");
1025 if (n->pkts_dst > 0 && n->bytes_dst > 0)
1026 presenter_print_counters(n->bytes_dst, n->pkts_dst,
1027 n->rate_bytes_dst,
1028 n->rate_pkts_dst, 2);
1031 static inline bool presenter_flow_wrong_state(struct flow_entry *n)
1033 switch (n->l4_proto) {
1034 case IPPROTO_TCP:
1035 switch (n->tcp_state) {
1036 case TCP_CONNTRACK_SYN_SENT:
1037 case TCP_CONNTRACK_SYN_RECV:
1038 case TCP_CONNTRACK_ESTABLISHED:
1039 case TCP_CONNTRACK_FIN_WAIT:
1040 case TCP_CONNTRACK_CLOSE_WAIT:
1041 case TCP_CONNTRACK_LAST_ACK:
1042 case TCP_CONNTRACK_TIME_WAIT:
1043 case TCP_CONNTRACK_CLOSE:
1044 case TCP_CONNTRACK_SYN_SENT2:
1045 case TCP_CONNTRACK_NONE:
1046 return false;
1047 break;
1049 break;
1050 case IPPROTO_SCTP:
1051 switch (n->sctp_state) {
1052 case SCTP_CONNTRACK_NONE:
1053 case SCTP_CONNTRACK_CLOSED:
1054 case SCTP_CONNTRACK_COOKIE_WAIT:
1055 case SCTP_CONNTRACK_COOKIE_ECHOED:
1056 case SCTP_CONNTRACK_ESTABLISHED:
1057 case SCTP_CONNTRACK_SHUTDOWN_SENT:
1058 case SCTP_CONNTRACK_SHUTDOWN_RECD:
1059 case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT:
1060 return false;
1061 break;
1063 break;
1064 case IPPROTO_DCCP:
1065 switch (n->dccp_state) {
1066 case DCCP_CONNTRACK_NONE:
1067 case DCCP_CONNTRACK_REQUEST:
1068 case DCCP_CONNTRACK_RESPOND:
1069 case DCCP_CONNTRACK_PARTOPEN:
1070 case DCCP_CONNTRACK_OPEN:
1071 case DCCP_CONNTRACK_CLOSEREQ:
1072 case DCCP_CONNTRACK_CLOSING:
1073 case DCCP_CONNTRACK_TIMEWAIT:
1074 case DCCP_CONNTRACK_IGNORE:
1075 case DCCP_CONNTRACK_INVALID:
1076 return false;
1077 break;
1079 break;
1080 case IPPROTO_UDP:
1081 case IPPROTO_UDPLITE:
1082 case IPPROTO_ICMP:
1083 case IPPROTO_ICMPV6:
1084 return false;
1085 break;
1088 return true;
1091 static void draw_flows(WINDOW *screen, struct flow_list *fl,
1092 int skip_lines)
1094 int skip_left = skip_lines;
1095 unsigned int flows = 0;
1096 unsigned int line = 3;
1097 struct flow_entry *n;
1098 int maxy = rows - 6;
1100 wclear(screen);
1101 clear();
1103 rcu_read_lock();
1105 n = rcu_dereference(fl->head);
1106 if (!n)
1107 mvwprintw(screen, line, 2, "(No sessions! "
1108 "Is netfilter running?)");
1110 for (; n; n = rcu_dereference(n->next)) {
1111 if (!n->is_visible)
1112 continue;
1114 if (presenter_flow_wrong_state(n))
1115 continue;
1117 /* count only flows which might be showed */
1118 flows++;
1120 if (maxy <= 0)
1121 continue;
1123 if (skip_left > 0) {
1124 skip_left--;
1125 continue;
1128 draw_flow_entry(screen, n, &line);
1130 line++;
1131 maxy -= (2 + (show_src ? 1 : 0));
1134 mvwprintw(screen, 1, 2, "Kernel netfilter flows(%u) for ", flows);
1136 if (what & INCLUDE_IPV4)
1137 printw("IPv4,");
1138 if (what & INCLUDE_IPV6)
1139 printw("IPv6,");
1140 if (what & INCLUDE_TCP)
1141 printw("TCP,");
1142 if (what & INCLUDE_UDP)
1143 printw("UDP,");
1144 if (what & INCLUDE_SCTP)
1145 printw("SCTP,");
1146 if (what & INCLUDE_DCCP)
1147 printw("DCCP,");
1148 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1149 printw("ICMP,");
1150 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1151 printw("ICMP6,");
1152 if (show_active_only)
1153 printw("Active,");
1155 printw(" [+%d]", skip_lines);
1157 if (is_flow_collecting)
1158 printw(" [Collecting flows ...]");
1160 rcu_read_unlock();
1163 static void draw_help(WINDOW *screen)
1165 int col = 0;
1166 int row = 1;
1167 int i;
1169 mvaddch(row, col, ACS_ULCORNER);
1170 mvaddch(rows - row - 1, col, ACS_LLCORNER);
1172 mvaddch(row, cols - 1, ACS_URCORNER);
1173 mvaddch(rows - row - 1, cols - 1, ACS_LRCORNER);
1175 for (i = 1; i < rows - row - 2; i++) {
1176 mvaddch(row + i, 0, ACS_VLINE);
1177 mvaddch(row + i, cols - 1, ACS_VLINE);
1179 for (i = 1; i < cols - col - 1; i++) {
1180 mvaddch(row, col + i, ACS_HLINE);
1181 mvaddch(rows - row - 1, col + i, ACS_HLINE);
1184 attron(A_BOLD);
1185 mvaddnstr(row, cols / 2 - 2, "| Help |", -1);
1187 attron(A_UNDERLINE);
1188 mvaddnstr(row + 2, col + 2, "Navigation", -1);
1189 attroff(A_BOLD | A_UNDERLINE);
1191 mvaddnstr(row + 4, col + 3, "Up, u, k Move up", -1);
1192 mvaddnstr(row + 5, col + 3, "Down, d, j Move down", -1);
1193 mvaddnstr(row + 6, col + 3, "? Toggle help window", -1);
1194 mvaddnstr(row + 7, col + 3, "q, Ctrl+C Quit", -1);
1196 attron(A_BOLD | A_UNDERLINE);
1197 mvaddnstr(row + 9, col + 2, "Display Settings", -1);
1198 attroff(A_BOLD | A_UNDERLINE);
1200 mvaddnstr(row + 11, col + 3, "b Toggle rate units (bits/bytes)", -1);
1201 mvaddnstr(row + 12, col + 3, "a Toggle display of active flows (rate > 0) only", -1);
1203 mvaddnstr(row + 14, col + 3, "T Toggle display TCP flows", -1);
1204 mvaddnstr(row + 15, col + 3, "U Toggle display UDP flows", -1);
1205 mvaddnstr(row + 16, col + 3, "D Toggle display DCCP flows", -1);
1206 mvaddnstr(row + 17, col + 3, "I Toggle display ICMP flows", -1);
1207 mvaddnstr(row + 18, col + 3, "S Toggle display SCTP flows", -1);
1210 static void draw_header(WINDOW *screen)
1212 int i;
1214 attron(A_STANDOUT);
1216 for (i = 0; i < cols; i++)
1217 mvaddch(0, i, ' ');
1219 mvwprintw(screen, 0, 2, "flowtop %s", VERSION_LONG);
1220 attroff(A_STANDOUT);
1223 static void draw_footer(WINDOW *screen)
1225 int i;
1227 attron(A_STANDOUT);
1229 for (i = 0; i < cols; i++)
1230 mvaddch(rows - 1, i, ' ');
1232 mvaddnstr(rows - 1, 1, "Press '?' for help", -1);
1233 addch(ACS_VLINE);
1234 attroff(A_STANDOUT);
1237 static void show_option_toggle(int opt)
1239 switch (opt) {
1240 case 'T':
1241 TOGGLE_FLAG(what, INCLUDE_TCP);
1242 break;
1243 case 'U':
1244 TOGGLE_FLAG(what, INCLUDE_UDP);
1245 break;
1246 case 'D':
1247 TOGGLE_FLAG(what, INCLUDE_DCCP);
1248 break;
1249 case 'I':
1250 TOGGLE_FLAG(what, INCLUDE_ICMP);
1251 break;
1252 case 'S':
1253 TOGGLE_FLAG(what, INCLUDE_SCTP);
1254 break;
1258 static void presenter(void)
1260 int time_sleep_us = 200000;
1261 int time_passed_us = 0;
1262 bool show_help = false;
1263 int skip_lines = 0;
1264 WINDOW *screen;
1266 lookup_init(LT_PORTS_TCP);
1267 lookup_init(LT_PORTS_UDP);
1268 screen = screen_init(false);
1270 start_color();
1271 init_pair(1, COLOR_RED, COLOR_BLACK);
1272 init_pair(2, COLOR_BLUE, COLOR_BLACK);
1273 init_pair(3, COLOR_YELLOW, COLOR_BLACK);
1274 init_pair(4, COLOR_GREEN, COLOR_BLACK);
1276 rcu_register_thread();
1277 while (!sigint) {
1278 bool redraw_flows = true;
1279 int ch;
1281 curs_set(0);
1282 getmaxyx(screen, rows, cols);
1284 ch = getch();
1285 switch (ch) {
1286 case 'q':
1287 sigint = 1;
1288 break;
1289 case KEY_UP:
1290 case 'u':
1291 case 'k':
1292 skip_lines--;
1293 if (skip_lines < 0)
1294 skip_lines = 0;
1295 break;
1296 case KEY_DOWN:
1297 case 'd':
1298 case 'j':
1299 skip_lines++;
1300 if (skip_lines > SCROLL_MAX)
1301 skip_lines = SCROLL_MAX;
1302 break;
1303 case 'b':
1304 if (rate_type == RATE_BYTES)
1305 rate_type = RATE_BITS;
1306 else
1307 rate_type = RATE_BYTES;
1308 break;
1309 case 'a':
1310 show_active_only = !show_active_only;
1311 break;
1312 case '?':
1313 show_help = !show_help;
1314 wclear(screen);
1315 clear();
1316 break;
1317 case 'T':
1318 case 'U':
1319 case 'D':
1320 case 'I':
1321 case 'S':
1322 show_option_toggle(ch);
1323 do_reload_flows = true;
1324 break;
1325 default:
1326 fflush(stdin);
1327 redraw_flows = false;
1328 break;
1331 if (!redraw_flows)
1332 redraw_flows = time_passed_us >= 1 * USEC_PER_SEC;
1334 if (show_help)
1335 redraw_flows = false;
1337 if (redraw_flows) {
1338 draw_flows(screen, &flow_list, skip_lines);
1339 time_passed_us = 0;
1340 } else {
1341 time_passed_us += time_sleep_us;
1344 draw_header(screen);
1346 if (show_help)
1347 draw_help(screen);
1349 draw_footer(screen);
1351 wrefresh(screen);
1352 refresh();
1353 usleep(time_sleep_us);
1355 rcu_unregister_thread();
1357 screen_end();
1358 lookup_cleanup(LT_PORTS_UDP);
1359 lookup_cleanup(LT_PORTS_TCP);
1362 static void restore_sysctl(void *obj)
1364 struct sysctl_params_ctx *sysctl_ctx = obj;
1366 if (sysctl_ctx->nfct_acct == 0)
1367 sysctl_set_int("net/netfilter/nf_conntrack_acct",
1368 sysctl_ctx->nfct_acct);
1370 if (sysctl_ctx->nfct_tstamp == 0)
1371 sysctl_set_int("net/netfilter/nf_conntrack_timestamp",
1372 sysctl_ctx->nfct_tstamp);
1375 static void on_panic_handler(void *arg)
1377 restore_sysctl(arg);
1378 screen_end();
1381 static void conntrack_acct_enable(void)
1383 /* We can still work w/o traffic accounting so just warn about error */
1384 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &sysctl.nfct_acct)) {
1385 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1386 strerror(errno));
1387 return;
1390 if (sysctl.nfct_acct == 1)
1391 return;
1393 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1394 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1395 strerror(errno));
1399 static void conntrack_tstamp_enable(void)
1401 if (sysctl_get_int("net/netfilter/nf_conntrack_timestamp", &sysctl.nfct_tstamp)) {
1402 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_timestamp: %s\n",
1403 strerror(errno));
1404 return;
1407 if (sysctl.nfct_tstamp == 1)
1408 return;
1410 if (sysctl_set_int("net/netfilter/nf_conntrack_timestamp", 1)) {
1411 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_timestamp: %s\n",
1412 strerror(errno));
1416 static void flow_entry_filter(struct flow_entry *n)
1418 if (show_active_only && !n->rate_bytes_src && !n->rate_bytes_dst)
1419 n->is_visible = false;
1420 else
1421 n->is_visible = true;
1424 static int flow_list_update_entry(struct flow_list *fl, struct nf_conntrack *ct)
1426 struct flow_entry *n;
1428 n = flow_list_find_id(&flow_list, nfct_get_attr_u32(ct, ATTR_ID));
1429 if (!n)
1430 return NFCT_CB_CONTINUE;
1432 flow_entry_calc_rate(n, ct);
1433 flow_entry_update_time(n);
1434 flow_entry_from_ct(n, ct);
1435 flow_entry_filter(n);
1437 return NFCT_CB_CONTINUE;
1440 static int flow_event_cb(enum nf_conntrack_msg_type type,
1441 struct nf_conntrack *ct, void *data __maybe_unused)
1443 if (sigint)
1444 return NFCT_CB_STOP;
1446 synchronize_rcu();
1447 spinlock_lock(&flow_list.lock);
1449 switch (type) {
1450 case NFCT_T_NEW:
1451 flow_list_new_entry(&flow_list, ct);
1452 break;
1453 case NFCT_T_UPDATE:
1454 flow_list_update_entry(&flow_list, ct);
1455 break;
1456 case NFCT_T_DESTROY:
1457 flow_list_destroy_entry(&flow_list, ct);
1458 break;
1459 default:
1460 break;
1463 spinlock_unlock(&flow_list.lock);
1465 if (sigint)
1466 return NFCT_CB_STOP;
1468 return NFCT_CB_CONTINUE;
1471 static void collector_refresh_flows(struct nfct_handle *handle)
1473 struct flow_entry *n;
1475 n = rcu_dereference(flow_list.head);
1476 for (; n; n = rcu_dereference(n->next))
1477 nfct_query(handle, NFCT_Q_GET, n->ct);
1480 static void collector_create_filter(struct nfct_handle *nfct)
1482 struct nfct_filter *filter;
1483 int ret;
1485 filter = nfct_filter_create();
1486 if (!filter)
1487 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1489 if (what & INCLUDE_UDP) {
1490 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1491 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1493 if (what & INCLUDE_TCP)
1494 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1495 if (what & INCLUDE_DCCP)
1496 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1497 if (what & INCLUDE_SCTP)
1498 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1499 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1500 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1501 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1502 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1503 if (what & INCLUDE_IPV4) {
1504 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1505 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1507 if (what & INCLUDE_IPV6) {
1508 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1509 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1512 ret = nfct_filter_attach(nfct_fd(nfct), filter);
1513 if (ret < 0)
1514 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1516 nfct_filter_destroy(filter);
1519 /* This hand-crafted filter looks ugly but it allows to do not
1520 * flush nfct connections & filter them by user specified filter.
1521 * May be it is better to replace this one by nfct_cmp. */
1522 static int flow_dump_cb(enum nf_conntrack_msg_type type,
1523 struct nf_conntrack *ct, void *data __maybe_unused)
1525 struct flow_entry fl;
1526 struct flow_entry *n = &fl;
1528 if (sigint)
1529 return NFCT_CB_STOP;
1531 synchronize_rcu();
1532 spinlock_lock(&flow_list.lock);
1534 if (!(what & ~(INCLUDE_IPV4 | INCLUDE_IPV6)))
1535 goto check_addr;
1537 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
1539 if (what & INCLUDE_UDP) {
1540 if (n->l4_proto == IPPROTO_UDP)
1541 goto check_addr;
1543 if (n->l4_proto == IPPROTO_UDPLITE)
1544 goto check_addr;
1547 if ((what & INCLUDE_TCP) && n->l4_proto == IPPROTO_TCP)
1548 goto check_addr;
1550 if ((what & INCLUDE_DCCP) && n->l4_proto == IPPROTO_DCCP)
1551 goto check_addr;
1553 if ((what & INCLUDE_SCTP) && n->l4_proto == IPPROTO_SCTP)
1554 goto check_addr;
1556 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV4) &&
1557 n->l4_proto == IPPROTO_ICMP) {
1558 goto check_addr;
1561 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV6) &&
1562 n->l4_proto == IPPROTO_ICMPV6) {
1563 goto check_addr;
1566 goto skip_flow;
1568 check_addr:
1569 /* filter loopback addresses */
1570 if (what & INCLUDE_IPV4) {
1571 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
1573 if (n->ip4_src_addr == filter_ipv4.addr)
1574 goto skip_flow;
1576 if (what & INCLUDE_IPV6) {
1577 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
1579 if (n->ip6_src_addr[0] == 0x0 &&
1580 n->ip6_src_addr[1] == 0x0 &&
1581 n->ip6_src_addr[2] == 0x0 &&
1582 n->ip6_src_addr[3] == 0x1)
1583 goto skip_flow;
1586 flow_list_new_entry(&flow_list, ct);
1588 skip_flow:
1589 spinlock_unlock(&flow_list.lock);
1590 return NFCT_CB_CONTINUE;
1593 static void collector_dump_flows(void)
1595 struct nfct_handle *nfct = nfct_open(CONNTRACK, 0);
1597 if (!nfct)
1598 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1600 nfct_callback_register(nfct, NFCT_T_ALL, flow_dump_cb, NULL);
1602 is_flow_collecting = true;
1603 if (what & INCLUDE_IPV4) {
1604 int family = AF_INET;
1605 nfct_query(nfct, NFCT_Q_DUMP, &family);
1607 if (what & INCLUDE_IPV6) {
1608 int family = AF_INET6;
1609 nfct_query(nfct, NFCT_Q_DUMP, &family);
1611 is_flow_collecting = false;
1613 nfct_close(nfct);
1616 static void *collector(void *null __maybe_unused)
1618 struct nfct_handle *ct_event;
1619 struct pollfd poll_fd[1];
1621 flow_list_init(&flow_list);
1623 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1624 NF_NETLINK_CONNTRACK_UPDATE |
1625 NF_NETLINK_CONNTRACK_DESTROY);
1626 if (!ct_event)
1627 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1629 collector_create_filter(ct_event);
1631 nfct_callback_register(ct_event, NFCT_T_ALL, flow_event_cb, NULL);
1633 poll_fd[0].fd = nfct_fd(ct_event);
1634 poll_fd[0].events = POLLIN;
1636 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1637 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1638 strerror(errno));
1640 rcu_register_thread();
1642 collector_dump_flows();
1644 while (!sigint) {
1645 int status;
1647 if (!do_reload_flows) {
1648 usleep(USEC_PER_SEC * interval);
1649 } else {
1650 do_reload_flows = false;
1652 flow_list_destroy(&flow_list);
1654 collector_create_filter(ct_event);
1655 collector_dump_flows();
1658 collector_refresh_flows(ct_event);
1660 status = poll(poll_fd, 1, 0);
1661 if (status < 0) {
1662 if (errno == EAGAIN || errno == EINTR)
1663 continue;
1665 panic("Error while polling: %s\n", strerror(errno));
1666 } else if (status == 0) {
1667 continue;
1670 if (poll_fd[0].revents & POLLIN)
1671 nfct_catch(ct_event);
1674 rcu_unregister_thread();
1676 flow_list_destroy(&flow_list);
1677 spinlock_destroy(&flow_list.lock);
1679 nfct_close(ct_event);
1681 pthread_exit(NULL);
1684 int main(int argc, char **argv)
1686 pthread_t tid;
1687 int ret, c, opt_index, what_cmd = 0;
1689 setfsuid(getuid());
1690 setfsgid(getgid());
1692 while ((c = getopt_long(argc, argv, short_options, long_options,
1693 &opt_index)) != EOF) {
1694 switch (c) {
1695 case '4':
1696 what_cmd |= INCLUDE_IPV4;
1697 break;
1698 case '6':
1699 what_cmd |= INCLUDE_IPV6;
1700 break;
1701 case 'T':
1702 what_cmd |= INCLUDE_TCP;
1703 break;
1704 case 'U':
1705 what_cmd |= INCLUDE_UDP;
1706 break;
1707 case 'D':
1708 what_cmd |= INCLUDE_DCCP;
1709 break;
1710 case 'I':
1711 what_cmd |= INCLUDE_ICMP;
1712 break;
1713 case 'S':
1714 what_cmd |= INCLUDE_SCTP;
1715 break;
1716 case 's':
1717 show_src = true;
1718 break;
1719 case 'b':
1720 rate_type = RATE_BITS;
1721 break;
1722 case 'u':
1723 update_geoip();
1724 die();
1725 break;
1726 case 't':
1727 interval = strtoul(optarg, NULL, 10);
1728 break;
1729 case 'n':
1730 resolve_dns = false;
1731 break;
1732 case 'G':
1733 resolve_geoip = false;
1734 break;
1735 case 'h':
1736 help();
1737 break;
1738 case 'v':
1739 version();
1740 break;
1741 default:
1742 break;
1746 if (what_cmd > 0) {
1747 what = what_cmd;
1749 if (!(what & (INCLUDE_IPV4 | INCLUDE_IPV6)))
1750 what |= INCLUDE_IPV4 | INCLUDE_IPV6;
1753 rcu_init();
1755 register_signal(SIGINT, signal_handler);
1756 register_signal(SIGQUIT, signal_handler);
1757 register_signal(SIGTERM, signal_handler);
1758 register_signal(SIGHUP, signal_handler);
1760 panic_handler_add(on_panic_handler, &sysctl);
1762 conntrack_acct_enable();
1763 conntrack_tstamp_enable();
1765 if (resolve_geoip)
1766 init_geoip(1);
1768 ret = pthread_create(&tid, NULL, collector, NULL);
1769 if (ret < 0)
1770 panic("Cannot create phthread!\n");
1772 presenter();
1774 if (resolve_geoip)
1775 destroy_geoip();
1777 restore_sysctl(&sysctl);
1779 return 0;