capt_get_packet(): check for key press only every 20ms
[iptraf-ng.git] / src / fltedit.c
blob300487f1eedb693e40a8f021dbb31a1de074f2de
1 /* For terms of usage/redistribution/modification see the LICENSE file */
2 /* For authors and contributors see the AUTHORS file */
4 /***
6 fltedit.c - the filter editing Facility
8 ***/
10 #include "iptraf-ng-compat.h"
12 #include "tui/labels.h"
13 #include "tui/menurt.h"
14 #include "tui/msgboxes.h"
15 #include "tui/winops.h"
17 #include "fltdefs.h"
18 #include "fltmgr.h"
19 #include "ipfilter.h"
20 #include "dirs.h"
21 #include "getpath.h"
22 #include "attrs.h"
23 #include "deskman.h"
24 #include "error.h"
25 #include "cidr.h"
27 void init_filter_table(struct filterlist *fl)
29 fl->head = fl->tail = NULL;
33 * Loads the filter from the filter file
36 int loadfilter(char *filename, struct filterlist *fl, int resolve)
38 struct filterent *fe;
39 int pfd;
40 unsigned int idx = 0;
41 int br;
42 int resolv_err = 0;
44 init_filter_table(fl);
46 pfd = open(filename, O_RDONLY);
48 if (pfd < 0) {
49 write_error("Error opening IP filter data file");
50 fl->head = NULL;
51 return 1;
53 do {
54 fe = xmalloc(sizeof(struct filterent));
55 br = read(pfd, &(fe->hp), sizeof(struct hostparams));
57 if (br > 0) {
58 fe->index = idx;
59 if (resolve) {
60 fe->saddr =
61 nametoaddr(fe->hp.s_fqdn, &resolv_err);
62 fe->daddr =
63 nametoaddr(fe->hp.d_fqdn, &resolv_err);
65 if (resolv_err) {
66 free(fe);
67 continue;
70 fe->smask = inet_addr(fe->hp.s_mask);
71 fe->dmask = inet_addr(fe->hp.d_mask);
73 if (fl->head == NULL) {
74 fl->head = fe;
75 fe->prev_entry = NULL;
76 } else {
77 fl->tail->next_entry = fe;
78 fe->prev_entry = fl->tail;
80 fe->next_entry = NULL;
81 fl->tail = fe;
82 idx++;
83 } else {
84 free(fe);
86 } while (br > 0);
88 if (br == 0)
89 close(pfd);
91 return 0;
94 void savefilter(char *filename, struct filterlist *fl)
96 struct filterent *fe = fl->head;
97 int pfd;
98 int bw;
100 pfd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
102 while (fe != NULL) {
103 bw = write(pfd, &(fe->hp), sizeof(struct hostparams));
105 if (bw < 0) {
106 tui_error(ANYKEY_MSG, "Unable to save filter changes");
107 return;
109 fe = fe->next_entry;
112 close(pfd);
115 void print_hostparam_line(struct filterent *fe, int idx, WINDOW * win, int attr)
117 struct in_addr binmask;
119 wattrset(win, attr);
121 scrollok(win, 0);
122 mvwprintw(win, idx, 0, "%78c", ' ');
124 mvwaddnstr(win, idx, 1, fe->hp.s_fqdn, 20);
125 if (inet_aton(fe->hp.s_mask, &binmask) == 0)
126 inet_aton("255.255.255.255", &binmask);
128 wprintw(win, "/%u", cidr_get_maskbits(binmask.s_addr));
129 if (fe->hp.sport2 == 0)
130 wprintw(win, ":%u", fe->hp.sport1);
131 else
132 wprintw(win, ":%u-%u", fe->hp.sport1, fe->hp.sport2);
134 wmove(win, idx, 34);
135 if (fe->hp.match_opposite != 'Y')
136 wprintw(win, "-->");
137 else
138 wprintw(win, "<->");
140 mvwaddnstr(win, idx, 38, fe->hp.d_fqdn, 15);
142 if (inet_aton(fe->hp.d_mask, &binmask) == 0)
143 inet_aton("255.255.255.255", &binmask);
145 wprintw(win, "/%u", cidr_get_maskbits(binmask.s_addr));
147 if (fe->hp.dport2 == 0)
148 wprintw(win, ":%u", fe->hp.dport1);
149 else
150 wprintw(win, ":%u-%u", fe->hp.dport1, fe->hp.dport2);
152 mvwprintw(win, idx, 76, "%c", toupper(fe->hp.reverse));
153 wmove(win, idx, 0);
156 void update_hp_screen(struct filterent *firstvisible, WINDOW * win)
158 struct filterent *ftmp = firstvisible;
159 int i;
161 wattrset(win, STDATTR);
162 if (firstvisible == NULL) {
163 mvwprintw(win, 0, 0, "%78c", ' ');
164 wmove(win, 0, 0);
165 return;
168 scrollok(win, 0);
169 for (i = 0; i <= 12; i++) {
170 if (ftmp != NULL) {
171 print_hostparam_line(ftmp, i, win, STDATTR);
172 ftmp = ftmp->next_entry;
173 } else {
174 mvwprintw(win, i, 0, "%78c", ' ');
175 wmove(win, i, 0);
178 scrollok(win, 1);
181 void modify_host_parameters(struct filterlist *fl)
183 WINDOW *bwin;
184 PANEL *bpanel;
185 WINDOW *win;
186 PANEL *panel;
187 struct filterent *fe;
188 struct filterent *ftemp;
190 struct filterent *firstvisible = NULL;
192 unsigned int idx = 0;
193 int endloop_local = 0;
194 int ch;
195 int gh_aborted = 0;
197 char s_portstr1[8];
198 char d_portstr1[8];
199 char s_portstr2[8];
200 char d_portstr2[8];
202 char inexstr[2];
203 char matchop[2];
205 bwin = newwin(15, 80, (LINES - 15) / 2, (COLS - 80) / 2);
207 bpanel = new_panel(bwin);
208 win = newwin(13, 78, (LINES - 13) / 2, (COLS - 78) / 2);
209 panel = new_panel(win);
211 wattrset(bwin, BOXATTR);
212 tx_box(bwin, ACS_VLINE, ACS_HLINE);
214 mvwprintw(bwin, 0, 2, " Source ");
215 mvwprintw(bwin, 0, 38, " Destination ");
216 mvwprintw(bwin, 0, 74, " I/E ");
218 mvwprintw(bwin, 14, 1, " Filter Data ");
219 tx_stdwinset(win);
220 scrollok(win, 0);
221 wattrset(win, STDATTR);
222 tx_colorwin(win);
224 move(LINES - 1, 1);
225 tx_printkeyhelp("Up/Down", "-move ptr ", stdscr, HIGHATTR,
226 STATUSBARATTR);
227 tx_printkeyhelp("I", "-insert ", stdscr, HIGHATTR, STATUSBARATTR);
228 tx_printkeyhelp("A", "-add to list ", stdscr, HIGHATTR, STATUSBARATTR);
229 tx_printkeyhelp("D", "-delete ", stdscr, HIGHATTR, STATUSBARATTR);
230 tx_printkeyhelp("Enter", "-edit ", stdscr, HIGHATTR, STATUSBARATTR);
231 tx_printkeyhelp("X/Ctrl+X", "-exit", stdscr, HIGHATTR, STATUSBARATTR);
233 update_panels();
234 doupdate();
236 firstvisible = fl->head;
238 update_hp_screen(firstvisible, win);
240 idx = 0;
241 fe = firstvisible;
243 update_panels();
244 doupdate();
246 do {
247 if (fe != NULL) {
248 print_hostparam_line(fe, idx, win, BARSTDATTR);
251 ch = wgetch(win);
253 if (fe != NULL)
254 print_hostparam_line(fe, idx, win, STDATTR);
256 switch (ch) {
257 case KEY_UP:
258 if (fl->head != NULL) {
259 if (fe->prev_entry != NULL) {
260 if (idx > 0)
261 idx--;
262 else {
263 scrollok(win, 1);
264 wscrl(win, -1);
265 firstvisible =
266 firstvisible->prev_entry;
268 fe = fe->prev_entry;
271 break;
272 case KEY_DOWN:
273 if (fl->head != NULL) {
274 if (fe->next_entry != NULL) {
275 if (idx < 12)
276 idx++;
277 else {
278 scrollok(win, 1);
279 wscrl(win, 1);
280 firstvisible =
281 firstvisible->next_entry;
283 fe = fe->next_entry;
286 break;
287 case 'i':
288 case 'I':
289 case KEY_IC:
290 ftemp = xmallocz(sizeof(struct filterent));
292 gethostparams(&(ftemp->hp), "", "", "", "", "", "", "",
293 "", "I", "N", &gh_aborted);
295 if (gh_aborted) {
296 free(ftemp);
297 continue;
300 if (fl->head == NULL) {
301 ftemp->next_entry = ftemp->prev_entry = NULL;
302 fl->head = fl->tail = ftemp;
303 firstvisible = fl->head;
304 idx = 0;
305 } else {
306 ftemp->next_entry = fe;
307 ftemp->prev_entry = fe->prev_entry;
310 * Point firstvisible at new entry if we inserted at the
311 * top of the list.
314 if (ftemp->prev_entry == NULL) {
315 fl->head = ftemp;
316 firstvisible = ftemp;
317 } else
318 fe->prev_entry->next_entry = ftemp;
320 fe->prev_entry = ftemp;
323 if (ftemp->next_entry == NULL)
324 fl->tail = ftemp;
326 fe = ftemp;
327 update_hp_screen(firstvisible, win);
328 break;
329 case 'a':
330 case 'A':
331 case 1:
332 ftemp = xmallocz(sizeof(struct filterent));
334 gethostparams(&(ftemp->hp), "", "", "", "", "", "", "",
335 "", "I", "N", &gh_aborted);
337 if (gh_aborted) {
338 free(ftemp);
339 continue;
343 * Add new node to the end of the list (or to the head if the
344 * list is empty.
346 if (fl->tail != NULL) {
347 fl->tail->next_entry = ftemp;
348 ftemp->prev_entry = fl->tail;
349 } else {
350 fl->head = ftemp;
351 fl->tail = ftemp;
352 ftemp->prev_entry = ftemp->next_entry = NULL;
353 firstvisible = fl->head;
354 fe = ftemp;
355 idx = 0;
358 ftemp->next_entry = NULL;
359 fl->tail = ftemp;
360 update_hp_screen(firstvisible, win);
361 break;
362 case 'd':
363 case 'D':
364 case KEY_DC:
365 if (fl->head != NULL) {
367 * Move firstvisible down if it's pointing to the target
368 * entry.
371 if (firstvisible == fe)
372 firstvisible = fe->next_entry;
375 * Detach target node from list.
377 if (fe->next_entry != NULL)
378 fe->next_entry->prev_entry =
379 fe->prev_entry;
380 else
381 fl->tail = fe->prev_entry;
383 if (fe->prev_entry != NULL)
384 fe->prev_entry->next_entry =
385 fe->next_entry;
386 else
387 fl->head = fe->next_entry;
390 * Move pointer up if we're deleting the last entry.
391 * The list tail pointer has since been moved to the
392 * previous entry.
394 if (fe->prev_entry == fl->tail) {
395 ftemp = fe->prev_entry;
398 * Move screen pointer up. Really adjust the index if
399 * the pointer is anywhere below the top of the screen.
401 if (idx > 0)
402 idx--;
403 else {
405 * Otherwise scroll the list down, and adjust the
406 * firstvisible pointer to point to the entry
407 * previous to the target.
409 if (ftemp != NULL) {
410 firstvisible = ftemp;
413 } else
415 * If we reach this point, we're deleting from before
416 * the tail of the list. In that case, we point the
417 * screen pointer at the entry following the target.
419 ftemp = fe->next_entry;
421 free(fe);
422 fe = ftemp;
423 update_hp_screen(firstvisible, win);
425 break;
426 case 13:
427 if (fe != NULL) {
428 sprintf(s_portstr1, "%u", fe->hp.sport1);
429 sprintf(s_portstr2, "%u", fe->hp.sport2);
430 sprintf(d_portstr1, "%u", fe->hp.dport1);
431 sprintf(d_portstr2, "%u", fe->hp.dport2);
432 inexstr[0] = toupper(fe->hp.reverse);
433 inexstr[1] = '\0';
434 matchop[0] = toupper(fe->hp.match_opposite);
435 matchop[1] = '\0';
437 gethostparams(&(fe->hp), fe->hp.s_fqdn,
438 fe->hp.s_mask, s_portstr1,
439 s_portstr2, fe->hp.d_fqdn,
440 fe->hp.d_mask, d_portstr1,
441 d_portstr2, inexstr, matchop,
442 &gh_aborted);
444 update_hp_screen(firstvisible, win);
447 break;
448 case 'x':
449 case 'X':
450 case 'q':
451 case 'Q':
452 case 27:
453 case 24:
454 endloop_local = 1;
455 break;
456 case 'l':
457 case 'L':
458 tx_refresh_screen();
459 break;
461 update_panels();
462 doupdate();
463 } while (!endloop_local);
465 del_panel(panel);
466 delwin(win);
467 del_panel(bpanel);
468 delwin(bwin);
469 update_panels();
470 doupdate();
473 /* remove a currently applied filter from memory */
474 void destroyfilter(struct filterlist *fl)
476 struct filterent *fe = fl->head;
478 while (fe != NULL) {
479 struct filterent *cfe = fe->next_entry;
481 free(fe);
482 fe = cfe;
485 fl->head = NULL;
486 fl->tail = NULL;
490 void definefilter(int *aborted)
492 struct filterfileent ffile;
493 char fntemp[14];
494 struct filterlist fl;
496 int pfd;
497 int bw;
499 get_filter_description(ffile.desc, aborted, "");
501 if (*aborted)
502 return;
504 genname(time(NULL), fntemp);
506 pfd =
507 open(get_path(T_WORKDIR, fntemp), O_CREAT | O_WRONLY | O_TRUNC,
508 S_IRUSR | S_IWUSR);
509 if (pfd < 0) {
510 tui_error(ANYKEY_MSG, "Cannot create filter data file");
511 *aborted = 1;
512 return;
515 close(pfd);
517 pfd =
518 open(OTHIPFLNAME, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR);
520 if (pfd < 0) {
521 listfileerr(1);
522 return;
524 strcpy(ffile.filename, fntemp);
525 bw = write(pfd, &ffile, sizeof(struct filterfileent));
526 if (bw < 0)
527 listfileerr(2);
529 close(pfd);
531 init_filter_table(&fl);
532 modify_host_parameters(&fl);
533 savefilter(get_path(T_WORKDIR, fntemp), &fl);
534 destroyfilter(&fl);
538 * Edit an existing filter
540 void editfilter(int *aborted)
542 char filename[FLT_FILENAME_MAX];
543 struct filterlist fl;
544 struct ffnode *flist;
545 struct ffnode *ffile;
546 struct filterfileent *ffe;
548 if (loadfilterlist(&flist) == 1) {
549 listfileerr(1);
550 destroyfilterlist(flist);
551 return;
553 pickafilter(flist, &ffile, aborted);
555 if ((*aborted)) {
556 destroyfilterlist(flist);
557 return;
559 ffe = &(ffile->ffe);
561 get_filter_description(ffe->desc, aborted, ffe->desc);
563 if (*aborted) {
564 destroyfilterlist(flist);
565 return;
567 strncpy(filename, get_path(T_WORKDIR, ffe->filename),
568 FLT_FILENAME_MAX - 1);
570 if (loadfilter(filename, &fl, FLT_DONTRESOLVE))
571 return;
573 modify_host_parameters(&fl);
575 save_filterlist(flist); /* This also destroys it */
576 savefilter(filename, &fl);
577 destroyfilter(&fl);
581 * Delete a filter record from the disk
584 void delfilter(int *aborted)
586 struct ffnode *fltfile;
587 struct ffnode *fltlist;
589 if (loadfilterlist(&fltlist) == 1) {
590 *aborted = 1;
591 listfileerr(1);
592 destroyfilterlist(fltlist);
593 return;
595 pickafilter(fltlist, &fltfile, aborted);
597 if (*aborted)
598 return;
600 unlink(get_path(T_WORKDIR, fltfile->ffe.filename));
602 if (fltfile->prev_entry == NULL) {
603 fltlist = fltlist->next_entry;
604 if (fltlist != NULL)
605 fltlist->prev_entry = NULL;
606 } else {
607 fltfile->prev_entry->next_entry = fltfile->next_entry;
609 if (fltfile->next_entry != NULL)
610 fltfile->next_entry->prev_entry = fltfile->prev_entry;
613 free(fltfile);
615 save_filterlist(fltlist);
616 *aborted = 0;