aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/google/gopacket/layers/prism.go
blob: e1711e7f5b9b0f1755f92d8ba6515bdf087cc5a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// 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 }