static int hs20_add_nai_home_realm_matches(struct hostapd_data *hapd, struct wpabuf *buf, const u8 *home_realm, size_t home_realm_len) { unsigned int i, j, k; u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len; struct hostapd_nai_realm_data *realm; const u8 *pos, *realm_name, *end; struct { unsigned int realm_data_idx; unsigned int realm_idx; } matches[10]; pos = home_realm; end = pos + home_realm_len; if (pos + 1 > end) { wpa_hexdump(MSG_DEBUG, "Too short NAI Home Realm Query", home_realm, home_realm_len); return -1; } num_realms = *pos++; for (i = 0; i < num_realms && num_matching < 10; i++) { if (pos + 2 > end) { wpa_hexdump(MSG_DEBUG, "Truncated NAI Home Realm Query", home_realm, home_realm_len); return -1; } encoding = *pos++; realm_len = *pos++; if (pos + realm_len > end) { wpa_hexdump(MSG_DEBUG, "Truncated NAI Home Realm Query", home_realm, home_realm_len); return -1; } realm_name = pos; for (j = 0; j < hapd->conf->nai_realm_count && num_matching < 10; j++) { const u8 *rpos, *rend; realm = &hapd->conf->nai_realm_data[j]; if (encoding != realm->encoding) continue; rpos = realm_name; while (rpos < realm_name + realm_len && num_matching < 10) { for (rend = rpos; rend < realm_name + realm_len; rend++) { if (*rend == ';') break; } for (k = 0; k < MAX_NAI_REALMS && realm->realm[k] && num_matching < 10; k++) { if ((int) os_strlen(realm->realm[k]) != rend - rpos || os_strncmp((char *) rpos, realm->realm[k], rend - rpos) != 0) continue; matches[num_matching].realm_data_idx = j; matches[num_matching].realm_idx = k; num_matching++; } rpos = rend + 1; } } pos += realm_len; } realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM); wpabuf_put_le16(buf, num_matching); /* * There are two ways to format. 1. each realm in a NAI Realm Data unit * 2. all realms that share the same EAP methods in a NAI Realm Data * unit. The first format is likely to be bigger in size than the * second, but may be easier to parse and process by the receiver. */ for (i = 0; i < num_matching; i++) { wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d", matches[i].realm_data_idx, matches[i].realm_idx); realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx]; anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx); } gas_anqp_set_element_len(buf, realm_list_len); return 0; }
static int process_hs_nai_home_realm(struct hostapd_data *hapd, struct wpabuf *buf, struct anqp_query_info *qi) { unsigned int i, j, k; u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len; struct hostapd_nai_realm_data *realm; const u8 *pos, *realm_name, *end; struct { unsigned int realm_data_idx; unsigned int realm_idx; } matches[10]; pos = qi->param; end = pos + qi->param_arg; num_realms = *pos++; for (i = 0; i < num_realms && num_matching < 10; i++) { encoding = *pos++; realm_len = *pos++; realm_name = pos; for (j = 0; j < hapd->conf->nai_realm_count && num_matching < 10; j++) { realm = &hapd->conf->nai_realm_data[j]; if (encoding != realm->encoding) continue; for (k = 0; realm->realm[k] && num_matching < 10; k++) { if (os_strncmp((char *) realm_name, realm->realm[k], realm_len) != 0) continue; matches[num_matching].realm_data_idx = j; matches[num_matching].realm_idx = k; num_matching++; } } pos += realm_len; if (pos > end) { wpa_hexdump(MSG_ERROR, "NAI Home Realm processing " "error", qi->param, qi->param_arg); return -1; } } realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM); wpabuf_put_le16(buf, num_matching); /* * There are two ways to format. 1. each realm in a NAI Realm Data unit * 2. all realms that share the same EAP methods in a NAI Realm Data * unit. The first format is likely to be bigger in size than the * second, but may be easier to parse and process by the receiver. */ for (i = 0; i < num_matching; i++) { wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d", matches[i].realm_data_idx, matches[i].realm_idx); realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx]; anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx); } gas_anqp_set_element_len(buf, realm_list_len); return 0; }