1*d49cb46eScanacar /* $OpenBSD: print-802_11.c,v 1.11 2007/07/02 22:09:01 canacar Exp $ */ 212a08440Sreyk 312a08440Sreyk /* 42c56d0d6Sreyk * Copyright (c) 2005 Reyk Floeter <reyk@openbsd.org> 512a08440Sreyk * 612a08440Sreyk * Permission to use, copy, modify, and distribute this software for any 712a08440Sreyk * purpose with or without fee is hereby granted, provided that the above 812a08440Sreyk * copyright notice and this permission notice appear in all copies. 912a08440Sreyk * 1012a08440Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1112a08440Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1212a08440Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1312a08440Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1412a08440Sreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1512a08440Sreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1612a08440Sreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1712a08440Sreyk */ 1812a08440Sreyk 1912a08440Sreyk #include <sys/param.h> 2012a08440Sreyk #include <sys/time.h> 2112a08440Sreyk #include <sys/socket.h> 2212a08440Sreyk #include <sys/file.h> 2312a08440Sreyk #include <sys/ioctl.h> 2412a08440Sreyk 2512a08440Sreyk #include <net/if.h> 2612a08440Sreyk 2712a08440Sreyk #include <netinet/in.h> 2812a08440Sreyk #include <netinet/in_systm.h> 2912a08440Sreyk #include <netinet/if_ether.h> 3012a08440Sreyk 3112a08440Sreyk #include <net80211/ieee80211.h> 3212a08440Sreyk #include <net80211/ieee80211_radiotap.h> 3312a08440Sreyk 3412a08440Sreyk #include <pcap.h> 3512a08440Sreyk #include <stdio.h> 3612a08440Sreyk #include <string.h> 3712a08440Sreyk 3812a08440Sreyk #include "addrtoname.h" 3912a08440Sreyk #include "interface.h" 4012a08440Sreyk 4112a08440Sreyk const char *ieee80211_mgt_subtype_name[] = { 4212a08440Sreyk "association request", 4312a08440Sreyk "association response", 4412a08440Sreyk "reassociation request", 4512a08440Sreyk "reassociation response", 4612a08440Sreyk "probe request", 4712a08440Sreyk "probe response", 4812a08440Sreyk "reserved#6", 4912a08440Sreyk "reserved#7", 5012a08440Sreyk "beacon", 5112a08440Sreyk "atim", 5212a08440Sreyk "disassociation", 5312a08440Sreyk "authentication", 5412a08440Sreyk "deauthentication", 5512a08440Sreyk "reserved#13", 5612a08440Sreyk "reserved#14", 5712a08440Sreyk "reserved#15" 5812a08440Sreyk }; 5912a08440Sreyk 6012a08440Sreyk int ieee80211_hdr(struct ieee80211_frame *); 61b72abdefSreyk int ieee80211_data(struct ieee80211_frame *, u_int); 6212a08440Sreyk void ieee80211_print_element(u_int8_t *, u_int); 6312a08440Sreyk void ieee80211_print_essid(u_int8_t *, u_int); 6412a08440Sreyk int ieee80211_elements(struct ieee80211_frame *, u_int); 6512a08440Sreyk int ieee80211_frame(struct ieee80211_frame *, u_int); 6612a08440Sreyk int ieee80211_print(struct ieee80211_frame *, u_int); 6712a08440Sreyk u_int ieee80211_any2ieee(u_int, u_int); 6818786664Sclaudio void ieee80211_reason(u_int16_t); 6912a08440Sreyk 7012a08440Sreyk #define TCARR(a) TCHECK2(*a, sizeof(a)) 7112a08440Sreyk 72c79cf170Sreyk int ieee80211_encap = 0; 73c79cf170Sreyk 7412a08440Sreyk int 7512a08440Sreyk ieee80211_hdr(struct ieee80211_frame *wh) 7612a08440Sreyk { 7712a08440Sreyk struct ieee80211_frame_addr4 *w4; 7812a08440Sreyk 7912a08440Sreyk switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 8012a08440Sreyk case IEEE80211_FC1_DIR_NODS: 8112a08440Sreyk TCARR(wh->i_addr2); 8212a08440Sreyk printf("%s", etheraddr_string(wh->i_addr2)); 8312a08440Sreyk TCARR(wh->i_addr1); 8412a08440Sreyk printf(" > %s", etheraddr_string(wh->i_addr1)); 8512a08440Sreyk TCARR(wh->i_addr3); 8612a08440Sreyk printf(", bssid %s", etheraddr_string(wh->i_addr3)); 8712a08440Sreyk break; 8812a08440Sreyk case IEEE80211_FC1_DIR_TODS: 8912a08440Sreyk TCARR(wh->i_addr2); 9012a08440Sreyk printf("%s", etheraddr_string(wh->i_addr2)); 9112a08440Sreyk TCARR(wh->i_addr3); 9212a08440Sreyk printf(" > %s", etheraddr_string(wh->i_addr3)); 9312a08440Sreyk TCARR(wh->i_addr1); 9412a08440Sreyk printf(", bssid %s, > DS", etheraddr_string(wh->i_addr1)); 9512a08440Sreyk break; 9612a08440Sreyk case IEEE80211_FC1_DIR_FROMDS: 9712a08440Sreyk TCARR(wh->i_addr3); 9812a08440Sreyk printf("%s", etheraddr_string(wh->i_addr3)); 9912a08440Sreyk TCARR(wh->i_addr1); 10012a08440Sreyk printf(" > %s", etheraddr_string(wh->i_addr1)); 10112a08440Sreyk TCARR(wh->i_addr2); 10212a08440Sreyk printf(", bssid %s, DS >", etheraddr_string(wh->i_addr2)); 10312a08440Sreyk break; 10412a08440Sreyk case IEEE80211_FC1_DIR_DSTODS: 10512a08440Sreyk w4 = (struct ieee80211_frame_addr4 *) wh; 10612a08440Sreyk TCARR(w4->i_addr4); 10712a08440Sreyk printf("%s", etheraddr_string(w4->i_addr4)); 10812a08440Sreyk TCARR(w4->i_addr3); 10912a08440Sreyk printf(" > %s", etheraddr_string(w4->i_addr3)); 11012a08440Sreyk TCARR(w4->i_addr2); 11112a08440Sreyk printf(", bssid %s", etheraddr_string(w4->i_addr2)); 11212a08440Sreyk TCARR(w4->i_addr1); 11312a08440Sreyk printf(" > %s, DS > DS", etheraddr_string(w4->i_addr1)); 11412a08440Sreyk break; 11512a08440Sreyk } 11612a08440Sreyk if (vflag) { 117cce1ba42Sclaudio u_int16_t seq; 11812a08440Sreyk TCARR(wh->i_seq); 119cce1ba42Sclaudio bcopy(wh->i_seq, &seq, sizeof(u_int16_t)); 120cce1ba42Sclaudio printf(" (seq %u): ", letoh16(seq)); 12112a08440Sreyk } else 12212a08440Sreyk printf(": "); 12312a08440Sreyk 12412a08440Sreyk return (0); 12512a08440Sreyk 12612a08440Sreyk trunc: 12712a08440Sreyk /* Truncated elements in frame */ 12812a08440Sreyk return (1); 12912a08440Sreyk } 13012a08440Sreyk 131b72abdefSreyk int 132b72abdefSreyk ieee80211_data(struct ieee80211_frame *wh, u_int len) 133b72abdefSreyk { 134b72abdefSreyk u_int8_t *t = (u_int8_t *)wh; 135*d49cb46eScanacar struct ieee80211_frame_addr4 *w4; 136b72abdefSreyk u_int datalen; 137b72abdefSreyk 138*d49cb46eScanacar TCHECK(*wh); 139b72abdefSreyk t += sizeof(struct ieee80211_frame); 140b72abdefSreyk datalen = len - sizeof(struct ieee80211_frame); 141b72abdefSreyk 142b72abdefSreyk switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 143b72abdefSreyk case IEEE80211_FC1_DIR_TODS: 144b72abdefSreyk llc_print(t, datalen, datalen, wh->i_addr2, wh->i_addr3); 145b72abdefSreyk break; 146b72abdefSreyk case IEEE80211_FC1_DIR_FROMDS: 147b72abdefSreyk llc_print(t, datalen, datalen, wh->i_addr3, wh->i_addr1); 148b72abdefSreyk break; 149b72abdefSreyk case IEEE80211_FC1_DIR_NODS: 150*d49cb46eScanacar llc_print(t, datalen, datalen, wh->i_addr2, wh->i_addr1); 151*d49cb46eScanacar break; 152b72abdefSreyk case IEEE80211_FC1_DIR_DSTODS: 153*d49cb46eScanacar w4 = (struct ieee80211_frame_addr4 *) wh; 154*d49cb46eScanacar TCHECK(*w4); 155*d49cb46eScanacar t = (u_int8_t *) (w4 + 1); 156*d49cb46eScanacar datalen = len - sizeof(*w4); 157*d49cb46eScanacar llc_print(t, datalen, datalen, w4->i_addr4, w4->i_addr3); 158b72abdefSreyk break; 159b72abdefSreyk } 160b72abdefSreyk 161b72abdefSreyk return (0); 162b72abdefSreyk 163b72abdefSreyk trunc: 164b72abdefSreyk /* Truncated elements in frame */ 165b72abdefSreyk return (1); 166b72abdefSreyk } 167b72abdefSreyk 16812a08440Sreyk /* Caller checks len */ 16912a08440Sreyk void 17012a08440Sreyk ieee80211_print_element(u_int8_t *data, u_int len) 17112a08440Sreyk { 17212a08440Sreyk u_int8_t *p; 1739cbdb746Sderaadt int i; 17412a08440Sreyk 17512a08440Sreyk printf(" 0x"); 1769cbdb746Sderaadt for (i = 0, p = data; i < len; i++, p++) 17712a08440Sreyk printf("%02x", *p); 17812a08440Sreyk } 17912a08440Sreyk 18012a08440Sreyk /* Caller checks len */ 18112a08440Sreyk void 18212a08440Sreyk ieee80211_print_essid(u_int8_t *essid, u_int len) 18312a08440Sreyk { 18412a08440Sreyk u_int8_t *p; 1859cbdb746Sderaadt int i; 18612a08440Sreyk 18712a08440Sreyk if (len > IEEE80211_NWID_LEN) 18812a08440Sreyk len = IEEE80211_NWID_LEN; 18912a08440Sreyk 19012a08440Sreyk /* determine printable or not */ 19112a08440Sreyk for (i = 0, p = essid; i < len; i++, p++) { 19212a08440Sreyk if (*p < ' ' || *p > 0x7e) 19312a08440Sreyk break; 19412a08440Sreyk } 19512a08440Sreyk if (i == len) { 19612a08440Sreyk printf(" ("); 19712a08440Sreyk for (i = 0, p = essid; i < len; i++, p++) 19812a08440Sreyk putchar(*p); 19912a08440Sreyk putchar(')'); 2009cbdb746Sderaadt } else 20112a08440Sreyk ieee80211_print_element(essid, len); 20212a08440Sreyk } 20312a08440Sreyk 20412a08440Sreyk int 20512a08440Sreyk ieee80211_elements(struct ieee80211_frame *wh, u_int flen) 20612a08440Sreyk { 20712a08440Sreyk u_int8_t *buf, *frm; 208cce1ba42Sclaudio u_int64_t tstamp; 209cce1ba42Sclaudio u_int16_t bintval, capinfo; 21012a08440Sreyk int i; 21112a08440Sreyk 21212a08440Sreyk buf = (u_int8_t *)wh; 21312a08440Sreyk frm = (u_int8_t *)&wh[1]; 21412a08440Sreyk 2150a05c5bfSreyk TCHECK2(*frm, 8); 216cce1ba42Sclaudio bcopy(frm, &tstamp, sizeof(u_int64_t)); 21712a08440Sreyk frm += 8; 21812a08440Sreyk 21912a08440Sreyk if (vflag > 1) 220cce1ba42Sclaudio printf(", timestamp %llu", letoh64(tstamp)); 22112a08440Sreyk 2220a05c5bfSreyk TCHECK2(*frm, 2); 223cce1ba42Sclaudio bcopy(frm, &bintval, sizeof(u_int16_t)); 22412a08440Sreyk frm += 2; 22512a08440Sreyk 22612a08440Sreyk if (vflag > 1) 227cce1ba42Sclaudio printf(", interval %u", letoh16(bintval)); 22812a08440Sreyk 2290a05c5bfSreyk TCHECK2(*frm, 2); 230cce1ba42Sclaudio bcopy(frm, &capinfo, sizeof(u_int16_t)); 23112a08440Sreyk frm += 2; 23212a08440Sreyk 23312a08440Sreyk if (vflag) 234cce1ba42Sclaudio printb(", caps", letoh16(capinfo), 23512a08440Sreyk IEEE80211_CAPINFO_BITS); 23612a08440Sreyk 23712a08440Sreyk while (TTEST2(*frm, 2)) { 23812a08440Sreyk u_int len = frm[1]; 23912a08440Sreyk u_int8_t *data = frm + 2; 24012a08440Sreyk 24112a08440Sreyk if (!TTEST2(*data, len)) 24212a08440Sreyk break; 24312a08440Sreyk 24412a08440Sreyk #define ELEM_CHECK(l) if (len != l) break 24512a08440Sreyk 24612a08440Sreyk switch (*frm) { 24712a08440Sreyk case IEEE80211_ELEMID_SSID: 24812a08440Sreyk printf(", ssid"); 24912a08440Sreyk ieee80211_print_essid(data, len); 25012a08440Sreyk break; 25112a08440Sreyk case IEEE80211_ELEMID_RATES: 25212a08440Sreyk printf(", rates"); 25312a08440Sreyk if (!vflag) 25412a08440Sreyk break; 25512a08440Sreyk for (i = len; i > 0; i--, data++) 25612a08440Sreyk printf(" %uM", 25712a08440Sreyk (data[0] & IEEE80211_RATE_VAL) / 2); 25812a08440Sreyk break; 25912a08440Sreyk case IEEE80211_ELEMID_FHPARMS: 26012a08440Sreyk ELEM_CHECK(5); 26112a08440Sreyk printf(", fh (dwell %u, chan %u, index %u)", 26212a08440Sreyk (data[1] << 8) | data[0], 26312a08440Sreyk (data[2] - 1) * 80 + data[3], /* FH_CHAN */ 26412a08440Sreyk data[4]); 26512a08440Sreyk break; 26612a08440Sreyk case IEEE80211_ELEMID_DSPARMS: 26712a08440Sreyk ELEM_CHECK(1); 26812a08440Sreyk printf(", ds"); 26912a08440Sreyk if (vflag) 27012a08440Sreyk printf(" (chan %u)", data[0]); 27112a08440Sreyk break; 27212a08440Sreyk case IEEE80211_ELEMID_CFPARMS: 27312a08440Sreyk printf(", cf"); 27412a08440Sreyk if (vflag) 27512a08440Sreyk ieee80211_print_element(data, len); 27612a08440Sreyk break; 27712a08440Sreyk case IEEE80211_ELEMID_TIM: 27812a08440Sreyk printf(", tim"); 27912a08440Sreyk if (vflag) 28012a08440Sreyk ieee80211_print_element(data, len); 28112a08440Sreyk break; 28212a08440Sreyk case IEEE80211_ELEMID_IBSSPARMS: 28312a08440Sreyk printf(", ibss"); 28412a08440Sreyk if (vflag) 28512a08440Sreyk ieee80211_print_element(data, len); 28612a08440Sreyk break; 28712a08440Sreyk case IEEE80211_ELEMID_COUNTRY: 28812a08440Sreyk printf(", country"); 28912a08440Sreyk for (i = len; i > 0; i--, data++) 29012a08440Sreyk printf(" %u", data[0]); 29112a08440Sreyk break; 29212a08440Sreyk case IEEE80211_ELEMID_CHALLENGE: 29312a08440Sreyk printf(", challenge"); 29412a08440Sreyk if (vflag) 29512a08440Sreyk ieee80211_print_element(data, len); 29612a08440Sreyk break; 29712a08440Sreyk case IEEE80211_ELEMID_ERP: 29812a08440Sreyk printf(", erp"); 29912a08440Sreyk if (vflag) 30012a08440Sreyk ieee80211_print_element(data, len); 30112a08440Sreyk break; 30212a08440Sreyk case IEEE80211_ELEMID_RSN: 30312a08440Sreyk printf(", rsn"); 30412a08440Sreyk if (vflag) 30512a08440Sreyk ieee80211_print_element(data, len); 30612a08440Sreyk break; 30712a08440Sreyk case IEEE80211_ELEMID_XRATES: 30812a08440Sreyk printf(", xrates"); 30912a08440Sreyk if (!vflag) 31012a08440Sreyk break; 31112a08440Sreyk for (i = len; i > 0; i--, data++) 31212a08440Sreyk printf(" %uM", 31312a08440Sreyk (data[0] & IEEE80211_RATE_VAL) / 2); 31412a08440Sreyk break; 31512a08440Sreyk case IEEE80211_ELEMID_TPC: 31612a08440Sreyk printf(", tpc"); 31712a08440Sreyk if (vflag) 31812a08440Sreyk ieee80211_print_element(data, len); 31912a08440Sreyk break; 32012a08440Sreyk case IEEE80211_ELEMID_CCKM: 32112a08440Sreyk printf(", cckm"); 32212a08440Sreyk if (vflag) 32312a08440Sreyk ieee80211_print_element(data, len); 32412a08440Sreyk break; 32512a08440Sreyk case IEEE80211_ELEMID_VENDOR: 32612a08440Sreyk printf(", vendor"); 32712a08440Sreyk if (vflag) 32812a08440Sreyk ieee80211_print_element(data, len); 32912a08440Sreyk break; 33012a08440Sreyk default: 33112a08440Sreyk printf(", %u:%u", (u_int) *frm, len); 33212a08440Sreyk if (vflag) 33312a08440Sreyk ieee80211_print_element(data, len); 33412a08440Sreyk break; 33512a08440Sreyk } 33612a08440Sreyk frm += len + 2; 33712a08440Sreyk 33812a08440Sreyk if (frm >= snapend) 33912a08440Sreyk break; 34012a08440Sreyk } 34112a08440Sreyk 34212a08440Sreyk #undef ELEM_CHECK 34312a08440Sreyk 34412a08440Sreyk return (0); 34512a08440Sreyk 34612a08440Sreyk trunc: 34712a08440Sreyk /* Truncated elements in frame */ 34812a08440Sreyk return (1); 34912a08440Sreyk } 35012a08440Sreyk 35112a08440Sreyk int 35212a08440Sreyk ieee80211_frame(struct ieee80211_frame *wh, u_int len) 35312a08440Sreyk { 35412a08440Sreyk u_int8_t subtype, type, *frm; 35512a08440Sreyk 35612a08440Sreyk TCARR(wh->i_fc); 35712a08440Sreyk 35812a08440Sreyk type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 35912a08440Sreyk subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 36012a08440Sreyk 36112a08440Sreyk frm = (u_int8_t *)&wh[1]; 36212a08440Sreyk 36312a08440Sreyk switch (type) { 36412a08440Sreyk case IEEE80211_FC0_TYPE_DATA: 365b72abdefSreyk printf(": data: "); 366b72abdefSreyk ieee80211_data(wh, len); 36712a08440Sreyk break; 36812a08440Sreyk case IEEE80211_FC0_TYPE_MGT: 36912a08440Sreyk printf(": %s", ieee80211_mgt_subtype_name[ 37012a08440Sreyk subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]); 37112a08440Sreyk switch (subtype) { 37212a08440Sreyk case IEEE80211_FC0_SUBTYPE_BEACON: 37312a08440Sreyk case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 37412a08440Sreyk if (ieee80211_elements(wh, len) != 0) 37512a08440Sreyk goto trunc; 37612a08440Sreyk break; 37712a08440Sreyk case IEEE80211_FC0_SUBTYPE_AUTH: 37812a08440Sreyk TCHECK2(*frm, 2); /* Auth Algorithm */ 37912a08440Sreyk switch (IEEE80211_AUTH_ALGORITHM(frm)) { 38012a08440Sreyk case IEEE80211_AUTH_ALG_OPEN: 38112a08440Sreyk TCHECK2(*frm, 4); /* Auth Transaction */ 38212a08440Sreyk switch (IEEE80211_AUTH_TRANSACTION(frm)) { 38312a08440Sreyk case IEEE80211_AUTH_OPEN_REQUEST: 38412a08440Sreyk printf(" request"); 38512a08440Sreyk break; 38612a08440Sreyk case IEEE80211_AUTH_OPEN_RESPONSE: 38712a08440Sreyk printf(" response"); 38812a08440Sreyk break; 38912a08440Sreyk } 39012a08440Sreyk break; 39112a08440Sreyk case IEEE80211_AUTH_ALG_SHARED: 39212a08440Sreyk TCHECK2(*frm, 4); /* Auth Transaction */ 39312a08440Sreyk switch (IEEE80211_AUTH_TRANSACTION(frm)) { 39412a08440Sreyk case IEEE80211_AUTH_SHARED_REQUEST: 39512a08440Sreyk printf(" request"); 39612a08440Sreyk break; 39712a08440Sreyk case IEEE80211_AUTH_SHARED_CHALLENGE: 39812a08440Sreyk printf(" challenge"); 39912a08440Sreyk break; 40012a08440Sreyk case IEEE80211_AUTH_SHARED_RESPONSE: 40112a08440Sreyk printf(" response"); 40212a08440Sreyk break; 40312a08440Sreyk case IEEE80211_AUTH_SHARED_PASS: 40412a08440Sreyk printf(" pass"); 40512a08440Sreyk break; 40612a08440Sreyk } 40712a08440Sreyk break; 40812a08440Sreyk case IEEE80211_AUTH_ALG_LEAP: 40912a08440Sreyk printf(" (leap)"); 41012a08440Sreyk break; 41112a08440Sreyk } 41212a08440Sreyk break; 41318786664Sclaudio case IEEE80211_FC0_SUBTYPE_DEAUTH: 41418786664Sclaudio case IEEE80211_FC0_SUBTYPE_DISASSOC: 41518786664Sclaudio TCHECK2(*frm, 2); /* Reason Code */ 41618786664Sclaudio ieee80211_reason(frm[0] | (frm[1] << 8)); 41718786664Sclaudio break; 41812a08440Sreyk } 41912a08440Sreyk break; 42012a08440Sreyk default: 42112a08440Sreyk printf(": type#%d", type); 42212a08440Sreyk break; 42312a08440Sreyk } 42412a08440Sreyk 42512a08440Sreyk if (wh->i_fc[1] & IEEE80211_FC1_WEP) 42612a08440Sreyk printf(", WEP"); 42712a08440Sreyk 42812a08440Sreyk return (0); 42912a08440Sreyk 43012a08440Sreyk trunc: 43112a08440Sreyk /* Truncated 802.11 frame */ 43212a08440Sreyk return (1); 43312a08440Sreyk } 43412a08440Sreyk 43512a08440Sreyk u_int 43612a08440Sreyk ieee80211_any2ieee(u_int freq, u_int flags) 43712a08440Sreyk { 43812a08440Sreyk if (flags & IEEE80211_CHAN_2GHZ) { 43912a08440Sreyk if (freq == 2484) 44012a08440Sreyk return 14; 44112a08440Sreyk if (freq < 2484) 44212a08440Sreyk return (freq - 2407) / 5; 44312a08440Sreyk else 44412a08440Sreyk return 15 + ((freq - 2512) / 20); 44512a08440Sreyk } else if (flags & IEEE80211_CHAN_5GHZ) { 44612a08440Sreyk return (freq - 5000) / 5; 44712a08440Sreyk } else { 44812a08440Sreyk /* Assume channel is already an IEEE number */ 44912a08440Sreyk return (freq); 45012a08440Sreyk } 45112a08440Sreyk } 45212a08440Sreyk 45312a08440Sreyk int 45412a08440Sreyk ieee80211_print(struct ieee80211_frame *wh, u_int len) 45512a08440Sreyk { 45612a08440Sreyk if (eflag) 45712a08440Sreyk if (ieee80211_hdr(wh)) 45812a08440Sreyk return (1); 45912a08440Sreyk 46012a08440Sreyk printf("802.11"); 46112a08440Sreyk 46212a08440Sreyk return (ieee80211_frame(wh, len)); 46312a08440Sreyk } 46412a08440Sreyk 46512a08440Sreyk void 46612a08440Sreyk ieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h, 46712a08440Sreyk const u_char *p) 46812a08440Sreyk { 46912a08440Sreyk struct ieee80211_frame *wh = (struct ieee80211_frame*)p; 47012a08440Sreyk 471c79cf170Sreyk if (!ieee80211_encap) 47212a08440Sreyk ts_print(&h->ts); 47312a08440Sreyk 47412a08440Sreyk packetp = p; 47512a08440Sreyk snapend = p + h->caplen; 47612a08440Sreyk 47712a08440Sreyk if (ieee80211_print(wh, (u_int)h->caplen) != 0) 47812a08440Sreyk printf("[|802.11]"); 47912a08440Sreyk 480c79cf170Sreyk if (!ieee80211_encap) { 48112a08440Sreyk if (xflag) 48212a08440Sreyk default_print(p, (u_int)h->caplen); 48312a08440Sreyk putchar('\n'); 48412a08440Sreyk } 485c79cf170Sreyk } 48612a08440Sreyk 48712a08440Sreyk void 48812a08440Sreyk ieee802_11_radio_if_print(u_char *user, const struct pcap_pkthdr *h, 48912a08440Sreyk const u_char *p) 49012a08440Sreyk { 49112a08440Sreyk struct ieee80211_radiotap_header *rh = 49212a08440Sreyk (struct ieee80211_radiotap_header*)p; 49312a08440Sreyk struct ieee80211_frame *wh; 49412a08440Sreyk u_int8_t *t; 49512a08440Sreyk u_int32_t present; 49612a08440Sreyk u_int len, rh_len; 497cce1ba42Sclaudio u_int16_t tmp; 49812a08440Sreyk 499c79cf170Sreyk if (!ieee80211_encap) 50012a08440Sreyk ts_print(&h->ts); 50112a08440Sreyk 50212a08440Sreyk packetp = p; 50312a08440Sreyk snapend = p + h->caplen; 50412a08440Sreyk 50512a08440Sreyk TCHECK(*rh); 50612a08440Sreyk 50712a08440Sreyk len = h->caplen; 50812a08440Sreyk rh_len = letoh16(rh->it_len); 50912a08440Sreyk if (rh->it_version != 0) { 510c79cf170Sreyk printf("[?radiotap + 802.11 v:%u]", rh->it_version); 51112a08440Sreyk goto out; 51212a08440Sreyk } 51312a08440Sreyk 51412a08440Sreyk wh = (struct ieee80211_frame *)(p + rh_len); 51512a08440Sreyk if (len <= rh_len || ieee80211_print(wh, len - rh_len)) 51612a08440Sreyk printf("[|802.11]"); 51712a08440Sreyk 51812a08440Sreyk t = (u_int8_t*)p + sizeof(struct ieee80211_radiotap_header); 51912a08440Sreyk 52012a08440Sreyk if ((present = letoh32(rh->it_present)) == 0) 52112a08440Sreyk goto out; 52212a08440Sreyk 52312a08440Sreyk printf(", <radiotap v%u", rh->it_version); 52412a08440Sreyk 52512a08440Sreyk #define RADIOTAP(_x) \ 52612a08440Sreyk (present & (1 << IEEE80211_RADIOTAP_##_x)) 52712a08440Sreyk 52812a08440Sreyk if (RADIOTAP(TSFT)) { 529cce1ba42Sclaudio u_int64_t tsf; 530cce1ba42Sclaudio 53112a08440Sreyk TCHECK2(*t, 8); 532cce1ba42Sclaudio bcopy(t, &tsf, sizeof(u_int64_t)); 53312a08440Sreyk if (vflag > 1) 534cce1ba42Sclaudio printf(", tsf %llu", letoh64(tsf)); 53512a08440Sreyk t += 8; 53612a08440Sreyk } 53712a08440Sreyk 53812a08440Sreyk if (RADIOTAP(FLAGS)) { 53912a08440Sreyk u_int8_t flags = *(u_int8_t*)t; 540026ca542Sderaadt TCHECK2(*t, 1); 541026ca542Sderaadt 54212a08440Sreyk if (flags & IEEE80211_RADIOTAP_F_CFP) 54312a08440Sreyk printf(", CFP"); 54412a08440Sreyk if (flags & IEEE80211_RADIOTAP_F_SHORTPRE) 54512a08440Sreyk printf(", SHORTPRE"); 54612a08440Sreyk if (flags & IEEE80211_RADIOTAP_F_WEP) 54712a08440Sreyk printf(", WEP"); 54812a08440Sreyk if (flags & IEEE80211_RADIOTAP_F_FRAG) 54912a08440Sreyk printf(", FRAG"); 55012a08440Sreyk t += 1; 55112a08440Sreyk } 55212a08440Sreyk 55312a08440Sreyk if (RADIOTAP(RATE)) { 55412a08440Sreyk TCHECK2(*t, 1); 55512a08440Sreyk if (vflag) 55612a08440Sreyk printf(", %uMbit/s", (*(u_int8_t*)t) / 2); 55712a08440Sreyk t += 1; 55812a08440Sreyk } 55912a08440Sreyk 56012a08440Sreyk if (RADIOTAP(CHANNEL)) { 56112a08440Sreyk u_int16_t freq, flags; 56212a08440Sreyk TCHECK2(*t, 2); 56312a08440Sreyk 564cce1ba42Sclaudio bcopy(t, &freq, sizeof(u_int16_t)); 565cce1ba42Sclaudio freq = letoh16(freq); 56612a08440Sreyk t += 2; 56712a08440Sreyk TCHECK2(*t, 2); 568cce1ba42Sclaudio bcopy(t, &flags, sizeof(u_int16_t)); 569cce1ba42Sclaudio flags = letoh16(flags); 57012a08440Sreyk t += 2; 57112a08440Sreyk 57212a08440Sreyk printf(", chan %u", ieee80211_any2ieee(freq, flags)); 57312a08440Sreyk 57412a08440Sreyk if (flags & IEEE80211_CHAN_DYN && 57512a08440Sreyk flags & IEEE80211_CHAN_2GHZ) 57612a08440Sreyk printf(", 11g"); 57712a08440Sreyk else if (flags & IEEE80211_CHAN_CCK && 57812a08440Sreyk flags & IEEE80211_CHAN_2GHZ) 57912a08440Sreyk printf(", 11b"); 58012a08440Sreyk else if (flags & IEEE80211_CHAN_OFDM && 58112a08440Sreyk flags & IEEE80211_CHAN_2GHZ) 58212a08440Sreyk printf(", 11G"); 58312a08440Sreyk else if (flags & IEEE80211_CHAN_OFDM && 58412a08440Sreyk flags & IEEE80211_CHAN_5GHZ) 58512a08440Sreyk printf(", 11a"); 58612a08440Sreyk 58712a08440Sreyk if (flags & IEEE80211_CHAN_TURBO) 58812a08440Sreyk printf(", TURBO"); 58912a08440Sreyk if (flags & IEEE80211_CHAN_XR) 59012a08440Sreyk printf(", XR"); 59112a08440Sreyk } 59212a08440Sreyk 59312a08440Sreyk if (RADIOTAP(FHSS)) { 59412a08440Sreyk TCHECK2(*t, 2); 59512a08440Sreyk printf(", fhss %u/%u", *(u_int8_t*)t, *(u_int8_t*)t + 1); 59612a08440Sreyk t += 2; 59712a08440Sreyk } 59812a08440Sreyk 59912a08440Sreyk if (RADIOTAP(DBM_ANTSIGNAL)) { 60012a08440Sreyk TCHECK(*t); 60112a08440Sreyk printf(", sig %ddBm", *(int8_t*)t); 60212a08440Sreyk t += 1; 60312a08440Sreyk } 60412a08440Sreyk 60512a08440Sreyk if (RADIOTAP(DBM_ANTNOISE)) { 60612a08440Sreyk TCHECK(*t); 60712a08440Sreyk printf(", noise %ddBm", *(int8_t*)t); 60812a08440Sreyk t += 1; 60912a08440Sreyk } 61012a08440Sreyk 61112a08440Sreyk if (RADIOTAP(LOCK_QUALITY)) { 61212a08440Sreyk TCHECK2(*t, 2); 613cce1ba42Sclaudio if (vflag) { 614cce1ba42Sclaudio bcopy(t, &tmp, sizeof(u_int16_t)); 615cce1ba42Sclaudio printf(", quality %u", letoh16(tmp)); 616cce1ba42Sclaudio } 61712a08440Sreyk t += 2; 61812a08440Sreyk } 61912a08440Sreyk 62012a08440Sreyk if (RADIOTAP(TX_ATTENUATION)) { 62112a08440Sreyk TCHECK2(*t, 2); 622cce1ba42Sclaudio if (vflag) { 623cce1ba42Sclaudio bcopy(t, &tmp, sizeof(u_int16_t)); 624cce1ba42Sclaudio printf(", txatt %u", letoh16(tmp)); 625cce1ba42Sclaudio } 62612a08440Sreyk t += 2; 62712a08440Sreyk } 62812a08440Sreyk 62912a08440Sreyk if (RADIOTAP(DB_TX_ATTENUATION)) { 63012a08440Sreyk TCHECK2(*t, 2); 631cce1ba42Sclaudio if (vflag) { 632cce1ba42Sclaudio bcopy(t, &tmp, sizeof(u_int16_t)); 633cce1ba42Sclaudio printf(", txatt %udB", letoh16(tmp)); 634cce1ba42Sclaudio } 63512a08440Sreyk t += 2; 63612a08440Sreyk } 63712a08440Sreyk 63812a08440Sreyk if (RADIOTAP(DBM_TX_POWER)) { 63912a08440Sreyk TCHECK(*t); 64012a08440Sreyk printf(", txpower %ddBm", *(int8_t*)t); 64112a08440Sreyk t += 1; 64212a08440Sreyk } 64312a08440Sreyk 64412a08440Sreyk if (RADIOTAP(ANTENNA)) { 64512a08440Sreyk TCHECK(*t); 64612a08440Sreyk if (vflag) 64712a08440Sreyk printf(", antenna %u", *(u_int8_t*)t); 64812a08440Sreyk t += 1; 64912a08440Sreyk } 65012a08440Sreyk 65112a08440Sreyk if (RADIOTAP(DB_ANTSIGNAL)) { 65212a08440Sreyk TCHECK(*t); 65312a08440Sreyk printf(", signal %udB", *(u_int8_t*)t); 65412a08440Sreyk t += 1; 65512a08440Sreyk } 65612a08440Sreyk 65712a08440Sreyk if (RADIOTAP(DB_ANTNOISE)) { 65812a08440Sreyk TCHECK(*t); 65912a08440Sreyk printf(", noise %udB", *(u_int8_t*)t); 66012a08440Sreyk t += 1; 66112a08440Sreyk } 66212a08440Sreyk 66312a08440Sreyk if (RADIOTAP(FCS)) { 66412a08440Sreyk TCHECK2(*t, 4); 665cce1ba42Sclaudio if (vflag) { 666cce1ba42Sclaudio u_int32_t fcs; 667cce1ba42Sclaudio bcopy(t, &fcs, sizeof(u_int32_t)); 668cce1ba42Sclaudio printf(", fcs %08x", letoh32(fcs)); 669cce1ba42Sclaudio } 67012a08440Sreyk t += 4; 67112a08440Sreyk } 67212a08440Sreyk 6736fc94ee3Sreyk if (RADIOTAP(RSSI)) { 6746fc94ee3Sreyk u_int8_t rssi, max_rssi; 6756fc94ee3Sreyk TCHECK(*t); 6766fc94ee3Sreyk rssi = *(u_int8_t*)t; 6776fc94ee3Sreyk t += 1; 6786fc94ee3Sreyk TCHECK(*t); 6796fc94ee3Sreyk max_rssi = *(u_int8_t*)t; 6806fc94ee3Sreyk t += 1; 6816fc94ee3Sreyk 6826fc94ee3Sreyk printf(", rssi %u/%u", rssi, max_rssi); 6836fc94ee3Sreyk } 6846fc94ee3Sreyk 68512a08440Sreyk #undef RADIOTAP 68612a08440Sreyk 68712a08440Sreyk putchar('>'); 68812a08440Sreyk goto out; 68912a08440Sreyk 69012a08440Sreyk trunc: 69112a08440Sreyk /* Truncated frame */ 69212a08440Sreyk printf("[|radiotap + 802.11]"); 69312a08440Sreyk 69412a08440Sreyk out: 695c79cf170Sreyk if (!ieee80211_encap) { 69612a08440Sreyk if (xflag) 69712a08440Sreyk default_print(p, h->caplen); 69812a08440Sreyk putchar('\n'); 69912a08440Sreyk } 700c79cf170Sreyk } 70118786664Sclaudio 70218786664Sclaudio void 70318786664Sclaudio ieee80211_reason(u_int16_t reason) 70418786664Sclaudio { 70518786664Sclaudio if (!vflag) 70618786664Sclaudio return; 70718786664Sclaudio 70818786664Sclaudio switch (reason) { 70918786664Sclaudio case IEEE80211_REASON_UNSPECIFIED: 71018786664Sclaudio printf(", unspecified failure"); 71118786664Sclaudio break; 71218786664Sclaudio case IEEE80211_REASON_AUTH_EXPIRE: 71318786664Sclaudio printf(", authentication expired"); 71418786664Sclaudio break; 71518786664Sclaudio case IEEE80211_REASON_AUTH_LEAVE: 71618786664Sclaudio printf(", deauth - station left"); 71718786664Sclaudio break; 71818786664Sclaudio case IEEE80211_REASON_ASSOC_EXPIRE: 71918786664Sclaudio printf(", association expired"); 72018786664Sclaudio break; 72118786664Sclaudio case IEEE80211_REASON_ASSOC_TOOMANY: 72218786664Sclaudio printf(", too many associated stations"); 72318786664Sclaudio break; 72418786664Sclaudio case IEEE80211_REASON_NOT_AUTHED: 72518786664Sclaudio printf(", not authenticated"); 72618786664Sclaudio break; 72718786664Sclaudio case IEEE80211_REASON_NOT_ASSOCED: 72818786664Sclaudio printf(", not associated"); 72918786664Sclaudio break; 73018786664Sclaudio case IEEE80211_REASON_ASSOC_LEAVE: 73118786664Sclaudio printf(", disassociated - station left"); 73218786664Sclaudio break; 73318786664Sclaudio case IEEE80211_REASON_ASSOC_NOT_AUTHED: 73418786664Sclaudio printf(", association but not authenticated"); 73518786664Sclaudio break; 73618786664Sclaudio case IEEE80211_REASON_RSN_REQUIRED: 73718786664Sclaudio printf(", rsn required"); 73818786664Sclaudio break; 73918786664Sclaudio case IEEE80211_REASON_RSN_INCONSISTENT: 74018786664Sclaudio printf(", rsn inconsistent"); 74118786664Sclaudio break; 74218786664Sclaudio case IEEE80211_REASON_IE_INVALID: 74318786664Sclaudio printf(", ie invalid"); 74418786664Sclaudio break; 74518786664Sclaudio case IEEE80211_REASON_MIC_FAILURE: 74618786664Sclaudio printf(", mic failure"); 74718786664Sclaudio break; 74818786664Sclaudio default: 74918786664Sclaudio printf(", unknown reason %u", reason); 75018786664Sclaudio } 75118786664Sclaudio } 752