147 lines
4.6 KiB
Go
147 lines
4.6 KiB
Go
|
// Copyright 2015 Google, Inc. All rights reserved.
|
||
|
//
|
||
|
// Use of this source code is governed by a BSD-style license
|
||
|
// that can be found in the LICENSE file in the root of the source
|
||
|
// tree.
|
||
|
|
||
|
// http://www.tcpdump.org/linktypes/LINKTYPE_IEEE802_11_PRISM.html
|
||
|
|
||
|
package layers
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"errors"
|
||
|
|
||
|
"github.com/google/gopacket"
|
||
|
)
|
||
|
|
||
|
func decodePrismValue(data []byte, pv *PrismValue) {
|
||
|
pv.DID = PrismDID(binary.LittleEndian.Uint32(data[0:4]))
|
||
|
pv.Status = binary.LittleEndian.Uint16(data[4:6])
|
||
|
pv.Length = binary.LittleEndian.Uint16(data[6:8])
|
||
|
pv.Data = data[8 : 8+pv.Length]
|
||
|
}
|
||
|
|
||
|
type PrismDID uint32
|
||
|
|
||
|
const (
|
||
|
PrismDIDType1HostTime PrismDID = 0x10044
|
||
|
PrismDIDType2HostTime PrismDID = 0x01041
|
||
|
PrismDIDType1MACTime PrismDID = 0x20044
|
||
|
PrismDIDType2MACTime PrismDID = 0x02041
|
||
|
PrismDIDType1Channel PrismDID = 0x30044
|
||
|
PrismDIDType2Channel PrismDID = 0x03041
|
||
|
PrismDIDType1RSSI PrismDID = 0x40044
|
||
|
PrismDIDType2RSSI PrismDID = 0x04041
|
||
|
PrismDIDType1SignalQuality PrismDID = 0x50044
|
||
|
PrismDIDType2SignalQuality PrismDID = 0x05041
|
||
|
PrismDIDType1Signal PrismDID = 0x60044
|
||
|
PrismDIDType2Signal PrismDID = 0x06041
|
||
|
PrismDIDType1Noise PrismDID = 0x70044
|
||
|
PrismDIDType2Noise PrismDID = 0x07041
|
||
|
PrismDIDType1Rate PrismDID = 0x80044
|
||
|
PrismDIDType2Rate PrismDID = 0x08041
|
||
|
PrismDIDType1TransmittedFrameIndicator PrismDID = 0x90044
|
||
|
PrismDIDType2TransmittedFrameIndicator PrismDID = 0x09041
|
||
|
PrismDIDType1FrameLength PrismDID = 0xA0044
|
||
|
PrismDIDType2FrameLength PrismDID = 0x0A041
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
PrismType1MessageCode uint16 = 0x00000044
|
||
|
PrismType2MessageCode uint16 = 0x00000041
|
||
|
)
|
||
|
|
||
|
func (p PrismDID) String() string {
|
||
|
dids := map[PrismDID]string{
|
||
|
PrismDIDType1HostTime: "Host Time",
|
||
|
PrismDIDType2HostTime: "Host Time",
|
||
|
PrismDIDType1MACTime: "MAC Time",
|
||
|
PrismDIDType2MACTime: "MAC Time",
|
||
|
PrismDIDType1Channel: "Channel",
|
||
|
PrismDIDType2Channel: "Channel",
|
||
|
PrismDIDType1RSSI: "RSSI",
|
||
|
PrismDIDType2RSSI: "RSSI",
|
||
|
PrismDIDType1SignalQuality: "Signal Quality",
|
||
|
PrismDIDType2SignalQuality: "Signal Quality",
|
||
|
PrismDIDType1Signal: "Signal",
|
||
|
PrismDIDType2Signal: "Signal",
|
||
|
PrismDIDType1Noise: "Noise",
|
||
|
PrismDIDType2Noise: "Noise",
|
||
|
PrismDIDType1Rate: "Rate",
|
||
|
PrismDIDType2Rate: "Rate",
|
||
|
PrismDIDType1TransmittedFrameIndicator: "Transmitted Frame Indicator",
|
||
|
PrismDIDType2TransmittedFrameIndicator: "Transmitted Frame Indicator",
|
||
|
PrismDIDType1FrameLength: "Frame Length",
|
||
|
PrismDIDType2FrameLength: "Frame Length",
|
||
|
}
|
||
|
|
||
|
if str, ok := dids[p]; ok {
|
||
|
return str
|
||
|
}
|
||
|
|
||
|
return "Unknown DID"
|
||
|
}
|
||
|
|
||
|
type PrismValue struct {
|
||
|
DID PrismDID
|
||
|
Status uint16
|
||
|
Length uint16
|
||
|
Data []byte
|
||
|
}
|
||
|
|
||
|
func (pv *PrismValue) IsSupplied() bool {
|
||
|
return pv.Status == 1
|
||
|
}
|
||
|
|
||
|
var ErrPrismExpectedMoreData = errors.New("Expected more data.")
|
||
|
var ErrPrismInvalidCode = errors.New("Invalid header code.")
|
||
|
|
||
|
func decodePrismHeader(data []byte, p gopacket.PacketBuilder) error {
|
||
|
d := &PrismHeader{}
|
||
|
return decodingLayerDecoder(d, data, p)
|
||
|
}
|
||
|
|
||
|
type PrismHeader struct {
|
||
|
BaseLayer
|
||
|
Code uint16
|
||
|
Length uint16
|
||
|
DeviceName string
|
||
|
Values []PrismValue
|
||
|
}
|
||
|
|
||
|
func (m *PrismHeader) LayerType() gopacket.LayerType { return LayerTypePrismHeader }
|
||
|
|
||
|
func (m *PrismHeader) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||
|
m.Code = binary.LittleEndian.Uint16(data[0:4])
|
||
|
m.Length = binary.LittleEndian.Uint16(data[4:8])
|
||
|
m.DeviceName = string(data[8:24])
|
||
|
m.BaseLayer = BaseLayer{Contents: data[:m.Length], Payload: data[m.Length:len(data)]}
|
||
|
|
||
|
switch m.Code {
|
||
|
case PrismType1MessageCode:
|
||
|
fallthrough
|
||
|
case PrismType2MessageCode:
|
||
|
// valid message code
|
||
|
default:
|
||
|
return ErrPrismInvalidCode
|
||
|
}
|
||
|
|
||
|
offset := uint16(24)
|
||
|
|
||
|
m.Values = make([]PrismValue, (m.Length-offset)/12)
|
||
|
for i := 0; i < len(m.Values); i++ {
|
||
|
decodePrismValue(data[offset:offset+12], &m.Values[i])
|
||
|
offset += 12
|
||
|
}
|
||
|
|
||
|
if offset != m.Length {
|
||
|
return ErrPrismExpectedMoreData
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (m *PrismHeader) CanDecode() gopacket.LayerClass { return LayerTypePrismHeader }
|
||
|
func (m *PrismHeader) NextLayerType() gopacket.LayerType { return LayerTypeDot11 }
|