Example #1
0
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
                                     int sock, eloop_sock_handler handler,
                                     void *eloop_data, void *user_data)
{
	struct eloop_sock *tmp;
	int new_max_sock;

	if (sock > eloop.max_sock)
		new_max_sock = sock;
	else
		new_max_sock = eloop.max_sock;

	if (table == NULL)
		return -1;

#ifdef CONFIG_ELOOP_POLL
	if (new_max_sock >= eloop.max_pollfd_map) {
		struct pollfd **nmap;
		nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50,
					sizeof(struct pollfd *));
		if (nmap == NULL)
			return -1;

		eloop.max_pollfd_map = new_max_sock + 50;
		eloop.pollfds_map = nmap;
	}

	if (eloop.count + 1 > eloop.max_poll_fds) {
		struct pollfd *n;
		int nmax = eloop.count + 1 + 50;
		n = os_realloc_array(eloop.pollfds, nmax,
				     sizeof(struct pollfd));
		if (n == NULL)
			return -1;

		eloop.max_poll_fds = nmax;
		eloop.pollfds = n;
	}
#endif /* CONFIG_ELOOP_POLL */

	eloop_trace_sock_remove_ref(table);
	tmp = os_realloc_array(table->table, table->count + 1,
			       sizeof(struct eloop_sock));
	if (tmp == NULL)
		return -1;

	tmp[table->count].sock = sock;
	tmp[table->count].eloop_data = eloop_data;
	tmp[table->count].user_data = user_data;
	tmp[table->count].handler = handler;
	wpa_trace_record(&tmp[table->count]);
	table->count++;
	table->table = tmp;
	eloop.max_sock = new_max_sock;
	eloop.count++;
	table->changed = 1;
	eloop_trace_sock_add_ref(table);

	return 0;
}
Example #2
0
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
									 int sock, eloop_sock_handler handler, void *eloop_data, void *user_data)
{
	struct eloop_sock *tmp;
	int new_max_sock;

	if (sock > eloop.max_sock)
		new_max_sock = sock;
	else
		new_max_sock = eloop.max_sock;

	if (table == NULL)
		return -1;

	if (new_max_sock >= eloop.max_pollfd_map) {
		struct pollfd **nmap;
		nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50, sizeof(struct pollfd *));
		if (nmap == NULL)
			return -1;

		eloop.max_pollfd_map = new_max_sock + 50;
		eloop.pollfds_map = nmap;
	}

	if (eloop.count + 1 > eloop.max_poll_fds) {
		struct pollfd *n;
		int nmax = eloop.count + 1 + 50;
		n = os_realloc_array(eloop.pollfds, nmax, sizeof(struct pollfd));
		if (n == NULL)
			return -1;

		eloop.max_poll_fds = nmax;
		eloop.pollfds = n;
	}

	tmp = os_realloc_array(table->table, table->count + 1, sizeof(struct eloop_sock));
	if (tmp == NULL)
		return -1;

	tmp[table->count].sock = sock;
	tmp[table->count].eloop_data = eloop_data;
	tmp[table->count].user_data = user_data;
	tmp[table->count].handler = handler;
	table->count++;
	table->table = tmp;
	eloop.max_sock = new_max_sock;
	eloop.count++;
	table->changed = 1;

	return 0;
}
Example #3
0
static int * bgscan_learn_get_supp_freqs(struct wpa_supplicant *wpa_s)
{
	struct hostapd_hw_modes *modes;
	int i, j, *freqs = NULL, *n;
	size_t count = 0;

	modes = wpa_s->hw.modes;
	if (modes == NULL)
		return NULL;

	for (i = 0; i < wpa_s->hw.num_modes; i++) {
		for (j = 0; j < modes[i].num_channels; j++) {
			if (modes[i].channels[j].flag & HOSTAPD_CHAN_DISABLED)
				continue;
			/* some hw modes (e.g. 11b & 11g) contain same freqs */
			if (in_array(freqs, modes[i].channels[j].freq))
				continue;
			n = os_realloc_array(freqs, count + 2, sizeof(int));
			if (n == NULL)
				continue;

			freqs = n;
			freqs[count] = modes[i].channels[j].freq;
			count++;
			freqs[count] = 0;
		}
	}

	return freqs;
}
Example #4
0
static int * bgscan_learn_get_probe_freq(struct bgscan_learn_data *data,
					 int *freqs, size_t count)
{
	int idx, *n;

	if (data->supp_freqs == NULL)
		return freqs;

	idx = data->probe_idx;
	do {
		if (!in_array(freqs, data->supp_freqs[idx])) {
			wpa_printf(MSG_DEBUG, "bgscan learn: Probe new freq "
				   "%u", data->supp_freqs[idx]);
			data->probe_idx = idx + 1;
			if (data->supp_freqs[data->probe_idx] == 0)
				data->probe_idx = 0;
			n = os_realloc_array(freqs, count + 2, sizeof(int));
			if (n == NULL)
				return freqs;
			freqs = n;
			freqs[count] = data->supp_freqs[idx];
			count++;
			freqs[count] = 0;
			break;
		}

		idx++;
		if (data->supp_freqs[idx] == 0)
			idx = 0;
	} while (idx != data->probe_idx);

	return freqs;
}
Example #5
0
struct p2p_group * p2p_group_init(struct p2p_data *p2p,
				  struct p2p_group_config *config)
{
	struct p2p_group *group, **groups;

	group = os_zalloc(sizeof(*group));
	if (group == NULL)
		return NULL;

	groups = os_realloc_array(p2p->groups, p2p->num_groups + 1,
				  sizeof(struct p2p_group *));
	if (groups == NULL) {
		os_free(group);
		return NULL;
	}
	groups[p2p->num_groups++] = group;
	p2p->groups = groups;

	group->p2p = p2p;
	group->cfg = config;
	group->group_formation = 1;
	group->beacon_update = 1;
	p2p_group_update_ies(group);
	group->cfg->idle_update(group->cfg->cb_ctx, 1);

