/* ** Copyright (C) 2003-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@ */ /* ** A "plug-in" (currently compile-time only) for rwflowpack to ** process NetFlow v5 PDUs from a file. ** ** The file's length must be an integer multiple of 1464 bytes, where ** each 1464-byte block contains the 24-byte NetFlow v5 header and ** space for thirty 48-byte flow records. For a block holding fewer ** than 30 NetFlow records, the block should be padded to 1464 bytes. ** */ #include "silk.h" RCSIDENT("$SiLK: pdufilereader.c 6070 2007-01-22 18:03:49Z mthomas $"); #include "rwflowpack.h" #include "pdusource.h" #include "libflowsource.h" /* MACROS and DATA TYPES */ #define READER_TYPE_NAME "PDU File Reader" /* PRIVATE FUNCTIONS */ static int readerSetup( fp_daemon_mode_t *is_daemon, const sk_vector_t *probe_vec, reader_options_t *options); static void readerTeardown(void); static int readerStart(flow_proc_t *fproc); static int readerStop(flow_proc_t *fproc); static fp_get_record_result_t readerGetRecord( rwRec *out_rec, const probe_def_t **out_probe, flow_proc_t *fproc); static int readerWantProbe(probe_def_t *probe); static void readerPrintStats(const flow_proc_t *fproc); /* PRIVATE VARIABLES */ /* The file from which to read records */ /* FUNCTION DEFINITIONS */ /* * readerTeardown(); * * Destroy the PDU reader. * * Invoked by reader_type->teardown_fn(); */ static void readerTeardown(void) { /* nothing to do */ } /* * readerStart() * * Create a flowsource object that will read PDU records from a * file. * * Invoked by reader_type->start_fn(); */ static int readerStart(flow_proc_t *fproc) { const char *filename = skProbeGetFileSource(fproc->probe); pduSource_t pdu_src; /* if a pdu_src already exists, just return. */ if (fproc->flow_src != NULL) { return 0; } if (filename == NULL) { skAppPrintErr("Probe not configured for reading from file"); logMsg("Probe not configured for reading from file"); return -1; } pdu_src = pduFileSourceCreate(filename, &logMsg); if (pdu_src == NULL) { skAppPrintErr("Could not create PDU source from file '%s'", filename); logMsg("Could not create PDU source from file '%s'", filename); return -1; } /* TODO: The below should use the log flags as returned from probeconf, but is left as-is until we have the time to make sure the change of default value will not bother our clients. pduSourceSetLogopt(pdu_src, skProbeGetLogFlags(fproc->probe)); */ /* Reduce verbosity of log */ pduSourceSetLogopt(pdu_src, SOURCE_LOG_BAD); fproc->flow_src = pdu_src; return 0; } /* * readerStop(); * * Stop reading records. * * Invoked by reader_type->stop_fn(); */ static int readerStop(flow_proc_t *fproc) { pduSource_t pdu_src = (pduSource_t)fproc->flow_src; if (pdu_src) { pduSourceDestroy(pdu_src); fproc->flow_src = NULL; } return 0; } /* * readerPrintStats(filename); * * Print to the log the statistics associated with the flowsource * file object 'filename'. */ static void readerPrintStats(const flow_proc_t *fproc) { const char *filename = skProbeGetFileSource(fproc->probe); pduSource_t pdu_src = (pduSource_t)fproc->flow_src; flowcap_stats_t stats; pduSourceGetStats(pdu_src, &stats); logMsg(("%s: Pkts %10" PRIu64 "/%" PRIu64 " Recs %10" PRIu64 " MissRecs %10" PRIu64 " BadRecs %10" PRId64), filename, (stats.procPkts - stats.badPkts), stats.procPkts, stats.goodRecs, stats.missingRecs, (stats.badRecs + fproc->rec_count_bad)); } /* * readerGetRecord(&out_rwrec, &out_probe); * * Fill 'out_rwrec' with an rw generic record from the underlying * flowsource object connected to a file. Fill 'out_probe' with * the probe where the flow was collected. * * Invoked by reader_type->get_record_fn(); */ static fp_get_record_result_t readerGetRecord( rwRec *out_rwrec, const probe_def_t **out_probe, flow_proc_t *fproc) { pduSource_t pdu_src = (pduSource_t)fproc->flow_src; const char *filename; if (-1 != pduSourceGetGeneric(pdu_src, out_rwrec)) { /* got a record */ *out_probe = fproc->probe; /* When reading from a file, should only stop at the end of a * file. */ return FP_RECORD; } /* At end of file */ /* print stats for file */ readerPrintStats(fproc); /* archive file if requested */ filename = skProbeGetFileSource(fproc->probe); archiveFile(filename); /* We can stop here. */ return FP_END_STREAM; } /* * pduFileReaderInitialize: * * Set initial state of this flow reader. * * Invoked by reader_type->initialize_fn(); */ int pduFileReaderInitialize(reader_type_t *reader_type) { /* Set my name */ reader_type->reader_name = READER_TYPE_NAME; /* Set function pointers */ reader_type->setup_fn = &readerSetup; reader_type->teardown_fn = &readerTeardown; reader_type->start_fn = &readerStart; reader_type->stop_fn = &readerStop; reader_type->get_record_fn = &readerGetRecord; reader_type->want_probe_fn = &readerWantProbe; return 0; } /* * yes_or_no = readerWantProbe(probe); * * Return a TRUE value this reader_type is able to process the data * from the 'probe'; return a FALSE value otherwise. */ static int readerWantProbe(probe_def_t *probe) { /* This is what we expect, a NetFlow based file reader */ if ((NULL != skProbeGetFileSource(probe)) && (PROBE_ENUM_NETFLOW == skProbeGetType(probe))) { return 1; } return 0; } /* * status = readerSetup(&out_daemon_mode, probe_vector, options); * * The reader_type should do any setup it requires prior to * starting its flow_processor instances: Validate and/or store the * reader_type's 'options'. 'probe_vector' is the list of probes * that this reader_type said it would process * (readerWantProbe). 'out_daemon_mode' should be set according * to how this reader_type expects to run. * * Invoked by reader_type->setup_fn(); */ static int readerSetup( fp_daemon_mode_t *is_daemon, const sk_vector_t *probe_vec, reader_options_t *options) { size_t count = skVectorGetCount(probe_vec); const char *netflow_file = options->pdu_file.netflow_file; probe_def_t *p; /* this function should only be called if we actually have probes * to process */ if (count == 0) { return 1; } if (count > 1) { skAppPrintErr("Only support one file-based probe."); return -1; } if (NULL != netflow_file) { /* Modify the probe to have the file name given on the command * line. */ if (0 == skVectorGetValue(&p, probe_vec, 0)) { if (skProbeSetFileSource(p, netflow_file)) { skAppPrintErr("Cannot change file source of probe"); return 1; } } } /* Not a deamon */ *is_daemon = FP_DAEMON_OFF; return 0; } /* ** Local variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */