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 const char *dst
, *src
, *bssid
;
312 mgmt
= (struct ieee80211_mgmt
*) pkt_pull(pkt
, sizeof(*mgmt
));
316 dst
= lookup_vendor((mgmt
->da
[0] << 16) | (mgmt
->da
[1] << 8) | mgmt
->da
[2]);
317 src
= lookup_vendor((mgmt
->sa
[0] << 16) | (mgmt
->sa
[1] << 8) | mgmt
->sa
[2]);
318 bssid
= lookup_vendor((mgmt
->bssid
[0] << 16) | (mgmt
->bssid
[1] << 8) | mgmt
->bssid
[2]);
320 seq_ctrl
= le16_to_cpu(mgmt
->seq_ctrl
);
322 tprintf("Duration (%u),", le16_to_cpu(mgmt
->duration
));
323 tprintf("\n\tDestination (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
324 mgmt
->da
[0], mgmt
->da
[1], mgmt
->da
[2], mgmt
->da
[3], mgmt
->da
[4], mgmt
->da
[5]);
326 tprintf("=> (%s:%.2x:%.2x:%.2x)", dst
, mgmt
->da
[3], mgmt
->da
[4], mgmt
->da
[5]);
327 tprintf("\n\tSource (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
328 mgmt
->sa
[0], mgmt
->sa
[1], mgmt
->sa
[2], mgmt
->sa
[3], mgmt
->sa
[4], mgmt
->sa
[5]);
330 tprintf("=> (%s:%.2x:%.2x:%.2x)", src
, mgmt
->sa
[3], mgmt
->sa
[4], mgmt
->sa
[5]);
331 tprintf("\n\tBSSID (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) ",
332 mgmt
->bssid
[0], mgmt
->bssid
[1], mgmt
->bssid
[2], mgmt
->bssid
[3], mgmt
->bssid
[4], mgmt
->bssid
[5]);
334 tprintf("=> (%s:%.2x:%.2x:%.2x)", bssid
, mgmt
->bssid
[3], mgmt
->bssid
[4], mgmt
->bssid
[5]);
335 tprintf("\n\tFragmentnr. (%u), Seqnr. (%u). ", seq_ctrl
& 0xf, seq_ctrl
>> 4);
339 *get_content
= assoc_req
;
340 return "Association Request";
342 *get_content
= assoc_resp
;
343 return "Association Response";
345 *get_content
= reassoc_req
;
346 return "Reassociation Request";
348 *get_content
= reassoc_resp
;
349 return "Reassociation Response";
351 *get_content
= probe_req
;
352 return "Probe Request";
354 *get_content
= probe_resp
;
355 return "Probe Response";
357 *get_content
= beacon
;
363 *get_content
= disassoc
;
364 return "Disassociation";
367 return "Authentication";
369 *get_content
= deauth
;
370 return "Deauthentication";
373 if ((subtype
>= 0b0110 && subtype
<= 0b0111) || (subtype
>= 0b1101 && subtype
<= 0b1111))
376 return "Management SubType not supported";
379 static char *ctrl_sub(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
)) {
383 *get_content
= ps_poll
;
395 *get_content
= cf_end
;
398 *get_content
= cf_end_ack
;
399 return "CF End + CF-ACK";
402 if (subtype
<= 0b1001)
405 return "Control SubType not supported";
408 static char *data_sub(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
)) {
415 *get_content
= data_cf_ack
;
416 return "Data + CF-ACK";
418 *get_content
= data_cf_poll
;
419 return "Data + CF-Poll";
421 *get_content
= data_cf_ack_poll
;
422 return "Data + CF-ACK + CF-Poll";
427 *get_content
= cf_ack
;
430 *get_content
= cf_poll
;
433 *get_content
= cf_ack_poll
;
434 return "CF-ACK + CF-Poll";
437 if (subtype
>= 0b1000 && subtype
<= 0b1111)
440 return "Data SubType not supported";
443 static char *frame_control_type(u8 type
, char *(**get_subtype
)(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
))) {
446 *get_subtype
= mgt_sub
;
449 *get_subtype
= ctrl_sub
;
452 *get_subtype
= data_sub
;
454 case 0b11: return "Reserved";
457 return "Control Type not supported";
461 static void ieee80211(struct pkt_buff
*pkt
)
463 int8_t (*get_content
)(struct pkt_buff
*pkt
) = NULL
;
464 char *(*get_subtype
)(u8 subtype
, struct pkt_buff
*pkt
, int8_t (**get_content
)(struct pkt_buff
*pkt
)) = NULL
;
466 struct ieee80211_frm_ctrl
*frm_ctrl
=
467 (struct ieee80211_frm_ctrl
*) pkt_pull(pkt
, sizeof(*frm_ctrl
));
468 if (frm_ctrl
== NULL
)
471 tprintf(" [ 802.11 Frame Control (0x%04x)]\n",
472 le16_to_cpu(frm_ctrl
->frame_control
));
473 tprintf("\t [ Proto Version (%u), ", frm_ctrl
->proto_version
);
474 tprintf("Type (%u, %s), ", frm_ctrl
->type
, frame_control_type(frm_ctrl
->type
, &get_subtype
));
476 tprintf("Subtype (%u, %s)", frm_ctrl
->subtype
, (*get_subtype
)(frm_ctrl
->subtype
, pkt
, &get_content
));
478 tprintf("\n%s%s%s", colorize_start_full(black
, red
),
479 "No SubType Data available", colorize_end());
481 frm_ctrl
->to_ds
? ", Frame goes to DS" : "",
482 frm_ctrl
->from_ds
? ", Frame comes from DS" : "");
483 tprintf("%s", frm_ctrl
->more_frags
? ", More Fragments" : "");
484 tprintf("%s", frm_ctrl
->retry
? ", Frame is retransmitted" : "");
485 tprintf("%s", frm_ctrl
->power_mgmt
? ", In Power Saving Mode" : "");
486 tprintf("%s", frm_ctrl
->more_data
? ", More Data" : "");
487 tprintf("%s", frm_ctrl
->wep
? ", Needs WEP" : "");
488 tprintf("%s", frm_ctrl
->order
? ", Order" : "");
492 if (!((*get_content
) (pkt
)))
493 tprintf("\n%s%s%s", colorize_start_full(black
, red
),
494 "Failed to dissect Subtype", colorize_end());
497 tprintf("\n%s%s%s", colorize_start_full(black
, red
),
498 "No SubType Data available", colorize_end());
500 // pkt_set_proto(pkt, &ieee802_lay2, ntohs(eth->h_proto));
503 static void ieee80211_less(struct pkt_buff
*pkt
)
505 tprintf("802.11 frame (more on todo)");
508 struct protocol ieee80211_ops
= {
510 .print_full
= ieee80211
,
511 .print_less
= ieee80211_less
,
514 EXPORT_SYMBOL(ieee80211_ops
);