	return group;
}
Example #6
0
int eloop_register_event(void *event, size_t event_size,
			 eloop_event_handler handler,
			 void *eloop_data, void *user_data)
{
	struct eloop_event *tmp;
	HANDLE h = event;

	if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
		return -1;

	if (eloop_prepare_handles())
		return -1;

	tmp = os_realloc_array(eloop.events, eloop.event_count + 1,
			       sizeof(struct eloop_event));
	if (tmp == NULL)
		return -1;

	tmp[eloop.event_count].eloop_data = eloop_data;
	tmp[eloop.event_count].user_data = user_data;
	tmp[eloop.event_count].handler = handler;
	tmp[eloop.event_count].event = h;
	eloop.event_count++;
	eloop.events = tmp;

	return 0;
}
Example #7
0
/**
 * radius_client_register - Register a RADIUS client RX handler
 * @radius: RADIUS client context from radius_client_init()
 * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT)
 * @handler: Handler for received RADIUS messages
 * @data: Context pointer for handler callbacks
 * Returns: 0 on success, -1 on failure
 *
 * This function is used to register a handler for processing received RADIUS
 * authentication and accounting messages. The handler() callback function will
 * be called whenever a RADIUS message is received from the active server.
 *
 * There can be multiple registered RADIUS message handlers. The handlers will
 * be called in order until one of them indicates that it has processed or
 * queued the message.
 */
int radius_client_register(struct radius_client_data *radius,
			   RadiusType msg_type,
			   RadiusRxResult (*handler)(struct radius_msg *msg,
						     struct radius_msg *req,
						     const u8 *shared_secret,
						     size_t shared_secret_len,
						     void *data),
			   void *data)
{
	struct radius_rx_handler **handlers, *newh;
	size_t *num;

	if (msg_type == RADIUS_ACCT) {
		handlers = &radius->acct_handlers;
		num = &radius->num_acct_handlers;
	} else {
		handlers = &radius->auth_handlers;
		num = &radius->num_auth_handlers;
	}

	newh = os_realloc_array(*handlers, *num + 1,
				sizeof(struct radius_rx_handler));
	if (newh == NULL)
		return -1;

	newh[*num].handler = handler;
	newh[*num].data = data;
	(*num)++;
	*handlers = newh;

	return 0;
}
static void add_alt_name_othername(struct http_ctx *ctx, struct http_cert *cert,
				   OTHERNAME *o)
{
	char txt[100];
	int res;
	struct http_othername *on;
	ASN1_TYPE *val;

	on = os_realloc_array(cert->othername, cert->num_othername + 1,
			      sizeof(struct http_othername));
	if (on == NULL)
		return;
	cert->othername = on;
	on = &on[cert->num_othername];
	os_memset(on, 0, sizeof(*on));

	res = OBJ_obj2txt(txt, sizeof(txt), o->type_id, 1);
	if (res < 0 || res >= (int) sizeof(txt))
		return;

	on->oid = os_strdup(txt);
	if (on->oid == NULL)
		return;

	val = o->value;
	on->data = val->value.octet_string->data;
	on->len = val->value.octet_string->length;

	cert->num_othername++;
}
static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
{
	struct wpa_supplicant *wpa_s = eloop_ctx;
	unsigned int timeout, sec, usec;
	u8 *trans_id, *nbuf;

	if (wpa_s->sme.sa_query_count > 0 &&
	    sme_check_sa_query_timeout(wpa_s))
		return;

	nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
				wpa_s->sme.sa_query_count + 1,
				WLAN_SA_QUERY_TR_ID_LEN);
	if (nbuf == NULL)
		return;
	if (wpa_s->sme.sa_query_count == 0) {
		/* Starting a new SA Query procedure */
		os_get_time(&wpa_s->sme.sa_query_start);
	}
	trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
	wpa_s->sme.sa_query_trans_id = nbuf;
	wpa_s->sme.sa_query_count++;

	os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);

	timeout = sa_query_retry_timeout;
	sec = ((timeout / 1000) * 1024) / 1000;
	usec = (timeout % 1000) * 1024;
	eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);

	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
		wpa_s->sme.sa_query_count);

	sme_send_sa_query_req(wpa_s, trans_id);
}
static void
wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
			      struct ieee80211req_scan_result *sr)
{
	struct wpa_scan_res *result, **tmp;
	size_t extra_len;
	u8 *pos;

	extra_len = 2 + sr->isr_ssid_len;
	extra_len += 2 + sr->isr_nrates;
	extra_len += 3; /* ERP IE */
	extra_len += sr->isr_ie_len;

	result = os_zalloc(sizeof(*result) + extra_len);
	if (result == NULL)
		return;
	os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN);
	result->freq = sr->isr_freq;
	result->beacon_int = sr->isr_intval;
	result->caps = sr->isr_capinfo;
	result->qual = sr->isr_rssi;
	result->noise = sr->isr_noise;

	pos = (u8 *)(result + 1);

	*pos++ = WLAN_EID_SSID;
	*pos++ = sr->isr_ssid_len;
	os_memcpy(pos, sr + 1, sr->isr_ssid_len);
	pos += sr->isr_ssid_len;

	/*
	 * Deal all rates as supported rate.
	 * Because net80211 doesn't report extended supported rate or not.
	 */
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos++ = sr->isr_nrates;
	os_memcpy(pos, sr->isr_rates, sr->isr_nrates);
	pos += sr->isr_nrates;

	*pos++ = WLAN_EID_ERP_INFO;
	*pos++ = 1;
	*pos++ = sr->isr_erp;

	os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len);
	pos += sr->isr_ie_len;

	result->ie_len = pos - (u8 *)(result + 1);

	tmp = os_realloc_array(res->res, res->num + 1,
			       sizeof(struct wpa_scan_res *));
	if (tmp == NULL) {
		os_free(result);
		return;
	}
	tmp[res->num++] = result;
	res->res = tmp;
}
static dbus_bool_t _wpa_dbus_dict_entry_get_binarray(
	DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
{
	struct wpa_dbus_dict_entry tmpentry;
	size_t buflen = 0;
	int i;

	if (dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE)
		return FALSE;

	entry->array_type = WPAS_DBUS_TYPE_BINARRAY;
	entry->array_len = 0;
	entry->binarray_value = NULL;

	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
		DBusMessageIter iter_array;

		if (entry->array_len == buflen) {
			struct wpabuf **newbuf;

			buflen += BIN_ARRAY_CHUNK_SIZE;

			newbuf = os_realloc_array(entry->binarray_value,
						  buflen, BIN_ARRAY_ITEM_SIZE);
			if (!newbuf)
				goto cleanup;
			entry->binarray_value = newbuf;
		}

		dbus_message_iter_recurse(iter, &iter_array);
		if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry)
					== FALSE)
			goto cleanup;

		entry->binarray_value[entry->array_len] =
			wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value,
					      tmpentry.array_len);
		if (entry->binarray_value[entry->array_len] == NULL) {
			wpa_dbus_dict_entry_clear(&tmpentry);
			goto cleanup;
		}
		entry->array_len++;
		dbus_message_iter_next(iter);
	}

	return TRUE;

 cleanup:
	for (i = 0; i < (int) entry->array_len; i++)
		wpabuf_free(entry->binarray_value[i]);
	os_free(entry->binarray_value);
	entry->array_len = 0;
	entry->binarray_value = NULL;
	return FALSE;
}
Example #12
0
/**
 * Decrease the usage counter for given ifname.
 * Returns
 *     -1 on error or if iface was not found
 *     0 if iface was found and is still present
 *     1 if iface was removed from global list
 */
