| // 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 } |