00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "server_stats.h"
00015 #include "flowps.h"
00016 #include "sfxhash.h"
00017
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <fcntl.h>
00021 #include <unistd.h>
00022 #include <string.h>
00023
00024 static void server_stats_init_entry(void);
00025
00026 typedef struct _SERVER_KEY
00027 {
00028 u_int32_t address;
00029 u_int32_t port;
00030 u_int32_t protocol;
00031 } SERVER_KEY;
00032
00033 static SERVER_KEY s_key;
00034 static int s_debug = 0;
00035
00036
00037
00038
00039
00040
00041 void server_stats_dump(SERVER_STATS *ssp)
00042 {
00043 SFXHASH_NODE *nodep;
00044
00045 if(ssp && ssp->ipv4_table)
00046 {
00047 for( nodep = sfxhash_ghead(ssp->ipv4_table);
00048 nodep != NULL;
00049 nodep = sfxhash_gnext(nodep) )
00050 {
00051 SERVER_KEY *kp = (SERVER_KEY *) nodep->key;
00052 u_int32_t count = *(u_int32_t *) nodep->data;
00053
00054 flow_printf("hits: %u proto: %3u port: %5u ip: %s\n",
00055 count,
00056 kp->protocol,
00057 kp->port,
00058 inet_ntoa(*(struct in_addr *)&kp->address));
00059 }
00060 }
00061 else
00062 {
00063 flow_printf("nothing to dump!\n");
00064 }
00065 }
00066
00067 void server_stats(SERVER_STATS *ssp, int dumpall)
00068 {
00069 unsigned total, fail, success, nodes, anr, overhead, memcap;
00070
00071 memcap = overhead = nodes = anr = total = fail = success = 0;
00072
00073 if(ssp && ssp->ipv4_table)
00074 {
00075 total = sfxhash_find_total(ssp->ipv4_table);
00076 fail = sfxhash_find_fail(ssp->ipv4_table);
00077 success = sfxhash_find_success(ssp->ipv4_table);
00078 nodes = sfxhash_count(ssp->ipv4_table);
00079 anr = sfxhash_anr_count(ssp->ipv4_table);
00080 memcap = server_stats_memcap(ssp);
00081 overhead = server_stats_overhead_bytes(ssp);
00082 }
00083
00084 flow_printf(",-----[SERVER STATS]------------\n");
00085 flow_printf(" Memcap: %u Overhead Bytes: %u\n",
00086 memcap, overhead);
00087
00088 flow_printf(" Finds: %u (Sucessful: %u(%%%lf) Unsucessful: %u(%%%lf))\n",
00089 total,
00090 success, calc_percent(success,total),
00091 fail, calc_percent(fail,total));
00092
00093 flow_printf(" Nodes: %u\n", nodes);
00094
00095 flow_printf(" Recovered Nodes: %u\n", anr);
00096 flow_printf("`-------------------------------\n");
00097
00098 if(dumpall)
00099 server_stats_dump(ssp);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 int server_stats_init(SERVER_STATS *ssp, IPSET *watchnetv4,
00116 unsigned int rows, int memcap)
00117 {
00118 if(!ssp || !watchnetv4)
00119 return FLOW_ENULL;
00120
00121 server_stats_init_entry();
00122
00123 memset(ssp, 0, sizeof(SERVER_STATS));
00124
00125
00126 if(ipset_family(watchnetv4) != IPV4_FAMILY)
00127 {
00128 return FLOW_EINVALID;
00129 }
00130
00131
00132 ssp->ipv4_table = sfxhash_new(rows,
00133 sizeof(SERVER_KEY),
00134 sizeof(u_int32_t),
00135 memcap,
00136 1,
00137 NULL,
00138 NULL,
00139 1);
00140
00141 if(ssp->ipv4_table == NULL)
00142 {
00143 return FLOW_ENOMEM;
00144 }
00145
00146 ssp->ipv4_watch = ipset_copy(watchnetv4);
00147
00148 if(!ssp->ipv4_watch)
00149 {
00150 sfxhash_delete(ssp->ipv4_table);
00151 return FLOW_ENOMEM;
00152 }
00153
00154 return FLOW_SUCCESS;
00155 }
00156
00157 int server_stats_destroy(SERVER_STATS *ssp)
00158 {
00159 if(!ssp)
00160 {
00161 return FLOW_ENULL;
00162 }
00163
00164 sfxhash_delete(ssp->ipv4_table);
00165 ipset_free(ssp->ipv4_watch);
00166
00167 return FLOW_SUCCESS;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 int server_stats_contains(SERVER_STATS *ssp, u_int32_t address)
00179 {
00180 if(ssp->ipv4_watch)
00181 {
00182 u_int32_t hostaddress = ntohl(address);
00183
00184 if(ipset_contains(ssp->ipv4_watch, &hostaddress, IPV4_FAMILY))
00185 {
00186 return FLOW_SUCCESS;
00187 }
00188 }
00189
00190 return FLOW_DISABLED;
00191 }
00192
00193
00194 u_int32_t server_stats_hitcount_ipv4(SERVER_STATS *ssp, u_int8_t ip_proto, u_int32_t address, u_int16_t port)
00195 {
00196 SERVER_KEY *kp = &s_key;
00197 u_int32_t *hitcountp;
00198 #ifdef DEBUG
00199 u_int32_t hostaddress = ntohl(address);
00200 #endif
00201
00202
00203 FLOWASSERT(ipset_contains(ssp->ipv4_watch, &hostaddress, IPV4_FAMILY));
00204
00205
00206 kp->address = address;
00207 kp->port = port;
00208 kp->protocol = ip_proto;
00209
00210 hitcountp = (u_int32_t *) sfxhash_find(ssp->ipv4_table, kp);
00211
00212 if(hitcountp != NULL)
00213 {
00214 return *hitcountp;
00215 }
00216
00217 return 0;
00218 }
00219
00220 int server_stats_add_ipv4(SERVER_STATS *ssp, u_int8_t ip_proto, u_int32_t address, u_int16_t port,
00221 u_int32_t *retcount)
00222 {
00223 SERVER_KEY *kp = &s_key;
00224 u_int32_t one = 1;
00225 u_int32_t *hitcountp = NULL;
00226 int ret;
00227 #ifdef DEBUG
00228 u_int32_t hostaddress = ntohl(address);
00229 #endif
00230
00231 if(ssp == NULL || retcount == NULL)
00232 return FLOW_ENULL;
00233
00234
00235 FLOWASSERT(ipset_contains(ssp->ipv4_watch, &hostaddress, IPV4_FAMILY));
00236
00237
00238 kp->address = address;
00239 kp->port = port;
00240 kp->protocol = ip_proto;
00241
00242
00243 ret = sfxhash_add(ssp->ipv4_table, kp, &one);
00244
00245 switch(ret)
00246 {
00247 case SFXHASH_NOMEM:
00248
00249
00250
00251 case SFXHASH_OK:
00252 *retcount = 1;
00253 break;
00254 case SFXHASH_INTABLE:
00255 hitcountp = (u_int32_t *) sfxhash_mru(ssp->ipv4_table);
00256
00257
00258 if(!hitcountp)
00259 {
00260
00261 return FLOW_BADJUJU;
00262 }
00263 else
00264 {
00265 if((*hitcountp) < SERVER_STATS_MAX_HITCOUNT)
00266 {
00267 (*hitcountp)++;
00268 }
00269 }
00270 break;
00271 }
00272
00273 return FLOW_SUCCESS;
00274 }
00275
00276 int server_stats_remove_ipv4(SERVER_STATS *ssp, u_int8_t ip_proto,
00277 u_int32_t address, u_int16_t port)
00278 {
00279 SERVER_KEY *kp = &s_key;
00280
00281 if(!ssp)
00282 return FLOW_ENULL;
00283
00284 kp->address = address;
00285 kp->port = port;
00286 kp->protocol = ip_proto;
00287
00288
00289 sfxhash_remove(ssp->ipv4_table, kp);
00290
00291 return FLOW_SUCCESS;
00292 }
00293
00294
00295
00296 #define FAMILY_SIZE 1
00297 #define FAMILY_OFFSET 0
00298
00299 #define IPV4_SIZE 4
00300 #define IPV4_OFFSET (FAMILY_SIZE)
00301
00302 #define PORT_SIZE 2
00303 #define PORT_OFFSET (IPV4_OFFSET + IPV4_SIZE)
00304
00305 #define IP_PROTO_SIZE 1
00306 #define IP_PROTO_OFFSET (PORT_OFFSET + PORT_SIZE)
00307
00308 #define COUNT_SIZE 4
00309 #define COUNT_OFFSET (IP_PROTO_OFFSET + IP_PROTO_SIZE)
00310
00311 #define STATSREC_SIZE (FAMILY_SIZE + IPV4_SIZE + PORT_SIZE + IP_PROTO_SIZE + COUNT_SIZE)
00312
00313
00314 int server_stats_save(SERVER_STATS *ssp, char *filename)
00315 {
00316 SFXHASH_NODE *nodep;
00317 unsigned char buf[STATSREC_SIZE];
00318 int fd;
00319
00320 if(!filename || !ssp)
00321 return FLOW_ENULL;
00322 #ifndef O_SYNC
00323 #define O_SYNC O_FSYNC
00324 #endif
00325
00326
00327
00328 fd = open(filename, O_CREAT|O_TRUNC|O_SYNC|O_WRONLY);
00329
00330 if(fd < 0)
00331 {
00332 if(s_debug)
00333 {
00334 flow_printf("%s was not found\n", filename);
00335 }
00336 return FLOW_NOTFOUND;
00337 }
00338
00339
00340 for( nodep = sfxhash_ghead(ssp->ipv4_table);
00341 nodep != NULL;
00342 nodep = sfxhash_gnext(nodep) )
00343 {
00344 SERVER_KEY *kp = (SERVER_KEY *) nodep->key;
00345 u_int32_t count = *(u_int32_t *) nodep->data;
00346 u_int8_t family = '4';
00347 u_int32_t ipv4_address;
00348 u_int16_t port;
00349 u_int8_t protocol;
00350 ssize_t wbytes = 0;
00351 ssize_t wsize;
00352
00353
00354 count = ntohl(count);
00355 ipv4_address = htonl(kp->address);
00356 port = htons(kp->port);
00357 protocol = kp->protocol;
00358
00359 memcpy(buf + FAMILY_OFFSET, &family, FAMILY_SIZE);
00360 memcpy(buf + IPV4_OFFSET, &ipv4_address, IPV4_SIZE);
00361 memcpy(buf + PORT_OFFSET, &port, PORT_SIZE);
00362 memcpy(buf + IP_PROTO_OFFSET, &protocol, IP_PROTO_SIZE);
00363 memcpy(buf + COUNT_OFFSET, &count, COUNT_SIZE);
00364
00365
00366 while(wbytes < STATSREC_SIZE)
00367 {
00368
00369
00370 wsize = write(fd, buf, (STATSREC_SIZE - wbytes));
00371
00372 if(wsize < 0)
00373 {
00374
00375 flow_printf("Truncated Server Record!\n");
00376 return FLOW_EINVALID;
00377 }
00378 else
00379 {
00380 wbytes += wsize;
00381 }
00382 }
00383 }
00384
00385 return FLOW_SUCCESS;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 int server_stats_load(SERVER_STATS *ssp, char *filename)
00409 {
00410 SERVER_KEY *kp = &s_key;
00411 size_t rsize;
00412 unsigned char buf[STATSREC_SIZE];
00413 int fd;
00414
00415 if(!filename || !ssp)
00416 return FLOW_ENULL;
00417
00418
00419 fd = open(filename, O_RDONLY);
00420
00421 if(fd < 0)
00422 {
00423 return FLOW_NOTFOUND;
00424 }
00425
00426
00427 while((rsize = read(fd, &buf, STATSREC_SIZE) == STATSREC_SIZE) > 0)
00428 {
00429 u_int8_t family;
00430 u_int32_t ipv4_address;
00431 u_int16_t port;
00432 u_int8_t protocol;
00433 u_int32_t count;
00434
00435 if(rsize != STATSREC_SIZE)
00436 {
00437
00438 close(fd);
00439 return FLOW_EINVALID;
00440 }
00441
00442 memcpy(&family, buf + FAMILY_OFFSET, FAMILY_SIZE);
00443 memcpy(&ipv4_address, buf + IPV4_OFFSET, IPV4_SIZE);
00444 memcpy(&port, buf + PORT_OFFSET, PORT_SIZE);
00445 memcpy(&protocol, buf + IP_PROTO_OFFSET, IP_PROTO_SIZE);
00446 memcpy(&count, buf + COUNT_OFFSET, COUNT_SIZE);
00447
00448
00449
00450 if(family != '4')
00451 {
00452 close(fd);
00453 return FLOW_EINVALID;
00454 }
00455
00456 kp->protocol = ntohs(protocol);
00457 kp->address = ntohl(ipv4_address);
00458 kp->port = ntohs(port);
00459 count = ntohl(count);
00460
00461 if(sfxhash_add(ssp->ipv4_table, kp, &count) != 0)
00462 {
00463 close(fd);
00464 return FLOW_BADJUJU;
00465 }
00466 }
00467
00468 close(fd);
00469 return FLOW_SUCCESS;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479 static void server_stats_init_entry(void)
00480 {
00481 static int init_once = 1;
00482
00483 if(init_once)
00484 {
00485 init_once = 0;
00486 memset(&s_key, 0, sizeof(SERVER_KEY));
00487 }
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 int server_stats_memcap(SERVER_STATS *sbp)
00499 {
00500 if(sbp != NULL && sbp->ipv4_table != NULL)
00501 return sbp->ipv4_table->mc.memcap;
00502
00503 return -1;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513 int server_stats_row_count(SERVER_STATS *sbp)
00514 {
00515 if(sbp != NULL && sbp->ipv4_table != NULL)
00516 return sbp->ipv4_table->nrows;
00517
00518 return -1;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 int server_stats_overhead_bytes(SERVER_STATS *sbp)
00530 {
00531 if(sbp != NULL && sbp->ipv4_table != NULL)
00532 return sfxhash_overhead_bytes(sbp->ipv4_table);
00533
00534 return -1;
00535 }
00536
00537