static int hapd_put_dynamic_iface(const char *parent, const char *ifname,
				  struct hostapd_data *hapd)
{
	size_t i;
	struct hostapd_dynamic_iface *j = NULL, **tmp;
	struct hapd_interfaces *hapd_glob = hapd->iface->interfaces;

	if (!parent)
		parent = "";

	for (i = 0; i < hapd_glob->count_dynamic; i++) {
		j = hapd_glob->dynamic_iface[i];
		if (os_strncmp(j->iface, ifname, sizeof(j->iface)) == 0 &&
		    os_strncmp(j->parent, parent, sizeof(j->parent)) == 0)
			break;
	}

	if (i == hapd_glob->count_dynamic) {
		/*
		 * Interface not in global list. This can happen if alloc in
		 * _get_ failed.
		 */
		return -1;
	}

	if (j->usage > 0) {
		j->usage--;
		return 0;
	}

	os_free(j);
	for (; i < hapd_glob->count_dynamic - 1; i++)
		hapd_glob->dynamic_iface[i] = hapd_glob->dynamic_iface[i + 1];
	hapd_glob->dynamic_iface[hapd_glob->count_dynamic - 1] = NULL;
	hapd_glob->count_dynamic--;

	if (hapd_glob->count_dynamic == 0) {
		os_free(hapd_glob->dynamic_iface);
		hapd_glob->dynamic_iface = NULL;
		return 1;
	}

	tmp = os_realloc_array(hapd_glob->dynamic_iface,
			       hapd_glob->count_dynamic,
			       sizeof(*hapd_glob->dynamic_iface));
	if (!tmp) {
		wpa_printf(MSG_ERROR, "VLAN: Failed to release memory in %s",
			   __func__);
		return -1;
	}
	hapd_glob->dynamic_iface = tmp;

	return 1;
}
static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
	DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
{
	dbus_uint32_t count = 0;
	dbus_bool_t success = FALSE;
	char *buffer, *nbuffer;

	entry->bytearray_value = NULL;
	entry->array_type = DBUS_TYPE_BYTE;

	buffer = os_calloc(BYTE_ARRAY_CHUNK_SIZE, BYTE_ARRAY_ITEM_SIZE);
	if (!buffer)
		return FALSE;

	entry->bytearray_value = buffer;
	entry->array_len = 0;
	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
		char byte;

		if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
			nbuffer = os_realloc_array(
				buffer, count + BYTE_ARRAY_CHUNK_SIZE,
				BYTE_ARRAY_ITEM_SIZE);
			if (nbuffer == NULL) {
				os_free(buffer);
				wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_"
					   "entry_get_byte_array out of "
					   "memory trying to retrieve the "
					   "string array");
				goto done;
			}
			buffer = nbuffer;
		}
		entry->bytearray_value = buffer;

		dbus_message_iter_get_basic(iter, &byte);
		entry->bytearray_value[count] = byte;
		entry->array_len = ++count;
		dbus_message_iter_next(iter);
	}

	/* Zero-length arrays are valid. */
	if (entry->array_len == 0) {
		os_free(entry->bytearray_value);
		entry->bytearray_value = NULL;
	}

	success = TRUE;

