diff --git a/src/binding/ieee80211/ieee80211.c b/src/binding/ieee80211/ieee80211.c index 0bd2fa3..519518f 100644 --- a/src/binding/ieee80211/ieee80211.c +++ b/src/binding/ieee80211/ieee80211.c @@ -104,6 +104,227 @@ static int ieee80211_ie_set_erp(char* buffer, uint32_t mode, uint8_t erpinfo) { return sizeof(struct ieee80211_ie_erp); } +/* */ +int ieee80211_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length) { + ASSERT(items != NULL); + ASSERT(data != NULL); + + /* */ + memset(items, 0, sizeof(struct ieee80211_ie_items)); + + /* Parsing */ + while (length >= 2) { + uint8_t ie_id = data[0]; + uint8_t ie_len = data[1]; + + /* Parsing Information Element */ + switch (ie_id) { + case IEEE80211_IE_SSID: { + if (ie_len > IEEE80211_IE_SSID_MAX_LENGTH) { + return -1; + } + + items->ssid = (struct ieee80211_ie_ssid*)data; + break; + } + + case IEEE80211_IE_SUPPORTED_RATES: { + if ((ie_len < IEEE80211_IE_SUPPORTED_RATES_MIN_LENGTH) || (ie_len > IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH)) { + return -1; + } + + items->supported_rates = (struct ieee80211_ie_supported_rates*)data; + break; + } + + case IEEE80211_IE_DSSS: { + if (ie_len != IEEE80211_IE_DSSS_LENGTH) { + return -1; + } + + items->dsss = (struct ieee80211_ie_dsss*)data; + break; + } + + case IEEE80211_IE_COUNTRY: { + if (ie_len < IEEE80211_IE_COUNTRY_MIN_LENGTH) { + return -1; + } + + items->country = (struct ieee80211_ie_country*)data; + break; + } + + case IEEE80211_IE_CHALLENGE_TEXT: { + if (ie_len < IEEE80211_IE_CHALLENGE_TEXT_MIN_LENGTH) { + return -1; + } + + items->challenge_text = (struct ieee80211_ie_challenge_text*)data; + break; + } + + case IEEE80211_IE_ERP: { + if (ie_len != IEEE80211_IE_ERP_LENGTH) { + return -1; + } + + items->erp = (struct ieee80211_ie_erp*)data; + break; + } + + case IEEE80211_IE_EXTENDED_SUPPORTED_RATES: { + if (ie_len < IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH) { + return -1; + } + + items->extended_supported_rates = (struct ieee80211_ie_extended_supported_rates*)data; + break; + } + + case IEEE80211_IE_EDCA_PARAMETER_SET: { + if (ie_len != IEEE80211_IE_EDCA_PARAMETER_SET_LENGTH) { + return -1; + } + + items->edca_parameter_set = (struct ieee80211_ie_edca_parameter_set*)data; + break; + } + + case IEEE80211_IE_QOS_CAPABILITY: { + if (ie_len != IEEE80211_IE_QOS_CAPABILITY_LENGTH) { + return -1; + } + + items->qos_capability = (struct ieee80211_ie_qos_capability*)data; + break; + } + + case IEEE80211_IE_POWER_CONSTRAINT: { + if (ie_len != IEEE80211_IE_POWER_CONSTRAINT_LENGTH) { + return -1; + } + + items->power_constraint = (struct ieee80211_ie_power_constraint*)data; + break; + } + + case IEEE80211_IE_SSID_LIST: { + items->ssid_list = (struct ieee80211_ie_ssid_list*)data; + break; + } + } + + /* Next Information Element */ + data += sizeof(struct ieee80211_ie) + ie_len; + length -= sizeof(struct ieee80211_ie) + ie_len; + } + + return (!length ? 0 : -1); +} + +/* */ +int ieee80211_aid_create(uint32_t* aidbitfield, uint16_t* aid) { + int i, j; + + ASSERT(aidbitfield != NULL); + ASSERT(aid != NULL); + + /* Search free aid bitfield */ + for (i = 0; i < IEEE80211_AID_BITFIELD_SIZE; i++) { + if (aidbitfield[i] != 0xffffffff) { + uint32_t bitfield = aidbitfield[i]; + + /* Search free bit */ + for (j = 0; j < 32; j++) { + if (!(bitfield & (1 << j))) { + *aid = i * 32 + j + 1; + if (*aid <= IEEE80211_AID_MAX_VALUE) { + aidbitfield[i] |= (1 << j); + return 0; + } + + break; + } + } + + break; + } + } + + *aid = 0; + return -1; +} + +/* */ +void ieee80211_aid_free(uint32_t* aidbitfield, uint16_t aid) { + ASSERT(aidbitfield != NULL); + ASSERT((aid > 0) && (aid <= IEEE80211_AID_MAX_VALUE)); + + aidbitfield[(aid - 1) / 32] &= ~(1 << ((aid - 1) % 32)); +} + +/* */ +unsigned long ieee80211_frequency_to_channel(uint32_t freq) { + if ((freq >= 2412) && (freq <= 2472)) { + return (freq - 2407) / 5; + } else if (freq == 2484) { + return 14; + } else if ((freq >= 4915) && (freq <= 4980)) { + return (freq - 4000) / 5; + } else if ((freq >= 5035) && (freq <= 5825)) { + return (freq - 5000) / 5; + } + + return 0; +} + +/* */ +int ieee80211_is_broadcast_addr(const uint8_t* addr) { + return (((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)) ? 1 : 0); +} + +/* */ +int ieee80211_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist) { + int ssidlength; + + ASSERT(ssid != NULL); + + if (!iessid) { + return IEEE80211_WRONG_SSID; + } + + /* Check SSID */ + ssidlength = strlen((char*)ssid); + if ((ssidlength == iessid->len) && !memcmp(ssid, iessid->ssid, ssidlength)) { + return IEEE80211_VALID_SSID; + } + + /* Check SSID list */ + if (isssidlist) { + int length = isssidlist->len; + uint8_t* pos = isssidlist->lists; + + while (length >= sizeof(struct ieee80211_ie)) { + struct ieee80211_ie_ssid* ssiditem = (struct ieee80211_ie_ssid*)pos; + + /* Check buffer */ + length -= sizeof(struct ieee80211_ie); + if ((ssiditem->id != IEEE80211_IE_SSID) || !ssiditem->len || (length < ssiditem->len)) { + break; + } else if ((ssidlength == ssiditem->len) && !memcmp(ssid, ssiditem->ssid, ssidlength)) { + return IEEE80211_VALID_SSID; + } + + /* Next */ + length -= ssiditem->len; + pos += sizeof(struct ieee80211_ie) + ssiditem->len; + } + } + + return (!iessid->len ? IEEE80211_WILDCARD_SSID : IEEE80211_WRONG_SSID); +} + /* */ uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnonerpcount, unsigned long stationnoshortpreamblecount, int shortpreamble) { uint8_t result = 0; diff --git a/src/binding/ieee80211/ieee80211.h b/src/binding/ieee80211/ieee80211.h index 0b03923..7e023b6 100644 --- a/src/binding/ieee80211/ieee80211.h +++ b/src/binding/ieee80211/ieee80211.h @@ -568,4 +568,20 @@ struct ieee80211_deauthentication_params { int ieee80211_create_deauthentication(char* buffer, int length, struct ieee80211_deauthentication_params* params); +/* Utils */ +int ieee80211_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length); +unsigned long ieee80211_frequency_to_channel(uint32_t freq); +int ieee80211_is_broadcast_addr(const uint8_t* addr); + +/* */ +#define IEEE80211_VALID_SSID 1 +#define IEEE80211_WILDCARD_SSID 0 +#define IEEE80211_WRONG_SSID -1 +int ieee80211_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist); + +/* IEEE802.11 Aid management */ +#define IEEE80211_AID_BITFIELD_SIZE 63 +int ieee80211_aid_create(uint32_t* aidbitfield, uint16_t* aid); +void ieee80211_aid_free(uint32_t* aidbitfield, uint16_t aid); + #endif /* __CAPWAP_IEEE802_11_HEADER__ */ diff --git a/src/binding/ieee80211/wifi_drivers.c b/src/binding/ieee80211/wifi_drivers.c index 987055f..682b558 100644 --- a/src/binding/ieee80211/wifi_drivers.c +++ b/src/binding/ieee80211/wifi_drivers.c @@ -572,224 +572,3 @@ int wifi_frequency_to_radiotype(uint32_t freq) { return -1; } - -/* */ -unsigned long wifi_frequency_to_channel(uint32_t freq) { - if ((freq >= 2412) && (freq <= 2472)) { - return (freq - 2407) / 5; - } else if (freq == 2484) { - return 14; - } else if ((freq >= 4915) && (freq <= 4980)) { - return (freq - 4000) / 5; - } else if ((freq >= 5035) && (freq <= 5825)) { - return (freq - 5000) / 5; - } - - return 0; -} - -/* */ -int wifi_is_broadcast_addr(const uint8_t* addr) { - return (((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)) ? 1 : 0); -} - -/* */ -int wifi_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist) { - int ssidlength; - - ASSERT(ssid != NULL); - - if (!iessid) { - return WIFI_WRONG_SSID; - } - - /* Check SSID */ - ssidlength = strlen((char*)ssid); - if ((ssidlength == iessid->len) && !memcmp(ssid, iessid->ssid, ssidlength)) { - return WIFI_VALID_SSID; - } - - /* Check SSID list */ - if (isssidlist) { - int length = isssidlist->len; - uint8_t* pos = isssidlist->lists; - - while (length >= sizeof(struct ieee80211_ie)) { - struct ieee80211_ie_ssid* ssiditem = (struct ieee80211_ie_ssid*)pos; - - /* Check buffer */ - length -= sizeof(struct ieee80211_ie); - if ((ssiditem->id != IEEE80211_IE_SSID) || !ssiditem->len || (length < ssiditem->len)) { - break; - } else if ((ssidlength == ssiditem->len) && !memcmp(ssid, ssiditem->ssid, ssidlength)) { - return WIFI_VALID_SSID; - } - - /* Next */ - length -= ssiditem->len; - pos += sizeof(struct ieee80211_ie) + ssiditem->len; - } - } - - return (!iessid->len ? WIFI_WILDCARD_SSID : WIFI_WRONG_SSID); -} - -/* */ -int wifi_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length) { - ASSERT(items != NULL); - ASSERT(data != NULL); - - /* */ - memset(items, 0, sizeof(struct ieee80211_ie_items)); - - /* Parsing */ - while (length >= 2) { - uint8_t ie_id = data[0]; - uint8_t ie_len = data[1]; - - /* Parsing Information Element */ - switch (ie_id) { - case IEEE80211_IE_SSID: { - if (ie_len > IEEE80211_IE_SSID_MAX_LENGTH) { - return -1; - } - - items->ssid = (struct ieee80211_ie_ssid*)data; - break; - } - - case IEEE80211_IE_SUPPORTED_RATES: { - if ((ie_len < IEEE80211_IE_SUPPORTED_RATES_MIN_LENGTH) || (ie_len > IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH)) { - return -1; - } - - items->supported_rates = (struct ieee80211_ie_supported_rates*)data; - break; - } - - case IEEE80211_IE_DSSS: { - if (ie_len != IEEE80211_IE_DSSS_LENGTH) { - return -1; - } - - items->dsss = (struct ieee80211_ie_dsss*)data; - break; - } - - case IEEE80211_IE_COUNTRY: { - if (ie_len < IEEE80211_IE_COUNTRY_MIN_LENGTH) { - return -1; - } - - items->country = (struct ieee80211_ie_country*)data; - break; - } - - case IEEE80211_IE_CHALLENGE_TEXT: { - if (ie_len < IEEE80211_IE_CHALLENGE_TEXT_MIN_LENGTH) { - return -1; - } - - items->challenge_text = (struct ieee80211_ie_challenge_text*)data; - break; - } - - case IEEE80211_IE_ERP: { - if (ie_len != IEEE80211_IE_ERP_LENGTH) { - return -1; - } - - items->erp = (struct ieee80211_ie_erp*)data; - break; - } - - case IEEE80211_IE_EXTENDED_SUPPORTED_RATES: { - if (ie_len < IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH) { - return -1; - } - - items->extended_supported_rates = (struct ieee80211_ie_extended_supported_rates*)data; - break; - } - - case IEEE80211_IE_EDCA_PARAMETER_SET: { - if (ie_len != IEEE80211_IE_EDCA_PARAMETER_SET_LENGTH) { - return -1; - } - - items->edca_parameter_set = (struct ieee80211_ie_edca_parameter_set*)data; - break; - } - - case IEEE80211_IE_QOS_CAPABILITY: { - if (ie_len != IEEE80211_IE_QOS_CAPABILITY_LENGTH) { - return -1; - } - - items->qos_capability = (struct ieee80211_ie_qos_capability*)data; - break; - } - - case IEEE80211_IE_POWER_CONSTRAINT: { - if (ie_len != IEEE80211_IE_POWER_CONSTRAINT_LENGTH) { - return -1; - } - - items->power_constraint = (struct ieee80211_ie_power_constraint*)data; - break; - } - - case IEEE80211_IE_SSID_LIST: { - items->ssid_list = (struct ieee80211_ie_ssid_list*)data; - break; - } - } - - /* Next Information Element */ - data += sizeof(struct ieee80211_ie) + ie_len; - length -= sizeof(struct ieee80211_ie) + ie_len; - } - - return (!length ? 0 : -1); -} - -/* */ -int wifi_aid_create(uint32_t* aidbitfield, uint16_t* aid) { - int i, j; - - ASSERT(aidbitfield != NULL); - ASSERT(aid != NULL); - - /* Search free aid bitfield */ - for (i = 0; i < WIFI_AID_BITFIELD_SIZE; i++) { - if (aidbitfield[i] != 0xffffffff) { - uint32_t bitfield = aidbitfield[i]; - - /* Search free bit */ - for (j = 0; j < 32; j++) { - if (!(bitfield & (1 << j))) { - *aid = i * 32 + j + 1; - if (*aid <= IEEE80211_AID_MAX_VALUE) { - aidbitfield[i] |= (1 << j); - return 0; - } - - break; - } - } - - break; - } - } - - *aid = 0; - return -1; -} - -/* */ -void wifi_aid_free(uint32_t* aidbitfield, uint16_t aid) { - ASSERT(aidbitfield != NULL); - ASSERT((aid > 0) && (aid <= IEEE80211_AID_MAX_VALUE)); - - aidbitfield[(aid - 1) / 32] &= ~(1 << ((aid - 1) % 32)); -} diff --git a/src/binding/ieee80211/wifi_drivers.h b/src/binding/ieee80211/wifi_drivers.h index f948eda..2ce38b9 100644 --- a/src/binding/ieee80211/wifi_drivers.h +++ b/src/binding/ieee80211/wifi_drivers.h @@ -63,9 +63,6 @@ #define WLAN_INTERFACE_AP 1 -/* IEEE802.11 Aid management */ -#define WIFI_AID_BITFIELD_SIZE 63 - /* */ typedef void* wifi_global_handle; typedef void* wifi_device_handle; @@ -290,22 +287,8 @@ uint32_t wifi_iface_index(const char* ifname); int wifi_iface_hwaddr(int sock, const char* ifname, uint8_t* hwaddr); int wifi_frequency_to_radiotype(uint32_t freq); -unsigned long wifi_frequency_to_channel(uint32_t freq); -int wifi_is_broadcast_addr(const uint8_t* addr); /* */ -#define WIFI_VALID_SSID 1 -#define WIFI_WILDCARD_SSID 0 -#define WIFI_WRONG_SSID -1 -int wifi_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist); - -/* */ -int wifi_aid_create(uint32_t* aidbitfield, uint16_t* aid); -void wifi_aid_free(uint32_t* aidbitfield, uint16_t aid); - -/* */ -int wifi_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length); - int wifi_iface_getstatus(int sock, const char* ifname); int wifi_iface_updown(int sock, const char* ifname, int up); #define wifi_iface_up(sock, ifname) wifi_iface_updown(sock, ifname, 1) diff --git a/src/binding/ieee80211/wifi_nl80211.c b/src/binding/ieee80211/wifi_nl80211.c index e1bd4eb..a83a62f 100644 --- a/src/binding/ieee80211/wifi_nl80211.c +++ b/src/binding/ieee80211/wifi_nl80211.c @@ -510,7 +510,7 @@ static void nl80211_station_clean(struct nl80211_wlan_handle* wlanhandle, struct ASSERT(station != NULL); if (station->aid) { - wifi_aid_free(wlanhandle->aidbitfield, station->aid); + ieee80211_aid_free(wlanhandle->aidbitfield, station->aid); } if (station->flags & NL80211_STATION_FLAGS_NON_ERP) { @@ -645,7 +645,7 @@ static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlan } /* Parsing Information Elements */ - if (wifi_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) { + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) { return; } @@ -655,8 +655,8 @@ static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlan } /* Verify the SSID */ - ssidcheck = wifi_is_valid_ssid(wlanhandle->ssid, ieitems.ssid, ieitems.ssid_list); - if (ssidcheck == WIFI_WRONG_SSID) { + ssidcheck = ieee80211_is_valid_ssid(wlanhandle->ssid, ieitems.ssid, ieitems.ssid_list); + if (ssidcheck == IEEE80211_WRONG_SSID) { return; } @@ -683,7 +683,7 @@ static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlan wlan_params.packet = g_bufferIEEE80211; wlan_params.length = responselength; wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency; - wlan_params.no_wait_ack = ((ssidcheck == WIFI_WILDCARD_SSID) && wifi_is_broadcast_addr(mgmt->da) ? 1 : 0); + wlan_params.no_wait_ack = ((ssidcheck == IEEE80211_WILDCARD_SSID) && ieee80211_is_broadcast_addr(mgmt->da) ? 1 : 0); if (nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) { capwap_logging_warning("Unable to send IEEE802.11 Probe Response"); @@ -727,7 +727,7 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla } /* Parsing Information Elements */ - if (wifi_retrieve_information_elements_position(&ieitems, &mgmt->authetication.ie[0], ielength)) { + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->authetication.ie[0], ielength)) { return; } @@ -793,14 +793,14 @@ static int nl80211_set_station_information(struct nl80211_wlan_handle* wlanhandl int updatebeacons = 0; /* Verify SSID */ - if (wifi_is_valid_ssid(wlanhandle->ssid, ieitems->ssid, NULL) != WIFI_VALID_SSID) { + if (ieee80211_is_valid_ssid(wlanhandle->ssid, ieitems->ssid, NULL) != IEEE80211_VALID_SSID) { return IEEE80211_STATUS_UNSPECIFIED_FAILURE; } /* */ station->capability = __le16_to_cpu(mgmt->associationrequest.capability); station->listeninterval = __le16_to_cpu(mgmt->associationrequest.listeninterval); - if (wifi_aid_create(wlanhandle->aidbitfield, &station->aid)) { + if (ieee80211_aid_create(wlanhandle->aidbitfield, &station->aid)) { return IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; } @@ -923,7 +923,7 @@ static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle } /* Parsing Information Elements */ - if (wifi_retrieve_information_elements_position(&ieitems, &mgmt->associationrequest.ie[0], ielength)) { + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->associationrequest.ie[0], ielength)) { return; } @@ -932,7 +932,7 @@ static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle /* */ if (wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { if (resultstatuscode == IEEE80211_STATUS_SUCCESS) { - if (wifi_aid_create(wlanhandle->aidbitfield, &station->aid)) { + if (ieee80211_aid_create(wlanhandle->aidbitfield, &station->aid)) { resultstatuscode = IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; } } @@ -1008,7 +1008,7 @@ static void nl80211_do_mgmt_frame_event(struct nl80211_wlan_handle* wlanhandle, } /* Check if sent packet to correct AP */ - broadcast = wifi_is_broadcast_addr(mgmt->bssid); + broadcast = ieee80211_is_broadcast_addr(mgmt->bssid); if (!broadcast && memcmp(mgmt->bssid, wlanhandle->address, ETH_ALEN)) { return; } @@ -1671,7 +1671,7 @@ static int cb_get_phydevice_capability(struct nl_msg* msg, void* data) { /* Retrieve frequency and channel */ freq->frequency = frequency; - freq->channel = wifi_frequency_to_channel(frequency); + freq->channel = ieee80211_frequency_to_channel(frequency); if (!radio80211bg && IS_IEEE80211_FREQ_BG(frequency)) { radio80211bg = 1; diff --git a/src/binding/ieee80211/wifi_nl80211.h b/src/binding/ieee80211/wifi_nl80211.h index 26aed7b..38dd0a3 100644 --- a/src/binding/ieee80211/wifi_nl80211.h +++ b/src/binding/ieee80211/wifi_nl80211.h @@ -117,7 +117,7 @@ struct nl80211_wlan_handle { unsigned long maxstationscount; struct capwap_hash* stations; - uint32_t aidbitfield[WIFI_AID_BITFIELD_SIZE]; + uint32_t aidbitfield[IEEE80211_AID_BITFIELD_SIZE]; }; /* Physical device info */