2
* jnettop, network online traffic visualiser
3
* Copyright (C) 2002-2006 Jakub Skopal
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* $Header: /cvsroot/jnettop/jnettop/juiadisplay.c,v 1.1 2006/04/11 15:21:06 merunka Exp $
25
#include "jprocessor.h"
28
#include "juiadisplay.h"
32
#define LISTEN_ERROR_ANSWER "listen:ASCII:NAK:Error compiling rule: syntax error\n\n"
33
#define ERROR_MAXIMUM_TIMEOUT_EXPIRED "\n\n"
34
#define GET_REQUEST_END_BOUNDARY "\n"
37
#define MAX_COMMAND_TIMEOUT_MINUTES 5
38
#define SMALL_WAIT 100
39
#define DEFAULT_LINE_COUNT 15
41
GMutex *displayStreamsMutex;
42
jbase_stream **displayStreams = NULL;
43
int displayStreamsCount = 0;
44
gboolean bHaveData = FALSE;
45
int nLineCount = DEFAULT_LINE_COUNT;
47
gboolean onoffPackets;
48
gboolean onoffBitValues;
50
static void processStreamsFunc(GPtrArray * streamArray) {
52
guint lines, oldLines;
53
jbase_stream **streams,**oldStreams;
55
streams = g_new0(jbase_stream *, nLineCount);
57
for (i=0,j=0; i<streamArray->len && j<nLineCount; i++) {
58
jbase_stream *s = (jbase_stream *)g_ptr_array_index(streamArray, i);
68
g_mutex_lock(displayStreamsMutex);
71
oldStreams = displayStreams;
72
oldLines = displayStreamsCount;
73
displayStreams = streams;
74
displayStreamsCount = lines;
75
g_mutex_unlock(displayStreamsMutex);
77
for (i=0; i<oldLines; i++) {
78
oldStreams[i]->displayed --;
85
static gchar * get_next_token_colon_delim(gchar ** text){
90
tmp = strsep(text, ":");
91
if(tmp && *tmp != '\0'){
98
void doWriteFormatedNetworkStreams(pid_t nSessionID, gulong lUSecsWaited) {
101
gchar srcport[10], dstport[10], srcbps[10], dstbps[10], bps[10];
103
debug(LOG_DEBUG, "streams count %d", displayStreamsCount);
105
// dump out the totals line...
106
jutil_formatNumber(onoffPackets?jprocessor_Stats.totalPPS:(onoffBitValues?8:1)*jprocessor_Stats.totalBPS, onoffPackets, bps, 6);
107
g_strlcat(bps, "/s", sizeof(bps));
108
jutil_formatNumber(onoffPackets?jprocessor_Stats.totalSrcPPS:(onoffBitValues?8:1)*jprocessor_Stats.totalSrcBPS, onoffPackets, srcbps, 6);
109
g_strlcat(srcbps, "/s", sizeof(srcbps));
110
jutil_formatNumber(onoffPackets?jprocessor_Stats.totalDstPPS:(onoffBitValues?8:1)*jprocessor_Stats.totalDstBPS, onoffPackets, dstbps, 6);
111
g_strlcat(dstbps, "/s", sizeof(dstbps));
113
sprintf(buffer, "get:ASCII:%d:%d:ACK:TOTAL:::::%s:%s:%s\n", nSessionID, (int)lUSecsWaited, srcbps, dstbps, bps);
114
//debug(LOG_DEBUG, "sending %d characters '%s'", strlen(buffer), buffer);
115
printf("%s", buffer);
117
for (i=0; i< displayStreamsCount; i++) {
118
gchar srcaddr[INET6_ADDRSTRLEN + 1], dstaddr[INET6_ADDRSTRLEN + 1];
119
gchar total[10], totalsrc[10], totaldst[10];
121
gchar linebuffer[1024];
122
const gchar *psrcaddr, *pdstaddr;
123
jbase_stream *s = displayStreams[i];
124
tmp = onoffPackets ? s->totalpps : (onoffBitValues?8:1)*s->totalbps;
125
jutil_formatNumber(tmp, onoffPackets, bps, 6);
126
g_strlcat(bps, "/s", sizeof(bps));
127
tmp = onoffPackets ? s->srcpps : (onoffBitValues?8:1)*s->srcbps;
128
jutil_formatNumber(tmp, onoffPackets, srcbps, 6);
129
g_strlcat(srcbps, "/s", sizeof(srcbps));
130
tmp = onoffPackets ? s->dstpps : (onoffBitValues?8:1)*s->dstbps;
131
jutil_formatNumber(tmp, onoffPackets, dstbps, 6);
132
g_strlcat(dstbps, "/s", sizeof(dstbps));
133
jutil_formatNumber(onoffPackets ? s->totalpackets : s->totalbytes, onoffPackets, total, 6);
134
jutil_formatNumber(onoffPackets ? s->srcpackets : s->srcbytes, onoffPackets, totalsrc, 6);
135
jutil_formatNumber(onoffPackets ? s->dstpackets : s->dstbytes, onoffPackets, totaldst, 6);
136
jutil_Address2String(JBASE_AF(s->proto), &s->src, srcaddr, INET6_ADDRSTRLEN);
137
if (s->srcresolv == NULL || s->srcresolv->name == NULL) {
140
psrcaddr = s->srcresolv->name;
142
jutil_Address2String(JBASE_AF(s->proto), &s->dst, dstaddr, INET6_ADDRSTRLEN);
143
if (s->dstresolv == NULL || s->dstresolv->name == NULL) {
146
pdstaddr = s->dstresolv->name;
148
if (s->srcport == -1)
149
strcpy(srcport, "AGGR.");
151
sprintf(srcport, "%d", s->srcport);
152
if (s->dstport == -1)
153
strcpy(dstport, "AGGR.");
155
sprintf(dstport, "%d", s->dstport);
156
sprintf(linebuffer, "%s:%s", psrcaddr, pdstaddr);
158
sprintf(buffer, "get:ASCII:%d:%d:ACK:%s:%s:%s:%s:%s:%s:%s:%s\n", nSessionID, (int)lUSecsWaited, srcaddr, srcport, JBASE_PROTOCOLS[s->proto], dstaddr, dstport, srcbps, dstbps, bps);
159
//debug(LOG_DEBUG, "sending %d characters '%s'", strlen(buffer), buffer);
160
printf("%s", buffer);
162
printf(GET_REQUEST_END_BOUNDARY);
165
static GTimeVal timeNow(){
167
g_get_current_time(&timeNow);
171
static void networkConnectionLoop(){
173
pid_t ourpid = getpid();
174
gboolean bExit = FALSE;
176
// setup timer here...
177
GTimeVal commandTimeout;
178
g_get_current_time(&commandTimeout);
180
while(!bExit && (timeNow().tv_sec - commandTimeout.tv_sec < MAX_COMMAND_TIMEOUT_MINUTES * 60)){
181
// make sure we don't block forever...
182
int nSelectReturn = 0;
185
tm.tv_sec = 10; // wait ten seconds...
188
FD_SET(fileno(stdin), &listenSet);
190
nSelectReturn = select(fileno(stdin)+1, &listenSet, NULL, NULL, &tm);
192
if(nSelectReturn > 0){
193
if(FD_ISSET(fileno(stdin), &listenSet)){
194
int nDataRecievedCount = 0;
195
gchar data[ MAXRECV + 1];
196
bzero(data, MAXRECV);
197
nDataRecievedCount = read(fileno(stdin), data, MAXRECV - 2);
199
if(nDataRecievedCount > 0){
200
gchar * strPid = NULL;
201
gchar * strType = NULL;
202
gchar * strMethod = NULL;
203
gchar * strMaxWaitUSecs = NULL;
204
gchar * cpdata = data;
207
// make sure we end the string...
208
data[nDataRecievedCount] = ':';
209
data[nDataRecievedCount + 1] = '\0';
211
// remove any control charaters...
212
for(nIndex = 0; nIndex<nDataRecievedCount; nIndex++){
213
if(iscntrl(data[nIndex])){
214
// this is a control character - change it to a :
219
strMethod = get_next_token_colon_delim(&cpdata);
220
strType = get_next_token_colon_delim(&cpdata);
221
strPid = get_next_token_colon_delim(&cpdata);
222
strMaxWaitUSecs = get_next_token_colon_delim(&cpdata);
224
if(strPid && ourpid != atoi(strPid)){
225
// error - key id not correct
226
debug(LOG_DEBUG, "Invalid session - %s given, %d expected", strPid, ourpid);
227
printf(LISTEN_ERROR_ANSWER);
228
}else if(strncmp(strMethod, "end", strlen("end")) == 0){
229
gchar endAnswer[16384];
230
g_get_current_time(&commandTimeout);
231
// recived an end command
232
sprintf(endAnswer, "end:ASCII:%d:ACK\n\n", ourpid);
233
debug(LOG_DEBUG, "Sending '%s'", endAnswer);
234
printf("%s", endAnswer);
236
}else if(strncmp(data, "get", strlen("get")) == 0){
237
gulong lMicroSeconds = 0;
238
gulong lWaitedSeconds = 0;
239
g_get_current_time(&commandTimeout);
240
// see how long we should wait...
243
lMicroSeconds = atol(strMaxWaitUSecs);
246
debug(LOG_DEBUG, "waiting for data - will wait %d useconds", lMicroSeconds);
247
while(!bHaveData && lWaitedSeconds < lMicroSeconds){
248
lWaitedSeconds += SMALL_WAIT;
249
g_usleep(SMALL_WAIT);
252
debug(LOG_DEBUG, "waited %d useconds - bHaveData - %d", lWaitedSeconds, bHaveData);
255
// recieved get request
257
g_mutex_lock(displayStreamsMutex);
258
doWriteFormatedNetworkStreams(ourpid, lWaitedSeconds);
259
g_mutex_unlock(displayStreamsMutex);
261
debug(LOG_DEBUG, "Timed out waiting for data - sending '%s'", ERROR_MAXIMUM_TIMEOUT_EXPIRED);
262
printf(ERROR_MAXIMUM_TIMEOUT_EXPIRED);
266
} // nDataRecievedCount
270
if(!(timeNow().tv_sec - commandTimeout.tv_sec < MAX_COMMAND_TIMEOUT_MINUTES * 60)){
271
// send timeout error
272
debug(LOG_WARNING, "Timed out while waiting for get/end command - waited %d seconds", timeNow().tv_sec - commandTimeout.tv_sec);
273
printf(ERROR_MAXIMUM_TIMEOUT_EXPIRED);
277
gboolean parseListenLineAndConfig(){
278
// wait here for a listen command with parameters...
279
gboolean bInitialized = FALSE;
281
static gchar data[ MAXRECV + 1];
283
pid_t ourpid = getpid();
284
gboolean bBitValuesBackup = onoffBitValues;
285
GTimeVal commandTimeout;
287
// backup the device name
288
gchar strDeviceBackup[30];
289
strDeviceBackup[0] = '\0';
291
if(jconfig_Settings.deviceName)
292
strcpy(strDeviceBackup, jconfig_Settings.deviceName);
295
// setup timer here...
296
g_get_current_time(&commandTimeout);
299
// keep going while we have not initialized, aren't shutting down, and haven't timed out
300
while(!bInitialized && (timeNow().tv_sec - commandTimeout.tv_sec < MAX_COMMAND_TIMEOUT_MINUTES * 60)){
301
// make sure we don't block forever...
304
int nSelectReturn = 0;
306
FD_SET(fileno(stdin), &listenSet);
307
tm.tv_sec = 10; // wait ten seconds...
309
nSelectReturn = select(fileno(stdin)+1, &listenSet, NULL, NULL, &tm);
311
if(nSelectReturn != -1){
312
// try to read stdout...
313
if(FD_ISSET(fileno(stdin), &listenSet)){
314
int nDataRecievedCount = read(fileno(stdin), data, MAXRECV - 2);
316
if(nDataRecievedCount > 0){
318
gchar * strMethod = NULL;
319
gchar * strType = NULL;
320
gchar * strDevice = NULL;
321
gchar * strBits = NULL;
322
gchar * strFilter = NULL;
323
gchar * strMaxLines = NULL;
324
gchar * cpdata = data; //(gchar *) strdup(data);
326
// make sure we end the string...
327
data[nDataRecievedCount] = ':';
328
data[nDataRecievedCount+1] = '\0';
330
// clear the bpf filter...
331
JCONFIG_BPFFILTERS_SETNONE;
332
// reset the device name
333
if(strlen(strDeviceBackup) > 0){
334
strcpy(jconfig_Settings.deviceName, strDeviceBackup);
336
// reset the bit values
337
onoffBitValues = bBitValuesBackup;
339
// remove any control charaters...
340
for(nIndex = 0; nIndex<nDataRecievedCount; nIndex++){
341
if(iscntrl(data[nIndex])){
342
// this is a control character - change it to a :
347
strMethod = get_next_token_colon_delim(&cpdata);
348
strType = get_next_token_colon_delim(&cpdata);
349
strDevice = get_next_token_colon_delim(&cpdata);
350
strBits = get_next_token_colon_delim(&cpdata);
351
strFilter = get_next_token_colon_delim(&cpdata);
352
strMaxLines = get_next_token_colon_delim(&cpdata);
354
if(strncmp(strMethod, "listen", strlen("listen")) == 0){
355
gchar firstAnswer[16384];
356
int nStrMaxLines = 0;
357
gboolean bIsRequestGood = TRUE;
360
nStrMaxLines = atoi(strMaxLines);
362
debug(LOG_DEBUG, "Got listen request");
363
// got a listen request
368
const char * strFilterResult = jutil_ValidateBPFFilter(strFilter);
369
if(!strFilterResult){
371
JCONFIG_BPFFILTERS_SETSELECTEDFILTER(JCONFIG_BPFFILTERS_LEN);
372
jconfig_AddBpfFilter("<fromlisten>", strFilter);
374
debug(LOG_WARNING, "strFilter is BAD - %s", strFilterResult);
375
bIsRequestGood = FALSE;
376
printf(LISTEN_ERROR_ANSWER);
381
debug(LOG_DEBUG, "Setting device name '%s'", strDevice);
383
jconfig_Settings.deviceName = strDevice;
386
if(strBits && strcmp(strBits, "bits") == 0){
387
debug(LOG_DEBUG, "Setting bits");
389
onoffBitValues = TRUE;
394
if(nStrMaxLines != 0)
395
nLineCount = nStrMaxLines;
397
sprintf(firstAnswer, "listen:ASCII:%d:ACK:%s:%s:%s:%s\n\n", ourpid, strDevice, strBits, strFilter, strMaxLines);
398
debug(LOG_DEBUG,"sending '%s'", firstAnswer);
402
printf(LISTEN_ERROR_ANSWER);
405
// reset the timeout timer..
406
g_get_current_time(&commandTimeout);
412
if(!(timeNow().tv_sec - commandTimeout.tv_sec < MAX_COMMAND_TIMEOUT_MINUTES * 60)){
413
// send timeout error
414
debug(LOG_NOTICE, "Timed out while waiting for listen command - waited %d seconds", timeNow().tv_sec - commandTimeout.tv_sec);
415
printf(ERROR_MAXIMUM_TIMEOUT_EXPIRED);fflush(NULL);
420
static gboolean juiadisplay_PreSetup() {
421
setvbuf(stdin, NULL, _IOLBF, 0);
422
setvbuf(stdout, NULL, _IOLBF, 0);
423
return parseListenLineAndConfig();
426
static void juiadisplay_Setup() {
427
displayStreamsMutex = g_mutex_new();
429
jprocessor_SetProcessStreamsFunc((ProcessStreamsFunc) processStreamsFunc);
430
onoffBitValues = FALSE;
431
onoffPackets = FALSE;
434
static void juiadisplay_PreRun() {
437
static gboolean juiadisplay_Run() {
438
networkConnectionLoop();
442
static void juiadisplay_Shutdown() {
445
static void juiadisplay_DrawStatus(const gchar *msg) {
448
static int juiadisplay_ProcessArgument(const gchar **arg, int argc) {
449
if (!strcmp(*arg, "-b") || !strcmp(*arg, "--bit-units")) {
450
onoffBitValues = TRUE;
456
jbase_display juiadisplay_Functions = {
458
juiadisplay_PreSetup,
462
juiadisplay_Shutdown,
463
juiadisplay_DrawStatus,
464
juiadisplay_ProcessArgument
469
jbase_display juiadisplay_Functions = { FALSE };