diff options
author | netblue30 <netblue30@yahoo.com> | 2015-08-08 19:12:30 -0400 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2015-08-08 19:12:30 -0400 |
commit | 1379851360349d6617ad32944a25ee5e2bb74fc2 (patch) | |
tree | f69b48e90708bfa3c2723d5a27ed3e024c827b43 /src/firemon/netstats.c | |
parent | delete files (diff) | |
download | firejail-1379851360349d6617ad32944a25ee5e2bb74fc2.tar.gz firejail-1379851360349d6617ad32944a25ee5e2bb74fc2.tar.zst firejail-1379851360349d6617ad32944a25ee5e2bb74fc2.zip |
Baseline firejail 0.9.28
Diffstat (limited to 'src/firemon/netstats.c')
-rw-r--r-- | src/firemon/netstats.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/src/firemon/netstats.c b/src/firemon/netstats.c new file mode 100644 index 000000000..6c4a767f1 --- /dev/null +++ b/src/firemon/netstats.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com) | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "firemon.h" | ||
21 | #include <termios.h> | ||
22 | #include <sys/ioctl.h> | ||
23 | #include <sys/types.h> | ||
24 | #include <sys/stat.h> | ||
25 | #include <unistd.h> | ||
26 | |||
27 | #define MAXBUF 4096 | ||
28 | |||
29 | static char *get_header(void) { | ||
30 | char *rv; | ||
31 | if (asprintf(&rv, "%-5.5s %-9.9s %-10.10s %-10.10s %s", | ||
32 | "PID", "User", "RX(KB/s)", "TX(KB/s)", "Command") == -1) | ||
33 | errExit("asprintf"); | ||
34 | |||
35 | return rv; | ||
36 | } | ||
37 | |||
38 | void get_stats(int parent) { | ||
39 | // find the first child | ||
40 | int child = -1; | ||
41 | for (child = parent + 1; child < max_pids; child++) { | ||
42 | if (pids[child].parent == parent) | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | if (child == -1) | ||
47 | goto errexit; | ||
48 | |||
49 | // open /proc/child/net/dev file and read rx and tx | ||
50 | char *fname; | ||
51 | if (asprintf(&fname, "/proc/%d/net/dev", child) == -1) | ||
52 | errExit("asprintf"); | ||
53 | FILE *fp = fopen(fname, "r"); | ||
54 | if (!fp) { | ||
55 | free(fname); | ||
56 | goto errexit; | ||
57 | } | ||
58 | |||
59 | char buf[MAXBUF]; | ||
60 | long long unsigned rx = 0; | ||
61 | long long unsigned tx = 0; | ||
62 | while (fgets(buf, MAXBUF, fp)) { | ||
63 | if (strncmp(buf, "Inter", 5) == 0) | ||
64 | continue; | ||
65 | if (strncmp(buf, " face", 5) == 0) | ||
66 | continue; | ||
67 | |||
68 | char *ptr = buf; | ||
69 | while (*ptr != '\0' && *ptr != ':') { | ||
70 | ptr++; | ||
71 | } | ||
72 | |||
73 | if (*ptr == '\0') { | ||
74 | fclose(fp); | ||
75 | free(fname); | ||
76 | goto errexit; | ||
77 | } | ||
78 | ptr++; | ||
79 | |||
80 | long long unsigned rxval; | ||
81 | long long unsigned txval; | ||
82 | unsigned a, b, c, d, e, f, g; | ||
83 | sscanf(ptr, "%llu %u %u %u %u %u %u %u %llu", | ||
84 | &rxval, &a, &b, &c, &d, &e, &f, &g, &txval); | ||
85 | rx += rxval; | ||
86 | tx += txval; | ||
87 | } | ||
88 | |||
89 | // store data | ||
90 | pids[parent].rx_delta = rx - pids[parent].rx; | ||
91 | pids[parent].rx = rx; | ||
92 | pids[parent].tx_delta = tx - pids[parent].tx; | ||
93 | pids[parent].tx = tx; | ||
94 | |||
95 | |||
96 | free(fname); | ||
97 | fclose(fp); | ||
98 | return; | ||
99 | |||
100 | errexit: | ||
101 | pids[parent].rx = 0; | ||
102 | pids[parent].tx = 0; | ||
103 | pids[parent].rx_delta = 0; | ||
104 | pids[parent].tx_delta = 0; | ||
105 | } | ||
106 | |||
107 | |||
108 | static void print_proc(int index, int itv, int col) { | ||
109 | // command | ||
110 | char *cmd = pid_proc_cmdline(index); | ||
111 | char *ptrcmd; | ||
112 | if (cmd == NULL) { | ||
113 | if (pids[index].zombie) | ||
114 | ptrcmd = "(zombie)"; | ||
115 | else | ||
116 | ptrcmd = ""; | ||
117 | } | ||
118 | else | ||
119 | ptrcmd = cmd; | ||
120 | // if the command doesn't have a --net= option, don't print | ||
121 | if (strstr(ptrcmd, "--net=") == NULL) { | ||
122 | if (cmd) | ||
123 | free(cmd); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | // pid | ||
128 | char pidstr[10]; | ||
129 | snprintf(pidstr, 10, "%u", index); | ||
130 | |||
131 | // user | ||
132 | char *user = pid_get_user_name(pids[index].uid); | ||
133 | char *ptruser; | ||
134 | if (user) | ||
135 | ptruser = user; | ||
136 | else | ||
137 | ptruser = ""; | ||
138 | |||
139 | |||
140 | float rx_kbps = ((float) pids[index].rx_delta / 1000) / itv; | ||
141 | char ptrrx[15]; | ||
142 | sprintf(ptrrx, "%.03f", rx_kbps); | ||
143 | |||
144 | float tx_kbps = ((float) pids[index].tx_delta / 1000) / itv; | ||
145 | char ptrtx[15]; | ||
146 | sprintf(ptrtx, "%.03f", tx_kbps); | ||
147 | |||
148 | char buf[1024 + 1]; | ||
149 | snprintf(buf, 1024, "%-5.5s %-9.9s %-10.10s %-10.10s %s", | ||
150 | pidstr, ptruser, ptrrx, ptrtx, ptrcmd); | ||
151 | if (col < 1024) | ||
152 | buf[col] = '\0'; | ||
153 | printf("%s\n", buf); | ||
154 | |||
155 | if (cmd) | ||
156 | free(cmd); | ||
157 | if (user) | ||
158 | free(user); | ||
159 | |||
160 | } | ||
161 | |||
162 | void netstats(void) { | ||
163 | if (getuid() == 0) | ||
164 | firemon_drop_privs(); | ||
165 | |||
166 | pid_read(0); // include all processes | ||
167 | |||
168 | printf("Displaying network statistics only for sandboxes using a new network namespace.\n"); | ||
169 | |||
170 | // print processes | ||
171 | while (1) { | ||
172 | // set pid table | ||
173 | int i; | ||
174 | int itv = 5; // 5 second interval | ||
175 | pid_read(0); // todo: preserve the last calculation if any, so we don't have to do get_stats() | ||
176 | |||
177 | // start rx/tx measurements | ||
178 | for (i = 0; i < max_pids; i++) { | ||
179 | if (pids[i].level == 1) | ||
180 | get_stats(i); | ||
181 | } | ||
182 | |||
183 | // wait 5 seconds | ||
184 | firemon_sleep(itv); | ||
185 | |||
186 | // grab screen size | ||
187 | struct winsize sz; | ||
188 | int row = 24; | ||
189 | int col = 80; | ||
190 | if (!ioctl(0, TIOCGWINSZ, &sz)) { | ||
191 | col = sz.ws_col; | ||
192 | row = sz.ws_row; | ||
193 | } | ||
194 | |||
195 | // start printing | ||
196 | firemon_clrscr(); | ||
197 | char *header = get_header(); | ||
198 | if (strlen(header) > col) | ||
199 | header[col] = '\0'; | ||
200 | printf("%s\n", header); | ||
201 | if (row > 0) | ||
202 | row--; | ||
203 | free(header); | ||
204 | |||
205 | // start rx/tx measurements | ||
206 | for (i = 0; i < max_pids; i++) { | ||
207 | if (pids[i].level == 1) { | ||
208 | get_stats(i); | ||
209 | print_proc(i, itv, col); | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||