done:
	return success;
}
Example #14
0
static int eloop_prepare_handles(void)
{
	HANDLE *n;

	if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
		return 0;
	n = os_realloc_array(eloop.handles, eloop.num_handles * 2,
			     sizeof(eloop.handles[0]));
	if (n == NULL)
		return -1;
	eloop.handles = n;
	eloop.num_handles *= 2;
	return 0;
}
Example #15
0
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
{
    struct hostapd_data *hapd = eloop_ctx;
    struct sta_info *sta = timeout_ctx;
    unsigned int timeout, sec, usec;
    u8 *trans_id, *nbuf;

    wpa_printf(MSG_DEBUG, "%s: SA Query timer for STA " MACSTR
               " (count=%d)",
               hapd->conf->iface, MAC2STR(sta->addr), sta->sa_query_count);

    if (sta->sa_query_count > 0 &&
            ap_check_sa_query_timeout(hapd, sta))
        return;

    nbuf = os_realloc_array(sta->sa_query_trans_id,
                            sta->sa_query_count + 1,
                            WLAN_SA_QUERY_TR_ID_LEN);
    if (nbuf == NULL)
        return;
    if (sta->sa_query_count == 0) {
        /* Starting a new SA Query procedure */
        os_get_reltime(&sta->sa_query_start);
    }
    trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
    sta->sa_query_trans_id = nbuf;
    sta->sa_query_count++;

    if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
        /*
         * We don't really care which ID is used here, so simply
         * hardcode this if the mostly theoretical os_get_random()
         * failure happens.
         */
        trans_id[0] = 0x12;
        trans_id[1] = 0x34;
    }

    timeout = hapd->conf->assoc_sa_query_retry_timeout;
    sec = ((timeout / 1000) * 1024) / 1000;
    usec = (timeout % 1000) * 1024;
    eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);

    hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                   HOSTAPD_LEVEL_DEBUG,
                   "association SA Query attempt %d", sta->sa_query_count);

    ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
}
Example #16
0
static void bgscan_learn_add_neighbor(struct bgscan_learn_bss *bss,
				      const u8 *bssid)
{
	u8 *n;

	if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
		return;
	if (bssid_in_array(bss->neigh, bss->num_neigh, bssid))
		return;

	n = os_realloc_array(bss->neigh, bss->num_neigh + 1, ETH_ALEN);
	if (n == NULL)
		return;

	os_memcpy(n + bss->num_neigh * ETH_ALEN, bssid, ETH_ALEN);
	bss->neigh = n;
	bss->num_neigh++;
}
Example #17
0
static void int_array_concat(int **res, const int *a)
{
	int reslen, alen, i;
	int *n;

	reslen = int_array_len(*res);
	alen = int_array_len(a);

	n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
	if (n == NULL) {
		os_free(*res);
		*res = NULL;
		return;
	}
	for (i = 0; i <= alen; i++)
		n[reslen + i] = a[i];
	*res = n;
}
Example #18
0
/**
 * Increase the usage counter for given parent/ifname combination.
 * If create is set, then this iface is added to the global list.
 * Returns
 * 	-1 on error
 * 	0 if iface is not in list
 * 	1 if iface is in list (was there or has been added)
 */
static int hapd_get_dynamic_iface(const char *parent, const char *ifname,
				  int create, struct hostapd_data *hapd)
{
	size_t i;
	struct hostapd_dynamic_iface *j = NULL, **tmp;
	struct hapd_interfaces *hapd_global = hapd->iface->interfaces;

	if (!parent)
		parent = "";

	for (i = 0; i < hapd_global->count_dynamic; i++) {
		j = hapd_global->dynamic_iface[i];
		if (os_strncmp(j->iface, ifname, sizeof(j->iface)) == 0 &&
		    os_strncmp(j->parent, parent, sizeof(j->parent)) == 0)
			break;
	}
	if (i < hapd_global->count_dynamic) {
		j->usage++;
		return 1;
	}

	/* new entry required */
	if (!create)
		return 0;

	j = os_zalloc(sizeof(*j));
	if (!j)
		return -1;
	os_strlcpy(j->iface, ifname, sizeof(j->iface));
	os_strlcpy(j->parent, parent, sizeof(j->parent));

	tmp = os_realloc_array(hapd_global->dynamic_iface, i + 1,
			       sizeof(*hapd_global->dynamic_iface));
	if (!tmp) {
		wpa_printf(MSG_ERROR, "VLAN: Failed to allocate memory in %s",
			   __func__);
		return -1;
	}
	hapd_global->count_dynamic++;
	hapd_global->dynamic_iface = tmp;
	hapd_global->dynamic_iface[i] = j;

	return 1;
}
static void add_alt_name_dns(struct http_ctx *ctx, struct http_cert *cert,
			     ASN1_STRING *name)
{
	char *buf;
	char **n;

	buf = NULL;
	if (ASN1_STRING_to_UTF8((unsigned char **) &buf, name) < 0)
		return;

	n = os_realloc_array(cert->dnsname, cert->num_dnsname + 1,
			     sizeof(char *));
	if (n == NULL)
		return;

	cert->dnsname = n;
	n[cert->num_dnsname] = buf;
	cert->num_dnsname++;
}
Example #20
0
int eloop_register_signal(int sig, eloop_signal_handler handler,
			  void *user_data)
{
	struct eloop_signal *tmp;

	tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
			       sizeof(struct eloop_signal));
	if (tmp == NULL)
		return -1;

	tmp[eloop.signal_count].sig = sig;
	tmp[eloop.signal_count].user_data = user_data;
	tmp[eloop.signal_count].handler = handler;
	tmp[eloop.signal_count].signaled = 0;
	eloop.signal_count++;
	eloop.signals = tmp;
	signal(sig, eloop_handle_signal);

	return 0;
}
Example #21
0
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
			     void *eloop_data, void *user_data)
{
	WSAEVENT event;
	struct eloop_sock *tmp;

	if (eloop_prepare_handles())
		return -1;

	event = WSACreateEvent();
	if (event == WSA_INVALID_EVENT) {
		printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
		return -1;
	}

	if (WSAEventSelect(sock, event, FD_READ)) {
		printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
		WSACloseEvent(event);
		return -1;
	}
	tmp = os_realloc_array(eloop.readers, eloop.reader_count + 1,
			       sizeof(struct eloop_sock));
	if (tmp == NULL) {
		WSAEventSelect(sock, event, 0);
		WSACloseEvent(event);
		return -1;
	}

	tmp[eloop.reader_count].sock = sock;
	tmp[eloop.reader_count].eloop_data = eloop_data;
	tmp[eloop.reader_count].user_data = user_data;
	tmp[eloop.reader_count].handler = handler;
	tmp[eloop.reader_count].event = event;
	eloop.reader_count++;
	eloop.readers = tmp;
	if (sock > eloop.max_sock)
		eloop.max_sock = sock;
	eloop.reader_table_changed = 1;

	return 0;
}
static int radius_msg_add_attr_to_array(struct radius_msg *msg,
					struct radius_attr_hdr *attr)
{
	if (msg->attr_used >= msg->attr_size) {
		size_t *nattr_pos;
		int nlen = msg->attr_size * 2;

		nattr_pos = os_realloc_array(msg->attr_pos, nlen,
					     sizeof(*msg->attr_pos));
		if (nattr_pos == NULL)
			return -1;

		msg->attr_pos = nattr_pos;
		msg->attr_size = nlen;
	}

