2021-06-11 08:42:32 -07:00
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
FORMAT_TYPE_UNKNOWN = iota
|
|
|
|
FORMAT_TYPE_STRING_FUNC
|
|
|
|
FORMAT_TYPE_STRING
|
|
|
|
FORMAT_TYPE_INTEGER
|
|
|
|
FORMAT_TYPE_IP
|
|
|
|
FORMAT_TYPE_MAC
|
2021-09-23 20:41:17 -07:00
|
|
|
FORMAT_TYPE_BYTES
|
2021-06-11 08:42:32 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
EtypeName = map[uint32]string{
|
|
|
|
0x806: "ARP",
|
|
|
|
0x800: "IPv4",
|
|
|
|
0x86dd: "IPv6",
|
|
|
|
}
|
|
|
|
ProtoName = map[uint32]string{
|
2021-12-20 16:53:00 +01:00
|
|
|
1: "ICMP",
|
|
|
|
6: "TCP",
|
|
|
|
17: "UDP",
|
|
|
|
58: "ICMPv6",
|
|
|
|
132: "SCTP",
|
2021-06-11 08:42:32 -07:00
|
|
|
}
|
|
|
|
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",
|
|
|
|
}
|
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
TextFields = map[string]int{
|
|
|
|
"Type": FORMAT_TYPE_STRING_FUNC,
|
|
|
|
"SamplerAddress": FORMAT_TYPE_IP,
|
|
|
|
"SrcAddr": FORMAT_TYPE_IP,
|
|
|
|
"DstAddr": FORMAT_TYPE_IP,
|
|
|
|
"SrcMac": FORMAT_TYPE_MAC,
|
|
|
|
"DstMac": FORMAT_TYPE_MAC,
|
|
|
|
"NextHop": FORMAT_TYPE_IP,
|
|
|
|
"MPLSLabelIP": FORMAT_TYPE_IP,
|
2021-06-11 08:42:32 -07:00
|
|
|
}
|
2022-10-08 15:29:06 -07:00
|
|
|
|
|
|
|
RenderExtras = map[string]RenderExtraFunction{
|
|
|
|
"EtypeName": RenderExtraFunctionEtypeName,
|
|
|
|
"ProtoName": RenderExtraFunctionProtoName,
|
|
|
|
"IcmpName": RenderExtraFunctionIcmpName,
|
2021-06-11 08:42:32 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
/*
|
2021-06-11 08:42:32 -07:00
|
|
|
func AddTextField(name string, jtype int) {
|
|
|
|
TextFields = append(TextFields, name)
|
|
|
|
TextFieldsTypes = append(TextFieldsTypes, jtype)
|
2022-10-08 15:29:06 -07:00
|
|
|
}*/
|
2021-06-11 08:42:32 -07:00
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
type RenderExtraFunction func(interface{}) string
|
2021-06-11 08:42:32 -07:00
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
func RenderExtraFetchNumbers(msg interface{}, fields []string) []uint64 {
|
2021-06-11 08:42:32 -07:00
|
|
|
vfm := reflect.ValueOf(msg)
|
|
|
|
vfm = reflect.Indirect(vfm)
|
|
|
|
|
|
|
|
values := make([]uint64, len(fields))
|
|
|
|
for i, kf := range fields {
|
|
|
|
fieldValue := vfm.FieldByName(kf)
|
|
|
|
if fieldValue.IsValid() {
|
|
|
|
values[i] = fieldValue.Uint()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return values
|
|
|
|
}
|
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
func RenderExtraFunctionEtypeName(msg interface{}) string {
|
2021-06-11 08:42:32 -07:00
|
|
|
num := RenderExtraFetchNumbers(msg, []string{"Etype"})
|
|
|
|
return EtypeName[uint32(num[0])]
|
|
|
|
}
|
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
func RenderExtraFunctionProtoName(msg interface{}) string {
|
2021-06-11 08:42:32 -07:00
|
|
|
num := RenderExtraFetchNumbers(msg, []string{"Proto"})
|
|
|
|
return ProtoName[uint32(num[0])]
|
|
|
|
}
|
2022-10-08 15:29:06 -07:00
|
|
|
func RenderExtraFunctionIcmpName(msg interface{}) string {
|
2021-06-11 08:42:32 -07:00
|
|
|
num := RenderExtraFetchNumbers(msg, []string{"Proto", "IcmpCode", "IcmpType"})
|
|
|
|
return IcmpCodeType(uint32(num[0]), uint32(num[1]), uint32(num[2]))
|
|
|
|
}
|
|
|
|
|
|
|
|
func IcmpCodeType(proto, icmpCode, icmpType uint32) string {
|
|
|
|
if proto == 1 {
|
|
|
|
return IcmpTypeName[icmpType]
|
|
|
|
} else if proto == 58 {
|
|
|
|
return Icmp6TypeName[icmpType]
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func RenderIP(addr []byte) string {
|
|
|
|
if addr == nil || (len(addr) != 4 && len(addr) != 16) {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
return net.IP(addr).String()
|
|
|
|
}
|
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
func FormatMessageReflectText(msg interface{}, ext string) string {
|
2021-06-11 08:42:32 -07:00
|
|
|
return FormatMessageReflectCustom(msg, ext, "", " ", "=", false)
|
|
|
|
}
|
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
func FormatMessageReflectJSON(msg interface{}, ext string) string {
|
2021-06-11 08:42:32 -07:00
|
|
|
return fmt.Sprintf("{%s}", FormatMessageReflectCustom(msg, ext, "\"", ",", ":", true))
|
|
|
|
}
|
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
func ExtractTag(name, original string, tag reflect.StructTag) string {
|
|
|
|
lookup, ok := tag.Lookup(name)
|
|
|
|
if !ok {
|
|
|
|
return original
|
|
|
|
}
|
|
|
|
before, _, _ := strings.Cut(lookup, ",")
|
|
|
|
return before
|
|
|
|
}
|
|
|
|
|
|
|
|
func FormatMessageReflectCustom(msg interface{}, ext, quotes, sep, sign string, null bool) string {
|
|
|
|
customSelector := selector
|
|
|
|
reMap := make(map[string]string)
|
2021-06-11 08:42:32 -07:00
|
|
|
|
|
|
|
vfm := reflect.ValueOf(msg)
|
|
|
|
vfm = reflect.Indirect(vfm)
|
2022-10-08 15:29:06 -07:00
|
|
|
vft := vfm.Type()
|
|
|
|
|
|
|
|
if len(customSelector) == 0 || selectorTag != "" {
|
|
|
|
/*
|
|
|
|
// we would need proto v2
|
|
|
|
msgR := msg.ProtoReflect()
|
|
|
|
customSelector = make([]string, msgR.Fields().Len())
|
|
|
|
for i := 0; i<len(customSelector);i++ {
|
|
|
|
customSelector[i] = msgR.Fields().Get(i).TextName()
|
|
|
|
}*/
|
|
|
|
|
|
|
|
customSelectorTmp := make([]string, vft.NumField())
|
|
|
|
for i := 0; i < len(customSelectorTmp); i++ {
|
|
|
|
field := vft.Field(i)
|
|
|
|
if !field.IsExported() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
fieldName := field.Name
|
|
|
|
if selectorTag != "" {
|
|
|
|
fieldName = ExtractTag(selectorTag, field.Name, field.Tag)
|
|
|
|
fmt.Println(fieldName, selectorTag, field.Tag)
|
|
|
|
reMap[fieldName] = field.Name
|
|
|
|
}
|
|
|
|
customSelectorTmp[i] = fieldName
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(customSelector) == 0 {
|
|
|
|
customSelector = customSelectorTmp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fstr := make([]string, len(customSelector))
|
2021-06-11 08:42:32 -07:00
|
|
|
|
|
|
|
var i int
|
2022-10-08 15:29:06 -07:00
|
|
|
|
|
|
|
for _, s := range customSelector {
|
|
|
|
fieldName := s
|
|
|
|
if fieldNameMap, ok := reMap[fieldName]; ok {
|
|
|
|
fieldName = fieldNameMap
|
|
|
|
}
|
|
|
|
fieldValue := vfm.FieldByName(fieldName)
|
|
|
|
// todo: replace s by json mapping of protobuf
|
2021-06-11 08:42:32 -07:00
|
|
|
if fieldValue.IsValid() {
|
|
|
|
|
2022-10-08 15:29:06 -07:00
|
|
|
if fieldType, ok := TextFields[fieldName]; ok {
|
|
|
|
switch fieldType {
|
|
|
|
case FORMAT_TYPE_STRING_FUNC:
|
|
|
|
strMethod := fieldValue.MethodByName("String").Call([]reflect.Value{})
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%q", quotes, s, quotes, sign, strMethod[0].String())
|
|
|
|
case FORMAT_TYPE_STRING:
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%q", quotes, s, quotes, sign, fieldValue.String())
|
|
|
|
case FORMAT_TYPE_INTEGER:
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%d", quotes, s, quotes, sign, fieldValue.Uint())
|
|
|
|
case FORMAT_TYPE_IP:
|
|
|
|
ip := fieldValue.Bytes()
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%q", quotes, s, quotes, sign, RenderIP(ip))
|
|
|
|
case FORMAT_TYPE_MAC:
|
|
|
|
mac := make([]byte, 8)
|
|
|
|
binary.BigEndian.PutUint64(mac, fieldValue.Uint())
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%q", quotes, s, quotes, sign, net.HardwareAddr(mac[2:]).String())
|
|
|
|
case FORMAT_TYPE_BYTES:
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%.2x", quotes, s, quotes, sign, fieldValue.Bytes())
|
|
|
|
default:
|
|
|
|
if null {
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%snull", quotes, s, quotes, sign)
|
|
|
|
} else {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if renderer, ok := RenderExtras[fieldName]; ok {
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%q", quotes, s, quotes, sign, renderer(msg))
|
|
|
|
} else {
|
|
|
|
// handle specific types here
|
|
|
|
switch fieldValue.Kind() {
|
|
|
|
case reflect.String:
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%q", quotes, s, quotes, sign, fieldValue.Interface())
|
|
|
|
default:
|
|
|
|
fstr[i] = fmt.Sprintf("%s%s%s%s%v", quotes, s, quotes, sign, fieldValue.Interface())
|
2021-06-11 08:42:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2022-10-08 15:29:06 -07:00
|
|
|
fstr = fstr[0:i]
|
2021-06-11 08:42:32 -07:00
|
|
|
|
|
|
|
return strings.Join(fstr, sep)
|
|
|
|
}
|