1 /* For terms of usage/redistribution/modification see the LICENSE file */
2 /* For authors and contributors see the AUTHORS file */
6 itrafmon.c - the IP traffic monitor module
10 #include "iptraf-ng-compat.h"
12 #include "tui/labels.h"
13 #include "tui/winops.h"
39 static void rotate_ipmon_log(int s __unused
)
42 strcpy(target_logname
, current_logfile
);
43 signal(SIGUSR1
, rotate_ipmon_log
);
46 /* Hot key indicators for the bottom line */
48 static void ipmonhelp(void)
51 tx_printkeyhelp("Up/Dn/PgUp/PgDn", "-scroll ", stdscr
, HIGHATTR
,
54 tx_printkeyhelp("W", "-chg actv win ", stdscr
, HIGHATTR
,
56 tx_printkeyhelp("S", "-sort TCP ", stdscr
, HIGHATTR
, STATUSBARATTR
);
60 static void uniq_help(int what
)
64 tx_printkeyhelp("M", "-more TCP info ", stdscr
, HIGHATTR
,
67 tx_printkeyhelp("Lft/Rt", "-vtcl scrl ", stdscr
, HIGHATTR
,
71 static void markactive(int curwin
, WINDOW
* tw
, WINDOW
* ow
)
75 int x1 __unused
, y1
, x2 __unused
, y2
;
85 getmaxyx(win1
, y1
, x1
);
86 getmaxyx(win2
, y2
, x2
);
88 wmove(win1
, --y1
, COLS
- 10);
89 wattrset(win1
, ACTIVEATTR
);
90 wprintw(win1
, " Active ");
91 wattrset(win1
, BOXATTR
);
92 wmove(win2
, --y2
, COLS
- 10);
93 whline(win2
, ACS_HLINE
, 8);
96 static void update_flowrates(struct tcptable
*table
, unsigned long msecs
)
98 struct tcptableent
*entry
;
99 for (entry
= table
->head
; entry
!= NULL
; entry
= entry
->next_entry
) {
100 rate_add_rate(&entry
->rate
, entry
->spanbr
, msecs
);
105 static void print_flowrate(struct tcptable
*table
)
107 if (table
->barptr
== NULL
) {
108 wattrset(table
->statwin
, IPSTATATTR
);
109 mvwprintw(table
->statwin
, 0, COLS
* 47 / 80,
112 wattrset(table
->statwin
, IPSTATLABELATTR
);
113 mvwprintw(table
->statwin
, 0, COLS
* 47 / 80,
117 rate_print(rate_get_average(&table
->barptr
->rate
), buf
, sizeof(buf
));
118 wattrset(table
->statwin
, IPSTATATTR
);
119 mvwprintw(table
->statwin
, 0, COLS
* 52 / 80 + 13, "%s", buf
);
124 * Scrolling and paging routines for the upper (TCP) window
127 static void scrollupperwin(struct tcptable
*table
, int direction
)
129 wattrset(table
->tcpscreen
, STDATTR
);
130 if (direction
== SCROLLUP
) {
131 if (table
->lastvisible
!= table
->tail
) {
132 table
->firstvisible
= table
->firstvisible
->next_entry
;
133 table
->lastvisible
= table
->lastvisible
->next_entry
;
135 wscrl(table
->tcpscreen
, 1);
136 scrollok(table
->tcpscreen
, 0);
137 wmove(table
->tcpscreen
, table
->imaxy
- 1, 0);
138 wprintw(table
->tcpscreen
, "%*c", COLS
- 2, ' ');
139 scrollok(table
->tcpscreen
, 1);
141 printentry(table
, table
->lastvisible
);
144 if (table
->firstvisible
!= table
->head
) {
145 table
->firstvisible
= table
->firstvisible
->prev_entry
;
146 table
->lastvisible
= table
->lastvisible
->prev_entry
;
148 wscrl(table
->tcpscreen
, -1);
149 mvwprintw(table
->tcpscreen
, 0, 0, "%*c", COLS
- 2, ' ');
151 printentry(table
, table
->firstvisible
);
156 static void move_tcp_bar_one(struct tcptable
*table
, int direction
)
160 if (table
->barptr
->next_entry
== NULL
)
163 if (table
->barptr
== table
->lastvisible
)
164 scrollupperwin(table
, SCROLLUP
);
166 table
->barptr
= table
->barptr
->next_entry
;
167 printentry(table
, table
->barptr
->prev_entry
); /* hide bar */
168 printentry(table
, table
->barptr
); /* show bar */
172 if (table
->barptr
->prev_entry
== NULL
)
175 if (table
->barptr
== table
->firstvisible
)
176 scrollupperwin(table
, SCROLLDOWN
);
178 table
->barptr
= table
->barptr
->prev_entry
;
179 printentry(table
, table
->barptr
->next_entry
); /* hide bar */
180 printentry(table
, table
->barptr
); /* show bar */
186 static void move_tcp_bar_many(struct tcptable
*table
, int direction
, int lines
)
190 while (lines
&& (table
->lastvisible
!= table
->tail
)) {
191 table
->firstvisible
= table
->firstvisible
->next_entry
;
192 table
->lastvisible
= table
->lastvisible
->next_entry
;
196 table
->barptr
= table
->firstvisible
;
198 table
->barptr
= table
->lastvisible
;
201 while (lines
&& (table
->firstvisible
!= table
->head
)) {
202 table
->firstvisible
= table
->firstvisible
->prev_entry
;
203 table
->lastvisible
= table
->lastvisible
->prev_entry
;
206 table
->barptr
= table
->firstvisible
;
209 refreshtcpwin(table
);
212 static void move_tcp_bar(struct tcptable
*table
, int direction
, int lines
)
214 if (table
->barptr
== NULL
)
220 move_tcp_bar_one(table
, direction
);
222 move_tcp_bar_many(table
, direction
, lines
);
224 print_flowrate(table
);
228 * Scrolling and paging routines for the lower (non-TCP) window.
231 static void scroll_othp_one(struct othptable
*table
, int direction
)
235 if (table
->lastvisible
!= table
->tail
) {
236 table
->firstvisible
= table
->firstvisible
->next_entry
;
237 table
->lastvisible
= table
->lastvisible
->next_entry
;
239 wscrl(table
->othpwin
, 1);
240 printothpentry(table
, table
->lastvisible
,
241 table
->oimaxy
- 1, 0, NULL
);
243 if (table
->htstat
== HIND
) { /* Head indicator on? */
244 wmove(table
->borderwin
, table
->obmaxy
- 1, 1);
245 whline(table
->borderwin
, ACS_HLINE
, 8);
246 table
->htstat
= NOHTIND
;
251 if (table
->firstvisible
!= table
->head
) {
252 table
->firstvisible
= table
->firstvisible
->prev_entry
;
253 table
->lastvisible
= table
->lastvisible
->prev_entry
;
255 wscrl(table
->othpwin
, -1);
256 printothpentry(table
, table
->firstvisible
, 0, 0, NULL
);
258 if (table
->htstat
== TIND
) { /* Tail indicator on? */
259 wmove(table
->borderwin
, table
->obmaxy
- 1, 1);
260 whline(table
->borderwin
, ACS_HLINE
, 8);
261 table
->htstat
= NOHTIND
;
268 static void scroll_othp_many(struct othptable
*table
, int direction
, int lines
)
272 while (lines
-- && (table
->lastvisible
!= table
->tail
)) {
273 table
->firstvisible
= table
->firstvisible
->next_entry
;
274 table
->lastvisible
= table
->lastvisible
->next_entry
;
276 if (table
->htstat
== HIND
) { /* Head indicator on? */
277 wmove(table
->borderwin
, table
->obmaxy
- 1, 1);
278 whline(table
->borderwin
, ACS_HLINE
, 8);
279 table
->htstat
= NOHTIND
;
283 while (lines
-- && (table
->firstvisible
!= table
->head
)) {
284 table
->firstvisible
= table
->firstvisible
->prev_entry
;
285 table
->lastvisible
= table
->lastvisible
->prev_entry
;
287 if (table
->htstat
== TIND
) { /* Tail indicator on? */
288 wmove(table
->borderwin
, table
->obmaxy
- 1, 1);
289 whline(table
->borderwin
, ACS_HLINE
, 8);
290 table
->htstat
= NOHTIND
;
294 refresh_othwindow(table
);
297 static void scroll_othp(struct othptable
*table
, int direction
, int lines
)
299 if (table
->head
== NULL
)
303 if (lines
< getmaxy(table
->othpwin
))
305 scroll_othp_one(table
, direction
);
307 scroll_othp_many(table
, direction
, lines
);
311 * Pop up sorting key window
314 static void show_tcpsort_win(WINDOW
** win
, PANEL
** panel
)
316 *win
= newwin(9, 35, (LINES
- 8) / 2, COLS
- 40);
317 *panel
= new_panel(*win
);
319 wattrset(*win
, DLGBOXATTR
);
321 tx_box(*win
, ACS_VLINE
, ACS_HLINE
);
322 wattrset(*win
, DLGTEXTATTR
);
323 mvwprintw(*win
, 2, 2, "Select sort criterion");
325 tx_printkeyhelp("P", " - sort by packet count", *win
, DLGHIGHATTR
,
328 tx_printkeyhelp("B", " - sort by byte count", *win
, DLGHIGHATTR
,
331 tx_printkeyhelp("Any other key", " - cancel sort", *win
, DLGHIGHATTR
,
338 * Routine to swap two TCP entries. p1 and p2 are pointers to TCP entries,
339 * but p1 must be ahead of p2. It's a linked list thing.
341 static void swap_tcp_entries(struct tcptable
*table
, struct tcptableent
*p1
,
342 struct tcptableent
*p2
)
344 struct tcptableent
*p2nextsaved
;
345 struct tcptableent
*p1prevsaved
;
352 p1
->index
= p2
->index
;
355 p1
->next_entry
->index
= p1
->index
+ 1;
356 p2
->next_entry
->index
= p2
->index
+ 1;
358 if (p1
->prev_entry
!= NULL
)
359 p1
->prev_entry
->next_entry
= p2
;
363 if (p2
->next_entry
->next_entry
!= NULL
)
364 p2
->next_entry
->next_entry
->prev_entry
= p1
->next_entry
;
366 table
->tail
= p1
->next_entry
;
368 p2nextsaved
= p2
->next_entry
->next_entry
;
369 p1prevsaved
= p1
->prev_entry
;
371 if (p1
->next_entry
->next_entry
== p2
) { /* swapping adjacent entries */
372 p2
->next_entry
->next_entry
= p1
;
373 p1
->prev_entry
= p2
->next_entry
;
375 p2
->next_entry
->next_entry
= p1
->next_entry
->next_entry
;
376 p1
->prev_entry
= p2
->prev_entry
;
377 p2
->prev_entry
->next_entry
= p1
;
378 p1
->next_entry
->next_entry
->prev_entry
= p2
->next_entry
;
381 p2
->prev_entry
= p1prevsaved
;
382 p1
->next_entry
->next_entry
= p2nextsaved
;
385 static unsigned long long qt_getkey(struct tcptableent
*entry
, int ch
)
388 return (max(entry
->bcount
, entry
->oth_connection
->bcount
));
390 return (max(entry
->pcount
, entry
->oth_connection
->pcount
));
393 static struct tcptableent
*qt_partition(struct tcptable
*table
,
394 struct tcptableent
**low
,
395 struct tcptableent
**high
, int ch
)
397 struct tcptableent
*pivot
= *low
;
399 struct tcptableent
*left
= *low
;
400 struct tcptableent
*right
= *high
;
401 struct tcptableent
*ptmp
;
403 unsigned long long pivot_value
;
405 pivot_value
= qt_getkey(pivot
, ch
);
407 while (left
->index
< right
->index
) {
408 while ((qt_getkey(left
, ch
) >= pivot_value
)
409 && (left
->next_entry
->next_entry
!= NULL
))
411 left
= left
->next_entry
->next_entry
;
413 while (qt_getkey(right
, ch
) < pivot_value
)
414 right
= right
->prev_entry
->prev_entry
;
416 if (left
->index
< right
->index
) {
417 swap_tcp_entries(table
, left
, right
);
430 swap_tcp_entries(table
, pivot
, right
);
442 * Quicksort the TCP entries.
444 static void quicksort_tcp_entries(struct tcptable
*table
,
445 struct tcptableent
*low
,
446 struct tcptableent
*high
, int ch
)
448 struct tcptableent
*pivot
;
450 if ((high
== NULL
) || (low
== NULL
))
453 if (high
->index
> low
->index
) {
455 qt_partition(table
, &low
, &high
, ch
);
457 if (pivot
->prev_entry
!= NULL
)
458 quicksort_tcp_entries(table
, low
,
459 pivot
->prev_entry
->prev_entry
, ch
);
461 quicksort_tcp_entries(table
, pivot
->next_entry
->next_entry
,
467 * This function sorts the TCP window. The old exchange sort has been
468 * replaced with a Quicksort algorithm.
471 static void sortipents(struct tcptable
*table
, int ch
)
473 if ((table
->head
== NULL
)
474 || (table
->head
->next_entry
->next_entry
== NULL
))
479 if ((ch
!= 'P') && (ch
!= 'B'))
482 quicksort_tcp_entries(table
, table
->head
, table
->tail
->prev_entry
, ch
);
484 table
->firstvisible
= table
->head
;
485 struct tcptableent
*ptmp
= table
->head
;
487 while (ptmp
&& ((int)ptmp
->index
<= getmaxy(table
->tcpscreen
))) {
488 table
->lastvisible
= ptmp
;
489 ptmp
= ptmp
->next_entry
;
494 * Attempt to communicate with rvnamed, and if it doesn't respond, try
498 static int checkrvnamed(void)
503 indicate("Trying to communicate with reverse lookup server");
504 if (!rvnamedactive()) {
505 indicate("Starting reverse lookup server");
507 if ((cpid
= fork()) == 0) {
512 execvp("rvnamed-ng", args
);
514 * execvp() never returns, so if we reach this point, we have
518 die("unable execvp() rvnamed-ng");
519 } else if (cpid
== -1) {
520 write_error("Can't spawn new process; lookups will block");
523 while (waitpid(cpid
, &cstat
, 0) < 0)
527 if (WEXITSTATUS(cstat
) == 1) {
528 write_error("Can't start rvnamed; lookups will block");
539 static void ipmon_process_key(int ch
, int *curwin
, struct tcptable
*table
, struct othptable
*othptbl
)
541 static int keymode
= 0;
542 static WINDOW
*sortwin
;
543 static PANEL
*sortpanel
;
549 scroll_othp(othptbl
, SCROLLDOWN
, 1);
551 move_tcp_bar(table
, SCROLLDOWN
, 1);
555 scroll_othp(othptbl
, SCROLLUP
, 1);
557 move_tcp_bar(table
, SCROLLUP
, 1);
563 if (othptbl
->strindex
!= VSCRL_OFFSET
)
564 othptbl
->strindex
= VSCRL_OFFSET
;
566 refresh_othwindow(othptbl
);
572 if (othptbl
->strindex
!= 0)
573 othptbl
->strindex
= 0;
575 refresh_othwindow(othptbl
);
580 scroll_othp(othptbl
, SCROLLDOWN
, othptbl
->oimaxy
);
582 move_tcp_bar(table
, SCROLLDOWN
, table
->imaxy
);
587 scroll_othp(othptbl
, SCROLLUP
, othptbl
->oimaxy
);
589 move_tcp_bar(table
, SCROLLUP
, table
->imaxy
);
593 scroll_othp(othptbl
, SCROLLDOWN
, INT_MAX
);
595 move_tcp_bar(table
, SCROLLDOWN
, INT_MAX
);
599 scroll_othp(othptbl
, SCROLLUP
, INT_MAX
);
601 move_tcp_bar(table
, SCROLLUP
, INT_MAX
);
608 markactive(*curwin
, table
->borderwin
,
616 table
->mode
= (table
->mode
+ 1) % 3;
617 if ((table
->mode
== 1) && !options
.mac
)
619 refreshtcpwin(table
);
631 flushclosedentries(table
);
632 refreshtcpwin(table
);
637 show_tcpsort_win(&sortwin
, &sortpanel
);
648 } else if (keymode
== 1) {
650 del_panel(sortpanel
);
652 flushclosedentries(table
);
653 sortipents(table
, ch
);
654 if (table
->barptr
!= NULL
) {
655 table
->barptr
= table
->firstvisible
;
657 refreshtcpwin(table
);
661 static void ipmon_process_packet(struct pkt_hdr
*pkt
, char *ifname
,
662 struct tcptable
*table
,
663 struct othptable
*othptbl
,
664 int logging
, FILE *logfile
,
665 int *revlook
, int rvnfd
)
667 in_port_t sport
= 0, dport
= 0; /* TCP/UDP port values */
668 unsigned int br
; /* bytes read. Differs from readlen */
669 char ifnamebuf
[IFNAMSIZ
];
670 struct tcptableent
*tcpentry
;
672 int pkt_result
= packet_process(pkt
, &br
, &sport
, &dport
,
673 MATCH_OPPOSITE_ALWAYS
,
676 if (pkt_result
!= PACKET_OK
)
680 /* we're capturing on "All interfaces", */
681 /* so get the name of the interface */
683 int r
= dev_get_ifname(pkt
->from
->sll_ifindex
, ifnamebuf
);
685 write_error("Unable to get interface name");
686 return; /* error getting interface name, get out! */
691 struct sockaddr_storage saddr
, daddr
;
692 switch(pkt
->pkt_protocol
) {
694 sockaddr_make_ipv4(&saddr
, pkt
->iphdr
->saddr
);
695 sockaddr_make_ipv4(&daddr
, pkt
->iphdr
->daddr
);
698 sockaddr_make_ipv6(&saddr
, &pkt
->ip6_hdr
->ip6_src
);
699 sockaddr_make_ipv6(&daddr
, &pkt
->ip6_hdr
->ip6_dst
);
702 add_othp_entry(othptbl
, pkt
, NULL
, NULL
,
705 pkt
->pkt_payload
, ifname
, 0,
706 0, logging
, logfile
);
710 /* only when packets fragmented */
711 char *ip_payload
= pkt
->pkt_payload
+ pkt_iph_len(pkt
);
712 switch (pkt_ip_protocol(pkt
)) {
714 struct tcphdr
*tcp
= (struct tcphdr
*)ip_payload
;
715 sockaddr_set_port(&saddr
, sport
);
716 sockaddr_set_port(&daddr
, dport
);
717 tcpentry
= in_table(table
, &saddr
, &daddr
, ifname
);
720 * Add a new entry if it doesn't exist, and,
721 * to reduce the chances of stales, not a FIN.
724 if (packet_is_first_fragment(pkt
) /* first frag only */
725 && (tcpentry
== NULL
)
729 * Ok, so we have a packet. Add it if this connection
730 * is not yet closed, or if it is a SYN packet.
732 int wasempty
= (table
->head
== NULL
);
733 tcpentry
= addentry(table
, &saddr
, &daddr
,
734 pkt_ip_protocol(pkt
),
735 ifname
, revlook
, rvnfd
);
736 if (tcpentry
!= NULL
) {
737 printentry(table
, tcpentry
->oth_connection
);
740 table
->barptr
= table
->firstvisible
;
745 * If we had an addentry() success, we should have no
746 * problem here. Same thing if we had a table lookup
750 if ((tcpentry
!= NULL
)
751 && !(tcpentry
->stat
& FLAG_RST
)) {
752 int p_sstat
= 0, p_dstat
= 0; /* Reverse lookup statuses prior to */
755 * Don't bother updating the entry if the connection
756 * has been previously reset. (Does this really
757 * happen in practice?)
761 p_sstat
= tcpentry
->s_fstat
;
762 p_dstat
= tcpentry
->d_fstat
;
766 updateentry(table
, pkt
, tcpentry
, tcp
,
771 updateentry(table
, pkt
, tcpentry
, tcp
,
776 * Log first packet of a TCP connection except if
777 * it's a RST, which was already logged earlier in
782 && (tcpentry
->pcount
== 1)
783 && (!(tcpentry
->stat
& FLAG_RST
))) {
785 strcpy(msgstring
, "first packet");
787 strcat(msgstring
, " (SYN)");
789 writetcplog(logging
, logfile
, tcpentry
,
790 pkt
->pkt_len
, msgstring
);
794 && (((p_sstat
!= RESOLVED
)
795 && (tcpentry
->s_fstat
== RESOLVED
))
796 || ((p_dstat
!= RESOLVED
)
797 && (tcpentry
->d_fstat
== RESOLVED
)))) {
798 clearaddr(table
, tcpentry
);
799 clearaddr(table
, tcpentry
->oth_connection
);
801 printentry(table
, tcpentry
);
804 * Special cases: Update other direction if it's
805 * an ACK in response to a FIN.
809 * Addresses were just resolved for the other
810 * direction, so we should also do so here.
813 if (((tcpentry
->oth_connection
->finsent
== 2)
814 && /* FINed and ACKed */
815 (ntohl(tcp
->seq
) == tcpentry
->oth_connection
->finack
))
817 && (((p_sstat
!= RESOLVED
)
818 && (tcpentry
->s_fstat
== RESOLVED
))
819 || ((p_dstat
!= RESOLVED
)
820 && (tcpentry
->d_fstat
== RESOLVED
)))))
821 printentry(table
, tcpentry
->oth_connection
);
826 check_icmp_dest_unreachable(table
, pkt
, ifname
);
827 /* print this ICMP(v6) and ... */
830 add_othp_entry(othptbl
, pkt
, &saddr
, &daddr
,
831 IS_IP
, pkt_ip_protocol(pkt
),
833 revlook
, rvnfd
, logging
, logfile
);
838 /* the IP Traffic Monitor */
839 void ipmon(time_t facilitytime
, char *ifptr
)
841 int logging
= options
.logging
;
843 FILE *logfile
= NULL
;
847 unsigned long long total_pkts
= 0;
849 struct tcptable table
;
851 struct othptable othptbl
;
861 int revlook
= options
.revlook
;
863 if (ifptr
&& !dev_up(ifptr
)) {
869 if (options
.promisc
) {
870 promisc_init(&promisc
, ifptr
);
871 promisc_set_list(&promisc
);
874 if (capt_init(&capt
, ifptr
) == -1) {
875 write_error("Unable to initialize packet capture interface");
881 open_rvn_socket(&rvnfd
);
885 if (options
.servnames
)
890 * Try to open log file if logging activated. Turn off logging
891 * (for this session only) if an error was discovered in opening
892 * the log file. Configuration setting is kept. Who knows, the
893 * situation may be corrected later.
897 if (strcmp(current_logfile
, "") == 0) {
898 strncpy(current_logfile
,
899 gen_instance_logname(IPMONLOG
, getpid()),
903 input_logfile(current_logfile
, &logging
);
908 opentlog(&logfile
, current_logfile
);
914 signal(SIGUSR1
, rotate_ipmon_log
);
917 writelog(logging
, logfile
,
918 "******** IP traffic monitor started ********");
921 init_tcp_table(&table
);
922 init_othp_table(&othptbl
);
924 markactive(curwin
, table
.borderwin
, othptbl
.borderwin
);
935 gettimeofday(&now
, NULL
);
936 struct timeval last_time
= now
;
937 struct timeval updtime
= now
;
938 time_t starttime
= now
.tv_sec
;
941 if (options
.closedint
!= 0)
942 check_closed
= now
.tv_sec
+ options
.closedint
* 60;
944 check_closed
= INT_MAX
;
946 /* set the time after which we terminate the process */
948 if (facilitytime
!= 0)
949 endtime
= now
.tv_sec
+ facilitytime
* 60;
954 gettimeofday(&now
, NULL
);
956 /* update screen at configured intervals. */
957 if (screen_update_needed(&now
, &updtime
)) {
958 show_stats(table
.statwin
, total_pkts
);
965 if (now
.tv_sec
> last_time
.tv_sec
) {
966 unsigned long msecs
= timeval_diff_msec(&now
, &last_time
);
967 /* update all flowrates ... */
968 update_flowrates(&table
, msecs
);
969 /* ... and print the current one every second */
970 print_flowrate(&table
);
972 /* print timer at bottom of screen */
973 printelapsedtime(now
.tv_sec
- starttime
, 15, othptbl
.borderwin
);
975 print_packet_drops(capt_get_dropped(&capt
), othptbl
.borderwin
, 40);
977 mark_timeouted_entries(&table
, logging
, logfile
);
979 /* automatically clear closed/timed out entries */
980 if (now
.tv_sec
> check_closed
) {
981 flushclosedentries(&table
);
982 refreshtcpwin(&table
);
983 check_closed
= now
.tv_sec
+ options
.closedint
* 60;
986 /* terminate after lifetime specified at the cmdline */
987 if (now
.tv_sec
> endtime
)
990 /* close and rotate log file if signal was received */
991 if (logging
&& (rotate_flag
== 1)) {
992 announce_rotate_prepare(logfile
);
993 write_tcp_unclosed(logging
, logfile
, &table
);
994 rotate_logfile(&logfile
, target_logname
);
995 announce_rotate_complete(logfile
);
1002 if (capt_get_packet(&capt
, &pkt
, &ch
, table
.tcpscreen
) == -1) {
1003 write_error("Packet receive failed");
1009 ipmon_process_key(ch
, &curwin
, &table
, &othptbl
);
1011 if (pkt
.pkt_len
> 0) {
1013 ipmon_process_packet(&pkt
, ifptr
, &table
, &othptbl
,
1016 capt_put_packet(&capt
, &pkt
);
1019 packet_destroy(&pkt
);
1021 destroyothptable(&othptbl
);
1022 destroytcptable(&table
);
1027 signal(SIGUSR1
, SIG_DFL
);
1028 writelog(logging
, logfile
,
1029 "******** IP traffic monitor stopped ********\n");
1031 strcpy(current_logfile
, "");
1035 if (options
.servnames
)
1039 close_rvn_socket(rvnfd
);
1041 capt_destroy(&capt
);
1043 if (options
.promisc
) {
1044 promisc_restore_list(&promisc
);
1045 promisc_destroy(&promisc
);