mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Improve packet parsing
This commit is contained in:
parent
3abaca1d90
commit
5d61b7b682
6 changed files with 62 additions and 21 deletions
|
@ -179,11 +179,13 @@ func (q *Queue) packetHandler(ctx context.Context) func(nfqueue.Attribute) int {
|
|||
verdictPending: abool.New(),
|
||||
}
|
||||
|
||||
if attrs.Payload != nil {
|
||||
pkt.Payload = *attrs.Payload
|
||||
if attrs.Payload == nil {
|
||||
// There is not payload.
|
||||
log.Warningf("nfqueue: packet #%s has no payload", pkt.pktID)
|
||||
return 0
|
||||
}
|
||||
|
||||
if err := pmpacket.Parse(pkt.Payload, pkt.Info()); err != nil {
|
||||
if err := pmpacket.Parse(*attrs.Payload, &pkt.Base); err != nil {
|
||||
log.Warningf("nfqueue: failed to parse payload: %s", err)
|
||||
_ = pkt.Drop()
|
||||
return 0
|
||||
|
|
|
@ -65,6 +65,11 @@ func (pkt *packet) ID() string {
|
|||
return fmt.Sprintf("pkt:%d qid:%d", pkt.pktID, pkt.queue.id)
|
||||
}
|
||||
|
||||
// LoadPacketData does nothing on Linux, as data is always fully parsed.
|
||||
func (pkt *packet) LoadPacketData() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(ppacher): revisit the following behavior:
|
||||
// The legacy implementation of nfqueue (and the interception) module
|
||||
// always accept a packet but may mark it so that a subsequent rule in
|
||||
|
|
|
@ -230,6 +230,7 @@ func GetPayload(packetID uint32, packetSize uint32) ([]byte, error) {
|
|||
if packetSize < uint32(len(buf)) {
|
||||
return buf[:packetSize], nil
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ type Packet struct {
|
|||
}
|
||||
|
||||
// GetPayload returns the full raw packet.
|
||||
func (pkt *Packet) GetPayload() ([]byte, error) {
|
||||
func (pkt *Packet) LoadPacketData() error {
|
||||
pkt.lock.Lock()
|
||||
defer pkt.lock.Unlock()
|
||||
|
||||
|
@ -33,17 +33,21 @@ func (pkt *Packet) GetPayload() ([]byte, error) {
|
|||
|
||||
payload, err := GetPayload(pkt.verdictRequest.id, pkt.verdictRequest.packetSize)
|
||||
if err != nil {
|
||||
log.Tracer(pkt.Ctx()).Warningf("windowskext: failed to load payload %s", err)
|
||||
log.Errorf("windowskext: failed to load payload %s", err)
|
||||
return nil, packet.ErrFailedToLoadPayload
|
||||
log.Tracer(pkt.Ctx()).Warningf("windowskext: failed to load payload: %s", err)
|
||||
return packet.ErrFailedToLoadPayload
|
||||
}
|
||||
|
||||
err = packet.Parse(payload, &pkt.Base)
|
||||
if err != nil {
|
||||
log.Tracer(pkt.Ctx()).Warningf("windowskext: failed to parse payload: %s", err)
|
||||
return packet.ErrFailedToLoadPayload
|
||||
}
|
||||
pkt.Payload = payload
|
||||
}
|
||||
|
||||
if len(pkt.Payload) == 0 {
|
||||
return nil, packet.ErrFailedToLoadPayload
|
||||
if len(pkt.Raw()) == 0 {
|
||||
return packet.ErrFailedToLoadPayload
|
||||
}
|
||||
return pkt.Payload, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Accept accepts the packet.
|
||||
|
|
|
@ -4,14 +4,18 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
// Base is a base structure for satisfying the Packet interface.
|
||||
type Base struct {
|
||||
ctx context.Context
|
||||
info Info
|
||||
connID string
|
||||
Payload []byte
|
||||
ctx context.Context
|
||||
info Info
|
||||
connID string
|
||||
layers gopacket.Packet
|
||||
layer3Data []byte
|
||||
layer5Data []byte
|
||||
}
|
||||
|
||||
// SetCtx sets the packet context.
|
||||
|
@ -65,9 +69,24 @@ func (pkt *Base) HasPorts() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// GetPayload returns the packet payload. In some cases, this will fetch the payload from the os integration system.
|
||||
func (pkt *Base) GetPayload() ([]byte, error) {
|
||||
return pkt.Payload, ErrFailedToLoadPayload
|
||||
// LoadPacketData loads packet data from the integration, if not yet done.
|
||||
func (pkt *Base) LoadPacketData() error {
|
||||
return ErrFailedToLoadPayload
|
||||
}
|
||||
|
||||
// Layers returns the parsed layer data.
|
||||
func (pkt *Base) Layers() gopacket.Packet {
|
||||
return pkt.layers
|
||||
}
|
||||
|
||||
// Raw returns the raw Layer 3 Network Data.
|
||||
func (pkt *Base) Raw() []byte {
|
||||
return pkt.layer3Data
|
||||
}
|
||||
|
||||
// Payload returns the raw Layer 5 Network Data.
|
||||
func (pkt *Base) Payload() []byte {
|
||||
return pkt.layer5Data
|
||||
}
|
||||
|
||||
// GetConnectionID returns the link ID for this packet.
|
||||
|
@ -214,9 +233,14 @@ type Packet interface {
|
|||
SetInbound()
|
||||
SetOutbound()
|
||||
HasPorts() bool
|
||||
GetPayload() ([]byte, error)
|
||||
GetConnectionID() string
|
||||
|
||||
// PAYLOAD
|
||||
LoadPacketData() error
|
||||
Layers() gopacket.Packet
|
||||
Raw() []byte
|
||||
Payload() []byte
|
||||
|
||||
// MATCHING
|
||||
MatchesAddress(bool, IPProtocol, *net.IPNet, uint16) bool
|
||||
MatchesIP(bool, *net.IPNet) bool
|
||||
|
|
|
@ -102,10 +102,11 @@ func checkError(packet gopacket.Packet, _ *Info) error {
|
|||
}
|
||||
|
||||
// Parse parses an IP packet and saves the information in the given packet object.
|
||||
func Parse(packetData []byte, pktInfo *Info) error {
|
||||
func Parse(packetData []byte, pktBase *Base) (err error) {
|
||||
if len(packetData) == 0 {
|
||||
return errors.New("empty packet")
|
||||
}
|
||||
pktBase.layer3Data = packetData
|
||||
|
||||
ipVersion := packetData[0] >> 4
|
||||
var networkLayerType gopacket.LayerType
|
||||
|
@ -137,11 +138,15 @@ func Parse(packetData []byte, pktInfo *Info) error {
|
|||
}
|
||||
|
||||
for _, dec := range availableDecoders {
|
||||
if err := dec(packet, pktInfo); err != nil {
|
||||
if err := dec(packet, pktBase.Info()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
pktBase.layers = packet
|
||||
if packet.TransportLayer() != nil {
|
||||
pktBase.layer5Data = packet.TransportLayer().LayerPayload()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue