Fix security issues in netflow_v9.c and ipfix.c

This commit is contained in:
Peter Haag 2016-05-07 08:35:34 +02:00
parent aeb703c762
commit ff0e855bd1
2 changed files with 98 additions and 71 deletions

View File

@ -42,7 +42,6 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <syslog.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
@ -322,7 +321,7 @@ int i;
cache.lookup_info = (struct element_param_s *)calloc(65536, sizeof(struct element_param_s)); cache.lookup_info = (struct element_param_s *)calloc(65536, sizeof(struct element_param_s));
cache.common_extensions = (uint32_t *)malloc((Max_num_extensions+1)*sizeof(uint32_t)); cache.common_extensions = (uint32_t *)malloc((Max_num_extensions+1)*sizeof(uint32_t));
if ( !cache.common_extensions || !cache.lookup_info ) { if ( !cache.common_extensions || !cache.lookup_info ) {
syslog(LOG_ERR, "Process_ipfix: Panic! malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError("Process_ipfix: Panic! malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return 0; return 0;
} }
@ -336,7 +335,7 @@ int i;
} }
cache.max_ipfix_elements = i; cache.max_ipfix_elements = i;
syslog(LOG_DEBUG,"Init IPFIX: Max number of IPFIX tags: %u", cache.max_ipfix_elements); LogError("Init IPFIX: Max number of IPFIX tags: %u", cache.max_ipfix_elements);
return 1; return 1;
@ -370,7 +369,7 @@ uint32_t ObservationDomain = ntohl(ipfix_header->ObservationDomain);
// nothing found // nothing found
*e = (exporter_ipfix_domain_t *)malloc(sizeof(exporter_ipfix_domain_t)); *e = (exporter_ipfix_domain_t *)malloc(sizeof(exporter_ipfix_domain_t));
if ( !(*e)) { if ( !(*e)) {
syslog(LOG_ERR, "Process_ipfix: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError("Process_ipfix: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return NULL; return NULL;
} }
memset((void *)(*e), 0, sizeof(exporter_ipfix_domain_t)); memset((void *)(*e), 0, sizeof(exporter_ipfix_domain_t));
@ -392,7 +391,7 @@ uint32_t ObservationDomain = ntohl(ipfix_header->ObservationDomain);
dbg_printf("[%u] New exporter: SysID: %u, Observation domain %u from: %s\n", dbg_printf("[%u] New exporter: SysID: %u, Observation domain %u from: %s\n",
ObservationDomain, (*e)->info.sysid, ObservationDomain, ipstr); ObservationDomain, (*e)->info.sysid, ObservationDomain, ipstr);
syslog(LOG_INFO, "Process_ipfix: New exporter: SysID: %u, Observation domain %u from: %s\n", LogInfo("Process_ipfix: New exporter: SysID: %u, Observation domain %u from: %s\n",
(*e)->info.sysid, ObservationDomain, ipstr); (*e)->info.sysid, ObservationDomain, ipstr);
@ -460,12 +459,12 @@ input_translation_t **table;
// so template refreshing may change the table size without danger of overflowing // so template refreshing may change the table size without danger of overflowing
*table = calloc(1, sizeof(input_translation_t)); *table = calloc(1, sizeof(input_translation_t));
if ( !(*table) ) { if ( !(*table) ) {
syslog(LOG_ERR, "Process_ipfix: Panic! calloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError("Process_ipfix: Panic! calloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return NULL; return NULL;
} }
(*table)->sequence = calloc(cache.max_ipfix_elements, sizeof(sequence_map_t)); (*table)->sequence = calloc(cache.max_ipfix_elements, sizeof(sequence_map_t));
if ( !(*table)->sequence ) { if ( !(*table)->sequence ) {
syslog(LOG_ERR, "Process_ipfix: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError("Process_ipfix: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return NULL; return NULL;
} }
@ -481,7 +480,7 @@ input_translation_t **table;
static void remove_translation_table(FlowSource_t *fs, exporter_ipfix_domain_t *exporter, uint16_t id) { static void remove_translation_table(FlowSource_t *fs, exporter_ipfix_domain_t *exporter, uint16_t id) {
input_translation_t *table, *parent; input_translation_t *table, *parent;
syslog(LOG_INFO, "Process_ipfix: [%u] Withdraw template id: %i", LogInfo("Process_ipfix: [%u] Withdraw template id: %i",
exporter->info.id, id); exporter->info.id, id);
parent = NULL; parent = NULL;
@ -492,7 +491,7 @@ input_translation_t *table, *parent;
} }
if ( table == NULL ) { if ( table == NULL ) {
syslog(LOG_ERR, "Process_ipfix: [%u] Withdraw template id: %i. translation table not found", LogError("Process_ipfix: [%u] Withdraw template id: %i. translation table not found",
exporter->info.id, id); exporter->info.id, id);
return; return;
} }
@ -521,7 +520,7 @@ input_translation_t *table, *parent;
static void remove_all_translation_tables(exporter_ipfix_domain_t *exporter) { static void remove_all_translation_tables(exporter_ipfix_domain_t *exporter) {
input_translation_t *table, *next; input_translation_t *table, *next;
syslog(LOG_INFO, "Process_ipfix: Withdraw all templates from observation domain %u\n", LogInfo("Process_ipfix: Withdraw all templates from observation domain %u\n",
exporter->info.id); exporter->info.id);
table = exporter->input_translation_table; table = exporter->input_translation_table;
@ -548,7 +547,7 @@ uint32_t i = table->number_of_sequences;
uint32_t index = cache.lookup_info[Type].index; uint32_t index = cache.lookup_info[Type].index;
if ( table->number_of_sequences >= cache.max_ipfix_elements ) { if ( table->number_of_sequences >= cache.max_ipfix_elements ) {
syslog(LOG_ERR, "Process_ipfix: Software bug! Sequence table full. at %s line %d", LogError("Process_ipfix: Software bug! Sequence table full. at %s line %d",
__FILE__, __LINE__); __FILE__, __LINE__);
dbg_printf("Software bug! Sequence table full. at %s line %d", dbg_printf("Software bug! Sequence table full. at %s line %d",
__FILE__, __LINE__); __FILE__, __LINE__);
@ -584,7 +583,7 @@ size_t size_required;
table = GetTranslationTable(exporter, id); table = GetTranslationTable(exporter, id);
if ( !table ) { if ( !table ) {
syslog(LOG_INFO, "Process_ipfix: [%u] Add template %u", exporter->info.id, id); LogInfo("Process_ipfix: [%u] Add template %u", exporter->info.id, id);
table = add_translation_table(exporter, id); table = add_translation_table(exporter, id);
if ( !table ) { if ( !table ) {
return NULL; return NULL;
@ -597,7 +596,7 @@ size_t size_required;
size_required = (size_required + 3) &~(size_t)3; size_required = (size_required + 3) &~(size_t)3;
extension_map = malloc(size_required); extension_map = malloc(size_required);
if ( !extension_map ) { if ( !extension_map ) {
syslog(LOG_ERR, "Process_ipfix: Panic! malloc() error in %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError("Process_ipfix: Panic! malloc() error in %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return NULL; return NULL;
} }
extension_map->type = ExtensionMapType; extension_map->type = ExtensionMapType;
@ -912,6 +911,13 @@ uint16_t Offset = 0;
// a template flowset can contain multiple records ( templates ) // a template flowset can contain multiple records ( templates )
while ( size_left ) { while ( size_left ) {
if ( size_left && size_left < 4 ) {
LogError("Process_ipfix [%u] Template size error at %s line %u" ,
exporter->info.id, __FILE__, __LINE__, strerror (errno));
size_left = 0;
continue;
}
// clear helper tables // clear helper tables
memset((void *)cache.common_extensions, 0, (Max_num_extensions+1)*sizeof(uint32_t)); memset((void *)cache.common_extensions, 0, (Max_num_extensions+1)*sizeof(uint32_t));
memset((void *)cache.lookup_info, 0, 65536 * sizeof(struct element_param_s)); memset((void *)cache.lookup_info, 0, 65536 * sizeof(struct element_param_s));
@ -940,7 +946,7 @@ uint16_t Offset = 0;
size_required = 4*count; size_required = 4*count;
if ( size_left < size_required ) { if ( size_left < size_required ) {
// if we fail this check, this flowset must be skipped. // if we fail this check, this flowset must be skipped.
syslog(LOG_ERR, "Process_ipfix: [%u] Not enough data for template elements! required: %i, left: %u", LogError("Process_ipfix: [%u] Not enough data for template elements! required: %i, left: %u",
exporter->info.id, size_required, size_left); exporter->info.id, size_required, size_left);
dbg_printf("ERROR: Not enough data for template elements! required: %i, left: %u", size_required, size_left); dbg_printf("ERROR: Not enough data for template elements! required: %i, left: %u", size_required, size_left);
return; return;
@ -974,7 +980,7 @@ uint16_t Offset = 0;
ipfix_template_elements_e_t *e = (ipfix_template_elements_e_t *)NextElement; ipfix_template_elements_e_t *e = (ipfix_template_elements_e_t *)NextElement;
size_required += 4; // ad 4 for enterprise value size_required += 4; // ad 4 for enterprise value
if ( size_left < size_required ) { if ( size_left < size_required ) {
syslog(LOG_ERR, "Process_ipfix: [%u] Not enough data for template elements! required: %i, left: %u", LogError("Process_ipfix: [%u] Not enough data for template elements! required: %i, left: %u",
exporter->info.id, size_required, size_left); exporter->info.id, size_required, size_left);
dbg_printf("ERROR: Not enough data for template elements! required: %i, left: %u", size_required, size_left); dbg_printf("ERROR: Not enough data for template elements! required: %i, left: %u", size_required, size_left);
return; return;
@ -1097,7 +1103,7 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
i = 0; // keep compiler happy i = 0; // keep compiler happy
size_left = GET_FLOWSET_LENGTH(option_template_flowset) - 4; // -4 for flowset header -> id and length size_left = GET_FLOWSET_LENGTH(option_template_flowset) - 4; // -4 for flowset header -> id and length
if ( size_left < 6 ) { if ( size_left < 6 ) {
syslog(LOG_ERR, "Process_ipfix: [%u] option template length error: size left %u too small for an options template", LogError("Process_ipfix: [%u] option template length error: size left %u too small for an options template",
exporter->info.id, size_left); exporter->info.id, size_left);
return; return;
} }
@ -1110,16 +1116,16 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
size_left -= 6; size_left -= 6;
if ( scope_field_count == 0 ) { if ( scope_field_count == 0 ) {
syslog(LOG_ERR, "Process_ipfx: [%u] scope field count error: length must not be zero", LogError("Process_ipfx: [%u] scope field count error: length must not be zero",
exporter->info.id); exporter->info.id);
dbg_printf("scope field count error: length must not be zero\n"); dbg_printf("scope field count error: length must not be zero\n");
return; return;
} }
size_required = field_count * 2 * sizeof(uint16_t); size_required = (field_count + scope_field_count) * 2 * sizeof(uint16_t);
dbg_printf("Size left: %u, size required: %u\n", size_left, size_required); dbg_printf("Size left: %u, size required: %u\n", size_left, size_required);
if ( size_left < size_required ) { if ( size_left < size_required ) {
syslog(LOG_ERR, "Process_ipfix: [%u] option template length error: size left %u too small for %u scopes length and %u options length", LogError("Process_ipfix: [%u] option template length error: size left %u too small for %u scopes length and %u options length",
exporter->info.id, size_left, field_count, scope_field_count); exporter->info.id, size_left, field_count, scope_field_count);
dbg_printf("option template length error: size left %u too small for field_count %u\n", dbg_printf("option template length error: size left %u too small for field_count %u\n",
size_left, field_count); size_left, field_count);
@ -1130,7 +1136,7 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
id, field_count, scope_field_count); id, field_count, scope_field_count);
if ( scope_field_count == 0 ) { if ( scope_field_count == 0 ) {
syslog(LOG_ERR, "Process_ipfxi: [%u] scope field count error: length must not be zero", LogError("Process_ipfxi: [%u] scope field count error: length must not be zero",
exporter->info.id); exporter->info.id);
return; return;
} }
@ -1140,14 +1146,20 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
uint16_t id, length; uint16_t id, length;
int Enterprise; int Enterprise;
if ( size_left && size_left < 4 ) {
LogError("Process_ipfix [%u] Template size error at %s line %u" ,
exporter->info.id, __FILE__, __LINE__, strerror (errno));
return;
}
id = Get_val16(DataPtr); DataPtr += 2; id = Get_val16(DataPtr); DataPtr += 2;
length = Get_val16(DataPtr); DataPtr += 2; length = Get_val16(DataPtr); DataPtr += 2;
size_left -= 4;
Enterprise = id & 0x8000 ? 1 : 0; Enterprise = id & 0x8000 ? 1 : 0;
if ( Enterprise ) { if ( Enterprise ) {
size_required += 4; size_required += 4;
dbg_printf("Adjusted: Size left: %u, size required: %u\n", size_left, size_required); dbg_printf("Adjusted: Size left: %u, size required: %u\n", size_left, size_required);
if ( size_left < size_required ) { if ( size_left < size_required ) {
syslog(LOG_ERR, "Process_ipfix: [%u] option template length error: size left %u too small for %u scopes length and %u options length", LogError("Process_ipfix: [%u] option template length error: size left %u too small for %u scopes length and %u options length",
exporter->info.id, size_left, field_count, scope_field_count); exporter->info.id, size_left, field_count, scope_field_count);
dbg_printf("option template length error: size left %u too small for field_count %u\n", dbg_printf("option template length error: size left %u too small for field_count %u\n",
size_left, field_count); size_left, field_count);
@ -1155,6 +1167,7 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
} }
enterprise_value = Get_val32(DataPtr); enterprise_value = Get_val32(DataPtr);
DataPtr += 4; DataPtr += 4;
size_left -= 4;
dbg_printf(" [%i] Enterprise: 1, scope id: %u, scope length %u enterprise value: %u\n", dbg_printf(" [%i] Enterprise: 1, scope id: %u, scope length %u enterprise value: %u\n",
i, id, length, enterprise_value); i, id, length, enterprise_value);
} else { } else {
@ -1168,12 +1181,13 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
id = Get_val16(DataPtr); DataPtr += 2; id = Get_val16(DataPtr); DataPtr += 2;
length = Get_val16(DataPtr); DataPtr += 2; length = Get_val16(DataPtr); DataPtr += 2;
size_left -= 4;
Enterprise = id & 0x8000 ? 1 : 0; Enterprise = id & 0x8000 ? 1 : 0;
if ( Enterprise ) { if ( Enterprise ) {
size_required += 4; size_required += 4;
dbg_printf("Adjusted: Size left: %u, size required: %u\n", size_left, size_required); dbg_printf("Adjusted: Size left: %u, size required: %u\n", size_left, size_required);
if ( size_left < size_required ) { if ( size_left < size_required ) {
syslog(LOG_ERR, "Process_ipfix: [%u] option template length error: size left %u too small for %u scopes length and %u options length", LogError("Process_ipfix: [%u] option template length error: size left %u too small for %u scopes length and %u options length",
exporter->info.id, size_left, field_count, scope_field_count); exporter->info.id, size_left, field_count, scope_field_count);
dbg_printf("option template length error: size left %u too small for field_count %u\n", dbg_printf("option template length error: size left %u too small for field_count %u\n",
size_left, field_count); size_left, field_count);
@ -1181,6 +1195,7 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
} }
enterprise_value = Get_val32(DataPtr); enterprise_value = Get_val32(DataPtr);
DataPtr += 4; DataPtr += 4;
size_left -= 4;
dbg_printf(" [%i] Enterprise: 1, option id: %u, option length %u enterprise value: %u\n", dbg_printf(" [%i] Enterprise: 1, option id: %u, option length %u enterprise value: %u\n",
i, id, length, enterprise_value); i, id, length, enterprise_value);
} else { } else {
@ -1300,7 +1315,7 @@ char *string;
if ( (size_left < table->input_record_size) ) { if ( (size_left < table->input_record_size) ) {
if ( size_left > 3 ) { if ( size_left > 3 ) {
syslog(LOG_WARNING,"Process_ipfix: Corrupt data flowset? Pad bytes: %u", size_left); LogError("Process_ipfix: Corrupt data flowset? Pad bytes: %u", size_left);
dbg_printf("Process_ipfix: Corrupt data flowset? Pad bytes: %u, table record_size: %u\n", dbg_printf("Process_ipfix: Corrupt data flowset? Pad bytes: %u, table record_size: %u\n",
size_left, table->input_record_size); size_left, table->input_record_size);
} }
@ -1311,7 +1326,7 @@ char *string;
// check for enough space in output buffer // check for enough space in output buffer
if ( !CheckBufferSpace(fs->nffile, table->output_record_size) ) { if ( !CheckBufferSpace(fs->nffile, table->output_record_size) ) {
// this should really never occur, because the buffer gets flushed ealier // this should really never occur, because the buffer gets flushed ealier
syslog(LOG_ERR,"Process_ipfix: output buffer size error. Abort ipfix record processing"); LogError("Process_ipfix: output buffer size error. Abort ipfix record processing");
dbg_printf("Process_ipfix: output buffer size error. Abort ipfix record processing"); dbg_printf("Process_ipfix: output buffer size error. Abort ipfix record processing");
return; return;
} }
@ -1455,7 +1470,7 @@ char *string;
break; break;
default: default:
syslog(LOG_ERR, "Process_ipfix: Software bug! Unknown Sequence: %u. at %s line %d", LogError("Process_ipfix: Software bug! Unknown Sequence: %u. at %s line %d",
table->sequence[i].id, __FILE__, __LINE__); table->sequence[i].id, __FILE__, __LINE__);
dbg_printf("Software bug! Unknown Sequence: %u. at %s line %d\n", dbg_printf("Software bug! Unknown Sequence: %u. at %s line %d\n",
table->sequence[i].id, __FILE__, __LINE__); table->sequence[i].id, __FILE__, __LINE__);
@ -1587,9 +1602,9 @@ char *string;
// buffer size sanity check // buffer size sanity check
if ( fs->nffile->block_header->size > BUFFSIZE ) { if ( fs->nffile->block_header->size > BUFFSIZE ) {
// should never happen // should never happen
syslog(LOG_ERR,"### Software error ###: %s line %d", __FILE__, __LINE__); LogError("### Software error ###: %s line %d", __FILE__, __LINE__);
syslog(LOG_ERR,"Process ipfix: Output buffer overflow! Flush buffer and skip records."); LogError("Process ipfix: Output buffer overflow! Flush buffer and skip records.");
syslog(LOG_ERR,"Buffer size: %u > %u", fs->nffile->block_header->size, BUFFSIZE); LogError("Buffer size: %u > %u", fs->nffile->block_header->size, BUFFSIZE);
// reset buffer // reset buffer
fs->nffile->block_header->size = 0; fs->nffile->block_header->size = 0;
@ -1614,7 +1629,7 @@ static uint32_t packet_cntr = 0;
size_left = in_buff_cnt; size_left = in_buff_cnt;
if ( size_left < IPFIX_HEADER_LENGTH ) { if ( size_left < IPFIX_HEADER_LENGTH ) {
syslog(LOG_ERR, "Process_ipfix: Too little data for ipfix packet: '%lli'", (long long)size_left); LogError("Process_ipfix: Too little data for ipfix packet: '%lli'", (long long)size_left);
return; return;
} }
@ -1625,7 +1640,7 @@ static uint32_t packet_cntr = 0;
exporter = GetExporter(fs, ipfix_header); exporter = GetExporter(fs, ipfix_header);
if ( !exporter ) { if ( !exporter ) {
syslog(LOG_ERR,"Process_ipfix: Exporter NULL: Abort ipfix record processing"); LogError("Process_ipfix: Exporter NULL: Abort ipfix record processing");
return; return;
} }
exporter->packets++; exporter->packets++;
@ -1665,6 +1680,13 @@ static uint32_t packet_cntr = 0;
while (size_left) { while (size_left) {
uint16_t flowset_id; uint16_t flowset_id;
if ( size_left && size_left < 4 ) {
LogError("Process_ipfix [%u] Template size error at %s line %u" ,
exporter->info.id, __FILE__, __LINE__, strerror (errno));
size_left = 0;
continue;
}
flowset_header = flowset_header + flowset_length; flowset_header = flowset_header + flowset_length;
flowset_id = GET_FLOWSET_ID(flowset_header); flowset_id = GET_FLOWSET_ID(flowset_header);
@ -1677,7 +1699,7 @@ static uint32_t packet_cntr = 0;
and smaller is an illegal flowset anyway ... and smaller is an illegal flowset anyway ...
if it happends, we can't determine the next flowset, so skip the entire export packet if it happends, we can't determine the next flowset, so skip the entire export packet
*/ */
syslog(LOG_ERR,"Process_ipfix: flowset zero length error."); LogError("Process_ipfix: flowset zero length error.");
dbg_printf("Process_ipfix: flowset zero length error.\n"); dbg_printf("Process_ipfix: flowset zero length error.\n");
return; return;
@ -1690,7 +1712,7 @@ static uint32_t packet_cntr = 0;
} }
if ( flowset_length > size_left ) { if ( flowset_length > size_left ) {
syslog(LOG_ERR,"Process_ipfix: flowset length error. Expected bytes: %u > buffersize: %lli", LogError("Process_ipfix: flowset length error. Expected bytes: %u > buffersize: %lli",
flowset_length, (long long)size_left); flowset_length, (long long)size_left);
size_left = 0; size_left = 0;
continue; continue;
@ -1713,7 +1735,7 @@ static uint32_t packet_cntr = 0;
default: { default: {
if ( flowset_id < IPFIX_MIN_RECORD_FLOWSET_ID ) { if ( flowset_id < IPFIX_MIN_RECORD_FLOWSET_ID ) {
dbg_printf("Invalid flowset id: %u. Skip flowset\n", flowset_id); dbg_printf("Invalid flowset id: %u. Skip flowset\n", flowset_id);
syslog(LOG_ERR,"Process_ipfix: Invalid flowset id: %u. Skip flowset", flowset_id); LogError("Process_ipfix: Invalid flowset id: %u. Skip flowset", flowset_id);
} else { } else {
input_translation_t *table; input_translation_t *table;
dbg_printf("Process data flowset, length: %u\n", flowset_length); dbg_printf("Process data flowset, length: %u\n", flowset_length);

View File

@ -43,7 +43,6 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <syslog.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
@ -451,7 +450,7 @@ int i;
cache.lookup_info = (struct element_param_s *)calloc(65536, sizeof(struct element_param_s)); cache.lookup_info = (struct element_param_s *)calloc(65536, sizeof(struct element_param_s));
cache.common_extensions = (uint32_t *)malloc((Max_num_extensions+1)*sizeof(uint32_t)); cache.common_extensions = (uint32_t *)malloc((Max_num_extensions+1)*sizeof(uint32_t));
if ( !cache.common_extensions || !cache.lookup_info ) { if ( !cache.common_extensions || !cache.lookup_info ) {
syslog(LOG_ERR, "Process_v9: Panic! malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError( "Process_v9: Panic! malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return 0; return 0;
} }
@ -465,7 +464,7 @@ int i;
} }
cache.max_v9_elements = i; cache.max_v9_elements = i;
syslog(LOG_DEBUG,"Init v9: Max number of v9 tags: %u", cache.max_v9_elements); dbg_printf("Init v9: Max number of v9 tags: %u", cache.max_v9_elements);
return 1; return 1;
@ -499,7 +498,7 @@ exporter_v9_domain_t **e = (exporter_v9_domain_t **)&(fs->exporter_data);
// nothing found // nothing found
*e = (exporter_v9_domain_t *)malloc(sizeof(exporter_v9_domain_t)); *e = (exporter_v9_domain_t *)malloc(sizeof(exporter_v9_domain_t));
if ( !(*e)) { if ( !(*e)) {
syslog(LOG_ERR, "Process_v9: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError( "Process_v9: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return NULL; return NULL;
} }
memset((void *)(*e), 0, sizeof(exporter_v9_domain_t)); memset((void *)(*e), 0, sizeof(exporter_v9_domain_t));
@ -521,7 +520,7 @@ exporter_v9_domain_t **e = (exporter_v9_domain_t **)&(fs->exporter_data);
dbg_printf("Process_v9: New exporter: SysID: %u, Domain: %u, IP: %s\n", dbg_printf("Process_v9: New exporter: SysID: %u, Domain: %u, IP: %s\n",
(*e)->info.sysid, exporter_id, ipstr); (*e)->info.sysid, exporter_id, ipstr);
syslog(LOG_INFO, "Process_v9: New exporter: SysID: %u, Domain: %u, IP: %s\n", LogInfo("Process_v9: New exporter: SysID: %u, Domain: %u, IP: %s\n",
(*e)->info.sysid, exporter_id, ipstr); (*e)->info.sysid, exporter_id, ipstr);
@ -591,12 +590,12 @@ input_translation_t **table;
// so template refreshing may change the table size without danger of overflowing // so template refreshing may change the table size without danger of overflowing
*table = calloc(1, sizeof(input_translation_t)); *table = calloc(1, sizeof(input_translation_t));
if ( !(*table) ) { if ( !(*table) ) {
syslog(LOG_ERR, "Process_v9: Panic! calloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError( "Process_v9: Panic! calloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return NULL; return NULL;
} }
(*table)->sequence = calloc(cache.max_v9_elements, sizeof(sequence_map_t)); (*table)->sequence = calloc(cache.max_v9_elements, sizeof(sequence_map_t));
if ( !(*table)->sequence ) { if ( !(*table)->sequence ) {
syslog(LOG_ERR, "Process_v9: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError( "Process_v9: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return NULL; return NULL;
} }
@ -614,7 +613,7 @@ uint32_t i = table->number_of_sequences;
uint32_t index = cache.lookup_info[Type].index; uint32_t index = cache.lookup_info[Type].index;
if ( table->number_of_sequences >= cache.max_v9_elements ) { if ( table->number_of_sequences >= cache.max_v9_elements ) {
syslog(LOG_ERR, "Process_v9: Software bug! Sequence table full. at %s line %d", LogError( "Process_v9: Software bug! Sequence table full. at %s line %d",
__FILE__, __LINE__); __FILE__, __LINE__);
dbg_printf("Software bug! Sequence table full. at %s line %d", dbg_printf("Software bug! Sequence table full. at %s line %d",
__FILE__, __LINE__); __FILE__, __LINE__);
@ -656,7 +655,7 @@ size_t size_required;
table = GetTranslationTable(exporter, id); table = GetTranslationTable(exporter, id);
if ( !table ) { if ( !table ) {
syslog(LOG_INFO, "Process_v9: [%u] Add template %u", exporter->info.id, id); LogInfo( "Process_v9: [%u] Add template %u", exporter->info.id, id);
dbg_printf("[%u] Add template %u\n", exporter->info.id, id); dbg_printf("[%u] Add template %u\n", exporter->info.id, id);
table = add_translation_table(exporter, id); table = add_translation_table(exporter, id);
if ( !table ) { if ( !table ) {
@ -670,7 +669,7 @@ size_t size_required;
size_required = (size_required + 3) &~(size_t)3; size_required = (size_required + 3) &~(size_t)3;
extension_map = malloc(size_required); extension_map = malloc(size_required);
if ( !extension_map ) { if ( !extension_map ) {
syslog(LOG_ERR, "Process_v9: Panic! malloc() error in %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError( "Process_v9: Panic! malloc() error in %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return NULL; return NULL;
} }
extension_map->type = ExtensionMapType; extension_map->type = ExtensionMapType;
@ -1099,7 +1098,7 @@ size_t size_required;
dbg_printf("%d byte Sampling ID included at offset %u\n", length, table->sampler_offset); dbg_printf("%d byte Sampling ID included at offset %u\n", length, table->sampler_offset);
break; break;
default: default:
syslog(LOG_ERR, "Process_v9: Unexpected SAMPLER ID field length: %d", LogError( "Process_v9: Unexpected SAMPLER ID field length: %d",
cache.lookup_info[NF9_FLOW_SAMPLER_ID].length); cache.lookup_info[NF9_FLOW_SAMPLER_ID].length);
dbg_printf("Unexpected SAMPLER ID field length: %d", dbg_printf("Unexpected SAMPLER ID field length: %d",
cache.lookup_info[NF9_FLOW_SAMPLER_ID].length); cache.lookup_info[NF9_FLOW_SAMPLER_ID].length);
@ -1189,7 +1188,7 @@ option_offset_t **t;
fprintf(stderr, "malloc() allocation error: %s\n", strerror(errno)); fprintf(stderr, "malloc() allocation error: %s\n", strerror(errno));
return ; return ;
} }
syslog(LOG_ERR, "Process_v9: New std sampler: interval: %i, algorithm: %i", LogError( "Process_v9: New std sampler: interval: %i, algorithm: %i",
offset_std_sampler_interval, offset_std_sampler_algorithm); offset_std_sampler_interval, offset_std_sampler_algorithm);
} // else existing table } // else existing table
@ -1240,7 +1239,7 @@ int i;
dbg_printf("template size: %u buffersize: %u\n", size_required, size_left); dbg_printf("template size: %u buffersize: %u\n", size_required, size_left);
if ( size_left < size_required ) { if ( size_left < size_required ) {
syslog(LOG_ERR, "Process_v9: [%u] buffer size error: expected %u available %u", LogError( "Process_v9: [%u] buffer size error: expected %u available %u",
exporter->info.id, size_required, size_left); exporter->info.id, size_required, size_left);
size_left = 0; size_left = 0;
continue; continue;
@ -1348,19 +1347,19 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
option_length = GET_OPTION_TEMPLATE_OPTION_LENGTH(option_template); option_length = GET_OPTION_TEMPLATE_OPTION_LENGTH(option_template);
if ( scope_length & 0x3 ) { if ( scope_length & 0x3 ) {
syslog(LOG_ERR, "Process_v9: [%u] scope length error: length %u not multiple of 4", LogError( "Process_v9: [%u] scope length error: length %u not multiple of 4",
exporter->info.id, scope_length); exporter->info.id, scope_length);
return; return;
} }
if ( option_length & 0x3 ) { if ( option_length & 0x3 ) {
syslog(LOG_ERR, "Process_v9: [%u] option length error: length %u not multiple of 4", LogError( "Process_v9: [%u] option length error: length %u not multiple of 4",
exporter->info.id, option_length); exporter->info.id, option_length);
return; return;
} }
if ( (scope_length + option_length) > size_left ) { if ( (scope_length + option_length) > size_left ) {
syslog(LOG_ERR, "Process_v9: [%u] option template length error: size left %u too small for %u scopes length and %u options length", LogError( "Process_v9: [%u] option template length error: size left %u too small for %u scopes length and %u options length",
exporter->info.id, size_left, scope_length, option_length); exporter->info.id, size_left, scope_length, option_length);
return; return;
} }
@ -1410,7 +1409,7 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa
} }
if ( index && v9_element_map[index].length != length ) { if ( index && v9_element_map[index].length != length ) {
syslog(LOG_ERR,"Process_v9: Option field Type: %u, length %u not supported\n", type, length); LogError("Process_v9: Option field Type: %u, length %u not supported\n", type, length);
dbg_printf("Process_v9: Option field Type: %u, length %u not supported\n", type, length); dbg_printf("Process_v9: Option field Type: %u, length %u not supported\n", type, length);
continue; continue;
} }
@ -1529,9 +1528,15 @@ char *string;
while (size_left) { while (size_left) {
common_record_t *data_record; common_record_t *data_record;
if ( (table->input_record_size == 0 )) {
LogError("Process_v9: Corrupt data flowset? table input_record_sizei = 0 ");
size_left = 0;
continue;
}
if ( (size_left < table->input_record_size) ) { if ( (size_left < table->input_record_size) ) {
if ( size_left > 3 ) { if ( size_left > 3 ) {
syslog(LOG_WARNING,"Process_v9: Corrupt data flowset? Pad bytes: %u", size_left); LogError("Process_v9: Corrupt data flowset? Pad bytes: %u", size_left);
dbg_printf("Process_v9: Corrupt data flowset? Pad bytes: %u, table record_size: %u\n", dbg_printf("Process_v9: Corrupt data flowset? Pad bytes: %u, table record_size: %u\n",
size_left, table->input_record_size); size_left, table->input_record_size);
} }
@ -1542,7 +1547,7 @@ char *string;
// check for enough space in output buffer // check for enough space in output buffer
if ( !CheckBufferSpace(fs->nffile, table->output_record_size) ) { if ( !CheckBufferSpace(fs->nffile, table->output_record_size) ) {
// this should really never occur, because the buffer gets flushed ealier // this should really never occur, because the buffer gets flushed ealier
syslog(LOG_ERR,"Process_v9: output buffer size error. Abort v9 record processing"); LogError("Process_v9: output buffer size error. Abort v9 record processing");
dbg_printf("Process_v9: output buffer size error. Abort v9 record processing"); dbg_printf("Process_v9: output buffer size error. Abort v9 record processing");
return; return;
} }
@ -1738,7 +1743,7 @@ char *string;
*((uint32_t *)&out[output_offset+12]) = 0; *((uint32_t *)&out[output_offset+12]) = 0;
} break; } break;
default: default:
syslog(LOG_ERR, "Process_v9: Software bug! Unknown Sequence: %u. at %s line %d", LogError( "Process_v9: Software bug! Unknown Sequence: %u. at %s line %d",
table->sequence[i].id, __FILE__, __LINE__); table->sequence[i].id, __FILE__, __LINE__);
dbg_printf("Software bug! Unknown Sequence: %u. at %s line %d", dbg_printf("Software bug! Unknown Sequence: %u. at %s line %d",
table->sequence[i].id, __FILE__, __LINE__); table->sequence[i].id, __FILE__, __LINE__);
@ -1936,9 +1941,9 @@ char *string;
// buffer size sanity check // buffer size sanity check
if ( fs->nffile->block_header->size > BUFFSIZE ) { if ( fs->nffile->block_header->size > BUFFSIZE ) {
// should never happen // should never happen
syslog(LOG_ERR,"### Software error ###: %s line %d", __FILE__, __LINE__); LogError("### Software error ###: %s line %d", __FILE__, __LINE__);
syslog(LOG_ERR,"Process v9: Output buffer overflow! Flush buffer and skip records."); LogError("Process v9: Output buffer overflow! Flush buffer and skip records.");
syslog(LOG_ERR,"Buffer size: %u > %u", fs->nffile->block_header->size, BUFFSIZE); LogError("Buffer size: %u > %u", fs->nffile->block_header->size, BUFFSIZE);
// reset buffer // reset buffer
fs->nffile->block_header->size = 0; fs->nffile->block_header->size = 0;
@ -1963,7 +1968,7 @@ uint8_t *in;
if ( !offset_table ) { if ( !offset_table ) {
// should never happen - catch it anyway // should never happen - catch it anyway
syslog(LOG_ERR, "Process_v9: Panic! - No Offset table found! : %s line %d", __FILE__, __LINE__); LogError( "Process_v9: Panic! - No Offset table found! : %s line %d", __FILE__, __LINE__);
return; return;
} }
@ -2007,7 +2012,7 @@ uint8_t *in;
dbg_printf("Sampler algorithm: %u\n", mode); dbg_printf("Sampler algorithm: %u\n", mode);
dbg_printf("Sampler interval : %u\n", interval); dbg_printf("Sampler interval : %u\n", interval);
syslog(LOG_INFO, "Set std sampler: algorithm: %u, interval: %u\n", LogInfo( "Set std sampler: algorithm: %u, interval: %u\n",
mode, interval); mode, interval);
dbg_printf("Set std sampler: algorithm: %u, interval: %u\n", dbg_printf("Set std sampler: algorithm: %u, interval: %u\n",
mode, interval); mode, interval);
@ -2029,7 +2034,7 @@ static int pkg_num = 0;
pkg_num++; pkg_num++;
size_left = in_buff_cnt; size_left = in_buff_cnt;
if ( size_left < NETFLOW_V9_HEADER_LENGTH ) { if ( size_left < NETFLOW_V9_HEADER_LENGTH ) {
syslog(LOG_ERR, "Process_v9: Too little data for v9 packet: '%lli'", (long long)size_left); LogError( "Process_v9: Too little data for v9 packet: '%lli'", (long long)size_left);
return; return;
} }
@ -2039,7 +2044,7 @@ static int pkg_num = 0;
exporter = GetExporter(fs, exporter_id); exporter = GetExporter(fs, exporter_id);
if ( !exporter ) { if ( !exporter ) {
syslog(LOG_ERR,"Process_v9: Exporter NULL: Abort v9 record processing"); LogError("Process_v9: Exporter NULL: Abort v9 record processing");
return; return;
} }
exporter->packets++; exporter->packets++;
@ -2078,7 +2083,7 @@ static int pkg_num = 0;
exporter->info.id, (long long)exporter->last_sequence, (long long)exporter->sequence, (long long)distance); exporter->info.id, (long long)exporter->last_sequence, (long long)exporter->sequence, (long long)distance);
/* /*
if ( report_seq ) if ( report_seq )
syslog(LOG_ERR,"Flow sequence mismatch. Missing: %lli packets", delta(last_count,distance)); LogError("Flow sequence mismatch. Missing: %lli packets", delta(last_count,distance));
*/ */
} }
} }
@ -2102,7 +2107,7 @@ static int pkg_num = 0;
and smaller is an illegal flowset anyway ... and smaller is an illegal flowset anyway ...
if it happends, we can't determine the next flowset, so skip the entire export packet if it happends, we can't determine the next flowset, so skip the entire export packet
*/ */
syslog(LOG_ERR,"Process_v9: flowset zero length error."); LogError("Process_v9: flowset zero length error.");
dbg_printf("Process_v9: flowset zero length error.\n"); dbg_printf("Process_v9: flowset zero length error.\n");
return; return;
} }
@ -2116,7 +2121,7 @@ static int pkg_num = 0;
if ( flowset_length > size_left ) { if ( flowset_length > size_left ) {
dbg_printf("flowset length error. Expected bytes: %u > buffersize: %lli", dbg_printf("flowset length error. Expected bytes: %u > buffersize: %lli",
flowset_length, (long long)size_left); flowset_length, (long long)size_left);
syslog(LOG_ERR,"Process_v9: flowset length error. Expected bytes: %u > buffersize: %lli", LogError("Process_v9: flowset length error. Expected bytes: %u > buffersize: %lli",
flowset_length, (long long)size_left); flowset_length, (long long)size_left);
size_left = 0; size_left = 0;
continue; continue;
@ -2135,14 +2140,14 @@ static int pkg_num = 0;
break; break;
case NF9_OPTIONS_FLOWSET_ID: case NF9_OPTIONS_FLOWSET_ID:
option_flowset = (option_template_flowset_t *)flowset_header; option_flowset = (option_template_flowset_t *)flowset_header;
syslog(LOG_DEBUG,"Process_v9: Found options flowset: template %u", ntohs(option_flowset->template_id)); dbg_printf("Process_v9: Found options flowset: template %u", ntohs(option_flowset->template_id));
Process_v9_option_templates(exporter, flowset_header, fs); Process_v9_option_templates(exporter, flowset_header, fs);
break; break;
default: { default: {
input_translation_t *table; input_translation_t *table;
if ( flowset_id < NF9_MIN_RECORD_FLOWSET_ID ) { if ( flowset_id < NF9_MIN_RECORD_FLOWSET_ID ) {
dbg_printf("Invalid flowset id: %u\n", flowset_id); dbg_printf("Invalid flowset id: %u\n", flowset_id);
syslog(LOG_ERR,"Process_v9: Invalid flowset id: %u", flowset_id); LogError("Process_v9: Invalid flowset id: %u", flowset_id);
} else { } else {
dbg_printf("[%u] ID %u Data flowset\n", exporter->info.id, flowset_id); dbg_printf("[%u] ID %u Data flowset\n", exporter->info.id, flowset_id);
@ -2168,7 +2173,7 @@ static int pkg_num = 0;
#ifdef DEVEL #ifdef DEVEL
if ( processed_records != expected_records ) { if ( processed_records != expected_records ) {
syslog(LOG_ERR, "Process_v9: Processed records %u, expected %u", processed_records, expected_records); LogError( "Process_v9: Processed records %u, expected %u", processed_records, expected_records);
printf("Process_v9: Processed records %u, expected %u\n", processed_records, expected_records); printf("Process_v9: Processed records %u, expected %u\n", processed_records, expected_records);
} }
#endif #endif
@ -2990,7 +2995,7 @@ generic_sampler_t *sampler;
// no samplers so far // no samplers so far
sampler = (generic_sampler_t *)malloc(sizeof(generic_sampler_t)); sampler = (generic_sampler_t *)malloc(sizeof(generic_sampler_t));
if ( !sampler ) { if ( !sampler ) {
syslog(LOG_ERR, "Process_v9: Panic! malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError( "Process_v9: Panic! malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return; return;
} }
@ -3004,7 +3009,7 @@ generic_sampler_t *sampler;
exporter->sampler = sampler; exporter->sampler = sampler;
FlushInfoSampler(fs, &(sampler->info)); FlushInfoSampler(fs, &(sampler->info));
syslog(LOG_INFO, "Add new sampler: ID: %i, mode: %u, interval: %u\n", LogInfo( "Add new sampler: ID: %i, mode: %u, interval: %u\n",
id, mode, interval); id, mode, interval);
dbg_printf("Add new sampler: ID: %i, mode: %u, interval: %u\n", dbg_printf("Add new sampler: ID: %i, mode: %u, interval: %u\n",
id, mode, interval); id, mode, interval);
@ -3015,7 +3020,7 @@ generic_sampler_t *sampler;
// test for update of existing sampler // test for update of existing sampler
if ( sampler->info.id == id ) { if ( sampler->info.id == id ) {
// found same sampler id - update record // found same sampler id - update record
syslog(LOG_INFO, "Update existing sampler id: %i, mode: %u, interval: %u\n", LogInfo( "Update existing sampler id: %i, mode: %u, interval: %u\n",
id, mode, interval); id, mode, interval);
dbg_printf("Update existing sampler id: %i, mode: %u, interval: %u\n", dbg_printf("Update existing sampler id: %i, mode: %u, interval: %u\n",
id, mode, interval); id, mode, interval);
@ -3037,7 +3042,7 @@ generic_sampler_t *sampler;
// end of sampler chain - insert new sampler // end of sampler chain - insert new sampler
sampler->next = (generic_sampler_t *)malloc(sizeof(generic_sampler_t)); sampler->next = (generic_sampler_t *)malloc(sizeof(generic_sampler_t));
if ( !sampler->next ) { if ( !sampler->next ) {
syslog(LOG_ERR, "Process_v9: Panic! malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno)); LogError( "Process_v9: Panic! malloc(): %s line %d: %s", __FILE__, __LINE__, strerror (errno));
return; return;
} }
sampler = sampler->next; sampler = sampler->next;
@ -3053,7 +3058,7 @@ generic_sampler_t *sampler;
FlushInfoSampler(fs, &(sampler->info)); FlushInfoSampler(fs, &(sampler->info));
syslog(LOG_INFO, "Append new sampler: ID: %u, mode: %u, interval: %u\n", LogInfo( "Append new sampler: ID: %u, mode: %u, interval: %u\n",
id, mode, interval); id, mode, interval);
dbg_printf("Append new sampler: ID: %u, mode: %u, interval: %u\n", dbg_printf("Append new sampler: ID: %u, mode: %u, interval: %u\n",
id, mode, interval); id, mode, interval);