summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Warren <pdw@ex-parrot.com>2022-10-09 22:07:55 +0100
committerPaul Warren <pdw@ex-parrot.com>2022-10-09 22:07:55 +0100
commitaee8e05f48f0ffee4a724c6bd582f51ca65b27f1 (patch)
tree76dab521c580e74095b55ba4c8ecf3c0561a9d2f
parent8d76ef06d225c4d72db544b54ea1ef1a0e077967 (diff)
Show local process names.origin/proc-display
Patch from Mark Benjamin
-rw-r--r--Makefile.am2
-rw-r--r--addr_hash.c1
-rw-r--r--cfgfile.c47
-rw-r--r--counter_hash.c1
-rw-r--r--hash.c7
-rw-r--r--hash.h1
-rw-r--r--ns_hash.c1
-rw-r--r--options.c15
-rw-r--r--options.h2
-rw-r--r--proc_hash.c198
-rw-r--r--proc_hash.h22
-rw-r--r--serv_hash.c1
-rw-r--r--tui.c30
-rw-r--r--ui.c23
-rw-r--r--ui_common.c40
-rw-r--r--ui_common.h15
16 files changed, 338 insertions, 68 deletions
diff --git a/Makefile.am b/Makefile.am
index 4a5ec95..e3e10a9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,7 +17,7 @@ iftop_SOURCES = addr_hash.c edline.c hash.c iftop.c ns_hash.c \
options.c resolver.c screenfilter.c serv_hash.c \
sorted_list.c threadprof.c ui_common.c ui.c tui.c util.c \
addrs_ioctl.c addrs_dlpi.c dlcommon.c \
- stringmap.c cfgfile.c vector.c
+ stringmap.c cfgfile.c vector.c proc_hash.c
#iftop_dump_SOURCES = counter_hash.c hash.c iftop-dump.c \
# options.c \
diff --git a/addr_hash.c b/addr_hash.c
index f5c002c..f2e73fd 100644
--- a/addr_hash.c
+++ b/addr_hash.c
@@ -94,6 +94,7 @@ hash_type* addr_hash_create() {
hash_table->hash = &hash;
hash_table->delete_key = &delete_key;
hash_table->copy_key = &copy_key;
+ hash_table->not_found_callback = NULL;
hash_initialise(hash_table);
return hash_table;
}
diff --git a/cfgfile.c b/cfgfile.c
index 581909b..f80352a 100644
--- a/cfgfile.c
+++ b/cfgfile.c
@@ -22,29 +22,30 @@
#define MAX_CONFIG_LINE 2048
char * config_directives[] = {
- "interface",
- "dns-resolution",
- "port-resolution",
- "filter-code",
- "show-bars",
- "promiscuous",
- "hide-source",
- "hide-destination",
- "use-bytes",
- "bandwidth-unit",
- "sort",
- "line-display",
- "show-totals",
- "log-scale",
- "max-bandwidth",
- "net-filter",
- "net-filter6",
- "link-local",
- "port-display",
- "timed-output",
- "no-curses",
- "num-lines",
- NULL
+ "interface",
+ "dns-resolution",
+ "port-resolution",
+ "filter-code",
+ "show-bars",
+ "promiscuous",
+ "hide-source",
+ "hide-destination",
+ "use-bytes",
+ "bandwidth-unit",
+ "sort",
+ "line-display",
+ "show-totals",
+ "log-scale",
+ "max-bandwidth",
+ "net-filter",
+ "net-filter6",
+ "link-local",
+ "port-display",
+ "timed-output",
+ "no-curses",
+ "num-lines",
+ "proc-names",
+ NULL
};
stringmap config;
diff --git a/counter_hash.c b/counter_hash.c
index d0a275b..f97c326 100644
--- a/counter_hash.c
+++ b/counter_hash.c
@@ -50,6 +50,7 @@ hash_type* counter_hash_create() {
hash_table->hash = &counter_hash_hash;
hash_table->delete_key = &counter_hash_delete_key;
hash_table->copy_key = &counter_hash_copy_key;
+ hash_table->not_found_callback = NULL;
hash_initialise(hash_table);
return hash_table;
}
diff --git a/hash.c b/hash.c
index 1c500f1..340c206 100644
--- a/hash.c
+++ b/hash.c
@@ -69,7 +69,12 @@ hash_status_enum hash_find(hash_type* hash_table, void* key, void **rec) {
while (p && !hash_table->compare(p->key, key)) {
p = p->next;
}
- if (!p) return HASH_STATUS_KEY_NOT_FOUND;
+ if (!p) {
+ if (hash_table->not_found_callback != NULL) {
+ hash_table->not_found_callback((void *)hash_table);
+ }
+ return HASH_STATUS_KEY_NOT_FOUND;
+ }
*rec = p->rec;
return HASH_STATUS_OK;
}
diff --git a/hash.h b/hash.h
index 9cb3460..5074084 100644
--- a/hash.h
+++ b/hash.h
@@ -24,6 +24,7 @@ typedef struct {
int (*hash) (void*);
void* (*copy_key) (void*);
void (*delete_key) (void*);
+ void (*not_found_callback)(void*);
hash_node_type** table;
int size;
} hash_type;
diff --git a/ns_hash.c b/ns_hash.c
index 219de95..6f57f7b 100644
--- a/ns_hash.c
+++ b/ns_hash.c
@@ -63,6 +63,7 @@ hash_type* ns_hash_create() {
hash_table->hash = &ns_hash_hash;
hash_table->delete_key = &ns_hash_delete_key;
hash_table->copy_key = &ns_hash_copy_key;
+ hash_table->not_found_callback = NULL;
hash_initialise(hash_table);
return hash_table;
}
diff --git a/options.c b/options.c
index a075357..d64ab35 100644
--- a/options.c
+++ b/options.c
@@ -30,7 +30,7 @@
options_t options;
-char optstr[] = "+i:f:nNF:G:lhpbBu:Pm:c:s:tL:o:";
+char optstr[] = "+i:f:nNF:G:lhpbBu:Pm:c:s:tL:o:A";
/* Global options. */
@@ -165,6 +165,7 @@ void options_set_defaults() {
options.timed_output = 0;
options.no_curses = 0;
options.num_lines = 10;
+ options.process_names = 0;
/* Figure out the name for the config file */
s = getenv("HOME");
@@ -204,6 +205,7 @@ static void usage(FILE *fp) {
" -G net6/mask6 show traffic flows in/out of IPv6 network\n"
" -l display and count link-local IPv6 traffic (default: off)\n"
" -P show ports as well as hosts\n"
+" -A show local process names\n"
" -m limit sets the upper limit for the bandwidth scale\n"
" -c config file specifies an alternative configuration file\n"
" -t use text interface without ncurses\n"
@@ -282,9 +284,9 @@ void options_read_args(int argc, char **argv) {
config_set_string("bandwidth-unit", "bytes");
break;
- case 'u':
- config_set_string("bandwidth-unit", optarg);
- break;
+ case 'u':
+ config_set_string("bandwidth-unit", optarg);
+ break;
case 's':
config_set_string("timed-output", optarg);
@@ -308,6 +310,10 @@ void options_read_args(int argc, char **argv) {
options.config_file_specified = 1;
break;
+ case 'A':
+ config_set_string("proc-names", "true");
+ break;
+
case '?':
fprintf(stderr, "iftop: unknown option -%c\n", optopt);
usage(stderr);
@@ -585,6 +591,7 @@ void options_make() {
options_config_get_int("timed-output", &options.timed_output);
options_config_get_bool("no-curses", &options.no_curses);
options_config_get_int("num-lines", &options.num_lines);
+ options_config_get_bool("proc-names", &options.process_names);
options_config_get_net_filter();
options_config_get_net_filter6();
};
diff --git a/options.h b/options.h
index 9628dfe..70f0ea9 100644
--- a/options.h
+++ b/options.h
@@ -97,6 +97,8 @@ typedef struct {
char *config_file;
int config_file_specified;
+ int process_names;
+
} options_t;
diff --git a/proc_hash.c b/proc_hash.c
new file mode 100644
index 0000000..8ff0eca
--- /dev/null
+++ b/proc_hash.c
@@ -0,0 +1,198 @@
+/* hash table */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+#include <unistd.h>
+#include "proc_hash.h"
+#include "hash.h"
+#include "iftop.h"
+
+// Deliberately not a power of 2 or 10
+#define hash_table_size 123
+
+typedef struct proc_list proc_list;
+
+struct proc_list {
+ ip_process* this;
+ proc_list* next;
+};
+
+static const char *const re_port_num = "^(udp|tcp)[[:space:]]*[[:alpha:]-]+[[:space:]]+[[:digit:]]+[[:space:]]+"
+ "[[:digit:]]+[[:space:]]+"
+ "(([[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+"
+ "(%[[:alnum:]]+)?)|(\\[([[:digit:]]*:)+[[:digit:]]*\\]))"
+ ":([[:digit:]]+)"; // \7 is port
+static const char *const re_proc_name_pid = "users:\\(\\(\"([[:alpha:]-]+)\",pid=([[:digit:]]+)"; // \1 is procname, \2 is pid
+
+regex_t rege_port_num;
+regex_t rege_proc_name_pid;
+
+int proc_hash_compare(void* a, void* b) {
+ ip_process* aa = (ip_process*)a;
+ ip_process* bb = (ip_process*)b;
+ return (aa->port == bb->port);
+}
+
+int proc_hash_hash(void* key) {
+ ip_process* pkey = (ip_process*)key;
+ return pkey->port % hash_table_size;
+}
+
+void* proc_hash_copy_key(void* orig) {
+ int* copy;
+ copy = xmalloc(sizeof *copy);
+ *copy = *(int*)orig;
+ return copy;
+}
+
+void proc_hash_delete_key(void* key) {
+ free(key);
+}
+
+void child_exec(int* pipe_fd, int option) {
+ close(pipe_fd[0]); // close reading end in the child
+ dup2(pipe_fd[1], 1); // send stdout to the pipe
+ dup2(pipe_fd[1], 2); // send stderr to the pipe
+ close(pipe_fd[1]); // this descriptor is no longer needed
+ switch (option) {
+ case 2:
+ execlp("ss", "-O", "-H", "-l", "-n", "-t", "-u", "-p", (char *)NULL);
+ break;
+ case 1:
+ execlp("ss", "-O", "-H", "-n", "-t", "-u", "-p", (char *)NULL);
+ break;
+ case 0:
+ default:
+ execlp("ss", "-O", "-H", "-a", "-n", "-t", "-u", "-p", (char *)NULL);
+ break;
+ }
+}
+
+proc_list* proc_parse_parent(int *pipefd) {
+ proc_list* list = malloc(sizeof(proc_list));
+ proc_list* ret = list;
+ list->this = malloc(sizeof(ip_process));
+ list->this->name = strdup("myprog");
+ list->this->port = 45678;
+ list->next = NULL;
+
+ regmatch_t pmatch[10];
+ regoff_t len, shift;
+ int buf_len = 65536;
+ char buffer[buf_len];
+ uint16_t tmp_port;
+ char* tmp_sport;
+ char* tmp_name;
+ close(pipefd[1]); // close the write end of the pipe in the parent
+ while (read(pipefd[0], buffer, sizeof(buffer)) != 0)
+ {
+ // parse results from child to match process names with port numbers
+ const char *c = buffer;
+ while (1) {
+ if (regexec(&rege_port_num, c, sizeof(pmatch) / sizeof(pmatch[0]), pmatch, 0)) {
+ break;
+ }
+ shift = pmatch[0].rm_eo;
+ len = pmatch[7].rm_eo - pmatch[7].rm_so;
+ tmp_sport = strndup(c + pmatch[7].rm_so, len);
+ tmp_port = atoi(tmp_sport);
+ if (regexec(&rege_proc_name_pid, c, sizeof(pmatch) / sizeof(pmatch[0]), pmatch, 0)) {
+ c += shift;
+ continue;
+ }
+ len = pmatch[1].rm_eo - pmatch[1].rm_so;
+ tmp_name = strndup(c + pmatch[1].rm_so, len);
+ // no need to retrieve pid
+ list->this = malloc(sizeof(ip_process));
+ list->this->port = tmp_port;
+ list->this->name = tmp_name;
+ list->next = malloc(sizeof(proc_list));
+ list = list->next;
+ list->this = NULL;
+ list->next = NULL;
+ c += pmatch[0].rm_eo;
+ }
+ memset(buffer, 0, sizeof(buffer));
+ }
+ return ret;
+}
+
+proc_list* proc_parse_fork() {
+ int pipefd[2];
+ pipe(pipefd);
+ if (fork() == 0) { // child
+ child_exec(pipefd, 0); // "-a" flag
+ }
+ return proc_parse_parent(pipefd);
+}
+
+
+// return value == true for 'more items in list'
+bool proc_result_free(proc_list** procs) {
+ if ((*procs)->next == NULL) {
+ free(*procs);
+ return false;
+ }
+ proc_list* rem = *procs;
+ *procs = (*procs)->next;
+ free(rem);
+ return true;
+}
+
+void proc_hash_init_refresh(hash_type* sh, bool refresh) {
+ proc_list* processes;
+ ip_process* process;
+ void* rec;
+ if (!refresh) {
+ regcomp(&rege_port_num, re_port_num, REG_NEWLINE | REG_EXTENDED);
+ regcomp(&rege_proc_name_pid, re_proc_name_pid, REG_NEWLINE | REG_EXTENDED);
+ }
+ processes = proc_parse_fork();
+ while (processes != NULL && processes->this != NULL) {
+ process = processes->this;
+ if (refresh && hash_find(sh, process, &rec) == HASH_STATUS_OK) {
+ if (strcmp((char *)rec, process->name) == 0) {
+ if (!proc_result_free(&processes)) {
+ break;
+ }
+ continue;
+ } else {
+ hash_delete(sh, process);
+ }
+ }
+ hash_insert(sh, process, strdup(process->name));
+ if (!proc_result_free(&processes)) {
+ break;
+ }
+ }
+}
+
+void proc_hash_not_found(void* vp_process_hash) {
+ static bool recursive;
+ static int n_times;
+ hash_type* process_hash = (hash_type*)vp_process_hash;
+ if (!recursive && ++n_times >= 20) {
+ n_times = 0;
+ recursive = true;
+ proc_hash_init_refresh(process_hash, true);
+ recursive = false;
+ }
+}
+
+/*
+ * Allocate and return a hash
+ */
+hash_type* proc_hash_create() {
+ hash_type* hash_table;
+ hash_table = xcalloc(hash_table_size, sizeof *hash_table);
+ hash_table->size = hash_table_size;
+ hash_table->compare = &proc_hash_compare;
+ hash_table->hash = &proc_hash_hash;
+ hash_table->delete_key = &proc_hash_delete_key;
+ hash_table->copy_key = &proc_hash_copy_key;
+ hash_table->not_found_callback = proc_hash_not_found;
+ hash_initialise(hash_table);
+ return hash_table;
+}
diff --git a/proc_hash.h b/proc_hash.h
new file mode 100644
index 0000000..49724b4
--- /dev/null
+++ b/proc_hash.h
@@ -0,0 +1,22 @@
+/*
+ * proc_hash.h:
+ *
+ */
+
+#ifndef __PROC_HASH_H_ /* include guard */
+#define __PROC_HASH_H_
+
+#include <stdint.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#include "hash.h"
+
+typedef struct {
+ uint16_t port;
+ char* name;
+} ip_process;
+
+hash_type* proc_hash_create(void);
+void proc_hash_init_refresh(hash_type* sh, bool refresh);
+
+#endif /* __PROC_HASH_H_ */
diff --git a/serv_hash.c b/serv_hash.c
index 279032e..c9dbdbd 100644
--- a/serv_hash.c
+++ b/serv_hash.c
@@ -44,6 +44,7 @@ hash_type* serv_hash_create() {
hash_table->hash = &serv_hash_hash;
hash_table->delete_key = &serv_hash_delete_key;
hash_table->copy_key = &serv_hash_copy_key;
+ hash_table->not_found_callback = NULL;
hash_initialise(hash_table);
return hash_table;
}
diff --git a/tui.c b/tui.c
index af10a2f..f061e97 100644
--- a/tui.c
+++ b/tui.c
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <unistd.h>
#if defined(HAVE_TERMIOS_H)
@@ -81,8 +82,10 @@ void tui_print() {
host_pair_line* screen_line = (host_pair_line*)nn->data;
/* Assemble host information */
- sprint_host(host1, screen_line->ap.af, &(screen_line->ap.src6), screen_line->ap.src_port, screen_line->ap.protocol, PRINT_WIDTH, options.aggregate_src);
- sprint_host(host2, screen_line->ap.af, &(screen_line->ap.dst6), screen_line->ap.dst_port, screen_line->ap.protocol, PRINT_WIDTH, options.aggregate_dest);
+ sprint_host(host1, screen_line->ap.af, &(screen_line->ap.src6), screen_line->ap.src_port,
+ screen_line->ap.protocol, PRINT_WIDTH, options.aggregate_src, true);
+ sprint_host(host2, screen_line->ap.af, &(screen_line->ap.dst6), screen_line->ap.dst_port,
+ screen_line->ap.protocol, PRINT_WIDTH, options.aggregate_dest, false);
/* Send rate per connection */
printf("%4d %s%s", l, host1, " =>");
@@ -169,6 +172,8 @@ void tui_init() {
screen_hash = addr_hash_create();
service_hash = serv_hash_create();
serv_hash_initialise(service_hash);
+ process_hash = proc_hash_create();
+ proc_hash_init_refresh(process_hash, false);
printf("Listening on %s\n", options.interface);
}
@@ -235,6 +240,11 @@ void tui_loop() {
printf("Port resolution is %s.\n\n", options.portresolution ? "ON" : "OFF");
tick(1);
break;
+ case 'A':
+ options.process_names ^= 1;
+ printf("Process name display is %s.\n\n", options.process_names ? "ON" : "OFF");
+ tick(1);
+ break;
case 's':
options.aggregate_src ^= 1;
printf("%s source host\n\n", options.aggregate_src ? "Hide" : "Show");
@@ -302,20 +312,20 @@ void tui_loop() {
if (options.paused) {
printf("Pausing... press 'P' again to continue.\n");
}
- else {
- printf("Continuing.\n\n");
- tick(1);
- }
- break;
+ else {
+ printf("Continuing.\n\n");
+ tick(1);
+ }
+ break;
case 'o':
options.freezeorder ^= 1;
printf("Order %s.\n\n", options.freezeorder ? "frozen" : "unfrozen");
- tick(1);
- break;
+ tick(1);
+ break;
case '1':
options.sort = OPTION_SORT_DIV1;
printf("Sorting by column 1.\n\n");
- tick(1);
+ tick(1);
break;
case '2':
options.sort = OPTION_SORT_DIV2;
diff --git a/ui.c b/ui.c
index 2165071..f2c3cc2 100644
--- a/ui.c
+++ b/ui.c
@@ -44,7 +44,8 @@
" S - toggle show source port l - set screen filter\n"\
" D - toggle show destination port L - lin/log scales\n"\
" p - toggle port display ! - shell command\n"\
-" q - quit\n"\
+" A - toggle show process names q - quit\n"\
+"\n"\
"Sorting:\n"\
" 1/2/3 - sort by 1st/2nd/3rd column\n"\
" < - sort by source name\n"\
@@ -315,11 +316,13 @@ void ui_print() {
sprint_host(host1, screen_line->ap.af,
&(screen_line->ap.src6),
screen_line->ap.src_port,
- screen_line->ap.protocol, L, options.aggregate_src);
+ screen_line->ap.protocol, L,
+ options.aggregate_src, true);
sprint_host(host2, screen_line->ap.af,
&(screen_line->ap.dst6),
screen_line->ap.dst_port,
- screen_line->ap.protocol, L, options.aggregate_dest);
+ screen_line->ap.protocol, L,
+ options.aggregate_dest, false);
if(!screen_filter_match(host1) && !screen_filter_match(host2)) {
continue;
@@ -467,6 +470,9 @@ void ui_init() {
service_hash = serv_hash_create();
serv_hash_initialise(service_hash);
+ process_hash = proc_hash_create();
+ proc_hash_init_refresh(process_hash, false);
+
snprintf(msg,20,"Listening on %s",options.interface);
showhelp(msg);
@@ -530,6 +536,17 @@ void ui_loop() {
tick(1);
break;
+ case 'A':
+ if (options.process_names) {
+ options.process_names = 0;
+ showhelp("Process names off");
+ } else {
+ options.process_names = 1;
+ showhelp("Process names on");
+ }
+ tick(1);
+ break;
+
case 'h':
case '?':
options.showhelp = !options.showhelp;
diff --git a/ui_common.c b/ui_common.c
index dcf6646..757bbc4 100644
--- a/ui_common.c
+++ b/ui_common.c
@@ -27,6 +27,14 @@ char* unit_disp[][UNIT_DIVISIONS] = {
[OPTION_BW_PKTS] = { "p", "Kp", "Mp", "GB"},
};
+sorted_list_type screen_list;
+host_pair_line totals;
+int peaksent, peakrecv, peaktotal;
+hash_type* screen_hash;
+hash_type* service_hash;
+hash_type* process_hash;
+
+
extern hash_type* history;
extern int history_pos;
extern int history_len;
@@ -281,18 +289,6 @@ void analyse_data() {
if(options.aggregate_dest) {
memset(&ap.dst6, '\0', sizeof(ap.dst6));
}
-
- /* Aggregate ports, if required */
- if(options.showports == OPTION_PORTS_DEST || options.showports == OPTION_PORTS_OFF) {
- ap.src_port = 0;
- }
- if(options.showports == OPTION_PORTS_SRC || options.showports == OPTION_PORTS_OFF) {
- ap.dst_port = 0;
- }
- if(options.showports == OPTION_PORTS_OFF) {
- ap.protocol = 0;
- }
-
if(hash_find(screen_hash, &ap, u_screen_line.void_pp) == HASH_STATUS_KEY_NOT_FOUND) {
screen_line = xcalloc(1, sizeof *screen_line);
@@ -324,7 +320,8 @@ void analyse_data() {
}
-void sprint_host(char * line, int af, struct in6_addr* addr, unsigned int port, unsigned int protocol, int L, int unspecified_as_star) {
+void sprint_host(char * line, int af, struct in6_addr* addr, unsigned int port,
+ unsigned int protocol, int L, int unspecified_as_star, bool is_local) {
char hostname[HOSTNAME_LENGTH];
char service[HOSTNAME_LENGTH];
char* s_name;
@@ -334,6 +331,7 @@ void sprint_host(char * line, int af, struct in6_addr* addr, unsigned int port,
} u_s_name = { &s_name };
ip_service skey;
+ ip_process pkey;
int left;
if(IN6_IS_ADDR_UNSPECIFIED(addr) && unspecified_as_star) {
@@ -346,21 +344,23 @@ void sprint_host(char * line, int af, struct in6_addr* addr, unsigned int port,
inet_ntop(af, addr, hostname, sizeof(hostname));
}
left = strlen(hostname);
-
- if(port != 0) {
+ service[0] = '\0';
+ if ((options.showports == OPTION_PORTS_ON) || (options.showports == OPTION_PORTS_SRC && is_local) ||
+ (options.showports == OPTION_PORTS_DEST && !is_local)) {
skey.port = port;
skey.protocol = protocol;
if(options.portresolution && hash_find(service_hash, &skey, u_s_name.void_pp) == HASH_STATUS_OK) {
snprintf(service, HOSTNAME_LENGTH, ":%s", s_name);
- }
- else {
+ } else {
snprintf(service, HOSTNAME_LENGTH, ":%d", port);
}
}
- else {
- service[0] = '\0';
+ pkey.port = (uint16_t)port;
+ if (options.process_names && is_local &&
+ hash_find(process_hash, &pkey, (void **) &(pkey.name)) == HASH_STATUS_OK) {
+ snprintf(service + strlen(service), HOSTNAME_LENGTH - strlen(service), "(%s)", pkey.name);
}
-
+
/* If we're showing IPv6 addresses with a port number, put them in square
* brackets. */
if(port == 0 || af == AF_INET || L < 2) {
diff --git a/ui_common.h b/ui_common.h
index 63ae5bb..44c04e6 100644
--- a/ui_common.h
+++ b/ui_common.h
@@ -11,6 +11,7 @@
#include <stdio.h>
#include "addr_hash.h"
+#include "proc_hash.h"
#include "serv_hash.h"
#include "iftop.h"
#include "resolver.h"
@@ -33,16 +34,18 @@ typedef struct host_pair_line_tag {
extern options_t options;
-sorted_list_type screen_list;
-host_pair_line totals;
-int peaksent, peakrecv, peaktotal;
+extern sorted_list_type screen_list;
+extern host_pair_line totals;
+extern int peaksent, peakrecv, peaktotal;
extern history_type history_totals;
-hash_type* screen_hash;
-hash_type* service_hash;
+extern hash_type* screen_hash;
+extern hash_type* service_hash;
+extern hash_type* process_hash;
void analyse_data(void);
void screen_list_init(void);
-void sprint_host(char * line, int af, struct in6_addr* addr, unsigned int port, unsigned int protocol, int L, int unspecified_as_star);
+void sprint_host(char * line, int af, struct in6_addr* addr, unsigned int port,
+ unsigned int protocol, int L, int unspecified_as_star, bool is_local);
void readable_size(float, char*, int, int, option_bw_unit_t);
#endif /* __UI_COMMON_H_ */