blob: e1711e7f5b9b0f1755f92d8ba6515bdf087cc5a4 [file] [log] [blame]
// 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 }