1*36fa064cSstsp /* $OpenBSD: print-802_11.c,v 1.23 2015/07/18 23:35:01 stsp 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/time.h> 2012a08440Sreyk #include <sys/socket.h> 2112a08440Sreyk #include <sys/file.h> 2212a08440Sreyk #include <sys/ioctl.h> 2312a08440Sreyk 2412a08440Sreyk #include <net/if.h> 2512a08440Sreyk 2612a08440Sreyk #include <netinet/in.h> 2712a08440Sreyk #include <netinet/if_ether.h> 2812a08440Sreyk 2912a08440Sreyk #include <net80211/ieee80211.h> 3012a08440Sreyk #include <net80211/ieee80211_radiotap.h> 3112a08440Sreyk 3277734011Sstsp #include <ctype.h> 3312a08440Sreyk #include <pcap.h> 3412a08440Sreyk #include <stdio.h> 3512a08440Sreyk #include <string.h> 3612a08440Sreyk 3712a08440Sreyk #include "addrtoname.h" 3812a08440Sreyk #include "interface.h" 3912a08440Sreyk 4012a08440Sreyk const char *ieee80211_mgt_subtype_name[] = { 4112a08440Sreyk "association request", 4212a08440Sreyk "association response", 4312a08440Sreyk "reassociation request", 4412a08440Sreyk "reassociation response", 4512a08440Sreyk "probe request", 4612a08440Sreyk "probe response", 4712a08440Sreyk "reserved#6", 4812a08440Sreyk "reserved#7", 4912a08440Sreyk "beacon", 5012a08440Sreyk "atim", 5112a08440Sreyk "disassociation", 5212a08440Sreyk "authentication", 5312a08440Sreyk "deauthentication", 54ab7e388eSclaudio "action", 55ab7e388eSclaudio "action noack", 5612a08440Sreyk "reserved#15" 5712a08440Sreyk }; 5812a08440Sreyk 59ab7e388eSclaudio const char *ieee80211_data_subtype_name[] = { 60ab7e388eSclaudio "data", 61ab7e388eSclaudio "data cf ack", 62ab7e388eSclaudio "data cf poll", 63ab7e388eSclaudio "data cf poll ack", 64ab7e388eSclaudio "no-data", 65ab7e388eSclaudio "no-data cf poll", 66ab7e388eSclaudio "no-data cf ack", 67ab7e388eSclaudio "no-data cf poll ack", 68ab7e388eSclaudio "QoS data", 69ab7e388eSclaudio "QoS data cf ack", 70ab7e388eSclaudio "QoS data cf poll", 71ab7e388eSclaudio "QoS data cf poll ack", 72ab7e388eSclaudio "QoS no-data", 73ab7e388eSclaudio "QoS no-data cf poll", 74ab7e388eSclaudio "QoS no-data cf ack", 75ab7e388eSclaudio "QoS no-data cf poll ack" 76ab7e388eSclaudio }; 77ab7e388eSclaudio 7812a08440Sreyk int ieee80211_hdr(struct ieee80211_frame *); 79b72abdefSreyk int ieee80211_data(struct ieee80211_frame *, u_int); 8012a08440Sreyk void ieee80211_print_element(u_int8_t *, u_int); 8112a08440Sreyk void ieee80211_print_essid(u_int8_t *, u_int); 8277734011Sstsp void ieee80211_print_country(u_int8_t *, u_int); 831e3bf20aSstsp void ieee80211_print_htcaps(u_int8_t *, u_int); 84*36fa064cSstsp void ieee80211_print_htop(u_int8_t *, u_int); 8512a08440Sreyk int ieee80211_elements(struct ieee80211_frame *, u_int); 8612a08440Sreyk int ieee80211_frame(struct ieee80211_frame *, u_int); 8712a08440Sreyk int ieee80211_print(struct ieee80211_frame *, u_int); 8812a08440Sreyk u_int ieee80211_any2ieee(u_int, u_int); 8918786664Sclaudio void ieee80211_reason(u_int16_t); 9012a08440Sreyk 9112a08440Sreyk #define TCARR(a) TCHECK2(*a, sizeof(a)) 9212a08440Sreyk 93c79cf170Sreyk int ieee80211_encap = 0; 94c79cf170Sreyk 9512a08440Sreyk int 9612a08440Sreyk ieee80211_hdr(struct ieee80211_frame *wh) 9712a08440Sreyk { 9812a08440Sreyk struct ieee80211_frame_addr4 *w4; 9912a08440Sreyk 10012a08440Sreyk switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 10112a08440Sreyk case IEEE80211_FC1_DIR_NODS: 10212a08440Sreyk TCARR(wh->i_addr2); 10312a08440Sreyk printf("%s", etheraddr_string(wh->i_addr2)); 10412a08440Sreyk TCARR(wh->i_addr1); 10512a08440Sreyk printf(" > %s", etheraddr_string(wh->i_addr1)); 10612a08440Sreyk TCARR(wh->i_addr3); 10712a08440Sreyk printf(", bssid %s", etheraddr_string(wh->i_addr3)); 10812a08440Sreyk break; 10912a08440Sreyk case IEEE80211_FC1_DIR_TODS: 11012a08440Sreyk TCARR(wh->i_addr2); 11112a08440Sreyk printf("%s", etheraddr_string(wh->i_addr2)); 11212a08440Sreyk TCARR(wh->i_addr3); 11312a08440Sreyk printf(" > %s", etheraddr_string(wh->i_addr3)); 11412a08440Sreyk TCARR(wh->i_addr1); 11512a08440Sreyk printf(", bssid %s, > DS", etheraddr_string(wh->i_addr1)); 11612a08440Sreyk break; 11712a08440Sreyk case IEEE80211_FC1_DIR_FROMDS: 11812a08440Sreyk TCARR(wh->i_addr3); 11912a08440Sreyk printf("%s", etheraddr_string(wh->i_addr3)); 12012a08440Sreyk TCARR(wh->i_addr1); 12112a08440Sreyk printf(" > %s", etheraddr_string(wh->i_addr1)); 12212a08440Sreyk TCARR(wh->i_addr2); 12312a08440Sreyk printf(", bssid %s, DS >", etheraddr_string(wh->i_addr2)); 12412a08440Sreyk break; 12512a08440Sreyk case IEEE80211_FC1_DIR_DSTODS: 12612a08440Sreyk w4 = (struct ieee80211_frame_addr4 *) wh; 12712a08440Sreyk TCARR(w4->i_addr4); 12812a08440Sreyk printf("%s", etheraddr_string(w4->i_addr4)); 12912a08440Sreyk TCARR(w4->i_addr3); 13012a08440Sreyk printf(" > %s", etheraddr_string(w4->i_addr3)); 13112a08440Sreyk TCARR(w4->i_addr2); 13212a08440Sreyk printf(", bssid %s", etheraddr_string(w4->i_addr2)); 13312a08440Sreyk TCARR(w4->i_addr1); 13412a08440Sreyk printf(" > %s, DS > DS", etheraddr_string(w4->i_addr1)); 13512a08440Sreyk break; 13612a08440Sreyk } 13712a08440Sreyk if (vflag) { 138cce1ba42Sclaudio u_int16_t seq; 13912a08440Sreyk TCARR(wh->i_seq); 140cce1ba42Sclaudio bcopy(wh->i_seq, &seq, sizeof(u_int16_t)); 141cce1ba42Sclaudio printf(" (seq %u): ", letoh16(seq)); 14212a08440Sreyk } else 14312a08440Sreyk printf(": "); 14412a08440Sreyk 14512a08440Sreyk return (0); 14612a08440Sreyk 14712a08440Sreyk trunc: 14812a08440Sreyk /* Truncated elements in frame */ 14912a08440Sreyk return (1); 15012a08440Sreyk } 15112a08440Sreyk 152b72abdefSreyk int 153b72abdefSreyk ieee80211_data(struct ieee80211_frame *wh, u_int len) 154b72abdefSreyk { 155b72abdefSreyk u_int8_t *t = (u_int8_t *)wh; 156d49cb46eScanacar struct ieee80211_frame_addr4 *w4; 157b72abdefSreyk u_int datalen; 15893cbfc44Sstsp int data = !(wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_NODATA); 159ab7e388eSclaudio u_char *esrc = NULL, *edst = NULL; 160b72abdefSreyk 161d49cb46eScanacar TCHECK(*wh); 162b72abdefSreyk t += sizeof(struct ieee80211_frame); 163b72abdefSreyk datalen = len - sizeof(struct ieee80211_frame); 164b72abdefSreyk 165b72abdefSreyk switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 166b72abdefSreyk case IEEE80211_FC1_DIR_TODS: 167ab7e388eSclaudio esrc = wh->i_addr2; 168ab7e388eSclaudio edst = wh->i_addr3; 169b72abdefSreyk break; 170b72abdefSreyk case IEEE80211_FC1_DIR_FROMDS: 171ab7e388eSclaudio esrc = wh->i_addr3; 172ab7e388eSclaudio edst = wh->i_addr1; 173b72abdefSreyk break; 174b72abdefSreyk case IEEE80211_FC1_DIR_NODS: 175ab7e388eSclaudio esrc = wh->i_addr2; 176ab7e388eSclaudio edst = wh->i_addr1; 177d49cb46eScanacar break; 178b72abdefSreyk case IEEE80211_FC1_DIR_DSTODS: 179d49cb46eScanacar w4 = (struct ieee80211_frame_addr4 *) wh; 180d49cb46eScanacar TCHECK(*w4); 181d49cb46eScanacar t = (u_int8_t *) (w4 + 1); 182d49cb46eScanacar datalen = len - sizeof(*w4); 183ab7e388eSclaudio esrc = w4->i_addr4; 184ab7e388eSclaudio edst = w4->i_addr3; 185b72abdefSreyk break; 186b72abdefSreyk } 187b72abdefSreyk 188ab7e388eSclaudio if (data && esrc) 189ab7e388eSclaudio llc_print(t, datalen, datalen, esrc, edst); 190ab7e388eSclaudio else if (eflag && esrc) 191ab7e388eSclaudio printf("%s > %s", 192ab7e388eSclaudio etheraddr_string(esrc), etheraddr_string(edst)); 193ab7e388eSclaudio 194b72abdefSreyk return (0); 195b72abdefSreyk 196b72abdefSreyk trunc: 197b72abdefSreyk /* Truncated elements in frame */ 198b72abdefSreyk return (1); 199b72abdefSreyk } 200b72abdefSreyk 20112a08440Sreyk /* Caller checks len */ 20212a08440Sreyk void 20312a08440Sreyk ieee80211_print_element(u_int8_t *data, u_int len) 20412a08440Sreyk { 20512a08440Sreyk u_int8_t *p; 2069cbdb746Sderaadt int i; 20712a08440Sreyk 20812a08440Sreyk printf(" 0x"); 2099cbdb746Sderaadt for (i = 0, p = data; i < len; i++, p++) 21012a08440Sreyk printf("%02x", *p); 21112a08440Sreyk } 21212a08440Sreyk 21312a08440Sreyk /* Caller checks len */ 21412a08440Sreyk void 21512a08440Sreyk ieee80211_print_essid(u_int8_t *essid, u_int len) 21612a08440Sreyk { 21712a08440Sreyk u_int8_t *p; 2189cbdb746Sderaadt int i; 21912a08440Sreyk 22012a08440Sreyk if (len > IEEE80211_NWID_LEN) 22112a08440Sreyk len = IEEE80211_NWID_LEN; 22212a08440Sreyk 22312a08440Sreyk /* determine printable or not */ 22412a08440Sreyk for (i = 0, p = essid; i < len; i++, p++) { 22512a08440Sreyk if (*p < ' ' || *p > 0x7e) 22612a08440Sreyk break; 22712a08440Sreyk } 22812a08440Sreyk if (i == len) { 22912a08440Sreyk printf(" ("); 23012a08440Sreyk for (i = 0, p = essid; i < len; i++, p++) 23112a08440Sreyk putchar(*p); 23212a08440Sreyk putchar(')'); 2339cbdb746Sderaadt } else 23412a08440Sreyk ieee80211_print_element(essid, len); 23512a08440Sreyk } 23612a08440Sreyk 2371e3bf20aSstsp /* Caller checks len */ 2381e3bf20aSstsp void 23977734011Sstsp ieee80211_print_country(u_int8_t *data, u_int len) 24077734011Sstsp { 24177734011Sstsp u_int8_t first_chan, nchan, maxpower; 24277734011Sstsp 24377734011Sstsp if (len < 6) 24477734011Sstsp return; 24577734011Sstsp 24677734011Sstsp /* country string */ 24777734011Sstsp printf((isprint(data[0]) ? " '%c" : " '\\%03o"), data[0]); 24877734011Sstsp printf((isprint(data[1]) ? "%c" : "\\%03o"), data[1]); 24977734011Sstsp printf((isprint(data[2]) ? "%c'" : "\\%03o'"), data[2]); 25077734011Sstsp 25177734011Sstsp len -= 3; 25277734011Sstsp data += 3; 25377734011Sstsp 25477734011Sstsp /* channels and corresponding TX power limits */ 25577734011Sstsp while (len > 3) { 25677734011Sstsp /* no pretty-printing for nonsensical zero values, 25777734011Sstsp * nor for operating extension IDs (values >= 201) */ 25877734011Sstsp if (data[0] == 0 || data[1] == 0 || 25977734011Sstsp data[0] >= 201 || data[1] >= 201) { 26077734011Sstsp printf(", %d %d %d", data[0], data[1], data[2]); 26177734011Sstsp continue; 26277734011Sstsp } 26377734011Sstsp 26477734011Sstsp first_chan = data[0]; 26577734011Sstsp nchan = data[1]; 26677734011Sstsp maxpower = data[2]; 26777734011Sstsp 26877734011Sstsp printf(", channel%s %d", nchan == 1 ? "" : "s", first_chan); 26977734011Sstsp if (nchan > 1) 27077734011Sstsp printf("-%d", first_chan + nchan - 1); 27177734011Sstsp printf(" limit %ddB", maxpower); 27277734011Sstsp 27377734011Sstsp len -= 3; 27477734011Sstsp data += 3; 27577734011Sstsp } 27677734011Sstsp } 27777734011Sstsp 27877734011Sstsp /* Caller checks len */ 27977734011Sstsp void 2801e3bf20aSstsp ieee80211_print_htcaps(u_int8_t *data, u_int len) 2811e3bf20aSstsp { 2821e3bf20aSstsp u_int16_t htcaps; 2831e3bf20aSstsp int smps, rxstbc; 2841e3bf20aSstsp 2851e3bf20aSstsp if (len < 2) { 2861e3bf20aSstsp ieee80211_print_element(data, len); 2871e3bf20aSstsp return; 2881e3bf20aSstsp } 2891e3bf20aSstsp 2901e3bf20aSstsp htcaps = (data[0]) | (data[1] << 8); 2911e3bf20aSstsp printf("=<"); 2921e3bf20aSstsp 2931e3bf20aSstsp /* channel width */ 2941e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_CBW20_40) 2951e3bf20aSstsp printf("20/40MHz"); 2961e3bf20aSstsp else 2971e3bf20aSstsp printf("20MHz"); 2981e3bf20aSstsp 2991e3bf20aSstsp /* LDPC coding */ 3001e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_LDPC) 3011e3bf20aSstsp printf(",LDPC"); 3021e3bf20aSstsp 3031e3bf20aSstsp /* spatial multiplexing power save mode */ 3041e3bf20aSstsp smps = (htcaps & IEEE80211_HTCAP_SMPS_MASK) 3051e3bf20aSstsp >> IEEE80211_HTCAP_SMPS_SHIFT; 3061e3bf20aSstsp if (smps == 0) 3071e3bf20aSstsp printf(",SMPS static"); 3081e3bf20aSstsp else if (smps == 1) 3091e3bf20aSstsp printf(",SMPS dynamic"); 3101e3bf20aSstsp 3111e3bf20aSstsp /* 11n greenfield mode */ 3121e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_GF) 3131e3bf20aSstsp printf(",greenfield"); 3141e3bf20aSstsp 3151e3bf20aSstsp /* short guard interval */ 3161e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_SGI20) 3171e3bf20aSstsp printf(",SGI@20MHz"); 3181e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_SGI40) 3191e3bf20aSstsp printf(",SGI@40MHz"); 3201e3bf20aSstsp 3211e3bf20aSstsp /* space-time block coding */ 3221e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_TXSTBC) 3231e3bf20aSstsp printf(",TXSTBC"); 3241e3bf20aSstsp rxstbc = (htcaps & IEEE80211_HTCAP_RXSTBC_MASK) 3251e3bf20aSstsp >> IEEE80211_HTCAP_RXSTBC_SHIFT; 3261e3bf20aSstsp if (rxstbc > 0 && rxstbc < 4) 3271e3bf20aSstsp printf(",RXSTBC %d stream", rxstbc); 3281e3bf20aSstsp 3291e3bf20aSstsp /* delayed block-ack */ 3301e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_DELAYEDBA) 3311e3bf20aSstsp printf(",delayed BA"); 3321e3bf20aSstsp 3331e3bf20aSstsp /* max A-MSDU length */ 3341e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_AMSDU7935) 3351e3bf20aSstsp printf(",A-MSDU 7935"); 3361e3bf20aSstsp else 3371e3bf20aSstsp printf(",A-MSDU 3839"); 3381e3bf20aSstsp 3391e3bf20aSstsp /* DSSS/CCK in 40MHz mode */ 3401e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_DSSSCCK40) 3411e3bf20aSstsp printf(",DSSS/CCK@40MHz"); 3421e3bf20aSstsp 3431e3bf20aSstsp /* 40MHz intolerant */ 3441e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_40INTOLERANT) 3451e3bf20aSstsp printf(",40MHz intolerant"); 3461e3bf20aSstsp 3471e3bf20aSstsp /* L-SIG TXOP protection */ 3481e3bf20aSstsp if (htcaps & IEEE80211_HTCAP_LSIGTXOPPROT) 3491e3bf20aSstsp printf(",L-SIG TXOP prot"); 3501e3bf20aSstsp 3511e3bf20aSstsp printf(">"); 3521e3bf20aSstsp } 3531e3bf20aSstsp 354*36fa064cSstsp /* Caller checks len */ 355*36fa064cSstsp void 356*36fa064cSstsp ieee80211_print_htop(u_int8_t *data, u_int len) 357*36fa064cSstsp { 358*36fa064cSstsp u_int8_t primary_chan; 359*36fa064cSstsp u_int8_t htopinfo[5]; 360*36fa064cSstsp u_int8_t basic_mcs[16]; 361*36fa064cSstsp int sco, prot, i; 362*36fa064cSstsp 363*36fa064cSstsp if (len < sizeof(primary_chan) + sizeof(htopinfo) + sizeof(basic_mcs)) { 364*36fa064cSstsp ieee80211_print_element(data, len); 365*36fa064cSstsp return; 366*36fa064cSstsp } 367*36fa064cSstsp 368*36fa064cSstsp htopinfo[0] = data[1]; 369*36fa064cSstsp 370*36fa064cSstsp printf("=<"); 371*36fa064cSstsp 372*36fa064cSstsp /* primary channel and secondary channel offset */ 373*36fa064cSstsp primary_chan = data[0]; 374*36fa064cSstsp sco = ((htopinfo[0] & IEEE80211_HTOP0_SCO_MASK) 375*36fa064cSstsp >> IEEE80211_HTOP0_SCO_SHIFT); 376*36fa064cSstsp if (sco == 0) 377*36fa064cSstsp printf("20MHz chan %d", primary_chan); 378*36fa064cSstsp else if (sco == 1) 379*36fa064cSstsp printf("40MHz primary chan %d secondary above", primary_chan); 380*36fa064cSstsp else if (sco == 3) 381*36fa064cSstsp printf("40MHz primary chan %d secondary below", primary_chan); 382*36fa064cSstsp else 383*36fa064cSstsp printf("chan %d [invalid secondary channel offset %d]", 384*36fa064cSstsp primary_chan, sco); 385*36fa064cSstsp 386*36fa064cSstsp /* STA channel width */ 387*36fa064cSstsp if ((htopinfo[0] & IEEE80211_HTOP0_CHW) == 0) 388*36fa064cSstsp printf(",STA chanw 20MHz"); 389*36fa064cSstsp 390*36fa064cSstsp /* reduced interframe space (RIFS) permitted */ 391*36fa064cSstsp if (htopinfo[0] & IEEE80211_HTOP0_RIFS) 392*36fa064cSstsp printf(",RIFS"); 393*36fa064cSstsp 394*36fa064cSstsp htopinfo[1] = data[2]; 395*36fa064cSstsp 396*36fa064cSstsp /* protection requirements for HT transmissions */ 397*36fa064cSstsp prot = ((htopinfo[1] & IEEE80211_HTOP1_PROT_MASK) 398*36fa064cSstsp >> IEEE80211_HTOP1_PROT_SHIFT); 399*36fa064cSstsp if (prot == 1) 400*36fa064cSstsp printf(",protect non-member"); 401*36fa064cSstsp else if (prot == 2) 402*36fa064cSstsp printf(",protect 20MHz"); 403*36fa064cSstsp else if (prot == 3) 404*36fa064cSstsp printf(",protect non-HT"); 405*36fa064cSstsp 406*36fa064cSstsp /* non-greenfield STA present */ 407*36fa064cSstsp if (htopinfo[1] & IEEE80211_HTOP1_NONGF_STA) 408*36fa064cSstsp printf(",non-greenfield STA"); 409*36fa064cSstsp 410*36fa064cSstsp /* non-HT STA present */ 411*36fa064cSstsp if (htopinfo[1] & IEEE80211_HTOP1_OBSS_NONHT_STA) 412*36fa064cSstsp printf(",non-HT STA"); 413*36fa064cSstsp 414*36fa064cSstsp htopinfo[3] = data[4]; 415*36fa064cSstsp 416*36fa064cSstsp /* dual-beacon */ 417*36fa064cSstsp if (htopinfo[3] & IEEE80211_HTOP2_DUALBEACON) 418*36fa064cSstsp printf(",dualbeacon"); 419*36fa064cSstsp 420*36fa064cSstsp /* dual CTS protection */ 421*36fa064cSstsp if (htopinfo[3] & IEEE80211_HTOP2_DUALCTSPROT) 422*36fa064cSstsp printf(",dualctsprot"); 423*36fa064cSstsp 424*36fa064cSstsp htopinfo[4] = data[5]; 425*36fa064cSstsp 426*36fa064cSstsp /* space-time block coding (STBC) beacon */ 427*36fa064cSstsp if ((htopinfo[4] << 8) & IEEE80211_HTOP2_DUALCTSPROT) 428*36fa064cSstsp printf(",STBC beacon"); 429*36fa064cSstsp 430*36fa064cSstsp /* L-SIG (non-HT signal field) TX opportunity (TXOP) protection */ 431*36fa064cSstsp if ((htopinfo[4] << 8) & IEEE80211_HTOP2_LSIGTXOP) 432*36fa064cSstsp printf(",lsigtxprot"); 433*36fa064cSstsp 434*36fa064cSstsp /* phased-coexistence operation (PCO) active */ 435*36fa064cSstsp if ((htopinfo[4] << 8) & IEEE80211_HTOP2_PCOACTIVE) { 436*36fa064cSstsp /* PCO phase */ 437*36fa064cSstsp if ((htopinfo[4] << 8) & IEEE80211_HTOP2_PCOPHASE40) 438*36fa064cSstsp printf(",pco40MHz"); 439*36fa064cSstsp else 440*36fa064cSstsp printf(",pco20MHz"); 441*36fa064cSstsp } 442*36fa064cSstsp 443*36fa064cSstsp /* basic MCS set */ 444*36fa064cSstsp memcpy(basic_mcs, &data[6], sizeof(basic_mcs)); 445*36fa064cSstsp printf(",basic MCS set 0x"); 446*36fa064cSstsp for (i = 0; i < sizeof(basic_mcs) / sizeof(basic_mcs[0]); i++) 447*36fa064cSstsp printf("%x", basic_mcs[i]); 448*36fa064cSstsp 449*36fa064cSstsp printf(">"); 450*36fa064cSstsp } 451*36fa064cSstsp 45212a08440Sreyk int 45312a08440Sreyk ieee80211_elements(struct ieee80211_frame *wh, u_int flen) 45412a08440Sreyk { 45512a08440Sreyk u_int8_t *buf, *frm; 456cce1ba42Sclaudio u_int64_t tstamp; 457cce1ba42Sclaudio u_int16_t bintval, capinfo; 45812a08440Sreyk int i; 45912a08440Sreyk 46012a08440Sreyk buf = (u_int8_t *)wh; 46112a08440Sreyk frm = (u_int8_t *)&wh[1]; 46212a08440Sreyk 4630a05c5bfSreyk TCHECK2(*frm, 8); 464cce1ba42Sclaudio bcopy(frm, &tstamp, sizeof(u_int64_t)); 46512a08440Sreyk frm += 8; 46612a08440Sreyk 46712a08440Sreyk if (vflag > 1) 468cce1ba42Sclaudio printf(", timestamp %llu", letoh64(tstamp)); 46912a08440Sreyk 4700a05c5bfSreyk TCHECK2(*frm, 2); 471cce1ba42Sclaudio bcopy(frm, &bintval, sizeof(u_int16_t)); 47212a08440Sreyk frm += 2; 47312a08440Sreyk 47412a08440Sreyk if (vflag > 1) 475cce1ba42Sclaudio printf(", interval %u", letoh16(bintval)); 47612a08440Sreyk 4770a05c5bfSreyk TCHECK2(*frm, 2); 478cce1ba42Sclaudio bcopy(frm, &capinfo, sizeof(u_int16_t)); 47912a08440Sreyk frm += 2; 48012a08440Sreyk 48112a08440Sreyk if (vflag) 482cce1ba42Sclaudio printb(", caps", letoh16(capinfo), 48312a08440Sreyk IEEE80211_CAPINFO_BITS); 48412a08440Sreyk 48512a08440Sreyk while (TTEST2(*frm, 2)) { 48612a08440Sreyk u_int len = frm[1]; 48712a08440Sreyk u_int8_t *data = frm + 2; 48812a08440Sreyk 48912a08440Sreyk if (!TTEST2(*data, len)) 49012a08440Sreyk break; 49112a08440Sreyk 49212a08440Sreyk #define ELEM_CHECK(l) if (len != l) break 49312a08440Sreyk 49412a08440Sreyk switch (*frm) { 49512a08440Sreyk case IEEE80211_ELEMID_SSID: 49612a08440Sreyk printf(", ssid"); 49712a08440Sreyk ieee80211_print_essid(data, len); 49812a08440Sreyk break; 49912a08440Sreyk case IEEE80211_ELEMID_RATES: 50012a08440Sreyk printf(", rates"); 50112a08440Sreyk if (!vflag) 50212a08440Sreyk break; 50312a08440Sreyk for (i = len; i > 0; i--, data++) 50412a08440Sreyk printf(" %uM", 50512a08440Sreyk (data[0] & IEEE80211_RATE_VAL) / 2); 50612a08440Sreyk break; 50712a08440Sreyk case IEEE80211_ELEMID_FHPARMS: 50812a08440Sreyk ELEM_CHECK(5); 50912a08440Sreyk printf(", fh (dwell %u, chan %u, index %u)", 51012a08440Sreyk (data[1] << 8) | data[0], 51112a08440Sreyk (data[2] - 1) * 80 + data[3], /* FH_CHAN */ 51212a08440Sreyk data[4]); 51312a08440Sreyk break; 51412a08440Sreyk case IEEE80211_ELEMID_DSPARMS: 51512a08440Sreyk ELEM_CHECK(1); 51612a08440Sreyk printf(", ds"); 51712a08440Sreyk if (vflag) 51812a08440Sreyk printf(" (chan %u)", data[0]); 51912a08440Sreyk break; 52012a08440Sreyk case IEEE80211_ELEMID_CFPARMS: 52112a08440Sreyk printf(", cf"); 52212a08440Sreyk if (vflag) 52312a08440Sreyk ieee80211_print_element(data, len); 52412a08440Sreyk break; 52512a08440Sreyk case IEEE80211_ELEMID_TIM: 52612a08440Sreyk printf(", tim"); 52712a08440Sreyk if (vflag) 52812a08440Sreyk ieee80211_print_element(data, len); 52912a08440Sreyk break; 53012a08440Sreyk case IEEE80211_ELEMID_IBSSPARMS: 53112a08440Sreyk printf(", ibss"); 53212a08440Sreyk if (vflag) 53312a08440Sreyk ieee80211_print_element(data, len); 53412a08440Sreyk break; 53512a08440Sreyk case IEEE80211_ELEMID_COUNTRY: 53612a08440Sreyk printf(", country"); 53777734011Sstsp ieee80211_print_country(data, len); 53812a08440Sreyk break; 53912a08440Sreyk case IEEE80211_ELEMID_CHALLENGE: 54012a08440Sreyk printf(", challenge"); 54112a08440Sreyk if (vflag) 54212a08440Sreyk ieee80211_print_element(data, len); 54312a08440Sreyk break; 544738acb58Ssthen case IEEE80211_ELEMID_CSA: 545958b7e45Ssthen ELEM_CHECK(3); 546738acb58Ssthen printf(", csa (chan %u count %u%s)", data[1], data[2], 547738acb58Ssthen (data[0] == 1) ? " noTX" : ""); 548738acb58Ssthen break; 54912a08440Sreyk case IEEE80211_ELEMID_ERP: 55012a08440Sreyk printf(", erp"); 55112a08440Sreyk if (vflag) 55212a08440Sreyk ieee80211_print_element(data, len); 55312a08440Sreyk break; 55412a08440Sreyk case IEEE80211_ELEMID_RSN: 55512a08440Sreyk printf(", rsn"); 55612a08440Sreyk if (vflag) 55712a08440Sreyk ieee80211_print_element(data, len); 55812a08440Sreyk break; 55912a08440Sreyk case IEEE80211_ELEMID_XRATES: 56012a08440Sreyk printf(", xrates"); 56112a08440Sreyk if (!vflag) 56212a08440Sreyk break; 56312a08440Sreyk for (i = len; i > 0; i--, data++) 56412a08440Sreyk printf(" %uM", 56512a08440Sreyk (data[0] & IEEE80211_RATE_VAL) / 2); 56612a08440Sreyk break; 5678138faddSstsp case IEEE80211_ELEMID_TPC_REPORT: 5688138faddSstsp printf(", tpcreport"); 56912a08440Sreyk if (vflag) 57012a08440Sreyk ieee80211_print_element(data, len); 57112a08440Sreyk break; 5728138faddSstsp case IEEE80211_ELEMID_TPC_REQUEST: 5738138faddSstsp printf(", tpcrequest"); 57412a08440Sreyk if (vflag) 57512a08440Sreyk ieee80211_print_element(data, len); 57612a08440Sreyk break; 5771e3bf20aSstsp case IEEE80211_ELEMID_HTCAPS: 5781e3bf20aSstsp printf(", htcaps"); 5791e3bf20aSstsp if (vflag) 5801e3bf20aSstsp ieee80211_print_htcaps(data, len); 5811e3bf20aSstsp break; 582*36fa064cSstsp case IEEE80211_ELEMID_HTOP: 583*36fa064cSstsp printf(", htop"); 584*36fa064cSstsp if (vflag) 585*36fa064cSstsp ieee80211_print_htop(data, len); 586*36fa064cSstsp break; 58777734011Sstsp case IEEE80211_ELEMID_POWER_CONSTRAINT: 58877734011Sstsp ELEM_CHECK(1); 58977734011Sstsp printf(", power constraint %udB", data[0]); 59077734011Sstsp break; 5918f0a8537Sstsp case IEEE80211_ELEMID_QBSS_LOAD: 5928f0a8537Sstsp ELEM_CHECK(5); 5938f0a8537Sstsp printf(", %u stations, %d%% utilization, " 5948f0a8537Sstsp "admission capacity %uus/s", 5958f0a8537Sstsp (data[0] | data[1] << 8), 5968f0a8537Sstsp (data[2] * 100) / 255, 5978f0a8537Sstsp (data[3] | data[4] << 8) / 32); 5988f0a8537Sstsp break; 59912a08440Sreyk case IEEE80211_ELEMID_VENDOR: 60012a08440Sreyk printf(", vendor"); 60112a08440Sreyk if (vflag) 60212a08440Sreyk ieee80211_print_element(data, len); 60312a08440Sreyk break; 60412a08440Sreyk default: 60512a08440Sreyk printf(", %u:%u", (u_int) *frm, len); 60612a08440Sreyk if (vflag) 60712a08440Sreyk ieee80211_print_element(data, len); 60812a08440Sreyk break; 60912a08440Sreyk } 61012a08440Sreyk frm += len + 2; 61112a08440Sreyk 61212a08440Sreyk if (frm >= snapend) 61312a08440Sreyk break; 61412a08440Sreyk } 61512a08440Sreyk 61612a08440Sreyk #undef ELEM_CHECK 61712a08440Sreyk 61812a08440Sreyk return (0); 61912a08440Sreyk 62012a08440Sreyk trunc: 62112a08440Sreyk /* Truncated elements in frame */ 62212a08440Sreyk return (1); 62312a08440Sreyk } 62412a08440Sreyk 62512a08440Sreyk int 62612a08440Sreyk ieee80211_frame(struct ieee80211_frame *wh, u_int len) 62712a08440Sreyk { 62812a08440Sreyk u_int8_t subtype, type, *frm; 62912a08440Sreyk 63012a08440Sreyk TCARR(wh->i_fc); 63112a08440Sreyk 63212a08440Sreyk type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 63312a08440Sreyk subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 63412a08440Sreyk 63512a08440Sreyk frm = (u_int8_t *)&wh[1]; 63612a08440Sreyk 637ab7e388eSclaudio if (vflag) 638ab7e388eSclaudio printb(" flags", wh->i_fc[1], IEEE80211_FC1_BITS); 639ab7e388eSclaudio 64012a08440Sreyk switch (type) { 64112a08440Sreyk case IEEE80211_FC0_TYPE_DATA: 642ab7e388eSclaudio printf(": %s: ", ieee80211_data_subtype_name[ 643ab7e388eSclaudio subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]); 644b72abdefSreyk ieee80211_data(wh, len); 64512a08440Sreyk break; 64612a08440Sreyk case IEEE80211_FC0_TYPE_MGT: 64712a08440Sreyk printf(": %s", ieee80211_mgt_subtype_name[ 64812a08440Sreyk subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]); 64912a08440Sreyk switch (subtype) { 65012a08440Sreyk case IEEE80211_FC0_SUBTYPE_BEACON: 65112a08440Sreyk case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 65212a08440Sreyk if (ieee80211_elements(wh, len) != 0) 65312a08440Sreyk goto trunc; 65412a08440Sreyk break; 65512a08440Sreyk case IEEE80211_FC0_SUBTYPE_AUTH: 65612a08440Sreyk TCHECK2(*frm, 2); /* Auth Algorithm */ 65712a08440Sreyk switch (IEEE80211_AUTH_ALGORITHM(frm)) { 65812a08440Sreyk case IEEE80211_AUTH_ALG_OPEN: 65912a08440Sreyk TCHECK2(*frm, 4); /* Auth Transaction */ 66012a08440Sreyk switch (IEEE80211_AUTH_TRANSACTION(frm)) { 66112a08440Sreyk case IEEE80211_AUTH_OPEN_REQUEST: 66212a08440Sreyk printf(" request"); 66312a08440Sreyk break; 66412a08440Sreyk case IEEE80211_AUTH_OPEN_RESPONSE: 66512a08440Sreyk printf(" response"); 66612a08440Sreyk break; 66712a08440Sreyk } 66812a08440Sreyk break; 66912a08440Sreyk case IEEE80211_AUTH_ALG_SHARED: 67012a08440Sreyk TCHECK2(*frm, 4); /* Auth Transaction */ 67112a08440Sreyk switch (IEEE80211_AUTH_TRANSACTION(frm)) { 67212a08440Sreyk case IEEE80211_AUTH_SHARED_REQUEST: 67312a08440Sreyk printf(" request"); 67412a08440Sreyk break; 67512a08440Sreyk case IEEE80211_AUTH_SHARED_CHALLENGE: 67612a08440Sreyk printf(" challenge"); 67712a08440Sreyk break; 67812a08440Sreyk case IEEE80211_AUTH_SHARED_RESPONSE: 67912a08440Sreyk printf(" response"); 68012a08440Sreyk break; 68112a08440Sreyk case IEEE80211_AUTH_SHARED_PASS: 68212a08440Sreyk printf(" pass"); 68312a08440Sreyk break; 68412a08440Sreyk } 68512a08440Sreyk break; 68612a08440Sreyk case IEEE80211_AUTH_ALG_LEAP: 68712a08440Sreyk printf(" (leap)"); 68812a08440Sreyk break; 68912a08440Sreyk } 69012a08440Sreyk break; 69118786664Sclaudio case IEEE80211_FC0_SUBTYPE_DEAUTH: 69218786664Sclaudio case IEEE80211_FC0_SUBTYPE_DISASSOC: 69318786664Sclaudio TCHECK2(*frm, 2); /* Reason Code */ 69418786664Sclaudio ieee80211_reason(frm[0] | (frm[1] << 8)); 69518786664Sclaudio break; 69612a08440Sreyk } 69712a08440Sreyk break; 69812a08440Sreyk default: 69912a08440Sreyk printf(": type#%d", type); 70012a08440Sreyk break; 70112a08440Sreyk } 70212a08440Sreyk 70312a08440Sreyk return (0); 70412a08440Sreyk 70512a08440Sreyk trunc: 70612a08440Sreyk /* Truncated 802.11 frame */ 70712a08440Sreyk return (1); 70812a08440Sreyk } 70912a08440Sreyk 71012a08440Sreyk u_int 71112a08440Sreyk ieee80211_any2ieee(u_int freq, u_int flags) 71212a08440Sreyk { 71312a08440Sreyk if (flags & IEEE80211_CHAN_2GHZ) { 71412a08440Sreyk if (freq == 2484) 71512a08440Sreyk return 14; 71612a08440Sreyk if (freq < 2484) 71712a08440Sreyk return (freq - 2407) / 5; 71812a08440Sreyk else 71912a08440Sreyk return 15 + ((freq - 2512) / 20); 72012a08440Sreyk } else if (flags & IEEE80211_CHAN_5GHZ) { 72112a08440Sreyk return (freq - 5000) / 5; 72212a08440Sreyk } else { 72312a08440Sreyk /* Assume channel is already an IEEE number */ 72412a08440Sreyk return (freq); 72512a08440Sreyk } 72612a08440Sreyk } 72712a08440Sreyk 72812a08440Sreyk int 72912a08440Sreyk ieee80211_print(struct ieee80211_frame *wh, u_int len) 73012a08440Sreyk { 73112a08440Sreyk if (eflag) 73212a08440Sreyk if (ieee80211_hdr(wh)) 73312a08440Sreyk return (1); 73412a08440Sreyk 73512a08440Sreyk printf("802.11"); 73612a08440Sreyk 73712a08440Sreyk return (ieee80211_frame(wh, len)); 73812a08440Sreyk } 73912a08440Sreyk 74012a08440Sreyk void 74112a08440Sreyk ieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h, 74212a08440Sreyk const u_char *p) 74312a08440Sreyk { 74412a08440Sreyk struct ieee80211_frame *wh = (struct ieee80211_frame*)p; 74512a08440Sreyk 746c79cf170Sreyk if (!ieee80211_encap) 74712a08440Sreyk ts_print(&h->ts); 74812a08440Sreyk 74912a08440Sreyk packetp = p; 75012a08440Sreyk snapend = p + h->caplen; 75112a08440Sreyk 752a0774ae9Smglocker if (ieee80211_print(wh, (u_int)h->len) != 0) 75312a08440Sreyk printf("[|802.11]"); 75412a08440Sreyk 755c79cf170Sreyk if (!ieee80211_encap) { 75612a08440Sreyk if (xflag) 757a0774ae9Smglocker default_print(p, (u_int)h->len); 75812a08440Sreyk putchar('\n'); 75912a08440Sreyk } 760c79cf170Sreyk } 76112a08440Sreyk 76212a08440Sreyk void 76312a08440Sreyk ieee802_11_radio_if_print(u_char *user, const struct pcap_pkthdr *h, 76412a08440Sreyk const u_char *p) 76512a08440Sreyk { 76612a08440Sreyk struct ieee80211_radiotap_header *rh = 76712a08440Sreyk (struct ieee80211_radiotap_header*)p; 76812a08440Sreyk struct ieee80211_frame *wh; 76912a08440Sreyk u_int8_t *t; 77012a08440Sreyk u_int32_t present; 77112a08440Sreyk u_int len, rh_len; 772cce1ba42Sclaudio u_int16_t tmp; 77312a08440Sreyk 774c79cf170Sreyk if (!ieee80211_encap) 77512a08440Sreyk ts_print(&h->ts); 77612a08440Sreyk 77712a08440Sreyk packetp = p; 77812a08440Sreyk snapend = p + h->caplen; 77912a08440Sreyk 78012a08440Sreyk TCHECK(*rh); 78112a08440Sreyk 782a0774ae9Smglocker len = h->len; 78312a08440Sreyk rh_len = letoh16(rh->it_len); 78412a08440Sreyk if (rh->it_version != 0) { 785c79cf170Sreyk printf("[?radiotap + 802.11 v:%u]", rh->it_version); 78612a08440Sreyk goto out; 78712a08440Sreyk } 78812a08440Sreyk 78912a08440Sreyk wh = (struct ieee80211_frame *)(p + rh_len); 79012a08440Sreyk if (len <= rh_len || ieee80211_print(wh, len - rh_len)) 79112a08440Sreyk printf("[|802.11]"); 79212a08440Sreyk 79312a08440Sreyk t = (u_int8_t*)p + sizeof(struct ieee80211_radiotap_header); 79412a08440Sreyk 79512a08440Sreyk if ((present = letoh32(rh->it_present)) == 0) 79612a08440Sreyk goto out; 79712a08440Sreyk 79812a08440Sreyk printf(", <radiotap v%u", rh->it_version); 79912a08440Sreyk 80012a08440Sreyk #define RADIOTAP(_x) \ 80112a08440Sreyk (present & (1 << IEEE80211_RADIOTAP_##_x)) 80212a08440Sreyk 80312a08440Sreyk if (RADIOTAP(TSFT)) { 804cce1ba42Sclaudio u_int64_t tsf; 805cce1ba42Sclaudio 80612a08440Sreyk TCHECK2(*t, 8); 807cce1ba42Sclaudio bcopy(t, &tsf, sizeof(u_int64_t)); 80812a08440Sreyk if (vflag > 1) 809cce1ba42Sclaudio printf(", tsf %llu", letoh64(tsf)); 81012a08440Sreyk t += 8; 81112a08440Sreyk } 81212a08440Sreyk 81312a08440Sreyk if (RADIOTAP(FLAGS)) { 81412a08440Sreyk u_int8_t flags = *(u_int8_t*)t; 815026ca542Sderaadt TCHECK2(*t, 1); 816026ca542Sderaadt 81712a08440Sreyk if (flags & IEEE80211_RADIOTAP_F_CFP) 81812a08440Sreyk printf(", CFP"); 81912a08440Sreyk if (flags & IEEE80211_RADIOTAP_F_SHORTPRE) 82012a08440Sreyk printf(", SHORTPRE"); 82112a08440Sreyk if (flags & IEEE80211_RADIOTAP_F_WEP) 82212a08440Sreyk printf(", WEP"); 82312a08440Sreyk if (flags & IEEE80211_RADIOTAP_F_FRAG) 82412a08440Sreyk printf(", FRAG"); 82512a08440Sreyk t += 1; 82612a08440Sreyk } 82712a08440Sreyk 82812a08440Sreyk if (RADIOTAP(RATE)) { 82912a08440Sreyk TCHECK2(*t, 1); 83012a08440Sreyk if (vflag) 83112a08440Sreyk printf(", %uMbit/s", (*(u_int8_t*)t) / 2); 83212a08440Sreyk t += 1; 83312a08440Sreyk } 83412a08440Sreyk 83512a08440Sreyk if (RADIOTAP(CHANNEL)) { 83612a08440Sreyk u_int16_t freq, flags; 83712a08440Sreyk TCHECK2(*t, 2); 83812a08440Sreyk 839cce1ba42Sclaudio bcopy(t, &freq, sizeof(u_int16_t)); 840cce1ba42Sclaudio freq = letoh16(freq); 84112a08440Sreyk t += 2; 84212a08440Sreyk TCHECK2(*t, 2); 843cce1ba42Sclaudio bcopy(t, &flags, sizeof(u_int16_t)); 844cce1ba42Sclaudio flags = letoh16(flags); 84512a08440Sreyk t += 2; 84612a08440Sreyk 84712a08440Sreyk printf(", chan %u", ieee80211_any2ieee(freq, flags)); 84812a08440Sreyk 84912a08440Sreyk if (flags & IEEE80211_CHAN_DYN && 85012a08440Sreyk flags & IEEE80211_CHAN_2GHZ) 85112a08440Sreyk printf(", 11g"); 85212a08440Sreyk else if (flags & IEEE80211_CHAN_CCK && 85312a08440Sreyk flags & IEEE80211_CHAN_2GHZ) 85412a08440Sreyk printf(", 11b"); 85512a08440Sreyk else if (flags & IEEE80211_CHAN_OFDM && 85612a08440Sreyk flags & IEEE80211_CHAN_2GHZ) 85712a08440Sreyk printf(", 11G"); 85812a08440Sreyk else if (flags & IEEE80211_CHAN_OFDM && 85912a08440Sreyk flags & IEEE80211_CHAN_5GHZ) 86012a08440Sreyk printf(", 11a"); 86112a08440Sreyk 86212a08440Sreyk if (flags & IEEE80211_CHAN_TURBO) 86312a08440Sreyk printf(", TURBO"); 86412a08440Sreyk if (flags & IEEE80211_CHAN_XR) 86512a08440Sreyk printf(", XR"); 86612a08440Sreyk } 86712a08440Sreyk 86812a08440Sreyk if (RADIOTAP(FHSS)) { 86912a08440Sreyk TCHECK2(*t, 2); 87012a08440Sreyk printf(", fhss %u/%u", *(u_int8_t*)t, *(u_int8_t*)t + 1); 87112a08440Sreyk t += 2; 87212a08440Sreyk } 87312a08440Sreyk 87412a08440Sreyk if (RADIOTAP(DBM_ANTSIGNAL)) { 87512a08440Sreyk TCHECK(*t); 87612a08440Sreyk printf(", sig %ddBm", *(int8_t*)t); 87712a08440Sreyk t += 1; 87812a08440Sreyk } 87912a08440Sreyk 88012a08440Sreyk if (RADIOTAP(DBM_ANTNOISE)) { 88112a08440Sreyk TCHECK(*t); 88212a08440Sreyk printf(", noise %ddBm", *(int8_t*)t); 88312a08440Sreyk t += 1; 88412a08440Sreyk } 88512a08440Sreyk 88612a08440Sreyk if (RADIOTAP(LOCK_QUALITY)) { 88712a08440Sreyk TCHECK2(*t, 2); 888cce1ba42Sclaudio if (vflag) { 889cce1ba42Sclaudio bcopy(t, &tmp, sizeof(u_int16_t)); 890cce1ba42Sclaudio printf(", quality %u", letoh16(tmp)); 891cce1ba42Sclaudio } 89212a08440Sreyk t += 2; 89312a08440Sreyk } 89412a08440Sreyk 89512a08440Sreyk if (RADIOTAP(TX_ATTENUATION)) { 89612a08440Sreyk TCHECK2(*t, 2); 897cce1ba42Sclaudio if (vflag) { 898cce1ba42Sclaudio bcopy(t, &tmp, sizeof(u_int16_t)); 899cce1ba42Sclaudio printf(", txatt %u", letoh16(tmp)); 900cce1ba42Sclaudio } 90112a08440Sreyk t += 2; 90212a08440Sreyk } 90312a08440Sreyk 90412a08440Sreyk if (RADIOTAP(DB_TX_ATTENUATION)) { 90512a08440Sreyk TCHECK2(*t, 2); 906cce1ba42Sclaudio if (vflag) { 907cce1ba42Sclaudio bcopy(t, &tmp, sizeof(u_int16_t)); 908cce1ba42Sclaudio printf(", txatt %udB", letoh16(tmp)); 909cce1ba42Sclaudio } 91012a08440Sreyk t += 2; 91112a08440Sreyk } 91212a08440Sreyk 91312a08440Sreyk if (RADIOTAP(DBM_TX_POWER)) { 91412a08440Sreyk TCHECK(*t); 91512a08440Sreyk printf(", txpower %ddBm", *(int8_t*)t); 91612a08440Sreyk t += 1; 91712a08440Sreyk } 91812a08440Sreyk 91912a08440Sreyk if (RADIOTAP(ANTENNA)) { 92012a08440Sreyk TCHECK(*t); 92112a08440Sreyk if (vflag) 92212a08440Sreyk printf(", antenna %u", *(u_int8_t*)t); 92312a08440Sreyk t += 1; 92412a08440Sreyk } 92512a08440Sreyk 92612a08440Sreyk if (RADIOTAP(DB_ANTSIGNAL)) { 92712a08440Sreyk TCHECK(*t); 92812a08440Sreyk printf(", signal %udB", *(u_int8_t*)t); 92912a08440Sreyk t += 1; 93012a08440Sreyk } 93112a08440Sreyk 93212a08440Sreyk if (RADIOTAP(DB_ANTNOISE)) { 93312a08440Sreyk TCHECK(*t); 93412a08440Sreyk printf(", noise %udB", *(u_int8_t*)t); 93512a08440Sreyk t += 1; 93612a08440Sreyk } 93712a08440Sreyk 93812a08440Sreyk if (RADIOTAP(FCS)) { 93912a08440Sreyk TCHECK2(*t, 4); 940cce1ba42Sclaudio if (vflag) { 941cce1ba42Sclaudio u_int32_t fcs; 942cce1ba42Sclaudio bcopy(t, &fcs, sizeof(u_int32_t)); 943cce1ba42Sclaudio printf(", fcs %08x", letoh32(fcs)); 944cce1ba42Sclaudio } 94512a08440Sreyk t += 4; 94612a08440Sreyk } 94712a08440Sreyk 9486fc94ee3Sreyk if (RADIOTAP(RSSI)) { 9496fc94ee3Sreyk u_int8_t rssi, max_rssi; 9506fc94ee3Sreyk TCHECK(*t); 9516fc94ee3Sreyk rssi = *(u_int8_t*)t; 9526fc94ee3Sreyk t += 1; 9536fc94ee3Sreyk TCHECK(*t); 9546fc94ee3Sreyk max_rssi = *(u_int8_t*)t; 9556fc94ee3Sreyk t += 1; 9566fc94ee3Sreyk 9576fc94ee3Sreyk printf(", rssi %u/%u", rssi, max_rssi); 9586fc94ee3Sreyk } 9596fc94ee3Sreyk 96012a08440Sreyk #undef RADIOTAP 96112a08440Sreyk 96212a08440Sreyk putchar('>'); 96312a08440Sreyk goto out; 96412a08440Sreyk 96512a08440Sreyk trunc: 96612a08440Sreyk /* Truncated frame */ 96712a08440Sreyk printf("[|radiotap + 802.11]"); 96812a08440Sreyk 96912a08440Sreyk out: 970c79cf170Sreyk if (!ieee80211_encap) { 97112a08440Sreyk if (xflag) 972a0774ae9Smglocker default_print(p, h->len); 97312a08440Sreyk putchar('\n'); 97412a08440Sreyk } 975c79cf170Sreyk } 97618786664Sclaudio 97718786664Sclaudio void 97818786664Sclaudio ieee80211_reason(u_int16_t reason) 97918786664Sclaudio { 98018786664Sclaudio if (!vflag) 98118786664Sclaudio return; 98218786664Sclaudio 98318786664Sclaudio switch (reason) { 98418786664Sclaudio case IEEE80211_REASON_UNSPECIFIED: 98518786664Sclaudio printf(", unspecified failure"); 98618786664Sclaudio break; 98718786664Sclaudio case IEEE80211_REASON_AUTH_EXPIRE: 98818786664Sclaudio printf(", authentication expired"); 98918786664Sclaudio break; 99018786664Sclaudio case IEEE80211_REASON_AUTH_LEAVE: 99118786664Sclaudio printf(", deauth - station left"); 99218786664Sclaudio break; 99318786664Sclaudio case IEEE80211_REASON_ASSOC_EXPIRE: 99418786664Sclaudio printf(", association expired"); 99518786664Sclaudio break; 99618786664Sclaudio case IEEE80211_REASON_ASSOC_TOOMANY: 99718786664Sclaudio printf(", too many associated stations"); 99818786664Sclaudio break; 99918786664Sclaudio case IEEE80211_REASON_NOT_AUTHED: 100018786664Sclaudio printf(", not authenticated"); 100118786664Sclaudio break; 100218786664Sclaudio case IEEE80211_REASON_NOT_ASSOCED: 100318786664Sclaudio printf(", not associated"); 100418786664Sclaudio break; 100518786664Sclaudio case IEEE80211_REASON_ASSOC_LEAVE: 100618786664Sclaudio printf(", disassociated - station left"); 100718786664Sclaudio break; 100818786664Sclaudio case IEEE80211_REASON_ASSOC_NOT_AUTHED: 100918786664Sclaudio printf(", association but not authenticated"); 101018786664Sclaudio break; 101118786664Sclaudio case IEEE80211_REASON_RSN_REQUIRED: 101218786664Sclaudio printf(", rsn required"); 101318786664Sclaudio break; 101418786664Sclaudio case IEEE80211_REASON_RSN_INCONSISTENT: 101518786664Sclaudio printf(", rsn inconsistent"); 101618786664Sclaudio break; 101718786664Sclaudio case IEEE80211_REASON_IE_INVALID: 101818786664Sclaudio printf(", ie invalid"); 101918786664Sclaudio break; 102018786664Sclaudio case IEEE80211_REASON_MIC_FAILURE: 102118786664Sclaudio printf(", mic failure"); 102218786664Sclaudio break; 102318786664Sclaudio default: 102418786664Sclaudio printf(", unknown reason %u", reason); 102518786664Sclaudio } 102618786664Sclaudio } 1027