diff options
author | bms <bms@FreeBSD.org> | 2004-03-31 09:17:26 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2004-03-31 09:17:26 +0000 |
commit | 281e9d71408deb6e8c5046c746c2e97002b0e7fe (patch) | |
tree | eb08e08f0f875c3b16f8e1aec86091f100906f1c /contrib/tcpdump/print-802_11.c | |
parent | be6faec6d07fc3a2a54836e76d0309c36192dfad (diff) | |
download | FreeBSD-src-281e9d71408deb6e8c5046c746c2e97002b0e7fe.zip FreeBSD-src-281e9d71408deb6e8c5046c746c2e97002b0e7fe.tar.gz |
Import tcpdump 3.8.3, from http://www.tcpdump.org/releases/tcpdump-3.8.3.tar.gz
Diffstat (limited to 'contrib/tcpdump/print-802_11.c')
-rw-r--r-- | contrib/tcpdump/print-802_11.c | 781 |
1 files changed, 463 insertions, 318 deletions
diff --git a/contrib/tcpdump/print-802_11.c b/contrib/tcpdump/print-802_11.c index b8c03d8..56462c9 100644 --- a/contrib/tcpdump/print-802_11.c +++ b/contrib/tcpdump/print-802_11.c @@ -21,19 +21,15 @@ */ #ifndef lint -static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.6.4.1 2002/05/13 08:34:50 guy Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.22.2.6 2003/12/10 09:52:33 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include <sys/param.h> -#include <sys/time.h> -#include <sys/socket.h> - -#include <netinet/in.h> +#include <tcpdump-stdinc.h> #include <stdio.h> #include <pcap.h> @@ -50,9 +46,10 @@ static const char rcsid[] = #define PRINT_RATES(p) \ do { \ int z; \ - char *sep = " ["; \ + const char *sep = " ["; \ for (z = 0; z < p.rates.length ; z++) { \ printf("%s%2.1f", sep, (.5 * (p.rates.rate[z] & 0x7f))); \ + if (p.rates.rate[z] & 0x80) printf("*"); \ sep = " "; \ } \ if (p.rates.length != 0) \ @@ -67,15 +64,15 @@ static const char *subtype_text[]={ "ReAssoc Response", "Probe Request", "Probe Response", - "RESERVED", - "RESERVED", + "", + "", "Beacon", "ATIM", "Disassociation", "Authentication", "DeAuthentication", - "RESERVED", - "RESERVED" + "", + "" }; static const char *status_text[] = { @@ -117,11 +114,12 @@ static const char *reason_text[] = { NULL }; -static int wep_print(const u_char *p,u_int length) +static int +wep_print(const u_char *p) { u_int32_t iv; - if (!TTEST2(*p, 4)) + if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN)) return 0; iv = EXTRACT_LE_32BITS(p); @@ -131,79 +129,90 @@ static int wep_print(const u_char *p,u_int length) return 1; } - -static int parse_elements(struct mgmt_body_t *pbody,const u_char *p,int offset) +static int +parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset) { for (;;) { if (!TTEST2(*(p + offset), 1)) return 1; switch (*(p + offset)) { case E_SSID: - if (!TTEST2(*(p+offset), 2)) + if (!TTEST2(*(p + offset), 2)) return 0; - memcpy(&(pbody->ssid),p+offset,2); offset += 2; - if (pbody->ssid.length > 0) - { - if (!TTEST2(*(p+offset), pbody->ssid.length)) - return 0; - memcpy(&(pbody->ssid.ssid),p+offset,pbody->ssid.length); offset += pbody->ssid.length; - pbody->ssid.ssid[pbody->ssid.length]='\0'; - } + 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; + pbody->ssid.ssid[pbody->ssid.length] = '\0'; break; case E_CHALLENGE: - if (!TTEST2(*(p+offset), 2)) + if (!TTEST2(*(p + offset), 2)) return 0; - memcpy(&(pbody->challenge),p+offset,2); offset += 2; - if (pbody->challenge.length > 0) - { - if (!TTEST2(*(p+offset), pbody->challenge.length)) - return 0; - memcpy(&(pbody->challenge.text),p+offset,pbody->challenge.length); offset += pbody->challenge.length; - pbody->challenge.text[pbody->challenge.length]='\0'; - } + 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; + pbody->challenge.text[pbody->challenge.length] = '\0'; break; case E_RATES: - if (!TTEST2(*(p+offset), 2)) + if (!TTEST2(*(p + offset), 2)) return 0; - memcpy(&(pbody->rates),p+offset,2); offset += 2; - if (pbody->rates.length > 0) { - if (!TTEST2(*(p+offset), pbody->rates.length)) - return 0; - memcpy(&(pbody->rates.rate),p+offset,pbody->rates.length); offset += pbody->rates.length; - } + 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; break; case E_DS: - if (!TTEST2(*(p+offset), 3)) + if (!TTEST2(*(p + offset), 3)) return 0; - memcpy(&(pbody->ds),p+offset,3); offset +=3; + memcpy(&pbody->ds, p + offset, 3); + offset += 3; break; case E_CF: - if (!TTEST2(*(p+offset), 8)) + if (!TTEST2(*(p + offset), 8)) return 0; - memcpy(&(pbody->cf),p+offset,8); offset +=8; + memcpy(&pbody->cf, p + offset, 8); + offset += 8; break; case E_TIM: - if (!TTEST2(*(p+offset), 2)) + if (!TTEST2(*(p + offset), 2)) return 0; - memcpy(&(pbody->tim),p+offset,2); offset +=2; - if (!TTEST2(*(p+offset), 3)) + memcpy(&pbody->tim, p + offset, 2); + offset += 2; + if (!TTEST2(*(p + offset), 3)) return 0; - memcpy(&(pbody->tim.count),p+offset,3); offset +=3; - - if ((pbody->tim.length -3) > 0) - { - if (!TTEST2(*(p+offset), pbody->tim.length -3)) - return 0; - memcpy((pbody->tim.bitmap),p+(pbody->tim.length -3),(pbody->tim.length -3)); - offset += pbody->tim.length -3; - } + memcpy(&pbody->tim.count, p + offset, 3); + offset += 3; + if (pbody->tim.length <= 3) + break; + if (!TTEST2(*(p + offset), pbody->tim.length - 3)) + return 0; + memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3), + (pbody->tim.length - 3)); + offset += pbody->tim.length - 3; break; default: #if 0 - printf("(1) unhandled element_id (%d) ", *(p+offset) ); + printf("(1) unhandled element_id (%d) ", + *(p + offset) ); #endif - offset+= *(p+offset+1) + 2; + offset += *(p + offset + 1) + 2; break; } } @@ -214,31 +223,32 @@ static int parse_elements(struct mgmt_body_t *pbody,const u_char *p,int offset) * Print Handle functions for the management frame types *********************************************************************************/ -static int handle_beacon(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_beacon(const u_char *p) { struct mgmt_body_t pbody; int offset = 0; memset(&pbody, 0, sizeof(pbody)); - if (!TTEST2(*p, 12)) + if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + + IEEE802_11_CAPINFO_LEN)) return 0; memcpy(&pbody.timestamp, p, 8); - offset += 8; + offset += IEEE802_11_TSTAMP_LEN; pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); - offset += 2; + offset += IEEE802_11_BCNINT_LEN; pbody.capability_info = EXTRACT_LE_16BITS(p+offset); - offset += 2; + offset += IEEE802_11_CAPINFO_LEN; - if (!parse_elements(&pbody,p,offset)) + if (!parse_elements(&pbody, p, offset)) return 0; - printf("%s (", subtype_text[FC_SUBTYPE(fc)]); + printf(" ("); fn_print(pbody.ssid.ssid, NULL); printf(")"); PRINT_RATES(pbody); - printf(" %s CH: %u %s", + printf(" %s CH: %u%s", CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS", pbody.ds.channel, CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" ); @@ -246,96 +256,96 @@ static int handle_beacon(u_int16_t fc, const struct mgmt_header_t *pmh, return 1; } -static int handle_assoc_request(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_assoc_request(const u_char *p) { struct mgmt_body_t pbody; int offset = 0; memset(&pbody, 0, sizeof(pbody)); - if (!TTEST2(*p, 4)) + if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)) return 0; pbody.capability_info = EXTRACT_LE_16BITS(p); - offset += 2; + offset += IEEE802_11_CAPINFO_LEN; pbody.listen_interval = EXTRACT_LE_16BITS(p+offset); - offset += 2; + offset += IEEE802_11_LISTENINT_LEN; - if (!parse_elements(&pbody,p,offset)) + if (!parse_elements(&pbody, p, offset)) return 0; - printf("%s (", subtype_text[FC_SUBTYPE(fc)]); + printf(" ("); fn_print(pbody.ssid.ssid, NULL); printf(")"); PRINT_RATES(pbody); return 1; } -static int handle_assoc_response(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_assoc_response(const u_char *p) { struct mgmt_body_t pbody; int offset = 0; memset(&pbody, 0, sizeof(pbody)); - if (!TTEST2(*p, 6)) + if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + + IEEE802_11_AID_LEN)) return 0; pbody.capability_info = EXTRACT_LE_16BITS(p); - offset += 2; + offset += IEEE802_11_CAPINFO_LEN; pbody.status_code = EXTRACT_LE_16BITS(p+offset); - offset += 2; + offset += IEEE802_11_STATUS_LEN; pbody.aid = EXTRACT_LE_16BITS(p+offset); - offset += 2; + offset += IEEE802_11_AID_LEN; - if (!parse_elements(&pbody,p,offset)) + if (!parse_elements(&pbody, p, offset)) return 0; - printf("%s AID(%x) :%s: %s", subtype_text[FC_SUBTYPE(fc)], - ((u_int16_t)(pbody.aid << 2 )) >> 2 , + 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")); return 1; } - -static int handle_reassoc_request(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_reassoc_request(const u_char *p) { struct mgmt_body_t pbody; int offset = 0; memset(&pbody, 0, sizeof(pbody)); - if (!TTEST2(*p, 10)) + if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + + IEEE802_11_AP_LEN)) return 0; pbody.capability_info = EXTRACT_LE_16BITS(p); - offset += 2; + offset += IEEE802_11_CAPINFO_LEN; pbody.listen_interval = EXTRACT_LE_16BITS(p+offset); - offset += 2; - memcpy(&pbody.ap,p+offset,6); - offset += 6; + offset += IEEE802_11_LISTENINT_LEN; + memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN); + offset += IEEE802_11_AP_LEN; - if (!parse_elements(&pbody,p,offset)) + if (!parse_elements(&pbody, p, offset)) return 0; - printf("%s (", subtype_text[FC_SUBTYPE(fc)]); + printf(" ("); fn_print(pbody.ssid.ssid, NULL); printf(") AP : %s", etheraddr_string( pbody.ap )); return 1; } -static int handle_reassoc_response(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_reassoc_response(const u_char *p) { /* Same as a Association Reponse */ - return handle_assoc_response(fc,pmh,p); + return handle_assoc_response(p); } -static int handle_probe_request(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_probe_request(const u_char *p) { struct mgmt_body_t pbody; int offset = 0; @@ -345,7 +355,7 @@ static int handle_probe_request(u_int16_t fc, const struct mgmt_header_t *pmh, if (!parse_elements(&pbody, p, offset)) return 0; - printf("%s (", subtype_text[FC_SUBTYPE(fc)]); + printf(" ("); fn_print(pbody.ssid.ssid, NULL); printf(")"); PRINT_RATES(pbody); @@ -353,27 +363,29 @@ static int handle_probe_request(u_int16_t fc, const struct mgmt_header_t *pmh, return 1; } -static int handle_probe_response(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_probe_response(const u_char *p) { struct mgmt_body_t pbody; int offset = 0; memset(&pbody, 0, sizeof(pbody)); - if (!TTEST2(*p, 12)) + if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + + IEEE802_11_CAPINFO_LEN)) return 0; - memcpy(&pbody.timestamp,p,8); - offset += 8; + + memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); + offset += IEEE802_11_TSTAMP_LEN; pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset); - offset += 2; + offset += IEEE802_11_BCNINT_LEN; pbody.capability_info = EXTRACT_LE_16BITS(p+offset); - offset += 2; + offset += IEEE802_11_CAPINFO_LEN; if (!parse_elements(&pbody, p, offset)) return 0; - printf("%s (", subtype_text[FC_SUBTYPE(fc)]); + printf(" ("); fn_print(pbody.ssid.ssid, NULL); printf(") "); PRINT_RATES(pbody); @@ -383,35 +395,33 @@ static int handle_probe_response(u_int16_t fc, const struct mgmt_header_t *pmh, return 1; } -static int handle_atim(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_atim(void) { /* the frame body for ATIM is null. */ - printf("ATIM"); return 1; } -static int handle_disassoc(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_disassoc(const u_char *p) { struct mgmt_body_t pbody; - int offset = 0; memset(&pbody, 0, sizeof(pbody)); - if (!TTEST2(*p, 2)) + if (!TTEST2(*p, IEEE802_11_REASON_LEN)) return 0; pbody.reason_code = EXTRACT_LE_16BITS(p); - offset += 2; - printf("%s: %s", subtype_text[FC_SUBTYPE(fc)], - pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" ); + printf(": %s", + (pbody.reason_code < 10) ? reason_text[pbody.reason_code] + : "Reserved" ); return 1; } -static int handle_auth(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_auth(const u_char *p) { struct mgmt_body_t pbody; int offset = 0; @@ -427,51 +437,55 @@ static int handle_auth(u_int16_t fc, const struct mgmt_header_t *pmh, pbody.status_code = EXTRACT_LE_16BITS(p + offset); offset += 2; - if (!parse_elements(&pbody,p,offset)) + if (!parse_elements(&pbody, p, offset)) return 0; if ((pbody.auth_alg == 1) && - ((pbody.auth_trans_seq_num == 2) || (pbody.auth_trans_seq_num == 3))) { - printf("%s (%s)-%x [Challenge Text] %s", - subtype_text[FC_SUBTYPE(fc)], - pbody.auth_alg < 4 ? 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") : "" )); - } else { - printf("%s (%s)-%x: %s", - subtype_text[FC_SUBTYPE(fc)], - pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" , + ((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_trans_seq_num, - ((pbody.auth_trans_seq_num % 2) ? (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a") : "")); + ((pbody.auth_trans_seq_num % 2) + ? ((pbody.status_code < 19) + ? 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_trans_seq_num, + (pbody.auth_trans_seq_num % 2) + ? ((pbody.status_code < 19) ? status_text[pbody.status_code] + : "n/a") + : ""); return 1; } -static int handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p) +static int +handle_deauth(const struct mgmt_header_t *pmh, const u_char *p) { struct mgmt_body_t pbody; int offset = 0; + const char *reason = NULL; memset(&pbody, 0, sizeof(pbody)); - if (!TTEST2(*p, 2)) + if (!TTEST2(*p, IEEE802_11_REASON_LEN)) return 0; pbody.reason_code = EXTRACT_LE_16BITS(p); - offset += 2; + offset += IEEE802_11_REASON_LEN; + + reason = (pbody.reason_code < 10) ? reason_text[pbody.reason_code] + : "Reserved"; if (eflag) { - printf("%s: %s", - subtype_text[FC_SUBTYPE(fc)], - pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" ); + printf(": %s", reason); } else { - printf("%s (%s): %s", - subtype_text[FC_SUBTYPE(fc)], etheraddr_string(pmh->sa), - pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" ); + printf(" (%s): %s", etheraddr_string(pmh->sa), reason); } - return 1; } @@ -481,42 +495,44 @@ static int handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh, *********************************************************************************/ -static int mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh, - const u_char *p, u_int length) +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: - return (handle_assoc_request(fc, pmh, p)); + return handle_assoc_request(p); case ST_ASSOC_RESPONSE: - return (handle_assoc_response(fc, pmh, p)); + return handle_assoc_response(p); case ST_REASSOC_REQUEST: - return (handle_reassoc_request(fc, pmh, p)); + return handle_reassoc_request(p); case ST_REASSOC_RESPONSE: - return (handle_reassoc_response(fc, pmh, p)); + return handle_reassoc_response(p); case ST_PROBE_REQUEST: - return (handle_probe_request(fc, pmh, p)); + return handle_probe_request(p); case ST_PROBE_RESPONSE: - return (handle_probe_response(fc, pmh, p)); + return handle_probe_response(p); case ST_BEACON: - return (handle_beacon(fc, pmh, p)); + return handle_beacon(p); case ST_ATIM: - return (handle_atim(fc, pmh, p)); + return handle_atim(); case ST_DISASSOC: - return (handle_disassoc(fc, pmh, p)); + return handle_disassoc(p); case ST_AUTH: if (!TTEST2(*p, 3)) return 0; if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) { printf("Authentication (Shared-Key)-3 "); - return (wep_print(p, length)); + return wep_print(p); } - else - return (handle_auth(fc, pmh, p)); + return handle_auth(p); case ST_DEAUTH: - return (handle_deauth(fc, pmh, p)); + return handle_deauth(pmh, p); break; default: - printf("Unhandled Managment subtype(%x)", + printf("Unhandled Management subtype(%x)", FC_SUBTYPE(fc)); return 1; } @@ -527,68 +543,63 @@ static int mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh, * Handles printing all the control frame types *********************************************************************************/ -static int ctrl_body_print(u_int16_t fc,const u_char *p, u_int length) +static int +ctrl_body_print(u_int16_t fc, const u_char *p) { switch (FC_SUBTYPE(fc)) { case CTRL_PS_POLL: - if (!TTEST2(*p, CTRL_PS_POLL_LEN)) + printf("Power Save-Poll"); + if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN)) return 0; - printf("Power Save-Poll AID(%x)", + printf(" AID(%x)", EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid))); break; case CTRL_RTS: - if (!TTEST2(*p, CTRL_RTS_LEN)) + printf("Request-To-Send"); + if (!TTEST2(*p, CTRL_RTS_HDRLEN)) return 0; - if (eflag) - printf("Request-To-Send"); - else - printf("Request-To-Send TA:%s ", + if (!eflag) + printf(" TA:%s ", etheraddr_string(((const struct ctrl_rts_t *)p)->ta)); break; case CTRL_CTS: - if (!TTEST2(*p, CTRL_CTS_LEN)) + printf("Clear-To-Send"); + if (!TTEST2(*p, CTRL_CTS_HDRLEN)) return 0; - if (eflag) - printf("Clear-To-Send"); - else - printf("Clear-To-Send RA:%s ", + if (!eflag) + printf(" RA:%s ", etheraddr_string(((const struct ctrl_cts_t *)p)->ra)); break; case CTRL_ACK: - if (!TTEST2(*p, CTRL_ACK_LEN)) + printf("Acknowledgment"); + if (!TTEST2(*p, CTRL_ACK_HDRLEN)) return 0; - if (eflag) - printf("Acknowledgment"); - else - printf("Acknowledgment RA:%s ", + if (!eflag) + printf(" RA:%s ", etheraddr_string(((const struct ctrl_ack_t *)p)->ra)); break; case CTRL_CF_END: - if (!TTEST2(*p, CTRL_END_LEN)) + printf("CF-End"); + if (!TTEST2(*p, CTRL_END_HDRLEN)) return 0; - if (eflag) - printf("CF-End"); - else - printf("CF-End RA:%s ", + if (!eflag) + printf(" RA:%s ", etheraddr_string(((const struct ctrl_end_t *)p)->ra)); break; case CTRL_END_ACK: - if (!TTEST2(*p, CTRL_END_ACK_LEN)) + printf("CF-End+CF-Ack"); + if (!TTEST2(*p, CTRL_END_ACK_HDRLEN)) return 0; - if (eflag) - printf("CF-End+CF-Ack"); - else - printf("CF-End+CF-Ack RA:%s ", + if (!eflag) + printf(" RA:%s ", etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra)); break; default: - printf("(B) Unknown Ctrl Subtype"); + printf("Unknown Ctrl Subtype"); } return 1; } - - /* * Print Header funcs */ @@ -603,31 +614,73 @@ static int ctrl_body_print(u_int16_t fc,const u_char *p, u_int length) * 1 | 1 | RA | TA | DA | SA */ -static void data_header_print(u_int16_t fc,const u_char *p, u_int length) +static void +data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp, + const u_int8_t **dstp) { + switch (FC_SUBTYPE(fc)) { + case DATA_DATA: + case DATA_NODATA: + break; + case DATA_DATA_CF_ACK: + case DATA_NODATA_CF_ACK: + printf("CF Ack "); + break; + case DATA_DATA_CF_POLL: + case DATA_NODATA_CF_POLL: + printf("CF Poll "); + break; + case DATA_DATA_CF_ACK_POLL: + case DATA_NODATA_CF_ACK_POLL: + printf("CF Ack/Poll "); + break; + } + #define ADDR1 (p + 4) #define ADDR2 (p + 10) #define ADDR3 (p + 16) #define ADDR4 (p + 24) - if (!FC_TO_DS(fc)) { - if (!FC_FROM_DS(fc)) - printf("DA:%s SA:%s BSSID:%s ", - etheraddr_string(ADDR1), etheraddr_string(ADDR2), - etheraddr_string(ADDR3)); - else - printf("DA:%s BSSID:%s SA:%s ", - etheraddr_string(ADDR1), etheraddr_string(ADDR2), - etheraddr_string(ADDR3)); - } else { - if (!FC_FROM_DS(fc)) - printf("BSSID:%s SA:%s DA:%s ", - etheraddr_string(ADDR1), etheraddr_string(ADDR2), - etheraddr_string(ADDR3)); - else - printf("RA:%s TA:%s DA:%s SA:%s ", - etheraddr_string(ADDR1), etheraddr_string(ADDR2), - etheraddr_string(ADDR3), etheraddr_string(ADDR4)); + if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) { + if (srcp != NULL) + *srcp = ADDR2; + if (dstp != NULL) + *dstp = ADDR1; + if (!eflag) + return; + printf("DA:%s SA:%s BSSID:%s ", + etheraddr_string(ADDR1), etheraddr_string(ADDR2), + etheraddr_string(ADDR3)); + } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) { + if (srcp != NULL) + *srcp = ADDR3; + if (dstp != NULL) + *dstp = ADDR1; + if (!eflag) + return; + printf("DA:%s BSSID:%s SA:%s ", + etheraddr_string(ADDR1), etheraddr_string(ADDR2), + etheraddr_string(ADDR3)); + } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) { + if (srcp != NULL) + *srcp = ADDR2; + if (dstp != NULL) + *dstp = ADDR3; + if (!eflag) + return; + printf("BSSID:%s SA:%s DA:%s ", + etheraddr_string(ADDR1), etheraddr_string(ADDR2), + etheraddr_string(ADDR3)); + } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) { + if (srcp != NULL) + *srcp = ADDR4; + if (dstp != NULL) + *dstp = ADDR3; + if (!eflag) + return; + printf("RA:%s TA:%s DA:%s SA:%s ", + etheraddr_string(ADDR1), etheraddr_string(ADDR2), + etheraddr_string(ADDR3), etheraddr_string(ADDR4)); } #undef ADDR1 @@ -636,18 +689,35 @@ static void data_header_print(u_int16_t fc,const u_char *p, u_int length) #undef ADDR4 } - -static void mgmt_header_print(const u_char *p, u_int length) +static void +mgmt_header_print(const u_char *p, const u_int8_t **srcp, + const u_int8_t **dstp) { const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; + if (srcp != NULL) + *srcp = hp->sa; + if (dstp != NULL) + *dstp = hp->da; + if (!eflag) + return; + printf("BSSID:%s DA:%s SA:%s ", etheraddr_string((hp)->bssid), etheraddr_string((hp)->da), etheraddr_string((hp)->sa)); } -static void ctrl_header_print(u_int16_t fc,const u_char *p, u_int length) +static void +ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp, + const u_int8_t **dstp) { + if (srcp != NULL) + *srcp = NULL; + if (dstp != NULL) + *dstp = NULL; + if (!eflag) + return; + switch (FC_SUBTYPE(fc)) { case CTRL_PS_POLL: printf("BSSID:%s TA:%s ", @@ -679,180 +749,255 @@ static void ctrl_header_print(u_int16_t fc,const u_char *p, u_int length) break; default: printf("(H) Unknown Ctrl Subtype"); + break; } } -static int GetHeaderLength(u_int16_t fc) +static int +extract_header_length(u_int16_t fc) { - int iLength=0; - switch (FC_TYPE(fc)) { case T_MGMT: - iLength = MGMT_HEADER_LEN; - break; + return MGMT_HDRLEN; case T_CTRL: switch (FC_SUBTYPE(fc)) { case CTRL_PS_POLL: - iLength = CTRL_PS_POLL_LEN; - break; + return CTRL_PS_POLL_HDRLEN; case CTRL_RTS: - iLength = CTRL_RTS_LEN; - break; + return CTRL_RTS_HDRLEN; case CTRL_CTS: - iLength = CTRL_CTS_LEN; - break; + return CTRL_CTS_HDRLEN; case CTRL_ACK: - iLength = CTRL_ACK_LEN; - break; + return CTRL_ACK_HDRLEN; case CTRL_CF_END: - iLength = CTRL_END_LEN; - break; + return CTRL_END_HDRLEN; case CTRL_END_ACK: - iLength = CTRL_END_ACK_LEN; - break; + return CTRL_END_ACK_HDRLEN; default: - iLength = 0; - break; + return 0; } - break; case T_DATA: - if (FC_TO_DS(fc) && FC_FROM_DS(fc)) - iLength = 30; - else - iLength = 24; - break; + return (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24; default: - printf("unknown IEEE802.11 frame type (%d)", - FC_TYPE(fc)); - break; + printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc)); + return 0; } - - return iLength; } /* - * Print the 802.11 MAC header + * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp" + * to point to the source and destination MAC addresses in any case if + * "srcp" and "dstp" aren't null. */ static inline void -ieee_802_11_print(u_int16_t fc, const u_char *p, u_int length) +ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp, + const u_int8_t **dstp) { + if (vflag) { + if (FC_MORE_DATA(fc)) + printf("More Data "); + if (FC_MORE_FLAG(fc)) + printf("More Fragments "); + if (FC_POWER_MGMT(fc)) + printf("Pwr Mgmt "); + if (FC_RETRY(fc)) + printf("Retry "); + if (FC_ORDER(fc)) + printf("Strictly Ordered "); + if (FC_WEP(fc)) + printf("WEP Encrypted "); + if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL) + printf("%dus ", + EXTRACT_LE_16BITS( + &((const struct mgmt_header_t *)p)->duration)); + } + switch (FC_TYPE(fc)) { case T_MGMT: - mgmt_header_print(p, length); + mgmt_header_print(p, srcp, dstp); break; - case T_CTRL: - ctrl_header_print(fc, p, length); + ctrl_header_print(fc, p, srcp, dstp); break; - case T_DATA: - data_header_print(fc, p, length); + data_header_print(fc, p, srcp, dstp); break; - default: printf("(header) unknown IEEE802.11 frame type (%d)", FC_TYPE(fc)); + *srcp = NULL; + *dstp = NULL; break; } } -/* - * This is the top level routine of the printer. 'p' is the points - * to the ether header of the packet, 'h->tv' is the timestamp, - * 'h->length' is the length of the packet off the wire, and 'h->caplen' - * is the number of bytes actually captured. - */ -void -ieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +static u_int +ieee802_11_print(const u_char *p, u_int length, u_int caplen) { - u_int caplen = h->caplen; - u_int length = h->len; u_int16_t fc; - u_int HEADER_LENGTH; + u_int hdrlen; + const u_int8_t *src, *dst; u_short extracted_ethertype; - ++infodelay; - ts_print(&h->ts); - if (caplen < IEEE802_11_FC_LEN) { printf("[|802.11]"); - goto out; + return caplen; } - fc=EXTRACT_LE_16BITS(p); + fc = EXTRACT_LE_16BITS(p); + hdrlen = extract_header_length(fc); - if (eflag) - ieee_802_11_print(fc, p, length); + if (caplen < hdrlen) { + printf("[|802.11]"); + return hdrlen; + } + + ieee_802_11_hdr_print(fc, p, &src, &dst); /* - * Some printers want to get back at the ethernet addresses, - * and/or check that they're not walking off the end of the packet. - * Rather than pass them all the way down, we set these globals. + * Go past the 802.11 header. */ - packetp = p; - snapend = p + caplen; - - HEADER_LENGTH=GetHeaderLength(fc); - - length -= HEADER_LENGTH; - caplen -= HEADER_LENGTH; - p += HEADER_LENGTH; + length -= hdrlen; + caplen -= hdrlen; + p += hdrlen; switch (FC_TYPE(fc)) { case T_MGMT: - if (!mgmt_body_print(fc, (const struct mgmt_header_t *)packetp, - p, length)) { + if (!mgmt_body_print(fc, + (const struct mgmt_header_t *)(p - hdrlen), p)) { printf("[|802.11]"); - goto out; + return hdrlen; } break; - case T_CTRL: - if (!ctrl_body_print(fc, p - HEADER_LENGTH, - length + HEADER_LENGTH)) { + if (!ctrl_body_print(fc, p - hdrlen)) { printf("[|802.11]"); - goto out; + return hdrlen; } break; - case T_DATA: /* There may be a problem w/ AP not having this bit set */ - if (FC_WEP(fc)) { - if (!wep_print(p,length)) { + if (FC_WEP(fc)) { + if (!wep_print(p)) { printf("[|802.11]"); - goto out; - } - } else { - if (llc_print(p, length, caplen, packetp + 10, - packetp + 4, &extracted_ethertype) == 0) { - /* - * Some kinds of LLC packet we cannot - * handle intelligently - */ - if (!eflag) - ieee_802_11_print(fc, p - HEADER_LENGTH, - length + HEADER_LENGTH); - if (extracted_ethertype) { - printf("(LLC %s) ", - etherproto_string(htons(extracted_ethertype))); - } - if (!xflag && !qflag) - default_print(p, caplen); + return hdrlen; } + } else if (llc_print(p, length, caplen, dst, src, + &extracted_ethertype) == 0) { + /* + * Some kinds of LLC packet we cannot + * handle intelligently + */ + if (!eflag) + ieee_802_11_hdr_print(fc, p - hdrlen, NULL, + NULL); + if (extracted_ethertype) + printf("(LLC %s) ", + etherproto_string( + htons(extracted_ethertype))); + if (!xflag && !qflag) + default_print(p, caplen); } break; - default: - printf("(body) unhandled IEEE802.11 frame type (%d)", - FC_TYPE(fc)); + printf("unknown 802.11 frame type (%d)", FC_TYPE(fc)); break; } - if (xflag) - default_print(p, caplen); - out: - putchar('\n'); - --infodelay; - if (infoprint) - info(0); + return hdrlen; +} + +/* + * This is the top level routine of the printer. 'p' points + * to the 802.11 header of the packet, 'h->ts' is the timestamp, + * 'h->length' is the length of the packet off the wire, and 'h->caplen' + * is the number of bytes actually captured. + */ +u_int +ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p) +{ + return ieee802_11_print(p, h->len, h->caplen); +} + +static u_int +ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen) +{ + u_int32_t caphdr_len; + + caphdr_len = EXTRACT_32BITS(p + 4); + if (caphdr_len < 8) { + /* + * Yow! The capture header length is claimed not + * to be large enough to include even the version + * cookie or capture header length! + */ + printf("[|802.11]"); + return caplen; + } + + if (caplen < caphdr_len) { + printf("[|802.11]"); + return caplen; + } + + return caphdr_len + ieee802_11_print(p + caphdr_len, + length - caphdr_len, caplen - caphdr_len); +} + +#define PRISM_HDR_LEN 144 + +#define WLANCAP_MAGIC_COOKIE_V1 0x80211001 + +/* + * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header, + * containing information such as radio information, which we + * currently ignore. + * + * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's + * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no + * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a + * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so + * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and + * the first 4 bytes of the header are used to indicate which it is). + */ +u_int +prism_if_print(const struct pcap_pkthdr *h, const u_char *p) +{ + u_int caplen = h->caplen; + u_int length = h->len; + + if (caplen < 4) { + printf("[|802.11]"); + return caplen; + } + + if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1) + return ieee802_11_radio_print(p, length, caplen); + + if (caplen < PRISM_HDR_LEN) { + printf("[|802.11]"); + return caplen; + } + + return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN, + length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN); +} + +/* + * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra + * header, containing information such as radio information, which we + * currently ignore. + */ +u_int +ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p) +{ + u_int caplen = h->caplen; + u_int length = h->len; + + if (caplen < 8) { + printf("[|802.11]"); + return caplen; + } + + return ieee802_11_radio_print(p, length, caplen); } |