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

View file

@ -9,37 +9,12 @@
#ifndef WNM_STA_H #ifndef WNM_STA_H
#define 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 { struct measurement_pilot {
u8 measurement_pilot; u8 measurement_pilot;
u8 subelem_len; u8 subelem_len;
u8 subelems[255]; u8 subelems[255];
}; };
struct rrm_enabled_capabilities {
u8 capabilities[5];
};
struct multiple_bssid { struct multiple_bssid {
u8 max_bssid_indicator; u8 max_bssid_indicator;
u8 subelem_len; u8 subelem_len;
@ -52,13 +27,23 @@ struct neighbor_report {
u8 regulatory_class; u8 regulatory_class;
u8 channel_number; u8 channel_number;
u8 phy_type; u8 phy_type;
struct tsf_info *tsf_info; u8 preference; /* valid if preference_present=1 */
struct condensed_country_string *con_coun_str; u16 tsf_offset; /* valid if tsf_present=1 */
struct bss_transition_candidate *bss_tran_can; u16 beacon_int; /* valid if tsf_present=1 */
struct bss_termination_duration *bss_term_dur; char country[2]; /* valid if country_present=1 */
struct bearing *bearing; 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 measurement_pilot *meas_pilot;
struct rrm_enabled_capabilities *rrm_cap;
struct multiple_bssid *mul_bssid; struct multiple_bssid *mul_bssid;
}; };