1
0
mirror of https://github.com/netsampler/goflow2.git synced 2024-05-06 15:54:52 +00:00
2023-08-09 19:47:20 -07:00

157 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,
"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))
}