1 /*
2 prints "status" message once per second to the commandline
3
4 The status message indicates:
5 - the rate in packets-per-second
6 - %done
7 - estimated time remaining of the scan
8 - number of 'tcbs' (TCP control blocks) of active TCP connections
9
10 */
11 #include "main-status.h"
12 #include "pixie-timer.h"
13 #include "unusedparm.h"
14 #include "main-globals.h"
15 #include "string_s.h"
16 #include <stdio.h>
17
18
19
20 /***************************************************************************
21 * Print a status message about once-per-second to the command-line. This
22 * algorithm is a little funky because checking the timestamp on EVERY
23 * packet is slow.
24 ***************************************************************************/
25 void
status_print(struct Status * status,uint64_t count,uint64_t max_count,double x,uint64_t total_tcbs,uint64_t total_synacks,uint64_t total_syns,uint64_t exiting)26 status_print(
27 struct Status *status,
28 uint64_t count,
29 uint64_t max_count,
30 double x,
31 uint64_t total_tcbs,
32 uint64_t total_synacks,
33 uint64_t total_syns,
34 uint64_t exiting)
35 {
36 double elapsed_time;
37 double rate;
38 double now;
39 double percent_done;
40 double time_remaining;
41 uint64_t current_tcbs = 0;
42 uint64_t current_synacks = 0;
43 uint64_t current_syns = 0;
44 double tcb_rate = 0.0;
45 double synack_rate = 0.0;
46 double syn_rate = 0.0;
47
48
49 /*
50 * #### FUGGLY TIME HACK ####
51 *
52 * PF_RING doesn't timestamp packets well, so we can't base time from
53 * incoming packets. Checking the time ourself is too ugly on per-packet
54 * basis. Therefore, we are going to create a global variable that keeps
55 * the time, and update that variable whenever it's convienient. This
56 * is one of those convenient places.
57 */
58 global_now = time(0);
59
60
61 /* Get the time. NOTE: this is CLOCK_MONOTONIC_RAW on Linux, not
62 * wall-clock time. */
63 now = (double)pixie_gettime();
64
65 /* Figure how many SECONDS have elapsed, in a floating point value.
66 * Since the above timestamp is in microseconds, we need to
67 * shift it by 1-million
68 */
69 elapsed_time = (now - status->last.clock)/1000000.0;
70 if (elapsed_time <= 0)
71 return;
72
73 /* Figure out the "packets-per-second" number, which is just:
74 *
75 * rate = packets_sent / elapsed_time;
76 */
77 rate = (count - status->last.count)*1.0/elapsed_time;
78
79 /*
80 * Smooth the number by averaging over the last 8 seconds
81 */
82 status->last_rates[status->last_count++ & 0x7] = rate;
83 rate = status->last_rates[0]
84 + status->last_rates[1]
85 + status->last_rates[2]
86 + status->last_rates[3]
87 + status->last_rates[4]
88 + status->last_rates[5]
89 + status->last_rates[6]
90 + status->last_rates[7]
91 ;
92 rate /= 8;
93 /*if (rate == 0)
94 return;*/
95
96 /*
97 * Calculate "percent-done", which is just the total number of
98 * packets sent divided by the number we need to send.
99 */
100 percent_done = (double)(count*100.0/max_count);
101
102
103 /*
104 * Calulate the time remaining in the scan
105 */
106 time_remaining = (1.0 - percent_done/100.0) * (max_count / rate);
107
108 /*
109 * some other stats
110 */
111 if (total_tcbs) {
112 current_tcbs = total_tcbs - status->total_tcbs;
113 status->total_tcbs = total_tcbs;
114 tcb_rate = (1.0*current_tcbs)/elapsed_time;
115 }
116 if (total_synacks) {
117 current_synacks = total_synacks - status->total_synacks;
118 status->total_synacks = total_synacks;
119 synack_rate = (1.0*current_synacks)/elapsed_time;
120 }
121 if (total_syns) {
122 current_syns = total_syns - status->total_syns;
123 status->total_syns = total_syns;
124 syn_rate = (1.0*current_syns)/elapsed_time;
125 }
126
127
128 /*
129 * Print the message to <stderr> so that <stdout> can be redirected
130 * to a file (<stdout> reports what systems were found).
131 */
132 if (status->is_infinite) {
133 fprintf(stderr,
134 "rate:%6.2f-kpps, syn/s=%.0f ack/s=%.0f tcb-rate=%.0f, %" PRIu64 "-tcbs, \r",
135 x/1000.0,
136 syn_rate,
137 synack_rate,
138 tcb_rate,
139 total_tcbs
140 );
141 } else {
142 if (is_tx_done) {
143
144 fprintf(stderr,
145 "rate:%6.2f-kpps, %5.2f%% done, waiting %d-secs, found=%" PRIu64 " \r",
146 x/1000.0,
147 percent_done,
148 (int)exiting,
149 total_synacks
150 );
151
152 } else {
153 fprintf(stderr,
154 "rate:%6.2f-kpps, %5.2f%% done,%4u:%02u:%02u remaining, found=%" PRIu64 " \r",
155 x/1000.0,
156 percent_done,
157 (unsigned)(time_remaining/60/60),
158 (unsigned)(time_remaining/60)%60,
159 (unsigned)(time_remaining)%60,
160 total_synacks
161 );
162 }
163 }
164 fflush(stderr);
165
166 /*
167 * Remember the values to be diffed against the next time around
168 */
169 status->last.clock = now;
170 status->last.count = count;
171 }
172
173 /***************************************************************************
174 ***************************************************************************/
175 void
status_finish(struct Status * status)176 status_finish(struct Status *status)
177 {
178 UNUSEDPARM(status);
179 fprintf(stderr,
180 " \r");
181 }
182
183 /***************************************************************************
184 ***************************************************************************/
185 void
status_start(struct Status * status)186 status_start(struct Status *status)
187 {
188 memset(status, 0, sizeof(*status));
189 status->last.clock = clock();
190 status->last.time = time(0);
191 status->last.count = 0;
192 status->timer = 0x1;
193 }
194