blob: e1711e7f5b9b0f1755f92d8ba6515bdf087cc5a4 [file] [log] [blame]
Takahiro Suzuki241c10e2020-12-17 20:17:57 +09001// Copyright 2015 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// http://www.tcpdump.org/linktypes/LINKTYPE_IEEE802_11_PRISM.html
8
9package layers
10
11import (
12 "encoding/binary"
13 "errors"
14
15 "github.com/google/gopacket"
16)
17
18func decodePrismValue(data []byte, pv *PrismValue) {
19 pv.DID = PrismDID(binary.LittleEndian.Uint32(data[0:4]))
20 pv.Status = binary.LittleEndian.Uint16(data[4:6])
21 pv.Length = binary.LittleEndian.Uint16(data[6:8])
22 pv.Data = data[8 : 8+pv.Length]
23}
24
25type PrismDID uint32
26
27const (
28 PrismDIDType1HostTime PrismDID = 0x10044
29 PrismDIDType2HostTime PrismDID = 0x01041
30 PrismDIDType1MACTime PrismDID = 0x20044
31 PrismDIDType2MACTime PrismDID = 0x02041
32 PrismDIDType1Channel PrismDID = 0x30044
33 PrismDIDType2Channel PrismDID = 0x03041
34 PrismDIDType1RSSI PrismDID = 0x40044
35 PrismDIDType2RSSI PrismDID = 0x04041
36 PrismDIDType1SignalQuality PrismDID = 0x50044
37 PrismDIDType2SignalQuality PrismDID = 0x05041
38 PrismDIDType1Signal PrismDID = 0x60044
39 PrismDIDType2Signal PrismDID = 0x06041
40 PrismDIDType1Noise PrismDID = 0x70044
41 PrismDIDType2Noise PrismDID = 0x07041
42 PrismDIDType1Rate PrismDID = 0x80044
43 PrismDIDType2Rate PrismDID = 0x08041
44 PrismDIDType1TransmittedFrameIndicator PrismDID = 0x90044
45 PrismDIDType2TransmittedFrameIndicator PrismDID = 0x09041
46 PrismDIDType1FrameLength PrismDID = 0xA0044
47 PrismDIDType2FrameLength PrismDID = 0x0A041
48)
49
50const (
51 PrismType1MessageCode uint16 = 0x00000044
52 PrismType2MessageCode uint16 = 0x00000041
53)
54
55func (p PrismDID) String() string {
56 dids := map[PrismDID]string{
57 PrismDIDType1HostTime: "Host Time",
58 PrismDIDType2HostTime: "Host Time",
59 PrismDIDType1MACTime: "MAC Time",
60 PrismDIDType2MACTime: "MAC Time",
61 PrismDIDType1Channel: "Channel",
62 PrismDIDType2Channel: "Channel",
63 PrismDIDType1RSSI: "RSSI",
64 PrismDIDType2RSSI: "RSSI",
65 PrismDIDType1SignalQuality: "Signal Quality",
66 PrismDIDType2SignalQuality: "Signal Quality",
67 PrismDIDType1Signal: "Signal",
68 PrismDIDType2Signal: "Signal",
69 PrismDIDType1Noise: "Noise",
70 PrismDIDType2Noise: "Noise",
71 PrismDIDType1Rate: "Rate",
72 PrismDIDType2Rate: "Rate",
73 PrismDIDType1TransmittedFrameIndicator: "Transmitted Frame Indicator",
74 PrismDIDType2TransmittedFrameIndicator: "Transmitted Frame Indicator",
75 PrismDIDType1FrameLength: "Frame Length",
76 PrismDIDType2FrameLength: "Frame Length",
77 }
78
79 if str, ok := dids[p]; ok {
80 return str
81 }
82
83 return "Unknown DID"
84}
85
86type PrismValue struct {
87 DID PrismDID
88 Status uint16
89 Length uint16
90 Data []byte
91}
92
93func (pv *PrismValue) IsSupplied() bool {
94 return pv.Status == 1
95}
96
97var ErrPrismExpectedMoreData = errors.New("Expected more data.")
98var ErrPrismInvalidCode = errors.New("Invalid header code.")
99
100func decodePrismHeader(data []byte, p gopacket.PacketBuilder) error {
101 d := &PrismHeader{}
102 return decodingLayerDecoder(d, data, p)
103}
104
105type PrismHeader struct {
106 BaseLayer
107 Code uint16
108 Length uint16
109 DeviceName string
110 Values []PrismValue
111}
112
113func (m *PrismHeader) LayerType() gopacket.LayerType { return LayerTypePrismHeader }
114
115func (m *PrismHeader) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
116 m.Code = binary.LittleEndian.Uint16(data[0:4])
117 m.Length = binary.LittleEndian.Uint16(data[4:8])
118 m.DeviceName = string(data[8:24])
119 m.BaseLayer = BaseLayer{Contents: data[:m.Length], Payload: data[m.Length:len(data)]}
120
121 switch m.Code {
122 case PrismType1MessageCode:
123 fallthrough
124 case PrismType2MessageCode:
125 // valid message code
126 default:
127 return ErrPrismInvalidCode
128 }
129
130 offset := uint16(24)
131
132 m.Values = make([]PrismValue, (m.Length-offset)/12)
133 for i := 0; i < len(m.Values); i++ {
134 decodePrismValue(data[offset:offset+12], &m.Values[i])
135 offset += 12
136 }
137
138 if offset != m.Length {
139 return ErrPrismExpectedMoreData
140 }
141
142 return nil
143}
144
145func (m *PrismHeader) CanDecode() gopacket.LayerClass { return LayerTypePrismHeader }
146func (m *PrismHeader) NextLayerType() gopacket.LayerType { return LayerTypeDot11 }