int parse_80211_header(const u_char* buf, int len, struct packet_info* p) { struct ieee80211_hdr* wh; int hdrlen; uint8_t *sa = NULL; uint8_t *da = NULL; u16 fc; if (len < 2) return -1; wh = (struct ieee80211_hdr*)buf; fc = le16toh(wh->frame_control); hdrlen = ieee80211_get_hdrlen(fc); DEBUG("len %d hdrlen %d\n", len, hdrlen); if (len < hdrlen) return -1; p->wlan_len = len; p->wlan_type = (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)); switch (p->wlan_type & IEEE80211_FCTL_FTYPE) { case IEEE80211_FTYPE_DATA: p->pkt_types = PKT_TYPE_DATA; switch (p->wlan_type & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_NULLFUNC: p->pkt_types |= PKT_TYPE_NULL; break; case IEEE80211_STYPE_QOS_DATA: /* TODO: ouch, should properly define a qos header */ p->wlan_qos_class = wh->addr4[0] & 0x7; DEBUG("***QDATA %x\n", p->wlan_qos_class); break; } sa = ieee80211_get_SA(wh); da = ieee80211_get_DA(wh); p->wlan_seqno = le16toh(wh->seq_ctrl) / 16; if (fc & IEEE80211_FCTL_PROTECTED) p->wlan_wep = 1; if (fc & IEEE80211_FCTL_RETRY) p->wlan_retry = 1; break; case IEEE80211_FTYPE_CTL: p->pkt_types = PKT_TYPE_CTRL; DEBUG("CTL\n"); switch (p->wlan_type & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_RTS: p->pkt_types |= PKT_TYPE_RTS; p->wlan_nav = le16toh(wh->duration_id); DEBUG("RTS NAV %d\n", p->wlan_nav); sa = wh->addr2; da = wh->addr1; break; case IEEE80211_STYPE_CTS: p->pkt_types |= PKT_TYPE_CTS; p->wlan_nav = le16toh(wh->duration_id); DEBUG("CTS NAV %d\n", p->wlan_nav); da = wh->addr1; break; case IEEE80211_STYPE_ACK: p->pkt_types |= PKT_TYPE_ACK; p->wlan_nav = le16toh(wh->duration_id); DEBUG("ACK NAV %d\n", p->wlan_nav); da = wh->addr1; break; case IEEE80211_STYPE_PSPOLL: sa = wh->addr2; break; case IEEE80211_STYPE_CFEND: da = wh->addr1; sa = wh->addr2; break; case IEEE80211_STYPE_CFENDACK: /* dont know, dont care */ break; } break; case IEEE80211_FTYPE_MGMT: p->pkt_types = PKT_TYPE_MGMT; DEBUG("MGMT\n"); break; } if (sa != NULL) { memcpy(p->wlan_src, sa, 6); DEBUG("SA %s\n", ether_sprintf(sa)); } if (da != NULL) { memcpy(p->wlan_dst, da, 6); DEBUG("DA %s\n", ether_sprintf(da)); } DEBUG("%s\n", get_packet_type_name(fc)); return 0; }
/* return rest of packet length (may be 0) or -1 on error */ static int parse_80211_header(unsigned char** buf, int len, struct packet_info* p) { struct wlan_frame* wh; int hdrlen; u_int8_t* ra = NULL; u_int8_t* ta = NULL; u_int8_t* bssid = NULL; u_int16_t fc, cap_i; if (len < 10) /* minimum frame size (CTS/ACK) */ return -1; p->wlan_mode = WLAN_MODE_UNKNOWN; wh = (struct wlan_frame*)*buf; fc = le16toh(wh->fc); p->wlan_type = (fc & WLAN_FRAME_FC_MASK); DEBUG("wlan_type %x - type %x - stype %x\n", fc, fc & WLAN_FRAME_FC_TYPE_MASK, fc & WLAN_FRAME_FC_STYPE_MASK); DEBUG("%s\n", get_packet_type_name(fc)); if (WLAN_FRAME_IS_DATA(fc)) { p->pkt_types |= PKT_TYPE_DATA; hdrlen = 24; if (WLAN_FRAME_IS_QOS(fc)) { hdrlen += 2; if (fc & WLAN_FRAME_FC_ORDER) hdrlen += 4; } /* AP, STA or IBSS */ if ((fc & WLAN_FRAME_FC_FROM_DS) == 0 && (fc & WLAN_FRAME_FC_TO_DS) == 0) { p->wlan_mode = WLAN_MODE_IBSS; bssid = wh->addr3; } else if ((fc & WLAN_FRAME_FC_FROM_DS) && (fc & WLAN_FRAME_FC_TO_DS)) { p->wlan_mode = WLAN_MODE_4ADDR; hdrlen += 6; if (WLAN_FRAME_IS_QOS(fc)) { u_int16_t qos = le16toh(wh->u.addr4_qos_ht.qos); DEBUG("4ADDR A-MSDU %x\n", qos & WLAN_FRAME_QOS_AMSDU_PRESENT); if (qos & WLAN_FRAME_QOS_AMSDU_PRESENT) bssid = wh->addr3; // in the MSDU case BSSID is unknown } } else if (fc & WLAN_FRAME_FC_FROM_DS) { p->wlan_mode = WLAN_MODE_AP; bssid = wh->addr2; } else if (fc & WLAN_FRAME_FC_TO_DS) { p->wlan_mode = WLAN_MODE_STA; bssid = wh->addr1; } if (len < hdrlen) return -1; p->wlan_nav = le16toh(wh->duration); DEBUG("DATA NAV %d\n", p->wlan_nav); p->wlan_seqno = le16toh(wh->seq); DEBUG("DATA SEQ %d\n", p->wlan_seqno); DEBUG("A1 %s\n", ether_sprintf(wh->addr1)); DEBUG("A2 %s\n", ether_sprintf(wh->addr2)); DEBUG("A3 %s\n", ether_sprintf(wh->addr3)); if (p->wlan_mode == WLAN_MODE_4ADDR) { DEBUG("A4 %s\n", ether_sprintf(wh->u.addr4)); } DEBUG("ToDS %d FromDS %d\n", (fc & WLAN_FRAME_FC_FROM_DS) != 0, (fc & WLAN_FRAME_FC_TO_DS) != 0); ra = wh->addr1; ta = wh->addr2; /* WEP */ if (fc & WLAN_FRAME_FC_PROTECTED) p->wlan_wep = 1; if (fc & WLAN_FRAME_FC_RETRY) p->wlan_retry = 1; } else if (WLAN_FRAME_IS_CTRL(fc)) { p->pkt_types |= PKT_TYPE_CTRL; if (p->wlan_type == WLAN_FRAME_CTS || p->wlan_type == WLAN_FRAME_ACK) hdrlen = 10; else hdrlen = 16; if (len < hdrlen) return -1; } else if (WLAN_FRAME_IS_MGMT(fc)) { p->pkt_types |= PKT_TYPE_MGMT; hdrlen = 24; if (fc & WLAN_FRAME_FC_ORDER) hdrlen += 4; if (len < hdrlen) return -1; ra = wh->addr1; ta = wh->addr2; bssid = wh->addr3; p->wlan_seqno = le16toh(wh->seq); DEBUG("MGMT SEQ %d\n", p->wlan_seqno); if (fc & WLAN_FRAME_FC_RETRY) p->wlan_retry = 1; } else { DEBUG("!!!UNKNOWN FRAME!!!"); return -1; } p->wlan_len = len; switch (p->wlan_type) { case WLAN_FRAME_NULL: p->pkt_types |= PKT_TYPE_NULL; break; case WLAN_FRAME_QDATA: p->pkt_types |= PKT_TYPE_QDATA; p->wlan_qos_class = le16toh(wh->u.qos) & WLAN_FRAME_QOS_TID_MASK; DEBUG("***QDATA %x\n", p->wlan_qos_class); break; case WLAN_FRAME_RTS: p->pkt_types |= PKT_TYPE_RTSCTS; p->wlan_nav = le16toh(wh->duration); DEBUG("RTS NAV %d\n", p->wlan_nav); ra = wh->addr1; ta = wh->addr2; break; case WLAN_FRAME_CTS: p->pkt_types |= PKT_TYPE_RTSCTS; p->wlan_nav = le16toh(wh->duration); DEBUG("CTS NAV %d\n", p->wlan_nav); ra = wh->addr1; break; case WLAN_FRAME_ACK: p->pkt_types |= PKT_TYPE_ACK; p->wlan_nav = le16toh(wh->duration); DEBUG("ACK NAV %d\n", p->wlan_nav); ra = wh->addr1; break; case WLAN_FRAME_PSPOLL: ra = wh->addr1; bssid = wh->addr1; ta = wh->addr2; break; case WLAN_FRAME_CF_END: case WLAN_FRAME_CF_END_ACK: ra = wh->addr1; ta = wh->addr2; bssid = wh->addr2; break; case WLAN_FRAME_BLKACK: case WLAN_FRAME_BLKACK_REQ: p->pkt_types |= PKT_TYPE_ACK; p->wlan_nav = le16toh(wh->duration); ra = wh->addr1; ta = wh->addr2; break; case WLAN_FRAME_BEACON: case WLAN_FRAME_PROBE_RESP: if (p->wlan_type == WLAN_FRAME_BEACON) p->pkt_types |= PKT_TYPE_BEACON; else p->pkt_types |= PKT_TYPE_PROBE; struct wlan_frame_beacon* bc = (struct wlan_frame_beacon*)(*buf + hdrlen); p->wlan_tsf = le64toh(bc->tsf); p->wlan_bintval = le16toh(bc->bintval); //DEBUG("TSF %u\n BINTVAL %u", p->wlan_tsf, p->wlan_bintval); wlan_parse_information_elements(bc->ie, len - hdrlen - sizeof(struct wlan_frame_beacon) - 4 /* FCS */, p); DEBUG("ESSID %s \n", p->wlan_essid ); DEBUG("CHAN %d \n", p->wlan_channel ); cap_i = le16toh(bc->capab); if (cap_i & WLAN_CAPAB_IBSS) p->wlan_mode = WLAN_MODE_IBSS; else if (cap_i & WLAN_CAPAB_ESS) p->wlan_mode = WLAN_MODE_AP; if (cap_i & WLAN_CAPAB_PRIVACY) p->wlan_wep = 1; break; case WLAN_FRAME_PROBE_REQ: p->pkt_types |= PKT_TYPE_PROBE; wlan_parse_information_elements((*buf + hdrlen), len - hdrlen - 4 /* FCS */, p); p->wlan_mode = WLAN_MODE_PROBE; break; case WLAN_FRAME_ASSOC_REQ: case WLAN_FRAME_ASSOC_RESP: case WLAN_FRAME_REASSOC_REQ: case WLAN_FRAME_REASSOC_RESP: case WLAN_FRAME_DISASSOC: p->pkt_types |= PKT_TYPE_ASSOC; break; case WLAN_FRAME_AUTH: if (fc & WLAN_FRAME_FC_PROTECTED) p->wlan_wep = 1; /* no break */ case WLAN_FRAME_DEAUTH: p->pkt_types |= PKT_TYPE_AUTH; break; case WLAN_FRAME_ACTION: break; } if (ta != NULL) { memcpy(p->wlan_src, ta, MAC_LEN); DEBUG("TA %s\n", ether_sprintf(ta)); } if (ra != NULL) { memcpy(p->wlan_dst, ra, MAC_LEN); DEBUG("RA %s\n", ether_sprintf(ra)); } if (bssid != NULL) { memcpy(p->wlan_bssid, bssid, MAC_LEN); DEBUG("BSSID %s\n", ether_sprintf(bssid)); } /* only data frames contain more info, otherwise stop parsing */ if (WLAN_FRAME_IS_DATA(p->wlan_type) && p->wlan_wep != 1) { *buf = *buf + hdrlen; return len - hdrlen; } return 0; }
void update_statistics_win(WINDOW *win) { int i; int line; int bps, dps, pps, rps; float duration; werase(win); wattron(win, WHITE); box(win, 0 , 0); print_centered(win, 0, COLS, " Packet Statistics "); if (stats.packets == 0) { wnoutrefresh(win); return; /* avoid floating point exceptions */ } mvwprintw(win, 2, 2, "Packets: %d", stats.packets ); mvwprintw(win, 3, 2, "Bytes: %s (%d)", kilo_mega_ize(stats.bytes), stats.bytes ); mvwprintw(win, 4, 2, "Average: ~%d B/Pkt", stats.bytes / stats.packets); mvwprintw(win, 2, 40, "Retries: %3.1f%% (%d)", stats.retries * 100.0 / stats.packets, stats.retries); get_per_second(stats.bytes, stats.duration, stats.packets, stats.retries, &bps, &dps, &pps, &rps); bps = bps * 8; mvwprintw(win, 3, 40, "Total bit/sec: %s (%d)", kilo_mega_ize(bps), bps); wattron(win, A_BOLD); mvwprintw(win, 4, 40, "Total Usage: %3.1f%% (%d)", dps * 1.0 / 10000, dps ); /* usec in % */ wattroff(win, A_BOLD); line = 6; mvwprintw(win, line, STAT_PACK_POS, " Packets"); mvwprintw(win, line, STAT_BYTE_POS, " Bytes"); mvwprintw(win, line, STAT_BPP_POS, "~B/P"); mvwprintw(win, line, STAT_PP_POS, "Pkts%%"); mvwprintw(win, line, STAT_BP_POS, "Byte%%"); wattron(win, A_BOLD); mvwprintw(win, line, STAT_AIR_POS, "Usage%%"); mvwprintw(win, line++, 2, "RATE"); wattroff(win, A_BOLD); mvwhline(win, line++, 2, '-', COLS-4); for (i = 1; i < MAX_RATES && line < LINES - 2; i++) { if (stats.packets_per_rate[i] > 0) { wattron(win, A_BOLD); if (i <= 12) mvwprintw(win, line, 2, "%3dM", rate_index_to_rate(i)/10); else mvwprintw(win, line, 2, "MCS%d", i - 12); wattroff(win, A_BOLD); mvwprintw(win, line, STAT_PACK_POS, "%8d", stats.packets_per_rate[i]); mvwprintw(win, line, STAT_BYTE_POS, "%8s", kilo_mega_ize(stats.bytes_per_rate[i])); mvwprintw(win, line, STAT_BPP_POS, "%4d", stats.bytes_per_rate[i] / stats.packets_per_rate[i]); mvwprintw(win, line, STAT_PP_POS, "%2.1f", stats.packets_per_rate[i] * 100.0 / stats.packets); mvwprintw(win, line, STAT_BP_POS, "%2.1f", stats.bytes_per_rate[i] * 100.0 / stats.bytes); wattron(win, A_BOLD); duration = stats.duration_per_rate[i] * 100.0 / stats.duration; mvwprintw(win, line, STAT_AIR_POS, "%2.1f", duration); mvwhline(win, line, STAT_AIRG_POS, '*', normalize(duration, 100, COLS - STAT_AIRG_POS - 2)); wattroff(win, A_BOLD); line++; } } line++; if (line < LINES - 2) { mvwprintw(win, line, STAT_PACK_POS, " Packets"); mvwprintw(win, line, STAT_BYTE_POS, " Bytes"); mvwprintw(win, line, STAT_BPP_POS, "~B/P"); mvwprintw(win, line, STAT_PP_POS, "Pkts%%"); mvwprintw(win, line, STAT_BP_POS, "Byte%%"); wattron(win, A_BOLD); mvwprintw(win, line, STAT_AIR_POS, "Usage%%"); mvwprintw(win, line++, 2, "TYPE"); wattroff(win, A_BOLD); } if (line < LINES - 2) mvwhline(win, line++, 2, '-', COLS - 4); for (i = 0; i < MAX_FSTYPE && line < LINES - 2; i++) { if (stats.packets_per_type[i] > 0) { wattron(win, get_packet_type_color(i)); wattron(win, A_BOLD); mvwprintw(win, line, 2, "%s", get_packet_type_name(i)); wattroff(win, A_BOLD); mvwprintw(win, line, STAT_PACK_POS, "%8d", stats.packets_per_type[i]); mvwprintw(win, line, STAT_BYTE_POS, "%8s", kilo_mega_ize(stats.bytes_per_type[i])); mvwprintw(win, line, STAT_BPP_POS, "%4d", stats.bytes_per_type[i] / stats.packets_per_type[i]); mvwprintw(win, line, STAT_PP_POS, "%2.1f", stats.packets_per_type[i] * 100.0 / stats.packets); mvwprintw(win, line, STAT_BP_POS, "%2.1f", stats.bytes_per_type[i] * 100.0 / stats.bytes); wattron(win, A_BOLD); if (stats.duration > 0) duration = stats.duration_per_type[i] * 100.0 / stats.duration; else duration = 100.0; mvwprintw(win, line, STAT_AIR_POS, "%2.1f", duration); mvwhline(win, line, STAT_AIRG_POS, '*', normalize(duration, 100, COLS - STAT_AIRG_POS - 2)); wattroff(win, A_BOLD); line++; } } wnoutrefresh(win); }