228 lines
6.6 KiB
Go
228 lines
6.6 KiB
Go
package bcap
|
|
|
|
import (
|
|
"net"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gopacket/gopacket"
|
|
"github.com/gopacket/gopacket/layers"
|
|
)
|
|
|
|
type DecodeOptions struct {
|
|
BaseTime time.Time
|
|
SrcMACOverride net.HardwareAddr
|
|
}
|
|
|
|
type Decoder struct{}
|
|
|
|
func NewDecoder() *Decoder {
|
|
return &Decoder{}
|
|
}
|
|
|
|
func (d *Decoder) Decode(packet gopacket.Packet) (Packet, error) {
|
|
return d.DecodeWithOptions(packet, DecodeOptions{})
|
|
}
|
|
|
|
func (d *Decoder) DecodeWithOptions(packet gopacket.Packet, opts DecodeOptions) (Packet, error) {
|
|
var decoded Packet
|
|
|
|
decoded.Raw.Packet = packet
|
|
if metadata := packet.Metadata(); metadata != nil {
|
|
decoded.Meta.Timestamp = metadata.Timestamp
|
|
decoded.Meta.TimestampMicros = metadata.Timestamp.UnixMicro()
|
|
decoded.Meta.CaptureLength = metadata.CaptureLength
|
|
decoded.Meta.Length = metadata.Length
|
|
if !opts.BaseTime.IsZero() {
|
|
decoded.Meta.RelativeTime = metadata.Timestamp.Sub(opts.BaseTime)
|
|
}
|
|
} else {
|
|
decoded.Meta.Timestamp = time.Now()
|
|
decoded.Meta.TimestampMicros = decoded.Meta.Timestamp.UnixMicro()
|
|
}
|
|
|
|
decodeLinkLayer(&decoded, packet)
|
|
if len(opts.SrcMACOverride) > 0 {
|
|
decoded.Link.SrcMAC = append(net.HardwareAddr(nil), opts.SrcMACOverride...)
|
|
}
|
|
|
|
if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil {
|
|
arp, ok := arpLayer.(*layers.ARP)
|
|
if !ok {
|
|
return decoded, NewParseError(ErrTypeNetwork, "ARP", "invalid arp layer", nil)
|
|
}
|
|
decodeARP(&decoded, arp)
|
|
return decoded, nil
|
|
}
|
|
|
|
if err := decodeNetworkLayer(&decoded, packet); err != nil {
|
|
return decoded, err
|
|
}
|
|
decodeTransportLayer(&decoded, packet)
|
|
return decoded, nil
|
|
}
|
|
|
|
func decodeLinkLayer(decoded *Packet, packet gopacket.Packet) {
|
|
decoded.Link.Kind = LinkKindUnknown
|
|
|
|
if ethLayer := packet.Layer(layers.LayerTypeEthernet); ethLayer != nil {
|
|
if eth, ok := ethLayer.(*layers.Ethernet); ok {
|
|
decoded.Link.Kind = LinkKindEthernet
|
|
decoded.Link.SrcMAC = append(net.HardwareAddr(nil), eth.SrcMAC...)
|
|
decoded.Link.DstMAC = append(net.HardwareAddr(nil), eth.DstMAC...)
|
|
return
|
|
}
|
|
}
|
|
if sllLayer := packet.Layer(layers.LayerTypeLinuxSLL); sllLayer != nil {
|
|
if sll, ok := sllLayer.(*layers.LinuxSLL); ok {
|
|
decoded.Link.Kind = LinkKindLinuxSLL
|
|
if sll.AddrType == 1 && sll.AddrLen == 6 {
|
|
decoded.Link.SrcMAC = append(net.HardwareAddr(nil), sll.Addr...)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
if sll2Layer := packet.Layer(layers.LayerTypeLinuxSLL2); sll2Layer != nil {
|
|
if sll2, ok := sll2Layer.(*layers.LinuxSLL2); ok {
|
|
decoded.Link.Kind = LinkKindLinuxSLL2
|
|
if sll2.ARPHardwareType == 1 && sll2.AddrLength == 6 {
|
|
decoded.Link.SrcMAC = append(net.HardwareAddr(nil), sll2.Addr...)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func decodeARP(decoded *Packet, arp *layers.ARP) {
|
|
decoded.Network.Family = NetworkFamilyARP
|
|
decoded.Network.ProtocolNumber = uint16(arp.Protocol)
|
|
decoded.Network.ARP = &ARPFacts{
|
|
Operation: arp.Operation,
|
|
SenderMAC: append(net.HardwareAddr(nil), arp.SourceHwAddress...),
|
|
TargetMAC: append(net.HardwareAddr(nil), arp.DstHwAddress...),
|
|
SenderIP: arpProtocolAddressString(arp.SourceProtAddress),
|
|
TargetIP: arpProtocolAddressString(arp.DstProtAddress),
|
|
}
|
|
decoded.Network.SrcIP = decoded.Network.ARP.SenderIP
|
|
decoded.Network.DstIP = decoded.Network.ARP.TargetIP
|
|
decoded.Transport.Kind = ProtocolARP
|
|
}
|
|
|
|
func arpProtocolAddressString(raw []byte) string {
|
|
switch len(raw) {
|
|
case net.IPv4len:
|
|
return net.IP(raw).String()
|
|
case net.IPv6len:
|
|
return net.IP(raw).String()
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func decodeNetworkLayer(decoded *Packet, packet gopacket.Packet) error {
|
|
nw := packet.NetworkLayer()
|
|
if nw == nil {
|
|
return NewParseError(ErrTypeNetwork, "Network", "no valid network layer found", nil)
|
|
}
|
|
|
|
src, dst := nw.NetworkFlow().Endpoints()
|
|
decoded.Network.SrcIP = src.String()
|
|
decoded.Network.DstIP = dst.String()
|
|
|
|
switch layer := nw.(type) {
|
|
case *layers.IPv4:
|
|
decoded.Network.Family = NetworkFamilyIPv4
|
|
decoded.Network.TTL = layer.TTL
|
|
decoded.Network.ProtocolNumber = uint16(layer.Protocol)
|
|
case *layers.IPv6:
|
|
decoded.Network.Family = NetworkFamilyIPv6
|
|
decoded.Network.HopLimit = layer.HopLimit
|
|
decoded.Network.ProtocolNumber = uint16(layer.NextHeader)
|
|
default:
|
|
decoded.Network.Family = NetworkFamilyUnknown
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func decodeTransportLayer(decoded *Packet, packet gopacket.Packet) {
|
|
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
|
|
if tcp, ok := tcpLayer.(*layers.TCP); ok {
|
|
payloadLen := len(tcpLayer.LayerPayload())
|
|
decoded.Transport.Kind = ProtocolTCP
|
|
decoded.Transport.Payload = payloadLen
|
|
decoded.Transport.TCP = &TCPFacts{
|
|
SrcPort: strconv.Itoa(int(tcp.SrcPort)),
|
|
DstPort: strconv.Itoa(int(tcp.DstPort)),
|
|
Seq: tcp.Seq,
|
|
Ack: tcp.Ack,
|
|
Window: tcp.Window,
|
|
SYN: tcp.SYN,
|
|
ACK: tcp.ACK,
|
|
FIN: tcp.FIN,
|
|
RST: tcp.RST,
|
|
ECE: tcp.ECE,
|
|
CWR: tcp.CWR,
|
|
PSH: tcp.PSH,
|
|
Checksum: tcp.Checksum,
|
|
Payload: payloadLen,
|
|
}
|
|
return
|
|
}
|
|
}
|
|
if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil {
|
|
if udp, ok := udpLayer.(*layers.UDP); ok {
|
|
payloadLen := len(udpLayer.LayerPayload())
|
|
decoded.Transport.Kind = ProtocolUDP
|
|
decoded.Transport.Payload = payloadLen
|
|
decoded.Transport.UDP = &UDPFacts{
|
|
SrcPort: strconv.Itoa(int(udp.SrcPort)),
|
|
DstPort: strconv.Itoa(int(udp.DstPort)),
|
|
Length: udp.Length,
|
|
Payload: payloadLen,
|
|
}
|
|
return
|
|
}
|
|
}
|
|
if icmpLayer := packet.Layer(layers.LayerTypeICMPv4); icmpLayer != nil {
|
|
if icmp, ok := icmpLayer.(*layers.ICMPv4); ok {
|
|
payloadLen := len(icmpLayer.LayerPayload())
|
|
decoded.Transport.Kind = ProtocolICMPv4
|
|
decoded.Transport.Payload = payloadLen
|
|
decoded.Transport.ICMP = &ICMPFacts{
|
|
Version: 4,
|
|
Type: uint8(icmp.TypeCode.Type()),
|
|
Code: uint8(icmp.TypeCode.Code()),
|
|
Checksum: icmp.Checksum,
|
|
ID: icmp.Id,
|
|
Seq: icmp.Seq,
|
|
Payload: payloadLen,
|
|
}
|
|
return
|
|
}
|
|
}
|
|
if icmpLayer := packet.Layer(layers.LayerTypeICMPv6); icmpLayer != nil {
|
|
if icmp, ok := icmpLayer.(*layers.ICMPv6); ok {
|
|
payloadLen := len(icmpLayer.LayerPayload())
|
|
decoded.Transport.Kind = ProtocolICMPv6
|
|
decoded.Transport.Payload = payloadLen
|
|
decoded.Transport.ICMP = &ICMPFacts{
|
|
Version: 6,
|
|
Type: uint8(icmp.TypeCode.Type()),
|
|
Code: uint8(icmp.TypeCode.Code()),
|
|
Checksum: icmp.Checksum,
|
|
Payload: payloadLen,
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
var payloadLen int
|
|
if app := packet.ApplicationLayer(); app != nil {
|
|
payloadLen = len(app.Payload())
|
|
} else if nw := packet.NetworkLayer(); nw != nil {
|
|
payloadLen = len(nw.LayerPayload())
|
|
}
|
|
decoded.Transport.Kind = ProtocolUnknown
|
|
decoded.Transport.Payload = payloadLen
|
|
decoded.Transport.Unknown = &UnknownTransportFacts{Payload: payloadLen}
|
|
}
|