	msg->attr_pos[msg->attr_used++] =
		(unsigned char *) attr - wpabuf_head_u8(msg->buf);

	return 0;
}
Example #23
0
static int * bgscan_learn_get_freqs(struct bgscan_learn_data *data,
				    size_t *count)
{
	struct bgscan_learn_bss *bss;
	int *freqs = NULL, *n;

	*count = 0;

	dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
		if (in_array(freqs, bss->freq))
			continue;
		n = os_realloc_array(freqs, *count + 2, sizeof(int));
		if (n == NULL)
			return freqs;
		freqs = n;
		freqs[*count] = bss->freq;
		(*count)++;
		freqs[*count] = 0;
	}

	return freqs;
}
Example #24
0
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
                                 int (*cb)(void *ctx, const u8 *sa,
                                         const u8 *da, const u8 *bssid,
                                         const u8 *ie, size_t ie_len,
                                         int ssi_signal),
                                 void *ctx)
{
    struct hostapd_probereq_cb *n;

    n = os_realloc_array(hapd->probereq_cb, hapd->num_probereq_cb + 1,
                         sizeof(struct hostapd_probereq_cb));
    if (n == NULL)
        return -1;

    hapd->probereq_cb = n;
    n = &hapd->probereq_cb[hapd->num_probereq_cb];
    hapd->num_probereq_cb++;

    n->cb = cb;
    n->ctx = ctx;

    return 0;
}
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
{
	struct hostapd_data *hapd = eloop_ctx;
	struct sta_info *sta = timeout_ctx;
	unsigned int timeout, sec, usec;
	u8 *trans_id, *nbuf;

	if (sta->sa_query_count > 0 &&
	    ap_check_sa_query_timeout(hapd, sta))
		return;

	nbuf = os_realloc_array(sta->sa_query_trans_id,
				sta->sa_query_count + 1,
				WLAN_SA_QUERY_TR_ID_LEN);
	if (nbuf == NULL)
		return;
	if (sta->sa_query_count == 0) {
		/* Starting a new SA Query procedure */
		os_get_time(&sta->sa_query_start);
	}
	trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
	sta->sa_query_trans_id = nbuf;
	sta->sa_query_count++;

	os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);

	timeout = hapd->conf->assoc_sa_query_retry_timeout;
	sec = ((timeout / 1000) * 1024) / 1000;
	usec = (timeout % 1000) * 1024;
	eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);

	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
		       HOSTAPD_LEVEL_DEBUG,
		       "association SA Query attempt %d", sta->sa_query_count);

	ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
}
Example #26
0
int main(int argc, char *argv[])
{
	int c, i;
	struct wpa_interface *ifaces, *iface;
	int iface_count, exitcode = -1;
	struct wpa_params params;
	struct wpa_global *global;

	if (os_program_init())
		return -1;

	os_memset(&params, 0, sizeof(params));
	params.wpa_debug_level = MSG_INFO;

	iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
	if (ifaces == NULL)
		return -1;
	iface_count = 1;

	wpa_supplicant_fd_workaround(1);

	for (;;) {
		c = getopt(argc, argv,
			   "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
		if (c < 0)
			break;
		switch (c) {
		case 'b':
			iface->bridge_ifname = optarg;
			break;
		case 'B':
			params.daemonize++;
			break;
		case 'c':
			iface->confname = optarg;
			break;
		case 'C':
			iface->ctrl_interface = optarg;
			break;
		case 'D':
			iface->driver = optarg;
			break;
		case 'd':
#ifdef CONFIG_NO_STDOUT_DEBUG
			printf("Debugging disabled with "
			       "CONFIG_NO_STDOUT_DEBUG=y build time "
			       "option.\n");
			goto out;
#else /* CONFIG_NO_STDOUT_DEBUG */
			params.wpa_debug_level--;
			break;
#endif /* CONFIG_NO_STDOUT_DEBUG */
		case 'e':
			params.entropy_file = optarg;
			break;
#ifdef CONFIG_DEBUG_FILE
		case 'f':
			params.wpa_debug_file_path = optarg;
			break;
#endif /* CONFIG_DEBUG_FILE */
		case 'g':
			params.ctrl_interface = optarg;
			break;
		case 'G':
			params.ctrl_interface_group = optarg;
			break;
		case 'h':
			usage();
			exitcode = 0;
			goto out;
		case 'i':
			iface->ifname = optarg;
			break;
		case 'I':
			iface->confanother = optarg;
			break;
		case 'K':
			params.wpa_debug_show_keys++;
			break;
		case 'L':
			license();
			exitcode = 0;
			goto out;
#ifdef CONFIG_P2P
		case 'm':
			params.conf_p2p_dev = optarg;
			break;
#endif /* CONFIG_P2P */
		case 'o':
			params.override_driver = optarg;
			break;
		case 'O':
			params.override_ctrl_interface = optarg;
			break;
		case 'p':
			iface->driver_param = optarg;
			break;
		case 'P':
			os_free(params.pid_file);
			params.pid_file = os_rel2abs_path(optarg);
			break;
		case 'q':
			params.wpa_debug_level++;
			break;
#ifdef CONFIG_DEBUG_SYSLOG
		case 's':
			params.wpa_debug_syslog++;
			break;
#endif /* CONFIG_DEBUG_SYSLOG */
#ifdef CONFIG_DEBUG_LINUX_TRACING
		case 'T':
			params.wpa_debug_tracing++;
			break;
#endif /* CONFIG_DEBUG_LINUX_TRACING */
		case 't':
			params.wpa_debug_timestamp++;
			break;
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
		case 'u':
			params.dbus_ctrl_interface = 1;
			break;
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
		case 'v':
			printf("%s\n", wpa_supplicant_version);
			exitcode = 0;
			goto out;
		case 'W':
			params.wait_for_monitor++;
			break;
#ifdef CONFIG_MATCH_IFACE
		case 'M':
			params.match_iface_count++;
			iface = os_realloc_array(params.match_ifaces,
						 params.match_iface_count,
						 sizeof(struct wpa_interface));
			if (!iface)
				goto out;
			params.match_ifaces = iface;
			iface = &params.match_ifaces[params.match_iface_count -
						     1];
			os_memset(iface, 0, sizeof(*iface));
			break;
#endif /* CONFIG_MATCH_IFACE */
		case 'N':
			iface_count++;
			iface = os_realloc_array(ifaces, iface_count,
						 sizeof(struct wpa_interface));
			if (iface == NULL)
				goto out;
			ifaces = iface;
			iface = &ifaces[iface_count - 1];
			os_memset(iface, 0, sizeof(*iface));
			break;
		default:
			usage();
			exitcode = 0;
			goto out;
		}
	}

	exitcode = 0;
	global = wpa_supplicant_init(&params);
	if (global == NULL) {
		wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
		exitcode = -1;
		goto out;
	} else {
		wpa_printf(MSG_INFO, "Successfully initialized "
			   "wpa_supplicant");
	}

	if (fst_global_init()) {
		wpa_printf(MSG_ERROR, "Failed to initialize FST");
		exitcode = -1;
		goto out;
	}

#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
	if (!fst_global_add_ctrl(fst_ctrl_cli))
		wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
#endif

	for (i = 0; exitcode == 0 && i < iface_count; i++) {
		struct wpa_supplicant *wpa_s;

		if ((ifaces[i].confname == NULL &&
		     ifaces[i].ctrl_interface == NULL) ||
		    ifaces[i].ifname == NULL) {
			if (iface_count == 1 && (params.ctrl_interface ||
#ifdef CONFIG_MATCH_IFACE
						 params.match_iface_count ||
#endif /* CONFIG_MATCH_IFACE */
						 params.dbus_ctrl_interface))
				break;
			usage();
			exitcode = -1;
			break;
		}
		wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
		if (wpa_s == NULL) {
			exitcode = -1;
			break;
		}
	}

#ifdef CONFIG_MATCH_IFACE
	if (exitcode == 0)
		exitcode = wpa_supplicant_init_match(global);
#endif /* CONFIG_MATCH_IFACE */

	if (exitcode == 0)
		exitcode = wpa_supplicant_run(global);

	wpa_supplicant_deinit(global);

	fst_global_deinit();

out:
	wpa_supplicant_fd_workaround(0);
	os_free(ifaces);
#ifdef CONFIG_MATCH_IFACE
	os_free(params.match_ifaces);
#endif /* CONFIG_MATCH_IFACE */
	os_free(params.pid_file);

	os_program_deinit();

	return exitcode;
}
Example #27
0
File: main.c Project: imw/hapd
int main(int argc, char *argv[])
{
	struct hapd_interfaces interfaces;
	int ret = 1;
	size_t i, j;
	int c, debug = 0;
	const char *log_file = NULL;
	const char *entropy_file = NULL;
	char **bss_config = NULL, **tmp_bss;
	size_t num_bss_configs = 0;
#ifdef CONFIG_DEBUG_LINUX_TRACING
	int enable_trace_dbg = 0;
#endif /* CONFIG_DEBUG_LINUX_TRACING */

	if (os_program_init())
		return -1;

	os_memset(&interfaces, 0, sizeof(interfaces));
	interfaces.reload_config = hostapd_reload_config;
	interfaces.config_read_cb = hostapd_config_read;
	interfaces.for_each_interface = hostapd_for_each_interface;
	interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
	interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
	interfaces.driver_init = hostapd_driver_init;
	interfaces.global_iface_path = NULL;
	interfaces.global_iface_name = NULL;
	interfaces.global_ctrl_sock = -1;

	wpa_supplicant_event = hostapd_wpa_event;
	for (;;) {
		c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:g:G:v::");
		if (c < 0)
			break;
		switch (c) {
		case 'h':
			usage();
			break;
		case 'd':
			debug++;
			if (wpa_debug_level > 0)
				wpa_debug_level--;
			break;
		case 'B':
			daemonize++;
			break;
		case 'e':
			entropy_file = optarg;
			break;
		case 'f':
			log_file = optarg;
			break;
		case 'K':
			wpa_debug_show_keys++;
			break;
		case 'P':
			os_free(pid_file);
			pid_file = os_rel2abs_path(optarg);
			break;
		case 't':
			wpa_debug_timestamp++;
			break;
#ifdef CONFIG_DEBUG_LINUX_TRACING
		case 'T':
			enable_trace_dbg = 1;
			break;
#endif /* CONFIG_DEBUG_LINUX_TRACING */
		case 'v':
			if (optarg)
				exit(!has_feature(optarg));
			show_version();
			exit(1);
			break;
		case 'g':
			if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
				return -1;
			break;
		case 'G':
			if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
				return -1;
			break;
		case 'b':
			tmp_bss = os_realloc_array(bss_config,
						   num_bss_configs + 1,
						   sizeof(char *));
			if (tmp_bss == NULL)
				goto out;
			bss_config = tmp_bss;
			bss_config[num_bss_configs++] = optarg;
			break;
#ifdef CONFIG_WPS
		case 'u':
			return gen_uuid(optarg);
#endif /* CONFIG_WPS */
		default:
			usage();
			break;
		}
	}

	if (optind == argc && interfaces.global_iface_path == NULL &&
	    num_bss_configs == 0)
		usage();

	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);

	if (log_file)
		wpa_debug_open_file(log_file);
#ifdef CONFIG_DEBUG_LINUX_TRACING
	if (enable_trace_dbg) {
		int tret = wpa_debug_open_linux_tracing();
		if (tret) {
			wpa_printf(MSG_ERROR, "Failed to enable trace logging");
			return -1;
		}
	}
#endif /* CONFIG_DEBUG_LINUX_TRACING */

	interfaces.count = argc - optind;
	if (interfaces.count || num_bss_configs) {
		interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
					     sizeof(struct hostapd_iface *));
		if (interfaces.iface == NULL) {
			wpa_printf(MSG_ERROR, "malloc failed");
			return -1;
		}
	}

	if (hostapd_global_init(&interfaces, entropy_file)) {
		wpa_printf(MSG_ERROR, "Failed to initilize global context");
		return -1;
	}

	/* Allocate and parse configuration for full interface files */
	for (i = 0; i < interfaces.count; i++) {
		interfaces.iface[i] = hostapd_interface_init(&interfaces,
							     argv[optind + i],
							     debug);
		if (!interfaces.iface[i]) {
			wpa_printf(MSG_ERROR, "Failed to initialize interface");
			goto out;
		}
	}

	/* Allocate and parse configuration for per-BSS files */
	for (i = 0; i < num_bss_configs; i++) {
		struct hostapd_iface *iface;
		char *fname;

		wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
		fname = os_strchr(bss_config[i], ':');
		if (fname == NULL) {
			wpa_printf(MSG_ERROR,
				   "Invalid BSS config identifier '%s'",
				   bss_config[i]);
			goto out;
		}
		*fname++ = '\0';
		iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
						   fname, debug);
		if (iface == NULL)
			goto out;
		for (j = 0; j < interfaces.count; j++) {
			if (interfaces.iface[j] == iface)
				break;
		}
		if (j == interfaces.count) {
			struct hostapd_iface **tmp;
			tmp = os_realloc_array(interfaces.iface,
					       interfaces.count + 1,
					       sizeof(struct hostapd_iface *));
			if (tmp == NULL) {
				hostapd_interface_deinit_free(iface);
				goto out;
			}
			interfaces.iface = tmp;
			interfaces.iface[interfaces.count++] = iface;
		}
	}

	/*
	 * Enable configured interfaces. Depending on channel configuration,
	 * this may complete full initialization before returning or use a
	 * callback mechanism to complete setup in case of operations like HT
	 * co-ex scans, ACS, or DFS are needed to determine channel parameters.
	 * In such case, the interface will be enabled from eloop context within
	 * hostapd_global_run().
	 */
	interfaces.terminate_on_error = interfaces.count;
	for (i = 0; i < interfaces.count; i++) {
		if (hostapd_driver_init(interfaces.iface[i]) ||
		    hostapd_setup_interface(interfaces.iface[i]))
			goto out;
	}

	hostapd_global_ctrl_iface_init(&interfaces);

	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
		wpa_printf(MSG_ERROR, "Failed to start eloop");
		goto out;
	}

	ret = 0;

 out:
	hostapd_global_ctrl_iface_deinit(&interfaces);
	/* Deinitialize all interfaces */
	for (i = 0; i < interfaces.count; i++) {
		if (!interfaces.iface[i])
			continue;
		interfaces.iface[i]->driver_ap_teardown =
			!!(interfaces.iface[i]->drv_flags &
			   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
		hostapd_interface_deinit_free(interfaces.iface[i]);
	}
	os_free(interfaces.iface);

	hostapd_global_deinit(pid_file);
	os_free(pid_file);

	if (log_file)
		wpa_debug_close_file();
	wpa_debug_close_linux_tracing();

	os_free(bss_config);

	os_program_deinit();

	return ret;
}
Example #28
0
/**
 * eap_peer_select_phase2_methods - Select phase 2 EAP method
 * @config: Pointer to the network configuration
 * @prefix: 'phase2' configuration prefix, e.g., "auth="
 * @types: Buffer for returning allocated list of allowed EAP methods
 * @num_types: Buffer for returning number of allocated EAP methods
 * Returns: 0 on success, -1 on failure
 *
 * This function is used to parse EAP method list and select allowed methods
 * for Phase2 authentication.
 */
