WNM: Simplify how candidate subelements are stored

There is no need to use a separately allocated data structures for this.
A bitfield indicating which information is present and variables within
struct neighbor_report are simpler to use and more efficient.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-11-22 15:37:27 +02:00
parent 8c9af762f3
commit 093226783d
2 changed files with 33 additions and 79 deletions

View file

@ -309,13 +309,7 @@ void wnm_deallocate_memory(struct wpa_supplicant *wpa_s)
int i;
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
os_free(wpa_s->wnm_neighbor_report_elements[i].tsf_info);
os_free(wpa_s->wnm_neighbor_report_elements[i].con_coun_str);
os_free(wpa_s->wnm_neighbor_report_elements[i].bss_tran_can);
os_free(wpa_s->wnm_neighbor_report_elements[i].bss_term_dur);
os_free(wpa_s->wnm_neighbor_report_elements[i].bearing);
os_free(wpa_s->wnm_neighbor_report_elements[i].meas_pilot);
os_free(wpa_s->wnm_neighbor_report_elements[i].rrm_cap);
os_free(wpa_s->wnm_neighbor_report_elements[i].mul_bssid);
}
@ -334,12 +328,9 @@ static void wnm_parse_neighbor_report_elem(struct neighbor_report *rep,
wpa_printf(MSG_DEBUG, "WNM: Too short TSF");
break;
}
os_free(rep->tsf_info);
rep->tsf_info = os_zalloc(sizeof(struct tsf_info));
if (rep->tsf_info == NULL)
break;
os_memcpy(rep->tsf_info->tsf_offset, pos, 2);
os_memcpy(rep->tsf_info->beacon_interval, pos + 2, 2);
rep->tsf_offset = WPA_GET_LE16(pos);
rep->beacon_int = WPA_GET_LE16(pos + 2);
rep->tsf_present = 1;
break;
case WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING:
if (elen < 2) {
@ -347,12 +338,8 @@ static void wnm_parse_neighbor_report_elem(struct neighbor_report *rep,
"country string");
break;
}
os_free(rep->con_coun_str);
rep->con_coun_str =
os_zalloc(sizeof(struct condensed_country_string));
if (rep->con_coun_str == NULL)
break;
os_memcpy(rep->con_coun_str->country_string, pos, 2);
os_memcpy(rep->country, pos, 2);
rep->country_present = 1;
break;
case WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE:
if (elen < 1) {
@ -360,25 +347,13 @@ static void wnm_parse_neighbor_report_elem(struct neighbor_report *rep,
"candidate");
break;
}
os_free(rep->bss_tran_can);
rep->bss_tran_can =
os_zalloc(sizeof(struct bss_transition_candidate));
if (rep->bss_tran_can == NULL)
break;
rep->bss_tran_can->preference = pos[0];
rep->preference = pos[0];
rep->preference_present = 1;
break;
case WNM_NEIGHBOR_BSS_TERMINATION_DURATION:
if (elen < 10) {
wpa_printf(MSG_DEBUG, "WNM: Too short BSS termination "
"duration");
break;
}
os_free(rep->bss_term_dur);
rep->bss_term_dur =
os_zalloc(sizeof(struct bss_termination_duration));
if (rep->bss_term_dur == NULL)
break;
os_memcpy(rep->bss_term_dur->duration, pos, 10);
rep->bss_term_tsf = WPA_GET_LE64(pos);
rep->bss_term_dur = WPA_GET_LE16(pos + 8);
rep->bss_term_present = 1;
break;
case WNM_NEIGHBOR_BEARING:
if (elen < 8) {
@ -386,11 +361,10 @@ static void wnm_parse_neighbor_report_elem(struct neighbor_report *rep,
"bearing");
break;
}
os_free(rep->bearing);
rep->bearing = os_zalloc(sizeof(struct bearing));
if (rep->bearing == NULL)
break;
os_memcpy(rep->bearing->bearing, pos, 8);
rep->bearing = WPA_GET_LE16(pos);
rep->distance = WPA_GET_LE32(pos + 2);
rep->rel_height = WPA_GET_LE16(pos + 2 + 4);
rep->bearing_present = 1;
break;
case WNM_NEIGHBOR_MEASUREMENT_PILOT:
if (elen < 1) {
@ -412,12 +386,8 @@ static void wnm_parse_neighbor_report_elem(struct neighbor_report *rep,
"capabilities");
break;
}
os_free(rep->rrm_cap);
rep->rrm_cap =
os_zalloc(sizeof(struct rrm_enabled_capabilities));
if (rep->rrm_cap == NULL)
break;
os_memcpy(rep->rrm_cap->capabilities, pos, 5);
os_memcpy(rep->rm_capab, pos, 5);
rep->rm_capab_present = 1;
break;
case WNM_NEIGHBOR_MULTIPLE_BSSID:
if (elen < 1) {
@ -632,8 +602,7 @@ static void wnm_dump_cand_list(struct wpa_supplicant *wpa_s)
i, MAC2STR(nei->bssid), nei->bssid_info,
nei->regulatory_class,
nei->channel_number, nei->phy_type,
nei->bss_tran_can ? nei->bss_tran_can->preference :
-1);
nei->preference_present ? nei->preference : -1);
}
}

View file

@ -9,37 +9,12 @@
#ifndef WNM_STA_H
#define WNM_STA_H
struct tsf_info {
u8 tsf_offset[2];
u8 beacon_interval[2];
};
struct condensed_country_string {
u8 country_string[2];
};
struct bss_transition_candidate {
u8 preference;
};
struct bss_termination_duration {
u8 duration[10];
};
struct bearing {
u8 bearing[8];
};
struct measurement_pilot {
u8 measurement_pilot;
u8 subelem_len;
u8 subelems[255];
};
struct rrm_enabled_capabilities {
u8 capabilities[5];
};
struct multiple_bssid {
u8 max_bssid_indicator;
u8 subelem_len;
@ -52,13 +27,23 @@ struct neighbor_report {
u8 regulatory_class;
u8 channel_number;
u8 phy_type;
struct tsf_info *tsf_info;
struct condensed_country_string *con_coun_str;
struct bss_transition_candidate *bss_tran_can;
struct bss_termination_duration *bss_term_dur;
struct bearing *bearing;
u8 preference; /* valid if preference_present=1 */
u16 tsf_offset; /* valid if tsf_present=1 */
u16 beacon_int; /* valid if tsf_present=1 */
char country[2]; /* valid if country_present=1 */
u8 rm_capab[5]; /* valid if rm_capab_present=1 */
u16 bearing; /* valid if bearing_present=1 */
u16 rel_height; /* valid if bearing_present=1 */
u32 distance; /* valid if bearing_present=1 */
u64 bss_term_tsf; /* valid if bss_term_present=1 */
u16 bss_term_dur; /* valid if bss_term_present=1 */
unsigned int preference_present:1;
unsigned int tsf_present:1;
unsigned int country_present:1;
unsigned int rm_capab_present:1;
unsigned int bearing_present:1;
unsigned int bss_term_present:1;
struct measurement_pilot *meas_pilot;
struct rrm_enabled_capabilities *rrm_cap;
struct multiple_bssid *mul_bssid;
};