/* ** Copyright (C) 2001-2007 by Carnegie Mellon University. ** ** @OPENSOURCE_HEADER_START@ ** ** Use of the SILK system and related source code is subject to the terms ** of the following licenses: ** ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract F19628-00-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ */ /* * rwtotal.c * * This is an analysis package which totals up various values in a * packfile, breaking them up by some combination of fields. * */ #include "silk.h" RCSIDENT("$SiLK: rwtotal.c 8269 2007-08-03 18:54:48Z mthomas $"); #include "rwtotal.h" /* LOCAL DEFINES AND TYPEDEFS */ /* Where to write filenames if --print-file specified */ #define PRINT_FILENAMES_FH stderr /* number of things to compute (used to compute size of countRecs[]) */ #define NUM_TOTALS 3 /* offsets into the countRecs[] and colWidth[] arrays */ #define C_RECS 0 #define C_BYTES 1 #define C_PKTS 2 /* * When generating output, this macro will evaluate to TRUE if the * record at position (i/3) is within the user-specified limits. Uses * the global limit variables. * * Since the only "limit" on rwtotal is to skip-zeroes, this macro * verifies that either skip_zeroes is false or one of the count * fields has a value. */ #define IS_RECORD_WITHIN_LIMITS(count_rec, i) \ (!skip_zeroes \ || (count_rec)[(i) + C_RECS] \ || (count_rec)[(i) + C_BYTES] \ || (count_rec)[(i) + C_PKTS]) /* EXPORTED VARIABLES */ int countMode; uint32_t totalRecs; int destFlag; iochecksInfoStruct_t *ioISP; int skip_zeroes = 0; int no_titles = 0; int no_columns = 0; char delimiter = '|'; int print_filenames = 0; /* name of program to run to page output */ char *pager = NULL; /* count of records */ uint64_t *countRecs = NULL; /* FUNCTION DEFINITIONS */ /* * countFile(file_name); * * Read the records from 'file_name' and add their byte, packet, * and flow counts to the appropriate bin. */ static void countFile(const char *inFName) { rwIOStruct_t *rwIOS; rwRec rwrec; uint32_t pointer = 0; /* open file */ rwIOS = rwOpenFile(inFName, ioISP->inputCopyFD); if (rwIOS == NULL) { skAppPrintErr("unable to open %s", inFName); exit(EXIT_FAILURE); } if (print_filenames) { fprintf(PRINT_FILENAMES_FH, "%s\n", rwGetFileName(rwIOS)); } while (rwRead(rwIOS, &rwrec)) { switch(countMode) { case RWTO_COPT_ADD8: pointer = (destFlag ? rwrec.dIP.ipnum : rwrec.sIP.ipnum) >> 24; break; case RWTO_COPT_ADD16: pointer = (destFlag ? rwrec.dIP.ipnum : rwrec.sIP.ipnum) >> 16; break; case RWTO_COPT_ADD24: pointer = (destFlag ? rwrec.dIP.ipnum : rwrec.sIP.ipnum) >> 8; break; case RWTO_COPT_LADD8: pointer = (destFlag ? rwrec.dIP.ipnum : rwrec.sIP.ipnum) & 0xFF; break; case RWTO_COPT_LADD16: pointer = (destFlag ? rwrec.dIP.ipnum : rwrec.sIP.ipnum) & 0xFFFF; break; case RWTO_COPT_PORT: pointer = (destFlag ? rwrec.dPort : rwrec.sPort); break; case RWTO_COPT_PROTO: pointer = rwrec.proto; break; case RWTO_COPT_PACKETS: /* if value is too large, fill final bin */ pointer = ((rwrec.pkts < totalRecs) ? rwrec.pkts : (totalRecs - 1)); break; case RWTO_COPT_BYTES: /* if value is too large, fill final bin */ pointer = ((rwrec.bytes < totalRecs) ? rwrec.bytes : (totalRecs - 1)); break; case RWTO_COPT_DURATION: pointer = rwrec.elapsed; break; case RWTO_COPT_ICMP: pointer = rwrec.dPort; break; default: skAppPrintErr("Unhandled option %d at %s:%d", countMode, __FILE__, __LINE__); exit(EXIT_FAILURE); } pointer *= NUM_TOTALS; countRecs[pointer + C_RECS]++; countRecs[pointer + C_BYTES] += rwrec.bytes; countRecs[pointer + C_PKTS] += rwrec.pkts; } /* close file */ rwCloseFile(rwIOS); rwIOS = (rwIOStruct_t *) NULL; return; } /* * dumpCounts(fh); * * Print the byte, packet, and flow counts to the named file handle * 'fh'. */ static void dumpCounts(FILE *outfp) { uint32_t i; uint32_t t; char buf[64]; const char * const fmt_count[] = { ("%11s%c%15" PRIu64 "%c%15" PRIu64 "%c%15" PRIu64 "%c\n"), ("%s%c%" PRIu64 "%c%" PRIu64 "%c%" PRIu64 "%c\n") }; const char * const fmt_title[] = { "%11s%c%15s%c%15s%c%15s%c\n", "%s%c%s%c%s%c%s%c\n" }; /* Print title */ if (!no_titles) { const char *key_name; switch (countMode) { case RWTO_COPT_ADD8: key_name = (destFlag ? "dIP_First8" : "sIP_First8"); break; case RWTO_COPT_ADD16: key_name = (destFlag ? "dIP_First16" : "sIP_First16"); break; case RWTO_COPT_ADD24: key_name = (destFlag ? "dIP_First24" : "sIP_First24"); break; case RWTO_COPT_LADD8: key_name = (destFlag ? "dIP_Last8" : "sIP_Last8"); break; case RWTO_COPT_LADD16: key_name = (destFlag ? "dIP_Last16" : "sIP_Last16"); break; case RWTO_COPT_PORT: key_name = (destFlag ? "dPort" : "sPort"); break; case RWTO_COPT_PROTO: key_name = "protocol"; break; case RWTO_COPT_PACKETS: key_name = "packets"; break; case RWTO_COPT_BYTES: key_name = "bytes"; break; case RWTO_COPT_DURATION: key_name = "elapsed"; break; case RWTO_COPT_ICMP: key_name = "icmpTypeCod"; break; default: skAppPrintErr("Unhandled option %d at %s:%d", countMode, __FILE__, __LINE__); exit(EXIT_FAILURE); } fprintf(outfp, fmt_title[no_columns], key_name, delimiter, "Records", delimiter, "Bytes", delimiter, "Packets", delimiter); } /* print bins */ for (t = 0, i = 0; t < totalRecs; ++t, i += NUM_TOTALS) { if (IS_RECORD_WITHIN_LIMITS(countRecs, i)) { switch (countMode) { case RWTO_COPT_ADD24: sprintf(buf, "%3u.%3u.%3u", (t >> 16), ((t >> 8) & 0xFF), (t & 0xFF)); break; case RWTO_COPT_ADD16: case RWTO_COPT_LADD16: sprintf(buf, "%3u.%3u", (t >> 8), (t & 0xFF)); break; case RWTO_COPT_ICMP: sprintf(buf, "%3u %3u", (t >> 8), (t & 0xFF)); break; default: sprintf(buf, "%u", t); break; } fprintf(outfp, fmt_count[no_columns], buf, delimiter, countRecs[i + C_RECS], delimiter, countRecs[i + C_BYTES], delimiter, countRecs[i + C_PKTS], delimiter); } } } int main(int argc, char **argv) { int counter; int using_pager = 0; FILE *stream_out; appSetup(argc, argv); /* never returns on error */ stream_out = ioISP->passFD[0]; /* * Alright, note that I'm actually condascending to use a malloc * here. Depending on what countRecs is doing (protocol is 256 * slots, /24's is 16 million); the number of bins can really * fluctuate. The array is unidimensional. */ countRecs = calloc(NUM_TOTALS * totalRecs, sizeof(uint64_t)); if (countRecs == NULL) { skAppPrintErr("Memory allocation error"); return 1; } /* Process each input stream/file */ for (counter = ioISP->firstFile; counter < ioISP->fileCount; counter++) { countFile(ioISP->fnArray[counter]); } /* Invoke the pager */ using_pager = skOpenPagerWhenStdoutTty(&stream_out, &pager); if (using_pager < 0) { exit(EXIT_FAILURE); } /* Print results */ dumpCounts(stream_out); /* close the pager */ if (using_pager) { skClosePager(stream_out, pager); } /* Done */ appTeardown(); return 0; } /* ** Local Variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */