mirror of
https://github.com/netsampler/goflow2.git
synced 2024-05-06 15:54:52 +00:00
792 lines
23 KiB
Go
792 lines
23 KiB
Go
package protoproducer
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/netsampler/goflow2/v2/decoders/netflow"
|
|
flowmessage "github.com/netsampler/goflow2/v2/pb"
|
|
"github.com/netsampler/goflow2/v2/producer"
|
|
)
|
|
|
|
type SamplingRateSystem interface {
|
|
GetSamplingRate(version uint16, obsDomainId uint32) (uint32, error)
|
|
AddSamplingRate(version uint16, obsDomainId uint32, samplingRate uint32)
|
|
}
|
|
|
|
type basicSamplingRateSystem struct {
|
|
//sampling map[uint16]map[uint32]uint32
|
|
sampling map[string]uint32
|
|
samplinglock *sync.RWMutex
|
|
}
|
|
|
|
func CreateSamplingSystem() SamplingRateSystem {
|
|
ts := &basicSamplingRateSystem{
|
|
//sampling: make(map[uint16]map[uint32]uint32),
|
|
sampling: make(map[string]uint32),
|
|
samplinglock: &sync.RWMutex{},
|
|
}
|
|
return ts
|
|
}
|
|
|
|
func (s *basicSamplingRateSystem) AddSamplingRate(version uint16, obsDomainId uint32, samplingRate uint32) {
|
|
s.samplinglock.Lock()
|
|
defer s.samplinglock.Unlock()
|
|
/*_, exists := s.sampling[version]
|
|
if exists != true {
|
|
s.sampling[version] = make(map[uint32]uint32)
|
|
}
|
|
s.sampling[version][obsDomainId] = samplingRate*/
|
|
s.sampling[fmt.Sprintf("%d-%d", version, obsDomainId)] = samplingRate
|
|
}
|
|
|
|
func (s *basicSamplingRateSystem) GetSamplingRate(version uint16, obsDomainId uint32) (uint32, error) {
|
|
s.samplinglock.RLock()
|
|
defer s.samplinglock.RUnlock()
|
|
if samplingRate, ok := s.sampling[fmt.Sprintf("%d-%d", version, obsDomainId)]; ok {
|
|
return samplingRate, nil
|
|
}
|
|
|
|
return 0, fmt.Errorf("sampling rate not found")
|
|
}
|
|
|
|
type SingleSamplingRateSystem struct {
|
|
Sampling uint32
|
|
}
|
|
|
|
func (s *SingleSamplingRateSystem) AddSamplingRate(version uint16, obsDomainId uint32, samplingRate uint32) {
|
|
}
|
|
|
|
func (s *SingleSamplingRateSystem) GetSamplingRate(version uint16, obsDomainId uint32) (uint32, error) {
|
|
return s.Sampling, nil
|
|
}
|
|
|
|
func NetFlowLookFor(dataFields []netflow.DataField, typeId uint16) (bool, interface{}) {
|
|
for _, dataField := range dataFields {
|
|
if dataField.Type == typeId {
|
|
return true, dataField.Value
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
func NetFlowPopulate(dataFields []netflow.DataField, typeId uint16, addr interface{}) (bool, error) {
|
|
exists, value := NetFlowLookFor(dataFields, typeId)
|
|
if exists && value != nil {
|
|
valueBytes, ok := value.([]byte)
|
|
valueReader := bytes.NewReader(valueBytes)
|
|
if ok {
|
|
switch addrt := addr.(type) {
|
|
//case *(net.IP):
|
|
// *addrt = valueBytes
|
|
case *(time.Time):
|
|
t := uint64(0)
|
|
if err := binary.Read(valueReader, binary.BigEndian, &t); err != nil {
|
|
return false, err
|
|
}
|
|
t64 := int64(t / 1000)
|
|
*addrt = time.Unix(t64, 0)
|
|
default:
|
|
if err := binary.Read(valueReader, binary.BigEndian, addr); err != nil {
|
|
return false, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return exists, nil
|
|
}
|
|
|
|
func WriteUDecoded(o uint64, out interface{}) error {
|
|
switch t := out.(type) {
|
|
case *byte:
|
|
*t = byte(o)
|
|
case *uint16:
|
|
*t = uint16(o)
|
|
case *uint32:
|
|
*t = uint32(o)
|
|
case *uint64:
|
|
*t = o
|
|
default:
|
|
return fmt.Errorf("the parameter is not a pointer to a byte/uint16/uint32/uint64 structure")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func WriteDecoded(o int64, out interface{}) error {
|
|
switch t := out.(type) {
|
|
case *int8:
|
|
*t = int8(o)
|
|
case *int16:
|
|
*t = int16(o)
|
|
case *int32:
|
|
*t = int32(o)
|
|
case *int64:
|
|
*t = o
|
|
default:
|
|
return fmt.Errorf("the parameter is not a pointer to a int8/int16/int32/int64 structure")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func DecodeUNumber(b []byte, out interface{}) error {
|
|
var o uint64
|
|
l := len(b)
|
|
switch l {
|
|
case 1:
|
|
o = uint64(b[0])
|
|
case 2:
|
|
o = uint64(binary.BigEndian.Uint16(b))
|
|
case 4:
|
|
o = uint64(binary.BigEndian.Uint32(b))
|
|
case 8:
|
|
o = binary.BigEndian.Uint64(b)
|
|
default:
|
|
if l < 8 {
|
|
var iter uint
|
|
for i := range b {
|
|
o |= uint64(b[i]) << uint(8*(uint(l)-iter-1))
|
|
iter++
|
|
}
|
|
} else {
|
|
return fmt.Errorf("non-regular number of bytes for a number: %v", l)
|
|
}
|
|
}
|
|
return WriteUDecoded(o, out)
|
|
}
|
|
|
|
func DecodeUNumberLE(b []byte, out interface{}) error {
|
|
var o uint64
|
|
l := len(b)
|
|
switch l {
|
|
case 1:
|
|
o = uint64(b[0])
|
|
case 2:
|
|
o = uint64(binary.LittleEndian.Uint16(b))
|
|
case 4:
|
|
o = uint64(binary.LittleEndian.Uint32(b))
|
|
case 8:
|
|
o = binary.LittleEndian.Uint64(b)
|
|
default:
|
|
if l < 8 {
|
|
var iter uint
|
|
for i := range b {
|
|
o |= uint64(b[i]) << uint(8*(iter))
|
|
iter++
|
|
}
|
|
} else {
|
|
return fmt.Errorf("non-regular number of bytes for a number: %v", l)
|
|
}
|
|
}
|
|
return WriteUDecoded(o, out)
|
|
}
|
|
|
|
func DecodeNumber(b []byte, out interface{}) error {
|
|
var o int64
|
|
l := len(b)
|
|
switch l {
|
|
case 1:
|
|
o = int64(int8(b[0]))
|
|
case 2:
|
|
o = int64(int16(binary.BigEndian.Uint16(b)))
|
|
case 4:
|
|
o = int64(int32(binary.BigEndian.Uint32(b)))
|
|
case 8:
|
|
o = int64(binary.BigEndian.Uint64(b))
|
|
default:
|
|
if l < 8 {
|
|
var iter int
|
|
for i := range b {
|
|
o |= int64(b[i]) << int(8*(int(l)-iter-1))
|
|
iter++
|
|
}
|
|
} else {
|
|
return fmt.Errorf("non-regular number of bytes for a number: %v", l)
|
|
}
|
|
}
|
|
return WriteDecoded(o, out)
|
|
}
|
|
|
|
func DecodeNumberLE(b []byte, out interface{}) error {
|
|
var o int64
|
|
l := len(b)
|
|
switch l {
|
|
case 1:
|
|
o = int64(int8(b[0]))
|
|
case 2:
|
|
o = int64(int16(binary.LittleEndian.Uint16(b)))
|
|
case 4:
|
|
o = int64(int32(binary.LittleEndian.Uint32(b)))
|
|
case 8:
|
|
o = int64(binary.LittleEndian.Uint64(b))
|
|
default:
|
|
if l < 8 {
|
|
var iter int
|
|
for i := range b {
|
|
o |= int64(b[i]) << int(8*(iter))
|
|
iter++
|
|
}
|
|
} else {
|
|
return fmt.Errorf("non-regular number of bytes for a number: %v", l)
|
|
}
|
|
}
|
|
return WriteDecoded(o, out)
|
|
}
|
|
|
|
func allZeroes(v []byte) bool {
|
|
for _, b := range v {
|
|
if b != 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func addrReplaceCheck(dstAddr *[]byte, v []byte, eType *uint32, ipv6 bool) {
|
|
if (len(*dstAddr) == 0 && len(v) > 0) ||
|
|
(len(*dstAddr) != 0 && len(v) > 0 && !allZeroes(v)) {
|
|
*dstAddr = v
|
|
|
|
if ipv6 {
|
|
*eType = 0x86dd
|
|
} else {
|
|
*eType = 0x800
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
func ConvertNetFlowDataSet(flowMessage *ProtoProducerMessage, version uint16, baseTime uint32, uptime uint32, record []netflow.DataField, mapperNetFlow *NetFlowMapper, mapperSFlow *SFlowMapper) error {
|
|
var time uint64
|
|
baseTimeNs := uint64(baseTime) * 1000000000
|
|
// the following should be overriden if the template contains timing information
|
|
// otherwise, defaults to the export time
|
|
flowMessage.TimeFlowStartNs = baseTimeNs
|
|
flowMessage.TimeFlowEndNs = baseTimeNs
|
|
|
|
if version == 9 {
|
|
flowMessage.Type = flowmessage.FlowMessage_NETFLOW_V9
|
|
} else if version == 10 {
|
|
flowMessage.Type = flowmessage.FlowMessage_IPFIX
|
|
}
|
|
|
|
for i := range record {
|
|
df := record[i]
|
|
|
|
v, ok := df.Value.([]byte)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if err := MapCustomNetFlow(flowMessage, df, mapperNetFlow); err != nil {
|
|
return err
|
|
}
|
|
|
|
if df.PenProvided {
|
|
continue
|
|
}
|
|
|
|
switch df.Type {
|
|
|
|
case netflow.IPFIX_FIELD_observationPointId:
|
|
if err := DecodeUNumber(v, &(flowMessage.ObservationPointId)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Statistics
|
|
case netflow.NFV9_FIELD_IN_BYTES:
|
|
if err := DecodeUNumber(v, &(flowMessage.Bytes)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_IN_PKTS:
|
|
if err := DecodeUNumber(v, &(flowMessage.Packets)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_OUT_BYTES:
|
|
if err := DecodeUNumber(v, &(flowMessage.Bytes)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_OUT_PKTS:
|
|
if err := DecodeUNumber(v, &(flowMessage.Packets)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// L4
|
|
case netflow.NFV9_FIELD_L4_SRC_PORT:
|
|
if err := DecodeUNumber(v, &(flowMessage.SrcPort)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_L4_DST_PORT:
|
|
if err := DecodeUNumber(v, &(flowMessage.DstPort)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_PROTOCOL:
|
|
if err := DecodeUNumber(v, &(flowMessage.Proto)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Network
|
|
case netflow.NFV9_FIELD_SRC_AS:
|
|
if err := DecodeUNumber(v, &(flowMessage.SrcAs)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_DST_AS:
|
|
if err := DecodeUNumber(v, &(flowMessage.DstAs)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Interfaces
|
|
case netflow.NFV9_FIELD_INPUT_SNMP:
|
|
if err := DecodeUNumber(v, &(flowMessage.InIf)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_OUTPUT_SNMP:
|
|
if err := DecodeUNumber(v, &(flowMessage.OutIf)); err != nil {
|
|
return err
|
|
}
|
|
|
|
case netflow.NFV9_FIELD_FORWARDING_STATUS:
|
|
if err := DecodeUNumber(v, &(flowMessage.ForwardingStatus)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_SRC_TOS:
|
|
if err := DecodeUNumber(v, &(flowMessage.IpTos)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_TCP_FLAGS:
|
|
if err := DecodeUNumber(v, &(flowMessage.TcpFlags)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_MIN_TTL:
|
|
if err := DecodeUNumber(v, &(flowMessage.IpTtl)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// IP
|
|
case netflow.NFV9_FIELD_IP_PROTOCOL_VERSION:
|
|
if len(v) > 0 {
|
|
if v[0] == 4 {
|
|
flowMessage.Etype = 0x800
|
|
} else if v[0] == 6 {
|
|
flowMessage.Etype = 0x86dd
|
|
}
|
|
}
|
|
|
|
case netflow.NFV9_FIELD_IPV4_SRC_ADDR:
|
|
addrReplaceCheck(&(flowMessage.SrcAddr), v, &(flowMessage.Etype), false)
|
|
|
|
case netflow.NFV9_FIELD_IPV4_DST_ADDR:
|
|
addrReplaceCheck(&(flowMessage.DstAddr), v, &(flowMessage.Etype), false)
|
|
|
|
case netflow.NFV9_FIELD_SRC_MASK:
|
|
if err := DecodeUNumber(v, &(flowMessage.SrcNet)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_DST_MASK:
|
|
if err := DecodeUNumber(v, &(flowMessage.DstNet)); err != nil {
|
|
return err
|
|
}
|
|
|
|
case netflow.NFV9_FIELD_IPV6_SRC_ADDR:
|
|
addrReplaceCheck(&(flowMessage.SrcAddr), v, &(flowMessage.Etype), true)
|
|
|
|
case netflow.NFV9_FIELD_IPV6_DST_ADDR:
|
|
addrReplaceCheck(&(flowMessage.DstAddr), v, &(flowMessage.Etype), true)
|
|
|
|
case netflow.NFV9_FIELD_IPV6_SRC_MASK:
|
|
if err := DecodeUNumber(v, &(flowMessage.SrcNet)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_IPV6_DST_MASK:
|
|
if err := DecodeUNumber(v, &(flowMessage.DstNet)); err != nil {
|
|
return err
|
|
}
|
|
|
|
case netflow.NFV9_FIELD_IPV4_NEXT_HOP:
|
|
flowMessage.NextHop = v
|
|
case netflow.NFV9_FIELD_BGP_IPV4_NEXT_HOP:
|
|
flowMessage.BgpNextHop = v
|
|
|
|
case netflow.NFV9_FIELD_IPV6_NEXT_HOP:
|
|
flowMessage.NextHop = v
|
|
case netflow.NFV9_FIELD_BGP_IPV6_NEXT_HOP:
|
|
flowMessage.BgpNextHop = v
|
|
|
|
// ICMP
|
|
case netflow.NFV9_FIELD_ICMP_TYPE:
|
|
var icmpTypeCode uint16
|
|
if err := DecodeUNumber(v, &icmpTypeCode); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.IcmpType = uint32(icmpTypeCode >> 8)
|
|
flowMessage.IcmpCode = uint32(icmpTypeCode & 0xff)
|
|
case netflow.IPFIX_FIELD_icmpTypeCodeIPv6:
|
|
var icmpTypeCode uint16
|
|
if err := DecodeUNumber(v, &icmpTypeCode); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.IcmpType = uint32(icmpTypeCode >> 8)
|
|
flowMessage.IcmpCode = uint32(icmpTypeCode & 0xff)
|
|
case netflow.IPFIX_FIELD_icmpTypeIPv4:
|
|
if err := DecodeUNumber(v, &(flowMessage.IcmpType)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.IPFIX_FIELD_icmpTypeIPv6:
|
|
if err := DecodeUNumber(v, &(flowMessage.IcmpType)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.IPFIX_FIELD_icmpCodeIPv4:
|
|
if err := DecodeUNumber(v, &(flowMessage.IcmpCode)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.IPFIX_FIELD_icmpCodeIPv6:
|
|
if err := DecodeUNumber(v, &(flowMessage.IcmpCode)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Mac
|
|
case netflow.NFV9_FIELD_IN_SRC_MAC:
|
|
if err := DecodeUNumber(v, &(flowMessage.SrcMac)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_IN_DST_MAC:
|
|
if err := DecodeUNumber(v, &(flowMessage.DstMac)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_OUT_SRC_MAC:
|
|
if err := DecodeUNumber(v, &(flowMessage.SrcMac)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_OUT_DST_MAC:
|
|
if err := DecodeUNumber(v, &(flowMessage.DstMac)); err != nil {
|
|
return err
|
|
}
|
|
|
|
case netflow.NFV9_FIELD_SRC_VLAN:
|
|
if err := DecodeUNumber(v, &(flowMessage.VlanId)); err != nil {
|
|
return err
|
|
}
|
|
if err := DecodeUNumber(v, &(flowMessage.SrcVlan)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_DST_VLAN:
|
|
if err := DecodeUNumber(v, &(flowMessage.DstVlan)); err != nil {
|
|
return err
|
|
}
|
|
|
|
case netflow.NFV9_FIELD_IPV4_IDENT:
|
|
if err := DecodeUNumber(v, &(flowMessage.FragmentId)); err != nil {
|
|
return err
|
|
}
|
|
case netflow.NFV9_FIELD_FRAGMENT_OFFSET:
|
|
var fragOffset uint32
|
|
if err := DecodeUNumber(v, &fragOffset); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.FragmentOffset |= fragOffset
|
|
case netflow.IPFIX_FIELD_fragmentFlags:
|
|
var ipFlags uint32
|
|
if err := DecodeUNumber(v, &ipFlags); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.FragmentOffset |= ipFlags
|
|
case netflow.NFV9_FIELD_IPV6_FLOW_LABEL:
|
|
if err := DecodeUNumber(v, &(flowMessage.Ipv6FlowLabel)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// MPLS
|
|
case netflow.IPFIX_FIELD_mplsTopLabelStackSection:
|
|
var mplsLabel uint32
|
|
if err := DecodeUNumber(v, &mplsLabel); err != nil {
|
|
return err
|
|
}
|
|
if len(flowMessage.MplsLabel) < 1 {
|
|
flowMessage.MplsLabel = make([]uint32, 1)
|
|
}
|
|
flowMessage.MplsLabel[0] = uint32(mplsLabel >> 4)
|
|
case netflow.IPFIX_FIELD_mplsLabelStackSection2:
|
|
var mplsLabel uint32
|
|
if err := DecodeUNumber(v, &mplsLabel); err != nil {
|
|
return err
|
|
}
|
|
if len(flowMessage.MplsLabel) < 2 {
|
|
flowMessage.MplsLabel = make([]uint32, 2)
|
|
}
|
|
flowMessage.MplsLabel[1] = uint32(mplsLabel >> 4)
|
|
case netflow.IPFIX_FIELD_mplsLabelStackSection3:
|
|
var mplsLabel uint32
|
|
if err := DecodeUNumber(v, &mplsLabel); err != nil {
|
|
return err
|
|
}
|
|
if len(flowMessage.MplsLabel) < 3 {
|
|
flowMessage.MplsLabel = make([]uint32, 3)
|
|
}
|
|
flowMessage.MplsLabel[2] = uint32(mplsLabel >> 4)
|
|
case netflow.IPFIX_FIELD_mplsTopLabelIPv4Address:
|
|
flowMessage.MplsIp = append(flowMessage.MplsIp, v)
|
|
case netflow.IPFIX_FIELD_mplsTopLabelIPv6Address:
|
|
flowMessage.MplsIp = append(flowMessage.MplsIp, v)
|
|
|
|
default:
|
|
if version == 9 {
|
|
// NetFlow v9 time works with a differential based on router's uptime
|
|
switch df.Type {
|
|
case netflow.NFV9_FIELD_FIRST_SWITCHED:
|
|
var timeFirstSwitched uint32
|
|
if err := DecodeUNumber(v, &timeFirstSwitched); err != nil {
|
|
return err
|
|
}
|
|
timeDiff := (uptime - timeFirstSwitched)
|
|
flowMessage.TimeFlowStartNs = baseTimeNs - uint64(timeDiff)*1000000000
|
|
case netflow.NFV9_FIELD_LAST_SWITCHED:
|
|
var timeLastSwitched uint32
|
|
if err := DecodeUNumber(v, &timeLastSwitched); err != nil {
|
|
return err
|
|
}
|
|
timeDiff := (uptime - timeLastSwitched)
|
|
flowMessage.TimeFlowEndNs = baseTimeNs - uint64(timeDiff)*1000000000
|
|
}
|
|
} else if version == 10 {
|
|
switch df.Type {
|
|
case netflow.IPFIX_FIELD_flowStartSeconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowStartNs = time * 1000000000
|
|
case netflow.IPFIX_FIELD_flowStartMilliseconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowStartNs = time * 1000000
|
|
case netflow.IPFIX_FIELD_flowStartMicroseconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowStartNs = time * 1000
|
|
case netflow.IPFIX_FIELD_flowStartNanoseconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowStartNs = time
|
|
case netflow.IPFIX_FIELD_flowEndSeconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowEndNs = time * 1000000000
|
|
case netflow.IPFIX_FIELD_flowEndMilliseconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowEndNs = time * 1000000
|
|
case netflow.IPFIX_FIELD_flowEndMicroseconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowEndNs = time * 1000
|
|
case netflow.IPFIX_FIELD_flowEndNanoseconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowEndNs = time
|
|
case netflow.IPFIX_FIELD_flowStartDeltaMicroseconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowStartNs = baseTimeNs - time*1000
|
|
case netflow.IPFIX_FIELD_flowEndDeltaMicroseconds:
|
|
if err := DecodeUNumber(v, &time); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.TimeFlowEndNs = baseTimeNs - time*1000
|
|
// RFC7133
|
|
case netflow.IPFIX_FIELD_dataLinkFrameSize:
|
|
if err := DecodeUNumber(v, &(flowMessage.Bytes)); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.Packets = 1
|
|
case netflow.IPFIX_FIELD_dataLinkFrameSection:
|
|
if err := ParseEthernetHeader(flowMessage, v, mapperSFlow); err != nil {
|
|
return err
|
|
}
|
|
flowMessage.Packets = 1
|
|
if flowMessage.Bytes == 0 {
|
|
flowMessage.Bytes = uint64(len(v))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func SearchNetFlowDataSetsRecords(version uint16, baseTime uint32, uptime uint32, dataRecords []netflow.DataRecord, mapperNetFlow *NetFlowMapper, mapperSFlow *SFlowMapper) (flowMessageSet []producer.ProducerMessage, err error) {
|
|
for _, record := range dataRecords {
|
|
fmsg := protoMessagePool.Get().(*ProtoProducerMessage)
|
|
fmsg.Reset()
|
|
if err := ConvertNetFlowDataSet(fmsg, version, baseTime, uptime, record.Values, mapperNetFlow, mapperSFlow); err != nil {
|
|
return flowMessageSet, err
|
|
}
|
|
if fmsg != nil {
|
|
flowMessageSet = append(flowMessageSet, fmsg)
|
|
}
|
|
}
|
|
return flowMessageSet, nil
|
|
}
|
|
|
|
func SearchNetFlowDataSets(version uint16, baseTime uint32, uptime uint32, dataFlowSet []netflow.DataFlowSet, mapperNetFlow *NetFlowMapper, mapperSFlow *SFlowMapper) (flowMessageSet []producer.ProducerMessage, err error) {
|
|
for _, dataFlowSetItem := range dataFlowSet {
|
|
fmsg, err := SearchNetFlowDataSetsRecords(version, baseTime, uptime, dataFlowSetItem.Records, mapperNetFlow, mapperSFlow)
|
|
if err != nil {
|
|
return flowMessageSet, err
|
|
}
|
|
if fmsg != nil {
|
|
flowMessageSet = append(flowMessageSet, fmsg...)
|
|
}
|
|
}
|
|
return flowMessageSet, nil
|
|
}
|
|
|
|
func SearchNetFlowOptionDataSets(dataFlowSet []netflow.OptionsDataFlowSet) (samplingRate uint32, found bool, err error) {
|
|
for _, dataFlowSetItem := range dataFlowSet {
|
|
for _, record := range dataFlowSetItem.Records {
|
|
if found, err := NetFlowPopulate(record.OptionsValues, 305, &samplingRate); err != nil || found {
|
|
return samplingRate, found, err
|
|
}
|
|
if found, err := NetFlowPopulate(record.OptionsValues, 50, &samplingRate); err != nil || found {
|
|
return samplingRate, found, err
|
|
}
|
|
if found, err := NetFlowPopulate(record.OptionsValues, 34, &samplingRate); err != nil || found {
|
|
return samplingRate, found, err
|
|
}
|
|
}
|
|
}
|
|
return samplingRate, found, err
|
|
}
|
|
|
|
func SplitNetFlowSets(packetNFv9 netflow.NFv9Packet) ([]netflow.DataFlowSet, []netflow.TemplateFlowSet, []netflow.NFv9OptionsTemplateFlowSet, []netflow.OptionsDataFlowSet) {
|
|
var dataFlowSet []netflow.DataFlowSet
|
|
var templatesFlowSet []netflow.TemplateFlowSet
|
|
var optionsTemplatesFlowSet []netflow.NFv9OptionsTemplateFlowSet
|
|
var optionsDataFlowSet []netflow.OptionsDataFlowSet
|
|
for _, flowSet := range packetNFv9.FlowSets {
|
|
switch tFlowSet := flowSet.(type) {
|
|
case netflow.TemplateFlowSet:
|
|
templatesFlowSet = append(templatesFlowSet, tFlowSet)
|
|
case netflow.NFv9OptionsTemplateFlowSet:
|
|
optionsTemplatesFlowSet = append(optionsTemplatesFlowSet, tFlowSet)
|
|
case netflow.DataFlowSet:
|
|
dataFlowSet = append(dataFlowSet, tFlowSet)
|
|
case netflow.OptionsDataFlowSet:
|
|
optionsDataFlowSet = append(optionsDataFlowSet, tFlowSet)
|
|
}
|
|
}
|
|
return dataFlowSet, templatesFlowSet, optionsTemplatesFlowSet, optionsDataFlowSet
|
|
}
|
|
|
|
func SplitIPFIXSets(packetIPFIX netflow.IPFIXPacket) ([]netflow.DataFlowSet, []netflow.TemplateFlowSet, []netflow.IPFIXOptionsTemplateFlowSet, []netflow.OptionsDataFlowSet) {
|
|
var dataFlowSet []netflow.DataFlowSet
|
|
var templatesFlowSet []netflow.TemplateFlowSet
|
|
var optionsTemplatesFlowSet []netflow.IPFIXOptionsTemplateFlowSet
|
|
var optionsDataFlowSet []netflow.OptionsDataFlowSet
|
|
for _, flowSet := range packetIPFIX.FlowSets {
|
|
switch tFlowSet := flowSet.(type) {
|
|
case netflow.TemplateFlowSet:
|
|
templatesFlowSet = append(templatesFlowSet, tFlowSet)
|
|
case netflow.IPFIXOptionsTemplateFlowSet:
|
|
optionsTemplatesFlowSet = append(optionsTemplatesFlowSet, tFlowSet)
|
|
case netflow.DataFlowSet:
|
|
dataFlowSet = append(dataFlowSet, tFlowSet)
|
|
case netflow.OptionsDataFlowSet:
|
|
optionsDataFlowSet = append(optionsDataFlowSet, tFlowSet)
|
|
}
|
|
}
|
|
return dataFlowSet, templatesFlowSet, optionsTemplatesFlowSet, optionsDataFlowSet
|
|
}
|
|
|
|
// Convert a NetFlow datastructure to a FlowMessage protobuf
|
|
// Does not put sampling rate
|
|
func ProcessMessageIPFIXConfig(packet *netflow.IPFIXPacket, samplingRateSys SamplingRateSystem, config *producerConfigMapped) (flowMessageSet []producer.ProducerMessage, err error) {
|
|
dataFlowSet, _, _, optionDataFlowSet := SplitIPFIXSets(*packet)
|
|
|
|
seqnum := packet.SequenceNumber
|
|
baseTime := packet.ExportTime
|
|
obsDomainId := packet.ObservationDomainId
|
|
|
|
var cfgIpfix *NetFlowMapper
|
|
var cfgSflow *SFlowMapper
|
|
if config != nil {
|
|
cfgIpfix = config.IPFIX
|
|
cfgSflow = config.SFlow
|
|
}
|
|
flowMessageSet, err = SearchNetFlowDataSets(10, baseTime, 0, dataFlowSet, cfgIpfix, cfgSflow)
|
|
if err != nil {
|
|
return flowMessageSet, err
|
|
}
|
|
|
|
samplingRate, found, err := SearchNetFlowOptionDataSets(optionDataFlowSet)
|
|
if err != nil {
|
|
return flowMessageSet, err
|
|
}
|
|
if samplingRateSys != nil {
|
|
if found {
|
|
samplingRateSys.AddSamplingRate(10, obsDomainId, samplingRate)
|
|
} else {
|
|
samplingRate, _ = samplingRateSys.GetSamplingRate(10, obsDomainId)
|
|
}
|
|
}
|
|
for _, msg := range flowMessageSet {
|
|
fmsg, ok := msg.(*ProtoProducerMessage)
|
|
if !ok {
|
|
continue
|
|
}
|
|
fmsg.SequenceNum = seqnum
|
|
fmsg.SamplingRate = uint64(samplingRate)
|
|
fmsg.ObservationDomainId = obsDomainId
|
|
}
|
|
return flowMessageSet, nil
|
|
}
|
|
|
|
// Convert a NetFlow datastructure to a FlowMessage protobuf
|
|
// Does not put sampling rate
|
|
func ProcessMessageNetFlowV9Config(packet *netflow.NFv9Packet, samplingRateSys SamplingRateSystem, config *producerConfigMapped) (flowMessageSet []producer.ProducerMessage, err error) {
|
|
dataFlowSet, _, _, optionDataFlowSet := SplitNetFlowSets(*packet)
|
|
|
|
seqnum := packet.SequenceNumber
|
|
baseTime := packet.UnixSeconds
|
|
uptime := packet.SystemUptime
|
|
obsDomainId := packet.SourceId
|
|
|
|
var cfg *NetFlowMapper
|
|
if config != nil {
|
|
cfg = config.NetFlowV9
|
|
}
|
|
flowMessageSet, err = SearchNetFlowDataSets(9, baseTime, uptime, dataFlowSet, cfg, nil)
|
|
if err != nil {
|
|
return flowMessageSet, err
|
|
}
|
|
samplingRate, found, err := SearchNetFlowOptionDataSets(optionDataFlowSet)
|
|
if err != nil {
|
|
return flowMessageSet, err
|
|
}
|
|
if samplingRateSys != nil {
|
|
if found {
|
|
samplingRateSys.AddSamplingRate(9, obsDomainId, samplingRate)
|
|
} else {
|
|
samplingRate, _ = samplingRateSys.GetSamplingRate(9, obsDomainId)
|
|
}
|
|
}
|
|
for _, msg := range flowMessageSet {
|
|
fmsg, ok := msg.(*ProtoProducerMessage)
|
|
if !ok {
|
|
continue
|
|
}
|
|
fmsg.SequenceNum = seqnum
|
|
fmsg.SamplingRate = uint64(samplingRate)
|
|
}
|
|
return flowMessageSet, nil
|
|
}
|