1 #include "common.h"
2 #include "ifinfo.h"
3 #include "iflist.h"
4 #include "traffic.h"
5 #include "dbsql.h"
6 #include "dbxml.h"
7 #include "dbjson.h"
8 #include "dbshow.h"
9 #include "misc.h"
10 #include "cfg.h"
11 #include "cfgoutput.h"
12 #include "vnstat_func.h"
13
initparams(PARAMS * p)14 void initparams(PARAMS *p)
15 {
16 db = NULL;
17 noexit = 0; /* allow functions to exit in case of error */
18 debug = 0; /* debug disabled by default */
19 disableprints = 0; /* let prints be visible */
20
21 p->addiface = 0;
22 p->query = 1;
23 p->setalias = 0;
24 p->dbifcount = 0;
25 p->force = 0;
26 p->traffic = 0;
27 p->livetraffic = 0;
28 p->defaultiface = 1;
29 p->removeiface = 0;
30 p->renameiface = 0;
31 p->livemode = 0;
32 p->limit = -1;
33 p->ifacelist = NULL;
34 p->interface[0] = '\0';
35 p->alias[0] = '\0';
36 p->newifname[0] = '\0';
37 p->filename[0] = '\0';
38 p->definterface[0] = '\0';
39 p->cfgfile[0] = '\0';
40 p->jsonmode = 'a';
41 p->xmlmode = 'a';
42 p->databegin[0] = '\0';
43 p->dataend[0] = '\0';
44 }
45
showhelp(PARAMS * p)46 void showhelp(PARAMS *p)
47 {
48 printf("vnStat %s by Teemu Toivola <tst at iki dot fi>\n\n", getversion());
49
50 printf(" -5, --fiveminutes [limit] show 5 minutes\n");
51 printf(" -h, --hours [limit] show hours\n");
52 printf(" -hg, --hoursgraph show hours graph\n");
53 printf(" -d, --days [limit] show days\n");
54 printf(" -m, --months [limit] show months\n");
55 printf(" -y, --years [limit] show years\n");
56 printf(" -t, --top [limit] show top days\n\n");
57
58 printf(" -b, --begin <date> set list begin date\n");
59 printf(" -e, --end <date> set list end date\n\n");
60
61 printf(" --oneline [mode] show simple parsable format\n");
62 printf(" --json [mode] [limit] show database in json format\n");
63 printf(" --xml [mode] [limit] show database in xml format\n\n");
64
65 printf(" -tr, --traffic [time] calculate traffic\n");
66 printf(" -l, --live [mode] show transfer rate in real time\n");
67 printf(" -i, --iface <interface> select interface");
68 if (strlen(p->definterface)) {
69 printf(" (default: %s)", p->definterface);
70 }
71 printf("\n\n");
72
73 printf("Use \"--longhelp\" or \"man vnstat\" for complete list of options.\n");
74 }
75
showlonghelp(PARAMS * p)76 void showlonghelp(PARAMS *p)
77 {
78 printf("vnStat %s by Teemu Toivola <tst at iki dot fi>\n\n", getversion());
79
80 printf("Query:\n");
81
82 printf(" -q, --query query database\n");
83 printf(" -s, --short use short output\n");
84 printf(" -5, --fiveminutes [limit] show 5 minutes\n");
85 printf(" -h, --hours [limit] show hours\n");
86 printf(" -hg, --hoursgraph show hours graph\n");
87 printf(" -d, --days [limit] show days\n");
88 printf(" -m, --months [limit] show months\n");
89 printf(" -y, --years [limit] show years\n");
90 printf(" -t, --top [limit] show top days\n");
91 printf(" -b, --begin <date> set list begin date\n");
92 printf(" -e, --end <date> set list end date\n");
93 printf(" --oneline [mode] show simple parsable format\n");
94 printf(" --json [mode] [limit] show database in json format\n");
95 printf(" --xml [mode] [limit] show database in xml format\n\n");
96
97 printf("Modify:\n");
98
99 printf(" --add add interface to database\n");
100 printf(" --remove remove interface from database\n");
101 printf(" --rename <name> rename interface in database\n");
102 printf(" --setalias <alias> set alias for interface\n\n");
103
104 printf("Misc:\n");
105
106 printf(" -i, --iface <interface> select interface");
107 if (strlen(p->definterface)) {
108 printf(" (default: %s)", p->definterface);
109 }
110 printf("\n");
111 printf(" -?, --help show short help\n");
112 printf(" -D, --debug show some additional debug information\n");
113 printf(" -v, --version show version\n");
114 printf(" -tr, --traffic [time] calculate traffic\n");
115 printf(" -l, --live [mode] show transfer rate in real time\n");
116 printf(" -ru, --rateunit [mode] swap configured rate unit\n");
117 printf(" --limit <limit> set output entry limit\n");
118 printf(" --style <mode> select output style (0-4)\n");
119 printf(" --iflist [mode] show list of available interfaces\n");
120 printf(" --dbiflist [mode] show list of interfaces in database\n");
121 printf(" --dbdir <directory> select database directory\n");
122 printf(" --locale <locale> set locale\n");
123 printf(" --config <config file> select config file\n");
124 printf(" --showconfig dump config file with current settings\n");
125 printf(" --longhelp show this help\n\n");
126
127 printf("See also \"man vnstat\" for longer descriptions of each option.\n");
128 }
129
parseargs(PARAMS * p,int argc,char ** argv)130 void parseargs(PARAMS *p, int argc, char **argv)
131 {
132 int currentarg;
133
134 /* parse parameters, maybe not the best way but... */
135 for (currentarg = 1; currentarg < argc; currentarg++) {
136 if (debug)
137 printf("arg %d: \"%s\"\n", currentarg, argv[currentarg]);
138 if (strcmp(argv[currentarg], "--longhelp") == 0) {
139 showlonghelp(p);
140 exit(EXIT_SUCCESS);
141 } else if ((strcmp(argv[currentarg], "-?") == 0) || (strcmp(argv[currentarg], "--help") == 0)) {
142 showhelp(p);
143 exit(EXIT_SUCCESS);
144 } else if ((strcmp(argv[currentarg], "-i") == 0) || (strcmp(argv[currentarg], "--iface") == 0) || (strcmp(argv[currentarg], "--interface") == 0)) {
145 if (currentarg + 1 < argc) {
146 if (strlen(argv[currentarg + 1]) > 31) {
147 printf("Error: Interface name is limited to 31 characters.\n");
148 exit(EXIT_FAILURE);
149 }
150 strncpy_nt(p->interface, argv[currentarg + 1], 32);
151 if (strlen(p->interface)) {
152 p->defaultiface = 0;
153 } else {
154 strncpy_nt(p->definterface, p->interface, 32);
155 }
156 if (debug)
157 printf("Used interface: \"%s\"\n", p->interface);
158 currentarg++;
159 } else {
160 printf("Error: Interface for %s missing.\n", argv[currentarg]);
161 exit(EXIT_FAILURE);
162 }
163 } else if (strcmp(argv[currentarg], "--config") == 0) {
164 /* config has already been parsed earlier so nothing to do here */
165 currentarg++;
166 } else if (strcmp(argv[currentarg], "--setalias") == 0 || strcmp(argv[currentarg], "--nick") == 0) {
167 if (strcmp(argv[currentarg], "--nick") == 0) {
168 printf("Warning: --nick is deprecated and will be removed in a future release. Use --setalias instead.\n");
169 }
170 if (currentarg + 1 < argc) {
171 strncpy_nt(p->alias, argv[currentarg + 1], 32);
172 if (debug)
173 printf("Used alias: \"%s\"\n", p->alias);
174 p->setalias = 1;
175 currentarg++;
176 } else {
177 printf("Error: Alias for %s missing.\n", argv[currentarg]);
178 exit(EXIT_FAILURE);
179 }
180 } else if ((strcmp(argv[currentarg], "--style")) == 0) {
181 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
182 cfg.ostyle = atoi(argv[currentarg + 1]);
183 if (cfg.ostyle > 4 || cfg.ostyle < 0) {
184 printf("Error: Invalid style parameter \"%d\"\n", cfg.ostyle);
185 showstylehelp();
186 exit(EXIT_FAILURE);
187 }
188 if (debug)
189 printf("Style changed: %d\n", cfg.ostyle);
190 currentarg++;
191 } else {
192 printf("Error: Style parameter for --style missing.\n");
193 showstylehelp();
194 exit(EXIT_FAILURE);
195 }
196 } else if ((strcmp(argv[currentarg], "--dbdir")) == 0) {
197 if (currentarg + 1 < argc) {
198 strncpy_nt(cfg.dbdir, argv[currentarg + 1], 512);
199 if (debug)
200 printf("DatabaseDir: \"%s\"\n", cfg.dbdir);
201 currentarg++;
202 } else {
203 printf("Error: Directory for %s missing.\n", argv[currentarg]);
204 exit(EXIT_FAILURE);
205 }
206 } else if ((strcmp(argv[currentarg], "--locale")) == 0) {
207 if (currentarg + 1 < argc) {
208 setlocale(LC_ALL, argv[currentarg + 1]);
209 if (debug)
210 printf("Locale: \"%s\"\n", argv[currentarg + 1]);
211 currentarg++;
212 } else {
213 printf("Error: Locale for %s missing.\n", argv[currentarg]);
214 exit(EXIT_FAILURE);
215 }
216 } else if (strcmp(argv[currentarg], "--add") == 0) {
217 p->addiface = 1;
218 p->query = 0;
219 } else if ((strcmp(argv[currentarg], "-u") == 0) || (strcmp(argv[currentarg], "--update") == 0)) {
220 printf("Error: The \"%s\" parameter is not supported in this version.\n", argv[currentarg]);
221 exit(EXIT_FAILURE);
222 } else if ((strcmp(argv[currentarg], "-q") == 0) || (strcmp(argv[currentarg], "--query") == 0)) {
223 p->query = 1;
224 } else if ((strcmp(argv[currentarg], "-D") == 0) || (strcmp(argv[currentarg], "--debug") == 0)) {
225 debug = 1;
226 } else if ((strcmp(argv[currentarg], "-d") == 0) || (strcmp(argv[currentarg], "--days") == 0)) {
227 cfg.qmode = 1;
228 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
229 cfg.listdays = atoi(argv[currentarg + 1]);
230 if (cfg.listdays < 0) {
231 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
232 exit(EXIT_FAILURE);
233 }
234 currentarg++;
235 }
236 } else if ((strcmp(argv[currentarg], "-m") == 0) || (strcmp(argv[currentarg], "--months") == 0)) {
237 cfg.qmode = 2;
238 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
239 cfg.listmonths = atoi(argv[currentarg + 1]);
240 if (cfg.listmonths < 0) {
241 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
242 exit(EXIT_FAILURE);
243 }
244 currentarg++;
245 }
246 } else if ((strcmp(argv[currentarg], "-t") == 0) || (strcmp(argv[currentarg], "--top") == 0)) {
247 cfg.qmode = 3;
248 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
249 cfg.listtop = atoi(argv[currentarg + 1]);
250 if (cfg.listtop < 0) {
251 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
252 exit(EXIT_FAILURE);
253 }
254 currentarg++;
255 }
256 } else if ((strcmp(argv[currentarg], "-s") == 0) || (strcmp(argv[currentarg], "--short") == 0)) {
257 cfg.qmode = 5;
258 } else if ((strcmp(argv[currentarg], "-y") == 0) || (strcmp(argv[currentarg], "--years") == 0)) {
259 cfg.qmode = 6;
260 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
261 cfg.listyears = atoi(argv[currentarg + 1]);
262 if (cfg.listyears < 0) {
263 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
264 exit(EXIT_FAILURE);
265 }
266 currentarg++;
267 }
268 } else if ((strcmp(argv[currentarg], "-hg") == 0) || (strcmp(argv[currentarg], "--hoursgraph") == 0)) {
269 cfg.qmode = 7;
270 } else if ((strcmp(argv[currentarg], "-h") == 0) || (strcmp(argv[currentarg], "--hours") == 0)) {
271 cfg.qmode = 11;
272 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
273 cfg.listhours = atoi(argv[currentarg + 1]);
274 if (cfg.listhours < 0) {
275 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
276 exit(EXIT_FAILURE);
277 }
278 currentarg++;
279 }
280 } else if ((strcmp(argv[currentarg], "-5") == 0) || (strcmp(argv[currentarg], "--fiveminutes") == 0)) {
281 cfg.qmode = 12;
282 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
283 cfg.listfivemins = atoi(argv[currentarg + 1]);
284 if (cfg.listfivemins < 0) {
285 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
286 exit(EXIT_FAILURE);
287 }
288 currentarg++;
289 }
290 } else if (strcmp(argv[currentarg], "--oneline") == 0) {
291 cfg.qmode = 9;
292 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
293 if (argv[currentarg + 1][0] == 'b') {
294 cfg.ostyle = 4;
295 currentarg++;
296 } else {
297 if (!ishelprequest(argv[currentarg + 1]))
298 printf("Error: Invalid mode parameter \"%s\".\n", argv[currentarg + 1]);
299 printf(" Valid parameters for --oneline:\n");
300 printf(" (none) - automatically scaled units visible\n");
301 printf(" b - all values in bytes\n");
302 exit(EXIT_FAILURE);
303 }
304 }
305 } else if (strcmp(argv[currentarg], "--xml") == 0) {
306 cfg.qmode = 8;
307 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
308 p->xmlmode = argv[currentarg + 1][0];
309 if (strlen(argv[currentarg + 1]) != 1 || strchr("afhdmyt", p->xmlmode) == NULL) {
310 if (!ishelprequest(argv[currentarg + 1]))
311 printf("Error: Invalid mode parameter \"%s\".\n", argv[currentarg + 1]);
312 printf(" Valid parameters for --xml:\n");
313 printf(" a - all (default)\n");
314 printf(" f - only 5 minutes\n");
315 printf(" h - only hours\n");
316 printf(" d - only days\n");
317 printf(" m - only months\n");
318 printf(" y - only years\n");
319 printf(" t - only top\n");
320 exit(EXIT_FAILURE);
321 }
322 currentarg++;
323 }
324 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
325 cfg.listjsonxml = atoi(argv[currentarg + 1]);
326 if (cfg.listjsonxml < 0) {
327 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
328 exit(EXIT_FAILURE);
329 }
330 currentarg++;
331 }
332 } else if (strcmp(argv[currentarg], "--json") == 0) {
333 cfg.qmode = 10;
334 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
335 p->jsonmode = argv[currentarg + 1][0];
336 if (strlen(argv[currentarg + 1]) != 1 || strchr("afhdmyt", p->jsonmode) == NULL) {
337 if (!ishelprequest(argv[currentarg + 1]))
338 printf("Error: Invalid mode parameter \"%s\".\n", argv[currentarg + 1]);
339 printf(" Valid parameters for --json:\n");
340 printf(" a - all (default)\n");
341 printf(" f - only 5 minutes\n");
342 printf(" h - only hours\n");
343 printf(" d - only days\n");
344 printf(" m - only months\n");
345 printf(" y - only years\n");
346 printf(" t - only top\n");
347 exit(EXIT_FAILURE);
348 }
349 currentarg++;
350 }
351 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
352 cfg.listjsonxml = atoi(argv[currentarg + 1]);
353 if (cfg.listjsonxml < 0) {
354 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
355 exit(EXIT_FAILURE);
356 }
357 currentarg++;
358 }
359 } else if ((strcmp(argv[currentarg], "-ru") == 0) || (strcmp(argv[currentarg], "--rateunit")) == 0) {
360 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
361 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
362 if (!ishelprequest(argv[currentarg + 1]))
363 printf("Error: Invalid parameter \"%s\".\n", argv[currentarg + 1]);
364 printf(" Valid parameters for %s:\n", argv[currentarg]);
365 printf(" 0 - bytes\n");
366 printf(" 1 - bits\n");
367 exit(EXIT_FAILURE);
368 }
369 cfg.rateunit = atoi(argv[currentarg + 1]);
370 if (debug)
371 printf("Rateunit changed: %d\n", cfg.rateunit);
372 currentarg++;
373 } else {
374 cfg.rateunit = !cfg.rateunit;
375 if (debug)
376 printf("Rateunit changed: %d\n", cfg.rateunit);
377 }
378 } else if ((strcmp(argv[currentarg], "-tr") == 0) || (strcmp(argv[currentarg], "--traffic") == 0)) {
379 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
380 cfg.sampletime = atoi(argv[currentarg + 1]);
381 currentarg++;
382 }
383 p->traffic = 1;
384 p->query = 0;
385 } else if ((strcmp(argv[currentarg], "-l") == 0) || (strcmp(argv[currentarg], "--live") == 0)) {
386 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
387 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
388 if (!ishelprequest(argv[currentarg + 1]))
389 printf("Error: Invalid mode parameter \"%s\".\n", argv[currentarg + 1]);
390 printf(" Valid parameters for %s:\n", argv[currentarg]);
391 printf(" 0 - show packets per second (default)\n");
392 printf(" 1 - show transfer counters\n");
393 exit(EXIT_FAILURE);
394 }
395 p->livemode = atoi(argv[currentarg + 1]);
396 currentarg++;
397 }
398 p->livetraffic = 1;
399 p->query = 0;
400 } else if (strcmp(argv[currentarg], "--force") == 0) {
401 p->force = 1;
402 } else if (strcmp(argv[currentarg], "--showconfig") == 0) {
403 printcfgfile();
404 exit(EXIT_SUCCESS);
405 } else if (strcmp(argv[currentarg], "--remove") == 0) {
406 p->removeiface = 1;
407 p->query = 0;
408 } else if (strcmp(argv[currentarg], "--rename") == 0) {
409 if (currentarg + 1 < argc) {
410 strncpy_nt(p->newifname, argv[currentarg + 1], 32);
411 if (debug)
412 printf("Given new interface name: \"%s\"\n", p->newifname);
413 p->renameiface = 1;
414 p->query = 0;
415 currentarg++;
416 } else {
417 printf("Error: New interface name for %s missing.\n", argv[currentarg]);
418 exit(EXIT_FAILURE);
419 }
420 } else if ((strcmp(argv[currentarg], "-b") == 0) || (strcmp(argv[currentarg], "--begin") == 0)) {
421 if (currentarg + 1 < argc) {
422 if (!validatedatetime(argv[currentarg + 1])) {
423 printf("Error: Invalid date format, expected YYYY-MM-DD HH:MM or YYYY-MM-DD.\n");
424 exit(EXIT_FAILURE);
425 }
426 strncpy_nt(p->databegin, argv[currentarg + 1], 18);
427 currentarg++;
428 } else {
429 printf("Error: Date of format YYYY-MM-DD HH:MM or YYYY-MM-DD for %s missing.\n", argv[currentarg]);
430 exit(EXIT_FAILURE);
431 }
432 } else if ((strcmp(argv[currentarg], "-e") == 0) || (strcmp(argv[currentarg], "--end") == 0)) {
433 if (currentarg + 1 < argc) {
434 if (!validatedatetime(argv[currentarg + 1])) {
435 printf("Error: Invalid date format, expected YYYY-MM-DD HH:MM or YYYY-MM-DD.\n");
436 exit(EXIT_FAILURE);
437 }
438 strncpy_nt(p->dataend, argv[currentarg + 1], 18);
439 currentarg++;
440 } else {
441 printf("Error: Date of format YYYY-MM-DD HH:MM or YYYY-MM-DD for %s missing.\n", argv[currentarg]);
442 exit(EXIT_FAILURE);
443 }
444 } else if (strcmp(argv[currentarg], "--iflist") == 0) {
445 p->query = 0;
446 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
447 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
448 if (!ishelprequest(argv[currentarg + 1]))
449 printf("Error: Invalid mode parameter \"%s\".\n", argv[currentarg + 1]);
450 printf(" Valid parameters for --iflist:\n");
451 printf(" 0 - show verbose (default)\n");
452 printf(" 1 - show one interface per line\n");
453 exit(EXIT_FAILURE);
454 }
455 p->query = atoi(argv[currentarg + 1]);
456 currentarg++;
457 }
458 showiflist(p->query);
459 exit(EXIT_SUCCESS);
460 } else if (strcmp(argv[currentarg], "--dbiflist") == 0) {
461 p->query = 0;
462 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
463 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
464 if (!ishelprequest(argv[currentarg + 1]))
465 printf("Error: Invalid mode parameter \"%s\".\n", argv[currentarg + 1]);
466 printf(" Valid parameters for --dbiflist:\n");
467 printf(" 0 - show verbose (default)\n");
468 printf(" 1 - show one interface per line\n");
469 exit(EXIT_FAILURE);
470 }
471 p->query = atoi(argv[currentarg + 1]);
472 currentarg++;
473 }
474 showdbiflist(p->query);
475 exit(EXIT_SUCCESS);
476 } else if (strcmp(argv[currentarg], "--limit") == 0) {
477 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
478 p->limit = atoi(argv[currentarg + 1]);
479 if (p->limit < 0) {
480 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
481 exit(EXIT_FAILURE);
482 }
483 currentarg++;
484 } else {
485 printf("Error: Invalid or missing parameter for %s.\n", argv[currentarg]);
486 exit(EXIT_FAILURE);
487 }
488 } else if ((strcmp(argv[currentarg], "-v") == 0) || (strcmp(argv[currentarg], "--version") == 0)) {
489 printf("vnStat %s by Teemu Toivola <tst at iki dot fi>\n", getversion());
490 exit(EXIT_SUCCESS);
491 } else {
492 if (argv[currentarg][0] == '-' || strlen(argv[currentarg]) == 1) {
493 printf("Unknown parameter \"%s\". Use --help for help.\n", argv[currentarg]);
494 exit(EXIT_FAILURE);
495 } else {
496 if (strlen(argv[currentarg]) > 31) {
497 printf("Error: Interface name is limited to 31 characters.\n");
498 exit(EXIT_FAILURE);
499 }
500 strncpy_nt(p->interface, argv[currentarg], 32);
501 if (strlen(p->interface)) {
502 p->defaultiface = 0;
503 } else {
504 strncpy_nt(p->definterface, p->interface, 32);
505 }
506 if (debug)
507 printf("Used interface: \"%s\"\n", p->interface);
508 }
509 }
510 }
511
512 if (p->limit != -1) {
513 cfg.listfivemins = cfg.listhours = cfg.listdays = cfg.listmonths = cfg.listyears = cfg.listtop = cfg.listjsonxml = p->limit;
514 }
515 }
516
showstylehelp(void)517 void showstylehelp(void)
518 {
519 printf(" Valid parameters for --style.:\n");
520 printf(" 0 - a more narrow output\n");
521 printf(" 1 - enable bar column if available\n");
522 printf(" 2 - average traffic rate in summary output\n");
523 printf(" 3 - average traffic rate in all outputs if available\n");
524 printf(" 4 - disable terminal control characters in -l / --live\n");
525 printf(" and show raw values in --oneline\n");
526 }
527
handleremoveinterface(PARAMS * p)528 void handleremoveinterface(PARAMS *p)
529 {
530 if (!p->removeiface) {
531 return;
532 }
533
534 if (p->defaultiface) {
535 printf("Error: Use -i parameter to specify an interface.\n");
536 exit(EXIT_FAILURE);
537 }
538
539 if (!db_getinterfacecountbyname(p->interface)) {
540 printf("Error: Interface \"%s\" not found in database.\n", p->interface);
541 exit(EXIT_FAILURE);
542 }
543
544 if (!p->force) {
545 printf("Warning:\nThe current option would remove all data about interface \"%s\" from the database. ", p->interface);
546 printf("Add --force in order to really do that.\n");
547 exit(EXIT_FAILURE);
548 }
549
550 #ifndef CHECK_VNSTAT
551 if (!db_close() || !db_open_rw(0)) {
552 printf("Error: Handling database \"%s/%s\" failing: %s\n", cfg.dbdir, DATABASEFILE, strerror(errno));
553 exit(EXIT_FAILURE);
554 }
555 #endif
556
557 if (db_removeinterface(p->interface)) {
558 printf("Interface \"%s\" removed from database.\n", p->interface);
559 printf("The interface will no longer be monitored. Use --add if monitoring the interface is again needed.\n");
560 #ifndef CHECK_VNSTAT
561 db_close();
562 exit(EXIT_SUCCESS);
563 #endif
564 } else {
565 printf("Error: Removing interface \"%s\" from database failed.\n", p->interface);
566 exit(EXIT_FAILURE);
567 }
568 }
569
handlerenameinterface(PARAMS * p)570 void handlerenameinterface(PARAMS *p)
571 {
572 if (!p->renameiface) {
573 return;
574 }
575
576 if (p->defaultiface) {
577 printf("Error: Use -i parameter to specify an interface.\n");
578 exit(EXIT_FAILURE);
579 }
580
581 if (!strlen(p->newifname)) {
582 printf("Error: New interface name must be at least one character long.\n");
583 exit(EXIT_FAILURE);
584 }
585
586 if (!db_getinterfacecountbyname(p->interface)) {
587 printf("Error: Interface \"%s\" not found in database.\n", p->interface);
588 exit(EXIT_FAILURE);
589 }
590
591 if (db_getinterfacecountbyname(p->newifname)) {
592 printf("Error: Interface \"%s\" already exists in database.\n", p->newifname);
593 exit(EXIT_FAILURE);
594 }
595
596 if (!p->force) {
597 printf("Warning:\nThe current option would rename interface \"%s\" -> \"%s\" in the database. ", p->interface, p->newifname);
598 printf("Add --force in order to really do that.\n");
599 exit(EXIT_FAILURE);
600 }
601
602 #ifndef CHECK_VNSTAT
603 if (!db_close() || !db_open_rw(0)) {
604 printf("Error: Handling database \"%s/%s\" failing: %s\n", cfg.dbdir, DATABASEFILE, strerror(errno));
605 exit(EXIT_FAILURE);
606 }
607 #endif
608
609 if (db_renameinterface(p->interface, p->newifname)) {
610 printf("Interface \"%s\" has been renamed \"%s\".\n", p->interface, p->newifname);
611 #ifndef CHECK_VNSTAT
612 db_close();
613 exit(EXIT_SUCCESS);
614 #endif
615 } else {
616 printf("Error: Renaming interface \"%s\" -> \"%s\" failed.\n", p->interface, p->newifname);
617 exit(EXIT_FAILURE);
618 }
619 }
620
handleaddinterface(PARAMS * p)621 void handleaddinterface(PARAMS *p)
622 {
623 if (!p->addiface) {
624 return;
625 }
626
627 if (p->defaultiface) {
628 printf("Error: Use -i parameter to specify an interface.\n");
629 exit(EXIT_FAILURE);
630 }
631
632 db_errcode = 0;
633 if (db_getinterfacecountbyname(p->interface)) {
634 printf("Error: Interface \"%s\" already exists in the database.\n", p->interface);
635 exit(EXIT_FAILURE);
636 }
637 if (db_errcode) {
638 exit(EXIT_FAILURE);
639 }
640
641 if (!p->force && !getifinfo(p->interface)) {
642 getifliststring(&p->ifacelist, 1);
643 printf("Only available interfaces can be added for monitoring.\n\n");
644 printf("The following interfaces are currently available:\n %s\n", p->ifacelist);
645 free(p->ifacelist);
646 exit(EXIT_FAILURE);
647 }
648
649 if (!p->force && !spacecheck(cfg.dbdir)) {
650 printf("Error: Not enough free diskspace available.\n");
651 exit(EXIT_FAILURE);
652 }
653
654 #ifndef CHECK_VNSTAT
655 if (!db_close() || !db_open_rw(0)) {
656 printf("Error: Handling database \"%s/%s\" failing: %s\n", cfg.dbdir, DATABASEFILE, strerror(errno));
657 exit(EXIT_FAILURE);
658 }
659 #endif
660
661 printf("Adding interface \"%s\" to database for monitoring.\n", p->interface);
662 if (db_addinterface(p->interface)) {
663 if (cfg.rescanonsave) {
664 printf("vnStat daemon will automatically start monitoring \"%s\" within %d minutes if the daemon process is currently running.\n", p->interface, cfg.saveinterval);
665 } else {
666 printf("Restart vnStat daemon if it is currently running in order to start monitoring \"%s\".\n", p->interface);
667 }
668 handlesetalias(p);
669 #ifndef CHECK_VNSTAT
670 db_close();
671 exit(EXIT_SUCCESS);
672 #endif
673 } else {
674 printf("Error: Adding interface \"%s\" to database failed.\n", p->interface);
675 exit(EXIT_FAILURE);
676 }
677 }
678
handlesetalias(PARAMS * p)679 void handlesetalias(PARAMS *p)
680 {
681 if (!p->setalias) {
682 return;
683 }
684
685 if (p->defaultiface) {
686 printf("Error: Use -i parameter to specify an interface.\n");
687 exit(EXIT_FAILURE);
688 }
689
690 if (!db_getinterfacecountbyname(p->interface)) {
691 printf("Error: Interface \"%s\" not found in database.\n", p->interface);
692 exit(EXIT_FAILURE);
693 }
694
695 #ifndef CHECK_VNSTAT
696 if (!db_close() || !db_open_rw(0)) {
697 printf("Error: Handling database \"%s/%s\" failing: %s\n", cfg.dbdir, DATABASEFILE, strerror(errno));
698 exit(EXIT_FAILURE);
699 }
700 #endif
701
702 if (db_setalias(p->interface, p->alias)) {
703 printf("Alias of interface \"%s\" set to \"%s\".\n", p->interface, p->alias);
704 #ifndef CHECK_VNSTAT
705 db_close();
706 exit(EXIT_SUCCESS);
707 #endif
708 } else {
709 printf("Error: Setting interface \"%s\" alias failed.\n", p->interface);
710 exit(EXIT_FAILURE);
711 }
712 }
713
handleshowdata(PARAMS * p)714 void handleshowdata(PARAMS *p)
715 {
716 int ifcount = 0;
717 iflist *dbifl = NULL, *dbifl_i = NULL;
718
719 if (!p->query) {
720 return;
721 }
722
723 /* show only specified file */
724 if (!p->defaultiface) {
725 showoneinterface(p);
726 return;
727 }
728
729 /* show all interfaces if -i isn't specified */
730 if (p->dbifcount == 0) {
731 p->query = 0;
732 } else if ((cfg.qmode == 0 || cfg.qmode == 8 || cfg.qmode == 10) && (p->dbifcount > 1)) {
733
734 if (cfg.qmode == 0) {
735 if (cfg.ostyle != 0) {
736 printf("\n rx / tx / total / estimated\n");
737 } else {
738 printf("\n rx / tx / total\n");
739 }
740 } else if (cfg.qmode == 8) {
741 xmlheader();
742 } else if (cfg.qmode == 10) {
743 jsonheader();
744 }
745
746 if (db_getiflist(&dbifl) <= 0) {
747 return;
748 }
749
750 dbifl_i = dbifl;
751
752 while (dbifl_i != NULL) {
753 strncpy_nt(p->interface, dbifl_i->interface, 32);
754 if (debug)
755 printf("\nProcessing interface \"%s\"...\n", p->interface);
756 if (cfg.qmode == 0) {
757 showdb(p->interface, 5, "", "");
758 } else if (cfg.qmode == 8) {
759 showxml(p->interface, p->xmlmode, p->databegin, p->dataend);
760 } else if (cfg.qmode == 10) {
761 showjson(p->interface, ifcount, p->jsonmode, p->databegin, p->dataend);
762 }
763 ifcount++;
764 dbifl_i = dbifl_i->next;
765 }
766 iflistfree(&dbifl);
767
768 if (cfg.qmode == 8) {
769 xmlfooter();
770 } else if (cfg.qmode == 10) {
771 jsonfooter();
772 }
773
774 /* show in qmode if there's only one interface or qmode!=0 */
775 } else {
776 showoneinterface(p);
777 }
778 }
779
showoneinterface(PARAMS * p)780 void showoneinterface(PARAMS *p)
781 {
782 if (!db_getinterfacecountbyname(p->interface)) {
783 if (strchr(p->interface, '+') == NULL) {
784 printf("Error: Interface \"%s\" not found in database.\n", p->interface);
785 } else {
786 printf("Error: Not all requested interfaces found in database or given interfaces aren't unique.\n");
787 }
788 exit(EXIT_FAILURE);
789 }
790
791 if (cfg.qmode == 5) {
792 if (cfg.ostyle != 0) {
793 printf("\n rx / tx / total / estimated\n");
794 } else {
795 printf("\n rx / tx / total\n");
796 }
797 }
798 if (cfg.qmode != 8 && cfg.qmode != 10) {
799 showdb(p->interface, cfg.qmode, p->databegin, p->dataend);
800 } else if (cfg.qmode == 8) {
801 xmlheader();
802 showxml(p->interface, p->xmlmode, p->databegin, p->dataend);
803 xmlfooter();
804 } else if (cfg.qmode == 10) {
805 jsonheader();
806 showjson(p->interface, 0, p->jsonmode, p->databegin, p->dataend);
807 jsonfooter();
808 }
809 }
810
handletrafficmeters(PARAMS * p)811 void handletrafficmeters(PARAMS *p)
812 {
813 int i;
814
815 if (!p->traffic && !p->livetraffic) {
816 return;
817 }
818
819 if (strchr(p->interface, '+') != NULL) {
820 printf("This feature doesn't support interface merges (\"%s\"), ", p->interface);
821 for (i = 0; i < (int)strlen(p->interface); i++) {
822 if (p->interface[i] == '+') {
823 p->interface[i] = '\0';
824 break;
825 }
826 }
827 p->defaultiface = 0;
828 printf("using \"%s\" instead.\n", p->interface);
829 }
830
831 if (!isifavailable(p->interface)) {
832 getifliststring(&p->ifacelist, 0);
833 if (p->defaultiface) {
834 printf("Error: Configured default interface \"%s\" isn't available.\n\n", p->interface);
835 if (strlen(cfg.cfgfile)) {
836 printf("Update \"Interface\" keyword value in configuration file \"%s\" to change ", cfg.cfgfile);
837 printf("the default interface or give an alternative interface using the -i parameter.\n\n");
838 } else {
839 printf("An alternative interface can be given using the -i parameter.\n\n");
840 }
841 printf("The following interfaces are currently available:\n %s\n", p->ifacelist);
842
843 } else {
844 printf("Error: Unable to get interface \"%s\" statistics.\n\n", p->interface);
845 printf("The following interfaces are currently available:\n %s\n", p->ifacelist);
846 }
847 free(p->ifacelist);
848 exit(EXIT_FAILURE);
849 }
850
851 /* calculate traffic */
852 if (p->traffic) {
853 trafficmeter(p->interface, (unsigned int)cfg.sampletime);
854 }
855
856 /* live traffic */
857 if (p->livetraffic) {
858 livetrafficmeter(p->interface, p->livemode);
859 }
860 }
861
handleifselection(PARAMS * p)862 void handleifselection(PARAMS *p)
863 {
864 int ifcount, dbifcount = 0, iffound = 0, dbopened = 0;
865 iflist *ifl = NULL;
866 iflist *dbifl = NULL, *dbifl_iterator = NULL;
867
868 if (!p->defaultiface) {
869 return;
870 }
871
872 if (strlen(p->definterface)) {
873 strncpy_nt(p->interface, p->definterface, 32);
874 return;
875 }
876
877 if (p->traffic || p->livetraffic) {
878 ifcount = getiflist(&ifl, 0, 1);
879
880 /* try to open database for extra information */
881 if (db == NULL) {
882 if (!db_open_ro()) {
883 db = NULL;
884 } else {
885 dbopened = 1;
886 }
887 }
888
889 if (db != NULL) {
890 dbifcount = db_getiflist_sorted(&dbifl, 1);
891 if (dbopened) {
892 db_close();
893 }
894 }
895
896 if (dbifcount > 0 && ifcount > 0) {
897 dbifl_iterator = dbifl;
898 while (dbifl_iterator != NULL) {
899 if (iflistsearch(&ifl, dbifl_iterator->interface)) {
900 strncpy_nt(p->interface, dbifl_iterator->interface, 32);
901 iffound = 1;
902 if (debug)
903 printf("Automatically selected interface with db: \"%s\"\n", p->interface);
904 break;
905 }
906 dbifl_iterator = dbifl_iterator->next;
907 }
908 }
909
910 if (!iffound) {
911 if (ifcount > 0) {
912 strncpy_nt(p->interface, ifl->interface, 32);
913 if (debug)
914 printf("Automatically selected interface without db: \"%s\"\n", p->interface);
915 } else {
916 printf("Error: Unable to find any suitable interface.\n");
917 iflistfree(&ifl);
918 iflistfree(&dbifl);
919 exit(EXIT_FAILURE);
920 }
921 }
922
923 iflistfree(&ifl);
924 } else if (p->query) {
925 if (db_getiflist_sorted(&dbifl, 1) <= 0) {
926 printf("Error: Unable to discover suitable interface from database.\n");
927 iflistfree(&dbifl);
928 exit(EXIT_FAILURE);
929 }
930 strncpy_nt(p->interface, dbifl->interface, 32);
931 if (debug)
932 printf("Automatically selected interface from db: \"%s\"\n", p->interface);
933 }
934
935 iflistfree(&dbifl);
936 }
937
showiflist(const int parseable)938 void showiflist(const int parseable)
939 {
940 char *ifacelist = NULL;
941 iflist *ifl = NULL, *ifl_iterator = NULL;
942
943 if (!parseable) {
944 if (!getifliststring(&ifacelist, 1)) {
945 exit(EXIT_FAILURE);
946 }
947 if (strlen(ifacelist)) {
948 printf("Available interfaces: %s\n", ifacelist);
949 } else {
950 printf("No usable interfaces found.\n");
951 }
952 free(ifacelist);
953 } else {
954 if (!getiflist(&ifl, 0, 1)) {
955 exit(EXIT_FAILURE);
956 }
957 ifl_iterator = ifl;
958 while (ifl_iterator != NULL) {
959 printf("%s\n", ifl_iterator->interface);
960 ifl_iterator = ifl_iterator->next;
961 }
962 iflistfree(&ifl);
963 }
964 }
965
showdbiflist(const int parseable)966 void showdbiflist(const int parseable)
967 {
968 int dbifcount;
969 iflist *dbifl = NULL, *dbifl_i = NULL;
970
971 if (db == NULL && !db_open_ro()) {
972 printf("Error: Failed to open database \"%s/%s\" in read-only mode.\n", cfg.dbdir, DATABASEFILE);
973 exit(EXIT_FAILURE);
974 }
975
976 dbifcount = db_getiflist(&dbifl);
977 if (dbifcount < 0) {
978 printf("Error: Failed to get interface list from database \"%s/%s\".\n", cfg.dbdir, DATABASEFILE);
979 exit(EXIT_FAILURE);
980 }
981
982 if (dbifcount == 0 && !parseable) {
983 printf("Database is empty.");
984 } else {
985 dbifl_i = dbifl;
986
987 if (!parseable) {
988 printf("Interfaces in database:");
989 while (dbifl_i != NULL) {
990 printf(" %s", dbifl_i->interface);
991 dbifl_i = dbifl_i->next;
992 }
993 printf("\n");
994 } else {
995 while (dbifl_i != NULL) {
996 printf("%s\n", dbifl_i->interface);
997 dbifl_i = dbifl_i->next;
998 }
999 }
1000 }
1001
1002 iflistfree(&dbifl);
1003 db_close();
1004 }
1005