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 7package layers 8 9import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 14 "github.com/ooni/psiphon/oopsi/github.com/google/gopacket" 15) 16 17type PFDirection uint8 18 19const ( 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 27type 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 42func (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 73func (pf *PFLog) LayerType() gopacket.LayerType { return LayerTypePFLog } 74 75func (pf *PFLog) CanDecode() gopacket.LayerClass { return LayerTypePFLog } 76 77func (pf *PFLog) NextLayerType() gopacket.LayerType { 78 return pf.Family.LayerType() 79} 80 81func decodePFLog(data []byte, p gopacket.PacketBuilder) error { 82 pf := &PFLog{} 83 return decodingLayerDecoder(pf, data, p) 84} 85