X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/9cdc268f1ba479ad39426763781878af9e9b9c8e..ffa1470e5c7ff0e50028d085a481dc797b0b51ed:/print-802_11.c diff --git a/print-802_11.c b/print-802_11.c index b4a1c7e9..891439e0 100644 --- a/print-802_11.c +++ b/print-802_11.c @@ -22,7 +22,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.1 2005-04-20 19:32:41 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.10 2005-11-13 20:23:09 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -46,39 +46,57 @@ static const char rcsid[] _U_ = #include "ieee802_11.h" #include "ieee802_11_radio.h" +#define PRINT_SSID(p) \ + switch (p.ssid_status) { \ + case TRUNCATED: \ + return 0; \ + case PRESENT: \ + printf(" ("); \ + fn_print(p.ssid.ssid, NULL); \ + printf(")"); \ + break; \ + case NOT_PRESENT: \ + break; \ + } + #define PRINT_RATE(_sep, _r, _suf) \ printf("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf) #define PRINT_RATES(p) \ -do { \ - int z; \ - const char *sep = " ["; \ - for (z = 0; z < p.rates.length ; z++) { \ - PRINT_RATE(sep, p.rates.rate[z], \ - (p.rates.rate[z] & 0x80 ? "*" : "")); \ - sep = " "; \ + switch (p.rates_status) { \ + case TRUNCATED: \ + return 0; \ + case PRESENT: \ + do { \ + int z; \ + const char *sep = " ["; \ + for (z = 0; z < p.rates.length ; z++) { \ + PRINT_RATE(sep, p.rates.rate[z], \ + (p.rates.rate[z] & 0x80 ? "*" : "")); \ + sep = " "; \ + } \ + if (p.rates.length != 0) \ + printf(" Mbit]"); \ + } while (0); \ + break; \ + case NOT_PRESENT: \ + break; \ + } + +#define PRINT_DS_CHANNEL(p) \ + switch (p.ds_status) { \ + case TRUNCATED: \ + return 0; \ + case PRESENT: \ + printf(" CH: %u", p.ds.channel); \ + break; \ + case NOT_PRESENT: \ + break; \ } \ - if (p.rates.length != 0) \ - printf(" Mbit]"); \ -} while (0) + printf("%s", \ + CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "" ); static const char *auth_alg_text[]={"Open System","Shared Key","EAP"}; -static const char *subtype_text[]={ - "Assoc Request", - "Assoc Response", - "ReAssoc Request", - "ReAssoc Response", - "Probe Request", - "Probe Response", - "", - "", - "Beacon", - "ATIM", - "Disassociation", - "Authentication", - "DeAuthentication", - "", - "" -}; +#define NUM_AUTH_ALGS (sizeof auth_alg_text / sizeof auth_alg_text[0]) static const char *status_text[] = { "Succesful", /* 0 */ @@ -102,8 +120,8 @@ static const char *status_text[] = { "Association denied because AP is unable to handle additional associated stations", /* 17 */ "Association denied due to requesting station not supporting all of the " \ "data rates in BSSBasicRateSet parameter", /* 18 */ - NULL }; +#define NUM_STATUSES (sizeof status_text / sizeof status_text[0]) static const char *reason_text[] = { "Reserved", /* 0 */ @@ -112,12 +130,12 @@ static const char *reason_text[] = { "Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */ "Disassociated due to inactivity", /* 4 */ "Disassociated because AP is unable to handle all currently associated stations", /* 5 */ - "Class 2 frame receivedfrom nonauthenticated station", /* 6 */ + "Class 2 frame received from nonauthenticated station", /* 6 */ "Class 3 frame received from nonassociated station", /* 7 */ "Disassociated because sending station is leaving (or has left) BSS", /* 8 */ "Station requesting (re)association is not authenticated with responding station", /* 9 */ - NULL }; +#define NUM_REASONS (sizeof reason_text / sizeof reason_text[0]) static int wep_print(const u_char *p) @@ -134,94 +152,141 @@ wep_print(const u_char *p) return 1; } -static int +static void parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset) { + /* + * We haven't seen any elements yet. + */ + pbody->challenge_status = NOT_PRESENT; + pbody->ssid_status = NOT_PRESENT; + pbody->rates_status = NOT_PRESENT; + pbody->ds_status = NOT_PRESENT; + pbody->cf_status = NOT_PRESENT; + pbody->tim_status = NOT_PRESENT; + for (;;) { if (!TTEST2(*(p + offset), 1)) - return 1; + return; switch (*(p + offset)) { case E_SSID: + /* Present, possibly truncated */ + pbody->ssid_status = TRUNCATED; if (!TTEST2(*(p + offset), 2)) - return 0; + return; memcpy(&pbody->ssid, p + offset, 2); offset += 2; - if (pbody->ssid.length <= 0) - break; - if (!TTEST2(*(p + offset), pbody->ssid.length)) - return 0; - memcpy(&pbody->ssid.ssid, p + offset, - pbody->ssid.length); - offset += pbody->ssid.length; + if (pbody->ssid.length != 0) { + if (pbody->ssid.length > + sizeof(pbody->ssid.ssid) - 1) + return; + if (!TTEST2(*(p + offset), pbody->ssid.length)) + return; + memcpy(&pbody->ssid.ssid, p + offset, + pbody->ssid.length); + offset += pbody->ssid.length; + } pbody->ssid.ssid[pbody->ssid.length] = '\0'; + /* Present and not truncated */ + pbody->ssid_status = PRESENT; break; case E_CHALLENGE: + /* Present, possibly truncated */ + pbody->challenge_status = TRUNCATED; if (!TTEST2(*(p + offset), 2)) - return 0; + return; memcpy(&pbody->challenge, p + offset, 2); offset += 2; - if (pbody->challenge.length <= 0) - break; - if (!TTEST2(*(p + offset), pbody->challenge.length)) - return 0; - memcpy(&pbody->challenge.text, p + offset, - pbody->challenge.length); - offset += pbody->challenge.length; + if (pbody->challenge.length != 0) { + if (pbody->challenge.length > + sizeof(pbody->challenge.text) - 1) + return; + if (!TTEST2(*(p + offset), pbody->challenge.length)) + return; + memcpy(&pbody->challenge.text, p + offset, + pbody->challenge.length); + offset += pbody->challenge.length; + } pbody->challenge.text[pbody->challenge.length] = '\0'; + /* Present and not truncated */ + pbody->challenge_status = PRESENT; break; case E_RATES: + /* Present, possibly truncated */ + pbody->rates_status = TRUNCATED; if (!TTEST2(*(p + offset), 2)) - return 0; + return; memcpy(&(pbody->rates), p + offset, 2); offset += 2; - if (pbody->rates.length <= 0) - break; - if (!TTEST2(*(p + offset), pbody->rates.length)) - return 0; - memcpy(&pbody->rates.rate, p + offset, - pbody->rates.length); - offset += pbody->rates.length; + if (pbody->rates.length != 0) { + if (pbody->rates.length > sizeof pbody->rates.rate) + return; + if (!TTEST2(*(p + offset), pbody->rates.length)) + return; + memcpy(&pbody->rates.rate, p + offset, + pbody->rates.length); + offset += pbody->rates.length; + } + /* Present and not truncated */ + pbody->rates_status = PRESENT; break; case E_DS: + /* Present, possibly truncated */ + pbody->ds_status = TRUNCATED; if (!TTEST2(*(p + offset), 3)) - return 0; + return; memcpy(&pbody->ds, p + offset, 3); offset += 3; + /* Present and not truncated */ + pbody->ds_status = PRESENT; break; case E_CF: + /* Present, possibly truncated */ + pbody->cf_status = TRUNCATED; if (!TTEST2(*(p + offset), 8)) - return 0; + return; memcpy(&pbody->cf, p + offset, 8); offset += 8; + /* Present and not truncated */ + pbody->cf_status = PRESENT; break; case E_TIM: + /* Present, possibly truncated */ + pbody->tim_status = TRUNCATED; if (!TTEST2(*(p + offset), 2)) - return 0; + return; memcpy(&pbody->tim, p + offset, 2); offset += 2; if (!TTEST2(*(p + offset), 3)) - return 0; + return; memcpy(&pbody->tim.count, p + offset, 3); offset += 3; if (pbody->tim.length <= 3) break; + if (pbody->rates.length > sizeof pbody->tim.bitmap) + return; if (!TTEST2(*(p + offset), pbody->tim.length - 3)) - return 0; + return; memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3), (pbody->tim.length - 3)); offset += pbody->tim.length - 3; + /* Present and not truncated */ + pbody->tim_status = PRESENT; break; default: #if 0 printf("(1) unhandled element_id (%d) ", *(p + offset) ); #endif + if (!TTEST2(*(p + offset), 2)) + return; + if (!TTEST2(*(p + offset + 2), *(p + offset + 1))) + return; offset += *(p + offset + 1) + 2; break; } } - return 1; } /********************************************************************************* @@ -239,24 +304,20 @@ handle_beacon(const u_char *p) if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + IEEE802_11_CAPINFO_LEN)) return 0; - memcpy(&pbody.timestamp, p, 8); + memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); offset += IEEE802_11_TSTAMP_LEN; pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); offset += IEEE802_11_BCNINT_LEN; pbody.capability_info = EXTRACT_LE_16BITS(p+offset); offset += IEEE802_11_CAPINFO_LEN; - if (!parse_elements(&pbody, p, offset)) - return 0; + parse_elements(&pbody, p, offset); - printf(" ("); - fn_print(pbody.ssid.ssid, NULL); - printf(")"); + PRINT_SSID(pbody); PRINT_RATES(pbody); - printf(" %s CH: %u%s", - CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS", - pbody.ds.channel, - CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" ); + printf(" %s", + CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS"); + PRINT_DS_CHANNEL(pbody); return 1; } @@ -276,12 +337,9 @@ handle_assoc_request(const u_char *p) pbody.listen_interval = EXTRACT_LE_16BITS(p+offset); offset += IEEE802_11_LISTENINT_LEN; - if (!parse_elements(&pbody, p, offset)) - return 0; + parse_elements(&pbody, p, offset); - printf(" ("); - fn_print(pbody.ssid.ssid, NULL); - printf(")"); + PRINT_SSID(pbody); PRINT_RATES(pbody); return 1; } @@ -304,12 +362,13 @@ handle_assoc_response(const u_char *p) pbody.aid = EXTRACT_LE_16BITS(p+offset); offset += IEEE802_11_AID_LEN; - if (!parse_elements(&pbody, p, offset)) - return 0; + parse_elements(&pbody, p, offset); printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 , CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "", - (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a")); + (pbody.status_code < NUM_STATUSES + ? status_text[pbody.status_code] + : "n/a")); return 1; } @@ -332,12 +391,10 @@ handle_reassoc_request(const u_char *p) memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN); offset += IEEE802_11_AP_LEN; - if (!parse_elements(&pbody, p, offset)) - return 0; + parse_elements(&pbody, p, offset); - printf(" ("); - fn_print(pbody.ssid.ssid, NULL); - printf(") AP : %s", etheraddr_string( pbody.ap )); + PRINT_SSID(pbody); + printf(" AP : %s", etheraddr_string( pbody.ap )); return 1; } @@ -357,12 +414,9 @@ handle_probe_request(const u_char *p) memset(&pbody, 0, sizeof(pbody)); - if (!parse_elements(&pbody, p, offset)) - return 0; + parse_elements(&pbody, p, offset); - printf(" ("); - fn_print(pbody.ssid.ssid, NULL); - printf(")"); + PRINT_SSID(pbody); PRINT_RATES(pbody); return 1; @@ -387,15 +441,11 @@ handle_probe_response(const u_char *p) pbody.capability_info = EXTRACT_LE_16BITS(p+offset); offset += IEEE802_11_CAPINFO_LEN; - if (!parse_elements(&pbody, p, offset)) - return 0; + parse_elements(&pbody, p, offset); - printf(" ("); - fn_print(pbody.ssid.ssid, NULL); - printf(") "); + PRINT_SSID(pbody); PRINT_RATES(pbody); - printf(" CH: %u%s", pbody.ds.channel, - CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" ); + PRINT_DS_CHANNEL(pbody); return 1; } @@ -419,8 +469,9 @@ handle_disassoc(const u_char *p) pbody.reason_code = EXTRACT_LE_16BITS(p); printf(": %s", - (pbody.reason_code < 10) ? reason_text[pbody.reason_code] - : "Reserved" ); + (pbody.reason_code < NUM_REASONS) + ? reason_text[pbody.reason_code] + : "Reserved" ); return 1; } @@ -442,28 +493,31 @@ handle_auth(const u_char *p) pbody.status_code = EXTRACT_LE_16BITS(p + offset); offset += 2; - if (!parse_elements(&pbody, p, offset)) - return 0; + parse_elements(&pbody, p, offset); if ((pbody.auth_alg == 1) && ((pbody.auth_trans_seq_num == 2) || (pbody.auth_trans_seq_num == 3))) { printf(" (%s)-%x [Challenge Text] %s", - (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg] - : "Reserved", + (pbody.auth_alg < NUM_AUTH_ALGS) + ? auth_alg_text[pbody.auth_alg] + : "Reserved", pbody.auth_trans_seq_num, ((pbody.auth_trans_seq_num % 2) - ? ((pbody.status_code < 19) + ? ((pbody.status_code < NUM_STATUSES) ? status_text[pbody.status_code] : "n/a") : "")); return 1; } printf(" (%s)-%x: %s", - (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg] : "Reserved", + (pbody.auth_alg < NUM_AUTH_ALGS) + ? auth_alg_text[pbody.auth_alg] + : "Reserved", pbody.auth_trans_seq_num, (pbody.auth_trans_seq_num % 2) - ? ((pbody.status_code < 19) ? status_text[pbody.status_code] - : "n/a") + ? ((pbody.status_code < NUM_STATUSES) + ? status_text[pbody.status_code] + : "n/a") : ""); return 1; @@ -483,8 +537,9 @@ handle_deauth(const struct mgmt_header_t *pmh, const u_char *p) pbody.reason_code = EXTRACT_LE_16BITS(p); offset += IEEE802_11_REASON_LEN; - reason = (pbody.reason_code < 10) ? reason_text[pbody.reason_code] - : "Reserved"; + reason = (pbody.reason_code < NUM_REASONS) + ? reason_text[pbody.reason_code] + : "Reserved"; if (eflag) { printf(": %s", reason); @@ -504,28 +559,36 @@ static int mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh, const u_char *p) { - printf("%s", subtype_text[FC_SUBTYPE(fc)]); - switch (FC_SUBTYPE(fc)) { case ST_ASSOC_REQUEST: + printf("Assoc Request"); return handle_assoc_request(p); case ST_ASSOC_RESPONSE: + printf("Assoc Response"); return handle_assoc_response(p); case ST_REASSOC_REQUEST: + printf("ReAssoc Request"); return handle_reassoc_request(p); case ST_REASSOC_RESPONSE: + printf("ReAssoc Response"); return handle_reassoc_response(p); case ST_PROBE_REQUEST: + printf("Probe Request"); return handle_probe_request(p); case ST_PROBE_RESPONSE: + printf("Probe Response"); return handle_probe_response(p); case ST_BEACON: + printf("Beacon"); return handle_beacon(p); case ST_ATIM: + printf("ATIM"); return handle_atim(); case ST_DISASSOC: + printf("Disassociation"); return handle_disassoc(p); case ST_AUTH: + printf("Authentication"); if (!TTEST2(*p, 3)) return 0; if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) { @@ -534,6 +597,7 @@ mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh, } return handle_auth(p); case ST_DEAUTH: + printf("DeAuthentication"); return handle_deauth(pmh, p); break; default: @@ -900,7 +964,7 @@ ieee802_11_print(const u_char *p, u_int length, u_int caplen) printf("(LLC %s) ", etherproto_string( htons(extracted_ethertype))); - if (!xflag && !qflag) + if (!suppress_default_print) default_print(p, caplen); } break;