From d2440ba01b058138052c9914bab0f3d1de7d51b1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 2 Apr 2009 16:09:48 +0300 Subject: [PATCH] Add Beacon configuration for wpa_supplicant AP mode --- src/drivers/driver.h | 9 +++- src/drivers/driver_ndis.c | 4 +- src/drivers/driver_nl80211.c | 88 ++++++++++++++++++++++++++++++++++-- src/drivers/driver_privsep.c | 4 +- src/drivers/driver_test.c | 4 +- wpa_supplicant/ap.c | 52 ++++++++++----------- wpa_supplicant/driver_i.h | 20 ++++++++ 7 files changed, 145 insertions(+), 36 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 8ce74c4a2..98d38c297 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1142,8 +1142,13 @@ struct wpa_driver_ops { * function is expected to take care of IEEE 802.11 authentication, * too. */ - int (*authenticate)(void *priv, - struct wpa_driver_auth_params *params); + int (*authenticate)(void *priv, + struct wpa_driver_auth_params *params); + + int (*set_beacon)(void *priv, const u8 *head, size_t head_len, + const u8 *tail, size_t tail_len, int dtim_period); + + int (*set_beacon_int)(void *priv, int value); }; /** diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c index 879bf103c..0501d9a17 100644 --- a/src/drivers/driver_ndis.c +++ b/src/drivers/driver_ndis.c @@ -3215,5 +3215,7 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = { NULL /* init2 */, wpa_driver_ndis_get_interfaces, NULL /* scan2 */, - NULL /* authenticate */ + NULL /* authenticate */, + NULL /* set_beacon */, + NULL /* set_beacon_int */ }; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 49b5a245d..74749e87f 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -64,6 +64,11 @@ struct wpa_driver_nl80211_data { int associated; u8 ssid[32]; size_t ssid_len; + +#ifdef CONFIG_AP + int beacon_int; + unsigned int beacon_set:1; +#endif /* CONFIG_AP */ }; @@ -1517,11 +1522,81 @@ nla_put_failure: #ifdef CONFIG_AP +static int wpa_driver_nl80211_set_beacon(void *priv, + const u8 *head, size_t head_len, + const u8 *tail, size_t tail_len, + int dtim_period) +{ + struct wpa_driver_nl80211_data *drv = priv; + struct nl_msg *msg; + u8 cmd = NL80211_CMD_NEW_BEACON; + int ret; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)", + drv->beacon_set); + if (drv->beacon_set) + cmd = NL80211_CMD_SET_BEACON; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, cmd, 0); + NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, head_len, head); + NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, tail_len, tail); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + if (!drv->beacon_int) + drv->beacon_int = 100; + NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, drv->beacon_int); + NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period); + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret) { + wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", + ret, strerror(-ret)); + } else + drv->beacon_set = 1; + return ret; + nla_put_failure: + return -ENOBUFS; +} + + +static int wpa_driver_nl80211_set_beacon_int(void *priv, int value) +{ + struct wpa_driver_nl80211_data *drv = priv; + struct nl_msg *msg; + + drv->beacon_int = value; + + if (!drv->beacon_set) + return 0; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + wpa_printf(MSG_DEBUG, "nl80211: Set beacon interval %d " + "(beacon_set=%d)", value, drv->beacon_set); + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_SET_BEACON, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + + NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: + return -ENOBUFS; +} + + static int wpa_driver_nl80211_set_freq2( struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { struct nl_msg *msg; + int ret; msg = nlmsg_alloc(); if (!msg) @@ -1532,11 +1607,13 @@ static int wpa_driver_nl80211_set_freq2( NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - /* TODO: proper channel configuration */ - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, 2437); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret == 0) return 0; + wpa_printf(MSG_DEBUG, "nl80211: MLME Failed to set channel (freq=%d): " + "%d (%s)", params->freq, ret, strerror(-ret)); nla_put_failure: return -1; } @@ -1551,7 +1628,6 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, /* TODO: setup monitor interface (and add code somewhere to remove this * when AP mode is stopped; associate with mode != 2 or drv_deinit) */ - /* TODO: setup beacon */ return 0; } @@ -1748,4 +1824,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .get_capa = wpa_driver_nl80211_get_capa, .set_operstate = wpa_driver_nl80211_set_operstate, .set_country = wpa_driver_nl80211_set_country, +#ifdef CONFIG_AP + .set_beacon = wpa_driver_nl80211_set_beacon, + .set_beacon_int = wpa_driver_nl80211_set_beacon_int, +#endif /* CONFIG_AP */ }; diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c index 4895f967f..965b85540 100644 --- a/src/drivers/driver_privsep.c +++ b/src/drivers/driver_privsep.c @@ -811,7 +811,9 @@ struct wpa_driver_ops wpa_driver_privsep_ops = { NULL /* init2 */, NULL /* get_interfaces */, NULL /* scan2 */, - NULL /* authenticate */ + NULL /* authenticate */, + NULL /* set_beacon */, + NULL /* set_beacon_int */ }; diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index b8bc0b0ff..4c38122d5 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -1327,5 +1327,7 @@ const struct wpa_driver_ops wpa_driver_test_ops = { wpa_driver_test_init2, wpa_driver_test_get_interfaces, wpa_driver_test_scan, - NULL /* authenticate */ + NULL /* authenticate */, + NULL /* set_beacon */, + NULL /* set_beacon_int */ }; diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index ed5ac4845..0ccdfdd28 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -180,25 +180,22 @@ static int ap_driver_set_freq(void *priv, struct hostapd_freq_params *freq) static int ap_driver_set_beacon(const char *iface, void *priv, - u8 *head, size_t head_len, - u8 *tail, size_t tail_len) + const u8 *head, size_t head_len, + const u8 *tail, size_t tail_len, + int dtim_period) { - wpa_printf(MSG_DEBUG, "AP TODO: %s", __func__); - return -1; + struct ap_driver_data *drv = priv; + struct wpa_supplicant *wpa_s = drv->hapd->iface->owner; + return wpa_drv_set_beacon(wpa_s, head, head_len, tail, tail_len, + dtim_period); } static int ap_driver_set_beacon_int(void *priv, int value) { - wpa_printf(MSG_DEBUG, "AP TODO: %s", __func__); - return -1; -} - - -static int ap_driver_set_dtim_period(const char *iface, void *priv, int value) -{ - wpa_printf(MSG_DEBUG, "AP TODO: %s", __func__); - return -1; + struct ap_driver_data *drv = priv; + struct wpa_supplicant *wpa_s = drv->hapd->iface->owner; + return wpa_drv_set_beacon_int(wpa_s, value); } @@ -261,7 +258,6 @@ static struct hapd_driver_ops ap_driver_ops = .set_freq = ap_driver_set_freq, .set_beacon = ap_driver_set_beacon, .set_beacon_int = ap_driver_set_beacon_int, - .set_dtim_period = ap_driver_set_dtim_period, .set_cts_protect = ap_driver_set_cts_protect, .set_preamble = ap_driver_set_preamble, .set_short_slot_time = ap_driver_set_short_slot_time, @@ -348,6 +344,21 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, } wpa_supplicant_ap_deinit(wpa_s); + + wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + + os_memset(¶ms, 0, sizeof(params)); + params.ssid = ssid->ssid; + params.ssid_len = ssid->ssid_len; + params.mode = ssid->mode; + params.freq = ssid->frequency; + + if (wpa_drv_associate(wpa_s, ¶ms) < 0) { + wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); + return -1; + } + wpa_s->ap_iface = hapd_iface = os_zalloc(sizeof(*wpa_s->ap_iface)); if (hapd_iface == NULL) return -1; @@ -389,19 +400,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, return -1; } - wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - - os_memset(¶ms, 0, sizeof(params)); - params.ssid = ssid->ssid; - params.ssid_len = ssid->ssid_len; - params.mode = ssid->mode; - - if (wpa_drv_associate(wpa_s, ¶ms) < 0) { - wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality"); - return -1; - } - return 0; } diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 8bf0ae5e1..4d1446f46 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -378,4 +378,24 @@ static inline int wpa_drv_set_probe_req_ie(struct wpa_supplicant *wpa_s, return -1; } +static inline int wpa_drv_set_beacon(struct wpa_supplicant *wpa_s, + const u8 *head, size_t head_len, + const u8 *tail, size_t tail_len, + int dtim_period) +{ + if (wpa_s->driver->set_beacon) + return wpa_s->driver->set_beacon(wpa_s->drv_priv, head, + head_len, tail, tail_len, + dtim_period); + return -1; +} + +static inline int wpa_drv_set_beacon_int(struct wpa_supplicant *wpa_s, + int value) +{ + if (wpa_s->driver->set_beacon_int) + return wpa_s->driver->set_beacon_int(wpa_s->drv_priv, value); + return -1; +} + #endif /* DRIVER_I_H */