Reputation: 141
Gopacket supports parsing information elements in beacon and probe response frames, like this:
for _, layer := range packet.Layers() {
if layer.LayerType() == layers.LayerTypeDot11InformationElement {
dot11info, ok := layer.(*layers.Dot11InformationElement)
}
}
But gopacket doesn't support parsing information elements in probe request frame.
I can only use packet.Layer(layers.LayerTypeDot11MgmtProbeReq).(*layers.Dot11MgmtProbeReq)
to get the Contents and Payload, and the information elements are in this Contents.
So how can I parse these information elements in probe request frame?
Upvotes: 2
Views: 1142
Reputation: 71
As a head's up, the reason that you can't just parse IEs from probe requests like you could from beacons or probe responses is because gopacket itself never actually assigns to the Payload
field of the Dot11MgmtProbeReq
struct. See DecodeFromBytes
in Dot11MgmtBeacon and Dot11MgmtProbeResp; Dot11MgmtProbeReq has no such method. Replacing Dot11MgmtProbeReq
from gopacket with the following code fixes this issue (although this may be overkill for you):
type Dot11MgmtProbeReq struct {
Dot11Mgmt
}
func decodeDot11MgmtProbeReq(data []byte, p gopacket.PacketBuilder) error {
d := &Dot11MgmtProbeReq{}
return decodingLayerDecoder(d, data, p)
}
func (m *Dot11MgmtProbeReq) LayerType() gopacket.LayerType { return LayerTypeDot11MgmtProbeReq }
func (m *Dot11MgmtProbeReq) CanDecode() gopacket.LayerClass { return LayerTypeDot11MgmtProbeReq }
func (m *Dot11MgmtProbeReq) NextLayerType() gopacket.LayerType {
return LayerTypeDot11InformationElement
}
func (m *Dot11MgmtProbeReq) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
m.Payload = data
return m.Dot11Mgmt.DecodeFromBytes(data, df)
}
One straightforward way to extract IEs in general is to set up a single core function to pass the list of IEs from the current frame into a function that decodes all relevant elements into a map[string][]byte
where the string is a human-readable name for the string. That way, any frame-specific fields can be requested in their specific cases. (You need to write a map[layers.Dot11InformationElementID]string` to do this).
Upvotes: 2
Reputation: 1380
I believe you have to write yourself. Have you already tried this implementation?
The parser is the following:
func (pr *capturedRequest) decodeProbeRequestLayer(probeLayer *layers.Dot11MgmtProbeReq) {
var body []byte
body = probeLayer.LayerContents()
for i := uint64(0); i < uint64(len(body)); {
id := layers.Dot11InformationElementID(body[i])
i++
switch id {
case layers.Dot11InformationElementIDSSID:
elemLen := uint64(body[i])
i++
if elemLen > 0 {
pr.SSID = string(body[i : i+elemLen])
i += elemLen
}
break
case layers.Dot11InformationElementIDVendor:
pr.VendorSpecific = body[i+1:]
return
default:
elemLen := uint64(body[i])
i += 1 + elemLen
break
}
}
}
Upvotes: 3