int eap_peer_select_phase2_methods(struct eap_peer_config *config,
				   const char *prefix,
				   struct eap_method_type **types,
				   size_t *num_types)
{
	char *start, *pos, *buf;
	struct eap_method_type *methods = NULL, *_methods;
	u8 method;
	size_t num_methods = 0, prefix_len;

	if (config == NULL || config->phase2 == NULL)
		goto get_defaults;

	start = buf = os_strdup(config->phase2);
	if (buf == NULL)
		return -1;

	prefix_len = os_strlen(prefix);

	while (start && *start != '\0') {
		int vendor;
		pos = os_strstr(start, prefix);
		if (pos == NULL)
			break;
		if (start != pos && *(pos - 1) != ' ') {
			start = pos + prefix_len;
			continue;
		}

		start = pos + prefix_len;
		pos = os_strchr(start, ' ');
		if (pos)
			*pos++ = '\0';
		method = eap_get_phase2_type(start, &vendor);
		if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) {
			wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP "
				   "method '%s'", start);
		} else {
			num_methods++;
			_methods = os_realloc_array(methods, num_methods,
						    sizeof(*methods));
			if (_methods == NULL) {
				os_free(methods);
				os_free(buf);
				return -1;
			}
			methods = _methods;
			methods[num_methods - 1].vendor = vendor;
			methods[num_methods - 1].method = method;
		}

		start = pos;
	}

	os_free(buf);

