mirror of
https://github.com/netsampler/goflow2.git
synced 2024-05-06 15:54:52 +00:00
158 lines
3.7 KiB
Go
158 lines
3.7 KiB
Go
package protoproducer
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"net"
|
|
"net/netip"
|
|
)
|
|
|
|
type RenderFunc func(msg *ProtoProducerMessage, fieldName string, data interface{}) interface{}
|
|
|
|
type RendererID string
|
|
|
|
const (
|
|
RendererNone RendererID = "none"
|
|
RendererIP RendererID = "ip"
|
|
RendererMac RendererID = "mac"
|
|
RendererEtype RendererID = "etype"
|
|
RendererProto RendererID = "proto"
|
|
RendererType RendererID = "type"
|
|
RendererNetwork RendererID = "network"
|
|
)
|
|
|
|
var (
|
|
renderers = map[RendererID]RenderFunc{
|
|
RendererNone: NilRenderer,
|
|
RendererIP: IPRenderer,
|
|
RendererMac: MacRenderer,
|
|
RendererEtype: EtypeRenderer,
|
|
RendererProto: ProtoRenderer,
|
|
}
|
|
|
|
defaultRenderers = map[string]RenderFunc{
|
|
"SrcMac": MacRenderer,
|
|
"DstMac": MacRenderer,
|
|
"SrcAddr": IPRenderer,
|
|
"DstAddr": IPRenderer,
|
|
"SamplerAddress": IPRenderer,
|
|
"NextHop": IPRenderer,
|
|
"BgpNextHop": IPRenderer,
|
|
"MplsLabelIp": IPRenderer,
|
|
"Etype": EtypeRenderer,
|
|
"Proto": ProtoRenderer,
|
|
"SrcNet": NetworkRenderer,
|
|
"DstNet": NetworkRenderer,
|
|
|
|
"icmp_name": ICMPRenderer,
|
|
}
|
|
|
|
etypeName = map[uint32]string{
|
|
0x806: "ARP",
|
|
0x800: "IPv4",
|
|
0x86dd: "IPv6",
|
|
}
|
|
protoName = map[uint32]string{
|
|
1: "ICMP",
|
|
6: "TCP",
|
|
17: "UDP",
|
|
58: "ICMPv6",
|
|
132: "SCTP",
|
|
}
|
|
icmpTypeName = map[uint32]string{
|
|
0: "EchoReply",
|
|
3: "DestinationUnreachable",
|
|
8: "Echo",
|
|
9: "RouterAdvertisement",
|
|
10: "RouterSolicitation",
|
|
11: "TimeExceeded",
|
|
}
|
|
icmp6TypeName = map[uint32]string{
|
|
1: "DestinationUnreachable",
|
|
2: "PacketTooBig",
|
|
3: "TimeExceeded",
|
|
128: "EchoRequest",
|
|
129: "EchoReply",
|
|
133: "RouterSolicitation",
|
|
134: "RouterAdvertisement",
|
|
}
|
|
)
|
|
|
|
func NilRenderer(msg *ProtoProducerMessage, fieldName string, data interface{}) interface{} {
|
|
if dataIf, ok := data.(interface {
|
|
String() string
|
|
}); ok {
|
|
return dataIf.String()
|
|
}
|
|
if dataC, ok := data.([]byte); ok {
|
|
return hex.EncodeToString(dataC)
|
|
}
|
|
return data
|
|
}
|
|
|
|
func MacRenderer(msg *ProtoProducerMessage, fieldName string, data interface{}) interface{} {
|
|
if dataC, ok := data.(uint64); ok {
|
|
var mac [8]byte
|
|
binary.BigEndian.PutUint64(mac[:], dataC)
|
|
return net.HardwareAddr(mac[2:]).String()
|
|
}
|
|
return NilRenderer(msg, fieldName, data)
|
|
|
|
}
|
|
|
|
func RenderIP(addr []byte) string {
|
|
if addr == nil || (len(addr) != 4 && len(addr) != 16) {
|
|
return ""
|
|
}
|
|
ip, _ := netip.AddrFromSlice(addr)
|
|
return ip.String()
|
|
}
|
|
|
|
func IPRenderer(msg *ProtoProducerMessage, fieldName string, data interface{}) interface{} {
|
|
if dataC, ok := data.([]byte); ok {
|
|
return RenderIP(dataC)
|
|
}
|
|
return NilRenderer(msg, fieldName, data)
|
|
}
|
|
|
|
func EtypeRenderer(msg *ProtoProducerMessage, fieldName string, data interface{}) interface{} {
|
|
if dataC, ok := data.(uint32); ok {
|
|
return etypeName[dataC]
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
func ProtoRenderer(msg *ProtoProducerMessage, fieldName string, data interface{}) interface{} {
|
|
if dataC, ok := data.(uint32); ok {
|
|
return protoName[dataC]
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
func NetworkRenderer(msg *ProtoProducerMessage, fieldName string, data interface{}) interface{} {
|
|
var addr netip.Addr
|
|
if fieldName == "SrcNet" {
|
|
addr, _ = netip.AddrFromSlice(msg.SrcAddr)
|
|
} else if fieldName == "DstNet" {
|
|
addr, _ = netip.AddrFromSlice(msg.DstAddr)
|
|
}
|
|
if dataC, ok := data.(uint32); ok {
|
|
prefix, _ := addr.Prefix(int(dataC))
|
|
return prefix.String()
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
func IcmpCodeType(proto, icmpCode, icmpType uint32) string {
|
|
if proto == 1 {
|
|
return icmpTypeName[icmpType]
|
|
} else if proto == 58 {
|
|
return icmp6TypeName[icmpType]
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
func ICMPRenderer(msg *ProtoProducerMessage, fieldName string, data interface{}) interface{} {
|
|
return IcmpCodeType(uint32(msg.Proto), uint32(msg.IcmpCode), uint32(msg.IcmpType))
|
|
}
|