~linuxhackerman/iwd

d55e00b31d7bccdbb2ea1cdeb0a749df77a51e47 — Andrew Zaborowski 1 year, 3 months ago 7713e00
ap: Move AP parameters to a struct

To limit the number of ap_start parameters, group basic AP config
parameters in the ap_config struct that is passed as a pointer and owned
by the ap_state.
2 files changed, 80 insertions(+), 61 deletions(-)

M src/ap.c
M src/ap.h
M src/ap.c => src/ap.c +68 -58
@@ 53,10 53,7 @@ struct ap_state {
	ap_event_func_t event_func;
	ap_stopped_func_t stopped_func;
	void *user_data;
	char *ssid;
	uint8_t channel;
	uint8_t *authorized_macs;
	int authorized_macs_num;
	struct ap_config *config;

	unsigned int ciphers;
	enum ie_rsn_cipher_suite group_cipher;


@@ 73,7 70,6 @@ struct ap_state {

	bool started : 1;
	bool gtk_set : 1;
	bool no_cck_rates : 1;
};

struct sta_state {


@@ 94,6 90,22 @@ struct sta_state {

static uint32_t netdev_watch;

void ap_config_free(struct ap_config *config)
{
	if (unlikely(!config))
		return;

	l_free(config->ssid);

	if (config->psk) {
		explicit_bzero(config->psk, strlen(config->psk));
		l_free(config->psk);
	}

	l_free(config->authorized_macs);
	l_free(config);
}

static void ap_sta_free(void *data)
{
	struct sta_state *sta = data;


@@ 121,8 133,6 @@ static void ap_reset(struct ap_state *ap)
{
	struct netdev *netdev = ap->netdev;

	l_free(ap->ssid);

	explicit_bzero(ap->pmk, sizeof(ap->pmk));

	if (ap->mlme_watch)


@@ 138,7 148,9 @@ static void ap_reset(struct ap_state *ap)
	if (ap->rates)
		l_uintset_free(ap->rates);

	l_free(ap->authorized_macs);
	ap_config_free(ap->config);
	ap->config = NULL;

	ap->started = false;
}



@@ 318,7 330,8 @@ static size_t ap_build_beacon_pr_head(struct ap_state *ap,

	/* SSID IE */
	ie_tlv_builder_next(&builder, IE_TYPE_SSID);
	ie_tlv_builder_set_data(&builder, ap->ssid, strlen(ap->ssid));
	ie_tlv_builder_set_data(&builder, ap->config->ssid,
				strlen(ap->config->ssid));

	/* Supported Rates IE */
	ie_tlv_builder_next(&builder, IE_TYPE_SUPPORTED_RATES);


@@ 343,7 356,7 @@ static size_t ap_build_beacon_pr_head(struct ap_state *ap,

	/* DSSS Parameter Set IE for DSSS, HR, ERP and HT PHY rates */
	ie_tlv_builder_next(&builder, IE_TYPE_DSSS_PARAMETER_SET);
	ie_tlv_builder_set_data(&builder, &ap->channel, 1);
	ie_tlv_builder_set_data(&builder, &ap->config->channel, 1);

	ie_tlv_builder_finalize(&builder, &len);
	return 36 + len;


@@ 375,7 388,8 @@ static uint32_t ap_send_mgmt_frame(struct ap_state *ap,
	struct l_genl_msg *msg;
	uint32_t ifindex = netdev_get_ifindex(ap->netdev);
	uint32_t id;
	uint32_t ch_freq = scan_channel_to_freq(ap->channel, SCAN_BAND_2_4_GHZ);
	uint32_t ch_freq = scan_channel_to_freq(ap->config->channel,
						SCAN_BAND_2_4_GHZ);

	msg = l_genl_msg_new_sized(NL80211_CMD_FRAME, 128 + frame_len);



@@ 386,7 400,7 @@ static uint32_t ap_send_mgmt_frame(struct ap_state *ap,
		l_genl_msg_append_attr(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK,
					0, NULL);

	if (ap->no_cck_rates)
	if (ap->config->no_cck_rates)
		l_genl_msg_append_attr(msg, NL80211_ATTR_TX_NO_CCK_RATE, 0,
					NULL);



@@ 446,7 460,8 @@ static void ap_start_rsna(struct sta_state *sta, const uint8_t *gtk_rsc)
	sta->hs = netdev_handshake_state_new(netdev);

	handshake_state_set_event_func(sta->hs, ap_handshake_event, sta);
	handshake_state_set_ssid(sta->hs, (void *)ap->ssid, strlen(ap->ssid));
	handshake_state_set_ssid(sta->hs, (void *) ap->config->ssid,
					strlen(ap->config->ssid));
	handshake_state_set_authenticator(sta->hs, true);
	handshake_state_set_authenticator_ie(sta->hs, bss_rsne);
	handshake_state_set_supplicant_ie(sta->hs, sta->assoc_rsne);


@@ 900,8 915,8 @@ static void ap_assoc_reassoc(struct sta_state *sta, bool reassoc,
			break;
		}

	if (!rates || !ssid || !rsn || ssid_len != strlen(ap->ssid) ||
			memcmp(ssid, ap->ssid, ssid_len)) {
	if (!rates || !ssid || !rsn || ssid_len != strlen(ap->config->ssid) ||
			memcmp(ssid, ap->config->ssid, ssid_len)) {
		err = MMPDU_REASON_CODE_INVALID_IE;
		goto bad_frame;
	}


@@ 1125,8 1140,8 @@ static void ap_probe_req_cb(const struct mmpdu_header *hdr, const void *body,

	if (!ssid || ssid_len == 0) /* Wildcard SSID */
		match = true;
	else if (ssid && ssid_len == strlen(ap->ssid) && /* Specific SSID */
			!memcmp(ssid, ap->ssid, ssid_len))
	else if (ssid && ssid_len == strlen(ap->config->ssid) && /* One SSID */
			!memcmp(ssid, ap->config->ssid, ssid_len))
		match = true;
	else if (ssid_list) { /* SSID List */
		ie_tlv_iter_init(&iter, ssid_list, ssid_list_len);


@@ 1138,15 1153,16 @@ static void ap_probe_req_cb(const struct mmpdu_header *hdr, const void *body,
			ssid = (const char *) ie_tlv_iter_get_data(&iter);
			ssid_len = ie_tlv_iter_get_length(&iter);

			if (ssid_len == strlen(ap->ssid) &&
					!memcmp(ssid, ap->ssid, ssid_len)) {
			if (ssid_len == strlen(ap->config->ssid) &&
					!memcmp(ssid, ap->config->ssid,
						ssid_len)) {
				match = true;
				break;
			}
		}
	}

	if (dsss_channel != 0 && dsss_channel != ap->channel)
	if (dsss_channel != 0 && dsss_channel != ap->config->channel)
		match = false;

	if (!match)


@@ 1247,14 1263,15 @@ static void ap_auth_cb(const struct mmpdu_header *hdr, const void *body,
			memcmp(hdr->address_3, bssid, 6))
		return;

	if (ap->authorized_macs) {
		int i;
	if (ap->config->authorized_macs_num) {
		unsigned int i;

		for (i = 0; i < ap->authorized_macs_num; i++)
			if (!memcmp(from, ap->authorized_macs + i * 6, 6))
		for (i = 0; i < ap->config->authorized_macs_num; i++)
			if (!memcmp(from, ap->config->authorized_macs + i * 6,
					6))
				break;

		if (i == ap->authorized_macs_num) {
		if (i == ap->config->authorized_macs_num) {
			ap_auth_reply(ap, from, MMPDU_REASON_CODE_UNSPECIFIED);
			return;
		}


@@ 1374,7 1391,8 @@ static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap)
	uint32_t nl_akm = CRYPTO_AKM_PSK;
	uint32_t wpa_version = NL80211_WPA_VERSION_2;
	uint32_t auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
	uint32_t ch_freq = scan_channel_to_freq(ap->channel, SCAN_BAND_2_4_GHZ);
	uint32_t ch_freq = scan_channel_to_freq(ap->config->channel,
						SCAN_BAND_2_4_GHZ);
	uint32_t ch_width = NL80211_CHAN_WIDTH_20;

	static const uint8_t bcast_addr[6] = {


@@ 1389,7 1407,7 @@ static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap)
		return NULL;

	cmd = l_genl_msg_new_sized(NL80211_CMD_START_AP, 256 + head_len +
					tail_len + strlen(ap->ssid));
					tail_len + strlen(ap->config->ssid));

	/* SET_BEACON attrs */
	l_genl_msg_append_attr(cmd, NL80211_ATTR_BEACON_HEAD, head_len, head);


@@ 1403,8 1421,8 @@ static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap)
				&ap->beacon_interval);
	l_genl_msg_append_attr(cmd, NL80211_ATTR_DTIM_PERIOD, 4, &dtim_period);
	l_genl_msg_append_attr(cmd, NL80211_ATTR_IFINDEX, 4, &ifindex);
	l_genl_msg_append_attr(cmd, NL80211_ATTR_SSID, strlen(ap->ssid),
				ap->ssid);
	l_genl_msg_append_attr(cmd, NL80211_ATTR_SSID, strlen(ap->config->ssid),
				ap->config->ssid);
	l_genl_msg_append_attr(cmd, NL80211_ATTR_HIDDEN_SSID, 4,
				&hidden_ssid);
	l_genl_msg_append_attr(cmd, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, 4,


@@ 1462,11 1480,13 @@ static void ap_mlme_notify(struct l_genl_msg *msg, void *user_data)
 * @event_func is required and must react to AP_EVENT_START_FAILED
 * and AP_EVENT_STOPPING by forgetting the ap_state struct, which
 * is going to be freed automatically.
 * @channel is optional.
 * In the @config struct only .ssid and .psk need to be non-NUL,
 * other fields are optional.  If @ap_start succeeds, the returned
 * ap_state takes ownership of @config and the caller shouldn't
 * free it or any of the memory pointed to by its members (they
 * also can't be static).
 */
struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
				const char *psk, int channel, bool no_cck_rates,
				const uint8_t **authorized_macs,
struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config,
				ap_event_func_t event_func, void *user_data)
{
	struct ap_state *ap;


@@ 1476,30 1496,14 @@ struct ap_state *ap_start(struct netdev *netdev, const char *ssid,

	ap = l_new(struct ap_state, 1);
	ap->nl80211 = l_genl_family_new(iwd_get_genl(), NL80211_GENL_NAME);
	ap->ssid = l_strdup(ssid);
	ap->config = config;
	ap->netdev = netdev;
	ap->no_cck_rates = no_cck_rates;
	ap->event_func = event_func;
	ap->user_data = user_data;

	if (channel)
		ap->channel = channel;
	else {
	if (!config->channel)
		/* TODO: Start a Get Survey to decide the channel */
		ap->channel = 6;
	}

	if (authorized_macs) {
		int i;

		for (i = 0; authorized_macs[i]; i++);
		ap->authorized_macs = l_malloc(i * 6);
		ap->authorized_macs_num = i;

		for (i = 0; authorized_macs[i]; i++)
			memcpy(ap->authorized_macs + i * 6, authorized_macs[i],
				6);
	}
		config->channel = 6;

	/* TODO: Add all ciphers supported by wiphy */
	ap->ciphers = wiphy_select_cipher(wiphy, 0xffff);


@@ 1507,7 1511,7 @@ struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
	ap->beacon_interval = 100;

	/* TODO: Pick from actual supported rates */
	if (no_cck_rates) {
	if (config->no_cck_rates) {
		l_uintset_put(ap->rates, 12); /* 6 Mbps*/
		l_uintset_put(ap->rates, 18); /* 9 Mbps*/
		l_uintset_put(ap->rates, 24); /* 12 Mbps*/


@@ 1523,8 1527,8 @@ struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
		l_uintset_put(ap->rates, 22); /* 11 Mbps*/
	}

	if (crypto_psk_from_passphrase(psk, (uint8_t *) ssid, strlen(ssid),
					ap->pmk) < 0)
	if (crypto_psk_from_passphrase(config->psk, (uint8_t *) config->ssid,
					strlen(config->ssid), ap->pmk) < 0)
		goto error;

	if (!frame_watch_add(wdev_id, 0, 0x0000 |


@@ 1757,6 1761,7 @@ static struct l_dbus_message *ap_dbus_start(struct l_dbus *dbus,
{
	struct ap_if_data *ap_if = user_data;
	const char *ssid, *wpa2_psk;
	struct ap_config *config;

	if (ap_if->ap && ap_if->ap->started)
		return dbus_error_already_exists(message);


@@ 1767,10 1772,15 @@ static struct l_dbus_message *ap_dbus_start(struct l_dbus *dbus,
	if (!l_dbus_message_get_arguments(message, "ss", &ssid, &wpa2_psk))
		return dbus_error_invalid_args(message);

	ap_if->ap = ap_start(ap_if->netdev, ssid, wpa2_psk, 0, false, NULL,
				ap_if_event_func, ap_if);
	if (!ap_if->ap)
	config = l_new(struct ap_config, 1);
	config->ssid = l_strdup(ssid);
	config->psk = l_strdup(wpa2_psk);

	ap_if->ap = ap_start(ap_if->netdev, config, ap_if_event_func, ap_if);
	if (!ap_if->ap) {
		ap_config_free(config);
		return dbus_error_invalid_args(message);
	}

	ap_if->pending = l_dbus_message_ref(message);
	return NULL;

M src/ap.h => src/ap.h +12 -3
@@ 45,9 45,18 @@ typedef void (*ap_event_func_t)(enum ap_event_type type, const void *event_data,
				void *user_data);
typedef void (*ap_stopped_func_t)(void *user_data);

struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
				const char *psk, int channel, bool no_cck_rates,
				const uint8_t **authorized_macs,
struct ap_config {
	char *ssid;
	char *psk;
	uint8_t channel;
	uint8_t *authorized_macs;
	unsigned int authorized_macs_num;
	bool no_cck_rates : 1;
};

void ap_config_free(struct ap_config *config);

struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config,
				ap_event_func_t event_func, void *user_data);
void ap_shutdown(struct ap_state *ap, ap_stopped_func_t stopped_func,
			void *user_data);