/* ** Copyright (C) 2004-2006 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@ */ /* ** Interface for converting from NetFlow v5 PDUs (aka cflowd records) ** */ #include "silk.h" RCSIDENT("$SiLK: convert-cflowd.c 4876 2006-09-14 21:18:03Z mthomas $"); #include "convert-cflowd.h" #include "convert-flowcap.h" /* ** CONVERTIME(t, rtr_boot_time); ** ** Converts IN PLACE the integer 't' that represents the 'First' or ** 'Last' field in a cflowd record---milliseconds since router ** booted---to a value in unix epoch seconds/milliseconds by adding ** the cflowdTimeInfo_t object 'rtr_boot_time' which represents the ** router's boot time. All are assumed to be in the local endian ** order. */ #ifdef CONVERTTIME #undef CONVERTTIME #endif #define CONVERTTIME(t, info) \ do { (t).quot += (info).rtr_unix_secs; \ (t).rem += (info).rtr_unix_msecs; \ if ((t).rem >= 1000) { \ (t).rem -= 1000; \ (t).quot++; \ } } while (0) static const imaxdiv_t rolloverAdjust = { UINT32_MAX / 1000, UINT32_MAX % 1000 + 1 /* The +1 is to make the difference 2^32 */ }; /* Number of milliseconds to adjust the SysUptime when determining event ordering. Routers are producing PDUs which are advertising times *before* the flow start and end times. */ const intmax_t sysUptimeAdjustMsecs = 1000 * 60 * 5; #define ROLLOVER32 ((intmax_t)UINT32_MAX + 1) #define ADJUST_FOR_ROLLOVER(t) \ do { (t).quot -= rolloverAdjust.quot; \ (t).rem -= rolloverAdjust.rem; \ if ((t).rem < 0) { \ (t).rem += 1000; \ (t).quot--; \ } } while (0) /* Encapsulates information from a netflowV5 header. The resulting * cflowdTimeInfo_t is used to do time calculations when processing * individual records. */ void cflowdTimeInfoSetup(const v5Header *hdr, cflowdTimeInfo_t *ti) { imaxdiv_t hdr_sys; imaxdiv_t hdr_unix; ti->sysUptime = ntohl(hdr->SysUptime); /* sysUpTime is in milliseconds, convert to seconds/milliseconds */ hdr_sys = imaxdiv(ti->sysUptime, 1000); /* unix seconds/nanoseconds to seconds/milliseconds */ hdr_unix.quot = ntohl(hdr->unix_secs); /* Round by adding 5e5 before dividing. */ hdr_unix.rem = (ntohl(hdr->unix_nsecs) + 5e5L) / 1e6L; /* subtract sysUpTime from unix seconds */ hdr_unix.quot -= hdr_sys.quot; /* borrow a sec? */ if (hdr_sys.rem > hdr_unix.rem) { --hdr_unix.quot; hdr_unix.rem += 1000; } hdr_unix.rem -= hdr_sys.rem; ti->rtr_unix_secs = hdr_unix.quot; ti->rtr_unix_msecs = hdr_unix.rem; /* See the comment for sysUptimeAdjustMsecs */ ti->sysUptime += sysUptimeAdjustMsecs; } /* Fills out a flowcap record from a v5pdu record. The variable 'ti' * can be NULL, in which case the start time will not necessarily * reflect reality. Version is the version of flowcapRec used. * Returns -1 on error, 0 on success. */ int cflowdToFlowcap( const v5Record *v5RPtr, flowcapRec_t *flowcap_rec, int flowcap_version, cflowdTimeInfo_t *ti) { rwRec rwrec; int rv; rv = cflowdToGeneric(v5RPtr, &rwrec, ti); if (rv) { return rv; } return genericToFlowcap(&rwrec, flowcap_rec, flowcap_version); } /* Fills out a rwRec from a v5pdu record. * The variable ti can be NULL, in which case the start time will not * necessarily reflect reality. */ int cflowdToGeneric( const v5Record *v5RPtr, rwRec *rwrec, cflowdTimeInfo_t *ti) { intmax_t s, e; imaxdiv_t sTime; imaxdiv_t duration; memset(rwrec, 0, sizeof(*rwrec)); /* Setup start and duration */ e = ntohl(v5RPtr->Last); s = ntohl(v5RPtr->First); if (s > e) { /* End has rolled over, while start has not. Adjust end by 2^32 msecs in order to allow us to subtract start from end and get a correct value. */ e += ROLLOVER32; } sTime = imaxdiv(s, 1000); if (ti) { /* Convert sTime to unix epoch times */ CONVERTTIME(sTime, *ti); /* Check to see if the start time is greater than the sysUptime. This should mean that the start time has rolled over. Note: sysUptime has been adjusted by sysUptimeAdjustMsecs in order to account for the fact that sysUptime has been found to be slightly less than the end time in real Cisco netflow data. This adjustment has been specifically done as a >32 bit value: i.e., _without_ rolling over. */ if (s > ti->sysUptime) { /* If the start time has rolled over, adjust the date forward by 2^32 msecs. */ ADJUST_FOR_ROLLOVER(sTime); } } duration = imaxdiv(e - s, 1000); assert(duration.quot <= UINT32_MAX); rwrec->sIP.ipnum = ntohl(v5RPtr->srcaddr.ipnum); rwrec->dIP.ipnum = ntohl(v5RPtr->dstaddr.ipnum); rwrec->sPort = ntohs(v5RPtr->srcport); rwrec->dPort = ntohs(v5RPtr->dstport); rwrec->proto = v5RPtr->prot; rwrec->flags = v5RPtr->tcp_flags; rwrec->input = ntohs(v5RPtr->input); rwrec->output = ntohs(v5RPtr->output); rwrec->nhIP.ipnum = ntohl(v5RPtr->nexthop.ipnum); rwrec->sTime = sTime.quot; rwrec->sTime_msec = sTime.rem; rwrec->pkts = ntohl(v5RPtr->dPkts); rwrec->bytes = ntohl(v5RPtr->dOctets); rwrec->elapsed = duration.quot; rwrec->elapsed_msec = duration.rem; rwrec->rest_flags = 0; rwrec->tcp_state = SK_TCPSTATE_NO_INFO; rwrec->application = 0; return 0; } /* ** Local variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */