func()

in pcap-cli/internal/transformer/json_translator.go [369:420]


func (t *JSONPcapTranslator) translateICMPv4Layer(ctx context.Context, icmp4 *layers.ICMPv4) fmt.Stringer {
	// see: https://github.com/google/gopacket/blob/master/layers/icmp4.go#L208-L215

	json := gabs.New()

	ICMP4, _ := json.Object("ICMP")

	ICMP4.Set(icmp4.TypeCode.Type(), "type")
	ICMP4.Set(icmp4.TypeCode.Code(), "code")
	ICMP4.Set(icmp4.Checksum, "xsum")

	// see: https://github.com/google/gopacket/blob/master/layers/icmp4.go#L78-L153
	ICMP4.Set(icmp4.TypeCode.String(), "msg")

	switch icmp4.TypeCode.Type() {
	case layers.ICMPv4TypeEchoRequest, layers.ICMPv4TypeEchoReply:
		ICMP4.Set(icmp4.Id, "id")
		ICMP4.Set(icmp4.Seq, "seq")
	case layers.ICMPv4TypeTimeExceeded, layers.ICMPv4TypeDestinationUnreachable, layers.ICMPv4TypeRedirect:
		IPv4, _ := ICMP4.Object("IPv4")

		// original IPv4 header starts from offset 8
		// reference:
		//   - https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Time_exceeded
		//   - https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Destination_unreachable
		ipHeader := icmp4.LayerPayload()

		IPv4.Set(binary.BigEndian.Uint16(ipHeader[4:6]), "id")
		IPv4.Set(uint8(ipHeader[8]), "ttl")
		IPv4.Set(uint8(ipHeader[9]), "proto")
		IPv4.Set(binary.BigEndian.Uint16(ipHeader[10:12]), "xsum")

		// IP addresses are represented as bigendian []byte slices in Go
		var ipBytes [4]byte

		copy(ipBytes[:], ipHeader[12:16])
		srcIP := netip.AddrFrom4(ipBytes)
		IPv4.Set(srcIP.String(), "src")

		copy(ipBytes[:], ipHeader[16:20])
		dstIP := netip.AddrFrom4(ipBytes)
		IPv4.Set(dstIP.String(), "dst")

		if icmp4.TypeCode.Type() == layers.ICMPv4TypeRedirect {
			// see: https://github.com/google/gopacket/blob/master/layers/icmp4.go#L230
			copy(ipBytes[:], icmp4.LayerContents()[4:8])
			ICMP4.Set(netip.AddrFrom4(ipBytes).String(), "tgt")
		}
	}

	return json
}