get_defaults:
	if (methods == NULL)
		methods = eap_get_phase2_types(config, &num_methods);

	if (methods == NULL) {
		wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available");
		return -1;
	}
	wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types",
		    (u8 *) methods,
		    num_methods * sizeof(struct eap_method_type));

	*types = methods;
	*num_types = num_methods;

	return 0;
}
static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
	DBusMessageIter *iter, int array_type,
	struct wpa_dbus_dict_entry *entry)
{
	dbus_uint32_t count = 0;
	dbus_bool_t success = FALSE;
	char **buffer, **nbuffer;

	entry->strarray_value = NULL;
	entry->array_type = DBUS_TYPE_STRING;

	buffer = os_calloc(STR_ARRAY_CHUNK_SIZE, STR_ARRAY_ITEM_SIZE);
	if (buffer == NULL)
		return FALSE;

	entry->strarray_value = buffer;
	entry->array_len = 0;
	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
		const char *value;
		char *str;

		if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
			nbuffer = os_realloc_array(
				buffer, count + STR_ARRAY_CHUNK_SIZE,
				STR_ARRAY_ITEM_SIZE);
			if (nbuffer == NULL) {
				os_free(buffer);
				wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_"
					   "entry_get_string_array out of "
					   "memory trying to retrieve the "
					   "string array");
				goto done;
			}
			buffer = nbuffer;
		}
		entry->strarray_value = buffer;

		dbus_message_iter_get_basic(iter, &value);
		str = os_strdup(value);
		if (str == NULL) {
			wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_entry_get_"
				   "string_array out of memory trying to "
				   "duplicate the string array");
			goto done;
		}
		entry->strarray_value[count] = str;
		entry->array_len = ++count;
		dbus_message_iter_next(iter);
	}

	/* Zero-length arrays are valid. */
	if (entry->array_len == 0) {
		os_free(entry->strarray_value);
		entry->strarray_value = NULL;
	}

	success = TRUE;

