void FlushExtensionMaps (FlowSource_t * fs) { int i; for (i = 0; i < fs->extension_map_list.next_free; i++) { extension_map_t *map = fs->extension_map_list.maps[i]; if (!CheckBufferSpace (fs->nffile, map->size)) { // fishy! - should never happen. maybe disk full? syslog (LOG_ERR, "FlushExtensionMaps: output buffer size error. Abort record processing"); return; } memcpy (fs->nffile->buff_ptr, (void *) map, map->size); fs->nffile->buff_ptr += map->size; fs->nffile->block_header->NumRecords++; fs->nffile->block_header->size += map->size; } } // End of FlushExtensionMaps
static inline void AppendToBuffer(nffile_t *nffile, void *record, size_t required) { // flush current buffer to disc if ( !CheckBufferSpace(nffile, required)) { return; } // enough buffer space available at this point memcpy(nffile->buff_ptr, record, required); // update stat nffile->block_header->NumRecords++; nffile->block_header->size += required; // advance write pointer nffile->buff_ptr = (void *)((pointer_addr_t)nffile->buff_ptr + required); } // End of AppendToBuffer
int StorePcapFlow(FlowSource_t *fs, struct FlowNode *Node) { common_record_t *common_record; uint32_t packets, bytes, pcap_output_record_size; uint64_t start_time, end_time; int j, id; char *string; void *data_ptr; if ( !pcap_extension_map ) { pcap_extension_map = (extension_map_t *)malloc(pcap_extension_info.map->size); if ( !pcap_extension_map ) { LogError("Process_pcap: malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror (errno)); return 0; } memcpy((void *)pcap_extension_map, (void *)pcap_extension_info.map, pcap_extension_info.map->size); if ( !AddExtensionMap(fs, pcap_extension_map) ) { LogError("Process_pcap: Fatal: AddExtensionMap() failed in %s line %d\n", __FILE__, __LINE__); return 0; } } if ( Node->version == AF_INET6 ) { pcap_output_record_size = pcap_output_record_size_v6; dbg_printf("Store Flow v6 node: size: %u\n", pcap_output_record_size); } else if ( Node->version == AF_INET ) { pcap_output_record_size = pcap_output_record_size_v4; dbg_printf("Store Flow v4 node: size: %u\n", pcap_output_record_size); } else { LogError("Process_pcap: Unexpected version in %s line %d: %u\n", __FILE__, __LINE__, Node->version); return 0; } // output buffer size check for all expected records if ( !CheckBufferSpace(fs->nffile, pcap_output_record_size) ) { // fishy! - should never happen. maybe disk full? LogError("Process_pcap: output buffer size error. Abort pcap record processing"); return 0; } // map output record to memory buffer common_record = (common_record_t *)fs->nffile->buff_ptr; // header data common_record->flags = 0; common_record->type = CommonRecordType; common_record->exporter_sysid = 0; common_record->ext_map = pcap_extension_map->map_id; common_record->size = pcap_output_record_size; // pcap common fields common_record->srcport = Node->src_port; common_record->dstport = Node->dst_port; common_record->tcp_flags = Node->flags; common_record->prot = Node->proto; common_record->tos = 0; common_record->fwd_status = 0; if ( Node->version == AF_INET6 ) { SetFlag(common_record->flags, FLAG_IPV6_ADDR); pcap_v6_block_t *pcap_v6_block = (pcap_v6_block_t *)common_record->data; pcap_v6_block->srcaddr[0] = Node->src_addr.v6[0]; pcap_v6_block->srcaddr[1] = Node->src_addr.v6[1]; pcap_v6_block->dstaddr[0] = Node->dst_addr.v6[0]; pcap_v6_block->dstaddr[1] = Node->dst_addr.v6[1]; pcap_v6_block->dPkts = packets = Node->packets; pcap_v6_block->dOctets = bytes = Node->bytes; data_ptr = (void *)pcap_v6_block->data; } else { pcap_v4_block_t *pcap_v4_block = (pcap_v4_block_t *)common_record->data; pcap_v4_block->srcaddr = Node->src_addr.v4; pcap_v4_block->dstaddr = Node->dst_addr.v4; pcap_v4_block->dPkts = packets = Node->packets; pcap_v4_block->dOctets = bytes = Node->bytes; data_ptr = (void *)pcap_v4_block->data; } // process optional extensions j = 0; while ( (id = pcap_extension_map->ex_id[j]) != 0 ) { switch (id) { case EX_IO_SNMP_2: { // 2 byte input/output interface index tpl_ext_4_t *tpl = (tpl_ext_4_t *)data_ptr; tpl->input = 0; tpl->output = 0; data_ptr = (void *)tpl->data; } break; default: // this should never happen, as pcap has no other extensions LogError("Process_pcap: Unexpected extension %i for pcap record. Skip extension", id); } j++; } common_record->first = Node->t_first.tv_sec; common_record->msec_first = Node->t_first.tv_usec / 1000; common_record->last = Node->t_last.tv_sec; common_record->msec_last = Node->t_last.tv_usec / 1000; start_time = (1000LL * (uint64_t)common_record->first) + (uint64_t)common_record->msec_first; end_time = (1000LL * (uint64_t)common_record->last) + (uint64_t)common_record->msec_last; // update first_seen, last_seen if ( start_time < fs->first_seen ) fs->first_seen = start_time; if ( end_time > fs->last_seen ) fs->last_seen = end_time; // Update stats switch (common_record->prot) { case IPPROTO_ICMP: case IPPROTO_ICMPV6: fs->nffile->stat_record->numflows_icmp++; fs->nffile->stat_record->numpackets_icmp += packets; fs->nffile->stat_record->numbytes_icmp += bytes; // fix odd CISCO behaviour for ICMP port/type in src port if ( common_record->srcport != 0 ) { uint8_t *s1, *s2; s1 = (uint8_t *)&(common_record->srcport); s2 = (uint8_t *)&(common_record->dstport); s2[0] = s1[1]; s2[1] = s1[0]; common_record->srcport = 0; } break; case IPPROTO_TCP: fs->nffile->stat_record->numflows_tcp++; fs->nffile->stat_record->numpackets_tcp += packets; fs->nffile->stat_record->numbytes_tcp += bytes; break; case IPPROTO_UDP: fs->nffile->stat_record->numflows_udp++; fs->nffile->stat_record->numpackets_udp += packets; fs->nffile->stat_record->numbytes_udp += bytes; break; default: fs->nffile->stat_record->numflows_other++; fs->nffile->stat_record->numpackets_other += packets; fs->nffile->stat_record->numbytes_other += bytes; } fs->nffile->stat_record->numflows++; fs->nffile->stat_record->numpackets += packets; fs->nffile->stat_record->numbytes += bytes; if ( fs->xstat ) { uint32_t bpp = packets ? bytes/packets : 0; if ( bpp > MAX_BPP ) bpp = MAX_BPP; if ( common_record->prot == IPPROTO_TCP ) { fs->xstat->bpp_histogram->tcp.bpp[bpp]++; fs->xstat->bpp_histogram->tcp.count++; fs->xstat->port_histogram->src_tcp.port[common_record->srcport]++; fs->xstat->port_histogram->dst_tcp.port[common_record->dstport]++; fs->xstat->port_histogram->src_tcp.count++; fs->xstat->port_histogram->dst_tcp.count++; } else if ( common_record->prot == IPPROTO_UDP ) { fs->xstat->bpp_histogram->udp.bpp[bpp]++; fs->xstat->bpp_histogram->udp.count++; fs->xstat->port_histogram->src_udp.port[common_record->srcport]++; fs->xstat->port_histogram->dst_udp.port[common_record->dstport]++; fs->xstat->port_histogram->src_udp.count++; fs->xstat->port_histogram->dst_udp.count++; } } if ( verbose ) { master_record_t master_record; ExpandRecord_v2((common_record_t *)common_record, &pcap_extension_info, NULL, &master_record); format_file_block_record(&master_record, &string, 0); printf("%s\n", string); } // update file record size ( -> output buffer size ) fs->nffile->block_header->NumRecords += 1; fs->nffile->block_header->size += pcap_output_record_size; fs->nffile->buff_ptr = data_ptr; return 1; } /* End of StorePcapFlow */
void Process_v1(void *in_buff, ssize_t in_buff_cnt, FlowSource_t *fs) { netflow_v1_header_t *v1_header; netflow_v1_record_t *v1_record; exporter_v1_t *exporter; extension_map_t *extension_map; common_record_t *common_record; uint64_t start_time, end_time, boot_time; uint32_t First, Last; uint16_t count; uint8_t flags; int i, done, flow_record_length; ssize_t size_left; char *string; // map v1 data structure to input buffer v1_header = (netflow_v1_header_t *)in_buff; exporter = GetExporter(fs, v1_header); if ( !exporter ) { syslog(LOG_ERR,"Process_v1: Exporter NULL: Abort v1 record processing"); return; } flags = 0; exporter->packets++; extension_map = exporter->extension_map; flow_record_length = NETFLOW_V1_RECORD_LENGTH; // this many data to process size_left = in_buff_cnt; common_record = fs->nffile->buff_ptr; done = 0; while ( !done ) { v1_block_t *v1_block; /* Process header */ // count check count = ntohs(v1_header->count); if ( count > NETFLOW_V1_MAX_RECORDS ) { syslog(LOG_ERR,"Process_v1: Unexpected record count in header: %i. Abort v1 record processing", count); fs->nffile->buff_ptr = (void *)common_record; return; } // input buffer size check for all expected records if ( size_left < ( NETFLOW_V1_HEADER_LENGTH + count * flow_record_length) ) { syslog(LOG_ERR,"Process_v1: Not enough data to process v1 record. Abort v1 record processing"); fs->nffile->buff_ptr = (void *)common_record; return; } // output buffer size check for all expected records if ( !CheckBufferSpace(fs->nffile, count * v1_output_record_size) ) { // fishy! - should never happen. maybe disk full? syslog(LOG_ERR,"Process_v1: output buffer size error. Abort v1 record processing"); return; } // map output record to memory buffer common_record = (common_record_t *)fs->nffile->buff_ptr; v1_block = (v1_block_t *)common_record->data; v1_header->SysUptime = ntohl(v1_header->SysUptime); v1_header->unix_secs = ntohl(v1_header->unix_secs); v1_header->unix_nsecs = ntohl(v1_header->unix_nsecs); /* calculate boot time in msec */ boot_time = ((uint64_t)(v1_header->unix_secs)*1000 + ((uint64_t)(v1_header->unix_nsecs) / 1000000) ) - (uint64_t)(v1_header->SysUptime); // process all records v1_record = (netflow_v1_record_t *)((pointer_addr_t)v1_header + NETFLOW_V1_HEADER_LENGTH); /* loop over each records associated with this header */ for (i = 0; i < count; i++) { pointer_addr_t bsize; void *data_ptr; uint8_t *s1, *s2; int j, id; // header data common_record->flags = flags; common_record->type = CommonRecordType; common_record->exporter_sysid = exporter->info.sysid; common_record->ext_map = extension_map->map_id; common_record->size = v1_output_record_size; // v1 common fields common_record->srcport = ntohs(v1_record->srcport); common_record->dstport = ntohs(v1_record->dstport); common_record->tcp_flags = v1_record->tcp_flags; common_record->prot = v1_record->prot; common_record->tos = v1_record->tos; common_record->fwd_status = 0; common_record->reserved = 0; // v1 typed data as fixed struct v1_block v1_block->srcaddr = ntohl(v1_record->srcaddr); v1_block->dstaddr = ntohl(v1_record->dstaddr); v1_block->dPkts = ntohl(v1_record->dPkts); v1_block->dOctets = ntohl(v1_record->dOctets); // process optional extensions data_ptr = (void *)v1_block->data; j = 0; while ( (id = extension_map->ex_id[j]) != 0 ) { switch (id) { case EX_IO_SNMP_2: { // 2 byte input/output interface index tpl_ext_4_t *tpl = (tpl_ext_4_t *)data_ptr; tpl->input = ntohs(v1_record->input); tpl->output = ntohs(v1_record->output); data_ptr = (void *)tpl->data; } break; case EX_NEXT_HOP_v4: { // IPv4 next hop tpl_ext_9_t *tpl = (tpl_ext_9_t *)data_ptr; tpl->nexthop = ntohl(v1_record->nexthop); data_ptr = (void *)tpl->data; } break; case EX_ROUTER_IP_v4: { // IPv4 router address tpl_ext_23_t *tpl = (tpl_ext_23_t *)data_ptr; tpl->router_ip = fs->ip.v4; data_ptr = (void *)tpl->data; ClearFlag(common_record->flags, FLAG_IPV6_EXP); } break; case EX_RECEIVED: { tpl_ext_27_t *tpl = (tpl_ext_27_t *)data_ptr; tpl->received = (uint64_t)((uint64_t)fs->received.tv_sec * 1000LL) + (uint64_t)((uint64_t)fs->received.tv_usec / 1000LL); data_ptr = (void *)tpl->data; } break; default: // this should never happen, as v1 has no other extensions syslog(LOG_ERR,"Process_v1: Unexpected extension %i for v1 record. Skip extension", id); } j++; } // Time issues First = ntohl(v1_record->First); Last = ntohl(v1_record->Last); if ( First > Last ) { /* First in msec, in case of msec overflow, between start and end */ start_time = boot_time - 0x100000000LL + (uint64_t)First; } else { start_time = boot_time + (uint64_t)First; } /* end time in msecs */ end_time = (uint64_t)Last + boot_time; // if overflow happened after flow ended but before got exported if ( Last > v1_header->SysUptime ) { start_time -= 0x100000000LL; end_time -= 0x100000000LL; } common_record->first = start_time/1000; common_record->msec_first = start_time - common_record->first*1000; common_record->last = end_time/1000; common_record->msec_last = end_time - common_record->last*1000; // update first_seen, last_seen if ( start_time < fs->first_seen ) fs->first_seen = start_time; if ( end_time > fs->last_seen ) fs->last_seen = end_time; // Update stats switch (common_record->prot) { case IPPROTO_ICMP: fs->nffile->stat_record->numflows_icmp++; fs->nffile->stat_record->numpackets_icmp += v1_block->dPkts; fs->nffile->stat_record->numbytes_icmp += v1_block->dOctets; // fix odd CISCO behaviour for ICMP port/type in src port if ( common_record->srcport != 0 ) { s1 = (uint8_t *)&(common_record->srcport); s2 = (uint8_t *)&(common_record->dstport); s2[0] = s1[1]; s2[1] = s1[0]; common_record->srcport = 0; } break; case IPPROTO_TCP: fs->nffile->stat_record->numflows_tcp++; fs->nffile->stat_record->numpackets_tcp += v1_block->dPkts; fs->nffile->stat_record->numbytes_tcp += v1_block->dOctets; break; case IPPROTO_UDP: fs->nffile->stat_record->numflows_udp++; fs->nffile->stat_record->numpackets_udp += v1_block->dPkts; fs->nffile->stat_record->numbytes_udp += v1_block->dOctets; break; default: fs->nffile->stat_record->numflows_other++; fs->nffile->stat_record->numpackets_other += v1_block->dPkts; fs->nffile->stat_record->numbytes_other += v1_block->dOctets; } exporter->flows++; fs->nffile->stat_record->numflows++; fs->nffile->stat_record->numpackets += v1_block->dPkts; fs->nffile->stat_record->numbytes += v1_block->dOctets; if ( fs->xstat ) { uint32_t bpp = v1_block->dPkts ? v1_block->dOctets/v1_block->dPkts : 0; if ( bpp > MAX_BPP ) bpp = MAX_BPP; if ( common_record->prot == IPPROTO_TCP ) { fs->xstat->bpp_histogram->tcp.bpp[bpp]++; fs->xstat->bpp_histogram->tcp.count++; fs->xstat->port_histogram->src_tcp.port[common_record->srcport]++; fs->xstat->port_histogram->dst_tcp.port[common_record->dstport]++; fs->xstat->port_histogram->src_tcp.count++; fs->xstat->port_histogram->dst_tcp.count++; } else if ( common_record->prot == IPPROTO_UDP ) { fs->xstat->bpp_histogram->udp.bpp[bpp]++; fs->xstat->bpp_histogram->udp.count++; fs->xstat->port_histogram->src_udp.port[common_record->srcport]++; fs->xstat->port_histogram->dst_udp.port[common_record->dstport]++; fs->xstat->port_histogram->src_udp.count++; fs->xstat->port_histogram->dst_udp.count++; } } if ( verbose ) { master_record_t master_record; ExpandRecord_v2((common_record_t *)common_record, &v1_extension_info, &(exporter->info), &master_record); format_file_block_record(&master_record, &string, 0); printf("%s\n", string); } // advance to next input flow record v1_record = (netflow_v1_record_t *)((pointer_addr_t)v1_record + flow_record_length); if ( ((pointer_addr_t)data_ptr - (pointer_addr_t)common_record) != v1_output_record_size ) { printf("Panic size check: ptr diff: %llu, record size: %u\n", (unsigned long long)((pointer_addr_t)data_ptr - (pointer_addr_t)common_record), v1_output_record_size ); abort(); } // advance to next output record common_record = (common_record_t *)data_ptr; v1_block = (v1_block_t *)common_record->data; // buffer size sanity check - should never happen, but check it anyway bsize = (pointer_addr_t)common_record - (pointer_addr_t)fs->nffile->block_header - sizeof(data_block_header_t); if ( bsize > BUFFSIZE ) { syslog(LOG_ERR,"### Software error ###: %s line %d", __FILE__, __LINE__); syslog(LOG_ERR,"Process_v1: Output buffer overflow! Flush buffer and skip records."); syslog(LOG_ERR,"Buffer size: size: %u, bsize: %llu > %u", fs->nffile->block_header->size, (unsigned long long)bsize, BUFFSIZE); // reset buffer fs->nffile->block_header->size = 0; fs->nffile->block_header->NumRecords = 0; fs->nffile->buff_ptr = (void *)((pointer_addr_t)fs->nffile->block_header + sizeof(data_block_header_t) ); return; } } // End of foreach v1 record // update file record size ( -> output buffer size ) fs->nffile->block_header->NumRecords += count; fs->nffile->block_header->size += count * v1_output_record_size; fs->nffile->buff_ptr = (void *)common_record; // still to go for this many input bytes size_left -= NETFLOW_V1_HEADER_LENGTH + count * flow_record_length; // next header v1_header = (netflow_v1_header_t *)v1_record; // should never be < 0 done = size_left <= 0; } // End of while !done return; } /* End of Process_v1 */
int AddExtensionMap (FlowSource_t * fs, extension_map_t * map) { pointer_addr_t bsize; int next_slot = fs->extension_map_list.next_free; // is it a new map, we have not yet in the list if (map->map_id == INIT_ID) { if (next_slot >= fs->extension_map_list.max_maps) { // extend map list extension_map_t **p = realloc ((void *) fs->extension_map_list.maps, (fs->extension_map_list.max_maps + MAP_BLOCKSIZE) * sizeof (extension_map_t *)); if (!p) { syslog (LOG_ERR, "malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror (errno)); return 0; } fs->extension_map_list.maps = p; fs->extension_map_list.max_maps += MAP_BLOCKSIZE; } fs->extension_map_list.maps[next_slot] = map; map->map_id = next_slot; fs->extension_map_list.next_free++; } // sanity check for buffer size bsize = (pointer_addr_t) fs->nffile->buff_ptr - (pointer_addr_t) fs->nffile->block_header; // at least space for the map size is required if (bsize >= (BUFFSIZE - map->size)) { syslog (LOG_WARNING, "AddExtensionMap: Outputbuffer full. Flush buffer but have to skip records."); return 0; } if (!CheckBufferSpace (fs->nffile, map->size)) { // fishy! - should never happen. maybe disk full? syslog (LOG_ERR, "AddExtensionMap: output buffer size error. Abort record processing"); return 0; } memcpy (fs->nffile->buff_ptr, (void *) map, map->size); fs->nffile->buff_ptr += map->size; fs->nffile->block_header->size += map->size; fs->nffile->block_header->NumRecords++; return 1; } // End of AddExtensionMap
static void PackRecord(master_record_t *master_record, nffile_t *nffile) { extension_map_t *extension_map = master_record->map_ref; uint32_t required = COMMON_RECORD_DATA_SIZE + extension_map->extension_size; size_t size; void *p; int i; // check size of packets and bytes if ( master_record->dPkts > 0xffffffffLL ) { master_record->flags |= FLAG_PKG_64; required += 8; } else { master_record->flags &= ~FLAG_PKG_64; required += 4; } if ( master_record->dOctets > 0xffffffffLL ) { master_record->flags |= FLAG_BYTES_64; required += 8; } else { master_record->flags &= ~FLAG_BYTES_64; required += 4; } if ( (master_record->flags & FLAG_IPV6_ADDR) != 0 ) // IPv6 required += 32; else required += 8; master_record->size = required; // flush current buffer to disc if not enough space if ( !CheckBufferSpace(nffile, required) ) { return; } // enough buffer space available at this point p = nffile->buff_ptr; // write common record size = COMMON_RECORD_DATA_SIZE; memcpy(p, (void *)master_record, size); p = (void *)((pointer_addr_t)p + size); // Required extension 1 - IP addresses if ( (master_record->flags & FLAG_IPV6_ADDR) != 0 ) { // IPv6 // IPv6 // keep compiler happy // memcpy(p, (void *)master_record->v6.srcaddr, 4 * sizeof(uint64_t)); memcpy(p, (void *)master_record->ip_union._ip_64.addr, 4 * sizeof(uint64_t)); p = (void *)((pointer_addr_t)p + 4 * sizeof(uint64_t)); } else { // IPv4 uint32_t *u = (uint32_t *)p; u[0] = master_record->v4.srcaddr; u[1] = master_record->v4.dstaddr; p = (void *)((pointer_addr_t)p + 2 * sizeof(uint32_t)); } // Required extension 2 - packet counter if ( (master_record->flags & FLAG_PKG_64 ) != 0 ) { // 64bit packet counter value64_t l, *v = (value64_t *)p; l.val.val64 = master_record->dPkts; v->val.val32[0] = l.val.val32[0]; v->val.val32[1] = l.val.val32[1]; p = (void *)((pointer_addr_t)p + sizeof(uint64_t)); } else { // 32bit packet counter *((uint32_t *)p) = master_record->dPkts; p = (void *)((pointer_addr_t)p + sizeof(uint32_t)); } // Required extension 3 - byte counter if ( (master_record->flags & FLAG_BYTES_64 ) != 0 ) { // 64bit byte counter value64_t l, *v = (value64_t *)p; l.val.val64 = master_record->dOctets; v->val.val32[0] = l.val.val32[0]; v->val.val32[1] = l.val.val32[1]; p = (void *)((pointer_addr_t)p + sizeof(uint64_t)); } else { // 32bit bytes counter *((uint32_t *)p) = master_record->dOctets; p = (void *)((pointer_addr_t)p + sizeof(uint32_t)); } // Process optional extensions i=0; while ( extension_map->ex_id[i] ) { switch (extension_map->ex_id[i++]) { // 0 - 3 should never be in an extension table so - ignore it case 0: case 1: case 2: case 3: break; case EX_IO_SNMP_2: { // input/output SNMP 2 byte tpl_ext_4_t *tpl = (tpl_ext_4_t *)p; tpl->input = master_record->input; tpl->output = master_record->output; p = (void *)tpl->data; } break; case EX_IO_SNMP_4: { // input/output SNMP 4 byte tpl_ext_5_t *tpl = (tpl_ext_5_t *)p; tpl->input = master_record->input; tpl->output = master_record->output; p = (void *)tpl->data; } break; case EX_AS_2: { // srcas/dstas 2 byte tpl_ext_6_t *tpl = (tpl_ext_6_t *)p; tpl->src_as = master_record->srcas; tpl->dst_as = master_record->dstas; p = (void *)tpl->data; } break; case EX_AS_4: { // srcas/dstas 4 byte tpl_ext_7_t *tpl = (tpl_ext_7_t *)p; tpl->src_as = master_record->srcas; tpl->dst_as = master_record->dstas; p = (void *)tpl->data; } break; case EX_MULIPLE: { tpl_ext_8_t *tpl = (tpl_ext_8_t *)p; // use a 32 bit int to copy all 4 fields tpl->any = master_record->any; p = (void *)tpl->data; } break; case EX_NEXT_HOP_v4: { tpl_ext_9_t *tpl = (tpl_ext_9_t *)p; tpl->nexthop = master_record->ip_nexthop.v4; p = (void *)tpl->data; } break; case EX_NEXT_HOP_v6: { tpl_ext_10_t *tpl = (tpl_ext_10_t *)p; tpl->nexthop[0] = master_record->ip_nexthop.v6[0]; tpl->nexthop[1] = master_record->ip_nexthop.v6[1]; p = (void *)tpl->data; } break; case EX_NEXT_HOP_BGP_v4: { tpl_ext_11_t *tpl = (tpl_ext_11_t *)p; tpl->bgp_nexthop = master_record->bgp_nexthop.v4; p = (void *)tpl->data; } break; case EX_NEXT_HOP_BGP_v6: { tpl_ext_12_t *tpl = (tpl_ext_12_t *)p; tpl->bgp_nexthop[0] = master_record->bgp_nexthop.v6[0]; tpl->bgp_nexthop[1] = master_record->bgp_nexthop.v6[1]; p = (void *)tpl->data; } break; case EX_VLAN: { tpl_ext_13_t *tpl = (tpl_ext_13_t *)p; tpl->src_vlan = master_record->src_vlan; tpl->dst_vlan = master_record->dst_vlan; p = (void *)tpl->data; } break; case EX_OUT_PKG_4: { tpl_ext_14_t *tpl = (tpl_ext_14_t *)p; tpl->out_pkts = master_record->out_pkts; p = (void *)tpl->data; } break; case EX_OUT_PKG_8: { tpl_ext_15_t v, *tpl = (tpl_ext_15_t *)p; v.out_pkts = master_record->out_pkts; tpl->v[0] = v.v[0]; tpl->v[1] = v.v[1]; p = (void *)tpl->data; } break; case EX_OUT_BYTES_4: { tpl_ext_16_t *tpl = (tpl_ext_16_t *)p; tpl->out_bytes = master_record->out_bytes; p = (void *)tpl->data; } break; case EX_OUT_BYTES_8: { tpl_ext_17_t v, *tpl = (tpl_ext_17_t *)p; v.out_bytes = master_record->out_bytes; tpl->v[0] = v.v[0]; tpl->v[1] = v.v[1]; p = (void *)tpl->data; } break; case EX_AGGR_FLOWS_4: { tpl_ext_18_t *tpl = (tpl_ext_18_t *)p; tpl->aggr_flows = master_record->aggr_flows; p = (void *)tpl->data; } break; case EX_AGGR_FLOWS_8: { tpl_ext_19_t v, *tpl = (tpl_ext_19_t *)p; v.aggr_flows = master_record->aggr_flows; tpl->v[0] = v.v[0]; tpl->v[1] = v.v[1]; p = (void *)tpl->data; } break; case EX_MAC_1: { tpl_ext_20_t v, *tpl = (tpl_ext_20_t *)p; v.in_src_mac = master_record->in_src_mac; tpl->v1[0] = v.v1[0]; tpl->v1[1] = v.v1[1]; v.out_dst_mac = master_record->out_dst_mac; tpl->v2[0] = v.v2[0]; tpl->v2[1] = v.v2[1]; p = (void *)tpl->data; } break; case EX_MAC_2: { tpl_ext_21_t v, *tpl = (tpl_ext_21_t *)p; v.in_dst_mac = master_record->in_dst_mac; tpl->v1[0] = v.v1[0]; tpl->v1[1] = v.v1[1]; v.out_src_mac = master_record->out_src_mac; tpl->v2[0] = v.v2[0]; tpl->v2[1] = v.v2[1]; p = (void *)tpl->data; } break; case EX_MPLS: { tpl_ext_22_t *tpl = (tpl_ext_22_t *)p; int j; for (j=0; j<10; j++ ) { tpl->mpls_label[j] = master_record->mpls_label[j]; } p = (void *)tpl->data; } break; case EX_ROUTER_IP_v4: { tpl_ext_23_t *tpl = (tpl_ext_23_t *)p; tpl->router_ip = master_record->ip_router.v4; p = (void *)tpl->data; } break; case EX_ROUTER_IP_v6: { tpl_ext_24_t *tpl = (tpl_ext_24_t *)p; tpl->router_ip[0] = master_record->ip_router.v6[0]; tpl->router_ip[1] = master_record->ip_router.v6[1]; p = (void *)tpl->data; } break; case EX_ROUTER_ID: { tpl_ext_25_t *tpl = (tpl_ext_25_t *)p; tpl->engine_type = master_record->engine_type; tpl->engine_id = master_record->engine_id; p = (void *)tpl->data; } break; case EX_BGPADJ: { tpl_ext_26_t *tpl = (tpl_ext_26_t *)p; tpl->bgpNextAdjacentAS = master_record->bgpNextAdjacentAS; tpl->bgpPrevAdjacentAS = master_record->bgpPrevAdjacentAS; p = (void *)tpl->data; } break; case EX_RECEIVED: { tpl_ext_27_t *tpl = (tpl_ext_27_t *)p; tpl->received = master_record->received; p = (void *)tpl->data; } break; #ifdef NSEL case EX_NSEL_COMMON: { tpl_ext_37_t *tpl = (tpl_ext_37_t *)p; tpl->flow_start = master_record->flow_start; tpl->conn_id = master_record->conn_id; tpl->fw_event = master_record->fw_event; tpl->nsel_icmp = master_record->icmp; tpl->fill = 0; tpl->fill2 = 0; tpl->fw_xevent = master_record->fw_xevent; p = (void *)tpl->data; } break; case EX_NSEL_XLATE_PORTS: { tpl_ext_38_t *tpl = (tpl_ext_38_t *)p; tpl->xlate_src_port = master_record->xlate_src_port; tpl->xlate_dst_port = master_record->xlate_dst_port; p = (void *)tpl->data; } break; case EX_NSEL_XLATE_IP_v4: { tpl_ext_39_t *tpl = (tpl_ext_39_t *)p; tpl->xlate_src_ip = master_record->xlate_src_ip.v4; tpl->xlate_dst_ip = master_record->xlate_dst_ip.v4; p = (void *)tpl->data; } break; case EX_NSEL_XLATE_IP_v6: { tpl_ext_40_t *tpl = (tpl_ext_40_t *)p; tpl->xlate_src_ip[0] = master_record->xlate_src_ip.v6[0]; tpl->xlate_src_ip[1] = master_record->xlate_src_ip.v6[1]; p = (void *)tpl->data; tpl->xlate_dst_ip[0] = master_record->xlate_dst_ip.v6[0]; tpl->xlate_dst_ip[1] = master_record->xlate_dst_ip.v6[1]; p = (void *)tpl->data; } break; case EX_NSEL_ACL: { tpl_ext_41_t *tpl = (tpl_ext_41_t *)p; int j; for (j=0; j<3; j++) { tpl->ingress_acl_id[j] = master_record->ingress_acl_id[j]; tpl->egress_acl_id[j] = master_record->egress_acl_id[j]; } p = (void *)tpl->data; } break; case EX_NSEL_USER: { tpl_ext_42_t *tpl = (tpl_ext_42_t *)p; strncpy((void *)tpl->username, (void *)master_record->username, sizeof(tpl->username)); tpl->username[sizeof(tpl->username)-1] = '\0'; // safety 0 p = (void *)tpl->data; } break; case EX_NSEL_USER_MAX: { tpl_ext_43_t *tpl = (tpl_ext_43_t *)p; strncpy((void *)tpl->username, (void *)master_record->username, sizeof(tpl->username)); tpl->username[sizeof(tpl->username)-1] = '\0'; // safety 0 p = (void *)tpl->data; } break; #endif #ifdef NEL case EX_NEL_COMMON: { tpl_ext_46_t *tpl = (tpl_ext_46_t *)p; tpl->nat_event = master_record->nat_event; tpl->fill = 0; tpl->flags = 0; tpl->post_src_port = master_record->post_src_port; tpl->post_dst_port = master_record->post_dst_port; tpl->ingress_vrfid = master_record->ingress_vrfid; p = (void *)tpl->data; } break; case EX_NEL_GLOBAL_IP_v4: { tpl_ext_47_t *tpl = (tpl_ext_47_t *)p; tpl->nat_inside = master_record->nat_inside.v4; tpl->nat_outside = master_record->nat_outside.v4; p = (void *)tpl->data; } break; case EX_NEL_GLOBAL_IP_v6: { tpl_ext_48_t *tpl = (tpl_ext_48_t *)p; tpl->nat_inside[0] = master_record->nat_inside.v6[0]; tpl->nat_inside[1] = master_record->nat_inside.v6[1]; p = (void *)tpl->data; tpl->nat_outside[0] = master_record->nat_outside.v6[0]; tpl->nat_outside[1] = master_record->nat_outside.v6[1]; p = (void *)tpl->data; } break; #endif } } nffile->block_header->size += required; nffile->block_header->NumRecords++; #ifdef DEVEL if ( ((pointer_addr_t)p - (pointer_addr_t)nffile->buff_ptr) != required ) { fprintf(stderr, "Packrecord: size missmatch: required: %i, written: %li!\n", required, (long)((ptrdiff_t)p - (ptrdiff_t)nffile->buff_ptr)); exit(255); } #endif nffile->buff_ptr = p; } // End of PackRecord