static int hostapd_setup_encryption(hostapd *hapd) { if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) hostapd_hexdump("Default WEP key", hapd->default_wep_key, hapd->conf->default_wep_key_len); hostapd_set_encryption(hapd->driver.data, "none", NULL, 0, NULL, 0); if (hostapd_set_encryption(hapd->driver.data, "WEP", NULL, hapd->default_wep_key_idx, hapd->default_wep_key, hapd->conf->default_wep_key_len)) { printf("Could not set WEP encryption.\n"); return -1; } /* Setup rekeying timer. */ if (hapd->conf->wep_rekeying_period > 0 && (hapd->default_wep_key || hapd->conf->individual_wep_key_len > 0) && eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, hostapd_rotate_wep, hapd, NULL)) { printf("Couldn't set rekeying timer.\n"); return -1; } return 0; }
int radius_client_send(struct radius_client_data *radius, struct radius_msg *msg, RadiusType msg_type, u8 *addr) { struct hostapd_data *hapd = radius->hapd; u8 *shared_secret; size_t shared_secret_len; char *name; int s, res; if (msg_type == RADIUS_ACCT_INTERIM) { /* Remove any pending interim acct update for the same STA. */ radius_client_list_del(radius, msg_type, addr); } if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { shared_secret = hapd->conf->acct_server->shared_secret; shared_secret_len = hapd->conf->acct_server->shared_secret_len; radius_msg_finish_acct(msg, shared_secret, shared_secret_len); name = "accounting"; s = radius->acct_serv_sock; hapd->conf->acct_server->requests++; } else { shared_secret = hapd->conf->auth_server->shared_secret; shared_secret_len = hapd->conf->auth_server->shared_secret_len; radius_msg_finish(msg, shared_secret, shared_secret_len); name = "authentication"; s = radius->auth_serv_sock; hapd->conf->auth_server->requests++; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Sending RADIUS message to %s server\n", name); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) radius_msg_dump(msg); res = send(s, msg->buf, msg->buf_used, 0); if (res < 0) radius_client_handle_send_error(radius, s, msg_type); radius_client_list_add(radius, msg, msg_type, shared_secret, shared_secret_len, addr); return res; }
static int bsd_send_eapol(void *priv, u8 *addr, u8 *data, size_t data_len, int encrypt) { struct bsd_driver_data *drv = priv; hostapd *hapd = drv->hapd; unsigned char buf[3000]; unsigned char *bp = buf; struct l2_ethhdr *eth; size_t len; int status; /* * Prepend the Etherent header. If the caller left us * space at the front we could just insert it but since * we don't know we copy to a local buffer. Given the frequency * and size of frames this probably doesn't matter. */ len = data_len + sizeof(struct l2_ethhdr); if (len > sizeof(buf)) { bp = malloc(len); if (bp == NULL) { printf("EAPOL frame discarded, cannot malloc temp " "buffer of size %u!\n", len); return -1; } } eth = (struct l2_ethhdr *) bp; memcpy(eth->h_dest, addr, ETH_ALEN); memcpy(eth->h_source, drv->hapd->own_addr, ETH_ALEN); eth->h_proto = htons(ETH_P_EAPOL); memcpy(eth+1, data, data_len); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) hostapd_hexdump("TX EAPOL", bp, len); status = l2_packet_send(drv->sock_xmit, bp, len); if (bp != buf) free(bp); return status; }
int radius_client_send(struct wpa_supplicant *wpa_s, struct radius_msg *msg, RadiusType msg_type, u8 *addr) { u8 *shared_secret; size_t shared_secret_len; char *name; int s, res; if (msg_type == RADIUS_ACCT_INTERIM) { /* Remove any pending interim acct update for the same STA. */ radius_client_list_del(wpa_s, msg_type, addr); } if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { shared_secret = wpa_s->acct_server->shared_secret; shared_secret_len = wpa_s->acct_server->shared_secret_len; radius_msg_finish_acct(msg, shared_secret, shared_secret_len); name = "accounting"; s = wpa_s->radius->acct_serv_sock; } else { shared_secret = wpa_s->auth_server->shared_secret; shared_secret_len = wpa_s->auth_server->shared_secret_len; radius_msg_finish(msg, shared_secret, shared_secret_len); name = "authentication"; s = wpa_s->radius->auth_serv_sock; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Sending RADIUS message to %s server\n", name); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) radius_msg_dump(msg); res = send(s, msg->buf, msg->buf_used, 0); if (res < 0) perror("send[RADIUS]"); radius_client_list_add(wpa_s, msg, msg_type, shared_secret, shared_secret_len, addr); return res; }
static void handle_beacon(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len) { struct ieee802_11_elems elems; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) { printf("handle_beacon - too short payload (len=%lu)\n", (unsigned long) len); return; } (void) ieee802_11_parse_elems(hapd, mgmt->u.beacon.variable, len - (IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)), &elems, 0); if (hapd->assoc_ap_state == WAIT_BEACON && memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) { if (elems.ssid && elems.ssid_len <= 32) { memcpy(hapd->assoc_ap_ssid, elems.ssid, elems.ssid_len); hapd->assoc_ap_ssid[elems.ssid_len] = '\0'; hapd->assoc_ap_ssid_len = elems.ssid_len; } ieee802_11_sta_authenticate(hapd, NULL); } if (!HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_EXCESSIVE)) return; printf("Beacon from " MACSTR, MAC2STR(mgmt->sa)); if (elems.ssid) { printf(" SSID='"); ieee802_11_print_ssid(elems.ssid, elems.ssid_len); printf("'"); } if (elems.ds_params && elems.ds_params_len == 1) printf(" CHAN=%d", elems.ds_params[0]); printf("\n"); }
/* The rekeying function: generate a new broadcast WEP key, rotate * the key index, and direct Key Transmit State Machines of all of the * authenticators to send a new key to the authenticated stations. */ static void hostapd_rotate_wep(void *eloop_ctx, void *timeout_ctx) { struct sta_info *s; hostapd *hapd = eloop_ctx; if (hapd->default_wep_key) free(hapd->default_wep_key); if (hapd->default_wep_key_idx >= 3) hapd->default_wep_key_idx = hapd->conf->individual_wep_key_len > 0 ? 1 : 0; else hapd->default_wep_key_idx++; hostapd_set_broadcast_wep(hapd); for (s = hapd->sta_list; s != NULL; s = s->next) ieee802_1x_notify_key_available(s->eapol_sm, 1); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { hostapd_hexdump("New WEP key generated", hapd->default_wep_key, hapd->conf->default_wep_key_len); } /* TODO: Could setup key for RX here, but change default TX keyid only * after new broadcast key has been sent to all stations. */ if (hostapd_set_encryption(hapd->driver.data, "WEP", NULL, hapd->default_wep_key_idx, hapd->default_wep_key, hapd->conf->default_wep_key_len)) { printf("Could not set WEP encryption.\n"); } if (hapd->conf->wep_rekeying_period > 0) eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, hostapd_rotate_wep, hapd, NULL); }
static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) { hostapd *hapd = (hostapd *) eloop_ctx; int len; unsigned char buf[3000]; len = recv(sock, buf, sizeof(buf), 0); if (len < 0) { perror("recv"); return; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "Received %d bytes management frame\n", len); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) { int i; printf(" dump:"); for (i = 0; i < len; i++) printf(" %02x", buf[i]); printf("\n"); } handle_frame(hapd, buf, len); }
int radius_client_send(hostapd *hapd, struct radius_msg *msg, RadiusType msg_type) { u8 *shared_secret; size_t shared_secret_len; char *name; int s, res; if (msg_type == RADIUS_ACCT) { shared_secret = hapd->conf->acct_server->shared_secret; shared_secret_len = hapd->conf->acct_server->shared_secret_len; radius_msg_finish_acct(msg, shared_secret, shared_secret_len); name = "accounting"; s = hapd->radius->acct_serv_sock; } else { shared_secret = hapd->conf->auth_server->shared_secret; shared_secret_len = hapd->conf->auth_server->shared_secret_len; radius_msg_finish(msg, shared_secret, shared_secret_len); name = "authentication"; s = hapd->radius->auth_serv_sock; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Sending RADIUS message to %s server\n", name); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) radius_msg_dump(msg); res = send(s, msg->buf, msg->buf_used, 0); if (res < 0) perror("send[RADIUS]"); radius_client_list_add(hapd, msg, msg_type, shared_secret, shared_secret_len); return res; }
ParseRes ieee802_11_parse_elems(struct hostapd_data *hapd, u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) { size_t left = len; u8 *pos = start; int unknown = 0; memset(elems, 0, sizeof(*elems)); while (left >= 2) { u8 id, elen; id = *pos++; elen = *pos++; left -= 2; if (elen > left) { if (show_errors) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.11 element parse " "failed (id=%d elen=%d " "left=%lu)\n", id, elen, (unsigned long) left); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) hostapd_hexdump("IEs", start, len); } return ParseFailed; } switch (id) { case WLAN_EID_SSID: elems->ssid = pos; elems->ssid_len = elen; break; case WLAN_EID_SUPP_RATES: elems->supp_rates = pos; elems->supp_rates_len = elen; break; case WLAN_EID_FH_PARAMS: elems->fh_params = pos; elems->fh_params_len = elen; break; case WLAN_EID_DS_PARAMS: elems->ds_params = pos; elems->ds_params_len = elen; break; case WLAN_EID_CF_PARAMS: elems->cf_params = pos; elems->cf_params_len = elen; break; case WLAN_EID_TIM: elems->tim = pos; elems->tim_len = elen; break; case WLAN_EID_IBSS_PARAMS: elems->ibss_params = pos; elems->ibss_params_len = elen; break; case WLAN_EID_CHALLENGE: elems->challenge = pos; elems->challenge_len = elen; break; case WLAN_EID_GENERIC: if (elen > 4 && memcmp(pos, WPA_OUI_TYPE, 4) == 0) { elems->wpa_ie = pos; elems->wpa_ie_len = elen; } else if (show_errors) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE, "IEEE 802.11 element parse " "ignored unknown generic element" " (id=%d elen=%d OUI:type=" "%02x-%02x-%02x:%d)\n", id, elen, elen >= 1 ? pos[0] : 0, elen >= 2 ? pos[1] : 0, elen >= 3 ? pos[2] : 0, elen >= 4 ? pos[3] : 0); unknown++; } else { unknown++; } break; case WLAN_EID_RSN: elems->rsn_ie = pos; elems->rsn_ie_len = elen; break; default: unknown++; if (!show_errors) break; HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE, "IEEE 802.11 element parse ignored " "unknown element (id=%d elen=%d)\n", id, elen); break; } left -= elen; pos += elen; } if (left) return ParseFailed; return unknown ? ParseUnknown : ParseOK; }
static int hostapd_setup_interface(struct hostapd_data *hapd) { struct hostapd_config *conf = hapd->conf; u8 ssid[HOSTAPD_SSID_LEN + 1]; int ssid_len, set_ssid; int ret = 0; if (hostapd_driver_init(hapd)) { printf("%s driver initialization failed.\n", hapd->driver ? hapd->driver->name : "Unknown"); hapd->driver = NULL; return -1; } /* * Fetch the SSID from the system and use it or, * if one was specified in the config file, verify they * match. */ ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid)); if (ssid_len < 0) { printf("Could not read SSID from system\n"); return -1; } if (conf->ssid_set) { /* * If SSID is specified in the config file and it differs * from what is being used then force installation of the * new SSID. */ set_ssid = (conf->ssid_len != ssid_len || memcmp(conf->ssid, ssid, ssid_len) != 0); } else { /* * No SSID in the config file; just use the one we got * from the system. */ set_ssid = 0; conf->ssid_len = ssid_len; memcpy(conf->ssid, ssid, conf->ssid_len); conf->ssid[conf->ssid_len] = '\0'; } printf("Using interface %s with hwaddr " MACSTR " and ssid '%s'\n", hapd->conf->iface, MAC2STR(hapd->own_addr), hapd->conf->ssid); if (hostapd_setup_wpa_psk(conf)) { printf("WPA-PSK setup failed.\n"); return -1; } /* Set SSID for the kernel driver (to be used in beacon and probe * response frames) */ if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid, conf->ssid_len)) { printf("Could not set SSID for kernel driver\n"); return -1; } if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) conf->radius->msg_dumps = 1; hapd->radius = radius_client_init(hapd, conf->radius); if (hapd->radius == NULL) { printf("RADIUS client initialization failed.\n"); return -1; } if (conf->radius_server_clients) { struct radius_server_conf srv; memset(&srv, 0, sizeof(srv)); srv.client_file = conf->radius_server_clients; srv.auth_port = conf->radius_server_auth_port; srv.hostapd_conf = conf; srv.eap_sim_db_priv = hapd->eap_sim_db_priv; srv.ssl_ctx = hapd->ssl_ctx; srv.ipv6 = conf->radius_server_ipv6; hapd->radius_srv = radius_server_init(&srv); if (hapd->radius_srv == NULL) { printf("RADIUS server initialization failed.\n"); return -1; } } if (hostapd_acl_init(hapd)) { printf("ACL initialization failed.\n"); return -1; } if (ieee802_1x_init(hapd)) { printf("IEEE 802.1X initialization failed.\n"); return -1; } if (hapd->conf->wpa && wpa_init(hapd)) { printf("WPA initialization failed.\n"); return -1; } #ifdef SIMPLE_CONFIG if (wsc_ie_init(hapd) < 0) { printf("WSC IE initialization failed.\n"); return -1; } #endif if (accounting_init(hapd)) { printf("Accounting initialization failed.\n"); return -1; } if (hapd->conf->ieee802_11f && (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) { printf("IEEE 802.11F (IAPP) initialization failed.\n"); return -1; } if (hostapd_wireless_event_init(hapd) < 0) return -1; if (hostapd_flush_old_stations(hapd)) return -1; if (hostapd_ctrl_iface_init(hapd)) { printf("Failed to setup control interface\n"); ret = -1; } return ret; }
static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) { struct radius_client_data *radius = eloop_ctx; struct hostapd_data *hapd = radius->hapd; RadiusType msg_type = (RadiusType) sock_ctx; int len, i, roundtrip; unsigned char buf[3000]; struct radius_msg *msg; struct radius_rx_handler *handlers; size_t num_handlers; struct radius_msg_list *req, *prev_req; struct timeval tv; struct hostapd_radius_server *rconf; int invalid_authenticator = 0; if (msg_type == RADIUS_ACCT) { handlers = radius->acct_handlers; num_handlers = radius->num_acct_handlers; rconf = hapd->conf->acct_server; } else { handlers = radius->auth_handlers; num_handlers = radius->num_auth_handlers; rconf = hapd->conf->auth_server; } len = recv(sock, buf, sizeof(buf), 0); if (len < 0) { perror("recv[RADIUS]"); return; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Received %d bytes from RADIUS server\n", len); if (len == sizeof(buf)) { printf("Possibly too long UDP frame for our buffer - " "dropping it\n"); return; } msg = radius_msg_parse(buf, len); if (msg == NULL) { printf("Parsing incoming RADIUS frame failed\n"); rconf->malformed_responses++; return; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Received RADIUS message\n"); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) radius_msg_dump(msg); switch (msg->hdr->code) { case RADIUS_CODE_ACCESS_ACCEPT: rconf->access_accepts++; break; case RADIUS_CODE_ACCESS_REJECT: rconf->access_rejects++; break; case RADIUS_CODE_ACCESS_CHALLENGE: rconf->access_challenges++; break; case RADIUS_CODE_ACCOUNTING_RESPONSE: rconf->responses++; break; } prev_req = NULL; req = radius->msgs; while (req) { /* TODO: also match by src addr:port of the packet when using * alternative RADIUS servers (?) */ if ((req->msg_type == msg_type || (req->msg_type == RADIUS_ACCT_INTERIM && msg_type == RADIUS_ACCT)) && req->msg->hdr->identifier == msg->hdr->identifier) break; prev_req = req; req = req->next; } if (req == NULL) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "No matching RADIUS request found (type=%d " "id=%d) - dropping packet\n", msg_type, msg->hdr->identifier); goto fail; } gettimeofday(&tv, NULL); roundtrip = (tv.tv_sec - req->last_attempt.tv_sec) * 100 + (tv.tv_usec - req->last_attempt.tv_usec) / 10000; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Received RADIUS packet matched " "with a pending request, round trip time %d.%02d sec\n", roundtrip / 100, roundtrip % 100); rconf->round_trip_time = roundtrip; /* Remove ACKed RADIUS packet from retransmit list */ if (prev_req) prev_req->next = req->next; else radius->msgs = req->next; radius->num_msgs--; for (i = 0; i < num_handlers; i++) { RadiusRxResult res; res = handlers[i].handler(msg, req->msg, req->shared_secret, req->shared_secret_len, handlers[i].data); switch (res) { case RADIUS_RX_PROCESSED: radius_msg_free(msg); free(msg); /* continue */ case RADIUS_RX_QUEUED: radius_client_msg_free(req); return; case RADIUS_RX_INVALID_AUTHENTICATOR: invalid_authenticator++; /* continue */ case RADIUS_RX_UNKNOWN: /* continue with next handler */ break; } } if (invalid_authenticator) rconf->bad_authenticators++; else rconf->unknown_types++; hostapd_logger(hapd, req->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " "(type=%d code=%d id=%d)%s - dropping packet", msg_type, msg->hdr->code, msg->hdr->identifier, invalid_authenticator ? " [INVALID AUTHENTICATOR]" : ""); radius_client_msg_free(req); fail: radius_msg_free(msg); free(msg); }
static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) { hostapd *hapd = (hostapd *) eloop_ctx; RadiusType msg_type = (RadiusType) sock_ctx; int len, i; unsigned char buf[3000]; struct radius_msg *msg; struct radius_rx_handler *handlers; size_t num_handlers; struct radius_msg_list *req, *prev_req; len = recv(sock, buf, sizeof(buf), 0); if (len < 0) { perror("recv[RADIUS]"); return; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Received %d bytes from RADIUS server\n", len); if (len == sizeof(buf)) { printf("Possibly too long UDP frame for our buffer - " "dropping it\n"); return; } msg = radius_msg_parse(buf, len); if (msg == NULL) { printf("Parsing incoming RADIUS frame failed\n"); return; } HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Received RADIUS message\n"); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) radius_msg_dump(msg); if (msg_type == RADIUS_ACCT) { handlers = hapd->radius->acct_handlers; num_handlers = hapd->radius->num_acct_handlers; } else { handlers = hapd->radius->auth_handlers; num_handlers = hapd->radius->num_auth_handlers; } prev_req = NULL; req = hapd->radius->msgs; while (req) { /* TODO: also match by src addr:port of the packet when using * alternative RADIUS servers (?) */ if (req->msg_type == msg_type && req->msg->hdr->identifier == msg->hdr->identifier) break; prev_req = req; req = req->next; } if (req == NULL) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "No maching RADIUS request found (type=%d id=%d)" " - dropping packet\n", msg_type, msg->hdr->identifier); goto fail; } /* Remove ACKed RADIUS packet from retransmit list */ if (prev_req) prev_req->next = req->next; else hapd->radius->msgs = req->next; hapd->radius->num_msgs--; for (i = 0; i < num_handlers; i++) { RadiusRxResult res; res = handlers[i].handler(hapd, msg, req->msg, req->shared_secret, req->shared_secret_len, handlers[i].data); switch (res) { case RADIUS_RX_PROCESSED: radius_msg_free(msg); free(msg); /* continue */ case RADIUS_RX_QUEUED: radius_client_msg_free(req); return; case RADIUS_RX_UNKNOWN: /* continue with next handler */ break; } } printf("No RADIUS RX handler found (type=%d code=%d id=%d) - dropping " "packet\n", msg_type, msg->hdr->code, msg->hdr->identifier); radius_client_msg_free(req); fail: radius_msg_free(msg); free(msg); }
static void handle_frame(hostapd *hapd, char *buf, size_t len) { struct ieee80211_hdr *hdr; u16 fc, extra_len, type, stype; unsigned char *extra = NULL; size_t data_len = len; int ver; /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass * these to user space */ if (len < 24) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "handle_frame: too short " "(%d)\n", len); return; } hdr = (struct ieee80211_hdr *) buf; fc = le_to_host16(hdr->frame_control); type = WLAN_FC_GET_TYPE(fc); stype = WLAN_FC_GET_STYPE(fc); if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON || hapd->conf->debug >= HOSTAPD_DEBUG_EXCESSIVE) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "Received %d bytes management frame\n", len); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) { hostapd_hexdump("RX frame", buf, len); } } ver = fc & WLAN_FC_PVER; /* protocol version 3 is reserved for indicating extra data after the * payload, version 2 for indicating ACKed frame (TX callbacks), and * version 1 for indicating failed frame (no ACK, TX callbacks) */ if (ver == 3) { u8 *pos = buf + len - 2; extra_len = (u16) pos[1] << 8 | pos[0]; printf("extra data in frame (elen=%d)\n", extra_len); if (extra_len + 2 > len) { printf(" extra data overflow\n"); return; } len -= extra_len + 2; extra = buf + len; } else if (ver == 1 || ver == 2) { handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0); return; } else if (ver != 0) { printf("unknown protocol version %d\n", ver); return; } switch (type) { case WLAN_FC_TYPE_MGMT: HOSTAPD_DEBUG(stype == WLAN_FC_STYPE_BEACON ? HOSTAPD_DEBUG_EXCESSIVE : HOSTAPD_DEBUG_VERBOSE, "MGMT\n"); ieee802_11_mgmt(hapd, buf, data_len, stype); break; case WLAN_FC_TYPE_CTRL: HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "CTRL\n"); break; case WLAN_FC_TYPE_DATA: HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "DATA\n"); handle_data(hapd, buf, data_len, stype); break; default: printf("unknown frame type %d\n", type); break; } }