github.com/gopacket/gopacket@v1.1.0/layers/pflog.go (about)

     1  // Copyright 2012 Google, Inc. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree.
     6  
     7  package layers
     8  
     9  import (
    10  	"encoding/binary"
    11  	"errors"
    12  	"fmt"
    13  
    14  	"github.com/gopacket/gopacket"
    15  )
    16  
    17  type PFDirection uint8
    18  
    19  const (
    20  	PFDirectionInOut PFDirection = 0
    21  	PFDirectionIn    PFDirection = 1
    22  	PFDirectionOut   PFDirection = 2
    23  )
    24  
    25  // PFLog provides the layer for 'pf' packet-filter logging, as described at
    26  // http://www.freebsd.org/cgi/man.cgi?query=pflog&sektion=4
    27  type PFLog struct {
    28  	BaseLayer
    29  	Length              uint8
    30  	Family              ProtocolFamily
    31  	Action, Reason      uint8
    32  	IFName, Ruleset     []byte
    33  	RuleNum, SubruleNum uint32
    34  	UID                 uint32
    35  	PID                 int32
    36  	RuleUID             uint32
    37  	RulePID             int32
    38  	Direction           PFDirection
    39  	// The remainder is padding
    40  }
    41  
    42  func (pf *PFLog) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
    43  	if len(data) < 60 {
    44  		df.SetTruncated()
    45  		return errors.New("PFLog data less than 60 bytes")
    46  	}
    47  	pf.Length = data[0]
    48  	pf.Family = ProtocolFamily(data[1])
    49  	pf.Action = data[2]
    50  	pf.Reason = data[3]
    51  	pf.IFName = data[4:20]
    52  	pf.Ruleset = data[20:36]
    53  	pf.RuleNum = binary.BigEndian.Uint32(data[36:40])
    54  	pf.SubruleNum = binary.BigEndian.Uint32(data[40:44])
    55  	pf.UID = binary.BigEndian.Uint32(data[44:48])
    56  	pf.PID = int32(binary.BigEndian.Uint32(data[48:52]))
    57  	pf.RuleUID = binary.BigEndian.Uint32(data[52:56])
    58  	pf.RulePID = int32(binary.BigEndian.Uint32(data[56:60]))
    59  	pf.Direction = PFDirection(data[60])
    60  	if pf.Length%4 != 1 {
    61  		return errors.New("PFLog header length should be 3 less than multiple of 4")
    62  	}
    63  	actualLength := int(pf.Length) + 3
    64  	if len(data) < actualLength {
    65  		return fmt.Errorf("PFLog data size < %d", actualLength)
    66  	}
    67  	pf.Contents = data[:actualLength]
    68  	pf.Payload = data[actualLength:]
    69  	return nil
    70  }
    71  
    72  // LayerType returns layers.LayerTypePFLog
    73  func (pf *PFLog) LayerType() gopacket.LayerType { return LayerTypePFLog }
    74  
    75  func (pf *PFLog) CanDecode() gopacket.LayerClass { return LayerTypePFLog }
    76  
    77  func (pf *PFLog) NextLayerType() gopacket.LayerType {
    78  	return pf.Family.LayerType()
    79  }
    80  
    81  func decodePFLog(data []byte, p gopacket.PacketBuilder) error {
    82  	pf := &PFLog{}
    83  	return decodingLayerDecoder(pf, data, p)
    84  }