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; }
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; }
/* 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); }
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 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; } }