done:
	return success;
}
static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
			      const u8 *osu_ssid, u8 osu_ssid_len,
			      const u8 *pos, size_t len)
{
	struct osu_provider *prov;
	const u8 *end = pos + len;
	u16 len2;
	const u8 *pos2;
	u8 uri_len, osu_method_len, osu_nai_len;

	wpa_hexdump(MSG_DEBUG, "HS 2.0: Parsing OSU Provider", pos, len);
	prov = os_realloc_array(wpa_s->osu_prov,
				wpa_s->osu_prov_count + 1,
				sizeof(*prov));
	if (prov == NULL)
		return;
	wpa_s->osu_prov = prov;
	prov = &prov[wpa_s->osu_prov_count];
	os_memset(prov, 0, sizeof(*prov));

	os_memcpy(prov->bssid, bss->bssid, ETH_ALEN);
	os_memcpy(prov->osu_ssid, osu_ssid, osu_ssid_len);
	prov->osu_ssid_len = osu_ssid_len;

	/* OSU Friendly Name Length */
	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
			   "Friendly Name Length");
		return;
	}
	len2 = WPA_GET_LE16(pos);
	pos += 2;
	if (len2 > end - pos) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
			   "Friendly Name Duples");
		return;
	}
	pos2 = pos;
	pos += len2;

	/* OSU Friendly Name Duples */
	while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) {
		struct osu_lang_string *f;
		if (1 + pos2[0] > pos - pos2 || pos2[0] < 3) {
			wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name");
			break;
		}
		f = &prov->friendly_name[prov->friendly_name_count++];
		os_memcpy(f->lang, pos2 + 1, 3);
		os_memcpy(f->text, pos2 + 1 + 3, pos2[0] - 3);
		pos2 += 1 + pos2[0];
	}

	/* OSU Server URI */
	if (end - pos < 1) {
		wpa_printf(MSG_DEBUG,
			   "HS 2.0: Not enough room for OSU Server URI length");
		return;
	}
	uri_len = *pos++;
	if (uri_len > end - pos) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Server "
			   "URI");
		return;
	}
	os_memcpy(prov->server_uri, pos, uri_len);
	pos += uri_len;

	/* OSU Method list */
	if (end - pos < 1) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
			   "list length");
		return;
	}
	osu_method_len = pos[0];
	if (osu_method_len > end - pos - 1) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
			   "list");
		return;
	}
	pos2 = pos + 1;
	pos += 1 + osu_method_len;
	while (pos2 < pos) {
		if (*pos2 < 32)
			prov->osu_methods |= BIT(*pos2);
		pos2++;
	}

	/* Icons Available Length */
	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
			   "Available Length");
		return;
	}
	len2 = WPA_GET_LE16(pos);
	pos += 2;
	if (len2 > end - pos) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
			   "Available");
		return;
	}
	pos2 = pos;
	pos += len2;

	/* Icons Available */
	while (pos2 < pos) {
		struct osu_icon *icon = &prov->icon[prov->icon_count];
		u8 flen;

		if (2 + 2 + 3 + 1 + 1 > pos - pos2) {
			wpa_printf(MSG_DEBUG, "HS 2.0: Invalid Icon Metadata");
			break;
		}

		icon->width = WPA_GET_LE16(pos2);
		pos2 += 2;
		icon->height = WPA_GET_LE16(pos2);
		pos2 += 2;
		os_memcpy(icon->lang, pos2, 3);
		pos2 += 3;

		flen = *pos2++;
		if (flen > pos - pos2) {
			wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon Type");
			break;
		}
		os_memcpy(icon->icon_type, pos2, flen);
		pos2 += flen;

		if (pos - pos2 < 1) {
			wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
				   "Filename length");
			break;
		}
		flen = *pos2++;
		if (flen > pos - pos2) {
			wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
				   "Filename");
			break;
		}
		os_memcpy(icon->filename, pos2, flen);
		pos2 += flen;

		prov->icon_count++;
	}

	/* OSU_NAI */
	if (end - pos < 1) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
		return;
	}
	osu_nai_len = *pos++;
	if (osu_nai_len > end - pos) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
		return;
	}
	os_memcpy(prov->osu_nai, pos, osu_nai_len);
	pos += osu_nai_len;

	/* OSU Service Description Length */
	if (end - pos < 2) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
			   "Service Description Length");
		return;
	}
	len2 = WPA_GET_LE16(pos);
	pos += 2;
	if (len2 > end - pos) {
		wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
			   "Service Description Duples");
		return;
	}
	pos2 = pos;
	pos += len2;

	/* OSU Service Description Duples */
	while (pos - pos2 >= 4 && prov->serv_desc_count < OSU_MAX_ITEMS) {
		struct osu_lang_string *f;
		u8 descr_len;

		descr_len = *pos2++;
		if (descr_len > pos - pos2 || descr_len < 3) {
			wpa_printf(MSG_DEBUG, "Invalid OSU Service "
				   "Description");
			break;
		}
		f = &prov->serv_desc[prov->serv_desc_count++];
		os_memcpy(f->lang, pos2, 3);
		os_memcpy(f->text, pos2 + 3, descr_len - 3);
		pos2 += descr_len;
	}

	wpa_printf(MSG_DEBUG, "HS 2.0: Added OSU Provider through " MACSTR,
		   MAC2STR(bss->bssid));
	wpa_s->osu_prov_count++;
}