/* ** Copyright (C) 2004-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@ */ /* ** Functions to support binary output: opening binary SiLK files for ** writing or appending. ** */ #include "silk.h" RCSIDENT("$SiLK: rwpack.c 6070 2007-01-22 18:03:49Z mthomas $"); #include "librw_priv.h" /* Convert bytes and packets fields in 'rwRP' to the values used in * rwfilter output files and in the packed file formats. See * librw_priv.h. */ int _packPackBytesPackets( uint32_t *bpp_out, uint32_t *pkts_out, uint32_t *pflag_out, const rwGenericRec_V3 *rwRP) { #define VERIFY_BPP 1 /* whether to verify bpp value in rwRP */ uint32_t packets; uint32_t bytes; assert(bpp_out); assert(pkts_out); assert(pflag_out); assert(rwRP); /* Check for 0 value in 'pkts' field */ packets = rwRP->pkts; if (packets == 0) { return LIBRW_ERR_PKTS_ZERO; } #if 0 /* Verify that there are more bytes than packets */ if (packets > rwRP->bytes) { return LIBRW_ERR_PKTS_GT_BYTES; } #endif /* Set packets field; check for overflow */ if (packets < MAX_PKTS) { *pkts_out = packets; *pflag_out = 0; } else { *pkts_out = packets / PKTS_DIVISOR; if (*pkts_out >= MAX_PKTS) { /* Double overflow in pkts */ return LIBRW_ERR_PKTS_OVRFLO; } /* pktsFlag */ *pflag_out = 1; } /* Use the bytes-per-packet field on rwGeneric if it is non-zero; * otherwise compute it. */ /* bpp: uint32_t bPPkt:14; uint32_t bPPFrac:6; */ if ((rwRP->bpp != 0) && !VERIFY_BPP) { /* use value as is */ *bpp_out = rwRP->bpp; } else { /* compute new value */ bytes = rwRP->bytes; *bpp_out = (((bytes / packets) << 6) | ((BPP_PRECN * (bytes % packets)) / packets)); #if VERIFY_BPP /* ignore fractional part in comparison */ if ((rwRP->bpp >> 6) == (*bpp_out >> 6)) { /* two values are equal, use the value from the rwrec. */ *bpp_out = rwRP->bpp; } else if (rwRP->bpp != 0) { /* don't print warning if bpp on rwrec was zero */ skAppPrintErr("Bad value in bpp field"); } #endif /* VERIFY_BPP */ } return LIBRW_OK; } /* Fill in the bytes and packets fields in rwRP by expanding the * values that were read from disk. See librw_priv.h for details. */ void _packUnpackBytesPackets( rwGenericRec_V3 *rwRP, uint32_t bpp, uint32_t pkts, uint32_t pflag) { uint32_t bytes; int bPPkt, bPPFrac; div_t i; if (pflag) { pkts *= PKTS_DIVISOR; } /* Unpack the bpp value: bPPkt:14; bPPFrac:6; */ bPPkt = GET_MASKED_BITS(bpp, 6, 14); bPPFrac = GET_MASKED_BITS(bpp, 0, 6); /* convert fraction to whole number */ i = div((bPPFrac * pkts), BPP_PRECN); bytes = ((bPPkt * pkts) + i.quot + ((i.rem >= BPP_PRECN_DIV_2) ? 1 : 0)); rwRP->pkts = pkts; rwRP->bytes = bytes; rwRP->bpp = bpp; } /* Pack the protocol, flags, and TCP state fields. See librw_priv.h */ void _packPackProtoFlags( uint8_t *is_tcp_out, uint8_t *prot_flags_out, uint8_t *tcp_state_out, uint8_t *rest_flags_out, const rwGenericRec_V3 *rwRP) { if (rwRP->proto != 6) { /* Flow is not TCP, so there is no additional TCP info. Set * '*rest_flags_out' to value of rwRP->flags. */ *is_tcp_out = 0; *prot_flags_out = rwRP->proto; *tcp_state_out = 0; *rest_flags_out = rwRP->flags; } else { /* Flow is TCP */ *is_tcp_out = 1; if (rwRP->tcp_state == 0) { /* There is no additional TCP info. */ *prot_flags_out = rwRP->flags; *tcp_state_out = 0; *rest_flags_out = 0; } else { /* There is additional TCP info. Put the initial TCP * flags into the '*prot_flags_out' value. */ *prot_flags_out = rwRP->init_flags; *tcp_state_out = rwRP->tcp_state; *rest_flags_out = rwRP->rest_flags; } } } /* Fill in the protocol, flags, and TCP state fields on the rwRP. See * librw_priv.h */ void _packUnpackProtoFlags( rwGenericRec_V3 *rwRP, uint8_t is_tcp, uint8_t prot_flags, uint8_t tcp_state, uint8_t rest_flags) { /* For some record types (e.g., RWWWW), proto is fixed at 6(TCP) * and there may be another value in the 'is_tcp' bit; ignore the * 'is_tcp' bit if the protocol is already set to TCP. */ if ((rwRP->proto == 6) || (is_tcp == 1)) { /* Flow is TCP */ rwRP->proto = 6; if (tcp_state == 0) { /* We don't have additional TCP info; 'prot_flags' holds * the flags. */ rwRP->flags = prot_flags; } else { /* We have additional flow information; value in * prot_flags are the flags on the first packet. */ rwRP->tcp_state = tcp_state; rwRP->init_flags = prot_flags; rwRP->rest_flags = rest_flags; rwRP->flags = (uint8_t)(prot_flags | rest_flags); } } else { /* Flow is not TCP so there can be no additional TCP info. * 'prot_flags' holds the protocol. Although 'flags' has no * real meaning here, the 'rest_flags' value has the value * that we got from the flow collector, so set 'rwRP->flags' * to that value. */ rwRP->proto = prot_flags; rwRP->flags = rest_flags; } } /* Compute the 'sbb' and 'pef' fields used in packed file formats. * See librw_priv.h. */ int _packPackSbbPef( uint32_t *sbb_out, uint32_t *pef_out, const rwGenericRec_V3 *rwRP, uint32_t file_start_time) { int rv = LIBRW_OK; /* return value */ uint32_t start_time; uint32_t pkts, bpp, pflag; if (rwRP->elapsed >= MAX_ELAPSED_TIME_OLD) { rv = LIBRW_ERR_ELPSD_OVRFLO; goto END; } if (rwRP->sTime < file_start_time) { rv = LIBRW_ERR_STIME_UNDRFLO; goto END; } start_time = rwRP->sTime - file_start_time; if (start_time >= MAX_START_TIME) { rv = LIBRW_ERR_STIME_OVRFLO; goto END; } rv = _packPackBytesPackets(&bpp, &pkts, &pflag, rwRP); if (rv) { goto END; } /* sbb: uint32_t sTime:12; uint32_t bPPkt:14; uint32_t bPPFrac:6; */ *sbb_out = ((start_time << 20) | (bpp & MASKARRAY_20)); /* pef: uint32_t pkts:20; uint32_t elapsed :11; uint32_t pktsFlag:1; */ *pef_out = ((pkts << 12) | (rwRP->elapsed << 1) | pflag); END: return rv; } /* Set values in rwRP by expanding the 'sbb' and 'pef' fields that * exist in the packed file formats. See librw_priv.h for details. */ void _packUnpackSbbPef( rwGenericRec_V3 *rwRP, uint32_t file_start_time, const uint32_t *sbb, const uint32_t *pef) { uint32_t pkts, pktsFlag, bpp, start_time; /* pef: uint32_t pkts:20; uint32_t elapsed :11; uint32_t pktsFlag:1; */ pkts = *pef >> 12; rwRP->elapsed = (*pef >> 1) & MASKARRAY_11; pktsFlag = *pef & MASKARRAY_01; /* sbb: uint32_t start_time:12; uint32_t bpp:20 */ bpp = *sbb & MASKARRAY_20; start_time = *sbb >> 20; rwRP->sTime = file_start_time + start_time; _packUnpackBytesPackets(rwRP, bpp, pkts, pktsFlag); } int _packPackTimeBytesPktsFlags( uint32_t *pkts_stime_out, uint32_t *bbe_out, uint32_t *msec_flags_out, const rwGenericRec_V3 *rwRP, uint32_t file_start_time) { int rv = LIBRW_OK; /* return value */ uint32_t start_time; uint32_t pkts, bpp, pflag, is_tcp; uint8_t prot_flags; if (rwRP->elapsed >= MAX_ELAPSED_TIME) { rv = LIBRW_ERR_ELPSD_OVRFLO; goto END; } if (rwRP->sTime < file_start_time) { rv = LIBRW_ERR_STIME_UNDRFLO; goto END; } start_time = rwRP->sTime - file_start_time; if (start_time >= MAX_START_TIME) { rv = LIBRW_ERR_STIME_OVRFLO; goto END; } rv = _packPackBytesPackets(&bpp, &pkts, &pflag, rwRP); if (rv) { goto END; } /* pkts_stime: pkts:20; sTime: 12; */ *pkts_stime_out = ((pkts << 12) | start_time); /* bbe: bpp: 20; elapsed: 12 */ *bbe_out = ((bpp << 12) | rwRP->elapsed); /* set is_tcp bit and prot_flags */ if (rwRP->proto == 6) { is_tcp = 1; prot_flags = rwRP->flags; } else { is_tcp = 0; prot_flags = rwRP->proto; } /* msec_flags: sTime_msec:10; elaps_msec:10; pflag:1; * is_tcp:1; pad:2; prot_flags:8;*/ *msec_flags_out = ((rwRP->sTime_msec << 22) | ((rwRP->elapsed_msec & MASKARRAY_10) << 12) | (pflag ? (1 << 11) : 0) | (is_tcp ? (1 << 10) : 0) | prot_flags); END: return rv; } void _packUnpackTimeBytesPktsFlags( rwGenericRec_V3 *rwRP, uint32_t file_start_time, const uint32_t *pkts_stime, const uint32_t *bbe, const uint32_t *msec_flags) { uint32_t pkts, bpp, is_tcp, pflag; uint8_t prot_flags; /* pkts_stime: pkts:20; sTime: 12; */ pkts = GET_MASKED_BITS(*pkts_stime, 12, 20); rwRP->sTime = file_start_time + GET_MASKED_BITS(*pkts_stime, 0, 12); /* bbe: bpp: 20; elapsed: 12 */ bpp = GET_MASKED_BITS(*bbe, 12, 20); rwRP->elapsed = GET_MASKED_BITS(*bbe, 0, 12); /* msec_flags: sTime_msec:10; elaps_msec:10; pflag:1; * is_tcp:1; pad:2, prot_flags:8; */ rwRP->sTime_msec = GET_MASKED_BITS(*msec_flags, 22, 10); rwRP->elapsed_msec = GET_MASKED_BITS(*msec_flags, 12, 10); pflag = GET_MASKED_BITS(*msec_flags, 11, 1); is_tcp = GET_MASKED_BITS(*msec_flags, 10, 1); prot_flags = (uint8_t)GET_MASKED_BITS(*msec_flags, 0, 8); if (rwRP->proto == 6) { /* caller has forced record to be TCP */ rwRP->flags = prot_flags; } else if (is_tcp == 0) { /* flow is not TCP */ rwRP->proto = prot_flags; } else { /* flow is TCP */ rwRP->proto = 6; rwRP->flags = prot_flags; } /* unpack the bpp value into bytes and packets */ _packUnpackBytesPackets(rwRP, bpp, pkts, pflag); } /* ** Local variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */