2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2012 Daniel Borkmann <borkmann@iogearbox.net>
4 * Copyright 2012 Markus Amend <markus@netsniff-ng.org>, Deutsche Flugsicherung GmbH
5 * Subject to the GPL, version 2.
10 #include <netinet/in.h> /* for ntohs() */
11 #include <asm/byteorder.h>
15 #include "dissector_80211.h"
20 /* Note: Fields are encoded in little-endian! */
21 struct ieee80211_frm_ctrl
{
25 #if defined(__LITTLE_ENDIAN_BITFIELD)
26 /* Correct order here ... */
27 __extension__ u16 proto_version
:2,
38 #elif defined(__BIG_ENDIAN_BITFIELD)
39 __extension__ u16 subtype
:4,
51 # error "Adjust your <asm/byteorder.h> defines"
57 /* Management Frame start */
58 /* Note: Fields are encoded in little-endian! */
59 struct ieee80211_mgmt
{
67 struct ieee80211_mgmt_auth
{
71 /* possibly followed by Challenge text */
75 struct ieee80211_mgmt_deauth
{
79 struct ieee80211_mgmt_assoc_req
{
82 /* followed by SSID and Supported rates */
86 struct ieee80211_mgmt_assoc_resp
{
90 /* followed by Supported rates */
94 struct ieee80211_mgmt_reassoc_resp
{
98 /* followed by Supported rates */
102 struct ieee80211_mgmt_reassoc_req
{
106 /* followed by SSID and Supported rates */
110 struct ieee80211_mgmt_disassoc
{
114 struct ieee80211_mgmt_probe_req
{
117 struct ieee80211_mgmt_beacon
{
121 /* followed by some of SSID, Supported rates,
122 * FH Params, DS Params, CF Params, IBSS Params, TIM */
126 struct ieee80211_mgmt_probe_resp
{
130 /* followed by some of SSID, Supported rates,
131 * FH Params, DS Params, CF Params, IBSS Params, TIM */
134 /* Management Frame end */
136 /* Control Frame start */
137 /* Note: Fields are encoded in little-endian! */
138 struct ieee80211_ctrl
{
141 struct ieee80211_ctrl_rts
{
147 struct ieee80211_ctrl_cts
{
152 struct ieee80211_ctrl_ack
{
157 struct ieee80211_ctrl_ps_poll
{
163 struct ieee80211_ctrl_cf_end
{
169 struct ieee80211_ctrl_cf_end_ack
{
174 /* Control Frame end */
176 /* Data Frame start */
177 /* Note: Fields are encoded in little-endian! */
178 struct ieee80211_data
{
185 /* http://www.sss-mag.com/pdf/802_11tut.pdf
186 * http://www.scribd.com/doc/78443651/111/Management-Frames
187 * http://www.wildpackets.com/resources/compendium/wireless_lan/wlan_packets
188 * http://www.rhyshaden.com/wireless.htm
191 /* Management Dissectors */
192 static int8_t assoc_req(struct pkt_buff
*pkt
) {
196 static int8_t assoc_resp(struct pkt_buff
*pkt
) {
200 static int8_t reassoc_req(struct pkt_buff
*pkt
) {
204 static int8_t reassoc_resp(struct pkt_buff
*pkt
) {
208 static int8_t probe_req(struct pkt_buff
*pkt
) {
212 static int8_t probe_resp(struct pkt_buff
*pkt
) {
216 static int8_t beacon(struct pkt_buff
*pkt
) {
217 struct ieee80211_mgmt_beacon
*beacon
=
218 (struct ieee80211_mgmt_beacon
*) pkt_pull(pkt
, sizeof(*beacon
));
221 tprintf("Timestamp 0x%.16lx, ", le64_to_cpu(beacon
->timestamp
));
222 tprintf("Beacon Interval (%fs), ",
223 le16_to_cpu(beacon
->beacon_int
) * 0.001024);
224 tprintf("Capabilites (0x%.8x)",
225 le16_to_cpu(beacon
->capab_info
));
229 static int8_t atim(struct pkt_buff
*pkt
) {
233 static int8_t disassoc(struct pkt_buff
*pkt
) {
237 static int8_t auth(struct pkt_buff
*pkt
) {
241 static int8_t deauth(struct pkt_buff
*pkt
) {
244 /* End Management Dissectors */
246 /* Control Dissectors */
247 static int8_t ps_poll(struct pkt_buff
*pkt
) {
251 static int8_t rts(struct pkt_buff
*pkt
) {
255 static int8_t cts(struct pkt_buff
*pkt
) {
259 static int8_t ack(struct pkt_buff
*pkt
) {
263 static int8_t cf_end(struct pkt_buff
*pkt
) {
267 static int8_t cf_end_ack(struct pkt_buff
*pkt
) {
270 /* End Control Dissectors */
272 /* Data Dissectors */
273 static int8_t data(struct pkt_buff
*pkt
) {
277 static int8_t data_cf_ack(struct pkt_buff
*pkt
) {
281 static int8_t data_cf_poll(struct pkt_buff
*pkt
) {
285 static int8_t data_cf_ack_poll(struct pkt_buff
*pkt
) {
289 static int8_t null(struct pkt_buff
*pkt
) {
293 static int8_t cf_ack(struct pkt_buff
*pkt
) {
297 static int8_t cf_poll(struct pkt_buff
*pkt
) {
301 static int8_t cf_ack_poll(struct pkt_buff
*pkt
) {
304 /* End Data Dissectors */
306 static char *mgt_sub(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
)) {
308 struct ieee80211_mgmt
*mgmt
=
309 (struct ieee80211_mgmt
*) pkt_pull(pkt
, sizeof(*mgmt
));
313 const char *dst
= lookup_vendor((mgmt
->da
[0] << 16) | (mgmt
->da
[1] << 8) | mgmt
->da
[2]);
314 const char *src
= lookup_vendor((mgmt
->sa
[0] << 16) | (mgmt
->sa
[1] << 8) | mgmt
->sa
[2]);
315 const char *bssid
= lookup_vendor((mgmt
->bssid
[0] << 16) | (mgmt
->bssid
[1] << 8) | mgmt
->bssid
[2]);
316 u16 seq_ctrl
= le16_to_cpu(mgmt
->seq_ctrl
);
318 tprintf("Duration (%u),", le16_to_cpu(mgmt
->duration
));
319 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
320 mgmt
->da
[0], mgmt
->da
[1], mgmt
->da
[2], mgmt
->da
[3], mgmt
->da
[4], mgmt
->da
[5]);
322 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst
, mgmt
->da
[3], mgmt
->da
[4], mgmt
->da
[5]);
323 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
324 mgmt
->sa
[0], mgmt
->sa
[1], mgmt
->sa
[2], mgmt
->sa
[3], mgmt
->sa
[4], mgmt
->sa
[5]);
326 tprintf("=> (%s:%.2x:%.2x:%.2x)", src
, mgmt
->sa
[3], mgmt
->sa
[4], mgmt
->sa
[5]);
327 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
328 mgmt
->bssid
[0], mgmt
->bssid
[1], mgmt
->bssid
[2], mgmt
->bssid
[3], mgmt
->bssid
[4], mgmt
->bssid
[5]);
330 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid
, mgmt
->bssid
[3], mgmt
->bssid
[4], mgmt
->bssid
[5]);
331 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ", seq_ctrl
& 0xf, seq_ctrl
>> 4);
335 *get_content
= assoc_req
;
336 return "Association Request";
338 *get_content
= assoc_resp
;
339 return "Association Response";
341 *get_content
= reassoc_req
;
342 return "Reassociation Request";
344 *get_content
= reassoc_resp
;
345 return "Reassociation Response";
347 *get_content
= probe_req
;
348 return "Probe Request";
350 *get_content
= probe_resp
;
351 return "Probe Response";
353 *get_content
= beacon
;
359 *get_content
= disassoc
;
360 return "Disassociation";
363 return "Authentication";
365 *get_content
= deauth
;
366 return "Deauthentication";
369 if ((subtype
>= 0b0110 && subtype
<= 0b0111) || (subtype
>= 0b1101 && subtype
<= 0b1111))
372 return "Management SubType not supported";
375 static char *ctrl_sub(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
)) {
379 *get_content
= ps_poll
;
391 *get_content
= cf_end
;
394 *get_content
= cf_end_ack
;
395 return "CF End + CF-ACK";
398 if (subtype
<= 0b1001)
401 return "Control SubType not supported";
404 static char *data_sub(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
)) {
411 *get_content
= data_cf_ack
;
412 return "Data + CF-ACK";
414 *get_content
= data_cf_poll
;
415 return "Data + CF-Poll";
417 *get_content
= data_cf_ack_poll
;
418 return "Data + CF-ACK + CF-Poll";
423 *get_content
= cf_ack
;
426 *get_content
= cf_poll
;
429 *get_content
= cf_ack_poll
;
430 return "CF-ACK + CF-Poll";
433 if (subtype
>= 0b1000 && subtype
<= 0b1111)
436 return "Data SubType not supported";
439 static char *frame_control_type(u8 type
, char *(**get_subtype
)(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
))) {
442 *get_subtype
= mgt_sub
;
445 *get_subtype
= ctrl_sub
;
448 *get_subtype
= data_sub
;
450 case 0b11: return "Reserved";
453 return "Control Type not supported";
457 static void ieee80211(struct pkt_buff
*pkt
)
459 int8_t (*get_content
)(struct pkt_buff
*pkt
) = NULL
;
460 char *(*get_subtype
)(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
)) = NULL
;
462 struct ieee80211_frm_ctrl
*frm_ctrl
=
463 (struct ieee80211_frm_ctrl
*) pkt_pull(pkt
, sizeof(*frm_ctrl
));
464 if (frm_ctrl
== NULL
)
467 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
468 le16_to_cpu(frm_ctrl
->frame_control
));
469 tprintf("\t [ Proto Version (%u), ", frm_ctrl
->proto_version
);
470 tprintf("Type (%u, %s), ", frm_ctrl
->type
, frame_control_type(frm_ctrl
->type
, &get_subtype
));
472 tprintf("Subtype (%u, %s)", frm_ctrl
->subtype
, (*get_subtype
)(frm_ctrl
->subtype
, pkt
, &get_content
));
474 tprintf("\n%s%s%s", colorize_start_full(black
, red
),
475 "No SubType Data available", colorize_end());
477 frm_ctrl
->to_ds
? ", Frame goes to DS" : "",
478 frm_ctrl
->from_ds
? ", Frame comes from DS" : "");
479 tprintf("%s", frm_ctrl
->more_frags
? ", More Fragments" : "");
480 tprintf("%s", frm_ctrl
->retry
? ", Frame is retransmitted" : "");
481 tprintf("%s", frm_ctrl
->power_mgmt
? ", In Power Saving Mode" : "");
482 tprintf("%s", frm_ctrl
->more_data
? ", More Data" : "");
483 tprintf("%s", frm_ctrl
->wep
? ", Needs WEP" : "");
484 tprintf("%s", frm_ctrl
->order
? ", Order" : "");
488 if (!((*get_content
) (pkt
)))
489 tprintf("\n%s%s%s", colorize_start_full(black
, red
),
490 "Failed to dissect Subtype", colorize_end());
493 tprintf("\n%s%s%s", colorize_start_full(black
, red
),
494 "No SubType Data available", colorize_end());
496 // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
499 static void ieee80211_less(struct pkt_buff
*pkt
)
501 tprintf("802.11 frame (more on todo)");
504 struct protocol ieee80211_ops
= {
506 .print_full
= ieee80211
,
507 .print_less
= ieee80211_less
,
510 EXPORT_SYMBOL(ieee80211_ops
);