safing-portmaster/network/packet/parse.go
2019-05-06 11:00:10 +02:00

91 lines
2.6 KiB
Go

package packet
import (
"errors"
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
// Parse parses an IP packet and saves the information in the given packet object.
func Parse(packetData []byte, packet *Base) error {
var parsedPacket gopacket.Packet
if len(packetData) == 0 {
return errors.New("empty packet")
}
switch packetData[0] >> 4 {
case 4:
parsedPacket = gopacket.NewPacket(packetData, layers.LayerTypeIPv4, gopacket.DecodeOptions{Lazy: true, NoCopy: true})
if ipv4Layer := parsedPacket.Layer(layers.LayerTypeIPv4); ipv4Layer != nil {
ipv4, _ := ipv4Layer.(*layers.IPv4)
packet.info.Version = IPv4
packet.info.Protocol = IPProtocol(ipv4.Protocol)
packet.info.Src = ipv4.SrcIP
packet.info.Dst = ipv4.DstIP
} else {
var err error
if errLayer := parsedPacket.ErrorLayer(); errLayer != nil {
err = errLayer.Error()
}
return fmt.Errorf("failed to parse IPv4 packet: %s", err)
}
case 6:
parsedPacket = gopacket.NewPacket(packetData, layers.LayerTypeIPv6, gopacket.DecodeOptions{Lazy: true, NoCopy: true})
if ipv6Layer := parsedPacket.Layer(layers.LayerTypeIPv6); ipv6Layer != nil {
ipv6, _ := ipv6Layer.(*layers.IPv6)
packet.info.Version = IPv6
packet.info.Protocol = IPProtocol(ipv6.NextHeader)
packet.info.Src = ipv6.SrcIP
packet.info.Dst = ipv6.DstIP
} else {
var err error
if errLayer := parsedPacket.ErrorLayer(); errLayer != nil {
err = errLayer.Error()
}
return fmt.Errorf("failed to parse IPv6 packet: %s", err)
}
default:
return errors.New("unknown IP version")
}
switch packet.info.Protocol {
case TCP:
if tcpLayer := parsedPacket.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
packet.info.SrcPort = uint16(tcp.SrcPort)
packet.info.DstPort = uint16(tcp.DstPort)
} else {
var err error
if errLayer := parsedPacket.ErrorLayer(); errLayer != nil {
err = errLayer.Error()
}
return fmt.Errorf("could not parse TCP layer: %s", err)
}
case UDP:
if udpLayer := parsedPacket.Layer(layers.LayerTypeUDP); udpLayer != nil {
udp, _ := udpLayer.(*layers.UDP)
packet.info.SrcPort = uint16(udp.SrcPort)
packet.info.DstPort = uint16(udp.DstPort)
} else {
var err error
if errLayer := parsedPacket.ErrorLayer(); errLayer != nil {
err = errLayer.Error()
}
return fmt.Errorf("could not parse UDP layer: %s", err)
}
}
if appLayer := parsedPacket.ApplicationLayer(); appLayer != nil {
packet.Payload = appLayer.Payload()
}
if errLayer := parsedPacket.ErrorLayer(); errLayer != nil {
return errLayer.Error()
}
return nil
}