flowtop: Calculate flow rate more carefully
[netsniff-ng.git] / flowtop.c
blob2791a74d5e76a713c92ea87c1b93913be2887f99
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 struct sysctl_params_ctx {
108 int nfct_acct;
109 int nfct_tstamp;
112 enum rate_units {
113 RATE_BITS,
114 RATE_BYTES
117 static volatile bool is_flow_collecting;
118 static volatile sig_atomic_t sigint = 0;
119 static int what = INCLUDE_IPV4 | INCLUDE_IPV6 | INCLUDE_TCP;
120 static struct flow_list flow_list;
121 static struct sysctl_params_ctx sysctl = { -1, -1 };
123 static unsigned int interval = 1;
124 static bool show_src = false;
125 static bool resolve_dns = true;
126 static bool resolve_geoip = true;
127 static enum rate_units rate_type = RATE_BYTES;
129 static const char *short_options = "vhTUsDIS46ut:nGb";
130 static const struct option long_options[] = {
131 {"ipv4", no_argument, NULL, '4'},
132 {"ipv6", no_argument, NULL, '6'},
133 {"tcp", no_argument, NULL, 'T'},
134 {"udp", no_argument, NULL, 'U'},
135 {"dccp", no_argument, NULL, 'D'},
136 {"icmp", no_argument, NULL, 'I'},
137 {"sctp", no_argument, NULL, 'S'},
138 {"no-dns", no_argument, NULL, 'n'},
139 {"no-geoip", no_argument, NULL, 'G'},
140 {"show-src", no_argument, NULL, 's'},
141 {"bits", no_argument, NULL, 'b'},
142 {"update", no_argument, NULL, 'u'},
143 {"interval", required_argument, NULL, 't'},
144 {"version", no_argument, NULL, 'v'},
145 {"help", no_argument, NULL, 'h'},
146 {NULL, 0, NULL, 0}
149 static const char *copyright = "Please report bugs to <netsniff-ng@googlegroups.com>\n"
150 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>\n"
151 "Copyright (C) 2011-2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>\n"
152 "Swiss federal institute of technology (ETH Zurich)\n"
153 "License: GNU GPL version 2.0\n"
154 "This is free software: you are free to change and redistribute it.\n"
155 "There is NO WARRANTY, to the extent permitted by law.";
157 static const char *const l3proto2str[AF_MAX] = {
158 [AF_INET] = "ipv4",
159 [AF_INET6] = "ipv6",
162 static const char *const l4proto2str[IPPROTO_MAX] = {
163 [IPPROTO_TCP] = "tcp",
164 [IPPROTO_UDP] = "udp",
165 [IPPROTO_UDPLITE] = "udplite",
166 [IPPROTO_ICMP] = "icmp",
167 [IPPROTO_ICMPV6] = "icmpv6",
168 [IPPROTO_SCTP] = "sctp",
169 [IPPROTO_GRE] = "gre",
170 [IPPROTO_DCCP] = "dccp",
171 [IPPROTO_IGMP] = "igmp",
172 [IPPROTO_IPIP] = "ipip",
173 [IPPROTO_EGP] = "egp",
174 [IPPROTO_PUP] = "pup",
175 [IPPROTO_IDP] = "idp",
176 [IPPROTO_RSVP] = "rsvp",
177 [IPPROTO_IPV6] = "ip6tun",
178 [IPPROTO_ESP] = "esp",
179 [IPPROTO_AH] = "ah",
180 [IPPROTO_PIM] = "pim",
181 [IPPROTO_COMP] = "comp",
184 static const char *const tcp_state2str[TCP_CONNTRACK_MAX] = {
185 [TCP_CONNTRACK_NONE] = "NOSTATE",
186 [TCP_CONNTRACK_SYN_SENT] = "SYN_SENT",
187 [TCP_CONNTRACK_SYN_RECV] = "SYN_RECV",
188 [TCP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
189 [TCP_CONNTRACK_FIN_WAIT] = "FIN_WAIT",
190 [TCP_CONNTRACK_CLOSE_WAIT] = "CLOSE_WAIT",
191 [TCP_CONNTRACK_LAST_ACK] = "LAST_ACK",
192 [TCP_CONNTRACK_TIME_WAIT] = "TIME_WAIT",
193 [TCP_CONNTRACK_CLOSE] = "CLOSE",
194 [TCP_CONNTRACK_SYN_SENT2] = "SYN_SENT2",
197 static const char *const dccp_state2str[DCCP_CONNTRACK_MAX] = {
198 [DCCP_CONNTRACK_NONE] = "NOSTATE",
199 [DCCP_CONNTRACK_REQUEST] = "REQUEST",
200 [DCCP_CONNTRACK_RESPOND] = "RESPOND",
201 [DCCP_CONNTRACK_PARTOPEN] = "PARTOPEN",
202 [DCCP_CONNTRACK_OPEN] = "OPEN",
203 [DCCP_CONNTRACK_CLOSEREQ] = "CLOSEREQ",
204 [DCCP_CONNTRACK_CLOSING] = "CLOSING",
205 [DCCP_CONNTRACK_TIMEWAIT] = "TIMEWAIT",
206 [DCCP_CONNTRACK_IGNORE] = "IGNORE",
207 [DCCP_CONNTRACK_INVALID] = "INVALID",
210 static const char *const sctp_state2str[SCTP_CONNTRACK_MAX] = {
211 [SCTP_CONNTRACK_NONE] = "NOSTATE",
212 [SCTP_CONNTRACK_CLOSED] = "CLOSED",
213 [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE_WAIT",
214 [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE_ECHOED",
215 [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED",
216 [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTDOWN_SENT",
217 [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTDOWN_RECD",
218 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTDOWN_ACK_SENT",
221 static const struct nfct_filter_ipv4 filter_ipv4 = {
222 .addr = __constant_htonl(INADDR_LOOPBACK),
223 .mask = 0xffffffff,
226 static const struct nfct_filter_ipv6 filter_ipv6 = {
227 .addr = { 0x0, 0x0, 0x0, 0x1 },
228 .mask = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
231 static int64_t time_after_us(struct timeval *tv)
233 struct timeval now;
235 bug_on(gettimeofday(&now, NULL));
237 now.tv_sec -= tv->tv_sec;
238 now.tv_usec -= tv->tv_usec;
240 return now.tv_sec * USEC_PER_SEC + now.tv_usec;
243 static void signal_handler(int number)
245 switch (number) {
246 case SIGINT:
247 case SIGQUIT:
248 case SIGTERM:
249 sigint = 1;
250 break;
251 case SIGHUP:
252 default:
253 break;
257 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct);
258 static void flow_entry_get_extended(struct flow_entry *n);
260 static void help(void)
262 printf("flowtop %s, top-like netfilter TCP/UDP/SCTP/.. flow tracking\n",
263 VERSION_STRING);
264 puts("http://www.netsniff-ng.org\n\n"
265 "Usage: flowtop [options]\n"
266 "Options:\n"
267 " -4|--ipv4 Show only IPv4 flows (default)\n"
268 " -6|--ipv6 Show only IPv6 flows (default)\n"
269 " -T|--tcp Show only TCP flows (default)\n"
270 " -U|--udp Show only UDP flows\n"
271 " -D|--dccp Show only DCCP flows\n"
272 " -I|--icmp Show only ICMP/ICMPv6 flows\n"
273 " -S|--sctp Show only SCTP flows\n"
274 " -n|--no-dns Don't perform hostname lookup\n"
275 " -G|--no-geoip Don't perform GeoIP lookup\n"
276 " -s|--show-src Also show source, not only dest\n"
277 " -b|--bits Show rates in bits/s instead of bytes/s\n"
278 " -u|--update Update GeoIP databases\n"
279 " -t|--interval <time> Refresh time in seconds (default 1s)\n"
280 " -v|--version Print version and exit\n"
281 " -h|--help Print this help and exit\n\n"
282 "Examples:\n"
283 " flowtop\n"
284 " flowtop -46UTDISs\n\n"
285 "Note:\n"
286 " If netfilter is not running, you can activate it with e.g.:\n"
287 " iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT\n"
288 " iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT\n");
289 puts(copyright);
290 die();
293 static void version(void)
295 printf("flowtop %s, Git id: %s\n", VERSION_LONG, GITVERSION);
296 puts("top-like netfilter TCP/UDP/SCTP/.. flow tracking\n"
297 "http://www.netsniff-ng.org\n");
298 puts(copyright);
299 die();
302 static void flow_entry_update_time(struct flow_entry *n)
304 bug_on(gettimeofday(&n->last_update, NULL));
307 #define CALC_RATE(fld) do { \
308 n->rate_##fld = (((fld) > n->fld) ? (((fld) - n->fld) / sec) : 0); \
309 } while (0)
311 static void flow_entry_calc_rate(struct flow_entry *n, const struct nf_conntrack *ct)
313 uint64_t bytes_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_BYTES);
314 uint64_t bytes_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_BYTES);
315 uint64_t pkts_src = nfct_get_attr_u64(ct, ATTR_ORIG_COUNTER_PACKETS);
316 uint64_t pkts_dst = nfct_get_attr_u64(ct, ATTR_REPL_COUNTER_PACKETS);
317 double sec = (double)time_after_us(&n->last_update) / USEC_PER_SEC;
319 if (sec < 1)
320 return;
322 CALC_RATE(bytes_src);
323 CALC_RATE(bytes_dst);
324 CALC_RATE(pkts_src);
325 CALC_RATE(pkts_dst);
328 static inline struct flow_entry *flow_entry_xalloc(void)
330 return xzmalloc(sizeof(struct flow_entry));
333 static inline void flow_entry_xfree(struct flow_entry *n)
335 if (n->ct)
336 nfct_destroy(n->ct);
338 xfree(n);
341 static inline void flow_list_init(struct flow_list *fl)
343 fl->head = NULL;
344 spinlock_init(&fl->lock);
347 static inline bool nfct_is_dns(const struct nf_conntrack *ct)
349 uint16_t port_src = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
350 uint16_t port_dst = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
352 return ntohs(port_src) == 53 || ntohs(port_dst) == 53;
355 static void flow_list_new_entry(struct flow_list *fl, const struct nf_conntrack *ct)
357 struct flow_entry *n;
359 /* We don't want to analyze / display DNS itself, since we
360 * use it to resolve reverse dns.
362 if (nfct_is_dns(ct))
363 return;
365 n = flow_entry_xalloc();
367 n->ct = nfct_clone(ct);
369 flow_entry_update_time(n);
370 flow_entry_from_ct(n, ct);
371 flow_entry_get_extended(n);
373 rcu_assign_pointer(n->next, fl->head);
374 rcu_assign_pointer(fl->head, n);
377 static struct flow_entry *flow_list_find_id(struct flow_list *fl,
378 uint32_t id)
380 struct flow_entry *n = rcu_dereference(fl->head);
382 while (n != NULL) {
383 if (n->flow_id == id)
384 return n;
386 n = rcu_dereference(n->next);
389 return NULL;
392 static struct flow_entry *flow_list_find_prev_id(const struct flow_list *fl,
393 uint32_t id)
395 struct flow_entry *prev = rcu_dereference(fl->head), *next;
397 if (prev->flow_id == id)
398 return NULL;
400 while ((next = rcu_dereference(prev->next)) != NULL) {
401 if (next->flow_id == id)
402 return prev;
404 prev = next;
407 return NULL;
410 static void flow_list_update_entry(struct flow_list *fl,
411 const struct nf_conntrack *ct)
413 struct flow_entry *n;
415 n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID));
416 if (n == NULL) {
417 flow_list_new_entry(fl, ct);
418 return;
421 flow_entry_from_ct(n, ct);
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 while (fl->head != NULL) {
452 n = rcu_dereference(fl->head->next);
453 fl->head->next = NULL;
455 flow_entry_xfree(fl->head);
456 rcu_assign_pointer(fl->head, n);
459 synchronize_rcu();
460 spinlock_destroy(&fl->lock);
463 static int walk_process(unsigned int pid, struct flow_entry *n)
465 int ret;
466 DIR *dir;
467 struct dirent *ent;
468 char path[1024];
470 if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
471 panic("giant process name! %u\n", pid);
473 dir = opendir(path);
474 if (!dir)
475 return 0;
477 while ((ent = readdir(dir))) {
478 struct stat statbuf;
480 if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
481 pid, ent->d_name) < 0)
482 continue;
484 if (stat(path, &statbuf) < 0)
485 continue;
487 if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == statbuf.st_ino) {
488 char cmdline[256];
490 ret = proc_get_cmdline(pid, cmdline, sizeof(cmdline));
491 if (ret < 0)
492 panic("Failed to get process cmdline: %s\n", strerror(errno));
494 if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0)
495 n->procname[0] = '\0';
496 n->procnum = pid;
497 closedir(dir);
498 return 1;
502 closedir(dir);
503 return 0;
506 static void walk_processes(struct flow_entry *n)
508 int ret;
509 DIR *dir;
510 struct dirent *ent;
512 /* n->inode must be set */
513 if (n->inode <= 0) {
514 n->procname[0] = '\0';
515 return;
518 dir = opendir("/proc");
519 if (!dir)
520 panic("Cannot open /proc: %s\n", strerror(errno));
522 while ((ent = readdir(dir))) {
523 const char *name = ent->d_name;
524 char *end;
525 unsigned int pid = strtoul(name, &end, 10);
527 /* not a PID */
528 if (pid == 0 && end == name)
529 continue;
531 ret = walk_process(pid, n);
532 if (ret > 0)
533 break;
536 closedir(dir);
539 static int get_port_inode(uint16_t port, int proto, bool is_ip6)
541 int ret = -ENOENT;
542 char path[128], buff[1024];
543 FILE *proc;
545 memset(path, 0, sizeof(path));
546 snprintf(path, sizeof(path), "/proc/net/%s%s",
547 l4proto2str[proto], is_ip6 ? "6" : "");
549 proc = fopen(path, "r");
550 if (!proc)
551 return -EIO;
553 memset(buff, 0, sizeof(buff));
555 while (fgets(buff, sizeof(buff), proc) != NULL) {
556 int inode = 0;
557 unsigned int lport = 0;
559 buff[sizeof(buff) - 1] = 0;
560 if (sscanf(buff, "%*u: %*X:%X %*X:%*X %*X %*X:%*X %*X:%*X "
561 "%*X %*u %*u %u", &lport, &inode) == 2) {
562 if ((uint16_t) lport == port) {
563 ret = inode;
564 break;
568 memset(buff, 0, sizeof(buff));
571 fclose(proc);
572 return ret;
575 #define CP_NFCT(elem, attr, x) \
576 do { n->elem = nfct_get_attr_u##x(ct,(attr)); } while (0)
577 #define CP_NFCT_BUFF(elem, attr) do { \
578 const uint8_t *buff = nfct_get_attr(ct,(attr)); \
579 if (buff != NULL) \
580 memcpy(n->elem, buff, sizeof(n->elem)); \
581 } while (0)
583 static void flow_entry_from_ct(struct flow_entry *n, const struct nf_conntrack *ct)
585 CP_NFCT(l3_proto, ATTR_ORIG_L3PROTO, 8);
586 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
588 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
589 CP_NFCT(ip4_dst_addr, ATTR_ORIG_IPV4_DST, 32);
591 CP_NFCT(port_src, ATTR_ORIG_PORT_SRC, 16);
592 CP_NFCT(port_dst, ATTR_ORIG_PORT_DST, 16);
594 CP_NFCT(status, ATTR_STATUS, 32);
596 CP_NFCT(tcp_state, ATTR_TCP_STATE, 8);
597 CP_NFCT(tcp_flags, ATTR_TCP_FLAGS_ORIG, 8);
598 CP_NFCT(sctp_state, ATTR_SCTP_STATE, 8);
599 CP_NFCT(dccp_state, ATTR_DCCP_STATE, 8);
601 CP_NFCT(pkts_src, ATTR_ORIG_COUNTER_PACKETS, 64);
602 CP_NFCT(bytes_src, ATTR_ORIG_COUNTER_BYTES, 64);
604 CP_NFCT(pkts_dst, ATTR_REPL_COUNTER_PACKETS, 64);
605 CP_NFCT(bytes_dst, ATTR_REPL_COUNTER_BYTES, 64);
607 CP_NFCT(timestamp_start, ATTR_TIMESTAMP_START, 64);
608 CP_NFCT(timestamp_stop, ATTR_TIMESTAMP_STOP, 64);
610 CP_NFCT(flow_id, ATTR_ID, 32);
611 CP_NFCT(use, ATTR_USE, 32);
613 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
614 CP_NFCT_BUFF(ip6_dst_addr, ATTR_ORIG_IPV6_DST);
616 n->port_src = ntohs(n->port_src);
617 n->port_dst = ntohs(n->port_dst);
619 n->ip4_src_addr = ntohl(n->ip4_src_addr);
620 n->ip4_dst_addr = ntohl(n->ip4_dst_addr);
623 #define SELFLD(dir,src_member,dst_member) \
624 (((dir) == FLOW_DIR_SRC) ? n->src_member : n->dst_member)
626 static void flow_entry_get_sain4_obj(const struct flow_entry *n,
627 enum flow_direction dir,
628 struct sockaddr_in *sa)
630 memset(sa, 0, sizeof(*sa));
631 sa->sin_family = PF_INET;
632 sa->sin_addr.s_addr = htonl(SELFLD(dir, ip4_src_addr, ip4_dst_addr));
635 static void flow_entry_get_sain6_obj(const struct flow_entry *n,
636 enum flow_direction dir,
637 struct sockaddr_in6 *sa)
639 memset(sa, 0, sizeof(*sa));
640 sa->sin6_family = PF_INET6;
642 memcpy(&sa->sin6_addr, SELFLD(dir, ip6_src_addr, ip6_dst_addr),
643 sizeof(sa->sin6_addr));
646 static void
647 flow_entry_geo_city_lookup_generic(struct flow_entry *n,
648 enum flow_direction dir)
650 struct sockaddr_in sa4;
651 struct sockaddr_in6 sa6;
652 const char *city = NULL;
654 switch (n->l3_proto) {
655 default:
656 bug();
658 case AF_INET:
659 flow_entry_get_sain4_obj(n, dir, &sa4);
660 city = geoip4_city_name(&sa4);
661 break;
663 case AF_INET6:
664 flow_entry_get_sain6_obj(n, dir, &sa6);
665 city = geoip6_city_name(&sa6);
666 break;
669 build_bug_on(sizeof(n->city_src) != sizeof(n->city_dst));
671 if (city)
672 strlcpy(SELFLD(dir, city_src, city_dst), city,
673 sizeof(n->city_src));
674 else
675 SELFLD(dir, city_src, city_dst)[0] = '\0';
678 static void
679 flow_entry_geo_country_lookup_generic(struct flow_entry *n,
680 enum flow_direction dir)
682 struct sockaddr_in sa4;
683 struct sockaddr_in6 sa6;
684 const char *country = NULL;
686 switch (n->l3_proto) {
687 default:
688 bug();
690 case AF_INET:
691 flow_entry_get_sain4_obj(n, dir, &sa4);
692 country = geoip4_country_name(&sa4);
693 break;
695 case AF_INET6:
696 flow_entry_get_sain6_obj(n, dir, &sa6);
697 country = geoip6_country_name(&sa6);
698 break;
701 build_bug_on(sizeof(n->country_src) != sizeof(n->country_dst));
703 if (country)
704 strlcpy(SELFLD(dir, country_src, country_dst), country,
705 sizeof(n->country_src));
706 else
707 SELFLD(dir, country_src, country_dst)[0] = '\0';
710 static void flow_entry_get_extended_geo(struct flow_entry *n,
711 enum flow_direction dir)
713 if (resolve_geoip) {
714 flow_entry_geo_city_lookup_generic(n, dir);
715 flow_entry_geo_country_lookup_generic(n, dir);
719 static void flow_entry_get_extended_revdns(struct flow_entry *n,
720 enum flow_direction dir)
722 size_t sa_len;
723 struct sockaddr_in sa4;
724 struct sockaddr_in6 sa6;
725 struct sockaddr *sa;
726 struct hostent *hent;
728 build_bug_on(sizeof(n->rev_dns_src) != sizeof(n->rev_dns_dst));
730 switch (n->l3_proto) {
731 default:
732 bug();
734 case AF_INET:
735 flow_entry_get_sain4_obj(n, dir, &sa4);
737 if (!resolve_dns) {
738 inet_ntop(AF_INET, &sa4.sin_addr,
739 SELFLD(dir, rev_dns_src, rev_dns_dst),
740 sizeof(n->rev_dns_src));
741 return;
744 sa = (struct sockaddr *) &sa4;
745 sa_len = sizeof(sa4);
746 hent = gethostbyaddr(&sa4.sin_addr, sizeof(sa4.sin_addr), AF_INET);
747 break;
749 case AF_INET6:
750 flow_entry_get_sain6_obj(n, dir, &sa6);
752 if (!resolve_dns) {
753 inet_ntop(AF_INET6, &sa6.sin6_addr,
754 SELFLD(dir, rev_dns_src, rev_dns_dst),
755 sizeof(n->rev_dns_src));
756 return;
759 sa = (struct sockaddr *) &sa6;
760 sa_len = sizeof(sa6);
761 hent = gethostbyaddr(&sa6.sin6_addr, sizeof(sa6.sin6_addr), AF_INET6);
762 break;
765 getnameinfo(sa, sa_len, SELFLD(dir, rev_dns_src, rev_dns_dst),
766 sizeof(n->rev_dns_src), NULL, 0, NI_NUMERICHOST);
768 if (hent)
769 strlcpy(SELFLD(dir, rev_dns_src, rev_dns_dst), hent->h_name,
770 sizeof(n->rev_dns_src));
773 static void flow_entry_get_extended(struct flow_entry *n)
775 if (n->flow_id == 0)
776 return;
778 if (show_src) {
779 flow_entry_get_extended_revdns(n, FLOW_DIR_SRC);
780 flow_entry_get_extended_geo(n, FLOW_DIR_SRC);
783 flow_entry_get_extended_revdns(n, FLOW_DIR_DST);
784 flow_entry_get_extended_geo(n, FLOW_DIR_DST);
786 /* Lookup application */
787 n->inode = get_port_inode(n->port_src, n->l4_proto,
788 n->l3_proto == AF_INET6);
789 if (n->inode > 0)
790 walk_processes(n);
793 static uint16_t presenter_get_port(uint16_t src, uint16_t dst, bool is_tcp)
795 if (src < dst && src < 1024) {
796 return src;
797 } else if (dst < src && dst < 1024) {
798 return dst;
799 } else {
800 const char *tmp1, *tmp2;
801 if (is_tcp) {
802 tmp1 = lookup_port_tcp(src);
803 tmp2 = lookup_port_tcp(dst);
804 } else {
805 tmp1 = lookup_port_udp(src);
806 tmp2 = lookup_port_udp(dst);
808 if (tmp1 && !tmp2) {
809 return src;
810 } else if (!tmp1 && tmp2) {
811 return dst;
812 } else {
813 if (src < dst)
814 return src;
815 else
816 return dst;
821 static char *bandw2str(double bytes, char *buf, size_t len)
823 if (bytes > 1000000000.)
824 snprintf(buf, len, "%.1fGB", bytes / 1000000000.);
825 else if (bytes > 1000000.)
826 snprintf(buf, len, "%.1fMB", bytes / 1000000.);
827 else if (bytes > 1000.)
828 snprintf(buf, len, "%.1fkB", bytes / 1000.);
829 else
830 snprintf(buf, len, "%g bytes", bytes);
832 return buf;
835 static char *rate2str(double rate, char *buf, size_t len)
837 const char * const unit_fmt[2][4] = {
838 { "%.1fGbit/s", "%.1fMbit/s", "%.1fkbit/s", "%gbit/s" },
839 { "%.1fGB/s", "%.1fMB/s", "%.1fkB/s", "%gB/s" }
842 if (rate_type == RATE_BITS)
843 rate *= 8;
845 if (rate > 1000000000.)
846 snprintf(buf, len, unit_fmt[rate_type][0], rate / 1000000000.);
847 else if (rate > 1000000.)
848 snprintf(buf, len, unit_fmt[rate_type][1], rate / 1000000.);
849 else if (rate > 1000.)
850 snprintf(buf, len, unit_fmt[rate_type][2], rate / 1000.);
851 else
852 snprintf(buf, len, unit_fmt[rate_type][3], rate);
854 return buf;
857 static void presenter_print_counters(uint64_t bytes, uint64_t pkts,
858 double rate_bytes, double rate_pkts,
859 int color)
861 char bytes_str[64];
863 printw(" -> (");
864 attron(COLOR_PAIR(color));
865 printw("%"PRIu64" pkts", pkts);
866 if (rate_pkts) {
867 attron(COLOR_PAIR(3));
868 printw("(%.1fpps)", rate_pkts);
869 attron(COLOR_PAIR(color));
872 printw(", %s", bandw2str(bytes, bytes_str, sizeof(bytes_str) - 1));
873 if (rate_bytes) {
874 attron(COLOR_PAIR(3));
875 printw("(%s)", rate2str(rate_bytes, bytes_str,
876 sizeof(bytes_str) - 1));
877 attron(COLOR_PAIR(color));
879 attroff(COLOR_PAIR(color));
880 printw(")");
883 static void presenter_print_flow_entry_time(const struct flow_entry *n)
885 int h, m, s;
886 time_t now;
888 time(&now);
890 s = now - (n->timestamp_start / NSEC_PER_SEC);
891 if (s <= 0)
892 return;
894 h = s / 3600;
895 s -= h * 3600;
896 m = s / 60;
897 s -= m * 60;
899 printw(" [ time");
900 if (h > 0)
901 printw(" %dh", h);
902 if (m > 0)
903 printw(" %dm", m);
904 if (s > 0)
905 printw(" %ds", s);
906 printw(" ]");
909 static void presenter_screen_do_line(WINDOW *screen, const struct flow_entry *n,
910 unsigned int *line)
912 char tmp[128], *pname = NULL;
913 uint16_t port;
915 mvwprintw(screen, *line, 2, "");
917 /* PID, application name */
918 if (n->procnum > 0) {
919 slprintf(tmp, sizeof(tmp), "%s(%d)", n->procname, n->procnum);
921 printw("[");
922 attron(COLOR_PAIR(3));
923 printw("%s", tmp);
924 attroff(COLOR_PAIR(3));
925 printw("]:");
928 /* L3 protocol, L4 protocol, states */
929 printw("%s:%s", l3proto2str[n->l3_proto], l4proto2str[n->l4_proto]);
930 printw("[");
931 attron(COLOR_PAIR(3));
932 switch (n->l4_proto) {
933 case IPPROTO_TCP:
934 printw("%s", tcp_state2str[n->tcp_state]);
935 break;
936 case IPPROTO_SCTP:
937 printw("%s", sctp_state2str[n->sctp_state]);
938 break;
939 case IPPROTO_DCCP:
940 printw("%s", dccp_state2str[n->dccp_state]);
941 break;
942 case IPPROTO_UDP:
943 case IPPROTO_UDPLITE:
944 case IPPROTO_ICMP:
945 case IPPROTO_ICMPV6:
946 printw("NOSTATE");
947 break;
949 attroff(COLOR_PAIR(3));
950 printw("]");
952 /* Guess application port */
953 switch (n->l4_proto) {
954 case IPPROTO_TCP:
955 port = presenter_get_port(n->port_src, n->port_dst, true);
956 pname = lookup_port_tcp(port);
957 break;
958 case IPPROTO_UDP:
959 case IPPROTO_UDPLITE:
960 port = presenter_get_port(n->port_src, n->port_dst, false);
961 pname = lookup_port_udp(port);
962 break;
964 if (pname) {
965 attron(A_BOLD);
966 printw(":%s", pname);
967 attroff(A_BOLD);
970 if (n->timestamp_start > 0)
971 presenter_print_flow_entry_time(n);
973 /* Show source information: reverse DNS, port, country, city, counters */
974 if (show_src) {
975 attron(COLOR_PAIR(1));
976 mvwprintw(screen, ++(*line), 8, "src: %s", n->rev_dns_src);
977 attroff(COLOR_PAIR(1));
979 printw(":%"PRIu16, n->port_src);
981 if (n->country_src[0]) {
982 printw(" (");
984 attron(COLOR_PAIR(4));
985 printw("%s", n->country_src);
986 attroff(COLOR_PAIR(4));
988 if (n->city_src[0])
989 printw(", %s", n->city_src);
991 printw(")");
994 if (n->pkts_src > 0 && n->bytes_src > 0)
995 presenter_print_counters(n->bytes_src, n->pkts_src,
996 n->rate_bytes_src,
997 n->rate_pkts_src, 1);
999 printw(" => ");
1002 /* Show dest information: reverse DNS, port, country, city, counters */
1003 attron(COLOR_PAIR(2));
1004 mvwprintw(screen, ++(*line), 8, "dst: %s", n->rev_dns_dst);
1005 attroff(COLOR_PAIR(2));
1007 printw(":%"PRIu16, n->port_dst);
1009 if (n->country_dst[0]) {
1010 printw(" (");
1012 attron(COLOR_PAIR(4));
1013 printw("%s", n->country_dst);
1014 attroff(COLOR_PAIR(4));
1016 if (n->city_dst[0])
1017 printw(", %s", n->city_dst);
1019 printw(")");
1022 if (n->pkts_dst > 0 && n->bytes_dst > 0)
1023 presenter_print_counters(n->bytes_dst, n->pkts_dst,
1024 n->rate_bytes_dst,
1025 n->rate_pkts_dst, 2);
1028 static inline bool presenter_flow_wrong_state(struct flow_entry *n)
1030 switch (n->l4_proto) {
1031 case IPPROTO_TCP:
1032 switch (n->tcp_state) {
1033 case TCP_CONNTRACK_SYN_SENT:
1034 case TCP_CONNTRACK_SYN_RECV:
1035 case TCP_CONNTRACK_ESTABLISHED:
1036 case TCP_CONNTRACK_FIN_WAIT:
1037 case TCP_CONNTRACK_CLOSE_WAIT:
1038 case TCP_CONNTRACK_LAST_ACK:
1039 case TCP_CONNTRACK_TIME_WAIT:
1040 case TCP_CONNTRACK_CLOSE:
1041 case TCP_CONNTRACK_SYN_SENT2:
1042 case TCP_CONNTRACK_NONE:
1043 return false;
1044 break;
1046 break;
1047 case IPPROTO_SCTP:
1048 switch (n->sctp_state) {
1049 case SCTP_CONNTRACK_NONE:
1050 case SCTP_CONNTRACK_CLOSED:
1051 case SCTP_CONNTRACK_COOKIE_WAIT:
1052 case SCTP_CONNTRACK_COOKIE_ECHOED:
1053 case SCTP_CONNTRACK_ESTABLISHED:
1054 case SCTP_CONNTRACK_SHUTDOWN_SENT:
1055 case SCTP_CONNTRACK_SHUTDOWN_RECD:
1056 case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT:
1057 return false;
1058 break;
1060 break;
1061 case IPPROTO_DCCP:
1062 switch (n->dccp_state) {
1063 case DCCP_CONNTRACK_NONE:
1064 case DCCP_CONNTRACK_REQUEST:
1065 case DCCP_CONNTRACK_RESPOND:
1066 case DCCP_CONNTRACK_PARTOPEN:
1067 case DCCP_CONNTRACK_OPEN:
1068 case DCCP_CONNTRACK_CLOSEREQ:
1069 case DCCP_CONNTRACK_CLOSING:
1070 case DCCP_CONNTRACK_TIMEWAIT:
1071 case DCCP_CONNTRACK_IGNORE:
1072 case DCCP_CONNTRACK_INVALID:
1073 return false;
1074 break;
1076 break;
1077 case IPPROTO_UDP:
1078 case IPPROTO_UDPLITE:
1079 case IPPROTO_ICMP:
1080 case IPPROTO_ICMPV6:
1081 return false;
1082 break;
1085 return true;
1088 static void presenter_screen_update(WINDOW *screen, struct flow_list *fl,
1089 int skip_lines)
1091 int maxy;
1092 int skip_left = skip_lines;
1093 unsigned int flows = 0;
1094 unsigned int line = 3;
1095 struct flow_entry *n;
1097 curs_set(0);
1099 maxy = getmaxy(screen);
1100 maxy -= 6;
1102 start_color();
1103 init_pair(1, COLOR_RED, COLOR_BLACK);
1104 init_pair(2, COLOR_BLUE, COLOR_BLACK);
1105 init_pair(3, COLOR_YELLOW, COLOR_BLACK);
1106 init_pair(4, COLOR_GREEN, COLOR_BLACK);
1108 wclear(screen);
1109 clear();
1111 rcu_read_lock();
1113 n = rcu_dereference(fl->head);
1114 if (!n)
1115 mvwprintw(screen, line, 2, "(No active sessions! "
1116 "Is netfilter running?)");
1118 for (; n; n = rcu_dereference(n->next)) {
1119 n->is_visible = false;
1121 if (presenter_flow_wrong_state(n))
1122 continue;
1124 /* count only flows which might be showed */
1125 flows++;
1127 if (maxy <= 0)
1128 continue;
1130 if (skip_left > 0) {
1131 skip_left--;
1132 continue;
1135 n->is_visible = true;
1137 presenter_screen_do_line(screen, n, &line);
1139 line++;
1140 maxy -= (2 + (show_src ? 1 : 0));
1143 mvwprintw(screen, 1, 2,
1144 "Kernel netfilter flows(%u) for %s%s%s%s%s%s"
1145 "[+%d]", flows, what & INCLUDE_TCP ? "TCP, " : "",
1146 what & INCLUDE_UDP ? "UDP, " : "",
1147 what & INCLUDE_SCTP ? "SCTP, " : "",
1148 what & INCLUDE_DCCP ? "DCCP, " : "",
1149 what & INCLUDE_ICMP && what & INCLUDE_IPV4 ? "ICMP, " : "",
1150 what & INCLUDE_ICMP && what & INCLUDE_IPV6 ? "ICMP6, " : "",
1151 skip_lines);
1153 if (is_flow_collecting)
1154 printw(" [Collecting flows ...]");
1156 rcu_read_unlock();
1158 wrefresh(screen);
1159 refresh();
1162 static void presenter(void)
1164 int skip_lines = 0;
1165 WINDOW *screen;
1167 lookup_init_ports(PORTS_TCP);
1168 lookup_init_ports(PORTS_UDP);
1169 screen = screen_init(false);
1171 rcu_register_thread();
1172 while (!sigint) {
1173 switch (getch()) {
1174 case 'q':
1175 sigint = 1;
1176 break;
1177 case KEY_UP:
1178 case 'u':
1179 case 'k':
1180 skip_lines--;
1181 if (skip_lines < 0)
1182 skip_lines = 0;
1183 break;
1184 case KEY_DOWN:
1185 case 'd':
1186 case 'j':
1187 skip_lines++;
1188 if (skip_lines > SCROLL_MAX)
1189 skip_lines = SCROLL_MAX;
1190 break;
1191 default:
1192 fflush(stdin);
1193 break;
1196 presenter_screen_update(screen, &flow_list, skip_lines);
1197 usleep(200000);
1199 rcu_unregister_thread();
1201 screen_end();
1202 lookup_cleanup_ports(PORTS_UDP);
1203 lookup_cleanup_ports(PORTS_TCP);
1206 static int flow_event_cb(enum nf_conntrack_msg_type type,
1207 struct nf_conntrack *ct, void *data __maybe_unused)
1209 if (sigint)
1210 return NFCT_CB_STOP;
1212 synchronize_rcu();
1213 spinlock_lock(&flow_list.lock);
1215 switch (type) {
1216 case NFCT_T_NEW:
1217 flow_list_new_entry(&flow_list, ct);
1218 break;
1219 case NFCT_T_UPDATE:
1220 flow_list_update_entry(&flow_list, ct);
1221 break;
1222 case NFCT_T_DESTROY:
1223 flow_list_destroy_entry(&flow_list, ct);
1224 break;
1225 default:
1226 break;
1229 spinlock_unlock(&flow_list.lock);
1231 return NFCT_CB_CONTINUE;
1234 static void restore_sysctl(void *obj)
1236 struct sysctl_params_ctx *sysctl_ctx = obj;
1238 if (sysctl_ctx->nfct_acct == 0)
1239 sysctl_set_int("net/netfilter/nf_conntrack_acct",
1240 sysctl_ctx->nfct_acct);
1242 if (sysctl_ctx->nfct_tstamp == 0)
1243 sysctl_set_int("net/netfilter/nf_conntrack_timestamp",
1244 sysctl_ctx->nfct_tstamp);
1247 static void on_panic_handler(void *arg)
1249 restore_sysctl(arg);
1250 screen_end();
1253 static void conntrack_acct_enable(void)
1255 /* We can still work w/o traffic accounting so just warn about error */
1256 if (sysctl_get_int("net/netfilter/nf_conntrack_acct", &sysctl.nfct_acct)) {
1257 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_acct: %s\n",
1258 strerror(errno));
1259 return;
1262 if (sysctl.nfct_acct == 1)
1263 return;
1265 if (sysctl_set_int("net/netfilter/nf_conntrack_acct", 1)) {
1266 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_acct: %s\n",
1267 strerror(errno));
1271 static void conntrack_tstamp_enable(void)
1273 if (sysctl_get_int("net/netfilter/nf_conntrack_timestamp", &sysctl.nfct_tstamp)) {
1274 fprintf(stderr, "Can't read net/netfilter/nf_conntrack_timestamp: %s\n",
1275 strerror(errno));
1276 return;
1279 if (sysctl.nfct_tstamp == 1)
1280 return;
1282 if (sysctl_set_int("net/netfilter/nf_conntrack_timestamp", 1)) {
1283 fprintf(stderr, "Can't write net/netfilter/nf_conntrack_timestamp: %s\n",
1284 strerror(errno));
1288 static int flow_update_cb(enum nf_conntrack_msg_type type,
1289 struct nf_conntrack *ct, void *data __maybe_unused)
1291 struct flow_entry *n;
1293 if (type != NFCT_T_UPDATE)
1294 return NFCT_CB_CONTINUE;
1296 if (sigint)
1297 return NFCT_CB_STOP;
1299 n = flow_list_find_id(&flow_list, nfct_get_attr_u32(ct, ATTR_ID));
1300 if (!n)
1301 return NFCT_CB_CONTINUE;
1303 flow_entry_calc_rate(n, ct);
1304 flow_entry_update_time(n);
1305 flow_entry_from_ct(n, ct);
1307 return NFCT_CB_CONTINUE;
1310 static void collector_refresh_flows(struct nfct_handle *handle)
1312 struct flow_entry *n;
1314 n = rcu_dereference(flow_list.head);
1315 for (; n; n = rcu_dereference(n->next)) {
1316 if (!n->is_visible)
1317 continue;
1319 nfct_query(handle, NFCT_Q_GET, n->ct);
1323 static void collector_create_filter(struct nfct_handle *nfct)
1325 struct nfct_filter *filter;
1326 int ret;
1328 filter = nfct_filter_create();
1329 if (!filter)
1330 panic("Cannot create a nfct filter: %s\n", strerror(errno));
1332 if (what & INCLUDE_UDP) {
1333 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
1334 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_UDPLITE);
1336 if (what & INCLUDE_TCP)
1337 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
1338 if (what & INCLUDE_DCCP)
1339 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_DCCP);
1340 if (what & INCLUDE_SCTP)
1341 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_SCTP);
1342 if (what & INCLUDE_ICMP && what & INCLUDE_IPV4)
1343 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMP);
1344 if (what & INCLUDE_ICMP && what & INCLUDE_IPV6)
1345 nfct_filter_add_attr_u32(filter, NFCT_FILTER_L4PROTO, IPPROTO_ICMPV6);
1346 if (what & INCLUDE_IPV4) {
1347 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV4, NFCT_FILTER_LOGIC_NEGATIVE);
1348 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
1350 if (what & INCLUDE_IPV6) {
1351 nfct_filter_set_logic(filter, NFCT_FILTER_SRC_IPV6, NFCT_FILTER_LOGIC_NEGATIVE);
1352 nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV6, &filter_ipv6);
1355 ret = nfct_filter_attach(nfct_fd(nfct), filter);
1356 if (ret < 0)
1357 panic("Cannot attach filter to handle: %s\n", strerror(errno));
1359 nfct_filter_destroy(filter);
1362 /* This hand-crafted filter looks ugly but it allows to do not
1363 * flush nfct connections & filter them by user specified filter.
1364 * May be it is better to replace this one by nfct_cmp. */
1365 static int flow_dump_cb(enum nf_conntrack_msg_type type,
1366 struct nf_conntrack *ct, void *data __maybe_unused)
1368 struct flow_entry fl;
1369 struct flow_entry *n = &fl;
1371 if (sigint)
1372 return NFCT_CB_STOP;
1374 synchronize_rcu();
1375 spinlock_lock(&flow_list.lock);
1377 if (!(what & ~(INCLUDE_IPV4 | INCLUDE_IPV6)))
1378 goto check_addr;
1380 CP_NFCT(l4_proto, ATTR_ORIG_L4PROTO, 8);
1382 if (what & INCLUDE_UDP) {
1383 if (n->l4_proto == IPPROTO_UDP)
1384 goto check_addr;
1386 if (n->l4_proto == IPPROTO_UDPLITE)
1387 goto check_addr;
1390 if ((what & INCLUDE_TCP) && n->l4_proto == IPPROTO_TCP)
1391 goto check_addr;
1393 if ((what & INCLUDE_DCCP) && n->l4_proto == IPPROTO_DCCP)
1394 goto check_addr;
1396 if ((what & INCLUDE_SCTP) && n->l4_proto == IPPROTO_SCTP)
1397 goto check_addr;
1399 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV4) &&
1400 n->l4_proto == IPPROTO_ICMP) {
1401 goto check_addr;
1404 if ((what & INCLUDE_ICMP) && (what & INCLUDE_IPV6) &&
1405 n->l4_proto == IPPROTO_ICMPV6) {
1406 goto check_addr;
1409 goto skip_flow;
1411 check_addr:
1412 /* filter loopback addresses */
1413 if (what & INCLUDE_IPV4) {
1414 CP_NFCT(ip4_src_addr, ATTR_ORIG_IPV4_SRC, 32);
1416 if (n->ip4_src_addr == filter_ipv4.addr)
1417 goto skip_flow;
1419 if (what & INCLUDE_IPV6) {
1420 CP_NFCT_BUFF(ip6_src_addr, ATTR_ORIG_IPV6_SRC);
1422 if (n->ip6_src_addr[0] == 0x0 &&
1423 n->ip6_src_addr[1] == 0x0 &&
1424 n->ip6_src_addr[2] == 0x0 &&
1425 n->ip6_src_addr[3] == 0x1)
1426 goto skip_flow;
1429 flow_list_new_entry(&flow_list, ct);
1431 skip_flow:
1432 spinlock_unlock(&flow_list.lock);
1433 return NFCT_CB_CONTINUE;
1436 static void collector_dump_flows(void)
1438 struct nfct_handle *nfct = nfct_open(CONNTRACK, 0);
1440 if (!nfct)
1441 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1443 nfct_callback_register(nfct, NFCT_T_ALL, flow_dump_cb, NULL);
1445 is_flow_collecting = true;
1446 if (what & INCLUDE_IPV4) {
1447 int family = AF_INET;
1448 nfct_query(nfct, NFCT_Q_DUMP, &family);
1450 if (what & INCLUDE_IPV6) {
1451 int family = AF_INET6;
1452 nfct_query(nfct, NFCT_Q_DUMP, &family);
1454 is_flow_collecting = false;
1456 nfct_close(nfct);
1459 static void *collector(void *null __maybe_unused)
1461 struct nfct_handle *ct_update;
1462 struct nfct_handle *ct_event;
1463 struct pollfd poll_fd[1];
1465 flow_list_init(&flow_list);
1467 ct_event = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW |
1468 NF_NETLINK_CONNTRACK_UPDATE |
1469 NF_NETLINK_CONNTRACK_DESTROY);
1470 if (!ct_event)
1471 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1473 collector_create_filter(ct_event);
1475 nfct_callback_register(ct_event, NFCT_T_ALL, flow_event_cb, NULL);
1477 ct_update = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_UPDATE);
1478 if (!ct_update)
1479 panic("Cannot create a nfct handle: %s\n", strerror(errno));
1481 nfct_callback_register(ct_update, NFCT_T_ALL, flow_update_cb, NULL);
1483 poll_fd[0].fd = nfct_fd(ct_event);
1484 poll_fd[0].events = POLLIN;
1486 if (fcntl(nfct_fd(ct_event), F_SETFL, O_NONBLOCK) == -1)
1487 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1488 strerror(errno));
1490 if (fcntl(nfct_fd(ct_update), F_SETFL, O_NONBLOCK) == -1)
1491 panic("Cannot set non-blocking socket: fcntl(): %s\n",
1492 strerror(errno));
1494 rcu_register_thread();
1496 collector_dump_flows();
1498 while (!sigint) {
1499 int status;
1501 usleep(USEC_PER_SEC * interval);
1503 collector_refresh_flows(ct_update);
1505 status = poll(poll_fd, 1, 0);
1506 if (status < 0) {
1507 if (errno == EAGAIN || errno == EINTR)
1508 continue;
1510 panic("Error while polling: %s\n", strerror(errno));
1511 } else if (status == 0) {
1512 continue;
1515 if (poll_fd[0].revents & POLLIN)
1516 nfct_catch(ct_event);
1519 rcu_unregister_thread();
1521 flow_list_destroy(&flow_list);
1522 nfct_close(ct_event);
1523 nfct_close(ct_update);
1525 pthread_exit(NULL);
1528 int main(int argc, char **argv)
1530 pthread_t tid;
1531 int ret, c, opt_index, what_cmd = 0;
1533 setfsuid(getuid());
1534 setfsgid(getgid());
1536 while ((c = getopt_long(argc, argv, short_options, long_options,
1537 &opt_index)) != EOF) {
1538 switch (c) {
1539 case '4':
1540 what_cmd |= INCLUDE_IPV4;
1541 break;
1542 case '6':
1543 what_cmd |= INCLUDE_IPV6;
1544 break;
1545 case 'T':
1546 what_cmd |= INCLUDE_TCP;
1547 break;
1548 case 'U':
1549 what_cmd |= INCLUDE_UDP;
1550 break;
1551 case 'D':
1552 what_cmd |= INCLUDE_DCCP;
1553 break;
1554 case 'I':
1555 what_cmd |= INCLUDE_ICMP;
1556 break;
1557 case 'S':
1558 what_cmd |= INCLUDE_SCTP;
1559 break;
1560 case 's':
1561 show_src = true;
1562 break;
1563 case 'b':
1564 rate_type = RATE_BITS;
1565 break;
1566 case 'u':
1567 update_geoip();
1568 die();
1569 break;
1570 case 't':
1571 interval = strtoul(optarg, NULL, 10);
1572 break;
1573 case 'n':
1574 resolve_dns = false;
1575 break;
1576 case 'G':
1577 resolve_geoip = false;
1578 break;
1579 case 'h':
1580 help();
1581 break;
1582 case 'v':
1583 version();
1584 break;
1585 default:
1586 break;
1590 if (what_cmd > 0) {
1591 what = what_cmd;
1593 if (!(what & (INCLUDE_IPV4 | INCLUDE_IPV6)))
1594 what |= INCLUDE_IPV4 | INCLUDE_IPV6;
1597 rcu_init();
1599 register_signal(SIGINT, signal_handler);
1600 register_signal(SIGQUIT, signal_handler);
1601 register_signal(SIGTERM, signal_handler);
1602 register_signal(SIGHUP, signal_handler);
1604 panic_handler_add(on_panic_handler, &sysctl);
1606 conntrack_acct_enable();
1607 conntrack_tstamp_enable();
1609 if (resolve_geoip)
1610 init_geoip(1);
1612 ret = pthread_create(&tid, NULL, collector, NULL);
1613 if (ret < 0)
1614 panic("Cannot create phthread!\n");
1616 presenter();
1618 if (resolve_geoip)
1619 destroy_geoip();
1621 restore_sysctl(&sysctl);
1623 return 0;