diff --git a/ChangeLog b/ChangeLog index 2e338ad..ec981c9 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2017-12-27 +- Add ipfix delta timestamp elements 158/159. +- Update sflow code to commit 7322984 of https://github.com/sflow/sflowtool + 2017-12-22 - Fix potential memory leaks in nfpcapd diff --git a/bin/Makefile.am b/bin/Makefile.am index 3b02f10..091652c 100755 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -111,7 +111,7 @@ nfpcapd_LDADD += -lpcap nfpcapd_LDFLAGS = -pthread endif -sfcapd_SOURCES = sfcapd.c sflow.c sflow.h sflow_proto.h \ +sfcapd_SOURCES = sfcapd.c sflow_nfdump.c sflow_nfdump.h sflow.h sflow_v2v4.h \ $(nfstatfile) $(launch) \ $(nfnet) $(collector) $(bookkeeper) $(expire) sfcapd_LDADD = -lnfdump diff --git a/bin/applybits_inline.c b/bin/applybits_inline.c index a35fbb6..6b13836 100755 --- a/bin/applybits_inline.c +++ b/bin/applybits_inline.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2017, Peter Haag * Copyright (c) 2014, Peter Haag * Copyright (c) 2009, Peter Haag * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung @@ -28,11 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author: haag $ - * - * $Id: applybits_inline.c 39 2009-11-25 08:11:15Z haag $ - * - * $LastChangedRevision: 39 $ * */ @@ -46,11 +42,11 @@ static inline void ApplyNetMaskBits(master_record_t *flow_record, int apply_netb uint32_t mask_bits = flow_record->src_mask; if ( mask_bits > 64 ) { mask = 0xffffffffffffffffLL << ( 128 - mask_bits ); - flow_record->v6.srcaddr[1] &= mask; + flow_record->V6.srcaddr[1] &= mask; } else { mask = 0xffffffffffffffffLL << ( 64 - mask_bits ); - flow_record->v6.srcaddr[0] &= mask; - flow_record->v6.srcaddr[1] = 0; + flow_record->V6.srcaddr[0] &= mask; + flow_record->V6.srcaddr[1] = 0; } } if ( apply_netbits & 2 ) { @@ -59,21 +55,21 @@ static inline void ApplyNetMaskBits(master_record_t *flow_record, int apply_netb if ( mask_bits > 64 ) { mask = 0xffffffffffffffffLL << ( 128 - mask_bits ); - flow_record->v6.dstaddr[1] &= mask; + flow_record->V6.dstaddr[1] &= mask; } else { mask = 0xffffffffffffffffLL << ( 64 - mask_bits ); - flow_record->v6.dstaddr[0] &= mask; - flow_record->v6.dstaddr[1] = 0; + flow_record->V6.dstaddr[0] &= mask; + flow_record->V6.dstaddr[1] = 0; } } } else { // IPv4 if ( apply_netbits & 1 ) { uint32_t srcmask = 0xffffffff << ( 32 - flow_record->src_mask ); - flow_record->v4.srcaddr &= srcmask; + flow_record->V4.srcaddr &= srcmask; } if ( apply_netbits & 2 ) { uint32_t dstmask = 0xffffffff << ( 32 - flow_record->dst_mask ); - flow_record->v4.dstaddr &= dstmask; + flow_record->V4.dstaddr &= dstmask; } } diff --git a/bin/collector.c b/bin/collector.c index 47ad6ae..a86c56d 100755 --- a/bin/collector.c +++ b/bin/collector.c @@ -155,15 +155,15 @@ int ok; uint64_t _ip[2]; ok = inet_pton(PF_INET6, p, _ip); (*source)->sa_family = PF_INET6; - (*source)->ip.v6[0] = ntohll(_ip[0]); - (*source)->ip.v6[1] = ntohll(_ip[1]); + (*source)->ip.V6[0] = ntohll(_ip[0]); + (*source)->ip.V6[1] = ntohll(_ip[1]); } else { uint32_t _ip; ok = inet_pton(PF_INET, p, &_ip); (*source)->sa_family = PF_INET; - (*source)->ip.v6[0] = 0; - (*source)->ip.v6[1] = 0; - (*source)->ip.v4 = ntohl(_ip); + (*source)->ip.V6[0] = 0; + (*source)->ip.V6[1] = 0; + (*source)->ip.V4 = ntohl(_ip); } switch (ok) { case 0: @@ -339,9 +339,9 @@ int err; } #endif (*source)->sa_family = PF_INET; - (*source)->ip.v6[0] = 0; - (*source)->ip.v6[1] = 0; - (*source)->ip.v4 = ntohl(u.sa_in->sin_addr.s_addr); + (*source)->ip.V6[0] = 0; + (*source)->ip.V6[1] = 0; + (*source)->ip.V4 = ntohl(u.sa_in->sin_addr.s_addr); ptr = &u.sa_in->sin_addr; } break; case PF_INET6: { @@ -358,14 +358,14 @@ int err; #endif // ptr = &((struct sockaddr_in6 *)sa)->sin6_addr; (*source)->sa_family = PF_INET6; - (*source)->ip.v6[0] = ntohll(ip_ptr[0]); - (*source)->ip.v6[1] = ntohll(ip_ptr[1]); + (*source)->ip.V6[0] = ntohll(ip_ptr[0]); + (*source)->ip.V6[1] = ntohll(ip_ptr[1]); ptr = &u.sa_in6->sin6_addr; } break; default: // keep compiler happy - (*source)->ip.v6[0] = 0; - (*source)->ip.v6[1] = 0; + (*source)->ip.V6[0] = 0; + (*source)->ip.V6[1] = 0; ptr = NULL; LogError("Unknown sa fanily: %d in '%s', line '%d'", ss->ss_family, __FILE__, __LINE__ ); @@ -530,14 +530,14 @@ int FlushInfoExporter(FlowSource_t *fs, exporter_info_record_t *exporter) { char ipstr[IP_STRING_LEN]; printf("Flush Exporter: "); if ( exporter->sa_family == AF_INET ) { - uint32_t _ip = htonl(exporter->ip.v4); + uint32_t _ip = htonl(exporter->ip.V4); inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); printf("SysID: %u, IP: %16s, version: %u, ID: %2u\n", exporter->sysid, ipstr, exporter->version, exporter->id); } else if ( exporter->sa_family == AF_INET6 ) { uint64_t _ip[2]; - _ip[0] = htonll(exporter->ip.v6[0]); - _ip[1] = htonll(exporter->ip.v6[1]); + _ip[0] = htonll(exporter->ip.V6[0]); + _ip[1] = htonll(exporter->ip.V6[1]); inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); printf("SysID: %u, IP: %40s, version: %u, ID: %2u\n", exporter->sysid, ipstr, exporter->version, exporter->id); diff --git a/bin/collector_inline.c b/bin/collector_inline.c index 4e1c22b..aaf518b 100755 --- a/bin/collector_inline.c +++ b/bin/collector_inline.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2017, Peter Haag * Copyright (c) 2014, Peter Haag * Copyright (c) 2009, Peter Haag * Copyright (c) 2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung @@ -28,12 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author: haag $ - * - * $Id: collector_inline.c 37 2009-11-10 08:40:30Z haag $ - * - * $LastChangedRevision: 37 $ - * */ static inline FlowSource_t *GetFlowSource(struct sockaddr_storage *ss) { @@ -59,9 +54,9 @@ char as[100]; return NULL; } #endif - ip.v6[0] = 0; - ip.v6[1] = 0; - ip.v4 = ntohl(u.sa_in->sin_addr.s_addr); + ip.V6[0] = 0; + ip.V6[1] = 0; + ip.V4 = ntohl(u.sa_in->sin_addr.s_addr); ptr = &u.sa_in->sin_addr; } break; case PF_INET6: { @@ -75,14 +70,14 @@ char as[100]; } #endif // ptr = &((struct sockaddr_in6 *)sa)->sin6_addr; - ip.v6[0] = ntohll(ip_ptr[0]); - ip.v6[1] = ntohll(ip_ptr[1]); + ip.V6[0] = ntohll(ip_ptr[0]); + ip.V6[1] = ntohll(ip_ptr[1]); ptr = &u.sa_in6->sin6_addr; } break; default: // keep compiler happy - ip.v6[0] = 0; - ip.v6[1] = 0; + ip.V6[0] = 0; + ip.V6[1] = 0; ptr = NULL; LogError("Unknown sa fanily: %d in '%s', line '%d'", ss->ss_family, __FILE__, __LINE__ ); @@ -97,7 +92,7 @@ char as[100]; fs = FlowSource; while ( fs ) { - if ( ip.v6[0] == fs->ip.v6[0] && ip.v6[1] == fs->ip.v6[1] ) + if ( ip.V6[0] == fs->ip.V6[0] && ip.V6[1] == fs->ip.V6[1] ) return fs; // if we match any source, store the current IP address - works as faster cache next time diff --git a/bin/exporter.c b/bin/exporter.c index 974935b..687d7b9 100755 --- a/bin/exporter.c +++ b/bin/exporter.c @@ -151,14 +151,14 @@ char *p1, *p2; #define IP_STRING_LEN 40 char ipstr[IP_STRING_LEN]; if ( exporter_record->sa_family == AF_INET ) { - uint32_t _ip = htonl(exporter_record->ip.v4); + uint32_t _ip = htonl(exporter_record->ip.V4); inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); printf("SysID: %u, IP: %16s, version: %u, ID: %2u, Slot: %u\n", exporter_record->sysid, ipstr, exporter_record->version, exporter_record->id, id); } else if ( exporter_record->sa_family == AF_INET6 ) { uint64_t _ip[2]; - _ip[0] = htonll(exporter_record->ip.v6[0]); - _ip[1] = htonll(exporter_record->ip.v6[1]); + _ip[0] = htonll(exporter_record->ip.V6[0]); + _ip[1] = htonll(exporter_record->ip.V6[1]); inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); printf("SysID: %u, IP: %40s, version: %u, ID: %2u, Slot: %u\n", exporter_record->sysid, ipstr, exporter_record->version, exporter_record->id, id); @@ -347,14 +347,14 @@ uint64_t total_bytes; found = 1; printf("\n"); if ( exporter_record->sa_family == AF_INET ) { - uint32_t _ip = htonl(exporter_record->ip.v4); + uint32_t _ip = htonl(exporter_record->ip.V4); inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); printf("SysID: %u, IP: %16s, version: %u, ID: %2u, Sequence Failures: %u\n", exporter_record->sysid, ipstr, exporter_record->version, exporter_record->exporter_id, exporter_record->sequence_failure); } else if ( exporter_record->sa_family == AF_INET6 ) { uint64_t _ip[2]; - _ip[0] = htonll(exporter_record->ip.v6[0]); - _ip[1] = htonll(exporter_record->ip.v6[1]); + _ip[0] = htonll(exporter_record->ip.V6[0]); + _ip[1] = htonll(exporter_record->ip.V6[1]); inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); printf("SysID: %u, IP: %40s, version: %u, ID: %2u, Sequence Failures: %u\n", exporter_record->sysid, ipstr, exporter_record->version, exporter_record->exporter_id, exporter_record->sequence_failure); @@ -410,7 +410,7 @@ uint64_t total_bytes; printf("\n"); exporter = &exporter_list[i]->info; if ( exporter->sa_family == AF_INET ) { - uint32_t _ip = htonl(exporter->ip.v4); + uint32_t _ip = htonl(exporter->ip.V4); inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); if ( exporter_list[i]->flows ) printf("SysID: %u, IP: %16s, version: %u, ID: %2u, Sequence failures: %u, packets: %llu, flows: %llu\n", @@ -424,8 +424,8 @@ uint64_t total_bytes; } else if ( exporter->sa_family == AF_INET6 ) { uint64_t _ip[2]; - _ip[0] = htonll(exporter->ip.v6[0]); - _ip[1] = htonll(exporter->ip.v6[1]); + _ip[0] = htonll(exporter->ip.V6[0]); + _ip[1] = htonll(exporter->ip.V6[1]); inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); if ( exporter_list[i]->flows ) printf("SysID: %u, IP: %40s, version: %u, ID: %2u, Sequence failures: %u, packets: %llu, flows: %llu\n ", diff --git a/bin/ft2nfdump.c b/bin/ft2nfdump.c index 4f37d76..86e7fa1 100644 --- a/bin/ft2nfdump.c +++ b/bin/ft2nfdump.c @@ -1,5 +1,6 @@ /* * All rights reserved. + * Copyright (c) 2017, Peter Haag * Copyright (c) 2016, Peter Haag * Copyright (c) 2014, Peter Haag * Copyright (c) 2009, Peter Haag @@ -238,8 +239,8 @@ uint32_t cnt; record.last = ftt.secs; record.msec_last = ftt.msecs; - record.v4.srcaddr = *((uint32_t*)(rec+fo.srcaddr)); - record.v4.dstaddr = *((uint32_t*)(rec+fo.dstaddr)); + record.V4.srcaddr = *((uint32_t*)(rec+fo.srcaddr)); + record.V4.dstaddr = *((uint32_t*)(rec+fo.dstaddr)); record.srcport = *((uint16_t*)(rec+fo.srcport)); record.dstport = *((uint16_t*)(rec+fo.dstport)); @@ -268,10 +269,10 @@ uint32_t cnt; record.dst_tos = 0; break; case EX_ROUTER_IP_v4: - record.ip_nexthop.v4 = *((uint32_t*)(rec+fo.peer_nexthop)); + record.ip_nexthop.V4 = *((uint32_t*)(rec+fo.peer_nexthop)); break; case EX_NEXT_HOP_v4: - record.ip_router.v4 = *((uint32_t*)(rec+fo.router_sc)); + record.ip_router.V4 = *((uint32_t*)(rec+fo.router_sc)); break; case EX_ROUTER_ID: record.engine_type = *((uint8_t*)(rec+fo.engine_type)); diff --git a/bin/ipfix.c b/bin/ipfix.c index 3e7b397..dbc18cc 100644 --- a/bin/ipfix.c +++ b/bin/ipfix.c @@ -28,12 +28,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author:$ - * - * $Id:$ - * - * $LastChangedRevision:$ - * */ #include "config.h" @@ -106,12 +100,13 @@ typedef struct sequence_map_s { #define move_mac 11 #define move_mpls 12 #define Time64Mili 13 -#define saveICMP 14 -#define zero8 15 -#define zero16 16 -#define zero32 17 -#define zero64 18 -#define zero128 19 +#define TimeDeltaMicro 14 +#define saveICMP 15 +#define zero8 16 +#define zero16 17 +#define zero32 18 +#define zero64 19 +#define zero128 20 uint32_t id; // sequence ID as defined above uint16_t input_offset; // copy/process data at this input offset @@ -135,6 +130,7 @@ typedef struct input_translation_s { uint32_t output_record_size; // required size in nfdump format // tmp vars needed while processing the data record + int delta_time; // delta micro or absolute ms time stamps uint64_t flow_start; // start time in msec uint64_t flow_end; // end time in msec uint32_t ICMP_offset; // offset of ICMP type/code in data stream @@ -266,6 +262,8 @@ static struct ipfix_element_map_s { { IPFIX_postSourceMacAddress, _6bytes, _8bytes, move_mac, zero64, EX_MAC_2}, { IPFIX_flowStartMilliseconds, _8bytes, _8bytes, Time64Mili, zero32, COMMON_BLOCK}, { IPFIX_flowEndMilliseconds, _8bytes, _8bytes, Time64Mili, zero32, COMMON_BLOCK}, + { IPFIX_flowStartDeltaMicroseconds, _4bytes, _4bytes, TimeDeltaMicro, zero32, COMMON_BLOCK}, + { IPFIX_flowEndDeltaMicroseconds, _4bytes, _4bytes, TimeDeltaMicro, zero32, COMMON_BLOCK}, {0, 0, 0} }; @@ -319,6 +317,8 @@ static inline void Process_ipfix_template_withdraw(exporter_ipfix_domain_t *expo static inline void Process_ipfix_option_data(exporter_ipfix_domain_t *exporter, void *data_flowset, FlowSource_t *fs); +static inline void Process_ipfix_data(exporter_ipfix_domain_t *exporter, uint32_t ExportTime, void *data_flowset, FlowSource_t *fs, input_translation_t *table ); + #include "inline.c" #include "nffile_inline.c" @@ -356,18 +356,18 @@ uint32_t ObservationDomain = ntohl(ipfix_header->ObservationDomain); while ( *e ) { if ( (*e)->info.id == ObservationDomain && (*e)->info.version == 10 && - (*e)->info.ip.v6[0] == fs->ip.v6[0] && (*e)->info.ip.v6[1] == fs->ip.v6[1]) + (*e)->info.ip.V6[0] == fs->ip.V6[0] && (*e)->info.ip.V6[1] == fs->ip.V6[1]) return *e; e = &((*e)->next); } if ( fs->sa_family == AF_INET ) { - uint32_t _ip = htonl(fs->ip.v4); + uint32_t _ip = htonl(fs->ip.V4); inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); } else if ( fs->sa_family == AF_INET6 ) { uint64_t _ip[2]; - _ip[0] = htonll(fs->ip.v6[0]); - _ip[1] = htonll(fs->ip.v6[1]); + _ip[0] = htonll(fs->ip.V6[0]); + _ip[1] = htonll(fs->ip.V6[1]); inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); } else { strncpy(ipstr, "", IP_STRING_LEN); @@ -637,7 +637,8 @@ size_t size_required; table->flags = 0; SetFlag(table->flags, FLAG_PKG_64); SetFlag(table->flags, FLAG_BYTES_64); - table->ICMP_offset = 0; + table->delta_time = 0; + table->ICMP_offset = 0; // table->sampler_offset = 0; // table->sampler_size = 0; // table->engine_offset = 0; @@ -658,10 +659,20 @@ size_t size_required; // The order we Push all ipfix elements, must corresponde to the structure of the common record // followed by all available extension in the extension map offset = BYTE_OFFSET_first; - PushSequence( table, IPFIX_flowStartMilliseconds, &offset, &table->flow_start); - offset = BYTE_OFFSET_first + 4; - PushSequence( table, IPFIX_flowEndMilliseconds, &offset, &table->flow_end); - offset = BYTE_OFFSET_first + 8; + if ( cache.lookup_info[IPFIX_flowStartDeltaMicroseconds].found ) { + PushSequence( table, IPFIX_flowStartDeltaMicroseconds, &offset, &table->flow_start); + offset = BYTE_OFFSET_first + 4; + PushSequence( table, IPFIX_flowEndDeltaMicroseconds, &offset, &table->flow_end); + offset = BYTE_OFFSET_first + 8; + table->delta_time = 1; + dbg_printf("Time stamp: flow start/end delta microseconds\n"); + } else if ( cache.lookup_info[IPFIX_flowStartMilliseconds].found ) { + PushSequence( table, IPFIX_flowStartMilliseconds, &offset, &table->flow_start); + offset = BYTE_OFFSET_first + 4; + PushSequence( table, IPFIX_flowEndMilliseconds, &offset, &table->flow_end); + offset = BYTE_OFFSET_first + 8; + dbg_printf("Time stamp: flow start/end absolute milliseconds\n"); + } offset +=1; // Skip netflow v9 fwd status PushSequence( table, IPFIX_tcpControlBits, &offset, NULL); PushSequence( table, IPFIX_protocolIdentifier, &offset, NULL); @@ -1133,7 +1144,7 @@ uint16_t Offset = 0; fs->sa_family == PF_INET6 ? "ipv6" : "ipv4", EX_ROUTER_IP_v4); } - // XXX for now, we do not stre router ID in IPFIX + // XXX for now, we do not store router ID in IPFIX extension_descriptor[EX_ROUTER_ID].enabled = 0; /* @@ -1380,7 +1391,7 @@ uint16_t offset_std_sampler_interval, offset_std_sampler_algorithm, found_std_sa } // End of Process_ipfix_option_templates -static inline void Process_ipfix_data(exporter_ipfix_domain_t *exporter, void *data_flowset, FlowSource_t *fs, input_translation_t *table ){ +static inline void Process_ipfix_data(exporter_ipfix_domain_t *exporter, uint32_t ExportTime, void *data_flowset, FlowSource_t *fs, input_translation_t *table ){ uint64_t sampling_rate; uint32_t size_left; uint8_t *in, *out; @@ -1550,6 +1561,11 @@ char *string; { uint64_t DateMiliseconds = Get_val64((void *)&in[input_offset]); *(uint64_t *)stack = DateMiliseconds; + } break; + case TimeDeltaMicro: + { uint64_t DeltaMicroSec = Get_val32((void *)&in[input_offset]); + *(uint64_t *)stack = ((1000000LL * (uint64_t)ExportTime) - DeltaMicroSec) / 1000LL; + } break; case move_mac: /* 64bit access to potentially unaligned output buffer. use 2 x 32bit for _LP64 CPUs */ @@ -1621,15 +1637,15 @@ char *string; // 64bit access to potentially unaligned output buffer. use 2 x 32bit for _LP64 CPUs type_mask_t t; - t.val.val64 = exporter->info.ip.v6[0]; + t.val.val64 = exporter->info.ip.V6[0]; *((uint32_t *)&out[output_offset]) = t.val.val32[0]; *((uint32_t *)&out[output_offset+4]) = t.val.val32[1]; - t.val.val64 = exporter->info.ip.v6[1]; + t.val.val64 = exporter->info.ip.V6[1]; *((uint32_t *)&out[output_offset+8]) = t.val.val32[0]; *((uint32_t *)&out[output_offset+12]) = t.val.val32[1]; } else { - *((uint32_t *)&out[output_offset]) = exporter->info.ip.v4; + *((uint32_t *)&out[output_offset]) = exporter->info.ip.V4; } } @@ -1892,7 +1908,7 @@ static uint32_t packet_cntr = 0; dbg_printf("Process data flowset, length: %u\n", flowset_length); table = GetTranslationTable(exporter, flowset_id); if ( table ) { - Process_ipfix_data(exporter, flowset_header, fs, table); + Process_ipfix_data(exporter, ExportTime, flowset_header, fs, table); exporter->DataRecords++; } else if ( HasOptionTable(fs, flowset_id) ) { Process_ipfix_option_data(exporter, flowset_header, fs); diff --git a/bin/ipfix.h b/bin/ipfix.h index 6c1feed..1b5e7c9 100644 --- a/bin/ipfix.h +++ b/bin/ipfix.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2017, Peter Haag * Copyright (c) 2014, Peter Haag * Copyright (c) 2009, Peter Haag * All rights reserved. @@ -27,12 +28,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author:$ - * - * $Id:$ - * - * $LastChangedRevision:$ - * */ #ifndef _IPFIX_H @@ -260,7 +255,8 @@ typedef struct ipfix_template_elements_e_s { #define IPFIX_packetTotalCount 86 #define IPFIX_flowStartMilliseconds 152 #define IPFIX_flowEndMilliseconds 153 -// reserved 89 +#define IPFIX_flowStartDeltaMicroseconds 158 +#define IPFIX_flowEndDeltaMicroseconds 159 /* prototypes */ int Init_IPFIX(void); diff --git a/bin/netflow_v1.c b/bin/netflow_v1.c index 2d18f5c..e6b8429 100644 --- a/bin/netflow_v1.c +++ b/bin/netflow_v1.c @@ -177,7 +177,7 @@ char ipstr[IP_STRING_LEN]; // search the appropriate exporter engine while ( *e ) { if ( (*e)->info.version == version && - (*e)->info.ip.v6[0] == fs->ip.v6[0] && (*e)->info.ip.v6[1] == fs->ip.v6[1]) + (*e)->info.ip.V6[0] == fs->ip.V6[0] && (*e)->info.ip.V6[1] == fs->ip.V6[1]) return *e; e = &((*e)->next); } @@ -223,12 +223,12 @@ char ipstr[IP_STRING_LEN]; FlushInfoExporter(fs, &((*e)->info)); if ( fs->sa_family == AF_INET ) { - uint32_t _ip = htonl(fs->ip.v4); + uint32_t _ip = htonl(fs->ip.V4); inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); } else if ( fs->sa_family == AF_INET6 ) { uint64_t _ip[2]; - _ip[0] = htonll(fs->ip.v6[0]); - _ip[1] = htonll(fs->ip.v6[1]); + _ip[0] = htonll(fs->ip.V6[0]); + _ip[1] = htonll(fs->ip.V6[1]); inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); } else { strncpy(ipstr, "", IP_STRING_LEN); @@ -364,7 +364,7 @@ char *string; } 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; + tpl->router_ip = fs->ip.V4; data_ptr = (void *)tpl->data; ClearFlag(common_record->flags, FLAG_IPV6_EXP); } break; diff --git a/bin/netflow_v5_v7.c b/bin/netflow_v5_v7.c index 779ac70..0ea9739 100644 --- a/bin/netflow_v5_v7.c +++ b/bin/netflow_v5_v7.c @@ -192,7 +192,7 @@ char ipstr[IP_STRING_LEN]; // search the appropriate exporter engine while ( *e ) { if ( (*e)->info.version == version && (*e)->info.id == engine_tag && - (*e)->info.ip.v6[0] == fs->ip.v6[0] && (*e)->info.ip.v6[1] == fs->ip.v6[1]) + (*e)->info.ip.V6[0] == fs->ip.V6[0] && (*e)->info.ip.V6[1] == fs->ip.V6[1]) return *e; e = &((*e)->next); } @@ -258,12 +258,12 @@ char ipstr[IP_STRING_LEN]; FlushInfoSampler(fs, &(sampler->info)); if ( fs->sa_family == AF_INET ) { - uint32_t _ip = htonl(fs->ip.v4); + uint32_t _ip = htonl(fs->ip.V4); inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); } else if ( fs->sa_family == AF_INET6 ) { uint64_t _ip[2]; - _ip[0] = htonll(fs->ip.v6[0]); - _ip[1] = htonll(fs->ip.v6[1]); + _ip[0] = htonll(fs->ip.V6[0]); + _ip[1] = htonll(fs->ip.V6[1]); inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); } else { strncpy(ipstr, "", IP_STRING_LEN); @@ -493,7 +493,7 @@ char *string; } 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; + tpl->router_ip = fs->ip.V4; data_ptr = (void *)tpl->data; ClearFlag(common_record->flags, FLAG_IPV6_EXP); } break; @@ -707,8 +707,8 @@ uint32_t i, id, t1, t2; v5_output_record->First = htonl(t1); v5_output_record->Last = htonl(t2); - v5_output_record->srcaddr = htonl(master_record->v4.srcaddr); - v5_output_record->dstaddr = htonl(master_record->v4.dstaddr); + v5_output_record->srcaddr = htonl(master_record->V4.srcaddr); + v5_output_record->dstaddr = htonl(master_record->V4.dstaddr); v5_output_record->srcport = htons(master_record->srcport); v5_output_record->dstport = htons(master_record->dstport); @@ -746,7 +746,7 @@ uint32_t i, id, t1, t2; v5_output_record->dst_mask = master_record->dst_mask; break; case EX_NEXT_HOP_v4: - v5_output_record->nexthop = htonl(master_record->ip_nexthop.v4); + v5_output_record->nexthop = htonl(master_record->ip_nexthop.V4); break; // default: Other extensions can not be sent with v5 } diff --git a/bin/netflow_v9.c b/bin/netflow_v9.c index be96590..f49587f 100644 --- a/bin/netflow_v9.c +++ b/bin/netflow_v9.c @@ -475,18 +475,18 @@ exporter_v9_domain_t **e = (exporter_v9_domain_t **)&(fs->exporter_data); while ( *e ) { if ( (*e)->info.id == exporter_id && (*e)->info.version == 9 && - (*e)->info.ip.v6[0] == fs->ip.v6[0] && (*e)->info.ip.v6[1] == fs->ip.v6[1]) + (*e)->info.ip.V6[0] == fs->ip.V6[0] && (*e)->info.ip.V6[1] == fs->ip.V6[1]) return *e; e = &((*e)->next); } if ( fs->sa_family == AF_INET ) { - uint32_t _ip = htonl(fs->ip.v4); + uint32_t _ip = htonl(fs->ip.V4); inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); } else if ( fs->sa_family == AF_INET6 ) { uint64_t _ip[2]; - _ip[0] = htonll(fs->ip.v6[0]); - _ip[1] = htonll(fs->ip.v6[1]); + _ip[0] = htonll(fs->ip.V6[0]); + _ip[1] = htonll(fs->ip.V6[1]); inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); } else { strncpy(ipstr, "", IP_STRING_LEN); @@ -1845,15 +1845,15 @@ char *string; /* 64bit access to potentially unaligned output buffer. use 2 x 32bit for _LP64 CPUs */ type_mask_t t; - t.val.val64 = exporter->info.ip.v6[0]; + t.val.val64 = exporter->info.ip.V6[0]; *((uint32_t *)&out[output_offset]) = t.val.val32[0]; *((uint32_t *)&out[output_offset+4]) = t.val.val32[1]; - t.val.val64 = exporter->info.ip.v6[1]; + t.val.val64 = exporter->info.ip.V6[1]; *((uint32_t *)&out[output_offset+8]) = t.val.val32[0]; *((uint32_t *)&out[output_offset+12]) = t.val.val32[1]; } else { - *((uint32_t *)&out[output_offset]) = exporter->info.ip.v4; + *((uint32_t *)&out[output_offset]) = exporter->info.ip.V4; } } @@ -2626,18 +2626,18 @@ uint16_t icmp; // IP address info if ((master_record->flags & FLAG_IPV6_ADDR) != 0 ) { // IPv6 - master_record->v6.srcaddr[0] = htonll(master_record->v6.srcaddr[0]); - master_record->v6.srcaddr[1] = htonll(master_record->v6.srcaddr[1]); - master_record->v6.dstaddr[0] = htonll(master_record->v6.dstaddr[0]); - master_record->v6.dstaddr[1] = htonll(master_record->v6.dstaddr[1]); + master_record->V6.srcaddr[0] = htonll(master_record->V6.srcaddr[0]); + master_record->V6.srcaddr[1] = htonll(master_record->V6.srcaddr[1]); + master_record->V6.dstaddr[0] = htonll(master_record->V6.dstaddr[0]); + master_record->V6.dstaddr[1] = htonll(master_record->V6.dstaddr[1]); // keep compiler happy - // memcpy(peer->buff_ptr, master_record->v6.srcaddr, 4 * sizeof(uint64_t)); + // memcpy(peer->buff_ptr, master_record->V6.srcaddr, 4 * sizeof(uint64_t)); memcpy(peer->buff_ptr, master_record->ip_union._ip_64.addr, 4 * sizeof(uint64_t)); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + 4 * sizeof(uint64_t)); } else { - Put_val32(htonl(master_record->v4.srcaddr), peer->buff_ptr); + Put_val32(htonl(master_record->V4.srcaddr), peer->buff_ptr); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + sizeof(uint32_t)); - Put_val32(htonl(master_record->v4.dstaddr), peer->buff_ptr); + Put_val32(htonl(master_record->V4.dstaddr), peer->buff_ptr); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + sizeof(uint32_t)); } @@ -2712,23 +2712,23 @@ uint16_t icmp; peer->buff_ptr = (void *)tpl->data; } break; case EX_NEXT_HOP_v4: - Put_val32(htonl(master_record->ip_nexthop.v4), peer->buff_ptr); + Put_val32(htonl(master_record->ip_nexthop.V4), peer->buff_ptr); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + sizeof(uint32_t)); break; case EX_NEXT_HOP_v6: - Put_val64(htonll(master_record->ip_nexthop.v6[0]), peer->buff_ptr); + Put_val64(htonll(master_record->ip_nexthop.V6[0]), peer->buff_ptr); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + sizeof(uint64_t)); - Put_val64(htonll(master_record->ip_nexthop.v6[1]), peer->buff_ptr); + Put_val64(htonll(master_record->ip_nexthop.V6[1]), peer->buff_ptr); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + sizeof(uint64_t)); break; case EX_NEXT_HOP_BGP_v4: - Put_val32(htonl(master_record->bgp_nexthop.v4), peer->buff_ptr); + Put_val32(htonl(master_record->bgp_nexthop.V4), peer->buff_ptr); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + sizeof(uint32_t)); break; case EX_NEXT_HOP_BGP_v6: - Put_val64(htonll(master_record->bgp_nexthop.v6[0]), peer->buff_ptr); + Put_val64(htonll(master_record->bgp_nexthop.V6[0]), peer->buff_ptr); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + sizeof(uint64_t)); - Put_val64(htonll(master_record->bgp_nexthop.v6[1]), peer->buff_ptr); + Put_val64(htonll(master_record->bgp_nexthop.V6[1]), peer->buff_ptr); peer->buff_ptr = (void *)((pointer_addr_t)peer->buff_ptr + sizeof(uint64_t)); break; case EX_VLAN: diff --git a/bin/nf_common.c b/bin/nf_common.c index 4793f90..fbecd31 100644 --- a/bin/nf_common.c +++ b/bin/nf_common.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2017, Peter Haag * Copyright (c) 2016, Peter Haag * Copyright (c) 2014, Peter Haag * Copyright (c) 2009, Peter Haag @@ -29,7 +30,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * */ #include "config.h" @@ -684,16 +684,16 @@ extension_map_t *extension_map = r->map_ref; uint64_t dnet[2]; // remember IPs for network - snet[0] = r->v6.srcaddr[0]; - snet[1] = r->v6.srcaddr[1]; - dnet[0] = r->v6.dstaddr[0]; - dnet[1] = r->v6.dstaddr[1]; - r->v6.srcaddr[0] = htonll(r->v6.srcaddr[0]); - r->v6.srcaddr[1] = htonll(r->v6.srcaddr[1]); - r->v6.dstaddr[0] = htonll(r->v6.dstaddr[0]); - r->v6.dstaddr[1] = htonll(r->v6.dstaddr[1]); - inet_ntop(AF_INET6, r->v6.srcaddr, as, sizeof(as)); - inet_ntop(AF_INET6, r->v6.dstaddr, ds, sizeof(ds)); + snet[0] = r->V6.srcaddr[0]; + snet[1] = r->V6.srcaddr[1]; + dnet[0] = r->V6.dstaddr[0]; + dnet[1] = r->V6.dstaddr[1]; + r->V6.srcaddr[0] = htonll(r->V6.srcaddr[0]); + r->V6.srcaddr[1] = htonll(r->V6.srcaddr[1]); + r->V6.dstaddr[0] = htonll(r->V6.dstaddr[0]); + r->V6.dstaddr[1] = htonll(r->V6.dstaddr[1]); + inet_ntop(AF_INET6, r->V6.srcaddr, as, sizeof(as)); + inet_ntop(AF_INET6, r->V6.dstaddr, ds, sizeof(ds)); if ( ! long_v6 ) { condense_v6(as); condense_v6(ds); @@ -730,12 +730,12 @@ extension_map_t *extension_map = r->map_ref; } else { // IPv4 uint32_t snet, dnet; - snet = r->v4.srcaddr; - dnet = r->v4.dstaddr; - r->v4.srcaddr = htonl(r->v4.srcaddr); - r->v4.dstaddr = htonl(r->v4.dstaddr); - inet_ntop(AF_INET, &r->v4.srcaddr, as, sizeof(as)); - inet_ntop(AF_INET, &r->v4.dstaddr, ds, sizeof(ds)); + snet = r->V4.srcaddr; + dnet = r->V4.dstaddr; + r->V4.srcaddr = htonl(r->V4.srcaddr); + r->V4.dstaddr = htonl(r->V4.dstaddr); + inet_ntop(AF_INET, &r->V4.srcaddr, as, sizeof(as)); + inet_ntop(AF_INET, &r->V4.dstaddr, ds, sizeof(ds)); if ( r->src_mask || r->dst_mask) { snet &= 0xffffffffL << ( 32 - r->src_mask ); snet = htonl(snet); @@ -866,8 +866,8 @@ extension_map_t *extension_map = r->map_ref; break; case EX_NEXT_HOP_v4: as[0] = 0; - r->ip_nexthop.v4 = htonl(r->ip_nexthop.v4); - inet_ntop(AF_INET, &r->ip_nexthop.v4, as, sizeof(as)); + r->ip_nexthop.V4 = htonl(r->ip_nexthop.V4); + inet_ntop(AF_INET, &r->ip_nexthop.V4, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, @@ -880,9 +880,9 @@ extension_map_t *extension_map = r->map_ref; break; case EX_NEXT_HOP_v6: as[0] = 0; - r->ip_nexthop.v6[0] = htonll(r->ip_nexthop.v6[0]); - r->ip_nexthop.v6[1] = htonll(r->ip_nexthop.v6[1]); - inet_ntop(AF_INET6, r->ip_nexthop.v6, as, sizeof(as)); + r->ip_nexthop.V6[0] = htonll(r->ip_nexthop.V6[0]); + r->ip_nexthop.V6[1] = htonll(r->ip_nexthop.V6[1]); + inet_ntop(AF_INET6, r->ip_nexthop.V6, as, sizeof(as)); if ( ! long_v6 ) { condense_v6(as); condense_v6(ds); @@ -898,8 +898,8 @@ extension_map_t *extension_map = r->map_ref; break; case EX_NEXT_HOP_BGP_v4: as[0] = 0; - r->bgp_nexthop.v4 = htonl(r->bgp_nexthop.v4); - inet_ntop(AF_INET, &r->bgp_nexthop.v4, as, sizeof(as)); + r->bgp_nexthop.V4 = htonl(r->bgp_nexthop.V4); + inet_ntop(AF_INET, &r->bgp_nexthop.V4, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, @@ -912,9 +912,9 @@ extension_map_t *extension_map = r->map_ref; break; case EX_NEXT_HOP_BGP_v6: as[0] = 0; - r->bgp_nexthop.v6[0] = htonll(r->bgp_nexthop.v6[0]); - r->bgp_nexthop.v6[1] = htonll(r->bgp_nexthop.v6[1]); - inet_ntop(AF_INET6, r->ip_nexthop.v6, as, sizeof(as)); + r->bgp_nexthop.V6[0] = htonll(r->bgp_nexthop.V6[0]); + r->bgp_nexthop.V6[1] = htonll(r->bgp_nexthop.V6[1]); + inet_ntop(AF_INET6, r->ip_nexthop.V6, as, sizeof(as)); if ( ! long_v6 ) { condense_v6(as); condense_v6(ds); @@ -1015,8 +1015,8 @@ extension_map_t *extension_map = r->map_ref; } break; case EX_ROUTER_IP_v4: as[0] = 0; - r->ip_router.v4 = htonl(r->ip_router.v4); - inet_ntop(AF_INET, &r->ip_router.v4, as, sizeof(as)); + r->ip_router.V4 = htonl(r->ip_router.V4); + inet_ntop(AF_INET, &r->ip_router.V4, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, @@ -1029,9 +1029,9 @@ extension_map_t *extension_map = r->map_ref; break; case EX_ROUTER_IP_v6: as[0] = 0; - r->ip_router.v6[0] = htonll(r->ip_router.v6[0]); - r->ip_router.v6[1] = htonll(r->ip_router.v6[1]); - inet_ntop(AF_INET6, &r->ip_router.v6, as, sizeof(as)); + r->ip_router.V6[0] = htonll(r->ip_router.V6[0]); + r->ip_router.V6[1] = htonll(r->ip_router.V6[1]); + inet_ntop(AF_INET6, &r->ip_router.V6, as, sizeof(as)); if ( ! long_v6 ) { condense_v6(as); } @@ -1223,15 +1223,15 @@ master_record_t *r = (master_record_t *)record; } // Make sure Endian does not screw us up - sa[0] = ( r->v6.srcaddr[0] >> 32 ) & 0xffffffffLL; - sa[1] = r->v6.srcaddr[0] & 0xffffffffLL; - sa[2] = ( r->v6.srcaddr[1] >> 32 ) & 0xffffffffLL; - sa[3] = r->v6.srcaddr[1] & 0xffffffffLL; + sa[0] = ( r->V6.srcaddr[0] >> 32 ) & 0xffffffffLL; + sa[1] = r->V6.srcaddr[0] & 0xffffffffLL; + sa[2] = ( r->V6.srcaddr[1] >> 32 ) & 0xffffffffLL; + sa[3] = r->V6.srcaddr[1] & 0xffffffffLL; - da[0] = ( r->v6.dstaddr[0] >> 32 ) & 0xffffffffLL; - da[1] = r->v6.dstaddr[0] & 0xffffffffLL; - da[2] = ( r->v6.dstaddr[1] >> 32 ) & 0xffffffffLL; - da[3] = r->v6.dstaddr[1] & 0xffffffffLL; + da[0] = ( r->V6.dstaddr[0] >> 32 ) & 0xffffffffLL; + da[1] = r->V6.dstaddr[0] & 0xffffffffLL; + da[2] = ( r->V6.dstaddr[1] >> 32 ) & 0xffffffffLL; + da[3] = r->V6.dstaddr[1] & 0xffffffffLL; snprintf(data_string, STRINGSIZE-1 ,"%i|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%llu|%llu", af, r->first, r->msec_first ,r->last, r->msec_last, r->prot, @@ -1261,16 +1261,16 @@ master_record_t *r = (master_record_t *)record; uint64_t dnet[2]; // remember IPs for network - snet[0] = r->v6.srcaddr[0]; - snet[1] = r->v6.srcaddr[1]; - dnet[0] = r->v6.dstaddr[0]; - dnet[1] = r->v6.dstaddr[1]; - r->v6.srcaddr[0] = htonll(r->v6.srcaddr[0]); - r->v6.srcaddr[1] = htonll(r->v6.srcaddr[1]); - r->v6.dstaddr[0] = htonll(r->v6.dstaddr[0]); - r->v6.dstaddr[1] = htonll(r->v6.dstaddr[1]); - inet_ntop(AF_INET6, r->v6.srcaddr, as, sizeof(as)); - inet_ntop(AF_INET6, r->v6.dstaddr, ds, sizeof(ds)); + snet[0] = r->V6.srcaddr[0]; + snet[1] = r->V6.srcaddr[1]; + dnet[0] = r->V6.dstaddr[0]; + dnet[1] = r->V6.dstaddr[1]; + r->V6.srcaddr[0] = htonll(r->V6.srcaddr[0]); + r->V6.srcaddr[1] = htonll(r->V6.srcaddr[1]); + r->V6.dstaddr[0] = htonll(r->V6.dstaddr[0]); + r->V6.dstaddr[1] = htonll(r->V6.dstaddr[1]); + inet_ntop(AF_INET6, r->V6.srcaddr, as, sizeof(as)); + inet_ntop(AF_INET6, r->V6.dstaddr, ds, sizeof(ds)); if ( r->src_mask || r->dst_mask) { if ( r->src_mask > 64 ) @@ -1300,12 +1300,12 @@ master_record_t *r = (master_record_t *)record; } else { // IPv4 uint32_t snet, dnet; - snet = r->v4.srcaddr; - dnet = r->v4.dstaddr; - r->v4.srcaddr = htonl(r->v4.srcaddr); - r->v4.dstaddr = htonl(r->v4.dstaddr); - inet_ntop(AF_INET, &r->v4.srcaddr, as, sizeof(as)); - inet_ntop(AF_INET, &r->v4.dstaddr, ds, sizeof(ds)); + snet = r->V4.srcaddr; + dnet = r->V4.dstaddr; + r->V4.srcaddr = htonl(r->V4.srcaddr); + r->V4.dstaddr = htonl(r->V4.dstaddr); + inet_ntop(AF_INET, &r->V4.srcaddr, as, sizeof(as)); + inet_ntop(AF_INET, &r->V4.dstaddr, ds, sizeof(ds)); if ( r->src_mask || r->dst_mask) { snet &= 0xffffffffL << ( 32 - r->src_mask ); snet = htonl(snet); @@ -1384,9 +1384,9 @@ master_record_t *r = (master_record_t *)record; if ( (r->flags & FLAG_IPV6_NH ) != 0 ) { // IPv6 // EX_NEXT_HOP_v6: as[0] = 0; - r->ip_nexthop.v6[0] = htonll(r->ip_nexthop.v6[0]); - r->ip_nexthop.v6[1] = htonll(r->ip_nexthop.v6[1]); - inet_ntop(AF_INET6, r->ip_nexthop.v6, as, sizeof(as)); + r->ip_nexthop.V6[0] = htonll(r->ip_nexthop.V6[0]); + r->ip_nexthop.V6[1] = htonll(r->ip_nexthop.V6[1]); + inet_ntop(AF_INET6, r->ip_nexthop.V6, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, ",%s", as); @@ -1397,8 +1397,8 @@ master_record_t *r = (master_record_t *)record; } else { // EX_NEXT_HOP_v4: as[0] = 0; - r->ip_nexthop.v4 = htonl(r->ip_nexthop.v4); - inet_ntop(AF_INET, &r->ip_nexthop.v4, as, sizeof(as)); + r->ip_nexthop.V4 = htonl(r->ip_nexthop.V4); + inet_ntop(AF_INET, &r->ip_nexthop.V4, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, ",%s", as); @@ -1410,9 +1410,9 @@ master_record_t *r = (master_record_t *)record; if ( (r->flags & FLAG_IPV6_NH ) != 0 ) { // IPv6 // EX_NEXT_HOP_BGP_v6: as[0] = 0; - r->bgp_nexthop.v6[0] = htonll(r->bgp_nexthop.v6[0]); - r->bgp_nexthop.v6[1] = htonll(r->bgp_nexthop.v6[1]); - inet_ntop(AF_INET6, r->ip_nexthop.v6, as, sizeof(as)); + r->bgp_nexthop.V6[0] = htonll(r->bgp_nexthop.V6[0]); + r->bgp_nexthop.V6[1] = htonll(r->bgp_nexthop.V6[1]); + inet_ntop(AF_INET6, r->ip_nexthop.V6, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, ",%s", as); @@ -1423,8 +1423,8 @@ master_record_t *r = (master_record_t *)record; } else { // EX_NEXT_HOP_BGP_v4: as[0] = 0; - r->bgp_nexthop.v4 = htonl(r->bgp_nexthop.v4); - inet_ntop(AF_INET, &r->bgp_nexthop.v4, as, sizeof(as)); + r->bgp_nexthop.V4 = htonl(r->bgp_nexthop.V4); + inet_ntop(AF_INET, &r->bgp_nexthop.V4, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, ",%s", as); @@ -1519,9 +1519,9 @@ master_record_t *r = (master_record_t *)record; if ( (r->flags & FLAG_IPV6_EXP ) != 0 ) { // IPv6 // EX_NEXT_HOP_v6: as[0] = 0; - r->ip_router.v6[0] = htonll(r->ip_router.v6[0]); - r->ip_router.v6[1] = htonll(r->ip_router.v6[1]); - inet_ntop(AF_INET6, r->ip_router.v6, as, sizeof(as)); + r->ip_router.V6[0] = htonll(r->ip_router.V6[0]); + r->ip_router.V6[1] = htonll(r->ip_router.V6[1]); + inet_ntop(AF_INET6, r->ip_router.V6, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, ",%s", as); @@ -1532,8 +1532,8 @@ master_record_t *r = (master_record_t *)record; } else { // EX_NEXT_HOP_v4: as[0] = 0; - r->ip_router.v4 = htonl(r->ip_router.v4); - inet_ntop(AF_INET, &r->ip_router.v4, as, sizeof(as)); + r->ip_router.V4 = htonl(r->ip_router.V4); + inet_ntop(AF_INET, &r->ip_router.V4, as, sizeof(as)); as[IP_STRING_LEN-1] = 0; snprintf(_s, slen-1, ",%s", as); @@ -1927,15 +1927,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->flags & FLAG_IPV6_ADDR ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->v6.srcaddr[0]); - ip[1] = htonll(r->v6.srcaddr[1]); + ip[0] = htonll(r->V6.srcaddr[0]); + ip[1] = htonll(r->V6.srcaddr[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->v4.srcaddr); + ip = htonl(r->V4.srcaddr); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -1956,8 +1956,8 @@ char tmp_str[IP_STRING_LEN], portchar; if ( (r->flags & FLAG_IPV6_ADDR ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->v6.srcaddr[0]); - ip[1] = htonll(r->v6.srcaddr[1]); + ip[0] = htonll(r->V6.srcaddr[0]); + ip[1] = htonll(r->V6.srcaddr[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); @@ -1965,7 +1965,7 @@ char tmp_str[IP_STRING_LEN], portchar; portchar = '.'; } else { // IPv4 uint32_t ip; - ip = htonl(r->v4.srcaddr); + ip = htonl(r->V4.srcaddr); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); portchar = ':'; } @@ -1987,15 +1987,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->flags & FLAG_IPV6_ADDR ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->v6.dstaddr[0]); - ip[1] = htonll(r->v6.dstaddr[1]); + ip[0] = htonll(r->V6.dstaddr[0]); + ip[1] = htonll(r->V6.dstaddr[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->v4.dstaddr); + ip = htonl(r->V4.dstaddr); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -2017,15 +2017,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->flags & FLAG_IPV6_NH ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->ip_nexthop.v6[0]); - ip[1] = htonll(r->ip_nexthop.v6[1]); + ip[0] = htonll(r->ip_nexthop.V6[0]); + ip[1] = htonll(r->ip_nexthop.V6[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->ip_nexthop.v4); + ip = htonl(r->ip_nexthop.V4); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -2046,15 +2046,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->flags & FLAG_IPV6_NH ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->bgp_nexthop.v6[0]); - ip[1] = htonll(r->bgp_nexthop.v6[1]); + ip[0] = htonll(r->bgp_nexthop.V6[0]); + ip[1] = htonll(r->bgp_nexthop.V6[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->bgp_nexthop.v4); + ip = htonl(r->bgp_nexthop.V4); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -2075,15 +2075,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->flags & FLAG_IPV6_EXP ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->ip_router.v6[0]); - ip[1] = htonll(r->ip_router.v6[1]); + ip[0] = htonll(r->ip_router.V6[0]); + ip[1] = htonll(r->ip_router.V6[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->ip_router.v4); + ip = htonl(r->ip_router.V4); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -2106,8 +2106,8 @@ char icmp_port[MAX_STRING_LENGTH]; if ( (r->flags & FLAG_IPV6_ADDR ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->v6.dstaddr[0]); - ip[1] = htonll(r->v6.dstaddr[1]); + ip[0] = htonll(r->V6.dstaddr[0]); + ip[1] = htonll(r->V6.dstaddr[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); @@ -2115,7 +2115,7 @@ char icmp_port[MAX_STRING_LENGTH]; portchar = '.'; } else { // IPv4 uint32_t ip; - ip = htonl(r->v4.dstaddr); + ip = htonl(r->V4.dstaddr); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); portchar = ':'; } @@ -2140,15 +2140,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->flags & FLAG_IPV6_ADDR ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->v6.srcaddr[0]); - ip[1] = htonll(r->v6.srcaddr[1]); + ip[0] = htonll(r->V6.srcaddr[0]); + ip[1] = htonll(r->V6.srcaddr[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->v4.srcaddr); + ip = htonl(r->V4.srcaddr); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -2171,15 +2171,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->flags & FLAG_IPV6_ADDR ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->v6.dstaddr[0]); - ip[1] = htonll(r->v6.dstaddr[1]); + ip[0] = htonll(r->V6.dstaddr[0]); + ip[1] = htonll(r->V6.dstaddr[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->v4.dstaddr); + ip = htonl(r->V4.dstaddr); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -2737,15 +2737,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->xlate_flags & 1 ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->xlate_src_ip.v6[0]); - ip[1] = htonll(r->xlate_src_ip.v6[1]); + ip[0] = htonll(r->xlate_src_ip.V6[0]); + ip[1] = htonll(r->xlate_src_ip.V6[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->xlate_src_ip.v4); + ip = htonl(r->xlate_src_ip.V4); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -2765,15 +2765,15 @@ char tmp_str[IP_STRING_LEN]; if ( (r->xlate_flags & 1 ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->xlate_dst_ip.v6[0]); - ip[1] = htonll(r->xlate_dst_ip.v6[1]); + ip[0] = htonll(r->xlate_dst_ip.V6[0]); + ip[1] = htonll(r->xlate_dst_ip.V6[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); } } else { // IPv4 uint32_t ip; - ip = htonl(r->xlate_dst_ip.v4); + ip = htonl(r->xlate_dst_ip.V4); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); } tmp_str[IP_STRING_LEN-1] = 0; @@ -2807,8 +2807,8 @@ char tmp_str[IP_STRING_LEN], portchar; if ( (r->xlate_flags & 1 ) != 0 ) { // IPv6 uint64_t ip[2]; - ip[0] = htonll(r->xlate_src_ip.v6[0]); - ip[1] = htonll(r->xlate_src_ip.v6[1]); + ip[0] = htonll(r->xlate_src_ip.V6[0]); + ip[1] = htonll(r->xlate_src_ip.V6[1]); inet_ntop(AF_INET6, ip, tmp_str, sizeof(tmp_str)); if ( ! long_v6 ) { condense_v6(tmp_str); @@ -2817,7 +2817,7 @@ char tmp_str[IP_STRING_LEN], portchar; portchar = '.'; } else { // IPv4 uint32_t ip; - ip = htonl(r->xlate_src_ip.v4); + ip = htonl(r->xlate_src_ip.V4); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); portchar = ':'; @@ -2850,7 +2850,7 @@ char tmp_str[IP_STRING_LEN], portchar; portchar = '.'; } else { // IPv4 uint32_t ip; - ip = htonl(r->xlate_dst_ip.v4); + ip = htonl(r->xlate_dst_ip.V4); inet_ntop(AF_INET, &ip, tmp_str, sizeof(tmp_str)); portchar = ':'; diff --git a/bin/nfanon.c b/bin/nfanon.c index 98debab..323c2a1 100755 --- a/bin/nfanon.c +++ b/bin/nfanon.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2017, Peter Haag * Copyright (c) 2014, Peter Haag * Copyright (c) 2009, Peter Haag * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung @@ -28,13 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author: haag $ - * - * $Id:$ - * - * $LastChangedRevision: 48 $ - * - * */ #include "config.h" @@ -106,18 +100,18 @@ int i; if ( (master_record->flags & FLAG_IPV6_ADDR) != 0 ) { // IPv6 // IPv6 uint64_t anon_ip[2]; - anonymize_v6(master_record->v6.srcaddr, anon_ip); - master_record->v6.srcaddr[0] = anon_ip[0]; - master_record->v6.srcaddr[1] = anon_ip[1]; + anonymize_v6(master_record->V6.srcaddr, anon_ip); + master_record->V6.srcaddr[0] = anon_ip[0]; + master_record->V6.srcaddr[1] = anon_ip[1]; - anonymize_v6(master_record->v6.dstaddr, anon_ip); - master_record->v6.dstaddr[0] = anon_ip[0]; - master_record->v6.dstaddr[1] = anon_ip[1]; + anonymize_v6(master_record->V6.dstaddr, anon_ip); + master_record->V6.dstaddr[0] = anon_ip[0]; + master_record->V6.dstaddr[1] = anon_ip[1]; } else { // IPv4 - master_record->v4.srcaddr = anonymize(master_record->v4.srcaddr); - master_record->v4.dstaddr = anonymize(master_record->v4.dstaddr); + master_record->V4.srcaddr = anonymize(master_record->V4.srcaddr); + master_record->V4.dstaddr = anonymize(master_record->V4.dstaddr); } // Process optional extensions @@ -133,45 +127,45 @@ int i; master_record->dstas = 0; break; case EX_NEXT_HOP_v4: - master_record->ip_nexthop.v4 = anonymize(master_record->ip_nexthop.v4); + master_record->ip_nexthop.V4 = anonymize(master_record->ip_nexthop.V4); break; case EX_NEXT_HOP_v6: { uint64_t anon_ip[2]; - anonymize_v6(master_record->ip_nexthop.v6, anon_ip); - master_record->ip_nexthop.v6[0] = anon_ip[0]; - master_record->ip_nexthop.v6[1] = anon_ip[1]; + anonymize_v6(master_record->ip_nexthop.V6, anon_ip); + master_record->ip_nexthop.V6[0] = anon_ip[0]; + master_record->ip_nexthop.V6[1] = anon_ip[1]; } break; case EX_NEXT_HOP_BGP_v4: - master_record->bgp_nexthop.v4 = anonymize(master_record->bgp_nexthop.v4); + master_record->bgp_nexthop.V4 = anonymize(master_record->bgp_nexthop.V4); break; case EX_NEXT_HOP_BGP_v6: { uint64_t anon_ip[2]; - anonymize_v6(master_record->bgp_nexthop.v6, anon_ip); - master_record->bgp_nexthop.v6[0] = anon_ip[0]; - master_record->bgp_nexthop.v6[1] = anon_ip[1]; + anonymize_v6(master_record->bgp_nexthop.V6, anon_ip); + master_record->bgp_nexthop.V6[0] = anon_ip[0]; + master_record->bgp_nexthop.V6[1] = anon_ip[1]; } break; case EX_ROUTER_IP_v4: - master_record->ip_router.v4 = anonymize(master_record->ip_router.v4); + master_record->ip_router.V4 = anonymize(master_record->ip_router.V4); break; case EX_ROUTER_IP_v6: { uint64_t anon_ip[2]; - anonymize_v6(master_record->ip_router.v6, anon_ip); - master_record->ip_router.v6[0] = anon_ip[0]; - master_record->ip_router.v6[1] = anon_ip[1]; + anonymize_v6(master_record->ip_router.V6, anon_ip); + master_record->ip_router.V6[0] = anon_ip[0]; + master_record->ip_router.V6[1] = anon_ip[1]; } break; #ifdef NSEL case EX_NSEL_XLATE_IP_v4: - master_record->xlate_src_ip.v4 = anonymize(master_record->xlate_src_ip.v4); - master_record->xlate_dst_ip.v4 = anonymize(master_record->xlate_dst_ip.v4); + master_record->xlate_src_ip.V4 = anonymize(master_record->xlate_src_ip.V4); + master_record->xlate_dst_ip.V4 = anonymize(master_record->xlate_dst_ip.V4); break; case EX_NSEL_XLATE_IP_v6: { uint64_t anon_ip[2]; - anonymize_v6(master_record->xlate_src_ip.v6, anon_ip); - master_record->xlate_src_ip.v6[0] = anon_ip[0]; - master_record->xlate_src_ip.v6[1] = anon_ip[1]; - anonymize_v6(master_record->xlate_dst_ip.v6, anon_ip); - master_record->xlate_dst_ip.v6[0] = anon_ip[0]; - master_record->xlate_dst_ip.v6[1] = anon_ip[1]; + anonymize_v6(master_record->xlate_src_ip.V6, anon_ip); + master_record->xlate_src_ip.V6[0] = anon_ip[0]; + master_record->xlate_src_ip.V6[1] = anon_ip[1]; + anonymize_v6(master_record->xlate_dst_ip.V6, anon_ip); + master_record->xlate_dst_ip.V6[0] = anon_ip[0]; + master_record->xlate_dst_ip.V6[1] = anon_ip[1]; } break; #endif } diff --git a/bin/nfexport.c b/bin/nfexport.c index cda68b7..87eb196 100755 --- a/bin/nfexport.c +++ b/bin/nfexport.c @@ -29,12 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author: haag $ - * - * $Id: nfexport.c 54 2010-01-29 11:30:22Z haag $ - * - * $LastChangedRevision: 54 $ - * */ #include "config.h" @@ -321,10 +315,10 @@ char *string; // 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]; + 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 ) @@ -368,10 +362,10 @@ char *string; // 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]; + 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 ) diff --git a/bin/nffile.c b/bin/nffile.c index abb7cf1..1d27fe2 100644 --- a/bin/nffile.c +++ b/bin/nffile.c @@ -1213,19 +1213,19 @@ void *p = (void *)input_record; if ( (input_record->flags & FLAG_IPV6_ADDR) != 0 ) { // IPv6 // IPv6 // keep compiler happy - // memcpy((void *)output_record->v6.srcaddr, p, 4 * sizeof(uint64_t)); + // memcpy((void *)output_record->V6.srcaddr, p, 4 * sizeof(uint64_t)); memcpy((void *)output_record->ip_union._ip_64.addr, p, 4 * sizeof(uint64_t)); p = (void *)((pointer_addr_t)p + 4 * sizeof(uint64_t)); } else { // IPv4 u = (uint32_t *)p; - output_record->v6.srcaddr[0] = 0; - output_record->v6.srcaddr[1] = 0; - output_record->v4.srcaddr = u[0]; + output_record->V6.srcaddr[0] = 0; + output_record->V6.srcaddr[1] = 0; + output_record->V4.srcaddr = u[0]; - output_record->v6.dstaddr[0] = 0; - output_record->v6.dstaddr[1] = 0; - output_record->v4.dstaddr = u[1]; + output_record->V6.dstaddr[0] = 0; + output_record->V6.dstaddr[1] = 0; + output_record->V4.dstaddr = u[1]; p = (void *)((pointer_addr_t)p + 2 * sizeof(uint32_t)); } diff --git a/bin/nffile.h b/bin/nffile.h index 15f1f25..89d1c6f 100644 --- a/bin/nffile.h +++ b/bin/nffile.h @@ -29,12 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author: haag $ - * - * $Id: nffile.h 40 2009-12-16 10:41:44Z haag $ - * - * $LastChangedRevision: 40 $ - * */ #ifndef _NFFILE_H @@ -345,7 +339,7 @@ typedef struct nffile_s { * +----+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ * | 2 | last (21) |fwd_status(89)| tcpflags (6) | proto (4) | src tos (5) | * +----+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ - * | 3 | srcport (7) | dstport(11)/ICMP (32) | exporter ID | | + * | 3 | srcport (7) | dstport(11)/ICMP (32) | exporter ID | reserved icmp type/code | * +----+--------------+--------------+--------------+--------------+--------------+--------------+--------------+--------------+ * @@ -494,8 +488,8 @@ typedef struct ip_addr_s { #define IP_ADDR_T } ip_addr_t; -#define v4 ip_union._v4 -#define v6 ip_union._v6 +#define V4 ip_union._v4 +#define V6 ip_union._v6 /* * Extension 2: @@ -1505,7 +1499,6 @@ typedef struct master_record_s { uint16_t icmp; }; - #ifdef WORDS_BIGENDIAN # define OffsetPort 3 # define OffsetExporterSysID 3 diff --git a/bin/nffile_inline.c b/bin/nffile_inline.c index 8401cac..d7c532e 100755 --- a/bin/nffile_inline.c +++ b/bin/nffile_inline.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2017, Peter Haag * Copyright (c) 2016, Peter Haag * Copyright (c) 2014, Peter Haag * Copyright (c) 2009, Peter Haag @@ -134,19 +135,19 @@ void *p = (void *)input_record; if ( (input_record->flags & FLAG_IPV6_ADDR) != 0 ) { // IPv6 // IPv6 // keep compiler happy - // memcpy((void *)output_record->v6.srcaddr, p, 4 * sizeof(uint64_t)); + // memcpy((void *)output_record->V6.srcaddr, p, 4 * sizeof(uint64_t)); memcpy((void *)output_record->ip_union._ip_64.addr, p, 4 * sizeof(uint64_t)); p = (void *)((pointer_addr_t)p + 4 * sizeof(uint64_t)); } else { // IPv4 u = (uint32_t *)p; - output_record->v6.srcaddr[0] = 0; - output_record->v6.srcaddr[1] = 0; - output_record->v4.srcaddr = u[0]; + output_record->V6.srcaddr[0] = 0; + output_record->V6.srcaddr[1] = 0; + output_record->V4.srcaddr = u[0]; - output_record->v6.dstaddr[0] = 0; - output_record->v6.dstaddr[1] = 0; - output_record->v4.dstaddr = u[1]; + output_record->V6.dstaddr[0] = 0; + output_record->V6.dstaddr[1] = 0; + output_record->V4.dstaddr = u[1]; p = (void *)((pointer_addr_t)p + 2 * sizeof(uint32_t)); } @@ -223,29 +224,29 @@ void *p = (void *)input_record; } break; case EX_NEXT_HOP_v4: { tpl_ext_9_t *tpl = (tpl_ext_9_t *)p; - output_record->ip_nexthop.v6[0] = 0; - output_record->ip_nexthop.v6[1] = 0; - output_record->ip_nexthop.v4 = tpl->nexthop; + output_record->ip_nexthop.V6[0] = 0; + output_record->ip_nexthop.V6[1] = 0; + output_record->ip_nexthop.V4 = tpl->nexthop; p = (void *)tpl->data; ClearFlag(output_record->flags, FLAG_IPV6_NH); } break; case EX_NEXT_HOP_v6: { tpl_ext_10_t *tpl = (tpl_ext_10_t *)p; - CopyV6IP((uint32_t *)output_record->ip_nexthop.v6, (uint32_t *)tpl->nexthop); + CopyV6IP((uint32_t *)output_record->ip_nexthop.V6, (uint32_t *)tpl->nexthop); p = (void *)tpl->data; SetFlag(output_record->flags, FLAG_IPV6_NH); } break; case EX_NEXT_HOP_BGP_v4: { tpl_ext_11_t *tpl = (tpl_ext_11_t *)p; - output_record->bgp_nexthop.v6[0] = 0; - output_record->bgp_nexthop.v6[1] = 0; - output_record->bgp_nexthop.v4 = tpl->bgp_nexthop; + output_record->bgp_nexthop.V6[0] = 0; + output_record->bgp_nexthop.V6[1] = 0; + output_record->bgp_nexthop.V4 = tpl->bgp_nexthop; ClearFlag(output_record->flags, FLAG_IPV6_NHB); p = (void *)tpl->data; } break; case EX_NEXT_HOP_BGP_v6: { tpl_ext_12_t *tpl = (tpl_ext_12_t *)p; - CopyV6IP((uint32_t *)output_record->bgp_nexthop.v6, (uint32_t *)tpl->bgp_nexthop); + CopyV6IP((uint32_t *)output_record->bgp_nexthop.V6, (uint32_t *)tpl->bgp_nexthop); p = (void *)tpl->data; SetFlag(output_record->flags, FLAG_IPV6_NHB); } break; @@ -322,15 +323,15 @@ void *p = (void *)input_record; } break; case EX_ROUTER_IP_v4: { tpl_ext_23_t *tpl = (tpl_ext_23_t *)p; - output_record->ip_router.v6[0] = 0; - output_record->ip_router.v6[1] = 0; - output_record->ip_router.v4 = tpl->router_ip; + output_record->ip_router.V6[0] = 0; + output_record->ip_router.V6[1] = 0; + output_record->ip_router.V4 = tpl->router_ip; p = (void *)tpl->data; ClearFlag(output_record->flags, FLAG_IPV6_EXP); } break; case EX_ROUTER_IP_v6: { tpl_ext_24_t *tpl = (tpl_ext_24_t *)p; - CopyV6IP((uint32_t *)output_record->ip_router.v6, (uint32_t *)tpl->router_ip); + CopyV6IP((uint32_t *)output_record->ip_router.V6, (uint32_t *)tpl->router_ip); p = (void *)tpl->data; SetFlag(output_record->flags, FLAG_IPV6_EXP); } break; @@ -383,21 +384,21 @@ void *p = (void *)input_record; } break; case EX_NSEL_XLATE_IP_v4: { tpl_ext_39_t *tpl = (tpl_ext_39_t *)p; - output_record->xlate_src_ip.v6[0] = 0; - output_record->xlate_src_ip.v6[1] = 0; - output_record->xlate_src_ip.v4 = tpl->xlate_src_ip; - output_record->xlate_dst_ip.v6[0] = 0; - output_record->xlate_dst_ip.v6[1] = 0; - output_record->xlate_dst_ip.v4 = tpl->xlate_dst_ip; + output_record->xlate_src_ip.V6[0] = 0; + output_record->xlate_src_ip.V6[1] = 0; + output_record->xlate_src_ip.V4 = tpl->xlate_src_ip; + output_record->xlate_dst_ip.V6[0] = 0; + output_record->xlate_dst_ip.V6[1] = 0; + output_record->xlate_dst_ip.V4 = tpl->xlate_dst_ip; p = (void *)tpl->data; output_record->xlate_flags = 0; } break; case EX_NSEL_XLATE_IP_v6: { tpl_ext_40_t *tpl = (tpl_ext_40_t *)p; - output_record->xlate_src_ip.v6[0] = tpl->xlate_src_ip[0]; - output_record->xlate_src_ip.v6[1] = tpl->xlate_src_ip[1]; - output_record->xlate_dst_ip.v6[0] = tpl->xlate_dst_ip[0]; - output_record->xlate_dst_ip.v6[1] = tpl->xlate_dst_ip[1]; + output_record->xlate_src_ip.V6[0] = tpl->xlate_src_ip[0]; + output_record->xlate_src_ip.V6[1] = tpl->xlate_src_ip[1]; + output_record->xlate_dst_ip.V6[0] = tpl->xlate_dst_ip[0]; + output_record->xlate_dst_ip.V6[1] = tpl->xlate_dst_ip[1]; p = (void *)tpl->data; output_record->xlate_flags = 1; } break; @@ -442,12 +443,12 @@ void *p = (void *)input_record; // compat record v1.6.10 case EX_NEL_GLOBAL_IP_v4: { tpl_ext_47_t *tpl = (tpl_ext_47_t *)p; - output_record->xlate_src_ip.v6[0] = 0; - output_record->xlate_src_ip.v6[1] = 0; - output_record->xlate_src_ip.v4 = tpl->nat_inside; - output_record->xlate_dst_ip.v6[0] = 0; - output_record->xlate_dst_ip.v6[1] = 0; - output_record->xlate_dst_ip.v4 = tpl->nat_outside; + output_record->xlate_src_ip.V6[0] = 0; + output_record->xlate_src_ip.V6[1] = 0; + output_record->xlate_src_ip.V4 = tpl->nat_inside; + output_record->xlate_dst_ip.V6[0] = 0; + output_record->xlate_dst_ip.V6[1] = 0; + output_record->xlate_dst_ip.V4 = tpl->nat_outside; p = (void *)tpl->data; output_record->xlate_src_port = compat_nel_bug.port[0]; @@ -522,14 +523,14 @@ int i; 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->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; + u[0] = master_record->V4.srcaddr; + u[1] = master_record->V4.dstaddr; p = (void *)((pointer_addr_t)p + 2 * sizeof(uint32_t)); } @@ -603,24 +604,24 @@ int i; } break; case EX_NEXT_HOP_v4: { tpl_ext_9_t *tpl = (tpl_ext_9_t *)p; - tpl->nexthop = master_record->ip_nexthop.v4; + 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]; + 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; + 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]; + 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: { @@ -695,13 +696,13 @@ int i; } break; case EX_ROUTER_IP_v4: { tpl_ext_23_t *tpl = (tpl_ext_23_t *)p; - tpl->router_ip = master_record->ip_router.v4; + 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]; + 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: { @@ -741,17 +742,17 @@ int i; } 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; + 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]; + 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]; + 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: { diff --git a/bin/nfgen.c b/bin/nfgen.c index bc37ea3..0b174ce 100644 --- a/bin/nfgen.c +++ b/bin/nfgen.c @@ -96,18 +96,18 @@ static void SetIPaddress(master_record_t *record, int af, char *src_ip, char *d if ( af == PF_INET6 ) { SetFlag(record->flags, FLAG_IPV6_ADDR); - inet_pton(PF_INET6, src_ip, &(record->v6.srcaddr[0])); - inet_pton(PF_INET6, dst_ip, &(record->v6.dstaddr[0])); - record->v6.srcaddr[0] = ntohll(record->v6.srcaddr[0]); - record->v6.srcaddr[1] = ntohll(record->v6.srcaddr[1]); - record->v6.dstaddr[0] = ntohll(record->v6.dstaddr[0]); - record->v6.dstaddr[1] = ntohll(record->v6.dstaddr[1]); + inet_pton(PF_INET6, src_ip, &(record->V6.srcaddr[0])); + inet_pton(PF_INET6, dst_ip, &(record->V6.dstaddr[0])); + record->V6.srcaddr[0] = ntohll(record->V6.srcaddr[0]); + record->V6.srcaddr[1] = ntohll(record->V6.srcaddr[1]); + record->V6.dstaddr[0] = ntohll(record->V6.dstaddr[0]); + record->V6.dstaddr[1] = ntohll(record->V6.dstaddr[1]); } else { ClearFlag(record->flags, FLAG_IPV6_ADDR); - inet_pton(PF_INET, src_ip, &record->v4.srcaddr); - inet_pton(PF_INET, dst_ip, &record->v4.dstaddr); - record->v4.srcaddr = ntohl(record->v4.srcaddr); - record->v4.dstaddr = ntohl(record->v4.dstaddr); + inet_pton(PF_INET, src_ip, &record->V4.srcaddr); + inet_pton(PF_INET, dst_ip, &record->V4.dstaddr); + record->V4.srcaddr = ntohl(record->V4.srcaddr); + record->V4.dstaddr = ntohl(record->V4.dstaddr); } } // End of SetIPaddress @@ -116,13 +116,13 @@ static void SetNextIPaddress(master_record_t *record, int af, char *next_ip) { if ( af == PF_INET6 ) { SetFlag(record->flags, FLAG_IPV6_NH); - inet_pton(PF_INET6, next_ip, &(record->ip_nexthop.v6[0])); - record->ip_nexthop.v6[0] = ntohll(record->ip_nexthop.v6[0]); - record->ip_nexthop.v6[1] = ntohll(record->ip_nexthop.v6[1]); + inet_pton(PF_INET6, next_ip, &(record->ip_nexthop.V6[0])); + record->ip_nexthop.V6[0] = ntohll(record->ip_nexthop.V6[0]); + record->ip_nexthop.V6[1] = ntohll(record->ip_nexthop.V6[1]); } else { ClearFlag(record->flags, FLAG_IPV6_NH); - inet_pton(PF_INET, next_ip, &record->ip_nexthop.v4); - record->ip_nexthop.v4 = ntohl(record->ip_nexthop.v4); + inet_pton(PF_INET, next_ip, &record->ip_nexthop.V4); + record->ip_nexthop.V4 = ntohl(record->ip_nexthop.V4); } } // End of SetNextIPaddress @@ -131,13 +131,13 @@ static void SetRouterIPaddress(master_record_t *record, int af, char *next_ip) if ( af == PF_INET6 ) { SetFlag(record->flags, FLAG_IPV6_NH); - inet_pton(PF_INET6, next_ip, &(record->ip_router.v6[0])); - record->ip_router.v6[0] = ntohll(record->ip_router.v6[0]); - record->ip_router.v6[1] = ntohll(record->ip_router.v6[1]); + inet_pton(PF_INET6, next_ip, &(record->ip_router.V6[0])); + record->ip_router.V6[0] = ntohll(record->ip_router.V6[0]); + record->ip_router.V6[1] = ntohll(record->ip_router.V6[1]); } else { ClearFlag(record->flags, FLAG_IPV6_NH); - inet_pton(PF_INET, next_ip, &record->ip_router.v4); - record->ip_router.v4 = ntohl(record->ip_router.v4); + inet_pton(PF_INET, next_ip, &record->ip_router.V4); + record->ip_router.V4 = ntohl(record->ip_router.V4); } } // End of SetRouterIPaddress @@ -146,13 +146,13 @@ static void SetBGPNextIPaddress(master_record_t *record, int af, char *next_ip) if ( af == PF_INET6 ) { SetFlag(record->flags, FLAG_IPV6_NHB); - inet_pton(PF_INET6, next_ip, &(record->bgp_nexthop.v6[0])); - record->bgp_nexthop.v6[0] = ntohll(record->bgp_nexthop.v6[0]); - record->bgp_nexthop.v6[1] = ntohll(record->bgp_nexthop.v6[1]); + inet_pton(PF_INET6, next_ip, &(record->bgp_nexthop.V6[0])); + record->bgp_nexthop.V6[0] = ntohll(record->bgp_nexthop.V6[0]); + record->bgp_nexthop.V6[1] = ntohll(record->bgp_nexthop.V6[1]); } else { ClearFlag(record->flags, FLAG_IPV6_NHB); - inet_pton(PF_INET, next_ip, &record->bgp_nexthop.v4); - record->bgp_nexthop.v4 = ntohl(record->bgp_nexthop.v4); + inet_pton(PF_INET, next_ip, &record->bgp_nexthop.V4); + record->bgp_nexthop.V4 = ntohl(record->bgp_nexthop.V4); } } // End of SetBGPNextIPaddress diff --git a/bin/nflowcache.c b/bin/nflowcache.c index 3aa2480..912e27b 100755 --- a/bin/nflowcache.c +++ b/bin/nflowcache.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2017, Peter Haag * Copyright (c) 2014, Peter Haag * Copyright (c) 2009, Peter Haag * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung @@ -28,12 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author: haag $ - * - * $Id: nflowcache.c 40 2009-12-16 10:41:44Z haag $ - * - * $LastChangedRevision: 40 $ - * */ #include "config.h" @@ -916,20 +911,20 @@ Default_key_t *keyptr; } else if ( swap_flow ) { // default 5-tuple aggregation for bidirectional flows keyptr = (Default_key_t *)keymem; - keyptr->srcaddr[0] = flow_record->v6.dstaddr[0]; - keyptr->srcaddr[1] = flow_record->v6.dstaddr[1]; - keyptr->dstaddr[0] = flow_record->v6.srcaddr[0]; - keyptr->dstaddr[1] = flow_record->v6.srcaddr[1]; + keyptr->srcaddr[0] = flow_record->V6.dstaddr[0]; + keyptr->srcaddr[1] = flow_record->V6.dstaddr[1]; + keyptr->dstaddr[0] = flow_record->V6.srcaddr[0]; + keyptr->dstaddr[1] = flow_record->V6.srcaddr[1]; keyptr->srcport = flow_record->dstport; keyptr->dstport = flow_record->srcport; keyptr->proto = flow_record->prot; } else { // default 5-tuple aggregation keyptr = (Default_key_t *)keymem; - keyptr->srcaddr[0] = flow_record->v6.srcaddr[0]; - keyptr->srcaddr[1] = flow_record->v6.srcaddr[1]; - keyptr->dstaddr[0] = flow_record->v6.dstaddr[0]; - keyptr->dstaddr[1] = flow_record->v6.dstaddr[1]; + keyptr->srcaddr[0] = flow_record->V6.srcaddr[0]; + keyptr->srcaddr[1] = flow_record->V6.srcaddr[1]; + keyptr->dstaddr[0] = flow_record->V6.dstaddr[0]; + keyptr->dstaddr[1] = flow_record->V6.dstaddr[1]; keyptr->srcport = flow_record->srcport; keyptr->dstport = flow_record->dstport; keyptr->proto = flow_record->prot; diff --git a/bin/nfreader.c b/bin/nfreader.c index 50f1312..3304795 100755 --- a/bin/nfreader.c +++ b/bin/nfreader.c @@ -29,13 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $Author: haag $ - * - * $Id: nfreader.c 48 2010-01-02 08:06:27Z haag $ - * - * $LastChangedRevision: 48 $ - * - * */ /* @@ -124,17 +117,17 @@ struct tm *ts; master_record_t *r = (master_record_t *)record; if ( (r->flags & FLAG_IPV6_ADDR ) != 0 ) { // IPv6 - r->v6.srcaddr[0] = htonll(r->v6.srcaddr[0]); - r->v6.srcaddr[1] = htonll(r->v6.srcaddr[1]); - r->v6.dstaddr[0] = htonll(r->v6.dstaddr[0]); - r->v6.dstaddr[1] = htonll(r->v6.dstaddr[1]); - inet_ntop(AF_INET6, r->v6.srcaddr, as, sizeof(as)); - inet_ntop(AF_INET6, r->v6.dstaddr, ds, sizeof(ds)); + r->V6.srcaddr[0] = htonll(r->V6.srcaddr[0]); + r->V6.srcaddr[1] = htonll(r->V6.srcaddr[1]); + r->V6.dstaddr[0] = htonll(r->V6.dstaddr[0]); + r->V6.dstaddr[1] = htonll(r->V6.dstaddr[1]); + inet_ntop(AF_INET6, r->V6.srcaddr, as, sizeof(as)); + inet_ntop(AF_INET6, r->V6.dstaddr, ds, sizeof(ds)); } else { // IPv4 - r->v4.srcaddr = htonl(r->v4.srcaddr); - r->v4.dstaddr = htonl(r->v4.dstaddr); - inet_ntop(AF_INET, &r->v4.srcaddr, as, sizeof(as)); - inet_ntop(AF_INET, &r->v4.dstaddr, ds, sizeof(ds)); + r->V4.srcaddr = htonl(r->V4.srcaddr); + r->V4.dstaddr = htonl(r->V4.dstaddr); + inet_ntop(AF_INET, &r->V4.srcaddr, as, sizeof(as)); + inet_ntop(AF_INET, &r->V4.dstaddr, ds, sizeof(ds)); } as[40-1] = 0; ds[40-1] = 0; diff --git a/bin/nfstat.c b/bin/nfstat.c index 450935e..41da14b 100644 --- a/bin/nfstat.c +++ b/bin/nfstat.c @@ -1543,10 +1543,10 @@ char *string; // 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]; + 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 ( aggr_record_mask ) { @@ -1718,10 +1718,10 @@ int i, max; // 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]; + 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 ) { @@ -1887,12 +1887,12 @@ uint64_t _tmp_ip[2]; uint64_t _tmp_l; uint32_t _tmp; - _tmp_ip[0] = flow_record->v6.srcaddr[0]; - _tmp_ip[1] = flow_record->v6.srcaddr[1]; - flow_record->v6.srcaddr[0] = flow_record->v6.dstaddr[0]; - flow_record->v6.srcaddr[1] = flow_record->v6.dstaddr[1]; - flow_record->v6.dstaddr[0] = _tmp_ip[0]; - flow_record->v6.dstaddr[1] = _tmp_ip[1]; + _tmp_ip[0] = flow_record->V6.srcaddr[0]; + _tmp_ip[1] = flow_record->V6.srcaddr[1]; + flow_record->V6.srcaddr[0] = flow_record->V6.dstaddr[0]; + flow_record->V6.srcaddr[1] = flow_record->V6.dstaddr[1]; + flow_record->V6.dstaddr[0] = _tmp_ip[0]; + flow_record->V6.dstaddr[1] = _tmp_ip[1]; _tmp = flow_record->srcport; flow_record->srcport = flow_record->dstport; diff --git a/bin/nftest.c b/bin/nftest.c index 5183a54..58aa48f 100644 --- a/bin/nftest.c +++ b/bin/nftest.c @@ -368,12 +368,12 @@ void *p; ret = check_filter_block("icmp-code 4", &flow_record, 0); - inet_pton(PF_INET6, "fe80::2110:abcd:1234:5678", flow_record.v6.srcaddr); - inet_pton(PF_INET6, "fe80::1104:fedc:4321:8765", flow_record.v6.dstaddr); - flow_record.v6.srcaddr[0] = ntohll(flow_record.v6.srcaddr[0]); - flow_record.v6.srcaddr[1] = ntohll(flow_record.v6.srcaddr[1]); - flow_record.v6.dstaddr[0] = ntohll(flow_record.v6.dstaddr[0]); - flow_record.v6.dstaddr[1] = ntohll(flow_record.v6.dstaddr[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1234:5678", flow_record.V6.srcaddr); + inet_pton(PF_INET6, "fe80::1104:fedc:4321:8765", flow_record.V6.dstaddr); + flow_record.V6.srcaddr[0] = ntohll(flow_record.V6.srcaddr[0]); + flow_record.V6.srcaddr[1] = ntohll(flow_record.V6.srcaddr[1]); + flow_record.V6.dstaddr[0] = ntohll(flow_record.V6.dstaddr[0]); + flow_record.V6.dstaddr[1] = ntohll(flow_record.V6.dstaddr[1]); ret = check_filter_block("src ip fe80::2110:abcd:1234:5678", &flow_record, 1); ret = check_filter_block("src ip fe80::2110:abcd:1234:5679", &flow_record, 0); ret = check_filter_block("src ip fe80::2111:abcd:1234:5678", &flow_record, 0); @@ -390,39 +390,39 @@ void *p; ret = check_filter_block("src ip in [fe80::2110:abcd:1234:5678]", &flow_record, 1); ret = check_filter_block("src ip in [fe80::2110:abcd:1234:5679]", &flow_record, 0); - inet_pton(PF_INET6, "fe80::2110:abcd:1234:0", flow_record.v6.srcaddr); - flow_record.v6.srcaddr[0] = ntohll(flow_record.v6.srcaddr[0]); - flow_record.v6.srcaddr[1] = ntohll(flow_record.v6.srcaddr[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1234:0", flow_record.V6.srcaddr); + flow_record.V6.srcaddr[0] = ntohll(flow_record.V6.srcaddr[0]); + flow_record.V6.srcaddr[1] = ntohll(flow_record.V6.srcaddr[1]); ret = check_filter_block("src net fe80::2110:abcd:1234:0/112", &flow_record, 1); - inet_pton(PF_INET6, "fe80::2110:abcd:1234:ffff", flow_record.v6.srcaddr); - flow_record.v6.srcaddr[0] = ntohll(flow_record.v6.srcaddr[0]); - flow_record.v6.srcaddr[1] = ntohll(flow_record.v6.srcaddr[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1234:ffff", flow_record.V6.srcaddr); + flow_record.V6.srcaddr[0] = ntohll(flow_record.V6.srcaddr[0]); + flow_record.V6.srcaddr[1] = ntohll(flow_record.V6.srcaddr[1]); ret = check_filter_block("src net fe80::2110:abcd:1234:0/112", &flow_record, 1); - inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.v6.srcaddr); - flow_record.v6.srcaddr[0] = ntohll(flow_record.v6.srcaddr[0]); - flow_record.v6.srcaddr[1] = ntohll(flow_record.v6.srcaddr[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.V6.srcaddr); + flow_record.V6.srcaddr[0] = ntohll(flow_record.V6.srcaddr[0]); + flow_record.V6.srcaddr[1] = ntohll(flow_record.V6.srcaddr[1]); ret = check_filter_block("src net fe80::2110:abcd:1234:0/112", &flow_record, 0); ret = check_filter_block("src net fe80::0/16", &flow_record, 1); ret = check_filter_block("src net fe81::0/16", &flow_record, 0); - flow_record.v6.srcaddr[0] = 0; - flow_record.v6.srcaddr[1] = 0; + flow_record.V6.srcaddr[0] = 0; + flow_record.V6.srcaddr[1] = 0; - inet_pton(PF_INET6, "fe80::2110:abcd:1234:0", flow_record.v6.dstaddr); - flow_record.v6.dstaddr[0] = ntohll(flow_record.v6.dstaddr[0]); - flow_record.v6.dstaddr[1] = ntohll(flow_record.v6.dstaddr[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1234:0", flow_record.V6.dstaddr); + flow_record.V6.dstaddr[0] = ntohll(flow_record.V6.dstaddr[0]); + flow_record.V6.dstaddr[1] = ntohll(flow_record.V6.dstaddr[1]); ret = check_filter_block("dst net fe80::2110:abcd:1234:0/112", &flow_record, 1); - inet_pton(PF_INET6, "fe80::2110:abcd:1234:ffff", flow_record.v6.dstaddr); - flow_record.v6.dstaddr[0] = ntohll(flow_record.v6.dstaddr[0]); - flow_record.v6.dstaddr[1] = ntohll(flow_record.v6.dstaddr[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1234:ffff", flow_record.V6.dstaddr); + flow_record.V6.dstaddr[0] = ntohll(flow_record.V6.dstaddr[0]); + flow_record.V6.dstaddr[1] = ntohll(flow_record.V6.dstaddr[1]); ret = check_filter_block("dst net fe80::2110:abcd:1234:0/112", &flow_record, 1); - inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.v6.dstaddr); - flow_record.v6.dstaddr[0] = ntohll(flow_record.v6.dstaddr[0]); - flow_record.v6.dstaddr[1] = ntohll(flow_record.v6.dstaddr[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.V6.dstaddr); + flow_record.V6.dstaddr[0] = ntohll(flow_record.V6.dstaddr[0]); + flow_record.V6.dstaddr[1] = ntohll(flow_record.V6.dstaddr[1]); ret = check_filter_block("dst net fe80::2110:abcd:1234:0/112", &flow_record, 0); ret = check_filter_block("dst net fe80::0/16", &flow_record, 1); ret = check_filter_block("not dst net fe80::0/16", &flow_record, 0); @@ -433,12 +433,12 @@ void *p; /* 172.32.7.16 => 0xac200710 * 10.10.10.11 => 0x0a0a0a0b */ - flow_record.v6.srcaddr[0] = 0; - flow_record.v6.srcaddr[1] = 0; - flow_record.v6.dstaddr[0] = 0; - flow_record.v6.dstaddr[1] = 0; - flow_record.v4.srcaddr = 0xac200710; - flow_record.v4.dstaddr = 0x0a0a0a0b; + flow_record.V6.srcaddr[0] = 0; + flow_record.V6.srcaddr[1] = 0; + flow_record.V6.dstaddr[0] = 0; + flow_record.V6.dstaddr[1] = 0; + flow_record.V4.srcaddr = 0xac200710; + flow_record.V4.dstaddr = 0x0a0a0a0b; ret = check_filter_block("src ip 172.32.7.16", &flow_record, 1); ret = check_filter_block("src ip 172.32.7.15", &flow_record, 0); ret = check_filter_block("dst ip 10.10.10.11", &flow_record, 1); @@ -596,53 +596,53 @@ void *p; ret = check_filter_block("src ip 172.32.7.15 and dst ip 10.10.10.11", &flow_record, 0); ret = check_filter_block("src ip 172.32.7.16 and dst ip 10.10.10.12", &flow_record, 0); - flow_record.v4.srcaddr = 0; - flow_record.v4.dstaddr = 0; + flow_record.V4.srcaddr = 0; + flow_record.V4.dstaddr = 0; // 172.32.7.16 => 0xac200710 - flow_record.ip_nexthop.v6[0] = 0; - flow_record.ip_nexthop.v6[1] = 0; - flow_record.ip_nexthop.v4 = 0xac200710; + flow_record.ip_nexthop.V6[0] = 0; + flow_record.ip_nexthop.V6[1] = 0; + flow_record.ip_nexthop.V4 = 0xac200710; ret = check_filter_block("next ip 172.32.7.16", &flow_record, 1); ret = check_filter_block("next ip 172.32.7.15", &flow_record, 0); ret = check_filter_block("next ip in [172.32.7.16 fe80::2110:abcd:1235:ffff]", &flow_record, 1); ret = check_filter_block("next ip in [172.32.7.15 fe80::2110:abcd:1235:ffff]", &flow_record, 0); - inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.ip_nexthop.v6); - flow_record.ip_nexthop.v6[0] = ntohll(flow_record.ip_nexthop.v6[0]); - flow_record.ip_nexthop.v6[1] = ntohll(flow_record.ip_nexthop.v6[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.ip_nexthop.V6); + flow_record.ip_nexthop.V6[0] = ntohll(flow_record.ip_nexthop.V6[0]); + flow_record.ip_nexthop.V6[1] = ntohll(flow_record.ip_nexthop.V6[1]); ret = check_filter_block("next ip fe80::2110:abcd:1235:ffff", &flow_record, 1); ret = check_filter_block("next ip in [172.32.7.16 fe80::2110:abcd:1235:ffff]", &flow_record, 1); ret = check_filter_block("next ip in [172.32.7.16 fe80::2110:abcd:1235:fffe]", &flow_record, 0); ret = check_filter_block("next ip fe80::2110:abcd:1235:fffe", &flow_record, 0); ret = check_filter_block("next ip fe81::2110:abcd:1235:ffff", &flow_record, 0); - flow_record.ip_nexthop.v6[0] = 0; - flow_record.ip_nexthop.v6[1] = 0; + flow_record.ip_nexthop.V6[0] = 0; + flow_record.ip_nexthop.V6[1] = 0; - flow_record.bgp_nexthop.v6[0] = 0; - flow_record.bgp_nexthop.v6[1] = 0; - flow_record.bgp_nexthop.v4 = 0xac200710; + flow_record.bgp_nexthop.V6[0] = 0; + flow_record.bgp_nexthop.V6[1] = 0; + flow_record.bgp_nexthop.V4 = 0xac200710; ret = check_filter_block("bgpnext ip 172.32.7.16", &flow_record, 1); ret = check_filter_block("bgpnext ip 172.32.7.15", &flow_record, 0); - inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.bgp_nexthop.v6); - flow_record.bgp_nexthop.v6[0] = ntohll(flow_record.bgp_nexthop.v6[0]); - flow_record.bgp_nexthop.v6[1] = ntohll(flow_record.bgp_nexthop.v6[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.bgp_nexthop.V6); + flow_record.bgp_nexthop.V6[0] = ntohll(flow_record.bgp_nexthop.V6[0]); + flow_record.bgp_nexthop.V6[1] = ntohll(flow_record.bgp_nexthop.V6[1]); ret = check_filter_block("bgpnext ip fe80::2110:abcd:1235:ffff", &flow_record, 1); ret = check_filter_block("bgpnext ip fe80::2110:abcd:1235:fffe", &flow_record, 0); ret = check_filter_block("bgpnext ip fe81::2110:abcd:1235:ffff", &flow_record, 0); - flow_record.ip_router.v6[0] = 0; - flow_record.ip_router.v6[1] = 0; - flow_record.ip_router.v4 = 0xac200720; - flow_record.ip_nexthop.v4 = 0xac200720; + flow_record.ip_router.V6[0] = 0; + flow_record.ip_router.V6[1] = 0; + flow_record.ip_router.V4 = 0xac200720; + flow_record.ip_nexthop.V4 = 0xac200720; ret = check_filter_block("router ip 172.32.7.32", &flow_record, 1); ret = check_filter_block("router ip 172.32.7.33", &flow_record, 0); - inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.ip_router.v6); - flow_record.ip_router.v6[0] = ntohll(flow_record.ip_router.v6[0]); - flow_record.ip_router.v6[1] = ntohll(flow_record.ip_router.v6[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.ip_router.V6); + flow_record.ip_router.V6[0] = ntohll(flow_record.ip_router.V6[0]); + flow_record.ip_router.V6[1] = ntohll(flow_record.ip_router.V6[1]); ret = check_filter_block("router ip fe80::2110:abcd:1235:ffff", &flow_record, 1); ret = check_filter_block("router ip fe80::2110:abcd:1235:fffe", &flow_record, 0); ret = check_filter_block("router ip fe81::2110:abcd:1235:ffff", &flow_record, 0); @@ -1039,12 +1039,12 @@ void *p; ret = check_filter_block("asa xevent < 1004", &flow_record, 0); ret = check_filter_block("asa xevent > 1004", &flow_record, 0); - flow_record.xlate_src_ip.v6[0] = 0; - flow_record.xlate_src_ip.v6[1] = 0; - flow_record.xlate_src_ip.v4 = 0xac200710; - flow_record.xlate_dst_ip.v6[0] = 0; - flow_record.xlate_dst_ip.v6[1] = 0; - flow_record.xlate_dst_ip.v4 = 0x0a0a0a0b; + flow_record.xlate_src_ip.V6[0] = 0; + flow_record.xlate_src_ip.V6[1] = 0; + flow_record.xlate_src_ip.V4 = 0xac200710; + flow_record.xlate_dst_ip.V6[0] = 0; + flow_record.xlate_dst_ip.V6[1] = 0; + flow_record.xlate_dst_ip.V4 = 0x0a0a0a0b; ret = check_filter_block("src xip 172.32.7.16", &flow_record, 1); ret = check_filter_block("src xip 172.32.7.15", &flow_record, 0); ret = check_filter_block("dst xip 10.10.10.11", &flow_record, 1); @@ -1060,23 +1060,23 @@ void *p; ret = check_filter_block("xnet 172.32.7.0/24", &flow_record, 1); ret = check_filter_block("xnet 10.10.10.0/24", &flow_record, 1); - inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.xlate_src_ip.v6); - flow_record.xlate_src_ip.v6[0] = ntohll(flow_record.xlate_src_ip.v6[0]); - flow_record.xlate_src_ip.v6[1] = ntohll(flow_record.xlate_src_ip.v6[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.xlate_src_ip.V6); + flow_record.xlate_src_ip.V6[0] = ntohll(flow_record.xlate_src_ip.V6[0]); + flow_record.xlate_src_ip.V6[1] = ntohll(flow_record.xlate_src_ip.V6[1]); ret = check_filter_block("src xip fe80::2110:abcd:1235:ffff", &flow_record, 1); ret = check_filter_block("src xip fe80::2110:abcd:1235:fffe", &flow_record, 0); - flow_record.xlate_src_ip.v6[0] = 0; - flow_record.xlate_src_ip.v6[1] = 0; - inet_pton(PF_INET6, "fe80::2110:abcd:1235:fffe", flow_record.xlate_dst_ip.v6); - flow_record.xlate_dst_ip.v6[0] = ntohll(flow_record.xlate_dst_ip.v6[0]); - flow_record.xlate_dst_ip.v6[1] = ntohll(flow_record.xlate_dst_ip.v6[1]); + flow_record.xlate_src_ip.V6[0] = 0; + flow_record.xlate_src_ip.V6[1] = 0; + inet_pton(PF_INET6, "fe80::2110:abcd:1235:fffe", flow_record.xlate_dst_ip.V6); + flow_record.xlate_dst_ip.V6[0] = ntohll(flow_record.xlate_dst_ip.V6[0]); + flow_record.xlate_dst_ip.V6[1] = ntohll(flow_record.xlate_dst_ip.V6[1]); ret = check_filter_block("dst xip fe80::2110:abcd:1235:fffe", &flow_record, 1); ret = check_filter_block("dst xip fe80::2110:abcd:1235:fffc", &flow_record, 0); - flow_record.xlate_src_ip.v6[0] = 0; - flow_record.xlate_src_ip.v6[1] = 0; - flow_record.xlate_dst_ip.v6[0] = 0; - flow_record.xlate_dst_ip.v6[1] = 0; + flow_record.xlate_src_ip.V6[0] = 0; + flow_record.xlate_src_ip.V6[1] = 0; + flow_record.xlate_dst_ip.V6[0] = 0; + flow_record.xlate_dst_ip.V6[1] = 0; flow_record.xlate_src_port = 1023; flow_record.xlate_dst_port = 32798; @@ -1205,12 +1205,12 @@ exit(0); flow_record.xlate_src_port = 0xffff; flow_record.xlate_dst_port = 0xffff; - flow_record.xlate_src_ip.v6[0] = 0; - flow_record.xlate_src_ip.v6[1] = 0; - flow_record.xlate_src_ip.v4 = 0xac200710; - flow_record.xlate_dst_ip.v6[0] = 0; - flow_record.xlate_dst_ip.v6[1] = 0; - flow_record.xlate_dst_ip.v4 = 0x0a0a0a0b; + flow_record.xlate_src_ip.V6[0] = 0; + flow_record.xlate_src_ip.V6[1] = 0; + flow_record.xlate_src_ip.V4 = 0xac200710; + flow_record.xlate_dst_ip.V6[0] = 0; + flow_record.xlate_dst_ip.V6[1] = 0; + flow_record.xlate_dst_ip.V4 = 0x0a0a0a0b; ret = check_filter_block("src nip 172.32.7.16", &flow_record, 1); ret = check_filter_block("src nip 172.32.7.15", &flow_record, 0); ret = check_filter_block("dst nip 10.10.10.11", &flow_record, 1); @@ -1220,17 +1220,17 @@ exit(0); ret = check_filter_block("nip 172.32.7.15", &flow_record, 0); ret = check_filter_block("nip 10.10.10.12", &flow_record, 0); - inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.xlate_src_ip.v6); - flow_record.xlate_src_ip.v6[0] = ntohll(flow_record.xlate_src_ip.v6[0]); - flow_record.xlate_src_ip.v6[1] = ntohll(flow_record.xlate_src_ip.v6[1]); + inet_pton(PF_INET6, "fe80::2110:abcd:1235:ffff", flow_record.xlate_src_ip.V6); + flow_record.xlate_src_ip.V6[0] = ntohll(flow_record.xlate_src_ip.V6[0]); + flow_record.xlate_src_ip.V6[1] = ntohll(flow_record.xlate_src_ip.V6[1]); ret = check_filter_block("src nip fe80::2110:abcd:1235:ffff", &flow_record, 1); ret = check_filter_block("src nip fe80::2110:abcd:1235:fffe", &flow_record, 0); - flow_record.xlate_src_ip.v6[0] = 0; - flow_record.xlate_src_ip.v6[1] = 0; - inet_pton(PF_INET6, "fe80::2110:abcd:1235:fffe", flow_record.xlate_dst_ip.v6); - flow_record.xlate_dst_ip.v6[0] = ntohll(flow_record.xlate_dst_ip.v6[0]); - flow_record.xlate_dst_ip.v6[1] = ntohll(flow_record.xlate_dst_ip.v6[1]); + flow_record.xlate_src_ip.V6[0] = 0; + flow_record.xlate_src_ip.V6[1] = 0; + inet_pton(PF_INET6, "fe80::2110:abcd:1235:fffe", flow_record.xlate_dst_ip.V6); + flow_record.xlate_dst_ip.V6[0] = ntohll(flow_record.xlate_dst_ip.V6[0]); + flow_record.xlate_dst_ip.V6[1] = ntohll(flow_record.xlate_dst_ip.V6[1]); ret = check_filter_block("dst nip fe80::2110:abcd:1235:fffe", &flow_record, 1); ret = check_filter_block("dst nip fe80::2110:abcd:1235:fffc", &flow_record, 0); diff --git a/bin/pack.pcap b/bin/pack.pcap deleted file mode 100644 index e0bb70a..0000000 Binary files a/bin/pack.pcap and /dev/null differ diff --git a/bin/sfcapd.c b/bin/sfcapd.c index cb90b34..e2ea145 100644 --- a/bin/sfcapd.c +++ b/bin/sfcapd.c @@ -91,7 +91,7 @@ #include "expire.h" -#include "sflow.h" +#include "sflow_nfdump.h" #define DEFAULTSFLOWPORT "6343" diff --git a/bin/sflow.c b/bin/sflow.c deleted file mode 100644 index 26e57d4..0000000 --- a/bin/sflow.c +++ /dev/null @@ -1,2751 +0,0 @@ -/* - * Copyright (c) 2017, Peter Haag - * Copyright (c) 2016, Peter Haag - * Copyright (c) 2014, Peter Haag - * Copyright (c) 2009, Peter Haag - * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of the author nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $Author: haag $ - * - * $Id: sflow.c 69 2010-09-09 07:17:43Z haag $ - * - * $LastChangedRevision: 69 $ - * - * - */ - -/* - * sfcapd makes use of code originated from sflowtool by InMon Corp. - * Those parts of the code are distributed under the InMon Public License below. - * All other/additional code is pubblished under BSD license. - */ - - -/* - * ----------------------------------------------------------------------- - * Copyright (c) 2001-2002 InMon Corp. All rights reserved. - * ----------------------------------------------------------------------- - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes sFlow(TM), freely available from - * http://www.inmon.com/". - * - * 4. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes sFlow(TM), freely available from - * http://www.inmon.com/". - * - * 5. InMon Corp. may publish revised and/or new versions - * of the license from time to time. Each version will be given a - * distinguishing version number. Once covered code has been - * published under a particular version of the license, you may - * always continue to use it under the terms of that version. You - * may also choose to use such covered code under the terms of any - * subsequent version of the license published by InMon Corp. - * No one other than the InMon Corp. has the right to modify the terms - * applicable to covered code created under this License. - * - * 6. The name "sFlow" must not be used to endorse or promote products - * derived from this software without prior written permission - * from InMon Corp. This does not apply to add-on libraries or tools - * that work in conjunction with sFlow. In such a case the sFlow name - * may be used to indicate that the product supports sFlow. - * - * 7. Products derived from this software may not be called "sFlow", - * nor may "sFlow" appear in their name, without prior written - * permission of InMon Corp. - * - * - * THIS SOFTWARE IS PROVIDED BY INMON CORP. ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * INMON CORP. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * -------------------------------------------------------------------- - * - * This software consists of voluntary contributions made by many - * individuals on behalf of InMon Corp. - * - * InMon Corp. can be contacted via Email at info@inmon.com. - * - * For more information on InMon Corp. and sFlow, - * please see http://www.inmon.com/. - * - * InMon Public License Version 1.0 written May 31, 2001 - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_STDINT_H -#include -#endif - -#include "nffile.h" -#include "nfx.h" -#include "nf_common.h" -#include "util.h" -#include "bookkeeper.h" -#include "collector.h" -#include "sflow.h" -#include "sflow_proto.h" // sFlow v5 - -/* -#ifdef DARWIN -#include -#define bswap_16(x) NXSwapShort(x) -#define bswap_32(x) NXSwapInt(x) -#else -#include -#endif -*/ - -#ifndef DEVEL -# define dbg_printf(...) /* printf(__VA_ARGS__) */ -#else -# define dbg_printf(...) printf(__VA_ARGS__) -#endif - -#define MAX_SFLOW_EXTENSIONS 8 - -typedef struct exporter_sflow_s { - // link chain - struct exporter_sflow_s *next; - - // generic exporter information - exporter_info_record_t info; - - uint64_t packets; // number of packets sent by this exporter - uint64_t flows; // number of flow records sent by this exporter - uint32_t sequence_failure; // number of sequence failues - - generic_sampler_t *sampler; - - // extension map - // extension maps are common for all exporters - extension_info_t sflow_extension_info[MAX_SFLOW_EXTENSIONS]; - -} exporter_sflow_t; - -extern extension_descriptor_t extension_descriptor[]; -extern FlowSource_t *FlowSource; - -/* module limited globals */ - -/* - * As sflow has no templates, we need to have an extension map for each possible - * combination of IPv4/IPv6 addresses in all ip fields - * - * index id: - * 0 : EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v4 - * 1 : EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v4 - * 2 : EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v4 - * 3 : EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v4 - * 4 : EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v6 - * 5 : EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v6 - * 6 : EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v6 - * 7 : EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v6 - */ -static uint16_t sflow_output_record_size[MAX_SFLOW_EXTENSIONS]; - -// All available extensions for sflow -static uint16_t sflow_extensions[] = { - EX_IO_SNMP_4, - EX_AS_4, - EX_MULIPLE, - EX_VLAN, - EX_MAC_1, - EX_RECEIVED, - 0 // final token -}; -static int Num_enabled_extensions; - -static struct sflow_ip_extensions_s { - int next_hop; - int next_hop_bgp; - int router_ip; -} sflow_ip_extensions[] = { - { EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v4 }, - { EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v4 }, - { EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v4 }, - { EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v4 }, - { EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v6 }, - { EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v6 }, - { EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v6 }, - { EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v6 }, -}; - -#define SFLOW_NEXT_HOP 1 -#define SFLOW_NEXT_HOP_BGP 2 -#define SFLOW_ROUTER_IP 4 -static int IP_extension_mask = 0; - -static inline exporter_sflow_t *GetExporter(FlowSource_t *fs, uint32_t agentSubId, uint32_t meanSkipCount); - -/* - * unused -// -static uint32_t MyByteSwap32(uint32_t n) { - return (((n & 0x000000FF)<<24) + - ((n & 0x0000FF00)<<8) + - ((n & 0x00FF0000)>>8) + - ((n & 0xFF000000)>>24)); -} - -static uint16_t MyByteSwap16(uint16_t n) { - return ((n >> 8) | (n << 8)); -} -*/ - -#define YES 1 -#define NO 0 - -/* define my own IP header struct - to ease portability */ -struct myiphdr { - uint8_t version_and_headerLen; - uint8_t tos; - uint16_t tot_len; - uint16_t id; - uint16_t frag_off; - uint8_t ttl; - uint8_t protocol; - uint16_t check; - uint32_t saddr; - uint32_t daddr; -}; - -/* same for tcp */ -struct mytcphdr { - uint16_t th_sport; /* source port */ - uint16_t th_dport; /* destination port */ - uint32_t th_seq; /* sequence number */ - uint32_t th_ack; /* acknowledgement number */ - uint8_t th_off_and_unused; - uint8_t th_flags; - uint16_t th_win; /* window */ - uint16_t th_sum; /* checksum */ - uint16_t th_urp; /* urgent pointer */ -}; - -/* and UDP */ -struct myudphdr { - uint16_t uh_sport; /* source port */ - uint16_t uh_dport; /* destination port */ - uint16_t uh_ulen; /* udp length */ - uint16_t uh_sum; /* udp checksum */ -}; - -/* and ICMP */ -struct myicmphdr { - uint8_t type; /* message type */ - uint8_t code; /* type sub-code */ - /* ignore the rest */ -}; - -typedef struct _SFForwardingTarget { - struct _SFForwardingTarget *nxt; - struct in_addr host; - uint32_t port; - struct sockaddr_in addr; - int sock; -} SFForwardingTarget; - -typedef enum { SFLFMT_FULL=0, SFLFMT_PCAP, SFLFMT_LINE } EnumSFLFormat; - -typedef struct _SFConfig { - uint16_t netFlowPeerAS; - int disableNetFlowScale; -} SFConfig; - -/* make the options structure global to the program */ -static SFConfig sfConfig; - -typedef struct _SFSample { - struct in_addr sourceIP; // EX_ROUTER_IP_v4 - SFLAddress agent_addr; - uint32_t agentSubId; - - /* the raw pdu */ - u_char *rawSample; - uint32_t rawSampleLen; - u_char *endp; - - /* decode cursor */ - uint32_t *datap; - - uint32_t datagramVersion; - uint32_t sampleType; - uint32_t ds_class; - uint32_t ds_index; - - /* generic interface counter sample */ - SFLIf_counters ifCounters; - - /* sample stream info */ - uint32_t sysUpTime; - uint32_t sequenceNo; - uint32_t sampledPacketSize; - uint32_t samplesGenerated; - uint32_t meanSkipCount; - uint32_t samplePool; - uint32_t dropEvents; - - /* exception handler context */ - jmp_buf env; - - /* the sampled header */ - uint32_t packet_data_tag; - uint32_t headerProtocol; - u_char *header; - int headerLen; - uint32_t stripped; - - /* header decode */ - int gotIPV4; - int offsetToIPV4; - int gotIPV6; // v6 flag - int offsetToIPV6; - struct in_addr dcd_srcIP; // Common (v4) - struct in_addr dcd_dstIP; // Common (v4) - uint32_t dcd_ipProtocol; // Common - uint32_t dcd_ipTos; // EX_MULIPLE - uint32_t dcd_ipTTL; - uint32_t dcd_sport; // Common - uint32_t dcd_dport; // Common - uint32_t dcd_tcpFlags; // Common - uint32_t ip_fragmentOffset; - uint32_t udp_pduLen; - - /* ports */ - uint32_t inputPortFormat; - uint32_t outputPortFormat; - uint32_t inputPort; // EX_IO_SNMP_4 - uint32_t outputPort; // EX_IO_SNMP_4 - - /* ethernet */ - uint32_t eth_type; - uint32_t eth_len; - u_char eth_src[8]; // EX_MAC_1 - u_char eth_dst[8]; // EX_MAC_1 - - /* vlan */ - uint32_t in_vlan; // EX_VLAN - uint32_t in_priority; - uint32_t internalPriority; - uint32_t out_vlan; // EX_VLAN - uint32_t out_priority; - - /* extended data fields */ - uint32_t num_extended; - uint32_t extended_data_tag; -#define SASAMPLE_EXTENDED_DATA_SWITCH 1 -#define SASAMPLE_EXTENDED_DATA_ROUTER 4 -#define SASAMPLE_EXTENDED_DATA_GATEWAY 8 -#define SASAMPLE_EXTENDED_DATA_USER 16 -#define SASAMPLE_EXTENDED_DATA_URL 32 -#define SASAMPLE_EXTENDED_DATA_MPLS 64 -#define SASAMPLE_EXTENDED_DATA_NAT 128 -#define SASAMPLE_EXTENDED_DATA_MPLS_TUNNEL 256 -#define SASAMPLE_EXTENDED_DATA_MPLS_VC 512 -#define SASAMPLE_EXTENDED_DATA_MPLS_FTN 1024 -#define SASAMPLE_EXTENDED_DATA_MPLS_LDP_FEC 2048 -#define SASAMPLE_EXTENDED_DATA_VLAN_TUNNEL 4096 - - /* IP forwarding info */ - SFLAddress nextHop; // EX_NEXT_HOP_v4, EX_NEXT_HOP_v6 - uint32_t srcMask; // EX_MULIPLE - uint32_t dstMask; // EX_MULIPLE - - /* BGP info */ - SFLAddress bgp_nextHop; // EX_NEXT_HOP_BGP_v4, EX_NEXT_HOP_BGP_v6 - uint32_t my_as; - uint32_t src_as; // EX_AS_4 - uint32_t src_peer_as; - uint32_t dst_as_path_len; - uint32_t *dst_as_path; - /* note: version 4 dst as path segments just get printed, not stored here, however - * the dst_peer and dst_as are filled in, since those are used for netflow encoding - */ - uint32_t dst_peer_as; - uint32_t dst_as; // EX_AS_4 - - uint32_t communities_len; - uint32_t *communities; - uint32_t localpref; - - /* user id */ -#define SA_MAX_EXTENDED_USER_LEN 200 - uint32_t src_user_charset; - uint32_t src_user_len; - char src_user[SA_MAX_EXTENDED_USER_LEN+1]; - uint32_t dst_user_charset; - uint32_t dst_user_len; - char dst_user[SA_MAX_EXTENDED_USER_LEN+1]; - - /* url */ -#define SA_MAX_EXTENDED_URL_LEN 200 -#define SA_MAX_EXTENDED_HOST_LEN 200 - uint32_t url_direction; - uint32_t url_len; - char url[SA_MAX_EXTENDED_URL_LEN+1]; - uint32_t host_len; - char host[SA_MAX_EXTENDED_HOST_LEN+1]; - - /* mpls */ - SFLAddress mpls_nextHop; - - /* nat */ - SFLAddress nat_src; - SFLAddress nat_dst; - - /* counter blocks */ - uint32_t statsSamplingInterval; - uint32_t counterBlockVersion; - -#define SFABORT(s, r) longjmp((s)->env, (r)) -#define SF_ABORT_EOS 1 -#define SF_ABORT_DECODE_ERROR 2 -#define SF_ABORT_LENGTH_ERROR 3 - - SFLAddress ipsrc; // Common (v6) - SFLAddress ipdst; // Common (v6) -} SFSample; - -int Setup_Extension_Info(FlowSource_t *fs, exporter_sflow_t *exporter, int num); - -static int printHex(const u_char *a, int len, char *buf, int bufLen, int marker, int bytesPerOutputLine); - -static char *IP_to_a(uint32_t ipaddr, char *buf, int buflen); - -static inline uint32_t getData32(SFSample *sample); - -static inline uint32_t getData32_nobswap(SFSample *sample); - -static inline uint64_t getData64(SFSample *sample); - -static void writeCountersLine(SFSample *sample); - -static void receiveError(SFSample *sample, char *errm, int hexdump) __attribute__ ((noreturn)); - -static inline void skipBytes(SFSample *sample, int skip); - -static inline uint32_t sf_log_next32(SFSample *sample, char *fieldName); - -static inline uint64_t sf_log_next64(SFSample *sample, char *fieldName); - -static inline void sf_log_percentage(SFSample *sample, char *fieldName); - -static inline uint32_t getString(SFSample *sample, char *buf, int bufLen); - -static inline uint32_t getAddress(SFSample *sample, SFLAddress *address); - -static inline void skipTLVRecord(SFSample *sample, uint32_t tag, uint32_t len, char *description); - -static inline void readSFlowDatagram(SFSample *sample, FlowSource_t *fs); - -static inline void readFlowSample(SFSample *sample, int expanded, FlowSource_t *fs); - -static inline void readCountersSample(SFSample *sample, int expanded, FlowSource_t *fs); - -static inline void readFlowSample_v2v4(SFSample *sample, FlowSource_t *fs); - -static inline void readCountersSample_v2v4(SFSample *sample, FlowSource_t *fs); - -static inline void StoreSflowRecord(SFSample *sample, FlowSource_t *fs); - -extern int verbose; - -#ifdef DEVEL -static inline char *printTag(uint32_t tag, char *buf, int bufLen); - -static inline char *printTag(uint32_t tag, char *buf, int bufLen) { - snprintf(buf, bufLen, "%u:%u", (tag >> 12), (tag & 0x00000FFF)); - return buf; -} // End of printTag - -#endif - - -/*_________________---------------------------__________________ - _________________ printHex __________________ - -----------------___________________________------------------ -*/ - -static u_char bin2hex(int nib) { return (nib < 10) ? ('0' + nib) : ('A' - 10 + nib); } - -static int printHex(const u_char *a, int len, char *buf, int bufLen, int marker, int bytesPerOutputLine) { - int b = 0, i = 0; - for(; i < len; i++) { - u_char byte; - if(b > (bufLen - 10)) break; - if(marker > 0 && i == marker) { - buf[b++] = '<'; - buf[b++] = '*'; - buf[b++] = '>'; - buf[b++] = '-'; - } - byte = a[i]; - buf[b++] = bin2hex(byte >> 4); - buf[b++] = bin2hex(byte & 0x0f); - if(i > 0 && (i % bytesPerOutputLine) == 0) buf[b++] = '\n'; - else { - // separate the bytes with a dash - if (i < (len - 1)) buf[b++] = '-'; - } - } - buf[b] = '\0'; - return b; -} - -/*_________________---------------------------__________________ - _________________ IP_to_a __________________ - -----------------___________________________------------------ -*/ - -static char *IP_to_a(uint32_t ipaddr, char *buf, int buflen) { - u_char *ip = (u_char *)&ipaddr; - snprintf(buf, buflen, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); - buf[buflen-1] = '\0'; - return buf; -} - -static char *printAddress(SFLAddress *address, char *buf, int bufLen) { - if(address->type == SFLADDRESSTYPE_IP_V4) - IP_to_a(address->address.ip_v4.s_addr, buf, bufLen); - else { - u_char *b = address->address.ip_v6.s6_addr; - snprintf(buf, bufLen, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", - b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7],b[8],b[9],b[10],b[11],b[12],b[13],b[14],b[15]); - } - return buf; -} - -/*_________________---------------------------__________________ - _________________ writeFlowLine __________________ - -----------------___________________________------------------ -*/ - -static void writeFlowLine(SFSample *sample) { -char agentIP[51], srcIP[51], dstIP[51]; - // source - printf("FLOW,%s,%d,%d,", - printAddress(&sample->agent_addr, agentIP, 50), - sample->inputPort, - sample->outputPort); - // layer 2 - printf("%02x%02x%02x%02x%02x%02x,%02x%02x%02x%02x%02x%02x,0x%04x,%d,%d", - sample->eth_src[0], - sample->eth_src[1], - sample->eth_src[2], - sample->eth_src[3], - sample->eth_src[4], - sample->eth_src[5], - sample->eth_dst[0], - sample->eth_dst[1], - sample->eth_dst[2], - sample->eth_dst[3], - sample->eth_dst[4], - sample->eth_dst[5], - sample->eth_type, - sample->in_vlan, - sample->out_vlan); - // layer 3/4 - printf(",IP: %s,%s,%d,0x%02x,%d,%d,%d,0x%02x", - IP_to_a(sample->dcd_srcIP.s_addr, srcIP, 51), - IP_to_a(sample->dcd_dstIP.s_addr, dstIP, 51), - sample->dcd_ipProtocol, - sample->dcd_ipTos, - sample->dcd_ipTTL, - sample->dcd_sport, - sample->dcd_dport, - sample->dcd_tcpFlags); - // bytes - printf(",%d,%d,%d\n", - sample->sampledPacketSize, - sample->sampledPacketSize - sample->stripped - sample->offsetToIPV4, - sample->meanSkipCount); -} - -/*_________________---------------------------__________________ - _________________ writeCountersLine __________________ - -----------------___________________________------------------ -*/ - -static void writeCountersLine(SFSample *sample) -{ - // source - char agentIP[51]; - printf("CNTR,%s,", printAddress(&sample->agent_addr, agentIP, 50)); - printf("%u,%u,%llu,%u,%u,%llu,%u,%u,%u,%u,%u,%u,%llu,%u,%u,%u,%u,%u,%u\n", - sample->ifCounters.ifIndex, - sample->ifCounters.ifType, - (unsigned long long)sample->ifCounters.ifSpeed, - sample->ifCounters.ifDirection, - sample->ifCounters.ifStatus, - (unsigned long long)sample->ifCounters.ifInOctets, - sample->ifCounters.ifInUcastPkts, - sample->ifCounters.ifInMulticastPkts, - sample->ifCounters.ifInBroadcastPkts, - sample->ifCounters.ifInDiscards, - sample->ifCounters.ifInErrors, - sample->ifCounters.ifInUnknownProtos, - (unsigned long long)sample->ifCounters.ifOutOctets, - sample->ifCounters.ifOutUcastPkts, - sample->ifCounters.ifOutMulticastPkts, - sample->ifCounters.ifOutBroadcastPkts, - sample->ifCounters.ifOutDiscards, - sample->ifCounters.ifOutErrors, - sample->ifCounters.ifPromiscuousMode); -} - -/*_________________---------------------------__________________ - _________________ receiveError __________________ - -----------------___________________________------------------ -*/ - -static void receiveError(SFSample *sample, char *errm, int hexdump) -{ - char ipbuf[51]; - char scratch[6000]; - char *msg = ""; - char *hex = ""; - uint32_t markOffset = (u_char *)sample->datap - sample->rawSample; - if(errm) msg = errm; - if(hexdump) { - printHex(sample->rawSample, sample->rawSampleLen, scratch, 6000, markOffset, 16); - hex = scratch; - } - LogError("SFLOW: %s (source IP = %s) %s", msg, IP_to_a(sample->sourceIP.s_addr, ipbuf, 51), hex); - - SFABORT(sample, SF_ABORT_DECODE_ERROR); - -} - -/*_________________---------------------------__________________ - _________________ lengthCheck __________________ - -----------------___________________________------------------ -*/ - -static void lengthCheck(SFSample *sample, char *description, u_char *start, int len) { - uint32_t actualLen = (u_char *)sample->datap - start; - uint32_t adjustedLen = ((len + 3) >> 2) << 2; - if(actualLen != adjustedLen) { - dbg_printf("%s length error (expected %d, found %d)\n", description, len, actualLen); - LogError("SFLOW: %s length error (expected %d, found %d)", description, len, actualLen); - SFABORT(sample, SF_ABORT_LENGTH_ERROR); - } - -} - -/*_________________---------------------------__________________ - _________________ decodeLinkLayer __________________ - -----------------___________________________------------------ - store the offset to the start of the ipv4 header in the sequence_number field - or -1 if not found. Decode the 802.1d if it's there. -*/ - -#define NFT_ETHHDR_SIZ 14 -#define NFT_8022_SIZ 3 -#define NFT_MAX_8023_LEN 1500 - -#define NFT_MIN_SIZ (NFT_ETHHDR_SIZ + sizeof(struct myiphdr)) - -static void decodeLinkLayer(SFSample *sample) -{ - u_char *start = (u_char *)sample->header; - u_char *end = start + sample->headerLen; - u_char *ptr = start; - uint16_t type_len; - - /* assume not found */ - sample->gotIPV4 = NO; - - if(sample->headerLen < NFT_ETHHDR_SIZ) return; /* not enough for an Ethernet header */ - - dbg_printf("dstMAC %02x%02x%02x%02x%02x%02x\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - memcpy(sample->eth_dst, ptr, 6); - ptr += 6; - - dbg_printf("srcMAC %02x%02x%02x%02x%02x%02x\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - memcpy(sample->eth_src, ptr, 6); - ptr += 6; - type_len = (ptr[0] << 8) + ptr[1]; - ptr += 2; - - if(type_len == 0x8100) { - /* VLAN - next two bytes */ - uint32_t vlanData = (ptr[0] << 8) + ptr[1]; - uint32_t vlan = vlanData & 0x0fff; -#ifdef DEVEL - uint32_t priority = vlanData >> 13; -#endif - ptr += 2; - /* _____________________________________ */ - /* | pri | c | vlan-id | */ - /* ------------------------------------- */ - /* [priority = 3bits] [Canonical Format Flag = 1bit] [vlan-id = 12 bits] */ - dbg_printf("decodedVLAN %u\n", vlan); - dbg_printf("decodedPriority %u\n", priority); - sample->in_vlan = vlan; - /* now get the type_len again (next two bytes) */ - type_len = (ptr[0] << 8) + ptr[1]; - ptr += 2; - } - - /* now we're just looking for IP */ - if(sample->headerLen < NFT_MIN_SIZ) return; /* not enough for an IPv4 header */ - - /* peek for IPX */ - if(type_len == 0x0200 || type_len == 0x0201 || type_len == 0x0600) { -#define IPX_HDR_LEN 30 -#define IPX_MAX_DATA 546 - int ipxChecksum = (ptr[0] == 0xff && ptr[1] == 0xff); - int ipxLen = (ptr[2] << 8) + ptr[3]; - if(ipxChecksum && - ipxLen >= IPX_HDR_LEN && - ipxLen <= (IPX_HDR_LEN + IPX_MAX_DATA)) - /* we don't do anything with IPX here */ - return; - } - - if(type_len <= NFT_MAX_8023_LEN) { - /* assume 802.3+802.2 header */ - /* check for SNAP */ - if(ptr[0] == 0xAA && - ptr[1] == 0xAA && - ptr[2] == 0x03) { - ptr += 3; - if(ptr[0] != 0 || - ptr[1] != 0 || - ptr[2] != 0) { - dbg_printf("VSNAP_OUI %02X-%02X-%02X\n", ptr[0], ptr[1], ptr[2]); - return; /* no further decode for vendor-specific protocol */ - } - ptr += 3; - /* OUI == 00-00-00 means the next two bytes are the ethernet type (RFC 2895) */ - type_len = (ptr[0] << 8) + ptr[1]; - ptr += 2; - } - else { - if (ptr[0] == 0x06 && - ptr[1] == 0x06 && - (ptr[2] & 0x01)) { - /* IP over 8022 */ - ptr += 3; - /* force the type_len to be IP so we can inline the IP decode below */ - type_len = 0x0800; - } - else return; - } - } - - /* assume type_len is an ethernet-type now */ - sample->eth_type = type_len; - - if(type_len == 0x0800) { - /* IPV4 */ - if((end - ptr) < sizeof(struct myiphdr)) return; - /* look at first byte of header.... */ - /* ___________________________ */ - /* | version | hdrlen | */ - /* --------------------------- */ - if((*ptr >> 4) != 4) return; /* not version 4 */ - if((*ptr & 15) < 5) return; /* not IP (hdr len must be 5 quads or more) */ - /* survived all the tests - store the offset to the start of the ip header */ - sample->gotIPV4 = YES; - sample->offsetToIPV4 = (ptr - start); - } - - if(type_len == 0x86DD) { - /* IPV6 */ - /* look at first byte of header.... */ - if((*ptr >> 4) != 6) return; /* not version 6 */ - /* survived all the tests - store the offset to the start of the ip6 header */ - sample->gotIPV6 = YES; - sample->offsetToIPV6 = (ptr - start); - } -} - - -/*_________________---------------------------__________________ - _________________ decodeIPLayer4 __________________ - -----------------___________________________------------------ -*/ - -static void decodeIPLayer4(SFSample *sample, u_char *ptr, uint32_t ipProtocol) { - u_char *end = sample->header + sample->headerLen; - if(ptr > (end - 8)) return; // not enough header bytes left - switch(ipProtocol) { - case 1: /* ICMP */ - case 58: /* ICMP6 */ - { - struct myicmphdr icmp; - memcpy(&icmp, ptr, sizeof(icmp)); - dbg_printf("ICMPType %u\n", icmp.type); - dbg_printf("ICMPCode %u\n", icmp.code); - sample->dcd_sport = icmp.type; - sample->dcd_dport = icmp.code; - } - break; - case 6: /* TCP */ - { - struct mytcphdr tcp; - memcpy(&tcp, ptr, sizeof(tcp)); - sample->dcd_sport = ntohs(tcp.th_sport); - sample->dcd_dport = ntohs(tcp.th_dport); - sample->dcd_tcpFlags = tcp.th_flags; - dbg_printf("TCPSrcPort %u\n", sample->dcd_sport); - dbg_printf("TCPDstPort %u\n",sample->dcd_dport); - dbg_printf("TCPFlags %u\n", sample->dcd_tcpFlags); - if(sample->dcd_dport == 80) { - int bytesLeft; - int headerBytes = (tcp.th_off_and_unused >> 4) * 4; - ptr += headerBytes; - bytesLeft = sample->header + sample->headerLen - ptr; - } - } - break; - case 17: /* UDP */ - { - struct myudphdr udp; - memcpy(&udp, ptr, sizeof(udp)); - sample->dcd_sport = ntohs(udp.uh_sport); - sample->dcd_dport = ntohs(udp.uh_dport); - sample->udp_pduLen = ntohs(udp.uh_ulen); - dbg_printf("UDPSrcPort %u\n", sample->dcd_sport); - dbg_printf("UDPDstPort %u\n", sample->dcd_dport); - dbg_printf("UDPBytes %u\n", sample->udp_pduLen); - } - break; - default: /* some other protcol */ - break; - } -} - -/*_________________---------------------------__________________ - _________________ decodeIPV4 __________________ - -----------------___________________________------------------ -*/ - -static void decodeIPV4(SFSample *sample) -{ - if(sample->gotIPV4) { -#ifdef DEVEL - char buf[51]; -#endif - u_char *ptr = sample->header + sample->offsetToIPV4; - /* Create a local copy of the IP header (cannot overlay structure in case it is not quad-aligned...some - platforms would core-dump if we tried that). It's OK coz this probably performs just as well anyway. */ - struct myiphdr ip; - memcpy(&ip, ptr, sizeof(ip)); - /* Value copy all ip elements into sample */ - sample->dcd_srcIP.s_addr = ip.saddr; - sample->dcd_dstIP.s_addr = ip.daddr; - sample->dcd_ipProtocol = ip.protocol; - sample->dcd_ipTos = ip.tos; - sample->dcd_ipTTL = ip.ttl; - dbg_printf("ip.tot_len %d\n", ntohs(ip.tot_len)); - /* Log out the decoded IP fields */ - dbg_printf("srcIP %s\n", IP_to_a(sample->dcd_srcIP.s_addr, buf, 51)); - dbg_printf("dstIP %s\n", IP_to_a(sample->dcd_dstIP.s_addr, buf, 51)); - dbg_printf("IPProtocol %u\n", sample->dcd_ipProtocol); - dbg_printf("IPTOS %u\n", sample->dcd_ipTos); - dbg_printf("IPTTL %u\n", sample->dcd_ipTTL); - /* check for fragments */ - sample->ip_fragmentOffset = ntohs(ip.frag_off) & 0x1FFF; - if(sample->ip_fragmentOffset > 0) { - dbg_printf("IPFragmentOffset %u\n", sample->ip_fragmentOffset); - } - else { - dbg_printf("Unfragmented\n"); - /* advance the pointer to the next protocol layer */ - /* ip headerLen is expressed as a number of quads */ - ptr += (ip.version_and_headerLen & 0x0f) * 4; - decodeIPLayer4(sample, ptr, ip.protocol); - } - } -} - -/*_________________---------------------------__________________ - _________________ decodeIPV6 __________________ - -----------------___________________________------------------ -*/ - -static void decodeIPV6(SFSample *sample) -{ - uint16_t payloadLen; - uint32_t label; - uint32_t nextHeader; - u_char *end = sample->header + sample->headerLen; - - if(sample->gotIPV6) { - u_char *ptr = sample->header + sample->offsetToIPV6; - - // check the version - { - int ipVersion = (*ptr >> 4); - if(ipVersion != 6) { - dbg_printf("header decode error: unexpected IP version: %d\n", ipVersion); - return; - } - } - - // get the tos (priority) - sample->dcd_ipTos = *ptr++ & 15; - dbg_printf("IPTOS %u\n", sample->dcd_ipTos); - // 24-bit label - label = *ptr++; - label <<= 8; - label += *ptr++; - label <<= 8; - label += *ptr++; - dbg_printf("IP6_label 0x%x\n", label); - // payload - payloadLen = (ptr[0] << 8) + ptr[1]; - ptr += 2; - // if payload is zero, that implies a jumbo payload - if(payloadLen == 0) dbg_printf("IPV6_payloadLen \n"); - else dbg_printf("IPV6_payloadLen %u\n", payloadLen); - - // next header - nextHeader = *ptr++; - - // TTL - sample->dcd_ipTTL = *ptr++; - dbg_printf("IPTTL %u\n", sample->dcd_ipTTL); - - {// src and dst address -#ifdef DEVEL - char buf[101]; -#endif - sample->ipsrc.type = SFLADDRESSTYPE_IP_V6; - memcpy(&sample->ipsrc.address, ptr, 16); - ptr +=16; - dbg_printf("srcIP6 %s\n", printAddress(&sample->ipsrc, buf, 100)); - sample->ipdst.type = SFLADDRESSTYPE_IP_V6; - memcpy(&sample->ipdst.address, ptr, 16); - ptr +=16; - dbg_printf("dstIP6 %s\n", printAddress(&sample->ipdst, buf, 100)); - } - - // skip over some common header extensions... - // http://searchnetworking.techtarget.com/originalContent/0,289142,sid7_gci870277,00.html - while(nextHeader == 0 || // hop - nextHeader == 43 || // routing - nextHeader == 44 || // fragment - // nextHeader == 50 || // encryption - don't bother coz we'll not be able to read any further - nextHeader == 51 || // auth - nextHeader == 60) { // destination options - uint32_t optionLen, skip; - dbg_printf("IP6HeaderExtension: %d\n", nextHeader); - nextHeader = ptr[0]; - optionLen = 8 * (ptr[1] + 1); // second byte gives option len in 8-byte chunks, not counting first 8 - skip = optionLen - 2; - ptr += skip; - if(ptr > end) return; // ran off the end of the header - } - - // now that we have eliminated the extension headers, nextHeader should have what we want to - // remember as the ip protocol... - sample->dcd_ipProtocol = nextHeader; - dbg_printf("IPProtocol %u\n", sample->dcd_ipProtocol); - decodeIPLayer4(sample, ptr, sample->dcd_ipProtocol); - } -} - - -#include "inline.c" -#include "nffile_inline.c" -#include "collector_inline.c" - -/*_________________---------------------------__________________ - _________________ StoreSflowRecord __________________ - -----------------___________________________------------------ -*/ - -static inline void StoreSflowRecord(SFSample *sample, FlowSource_t *fs) { -common_record_t *common_record; -stat_record_t *stat_record = fs->nffile->stat_record; -exporter_sflow_t *exporter; -extension_map_t *extension_map; -struct timeval now; -void *next_data; -value32_t *val; -uint32_t bytes, j, id, ipsize, ip_flags; -uint64_t _bytes, _packets, _t; // tmp buffers - - dbg_printf("StoreSflowRecord\n"); - - gettimeofday(&now, NULL); - - if( sample->ip_fragmentOffset > 0 ) { - sample->dcd_sport = 0; - sample->dcd_dport = 0; - } - - bytes = sample->sampledPacketSize; - - ip_flags = 0; - if ( sample->nextHop.type == SFLADDRESSTYPE_IP_V6 ) - SetFlag(ip_flags, SFLOW_NEXT_HOP); - - if ( sample->bgp_nextHop.type == SFLADDRESSTYPE_IP_V6 ) - SetFlag(ip_flags, SFLOW_NEXT_HOP_BGP); - - if ( fs->sa_family == AF_INET6 ) - SetFlag(ip_flags, SFLOW_ROUTER_IP); - - ip_flags &= IP_extension_mask; - - if ( ip_flags >= MAX_SFLOW_EXTENSIONS ) { - LogError("SFLOW: Corrupt ip_flags: %u", ip_flags); - } - exporter = GetExporter(fs, sample->agentSubId, sample->meanSkipCount); - if ( !exporter ) { - LogError("SFLOW: Exporter NULL: Abort sflow record processing"); - return; - } - exporter->packets++; - - // get appropriate extension map - extension_map = exporter->sflow_extension_info[ip_flags].map; - if ( !extension_map ) { - LogInfo("SFLOW: setup extension map: %u", ip_flags); - if ( !Setup_Extension_Info(fs, exporter, ip_flags ) ) { - LogError("SFLOW: Extension map: NULL: Abort sflow record processing"); - return; - } - extension_map = exporter->sflow_extension_info[ip_flags].map; - LogInfo("SFLOW: setup extension map: %u done", ip_flags); - } - - // output buffer size check - // IPv6 needs 2 x 16 bytes, IPv4 2 x 4 bytes - ipsize = sample->gotIPV6 ? 32 : 8; - if ( !CheckBufferSpace(fs->nffile, sflow_output_record_size[ip_flags] + ipsize )) { - // fishy! - should never happen. maybe disk full? - LogError("SFLOW: output buffer size error. Abort sflow record processing"); - return; - } - - dbg_printf("Fill Record\n"); - common_record = (common_record_t *)fs->nffile->buff_ptr; - - common_record->size = sflow_output_record_size[ip_flags] + ipsize; - common_record->type = CommonRecordType; - common_record->flags = 0; - SetFlag(common_record->flags, FLAG_SAMPLED); - - common_record->exporter_sysid = exporter->info.sysid; - common_record->ext_map = extension_map->map_id; - - common_record->first = now.tv_sec; - common_record->last = common_record->first; - common_record->msec_first = now.tv_usec / 1000; - common_record->msec_last = common_record->msec_first; - _t = 1000LL * now.tv_sec + common_record->msec_first; // tmp buff for first_seen - - common_record->fwd_status = 0; - common_record->reserved = 0; - common_record->tcp_flags = sample->dcd_tcpFlags; - common_record->prot = sample->dcd_ipProtocol; - common_record->tos = sample->dcd_ipTos; - common_record->srcport = (uint16_t)sample->dcd_sport; - common_record->dstport = (uint16_t)sample->dcd_dport; - - if(sample->gotIPV6) { - u_char *b; - uint64_t *u; - ipv6_block_t *ipv6 = (ipv6_block_t *)common_record->data; - SetFlag(common_record->flags, FLAG_IPV6_ADDR); - - b = sample->ipsrc.address.ip_v6.s6_addr; - u = (uint64_t *)b; - ipv6->srcaddr[0] = ntohll(*u); - u = (uint64_t *)&(b[8]); - ipv6->srcaddr[1] = ntohll(*u); - - b = sample->ipdst.address.ip_v6.s6_addr; - u = (uint64_t *)b; - ipv6->dstaddr[0] = ntohll(*u); - u = (uint64_t *)&(b[8]); - ipv6->dstaddr[1] = ntohll(*u); - - next_data = (void *)ipv6->data; - } else { - ipv4_block_t *ipv4 = (ipv4_block_t *)common_record->data; - ipv4->srcaddr = ntohl(sample->dcd_srcIP.s_addr); - ipv4->dstaddr = ntohl(sample->dcd_dstIP.s_addr); - - next_data = (void *)ipv4->data; - } - - // 4 byte Packet value - val = (value32_t *)next_data; - val->val = sample->meanSkipCount; - _packets = val->val; - - // 4 byte Bytes value - val = (value32_t *)val->data; - val->val = sample->meanSkipCount * bytes; - _bytes = val->val; - - next_data = (void *)val->data; - - j = 0; - while ( (id = extension_map->ex_id[j]) != 0 ) { - switch (id) { - case EX_IO_SNMP_4: { // 4 byte input/output interface index - tpl_ext_5_t *tpl = (tpl_ext_5_t *)next_data; - tpl->input = sample->inputPort; - tpl->output = sample->outputPort; - next_data = (void *)tpl->data; - } break; - case EX_AS_4: { // 4 byte src/dst AS number - tpl_ext_7_t *tpl = (tpl_ext_7_t *)next_data; - tpl->src_as = sample->src_as; - tpl->dst_as = sample->dst_as; - next_data = (void *)tpl->data; - } break; - case EX_VLAN: { // 2 byte valn label - tpl_ext_13_t *tpl = (tpl_ext_13_t *)next_data; - tpl->src_vlan = sample->in_vlan; - tpl->dst_vlan = sample->out_vlan; - next_data = (void *)tpl->data; - } break; - case EX_MULIPLE: { // dst tos, direction, src/dst mask - tpl_ext_8_t *tpl = (tpl_ext_8_t *)next_data; - tpl->dst_tos = sample->dcd_ipTos; - tpl->dir = 0; - tpl->src_mask = sample->srcMask; - tpl->dst_mask = sample->dstMask; - next_data = (void *)tpl->data; - } break; - case EX_MAC_1: { // MAC addreses - tpl_ext_20_t *tpl = (tpl_ext_20_t *)next_data; - tpl->in_src_mac = Get_val48((void *)&sample->eth_src); - tpl->out_dst_mac = Get_val48((void *)&sample->eth_dst); - next_data = (void *)tpl->data; - } break; - case EX_NEXT_HOP_v4: { // next hop IPv4 router address - tpl_ext_9_t *tpl = (tpl_ext_9_t *)next_data; - if ( sample->nextHop.type == SFLADDRESSTYPE_IP_V4 ) { - tpl->nexthop = ntohl(sample->nextHop.address.ip_v4.s_addr); - } else { - tpl->nexthop = 0; - } - next_data = (void *)tpl->data; - } break; - case EX_NEXT_HOP_v6: { // next hop IPv6 router address - tpl_ext_10_t *tpl = (tpl_ext_10_t *)next_data; - void *ptr = (void *)sample->nextHop.address.ip_v6.s6_addr; - if ( sample->nextHop.type == SFLADDRESSTYPE_IP_V6 ) { - tpl->nexthop[0] = ntohll(((uint64_t *)ptr)[0]); - tpl->nexthop[1] = ntohll(((uint64_t *)ptr)[1]); - } else { - tpl->nexthop[0] = 0; - tpl->nexthop[1] = 0; - } - SetFlag(common_record->flags, FLAG_IPV6_NH); - next_data = (void *)tpl->data; - } break; - case EX_NEXT_HOP_BGP_v4: { // next hop bgp IPv4 router address - tpl_ext_11_t *tpl = (tpl_ext_11_t *)next_data; - if ( sample->bgp_nextHop.type == SFLADDRESSTYPE_IP_V4 ) { - tpl->bgp_nexthop = ntohl(sample->bgp_nextHop.address.ip_v4.s_addr); - } else { - tpl->bgp_nexthop = 0; - } - next_data = (void *)tpl->data; - } break; - case EX_NEXT_HOP_BGP_v6: { // next hop IPv4 router address - tpl_ext_12_t *tpl = (tpl_ext_12_t *)next_data; - void *ptr = (void *)sample->bgp_nextHop.address.ip_v6.s6_addr; - if ( sample->bgp_nextHop.type == SFLADDRESSTYPE_IP_V6 ) { - tpl->bgp_nexthop[0] = ntohll(((uint64_t *)ptr)[0]); - tpl->bgp_nexthop[1] = ntohll(((uint64_t *)ptr)[1]); - } else { - tpl->bgp_nexthop[0] = 0; - tpl->bgp_nexthop[1] = 0; - } - SetFlag(common_record->flags, FLAG_IPV6_NHB); - next_data = (void *)tpl->data; - } break; - case EX_ROUTER_IP_v4: - case EX_ROUTER_IP_v6: // IPv4/IPv6 router address - if(sample->agent_addr.type == SFLADDRESSTYPE_IP_V4) { - tpl_ext_23_t *tpl = (tpl_ext_23_t *)next_data; - tpl->router_ip = ntohl(sample->agent_addr.address.ip_v4.s_addr); - next_data = (void *)tpl->data; - ClearFlag(common_record->flags, FLAG_IPV6_EXP); - } else { - tpl_ext_24_t *tpl = (tpl_ext_24_t *)next_data; - void *ptr = (void *)sample->agent_addr.address.ip_v6.s6_addr; - tpl->router_ip[0] = ntohll(((uint64_t *)ptr)[0]); - tpl->router_ip[1] = ntohll(((uint64_t *)ptr)[1]); - next_data = (void *)tpl->data; - SetFlag(common_record->flags, FLAG_IPV6_EXP); - } - break; - case EX_RECEIVED: { - tpl_ext_27_t *tpl = (tpl_ext_27_t *)next_data; - tpl->received = (uint64_t)((uint64_t)fs->received.tv_sec * 1000LL) + (uint64_t)((uint64_t)fs->received.tv_usec / 1000LL); - next_data = (void *)tpl->data; - } break; - default: - // this should never happen - LogError("SFLOW: Unexpected extension %i for sflow record. Skip extension", id); - dbg_printf("SFLOW: Unexpected extension %i for sflow record. Skip extension", id); - } - j++; - } - -/* - if(sfConfig.netFlowPeerAS) { - pkt.flow.srcAS = htons((uint16_t)sample->src_peer_as); - pkt.flow.dstAS = htons((uint16_t)sample->dst_peer_as); - } - else { - pkt.flow.srcAS = htons((uint16_t)sample->src_as); - pkt.flow.dstAS = htons((uint16_t)sample->dst_as); - } -*/ - - // update first_seen, last_seen - if ( _t < fs->first_seen ) // the very first time stamp need to be set - fs->first_seen = _t; - fs->last_seen = _t; - - // Update stats - switch (common_record->prot) { - case 1: - stat_record->numflows_icmp++; - stat_record->numpackets_icmp += _packets; - stat_record->numbytes_icmp += _bytes; - break; - case 6: - stat_record->numflows_tcp++; - stat_record->numpackets_tcp += _packets; - stat_record->numbytes_tcp += _bytes; - break; - case 17: - stat_record->numflows_udp++; - stat_record->numpackets_udp += _packets; - stat_record->numbytes_udp += _bytes; - break; - default: - stat_record->numflows_other++; - stat_record->numpackets_other += _packets; - stat_record->numbytes_other += _bytes; - } - exporter->flows++; - stat_record->numflows++; - stat_record->numpackets += _packets; - stat_record->numbytes += _bytes; - - if ( verbose ) { - master_record_t master_record; - char *string; - ExpandRecord_v2((common_record_t *)common_record, &exporter->sflow_extension_info[ip_flags], &(exporter->info), &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++; - fs->nffile->block_header->size += (sflow_output_record_size[ip_flags] + ipsize); -#ifdef DEVEL - if ( (next_data - fs->nffile->buff_ptr) != (sflow_output_record_size[ip_flags] + ipsize) ) { - printf("PANIC: Size error. Buffer diff: %llu, Size: %u\n", - (unsigned long long)(next_data - fs->nffile->buff_ptr), - (sflow_output_record_size[ip_flags] + ipsize)); - exit(255); - } -#endif - fs->nffile->buff_ptr = next_data; - -} - -/*_________________---------------------------__________________ - _________________ read data fns __________________ - -----------------___________________________------------------ -*/ - -static inline uint32_t getData32(SFSample *sample) { - if ((u_char *)sample->datap > sample->endp) - SFABORT(sample, SF_ABORT_EOS); - return ntohl(*(sample->datap)++); -} // End of getData32 - -static inline uint32_t getData32_nobswap(SFSample *sample) { - if ((u_char *)sample->datap > sample->endp) - SFABORT(sample, SF_ABORT_EOS); - return *(sample->datap)++; -} // End of getData32_nobswap - -static inline uint64_t getData64(SFSample *sample) { -uint64_t tmpLo, tmpHi; - - tmpHi = getData32(sample); - tmpLo = getData32(sample); - return (tmpHi << 32) + tmpLo; -} // End of getData64 - -static inline void skipBytes(SFSample *sample, int skip) { -int quads = (skip + 3) / 4; - - sample->datap += quads; - if ( (u_char *)sample->datap > sample->endp) - SFABORT(sample, SF_ABORT_EOS); -} // End of skipBytes - -static inline uint32_t sf_log_next32(SFSample *sample, char *fieldName) { -uint32_t val = getData32(sample); - - dbg_printf("%s %u\n", fieldName, val); - return val; -} // End of sf_log_next32 - -static inline uint64_t sf_log_next64(SFSample *sample, char *fieldName) { -uint64_t val64 = getData64(sample); - - dbg_printf("%s %llu\n", fieldName, (unsigned long long)val64); - return val64; -} // End of sf_log_next64 - -static inline void sf_log_percentage(SFSample *sample, char *fieldName) { -uint32_t hundredths = getData32(sample); - - if ( hundredths == (uint32_t)-1) - dbg_printf("%s unknown\n", fieldName); - else { -#ifdef DEVEL - float percent = (float)hundredths / 10.0; -#endif - dbg_printf("%s %.1f\n", fieldName, percent); - } -} // End of sf_log_percentage - - -static inline uint32_t getString(SFSample *sample, char *buf, int bufLen) { -uint32_t len, read_len; - - len = getData32(sample); - // truncate if too long - read_len = (len >= bufLen) ? (bufLen - 1) : len; - memcpy(buf, sample->datap, read_len); - buf[read_len] = '\0'; // null terminate - skipBytes(sample, len); - return len; -} // End of getString - -static inline uint32_t getAddress(SFSample *sample, SFLAddress *address) { - - address->type = getData32(sample); - if(address->type == SFLADDRESSTYPE_IP_V4) - address->address.ip_v4.s_addr = getData32_nobswap(sample); - else { - memcpy(&address->address.ip_v6.s6_addr, sample->datap, 16); - skipBytes(sample, 16); - } - return address->type; -} // End of getAddress - -static inline void skipTLVRecord(SFSample *sample, uint32_t tag, uint32_t len, char *description) { - -#ifdef DEVEL - char buf[51]; - snprintf(buf, 50, "%u:%u", (tag >> 12), (tag & 0x00000FFF)); - printf("skipping unknown %s: 0x%x, %s len=%d\n", description, tag, buf, len); -#endif - - skipBytes(sample, len); -} // End of skipTLVRecord - -/*_________________---------------------------__________________ - _________________ readExtendedSwitch __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedSwitch(SFSample *sample) -{ - dbg_printf("extendedType SWITCH\n"); - sample->in_vlan = getData32(sample); - sample->in_priority = getData32(sample); - sample->out_vlan = getData32(sample); - sample->out_priority = getData32(sample); - - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_SWITCH; - - dbg_printf("in_vlan %u\n", sample->in_vlan); - dbg_printf("in_priority %u\n", sample->in_priority); - dbg_printf("out_vlan %u\n", sample->out_vlan); - dbg_printf("out_priority %u\n", sample->out_priority); -} - -/*_________________---------------------------__________________ - _________________ readExtendedRouter __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedRouter(SFSample *sample) -{ -#ifdef DEVEL -char buf[51]; -#endif - - dbg_printf("extendedType ROUTER\n"); - getAddress(sample, &sample->nextHop); - sample->srcMask = getData32(sample); - sample->dstMask = getData32(sample); - - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_ROUTER; - - dbg_printf("nextHop %s\n", printAddress(&sample->nextHop, buf, 50)); - dbg_printf("srcSubnetMask %u\n", sample->srcMask); - dbg_printf("dstSubnetMask %u\n", sample->dstMask); -} - -/*_________________---------------------------__________________ - _________________ readExtendedGateway_v2 __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedGateway_v2(SFSample *sample) -{ - dbg_printf("extendedType GATEWAY\n"); - - sample->my_as = getData32(sample); - sample->src_as = getData32(sample); - sample->src_peer_as = getData32(sample); - sample->dst_as_path_len = getData32(sample); - /* just point at the dst_as_path array */ - if(sample->dst_as_path_len > 0) { - sample->dst_as_path = sample->datap; - /* and skip over it in the input */ - skipBytes(sample, sample->dst_as_path_len * 4); - // fill in the dst and dst_peer fields too - sample->dst_peer_as = ntohl(sample->dst_as_path[0]); - sample->dst_as = ntohl(sample->dst_as_path[sample->dst_as_path_len - 1]); - } - - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_GATEWAY; - - dbg_printf("my_as %u\n", sample->my_as); - dbg_printf("src_as %u\n", sample->src_as); - dbg_printf("src_peer_as %u\n", sample->src_peer_as); - dbg_printf("dst_as %u\n", sample->dst_as); - dbg_printf("dst_peer_as %u\n", sample->dst_peer_as); - dbg_printf("dst_as_path_len %u\n", sample->dst_as_path_len); - if(sample->dst_as_path_len > 0) { - uint32_t i = 0; - for(; i < sample->dst_as_path_len; i++) { - if(i == 0) dbg_printf("dst_as_path "); - else dbg_printf("-"); - dbg_printf("%u", ntohl(sample->dst_as_path[i])); - } - dbg_printf("\n"); - } -} - -/*_________________---------------------------__________________ - _________________ readExtendedGateway __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedGateway(SFSample *sample) -{ -#ifdef DEVEL - char buf[51]; -#endif - uint32_t segments; - int seg; - - dbg_printf("extendedType GATEWAY\n"); - - if(sample->datagramVersion >= 5) { - getAddress(sample, &sample->bgp_nextHop); - dbg_printf("bgp_nexthop %s\n", printAddress(&sample->bgp_nextHop, buf, 50)); - } - - sample->my_as = getData32(sample); - sample->src_as = getData32(sample); - sample->src_peer_as = getData32(sample); - dbg_printf("my_as %u\n", sample->my_as); - dbg_printf("src_as %u\n", sample->src_as); - dbg_printf("src_peer_as %u\n", sample->src_peer_as); - segments = getData32(sample); - if(segments > 0) { - dbg_printf("dst_as_path "); - for(seg = 0; seg < segments; seg++) { - uint32_t seg_type; - uint32_t seg_len; - int i; - seg_type = getData32(sample); - seg_len = getData32(sample); - for(i = 0; i < seg_len; i++) { - uint32_t asNumber; - asNumber = getData32(sample); - /* mark the first one as the dst_peer_as */ - if(i == 0 && seg == 0) sample->dst_peer_as = asNumber; - else dbg_printf("-"); - /* make sure the AS sets are in parentheses */ - if(i == 0 && seg_type == SFLEXTENDED_AS_SET) dbg_printf("("); - dbg_printf("%u", asNumber); - /* mark the last one as the dst_as */ - if(seg == (segments - 1) && i == (seg_len - 1)) sample->dst_as = asNumber; - } - if(seg_type == SFLEXTENDED_AS_SET) dbg_printf(")"); - } - dbg_printf("\n"); - } - dbg_printf("dst_as %u\n", sample->dst_as); - dbg_printf("dst_peer_as %u\n", sample->dst_peer_as); - - sample->communities_len = getData32(sample); - /* just point at the communities array */ - if(sample->communities_len > 0) sample->communities = sample->datap; - /* and skip over it in the input */ - skipBytes(sample, sample->communities_len * 4); - - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_GATEWAY; - if(sample->communities_len > 0) { - int j = 0; - for(; j < sample->communities_len; j++) { - if(j == 0) dbg_printf("BGP_communities "); - else dbg_printf("-"); - dbg_printf("%u", ntohl(sample->communities[j])); - } - dbg_printf("\n"); - } - - sample->localpref = getData32(sample); - dbg_printf("BGP_localpref %u\n", sample->localpref); - -} - -/*_________________---------------------------__________________ - _________________ readExtendedUser __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedUser(SFSample *sample) -{ - dbg_printf("extendedType USER\n"); - - if(sample->datagramVersion >= 5) { - sample->src_user_charset = getData32(sample); - dbg_printf("src_user_charset %d\n", sample->src_user_charset); - } - - sample->src_user_len = getString(sample, sample->src_user, SA_MAX_EXTENDED_USER_LEN); - - if(sample->datagramVersion >= 5) { - sample->dst_user_charset = getData32(sample); - dbg_printf("dst_user_charset %d\n", sample->dst_user_charset); - } - - sample->dst_user_len = getString(sample, sample->dst_user, SA_MAX_EXTENDED_USER_LEN); - - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_USER; - - dbg_printf("src_user %s\n", sample->src_user); - dbg_printf("dst_user %s\n", sample->dst_user); -} - -/*_________________---------------------------__________________ - _________________ readExtendedUrl __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedUrl(SFSample *sample) -{ - dbg_printf("extendedType URL\n"); - - sample->url_direction = getData32(sample); - dbg_printf("url_direction %u\n", sample->url_direction); - sample->url_len = getString(sample, sample->url, SA_MAX_EXTENDED_URL_LEN); - dbg_printf("url %s\n", sample->url); - if(sample->datagramVersion >= 5) { - sample->host_len = getString(sample, sample->host, SA_MAX_EXTENDED_HOST_LEN); - dbg_printf("host %s\n", sample->host); - } - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_URL; -} - - -/*_________________---------------------------__________________ - _________________ mplsLabelStack __________________ - -----------------___________________________------------------ -*/ - -static void mplsLabelStack(SFSample *sample, char *fieldName) -{ - SFLLabelStack lstk; - uint32_t lab; - lstk.depth = getData32(sample); - /* just point at the lablelstack array */ - if(lstk.depth > 0) - lstk.stack = (uint32_t *)sample->datap; - else - lstk.stack = NULL; - /* and skip over it in the input */ - skipBytes(sample, lstk.depth * 4); - - if(lstk.depth > 0) { - int j = 0; - for(; j < lstk.depth; j++) { - if(j == 0) dbg_printf("%s ", fieldName); - else dbg_printf("-"); - lab = ntohl(lstk.stack[j]); - dbg_printf("%u.%u.%u.%u", - (lab >> 12), // label - (lab >> 9) & 7, // experimental - (lab >> 8) & 1, // bottom of stack - (lab & 255)); // TTL - } - dbg_printf("\n"); - } -} - -/*_________________---------------------------__________________ - _________________ readExtendedMpls __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedMpls(SFSample *sample) -{ -#ifdef DEVEL - char buf[51]; -#endif - dbg_printf("extendedType MPLS\n"); - getAddress(sample, &sample->mpls_nextHop); - dbg_printf("mpls_nexthop %s\n", printAddress(&sample->mpls_nextHop, buf, 50)); - - mplsLabelStack(sample, "mpls_input_stack"); - mplsLabelStack(sample, "mpls_output_stack"); - - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS; -} - -/*_________________---------------------------__________________ - _________________ readExtendedNat __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedNat(SFSample *sample) -{ -#ifdef DEVEL - char buf[51]; -#endif - dbg_printf("extendedType NAT\n"); - getAddress(sample, &sample->nat_src); - dbg_printf("nat_src %s\n", printAddress(&sample->nat_src, buf, 50)); - getAddress(sample, &sample->nat_dst); - dbg_printf("nat_dst %s\n", printAddress(&sample->nat_dst, buf, 50)); - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_NAT; -} - - -/*_________________---------------------------__________________ - _________________ readExtendedMplsTunnel __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedMplsTunnel(SFSample *sample) -{ -#define SA_MAX_TUNNELNAME_LEN 100 - char tunnel_name[SA_MAX_TUNNELNAME_LEN+1]; - uint32_t tunnel_id, tunnel_cos; - - if(getString(sample, tunnel_name, SA_MAX_TUNNELNAME_LEN) > 0) - dbg_printf("mpls_tunnel_lsp_name %s\n", tunnel_name); - tunnel_id = getData32(sample); - dbg_printf("mpls_tunnel_id %u\n", tunnel_id); - tunnel_cos = getData32(sample); - dbg_printf("mpls_tunnel_cos %u\n", tunnel_cos); - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_TUNNEL; -} - -/*_________________---------------------------__________________ - _________________ readExtendedMplsVC __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedMplsVC(SFSample *sample) -{ -#define SA_MAX_VCNAME_LEN 100 - char vc_name[SA_MAX_VCNAME_LEN+1]; - uint32_t vll_vc_id, vc_cos; - if(getString(sample, vc_name, SA_MAX_VCNAME_LEN) > 0) - dbg_printf("mpls_vc_name %s\n", vc_name); - vll_vc_id = getData32(sample); - dbg_printf("mpls_vll_vc_id %u\n", vll_vc_id); - vc_cos = getData32(sample); - dbg_printf("mpls_vc_cos %u\n", vc_cos); - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_VC; -} - -/*_________________---------------------------__________________ - _________________ readExtendedMplsFTN __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedMplsFTN(SFSample *sample) -{ -#define SA_MAX_FTN_LEN 100 - char ftn_descr[SA_MAX_FTN_LEN+1]; - uint32_t ftn_mask; - if(getString(sample, ftn_descr, SA_MAX_FTN_LEN) > 0) - dbg_printf("mpls_ftn_descr %s\n", ftn_descr); - ftn_mask = getData32(sample); - dbg_printf("mpls_ftn_mask %u\n", ftn_mask); - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_FTN; -} - -/*_________________---------------------------__________________ - _________________ readExtendedMplsLDP_FEC __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedMplsLDP_FEC(SFSample *sample) -{ -#ifdef DEVEL - uint32_t fec_addr_prefix_len = getData32(sample); -#endif - dbg_printf("mpls_fec_addr_prefix_len %u\n", fec_addr_prefix_len); - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_LDP_FEC; -} - -/*_________________---------------------------__________________ - _________________ readExtendedVlanTunnel __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedVlanTunnel(SFSample *sample) -{ - uint32_t lab; - SFLLabelStack lstk; - lstk.depth = getData32(sample); - /* just point at the lablelstack array */ - if(lstk.depth > 0) - lstk.stack = (uint32_t *)sample->datap; - else - lstk.stack = NULL; - /* and skip over it in the input */ - skipBytes(sample, lstk.depth * 4); - - if(lstk.depth > 0) { - int j = 0; - for(; j < lstk.depth; j++) { - if(j == 0) dbg_printf("vlan_tunnel "); - else dbg_printf("-"); - lab = ntohl(lstk.stack[j]); - dbg_printf("0x%04x.%u.%u.%u", - (lab >> 16), // TPI - (lab >> 13) & 7, // priority - (lab >> 12) & 1, // CFI - (lab & 4095)); // VLAN - } - dbg_printf("\n"); - } - sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_VLAN_TUNNEL; -} - -/*_________________---------------------------__________________ - _________________ readExtendedProcess __________________ - -----------------___________________________------------------ -*/ - -static void readExtendedProcess(SFSample *sample) -{ - char pname[51]; - uint32_t num_processes, i; - dbg_printf("extendedType process\n"); - num_processes = getData32(sample); - for(i = 0; i < num_processes; i++) { -#ifdef DEVEL - uint32_t pid = getData32(sample); -#endif - if(getString(sample, pname, 50) > 0) dbg_printf("pid %u %s\n", pid, pname); - else dbg_printf("pid %u \n", pid); - } -} - -/*_________________---------------------------__________________ - _________________ readFlowSample_header __________________ - -----------------___________________________------------------ -*/ - -static void readFlowSample_header(SFSample *sample) { - dbg_printf("flowSampleType HEADER\n"); - sample->headerProtocol = getData32(sample); - dbg_printf("headerProtocol %u\n", sample->headerProtocol); - sample->sampledPacketSize = getData32(sample); - dbg_printf("sampledPacketSize %u\n", sample->sampledPacketSize); - if(sample->datagramVersion > 4) { - // stripped count introduced in sFlow version 5 - sample->stripped = getData32(sample); - dbg_printf("strippedBytes %u\n", sample->stripped); - } - sample->headerLen = getData32(sample); - dbg_printf("headerLen %u\n", sample->headerLen); - - sample->header = (u_char *)sample->datap; /* just point at the header */ - skipBytes(sample, sample->headerLen); - { - char scratch[2000]; - printHex(sample->header, sample->headerLen, scratch, 2000, 0, 2000); - dbg_printf("headerBytes %s\n", scratch); - } - - switch(sample->headerProtocol) { - /* the header protocol tells us where to jump into the decode */ - case SFLHEADER_ETHERNET_ISO8023: - decodeLinkLayer(sample); - break; - case SFLHEADER_IPv4: - sample->gotIPV4 = YES; - sample->offsetToIPV4 = 0; - break; - case SFLHEADER_ISO88024_TOKENBUS: - case SFLHEADER_ISO88025_TOKENRING: - case SFLHEADER_FDDI: - case SFLHEADER_FRAME_RELAY: - case SFLHEADER_X25: - case SFLHEADER_PPP: - case SFLHEADER_SMDS: - case SFLHEADER_AAL5: - case SFLHEADER_AAL5_IP: - case SFLHEADER_IPv6: - case SFLHEADER_MPLS: - dbg_printf("NO_DECODE headerProtocol=%d\n", sample->headerProtocol); - break; - default: - LogError("SFLOW: undefined headerProtocol = %d", sample->headerProtocol); - exit(-12); - } - - if(sample->gotIPV4) { - // report the size of the original IPPdu (including the IP header) - dbg_printf("IPSize %d\n", sample->sampledPacketSize - sample->stripped - sample->offsetToIPV4); - decodeIPV4(sample); - } - else if(sample->gotIPV6) { - // report the size of the original IPPdu (including the IP header) - dbg_printf("IPSize %d\n", sample->sampledPacketSize - sample->stripped - sample->offsetToIPV6); - decodeIPV6(sample); - } - -} - -/*_________________---------------------------__________________ - _________________ readFlowSample_ethernet __________________ - -----------------___________________________------------------ -*/ - -static void readFlowSample_ethernet(SFSample *sample) -{ - u_char *p; - dbg_printf("flowSampleType ETHERNET\n"); - sample->eth_len = getData32(sample); - memcpy(sample->eth_src, sample->datap, 6); - skipBytes(sample, 6); - memcpy(sample->eth_dst, sample->datap, 6); - skipBytes(sample, 6); - sample->eth_type = getData32(sample); - dbg_printf("ethernet_type %u\n", sample->eth_type); - dbg_printf("ethernet_len %u\n", sample->eth_len); - p = sample->eth_src; - dbg_printf("ethernet_src %02x%02x%02x%02x%02x%02x\n", p[0], p[1], p[2], p[3], p[4], p[5]); - p = sample->eth_dst; - dbg_printf("ethernet_dst %02x%02x%02x%02x%02x%02x\n", p[0], p[1], p[2], p[3], p[4], p[5]); -} - - -/*_________________---------------------------__________________ - _________________ readFlowSample_IPv4 __________________ - -----------------___________________________------------------ -*/ - -static void readFlowSample_IPv4(SFSample *sample) -{ - dbg_printf("flowSampleType IPV4\n"); - sample->headerLen = sizeof(SFLSampled_ipv4); - sample->header = (u_char *)sample->datap; /* just point at the header */ - skipBytes(sample, sample->headerLen); - { -#ifdef DEVEL - char buf[51]; -#endif - SFLSampled_ipv4 nfKey; - memcpy(&nfKey, sample->header, sizeof(nfKey)); - sample->sampledPacketSize = ntohl(nfKey.length); - dbg_printf("sampledPacketSize %u\n", sample->sampledPacketSize); - dbg_printf("IPSize %d\n", sample->sampledPacketSize); - sample->dcd_srcIP = nfKey.src_ip; - sample->dcd_dstIP = nfKey.dst_ip; - sample->dcd_ipProtocol = ntohl(nfKey.protocol); - sample->dcd_ipTos = ntohl(nfKey.tos); - dbg_printf("srcIP %s\n", IP_to_a(sample->dcd_srcIP.s_addr, buf, 51)); - dbg_printf("dstIP %s\n", IP_to_a(sample->dcd_dstIP.s_addr, buf, 51)); - dbg_printf("IPProtocol %u\n", sample->dcd_ipProtocol); - dbg_printf("IPTOS %u\n", sample->dcd_ipTos); - sample->dcd_sport = ntohl(nfKey.src_port); - sample->dcd_dport = ntohl(nfKey.dst_port); - switch(sample->dcd_ipProtocol) { - case 1: /* ICMP */ - dbg_printf("ICMPType %u\n", sample->dcd_dport); - /* not sure about the dest port being icmp type - - might be that src port is icmp type and dest - port is icmp code. Still, have seen some - implementations where src port is 0 and dst - port is the type, so it may be safer to - assume that the destination port has the type */ - break; - case 6: /* TCP */ - dbg_printf("TCPSrcPort %u\n", sample->dcd_sport); - dbg_printf("TCPDstPort %u\n", sample->dcd_dport); - sample->dcd_tcpFlags = ntohl(nfKey.tcp_flags); - dbg_printf("TCPFlags %u\n", sample->dcd_tcpFlags); - break; - case 17: /* UDP */ - dbg_printf("UDPSrcPort %u\n", sample->dcd_sport); - dbg_printf("UDPDstPort %u\n", sample->dcd_dport); - break; - default: /* some other protcol */ - break; - } - } -} - -/*_________________---------------------------__________________ - _________________ readFlowSample_IPv6 __________________ - -----------------___________________________------------------ -*/ - -static void readFlowSample_IPv6(SFSample *sample) -{ - dbg_printf("flowSampleType IPV6\n"); - sample->header = (u_char *)sample->datap; /* just point at the header */ - sample->headerLen = sizeof(SFLSampled_ipv6); - skipBytes(sample, sample->headerLen); - { - SFLSampled_ipv6 nfKey6; - memcpy(&nfKey6, sample->header, sizeof(nfKey6)); - sample->sampledPacketSize = ntohl(nfKey6.length); - dbg_printf("sampledPacketSize %u\n", sample->sampledPacketSize); - } - /* bug: more decode to do here */ -} - -/*_________________---------------------------__________________ - _________________ readFlowSample_v2v4 __________________ - -----------------___________________________------------------ -*/ - -static void readFlowSample_v2v4(SFSample *sample, FlowSource_t *fs) { - dbg_printf("sampleType FLOWSAMPLE\n"); - - sample->samplesGenerated = getData32(sample); - dbg_printf("sampleSequenceNo %u\n", sample->samplesGenerated); - { - uint32_t samplerId = getData32(sample); - sample->ds_class = samplerId >> 24; - sample->ds_index = samplerId & 0x00ffffff; - dbg_printf("sourceId %u:%u\n", sample->ds_class, sample->ds_index); - } - - sample->meanSkipCount = getData32(sample); - sample->samplePool = getData32(sample); - sample->dropEvents = getData32(sample); - sample->inputPort = getData32(sample); - sample->outputPort = getData32(sample); - dbg_printf("meanSkipCount %u\n", sample->meanSkipCount); - dbg_printf("samplePool %u\n", sample->samplePool); - dbg_printf("dropEvents %u\n", sample->dropEvents); - dbg_printf("inputPort %u\n", sample->inputPort); - if(sample->outputPort & 0x80000000) { - uint32_t numOutputs = sample->outputPort & 0x7fffffff; - if(numOutputs > 0) dbg_printf("outputPort multiple %d\n", numOutputs); - else dbg_printf("outputPort multiple >1\n"); - } - else dbg_printf("outputPort %u\n", sample->outputPort); - - sample->packet_data_tag = getData32(sample); - - switch(sample->packet_data_tag) { - - case INMPACKETTYPE_HEADER: readFlowSample_header(sample); break; - case INMPACKETTYPE_IPV4: readFlowSample_IPv4(sample); break; - case INMPACKETTYPE_IPV6: readFlowSample_IPv6(sample); break; - default: receiveError(sample, "unexpected packet_data_tag", YES); break; - } - - sample->extended_data_tag = 0; - { - uint32_t x; - sample->num_extended = getData32(sample); - for(x = 0; x < sample->num_extended; x++) { - uint32_t extended_tag; - extended_tag = getData32(sample); - switch(extended_tag) { - case INMEXTENDED_SWITCH: - readExtendedSwitch(sample); break; - case INMEXTENDED_ROUTER: - readExtendedRouter(sample); break; - case INMEXTENDED_GATEWAY: - if(sample->datagramVersion == 2) - readExtendedGateway_v2(sample); - else - readExtendedGateway(sample); - break; - case INMEXTENDED_USER: - readExtendedUser(sample); break; - case INMEXTENDED_URL: - readExtendedUrl(sample); break; - default: - LogError("Unrecognized extended data tag: %u", extended_tag); - receiveError(sample, "unrecognized extended data tag", YES); - break; - } - } - } - - if(sample->gotIPV4 || sample->gotIPV6) - StoreSflowRecord(sample, fs); - - /* if we are writing tcpdump format, write the next packet record now */ - /* or line-by-line output... */ - if ( verbose ) - writeFlowLine(sample); -} - -/*_________________---------------------------__________________ - _________________ readFlowSample __________________ - -----------------___________________________------------------ -*/ - -static void readFlowSample(SFSample *sample, int expanded, FlowSource_t *fs) { - uint32_t num_elements, sampleLength; - u_char *sampleStart; - - dbg_printf("sampleType FLOWSAMPLE\n"); - sampleLength = getData32(sample); - sampleStart = (u_char *)sample->datap; - sample->samplesGenerated = getData32(sample); - dbg_printf("sampleSequenceNo %u\n", sample->samplesGenerated); - if(expanded) { - sample->ds_class = getData32(sample); - sample->ds_index = getData32(sample); - } - else { - uint32_t samplerId = getData32(sample); - sample->ds_class = samplerId >> 24; - sample->ds_index = samplerId & 0x00ffffff; - } - dbg_printf("sourceId %u:%u\n", sample->ds_class, sample->ds_index); - - sample->meanSkipCount = getData32(sample); - sample->samplePool = getData32(sample); - sample->dropEvents = getData32(sample); - dbg_printf("meanSkipCount %u\n", sample->meanSkipCount); - dbg_printf("samplePool %u\n", sample->samplePool); - dbg_printf("dropEvents %u\n", sample->dropEvents); - if(expanded) { - sample->inputPortFormat = getData32(sample); - sample->inputPort = getData32(sample); - sample->outputPortFormat = getData32(sample); - sample->outputPort = getData32(sample); - } - else { - uint32_t inp, outp; - inp = getData32(sample); - outp = getData32(sample); - sample->inputPortFormat = inp >> 30; - sample->outputPortFormat = outp >> 30; - sample->inputPort = inp & 0x3fffffff; - sample->outputPort = outp & 0x3fffffff; - } - if(sample->inputPortFormat == 3) dbg_printf("inputPort format==3 %u\n", sample->inputPort); - else if(sample->inputPortFormat == 2) dbg_printf("inputPort multiple %u\n", sample->inputPort); - else if(sample->inputPortFormat == 1) dbg_printf("inputPort dropCode %u\n", sample->inputPort); - else if(sample->inputPortFormat == 0) dbg_printf("inputPort %u\n", sample->inputPort); - if(sample->outputPortFormat == 3) dbg_printf("outputPort format==3 %u\n", sample->outputPort); - else if(sample->outputPortFormat == 2) dbg_printf("outputPort multiple %u\n", sample->outputPort); - else if(sample->outputPortFormat == 1) dbg_printf("outputPort dropCode %u\n", sample->outputPort); - else if(sample->outputPortFormat == 0) dbg_printf("outputPort %u\n", sample->outputPort); - - num_elements = getData32(sample); - { - int el; - for(el = 0; el < num_elements; el++) { -#ifdef DEVEL - char buf[51]; -#endif - uint32_t tag, length; - u_char *start; - tag = getData32(sample); - dbg_printf("flowBlock_tag %s\n", printTag(tag, buf, 50)); - length = getData32(sample); - start = (u_char *)sample->datap; - - switch(tag) { - case SFLFLOW_HEADER: readFlowSample_header(sample); break; - case SFLFLOW_ETHERNET: readFlowSample_ethernet(sample); break; - case SFLFLOW_IPV4: readFlowSample_IPv4(sample); break; - case SFLFLOW_IPV6: readFlowSample_IPv6(sample); break; - case SFLFLOW_EX_SWITCH: readExtendedSwitch(sample); break; - case SFLFLOW_EX_ROUTER: readExtendedRouter(sample); break; - case SFLFLOW_EX_GATEWAY: readExtendedGateway(sample); break; - case SFLFLOW_EX_USER: readExtendedUser(sample); break; - case SFLFLOW_EX_URL: readExtendedUrl(sample); break; - case SFLFLOW_EX_MPLS: readExtendedMpls(sample); break; - case SFLFLOW_EX_NAT: readExtendedNat(sample); break; - case SFLFLOW_EX_MPLS_TUNNEL: readExtendedMplsTunnel(sample); break; - case SFLFLOW_EX_MPLS_VC: readExtendedMplsVC(sample); break; - case SFLFLOW_EX_MPLS_FTN: readExtendedMplsFTN(sample); break; - case SFLFLOW_EX_MPLS_LDP_FEC: readExtendedMplsLDP_FEC(sample); break; - case SFLFLOW_EX_VLAN_TUNNEL: readExtendedVlanTunnel(sample); break; - case SFLFLOW_EX_PROCESS: readExtendedProcess(sample); break; - default: skipTLVRecord(sample, tag, length, "flow_sample_element"); break; - } - lengthCheck(sample, "flow_sample_element", start, length); - } - } - lengthCheck(sample, "flow_sample", sampleStart, sampleLength); - - if ( sample->gotIPV4 || sample->gotIPV6 ) - StoreSflowRecord(sample, fs); - - /* or line-by-line output... */ - if ( verbose ) - writeFlowLine(sample); -} - -/*_________________---------------------------__________________ - _________________ readCounters_generic __________________ - -----------------___________________________------------------ -*/ - -static void readCounters_generic(SFSample *sample) -{ - /* the first part of the generic counters block is really just more info about the interface. */ - sample->ifCounters.ifIndex = sf_log_next32(sample, "ifIndex"); - sample->ifCounters.ifType = sf_log_next32(sample, "networkType"); - sample->ifCounters.ifSpeed = sf_log_next64(sample, "ifSpeed"); - sample->ifCounters.ifDirection = sf_log_next32(sample, "ifDirection"); - sample->ifCounters.ifStatus = sf_log_next32(sample, "ifStatus"); - /* the generic counters always come first */ - sample->ifCounters.ifInOctets = sf_log_next64(sample, "ifInOctets"); - sample->ifCounters.ifInUcastPkts = sf_log_next32(sample, "ifInUcastPkts"); - sample->ifCounters.ifInMulticastPkts = sf_log_next32(sample, "ifInMulticastPkts"); - sample->ifCounters.ifInBroadcastPkts = sf_log_next32(sample, "ifInBroadcastPkts"); - sample->ifCounters.ifInDiscards = sf_log_next32(sample, "ifInDiscards"); - sample->ifCounters.ifInErrors = sf_log_next32(sample, "ifInErrors"); - sample->ifCounters.ifInUnknownProtos = sf_log_next32(sample, "ifInUnknownProtos"); - sample->ifCounters.ifOutOctets = sf_log_next64(sample, "ifOutOctets"); - sample->ifCounters.ifOutUcastPkts = sf_log_next32(sample, "ifOutUcastPkts"); - sample->ifCounters.ifOutMulticastPkts = sf_log_next32(sample, "ifOutMulticastPkts"); - sample->ifCounters.ifOutBroadcastPkts = sf_log_next32(sample, "ifOutBroadcastPkts"); - sample->ifCounters.ifOutDiscards = sf_log_next32(sample, "ifOutDiscards"); - sample->ifCounters.ifOutErrors = sf_log_next32(sample, "ifOutErrors"); - sample->ifCounters.ifPromiscuousMode = sf_log_next32(sample, "ifPromiscuousMode"); -} - -/*_________________---------------------------__________________ - _________________ readCounters_ethernet __________________ - -----------------___________________________------------------ -*/ - -static void readCounters_ethernet(SFSample *sample) -{ - sf_log_next32(sample, "dot3StatsAlignmentErrors"); - sf_log_next32(sample, "dot3StatsFCSErrors"); - sf_log_next32(sample, "dot3StatsSingleCollisionFrames"); - sf_log_next32(sample, "dot3StatsMultipleCollisionFrames"); - sf_log_next32(sample, "dot3StatsSQETestErrors"); - sf_log_next32(sample, "dot3StatsDeferredTransmissions"); - sf_log_next32(sample, "dot3StatsLateCollisions"); - sf_log_next32(sample, "dot3StatsExcessiveCollisions"); - sf_log_next32(sample, "dot3StatsInternalMacTransmitErrors"); - sf_log_next32(sample, "dot3StatsCarrierSenseErrors"); - sf_log_next32(sample, "dot3StatsFrameTooLongs"); - sf_log_next32(sample, "dot3StatsInternalMacReceiveErrors"); - sf_log_next32(sample, "dot3StatsSymbolErrors"); -} - - -/*_________________---------------------------__________________ - _________________ readCounters_tokenring __________________ - -----------------___________________________------------------ -*/ - -static void readCounters_tokenring(SFSample *sample) -{ - sf_log_next32(sample, "dot5StatsLineErrors"); - sf_log_next32(sample, "dot5StatsBurstErrors"); - sf_log_next32(sample, "dot5StatsACErrors"); - sf_log_next32(sample, "dot5StatsAbortTransErrors"); - sf_log_next32(sample, "dot5StatsInternalErrors"); - sf_log_next32(sample, "dot5StatsLostFrameErrors"); - sf_log_next32(sample, "dot5StatsReceiveCongestions"); - sf_log_next32(sample, "dot5StatsFrameCopiedErrors"); - sf_log_next32(sample, "dot5StatsTokenErrors"); - sf_log_next32(sample, "dot5StatsSoftErrors"); - sf_log_next32(sample, "dot5StatsHardErrors"); - sf_log_next32(sample, "dot5StatsSignalLoss"); - sf_log_next32(sample, "dot5StatsTransmitBeacons"); - sf_log_next32(sample, "dot5StatsRecoverys"); - sf_log_next32(sample, "dot5StatsLobeWires"); - sf_log_next32(sample, "dot5StatsRemoves"); - sf_log_next32(sample, "dot5StatsSingles"); - sf_log_next32(sample, "dot5StatsFreqErrors"); -} - - -/*_________________---------------------------__________________ - _________________ readCounters_vg __________________ - -----------------___________________________------------------ -*/ - -static void readCounters_vg(SFSample *sample) -{ - sf_log_next32(sample, "dot12InHighPriorityFrames"); - sf_log_next64(sample, "dot12InHighPriorityOctets"); - sf_log_next32(sample, "dot12InNormPriorityFrames"); - sf_log_next64(sample, "dot12InNormPriorityOctets"); - sf_log_next32(sample, "dot12InIPMErrors"); - sf_log_next32(sample, "dot12InOversizeFrameErrors"); - sf_log_next32(sample, "dot12InDataErrors"); - sf_log_next32(sample, "dot12InNullAddressedFrames"); - sf_log_next32(sample, "dot12OutHighPriorityFrames"); - sf_log_next64(sample, "dot12OutHighPriorityOctets"); - sf_log_next32(sample, "dot12TransitionIntoTrainings"); - sf_log_next64(sample, "dot12HCInHighPriorityOctets"); - sf_log_next64(sample, "dot12HCInNormPriorityOctets"); - sf_log_next64(sample, "dot12HCOutHighPriorityOctets"); -} - - - -/*_________________---------------------------__________________ - _________________ readCounters_vlan __________________ - -----------------___________________________------------------ -*/ - -static void readCounters_vlan(SFSample *sample) -{ - sample->in_vlan = getData32(sample); - dbg_printf("in_vlan %u\n", sample->in_vlan); - sf_log_next64(sample, "octets"); - sf_log_next32(sample, "ucastPkts"); - sf_log_next32(sample, "multicastPkts"); - sf_log_next32(sample, "broadcastPkts"); - sf_log_next32(sample, "discards"); -} - -/*_________________---------------------------__________________ - _________________ readCounters_processor __________________ - -----------------___________________________------------------ -*/ - -static void readCounters_processor(SFSample *sample) -{ - sf_log_percentage(sample, "5s_cpu"); - sf_log_percentage(sample, "1m_cpu"); - sf_log_percentage(sample, "5m_cpu"); - sf_log_next64(sample, "total_memory_bytes"); - sf_log_next64(sample, "free_memory_bytes"); -} - -/*_________________---------------------------__________________ - _________________ readCountersSample_v2v4 __________________ - -----------------___________________________------------------ -*/ - -static void readCountersSample_v2v4(SFSample *sample, FlowSource_t *fs) -{ - dbg_printf("sampleType COUNTERSSAMPLE\n"); - sample->samplesGenerated = getData32(sample); - dbg_printf("sampleSequenceNo %u\n", sample->samplesGenerated); - { - uint32_t samplerId = getData32(sample); - sample->ds_class = samplerId >> 24; - sample->ds_index = samplerId & 0x00ffffff; - } - dbg_printf("sourceId %u:%u\n", sample->ds_class, sample->ds_index); - - - sample->statsSamplingInterval = getData32(sample); - dbg_printf("statsSamplingInterval %u\n", sample->statsSamplingInterval); - /* now find out what sort of counter blocks we have here... */ - sample->counterBlockVersion = getData32(sample); - dbg_printf("counterBlockVersion %u\n", sample->counterBlockVersion); - - /* first see if we should read the generic stats */ - switch(sample->counterBlockVersion) { - case INMCOUNTERSVERSION_GENERIC: - case INMCOUNTERSVERSION_ETHERNET: - case INMCOUNTERSVERSION_TOKENRING: - case INMCOUNTERSVERSION_FDDI: - case INMCOUNTERSVERSION_VG: - case INMCOUNTERSVERSION_WAN: readCounters_generic(sample); break; - case INMCOUNTERSVERSION_VLAN: break; - default: receiveError(sample, "unknown stats version", YES); break; - } - - /* now see if there are any specific counter blocks to add */ - switch(sample->counterBlockVersion) { - case INMCOUNTERSVERSION_GENERIC: /* nothing more */ break; - case INMCOUNTERSVERSION_ETHERNET: readCounters_ethernet(sample); break; - case INMCOUNTERSVERSION_TOKENRING:readCounters_tokenring(sample); break; - case INMCOUNTERSVERSION_FDDI: break; - case INMCOUNTERSVERSION_VG: readCounters_vg(sample); break; - case INMCOUNTERSVERSION_WAN: break; - case INMCOUNTERSVERSION_VLAN: readCounters_vlan(sample); break; - default: receiveError(sample, "unknown INMCOUNTERSVERSION", YES); break; - } - /* line-by-line output... */ - if ( verbose ) - writeCountersLine(sample); -} - -/*_________________---------------------------__________________ - _________________ readCountersSample __________________ - -----------------___________________________------------------ -*/ - -static void readCountersSample(SFSample *sample, int expanded, FlowSource_t *fs) { - uint32_t sampleLength; - uint32_t num_elements; - u_char *sampleStart; - dbg_printf("sampleType COUNTERSSAMPLE\n"); - sampleLength = getData32(sample); - sampleStart = (u_char *)sample->datap; - sample->samplesGenerated = getData32(sample); - - dbg_printf("sampleSequenceNo %u\n", sample->samplesGenerated); - if(expanded) { - sample->ds_class = getData32(sample); - sample->ds_index = getData32(sample); - } - else { - uint32_t samplerId = getData32(sample); - sample->ds_class = samplerId >> 24; - sample->ds_index = samplerId & 0x00ffffff; - } - dbg_printf("sourceId %u:%u\n", sample->ds_class, sample->ds_index); - - num_elements = getData32(sample); - { - int el; - for(el = 0; el < num_elements; el++) { -#ifdef DEVEL - char buf[51]; -#endif - uint32_t tag, length; - u_char *start; - tag = getData32(sample); - dbg_printf("counterBlock_tag %s\n", printTag(tag, buf, 50)); - length = getData32(sample); - start = (u_char *)sample->datap; - - switch(tag) { - case SFLCOUNTERS_GENERIC: readCounters_generic(sample); break; - case SFLCOUNTERS_ETHERNET: readCounters_ethernet(sample); break; - case SFLCOUNTERS_TOKENRING:readCounters_tokenring(sample); break; - case SFLCOUNTERS_VG: readCounters_vg(sample); break; - case SFLCOUNTERS_VLAN: readCounters_vlan(sample); break; - case SFLCOUNTERS_PROCESSOR: readCounters_processor(sample); break; - default: skipTLVRecord(sample, tag, length, "counters_sample_element"); break; - } - lengthCheck(sample, "counters_sample_element", start, length); - } - } - lengthCheck(sample, "counters_sample", sampleStart, sampleLength); - /* line-by-line output... */ - if ( verbose ) - writeCountersLine(sample); - -} - -/*_________________---------------------------__________________ - _________________ readSFlowDatagram __________________ - -----------------___________________________------------------ -*/ - -static inline void readSFlowDatagram(SFSample *sample, FlowSource_t *fs) { -uint32_t samplesInPacket; -uint32_t samp = 0; -struct timeval now; -#ifdef DEVEL -char buf[51]; -#endif - - /* log some datagram info */ - now.tv_sec = time(NULL); - now.tv_usec = 0; - dbg_printf("datagramSourceIP %s\n", IP_to_a(sample->sourceIP.s_addr, buf, 51)); - dbg_printf("datagramSize %u\n", sample->rawSampleLen); - dbg_printf("unixSecondsUTC %llu\n", (unsigned long long)now.tv_sec); - - /* check the version */ - sample->datagramVersion = getData32(sample); - dbg_printf("datagramVersion %d\n", sample->datagramVersion); - if(sample->datagramVersion != 2 && - sample->datagramVersion != 4 && - sample->datagramVersion != 5) { - receiveError(sample, "unexpected datagram version number\n", YES); - } - - /* get the agent address */ - getAddress(sample, &sample->agent_addr); - - /* version 5 has an agent sub-id as well */ - if(sample->datagramVersion >= 5) { - sample->agentSubId = getData32(sample); - dbg_printf("agentSubId %u\n", sample->agentSubId); - } - - sample->sequenceNo = getData32(sample); /* this is the packet sequence number */ - sample->sysUpTime = getData32(sample); - samplesInPacket = getData32(sample); - dbg_printf("agent %s\n", printAddress(&sample->agent_addr, buf, 50)); - dbg_printf("packetSequenceNo %u\n", sample->sequenceNo); - dbg_printf("sysUpTime %u\n", sample->sysUpTime); - dbg_printf("samplesInPacket %u\n", samplesInPacket); - - /* now iterate and pull out the flows and counters samples */ - for(; samp < samplesInPacket; samp++) { - memset(&sample->packet_data_tag, 0, - sizeof(*sample) - ((void *)&sample->packet_data_tag - (void *)sample)); - - // just read the tag, then call the approriate decode fn - sample->sampleType = getData32(sample); - dbg_printf("startSample ----------------------\n"); - dbg_printf("sampleType_tag %s\n", printTag(sample->sampleType, buf, 50)); - if(sample->datagramVersion >= 5) { - switch(sample->sampleType) { - case SFLFLOW_SAMPLE: readFlowSample(sample, NO, fs); - break; - case SFLCOUNTERS_SAMPLE: readCountersSample(sample, NO, fs); - break; - case SFLFLOW_SAMPLE_EXPANDED: readFlowSample(sample, YES, fs); - break; - case SFLCOUNTERS_SAMPLE_EXPANDED: readCountersSample(sample, YES, fs); - break; - default: skipTLVRecord(sample, sample->sampleType, getData32(sample), "sample"); - break; - } - } else { - switch(sample->sampleType) { - case FLOWSAMPLE: readFlowSample_v2v4(sample, fs); - break; - case COUNTERSSAMPLE: readCountersSample_v2v4(sample, fs); - break; - default: receiveError(sample, "unexpected sample type", YES); - break; - } - } - dbg_printf("endSample ----------------------\n"); - } -} // readSFlowDatagram - - -void Init_sflow(void) { -int i, id; - - sfConfig.disableNetFlowScale = 0; - sfConfig.netFlowPeerAS = 0; - - i=0; - Num_enabled_extensions = 0; - while ( (id = sflow_extensions[i]) != 0 ) { - if ( extension_descriptor[id].enabled ) { - dbg_printf("Enabled extension: %i\n", id); - Num_enabled_extensions++; - } - i++; - } - - IP_extension_mask = 0; - i=0; - while ( extension_descriptor[i].description != NULL ) { - switch (extension_descriptor[i].id) { - case EX_NEXT_HOP_v4: - // case EX_NEXT_HOP_v6: - not really needed - if ( extension_descriptor[i].enabled ) { - SetFlag(IP_extension_mask, SFLOW_NEXT_HOP); - Num_enabled_extensions++; - } break; - case EX_NEXT_HOP_BGP_v4: - // case EX_NEXT_HOP_BGP_v6: - not really needed - if ( extension_descriptor[i].enabled ) { - SetFlag(IP_extension_mask, SFLOW_NEXT_HOP_BGP); - Num_enabled_extensions++; - } break; - case EX_ROUTER_IP_v4: - // case EX_ROUTER_IP_v6: - not really needed - if ( extension_descriptor[i].enabled ) { - SetFlag(IP_extension_mask, SFLOW_ROUTER_IP); - Num_enabled_extensions++; - } break; - } - i++; - } - - dbg_printf("Num enabled Extensions: %i\n", Num_enabled_extensions); - -} // End of Init_sflow - -int Setup_Extension_Info(FlowSource_t *fs, exporter_sflow_t *exporter, int num) { -int i, id, extension_size, map_size, map_index; - - dbg_printf("Setup Extension ID 0x%x\n", num); - LogInfo("SFLOW: setup extension map %u", num); - - // prepare sflow extension map - exporter->sflow_extension_info[num].map = NULL; - extension_size = 0; - - // calculate the full extension map size - map_size = Num_enabled_extensions * sizeof(uint16_t) + sizeof(extension_map_t); - - // align 32 bits - if ( ( map_size & 0x3 ) != 0 ) - map_size += 2; - - - // Create a generic sflow extension map - exporter->sflow_extension_info[num].map = (extension_map_t *)malloc((size_t)map_size); - if ( !exporter->sflow_extension_info[num].map ) { - LogError("malloc() allocation error in %s line %d: %s", __FILE__, __LINE__, strerror(errno) ); - return 0; - } - - // calclate the extension size - i=0; - map_index = 0; - while ( (id = sflow_extensions[i]) != 0 ) { - if ( extension_descriptor[id].enabled ) { - extension_size += extension_descriptor[id].size; - exporter->sflow_extension_info[num].map->ex_id[map_index++] = id; - } - i++; - } - - if ( TestFlag(IP_extension_mask, SFLOW_NEXT_HOP)) { - id = sflow_ip_extensions[num].next_hop; - extension_size += extension_descriptor[id].size; - exporter->sflow_extension_info[num].map->ex_id[map_index++] = id; - } - - if ( TestFlag(IP_extension_mask, SFLOW_NEXT_HOP_BGP)) { - id = sflow_ip_extensions[num].next_hop_bgp; - extension_size += extension_descriptor[id].size; - exporter->sflow_extension_info[num].map->ex_id[map_index++] = id; - } - - if ( TestFlag(IP_extension_mask, SFLOW_ROUTER_IP)) { - id = sflow_ip_extensions[num].router_ip; - extension_size += extension_descriptor[id].size; - exporter->sflow_extension_info[num].map->ex_id[map_index++] = id; - } - - // terminating null record - exporter->sflow_extension_info[num].map->ex_id[map_index] = 0; - - dbg_printf("Extension size: %i\n", extension_size); - - // caculate the basic record size: without IP addr space ( v4/v6 dependant ) - // byte/packet counters are 32bit -> 2 x uint32_t - // extension_size contains the sum of all optional extensions - sflow_output_record_size[num] = COMMON_RECORD_DATA_SIZE + 2*sizeof(uint32_t) + extension_size; - - dbg_printf("Record size: %i\n", sflow_output_record_size[num]); - - exporter->sflow_extension_info[num].map->type = ExtensionMapType; - exporter->sflow_extension_info[num].map->size = map_size; - exporter->sflow_extension_info[num].map->map_id = INIT_ID; - exporter->sflow_extension_info[num].map->extension_size = extension_size; - - LogInfo("Extension size: %i", extension_size); - LogInfo("Extension map size: %i", map_size); - - if ( !AddExtensionMap(fs, exporter->sflow_extension_info[num].map) ) { - // bad - we must free this map and fail - otherwise data can not be read any more - free(exporter->sflow_extension_info[num].map); - exporter->sflow_extension_info[num].map = NULL; - return 0; - } - dbg_printf("New Extension map ID %i\n", exporter->sflow_extension_info[num].map->map_id); - LogInfo("New extension map id: %i", exporter->sflow_extension_info[num].map->map_id); - - return 1; - -} // End of Setup_Extension_Info - -static inline exporter_sflow_t *GetExporter(FlowSource_t *fs, uint32_t agentSubId, uint32_t meanSkipCount) { -exporter_sflow_t **e = (exporter_sflow_t **)&(fs->exporter_data); -generic_sampler_t *sampler; -#define IP_STRING_LEN 40 -char ipstr[IP_STRING_LEN]; -int i; - - // search the appropriate exporter engine - while ( *e ) { - if ( (*e)->info.id == agentSubId && (*e)->info.version == SFLOW_VERSION && - (*e)->info.ip.v6[0] == fs->ip.v6[0] && (*e)->info.ip.v6[1] == fs->ip.v6[1]) - return *e; - e = &((*e)->next); - } - - if ( fs->sa_family == AF_INET ) { - uint32_t _ip = htonl(fs->ip.v4); - inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); - } else if ( fs->sa_family == AF_INET6 ) { - uint64_t _ip[2]; - _ip[0] = htonll(fs->ip.v6[0]); - _ip[1] = htonll(fs->ip.v6[1]); - inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); - } else { - strncpy(ipstr, "", IP_STRING_LEN); - } - - // nothing found - LogInfo("SFLOW: New exporter" ); - - *e = (exporter_sflow_t *)malloc(sizeof(exporter_sflow_t)); - if ( !(*e)) { - LogError("SFLOW: malloc() error in %s line %d: %s", __FILE__, __LINE__, strerror (errno)); - return NULL; - } - memset((void *)(*e), 0, sizeof(exporter_sflow_t)); - (*e)->next = NULL; - (*e)->info.header.type = ExporterInfoRecordType; - (*e)->info.header.size = sizeof(exporter_info_record_t); - (*e)->info.version = SFLOW_VERSION; - (*e)->info.id = agentSubId; - (*e)->info.ip = fs->ip; - (*e)->info.sa_family = fs->sa_family; - (*e)->sequence_failure = 0; - (*e)->packets = 0; - (*e)->flows = 0; - for (i=0; isflow_extension_info[i].map = NULL; - } - - sampler = (generic_sampler_t *)malloc(sizeof(generic_sampler_t)); - if ( !sampler ) { - LogError("SFLOW: malloc() error in %s line %d: %s", __FILE__, __LINE__, strerror (errno)); - return NULL; - } - (*e)->sampler = sampler; - - sampler->info.header.type = SamplerInfoRecordype; - sampler->info.header.size = sizeof(sampler_info_record_t); - sampler->info.id = -1; - sampler->info.mode = 0; - sampler->info.interval = meanSkipCount; - sampler->next = NULL; - - FlushInfoExporter(fs, &((*e)->info)); - sampler->info.exporter_sysid = (*e)->info.sysid; - FlushInfoSampler(fs, &(sampler->info)); - - dbg_printf("SFLOW: New exporter: SysID: %u, agentSubId: %u, MeanSkipCount: %u, IP: %s\n", - (*e)->info.sysid, agentSubId, meanSkipCount, ipstr); - LogInfo("SFLOW: New exporter: SysID: %u, agentSubId: %u, MeanSkipCount: %u, IP: %s", - (*e)->info.sysid, agentSubId, meanSkipCount, ipstr); - - return (*e); - -} // End of GetExporter - -void Process_sflow(void *in_buff, ssize_t in_buff_cnt, FlowSource_t *fs) { - -SFSample sample; -int exceptionVal; - - memset(&sample, 0, sizeof(sample)); - sample.rawSample = in_buff; - sample.rawSampleLen = in_buff_cnt; - sample.sourceIP.s_addr = fs->sa_family == PF_INET ? htonl(fs->ip.v4) : 0;; - - dbg_printf("startDatagram =================================\n"); - if((exceptionVal = setjmp(sample.env)) == 0) { - // TRY - sample.datap = (uint32_t *)sample.rawSample; - sample.endp = (u_char *)sample.rawSample + sample.rawSampleLen; - readSFlowDatagram(&sample, fs ); - } else { - // CATCH - dbg_printf("SFLOW: caught exception: %d\n", exceptionVal); - LogError("SFLOW: caught exception: %d", exceptionVal); - } - dbg_printf("endDatagram =================================\n"); - -} // End of Process_sflow diff --git a/bin/sflow.h b/bin/sflow.h index 272b785..1fa8a0f 100644 --- a/bin/sflow.h +++ b/bin/sflow.h @@ -1,306 +1,703 @@ -/* - * Copyright (c) 2014, Peter Haag - * Copyright (c) 2009, Peter Haag - * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of the author nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $Author: haag $ - * - * $Id: sflow.h 39 2009-11-25 08:11:15Z haag $ - * - * $LastChangedRevision: 39 $ - * - * - */ - -#ifndef _SFLOW_H -#define _SFLOW_H 1 - -/* - * sfcapd makes use of code originated from sflowtool by InMon Corp. - * Those parts of the code are distributed under the InMon Public License below. - * All other/additional code is pubblished under BSD license. - */ - +/* Copyright (c) 2002-2011 InMon Corp. Licensed under the terms of the InMon sFlow licence: */ +/* http://www.inmon.com/technology/sflowlicense.txt */ /* - * ----------------------------------------------------------------------- - * Copyright (c) 2001-2002 InMon Corp. All rights reserved. - * ----------------------------------------------------------------------- - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes sFlow(TM), freely available from - * http://www.inmon.com/". - * - * 4. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes sFlow(TM), freely available from - * http://www.inmon.com/". - * - * 5. InMon Corp. may publish revised and/or new versions - * of the license from time to time. Each version will be given a - * distinguishing version number. Once covered code has been - * published under a particular version of the license, you may - * always continue to use it under the terms of that version. You - * may also choose to use such covered code under the terms of any - * subsequent version of the license published by InMon Corp. - * No one other than the InMon Corp. has the right to modify the terms - * applicable to covered code created under this License. - * - * 6. The name "sFlow" must not be used to endorse or promote products - * derived from this software without prior written permission - * from InMon Corp. This does not apply to add-on libraries or tools - * that work in conjunction with sFlow. In such a case the sFlow name - * may be used to indicate that the product supports sFlow. - * - * 7. Products derived from this software may not be called "sFlow", - * nor may "sFlow" appear in their name, without prior written - * permission of InMon Corp. - * - * - * THIS SOFTWARE IS PROVIDED BY INMON CORP. ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * INMON CORP. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * -------------------------------------------------------------------- - * - * This software consists of voluntary contributions made by many - * individuals on behalf of InMon Corp. - * - * InMon Corp. can be contacted via Email at info@inmon.com. - * - * For more information on InMon Corp. and sFlow, - * please see http://www.inmon.com/. - * - * InMon Public License Version 1.0 written May 31, 2001 - * - */ +///////////////////////////////////////////////////////////////////////////////// +/////////////////////// sFlow Sampling Packet Data Types //////////////////////// +///////////////////////////////////////////////////////////////////////////////// +*/ +#ifndef SFLOW_H +#define SFLOW_H 1 -enum INMAddress_type { - INMADDRESSTYPE_IP_V4 = 1, - INMADDRESSTYPE_IP_V6 = 2 +#if defined(__cplusplus) +extern "C" { +#endif + +typedef struct { + uint32_t addr; +} SFLIPv4; + +typedef struct { + uint8_t addr[16]; +} SFLIPv6; + +typedef union _SFLAddress_value { + SFLIPv4 ip_v4; + SFLIPv6 ip_v6; +} SFLAddress_value; + +enum SFLAddress_type { + SFLADDRESSTYPE_UNDEFINED = 0, + SFLADDRESSTYPE_IP_V4 = 1, + SFLADDRESSTYPE_IP_V6 = 2 }; -typedef union _INMAddress_value { - struct in_addr ip_v4; - struct in6_addr ip_v6; -} INMAddress_value; - -typedef struct _INMAddress { - uint32_t type; /* enum INMAddress_type */ - INMAddress_value address; -} INMAddress; +typedef struct _SFLAddress { + uint32_t type; /* enum SFLAddress_type */ + SFLAddress_value address; +} SFLAddress; /* Packet header data */ -#define INM_MAX_HEADER_SIZE 256 /* The maximum sampled header size. */ -#define INM_DEFAULT_HEADER_SIZE 128 -#define INM_DEFAULT_COLLECTOR_PORT 6343 -#define INM_DEFAULT_SAMPLING_RATE 400 +#define SFL_DEFAULT_HEADER_SIZE 128 +#define SFL_DEFAULT_COLLECTOR_PORT 6343 +#define SFL_DEFAULT_SAMPLING_RATE 400 /* The header protocol describes the format of the sampled header */ -enum INMHeader_protocol { - INMHEADER_ETHERNET_ISO8023 = 1, - INMHEADER_ISO88024_TOKENBUS = 2, - INMHEADER_ISO88025_TOKENRING = 3, - INMHEADER_FDDI = 4, - INMHEADER_FRAME_RELAY = 5, - INMHEADER_X25 = 6, - INMHEADER_PPP = 7, - INMHEADER_SMDS = 8, - INMHEADER_AAL5 = 9, - INMHEADER_AAL5_IP = 10, /* e.g. Cisco AAL5 mux */ - INMHEADER_IPv4 = 11, - INMHEADER_IPv6 = 12 +enum SFLHeader_protocol { + SFLHEADER_ETHERNET_ISO8023 = 1, + SFLHEADER_ISO88024_TOKENBUS = 2, + SFLHEADER_ISO88025_TOKENRING = 3, + SFLHEADER_FDDI = 4, + SFLHEADER_FRAME_RELAY = 5, + SFLHEADER_X25 = 6, + SFLHEADER_PPP = 7, + SFLHEADER_SMDS = 8, + SFLHEADER_AAL5 = 9, + SFLHEADER_AAL5_IP = 10, /* e.g. Cisco AAL5 mux */ + SFLHEADER_IPv4 = 11, + SFLHEADER_IPv6 = 12, + SFLHEADER_MPLS = 13, + SFLHEADER_POS = 14, + SFLHEADER_IEEE80211MAC = 15, + SFLHEADER_IEEE80211_AMPDU = 16, + SFLHEADER_IEEE80211_AMSDU_SUBFRAME = 17 }; -typedef struct _INMSampled_header { - uint32_t header_protocol; /* (enum INMHeader_protocol) */ +/* raw sampled header */ + +typedef struct _SFLSampled_header { + uint32_t header_protocol; /* (enum SFLHeader_protocol) */ uint32_t frame_length; /* Original length of packet before sampling */ + uint32_t stripped; /* header/trailer bytes stripped by sender */ uint32_t header_length; /* length of sampled header bytes to follow */ - uint8_t header[INM_MAX_HEADER_SIZE]; /* Header bytes */ -} INMSampled_header; + uint8_t *header_bytes; /* Header bytes */ +} SFLSampled_header; -/* Packet IP version 4 data */ +/* decoded ethernet header */ -typedef struct _INMSampled_ipv4 { +typedef struct _SFLSampled_ethernet { + uint32_t eth_len; /* The length of the MAC packet excluding + lower layer encapsulations */ + uint8_t src_mac[8]; /* 6 bytes + 2 pad */ + uint8_t dst_mac[8]; + uint32_t eth_type; +} SFLSampled_ethernet; + +/* decoded IP version 4 header */ + +typedef struct _SFLSampled_ipv4 { uint32_t length; /* The length of the IP packet excluding lower layer encapsulations */ uint32_t protocol; /* IP Protocol type (for example, TCP = 6, UDP = 17) */ - struct in_addr src_ip; /* Source IP Address */ - struct in_addr dst_ip; /* Destination IP Address */ + SFLIPv4 src_ip; /* Source IP Address */ + SFLIPv4 dst_ip; /* Destination IP Address */ uint32_t src_port; /* TCP/UDP source port number or equivalent */ uint32_t dst_port; /* TCP/UDP destination port number or equivalent */ uint32_t tcp_flags; /* TCP flags */ uint32_t tos; /* IP type of service */ -} INMSampled_ipv4; +} SFLSampled_ipv4; -/* Packet IP version 6 data */ +/* decoded IP version 6 data */ -typedef struct _INMSampled_ipv6 { +typedef struct _SFLSampled_ipv6 { uint32_t length; /* The length of the IP packet excluding lower layer encapsulations */ uint32_t protocol; /* IP Protocol type (for example, TCP = 6, UDP = 17) */ - struct in6_addr src_ip; /* Source IP Address */ - struct in6_addr dst_ip; /* Destination IP Address */ + SFLIPv6 src_ip; /* Source IP Address */ + SFLIPv6 dst_ip; /* Destination IP Address */ uint32_t src_port; /* TCP/UDP source port number or equivalent */ uint32_t dst_port; /* TCP/UDP destination port number or equivalent */ uint32_t tcp_flags; /* TCP flags */ - uint32_t tos; /* IP type of service */ -} INMSampled_ipv6; - - -/* Packet data */ - -enum INMPacket_information_type { - INMPACKETTYPE_HEADER = 1, /* Packet headers are sampled */ - INMPACKETTYPE_IPV4 = 2, /* IP version 4 data */ - INMPACKETTYPE_IPV6 = 3 /* IP version 4 data */ -}; - -typedef union _INMPacket_data_type { - INMSampled_header header; - INMSampled_ipv4 ipv4; - INMSampled_ipv6 ipv6; -} INMPacket_data_type; + uint32_t priority; /* IP priority */ +} SFLSampled_ipv6; /* Extended data types */ /* Extended switch data */ -typedef struct _INMExtended_switch { +typedef struct _SFLExtended_switch { uint32_t src_vlan; /* The 802.1Q VLAN id of incomming frame */ uint32_t src_priority; /* The 802.1p priority */ uint32_t dst_vlan; /* The 802.1Q VLAN id of outgoing frame */ uint32_t dst_priority; /* The 802.1p priority */ -} INMExtended_switch; +} SFLExtended_switch; /* Extended router data */ -typedef struct _INMExtended_router { - INMAddress nexthop; /* IP address of next hop router */ +typedef struct _SFLExtended_router { + SFLAddress nexthop; /* IP address of next hop router */ uint32_t src_mask; /* Source address prefix mask bits */ uint32_t dst_mask; /* Destination address prefix mask bits */ -} INMExtended_router; +} SFLExtended_router; /* Extended gateway data */ - -enum INMExtended_as_path_segment_type { - INMEXTENDED_AS_SET = 1, /* Unordered set of ASs */ - INMEXTENDED_AS_SEQUENCE = 2 /* Ordered sequence of ASs */ +enum SFLExtended_as_path_segment_type { + SFLEXTENDED_AS_SET = 1, /* Unordered set of ASs */ + SFLEXTENDED_AS_SEQUENCE = 2 /* Ordered sequence of ASs */ }; - -typedef struct _INMExtended_as_path_segment { - uint32_t type; /* enum INMExtended_as_path_segment_type */ + +typedef struct _SFLExtended_as_path_segment { + uint32_t type; /* enum SFLExtended_as_path_segment_type */ uint32_t length; /* number of AS numbers in set/sequence */ union { uint32_t *set; uint32_t *seq; } as; -} INMExtended_as_path_segment; +} SFLExtended_as_path_segment; -/* note: the INMExtended_gateway structure has changed between v2 and v4. - Here is the old version first... */ - -typedef struct _INMExtended_gateway_v2 { - uint32_t as; /* AS number for this gateway */ - uint32_t src_as; /* AS number of source (origin) */ - uint32_t src_peer_as; /* AS number of source peer */ - uint32_t dst_as_path_length; /* number of AS numbers in path */ - uint32_t *dst_as_path; -} INMExtended_gateway_v2; - -/* now here is the new version... */ - -typedef struct _INMExtended_gateway_v4 { +typedef struct _SFLExtended_gateway { + SFLAddress nexthop; /* Address of the border router that should + be used for the destination network */ uint32_t as; /* AS number for this gateway */ uint32_t src_as; /* AS number of source (origin) */ uint32_t src_peer_as; /* AS number of source peer */ uint32_t dst_as_path_segments; /* number of segments in path */ - INMExtended_as_path_segment *dst_as_path; /* list of seqs or sets */ + SFLExtended_as_path_segment *dst_as_path; /* list of seqs or sets */ uint32_t communities_length; /* number of communities */ uint32_t *communities; /* set of communities */ uint32_t localpref; /* LocalPref associated with this route */ -} INMExtended_gateway_v4; +} SFLExtended_gateway; + +typedef struct _SFLString { + uint32_t len; + char *str; +} SFLString; /* Extended user data */ -typedef struct _INMExtended_user { - uint32_t src_user_len; - char *src_user; - uint32_t dst_user_len; - char *dst_user; -} INMExtended_user; -enum INMExtended_url_direction { - INMEXTENDED_URL_SRC = 1, /* URL is associated with source address */ - INMEXTENDED_URL_DST = 2 /* URL is associated with destination address */ + +typedef struct _SFLExtended_user { + uint32_t src_charset; /* MIBEnum value of character set used to encode a string - See RFC 2978 + Where possible UTF-8 encoding (MIBEnum=106) should be used. A value + of zero indicates an unknown encoding. */ + SFLString src_user; + uint32_t dst_charset; + SFLString dst_user; +} SFLExtended_user; + +/* Extended URL data */ + +enum SFLExtended_url_direction { + SFLEXTENDED_URL_SRC = 1, /* URL is associated with source address */ + SFLEXTENDED_URL_DST = 2 /* URL is associated with destination address */ }; -typedef struct _INMExtended_url { - uint32_t direction; /* enum INMExtended_url_direction */ - uint32_t url_len; - char *url; -} INMExtended_url; +typedef struct _SFLExtended_url { + uint32_t direction; /* enum SFLExtended_url_direction */ + SFLString url; /* URL associated with the packet flow. + Must be URL encoded */ + SFLString host; /* The host field from the HTTP header */ +} SFLExtended_url; -/* Extended data */ +/* Extended MPLS data */ -enum INMExtended_information_type { - INMEXTENDED_SWITCH = 1, /* Extended switch information */ - INMEXTENDED_ROUTER = 2, /* Extended router information */ - INMEXTENDED_GATEWAY = 3, /* Extended gateway router information */ - INMEXTENDED_USER = 4, /* Extended TACAS/RADIUS user information */ - INMEXTENDED_URL = 5 /* Extended URL information */ +typedef struct _SFLLabelStack { + uint32_t depth; + uint32_t *stack; /* first entry is top of stack - see RFC 3032 for encoding */ +} SFLLabelStack; + +typedef struct _SFLExtended_mpls { + SFLAddress nextHop; /* Address of the next hop */ + SFLLabelStack in_stack; + SFLLabelStack out_stack; +} SFLExtended_mpls; + + /* Extended NAT data + Packet header records report addresses as seen at the sFlowDataSource. + The extended_nat structure reports on translated source and/or destination + addesses for this packet. If an address was not translated it should + be equal to that reported for the header. */ + +typedef struct _SFLExtended_nat { + SFLAddress src; /* Source address */ + SFLAddress dst; /* Destination address */ +} SFLExtended_nat; + +typedef struct _SFLExtended_nat_port { + uint32_t src_port; + uint32_t dst_port; +} SFLExtended_nat_port; + + /* additional Extended MPLS stucts */ + +typedef struct _SFLExtended_mpls_tunnel { + SFLString tunnel_lsp_name; /* Tunnel name */ + uint32_t tunnel_id; /* Tunnel ID */ + uint32_t tunnel_cos; /* Tunnel COS value */ +} SFLExtended_mpls_tunnel; + +typedef struct _SFLExtended_mpls_vc { + SFLString vc_instance_name; /* VC instance name */ + uint32_t vll_vc_id; /* VLL/VC instance ID */ + uint32_t vc_label_cos; /* VC Label COS value */ +} SFLExtended_mpls_vc; + +/* Extended MPLS FEC + - Definitions from MPLS-FTN-STD-MIB mplsFTNTable */ + +typedef struct _SFLExtended_mpls_FTN { + SFLString mplsFTNDescr; + uint32_t mplsFTNMask; +} SFLExtended_mpls_FTN; + +/* Extended MPLS LVP FEC + - Definition from MPLS-LDP-STD-MIB mplsFecTable + Note: mplsFecAddrType, mplsFecAddr information available + from packet header */ + +typedef struct _SFLExtended_mpls_LDP_FEC { + uint32_t mplsFecAddrPrefixLength; +} SFLExtended_mpls_LDP_FEC; + +/* Extended VLAN tunnel information + Record outer VLAN encapsulations that have + been stripped. extended_vlantunnel information + should only be reported if all the following conditions are satisfied: + 1. The packet has nested vlan tags, AND + 2. The reporting device is VLAN aware, AND + 3. One or more VLAN tags have been stripped, either + because they represent proprietary encapsulations, or + because switch hardware automatically strips the outer VLAN + encapsulation. + Reporting extended_vlantunnel information is not a substitute for + reporting extended_switch information. extended_switch data must + always be reported to describe the ingress/egress VLAN information + for the packet. The extended_vlantunnel information only applies to + nested VLAN tags, and then only when one or more tags has been + stripped. */ + +typedef SFLLabelStack SFLVlanStack; +typedef struct _SFLExtended_vlan_tunnel { + SFLVlanStack stack; /* List of stripped 802.1Q TPID/TCI layers. Each + TPID,TCI pair is represented as a single 32 bit + integer. Layers listed from outermost to + innermost. */ +} SFLExtended_vlan_tunnel; + +/* + ////////////////// IEEE 802.11 Extension structs //////////////////// + + The 4-byte cipher_suite identifier follows the format of the cipher suite + selector value from the 802.11i (TKIP/CCMP amendment to 802.11i) + The most significant three bytes contain the OUI and the least significant + byte contains the Suite Type. + + The currently assigned values are: + + OUI |Suite type |Meaning + ---------------------------------------------------- + 00-0F-AC | 0 | Use group cipher suite + 00-0F-AC | 1 | WEP-40 + 00-0F-AC | 2 | TKIP + 00-0F-AC | 3 | Reserved + 00-0F-AC | 4 | CCMP + 00-0F-AC | 5 | WEP-104 + 00-0F-AC | 6-255 | Reserved + Vendor OUI | Other | Vendor specific + Other | Any | Reserved + ---------------------------------------------------- +*/ + +typedef uint32_t SFLCipherSuite; + +/* Extended wifi Payload + Used to provide unencrypted version of 802.11 MAC data. If the + MAC data is not encrypted then the agent must not include an + extended_wifi_payload structure. + If 802.11 MAC data is encrypted then the sampled_header structure + should only contain the MAC header (since encrypted data cannot + be decoded by the sFlow receiver). If the sFlow agent has access to + the unencrypted payload, it should add an extended_wifi_payload + structure containing the unencrypted data bytes from the sampled + packet header, starting at the beginning of the 802.2 LLC and not + including any trailing encryption footers. */ +/* opaque = flow_data; enterprise = 0; format = 1013 */ + +typedef struct _SFLExtended_wifi_payload { + SFLCipherSuite cipherSuite; + SFLSampled_header header; +} SFLExtended_wifi_payload; + +typedef enum { + IEEE80211_A=1, + IEEE80211_B=2, + IEEE80211_G=3, + IEEE80211_N=4, +} SFL_IEEE80211_version; + +/* opaque = flow_data; enterprise = 0; format = 1014 */ + +#define SFL_MAX_SSID_LEN 256 + +typedef struct _SFLExtended_wifi_rx { + uint32_t ssid_len; + char *ssid; + char bssid[6]; /* BSSID */ + SFL_IEEE80211_version version; /* version */ + uint32_t channel; /* channel number */ + uint64_t speed; + uint32_t rsni; /* received signal to noise ratio, see dot11FrameRprtRSNI */ + uint32_t rcpi; /* received channel power, see dot11FrameRprtLastRCPI */ + uint32_t packet_duration_us; /* amount of time that the successfully received pkt occupied RF medium.*/ +} SFLExtended_wifi_rx; + +/* opaque = flow_data; enterprise = 0; format = 1015 */ + +typedef struct _SFLExtended_wifi_tx { + uint32_t ssid_len; + char *ssid; /* SSID string */ + char bssid[6]; /* BSSID */ + SFL_IEEE80211_version version; /* version */ + uint32_t transmissions; /* number of transmissions for sampled + packet. + 0 = unkown + 1 = packet was successfully transmitted + on first attempt + n > 1 = n - 1 retransmissions */ + uint32_t packet_duration_us; /* amount of time that the successfully + transmitted packet occupied the + RF medium */ + uint32_t retrans_duration_us; /* amount of time that failed transmission + attempts occupied the RF medium */ + uint32_t channel; /* channel number */ + uint64_t speed; + uint32_t power_mw; /* transmit power in mW. */ +} SFLExtended_wifi_tx; + +/* Extended 802.11 Aggregation Data */ +/* A flow_sample of an aggregated frame would consist of a packet + header for the whole frame + any other extended structures that + apply (e.g. 80211_tx/rx etc.) + an extended_wifi_aggregation + structure which would contain an array of pdu structures (one + for each PDU in the aggregate). A pdu is simply an array of + flow records, in the simplest case a packet header for each PDU, + but extended structures could be included as well. */ + +/* opaque = flow_data; enterprise = 0; format = 1016 */ + +struct _SFLFlow_Pdu; /* forward decl */ + +typedef struct _SFLExtended_aggregation { + uint32_t num_pdus; + struct _SFFlow_Pdu *pdus; +} SFLExtended_aggregation; +/* TCP connection state */ +/* Based on struct tcp_info in /usr/include/linux/tcp.h */ +/* opaque = flow_data; enterprise=0; format=2209 */ + +typedef enum { + PKTDIR_unknown = 0, + PKTDIR_received = 1, + PKTDIR_sent = 2 +} EnumPktDirection; + +typedef struct _SFLExtended_TCP_info { + uint32_t dirn; /* EnumPktDirection: Sampled packet direction */ + uint32_t snd_mss; /* Cached effective mss, not including SACKS */ + uint32_t rcv_mss; /* Max. recv. segment size */ + uint32_t unacked; /* Packets which are "in flight" */ + uint32_t lost; /* Lost packets */ + uint32_t retrans; /* Retransmitted packets */ + uint32_t pmtu; /* Last pmtu seen by socket */ + uint32_t rtt; /* smoothed RTT (microseconds) */ + uint32_t rttvar; /* RTT variance (microseconds) */ + uint32_t snd_cwnd; /* Sending congestion window */ + uint32_t reordering; /* Reordering */ + uint32_t min_rtt; /* Minimum RTT (microseconds) */ +} SFLExtended_TCP_info; + +#define XDRSIZ_SFLEXTENDED_TCP_INFO 48 + +/* Extended socket information, + Must be filled in for all application transactions associated with a network socket + Omit if transaction associated with non-network IPC */ + +/* IPv4 Socket */ +/* opaque = flow_data; enterprise = 0; format = 2100 */ +typedef struct _SFLExtended_socket_ipv4 { + uint32_t protocol; /* IP Protocol (e.g. TCP = 6, UDP = 17) */ + SFLIPv4 local_ip; /* local IP address */ + SFLIPv4 remote_ip; /* remote IP address */ + uint32_t local_port; /* TCP/UDP local port number or equivalent */ + uint32_t remote_port; /* TCP/UDP remote port number of equivalent */ +} SFLExtended_socket_ipv4; + +#define XDRSIZ_SFLEXTENDED_SOCKET4 20 + +/* IPv6 Socket */ +/* opaque = flow_data; enterprise = 0; format = 2101 */ +typedef struct _SFLExtended_socket_ipv6 { + uint32_t protocol; /* IP Protocol (e.g. TCP = 6, UDP = 17) */ + SFLIPv6 local_ip; /* local IP address */ + SFLIPv6 remote_ip; /* remote IP address */ + uint32_t local_port; /* TCP/UDP local port number or equivalent */ + uint32_t remote_port; /* TCP/UDP remote port number of equivalent */ +} SFLExtended_socket_ipv6; + +#define XDRSIZ_SFLEXTENDED_SOCKET6 44 + +typedef enum { + MEMCACHE_PROT_OTHER = 0, + MEMCACHE_PROT_ASCII = 1, + MEMCACHE_PROT_BINARY = 2 +} SFLMemcache_prot; + +typedef enum { + MEMCACHE_CMD_OTHER = 0, + MEMCACHE_CMD_SET = 1, + MEMCACHE_CMD_ADD = 2, + MEMCACHE_CMD_REPLACE = 3, + MEMCACHE_CMD_APPEND = 4, + MEMCACHE_CMD_PREPEND = 5, + MEMCACHE_CMD_CAS = 6, + MEMCACHE_CMD_GET = 7, + MEMCACHE_CMD_GETS = 8, + MEMCACHE_CMD_INCR = 9, + MEMCACHE_CMD_DECR = 10, + MEMCACHE_CMD_DELETE = 11, + MEMCACHE_CMD_STATS = 12, + MEMCACHE_CMD_FLUSH = 13, + MEMCACHE_CMD_VERSION = 14, + MEMCACHE_CMD_QUIT = 15, + MEMCACHE_CMD_TOUCH = 16 +} SFLMemcache_cmd; + +enum SFLMemcache_operation_status { + MEMCACHE_OP_UNKNOWN = 0, + MEMCACHE_OP_OK = 1, + MEMCACHE_OP_ERROR = 2, + MEMCACHE_OP_CLIENT_ERROR = 3, + MEMCACHE_OP_SERVER_ERROR = 4, + MEMCACHE_OP_STORED = 5, + MEMCACHE_OP_NOT_STORED = 6, + MEMCACHE_OP_EXISTS = 7, + MEMCACHE_OP_NOT_FOUND = 8, + MEMCACHE_OP_DELETED = 9 }; -/* Format of a single sample */ +#define SFL_MAX_MEMCACHE_KEY 255 -typedef struct _INMFlow_sample { +typedef struct _SFLSampled_memcache { + uint32_t protocol; /* SFLMemcache_prot */ + uint32_t command; /* SFLMemcache_cmd */ + SFLString key; /* up to 255 chars */ + uint32_t nkeys; + uint32_t value_bytes; + uint32_t duration_uS; + uint32_t status; /* SFLMemcache_operation_status */ +} SFLSampled_memcache; + +typedef enum { + SFHTTP_OTHER = 0, + SFHTTP_OPTIONS = 1, + SFHTTP_GET = 2, + SFHTTP_HEAD = 3, + SFHTTP_POST = 4, + SFHTTP_PUT = 5, + SFHTTP_DELETE = 6, + SFHTTP_TRACE = 7, + SFHTTP_CONNECT = 8 +} SFLHTTP_method; + +#define SFL_MAX_HTTP_URI 255 +#define SFL_MAX_HTTP_HOST 64 +#define SFL_MAX_HTTP_REFERRER 255 +#define SFL_MAX_HTTP_USERAGENT 128 +#define SFL_MAX_HTTP_XFF 64 +#define SFL_MAX_HTTP_AUTHUSER 32 +#define SFL_MAX_HTTP_MIMETYPE 64 + +typedef struct _SFLSampled_http { + SFLHTTP_method method; + uint32_t protocol; /* 1.1=1001 */ + SFLString uri; /* URI exactly as it came from the client (up to 255 bytes) */ + SFLString host; /* Host value from request header (<= 64 bytes) */ + SFLString referrer; /* Referer value from request header (<=255 bytes) */ + SFLString useragent; /* User-Agent value from request header (<= 128 bytes)*/ + SFLString xff; /* X-Forwarded-For value from request header (<= 64 bytes)*/ + SFLString authuser; /* RFC 1413 identity of user (<=32 bytes)*/ + SFLString mimetype; /* Mime-Type (<=64 bytes) */ + uint64_t req_bytes; /* Content-Length of request */ + uint64_t resp_bytes; /* Content-Length of response */ + uint32_t uS; /* duration of the operation (microseconds) */ + uint32_t status; /* HTTP status code */ +} SFLSampled_http; + + +typedef enum { + SFLAPP_SUCCESS = 0, + SFLAPP_OTHER = 1, + SFLAPP_TIMEOUT = 2, + SFLAPP_INTERNAL_ERROR = 3, + SFLAPP_BAD_REQUEST = 4, + SFLAPP_FORBIDDEN = 5, + SFLAPP_TOO_LARGE = 6, + SFLAPP_NOT_IMPLEMENTED = 7, + SFLAPP_NOT_FOUND = 8, + SFLAPP_UNAVAILABLE = 9, + SFLAPP_UNAUTHORIZED = 10, + SFLAPP_NUM_STATUS_CODES +} EnumSFLAPPStatus; + + static const char *SFL_APP_STATUS_names[] = { "SUCCESS", + "OTHER", + "TIMEOUT", + "INTERNAL_ERROR", + "BAD_REQUEST", + "FORBIDDEN", + "TOO_LARGE", + "NOT_IMPLEMENTED", + "NOT_FOUND", + "UNAVAILABLE", + "UNATHORIZED" }; + +/* Operation context */ +typedef struct { + SFLString application; + SFLString operation; /* type of operation (e.g. authorization, payment) */ + SFLString attributes; /* specific attributes associated operation */ +} SFLSampled_APP_CTXT; + +#define SFLAPP_MAX_APPLICATION_LEN 32 +#define SFLAPP_MAX_OPERATION_LEN 32 +#define SFLAPP_MAX_ATTRIBUTES_LEN 255 + +/* Sampled Enterprise Operation */ +/* opaque = flow_data; enterprise = 0; format = 2202 */ +typedef struct { + SFLSampled_APP_CTXT context; /* attributes describing the operation */ + SFLString status_descr; /* additional text describing status (e.g. "unknown client") */ + uint64_t req_bytes; /* size of request body (exclude headers) */ + uint64_t resp_bytes; /* size of response body (exclude headers) */ + uint32_t duration_uS; /* duration of the operation (microseconds) */ + EnumSFLAPPStatus status; /* status code */ +} SFLSampled_APP; + +#define SFLAPP_MAX_STATUS_LEN 32 + +typedef struct { + SFLString actor; +} SFLSampled_APP_ACTOR; + +#define SFLAPP_MAX_ACTOR_LEN 64 + +typedef struct _SFLExtended_vni { + uint32_t vni; /* virtual network identifier */ +} SFLExtended_vni; + +typedef struct _SFLExtended_decap { + uint32_t innerHeaderOffset; +} SFLExtended_decap; + +enum SFLFlow_type_tag { + /* enterprise = 0, format = ... */ + SFLFLOW_HEADER = 1, /* Packet headers are sampled */ + SFLFLOW_ETHERNET = 2, /* MAC layer information */ + SFLFLOW_IPV4 = 3, /* IP version 4 data */ + SFLFLOW_IPV6 = 4, /* IP version 6 data */ + SFLFLOW_EX_SWITCH = 1001, /* Extended switch information */ + SFLFLOW_EX_ROUTER = 1002, /* Extended router information */ + SFLFLOW_EX_GATEWAY = 1003, /* Extended gateway router information */ + SFLFLOW_EX_USER = 1004, /* Extended TACAS/RADIUS user information */ + SFLFLOW_EX_URL = 1005, /* Extended URL information */ + SFLFLOW_EX_MPLS = 1006, /* Extended MPLS information */ + SFLFLOW_EX_NAT = 1007, /* Extended NAT information */ + SFLFLOW_EX_MPLS_TUNNEL = 1008, /* additional MPLS information */ + SFLFLOW_EX_MPLS_VC = 1009, + SFLFLOW_EX_MPLS_FTN = 1010, + SFLFLOW_EX_MPLS_LDP_FEC = 1011, + SFLFLOW_EX_VLAN_TUNNEL = 1012, /* VLAN stack */ + SFLFLOW_EX_80211_PAYLOAD = 1013, + SFLFLOW_EX_80211_RX = 1014, + SFLFLOW_EX_80211_TX = 1015, + SFLFLOW_EX_AGGREGATION = 1016, + SFLFLOW_EX_NAT_PORT = 1020, /* Extended NAT port information */ + SFLFLOW_EX_L2_TUNNEL_OUT = 1021, /* http://sflow.org/sflow_tunnels.txt */ + SFLFLOW_EX_L2_TUNNEL_IN = 1022, + SFLFLOW_EX_IPV4_TUNNEL_OUT = 1023, + SFLFLOW_EX_IPV4_TUNNEL_IN = 1024, + SFLFLOW_EX_IPV6_TUNNEL_OUT = 1025, + SFLFLOW_EX_IPV6_TUNNEL_IN = 1026, + SFLFLOW_EX_DECAP_OUT = 1027, + SFLFLOW_EX_DECAP_IN = 1028, + SFLFLOW_EX_VNI_OUT = 1029, + SFLFLOW_EX_VNI_IN = 1030, + SFLFLOW_EX_SOCKET4 = 2100, + SFLFLOW_EX_SOCKET6 = 2101, + SFLFLOW_EX_PROXYSOCKET4 = 2102, + SFLFLOW_EX_PROXYSOCKET6 = 2103, + SFLFLOW_MEMCACHE = 2200, + SFLFLOW_HTTP = 2201, + SFLFLOW_APP = 2202, /* transaction sample */ + SFLFLOW_APP_CTXT = 2203, /* enclosing server context */ + SFLFLOW_APP_ACTOR_INIT = 2204, /* initiator */ + SFLFLOW_APP_ACTOR_TGT = 2205, /* target */ + SFLFLOW_HTTP2 = 2206, + SFLFLOW_EX_TCP_INFO = 2209, +}; + +typedef union _SFLFlow_type { + SFLSampled_header header; + SFLSampled_ethernet ethernet; + SFLSampled_ipv4 ipv4; + SFLSampled_ipv6 ipv6; + SFLSampled_memcache memcache; + SFLSampled_http http; + SFLSampled_APP app; + SFLSampled_APP_CTXT appCtxt; + SFLSampled_APP_ACTOR appActor; + SFLExtended_switch sw; + SFLExtended_router router; + SFLExtended_gateway gateway; + SFLExtended_user user; + SFLExtended_url url; + SFLExtended_mpls mpls; + SFLExtended_nat nat; + SFLExtended_nat_port nat_port; + SFLExtended_mpls_tunnel mpls_tunnel; + SFLExtended_mpls_vc mpls_vc; + SFLExtended_mpls_FTN mpls_ftn; + SFLExtended_mpls_LDP_FEC mpls_ldp_fec; + SFLExtended_vlan_tunnel vlan_tunnel; + SFLExtended_wifi_payload wifi_payload; + SFLExtended_wifi_rx wifi_rx; + SFLExtended_wifi_tx wifi_tx; + SFLExtended_aggregation aggregation; + SFLExtended_socket_ipv4 socket4; + SFLExtended_socket_ipv6 socket6; + SFLExtended_vni tunnel_vni; + SFLExtended_decap tunnel_decap; +} SFLFlow_type; + +typedef struct _SFLFlow_sample_element { + struct _SFLFlow_sample_element *nxt; + uint32_t tag; /* SFLFlow_type_tag */ + uint32_t length; + SFLFlow_type flowType; +} SFLFlow_sample_element; + +enum SFL_sample_tag { + SFLFLOW_SAMPLE = 1, /* enterprise = 0 : format = 1 */ + SFLCOUNTERS_SAMPLE = 2, /* enterprise = 0 : format = 2 */ + SFLFLOW_SAMPLE_EXPANDED = 3, /* enterprise = 0 : format = 3 */ + SFLCOUNTERS_SAMPLE_EXPANDED = 4, /* enterprise = 0 : format = 4 */ + SFLRTMETRIC = ((4300 << 12) + 1002), + SFLRTFLOW = ((4300 << 12) + 1003) +}; + +typedef struct _SFLFlow_Pdu { + struct _SFLFlow_Pdu *nxt; + uint32_t num_elements; + SFLFlow_sample_element *elements; +} SFLFlow_Pdu; + + +/* Format of a single flow sample */ + +typedef struct _SFLFlow_sample { + /* uint32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 1 */ + /* uint32_t length; */ uint32_t sequence_number; /* Incremented with each flow sample generated */ uint32_t source_id; /* fsSourceId */ @@ -327,37 +724,44 @@ typedef struct _INMFlow_sample { 0x80000000 indicates a packet sent to an unknown number of interfaces greater than 1.*/ - uint32_t packet_data_tag; /* enum INMPacket_information_type */ - INMPacket_data_type packet_data; /* Information about sampled packet */ + uint32_t num_elements; + SFLFlow_sample_element *elements; +} SFLFlow_sample; - /* in the sFlow packet spec the next field is the number of extended objects - followed by the data for each one (tagged with the type). Here we just - provide space for each one, and flags to enable them. The correct format - is then put together by the serialization code */ - int gotSwitch; - INMExtended_switch switchDevice; - int gotRouter; - INMExtended_router router; - int gotGateway; - union { - INMExtended_gateway_v2 sf_v2; /* make the version explicit so that there is */ - INMExtended_gateway_v4 sf_v4; /* less danger of mistakes when upgrading code */ - } gateway; - int gotUser; - INMExtended_user user; - int gotUrl; - INMExtended_url url; -} INMFlow_sample; + /* same thing, but the expanded version (for full 32-bit ifIndex numbers) */ + +typedef struct _SFLFlow_sample_expanded { + /* uint32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 1 */ + /* uint32_t length; */ + uint32_t sequence_number; /* Incremented with each flow sample + generated */ + uint32_t ds_class; /* EXPANDED */ + uint32_t ds_index; /* EXPANDED */ + uint32_t sampling_rate; /* fsPacketSamplingRate */ + uint32_t sample_pool; /* Total number of packets that could have been + sampled (i.e. packets skipped by sampling + process + total number of samples) */ + uint32_t drops; /* Number of times a packet was dropped due to + lack of resources */ + uint32_t inputFormat; /* EXPANDED */ + uint32_t input; /* SNMP ifIndex of input interface. + 0 if interface is not known. */ + uint32_t outputFormat; /* EXPANDED */ + uint32_t output; /* SNMP ifIndex of output interface, + 0 if interface is not known. */ + uint32_t num_elements; + SFLFlow_sample_element *elements; +} SFLFlow_sample_expanded; /* Counter types */ /* Generic interface counters - see RFC 1573, 2233 */ -typedef struct _INMIf_counters { +typedef struct _SFLIf_counters { uint32_t ifIndex; uint32_t ifType; uint64_t ifSpeed; - uint32_t ifDirection; /* Derived from MAU MIB (RFC 2239) + uint32_t ifDirection; /* Derived from MAU MIB (RFC 2668) 0 = unknown, 1 = full-duplex, 2 = half-duplex, 3 = in, 4 = out */ uint32_t ifStatus; /* bit field with the following bits assigned: @@ -377,10 +781,10 @@ typedef struct _INMIf_counters { uint32_t ifOutDiscards; uint32_t ifOutErrors; uint32_t ifPromiscuousMode; -} INMIf_counters; +} SFLIf_counters; /* Ethernet interface counters - see RFC 2358 */ -typedef struct _INMEthernet_specific_counters { +typedef struct _SFLEthernet_counters { uint32_t dot3StatsAlignmentErrors; uint32_t dot3StatsFCSErrors; uint32_t dot3StatsSingleCollisionFrames; @@ -394,21 +798,11 @@ typedef struct _INMEthernet_specific_counters { uint32_t dot3StatsFrameTooLongs; uint32_t dot3StatsInternalMacReceiveErrors; uint32_t dot3StatsSymbolErrors; -} INMEthernet_specific_counters; - -typedef struct _INMEthernet_counters { - INMIf_counters generic; - INMEthernet_specific_counters ethernet; -} INMEthernet_counters; - -/* FDDI interface counters - see RFC 1512 */ -typedef struct _INMFddi_counters { - INMIf_counters generic; -} INMFddi_counters; +} SFLEthernet_counters; /* Token ring counters - see RFC 1748 */ -typedef struct _INMTokenring_specific_counters { +typedef struct _SFLTokenring_counters { uint32_t dot5StatsLineErrors; uint32_t dot5StatsBurstErrors; uint32_t dot5StatsACErrors; @@ -427,16 +821,11 @@ typedef struct _INMTokenring_specific_counters { uint32_t dot5StatsRemoves; uint32_t dot5StatsSingles; uint32_t dot5StatsFreqErrors; -} INMTokenring_specific_counters; - -typedef struct _INMTokenring_counters { - INMIf_counters generic; - INMTokenring_specific_counters tokenring; -} INMTokenring_counters; +} SFLTokenring_counters; /* 100 BaseVG interface counters - see RFC 2020 */ -typedef struct _INMVg_specific_counters { +typedef struct _SFLVg_counters { uint32_t dot12InHighPriorityFrames; uint64_t dot12InHighPriorityOctets; uint32_t dot12InNormPriorityFrames; @@ -451,121 +840,810 @@ typedef struct _INMVg_specific_counters { uint64_t dot12HCInHighPriorityOctets; uint64_t dot12HCInNormPriorityOctets; uint64_t dot12HCOutHighPriorityOctets; -} INMVg_specific_counters; +} SFLVg_counters; -typedef struct _INMVg_counters { - INMIf_counters generic; - INMVg_specific_counters vg; -} INMVg_counters; - -/* WAN counters */ - -typedef struct _INMWan_counters { - INMIf_counters generic; -} INMWan_counters; - -typedef struct _INMVlan_counters { +typedef struct _SFLVlan_counters { uint32_t vlan_id; uint64_t octets; uint32_t ucastPkts; uint32_t multicastPkts; uint32_t broadcastPkts; uint32_t discards; -} INMVlan_counters; +} SFLVlan_counters; + +typedef struct _SFLWifi_counters { + uint32_t dot11TransmittedFragmentCount; + uint32_t dot11MulticastTransmittedFrameCount; + uint32_t dot11FailedCount; + uint32_t dot11RetryCount; + uint32_t dot11MultipleRetryCount; + uint32_t dot11FrameDuplicateCount; + uint32_t dot11RTSSuccessCount; + uint32_t dot11RTSFailureCount; + uint32_t dot11ACKFailureCount; + uint32_t dot11ReceivedFragmentCount; + uint32_t dot11MulticastReceivedFrameCount; + uint32_t dot11FCSErrorCount; + uint32_t dot11TransmittedFrameCount; + uint32_t dot11WEPUndecryptableCount; + uint32_t dot11QoSDiscardedFragmentCount; + uint32_t dot11AssociatedStationCount; + uint32_t dot11QoSCFPollsReceivedCount; + uint32_t dot11QoSCFPollsUnusedCount; + uint32_t dot11QoSCFPollsUnusableCount; + uint32_t dot11QoSCFPollsLostCount; +} SFLWifi_counters; + +/* Processor Information */ +/* opaque = counter_data; enterprise = 0; format = 1001 */ + +typedef struct _SFLProcessor_counters { + uint32_t five_sec_cpu; /* 5 second average CPU utilization */ + uint32_t one_min_cpu; /* 1 minute average CPU utilization */ + uint32_t five_min_cpu; /* 5 minute average CPU utilization */ + uint64_t total_memory; /* total memory (in bytes) */ + uint64_t free_memory; /* free memory (in bytes) */ +} SFLProcessor_counters; + +typedef struct _SFLRadio_counters { + uint32_t elapsed_time; /* elapsed time in ms */ + uint32_t on_channel_time; /* time in ms spent on channel */ + uint32_t on_channel_busy_time; /* time in ms spent on channel and busy */ +} SFLRadio_counters; + + /* host sflow */ + +enum SFLMachine_type { + SFLMT_unknown = 0, + SFLMT_other = 1, + SFLMT_x86 = 2, + SFLMT_x86_64 = 3, + SFLMT_ia64 = 4, + SFLMT_sparc = 5, + SFLMT_alpha = 6, + SFLMT_powerpc = 7, + SFLMT_m68k = 8, + SFLMT_mips = 9, + SFLMT_arm = 10, + SFLMT_hppa = 11, + SFLMT_s390 = 12 +}; + +enum SFLOS_name { + SFLOS_unknown = 0, + SFLOS_other = 1, + SFLOS_linux = 2, + SFLOS_windows = 3, + SFLOS_darwin = 4, + SFLOS_hpux = 5, + SFLOS_aix = 6, + SFLOS_dragonfly = 7, + SFLOS_freebsd = 8, + SFLOS_netbsd = 9, + SFLOS_openbsd = 10, + SFLOS_osf = 11, + SFLOS_solaris = 12 +}; + +typedef struct _SFLMacAddress { + uint8_t mac[8]; +} SFLMacAddress; + +typedef struct _SFLAdaptor { + uint32_t ifIndex; + uint32_t num_macs; + SFLMacAddress macs[1]; +} SFLAdaptor; + +typedef struct _SFLAdaptorList { + uint32_t capacity; + uint32_t num_adaptors; + SFLAdaptor **adaptors; +} SFLAdaptorList; + +typedef struct _SFLHost_parent { + uint32_t dsClass; /* sFlowDataSource class */ + uint32_t dsIndex; /* sFlowDataSource index */ +} SFLHost_parent; + + +#define SFL_MAX_HOSTNAME_LEN 64 +#define SFL_MAX_OSRELEASE_LEN 32 + +typedef struct _SFLHostId { + SFLString hostname; + uint8_t uuid[16]; + uint32_t machine_type; /* enum SFLMachine_type */ + uint32_t os_name; /* enum SFLOS_name */ + SFLString os_release; /* max len 32 bytes */ +} SFLHostId; + +typedef struct _SFLHost_nio_counters { + uint64_t bytes_in; + uint32_t pkts_in; + uint32_t errs_in; + uint32_t drops_in; + uint64_t bytes_out; + uint32_t pkts_out; + uint32_t errs_out; + uint32_t drops_out; +} SFLHost_nio_counters; + +typedef struct _SFLHost_cpu_counters { + float load_one; /* 1 minute load avg. */ + float load_five; /* 5 minute load avg. */ + float load_fifteen; /* 15 minute load avg. */ + uint32_t proc_run; /* running threads */ + uint32_t proc_total; /* total threads */ + uint32_t cpu_num; /* # CPU cores */ + uint32_t cpu_speed; /* speed in MHz of CPU */ + uint32_t uptime; /* seconds since last reboot */ + uint32_t cpu_user; /* time executing in user mode processes (ms) */ + uint32_t cpu_nice; /* time executing niced processs (ms) */ + uint32_t cpu_system; /* time executing kernel mode processes (ms) */ + uint32_t cpu_idle; /* idle time (ms) */ + uint32_t cpu_wio; /* time waiting for I/O to complete (ms) */ + uint32_t cpu_intr; /* time servicing interrupts (ms) */ + uint32_t cpu_sintr; /* time servicing softirqs (ms) */ + uint32_t interrupts; /* interrupt count */ + uint32_t contexts; /* context switch count */ + uint32_t cpu_steal; /* time spent in other OS instances (virtual env) (ms) */ + uint32_t cpu_guest; /* time spent running vcpu for guest OS */ + uint32_t cpu_guest_nice; /* time spent running vcpu for "niced" guest OS */ +} SFLHost_cpu_counters; + +typedef struct _SFLHost_mem_counters { + uint64_t mem_total; /* total bytes */ + uint64_t mem_free; /* free bytes */ + uint64_t mem_shared; /* shared bytes */ + uint64_t mem_buffers; /* buffers bytes */ + uint64_t mem_cached; /* cached bytes */ + uint64_t swap_total; /* swap total bytes */ + uint64_t swap_free; /* swap free bytes */ + uint32_t page_in; /* page in count */ + uint32_t page_out; /* page out count */ + uint32_t swap_in; /* swap in count */ + uint32_t swap_out; /* swap out count */ +} SFLHost_mem_counters; + +typedef struct _SFLHost_dsk_counters { + uint64_t disk_total; + uint64_t disk_free; + uint32_t part_max_used; /* as percent * 100, so 100==1% */ + uint32_t reads; /* reads issued */ + uint64_t bytes_read; /* bytes read */ + uint32_t read_time; /* read time (ms) */ + uint32_t writes; /* writes completed */ + uint64_t bytes_written; /* bytes written */ + uint32_t write_time; /* write time (ms) */ +} SFLHost_dsk_counters; + +/* Virtual Node Statistics */ +/* opaque = counter_data; enterprise = 0; format = 2100 */ + +typedef struct _SFLHost_vrt_node_counters { + uint32_t mhz; /* expected CPU frequency */ + uint32_t cpus; /* the number of active CPUs */ + uint64_t memory; /* memory size in bytes */ + uint64_t memory_free; /* unassigned memory in bytes */ + uint32_t num_domains; /* number of active domains */ +} SFLHost_vrt_node_counters; + +/* Virtual Domain Statistics */ +/* opaque = counter_data; enterprise = 0; format = 2101 */ + +/* virDomainState imported from libvirt.h */ +enum SFLVirDomainState { + SFL_VIR_DOMAIN_NOSTATE = 0, /* no state */ + SFL_VIR_DOMAIN_RUNNING = 1, /* the domain is running */ + SFL_VIR_DOMAIN_BLOCKED = 2, /* the domain is blocked on resource */ + SFL_VIR_DOMAIN_PAUSED = 3, /* the domain is paused by user */ + SFL_VIR_DOMAIN_SHUTDOWN= 4, /* the domain is being shut down */ + SFL_VIR_DOMAIN_SHUTOFF = 5, /* the domain is shut off */ + SFL_VIR_DOMAIN_CRASHED = 6 /* the domain is crashed */ +}; + +typedef struct _SFLHost_vrt_cpu_counters { + uint32_t state; /* virtDomainState */ + uint32_t cpuTime; /* the CPU time used in mS */ + uint32_t cpuCount; /* number of virtual CPUs for the domain */ +} SFLHost_vrt_cpu_counters; + +/* Virtual Domain Memory statistics */ +/* opaque = counter_data; enterprise = 0; format = 2102 */ + +typedef struct _SFLHost_vrt_mem_counters { + uint64_t memory; /* memory in bytes used by domain */ + uint64_t maxMemory; /* memory in bytes allowed */ +} SFLHost_vrt_mem_counters; + +/* Virtual Domain Disk statistics */ +/* opaque = counter_data; enterprise = 0; format = 2103 */ + +typedef struct _SFLHost_vrt_dsk_counters { + uint64_t capacity; /* logical size in bytes */ + uint64_t allocation; /* current allocation in bytes */ + uint64_t available; /* remaining free bytes */ + uint32_t rd_req; /* number of read requests */ + uint64_t rd_bytes; /* number of read bytes */ + uint32_t wr_req; /* number of write requests */ + uint64_t wr_bytes; /* number of written bytes */ + uint32_t errs; /* read/write errors */ +} SFLHost_vrt_dsk_counters; + +/* Virtual Domain Network statistics */ +/* opaque = counter_data; enterprise = 0; format = 2104 */ + +typedef struct _SFLHost_vrt_nio_counters { + uint64_t bytes_in; + uint32_t pkts_in; + uint32_t errs_in; + uint32_t drops_in; + uint64_t bytes_out; + uint32_t pkts_out; + uint32_t errs_out; + uint32_t drops_out; +} SFLHost_vrt_nio_counters; + +/* NVML statistics */ +/* opaque = counter_data; enterprise = 5703, format=1 */ +typedef struct _SFLHost_gpu_nvml { + uint32_t device_count; /* see nvmlGetDeviceCount */ + uint32_t processes; /* see nvmlDeviceGetComputeRunningProcesses */ + uint32_t gpu_time; /* total milliseconds in which one or more kernels was executing on GPU */ + uint32_t mem_time; /* total milliseconds during which global device memory was being read/written */ + uint64_t mem_total; /* bytes. see nvmlDeviceGetMemoryInfo */ + uint64_t mem_free; /* bytes. see nvmlDeviceGetMemoryInfo */ + uint32_t ecc_errors; /* see nvmlDeviceGetTotalEccErrors */ + uint32_t energy; /* mJ. see nvmlDeviceGetPowerUsage */ + uint32_t temperature; /* C. maximum across devices - see nvmlDeviceGetTemperature */ + uint32_t fan_speed; /* %. maximum across devices - see nvmlDeviceGetFanSpeed */ +} SFLHost_gpu_nvml; + +/* Broadcom switch ASIC table utilizations */ +/* opaque = counter_data; enterprise = 4413 (Broadcom); format = 3 */ +typedef struct { + uint32_t bcm_host_entries; + uint32_t bcm_host_entries_max; + uint32_t bcm_ipv4_entries; + uint32_t bcm_ipv4_entries_max; + uint32_t bcm_ipv6_entries; + uint32_t bcm_ipv6_entries_max; + uint32_t bcm_ipv4_ipv6_entries; + uint32_t bcm_ipv4_ipv6_entries_max; + uint32_t bcm_long_ipv6_entries; + uint32_t bcm_long_ipv6_entries_max; + uint32_t bcm_total_routes; + uint32_t bcm_total_routes_max; + uint32_t bcm_ecmp_nexthops; + uint32_t bcm_ecmp_nexthops_max; + uint32_t bcm_mac_entries; + uint32_t bcm_mac_entries_max; + uint32_t bcm_ipv4_neighbors; + uint32_t bcm_ipv6_neighbors; + uint32_t bcm_ipv4_routes; + uint32_t bcm_ipv6_routes; + uint32_t bcm_acl_ingress_entries; + uint32_t bcm_acl_ingress_entries_max; + uint32_t bcm_acl_ingress_counters; + uint32_t bcm_acl_ingress_counters_max; + uint32_t bcm_acl_ingress_meters; + uint32_t bcm_acl_ingress_meters_max; + uint32_t bcm_acl_ingress_slices; + uint32_t bcm_acl_ingress_slices_max; + uint32_t bcm_acl_egress_entries; + uint32_t bcm_acl_egress_entries_max; + uint32_t bcm_acl_egress_counters; + uint32_t bcm_acl_egress_counters_max; + uint32_t bcm_acl_egress_meters; + uint32_t bcm_acl_egress_meters_max; + uint32_t bcm_acl_egress_slices; + uint32_t bcm_acl_egress_slices_max; +} SFLBCM_tables; + + ///////////// TCP/UDP/ICMP from MIB-II /////////////////////// + + /* IP Group - see MIB-II */ + /* opaque = counter_data; enterprise = 0; format = 2007 */ + + typedef struct _SFLHost_IP_counters { + uint32_t ipForwarding; + uint32_t ipDefaultTTL; + uint32_t ipInReceives; + uint32_t ipInHdrErrors; + uint32_t ipInAddrErrors; + uint32_t ipForwDatagrams; + uint32_t ipInUnknownProtos; + uint32_t ipInDiscards; + uint32_t ipInDelivers; + uint32_t ipOutRequests; + uint32_t ipOutDiscards; + uint32_t ipOutNoRoutes; + uint32_t ipReasmTimeout; + uint32_t ipReasmReqds; + uint32_t ipReasmOKs; + uint32_t ipReasmFails; + uint32_t ipFragOKs; + uint32_t ipFragFails; + uint32_t ipFragCreates; + } SFLHost_IP_counters; + + /* ICMP Group - see MIB-II */ + /* opaque = counter_data; enterprise = 0; format = 2008 */ + + typedef struct _SFLHost_ICMP_counters { + uint32_t icmpInMsgs; + uint32_t icmpInErrors; + uint32_t icmpInDestUnreachs; + uint32_t icmpInTimeExcds; + uint32_t icmpInParamProbs; + uint32_t icmpInSrcQuenchs; + uint32_t icmpInRedirects; + uint32_t icmpInEchos; + uint32_t icmpInEchoReps; + uint32_t icmpInTimestamps; + uint32_t icmpInAddrMasks; + uint32_t icmpInAddrMaskReps; + uint32_t icmpOutMsgs; + uint32_t icmpOutErrors; + uint32_t icmpOutDestUnreachs; + uint32_t icmpOutTimeExcds; + uint32_t icmpOutParamProbs; + uint32_t icmpOutSrcQuenchs; + uint32_t icmpOutRedirects; + uint32_t icmpOutEchos; + uint32_t icmpOutEchoReps; + uint32_t icmpOutTimestamps; + uint32_t icmpOutTimestampReps; + uint32_t icmpOutAddrMasks; + uint32_t icmpOutAddrMaskReps; + } SFLHost_ICMP_counters; + + /* TCP Group - see MIB-II */ + /* opaque = counter_data; enterprise = 0; format = 2009 */ + + typedef struct _SFLHost_TCP_counters { + uint32_t tcpRtoAlgorithm; + uint32_t tcpRtoMin; + uint32_t tcpRtoMax; + uint32_t tcpMaxConn; + uint32_t tcpActiveOpens; + uint32_t tcpPassiveOpens; + uint32_t tcpAttemptFails; + uint32_t tcpEstabResets; + uint32_t tcpCurrEstab; + uint32_t tcpInSegs; + uint32_t tcpOutSegs; + uint32_t tcpRetransSegs; + uint32_t tcpInErrs; + uint32_t tcpOutRsts; + uint32_t tcpInCsumErrors; + } SFLHost_TCP_counters; + + /* UDP Group - see MIB-II */ + /* opaque = counter_data; enterprise = 0; format = 2010 */ + + typedef struct _SFLHost_UDP_counters { + uint32_t udpInDatagrams; + uint32_t udpNoPorts; + uint32_t udpInErrors; + uint32_t udpOutDatagrams; + uint32_t udpRcvbufErrors; + uint32_t udpSndbufErrors; + uint32_t udpInCsumErrors; + } SFLHost_UDP_counters; + + /* memcache */ + /* opaque = counter_data; enterprise = 0; format = 2204 */ + +typedef struct _SFLMemcache_counters { + uint32_t uptime; /* not in 2204 */ + uint32_t rusage_user; /* not in 2204 */ + uint32_t rusage_system; /* not in 2204 */ + uint32_t cmd_get; /* not in 2204 */ + uint32_t accepting_conns; /* not in 2204 */ + uint32_t cmd_set; + uint32_t cmd_touch; /* added for 2204 */ + uint32_t cmd_flush; + uint32_t get_hits; + uint32_t get_misses; + uint32_t delete_hits; + uint32_t delete_misses; + uint32_t incr_hits; + uint32_t incr_misses; + uint32_t decr_hits; + uint32_t decr_misses; + uint32_t cas_hits; + uint32_t cas_misses; + uint32_t cas_badval; + uint32_t auth_cmds; + uint32_t auth_errors; + uint32_t threads; + uint32_t conn_yields; + uint32_t listen_disabled_num; + uint32_t curr_connections; + uint32_t rejected_connections; /* added for 2204 */ + uint32_t total_connections; + uint32_t connection_structures; + uint32_t evictions; + uint32_t reclaimed; /* added for 2204 */ + uint32_t curr_items; + uint32_t total_items; + uint64_t bytes_read; + uint64_t bytes_written; + uint64_t bytes; + uint64_t limit_maxbytes; /* converted to 64-bit for structure 2204 */ +} SFLMemcache_counters; + + /* http */ + /* opaque = counter_data; enterprise = 0; format = 2201 */ + +typedef struct _SFLHTTP_counters { + uint32_t method_option_count; + uint32_t method_get_count; + uint32_t method_head_count; + uint32_t method_post_count; + uint32_t method_put_count; + uint32_t method_delete_count; + uint32_t method_trace_count; + uint32_t methd_connect_count; + uint32_t method_other_count; + uint32_t status_1XX_count; + uint32_t status_2XX_count; + uint32_t status_3XX_count; + uint32_t status_4XX_count; + uint32_t status_5XX_count; + uint32_t status_other_count; +} SFLHTTP_counters; + + +/* Enterprise counters */ +/* opaque = counter_data; enterprise = 0; format = 2202 */ +typedef struct _SFLAPP_counters { + SFLString application; + uint32_t status_OK; + uint32_t errors_OTHER; + uint32_t errors_TIMEOUT; + uint32_t errors_INTERNAL_ERROR; + uint32_t errors_BAD_REQUEST; + uint32_t errors_FORBIDDEN; + uint32_t errors_TOO_LARGE; + uint32_t errors_NOT_IMPLEMENTED; + uint32_t errors_NOT_FOUND; + uint32_t errors_UNAVAILABLE; + uint32_t errors_UNAUTHORIZED; +} SFLAPP_counters; + +/* Enterprise resource counters */ +/* opaque = counter_data; enterprise = 0; format = 2203 */ +typedef struct { + uint32_t user_time; /* in milliseconds */ + uint32_t system_time; /* in milliseconds */ + uint64_t mem_used; + uint64_t mem_max; + uint32_t fd_open; + uint32_t fd_max; + uint32_t conn_open; + uint32_t conn_max; +} SFLAPP_resources; + +/* Enterprise application workers */ +/* opaque = counter_data; enterprise = 0; format = 2206 */ + +typedef struct { + uint32_t workers_active; + uint32_t workers_idle; + uint32_t workers_max; + uint32_t req_delayed; + uint32_t req_dropped; +} SFLAPP_workers; + +typedef struct _SFLJVM_ID { + SFLString vm_name; + SFLString vm_vendor; + SFLString vm_version; +} SFLJVM_ID; + +#define SFLJVM_MAX_VMNAME_LEN 64 +#define SFLJVM_MAX_VENDOR_LEN 32 +#define SFLJVM_MAX_VERSION_LEN 32 + +typedef struct _SFLJMX_counters { + uint64_t hmem_initial; + uint64_t hmem_used; + uint64_t hmem_committed; + uint64_t hmem_max; + uint64_t nhmem_initial; + uint64_t nhmem_used; + uint64_t nhmem_committed; + uint64_t nhmem_max; + uint32_t gc_count; + uint32_t gc_ms; + uint32_t cls_loaded; + uint32_t cls_total; + uint32_t cls_unloaded; + uint32_t comp_ms; + uint32_t thread_live; + uint32_t thread_daemon; + uint32_t thread_started; + uint32_t fds_open; + uint32_t fds_max; +} SFLJMX_counters; + +#define XDRSIZ_JMX_COUNTERS 108 + +typedef struct _SFLVdi_counters { + uint32_t sessions_current; /* number of current sessions */ + uint32_t sessions_total; /* total sessions started */ + uint32_t sessions_duration; /* cumulative session time (in seconds) + across all sessions, such that average + session duration = sessions_duration + / sessions_total */ + uint32_t rx_bytes; /* total bytes received */ + uint32_t tx_bytes; /* total bytes sent */ + uint32_t rx_packets; /* total packet received */ + uint32_t tx_packets; /* total packets sent */ + uint32_t rx_packets_lost; /* total received packets lost */ + uint32_t tx_packets_lost; /* total sent packets lost */ + uint32_t rtt_min_ms; /* minimum round trip latency with client + across all current sessions + measured in milliseconds */ + uint32_t rtt_max_ms; /* maximum round trip latency with client + across all current sessions + measured in millisecond */ + uint32_t rtt_avg_ms; /* average round trip latency with client + across all current sessions + measured in milliseconds */ + uint32_t audio_rx_bytes; /* total bytes of audio data received */ + uint32_t audio_tx_bytes; /* total bytes of audio data sent */ + uint32_t audio_tx_limit; /* administrative limit on audio transmission + bandwidth (in bits per second) */ + uint32_t img_rx_bytes; /* total bytes of imaging data recieved */ + uint32_t img_tx_bytes; /* total bytes of imaging data sent */ + uint32_t img_frames; /* total image frames encoded */ + uint32_t img_qual_min; /* minimum image encoding quality across + current sessions, on a scale of 0 to 100 */ + uint32_t img_qual_max; /* best image encoding quality across + current sessions, on a scale of 0 to 100 */ + uint32_t img_qual_avg; /* average image encoding quality across + current sessions, on a scale of 0 to 100 */ + uint32_t usb_rx_bytes; /* total bytes of usb data received */ + uint32_t usb_tx_bytes; /* total bytes of usb data sent */ +} SFLVdi_counters; + + /* LAG Port Statistics - see IEEE8023-LAG-MIB */ + /* opaque = counter_data; enterprise = 0; format = 7 */ +typedef union _SFLLACP_portState { + uint32_t all; + struct { + uint8_t actorAdmin; + uint8_t actorOper; + uint8_t partnerAdmin; + uint8_t partnerOper; + } v; +} SFLLACP_portState; + +typedef struct _SFLLACP_counters { + uint8_t actorSystemID[8]; /* 6 bytes + 2 pad */ + uint8_t partnerSystemID[8]; /* 6 bytes + 2 pad */ + uint32_t attachedAggID; + SFLLACP_portState portState; + uint32_t LACPDUsRx; + uint32_t markerPDUsRx; + uint32_t markerResponsePDUsRx; + uint32_t unknownRx; + uint32_t illegalRx; + uint32_t LACPDUsTx; + uint32_t markerPDUsTx; + uint32_t markerResponsePDUsTx; +} SFLLACP_counters; + +#define XDRSIZ_LACP_COUNTERS 56 + +/* openflow port */ +/* opaque = counter_data; enterprise = 0; format = 1004 */ +typedef struct { + uint64_t datapath_id; + uint32_t port_no; +} SFLOFPort; + +#define XDRSIZ_OFPORT 12 + +/* port name */ +/* opaque = counter_data; enterprise = 0; format = 1005 */ +typedef struct { + SFLString portName; +} SFLPortName; + +#define SFL_MAX_PORTNAME_LEN 255 + +/* OVS datapath stats */ +typedef struct _SFLOVSDP_counters { + uint32_t n_hit; + uint32_t n_missed; + uint32_t n_lost; + uint32_t n_mask_hit; + uint32_t n_flows; + uint32_t n_masks; +} SFLOVSDP_counters; + +#define XDRSIZE_OVSDP 24 + +/* Optical SFP/QSFP metrics */ +/* opaque = counter_data; enterprise = 0; format = 10 */ + +typedef struct { + uint32_t lane_index; /* index of lane in module - starting from 1 */ + uint32_t tx_bias_current; /* microamps */ + uint32_t tx_power; /* microwatts */ + uint32_t tx_power_min; /* microwatts */ + uint32_t tx_power_max; /* microwatts */ + uint32_t tx_wavelength; /* nanometers */ + uint32_t rx_power; /* microwatts */ + uint32_t rx_power_min; /* microwatts */ + uint32_t rx_power_max; /* microwatts */ + uint32_t rx_wavelength; /* nanometers */ +} SFLLane; + +#define XDRSIZ_LANE_COUNTERS 40 + +typedef struct { + uint32_t module_id; + uint32_t module_total_lanes; /* total lanes in module */ + uint32_t module_supply_voltage; /* millivolts */ + int32_t module_temperature; /* signed - in oC / 1000 */ + uint32_t num_lanes; /* number of active lane structs to come */ + SFLLane *lanes; +} SFLSFP_counters; /* Counters data */ -enum INMCounters_version { - INMCOUNTERSVERSION_GENERIC = 1, - INMCOUNTERSVERSION_ETHERNET = 2, - INMCOUNTERSVERSION_TOKENRING = 3, - INMCOUNTERSVERSION_FDDI = 4, - INMCOUNTERSVERSION_VG = 5, - INMCOUNTERSVERSION_WAN = 6, - INMCOUNTERSVERSION_VLAN = 7 +enum SFLCounters_type_tag { + /* enterprise = 0, format = ... */ + SFLCOUNTERS_GENERIC = 1, + SFLCOUNTERS_ETHERNET = 2, + SFLCOUNTERS_TOKENRING = 3, + SFLCOUNTERS_VG = 4, + SFLCOUNTERS_VLAN = 5, + SFLCOUNTERS_80211 = 6, + SFLCOUNTERS_LACP = 7, + SFLCOUNTERS_SFP = 10, + SFLCOUNTERS_PROCESSOR = 1001, + SFLCOUNTERS_RADIO = 1002, + SFLCOUNTERS_OFPORT = 1004, + SFLCOUNTERS_PORTNAME = 1005, + SFLCOUNTERS_HOST_HID = 2000, /* host id */ + SFLCOUNTERS_ADAPTORS = 2001, /* host adaptors */ + SFLCOUNTERS_HOST_PAR = 2002, /* host parent */ + SFLCOUNTERS_HOST_CPU = 2003, /* host cpu */ + SFLCOUNTERS_HOST_MEM = 2004, /* host memory */ + SFLCOUNTERS_HOST_DSK = 2005, /* host storage I/O */ + SFLCOUNTERS_HOST_NIO = 2006, /* host network I/O */ + SFLCOUNTERS_HOST_IP = 2007, + SFLCOUNTERS_HOST_ICMP = 2008, + SFLCOUNTERS_HOST_TCP = 2009, + SFLCOUNTERS_HOST_UDP = 2010, + SFLCOUNTERS_HOST_VRT_NODE = 2100, /* host virt node */ + SFLCOUNTERS_HOST_VRT_CPU = 2101, /* host virt cpu */ + SFLCOUNTERS_HOST_VRT_MEM = 2102, /* host virt mem */ + SFLCOUNTERS_HOST_VRT_DSK = 2103, /* host virt storage */ + SFLCOUNTERS_HOST_VRT_NIO = 2104, /* host virt network I/O */ + SFLCOUNTERS_JVM = 2105, /* java runtime */ + SFLCOUNTERS_JMX = 2106, /* java JMX stats */ + SFLCOUNTERS_MEMCACHE = 2200, /* memcached (deprecated) */ + SFLCOUNTERS_HTTP = 2201, /* http */ + SFLCOUNTERS_APP = 2202, + SFLCOUNTERS_APP_RESOURCE = 2203, + SFLCOUNTERS_MEMCACHE2 = 2204, /* memcached */ + SFLCOUNTERS_VDI = 2205, + SFLCOUNTERS_APP_WORKERS = 2206, + SFLCOUNTERS_OVSDP = 2207, + SFLCOUNTERS_HOST_GPU_NVML = (5703 << 12) + 1, /* = 23359489 */ + SFLCOUNTERS_BCM_TABLES = (4413 << 12) + 3, }; -typedef union _INMCounters_type { - INMIf_counters generic; - INMEthernet_counters ethernet; - INMTokenring_counters tokenring; - INMFddi_counters fddi; - INMVg_counters vg; - INMWan_counters wan; - INMVlan_counters vlan; -} INMCounters_type; +typedef union _SFLCounters_type { + SFLIf_counters generic; + SFLEthernet_counters ethernet; + SFLTokenring_counters tokenring; + SFLVg_counters vg; + SFLVlan_counters vlan; + SFLWifi_counters wifi; + SFLProcessor_counters processor; + SFLRadio_counters radio; + SFLHostId hostId; + SFLAdaptorList *adaptors; + SFLHost_parent host_par; + SFLHost_cpu_counters host_cpu; + SFLHost_mem_counters host_mem; + SFLHost_dsk_counters host_dsk; + SFLHost_nio_counters host_nio; + SFLHost_IP_counters host_ip; + SFLHost_ICMP_counters host_icmp; + SFLHost_TCP_counters host_tcp; + SFLHost_UDP_counters host_udp; + SFLHost_vrt_node_counters host_vrt_node; + SFLHost_vrt_cpu_counters host_vrt_cpu; + SFLHost_vrt_mem_counters host_vrt_mem; + SFLHost_vrt_dsk_counters host_vrt_dsk; + SFLHost_vrt_nio_counters host_vrt_nio; + SFLHost_gpu_nvml host_gpu_nvml; + SFLBCM_tables bcm_tables; + SFLMemcache_counters memcache; + SFLHTTP_counters http; + SFLJVM_ID jvm; + SFLJMX_counters jmx; + SFLAPP_counters app; + SFLAPP_resources appResources; + SFLAPP_workers appWorkers; + SFLVdi_counters vdi; + SFLLACP_counters lacp; + SFLPortName portName; + SFLSFP_counters sfp; + SFLOVSDP_counters ovsdp; +} SFLCounters_type; -typedef struct _INMCounters_sample_hdr { +typedef struct _SFLCounters_sample_element { + struct _SFLCounters_sample_element *nxt; /* linked list */ + uint32_t tag; /* SFLCounters_type_tag */ + uint32_t length; + SFLCounters_type counterBlock; +} SFLCounters_sample_element; + +typedef struct _SFLCounters_sample { + /* uint32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 2 */ + /* uint32_t length; */ uint32_t sequence_number; /* Incremented with each counters sample generated by this source_id */ uint32_t source_id; /* fsSourceId */ - uint32_t sampling_interval; /* fsCounterSamplingInterval */ -} INMCounters_sample_hdr; + uint32_t num_elements; + SFLCounters_sample_element *elements; +} SFLCounters_sample; -typedef struct _INMCounters_sample { - INMCounters_sample_hdr hdr; - uint32_t counters_type_tag; /* Enum INMCounters_version */ - INMCounters_type counters; /* Counter set for this interface type */ -} INMCounters_sample; +/* same thing, but the expanded version, so ds_index can be a full 32 bits */ +typedef struct _SFLCounters_sample_expanded { + /* uint32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 2 */ + /* uint32_t length; */ + uint32_t sequence_number; /* Incremented with each counters sample + generated by this source_id */ + uint32_t ds_class; /* EXPANDED */ + uint32_t ds_index; /* EXPANDED */ + uint32_t num_elements; + SFLCounters_sample_element *elements; +} SFLCounters_sample_expanded; -/* when I turn on optimisation with the Microsoft compiler it seems to change - the values of these enumerated types and break the program - not sure why */ -enum INMSample_types { - FLOWSAMPLE = 1, - COUNTERSSAMPLE = 2 -}; - -typedef union _INMSample_type { - INMFlow_sample flowsample; - INMCounters_sample counterssample; -} INMSample_type; +#define SFLADD_ELEMENT(_sm, _el) do { (_el)->nxt = (_sm)->elements; (_sm)->elements = (_el); } while(0) /* Format of a sample datagram */ -enum INMDatagram_version { - INMDATAGRAM_VERSION2 = 2, - INMDATAGRAM_VERSION4 = 4 +enum SFLDatagram_version { + SFLDATAGRAM_VERSION2 = 2, + SFLDATAGRAM_VERSION4 = 4, + SFLDATAGRAM_VERSION5 = 5 }; -typedef struct _INMSample_datagram_hdr { - uint32_t datagram_version; /* (enum INMDatagram_version) = VERSION4 */ - INMAddress agent_address; /* IP address of sampling agent */ +typedef struct _SFLSample_datagram_hdr { + uint32_t datagram_version; /* (enum SFLDatagram_version) = VERSION5 = 5 */ + SFLAddress agent_address; /* IP address of sampling agent */ + uint32_t sub_agent_id; /* Used to distinguishing between datagram + streams from separate agent sub entities + within an device. */ uint32_t sequence_number; /* Incremented with each sample datagram generated */ uint32_t uptime; /* Current time (in milliseconds since device last booted). Should be set as close to datagram transmission time as possible.*/ - uint32_t num_samples; /* Number of flow and counters samples to follow */ -} INMSample_datagram_hdr; + uint32_t num_records; /* Number of tag-len-val flow/counter records to follow */ +} SFLSample_datagram_hdr; -#define INM_MAX_DATAGRAM_SIZE 1500 -#define INM_MIN_DATAGRAM_SIZE 200 -#define INM_DEFAULT_DATAGRAM_SIZE 1400 +#define SFL_MAX_DATAGRAM_SIZE 1500 +#define SFL_MIN_DATAGRAM_SIZE 200 +#define SFL_DEFAULT_DATAGRAM_SIZE 1400 -#define INM_DATA_PAD 400 - -void Init_sflow(void); - -void Process_sflow(void *in_buff, ssize_t in_buff_cnt, FlowSource_t *fs); - -/* - * Extension map for sflow ( compatibility for now ) - * - * Required extensions: - * - * 4 byte byte counter - * | 4byte packet counter - * | | IPv4 - * | | | - * xxxx x0 0 0 - * - * Optional extensions: - * - * 4 : 2 byte input/output interface id - * 6 : 2 byte src/dst as - */ - - -#endif //_SFLOW_H +#define SFL_DATA_PAD 400 +#if defined(__cplusplus) +} /* extern "C" */ +#endif +#endif /* SFLOW_H */ diff --git a/bin/sflow_nfdump.c b/bin/sflow_nfdump.c new file mode 100644 index 0000000..1788913 --- /dev/null +++ b/bin/sflow_nfdump.c @@ -0,0 +1,4431 @@ +/* + * Copyright (c) 2017, Peter Haag + * Copyright (c) 2016, Peter Haag + * Copyright (c) 2014, Peter Haag + * Copyright (c) 2009, Peter Haag + * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * sfcapd makes use of code originated from sflowtool by InMon Corp. + * Those parts of the code are distributed under the InMon Public License below. + * All other/additional code is pubblished under BSD license. + */ + + +/* + * ----------------------------------------------------------------------- + * Copyright (c) 2001-2002 InMon Corp. All rights reserved. + * ----------------------------------------------------------------------- + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes sFlow(TM), freely available from + * http://www.inmon.com/". + * + * 4. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes sFlow(TM), freely available from + * http://www.inmon.com/". + * + * 5. InMon Corp. may publish revised and/or new versions + * of the license from time to time. Each version will be given a + * distinguishing version number. Once covered code has been + * published under a particular version of the license, you may + * always continue to use it under the terms of that version. You + * may also choose to use such covered code under the terms of any + * subsequent version of the license published by InMon Corp. + * No one other than the InMon Corp. has the right to modify the terms + * applicable to covered code created under this License. + * + * 6. The name "sFlow" must not be used to endorse or promote products + * derived from this software without prior written permission + * from InMon Corp. This does not apply to add-on libraries or tools + * that work in conjunction with sFlow. In such a case the sFlow name + * may be used to indicate that the product supports sFlow. + * + * 7. Products derived from this software may not be called "sFlow", + * nor may "sFlow" appear in their name, without prior written + * permission of InMon Corp. + * + * + * THIS SOFTWARE IS PROVIDED BY INMON CORP. ``AS IS'' AND + * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * INMON CORP. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * -------------------------------------------------------------------- + * + * This software consists of voluntary contributions made by many + * individuals on behalf of InMon Corp. + * + * InMon Corp. can be contacted via Email at info@inmon.com. + * + * For more information on InMon Corp. and sFlow, + * please see http://www.inmon.com/. + * + * InMon Public License Version 1.0 written May 31, 2001 + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_STDINT_H +#include +#endif + +#include "nffile.h" +#include "nfx.h" +#include "nf_common.h" +#include "util.h" +#include "bookkeeper.h" +#include "collector.h" + +#include "sflow.h" /* sFlow v5 */ +#include "sflow_v2v4.h" /* sFlow v2/4 */ +#include "sflow_nfdump.h" + + +/* +#ifdef DARWIN +#include +#define bswap_16(x) NXSwapShort(x) +#define bswap_32(x) NXSwapInt(x) +#else +#include +#endif +*/ + +#ifndef DEVEL +# define dbg_printf(...) /* printf(__VA_ARGS__) */ +#else +# define dbg_printf(...) printf(__VA_ARGS__) +#endif + +#define MAX_SFLOW_EXTENSIONS 8 + +typedef struct exporter_sflow_s { + // link chain + struct exporter_sflow_s *next; + + // generic exporter information + exporter_info_record_t info; + + uint64_t packets; // number of packets sent by this exporter + uint64_t flows; // number of flow records sent by this exporter + uint32_t sequence_failure; // number of sequence failues + + generic_sampler_t *sampler; + + // extension map + // extension maps are common for all exporters + extension_info_t sflow_extension_info[MAX_SFLOW_EXTENSIONS]; + +} exporter_sflow_t; + +extern extension_descriptor_t extension_descriptor[]; +extern FlowSource_t *FlowSource; + +/* module limited globals */ + +/* + * As sflow has no templates, we need to have an extension map for each possible + * combination of IPv4/IPv6 addresses in all ip fields + * + * index id: + * 0 : EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v4 + * 1 : EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v4 + * 2 : EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v4 + * 3 : EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v4 + * 4 : EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v6 + * 5 : EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v6 + * 6 : EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v6 + * 7 : EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v6 + */ +static uint16_t sflow_output_record_size[MAX_SFLOW_EXTENSIONS]; + +// All available extensions for sflow +static uint16_t sflow_extensions[] = { + EX_IO_SNMP_4, + EX_AS_4, + EX_MULIPLE, + EX_VLAN, + EX_MAC_1, + EX_RECEIVED, + 0 // final token +}; +static int Num_enabled_extensions; + +static struct sflow_ip_extensions_s { + int next_hop; + int next_hop_bgp; + int router_ip; +} sflow_ip_extensions[] = { + { EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v4 }, + { EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v4 }, + { EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v4 }, + { EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v4 }, + { EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v6 }, + { EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v4, EX_ROUTER_IP_v6 }, + { EX_NEXT_HOP_v4, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v6 }, + { EX_NEXT_HOP_v6, EX_NEXT_HOP_BGP_v6, EX_ROUTER_IP_v6 }, +}; + +#define SFLOW_NEXT_HOP 1 +#define SFLOW_NEXT_HOP_BGP 2 +#define SFLOW_ROUTER_IP 4 +static int IP_extension_mask = 0; + +static inline exporter_sflow_t *GetExporter(FlowSource_t *fs, uint32_t agentSubId, uint32_t meanSkipCount); + +/* + * unused +// +static uint32_t MyByteSwap32(uint32_t n) { + return (((n & 0x000000FF)<<24) + + ((n & 0x0000FF00)<<8) + + ((n & 0x00FF0000)>>8) + + ((n & 0xFF000000)>>24)); +} + +static uint16_t MyByteSwap16(uint16_t n) { + return ((n >> 8) | (n << 8)); +} +*/ + +#define YES 1 +#define NO 0 + +/* define my own IP header struct - to ease portability */ +struct myiphdr { + uint8_t version_and_headerLen; + uint8_t tos; + uint16_t tot_len; + uint16_t id; + uint16_t frag_off; + uint8_t ttl; + uint8_t protocol; + uint16_t check; + uint32_t saddr; + uint32_t daddr; +}; + +/* ip6 header if no option headers */ +struct myip6hdr { + uint8_t version_and_priority; + uint8_t label1; + uint8_t label2; + uint8_t label3; + uint16_t payloadLength; + uint8_t nextHeader; + uint8_t ttl; + struct in6_addr saddr; + struct in6_addr daddr; +}; + +/* same for tcp */ +struct mytcphdr { + uint16_t th_sport; /* source port */ + uint16_t th_dport; /* destination port */ + uint32_t th_seq; /* sequence number */ + uint32_t th_ack; /* acknowledgement number */ + uint8_t th_off_and_unused; + uint8_t th_flags; + uint16_t th_win; /* window */ + uint16_t th_sum; /* checksum */ + uint16_t th_urp; /* urgent pointer */ +}; + +/* and UDP */ +struct myudphdr { + uint16_t uh_sport; /* source port */ + uint16_t uh_dport; /* destination port */ + uint16_t uh_ulen; /* udp length */ + uint16_t uh_sum; /* udp checksum */ +}; + +/* and ICMP */ +struct myicmphdr { + uint8_t type; /* message type */ + uint8_t code; /* type sub-code */ + /* ignore the rest */ +}; + +typedef struct _SFForwardingTarget { + struct _SFForwardingTarget *nxt; + struct in_addr host; + uint32_t port; + struct sockaddr_in addr; + int sock; +} SFForwardingTarget; + +typedef enum { SFLFMT_FULL=0, SFLFMT_PCAP, SFLFMT_LINE } EnumSFLFormat; + +typedef struct _SFSample { + /* exception handler context */ + jmp_buf env; + + struct in_addr sourceIP; // EX_ROUTER_IP_v4 + + SFLAddress agent_addr; + uint32_t agentSubId; + + /* the raw pdu */ + uint8_t *rawSample; + uint32_t rawSampleLen; + uint8_t *endp; + time_t readTimestamp; + + /* decode cursor */ + uint32_t *datap; + + uint32_t datagramVersion; + uint32_t sampleType; + uint32_t elementType; + uint32_t ds_class; + uint32_t ds_index; + + /* generic interface counter sample */ + SFLIf_counters ifCounters; + + /* sample stream info */ + uint32_t sysUpTime; + uint32_t sequenceNo; + uint32_t sampledPacketSize; + uint32_t samplesGenerated; + uint32_t meanSkipCount; + uint32_t samplePool; + uint32_t dropEvents; + + /* the sampled header */ + uint32_t packet_data_tag; + uint32_t headerProtocol; + uint8_t *header; + uint32_t headerLen; + uint32_t stripped; + + /* header decode */ + int gotIPV4; + int gotIPV4Struct; + int offsetToIPV4; + int gotIPV6; // v6 flag + int gotIPV6Struct; + int offsetToIPV6; + int offsetToPayload; + SFLAddress ipsrc; // Common (v6) + SFLAddress ipdst; // Common (v6) +// XXX + struct in_addr dcd_srcIP; // Common (v4) + struct in_addr dcd_dstIP; // Common (v4) + uint32_t dcd_ipProtocol; // Common + uint32_t dcd_ipTos; // EX_MULIPLE + uint32_t dcd_ipTTL; + uint32_t dcd_sport; // Common + uint32_t dcd_dport; // Common + uint32_t dcd_tcpFlags; // Common + uint32_t ip_fragmentOffset; + uint32_t udp_pduLen; + + /* ports */ + uint32_t inputPortFormat; + uint32_t outputPortFormat; + uint32_t inputPort; // EX_IO_SNMP_4 + uint32_t outputPort; // EX_IO_SNMP_4 + + /* ethernet */ + uint32_t eth_type; + uint32_t eth_len; + u_char eth_src[8]; // EX_MAC_1 + u_char eth_dst[8]; // EX_MAC_1 + + /* vlan */ + uint32_t in_vlan; // EX_VLAN + uint32_t in_priority; + uint32_t internalPriority; + uint32_t out_vlan; // EX_VLAN + uint32_t out_priority; + int vlanFilterReject; + + /* extended data fields */ + uint32_t num_extended; + uint32_t extended_data_tag; +#define SASAMPLE_EXTENDED_DATA_SWITCH 1 +#define SASAMPLE_EXTENDED_DATA_ROUTER 4 +#define SASAMPLE_EXTENDED_DATA_GATEWAY 8 +#define SASAMPLE_EXTENDED_DATA_USER 16 +#define SASAMPLE_EXTENDED_DATA_URL 32 +#define SASAMPLE_EXTENDED_DATA_MPLS 64 +#define SASAMPLE_EXTENDED_DATA_NAT 128 +#define SASAMPLE_EXTENDED_DATA_MPLS_TUNNEL 256 +#define SASAMPLE_EXTENDED_DATA_MPLS_VC 512 +#define SASAMPLE_EXTENDED_DATA_MPLS_FTN 1024 +#define SASAMPLE_EXTENDED_DATA_MPLS_LDP_FEC 2048 +#define SASAMPLE_EXTENDED_DATA_VLAN_TUNNEL 4096 +#define SASAMPLE_EXTENDED_DATA_NAT_PORT 8192 + + /* IP forwarding info */ + SFLAddress nextHop; // EX_NEXT_HOP_v4, EX_NEXT_HOP_v6 + uint32_t srcMask; // EX_MULIPLE + uint32_t dstMask; // EX_MULIPLE + + /* BGP info */ + SFLAddress bgp_nextHop; // EX_NEXT_HOP_BGP_v4, EX_NEXT_HOP_BGP_v6 + uint32_t my_as; + uint32_t src_as; // EX_AS_4 + uint32_t src_peer_as; + uint32_t dst_as_path_len; + uint32_t *dst_as_path; + /* note: version 4 dst as path segments just get printed, not stored here, however + * the dst_peer and dst_as are filled in, since those are used for netflow encoding + */ + uint32_t dst_peer_as; + uint32_t dst_as; // EX_AS_4 + + uint32_t communities_len; + uint32_t *communities; + uint32_t localpref; + + /* user id */ +#define SA_MAX_EXTENDED_USER_LEN 200 + uint32_t src_user_charset; + uint32_t src_user_len; + char src_user[SA_MAX_EXTENDED_USER_LEN+1]; + uint32_t dst_user_charset; + uint32_t dst_user_len; + char dst_user[SA_MAX_EXTENDED_USER_LEN+1]; + + /* url */ +#define SA_MAX_EXTENDED_URL_LEN 200 +#define SA_MAX_EXTENDED_HOST_LEN 200 + uint32_t url_direction; + uint32_t url_len; + char url[SA_MAX_EXTENDED_URL_LEN+1]; + uint32_t host_len; + char host[SA_MAX_EXTENDED_HOST_LEN+1]; + + /* mpls */ + SFLAddress mpls_nextHop; + + /* nat */ + SFLAddress nat_src; + SFLAddress nat_dst; + + /* counter blocks */ + uint32_t statsSamplingInterval; + uint32_t counterBlockVersion; + +#define SFABORT(s, r) longjmp((s)->env, (r)) +#define SF_ABORT_EOS 1 +#define SF_ABORT_DECODE_ERROR 2 +#define SF_ABORT_LENGTH_ERROR 3 + +} SFSample; + +int Setup_Extension_Info(FlowSource_t *fs, exporter_sflow_t *exporter, int num); + +static int printHex(const u_char *a, int len, char *buf, int bufLen, int marker, int bytesPerOutputLine); + +static char *IP_to_a(uint32_t ipaddr, char *buf, int buflen); + +static inline uint32_t getData32(SFSample *sample); + +static inline uint32_t getData32_nobswap(SFSample *sample); + +static inline uint64_t getData64(SFSample *sample); + +static void writeCountersLine(SFSample *sample); + +static void receiveError(SFSample *sample, char *errm, int hexdump) __attribute__ ((noreturn)); + +static inline void skipBytes(SFSample *sample, uint32_t skip); + +static inline uint32_t sf_log_next32(SFSample *sample, char *fieldName); + +static inline uint64_t sf_log_next64(SFSample *sample, char *fieldName); + +static inline void sf_log_nextMAC(SFSample *sample, char *fieldName); + +static inline void sf_log_percentage(SFSample *sample, char *fieldName); + +static inline uint32_t getString(SFSample *sample, char *buf, uint32_t bufLen); + +static inline uint32_t getAddress(SFSample *sample, SFLAddress *address); + +static inline void skipTLVRecord(SFSample *sample, uint32_t tag, uint32_t len, char *description); + +static inline void readSFlowDatagram(SFSample *sample, FlowSource_t *fs); + +static inline void readFlowSample(SFSample *sample, int expanded, FlowSource_t *fs); + +static inline void readCountersSample(SFSample *sample, int expanded, FlowSource_t *fs); + +static inline void readFlowSample_header(SFSample *sample); + +static inline void readFlowSample_v2v4(SFSample *sample, FlowSource_t *fs); + +static inline void readCountersSample_v2v4(SFSample *sample, FlowSource_t *fs); + +static inline void StoreSflowRecord(SFSample *sample, FlowSource_t *fs); + +#ifdef DEVEL +static char *URLEncode(char *in, char *out, int outlen); +#endif + +static int printUUID(const uint8_t *a, char *buf, int bufLen); + +extern int verbose; + +#ifdef DEVEL +static inline char *printTag(uint32_t tag, char *buf, int bufLen); + +static inline char *printTag(uint32_t tag, char *buf, int bufLen) { + snprintf(buf, bufLen, "%u:%u", (tag >> 12), (tag & 0x00000FFF)); + return buf; +} // End of printTag + +#endif + + +/*_________________---------------------------__________________ + _________________ printHex __________________ + -----------------___________________________------------------ +*/ + +static u_char bin2hex(int nib) { return (nib < 10) ? ('0' + nib) : ('A' - 10 + nib); } + +static int printHex(const u_char *a, int len, char *buf, int bufLen, int marker, int bytesPerOutputLine) { + int b = 0, i = 0; + for(; i < len; i++) { + u_char byte; + if(b > (bufLen - 10)) break; + if(marker > 0 && i == marker) { + buf[b++] = '<'; + buf[b++] = '*'; + buf[b++] = '>'; + buf[b++] = '-'; + } + byte = a[i]; + buf[b++] = bin2hex(byte >> 4); + buf[b++] = bin2hex(byte & 0x0f); + if(i > 0 && (i % bytesPerOutputLine) == 0) buf[b++] = '\n'; + else { + // separate the bytes with a dash + if (i < (len - 1)) buf[b++] = '-'; + } + } + buf[b] = '\0'; + return b; +} + +/*_________________---------------------------__________________ + _________________ IP_to_a __________________ + -----------------___________________________------------------ +*/ + +static char *IP_to_a(uint32_t ipaddr, char *buf, int buflen) { + u_char *ip = (u_char *)&ipaddr; + snprintf(buf, buflen, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); + buf[buflen-1] = '\0'; + return buf; +} + +static char *printAddress(SFLAddress *address, char *buf, int bufLen) { + switch(address->type) { + case SFLADDRESSTYPE_IP_V4: + IP_to_a(address->address.ip_v4.addr, buf, bufLen); + break; + case SFLADDRESSTYPE_IP_V6: { + u_char *b = address->address.ip_v6.addr; + snprintf(buf, bufLen, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7],b[8],b[9],b[10],b[11],b[12],b[13],b[14],b[15]); + } break; + default: + sprintf(buf, "-"); + } + return buf; +} + +/*_________________---------------------------__________________ + _________________ writeFlowLine __________________ + -----------------___________________________------------------ +*/ + +static void writeFlowLine(SFSample *sample) { +char agentIP[51], srcIP[51], dstIP[51]; + // source + printf("FLOW,%s,%d,%d,", + printAddress(&sample->agent_addr, agentIP, 50), + sample->inputPort, + sample->outputPort); + // layer 2 + printf("%02x%02x%02x%02x%02x%02x,%02x%02x%02x%02x%02x%02x,0x%04x,%d,%d", + sample->eth_src[0], + sample->eth_src[1], + sample->eth_src[2], + sample->eth_src[3], + sample->eth_src[4], + sample->eth_src[5], + sample->eth_dst[0], + sample->eth_dst[1], + sample->eth_dst[2], + sample->eth_dst[3], + sample->eth_dst[4], + sample->eth_dst[5], + sample->eth_type, + sample->in_vlan, + sample->out_vlan); + // layer 3/4 + printf(",IP: %s,%s,%d,0x%02x,%d,%d,%d,0x%02x", + IP_to_a(sample->dcd_srcIP.s_addr, srcIP, 51), + IP_to_a(sample->dcd_dstIP.s_addr, dstIP, 51), + sample->dcd_ipProtocol, + sample->dcd_ipTos, + sample->dcd_ipTTL, + sample->dcd_sport, + sample->dcd_dport, + sample->dcd_tcpFlags); + // bytes + printf(",%d,%d,%d\n", + sample->sampledPacketSize, + sample->sampledPacketSize - sample->stripped - sample->offsetToIPV4, + sample->meanSkipCount); +} + +/*_________________---------------------------__________________ + _________________ writeCountersLine __________________ + -----------------___________________________------------------ +*/ + +static void writeCountersLine(SFSample *sample) +{ + // source + char agentIP[51]; + printf("CNTR,%s,", printAddress(&sample->agent_addr, agentIP, 50)); + printf("%u,%u,%llu,%u,%u,%llu,%u,%u,%u,%u,%u,%u,%llu,%u,%u,%u,%u,%u,%u\n", + sample->ifCounters.ifIndex, + sample->ifCounters.ifType, + (unsigned long long)sample->ifCounters.ifSpeed, + sample->ifCounters.ifDirection, + sample->ifCounters.ifStatus, + (unsigned long long)sample->ifCounters.ifInOctets, + sample->ifCounters.ifInUcastPkts, + sample->ifCounters.ifInMulticastPkts, + sample->ifCounters.ifInBroadcastPkts, + sample->ifCounters.ifInDiscards, + sample->ifCounters.ifInErrors, + sample->ifCounters.ifInUnknownProtos, + (unsigned long long)sample->ifCounters.ifOutOctets, + sample->ifCounters.ifOutUcastPkts, + sample->ifCounters.ifOutMulticastPkts, + sample->ifCounters.ifOutBroadcastPkts, + sample->ifCounters.ifOutDiscards, + sample->ifCounters.ifOutErrors, + sample->ifCounters.ifPromiscuousMode); +} + +/*_________________---------------------------__________________ + _________________ receiveError __________________ + -----------------___________________________------------------ +*/ + +static void receiveError(SFSample *sample, char *errm, int hexdump) +{ + char ipbuf[51]; + char scratch[6000]; + char *msg = ""; + char *hex = ""; + uint32_t markOffset = (u_char *)sample->datap - sample->rawSample; + if(errm) msg = errm; + if(hexdump) { + printHex(sample->rawSample, sample->rawSampleLen, scratch, 6000, markOffset, 16); + hex = scratch; + } + LogError("SFLOW: %s (source IP = %s) %s", msg, IP_to_a(sample->sourceIP.s_addr, ipbuf, 51), hex); + + SFABORT(sample, SF_ABORT_DECODE_ERROR); + +} + +/*_________________---------------------------__________________ + _________________ lengthCheck __________________ + -----------------___________________________------------------ +*/ + +static void lengthCheck(SFSample *sample, char *description, u_char *start, int len) { + uint32_t actualLen = (u_char *)sample->datap - start; + uint32_t adjustedLen = ((len + 3) >> 2) << 2; + if(actualLen != adjustedLen) { + dbg_printf("%s length error (expected %d, found %d)\n", description, len, actualLen); + LogError("SFLOW: %s length error (expected %d, found %d)", description, len, actualLen); + SFABORT(sample, SF_ABORT_LENGTH_ERROR); + } + +} + +/*_________________---------------------------__________________ + _________________ decodeLinkLayer __________________ + -----------------___________________________------------------ + store the offset to the start of the ipv4 header in the sequence_number field + or -1 if not found. Decode the 802.1d if it's there. +*/ + +#define NFT_ETHHDR_SIZ 14 +#define NFT_8022_SIZ 3 +#define NFT_MAX_8023_LEN 1500 + +#define NFT_MIN_SIZ (NFT_ETHHDR_SIZ + sizeof(struct myiphdr)) + +static void decodeLinkLayer(SFSample *sample) +{ + uint8_t *start = sample->header; + uint8_t *end = start + sample->headerLen; + uint8_t *ptr = start; + uint16_t type_len; + + /* assume not found */ + sample->gotIPV4 = NO; + sample->gotIPV6 = NO; + + if((end - ptr) < NFT_ETHHDR_SIZ) return; /* not enough for an Ethernet header */ + + dbg_printf("dstMAC %02x%02x%02x%02x%02x%02x\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + memcpy(sample->eth_dst, ptr, 6); + ptr += 6; + dbg_printf("srcMAC %02x%02x%02x%02x%02x%02x\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + memcpy(sample->eth_src, ptr, 6); + ptr += 6; + type_len = (ptr[0] << 8) + ptr[1]; + ptr += 2; + + if(type_len == 0x8100) { + if((end - ptr) < 4) return; /* not enough for an 802.1Q header */ + /* VLAN - next two bytes */ + uint32_t vlanData = (ptr[0] << 8) + ptr[1]; + uint32_t vlan = vlanData & 0x0fff; +#ifdef DEVEL + uint32_t priority = vlanData >> 13; +#endif + ptr += 2; + /* _____________________________________ */ + /* | pri | c | vlan-id | */ + /* ------------------------------------- */ + /* [priority = 3bits] [Canonical Format Flag = 1bit] [vlan-id = 12 bits] */ + dbg_printf("decodedVLAN %u\n", vlan); + dbg_printf("decodedPriority %u\n", priority); + sample->in_vlan = vlan; + /* now get the type_len again (next two bytes) */ + type_len = (ptr[0] << 8) + ptr[1]; + ptr += 2; + } + + /* now we're just looking for IP */ + if((end - start) < sizeof(struct myiphdr)) return; /* not enough for an IPv4 header (or IPX, or SNAP) */ + + /* peek for IPX */ + if(type_len == 0x0200 || type_len == 0x0201 || type_len == 0x0600) { +#define IPX_HDR_LEN 30 +#define IPX_MAX_DATA 546 + int ipxChecksum = (ptr[0] == 0xff && ptr[1] == 0xff); + int ipxLen = (ptr[2] << 8) + ptr[3]; + if(ipxChecksum && + ipxLen >= IPX_HDR_LEN && + ipxLen <= (IPX_HDR_LEN + IPX_MAX_DATA)) + /* we don't do anything with IPX here */ + return; + } + if(type_len <= NFT_MAX_8023_LEN) { + /* assume 802.3+802.2 header */ + /* check for SNAP */ + if(ptr[0] == 0xAA && + ptr[1] == 0xAA && + ptr[2] == 0x03) { + ptr += 3; + if(ptr[0] != 0 || + ptr[1] != 0 || + ptr[2] != 0) { + dbg_printf("VSNAP_OUI %02X-%02X-%02X\n", ptr[0], ptr[1], ptr[2]); + return; /* no further decode for vendor-specific protocol */ + } + ptr += 3; + /* OUI == 00-00-00 means the next two bytes are the ethernet type (RFC 2895) */ + type_len = (ptr[0] << 8) + ptr[1]; + ptr += 2; + } + else { + if (ptr[0] == 0x06 && + ptr[1] == 0x06 && + (ptr[2] & 0x01)) { + /* IP over 8022 */ + ptr += 3; + /* force the type_len to be IP so we can inline the IP decode below */ + type_len = 0x0800; + } + else return; + } + } + + /* assume type_len is an ethernet-type now */ + sample->eth_type = type_len; + + if(type_len == 0x0800) { + /* IPV4 - check again that we have enough header bytes */ + if((end - ptr) < sizeof(struct myiphdr)) return; + /* look at first byte of header.... */ + /* ___________________________ */ + /* | version | hdrlen | */ + /* --------------------------- */ + if((*ptr >> 4) != 4) return; /* not version 4 */ + if((*ptr & 15) < 5) return; /* not IP (hdr len must be 5 quads or more) */ + /* survived all the tests - store the offset to the start of the ip header */ + sample->gotIPV4 = YES; + sample->offsetToIPV4 = (ptr - start); + } + + if(type_len == 0x86DD) { + /* IPV6 */ + /* look at first byte of header.... */ + if((*ptr >> 4) != 6) return; /* not version 6 */ + /* survived all the tests - store the offset to the start of the ip6 header */ + sample->gotIPV6 = YES; + sample->offsetToIPV6 = (ptr - start); + } +} + +#define WIFI_MIN_HDR_SIZ 24 + +static void decode80211MAC(SFSample *sample) +{ + uint8_t *start = sample->header; +// uint8_t *end = start + sample->headerLen; + uint8_t *ptr = start; + + /* assume not found */ + sample->gotIPV4 = NO; + sample->gotIPV6 = NO; + + if(sample->headerLen < WIFI_MIN_HDR_SIZ) return; /* not enough for an 80211 MAC header */ + + uint32_t fc = (ptr[1] << 8) + ptr[0]; /* [b7..b0][b15..b8] */ + uint32_t control = (fc >> 2) & 3; + uint32_t toDS = (fc >> 8) & 1; + uint32_t fromDS = (fc >> 9) & 1; +/* not used +uint32_t protocolVersion = fc & 3; +uint32_t subType = (fc >> 4) & 15; +uint32_t moreFrag = (fc >> 10) & 1; +uint32_t retry = (fc >> 11) & 1; +uint32_t pwrMgt = (fc >> 12) & 1; +uint32_t moreData = (fc >> 13) & 1; +uint32_t encrypted = (fc >> 14) & 1; +uint32_t order = fc >> 15; +*/ + ptr += 2; + +// uint32_t duration_id = (ptr[1] << 8) + ptr[0]; /* not in network byte order either? */ + ptr += 2; + + switch(control) { + case 0: /* mgmt */ + case 1: /* ctrl */ + case 3: /* rsvd */ + break; + + case 2: /* data */ + { + + uint8_t *macAddr1 = ptr; + ptr += 6; + uint8_t *macAddr2 = ptr; + ptr += 6; + uint8_t *macAddr3 = ptr; + ptr += 6; + // XXX not used uint32_t sequence = (ptr[0] << 8) + ptr[1]; + ptr += 2; + + /* ToDS FromDS Addr1 Addr2 Addr3 Addr4 + 0 0 DA SA BSSID N/A (ad-hoc) + 0 1 DA BSSID SA N/A + 1 0 BSSID SA DA N/A + 1 1 RA TA DA SA (wireless bridge) */ + + uint8_t *rxMAC = macAddr1; + uint8_t *txMAC = macAddr2; + uint8_t *srcMAC = NULL; + uint8_t *dstMAC = NULL; + + if(toDS) { + dstMAC = macAddr3; + if(fromDS) { + srcMAC = ptr; /* macAddr4. 1,1 => (wireless bridge) */ + ptr += 6; + } + else srcMAC = macAddr2; /* 1,0 */ + } + else { + dstMAC = macAddr1; + if(fromDS) srcMAC = macAddr3; /* 0,1 */ + else srcMAC = macAddr2; /* 0,0 */ + } + + if(srcMAC) { + dbg_printf("srcMAC %02x%02x%02x%02x%02x%02x\n", srcMAC[0], srcMAC[1], srcMAC[2], srcMAC[3], srcMAC[4], srcMAC[5]); + memcpy(sample->eth_src, srcMAC, 6); + } + if(dstMAC) { + dbg_printf("dstMAC %02x%02x%02x%02x%02x%02x\n", dstMAC[0], dstMAC[1], dstMAC[2], dstMAC[3], dstMAC[4], dstMAC[5]); + memcpy(sample->eth_dst, dstMAC, 6); + } + if(txMAC) dbg_printf("txMAC %02x%02x%02x%02x%02x%02x\n", txMAC[0], txMAC[1], txMAC[2], txMAC[3], txMAC[4], txMAC[5]); + if(rxMAC) dbg_printf("rxMAC %02x%02x%02x%02x%02x%02x\n", rxMAC[0], rxMAC[1], rxMAC[2], rxMAC[3], rxMAC[4], rxMAC[5]); + } + } +} + + +/*_________________---------------------------__________________ + _________________ decodeIPLayer4 __________________ + -----------------___________________________------------------ +*/ + +static void decodeIPLayer4(SFSample *sample, uint8_t *ptr) { + uint8_t *end = sample->header + sample->headerLen; + if(ptr > (end - 8)) { + /* not enough header bytes left */ + return; + } + switch(sample->dcd_ipProtocol) { + case 1: /* ICMP */ + { + struct myicmphdr icmp; + memcpy(&icmp, ptr, sizeof(icmp)); + dbg_printf("ICMPType %u\n", icmp.type); + dbg_printf("ICMPCode %u\n", icmp.code); + sample->dcd_sport = icmp.type; + sample->dcd_dport = icmp.code; + sample->offsetToPayload = ptr + sizeof(icmp) - sample->header; + } + break; + case 6: /* TCP */ + { + struct mytcphdr tcp; + int headerBytes; + memcpy(&tcp, ptr, sizeof(tcp)); + sample->dcd_sport = ntohs(tcp.th_sport); + sample->dcd_dport = ntohs(tcp.th_dport); + sample->dcd_tcpFlags = tcp.th_flags; + dbg_printf("TCPSrcPort %u\n", sample->dcd_sport); + dbg_printf("TCPDstPort %u\n",sample->dcd_dport); + dbg_printf("TCPFlags %u\n", sample->dcd_tcpFlags); + headerBytes = (tcp.th_off_and_unused >> 4) * 4; + ptr += headerBytes; + sample->offsetToPayload = ptr - sample->header; + } + break; + case 17: /* UDP */ + { + struct myudphdr udp; + memcpy(&udp, ptr, sizeof(udp)); + sample->dcd_sport = ntohs(udp.uh_sport); + sample->dcd_dport = ntohs(udp.uh_dport); + sample->udp_pduLen = ntohs(udp.uh_ulen); + dbg_printf("UDPSrcPort %u\n", sample->dcd_sport); + dbg_printf("UDPDstPort %u\n", sample->dcd_dport); + dbg_printf("UDPBytes %u\n", sample->udp_pduLen); + sample->offsetToPayload = ptr + sizeof(udp) - sample->header; + } + break; + default: /* some other protcol */ + sample->offsetToPayload = ptr - sample->header; + break; + } +} + + +/*_________________---------------------------__________________ + _________________ decodeIPV4 __________________ + -----------------___________________________------------------ +*/ + +static void decodeIPV4(SFSample *sample) +{ + if(sample->gotIPV4) { +#ifdef DEVEL + char buf[51]; +#endif + uint8_t *end = sample->header + sample->headerLen; + uint8_t *start = sample->header + sample->offsetToIPV4; + uint8_t *ptr = start; + if((end - ptr) < sizeof(struct myiphdr)) return; + + /* Create a local copy of the IP header (cannot overlay structure in case it is not quad-aligned...some + platforms would core-dump if we tried that). It's OK coz this probably performs just as well anyway. */ + struct myiphdr ip; + memcpy(&ip, ptr, sizeof(ip)); + /* Value copy all ip elements into sample */ + sample->ipsrc.type = SFLADDRESSTYPE_IP_V4; + sample->ipsrc.address.ip_v4.addr = ip.saddr; + sample->ipdst.type = SFLADDRESSTYPE_IP_V4; + sample->ipdst.address.ip_v4.addr = ip.daddr; + sample->dcd_srcIP.s_addr = ip.saddr; + sample->dcd_dstIP.s_addr = ip.daddr; + sample->dcd_ipProtocol = ip.protocol; + sample->dcd_ipTos = ip.tos; + sample->dcd_ipTTL = ip.ttl; + dbg_printf("ip.tot_len %d\n", ntohs(ip.tot_len)); + /* Log out the decoded IP fields */ + dbg_printf("srcIP %s\n", IP_to_a(sample->dcd_srcIP.s_addr, buf, 51)); + dbg_printf("dstIP %s\n", IP_to_a(sample->dcd_dstIP.s_addr, buf, 51)); + dbg_printf("IPProtocol %u\n", sample->dcd_ipProtocol); + dbg_printf("IPTOS %u\n", sample->dcd_ipTos); + dbg_printf("IPTTL %u\n", sample->dcd_ipTTL); + /* check for fragments */ + sample->ip_fragmentOffset = ntohs(ip.frag_off) & 0x1FFF; + if(sample->ip_fragmentOffset > 0) { + dbg_printf("IPFragmentOffset %u\n", sample->ip_fragmentOffset); + } + else { + dbg_printf("Unfragmented\n"); + /* advance the pointer to the next protocol layer */ + /* ip headerLen is expressed as a number of quads */ + uint32_t headerBytes = (ip.version_and_headerLen & 0x0f) * 4; + if((end - ptr) < headerBytes) return; + ptr += headerBytes; + decodeIPLayer4(sample, ptr); + } + } +} + +/*_________________---------------------------__________________ + _________________ decodeIPV6 __________________ + -----------------___________________________------------------ +*/ + +static void decodeIPV6(SFSample *sample) +{ + uint16_t payloadLen; + uint32_t label; + uint32_t nextHeader; + + uint8_t *end = sample->header + sample->headerLen; + uint8_t *start = sample->header + sample->offsetToIPV6; + uint8_t *ptr = start; + if((end - ptr) < sizeof(struct myip6hdr)) return; + + if(sample->gotIPV6) { + u_char *ptr = sample->header + sample->offsetToIPV6; + // check the version + { + int ipVersion = (*ptr >> 4); + if(ipVersion != 6) { + LogError("SFLOW: decodeIPV6() header decode error: unexpected IP version: %d\n", ipVersion); + return; + } + } + + // get the tos (priority) + sample->dcd_ipTos = *ptr++ & 15; + dbg_printf("IPTOS %u\n", sample->dcd_ipTos); + // 24-bit label + label = *ptr++; + label <<= 8; + label += *ptr++; + label <<= 8; + label += *ptr++; + dbg_printf("IP6_label 0x%x\n", label); + // payload + payloadLen = (ptr[0] << 8) + ptr[1]; + ptr += 2; + // if payload is zero, that implies a jumbo payload + if(payloadLen == 0) dbg_printf("IPV6_payloadLen \n"); + else dbg_printf("IPV6_payloadLen %u\n", payloadLen); + + // next header + nextHeader = *ptr++; + + // TTL + sample->dcd_ipTTL = *ptr++; + dbg_printf("IPTTL %u\n", sample->dcd_ipTTL); + + {// src and dst address +#ifdef DEVEL + char buf[101]; +#endif + sample->ipsrc.type = SFLADDRESSTYPE_IP_V6; + memcpy(&sample->ipsrc.address, ptr, 16); + ptr +=16; + dbg_printf("srcIP6 %s\n", printAddress(&sample->ipsrc, buf, 100)); + sample->ipdst.type = SFLADDRESSTYPE_IP_V6; + memcpy(&sample->ipdst.address, ptr, 16); + ptr +=16; + dbg_printf("dstIP6 %s\n", printAddress(&sample->ipdst, buf, 100)); + } + + // skip over some common header extensions... + // http://searchnetworking.techtarget.com/originalContent/0,289142,sid7_gci870277,00.html + while(nextHeader == 0 || // hop + nextHeader == 43 || // routing + nextHeader == 44 || // fragment + // nextHeader == 50 || // encryption - don't bother coz we'll not be able to read any further + nextHeader == 51 || // auth + nextHeader == 60) { // destination options + uint32_t optionLen, skip; + dbg_printf("IP6HeaderExtension: %d\n", nextHeader); + nextHeader = ptr[0]; + optionLen = 8 * (ptr[1] + 1); // second byte gives option len in 8-byte chunks, not counting first 8 + skip = optionLen - 2; + ptr += skip; + if(ptr > end) return; // ran off the end of the header + } + + // now that we have eliminated the extension headers, nextHeader should have what we want to + // remember as the ip protocol... + sample->dcd_ipProtocol = nextHeader; + dbg_printf("IPProtocol %u\n", sample->dcd_ipProtocol); + decodeIPLayer4(sample, ptr); + } +} + + +#include "inline.c" +#include "nffile_inline.c" +#include "collector_inline.c" + +/*_________________---------------------------__________________ + _________________ StoreSflowRecord __________________ + -----------------___________________________------------------ +*/ + +static inline void StoreSflowRecord(SFSample *sample, FlowSource_t *fs) { +common_record_t *common_record; +stat_record_t *stat_record = fs->nffile->stat_record; +exporter_sflow_t *exporter; +extension_map_t *extension_map; +struct timeval now; +void *next_data; +value32_t *val; +uint32_t bytes, j, id, ipsize, ip_flags; +uint64_t _bytes, _packets, _t; // tmp buffers + + dbg_printf("StoreSflowRecord\n"); + + gettimeofday(&now, NULL); + + if( sample->ip_fragmentOffset > 0 ) { + sample->dcd_sport = 0; + sample->dcd_dport = 0; + } + + bytes = sample->sampledPacketSize; + + ip_flags = 0; + if ( sample->nextHop.type == SFLADDRESSTYPE_IP_V6 ) + SetFlag(ip_flags, SFLOW_NEXT_HOP); + + if ( sample->bgp_nextHop.type == SFLADDRESSTYPE_IP_V6 ) + SetFlag(ip_flags, SFLOW_NEXT_HOP_BGP); + + if ( fs->sa_family == AF_INET6 ) + SetFlag(ip_flags, SFLOW_ROUTER_IP); + + ip_flags &= IP_extension_mask; + + if ( ip_flags >= MAX_SFLOW_EXTENSIONS ) { + LogError("SFLOW: Corrupt ip_flags: %u", ip_flags); + } + exporter = GetExporter(fs, sample->agentSubId, sample->meanSkipCount); + if ( !exporter ) { + LogError("SFLOW: Exporter NULL: Abort sflow record processing"); + return; + } + exporter->packets++; + + // get appropriate extension map + extension_map = exporter->sflow_extension_info[ip_flags].map; + if ( !extension_map ) { + LogInfo("SFLOW: setup extension map: %u", ip_flags); + if ( !Setup_Extension_Info(fs, exporter, ip_flags ) ) { + LogError("SFLOW: Extension map: NULL: Abort sflow record processing"); + return; + } + extension_map = exporter->sflow_extension_info[ip_flags].map; + LogInfo("SFLOW: setup extension map: %u done", ip_flags); + } + + // output buffer size check + // IPv6 needs 2 x 16 bytes, IPv4 2 x 4 bytes + ipsize = sample->gotIPV6 ? 32 : 8; + if ( !CheckBufferSpace(fs->nffile, sflow_output_record_size[ip_flags] + ipsize )) { + // fishy! - should never happen. maybe disk full? + LogError("SFLOW: output buffer size error. Abort sflow record processing"); + return; + } + + dbg_printf("Fill Record\n"); + common_record = (common_record_t *)fs->nffile->buff_ptr; + + common_record->size = sflow_output_record_size[ip_flags] + ipsize; + common_record->type = CommonRecordType; + common_record->flags = 0; + SetFlag(common_record->flags, FLAG_SAMPLED); + + common_record->exporter_sysid = exporter->info.sysid; + common_record->ext_map = extension_map->map_id; + + common_record->first = now.tv_sec; + common_record->last = common_record->first; + common_record->msec_first = now.tv_usec / 1000; + common_record->msec_last = common_record->msec_first; + _t = 1000LL * now.tv_sec + common_record->msec_first; // tmp buff for first_seen + + common_record->fwd_status = 0; + common_record->reserved = 0; + common_record->tcp_flags = sample->dcd_tcpFlags; + common_record->prot = sample->dcd_ipProtocol; + common_record->tos = sample->dcd_ipTos; + common_record->srcport = (uint16_t)sample->dcd_sport; + common_record->dstport = (uint16_t)sample->dcd_dport; + + if(sample->gotIPV6) { + u_char *b; + uint64_t *u; + ipv6_block_t *ipv6 = (ipv6_block_t *)common_record->data; + SetFlag(common_record->flags, FLAG_IPV6_ADDR); + + b = sample->ipsrc.address.ip_v6.addr; + u = (uint64_t *)b; + ipv6->srcaddr[0] = ntohll(*u); + u = (uint64_t *)&(b[8]); + ipv6->srcaddr[1] = ntohll(*u); + + b = sample->ipdst.address.ip_v6.addr; + u = (uint64_t *)b; + ipv6->dstaddr[0] = ntohll(*u); + u = (uint64_t *)&(b[8]); + ipv6->dstaddr[1] = ntohll(*u); + + next_data = (void *)ipv6->data; + } else { + ipv4_block_t *ipv4 = (ipv4_block_t *)common_record->data; + ipv4->srcaddr = ntohl(sample->dcd_srcIP.s_addr); + ipv4->dstaddr = ntohl(sample->dcd_dstIP.s_addr); + + next_data = (void *)ipv4->data; + } + + // 4 byte Packet value + val = (value32_t *)next_data; + val->val = sample->meanSkipCount; + _packets = val->val; + + // 4 byte Bytes value + val = (value32_t *)val->data; + val->val = sample->meanSkipCount * bytes; + _bytes = val->val; + + next_data = (void *)val->data; + + j = 0; + while ( (id = extension_map->ex_id[j]) != 0 ) { + switch (id) { + case EX_IO_SNMP_4: { // 4 byte input/output interface index + tpl_ext_5_t *tpl = (tpl_ext_5_t *)next_data; + tpl->input = sample->inputPort; + tpl->output = sample->outputPort; + next_data = (void *)tpl->data; + } break; + case EX_AS_4: { // 4 byte src/dst AS number + tpl_ext_7_t *tpl = (tpl_ext_7_t *)next_data; + tpl->src_as = sample->src_as; + tpl->dst_as = sample->dst_as; + next_data = (void *)tpl->data; + } break; + case EX_VLAN: { // 2 byte valn label + tpl_ext_13_t *tpl = (tpl_ext_13_t *)next_data; + tpl->src_vlan = sample->in_vlan; + tpl->dst_vlan = sample->out_vlan; + next_data = (void *)tpl->data; + } break; + case EX_MULIPLE: { // dst tos, direction, src/dst mask + tpl_ext_8_t *tpl = (tpl_ext_8_t *)next_data; + tpl->dst_tos = sample->dcd_ipTos; + tpl->dir = 0; + tpl->src_mask = sample->srcMask; + tpl->dst_mask = sample->dstMask; + next_data = (void *)tpl->data; + } break; + case EX_MAC_1: { // MAC addreses + tpl_ext_20_t *tpl = (tpl_ext_20_t *)next_data; + tpl->in_src_mac = Get_val48((void *)&sample->eth_src); + tpl->out_dst_mac = Get_val48((void *)&sample->eth_dst); + next_data = (void *)tpl->data; + } break; + case EX_NEXT_HOP_v4: { // next hop IPv4 router address + tpl_ext_9_t *tpl = (tpl_ext_9_t *)next_data; + if ( sample->nextHop.type == SFLADDRESSTYPE_IP_V4 ) { + tpl->nexthop = ntohl(sample->nextHop.address.ip_v4.addr); + } else { + tpl->nexthop = 0; + } + next_data = (void *)tpl->data; + } break; + case EX_NEXT_HOP_v6: { // next hop IPv6 router address + tpl_ext_10_t *tpl = (tpl_ext_10_t *)next_data; + void *ptr = (void *)sample->nextHop.address.ip_v6.addr; + if ( sample->nextHop.type == SFLADDRESSTYPE_IP_V6 ) { + tpl->nexthop[0] = ntohll(((uint64_t *)ptr)[0]); + tpl->nexthop[1] = ntohll(((uint64_t *)ptr)[1]); + } else { + tpl->nexthop[0] = 0; + tpl->nexthop[1] = 0; + } + SetFlag(common_record->flags, FLAG_IPV6_NH); + next_data = (void *)tpl->data; + } break; + case EX_NEXT_HOP_BGP_v4: { // next hop bgp IPv4 router address + tpl_ext_11_t *tpl = (tpl_ext_11_t *)next_data; + if ( sample->bgp_nextHop.type == SFLADDRESSTYPE_IP_V4 ) { + tpl->bgp_nexthop = ntohl(sample->bgp_nextHop.address.ip_v4.addr); + } else { + tpl->bgp_nexthop = 0; + } + next_data = (void *)tpl->data; + } break; + case EX_NEXT_HOP_BGP_v6: { // next hop IPv4 router address + tpl_ext_12_t *tpl = (tpl_ext_12_t *)next_data; + void *ptr = (void *)sample->bgp_nextHop.address.ip_v6.addr; + if ( sample->bgp_nextHop.type == SFLADDRESSTYPE_IP_V6 ) { + tpl->bgp_nexthop[0] = ntohll(((uint64_t *)ptr)[0]); + tpl->bgp_nexthop[1] = ntohll(((uint64_t *)ptr)[1]); + } else { + tpl->bgp_nexthop[0] = 0; + tpl->bgp_nexthop[1] = 0; + } + SetFlag(common_record->flags, FLAG_IPV6_NHB); + next_data = (void *)tpl->data; + } break; + case EX_ROUTER_IP_v4: + case EX_ROUTER_IP_v6: // IPv4/IPv6 router address + if(sample->agent_addr.type == SFLADDRESSTYPE_IP_V4) { + tpl_ext_23_t *tpl = (tpl_ext_23_t *)next_data; + tpl->router_ip = ntohl(sample->agent_addr.address.ip_v4.addr); + next_data = (void *)tpl->data; + ClearFlag(common_record->flags, FLAG_IPV6_EXP); + } else { + tpl_ext_24_t *tpl = (tpl_ext_24_t *)next_data; + void *ptr = (void *)sample->agent_addr.address.ip_v6.addr; + tpl->router_ip[0] = ntohll(((uint64_t *)ptr)[0]); + tpl->router_ip[1] = ntohll(((uint64_t *)ptr)[1]); + next_data = (void *)tpl->data; + SetFlag(common_record->flags, FLAG_IPV6_EXP); + } + break; + case EX_RECEIVED: { + tpl_ext_27_t *tpl = (tpl_ext_27_t *)next_data; + tpl->received = (uint64_t)((uint64_t)fs->received.tv_sec * 1000LL) + (uint64_t)((uint64_t)fs->received.tv_usec / 1000LL); + next_data = (void *)tpl->data; + } break; + default: + // this should never happen + LogError("SFLOW: Unexpected extension %i for sflow record. Skip extension", id); + dbg_printf("SFLOW: Unexpected extension %i for sflow record. Skip extension", id); + } + j++; + } + + // update first_seen, last_seen + if ( _t < fs->first_seen ) // the very first time stamp need to be set + fs->first_seen = _t; + fs->last_seen = _t; + + // Update stats + switch (common_record->prot) { + case 1: + stat_record->numflows_icmp++; + stat_record->numpackets_icmp += _packets; + stat_record->numbytes_icmp += _bytes; + break; + case 6: + stat_record->numflows_tcp++; + stat_record->numpackets_tcp += _packets; + stat_record->numbytes_tcp += _bytes; + break; + case 17: + stat_record->numflows_udp++; + stat_record->numpackets_udp += _packets; + stat_record->numbytes_udp += _bytes; + break; + default: + stat_record->numflows_other++; + stat_record->numpackets_other += _packets; + stat_record->numbytes_other += _bytes; + } + exporter->flows++; + stat_record->numflows++; + stat_record->numpackets += _packets; + stat_record->numbytes += _bytes; + + if ( verbose ) { + master_record_t master_record; + char *string; + ExpandRecord_v2((common_record_t *)common_record, &exporter->sflow_extension_info[ip_flags], &(exporter->info), &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++; + fs->nffile->block_header->size += (sflow_output_record_size[ip_flags] + ipsize); +#ifdef DEVEL + if ( (next_data - fs->nffile->buff_ptr) != (sflow_output_record_size[ip_flags] + ipsize) ) { + printf("PANIC: Size error. Buffer diff: %llu, Size: %u\n", + (unsigned long long)(next_data - fs->nffile->buff_ptr), + (sflow_output_record_size[ip_flags] + ipsize)); + exit(255); + } +#endif + fs->nffile->buff_ptr = next_data; + +} + +void Init_sflow(void) { +int i, id; + + i=0; + Num_enabled_extensions = 0; + while ( (id = sflow_extensions[i]) != 0 ) { + if ( extension_descriptor[id].enabled ) { + dbg_printf("Enabled extension: %i\n", id); + Num_enabled_extensions++; + } + i++; + } + + IP_extension_mask = 0; + i=0; + while ( extension_descriptor[i].description != NULL ) { + switch (extension_descriptor[i].id) { + case EX_NEXT_HOP_v4: + // case EX_NEXT_HOP_v6: - not really needed + if ( extension_descriptor[i].enabled ) { + SetFlag(IP_extension_mask, SFLOW_NEXT_HOP); + Num_enabled_extensions++; + } break; + case EX_NEXT_HOP_BGP_v4: + // case EX_NEXT_HOP_BGP_v6: - not really needed + if ( extension_descriptor[i].enabled ) { + SetFlag(IP_extension_mask, SFLOW_NEXT_HOP_BGP); + Num_enabled_extensions++; + } break; + case EX_ROUTER_IP_v4: + // case EX_ROUTER_IP_v6: - not really needed + if ( extension_descriptor[i].enabled ) { + SetFlag(IP_extension_mask, SFLOW_ROUTER_IP); + Num_enabled_extensions++; + } break; + } + i++; + } + + dbg_printf("Num enabled Extensions: %i\n", Num_enabled_extensions); + +} // End of Init_sflow + +int Setup_Extension_Info(FlowSource_t *fs, exporter_sflow_t *exporter, int num) { +int i, id, extension_size, map_size, map_index; + + dbg_printf("Setup Extension ID 0x%x\n", num); + LogInfo("SFLOW: setup extension map %u", num); + + // prepare sflow extension map + exporter->sflow_extension_info[num].map = NULL; + extension_size = 0; + + // calculate the full extension map size + map_size = Num_enabled_extensions * sizeof(uint16_t) + sizeof(extension_map_t); + + // align 32 bits + if ( ( map_size & 0x3 ) != 0 ) + map_size += 2; + + + // Create a generic sflow extension map + exporter->sflow_extension_info[num].map = (extension_map_t *)malloc((size_t)map_size); + if ( !exporter->sflow_extension_info[num].map ) { + LogError("SFLOW: malloc() allocation error in %s line %d: %s", __FILE__, __LINE__, strerror(errno) ); + return 0; + } + + // calclate the extension size + i=0; + map_index = 0; + while ( (id = sflow_extensions[i]) != 0 ) { + if ( extension_descriptor[id].enabled ) { + extension_size += extension_descriptor[id].size; + exporter->sflow_extension_info[num].map->ex_id[map_index++] = id; + } + i++; + } + + if ( TestFlag(IP_extension_mask, SFLOW_NEXT_HOP)) { + id = sflow_ip_extensions[num].next_hop; + extension_size += extension_descriptor[id].size; + exporter->sflow_extension_info[num].map->ex_id[map_index++] = id; + } + + if ( TestFlag(IP_extension_mask, SFLOW_NEXT_HOP_BGP)) { + id = sflow_ip_extensions[num].next_hop_bgp; + extension_size += extension_descriptor[id].size; + exporter->sflow_extension_info[num].map->ex_id[map_index++] = id; + } + + if ( TestFlag(IP_extension_mask, SFLOW_ROUTER_IP)) { + id = sflow_ip_extensions[num].router_ip; + extension_size += extension_descriptor[id].size; + exporter->sflow_extension_info[num].map->ex_id[map_index++] = id; + } + + // terminating null record + exporter->sflow_extension_info[num].map->ex_id[map_index] = 0; + + dbg_printf("Extension size: %i\n", extension_size); + + // caculate the basic record size: without IP addr space ( v4/v6 dependant ) + // byte/packet counters are 32bit -> 2 x uint32_t + // extension_size contains the sum of all optional extensions + sflow_output_record_size[num] = COMMON_RECORD_DATA_SIZE + 2*sizeof(uint32_t) + extension_size; + + dbg_printf("Record size: %i\n", sflow_output_record_size[num]); + + exporter->sflow_extension_info[num].map->type = ExtensionMapType; + exporter->sflow_extension_info[num].map->size = map_size; + exporter->sflow_extension_info[num].map->map_id = INIT_ID; + exporter->sflow_extension_info[num].map->extension_size = extension_size; + + LogInfo("Extension size: %i", extension_size); + LogInfo("Extension map size: %i", map_size); + + if ( !AddExtensionMap(fs, exporter->sflow_extension_info[num].map) ) { + // bad - we must free this map and fail - otherwise data can not be read any more + free(exporter->sflow_extension_info[num].map); + exporter->sflow_extension_info[num].map = NULL; + return 0; + } + dbg_printf("New Extension map ID %i\n", exporter->sflow_extension_info[num].map->map_id); + LogInfo("New extension map id: %i", exporter->sflow_extension_info[num].map->map_id); + + return 1; + +} // End of Setup_Extension_Info + +static inline exporter_sflow_t *GetExporter(FlowSource_t *fs, uint32_t agentSubId, uint32_t meanSkipCount) { +exporter_sflow_t **e = (exporter_sflow_t **)&(fs->exporter_data); +generic_sampler_t *sampler; +#define IP_STRING_LEN 40 +char ipstr[IP_STRING_LEN]; +int i; + + // search the appropriate exporter engine + while ( *e ) { + if ( (*e)->info.id == agentSubId && (*e)->info.version == SFLOW_VERSION && + (*e)->info.ip.V6[0] == fs->ip.V6[0] && (*e)->info.ip.V6[1] == fs->ip.V6[1]) + return *e; + e = &((*e)->next); + } + + if ( fs->sa_family == AF_INET ) { + uint32_t _ip = htonl(fs->ip.V4); + inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr)); + } else if ( fs->sa_family == AF_INET6 ) { + uint64_t _ip[2]; + _ip[0] = htonll(fs->ip.V6[0]); + _ip[1] = htonll(fs->ip.V6[1]); + inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr)); + } else { + strncpy(ipstr, "", IP_STRING_LEN); + } + + // nothing found + LogInfo("SFLOW: New exporter" ); + + *e = (exporter_sflow_t *)malloc(sizeof(exporter_sflow_t)); + if ( !(*e)) { + LogError("SFLOW: malloc() error in %s line %d: %s", __FILE__, __LINE__, strerror (errno)); + return NULL; + } + memset((void *)(*e), 0, sizeof(exporter_sflow_t)); + (*e)->next = NULL; + (*e)->info.header.type = ExporterInfoRecordType; + (*e)->info.header.size = sizeof(exporter_info_record_t); + (*e)->info.version = SFLOW_VERSION; + (*e)->info.id = agentSubId; + (*e)->info.ip = fs->ip; + (*e)->info.sa_family = fs->sa_family; + (*e)->sequence_failure = 0; + (*e)->packets = 0; + (*e)->flows = 0; + for (i=0; isflow_extension_info[i].map = NULL; + } + + sampler = (generic_sampler_t *)malloc(sizeof(generic_sampler_t)); + if ( !sampler ) { + LogError("SFLOW: malloc() error in %s line %d: %s", __FILE__, __LINE__, strerror (errno)); + return NULL; + } + (*e)->sampler = sampler; + + sampler->info.header.type = SamplerInfoRecordype; + sampler->info.header.size = sizeof(sampler_info_record_t); + sampler->info.id = -1; + sampler->info.mode = 0; + sampler->info.interval = meanSkipCount; + sampler->next = NULL; + + FlushInfoExporter(fs, &((*e)->info)); + sampler->info.exporter_sysid = (*e)->info.sysid; + FlushInfoSampler(fs, &(sampler->info)); + + dbg_printf("SFLOW: New exporter: SysID: %u, agentSubId: %u, MeanSkipCount: %u, IP: %s\n", + (*e)->info.sysid, agentSubId, meanSkipCount, ipstr); + LogInfo("SFLOW: New exporter: SysID: %u, agentSubId: %u, MeanSkipCount: %u, IP: %s", + (*e)->info.sysid, agentSubId, meanSkipCount, ipstr); + + return (*e); + +} // End of GetExporter + +void Process_sflow(void *in_buff, ssize_t in_buff_cnt, FlowSource_t *fs) { + +SFSample sample; +int exceptionVal; + + memset(&sample, 0, sizeof(sample)); + sample.rawSample = in_buff; + sample.rawSampleLen = in_buff_cnt; + sample.sourceIP.s_addr = fs->sa_family == PF_INET ? htonl(fs->ip.V4) : 0;; + + dbg_printf("startDatagram =================================\n"); + if((exceptionVal = setjmp(sample.env)) == 0) { + // TRY + sample.datap = (uint32_t *)sample.rawSample; + sample.endp = (u_char *)sample.rawSample + sample.rawSampleLen; + readSFlowDatagram(&sample, fs ); + } else { + // CATCH + dbg_printf("SFLOW: caught exception: %d\n", exceptionVal); + LogError("SFLOW: caught exception: %d", exceptionVal); + } + dbg_printf("endDatagram =================================\n"); + +} // End of Process_sflow + + +// include sflow functions +// based on sflowtool https://github.com/sflow/sflowtool +// commit 7322984 on Jul 21 + +/*_________________---------------------------__________________ + _________________ read data fns __________________ + -----------------___________________________------------------ +*/ + +static uint32_t getData32_nobswap(SFSample *sample) { + uint32_t ans = *(sample->datap)++; + /* make sure we didn't run off the end of the datagram. Thanks to + Sven Eschenberg for spotting a bug/overrun-vulnerabilty that was here before. */ + if((uint8_t *)sample->datap > sample->endp) { + SFABORT(sample, SF_ABORT_EOS); + } + return ans; +} + +static uint32_t getData32(SFSample *sample) { + return ntohl(getData32_nobswap(sample)); +} + +static float getFloat(SFSample *sample) { + float fl; + uint32_t reg = getData32(sample); + memcpy(&fl, ®, 4); + return fl; +} + +static uint64_t getData64(SFSample *sample) { + uint64_t tmpLo, tmpHi; + tmpHi = getData32(sample); + tmpLo = getData32(sample); + return (tmpHi << 32) + tmpLo; +} + +static double getDouble(SFSample *sample) { + double dbl; + uint64_t reg = getData64(sample); + memcpy(&dbl, ®, 8); + return dbl; +} + +static void inline skipBytes(SFSample *sample, uint32_t skip) { + int quads = (skip + 3) / 4; + sample->datap += quads; + if(skip > sample->rawSampleLen || (uint8_t *)sample->datap > sample->endp) { + SFABORT(sample, SF_ABORT_EOS); + } +} + +static uint32_t sf_log_next32(SFSample *sample, char *fieldName) { + uint32_t val = getData32(sample); + dbg_printf("%s %u\n", fieldName, val); + return val; +} + +static uint64_t sf_log_next64(SFSample *sample, char *fieldName) { + uint64_t val64 = getData64(sample); + dbg_printf("%s %llu\n", fieldName, (unsigned long long)val64); + return val64; +} + +void sf_log_percentage(SFSample *sample, char *fieldName) +{ + uint32_t hundredths = getData32(sample); + if(hundredths == (uint32_t)-1) dbg_printf("%s unknown\n", fieldName); + else { +#ifdef DEVEL + float percent = (float)hundredths / (float)100.0; + dbg_printf("%s %.2f\n", fieldName, percent); +#endif + } +} + +static float sf_log_nextFloat(SFSample *sample, char *fieldName) { + float val = getFloat(sample); + dbg_printf("%s %.3f\n", fieldName, val); + return val; +} + +static void sf_log_nextMAC(SFSample *sample, char *fieldName) +{ +#ifdef DEVEL + uint8_t *mac = (uint8_t *)sample->datap; +#endif + skipBytes(sample, 6); + dbg_printf("%s %02x%02x%02x%02x%02x%02x\n", fieldName, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +static inline uint32_t getString(SFSample *sample, char *buf, uint32_t bufLen) { + uint32_t len, read_len; + len = getData32(sample); + /* check the bytes are there first */ + uint32_t *dp = sample->datap; + skipBytes(sample, len); + /* truncate if too long */ + read_len = (len >= bufLen) ? (bufLen - 1) : len; + memcpy(buf, dp, read_len); + buf[read_len] = '\0'; /* null terminate */ + return len; +} + +static uint32_t getAddress(SFSample *sample, SFLAddress *address) { + address->type = getData32(sample); + switch(address->type) { + case SFLADDRESSTYPE_IP_V4: + address->address.ip_v4.addr = getData32_nobswap(sample); + break; + case SFLADDRESSTYPE_IP_V6: + { + /* make sure the data is there before we memcpy */ + uint32_t *dp = sample->datap; + skipBytes(sample, 16); + memcpy(&address->address.ip_v6.addr, dp, 16); + } + break; + default: + /* undefined address type - bail out */ + LogError("SFLOW: getAddress() unknown address type = %d\n", address->type); + SFABORT(sample, SF_ABORT_EOS); + } + return address->type; +} + +static void skipTLVRecord(SFSample *sample, uint32_t tag, uint32_t len, char *description) { +#ifdef DEVEL + char buf[51]; +#endif + dbg_printf("skipping unknown %s: %s len=%d\n", description, printTag(tag, buf, 50), len); + skipBytes(sample, len); +} + +/*_________________---------------------------__________________ + _________________ readExtendedSwitch __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedSwitch(SFSample *sample) +{ + dbg_printf("extendedType SWITCH\n"); + sample->in_vlan = getData32(sample); + sample->in_priority = getData32(sample); + sample->out_vlan = getData32(sample); + sample->out_priority = getData32(sample); + + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_SWITCH; + + dbg_printf("in_vlan %u\n", sample->in_vlan); + dbg_printf("in_priority %u\n", sample->in_priority); + dbg_printf("out_vlan %u\n", sample->out_vlan); + dbg_printf("out_priority %u\n", sample->out_priority); +} + +/*_________________---------------------------__________________ + _________________ readExtendedRouter __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedRouter(SFSample *sample) +{ +#ifdef DEVEL + char buf[51]; +#endif + dbg_printf("extendedType ROUTER\n"); + getAddress(sample, &sample->nextHop); + sample->srcMask = getData32(sample); + sample->dstMask = getData32(sample); + + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_ROUTER; + + dbg_printf("nextHop %s\n", printAddress(&sample->nextHop, buf, 50)); + dbg_printf("srcSubnetMask %u\n", sample->srcMask); + dbg_printf("dstSubnetMask %u\n", sample->dstMask); +} + +/*_________________---------------------------__________________ + _________________ readExtendedGateway_v2 __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedGateway_v2(SFSample *sample) +{ + dbg_printf("extendedType GATEWAY\n"); + + sample->my_as = getData32(sample); + sample->src_as = getData32(sample); + sample->src_peer_as = getData32(sample); + + /* clear dst_peer_as and dst_as to make sure we are not + remembering values from a previous sample - (thanks Marc Lavine) */ + sample->dst_peer_as = 0; + sample->dst_as = 0; + + sample->dst_as_path_len = getData32(sample); + /* just point at the dst_as_path array */ + if(sample->dst_as_path_len > 0) { + sample->dst_as_path = sample->datap; + /* and skip over it in the input */ + skipBytes(sample, sample->dst_as_path_len * 4); + /* fill in the dst and dst_peer fields too */ + sample->dst_peer_as = ntohl(sample->dst_as_path[0]); + sample->dst_as = ntohl(sample->dst_as_path[sample->dst_as_path_len - 1]); + } + + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_GATEWAY; + + dbg_printf("my_as %u\n", sample->my_as); + dbg_printf("src_as %u\n", sample->src_as); + dbg_printf("src_peer_as %u\n", sample->src_peer_as); + dbg_printf("dst_as %u\n", sample->dst_as); + dbg_printf("dst_peer_as %u\n", sample->dst_peer_as); + dbg_printf("dst_as_path_len %u\n", sample->dst_as_path_len); + if(sample->dst_as_path_len > 0) { + uint32_t i = 0; + for(; i < sample->dst_as_path_len; i++) { + if(i == 0) dbg_printf("dst_as_path "); + else dbg_printf("-"); + dbg_printf("%u", ntohl(sample->dst_as_path[i])); + } + dbg_printf("\n"); + } +} + +/*_________________---------------------------__________________ + _________________ readExtendedGateway __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedGateway(SFSample *sample) +{ + uint32_t segments; + uint32_t seg; +#ifdef DEVEL + char buf[51]; +#endif + + dbg_printf("extendedType GATEWAY\n"); + + if(sample->datagramVersion >= 5) { + getAddress(sample, &sample->bgp_nextHop); + dbg_printf("bgp_nexthop %s\n", printAddress(&sample->bgp_nextHop, buf, 50)); + } + + sample->my_as = getData32(sample); + sample->src_as = getData32(sample); + sample->src_peer_as = getData32(sample); + dbg_printf("my_as %u\n", sample->my_as); + dbg_printf("src_as %u\n", sample->src_as); + dbg_printf("src_peer_as %u\n", sample->src_peer_as); + segments = getData32(sample); + + /* clear dst_peer_as and dst_as to make sure we are not + remembering values from a previous sample - (thanks Marc Lavine) */ + sample->dst_peer_as = 0; + sample->dst_as = 0; + + if(segments > 0) { + dbg_printf("dst_as_path "); + for(seg = 0; seg < segments; seg++) { + uint32_t seg_type; + uint32_t seg_len; + uint32_t i; + seg_type = getData32(sample); + seg_len = getData32(sample); + for(i = 0; i < seg_len; i++) { + uint32_t asNumber; + asNumber = getData32(sample); + /* mark the first one as the dst_peer_as */ + if(i == 0 && seg == 0) sample->dst_peer_as = asNumber; + else dbg_printf("-"); + /* make sure the AS sets are in parentheses */ + if(i == 0 && seg_type == SFLEXTENDED_AS_SET) dbg_printf("("); + dbg_printf("%u", asNumber); + /* mark the last one as the dst_as */ + if(seg == (segments - 1) && i == (seg_len - 1)) sample->dst_as = asNumber; + } + if(seg_type == SFLEXTENDED_AS_SET) dbg_printf(")"); + } + dbg_printf("\n"); + } + dbg_printf("dst_as %u\n", sample->dst_as); + dbg_printf("dst_peer_as %u\n", sample->dst_peer_as); + + sample->communities_len = getData32(sample); + /* just point at the communities array */ + if(sample->communities_len > 0) sample->communities = sample->datap; + /* and skip over it in the input */ + skipBytes(sample, sample->communities_len * 4); + + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_GATEWAY; + if(sample->communities_len > 0) { + uint32_t j = 0; + for(; j < sample->communities_len; j++) { + if(j == 0) dbg_printf("BGP_communities "); + else dbg_printf("-"); + dbg_printf("%u", ntohl(sample->communities[j])); + } + dbg_printf("\n"); + } + + sample->localpref = getData32(sample); + dbg_printf("BGP_localpref %u\n", sample->localpref); + +} + +/*_________________---------------------------__________________ + _________________ readExtendedUser __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedUser(SFSample *sample) +{ + dbg_printf("extendedType USER\n"); + + if(sample->datagramVersion >= 5) { + sample->src_user_charset = getData32(sample); + dbg_printf("src_user_charset %d\n", sample->src_user_charset); + } + + sample->src_user_len = getString(sample, sample->src_user, SA_MAX_EXTENDED_USER_LEN); + + if(sample->datagramVersion >= 5) { + sample->dst_user_charset = getData32(sample); + dbg_printf("dst_user_charset %d\n", sample->dst_user_charset); + } + + sample->dst_user_len = getString(sample, sample->dst_user, SA_MAX_EXTENDED_USER_LEN); + + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_USER; + + dbg_printf("src_user %s\n", sample->src_user); + dbg_printf("dst_user %s\n", sample->dst_user); +} + +/*_________________---------------------------__________________ + _________________ readExtendedUrl __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedUrl(SFSample *sample) +{ + dbg_printf("extendedType URL\n"); + + sample->url_direction = getData32(sample); + dbg_printf("url_direction %u\n", sample->url_direction); + sample->url_len = getString(sample, sample->url, SA_MAX_EXTENDED_URL_LEN); + dbg_printf("url %s\n", sample->url); + if(sample->datagramVersion >= 5) { + sample->host_len = getString(sample, sample->host, SA_MAX_EXTENDED_HOST_LEN); + dbg_printf("host %s\n", sample->host); + } + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_URL; +} + + +/*_________________---------------------------__________________ + _________________ mplsLabelStack __________________ + -----------------___________________________------------------ +*/ + +static void mplsLabelStack(SFSample *sample, char *fieldName) +{ + SFLLabelStack lstk; + uint32_t lab; + lstk.depth = getData32(sample); + /* just point at the lablelstack array */ + if(lstk.depth > 0) lstk.stack = (uint32_t *)sample->datap; + /* and skip over it in the input */ + skipBytes(sample, lstk.depth * 4); + + if(lstk.depth > 0) { + uint32_t j = 0; + for(; j < lstk.depth; j++) { + if(j == 0) dbg_printf("%s ", fieldName); + else dbg_printf("-"); + lab = ntohl(lstk.stack[j]); + dbg_printf("%u.%u.%u.%u", + (lab >> 12), /* label */ + (lab >> 9) & 7, /* experimental */ + (lab >> 8) & 1, /* bottom of stack */ + (lab & 255)); /* TTL */ + } + dbg_printf("\n"); + } +} + +/*_________________---------------------------__________________ + _________________ readExtendedMpls __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedMpls(SFSample *sample) +{ +#ifdef DEVEL + char buf[51]; +#endif + dbg_printf("extendedType MPLS\n"); + getAddress(sample, &sample->mpls_nextHop); + dbg_printf("mpls_nexthop %s\n", printAddress(&sample->mpls_nextHop, buf, 50)); + + mplsLabelStack(sample, "mpls_input_stack"); + mplsLabelStack(sample, "mpls_output_stack"); + + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS; +} + +/*_________________---------------------------__________________ + _________________ readExtendedNat __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedNat(SFSample *sample) +{ +#ifdef DEVEL + char buf[51]; +#endif + dbg_printf("extendedType NAT\n"); + getAddress(sample, &sample->nat_src); + dbg_printf("nat_src %s\n", printAddress(&sample->nat_src, buf, 50)); + getAddress(sample, &sample->nat_dst); + dbg_printf("nat_dst %s\n", printAddress(&sample->nat_dst, buf, 50)); + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_NAT; +} + +/*_________________---------------------------__________________ + _________________ readExtendedNatPort __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedNatPort(SFSample *sample) +{ + dbg_printf("extendedType NAT PORT\n"); + sf_log_next32(sample, "nat_src_port"); + sf_log_next32(sample, "nat_dst_port"); +} + + +/*_________________---------------------------__________________ + _________________ readExtendedMplsTunnel __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedMplsTunnel(SFSample *sample) +{ +#define SA_MAX_TUNNELNAME_LEN 100 + char tunnel_name[SA_MAX_TUNNELNAME_LEN+1]; + uint32_t tunnel_id, tunnel_cos; + + if(getString(sample, tunnel_name, SA_MAX_TUNNELNAME_LEN) > 0) + dbg_printf("mpls_tunnel_lsp_name %s\n", tunnel_name); + tunnel_id = getData32(sample); + dbg_printf("mpls_tunnel_id %u\n", tunnel_id); + tunnel_cos = getData32(sample); + dbg_printf("mpls_tunnel_cos %u\n", tunnel_cos); + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_TUNNEL; +} + +/*_________________---------------------------__________________ + _________________ readExtendedMplsVC __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedMplsVC(SFSample *sample) +{ +#define SA_MAX_VCNAME_LEN 100 + char vc_name[SA_MAX_VCNAME_LEN+1]; + uint32_t vll_vc_id, vc_cos; + if(getString(sample, vc_name, SA_MAX_VCNAME_LEN) > 0) + dbg_printf("mpls_vc_name %s\n", vc_name); + vll_vc_id = getData32(sample); + dbg_printf("mpls_vll_vc_id %u\n", vll_vc_id); + vc_cos = getData32(sample); + dbg_printf("mpls_vc_cos %u\n", vc_cos); + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_VC; +} + +/*_________________---------------------------__________________ + _________________ readExtendedMplsFTN __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedMplsFTN(SFSample *sample) +{ +#define SA_MAX_FTN_LEN 100 + char ftn_descr[SA_MAX_FTN_LEN+1]; + uint32_t ftn_mask; + if(getString(sample, ftn_descr, SA_MAX_FTN_LEN) > 0) + dbg_printf("mpls_ftn_descr %s\n", ftn_descr); + ftn_mask = getData32(sample); + dbg_printf("mpls_ftn_mask %u\n", ftn_mask); + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_FTN; +} + +/*_________________---------------------------__________________ + _________________ readExtendedMplsLDP_FEC __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedMplsLDP_FEC(SFSample *sample) +{ +#ifdef DEVEL + uint32_t fec_addr_prefix_len = getData32(sample); + dbg_printf("mpls_fec_addr_prefix_len %u\n", fec_addr_prefix_len); +#endif + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_LDP_FEC; +} + +/*_________________---------------------------__________________ + _________________ readExtendedVlanTunnel __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedVlanTunnel(SFSample *sample) +{ + uint32_t lab; + SFLLabelStack lstk; + lstk.depth = getData32(sample); + /* just point at the lablelstack array */ + if(lstk.depth > 0) lstk.stack = (uint32_t *)sample->datap; + /* and skip over it in the input */ + skipBytes(sample, lstk.depth * 4); + + if(lstk.depth > 0) { + uint32_t j = 0; + for(; j < lstk.depth; j++) { + if(j == 0) dbg_printf("vlan_tunnel "); + else dbg_printf("-"); + lab = ntohl(lstk.stack[j]); + dbg_printf("0x%04x.%u.%u.%u", + (lab >> 16), /* TPI */ + (lab >> 13) & 7, /* priority */ + (lab >> 12) & 1, /* CFI */ + (lab & 4095)); /* VLAN */ + } + dbg_printf("\n"); + } + sample->extended_data_tag |= SASAMPLE_EXTENDED_DATA_VLAN_TUNNEL; +} + +/*_________________---------------------------__________________ + _________________ readExtendedWifiPayload __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedWifiPayload(SFSample *sample) +{ + sf_log_next32(sample, "cipher_suite"); + readFlowSample_header(sample); +} + +/*_________________---------------------------__________________ + _________________ readExtendedWifiRx __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedWifiRx(SFSample *sample) +{ + uint32_t i; + uint8_t *bssid; + char ssid[SFL_MAX_SSID_LEN+1]; + if(getString(sample, ssid, SFL_MAX_SSID_LEN) > 0) { + dbg_printf("rx_SSID %s\n", ssid); + } + + bssid = (uint8_t *)sample->datap; + dbg_printf("rx_BSSID "); + for(i = 0; i < 6; i++) dbg_printf("%02x", bssid[i]); + dbg_printf("\n"); + skipBytes(sample, 6); + + sf_log_next32(sample, "rx_version"); + sf_log_next32(sample, "rx_channel"); + sf_log_next64(sample, "rx_speed"); + sf_log_next32(sample, "rx_rsni"); + sf_log_next32(sample, "rx_rcpi"); + sf_log_next32(sample, "rx_packet_uS"); +} + +/*_________________---------------------------__________________ + _________________ readExtendedWifiTx __________________ + -----------------___________________________------------------ +*/ + +static void readExtendedWifiTx(SFSample *sample) +{ + uint32_t i; + uint8_t *bssid; + char ssid[SFL_MAX_SSID_LEN+1]; + if(getString(sample, ssid, SFL_MAX_SSID_LEN) > 0) { + dbg_printf("tx_SSID %s\n", ssid); + } + + bssid = (uint8_t *)sample->datap; + dbg_printf("tx_BSSID "); + for(i = 0; i < 6; i++) dbg_printf("%02x", bssid[i]); + dbg_printf("\n"); + skipBytes(sample, 6); + + sf_log_next32(sample, "tx_version"); + sf_log_next32(sample, "tx_transmissions"); + sf_log_next32(sample, "tx_packet_uS"); + sf_log_next32(sample, "tx_retrans_uS"); + sf_log_next32(sample, "tx_channel"); + sf_log_next64(sample, "tx_speed"); + sf_log_next32(sample, "tx_power_mW"); +} + +/*_________________---------------------------__________________ + _________________ readExtendedAggregation __________________ + -----------------___________________________------------------ +*/ + +#if 0 /* commenting this out until its caller is uncommented too */ +static void readExtendedAggregation(SFSample *sample) +{ + uint32_t i, num_pdus = getData32(sample); + dbg_printf("aggregation_num_pdus %u\n", num_pdus); + for(i = 0; i < num_pdus; i++) { + dbg_printf("aggregation_pdu %u\n", i); + readFlowSample(sample, NO); /* not sure if this the right one here */ + } +} +#endif + +/*_________________---------------------------__________________ + _________________ readFlowSample_header __________________ + -----------------___________________________------------------ +*/ + +static void readFlowSample_header(SFSample *sample) +{ + dbg_printf("flowSampleType HEADER\n"); + sample->headerProtocol = getData32(sample); + dbg_printf("headerProtocol %u\n", sample->headerProtocol); + sample->sampledPacketSize = getData32(sample); + dbg_printf("sampledPacketSize %u\n", sample->sampledPacketSize); + if(sample->datagramVersion > 4) { + /* stripped count introduced in sFlow version 5 */ + sample->stripped = getData32(sample); + dbg_printf("strippedBytes %u\n", sample->stripped); + } + sample->headerLen = getData32(sample); + dbg_printf("headerLen %u\n", sample->headerLen); + + sample->header = (uint8_t *)sample->datap; /* just point at the header */ + skipBytes(sample, sample->headerLen); + { + char scratch[2000]; + printHex(sample->header, sample->headerLen, scratch, 2000, 0, 2000); + dbg_printf("headerBytes %s\n", scratch); + } + + switch(sample->headerProtocol) { + /* the header protocol tells us where to jump into the decode */ + case SFLHEADER_ETHERNET_ISO8023: + decodeLinkLayer(sample); + break; + case SFLHEADER_IPv4: + sample->gotIPV4 = YES; + sample->offsetToIPV4 = 0; + break; + case SFLHEADER_IPv6: + sample->gotIPV6 = YES; + sample->offsetToIPV6 = 0; + break; + case SFLHEADER_IEEE80211MAC: + decode80211MAC(sample); + break; + case SFLHEADER_ISO88024_TOKENBUS: + case SFLHEADER_ISO88025_TOKENRING: + case SFLHEADER_FDDI: + case SFLHEADER_FRAME_RELAY: + case SFLHEADER_X25: + case SFLHEADER_PPP: + case SFLHEADER_SMDS: + case SFLHEADER_AAL5: + case SFLHEADER_AAL5_IP: + case SFLHEADER_MPLS: + case SFLHEADER_POS: + case SFLHEADER_IEEE80211_AMPDU: + case SFLHEADER_IEEE80211_AMSDU_SUBFRAME: + dbg_printf("NO_DECODE headerProtocol=%d\n", sample->headerProtocol); + break; + default: + LogError("SFLOW: readFlowSample_header() undefined headerProtocol = %d\n", sample->headerProtocol); + exit(-12); + } + + if(sample->gotIPV4) { + /* report the size of the original IPPdu (including the IP header) */ + dbg_printf("IPSize %d\n", sample->sampledPacketSize - sample->stripped - sample->offsetToIPV4); + decodeIPV4(sample); + } + else if(sample->gotIPV6) { + /* report the size of the original IPPdu (including the IP header) */ + dbg_printf("IPSize %d\n", sample->sampledPacketSize - sample->stripped - sample->offsetToIPV6); + decodeIPV6(sample); + } + +} + +/*_________________---------------------------__________________ + _________________ readFlowSample_ethernet __________________ + -----------------___________________________------------------ +*/ + +static void readFlowSample_ethernet(SFSample *sample, char *prefix) +{ + uint8_t *p; + dbg_printf("flowSampleType %sETHERNET\n", prefix); + sample->eth_len = getData32(sample); + memcpy(sample->eth_src, sample->datap, 6); + skipBytes(sample, 6); + memcpy(sample->eth_dst, sample->datap, 6); + skipBytes(sample, 6); + sample->eth_type = getData32(sample); + dbg_printf("%sethernet_type %u\n", prefix, sample->eth_type); + dbg_printf("%sethernet_len %u\n", prefix, sample->eth_len); + p = sample->eth_src; + dbg_printf("%sethernet_src %02x%02x%02x%02x%02x%02x\n", prefix, p[0], p[1], p[2], p[3], p[4], p[5]); + p = sample->eth_dst; + dbg_printf("%sethernet_dst %02x%02x%02x%02x%02x%02x\n", prefix, p[0], p[1], p[2], p[3], p[4], p[5]); +} + + +/*_________________---------------------------__________________ + _________________ readFlowSample_IPv4 __________________ + -----------------___________________________------------------ +*/ + +static void readFlowSample_IPv4(SFSample *sample, char *prefix) +{ + dbg_printf("flowSampleType %sIPV4\n", prefix); + sample->headerLen = sizeof(SFLSampled_ipv4); + sample->header = (uint8_t *)sample->datap; /* just point at the header */ + skipBytes(sample, sample->headerLen); + { +#ifdef DEVEL + char buf[51]; +#endif + SFLSampled_ipv4 nfKey; + memcpy(&nfKey, sample->header, sizeof(nfKey)); + sample->sampledPacketSize = ntohl(nfKey.length); + dbg_printf("%ssampledPacketSize %u\n", prefix, sample->sampledPacketSize); + dbg_printf("%sIPSize %u\n", prefix, sample->sampledPacketSize); + sample->ipsrc.type = SFLADDRESSTYPE_IP_V4; + sample->ipsrc.address.ip_v4 = nfKey.src_ip; + sample->ipdst.type = SFLADDRESSTYPE_IP_V4; + sample->ipdst.address.ip_v4 = nfKey.dst_ip; + sample->dcd_ipProtocol = ntohl(nfKey.protocol); + sample->dcd_ipTos = ntohl(nfKey.tos); + dbg_printf("%ssrcIP %s\n", prefix, printAddress(&sample->ipsrc, buf, 50)); + dbg_printf("%sdstIP %s\n", prefix, printAddress(&sample->ipdst, buf, 50)); + dbg_printf("%sIPProtocol %u\n", prefix, sample->dcd_ipProtocol); + dbg_printf("%sIPTOS %u\n", prefix, sample->dcd_ipTos); + sample->dcd_sport = ntohl(nfKey.src_port); + sample->dcd_dport = ntohl(nfKey.dst_port); + switch(sample->dcd_ipProtocol) { + case 1: /* ICMP */ + dbg_printf("%sICMPType %u\n", prefix, sample->dcd_dport); + /* not sure about the dest port being icmp type + - might be that src port is icmp type and dest + port is icmp code. Still, have seen some + implementations where src port is 0 and dst + port is the type, so it may be safer to + assume that the destination port has the type */ + break; + case 6: /* TCP */ + dbg_printf("%sTCPSrcPort %u\n", prefix, sample->dcd_sport); + dbg_printf("%sTCPDstPort %u\n", prefix, sample->dcd_dport); + sample->dcd_tcpFlags = ntohl(nfKey.tcp_flags); + dbg_printf("%sTCPFlags %u\n", prefix, sample->dcd_tcpFlags); + break; + case 17: /* UDP */ + dbg_printf("%sUDPSrcPort %u\n", prefix, sample->dcd_sport); + dbg_printf("%sUDPDstPort %u\n", prefix, sample->dcd_dport); + break; + default: /* some other protcol */ + break; + } + } +} + +/*_________________---------------------------__________________ + _________________ readFlowSample_IPv6 __________________ + -----------------___________________________------------------ +*/ + +static void readFlowSample_IPv6(SFSample *sample, char *prefix) +{ + dbg_printf("flowSampleType %sIPV6\n", prefix); + sample->header = (uint8_t *)sample->datap; /* just point at the header */ + sample->headerLen = sizeof(SFLSampled_ipv6); + skipBytes(sample, sample->headerLen); + { +#ifdef DEVEL + char buf[51]; +#endif + SFLSampled_ipv6 nfKey6; + memcpy(&nfKey6, sample->header, sizeof(nfKey6)); + sample->sampledPacketSize = ntohl(nfKey6.length); + dbg_printf("%ssampledPacketSize %u\n", prefix, sample->sampledPacketSize); + dbg_printf("%sIPSize %u\n", prefix, sample->sampledPacketSize); + sample->ipsrc.type = SFLADDRESSTYPE_IP_V6; + memcpy(&sample->ipsrc.address.ip_v6, &nfKey6.src_ip, 16); + sample->ipdst.type = SFLADDRESSTYPE_IP_V6; + memcpy(&sample->ipdst.address.ip_v6, &nfKey6.dst_ip, 16); + sample->dcd_ipProtocol = ntohl(nfKey6.protocol); + dbg_printf("%ssrcIP6 %s\n", prefix, printAddress(&sample->ipsrc, buf, 50)); + dbg_printf("%sdstIP6 %s\n", prefix, printAddress(&sample->ipdst, buf, 50)); + dbg_printf("%sIPProtocol %u\n", prefix, sample->dcd_ipProtocol); + dbg_printf("%spriority %u\n", prefix, ntohl(nfKey6.priority)); + sample->dcd_sport = ntohl(nfKey6.src_port); + sample->dcd_dport = ntohl(nfKey6.dst_port); + switch(sample->dcd_ipProtocol) { + case 1: /* ICMP */ + dbg_printf("%sICMPType %u\n", prefix, sample->dcd_dport); + /* not sure about the dest port being icmp type + - might be that src port is icmp type and dest + port is icmp code. Still, have seen some + implementations where src port is 0 and dst + port is the type, so it may be safer to + assume that the destination port has the type */ + break; + case 6: /* TCP */ + dbg_printf("%sTCPSrcPort %u\n", prefix, sample->dcd_sport); + dbg_printf("%sTCPDstPort %u\n", prefix, sample->dcd_dport); + sample->dcd_tcpFlags = ntohl(nfKey6.tcp_flags); + dbg_printf("%sTCPFlags %u\n", prefix, sample->dcd_tcpFlags); + break; + case 17: /* UDP */ + dbg_printf("%sUDPSrcPort %u\n", prefix, sample->dcd_sport); + dbg_printf("%sUDPDstPort %u\n", prefix, sample->dcd_dport); + break; + default: /* some other protcol */ + break; + } + } +} + +/*_________________----------------------------__________________ + _________________ readFlowSample_memcache __________________ + -----------------____________________________------------------ +*/ + +static void readFlowSample_memcache(SFSample *sample) +{ + char key[SFL_MAX_MEMCACHE_KEY+1]; +#define ENC_KEY_BYTES (SFL_MAX_MEMCACHE_KEY * 3) + 1 + dbg_printf("flowSampleType memcache\n"); + sf_log_next32(sample, "memcache_op_protocol"); + sf_log_next32(sample, "memcache_op_cmd"); + if(getString(sample, key, SFL_MAX_MEMCACHE_KEY) > 0) { +#ifdef DEVEL + char enc_key[ENC_KEY_BYTES]; + dbg_printf("memcache_op_key %s\n", URLEncode(key, enc_key, ENC_KEY_BYTES)); +#endif + } + sf_log_next32(sample, "memcache_op_nkeys"); + sf_log_next32(sample, "memcache_op_value_bytes"); + sf_log_next32(sample, "memcache_op_duration_uS"); + sf_log_next32(sample, "memcache_op_status"); +} + +/*_________________----------------------------__________________ + _________________ readFlowSample_http __________________ + -----------------____________________________------------------ +*/ + +/* absorb compiler warning about strftime printing */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat" + +static void readFlowSample_http(SFSample *sample, uint32_t tag) +{ + char uri[SFL_MAX_HTTP_URI+1]; + char host[SFL_MAX_HTTP_HOST+1]; + char referrer[SFL_MAX_HTTP_REFERRER+1]; + char useragent[SFL_MAX_HTTP_USERAGENT+1]; + char xff[SFL_MAX_HTTP_XFF+1]; + char authuser[SFL_MAX_HTTP_AUTHUSER+1]; + char mimetype[SFL_MAX_HTTP_MIMETYPE+1]; + uint32_t method; + uint32_t protocol; + uint32_t status; + uint64_t req_bytes; + uint64_t resp_bytes; + + dbg_printf("flowSampleType http\n"); + method = sf_log_next32(sample, "http_method"); + protocol = sf_log_next32(sample, "http_protocol"); + if(getString(sample, uri, SFL_MAX_HTTP_URI) > 0) { + dbg_printf("http_uri %s\n", uri); + } + if(getString(sample, host, SFL_MAX_HTTP_HOST) > 0) { + dbg_printf("http_host %s\n", host); + } + if(getString(sample, referrer, SFL_MAX_HTTP_REFERRER) > 0) { + dbg_printf("http_referrer %s\n", referrer); + } + if(getString(sample, useragent, SFL_MAX_HTTP_USERAGENT) > 0) { + dbg_printf("http_useragent %s\n", useragent); + } + if(tag == SFLFLOW_HTTP2) { + if(getString(sample, xff, SFL_MAX_HTTP_XFF) > 0) { + dbg_printf("http_xff %s\n", xff); + } + } + if(getString(sample, authuser, SFL_MAX_HTTP_AUTHUSER) > 0) { + dbg_printf("http_authuser %s\n", authuser); + } + if(getString(sample, mimetype, SFL_MAX_HTTP_MIMETYPE) > 0) { + dbg_printf("http_mimetype %s\n", mimetype); + } + if(tag == SFLFLOW_HTTP2) { + req_bytes = sf_log_next64(sample, "http_request_bytes"); + } + resp_bytes = sf_log_next64(sample, "http_bytes"); + sf_log_next32(sample, "http_duration_uS"); + status = sf_log_next32(sample, "http_status"); + +// XXX +#ifdef DEVEL + { + static const char *SFHTTP_method_names[] = { "-", "OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT" }; + + time_t now = time(NULL); + char nowstr[200]; + strftime(nowstr, 200, "%d/%b/%Y:%H:%M:%S %z", localtime(&now)); /* there seems to be no simple portable equivalent to %z */ + /* should really be: snprintf(sfCLF.http_log, SFLFMT_CLF_MAX_LINE,...) but snprintf() is not always available */ + printf("- %s [%s] \"%s %s HTTP/%u.%u\" %u %llu \"%s\" \"%s\"", + authuser[0] ? authuser : "-", + nowstr, + SFHTTP_method_names[method], + uri[0] ? uri : "-", + protocol / 1000, + protocol % 1000, + status, + resp_bytes, + referrer[0] ? referrer : "-", + useragent[0] ? useragent : "-"); + } +#endif +} + +#pragma GCC diagnostic pop + +/*_________________----------------------------__________________ + _________________ readFlowSample_APP __________________ + -----------------____________________________------------------ +*/ + +static void readFlowSample_APP(SFSample *sample) +{ + char application[SFLAPP_MAX_APPLICATION_LEN]; + char operation[SFLAPP_MAX_OPERATION_LEN]; + char attributes[SFLAPP_MAX_ATTRIBUTES_LEN]; + char status[SFLAPP_MAX_STATUS_LEN]; + uint32_t status32; + + dbg_printf("flowSampleType applicationOperation\n"); + + if(getString(sample, application, SFLAPP_MAX_APPLICATION_LEN) > 0) { + dbg_printf("application %s\n", application); + } + if(getString(sample, operation, SFLAPP_MAX_OPERATION_LEN) > 0) { + dbg_printf("operation %s\n", operation); + } + if(getString(sample, attributes, SFLAPP_MAX_ATTRIBUTES_LEN) > 0) { + dbg_printf("attributes %s\n", attributes); + } + if(getString(sample, status, SFLAPP_MAX_STATUS_LEN) > 0) { + dbg_printf("status_descr %s\n", status); + } + sf_log_next64(sample, "request_bytes"); + sf_log_next64(sample, "response_bytes"); + sf_log_next32(sample, "duration_uS"); + status32 = getData32(sample); + if(status32 >= SFLAPP_NUM_STATUS_CODES) + dbg_printf("status \n", status32); + else + dbg_printf("status %s\n", SFL_APP_STATUS_names[status32]); +} + + +/*_________________----------------------------__________________ + _________________ readFlowSample_APP_CTXT __________________ + -----------------____________________________------------------ +*/ + +static void readFlowSample_APP_CTXT(SFSample *sample) +{ + char application[SFLAPP_MAX_APPLICATION_LEN]; + char operation[SFLAPP_MAX_OPERATION_LEN]; + char attributes[SFLAPP_MAX_ATTRIBUTES_LEN]; + if(getString(sample, application, SFLAPP_MAX_APPLICATION_LEN) > 0) { + dbg_printf("server_context_application %s\n", application); + } + if(getString(sample, operation, SFLAPP_MAX_OPERATION_LEN) > 0) { + dbg_printf("server_context_operation %s\n", operation); + } + if(getString(sample, attributes, SFLAPP_MAX_ATTRIBUTES_LEN) > 0) { + dbg_printf("server_context_attributes %s\n", attributes); + } +} + +/*_________________---------------------------------__________________ + _________________ readFlowSample_APP_ACTOR_INIT __________________ + -----------------_________________________________------------------ +*/ + +static void readFlowSample_APP_ACTOR_INIT(SFSample *sample) +{ + char actor[SFLAPP_MAX_ACTOR_LEN]; + if(getString(sample, actor, SFLAPP_MAX_ACTOR_LEN) > 0) { + dbg_printf("actor_initiator %s\n", actor); + } +} + +/*_________________---------------------------------__________________ + _________________ readFlowSample_APP_ACTOR_TGT __________________ + -----------------_________________________________------------------ +*/ + +static void readFlowSample_APP_ACTOR_TGT(SFSample *sample) +{ + char actor[SFLAPP_MAX_ACTOR_LEN]; + if(getString(sample, actor, SFLAPP_MAX_ACTOR_LEN) > 0) { + dbg_printf("actor_target %s\n", actor); + } +} + +/*_________________----------------------------__________________ + _________________ readExtendedSocket4 __________________ + -----------------____________________________------------------ +*/ + +static void readExtendedSocket4(SFSample *sample) +{ +#ifdef DEVEL + char buf[51]; +#endif + dbg_printf("extendedType socket4\n"); + sf_log_next32(sample, "socket4_ip_protocol"); + sample->ipsrc.type = SFLADDRESSTYPE_IP_V4; + sample->ipsrc.address.ip_v4.addr = getData32_nobswap(sample); + sample->ipdst.type = SFLADDRESSTYPE_IP_V4; + sample->ipdst.address.ip_v4.addr = getData32_nobswap(sample); + dbg_printf("socket4_local_ip %s\n", printAddress(&sample->ipsrc, buf, 50)); + dbg_printf("socket4_remote_ip %s\n", printAddress(&sample->ipdst, buf, 50)); + sf_log_next32(sample, "socket4_local_port"); + sf_log_next32(sample, "socket4_remote_port"); + +} + +/*_________________----------------------------__________________ + _________________ readExtendedProxySocket4 __________________ + -----------------____________________________------------------ +*/ + +static void readExtendedProxySocket4(SFSample *sample) +{ +#ifdef DEVEL + char buf[51]; +#endif + SFLAddress ipsrc,ipdst; + dbg_printf("extendedType proxy_socket4\n"); + sf_log_next32(sample, "proxy_socket4_ip_protocol"); + ipsrc.type = SFLADDRESSTYPE_IP_V4; + ipsrc.address.ip_v4.addr = getData32_nobswap(sample); + ipdst.type = SFLADDRESSTYPE_IP_V4; + ipdst.address.ip_v4.addr = getData32_nobswap(sample); + dbg_printf("proxy_socket4_local_ip %s\n", printAddress(&ipsrc, buf, 50)); + dbg_printf("proxy_socket4_remote_ip %s\n", printAddress(&ipdst, buf, 50)); + sf_log_next32(sample, "proxy_socket4_local_port"); + sf_log_next32(sample, "proxy_socket4_remote_port"); +} + +/*_________________----------------------------__________________ + _________________ readExtendedSocket6 __________________ + -----------------____________________________------------------ +*/ + +static void readExtendedSocket6(SFSample *sample) +{ +#ifdef DEVEL + char buf[51]; +#endif + dbg_printf("extendedType socket6\n"); + sf_log_next32(sample, "socket6_ip_protocol"); + sample->ipsrc.type = SFLADDRESSTYPE_IP_V6; + memcpy(&sample->ipsrc.address.ip_v6, sample->datap, 16); + skipBytes(sample, 16); + sample->ipdst.type = SFLADDRESSTYPE_IP_V6; + memcpy(&sample->ipdst.address.ip_v6, sample->datap, 16); + skipBytes(sample, 16); + dbg_printf("socket6_local_ip %s\n", printAddress(&sample->ipsrc, buf, 50)); + dbg_printf("socket6_remote_ip %s\n", printAddress(&sample->ipdst, buf, 50)); + sf_log_next32(sample, "socket6_local_port"); + sf_log_next32(sample, "socket6_remote_port"); + +} + +/*_________________----------------------------__________________ + _________________ readExtendedProxySocket6 __________________ + -----------------____________________________------------------ +*/ + +static void readExtendedProxySocket6(SFSample *sample) +{ +#ifdef DEVEL + char buf[51]; +#endif + SFLAddress ipsrc, ipdst; + dbg_printf("extendedType proxy_socket6\n"); + sf_log_next32(sample, "proxy_socket6_ip_protocol"); + ipsrc.type = SFLADDRESSTYPE_IP_V6; + memcpy(&ipsrc.address.ip_v6, sample->datap, 16); + skipBytes(sample, 16); + ipdst.type = SFLADDRESSTYPE_IP_V6; + memcpy(&ipdst.address.ip_v6, sample->datap, 16); + skipBytes(sample, 16); + dbg_printf("proxy_socket6_local_ip %s\n", printAddress(&ipsrc, buf, 50)); + dbg_printf("proxy_socket6_remote_ip %s\n", printAddress(&ipdst, buf, 50)); + sf_log_next32(sample, "proxy_socket6_local_port"); + sf_log_next32(sample, "proxy_socket6_remote_port"); +} + +/*_________________----------------------------__________________ + _________________ readExtendedDecap __________________ + -----------------____________________________------------------ +*/ + +static void readExtendedDecap(SFSample *sample, char *prefix) +{ +#ifdef DEVEL + uint32_t offset = getData32(sample); + dbg_printf("extendedType %sdecap\n", prefix); + dbg_printf("%sdecap_inner_header_offset %u\n", prefix, offset); +#endif +} + +/*_________________----------------------------__________________ + _________________ readExtendedVNI __________________ + -----------------____________________________------------------ +*/ + +static void readExtendedVNI(SFSample *sample, char *prefix) +{ +#ifdef DEVEL + uint32_t vni = getData32(sample); + dbg_printf("extendedType %sVNI\n", prefix); + dbg_printf("%sVNI %u\n", prefix, vni); +#endif +} + +/*_________________----------------------------__________________ + _________________ readExtendedTCPInfo __________________ + -----------------____________________________------------------ +*/ + +static void readExtendedTCPInfo(SFSample *sample) +{ + char *direction; + EnumPktDirection dirn = getData32(sample); + switch(dirn) { + case PKTDIR_unknown: direction = "unknown"; break; + case PKTDIR_received: direction = "received"; break; + case PKTDIR_sent: direction = "sent"; break; + default: direction = ""; break; + } + dbg_printf( "tcpinfo_direction %s\n", direction); + sf_log_next32(sample, "tcpinfo_send_mss"); + sf_log_next32(sample, "tcpinfo_receive_mss"); + sf_log_next32(sample, "tcpinfo_unacked_pkts"); + sf_log_next32(sample, "tcpinfo_lost_pkts"); + sf_log_next32(sample, "tcpinfo_retrans_pkts"); + sf_log_next32(sample, "tcpinfo_path_mtu"); + sf_log_next32(sample, "tcpinfo_rtt_uS"); + sf_log_next32(sample, "tcpinfo_rtt_uS_var"); + sf_log_next32(sample, "tcpinfo_send_congestion_win"); + sf_log_next32(sample, "tcpinfo_reordering"); + sf_log_next32(sample, "tcpinfo_rtt_uS_min"); +} + +/*_________________---------------------------__________________ + _________________ readFlowSample_v2v4 __________________ + -----------------___________________________------------------ +*/ + +static void readFlowSample_v2v4(SFSample *sample, FlowSource_t *fs) +{ + dbg_printf("sampleType FLOWSAMPLE\n"); + + sample->samplesGenerated = getData32(sample); + dbg_printf("sampleSequenceNo %u\n", sample->samplesGenerated); + { + uint32_t samplerId = getData32(sample); + sample->ds_class = samplerId >> 24; + sample->ds_index = samplerId & 0x00ffffff; + dbg_printf("sourceId %u:%u\n", sample->ds_class, sample->ds_index); + } + + sample->meanSkipCount = getData32(sample); + sample->samplePool = getData32(sample); + sample->dropEvents = getData32(sample); + sample->inputPort = getData32(sample); + sample->outputPort = getData32(sample); + dbg_printf("meanSkipCount %u\n", sample->meanSkipCount); + dbg_printf("samplePool %u\n", sample->samplePool); + dbg_printf("dropEvents %u\n", sample->dropEvents); + dbg_printf("inputPort %u\n", sample->inputPort); + if(sample->outputPort & 0x80000000) { + uint32_t numOutputs = sample->outputPort & 0x7fffffff; + if(numOutputs > 0) dbg_printf("outputPort multiple %d\n", numOutputs); + else dbg_printf("outputPort multiple >1\n"); + } + else dbg_printf("outputPort %u\n", sample->outputPort); + + sample->packet_data_tag = getData32(sample); + + switch(sample->packet_data_tag) { + + case INMPACKETTYPE_HEADER: readFlowSample_header(sample); break; + case INMPACKETTYPE_IPV4: + sample->gotIPV4Struct = YES; + readFlowSample_IPv4(sample, ""); + break; + case INMPACKETTYPE_IPV6: + sample->gotIPV6Struct = YES; + readFlowSample_IPv6(sample, ""); + break; + default: receiveError(sample, "unexpected packet_data_tag", YES); break; + } + + sample->extended_data_tag = 0; + { + uint32_t x; + sample->num_extended = getData32(sample); + for(x = 0; x < sample->num_extended; x++) { + uint32_t extended_tag; + extended_tag = getData32(sample); + switch(extended_tag) { + case INMEXTENDED_SWITCH: readExtendedSwitch(sample); break; + case INMEXTENDED_ROUTER: readExtendedRouter(sample); break; + case INMEXTENDED_GATEWAY: + if(sample->datagramVersion == 2) readExtendedGateway_v2(sample); + else readExtendedGateway(sample); + break; + case INMEXTENDED_USER: readExtendedUser(sample); break; + case INMEXTENDED_URL: readExtendedUrl(sample); break; + default: receiveError(sample, "unrecognized extended data tag", YES); break; + } + } + } + + if(sample->gotIPV4 || sample->gotIPV6) + StoreSflowRecord(sample, fs); + + if ( verbose ) + writeFlowLine(sample); + +} + +/*_________________---------------------------__________________ + _________________ readFlowSample __________________ + -----------------___________________________------------------ +*/ + +static void readFlowSample(SFSample *sample, int expanded, FlowSource_t *fs) +{ + uint32_t num_elements, sampleLength; + uint8_t *sampleStart; + + dbg_printf("sampleType FLOWSAMPLE\n"); + sampleLength = getData32(sample); + sampleStart = (uint8_t *)sample->datap; + sample->samplesGenerated = getData32(sample); + dbg_printf("sampleSequenceNo %u\n", sample->samplesGenerated); + if(expanded) { + sample->ds_class = getData32(sample); + sample->ds_index = getData32(sample); + } + else { + uint32_t samplerId = getData32(sample); + sample->ds_class = samplerId >> 24; + sample->ds_index = samplerId & 0x00ffffff; + } + dbg_printf("sourceId %u:%u\n", sample->ds_class, sample->ds_index); + + sample->meanSkipCount = getData32(sample); + sample->samplePool = getData32(sample); + sample->dropEvents = getData32(sample); + dbg_printf("meanSkipCount %u\n", sample->meanSkipCount); + dbg_printf("samplePool %u\n", sample->samplePool); + dbg_printf("dropEvents %u\n", sample->dropEvents); + if(expanded) { + sample->inputPortFormat = getData32(sample); + sample->inputPort = getData32(sample); + sample->outputPortFormat = getData32(sample); + sample->outputPort = getData32(sample); + } + else { + uint32_t inp, outp; + inp = getData32(sample); + outp = getData32(sample); + sample->inputPortFormat = inp >> 30; + sample->outputPortFormat = outp >> 30; + sample->inputPort = inp & 0x3fffffff; + sample->outputPort = outp & 0x3fffffff; + } + + switch(sample->inputPortFormat) { + case 3: dbg_printf("inputPort format==3 %u\n", sample->inputPort); break; + case 2: dbg_printf("inputPort multiple %u\n", sample->inputPort); break; + case 1: dbg_printf("inputPort dropCode %u\n", sample->inputPort); break; + case 0: dbg_printf("inputPort %u\n", sample->inputPort); break; + } + + switch(sample->outputPortFormat) { + case 3: dbg_printf("outputPort format==3 %u\n", sample->outputPort); break; + case 2: dbg_printf("outputPort multiple %u\n", sample->outputPort); break; + case 1: dbg_printf("outputPort dropCode %u\n", sample->outputPort); break; + case 0: dbg_printf("outputPort %u\n", sample->outputPort); break; + } + + num_elements = getData32(sample); + { + uint32_t el; + for(el = 0; el < num_elements; el++) { + uint32_t tag, length; + uint8_t *start; +#ifdef DEVEL + char buf[51]; +#endif + tag = sample->elementType = getData32(sample); + dbg_printf("flowBlock_tag %s\n", printTag(tag, buf, 50)); + length = getData32(sample); + start = (uint8_t *)sample->datap; + + switch(tag) { + case SFLFLOW_HEADER: readFlowSample_header(sample); break; + case SFLFLOW_ETHERNET: readFlowSample_ethernet(sample, ""); break; + case SFLFLOW_IPV4: readFlowSample_IPv4(sample, ""); break; + case SFLFLOW_IPV6: readFlowSample_IPv6(sample, ""); break; + case SFLFLOW_MEMCACHE: readFlowSample_memcache(sample); break; + case SFLFLOW_HTTP: readFlowSample_http(sample, tag); break; + case SFLFLOW_HTTP2: readFlowSample_http(sample, tag); break; + case SFLFLOW_APP: readFlowSample_APP(sample); break; + case SFLFLOW_APP_CTXT: readFlowSample_APP_CTXT(sample); break; + case SFLFLOW_APP_ACTOR_INIT: readFlowSample_APP_ACTOR_INIT(sample); break; + case SFLFLOW_APP_ACTOR_TGT: readFlowSample_APP_ACTOR_TGT(sample); break; + case SFLFLOW_EX_SWITCH: readExtendedSwitch(sample); break; + case SFLFLOW_EX_ROUTER: readExtendedRouter(sample); break; + case SFLFLOW_EX_GATEWAY: readExtendedGateway(sample); break; + case SFLFLOW_EX_USER: readExtendedUser(sample); break; + case SFLFLOW_EX_URL: readExtendedUrl(sample); break; + case SFLFLOW_EX_MPLS: readExtendedMpls(sample); break; + case SFLFLOW_EX_NAT: readExtendedNat(sample); break; + case SFLFLOW_EX_NAT_PORT: readExtendedNatPort(sample); break; + case SFLFLOW_EX_MPLS_TUNNEL: readExtendedMplsTunnel(sample); break; + case SFLFLOW_EX_MPLS_VC: readExtendedMplsVC(sample); break; + case SFLFLOW_EX_MPLS_FTN: readExtendedMplsFTN(sample); break; + case SFLFLOW_EX_MPLS_LDP_FEC: readExtendedMplsLDP_FEC(sample); break; + case SFLFLOW_EX_VLAN_TUNNEL: readExtendedVlanTunnel(sample); break; + case SFLFLOW_EX_80211_PAYLOAD: readExtendedWifiPayload(sample); break; + case SFLFLOW_EX_80211_RX: readExtendedWifiRx(sample); break; + case SFLFLOW_EX_80211_TX: readExtendedWifiTx(sample); break; + /* case SFLFLOW_EX_AGGREGATION: readExtendedAggregation(sample); break; */ + case SFLFLOW_EX_SOCKET4: readExtendedSocket4(sample); break; + case SFLFLOW_EX_SOCKET6: readExtendedSocket6(sample); break; + case SFLFLOW_EX_PROXYSOCKET4: readExtendedProxySocket4(sample); break; + case SFLFLOW_EX_PROXYSOCKET6: readExtendedProxySocket6(sample); break; + case SFLFLOW_EX_L2_TUNNEL_OUT: readFlowSample_ethernet(sample, "tunnel_l2_out_"); break; + case SFLFLOW_EX_L2_TUNNEL_IN: readFlowSample_ethernet(sample, "tunnel_l2_in_"); break; + case SFLFLOW_EX_IPV4_TUNNEL_OUT: readFlowSample_IPv4(sample, "tunnel_ipv4_out_"); break; + case SFLFLOW_EX_IPV4_TUNNEL_IN: readFlowSample_IPv4(sample, "tunnel_ipv4_in_"); break; + case SFLFLOW_EX_IPV6_TUNNEL_OUT: readFlowSample_IPv6(sample, "tunnel_ipv6_out_"); break; + case SFLFLOW_EX_IPV6_TUNNEL_IN: readFlowSample_IPv6(sample, "tunnel_ipv6_in_"); break; + case SFLFLOW_EX_DECAP_OUT: readExtendedDecap(sample, "out_"); break; + case SFLFLOW_EX_DECAP_IN: readExtendedDecap(sample, "in_"); break; + case SFLFLOW_EX_VNI_OUT: readExtendedVNI(sample, "out_"); break; + case SFLFLOW_EX_VNI_IN: readExtendedVNI(sample, "in_"); break; + case SFLFLOW_EX_TCP_INFO: readExtendedTCPInfo(sample); break; + default: skipTLVRecord(sample, tag, length, "flow_sample_element"); break; + } + lengthCheck(sample, "flow_sample_element", start, length); + } + } + lengthCheck(sample, "flow_sample", sampleStart, sampleLength); + + if ( sample->gotIPV4 || sample->gotIPV6 ) + StoreSflowRecord(sample, fs); + + /* or line-by-line output... */ + if ( verbose ) + writeFlowLine(sample); + +} + +/*_________________---------------------------__________________ + _________________ readCounters_generic __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_generic(SFSample *sample) +{ + /* the first part of the generic counters block is really just more info about the interface. */ + sample->ifCounters.ifIndex = sf_log_next32(sample, "ifIndex"); + sample->ifCounters.ifType = sf_log_next32(sample, "networkType"); + sample->ifCounters.ifSpeed = sf_log_next64(sample, "ifSpeed"); + sample->ifCounters.ifDirection = sf_log_next32(sample, "ifDirection"); + sample->ifCounters.ifStatus = sf_log_next32(sample, "ifStatus"); + /* the generic counters always come first */ + sample->ifCounters.ifInOctets = sf_log_next64(sample, "ifInOctets"); + sample->ifCounters.ifInUcastPkts = sf_log_next32(sample, "ifInUcastPkts"); + sample->ifCounters.ifInMulticastPkts = sf_log_next32(sample, "ifInMulticastPkts"); + sample->ifCounters.ifInBroadcastPkts = sf_log_next32(sample, "ifInBroadcastPkts"); + sample->ifCounters.ifInDiscards = sf_log_next32(sample, "ifInDiscards"); + sample->ifCounters.ifInErrors = sf_log_next32(sample, "ifInErrors"); + sample->ifCounters.ifInUnknownProtos = sf_log_next32(sample, "ifInUnknownProtos"); + sample->ifCounters.ifOutOctets = sf_log_next64(sample, "ifOutOctets"); + sample->ifCounters.ifOutUcastPkts = sf_log_next32(sample, "ifOutUcastPkts"); + sample->ifCounters.ifOutMulticastPkts = sf_log_next32(sample, "ifOutMulticastPkts"); + sample->ifCounters.ifOutBroadcastPkts = sf_log_next32(sample, "ifOutBroadcastPkts"); + sample->ifCounters.ifOutDiscards = sf_log_next32(sample, "ifOutDiscards"); + sample->ifCounters.ifOutErrors = sf_log_next32(sample, "ifOutErrors"); + sample->ifCounters.ifPromiscuousMode = sf_log_next32(sample, "ifPromiscuousMode"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_ethernet __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_ethernet(SFSample *sample) +{ + sf_log_next32(sample, "dot3StatsAlignmentErrors"); + sf_log_next32(sample, "dot3StatsFCSErrors"); + sf_log_next32(sample, "dot3StatsSingleCollisionFrames"); + sf_log_next32(sample, "dot3StatsMultipleCollisionFrames"); + sf_log_next32(sample, "dot3StatsSQETestErrors"); + sf_log_next32(sample, "dot3StatsDeferredTransmissions"); + sf_log_next32(sample, "dot3StatsLateCollisions"); + sf_log_next32(sample, "dot3StatsExcessiveCollisions"); + sf_log_next32(sample, "dot3StatsInternalMacTransmitErrors"); + sf_log_next32(sample, "dot3StatsCarrierSenseErrors"); + sf_log_next32(sample, "dot3StatsFrameTooLongs"); + sf_log_next32(sample, "dot3StatsInternalMacReceiveErrors"); + sf_log_next32(sample, "dot3StatsSymbolErrors"); +} + + +/*_________________---------------------------__________________ + _________________ readCounters_tokenring __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_tokenring(SFSample *sample) +{ + sf_log_next32(sample, "dot5StatsLineErrors"); + sf_log_next32(sample, "dot5StatsBurstErrors"); + sf_log_next32(sample, "dot5StatsACErrors"); + sf_log_next32(sample, "dot5StatsAbortTransErrors"); + sf_log_next32(sample, "dot5StatsInternalErrors"); + sf_log_next32(sample, "dot5StatsLostFrameErrors"); + sf_log_next32(sample, "dot5StatsReceiveCongestions"); + sf_log_next32(sample, "dot5StatsFrameCopiedErrors"); + sf_log_next32(sample, "dot5StatsTokenErrors"); + sf_log_next32(sample, "dot5StatsSoftErrors"); + sf_log_next32(sample, "dot5StatsHardErrors"); + sf_log_next32(sample, "dot5StatsSignalLoss"); + sf_log_next32(sample, "dot5StatsTransmitBeacons"); + sf_log_next32(sample, "dot5StatsRecoverys"); + sf_log_next32(sample, "dot5StatsLobeWires"); + sf_log_next32(sample, "dot5StatsRemoves"); + sf_log_next32(sample, "dot5StatsSingles"); + sf_log_next32(sample, "dot5StatsFreqErrors"); +} + + +/*_________________---------------------------__________________ + _________________ readCounters_vg __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_vg(SFSample *sample) +{ + sf_log_next32(sample, "dot12InHighPriorityFrames"); + sf_log_next64(sample, "dot12InHighPriorityOctets"); + sf_log_next32(sample, "dot12InNormPriorityFrames"); + sf_log_next64(sample, "dot12InNormPriorityOctets"); + sf_log_next32(sample, "dot12InIPMErrors"); + sf_log_next32(sample, "dot12InOversizeFrameErrors"); + sf_log_next32(sample, "dot12InDataErrors"); + sf_log_next32(sample, "dot12InNullAddressedFrames"); + sf_log_next32(sample, "dot12OutHighPriorityFrames"); + sf_log_next64(sample, "dot12OutHighPriorityOctets"); + sf_log_next32(sample, "dot12TransitionIntoTrainings"); + sf_log_next64(sample, "dot12HCInHighPriorityOctets"); + sf_log_next64(sample, "dot12HCInNormPriorityOctets"); + sf_log_next64(sample, "dot12HCOutHighPriorityOctets"); +} + + + +/*_________________---------------------------__________________ + _________________ readCounters_vlan __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_vlan(SFSample *sample) +{ + sample->in_vlan = getData32(sample); + dbg_printf("in_vlan %u\n", sample->in_vlan); + sf_log_next64(sample, "octets"); + sf_log_next32(sample, "ucastPkts"); + sf_log_next32(sample, "multicastPkts"); + sf_log_next32(sample, "broadcastPkts"); + sf_log_next32(sample, "discards"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_80211 __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_80211(SFSample *sample) +{ + sf_log_next32(sample, "dot11TransmittedFragmentCount"); + sf_log_next32(sample, "dot11MulticastTransmittedFrameCount"); + sf_log_next32(sample, "dot11FailedCount"); + sf_log_next32(sample, "dot11RetryCount"); + sf_log_next32(sample, "dot11MultipleRetryCount"); + sf_log_next32(sample, "dot11FrameDuplicateCount"); + sf_log_next32(sample, "dot11RTSSuccessCount"); + sf_log_next32(sample, "dot11RTSFailureCount"); + sf_log_next32(sample, "dot11ACKFailureCount"); + sf_log_next32(sample, "dot11ReceivedFragmentCount"); + sf_log_next32(sample, "dot11MulticastReceivedFrameCount"); + sf_log_next32(sample, "dot11FCSErrorCount"); + sf_log_next32(sample, "dot11TransmittedFrameCount"); + sf_log_next32(sample, "dot11WEPUndecryptableCount"); + sf_log_next32(sample, "dot11QoSDiscardedFragmentCount"); + sf_log_next32(sample, "dot11AssociatedStationCount"); + sf_log_next32(sample, "dot11QoSCFPollsReceivedCount"); + sf_log_next32(sample, "dot11QoSCFPollsUnusedCount"); + sf_log_next32(sample, "dot11QoSCFPollsUnusableCount"); + sf_log_next32(sample, "dot11QoSCFPollsLostCount"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_processor __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_processor(SFSample *sample) +{ + sf_log_percentage(sample, "5s_cpu"); + sf_log_percentage(sample, "1m_cpu"); + sf_log_percentage(sample, "5m_cpu"); + sf_log_next64(sample, "total_memory_bytes"); + sf_log_next64(sample, "free_memory_bytes"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_radio __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_radio(SFSample *sample) +{ + sf_log_next32(sample, "radio_elapsed_time"); + sf_log_next32(sample, "radio_on_channel_time"); + sf_log_next32(sample, "radio_on_channel_busy_time"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_OFPort __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_OFPort(SFSample *sample) +{ +#ifdef DEVEL + uint64_t dpid = getData64(sample); + dbg_printf( "openflow_datapath_id %llx\n", dpid); +#endif + sf_log_next32(sample, "openflow_port"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_portName __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_portName(SFSample *sample) +{ + char ifname[SFL_MAX_PORTNAME_LEN+1]; + if(getString(sample, ifname, SFL_MAX_PORTNAME_LEN) > 0) { + dbg_printf("ifName %s\n", ifname); + } +} + +/*_________________---------------------------__________________ + _________________ readCounters_OVSDP __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_OVSDP(SFSample *sample) +{ + sf_log_next32(sample, "OVS_dp_hits"); + sf_log_next32(sample, "OVS_dp_misses"); + sf_log_next32(sample, "OVS_dp_lost"); + sf_log_next32(sample, "OVS_dp_mask_hits"); + sf_log_next32(sample, "OVS_dp_flows"); + sf_log_next32(sample, "OVS_dp_masks"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_host_hid __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_hid(SFSample *sample) +{ + uint8_t *uuid; + char hostname[SFL_MAX_HOSTNAME_LEN+1]; + char os_release[SFL_MAX_OSRELEASE_LEN+1]; + char uuidStr[100]; + if(getString(sample, hostname, SFL_MAX_HOSTNAME_LEN) > 0) { + dbg_printf("hostname %s\n", hostname); + } + uuid = (uint8_t *)sample->datap; + printUUID(uuid, uuidStr, 100); + dbg_printf("UUID %s\n", uuidStr); + skipBytes(sample, 16); + sf_log_next32(sample, "machine_type"); + sf_log_next32(sample, "os_name"); + if(getString(sample, os_release, SFL_MAX_OSRELEASE_LEN) > 0) { + dbg_printf("os_release %s\n", os_release); + } +} + +/*_________________---------------------------__________________ + _________________ readCounters_adaptors __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_adaptors(SFSample *sample) +{ + uint8_t *mac; + uint32_t i, j, ifindex, num_macs, num_adaptors = getData32(sample); + for(i = 0; i < num_adaptors; i++) { + ifindex = getData32(sample); + dbg_printf("adaptor_%u_ifIndex %u\n", i, ifindex); + num_macs = getData32(sample); + dbg_printf("adaptor_%u_MACs %u\n", i, num_macs); + for(j = 0; j < num_macs; j++) { + mac = (uint8_t *)sample->datap; + dbg_printf("adaptor_%u_MAC_%u %02x%02x%02x%02x%02x%02x\n", + i, j, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + skipBytes(sample, 8); + } + } +} + + +/*_________________----------------------------__________________ + _________________ readCounters_host_parent __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_host_parent(SFSample *sample) +{ + sf_log_next32(sample, "parent_dsClass"); + sf_log_next32(sample, "parent_dsIndex"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_host_cpu __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_cpu(SFSample *sample, uint32_t length) +{ + sf_log_nextFloat(sample, "cpu_load_one"); + sf_log_nextFloat(sample, "cpu_load_five"); + sf_log_nextFloat(sample, "cpu_load_fifteen"); + sf_log_next32(sample, "cpu_proc_run"); + sf_log_next32(sample, "cpu_proc_total"); + sf_log_next32(sample, "cpu_num"); + sf_log_next32(sample, "cpu_speed"); + sf_log_next32(sample, "cpu_uptime"); + sf_log_next32(sample, "cpu_user"); + sf_log_next32(sample, "cpu_nice"); + sf_log_next32(sample, "cpu_system"); + sf_log_next32(sample, "cpu_idle"); + sf_log_next32(sample, "cpu_wio"); + sf_log_next32(sample, "cpuintr"); + sf_log_next32(sample, "cpu_sintr"); + sf_log_next32(sample, "cpuinterrupts"); + sf_log_next32(sample, "cpu_contexts"); + if(length > 68) { + /* these three fields were added in December 2014 */ + sf_log_next32(sample, "cpu_steal"); + sf_log_next32(sample, "cpu_guest"); + sf_log_next32(sample, "cpu_guest_nice"); + } +} + +/*_________________---------------------------__________________ + _________________ readCounters_host_mem __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_mem(SFSample *sample) +{ + sf_log_next64(sample, "mem_total"); + sf_log_next64(sample, "mem_free"); + sf_log_next64(sample, "mem_shared"); + sf_log_next64(sample, "mem_buffers"); + sf_log_next64(sample, "mem_cached"); + sf_log_next64(sample, "swap_total"); + sf_log_next64(sample, "swap_free"); + sf_log_next32(sample, "page_in"); + sf_log_next32(sample, "page_out"); + sf_log_next32(sample, "swap_in"); + sf_log_next32(sample, "swap_out"); +} + + +/*_________________---------------------------__________________ + _________________ readCounters_host_dsk __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_dsk(SFSample *sample) +{ + sf_log_next64(sample, "disk_total"); + sf_log_next64(sample, "disk_free"); + sf_log_percentage(sample, "disk_partition_max_used"); + sf_log_next32(sample, "disk_reads"); + sf_log_next64(sample, "disk_bytes_read"); + sf_log_next32(sample, "disk_read_time"); + sf_log_next32(sample, "disk_writes"); + sf_log_next64(sample, "disk_bytes_written"); + sf_log_next32(sample, "disk_write_time"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_host_nio __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_nio(SFSample *sample) +{ + sf_log_next64(sample, "nio_bytes_in"); + sf_log_next32(sample, "nio_pkts_in"); + sf_log_next32(sample, "nio_errs_in"); + sf_log_next32(sample, "nio_drops_in"); + sf_log_next64(sample, "nio_bytes_out"); + sf_log_next32(sample, "nio_pkts_out"); + sf_log_next32(sample, "nio_errs_out"); + sf_log_next32(sample, "nio_drops_out"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_host_ip __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_ip(SFSample *sample) +{ + sf_log_next32(sample, "ipForwarding"); + sf_log_next32(sample, "ipDefaultTTL"); + sf_log_next32(sample, "ipInReceives"); + sf_log_next32(sample, "ipInHdrErrors"); + sf_log_next32(sample, "ipInAddrErrors"); + sf_log_next32(sample, "ipForwDatagrams"); + sf_log_next32(sample, "ipInUnknownProtos"); + sf_log_next32(sample, "ipInDiscards"); + sf_log_next32(sample, "ipInDelivers"); + sf_log_next32(sample, "ipOutRequests"); + sf_log_next32(sample, "ipOutDiscards"); + sf_log_next32(sample, "ipOutNoRoutes"); + sf_log_next32(sample, "ipReasmTimeout"); + sf_log_next32(sample, "ipReasmReqds"); + sf_log_next32(sample, "ipReasmOKs"); + sf_log_next32(sample, "ipReasmFails"); + sf_log_next32(sample, "ipFragOKs"); + sf_log_next32(sample, "ipFragFails"); + sf_log_next32(sample, "ipFragCreates"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_host_icmp __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_icmp(SFSample *sample) +{ + sf_log_next32(sample, "icmpInMsgs"); + sf_log_next32(sample, "icmpInErrors"); + sf_log_next32(sample, "icmpInDestUnreachs"); + sf_log_next32(sample, "icmpInTimeExcds"); + sf_log_next32(sample, "icmpInParamProbs"); + sf_log_next32(sample, "icmpInSrcQuenchs"); + sf_log_next32(sample, "icmpInRedirects"); + sf_log_next32(sample, "icmpInEchos"); + sf_log_next32(sample, "icmpInEchoReps"); + sf_log_next32(sample, "icmpInTimestamps"); + sf_log_next32(sample, "icmpInAddrMasks"); + sf_log_next32(sample, "icmpInAddrMaskReps"); + sf_log_next32(sample, "icmpOutMsgs"); + sf_log_next32(sample, "icmpOutErrors"); + sf_log_next32(sample, "icmpOutDestUnreachs"); + sf_log_next32(sample, "icmpOutTimeExcds"); + sf_log_next32(sample, "icmpOutParamProbs"); + sf_log_next32(sample, "icmpOutSrcQuenchs"); + sf_log_next32(sample, "icmpOutRedirects"); + sf_log_next32(sample, "icmpOutEchos"); + sf_log_next32(sample, "icmpOutEchoReps"); + sf_log_next32(sample, "icmpOutTimestamps"); + sf_log_next32(sample, "icmpOutTimestampReps"); + sf_log_next32(sample, "icmpOutAddrMasks"); + sf_log_next32(sample, "icmpOutAddrMaskReps"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_host_tcp __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_tcp(SFSample *sample) +{ + sf_log_next32(sample, "tcpRtoAlgorithm"); + sf_log_next32(sample, "tcpRtoMin"); + sf_log_next32(sample, "tcpRtoMax"); + sf_log_next32(sample, "tcpMaxConn"); + sf_log_next32(sample, "tcpActiveOpens"); + sf_log_next32(sample, "tcpPassiveOpens"); + sf_log_next32(sample, "tcpAttemptFails"); + sf_log_next32(sample, "tcpEstabResets"); + sf_log_next32(sample, "tcpCurrEstab"); + sf_log_next32(sample, "tcpInSegs"); + sf_log_next32(sample, "tcpOutSegs"); + sf_log_next32(sample, "tcpRetransSegs"); + sf_log_next32(sample, "tcpInErrs"); + sf_log_next32(sample, "tcpOutRsts"); + sf_log_next32(sample, "tcpInCsumErrors"); +} + +/*_________________---------------------------__________________ + _________________ readCounters_host_udp __________________ + -----------------___________________________------------------ +*/ + +static void readCounters_host_udp(SFSample *sample) +{ + sf_log_next32(sample, "udpInDatagrams"); + sf_log_next32(sample, "udpNoPorts"); + sf_log_next32(sample, "udpInErrors"); + sf_log_next32(sample, "udpOutDatagrams"); + sf_log_next32(sample, "udpRcvbufErrors"); + sf_log_next32(sample, "udpSndbufErrors"); + sf_log_next32(sample, "udpInCsumErrors"); +} + +/*_________________-----------------------------__________________ + _________________ readCounters_host_vnode __________________ + -----------------_____________________________------------------ +*/ + +static void readCounters_host_vnode(SFSample *sample) +{ + sf_log_next32(sample, "vnode_mhz"); + sf_log_next32(sample, "vnode_cpus"); + sf_log_next64(sample, "vnode_memory"); + sf_log_next64(sample, "vnode_memory_free"); + sf_log_next32(sample, "vnode_num_domains"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_host_vcpu __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_host_vcpu(SFSample *sample) +{ + sf_log_next32(sample, "vcpu_state"); + sf_log_next32(sample, "vcpu_cpu_mS"); + sf_log_next32(sample, "vcpu_cpuCount"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_host_vmem __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_host_vmem(SFSample *sample) +{ + sf_log_next64(sample, "vmem_memory"); + sf_log_next64(sample, "vmem_maxMemory"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_host_vdsk __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_host_vdsk(SFSample *sample) +{ + sf_log_next64(sample, "vdsk_capacity"); + sf_log_next64(sample, "vdsk_allocation"); + sf_log_next64(sample, "vdsk_available"); + sf_log_next32(sample, "vdsk_rd_req"); + sf_log_next64(sample, "vdsk_rd_bytes"); + sf_log_next32(sample, "vdsk_wr_req"); + sf_log_next64(sample, "vdsk_wr_bytes"); + sf_log_next32(sample, "vdsk_errs"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_host_vnio __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_host_vnio(SFSample *sample) +{ + sf_log_next64(sample, "vnio_bytes_in"); + sf_log_next32(sample, "vnio_pkts_in"); + sf_log_next32(sample, "vnio_errs_in"); + sf_log_next32(sample, "vnio_drops_in"); + sf_log_next64(sample, "vnio_bytes_out"); + sf_log_next32(sample, "vnio_pkts_out"); + sf_log_next32(sample, "vnio_errs_out"); + sf_log_next32(sample, "vnio_drops_out"); +} + +/*_________________------------------------------__________________ + _________________ readCounters_host_gpu_nvml __________________ + -----------------______________________________------------------ +*/ + +static void readCounters_host_gpu_nvml(SFSample *sample) +{ + sf_log_next32(sample, "nvml_device_count"); + sf_log_next32(sample, "nvml_processes"); + sf_log_next32(sample, "nvml_gpu_mS"); + sf_log_next32(sample, "nvml_mem_mS"); + sf_log_next64(sample, "nvml_mem_bytes_total"); + sf_log_next64(sample, "nvml_mem_bytes_free"); + sf_log_next32(sample, "nvml_ecc_errors"); + sf_log_next32(sample, "nvml_energy_mJ"); + sf_log_next32(sample, "nvml_temperature_C"); + sf_log_next32(sample, "nvml_fan_speed_pc"); +} + +/*_________________------------------------------__________________ + _________________ readCounters_bcm_tables __________________ + -----------------______________________________------------------ +*/ + +static void readCounters_bcm_tables(SFSample *sample) +{ + sf_log_next32(sample, "bcm_asic_host_entries"); + sf_log_next32(sample, "bcm_host_entries_max"); + sf_log_next32(sample, "bcm_ipv4_entries"); + sf_log_next32(sample, "bcm_ipv4_entries_max"); + sf_log_next32(sample, "bcm_ipv6_entries"); + sf_log_next32(sample, "bcm_ipv6_entries_max"); + sf_log_next32(sample, "bcm_ipv4_ipv6_entries"); + sf_log_next32(sample, "bcm_ipv4_ipv6_entries_max"); + sf_log_next32(sample, "bcm_long_ipv6_entries"); + sf_log_next32(sample, "bcm_long_ipv6_entries_max"); + sf_log_next32(sample, "bcm_total_routes"); + sf_log_next32(sample, "bcm_total_routes_max"); + sf_log_next32(sample, "bcm_ecmp_nexthops"); + sf_log_next32(sample, "bcm_ecmp_nexthops_max"); + sf_log_next32(sample, "bcm_mac_entries"); + sf_log_next32(sample, "bcm_mac_entries_max"); + sf_log_next32(sample, "bcm_ipv4_neighbors"); + sf_log_next32(sample, "bcm_ipv6_neighbors"); + sf_log_next32(sample, "bcm_ipv4_routes"); + sf_log_next32(sample, "bcm_ipv6_routes"); + sf_log_next32(sample, "bcm_acl_ingress_entries"); + sf_log_next32(sample, "bcm_acl_ingress_entries_max"); + sf_log_next32(sample, "bcm_acl_ingress_counters"); + sf_log_next32(sample, "bcm_acl_ingress_counters_max"); + sf_log_next32(sample, "bcm_acl_ingress_meters"); + sf_log_next32(sample, "bcm_acl_ingress_meters_max"); + sf_log_next32(sample, "bcm_acl_ingress_slices"); + sf_log_next32(sample, "bcm_acl_ingress_slices_max"); + sf_log_next32(sample, "bcm_acl_egress_entries"); + sf_log_next32(sample, "bcm_acl_egress_entries_max"); + sf_log_next32(sample, "bcm_acl_egress_counters"); + sf_log_next32(sample, "bcm_acl_egress_counters_max"); + sf_log_next32(sample, "bcm_acl_egress_meters"); + sf_log_next32(sample, "bcm_acl_egress_meters_max"); + sf_log_next32(sample, "bcm_acl_egress_slices"); + sf_log_next32(sample, "bcm_acl_egress_slices_max"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_memcache __________________ + -----------------____________________________------------------ + for structure 2200 (deprecated) +*/ + +static void readCounters_memcache(SFSample *sample) +{ + sf_log_next32(sample, "memcache_uptime"); + sf_log_next32(sample, "memcache_rusage_user"); + sf_log_next32(sample, "memcache_rusage_system"); + sf_log_next32(sample, "memcache_curr_connections"); + sf_log_next32(sample, "memcache_total_connections"); + sf_log_next32(sample, "memcache_connection_structures"); + sf_log_next32(sample, "memcache_cmd_get"); + sf_log_next32(sample, "memcache_cmd_set"); + sf_log_next32(sample, "memcache_cmd_flush"); + sf_log_next32(sample, "memcache_get_hits"); + sf_log_next32(sample, "memcache_get_misses"); + sf_log_next32(sample, "memcache_delete_misses"); + sf_log_next32(sample, "memcache_delete_hits"); + sf_log_next32(sample, "memcache_incr_misses"); + sf_log_next32(sample, "memcache_incr_hits"); + sf_log_next32(sample, "memcache_decr_misses"); + sf_log_next32(sample, "memcache_decr_hits"); + sf_log_next32(sample, "memcache_cas_misses"); + sf_log_next32(sample, "memcache_cas_hits"); + sf_log_next32(sample, "memcache_cas_badval"); + sf_log_next32(sample, "memcache_auth_cmds"); + sf_log_next32(sample, "memcache_auth_errors"); + sf_log_next64(sample, "memcache_bytes_read"); + sf_log_next64(sample, "memcache_bytes_written"); + sf_log_next32(sample, "memcache_limit_maxbytes"); + sf_log_next32(sample, "memcache_accepting_conns"); + sf_log_next32(sample, "memcache_listen_disabled_num"); + sf_log_next32(sample, "memcache_threads"); + sf_log_next32(sample, "memcache_conn_yields"); + sf_log_next64(sample, "memcache_bytes"); + sf_log_next32(sample, "memcache_curr_items"); + sf_log_next32(sample, "memcache_total_items"); + sf_log_next32(sample, "memcache_evictions"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_memcache2 __________________ + -----------------____________________________------------------ + for structure 2204 +*/ + +static void readCounters_memcache2(SFSample *sample) +{ + sf_log_next32(sample, "memcache_cmd_set"); + sf_log_next32(sample, "memcache_cmd_touch"); + sf_log_next32(sample, "memcache_cmd_flush"); + sf_log_next32(sample, "memcache_get_hits"); + sf_log_next32(sample, "memcache_get_misses"); + sf_log_next32(sample, "memcache_delete_hits"); + sf_log_next32(sample, "memcache_delete_misses"); + sf_log_next32(sample, "memcache_incr_hits"); + sf_log_next32(sample, "memcache_incr_misses"); + sf_log_next32(sample, "memcache_decr_hits"); + sf_log_next32(sample, "memcache_decr_misses"); + sf_log_next32(sample, "memcache_cas_hits"); + sf_log_next32(sample, "memcache_cas_misses"); + sf_log_next32(sample, "memcache_cas_badval"); + sf_log_next32(sample, "memcache_auth_cmds"); + sf_log_next32(sample, "memcache_auth_errors"); + sf_log_next32(sample, "memcache_threads"); + sf_log_next32(sample, "memcache_conn_yields"); + sf_log_next32(sample, "memcache_listen_disabled_num"); + sf_log_next32(sample, "memcache_curr_connections"); + sf_log_next32(sample, "memcache_rejected_connections"); + sf_log_next32(sample, "memcache_total_connections"); + sf_log_next32(sample, "memcache_connection_structures"); + sf_log_next32(sample, "memcache_evictions"); + sf_log_next32(sample, "memcache_reclaimed"); + sf_log_next32(sample, "memcache_curr_items"); + sf_log_next32(sample, "memcache_total_items"); + sf_log_next64(sample, "memcache_bytes_read"); + sf_log_next64(sample, "memcache_bytes_written"); + sf_log_next64(sample, "memcache_bytes"); + sf_log_next64(sample, "memcache_limit_maxbytes"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_http __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_http(SFSample *sample) +{ + sf_log_next32(sample, "http_method_option_count"); + sf_log_next32(sample, "http_method_get_count"); + sf_log_next32(sample, "http_method_head_count"); + sf_log_next32(sample, "http_method_post_count"); + sf_log_next32(sample, "http_method_put_count"); + sf_log_next32(sample, "http_method_delete_count"); + sf_log_next32(sample, "http_method_trace_count"); + sf_log_next32(sample, "http_methd_connect_count"); + sf_log_next32(sample, "http_method_other_count"); + sf_log_next32(sample, "http_status_1XX_count"); + sf_log_next32(sample, "http_status_2XX_count"); + sf_log_next32(sample, "http_status_3XX_count"); + sf_log_next32(sample, "http_status_4XX_count"); + sf_log_next32(sample, "http_status_5XX_count"); + sf_log_next32(sample, "http_status_other_count"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_JVM __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_JVM(SFSample *sample) +{ + char vm_name[SFLJVM_MAX_VMNAME_LEN]; + char vendor[SFLJVM_MAX_VENDOR_LEN]; + char version[SFLJVM_MAX_VERSION_LEN]; + if(getString(sample, vm_name, SFLJVM_MAX_VMNAME_LEN) > 0) { + dbg_printf("jvm_name %s\n", vm_name); + } + if(getString(sample, vendor, SFLJVM_MAX_VENDOR_LEN) > 0) { + dbg_printf("jvm_vendor %s\n", vendor); + } + if(getString(sample, version, SFLJVM_MAX_VERSION_LEN) > 0) { + dbg_printf("jvm_version %s\n", version); + } +} + +/*_________________----------------------------__________________ + _________________ readCounters_JMX __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_JMX(SFSample *sample, uint32_t length) +{ + sf_log_next64(sample, "heap_mem_initial"); + sf_log_next64(sample, "heap_mem_used"); + sf_log_next64(sample, "heap_mem_committed"); + sf_log_next64(sample, "heap_mem_max"); + sf_log_next64(sample, "non_heap_mem_initial"); + sf_log_next64(sample, "non_heap_mem_used"); + sf_log_next64(sample, "non_heap_mem_committed"); + sf_log_next64(sample, "non_heap_mem_max"); + sf_log_next32(sample, "gc_count"); + sf_log_next32(sample, "gc_mS"); + sf_log_next32(sample, "classes_loaded"); + sf_log_next32(sample, "classes_total"); + sf_log_next32(sample, "classes_unloaded"); + sf_log_next32(sample, "compilation_mS"); + sf_log_next32(sample, "threads_live"); + sf_log_next32(sample, "threads_daemon"); + sf_log_next32(sample, "threads_started"); + if(length > 100) { + sf_log_next32(sample, "fds_open"); + sf_log_next32(sample, "fds_max"); + } +} + +/*_________________----------------------------__________________ + _________________ readCounters_APP __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_APP(SFSample *sample) +{ + char application[SFLAPP_MAX_APPLICATION_LEN]; + if(getString(sample, application, SFLAPP_MAX_APPLICATION_LEN) > 0) { + dbg_printf("application %s\n", application); + } + sf_log_next32(sample, "status_OK"); + sf_log_next32(sample, "errors_OTHER"); + sf_log_next32(sample, "errors_TIMEOUT"); + sf_log_next32(sample, "errors_INTERNAL_ERROR"); + sf_log_next32(sample, "errors_BAD_REQUEST"); + sf_log_next32(sample, "errors_FORBIDDEN"); + sf_log_next32(sample, "errors_TOO_LARGE"); + sf_log_next32(sample, "errors_NOT_IMPLEMENTED"); + sf_log_next32(sample, "errors_NOT_FOUND"); + sf_log_next32(sample, "errors_UNAVAILABLE"); + sf_log_next32(sample, "errors_UNAUTHORIZED"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_APP_RESOURCE __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_APP_RESOURCE(SFSample *sample) +{ + sf_log_next32(sample, "user_time"); + sf_log_next32(sample, "system_time"); + sf_log_next64(sample, "memory_used"); + sf_log_next64(sample, "memory_max"); + sf_log_next32(sample, "files_open"); + sf_log_next32(sample, "files_max"); + sf_log_next32(sample, "connections_open"); + sf_log_next32(sample, "connections_max"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_APP_WORKERS __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_APP_WORKERS(SFSample *sample) +{ + sf_log_next32(sample, "workers_active"); + sf_log_next32(sample, "workers_idle"); + sf_log_next32(sample, "workers_max"); + sf_log_next32(sample, "requests_delayed"); + sf_log_next32(sample, "requests_dropped"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_VDI __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_VDI(SFSample *sample) +{ + sf_log_next32(sample, "vdi_sessions_current"); + sf_log_next32(sample, "vdi_sessions_total"); + sf_log_next32(sample, "vdi_sessions_duration"); + sf_log_next32(sample, "vdi_rx_bytes"); + sf_log_next32(sample, "vdi_tx_bytes"); + sf_log_next32(sample, "vdi_rx_packets"); + sf_log_next32(sample, "vdi_tx_packets"); + sf_log_next32(sample, "vdi_rx_packets_lost"); + sf_log_next32(sample, "vdi_tx_packets_lost"); + sf_log_next32(sample, "vdi_rtt_min_ms"); + sf_log_next32(sample, "vdi_rtt_max_ms"); + sf_log_next32(sample, "vdi_rtt_avg_ms"); + sf_log_next32(sample, "vdi_audio_rx_bytes"); + sf_log_next32(sample, "vdi_audio_tx_bytes"); + sf_log_next32(sample, "vdi_audio_tx_limit"); + sf_log_next32(sample, "vdi_img_rx_bytes"); + sf_log_next32(sample, "vdi_img_tx_bytes"); + sf_log_next32(sample, "vdi_img_frames"); + sf_log_next32(sample, "vdi_img_qual_min"); + sf_log_next32(sample, "vdi_img_qual_max"); + sf_log_next32(sample, "vdi_img_qual_avg"); + sf_log_next32(sample, "vdi_usb_rx_bytes"); + sf_log_next32(sample, "vdi_usb_tx_bytes"); +} + +/*_________________------------------------------__________________ + _________________ readCounters_LACP __________________ + -----------------______________________________------------------ +*/ + +static void readCounters_LACP(SFSample *sample) +{ + SFLLACP_portState portState; + sf_log_nextMAC(sample, "actorSystemID"); + sf_log_nextMAC(sample, "partnerSystemID"); + sf_log_next32(sample, "attachedAggID"); + portState.all = getData32_nobswap(sample); + dbg_printf("actorAdminPortState %u\n", portState.v.actorAdmin); + dbg_printf("actorOperPortState %u\n", portState.v.actorOper); + dbg_printf("partnerAdminPortState %u\n", portState.v.partnerAdmin); + dbg_printf("partnerOperPortState %u\n", portState.v.partnerOper); + sf_log_next32(sample, "LACPDUsRx"); + sf_log_next32(sample, "markerPDUsRx"); + sf_log_next32(sample, "markerResponsePDUsRx"); + sf_log_next32(sample, "unknownRx"); + sf_log_next32(sample, "illegalRx"); + sf_log_next32(sample, "LACPDUsTx"); + sf_log_next32(sample, "markerPDUsTx"); + sf_log_next32(sample, "markerResponsePDUsTx"); +} + +/*_________________----------------------------__________________ + _________________ readCounters_SFP __________________ + -----------------____________________________------------------ +*/ + +static void readCounters_SFP(SFSample *sample) +{ + uint32_t num_lanes,ll; + sf_log_next32(sample, "sfp_module_id"); + sf_log_next32(sample, "sfp_module_total_lanes"); + sf_log_next32(sample, "sfp_module_supply_voltage"); + sf_log_next32(sample, "sfp_module_temperature"); + num_lanes = getData32(sample); + dbg_printf( "sfp_module_active_lanes %u\n", num_lanes); + for(ll=0; ll < num_lanes; ll++) { + dbg_printf( "sfp_lane_index.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_tx_bias_current_uA.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_tx_power_uW.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_tx_power_min_uW.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_tx_power_max_uW.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_tx_wavelength_nM.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_rx_power_uW.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_rx_power_min_uW.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_rx_power_max_uW.%u %u\n", ll, getData32(sample)); + dbg_printf( "sfp_lane_rx_wavelength_nM.%u %u\n", ll, getData32(sample)); + } +} + +/*_________________---------------------------__________________ + _________________ readCountersSample_v2v4 __________________ + -----------------___________________________------------------ +*/ + +static void readCountersSample_v2v4(SFSample *sample, FlowSource_t *fs) +{ + dbg_printf("sampleType COUNTERSSAMPLE\n"); + sample->samplesGenerated = getData32(sample); + dbg_printf("sampleSequenceNo %u\n", sample->samplesGenerated); + { + uint32_t samplerId = getData32(sample); + sample->ds_class = samplerId >> 24; + sample->ds_index = samplerId & 0x00ffffff; + } + dbg_printf("sourceId %u:%u\n", sample->ds_class, sample->ds_index); + + + sample->statsSamplingInterval = getData32(sample); + dbg_printf("statsSamplingInterval %u\n", sample->statsSamplingInterval); + /* now find out what sort of counter blocks we have here... */ + sample->counterBlockVersion = getData32(sample); + dbg_printf("counterBlockVersion %u\n", sample->counterBlockVersion); + + /* first see if we should read the generic stats */ + switch(sample->counterBlockVersion) { + case INMCOUNTERSVERSION_GENERIC: + case INMCOUNTERSVERSION_ETHERNET: + case INMCOUNTERSVERSION_TOKENRING: + case INMCOUNTERSVERSION_FDDI: + case INMCOUNTERSVERSION_VG: + case INMCOUNTERSVERSION_WAN: readCounters_generic(sample); break; + case INMCOUNTERSVERSION_VLAN: break; + default: receiveError(sample, "unknown stats version", YES); break; + } + + /* now see if there are any specific counter blocks to add */ + switch(sample->counterBlockVersion) { + case INMCOUNTERSVERSION_GENERIC: /* nothing more */ break; + case INMCOUNTERSVERSION_ETHERNET: readCounters_ethernet(sample); break; + case INMCOUNTERSVERSION_TOKENRING:readCounters_tokenring(sample); break; + case INMCOUNTERSVERSION_FDDI: break; + case INMCOUNTERSVERSION_VG: readCounters_vg(sample); break; + case INMCOUNTERSVERSION_WAN: break; + case INMCOUNTERSVERSION_VLAN: readCounters_vlan(sample); break; + default: receiveError(sample, "unknown INMCOUNTERSVERSION", YES); break; + } + /* line-by-line output... */ + if ( verbose ) + writeCountersLine(sample); +} + +/*_________________---------------------------__________________ + _________________ readCountersSample __________________ + -----------------___________________________------------------ +*/ + +static void readCountersSample(SFSample *sample, int expanded, FlowSource_t *fs) +{ + uint32_t sampleLength; + uint32_t num_elements; + uint8_t *sampleStart; + dbg_printf("sampleType COUNTERSSAMPLE\n"); + sampleLength = getData32(sample); + sampleStart = (uint8_t *)sample->datap; + sample->samplesGenerated = getData32(sample); + + dbg_printf("sampleSequenceNo %u\n", sample->samplesGenerated); + if(expanded) { + sample->ds_class = getData32(sample); + sample->ds_index = getData32(sample); + } + else { + uint32_t samplerId = getData32(sample); + sample->ds_class = samplerId >> 24; + sample->ds_index = samplerId & 0x00ffffff; + } + dbg_printf("sourceId %u:%u\n", sample->ds_class, sample->ds_index); + + num_elements = getData32(sample); + { + uint32_t el; + for(el = 0; el < num_elements; el++) { + uint32_t tag, length; + uint8_t *start; +#ifdef DEVEL + char buf[51]; +#endif + tag = sample->elementType = getData32(sample); + dbg_printf("counterBlock_tag %s\n", printTag(tag, buf, 50)); + length = getData32(sample); + start = (uint8_t *)sample->datap; + + switch(tag) { + case SFLCOUNTERS_GENERIC: readCounters_generic(sample); break; + case SFLCOUNTERS_ETHERNET: readCounters_ethernet(sample); break; + case SFLCOUNTERS_TOKENRING:readCounters_tokenring(sample); break; + case SFLCOUNTERS_VG: readCounters_vg(sample); break; + case SFLCOUNTERS_VLAN: readCounters_vlan(sample); break; + case SFLCOUNTERS_80211: readCounters_80211(sample); break; + case SFLCOUNTERS_LACP: readCounters_LACP(sample); break; + case SFLCOUNTERS_SFP: readCounters_SFP(sample); break; + case SFLCOUNTERS_PROCESSOR: readCounters_processor(sample); break; + case SFLCOUNTERS_RADIO: readCounters_radio(sample); break; + case SFLCOUNTERS_OFPORT: readCounters_OFPort(sample); break; + case SFLCOUNTERS_PORTNAME: readCounters_portName(sample); break; + case SFLCOUNTERS_HOST_HID: readCounters_host_hid(sample); break; + case SFLCOUNTERS_ADAPTORS: readCounters_adaptors(sample); break; + case SFLCOUNTERS_HOST_PAR: readCounters_host_parent(sample); break; + case SFLCOUNTERS_HOST_CPU: readCounters_host_cpu(sample, length); break; + case SFLCOUNTERS_HOST_MEM: readCounters_host_mem(sample); break; + case SFLCOUNTERS_HOST_DSK: readCounters_host_dsk(sample); break; + case SFLCOUNTERS_HOST_NIO: readCounters_host_nio(sample); break; + case SFLCOUNTERS_HOST_IP: readCounters_host_ip(sample); break; + case SFLCOUNTERS_HOST_ICMP: readCounters_host_icmp(sample); break; + case SFLCOUNTERS_HOST_TCP: readCounters_host_tcp(sample); break; + case SFLCOUNTERS_HOST_UDP: readCounters_host_udp(sample); break; + case SFLCOUNTERS_HOST_VRT_NODE: readCounters_host_vnode(sample); break; + case SFLCOUNTERS_HOST_VRT_CPU: readCounters_host_vcpu(sample); break; + case SFLCOUNTERS_HOST_VRT_MEM: readCounters_host_vmem(sample); break; + case SFLCOUNTERS_HOST_VRT_DSK: readCounters_host_vdsk(sample); break; + case SFLCOUNTERS_HOST_VRT_NIO: readCounters_host_vnio(sample); break; + case SFLCOUNTERS_HOST_GPU_NVML: readCounters_host_gpu_nvml(sample); break; + case SFLCOUNTERS_BCM_TABLES: readCounters_bcm_tables(sample); break; + case SFLCOUNTERS_MEMCACHE: readCounters_memcache(sample); break; + case SFLCOUNTERS_MEMCACHE2: readCounters_memcache2(sample); break; + case SFLCOUNTERS_HTTP: readCounters_http(sample); break; + case SFLCOUNTERS_JVM: readCounters_JVM(sample); break; + case SFLCOUNTERS_JMX: readCounters_JMX(sample, length); break; + case SFLCOUNTERS_APP: readCounters_APP(sample); break; + case SFLCOUNTERS_APP_RESOURCE: readCounters_APP_RESOURCE(sample); break; + case SFLCOUNTERS_APP_WORKERS: readCounters_APP_WORKERS(sample); break; + case SFLCOUNTERS_VDI: readCounters_VDI(sample); break; + case SFLCOUNTERS_OVSDP: readCounters_OVSDP(sample); break; + default: skipTLVRecord(sample, tag, length, "counters_sample_element"); break; + } + lengthCheck(sample, "counters_sample_element", start, length); + } + } + lengthCheck(sample, "counters_sample", sampleStart, sampleLength); + /* line-by-line output... */ + if ( verbose ) + writeCountersLine(sample); +} + +/*_________________---------------------------__________________ + _________________ readRTMetric __________________ + -----------------___________________________------------------ +*/ + +static void readRTMetric(SFSample *sample, FlowSource_t *fs) +{ +#define SFL_MAX_RTMETRIC_KEY_LEN 64 +#define SFL_MAX_RTMETRIC_VAL_LEN 255 + char dsName[SFL_MAX_RTMETRIC_KEY_LEN]; + uint32_t sampleLength; + uint32_t num_elements; + uint8_t *sampleStart; + dbg_printf("sampleType RTMETRIC\n"); + sampleLength = getData32(sample); + sampleStart = (uint8_t *)sample->datap; + if(getString(sample, dsName, SFL_MAX_RTMETRIC_KEY_LEN) > 0) { + dbg_printf( "rtmetric_datasource_name %s\n", dsName); + } + num_elements = getData32(sample); + { + uint32_t el; + for(el = 0; el < num_elements; el++) { + char mname[SFL_MAX_RTMETRIC_KEY_LEN]; + uint32_t mtype; + char mvalstr[SFL_MAX_RTMETRIC_VAL_LEN]; + uint32_t mvali32; + uint64_t mvali64; + float mvalfloat; + double mvaldouble; + getString(sample, mname, SFL_MAX_RTMETRIC_KEY_LEN); + mtype = getData32(sample); + switch(mtype) { + case 0: + getString(sample, mvalstr, SFL_MAX_RTMETRIC_VAL_LEN); + dbg_printf( "rtmetric %s = (string) \"%s\"\n", mname, mvalstr); + break; + case 1: + mvali32 = getData32(sample); + dbg_printf( "rtmetric %s = (counter32) %u\n", mname, mvali32); + break; + case 2: + mvali64 = getData64(sample); + dbg_printf( "rtmetric %s = (counter64) %llu\n", mname, mvali64); + break; + case 3: + mvali32 = getData32(sample); + dbg_printf( "rtmetric %s = (gauge32) %u\n", mname, mvali32); + break; + case 4: + mvali64 = getData64(sample); + dbg_printf( "rtmetric %s = (gauge64) %llu\n", mname, mvali64); + break; + case 5: + mvalfloat = getFloat(sample); + dbg_printf( "rtmetric %s = (gaugefloat) %.3f\n", mname, mvalfloat); + break; + case 6: + mvaldouble = getDouble(sample); + dbg_printf( "rtmetric %s = (gaugefloat) %.3f\n", mname, mvaldouble); + break; + default: + dbg_printf( "rtmetric unknown_type %u\n", mtype); + SFABORT(sample, SF_ABORT_DECODE_ERROR); + break; + } + } + } + lengthCheck(sample, "rtmetric_sample", sampleStart, sampleLength); + + if ( verbose ) + writeCountersLine(sample); + +} + +/*_________________---------------------------__________________ + _________________ readRTFlow __________________ + -----------------___________________________------------------ +*/ + +static void readRTFlow(SFSample *sample, FlowSource_t *fs) +{ + char dsName[SFL_MAX_RTMETRIC_KEY_LEN]; + uint32_t sampleLength; + uint32_t num_elements; + uint8_t *sampleStart; + dbg_printf("sampleType RTFLOW\n"); + sampleLength = getData32(sample); + sampleStart = (uint8_t *)sample->datap; + if(getString(sample, dsName, SFL_MAX_RTMETRIC_KEY_LEN) > 0) { + dbg_printf( "rtflow_datasource_name %s\n", dsName); + } + sf_log_next32(sample, "rtflow_sampling_rate"); + sf_log_next32(sample, "rtflow_sample_pool"); + num_elements = getData32(sample); + { + uint32_t el; + for(el = 0; el < num_elements; el++) { + char fname[SFL_MAX_RTMETRIC_KEY_LEN]; + uint32_t ftype; + char fvalstr[SFL_MAX_RTMETRIC_VAL_LEN]; + uint32_t fvali32; + uint64_t fvali64; + float fvalfloat; + double fvaldouble; + SFLAddress fvaladdr; +#ifdef DEVEL + char fvaladdrstr[64]; +#endif + u_char fvalmac[6]; + char fvalmacstr[32]; + getString(sample, fname, SFL_MAX_RTMETRIC_KEY_LEN); + ftype = getData32(sample); + switch(ftype) { + case 0: + getString(sample, fvalstr, SFL_MAX_RTMETRIC_VAL_LEN); + dbg_printf( "rtflow %s = (string) \"%s\"\n", fname, fvalstr); + break; + case 1: + memcpy(fvalmac, sample->datap, 6); + skipBytes(sample, 6); + printHex(fvalmac, 6, fvalmacstr, 32, 0, 100); + dbg_printf( "rtflow %s = (mac) %s\n", fname, fvalmacstr); + break; + case 2: + fvaladdr.type = SFLADDRESSTYPE_IP_V4; + fvaladdr.address.ip_v4.addr = getData32_nobswap(sample); + dbg_printf( "rtflow %s = (ip) %s\n", + fname, + printAddress(&fvaladdr,fvaladdrstr, 63)); + break; + case 3: + fvaladdr.type = SFLADDRESSTYPE_IP_V6; + memcpy(fvaladdr.address.ip_v6.addr, sample->datap, 16); + skipBytes(sample, 16); + dbg_printf( "rtflow %s = (ip6) %s\n", + fname, + printAddress(&fvaladdr,fvaladdrstr, 63)); + break; + case 4: + fvali32 = getData32(sample); + dbg_printf( "rtflow %s = (int32) %u\n", fname, fvali32); + break; + case 5: + fvali64 = getData64(sample); + dbg_printf( "rtflow %s = (int64) %llu\n", fname, fvali64); + break; + case 6: + fvalfloat = getFloat(sample); + dbg_printf( "rtflow %s = (gaugefloat) %.3f\n", fname, fvalfloat); + break; + case 7: + fvaldouble = getDouble(sample); + dbg_printf( "rtflow %s = (gaugefloat) %.3f\n", fname, fvaldouble); + break; + default: + dbg_printf( "rtflow unknown_type %u\n", ftype); + SFABORT(sample, SF_ABORT_DECODE_ERROR); + break; + } + } + } + lengthCheck(sample, "rtflow_sample", sampleStart, sampleLength); + + if ( verbose ) + writeCountersLine(sample); + +} + +/*_________________---------------------------__________________ + _________________ readSFlowDatagram __________________ + -----------------___________________________------------------ +*/ + +static void readSFlowDatagram(SFSample *sample, FlowSource_t *fs) +{ + uint32_t samplesInPacket; +#ifdef DEVEL + char buf[51]; +#endif + + /* log some datagram info */ + dbg_printf("datagramSourceIP %s\n", IP_to_a(sample->sourceIP.s_addr, buf, 51)); + dbg_printf("datagramSize %u\n", sample->rawSampleLen); + dbg_printf("unixSecondsUTC %llu\n", (unsigned long long)sample->readTimestamp); + + /* check the version */ + sample->datagramVersion = getData32(sample); + dbg_printf("datagramVersion %d\n", sample->datagramVersion); + if(sample->datagramVersion != 2 && + sample->datagramVersion != 4 && + sample->datagramVersion != 5) { + receiveError(sample, "unexpected datagram version number\n", YES); + } + + /* get the agent address */ + getAddress(sample, &sample->agent_addr); + + /* version 5 has an agent sub-id as well */ + if(sample->datagramVersion >= 5) { + sample->agentSubId = getData32(sample); + dbg_printf("agentSubId %u\n", sample->agentSubId); + } + + sample->sequenceNo = getData32(sample); /* this is the packet sequence number */ + sample->sysUpTime = getData32(sample); + samplesInPacket = getData32(sample); + dbg_printf("agent %s\n", printAddress(&sample->agent_addr, buf, 50)); + dbg_printf("packetSequenceNo %u\n", sample->sequenceNo); + dbg_printf("sysUpTime %u\n", sample->sysUpTime); + dbg_printf("samplesInPacket %u\n", samplesInPacket); + + /* now iterate and pull out the flows and counters samples */ + { + uint32_t samp = 0; + for(; samp < samplesInPacket; samp++) { + if((uint8_t *)sample->datap >= sample->endp) { + LogError("SFLOW: readSFlowDatagram() unexpected end of datagram after sample %d of %d\n", samp, samplesInPacket); + SFABORT(sample, SF_ABORT_EOS); + } + /* just read the tag, then call the approriate decode fn */ + sample->elementType = 0; + sample->sampleType = getData32(sample); + dbg_printf("startSample ----------------------\n"); + dbg_printf("sampleType_tag %s\n", printTag(sample->sampleType, buf, 50)); + if(sample->datagramVersion >= 5) { + switch(sample->sampleType) { + case SFLFLOW_SAMPLE: readFlowSample(sample, NO, fs); break; + case SFLCOUNTERS_SAMPLE: readCountersSample(sample, NO, fs); break; + case SFLFLOW_SAMPLE_EXPANDED: readFlowSample(sample, YES, fs); break; + case SFLCOUNTERS_SAMPLE_EXPANDED: readCountersSample(sample, YES, fs); break; + case SFLRTMETRIC: readRTMetric(sample, fs); break; + case SFLRTFLOW: readRTFlow(sample, fs); break; + default: skipTLVRecord(sample, sample->sampleType, getData32(sample), "sample"); break; + } + } + else { + switch(sample->sampleType) { + case FLOWSAMPLE: readFlowSample_v2v4(sample, fs); break; + case COUNTERSSAMPLE: readCountersSample_v2v4(sample, fs); break; + default: receiveError(sample, "unexpected sample type", YES); break; + } + } + dbg_printf("endSample ----------------------\n"); + } + } +} + +/*_________________---------------------------__________________ + _________________ printUUID __________________ + -----------------___________________________------------------ +*/ + + static int printUUID(const uint8_t *a, char *buf, int bufLen) + { + int i, b = 0; + b += printHex(a, 4, buf, bufLen, 0, 100); + buf[b++] = '-'; + b += printHex(a + 4, 2, buf + b, bufLen - b, 0, 100); + buf[b++] = '-'; + b += printHex(a + 6, 2, buf + b, bufLen - b, 0, 100); + buf[b++] = '-'; + b += printHex(a + 8, 2, buf + b, bufLen - b, 0, 100); + buf[b++] = '-'; + b += printHex(a + 10, 6, buf + b, bufLen - b, 0, 100); + + /* should really be lowercase hex - fix that here */ + for(i = 0; i < b; i++) buf[i] = tolower(buf[i]); + + /* add NUL termination */ + buf[b] = '\0'; + + return b; + } + +#ifdef DEVEL +static char *URLEncode(char *in, char *out, int outlen) +{ + register char c, *r = in, *w = out; + int maxlen = (strlen(in) * 3) + 1; + if(outlen < maxlen) return "URLEncode: not enough space"; + while ((c = *r++)) { + if(isalnum(c)) *w++ = c; + else if(isspace(c)) *w++ = '+'; + else { + *w++ = '%'; + *w++ = bin2hex(c >> 4); + *w++ = bin2hex(c & 0x0f); + } + } + *w++ = '\0'; + return out; +} +#endif diff --git a/bin/sflow_nfdump.h b/bin/sflow_nfdump.h new file mode 100644 index 0000000..b494338 --- /dev/null +++ b/bin/sflow_nfdump.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, Peter Haag + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SFLOW_NFDUMP_H +#define _SFLOW_NFDUMP_H 1 + +void Init_sflow(void); + +void Process_sflow(void *in_buff, ssize_t in_buff_cnt, FlowSource_t *fs); + +/* + * Extension map for sflow ( compatibility for now ) + * + * Required extensions: + * + * 4 byte byte counter + * | 4byte packet counter + * | | IPv4 + * | | | + * xxxx x0 0 0 + * + * Optional extensions: + * + * 4 : 2 byte input/output interface id + * 6 : 2 byte src/dst as + */ + +#endif // _SFLOW_NFDUMP_H diff --git a/bin/sflow_proto.h b/bin/sflow_proto.h deleted file mode 100644 index 34302e8..0000000 --- a/bin/sflow_proto.h +++ /dev/null @@ -1,702 +0,0 @@ -/* - * Copyright (c) 2014, Peter Haag - * Copyright (c) 2009, Peter Haag - * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of the author nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $Author: haag $ - * - * $Id: sflow_proto.h 39 2009-11-25 08:11:15Z haag $ - * - * $LastChangedRevision: 39 $ - * - * - */ - -/* - * sfcapd makes use of code originated from sflowtool by InMon Corp. - * Those parts of the code are distributed under the InMon Public License below. - * All other/additional code is pubblished under BSD license. - */ - - -/* - * ----------------------------------------------------------------------- - * Copyright (c) 2001-2002 InMon Corp. All rights reserved. - * ----------------------------------------------------------------------- - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes sFlow(TM), freely available from - * http://www.inmon.com/". - * - * 4. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes sFlow(TM), freely available from - * http://www.inmon.com/". - * - * 5. InMon Corp. may publish revised and/or new versions - * of the license from time to time. Each version will be given a - * distinguishing version number. Once covered code has been - * published under a particular version of the license, you may - * always continue to use it under the terms of that version. You - * may also choose to use such covered code under the terms of any - * subsequent version of the license published by InMon Corp. - * No one other than the InMon Corp. has the right to modify the terms - * applicable to covered code created under this License. - * - * 6. The name "sFlow" must not be used to endorse or promote products - * derived from this software without prior written permission - * from InMon Corp. This does not apply to add-on libraries or tools - * that work in conjunction with sFlow. In such a case the sFlow name - * may be used to indicate that the product supports sFlow. - * - * 7. Products derived from this software may not be called "sFlow", - * nor may "sFlow" appear in their name, without prior written - * permission of InMon Corp. - * - * - * THIS SOFTWARE IS PROVIDED BY INMON CORP. ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * INMON CORP. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * -------------------------------------------------------------------- - * - * This software consists of voluntary contributions made by many - * individuals on behalf of InMon Corp. - * - * InMon Corp. can be contacted via Email at info@inmon.com. - * - * For more information on InMon Corp. and sFlow, - * please see http://www.inmon.com/. - * - * InMon Public License Version 1.0 written May 31, 2001 - * - */ - -///////////////////////////////////////////////////////////////////////////////// -/////////////////////// sFlow Sampling Packet Data Types //////////////////////// -///////////////////////////////////////////////////////////////////////////////// - -#ifndef _SFLOW_PROTO_H -#define _SFLOW_PROTO_H 1 - -#if defined(__cplusplus) -extern "C" { -#endif - -enum SFLAddress_type { - SFLADDRESSTYPE_IP_V4 = 1, - SFLADDRESSTYPE_IP_V6 = 2 -}; - -typedef union _SFLAddress_value { - struct in_addr ip_v4; - struct in6_addr ip_v6; -} SFLAddress_value; - -typedef struct _SFLAddress { - uint32_t type; /* enum SFLAddress_type */ - SFLAddress_value address; -} SFLAddress; - -/* Packet header data */ - -#define SFL_DEFAULT_HEADER_SIZE 128 -#define SFL_DEFAULT_COLLECTOR_PORT 6343 -#define SFL_DEFAULT_SAMPLING_RATE 400 - -/* The header protocol describes the format of the sampled header */ -enum SFLHeader_protocol { - SFLHEADER_ETHERNET_ISO8023 = 1, - SFLHEADER_ISO88024_TOKENBUS = 2, - SFLHEADER_ISO88025_TOKENRING = 3, - SFLHEADER_FDDI = 4, - SFLHEADER_FRAME_RELAY = 5, - SFLHEADER_X25 = 6, - SFLHEADER_PPP = 7, - SFLHEADER_SMDS = 8, - SFLHEADER_AAL5 = 9, - SFLHEADER_AAL5_IP = 10, /* e.g. Cisco AAL5 mux */ - SFLHEADER_IPv4 = 11, - SFLHEADER_IPv6 = 12, - SFLHEADER_MPLS = 13 -}; - -/* raw sampled header */ - -typedef struct _SFLSampled_header { - uint32_t header_protocol; /* (enum SFLHeader_protocol) */ - uint32_t frame_length; /* Original length of packet before sampling */ - uint32_t stripped; /* header/trailer bytes stripped by sender */ - uint32_t header_length; /* length of sampled header bytes to follow */ - uint8_t *header_bytes; /* Header bytes */ -} SFLSampled_header; - -/* decoded ethernet header */ - -typedef struct _SFLSampled_ethernet { - uint32_t eth_len; /* The length of the MAC packet excluding - lower layer encapsulations */ - uint8_t src_mac[8]; /* 6 bytes + 2 pad */ - uint8_t dst_mac[8]; - uint32_t eth_type; -} SFLSampled_ethernet; - -/* decoded IP version 4 header */ - -typedef struct _SFLSampled_ipv4 { - uint32_t length; /* The length of the IP packet - excluding lower layer encapsulations */ - uint32_t protocol; /* IP Protocol type (for example, TCP = 6, UDP = 17) */ - struct in_addr src_ip; /* Source IP Address */ - struct in_addr dst_ip; /* Destination IP Address */ - uint32_t src_port; /* TCP/UDP source port number or equivalent */ - uint32_t dst_port; /* TCP/UDP destination port number or equivalent */ - uint32_t tcp_flags; /* TCP flags */ - uint32_t tos; /* IP type of service */ -} SFLSampled_ipv4; - -/* decoded IP version 6 data */ - -typedef struct _SFLSampled_ipv6 { - uint32_t length; /* The length of the IP packet - excluding lower layer encapsulations */ - uint32_t protocol; /* IP Protocol type (for example, TCP = 6, UDP = 17) */ - struct in6_addr src_ip; /* Source IP Address */ - struct in6_addr dst_ip; /* Destination IP Address */ - uint32_t src_port; /* TCP/UDP source port number or equivalent */ - uint32_t dst_port; /* TCP/UDP destination port number or equivalent */ - uint32_t tcp_flags; /* TCP flags */ - uint32_t priority; /* IP priority */ -} SFLSampled_ipv6; - -/* Extended data types */ - -/* Extended switch data */ - -typedef struct _SFLExtended_switch { - uint32_t src_vlan; /* The 802.1Q VLAN id of incomming frame */ - uint32_t src_priority; /* The 802.1p priority */ - uint32_t dst_vlan; /* The 802.1Q VLAN id of outgoing frame */ - uint32_t dst_priority; /* The 802.1p priority */ -} SFLExtended_switch; - -/* Extended router data */ - -typedef struct _SFLExtended_router { - SFLAddress nexthop; /* IP address of next hop router */ - uint32_t src_mask; /* Source address prefix mask bits */ - uint32_t dst_mask; /* Destination address prefix mask bits */ -} SFLExtended_router; - -/* Extended gateway data */ -enum SFLExtended_as_path_segment_type { - SFLEXTENDED_AS_SET = 1, /* Unordered set of ASs */ - SFLEXTENDED_AS_SEQUENCE = 2 /* Ordered sequence of ASs */ -}; - -typedef struct _SFLExtended_as_path_segment { - uint32_t type; /* enum SFLExtended_as_path_segment_type */ - uint32_t length; /* number of AS numbers in set/sequence */ - union { - uint32_t *set; - uint32_t *seq; - } as; -} SFLExtended_as_path_segment; - -typedef struct _SFLExtended_gateway { - SFLAddress nexthop; /* Address of the border router that should - be used for the destination network */ - uint32_t as; /* AS number for this gateway */ - uint32_t src_as; /* AS number of source (origin) */ - uint32_t src_peer_as; /* AS number of source peer */ - uint32_t dst_as_path_segments; /* number of segments in path */ - SFLExtended_as_path_segment *dst_as_path; /* list of seqs or sets */ - uint32_t communities_length; /* number of communities */ - uint32_t *communities; /* set of communities */ - uint32_t localpref; /* LocalPref associated with this route */ -} SFLExtended_gateway; - -typedef struct _SFLString { - uint32_t len; - char *str; -} SFLString; - -/* Extended user data */ - -typedef struct _SFLExtended_user { - uint32_t src_charset; /* MIBEnum value of character set used to encode a string - See RFC 2978 - Where possible UTF-8 encoding (MIBEnum=106) should be used. A value - of zero indicates an unknown encoding. */ - SFLString src_user; - uint32_t dst_charset; - SFLString dst_user; -} SFLExtended_user; - -/* Extended URL data */ - -enum SFLExtended_url_direction { - SFLEXTENDED_URL_SRC = 1, /* URL is associated with source address */ - SFLEXTENDED_URL_DST = 2 /* URL is associated with destination address */ -}; - -typedef struct _SFLExtended_url { - uint32_t direction; /* enum SFLExtended_url_direction */ - SFLString url; /* URL associated with the packet flow. - Must be URL encoded */ - SFLString host; /* The host field from the HTTP header */ -} SFLExtended_url; - -/* Extended MPLS data */ - -typedef struct _SFLLabelStack { - uint32_t depth; - uint32_t *stack; /* first entry is top of stack - see RFC 3032 for encoding */ -} SFLLabelStack; - -typedef struct _SFLExtended_mpls { - SFLAddress nextHop; /* Address of the next hop */ - SFLLabelStack in_stack; - SFLLabelStack out_stack; -} SFLExtended_mpls; - - /* Extended NAT data - Packet header records report addresses as seen at the sFlowDataSource. - The extended_nat structure reports on translated source and/or destination - addesses for this packet. If an address was not translated it should - be equal to that reported for the header. */ - -typedef struct _SFLExtended_nat { - SFLAddress src; /* Source address */ - SFLAddress dst; /* Destination address */ -} SFLExtended_nat; - - /* additional Extended MPLS stucts */ - -typedef struct _SFLExtended_mpls_tunnel { - SFLString tunnel_lsp_name; /* Tunnel name */ - uint32_t tunnel_id; /* Tunnel ID */ - uint32_t tunnel_cos; /* Tunnel COS value */ -} SFLExtended_mpls_tunnel; - -typedef struct _SFLExtended_mpls_vc { - SFLString vc_instance_name; /* VC instance name */ - uint32_t vll_vc_id; /* VLL/VC instance ID */ - uint32_t vc_label_cos; /* VC Label COS value */ -} SFLExtended_mpls_vc; - -/* Extended MPLS FEC - - Definitions from MPLS-FTN-STD-MIB mplsFTNTable */ - -typedef struct _SFLExtended_mpls_FTN { - SFLString mplsFTNDescr; - uint32_t mplsFTNMask; -} SFLExtended_mpls_FTN; - -/* Extended MPLS LVP FEC - - Definition from MPLS-LDP-STD-MIB mplsFecTable - Note: mplsFecAddrType, mplsFecAddr information available - from packet header */ - -typedef struct _SFLExtended_mpls_LDP_FEC { - uint32_t mplsFecAddrPrefixLength; -} SFLExtended_mpls_LDP_FEC; - -/* Extended VLAN tunnel information - Record outer VLAN encapsulations that have - been stripped. extended_vlantunnel information - should only be reported if all the following conditions are satisfied: - 1. The packet has nested vlan tags, AND - 2. The reporting device is VLAN aware, AND - 3. One or more VLAN tags have been stripped, either - because they represent proprietary encapsulations, or - because switch hardware automatically strips the outer VLAN - encapsulation. - Reporting extended_vlantunnel information is not a substitute for - reporting extended_switch information. extended_switch data must - always be reported to describe the ingress/egress VLAN information - for the packet. The extended_vlantunnel information only applies to - nested VLAN tags, and then only when one or more tags has been - stripped. */ - -typedef SFLLabelStack SFLVlanStack; -typedef struct _SFLExtended_vlan_tunnel { - SFLVlanStack stack; /* List of stripped 802.1Q TPID/TCI layers. Each - TPID,TCI pair is represented as a single 32 bit - integer. Layers listed from outermost to - innermost. */ -} SFLExtended_vlan_tunnel; - - - ////////////////// InMon Extension structs ////////////////////////// - -typedef struct _SFLProcess { - uint32_t pid; - SFLString command; -} SFLProcess; - -#define SFL_MAX_PROCESSES 10 -typedef struct _SFLExtended_process { - uint32_t num_processes; - SFLProcess processes[SFL_MAX_PROCESSES]; -} SFLExtended_process; - - ////////////////////////////////////////////////////////////////////// - -enum SFLFlow_type_tag { - /* enterprise = 0, format = ... */ - SFLFLOW_HEADER = 1, /* Packet headers are sampled */ - SFLFLOW_ETHERNET = 2, /* MAC layer information */ - SFLFLOW_IPV4 = 3, /* IP version 4 data */ - SFLFLOW_IPV6 = 4, /* IP version 6 data */ - SFLFLOW_EX_SWITCH = 1001, /* Extended switch information */ - SFLFLOW_EX_ROUTER = 1002, /* Extended router information */ - SFLFLOW_EX_GATEWAY = 1003, /* Extended gateway router information */ - SFLFLOW_EX_USER = 1004, /* Extended TACAS/RADIUS user information */ - SFLFLOW_EX_URL = 1005, /* Extended URL information */ - SFLFLOW_EX_MPLS = 1006, /* Extended MPLS information */ - SFLFLOW_EX_NAT = 1007, /* Extended NAT information */ - SFLFLOW_EX_MPLS_TUNNEL = 1008, /* additional MPLS information */ - SFLFLOW_EX_MPLS_VC = 1009, - SFLFLOW_EX_MPLS_FTN = 1010, - SFLFLOW_EX_MPLS_LDP_FEC = 1011, - SFLFLOW_EX_VLAN_TUNNEL = 1012, /* VLAN stack */ - /* enterprise = 4300 (inmon)...*/ - SFLFLOW_EX_PROCESS = (4300 << 12) + 3, /* =17612803 Extended Process information */ -}; - -typedef union _SFLFlow_type { - SFLSampled_header header; - SFLSampled_ethernet ethernet; - SFLSampled_ipv4 ipv4; - SFLSampled_ipv6 ipv6; - SFLExtended_switch sw; - SFLExtended_router router; - SFLExtended_gateway gateway; - SFLExtended_user user; - SFLExtended_url url; - SFLExtended_mpls mpls; - SFLExtended_nat nat; - SFLExtended_mpls_tunnel mpls_tunnel; - SFLExtended_mpls_vc mpls_vc; - SFLExtended_mpls_FTN mpls_ftn; - SFLExtended_mpls_LDP_FEC mpls_ldp_fec; - SFLExtended_vlan_tunnel vlan_tunnel; - // extensions - SFLExtended_process process; -} SFLFlow_type; - -typedef struct _SFLFlow_sample_element { - struct _SFLFlow_sample_element *nxt; - uint32_t tag; /* SFLFlow_type_tag */ - uint32_t length; - SFLFlow_type flowType; -} SFLFlow_sample_element; - -enum SFL_sample_tag { - SFLFLOW_SAMPLE = 1, /* enterprise = 0 : format = 1 */ - SFLCOUNTERS_SAMPLE = 2, /* enterprise = 0 : format = 2 */ - SFLFLOW_SAMPLE_EXPANDED = 3, /* enterprise = 0 : format = 3 */ - SFLCOUNTERS_SAMPLE_EXPANDED = 4 /* enterprise = 0 : format = 4 */ -}; - -/* Format of a single flow sample */ - -typedef struct _SFLFlow_sample { - /* uint32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 1 */ - /* uint32_t length; */ - uint32_t sequence_number; /* Incremented with each flow sample - generated */ - uint32_t source_id; /* fsSourceId */ - uint32_t sampling_rate; /* fsPacketSamplingRate */ - uint32_t sample_pool; /* Total number of packets that could have been - sampled (i.e. packets skipped by sampling - process + total number of samples) */ - uint32_t drops; /* Number of times a packet was dropped due to - lack of resources */ - uint32_t input; /* SNMP ifIndex of input interface. - 0 if interface is not known. */ - uint32_t output; /* SNMP ifIndex of output interface, - 0 if interface is not known. - Set most significant bit to indicate - multiple destination interfaces - (i.e. in case of broadcast or multicast) - and set lower order bits to indicate - number of destination interfaces. - Examples: - 0x00000002 indicates ifIndex = 2 - 0x00000000 ifIndex unknown. - 0x80000007 indicates a packet sent - to 7 interfaces. - 0x80000000 indicates a packet sent to - an unknown number of - interfaces greater than 1.*/ - uint32_t num_elements; - SFLFlow_sample_element *elements; -} SFLFlow_sample; - - /* same thing, but the expanded version (for full 32-bit ifIndex numbers) */ - -typedef struct _SFLFlow_sample_expanded { - /* uint32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 1 */ - /* uint32_t length; */ - uint32_t sequence_number; /* Incremented with each flow sample - generated */ - uint32_t ds_class; /* EXPANDED */ - uint32_t ds_index; /* EXPANDED */ - uint32_t sampling_rate; /* fsPacketSamplingRate */ - uint32_t sample_pool; /* Total number of packets that could have been - sampled (i.e. packets skipped by sampling - process + total number of samples) */ - uint32_t drops; /* Number of times a packet was dropped due to - lack of resources */ - uint32_t inputFormat; /* EXPANDED */ - uint32_t input; /* SNMP ifIndex of input interface. - 0 if interface is not known. */ - uint32_t outputFormat; /* EXPANDED */ - uint32_t output; /* SNMP ifIndex of output interface, - 0 if interface is not known. */ - uint32_t num_elements; - SFLFlow_sample_element *elements; -} SFLFlow_sample_expanded; - -/* Counter types */ - -/* Generic interface counters - see RFC 1573, 2233 */ - -typedef struct _SFLIf_counters { - uint32_t ifIndex; - uint32_t ifType; - uint64_t ifSpeed; - uint32_t ifDirection; /* Derived from MAU MIB (RFC 2668) - 0 = unknown, 1 = full-duplex, - 2 = half-duplex, 3 = in, 4 = out */ - uint32_t ifStatus; /* bit field with the following bits assigned: - bit 0 = ifAdminStatus (0 = down, 1 = up) - bit 1 = ifOperStatus (0 = down, 1 = up) */ - uint64_t ifInOctets; - uint32_t ifInUcastPkts; - uint32_t ifInMulticastPkts; - uint32_t ifInBroadcastPkts; - uint32_t ifInDiscards; - uint32_t ifInErrors; - uint32_t ifInUnknownProtos; - uint64_t ifOutOctets; - uint32_t ifOutUcastPkts; - uint32_t ifOutMulticastPkts; - uint32_t ifOutBroadcastPkts; - uint32_t ifOutDiscards; - uint32_t ifOutErrors; - uint32_t ifPromiscuousMode; -} SFLIf_counters; - -/* Ethernet interface counters - see RFC 2358 */ -typedef struct _SFLEthernet_counters { - uint32_t dot3StatsAlignmentErrors; - uint32_t dot3StatsFCSErrors; - uint32_t dot3StatsSingleCollisionFrames; - uint32_t dot3StatsMultipleCollisionFrames; - uint32_t dot3StatsSQETestErrors; - uint32_t dot3StatsDeferredTransmissions; - uint32_t dot3StatsLateCollisions; - uint32_t dot3StatsExcessiveCollisions; - uint32_t dot3StatsInternalMacTransmitErrors; - uint32_t dot3StatsCarrierSenseErrors; - uint32_t dot3StatsFrameTooLongs; - uint32_t dot3StatsInternalMacReceiveErrors; - uint32_t dot3StatsSymbolErrors; -} SFLEthernet_counters; - -/* Token ring counters - see RFC 1748 */ - -typedef struct _SFLTokenring_counters { - uint32_t dot5StatsLineErrors; - uint32_t dot5StatsBurstErrors; - uint32_t dot5StatsACErrors; - uint32_t dot5StatsAbortTransErrors; - uint32_t dot5StatsInternalErrors; - uint32_t dot5StatsLostFrameErrors; - uint32_t dot5StatsReceiveCongestions; - uint32_t dot5StatsFrameCopiedErrors; - uint32_t dot5StatsTokenErrors; - uint32_t dot5StatsSoftErrors; - uint32_t dot5StatsHardErrors; - uint32_t dot5StatsSignalLoss; - uint32_t dot5StatsTransmitBeacons; - uint32_t dot5StatsRecoverys; - uint32_t dot5StatsLobeWires; - uint32_t dot5StatsRemoves; - uint32_t dot5StatsSingles; - uint32_t dot5StatsFreqErrors; -} SFLTokenring_counters; - -/* 100 BaseVG interface counters - see RFC 2020 */ - -typedef struct _SFLVg_counters { - uint32_t dot12InHighPriorityFrames; - uint64_t dot12InHighPriorityOctets; - uint32_t dot12InNormPriorityFrames; - uint64_t dot12InNormPriorityOctets; - uint32_t dot12InIPMErrors; - uint32_t dot12InOversizeFrameErrors; - uint32_t dot12InDataErrors; - uint32_t dot12InNullAddressedFrames; - uint32_t dot12OutHighPriorityFrames; - uint64_t dot12OutHighPriorityOctets; - uint32_t dot12TransitionIntoTrainings; - uint64_t dot12HCInHighPriorityOctets; - uint64_t dot12HCInNormPriorityOctets; - uint64_t dot12HCOutHighPriorityOctets; -} SFLVg_counters; - -typedef struct _SFLVlan_counters { - uint32_t vlan_id; - uint64_t octets; - uint32_t ucastPkts; - uint32_t multicastPkts; - uint32_t broadcastPkts; - uint32_t discards; -} SFLVlan_counters; - -/* Processor Information */ -/* opaque = counter_data; enterprise = 0; format = 1001 */ - -typedef struct _SFLProcessor_counters { - uint32_t five_sec_cpu; /* 5 second average CPU utilization */ - uint32_t one_min_cpu; /* 1 minute average CPU utilization */ - uint32_t five_min_cpu; /* 5 minute average CPU utilization */ - uint64_t total_memory; /* total memory (in bytes) */ - uint64_t free_memory; /* free memory (in bytes) */ -} SFLProcessor_counters; - -/* Counters data */ - -enum SFLCounters_type_tag { - /* enterprise = 0, format = ... */ - SFLCOUNTERS_GENERIC = 1, - SFLCOUNTERS_ETHERNET = 2, - SFLCOUNTERS_TOKENRING = 3, - SFLCOUNTERS_VG = 4, - SFLCOUNTERS_VLAN = 5, - SFLCOUNTERS_PROCESSOR = 1001 -}; - -typedef union _SFLCounters_type { - SFLIf_counters generic; - SFLEthernet_counters ethernet; - SFLTokenring_counters tokenring; - SFLVg_counters vg; - SFLVlan_counters vlan; - SFLProcessor_counters processor; -} SFLCounters_type; - -typedef struct _SFLCounters_sample_element { - struct _SFLCounters_sample_element *nxt; /* linked list */ - uint32_t tag; /* SFLCounters_type_tag */ - uint32_t length; - SFLCounters_type counterBlock; -} SFLCounters_sample_element; - -typedef struct _SFLCounters_sample { - /* uint32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 2 */ - /* uint32_t length; */ - uint32_t sequence_number; /* Incremented with each counters sample - generated by this source_id */ - uint32_t source_id; /* fsSourceId */ - uint32_t num_elements; - SFLCounters_sample_element *elements; -} SFLCounters_sample; - -/* same thing, but the expanded version, so ds_index can be a full 32 bits */ -typedef struct _SFLCounters_sample_expanded { - /* uint32_t tag; */ /* SFL_sample_tag -- enterprise = 0 : format = 2 */ - /* uint32_t length; */ - uint32_t sequence_number; /* Incremented with each counters sample - generated by this source_id */ - uint32_t ds_class; /* EXPANDED */ - uint32_t ds_index; /* EXPANDED */ - uint32_t num_elements; - SFLCounters_sample_element *elements; -} SFLCounters_sample_expanded; - -#define SFLADD_ELEMENT(_sm, _el) do { (_el)->nxt = (_sm)->elements; (_sm)->elements = (_el); } while(0) - -/* Format of a sample datagram */ - -enum SFLDatagram_version { - SFLDATAGRAM_VERSION2 = 2, - SFLDATAGRAM_VERSION4 = 4, - SFLDATAGRAM_VERSION5 = 5 -}; - -typedef struct _SFLSample_datagram_hdr { - uint32_t datagram_version; /* (enum SFLDatagram_version) = VERSION5 = 5 */ - SFLAddress agent_address; /* IP address of sampling agent */ - uint32_t sub_agent_id; /* Used to distinguishing between datagram - streams from separate agent sub entities - within an device. */ - uint32_t sequence_number; /* Incremented with each sample datagram - generated */ - uint32_t uptime; /* Current time (in milliseconds since device - last booted). Should be set as close to - datagram transmission time as possible.*/ - uint32_t num_records; /* Number of tag-len-val flow/counter records to follow */ -} SFLSample_datagram_hdr; - -#define SFL_MAX_DATAGRAM_SIZE 1500 -#define SFL_MIN_DATAGRAM_SIZE 200 -#define SFL_DEFAULT_DATAGRAM_SIZE 1400 - -#define SFL_DATA_PAD 400 - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -#endif /* _SFLOW_PROTO_H */ diff --git a/bin/sflow_v2v4.h b/bin/sflow_v2v4.h new file mode 100755 index 0000000..1231c10 --- /dev/null +++ b/bin/sflow_v2v4.h @@ -0,0 +1,436 @@ +/* Copyright (c) 2002-2011 InMon Corp. Licensed under the terms of the InMon sFlow licence: */ +/* http://www.inmon.com/technology/sflowlicense.txt */ + +#ifndef SFLOW_V2V4_H +#define SFLOW_V2V4_H 1 + +#if defined(__cplusplus) +extern "C" { +#endif + +enum INMAddress_type { + INMADDRESSTYPE_IP_V4 = 1, + INMADDRESSTYPE_IP_V6 = 2 +}; + +typedef union _INMAddress_value { + SFLIPv4 ip_v4; + SFLIPv6 ip_v6; +} INMAddress_value; + +typedef struct _INMAddress { + uint32_t type; /* enum INMAddress_type */ + INMAddress_value address; +} INMAddress; + +/* Packet header data */ + +#define INM_MAX_HEADER_SIZE 256 /* The maximum sampled header size. */ +#define INM_DEFAULT_HEADER_SIZE 128 +#define INM_DEFAULT_COLLECTOR_PORT 6343 +#define INM_DEFAULT_SAMPLING_RATE 400 + +/* The header protocol describes the format of the sampled header */ +enum INMHeader_protocol { + INMHEADER_ETHERNET_ISO8023 = 1, + INMHEADER_ISO88024_TOKENBUS = 2, + INMHEADER_ISO88025_TOKENRING = 3, + INMHEADER_FDDI = 4, + INMHEADER_FRAME_RELAY = 5, + INMHEADER_X25 = 6, + INMHEADER_PPP = 7, + INMHEADER_SMDS = 8, + INMHEADER_AAL5 = 9, + INMHEADER_AAL5_IP = 10, /* e.g. Cisco AAL5 mux */ + INMHEADER_IPv4 = 11, + INMHEADER_IPv6 = 12 +}; + +typedef struct _INMSampled_header { + uint32_t header_protocol; /* (enum INMHeader_protocol) */ + uint32_t frame_length; /* Original length of packet before sampling */ + uint32_t header_length; /* length of sampled header bytes to follow */ + uint8_t header[INM_MAX_HEADER_SIZE]; /* Header bytes */ +} INMSampled_header; + +/* Packet IP version 4 data */ + +typedef struct _INMSampled_ipv4 { + uint32_t length; /* The length of the IP packet + excluding lower layer encapsulations */ + uint32_t protocol; /* IP Protocol type (for example, TCP = 6, UDP = 17) */ + SFLIPv4 src_ip; /* Source IP Address */ + SFLIPv4 dst_ip; /* Destination IP Address */ + uint32_t src_port; /* TCP/UDP source port number or equivalent */ + uint32_t dst_port; /* TCP/UDP destination port number or equivalent */ + uint32_t tcp_flags; /* TCP flags */ + uint32_t tos; /* IP type of service */ +} INMSampled_ipv4; + +/* Packet IP version 6 data */ + +typedef struct _INMSampled_ipv6 { + uint32_t length; /* The length of the IP packet + excluding lower layer encapsulations */ + uint32_t protocol; /* IP Protocol type (for example, TCP = 6, UDP = 17) */ + SFLIPv6 src_ip; /* Source IP Address */ + SFLIPv6 dst_ip; /* Destination IP Address */ + uint32_t src_port; /* TCP/UDP source port number or equivalent */ + uint32_t dst_port; /* TCP/UDP destination port number or equivalent */ + uint32_t tcp_flags; /* TCP flags */ + uint32_t tos; /* IP type of service */ +} INMSampled_ipv6; + + +/* Packet data */ + +enum INMPacket_information_type { + INMPACKETTYPE_HEADER = 1, /* Packet headers are sampled */ + INMPACKETTYPE_IPV4 = 2, /* IP version 4 data */ + INMPACKETTYPE_IPV6 = 3 /* IP version 4 data */ +}; + +typedef union _INMPacket_data_type { + INMSampled_header header; + INMSampled_ipv4 ipv4; + INMSampled_ipv6 ipv6; +} INMPacket_data_type; + +/* Extended data types */ + +/* Extended switch data */ + +typedef struct _INMExtended_switch { + uint32_t src_vlan; /* The 802.1Q VLAN id of incomming frame */ + uint32_t src_priority; /* The 802.1p priority */ + uint32_t dst_vlan; /* The 802.1Q VLAN id of outgoing frame */ + uint32_t dst_priority; /* The 802.1p priority */ +} INMExtended_switch; + +/* Extended router data */ + +typedef struct _INMExtended_router { + INMAddress nexthop; /* IP address of next hop router */ + uint32_t src_mask; /* Source address prefix mask bits */ + uint32_t dst_mask; /* Destination address prefix mask bits */ +} INMExtended_router; + +/* Extended gateway data */ + +enum INMExtended_as_path_segment_type { + INMEXTENDED_AS_SET = 1, /* Unordered set of ASs */ + INMEXTENDED_AS_SEQUENCE = 2 /* Ordered sequence of ASs */ +}; + +typedef struct _INMExtended_as_path_segment { + uint32_t type; /* enum INMExtended_as_path_segment_type */ + uint32_t length; /* number of AS numbers in set/sequence */ + union { + uint32_t *set; + uint32_t *seq; + } as; +} INMExtended_as_path_segment; + +/* note: the INMExtended_gateway structure has changed between v2 and v4. + Here is the old version first... */ + +typedef struct _INMExtended_gateway_v2 { + uint32_t as; /* AS number for this gateway */ + uint32_t src_as; /* AS number of source (origin) */ + uint32_t src_peer_as; /* AS number of source peer */ + uint32_t dst_as_path_length; /* number of AS numbers in path */ + uint32_t *dst_as_path; +} INMExtended_gateway_v2; + +/* now here is the new version... */ + +typedef struct _INMExtended_gateway_v4 { + uint32_t as; /* AS number for this gateway */ + uint32_t src_as; /* AS number of source (origin) */ + uint32_t src_peer_as; /* AS number of source peer */ + uint32_t dst_as_path_segments; /* number of segments in path */ + INMExtended_as_path_segment *dst_as_path; /* list of seqs or sets */ + uint32_t communities_length; /* number of communities */ + uint32_t *communities; /* set of communities */ + uint32_t localpref; /* LocalPref associated with this route */ +} INMExtended_gateway_v4; + +/* Extended user data */ +typedef struct _INMExtended_user { + uint32_t src_user_len; + char *src_user; + uint32_t dst_user_len; + char *dst_user; +} INMExtended_user; +enum INMExtended_url_direction { + INMEXTENDED_URL_SRC = 1, /* URL is associated with source address */ + INMEXTENDED_URL_DST = 2 /* URL is associated with destination address */ +}; + +typedef struct _INMExtended_url { + uint32_t direction; /* enum INMExtended_url_direction */ + uint32_t url_len; + char *url; +} INMExtended_url; + +/* Extended data */ + +enum INMExtended_information_type { + INMEXTENDED_SWITCH = 1, /* Extended switch information */ + INMEXTENDED_ROUTER = 2, /* Extended router information */ + INMEXTENDED_GATEWAY = 3, /* Extended gateway router information */ + INMEXTENDED_USER = 4, /* Extended TACAS/RADIUS user information */ + INMEXTENDED_URL = 5 /* Extended URL information */ +}; + +/* Format of a single sample */ + +typedef struct _INMFlow_sample { + uint32_t sequence_number; /* Incremented with each flow sample + generated */ + uint32_t source_id; /* fsSourceId */ + uint32_t sampling_rate; /* fsPacketSamplingRate */ + uint32_t sample_pool; /* Total number of packets that could have been + sampled (i.e. packets skipped by sampling + process + total number of samples) */ + uint32_t drops; /* Number of times a packet was dropped due to + lack of resources */ + uint32_t input; /* SNMP ifIndex of input interface. + 0 if interface is not known. */ + uint32_t output; /* SNMP ifIndex of output interface, + 0 if interface is not known. + Set most significant bit to indicate + multiple destination interfaces + (i.e. in case of broadcast or multicast) + and set lower order bits to indicate + number of destination interfaces. + Examples: + 0x00000002 indicates ifIndex = 2 + 0x00000000 ifIndex unknown. + 0x80000007 indicates a packet sent + to 7 interfaces. + 0x80000000 indicates a packet sent to + an unknown number of + interfaces greater than 1.*/ + uint32_t packet_data_tag; /* enum INMPacket_information_type */ + INMPacket_data_type packet_data; /* Information about sampled packet */ + + /* in the sFlow packet spec the next field is the number of extended objects + followed by the data for each one (tagged with the type). Here we just + provide space for each one, and flags to enable them. The correct format + is then put together by the serialization code */ + int gotSwitch; + INMExtended_switch switchDevice; + int gotRouter; + INMExtended_router router; + int gotGateway; + union { + INMExtended_gateway_v2 v2; /* make the version explicit so that there is */ + INMExtended_gateway_v4 v4; /* less danger of mistakes when upgrading code */ + } gateway; + int gotUser; + INMExtended_user user; + int gotUrl; + INMExtended_url url; +} INMFlow_sample; + +/* Counter types */ + +/* Generic interface counters - see RFC 1573, 2233 */ + +typedef struct _INMIf_counters { + uint32_t ifIndex; + uint32_t ifType; + uint64_t ifSpeed; + uint32_t ifDirection; /* Derived from MAU MIB (RFC 2239) + 0 = unknown, 1 = full-duplex, + 2 = half-duplex, 3 = in, 4 = out */ + uint32_t ifStatus; /* bit field with the following bits assigned: + bit 0 = ifAdminStatus (0 = down, 1 = up) + bit 1 = ifOperStatus (0 = down, 1 = up) */ + uint64_t ifInOctets; + uint32_t ifInUcastPkts; + uint32_t ifInMulticastPkts; + uint32_t ifInBroadcastPkts; + uint32_t ifInDiscards; + uint32_t ifInErrors; + uint32_t ifInUnknownProtos; + uint64_t ifOutOctets; + uint32_t ifOutUcastPkts; + uint32_t ifOutMulticastPkts; + uint32_t ifOutBroadcastPkts; + uint32_t ifOutDiscards; + uint32_t ifOutErrors; + uint32_t ifPromiscuousMode; +} INMIf_counters; + +/* Ethernet interface counters - see RFC 2358 */ +typedef struct _INMEthernet_specific_counters { + uint32_t dot3StatsAlignmentErrors; + uint32_t dot3StatsFCSErrors; + uint32_t dot3StatsSingleCollisionFrames; + uint32_t dot3StatsMultipleCollisionFrames; + uint32_t dot3StatsSQETestErrors; + uint32_t dot3StatsDeferredTransmissions; + uint32_t dot3StatsLateCollisions; + uint32_t dot3StatsExcessiveCollisions; + uint32_t dot3StatsInternalMacTransmitErrors; + uint32_t dot3StatsCarrierSenseErrors; + uint32_t dot3StatsFrameTooLongs; + uint32_t dot3StatsInternalMacReceiveErrors; + uint32_t dot3StatsSymbolErrors; +} INMEthernet_specific_counters; + +typedef struct _INMEthernet_counters { + INMIf_counters generic; + INMEthernet_specific_counters ethernet; +} INMEthernet_counters; + +/* FDDI interface counters - see RFC 1512 */ +typedef struct _INMFddi_counters { + INMIf_counters generic; +} INMFddi_counters; + +/* Token ring counters - see RFC 1748 */ + +typedef struct _INMTokenring_specific_counters { + uint32_t dot5StatsLineErrors; + uint32_t dot5StatsBurstErrors; + uint32_t dot5StatsACErrors; + uint32_t dot5StatsAbortTransErrors; + uint32_t dot5StatsInternalErrors; + uint32_t dot5StatsLostFrameErrors; + uint32_t dot5StatsReceiveCongestions; + uint32_t dot5StatsFrameCopiedErrors; + uint32_t dot5StatsTokenErrors; + uint32_t dot5StatsSoftErrors; + uint32_t dot5StatsHardErrors; + uint32_t dot5StatsSignalLoss; + uint32_t dot5StatsTransmitBeacons; + uint32_t dot5StatsRecoverys; + uint32_t dot5StatsLobeWires; + uint32_t dot5StatsRemoves; + uint32_t dot5StatsSingles; + uint32_t dot5StatsFreqErrors; +} INMTokenring_specific_counters; + +typedef struct _INMTokenring_counters { + INMIf_counters generic; + INMTokenring_specific_counters tokenring; +} INMTokenring_counters; + +/* 100 BaseVG interface counters - see RFC 2020 */ + +typedef struct _INMVg_specific_counters { + uint32_t dot12InHighPriorityFrames; + uint64_t dot12InHighPriorityOctets; + uint32_t dot12InNormPriorityFrames; + uint64_t dot12InNormPriorityOctets; + uint32_t dot12InIPMErrors; + uint32_t dot12InOversizeFrameErrors; + uint32_t dot12InDataErrors; + uint32_t dot12InNullAddressedFrames; + uint32_t dot12OutHighPriorityFrames; + uint64_t dot12OutHighPriorityOctets; + uint32_t dot12TransitionIntoTrainings; + uint64_t dot12HCInHighPriorityOctets; + uint64_t dot12HCInNormPriorityOctets; + uint64_t dot12HCOutHighPriorityOctets; +} INMVg_specific_counters; + +typedef struct _INMVg_counters { + INMIf_counters generic; + INMVg_specific_counters vg; +} INMVg_counters; + +/* WAN counters */ + +typedef struct _INMWan_counters { + INMIf_counters generic; +} INMWan_counters; + +typedef struct _INMVlan_counters { + uint32_t vlan_id; + uint64_t octets; + uint32_t ucastPkts; + uint32_t multicastPkts; + uint32_t broadcastPkts; + uint32_t discards; +} INMVlan_counters; + +/* Counters data */ + +enum INMCounters_version { + INMCOUNTERSVERSION_GENERIC = 1, + INMCOUNTERSVERSION_ETHERNET = 2, + INMCOUNTERSVERSION_TOKENRING = 3, + INMCOUNTERSVERSION_FDDI = 4, + INMCOUNTERSVERSION_VG = 5, + INMCOUNTERSVERSION_WAN = 6, + INMCOUNTERSVERSION_VLAN = 7 +}; + +typedef union _INMCounters_type { + INMIf_counters generic; + INMEthernet_counters ethernet; + INMTokenring_counters tokenring; + INMFddi_counters fddi; + INMVg_counters vg; + INMWan_counters wan; + INMVlan_counters vlan; +} INMCounters_type; + +typedef struct _INMCounters_sample_hdr { + uint32_t sequence_number; /* Incremented with each counters sample + generated by this source_id */ + uint32_t source_id; /* fsSourceId */ + uint32_t sampling_interval; /* fsCounterSamplingInterval */ +} INMCounters_sample_hdr; + +typedef struct _INMCounters_sample { + INMCounters_sample_hdr hdr; + uint32_t counters_type_tag; /* Enum INMCounters_version */ + INMCounters_type counters; /* Counter set for this interface type */ +} INMCounters_sample; + +/* when I turn on optimisation with the Microsoft compiler it seems to change + the values of these enumerated types and break the program - not sure why */ +enum INMSample_types { + FLOWSAMPLE = 1, + COUNTERSSAMPLE = 2 +}; + +typedef union _INMSample_type { + INMFlow_sample flowsample; + INMCounters_sample counterssample; +} INMSample_type; + +/* Format of a sample datagram */ + +enum INMDatagram_version { + INMDATAGRAM_VERSION2 = 2, + INMDATAGRAM_VERSION4 = 4 +}; + +typedef struct _INMSample_datagram_hdr { + uint32_t datagram_version; /* (enum INMDatagram_version) = VERSION4 */ + INMAddress agent_address; /* IP address of sampling agent */ + uint32_t sequence_number; /* Incremented with each sample datagram + generated */ + uint32_t uptime; /* Current time (in milliseconds since device + last booted). Should be set as close to + datagram transmission time as possible.*/ + uint32_t num_samples; /* Number of flow and counters samples to follow */ +} INMSample_datagram_hdr; + +#define INM_MAX_DATAGRAM_SIZE 1500 +#define INM_MIN_DATAGRAM_SIZE 200 +#define INM_DEFAULT_DATAGRAM_SIZE 1400 + +#define INM_DATA_PAD 400 + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /* SFLOW_V2V4_H */