trafgen: Make sure yyin is set before close it
[netsniff-ng.git] / flowtop.c
blobd38dbd105a2cae31be0e9890c2406d950d5055f8
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,
1149 "Kernel netfilter flows(%u) for %s%s%s%s%s%s"
1150 "[+%d]", flows, what & INCLUDE_TCP ? "TCP, " : "",
1151 what & INCLUDE_UDP ? "UDP, " : "",
1152 what & INCLUDE_SCTP ? "SCTP, " : "",
1153 what & INCLUDE_DCCP ? "DCCP, " : "",
1154 what & INCLUDE_ICMP && what & INCLUDE_IPV4 ? "ICMP, " : "",
1155 what & INCLUDE_ICMP && what & INCLUDE_IPV6 ? "ICMP6, " : "",
1156 skip_lines);
1158 if (is_flow_collecting)
1159 printw(" [Collecting flows ...]");
1161 rcu_read_unlock();
1164 static void draw_help(WINDOW *screen)
1166 int col = 0;
1167 int row = 1;
1168 int i;
1170 mvaddch(row, col, ACS_ULCORNER);
1171 mvaddch(rows - row - 1, col, ACS_LLCORNER);
1173 mvaddch(row, cols - 1, ACS_URCORNER);
1174 mvaddch(rows - row - 1, cols - 1, ACS_LRCORNER);
1176 for (i = 1; i < rows - row - 2; i++) {
1177 mvaddch(row + i, 0, ACS_VLINE);
1178 mvaddch(row + i, cols - 1, ACS_VLINE);
1180 for (i = 1; i < cols - col - 1; i++) {
1181 mvaddch(row, col + i, ACS_HLINE);
1182 mvaddch(rows - row - 1, col + i, ACS_HLINE);
1185 attron(A_BOLD);
1186 mvaddnstr(row, cols / 2 - 2, "| Help |", -1);
1188 attron(A_UNDERLINE);
1189 mvaddnstr(row + 2, col + 2, "Navigation", -1);
1190 attroff(A_BOLD | A_UNDERLINE);
1192 mvaddnstr(row + 4, col + 3, "Up, u, k Move up", -1);
1193 mvaddnstr(row + 5, col + 3, "Down, d, j Move down", -1);
1194 mvaddnstr(row + 6, col + 3, "? Toggle help window", -1);
1195 mvaddnstr(row + 7, col + 3, "q, Ctrl+C Quit", -1);
1197 attron(A_BOLD | A_UNDERLINE);
1198 mvaddnstr(row + 9, col + 2, "Display Settings", -1);
1199 attroff(A_BOLD | A_UNDERLINE);
1201 mvaddnstr(row + 11, col + 3, "b Toggle rate units (bits/bytes)", -1);
1202 mvaddnstr(row + 12, col + 3, "a Toggle display of active flows (rate > 0) only", -1);
1204 mvaddnstr(row + 14, col + 3, "T Toggle display TCP flows", -1);
1205 mvaddnstr(row + 15, col + 3, "U Toggle display UDP flows", -1);
1206 mvaddnstr(row + 16, col + 3, "D Toggle display DCCP flows", -1);
1207 mvaddnstr(row + 17, col + 3, "I Toggle display ICMP flows", -1);
1208 mvaddnstr(row + 18, col + 3, "S Toggle display SCTP flows", -1);
1211 static void draw_header(WINDOW *screen)
1213 int i;
1215 attron(A_STANDOUT);
1217 for (i = 0; i < cols; i++)
1218 mvaddch(0, i, ' ');
1220 mvwprintw(screen, 0, 2, "flowtop %s", VERSION_LONG);
1221 attroff(A_STANDOUT);
1224 static void draw_footer(WINDOW *screen)
1226 int i;
1228 attron(A_STANDOUT);
1230 for (i = 0; i < cols; i++)
1231 mvaddch(rows - 1, i, ' ');
1233 mvaddnstr(rows - 1, 1, "Press '?' for help", -1);
1234 addch(ACS_VLINE);
1235 attroff(A_STANDOUT);
1238 static void show_option_toggle(int opt)
1240 switch (opt) {
1241 case 'T':
1242 TOGGLE_FLAG(what, INCLUDE_TCP);
1243 break;
1244 case 'U':
1245 TOGGLE_FLAG(what, INCLUDE_UDP);
1246 break;
1247 case 'D':
1248 TOGGLE_FLAG(what, INCLUDE_DCCP);
1249 break;
1250 case 'I':
1251 TOGGLE_FLAG(what, INCLUDE_ICMP);
1252 break;
1253 case 'S':
1254 TOGGLE_FLAG(what, INCLUDE_SCTP);
1255 break;
1259 static void presenter(void)
1261 int time_sleep_us = 200000;
1262 int time_passed_us = 0;
1263 bool show_help = false;
1264 int skip_lines = 0;
1265 WINDOW *screen;
1267 lookup_init(LT_PORTS_TCP);
1268 lookup_init(LT_PORTS_UDP);
1269 screen = screen_init(false);
1271 start_color();
1272 init_pair(1, COLOR_RED, COLOR_BLACK);
1273 init_pair(2, COLOR_BLUE, COLOR_BLACK);
1274 init_pair(3, COLOR_YELLOW, COLOR_BLACK);
1275 init_pair(4, COLOR_GREEN, COLOR_BLACK);
1277 rcu_register_thread();
1278 while (!sigint) {
1279 bool redraw_flows = true;
1280 int ch;
1282 curs_set(0);
1283 getmaxyx(screen, rows, cols);
1285 ch = getch();
1286 switch (ch) {
1287 case 'q':
1288 sigint = 1;
1289 break;
1290 case KEY_UP:
1291 case 'u':
1292 case 'k':
1293 skip_lines--;
1294 if (skip_lines < 0)
1295 skip_lines = 0;
1296 break;
1297 case KEY_DOWN:
1298 case 'd':
1299 case 'j':
1300 skip_lines++;
1301 if (skip_lines > SCROLL_MAX)
1302 skip_lines = SCROLL_MAX;
1303 break;
1304 case 'b':
1305 if (rate_type == RATE_BYTES)
1306 rate_type = RATE_BITS;
1307 else
1308 rate_type = RATE_BYTES;
1309 break;
1310 case 'a':
1311 show_active_only = !show_active_only;
1312 break;
1313 case '?':
1314 show_help = !show_help;
1315 wclear(screen);
1316 clear();
1317 break;
1318 case 'T':
1319 case 'U':
1320 case 'D':
1321 case 'I':
1322 case 'S':
1323 show_option_toggle(ch);
1324 do_reload_flows = true;
1325 break;
1326 default:
1327 fflush(stdin);
1328 redraw_flows = false;
1329 break;
1332 if (!redraw_flows)
1333 redraw_flows = time_passed_us >= 1 * USEC_PER_SEC;
1335 if (show_help)
1336 redraw_flows = false;
1338 if (redraw_flows) {
1339 draw_flows(screen, &flow_list, skip_lines);
1340 time_passed_us = 0;
1341 } else {
1342 time_passed_us += time_sleep_us;
1345 draw_header(screen);
1347 if (show_help)
1348 draw_help(screen);
1350 draw_footer(screen);
1352 wrefresh(screen);
1353 refresh();
1354 usleep(time_sleep_us);
1356 rcu_unregister_thread();
1358 screen_end();
1359 lookup_cleanup(LT_PORTS_UDP);
1360 lookup_cleanup(LT_PORTS_TCP);
1363 static int flow_event_cb(enum nf_conntrack_msg_type type,
1364 struct nf_conntrack *ct, void *data __maybe_unused)
1366 if (sigint)
1367 return NFCT_CB_STOP;
1369 synchronize_rcu();
1370 spinlock_lock(&flow_list.lock);
1372 switch (type) {
1373 case NFCT_T_NEW:
1374 flow_list_new_entry(&flow_list, ct);
1375 break;
1376 case NFCT_T_UPDATE:
1377 flow_list_update_entry(&flow_list, ct);
1378 break;
1379 case NFCT_T_DESTROY:
1380 flow_list_destroy_entry(&flow_list, ct);
1381 break;
1382 default:
1383 break;
1386 spinlock_unlock(&flow_list.lock);
1388 return NFCT_CB_CONTINUE;
1391 static void restore_sysctl(void *obj)
1393 struct sysctl_params_ctx *sysctl_ctx = obj;
1395 if (sysctl_ctx->nfct_acct == 0)
1396 sysctl_set_int("net/netfilter/nf_conntrack_acct",
1397 sysctl_ctx->nfct_acct);
1399 if (sysctl_ctx->nfct_tstamp == 0)
1400 sysctl_set_int("net/netfilter/nf_conntrack_timestamp",
1401 sysctl_ctx->nfct_tstamp);
1404 static void on_panic_handler(void *arg)
1406 restore_sysctl(arg);
1407 screen_end();
1410 static void conntrack_acct_enable(void)
1412 /* We can still work w/o traffic accounting so just warn about error */
1413 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &sysctl.nfct_acct)) {
1414 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1415 strerror(errno));
1416 return;
1419 if (sysctl.nfct_acct == 1)
1420 return;
1422 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1423 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1424 strerror(errno));
1428 static void conntrack_tstamp_enable(void)
1430 if (sysctl_get_int("net/netfilter/nf_conntrack_timestamp", &sysctl.nfct_tstamp)) {
1431 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_timestamp: %s\n",
1432 strerror(errno));
1433 return;
1436 if (sysctl.nfct_tstamp == 1)
1437 return;
1439 if (sysctl_set_int("net/netfilter/nf_conntrack_timestamp", 1)) {
1440 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_timestamp: %s\n",
1441 strerror(errno));
1445 static void flow_entry_filter(struct flow_entry *n)
1447 if (show_active_only && !n->rate_bytes_src && !n->rate_bytes_dst)
1448 n->is_visible = false;
1449 else
1450 n->is_visible = true;
1453 static int flow_update_cb(enum nf_conntrack_msg_type type,
1454 struct nf_conntrack *ct, void *data __maybe_unused)
1456 struct flow_entry *n;
1458 if (type != NFCT_T_UPDATE)
1459 return NFCT_CB_CONTINUE;
1461 if (sigint)
1462 return NFCT_CB_STOP;
1464 n = flow_list_find_id(&flow_list, nfct_get_attr_u32(ct, ATTR_ID));
1465 if (!n)
1466 return NFCT_CB_CONTINUE;
1468 flow_entry_calc_rate(n, ct);
1469 flow_entry_update_time(n);
1470 flow_entry_from_ct(n, ct);
1471 flow_entry_filter(n);
1473 return NFCT_CB_CONTINUE;
1476 static void collector_refresh_flows(struct nfct_handle *handle)
1478 struct flow_entry *n;
1480 n = rcu_dereference(flow_list.head);
1481 for (; n; n = rcu_dereference(n->next))
1482 nfct_query(handle, NFCT_Q_GET, n->ct);
1485 static void collector_create_filter(struct nfct_handle *nfct)
1487 struct nfct_filter *filter;
1488 int ret;
1490 filter = nfct_filter_create();
1491 if (!filter)
1492 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1494 if (what & INCLUDE_UDP) {
1495 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1496 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1498 if (what & INCLUDE_TCP)
1499 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1500 if (what & INCLUDE_DCCP)
1501 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1502 if (what & INCLUDE_SCTP)
1503 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1504 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1505 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1506 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1507 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1508 if (what & INCLUDE_IPV4) {
1509 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1510 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1512 if (what & INCLUDE_IPV6) {
1513 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1514 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1517 ret = nfct_filter_attach(nfct_fd(nfct), filter);
1518 if (ret < 0)
1519 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1521 nfct_filter_destroy(filter);
1524 /* This hand-crafted filter looks ugly but it allows to do not
1525 * flush nfct connections & filter them by user specified filter.
1526 * May be it is better to replace this one by nfct_cmp. */
1527 static int flow_dump_cb(enum nf_conntrack_msg_type type,
1528 struct nf_conntrack *ct, void *data __maybe_unused)
1530 struct flow_entry fl;
1531 struct flow_entry *n = &fl;
1533 if (sigint)
1534 return NFCT_CB_STOP;
1536 synchronize_rcu();
1537 spinlock_lock(&flow_list.lock);
1539 if (!(what & ~(INCLUDE_IPV4 | INCLUDE_IPV6)))
1540 goto check_addr;
1542 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
1544 if (what & INCLUDE_UDP) {
1545 if (n->l4_proto == IPPROTO_UDP)
1546 goto check_addr;
1548 if (n->l4_proto == IPPROTO_UDPLITE)
1549 goto check_addr;
1552 if ((what & INCLUDE_TCP) && n->l4_proto == IPPROTO_TCP)
1553 goto check_addr;
1555 if ((what & INCLUDE_DCCP) && n->l4_proto == IPPROTO_DCCP)
1556 goto check_addr;
1558 if ((what & INCLUDE_SCTP) && n->l4_proto == IPPROTO_SCTP)
1559 goto check_addr;
1561 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV4) &&
1562 n->l4_proto == IPPROTO_ICMP) {
1563 goto check_addr;
1566 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV6) &&
1567 n->l4_proto == IPPROTO_ICMPV6) {
1568 goto check_addr;
1571 goto skip_flow;
1573 check_addr:
1574 /* filter loopback addresses */
1575 if (what & INCLUDE_IPV4) {
1576 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
1578 if (n->ip4_src_addr == filter_ipv4.addr)
1579 goto skip_flow;
1581 if (what & INCLUDE_IPV6) {
1582 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
1584 if (n->ip6_src_addr[0] == 0x0 &&
1585 n->ip6_src_addr[1] == 0x0 &&
1586 n->ip6_src_addr[2] == 0x0 &&
1587 n->ip6_src_addr[3] == 0x1)
1588 goto skip_flow;
1591 flow_list_new_entry(&flow_list, ct);
1593 skip_flow:
1594 spinlock_unlock(&flow_list.lock);
1595 return NFCT_CB_CONTINUE;
1598 static void collector_dump_flows(void)
1600 struct nfct_handle *nfct = nfct_open(CONNTRACK, 0);
1602 if (!nfct)
1603 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1605 nfct_callback_register(nfct, NFCT_T_ALL, flow_dump_cb, NULL);
1607 is_flow_collecting = true;
1608 if (what & INCLUDE_IPV4) {
1609 int family = AF_INET;
1610 nfct_query(nfct, NFCT_Q_DUMP, &family);
1612 if (what & INCLUDE_IPV6) {
1613 int family = AF_INET6;
1614 nfct_query(nfct, NFCT_Q_DUMP, &family);
1616 is_flow_collecting = false;
1618 nfct_close(nfct);
1621 static void *collector(void *null __maybe_unused)
1623 struct nfct_handle *ct_update;
1624 struct nfct_handle *ct_event;
1625 struct pollfd poll_fd[1];
1627 flow_list_init(&flow_list);
1629 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1630 NF_NETLINK_CONNTRACK_UPDATE |
1631 NF_NETLINK_CONNTRACK_DESTROY);
1632 if (!ct_event)
1633 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1635 collector_create_filter(ct_event);
1637 nfct_callback_register(ct_event, NFCT_T_ALL, flow_event_cb, NULL);
1639 ct_update = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_UPDATE);
1640 if (!ct_update)
1641 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1643 nfct_callback_register(ct_update, NFCT_T_ALL, flow_update_cb, NULL);
1645 poll_fd[0].fd = nfct_fd(ct_event);
1646 poll_fd[0].events = POLLIN;
1648 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1649 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1650 strerror(errno));
1652 if (fcntl(nfct_fd(ct_update), F_SETFL, O_NONBLOCK) == -1)
1653 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1654 strerror(errno));
1656 rcu_register_thread();
1658 collector_dump_flows();
1660 while (!sigint) {
1661 int status;
1663 if (!do_reload_flows) {
1664 usleep(USEC_PER_SEC * interval);
1665 } else {
1666 flow_list_destroy(&flow_list);
1668 collector_create_filter(ct_event);
1669 collector_dump_flows();
1671 do_reload_flows = false;
1674 collector_refresh_flows(ct_update);
1676 status = poll(poll_fd, 1, 0);
1677 if (status < 0) {
1678 if (errno == EAGAIN || errno == EINTR)
1679 continue;
1681 panic("Error while polling: %s\n", strerror(errno));
1682 } else if (status == 0) {
1683 continue;
1686 if (poll_fd[0].revents & POLLIN)
1687 nfct_catch(ct_event);
1690 rcu_unregister_thread();
1692 flow_list_destroy(&flow_list);
1693 spinlock_destroy(&flow_list.lock);
1695 nfct_close(ct_event);
1696 nfct_close(ct_update);
1698 pthread_exit(NULL);
1701 int main(int argc, char **argv)
1703 pthread_t tid;
1704 int ret, c, opt_index, what_cmd = 0;
1706 setfsuid(getuid());
1707 setfsgid(getgid());
1709 while ((c = getopt_long(argc, argv, short_options, long_options,
1710 &opt_index)) != EOF) {
1711 switch (c) {
1712 case '4':
1713 what_cmd |= INCLUDE_IPV4;
1714 break;
1715 case '6':
1716 what_cmd |= INCLUDE_IPV6;
1717 break;
1718 case 'T':
1719 what_cmd |= INCLUDE_TCP;
1720 break;
1721 case 'U':
1722 what_cmd |= INCLUDE_UDP;
1723 break;
1724 case 'D':
1725 what_cmd |= INCLUDE_DCCP;
1726 break;
1727 case 'I':
1728 what_cmd |= INCLUDE_ICMP;
1729 break;
1730 case 'S':
1731 what_cmd |= INCLUDE_SCTP;
1732 break;
1733 case 's':
1734 show_src = true;
1735 break;
1736 case 'b':
1737 rate_type = RATE_BITS;
1738 break;
1739 case 'u':
1740 update_geoip();
1741 die();
1742 break;
1743 case 't':
1744 interval = strtoul(optarg, NULL, 10);
1745 break;
1746 case 'n':
1747 resolve_dns = false;
1748 break;
1749 case 'G':
1750 resolve_geoip = false;
1751 break;
1752 case 'h':
1753 help();
1754 break;
1755 case 'v':
1756 version();
1757 break;
1758 default:
1759 break;
1763 if (what_cmd > 0) {
1764 what = what_cmd;
1766 if (!(what & (INCLUDE_IPV4 | INCLUDE_IPV6)))
1767 what |= INCLUDE_IPV4 | INCLUDE_IPV6;
1770 rcu_init();
1772 register_signal(SIGINT, signal_handler);
1773 register_signal(SIGQUIT, signal_handler);
1774 register_signal(SIGTERM, signal_handler);
1775 register_signal(SIGHUP, signal_handler);
1777 panic_handler_add(on_panic_handler, &sysctl);
1779 conntrack_acct_enable();
1780 conntrack_tstamp_enable();
1782 if (resolve_geoip)
1783 init_geoip(1);
1785 ret = pthread_create(&tid, NULL, collector, NULL);
1786 if (ret < 0)
1787 panic("Cannot create phthread!\n");
1789 presenter();
1791 if (resolve_geoip)
1792 destroy_geoip();
1794 restore_sysctl(&sysctl);
1796 return 0;