print-802_11.c revision 111726
198524Sfenner/* 298524Sfenner * Copyright (c) 2001 398524Sfenner * Fortress Technologies, Inc. All rights reserved. 498524Sfenner * Charlie Lenahan (clenahan@fortresstech.com) 598524Sfenner * 698524Sfenner * Redistribution and use in source and binary forms, with or without 798524Sfenner * modification, are permitted provided that: (1) source code distributions 898524Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 998524Sfenner * distributions including binary code include the above copyright notice and 1098524Sfenner * this paragraph in its entirety in the documentation or other materials 1198524Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1298524Sfenner * features or use of this software display the following acknowledgement: 1398524Sfenner * ``This product includes software developed by the University of California, 1498524Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1598524Sfenner * the University nor the names of its contributors may be used to endorse 1698524Sfenner * or promote products derived from this software without specific prior 1798524Sfenner * written permission. 1898524Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1998524Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 2098524Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2198524Sfenner */ 2298524Sfenner 2398524Sfenner#ifndef lint 2498524Sfennerstatic const char rcsid[] = 25111726Sfenner "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.6.4.1 2002/05/13 08:34:50 guy Exp $ (LBL)"; 2698524Sfenner#endif 2798524Sfenner 2898524Sfenner#ifdef HAVE_CONFIG_H 2998524Sfenner#include "config.h" 3098524Sfenner#endif 3198524Sfenner 3298524Sfenner#include <sys/param.h> 3398524Sfenner#include <sys/time.h> 3498524Sfenner#include <sys/socket.h> 3598524Sfenner 3698524Sfenner#include <netinet/in.h> 3798524Sfenner 3898524Sfenner#include <stdio.h> 3998524Sfenner#include <pcap.h> 4098524Sfenner#include <string.h> 4198524Sfenner 4298524Sfenner#include "interface.h" 4398524Sfenner#include "addrtoname.h" 4498524Sfenner#include "ethertype.h" 4598524Sfenner 4698524Sfenner#include "extract.h" 4798524Sfenner 4898524Sfenner#include "ieee802_11.h" 4998524Sfenner 50111726Sfenner#define PRINT_RATES(p) \ 5198524Sfennerdo { \ 52111726Sfenner int z; \ 53111726Sfenner char *sep = " ["; \ 54111726Sfenner for (z = 0; z < p.rates.length ; z++) { \ 55111726Sfenner printf("%s%2.1f", sep, (.5 * (p.rates.rate[z] & 0x7f))); \ 56111726Sfenner sep = " "; \ 57111726Sfenner } \ 58111726Sfenner if (p.rates.length != 0) \ 59111726Sfenner printf(" Mbit]"); \ 6098524Sfenner} while (0) 6198524Sfenner 6298524Sfennerstatic const char *auth_alg_text[]={"Open System","Shared Key","EAP"}; 6398524Sfennerstatic const char *subtype_text[]={ 6498524Sfenner "Assoc Request", 6598524Sfenner "Assoc Response", 6698524Sfenner "ReAssoc Request", 6798524Sfenner "ReAssoc Response", 6898524Sfenner "Probe Request", 6998524Sfenner "Probe Response", 7098524Sfenner "RESERVED", 7198524Sfenner "RESERVED", 7298524Sfenner "Beacon", 7398524Sfenner "ATIM", 7498524Sfenner "Disassociation", 7598524Sfenner "Authentication", 7698524Sfenner "DeAuthentication", 7798524Sfenner "RESERVED", 7898524Sfenner "RESERVED" 7998524Sfenner}; 8098524Sfenner 8198524Sfennerstatic const char *status_text[] = { 8298524Sfenner "Succesful", /* 0 */ 8398524Sfenner "Unspecified failure", /* 1 */ 8498524Sfenner "Reserved", /* 2 */ 8598524Sfenner "Reserved", /* 3 */ 8698524Sfenner "Reserved", /* 4 */ 8798524Sfenner "Reserved", /* 5 */ 8898524Sfenner "Reserved", /* 6 */ 8998524Sfenner "Reserved", /* 7 */ 9098524Sfenner "Reserved", /* 8 */ 9198524Sfenner "Reserved", /* 9 */ 9298524Sfenner "Cannot Support all requested capabilities in the Capability Information field", /* 10 */ 9398524Sfenner "Reassociation denied due to inability to confirm that association exists", /* 11 */ 9498524Sfenner "Association denied due to reason outside the scope of the standard", /* 12 */ 9598524Sfenner "Responding station does not support the specified authentication algorithm ", /* 13 */ 9698524Sfenner "Received an Authentication frame with authentication transaction " \ 9798524Sfenner "sequence number out of expected sequence", /* 14 */ 9898524Sfenner "Authentication rejected because of challenge failure", /* 15 */ 9998524Sfenner "Authentication rejected due to timeout waiting for next frame in sequence", /* 16 */ 10098524Sfenner "Association denied because AP is unable to handle additional associated stations", /* 17 */ 10198524Sfenner "Association denied due to requesting station not supporting all of the " \ 10298524Sfenner "data rates in BSSBasicRateSet parameter", /* 18 */ 10398524Sfenner NULL 10498524Sfenner}; 10598524Sfenner 10698524Sfennerstatic const char *reason_text[] = { 10798524Sfenner "Reserved", /* 0 */ 10898524Sfenner "Unspecified reason", /* 1 */ 10998524Sfenner "Previous authentication no longer valid", /* 2 */ 11098524Sfenner "Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */ 11198524Sfenner "Disassociated due to inactivity", /* 4 */ 11298524Sfenner "Disassociated because AP is unable to handle all currently associated stations", /* 5 */ 11398524Sfenner "Class 2 frame receivedfrom nonauthenticated station", /* 6 */ 11498524Sfenner "Class 3 frame received from nonassociated station", /* 7 */ 11598524Sfenner "Disassociated because sending station is leaving (or has left) BSS", /* 8 */ 11698524Sfenner "Station requesting (re)association is not authenticated with responding station", /* 9 */ 11798524Sfenner NULL 11898524Sfenner}; 11998524Sfenner 12098524Sfennerstatic int wep_print(const u_char *p,u_int length) 12198524Sfenner{ 12298524Sfenner u_int32_t iv; 12398524Sfenner 12498524Sfenner if (!TTEST2(*p, 4)) 12598524Sfenner return 0; 12698524Sfenner iv = EXTRACT_LE_32BITS(p); 12798524Sfenner 12898524Sfenner printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv), 12998524Sfenner IV_KEYID(iv)); 13098524Sfenner 13198524Sfenner return 1; 13298524Sfenner} 13398524Sfenner 13498524Sfenner 13598524Sfennerstatic int parse_elements(struct mgmt_body_t *pbody,const u_char *p,int offset) 13698524Sfenner{ 13798524Sfenner for (;;) { 13898524Sfenner if (!TTEST2(*(p + offset), 1)) 139111726Sfenner return 1; 14098524Sfenner switch (*(p + offset)) { 14198524Sfenner case E_SSID: 14298524Sfenner if (!TTEST2(*(p+offset), 2)) 14398524Sfenner return 0; 14498524Sfenner memcpy(&(pbody->ssid),p+offset,2); offset += 2; 14598524Sfenner if (pbody->ssid.length > 0) 14698524Sfenner { 14798524Sfenner if (!TTEST2(*(p+offset), pbody->ssid.length)) 14898524Sfenner return 0; 14998524Sfenner memcpy(&(pbody->ssid.ssid),p+offset,pbody->ssid.length); offset += pbody->ssid.length; 15098524Sfenner pbody->ssid.ssid[pbody->ssid.length]='\0'; 15198524Sfenner } 15298524Sfenner break; 15398524Sfenner case E_CHALLENGE: 15498524Sfenner if (!TTEST2(*(p+offset), 2)) 15598524Sfenner return 0; 15698524Sfenner memcpy(&(pbody->challenge),p+offset,2); offset += 2; 15798524Sfenner if (pbody->challenge.length > 0) 15898524Sfenner { 15998524Sfenner if (!TTEST2(*(p+offset), pbody->challenge.length)) 16098524Sfenner return 0; 16198524Sfenner memcpy(&(pbody->challenge.text),p+offset,pbody->challenge.length); offset += pbody->challenge.length; 16298524Sfenner pbody->challenge.text[pbody->challenge.length]='\0'; 16398524Sfenner } 16498524Sfenner break; 16598524Sfenner case E_RATES: 16698524Sfenner if (!TTEST2(*(p+offset), 2)) 16798524Sfenner return 0; 16898524Sfenner memcpy(&(pbody->rates),p+offset,2); offset += 2; 16998524Sfenner if (pbody->rates.length > 0) { 17098524Sfenner if (!TTEST2(*(p+offset), pbody->rates.length)) 17198524Sfenner return 0; 17298524Sfenner memcpy(&(pbody->rates.rate),p+offset,pbody->rates.length); offset += pbody->rates.length; 17398524Sfenner } 17498524Sfenner break; 17598524Sfenner case E_DS: 17698524Sfenner if (!TTEST2(*(p+offset), 3)) 17798524Sfenner return 0; 17898524Sfenner memcpy(&(pbody->ds),p+offset,3); offset +=3; 17998524Sfenner break; 18098524Sfenner case E_CF: 18198524Sfenner if (!TTEST2(*(p+offset), 8)) 18298524Sfenner return 0; 18398524Sfenner memcpy(&(pbody->cf),p+offset,8); offset +=8; 18498524Sfenner break; 18598524Sfenner case E_TIM: 18698524Sfenner if (!TTEST2(*(p+offset), 2)) 18798524Sfenner return 0; 18898524Sfenner memcpy(&(pbody->tim),p+offset,2); offset +=2; 18998524Sfenner if (!TTEST2(*(p+offset), 3)) 19098524Sfenner return 0; 19198524Sfenner memcpy(&(pbody->tim.count),p+offset,3); offset +=3; 19298524Sfenner 19398524Sfenner if ((pbody->tim.length -3) > 0) 19498524Sfenner { 19598524Sfenner if (!TTEST2(*(p+offset), pbody->tim.length -3)) 19698524Sfenner return 0; 19798524Sfenner memcpy((pbody->tim.bitmap),p+(pbody->tim.length -3),(pbody->tim.length -3)); 19898524Sfenner offset += pbody->tim.length -3; 19998524Sfenner } 20098524Sfenner 20198524Sfenner break; 20298524Sfenner default: 20398524Sfenner#if 0 20498524Sfenner printf("(1) unhandled element_id (%d) ", *(p+offset) ); 20598524Sfenner#endif 20698524Sfenner offset+= *(p+offset+1) + 2; 20798524Sfenner break; 20898524Sfenner } 20998524Sfenner } 21098524Sfenner return 1; 21198524Sfenner} 21298524Sfenner 21398524Sfenner/********************************************************************************* 21498524Sfenner * Print Handle functions for the management frame types 21598524Sfenner *********************************************************************************/ 21698524Sfenner 21798524Sfennerstatic int handle_beacon(u_int16_t fc, const struct mgmt_header_t *pmh, 21898524Sfenner const u_char *p) 21998524Sfenner{ 22098524Sfenner struct mgmt_body_t pbody; 22198524Sfenner int offset = 0; 22298524Sfenner 22398524Sfenner memset(&pbody, 0, sizeof(pbody)); 22498524Sfenner 22598524Sfenner if (!TTEST2(*p, 12)) 22698524Sfenner return 0; 22798524Sfenner memcpy(&pbody.timestamp, p, 8); 22898524Sfenner offset += 8; 22998524Sfenner pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); 23098524Sfenner offset += 2; 23198524Sfenner pbody.capability_info = EXTRACT_LE_16BITS(p+offset); 23298524Sfenner offset += 2; 23398524Sfenner 23498524Sfenner if (!parse_elements(&pbody,p,offset)) 23598524Sfenner return 0; 23698524Sfenner 237111726Sfenner printf("%s (", subtype_text[FC_SUBTYPE(fc)]); 238111726Sfenner fn_print(pbody.ssid.ssid, NULL); 239111726Sfenner printf(")"); 240111726Sfenner PRINT_RATES(pbody); 241111726Sfenner printf(" %s CH: %u %s", 24298524Sfenner CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS", 24398524Sfenner pbody.ds.channel, 24498524Sfenner CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" ); 24598524Sfenner 24698524Sfenner return 1; 24798524Sfenner} 24898524Sfenner 24998524Sfennerstatic int handle_assoc_request(u_int16_t fc, const struct mgmt_header_t *pmh, 25098524Sfenner const u_char *p) 25198524Sfenner{ 25298524Sfenner struct mgmt_body_t pbody; 25398524Sfenner int offset = 0; 25498524Sfenner 25598524Sfenner memset(&pbody, 0, sizeof(pbody)); 25698524Sfenner 25798524Sfenner if (!TTEST2(*p, 4)) 25898524Sfenner return 0; 25998524Sfenner pbody.capability_info = EXTRACT_LE_16BITS(p); 26098524Sfenner offset += 2; 26198524Sfenner pbody.listen_interval = EXTRACT_LE_16BITS(p+offset); 26298524Sfenner offset += 2; 26398524Sfenner 26498524Sfenner if (!parse_elements(&pbody,p,offset)) 26598524Sfenner return 0; 26698524Sfenner 267111726Sfenner printf("%s (", subtype_text[FC_SUBTYPE(fc)]); 268111726Sfenner fn_print(pbody.ssid.ssid, NULL); 269111726Sfenner printf(")"); 270111726Sfenner PRINT_RATES(pbody); 27198524Sfenner return 1; 27298524Sfenner} 27398524Sfenner 27498524Sfennerstatic int handle_assoc_response(u_int16_t fc, const struct mgmt_header_t *pmh, 27598524Sfenner const u_char *p) 27698524Sfenner{ 27798524Sfenner struct mgmt_body_t pbody; 27898524Sfenner int offset = 0; 27998524Sfenner 28098524Sfenner memset(&pbody, 0, sizeof(pbody)); 28198524Sfenner 28298524Sfenner if (!TTEST2(*p, 6)) 28398524Sfenner return 0; 28498524Sfenner pbody.capability_info = EXTRACT_LE_16BITS(p); 28598524Sfenner offset += 2; 28698524Sfenner pbody.status_code = EXTRACT_LE_16BITS(p+offset); 28798524Sfenner offset += 2; 28898524Sfenner pbody.aid = EXTRACT_LE_16BITS(p+offset); 28998524Sfenner offset += 2; 29098524Sfenner 29198524Sfenner if (!parse_elements(&pbody,p,offset)) 29298524Sfenner return 0; 29398524Sfenner 294111726Sfenner printf("%s AID(%x) :%s: %s", subtype_text[FC_SUBTYPE(fc)], 29598524Sfenner ((u_int16_t)(pbody.aid << 2 )) >> 2 , 29698524Sfenner CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "", 29798524Sfenner (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a")); 29898524Sfenner 29998524Sfenner return 1; 30098524Sfenner} 30198524Sfenner 30298524Sfenner 30398524Sfennerstatic int handle_reassoc_request(u_int16_t fc, const struct mgmt_header_t *pmh, 30498524Sfenner const u_char *p) 30598524Sfenner{ 30698524Sfenner struct mgmt_body_t pbody; 30798524Sfenner int offset = 0; 30898524Sfenner 30998524Sfenner memset(&pbody, 0, sizeof(pbody)); 31098524Sfenner 31198524Sfenner if (!TTEST2(*p, 10)) 31298524Sfenner return 0; 31398524Sfenner pbody.capability_info = EXTRACT_LE_16BITS(p); 31498524Sfenner offset += 2; 31598524Sfenner pbody.listen_interval = EXTRACT_LE_16BITS(p+offset); 31698524Sfenner offset += 2; 31798524Sfenner memcpy(&pbody.ap,p+offset,6); 31898524Sfenner offset += 6; 31998524Sfenner 32098524Sfenner if (!parse_elements(&pbody,p,offset)) 32198524Sfenner return 0; 32298524Sfenner 323111726Sfenner printf("%s (", subtype_text[FC_SUBTYPE(fc)]); 324111726Sfenner fn_print(pbody.ssid.ssid, NULL); 325111726Sfenner printf(") AP : %s", etheraddr_string( pbody.ap )); 32698524Sfenner 32798524Sfenner return 1; 32898524Sfenner} 32998524Sfenner 33098524Sfennerstatic int handle_reassoc_response(u_int16_t fc, const struct mgmt_header_t *pmh, 33198524Sfenner const u_char *p) 33298524Sfenner{ 33398524Sfenner /* Same as a Association Reponse */ 33498524Sfenner return handle_assoc_response(fc,pmh,p); 33598524Sfenner} 33698524Sfenner 33798524Sfennerstatic int handle_probe_request(u_int16_t fc, const struct mgmt_header_t *pmh, 33898524Sfenner const u_char *p) 33998524Sfenner{ 34098524Sfenner struct mgmt_body_t pbody; 34198524Sfenner int offset = 0; 34298524Sfenner 34398524Sfenner memset(&pbody, 0, sizeof(pbody)); 34498524Sfenner 34598524Sfenner if (!parse_elements(&pbody, p, offset)) 34698524Sfenner return 0; 34798524Sfenner 348111726Sfenner printf("%s (", subtype_text[FC_SUBTYPE(fc)]); 349111726Sfenner fn_print(pbody.ssid.ssid, NULL); 350111726Sfenner printf(")"); 351111726Sfenner PRINT_RATES(pbody); 35298524Sfenner 35398524Sfenner return 1; 35498524Sfenner} 35598524Sfenner 35698524Sfennerstatic int handle_probe_response(u_int16_t fc, const struct mgmt_header_t *pmh, 35798524Sfenner const u_char *p) 35898524Sfenner{ 35998524Sfenner struct mgmt_body_t pbody; 36098524Sfenner int offset = 0; 36198524Sfenner 36298524Sfenner memset(&pbody, 0, sizeof(pbody)); 36398524Sfenner 36498524Sfenner if (!TTEST2(*p, 12)) 36598524Sfenner return 0; 36698524Sfenner memcpy(&pbody.timestamp,p,8); 36798524Sfenner offset += 8; 36898524Sfenner pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); 36998524Sfenner offset += 2; 37098524Sfenner pbody.capability_info = EXTRACT_LE_16BITS(p+offset); 37198524Sfenner offset += 2; 37298524Sfenner 37398524Sfenner if (!parse_elements(&pbody, p, offset)) 37498524Sfenner return 0; 37598524Sfenner 376111726Sfenner printf("%s (", subtype_text[FC_SUBTYPE(fc)]); 377111726Sfenner fn_print(pbody.ssid.ssid, NULL); 378111726Sfenner printf(") "); 379111726Sfenner PRINT_RATES(pbody); 380111726Sfenner printf(" CH: %u%s", pbody.ds.channel, 381111726Sfenner CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" ); 38298524Sfenner 38398524Sfenner return 1; 38498524Sfenner} 38598524Sfenner 38698524Sfennerstatic int handle_atim(u_int16_t fc, const struct mgmt_header_t *pmh, 38798524Sfenner const u_char *p) 38898524Sfenner{ 38998524Sfenner /* the frame body for ATIM is null. */ 39098524Sfenner printf("ATIM"); 39198524Sfenner return 1; 39298524Sfenner} 39398524Sfenner 39498524Sfennerstatic int handle_disassoc(u_int16_t fc, const struct mgmt_header_t *pmh, 39598524Sfenner const u_char *p) 39698524Sfenner{ 39798524Sfenner struct mgmt_body_t pbody; 39898524Sfenner int offset = 0; 39998524Sfenner 40098524Sfenner memset(&pbody, 0, sizeof(pbody)); 40198524Sfenner 40298524Sfenner if (!TTEST2(*p, 2)) 40398524Sfenner return 0; 40498524Sfenner pbody.reason_code = EXTRACT_LE_16BITS(p); 40598524Sfenner offset += 2; 40698524Sfenner 407111726Sfenner printf("%s: %s", subtype_text[FC_SUBTYPE(fc)], 40898524Sfenner pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" ); 40998524Sfenner 41098524Sfenner return 1; 41198524Sfenner} 41298524Sfenner 41398524Sfennerstatic int handle_auth(u_int16_t fc, const struct mgmt_header_t *pmh, 41498524Sfenner const u_char *p) 41598524Sfenner{ 41698524Sfenner struct mgmt_body_t pbody; 41798524Sfenner int offset = 0; 41898524Sfenner 41998524Sfenner memset(&pbody, 0, sizeof(pbody)); 42098524Sfenner 42198524Sfenner if (!TTEST2(*p, 6)) 42298524Sfenner return 0; 42398524Sfenner pbody.auth_alg = EXTRACT_LE_16BITS(p); 42498524Sfenner offset += 2; 42598524Sfenner pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset); 42698524Sfenner offset += 2; 42798524Sfenner pbody.status_code = EXTRACT_LE_16BITS(p + offset); 42898524Sfenner offset += 2; 42998524Sfenner 43098524Sfenner if (!parse_elements(&pbody,p,offset)) 43198524Sfenner return 0; 43298524Sfenner 43398524Sfenner if ((pbody.auth_alg == 1) && 43498524Sfenner ((pbody.auth_trans_seq_num == 2) || (pbody.auth_trans_seq_num == 3))) { 43598524Sfenner printf("%s (%s)-%x [Challenge Text] %s", 43698524Sfenner subtype_text[FC_SUBTYPE(fc)], 43798524Sfenner pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" , 43898524Sfenner pbody.auth_trans_seq_num, 43998524Sfenner ((pbody.auth_trans_seq_num % 2) ? 44098524Sfenner (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a") : "" )); 44198524Sfenner } else { 44298524Sfenner printf("%s (%s)-%x: %s", 44398524Sfenner subtype_text[FC_SUBTYPE(fc)], 44498524Sfenner pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" , 44598524Sfenner pbody.auth_trans_seq_num, 44698524Sfenner ((pbody.auth_trans_seq_num % 2) ? (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a") : "")); 44798524Sfenner } 44898524Sfenner 44998524Sfenner return 1; 45098524Sfenner} 45198524Sfenner 45298524Sfennerstatic int handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh, 45398524Sfenner const u_char *p) 45498524Sfenner{ 45598524Sfenner struct mgmt_body_t pbody; 45698524Sfenner int offset = 0; 45798524Sfenner 45898524Sfenner memset(&pbody, 0, sizeof(pbody)); 45998524Sfenner 46098524Sfenner if (!TTEST2(*p, 2)) 46198524Sfenner return 0; 46298524Sfenner pbody.reason_code = EXTRACT_LE_16BITS(p); 46398524Sfenner offset += 2; 46498524Sfenner 46598524Sfenner if (eflag) { 46698524Sfenner printf("%s: %s", 46798524Sfenner subtype_text[FC_SUBTYPE(fc)], 46898524Sfenner pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" ); 46998524Sfenner } else { 47098524Sfenner printf("%s (%s): %s", 47198524Sfenner subtype_text[FC_SUBTYPE(fc)], etheraddr_string(pmh->sa), 47298524Sfenner pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" ); 47398524Sfenner } 47498524Sfenner 47598524Sfenner return 1; 47698524Sfenner} 47798524Sfenner 47898524Sfenner 47998524Sfenner/********************************************************************************* 48098524Sfenner * Print Body funcs 48198524Sfenner *********************************************************************************/ 48298524Sfenner 48398524Sfenner 48498524Sfennerstatic int mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh, 48598524Sfenner const u_char *p, u_int length) 48698524Sfenner{ 48798524Sfenner switch (FC_SUBTYPE(fc)) { 48898524Sfenner case ST_ASSOC_REQUEST: 48998524Sfenner return (handle_assoc_request(fc, pmh, p)); 49098524Sfenner case ST_ASSOC_RESPONSE: 49198524Sfenner return (handle_assoc_response(fc, pmh, p)); 49298524Sfenner case ST_REASSOC_REQUEST: 49398524Sfenner return (handle_reassoc_request(fc, pmh, p)); 49498524Sfenner case ST_REASSOC_RESPONSE: 49598524Sfenner return (handle_reassoc_response(fc, pmh, p)); 49698524Sfenner case ST_PROBE_REQUEST: 49798524Sfenner return (handle_probe_request(fc, pmh, p)); 49898524Sfenner case ST_PROBE_RESPONSE: 49998524Sfenner return (handle_probe_response(fc, pmh, p)); 50098524Sfenner case ST_BEACON: 50198524Sfenner return (handle_beacon(fc, pmh, p)); 50298524Sfenner case ST_ATIM: 50398524Sfenner return (handle_atim(fc, pmh, p)); 50498524Sfenner case ST_DISASSOC: 50598524Sfenner return (handle_disassoc(fc, pmh, p)); 50698524Sfenner case ST_AUTH: 50798524Sfenner if (!TTEST2(*p, 3)) 50898524Sfenner return 0; 50998524Sfenner if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) { 51098524Sfenner printf("Authentication (Shared-Key)-3 "); 51198524Sfenner return (wep_print(p, length)); 51298524Sfenner } 51398524Sfenner else 51498524Sfenner return (handle_auth(fc, pmh, p)); 51598524Sfenner case ST_DEAUTH: 51698524Sfenner return (handle_deauth(fc, pmh, p)); 51798524Sfenner break; 51898524Sfenner default: 51998524Sfenner printf("Unhandled Managment subtype(%x)", 52098524Sfenner FC_SUBTYPE(fc)); 52198524Sfenner return 1; 52298524Sfenner } 52398524Sfenner} 52498524Sfenner 52598524Sfenner 52698524Sfenner/********************************************************************************* 52798524Sfenner * Handles printing all the control frame types 52898524Sfenner *********************************************************************************/ 52998524Sfenner 53098524Sfennerstatic int ctrl_body_print(u_int16_t fc,const u_char *p, u_int length) 53198524Sfenner{ 53298524Sfenner switch (FC_SUBTYPE(fc)) { 53398524Sfenner case CTRL_PS_POLL: 53498524Sfenner if (!TTEST2(*p, CTRL_PS_POLL_LEN)) 53598524Sfenner return 0; 53698524Sfenner printf("Power Save-Poll AID(%x)", 53798524Sfenner EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid))); 53898524Sfenner break; 53998524Sfenner case CTRL_RTS: 54098524Sfenner if (!TTEST2(*p, CTRL_RTS_LEN)) 54198524Sfenner return 0; 54298524Sfenner if (eflag) 54398524Sfenner printf("Request-To-Send"); 54498524Sfenner else 54598524Sfenner printf("Request-To-Send TA:%s ", 54698524Sfenner etheraddr_string(((const struct ctrl_rts_t *)p)->ta)); 54798524Sfenner break; 54898524Sfenner case CTRL_CTS: 54998524Sfenner if (!TTEST2(*p, CTRL_CTS_LEN)) 55098524Sfenner return 0; 55198524Sfenner if (eflag) 55298524Sfenner printf("Clear-To-Send"); 55398524Sfenner else 55498524Sfenner printf("Clear-To-Send RA:%s ", 55598524Sfenner etheraddr_string(((const struct ctrl_cts_t *)p)->ra)); 55698524Sfenner break; 55798524Sfenner case CTRL_ACK: 55898524Sfenner if (!TTEST2(*p, CTRL_ACK_LEN)) 55998524Sfenner return 0; 56098524Sfenner if (eflag) 56198524Sfenner printf("Acknowledgment"); 56298524Sfenner else 56398524Sfenner printf("Acknowledgment RA:%s ", 56498524Sfenner etheraddr_string(((const struct ctrl_ack_t *)p)->ra)); 56598524Sfenner break; 56698524Sfenner case CTRL_CF_END: 56798524Sfenner if (!TTEST2(*p, CTRL_END_LEN)) 56898524Sfenner return 0; 56998524Sfenner if (eflag) 57098524Sfenner printf("CF-End"); 57198524Sfenner else 57298524Sfenner printf("CF-End RA:%s ", 57398524Sfenner etheraddr_string(((const struct ctrl_end_t *)p)->ra)); 57498524Sfenner break; 57598524Sfenner case CTRL_END_ACK: 57698524Sfenner if (!TTEST2(*p, CTRL_END_ACK_LEN)) 57798524Sfenner return 0; 57898524Sfenner if (eflag) 57998524Sfenner printf("CF-End+CF-Ack"); 58098524Sfenner else 58198524Sfenner printf("CF-End+CF-Ack RA:%s ", 58298524Sfenner etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra)); 58398524Sfenner break; 58498524Sfenner default: 58598524Sfenner printf("(B) Unknown Ctrl Subtype"); 58698524Sfenner } 58798524Sfenner return 1; 58898524Sfenner} 58998524Sfenner 59098524Sfenner 59198524Sfenner 59298524Sfenner/* 59398524Sfenner * Print Header funcs 59498524Sfenner */ 59598524Sfenner 59698524Sfenner/* 59798524Sfenner * Data Frame - Address field contents 59898524Sfenner * 59998524Sfenner * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4 60098524Sfenner * 0 | 0 | DA | SA | BSSID | n/a 60198524Sfenner * 0 | 1 | DA | BSSID | SA | n/a 60298524Sfenner * 1 | 0 | BSSID | SA | DA | n/a 60398524Sfenner * 1 | 1 | RA | TA | DA | SA 60498524Sfenner */ 60598524Sfenner 60698524Sfennerstatic void data_header_print(u_int16_t fc,const u_char *p, u_int length) 60798524Sfenner{ 60898524Sfenner#define ADDR1 (p + 4) 60998524Sfenner#define ADDR2 (p + 10) 61098524Sfenner#define ADDR3 (p + 16) 61198524Sfenner#define ADDR4 (p + 24) 61298524Sfenner 61398524Sfenner if (!FC_TO_DS(fc)) { 61498524Sfenner if (!FC_FROM_DS(fc)) 61598524Sfenner printf("DA:%s SA:%s BSSID:%s ", 61698524Sfenner etheraddr_string(ADDR1), etheraddr_string(ADDR2), 61798524Sfenner etheraddr_string(ADDR3)); 61898524Sfenner else 61998524Sfenner printf("DA:%s BSSID:%s SA:%s ", 62098524Sfenner etheraddr_string(ADDR1), etheraddr_string(ADDR2), 62198524Sfenner etheraddr_string(ADDR3)); 62298524Sfenner } else { 62398524Sfenner if (!FC_FROM_DS(fc)) 62498524Sfenner printf("BSSID:%s SA:%s DA:%s ", 62598524Sfenner etheraddr_string(ADDR1), etheraddr_string(ADDR2), 62698524Sfenner etheraddr_string(ADDR3)); 62798524Sfenner else 62898524Sfenner printf("RA:%s TA:%s DA:%s SA:%s ", 62998524Sfenner etheraddr_string(ADDR1), etheraddr_string(ADDR2), 63098524Sfenner etheraddr_string(ADDR3), etheraddr_string(ADDR4)); 63198524Sfenner } 63298524Sfenner 63398524Sfenner#undef ADDR1 63498524Sfenner#undef ADDR2 63598524Sfenner#undef ADDR3 63698524Sfenner#undef ADDR4 63798524Sfenner} 63898524Sfenner 63998524Sfenner 64098524Sfennerstatic void mgmt_header_print(const u_char *p, u_int length) 64198524Sfenner{ 64298524Sfenner const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; 64398524Sfenner 64498524Sfenner printf("BSSID:%s DA:%s SA:%s ", 64598524Sfenner etheraddr_string((hp)->bssid), etheraddr_string((hp)->da), 64698524Sfenner etheraddr_string((hp)->sa)); 64798524Sfenner} 64898524Sfenner 64998524Sfennerstatic void ctrl_header_print(u_int16_t fc,const u_char *p, u_int length) 65098524Sfenner{ 65198524Sfenner switch (FC_SUBTYPE(fc)) { 65298524Sfenner case CTRL_PS_POLL: 65398524Sfenner printf("BSSID:%s TA:%s ", 65498524Sfenner etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid), 65598524Sfenner etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta)); 65698524Sfenner break; 65798524Sfenner case CTRL_RTS: 65898524Sfenner printf("RA:%s TA:%s ", 65998524Sfenner etheraddr_string(((const struct ctrl_rts_t *)p)->ra), 66098524Sfenner etheraddr_string(((const struct ctrl_rts_t *)p)->ta)); 66198524Sfenner break; 66298524Sfenner case CTRL_CTS: 66398524Sfenner printf("RA:%s ", 66498524Sfenner etheraddr_string(((const struct ctrl_cts_t *)p)->ra)); 66598524Sfenner break; 66698524Sfenner case CTRL_ACK: 66798524Sfenner printf("RA:%s ", 66898524Sfenner etheraddr_string(((const struct ctrl_ack_t *)p)->ra)); 66998524Sfenner break; 67098524Sfenner case CTRL_CF_END: 67198524Sfenner printf("RA:%s BSSID:%s ", 67298524Sfenner etheraddr_string(((const struct ctrl_end_t *)p)->ra), 67398524Sfenner etheraddr_string(((const struct ctrl_end_t *)p)->bssid)); 67498524Sfenner break; 67598524Sfenner case CTRL_END_ACK: 67698524Sfenner printf("RA:%s BSSID:%s ", 67798524Sfenner etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra), 67898524Sfenner etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid)); 67998524Sfenner break; 68098524Sfenner default: 68198524Sfenner printf("(H) Unknown Ctrl Subtype"); 68298524Sfenner } 68398524Sfenner} 68498524Sfenner 68598524Sfennerstatic int GetHeaderLength(u_int16_t fc) 68698524Sfenner{ 68798524Sfenner int iLength=0; 68898524Sfenner 68998524Sfenner switch (FC_TYPE(fc)) { 69098524Sfenner case T_MGMT: 69198524Sfenner iLength = MGMT_HEADER_LEN; 69298524Sfenner break; 69398524Sfenner case T_CTRL: 69498524Sfenner switch (FC_SUBTYPE(fc)) { 69598524Sfenner case CTRL_PS_POLL: 69698524Sfenner iLength = CTRL_PS_POLL_LEN; 69798524Sfenner break; 69898524Sfenner case CTRL_RTS: 69998524Sfenner iLength = CTRL_RTS_LEN; 70098524Sfenner break; 70198524Sfenner case CTRL_CTS: 70298524Sfenner iLength = CTRL_CTS_LEN; 70398524Sfenner break; 70498524Sfenner case CTRL_ACK: 70598524Sfenner iLength = CTRL_ACK_LEN; 70698524Sfenner break; 70798524Sfenner case CTRL_CF_END: 70898524Sfenner iLength = CTRL_END_LEN; 70998524Sfenner break; 71098524Sfenner case CTRL_END_ACK: 71198524Sfenner iLength = CTRL_END_ACK_LEN; 71298524Sfenner break; 71398524Sfenner default: 71498524Sfenner iLength = 0; 71598524Sfenner break; 71698524Sfenner } 71798524Sfenner break; 71898524Sfenner case T_DATA: 71998524Sfenner if (FC_TO_DS(fc) && FC_FROM_DS(fc)) 72098524Sfenner iLength = 30; 72198524Sfenner else 72298524Sfenner iLength = 24; 72398524Sfenner break; 72498524Sfenner default: 72598524Sfenner printf("unknown IEEE802.11 frame type (%d)", 72698524Sfenner FC_TYPE(fc)); 72798524Sfenner break; 72898524Sfenner } 72998524Sfenner 73098524Sfenner return iLength; 73198524Sfenner} 73298524Sfenner 73398524Sfenner/* 73498524Sfenner * Print the 802.11 MAC header 73598524Sfenner */ 73698524Sfennerstatic inline void 73798524Sfennerieee_802_11_print(u_int16_t fc, const u_char *p, u_int length) 73898524Sfenner{ 73998524Sfenner switch (FC_TYPE(fc)) { 74098524Sfenner case T_MGMT: 74198524Sfenner mgmt_header_print(p, length); 74298524Sfenner break; 74398524Sfenner 74498524Sfenner case T_CTRL: 74598524Sfenner ctrl_header_print(fc, p, length); 74698524Sfenner break; 74798524Sfenner 74898524Sfenner case T_DATA: 74998524Sfenner data_header_print(fc, p, length); 75098524Sfenner break; 75198524Sfenner 75298524Sfenner default: 75398524Sfenner printf("(header) unknown IEEE802.11 frame type (%d)", 75498524Sfenner FC_TYPE(fc)); 75598524Sfenner break; 75698524Sfenner } 75798524Sfenner} 75898524Sfenner 75998524Sfenner/* 76098524Sfenner * This is the top level routine of the printer. 'p' is the points 76198524Sfenner * to the ether header of the packet, 'h->tv' is the timestamp, 76298524Sfenner * 'h->length' is the length of the packet off the wire, and 'h->caplen' 76398524Sfenner * is the number of bytes actually captured. 76498524Sfenner */ 76598524Sfennervoid 76698524Sfennerieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 76798524Sfenner{ 76898524Sfenner u_int caplen = h->caplen; 76998524Sfenner u_int length = h->len; 77098524Sfenner u_int16_t fc; 77198524Sfenner u_int HEADER_LENGTH; 77298524Sfenner u_short extracted_ethertype; 77398524Sfenner 77498524Sfenner ++infodelay; 77598524Sfenner ts_print(&h->ts); 77698524Sfenner 77798524Sfenner if (caplen < IEEE802_11_FC_LEN) { 77898524Sfenner printf("[|802.11]"); 77998524Sfenner goto out; 78098524Sfenner } 78198524Sfenner 78298524Sfenner fc=EXTRACT_LE_16BITS(p); 78398524Sfenner 78498524Sfenner if (eflag) 78598524Sfenner ieee_802_11_print(fc, p, length); 78698524Sfenner 78798524Sfenner /* 78898524Sfenner * Some printers want to get back at the ethernet addresses, 78998524Sfenner * and/or check that they're not walking off the end of the packet. 79098524Sfenner * Rather than pass them all the way down, we set these globals. 79198524Sfenner */ 79298524Sfenner packetp = p; 79398524Sfenner snapend = p + caplen; 79498524Sfenner 79598524Sfenner HEADER_LENGTH=GetHeaderLength(fc); 79698524Sfenner 79798524Sfenner length -= HEADER_LENGTH; 79898524Sfenner caplen -= HEADER_LENGTH; 79998524Sfenner p += HEADER_LENGTH; 80098524Sfenner 80198524Sfenner switch (FC_TYPE(fc)) { 80298524Sfenner case T_MGMT: 80398524Sfenner if (!mgmt_body_print(fc, (const struct mgmt_header_t *)packetp, 80498524Sfenner p, length)) { 80598524Sfenner printf("[|802.11]"); 80698524Sfenner goto out; 80798524Sfenner } 80898524Sfenner break; 80998524Sfenner 81098524Sfenner case T_CTRL: 81198524Sfenner if (!ctrl_body_print(fc, p - HEADER_LENGTH, 81298524Sfenner length + HEADER_LENGTH)) { 81398524Sfenner printf("[|802.11]"); 81498524Sfenner goto out; 81598524Sfenner } 81698524Sfenner break; 81798524Sfenner 81898524Sfenner case T_DATA: 81998524Sfenner /* There may be a problem w/ AP not having this bit set */ 82098524Sfenner if (FC_WEP(fc)) { 82198524Sfenner if (!wep_print(p,length)) { 82298524Sfenner printf("[|802.11]"); 82398524Sfenner goto out; 82498524Sfenner } 82598524Sfenner } else { 82698524Sfenner if (llc_print(p, length, caplen, packetp + 10, 82798524Sfenner packetp + 4, &extracted_ethertype) == 0) { 82898524Sfenner /* 82998524Sfenner * Some kinds of LLC packet we cannot 83098524Sfenner * handle intelligently 83198524Sfenner */ 83298524Sfenner if (!eflag) 83398524Sfenner ieee_802_11_print(fc, p - HEADER_LENGTH, 83498524Sfenner length + HEADER_LENGTH); 83598524Sfenner if (extracted_ethertype) { 83698524Sfenner printf("(LLC %s) ", 83798524Sfenner etherproto_string(htons(extracted_ethertype))); 83898524Sfenner } 83998524Sfenner if (!xflag && !qflag) 84098524Sfenner default_print(p, caplen); 84198524Sfenner } 84298524Sfenner } 84398524Sfenner break; 84498524Sfenner 84598524Sfenner default: 84698524Sfenner printf("(body) unhandled IEEE802.11 frame type (%d)", 84798524Sfenner FC_TYPE(fc)); 84898524Sfenner break; 84998524Sfenner } 85098524Sfenner 85198524Sfenner if (xflag) 85298524Sfenner default_print(p, caplen); 85398524Sfenner out: 85498524Sfenner putchar('\n'); 85598524Sfenner --infodelay; 85698524Sfenner if (infoprint) 85798524Sfenner info(0); 85898524Sfenner} 859