static inline void New_Hash_Key(void *keymem, master_record_t *flow_record, int swap_flow) { uint64_t *record = (uint64_t *)flow_record; Default_key_t *keyptr; // apply src/dst mask bits if requested if ( FlowTable.apply_netbits ) { ApplyNetMaskBits(flow_record, FlowTable.apply_netbits); } if ( aggregate_stack ) { // custom user aggregation aggregate_param_t *aggr_param = aggregate_stack; while ( aggr_param->size ) { uint64_t val = (record[aggr_param->offset] & aggr_param->mask) >> aggr_param->shift; switch ( aggr_param->size ) { case 8: { uint64_t *_v = (uint64_t *)keymem; *_v = val; keymem += sizeof(uint64_t); } break; case 4: { uint32_t *_v = (uint32_t *)keymem; *_v = val; keymem += sizeof(uint32_t); } break; case 2: { uint16_t *_v = (uint16_t *)keymem; *_v = val; keymem += sizeof(uint16_t); } break; case 1: { uint8_t *_v = (uint8_t *)keymem; *_v = val; keymem += sizeof(uint8_t); } break; default: fprintf(stderr, "Panic: Software error in %s line %d\n", __FILE__, __LINE__); exit(255); } // switch aggr_param++; } // while } else if ( swap_flow ) {
int ExportFlowTable(nffile_t *nffile, int aggregate, int bidir, int date_sorted, extension_map_list_t *extension_map_list) { hash_FlowTable *FlowTable; FlowTableRecord_t *r; SortElement_t *SortList; master_record_t *aggr_record_mask; uint32_t i; uint32_t maxindex, c; #ifdef DEVEL char *string; #endif ExportExtensionMaps(aggregate, bidir, nffile, extension_map_list); ExportExporterList(nffile); aggr_record_mask = GetMasterAggregateMask(); FlowTable = GetFlowTable(); c = 0; maxindex = FlowTable->NumRecords; if ( date_sorted ) { // Sort records according the date SortList = (SortElement_t *)calloc(maxindex, sizeof(SortElement_t)); if ( !SortList ) { LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror (errno)); return 0; } // preset SortList table - still unsorted for ( i=0; i<=FlowTable->IndexMask; i++ ) { r = FlowTable->bucket[i]; if ( !r ) continue; // foreach elem in this bucket while ( r ) { SortList[c].count = 1000LL * r->flowrecord.first + r->flowrecord.msec_first; // sort according the date SortList[c].record = (void *)r; c++; r = r->next; } } if ( c != maxindex ) { LogError("Abort: Mismatch %s line %d: %s\n", __FILE__, __LINE__, strerror (errno)); return 0; } if ( c >= 2 ) heapSort(SortList, c, 0); for ( i = 0; i < c; i++ ) { master_record_t *flow_record; common_record_t *raw_record; extension_info_t *extension_info; r = (FlowTableRecord_t *)(SortList[i].record); raw_record = &(r->flowrecord); extension_info = r->map_info_ref; flow_record = &(extension_info->master_record); ExpandRecord_v2( raw_record, extension_info, r->exp_ref, flow_record); flow_record->dPkts = r->counter[INPACKETS]; flow_record->dOctets = r->counter[INBYTES]; flow_record->out_pkts = r->counter[OUTPACKETS]; flow_record->out_bytes = r->counter[OUTBYTES]; flow_record->aggr_flows = r->counter[FLOWS]; // apply IP mask from aggregation, to provide a pretty output if ( FlowTable->has_masks ) { flow_record->V6.srcaddr[0] &= FlowTable->IPmask[0]; flow_record->V6.srcaddr[1] &= FlowTable->IPmask[1]; flow_record->V6.dstaddr[0] &= FlowTable->IPmask[2]; flow_record->V6.dstaddr[1] &= FlowTable->IPmask[3]; } if ( FlowTable->apply_netbits ) ApplyNetMaskBits(flow_record, FlowTable->apply_netbits); if ( aggr_record_mask ) { ApplyAggrMask(flow_record, aggr_record_mask); } // switch to output extension map flow_record->map_ref = extension_info->map; flow_record->ext_map = extension_info->map->map_id; PackRecord(flow_record, nffile); #ifdef DEVEL format_file_block_record((void *)flow_record, &string, 0); printf("%s\n", string); #endif // Update statistics UpdateStat(nffile->stat_record, flow_record); } } else { // print them as they came for ( i=0; i<=FlowTable->IndexMask; i++ ) { r = FlowTable->bucket[i]; while ( r ) { master_record_t *flow_record; common_record_t *raw_record; extension_info_t *extension_info; raw_record = &(r->flowrecord); extension_info = r->map_info_ref; flow_record = &(extension_info->master_record); ExpandRecord_v2( raw_record, extension_info, r->exp_ref, flow_record); flow_record->dPkts = r->counter[INPACKETS]; flow_record->dOctets = r->counter[INBYTES]; flow_record->out_pkts = r->counter[OUTPACKETS]; flow_record->out_bytes = r->counter[OUTBYTES]; flow_record->aggr_flows = r->counter[FLOWS]; // apply IP mask from aggregation, to provide a pretty output if ( FlowTable->has_masks ) { flow_record->V6.srcaddr[0] &= FlowTable->IPmask[0]; flow_record->V6.srcaddr[1] &= FlowTable->IPmask[1]; flow_record->V6.dstaddr[0] &= FlowTable->IPmask[2]; flow_record->V6.dstaddr[1] &= FlowTable->IPmask[3]; } if ( FlowTable->apply_netbits ) ApplyNetMaskBits(flow_record, FlowTable->apply_netbits); if ( aggr_record_mask ) { ApplyAggrMask(flow_record, aggr_record_mask); } // switch to output extension map flow_record->map_ref = extension_info->map; flow_record->ext_map = extension_info->map->map_id; PackRecord(flow_record, nffile); #ifdef DEVEL format_file_block_record((void *)flow_record, &string, 0); printf("%s\n", string); #endif // Update statistics UpdateStat(nffile->stat_record, flow_record); r = r->next; } } } if ( nffile->block_header->NumRecords ) { if ( WriteBlock(nffile) <= 0 ) { LogError("Failed to write output buffer to disk: '%s'" , strerror(errno)); return 0; } } return 1; } // End of ExportFlowTable