mirror of
https://github.com/safing/portmaster
synced 2025-09-01 10:09:11 +00:00
91 lines
2.6 KiB
Go
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
|
|
}
|