Add Beacon configuration for wpa_supplicant AP mode

This commit is contained in:
Jouni Malinen 2009-04-02 16:09:48 +03:00 committed by Jouni Malinen
parent 74f2ad326f
commit d2440ba01b
7 changed files with 145 additions and 36 deletions

View file

@ -1144,6 +1144,11 @@ struct wpa_driver_ops {
*/ */
int (*authenticate)(void *priv, int (*authenticate)(void *priv,
struct wpa_driver_auth_params *params); 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);
}; };
/** /**

View file

@ -3215,5 +3215,7 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
NULL /* init2 */, NULL /* init2 */,
wpa_driver_ndis_get_interfaces, wpa_driver_ndis_get_interfaces,
NULL /* scan2 */, NULL /* scan2 */,
NULL /* authenticate */ NULL /* authenticate */,
NULL /* set_beacon */,
NULL /* set_beacon_int */
}; };

View file

@ -64,6 +64,11 @@ struct wpa_driver_nl80211_data {
int associated; int associated;
u8 ssid[32]; u8 ssid[32];
size_t ssid_len; 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 #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( static int wpa_driver_nl80211_set_freq2(
struct wpa_driver_nl80211_data *drv, struct wpa_driver_nl80211_data *drv,
struct wpa_driver_associate_params *params) struct wpa_driver_associate_params *params)
{ {
struct nl_msg *msg; struct nl_msg *msg;
int ret;
msg = nlmsg_alloc(); msg = nlmsg_alloc();
if (!msg) if (!msg)
@ -1532,11 +1607,13 @@ static int wpa_driver_nl80211_set_freq2(
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
/* TODO: proper channel configuration */ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, 2437);
if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret == 0)
return 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: nla_put_failure:
return -1; 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 /* TODO: setup monitor interface (and add code somewhere to remove this
* when AP mode is stopped; associate with mode != 2 or drv_deinit) */ * when AP mode is stopped; associate with mode != 2 or drv_deinit) */
/* TODO: setup beacon */
return 0; return 0;
} }
@ -1748,4 +1824,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.get_capa = wpa_driver_nl80211_get_capa, .get_capa = wpa_driver_nl80211_get_capa,
.set_operstate = wpa_driver_nl80211_set_operstate, .set_operstate = wpa_driver_nl80211_set_operstate,
.set_country = wpa_driver_nl80211_set_country, .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 */
}; };

View file

@ -811,7 +811,9 @@ struct wpa_driver_ops wpa_driver_privsep_ops = {
NULL /* init2 */, NULL /* init2 */,
NULL /* get_interfaces */, NULL /* get_interfaces */,
NULL /* scan2 */, NULL /* scan2 */,
NULL /* authenticate */ NULL /* authenticate */,
NULL /* set_beacon */,
NULL /* set_beacon_int */
}; };

View file

@ -1327,5 +1327,7 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
wpa_driver_test_init2, wpa_driver_test_init2,
wpa_driver_test_get_interfaces, wpa_driver_test_get_interfaces,
wpa_driver_test_scan, wpa_driver_test_scan,
NULL /* authenticate */ NULL /* authenticate */,
NULL /* set_beacon */,
NULL /* set_beacon_int */
}; };

View file

@ -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, static int ap_driver_set_beacon(const char *iface, void *priv,
u8 *head, size_t head_len, const u8 *head, size_t head_len,
u8 *tail, size_t tail_len) const u8 *tail, size_t tail_len,
int dtim_period)
{ {
wpa_printf(MSG_DEBUG, "AP TODO: %s", __func__); struct ap_driver_data *drv = priv;
return -1; 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) static int ap_driver_set_beacon_int(void *priv, int value)
{ {
wpa_printf(MSG_DEBUG, "AP TODO: %s", __func__); struct ap_driver_data *drv = priv;
return -1; struct wpa_supplicant *wpa_s = drv->hapd->iface->owner;
} return wpa_drv_set_beacon_int(wpa_s, value);
static int ap_driver_set_dtim_period(const char *iface, void *priv, int value)
{
wpa_printf(MSG_DEBUG, "AP TODO: %s", __func__);
return -1;
} }
@ -261,7 +258,6 @@ static struct hapd_driver_ops ap_driver_ops =
.set_freq = ap_driver_set_freq, .set_freq = ap_driver_set_freq,
.set_beacon = ap_driver_set_beacon, .set_beacon = ap_driver_set_beacon,
.set_beacon_int = ap_driver_set_beacon_int, .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_cts_protect = ap_driver_set_cts_protect,
.set_preamble = ap_driver_set_preamble, .set_preamble = ap_driver_set_preamble,
.set_short_slot_time = ap_driver_set_short_slot_time, .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_supplicant_ap_deinit(wpa_s);
wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
os_memset(&params, 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, &params) < 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)); wpa_s->ap_iface = hapd_iface = os_zalloc(sizeof(*wpa_s->ap_iface));
if (hapd_iface == NULL) if (hapd_iface == NULL)
return -1; return -1;
@ -389,19 +400,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
return -1; return -1;
} }
wpa_printf(MSG_DEBUG, "Setting up AP (SSID='%s')",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
os_memset(&params, 0, sizeof(params));
params.ssid = ssid->ssid;
params.ssid_len = ssid->ssid_len;
params.mode = ssid->mode;
if (wpa_drv_associate(wpa_s, &params) < 0) {
wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
return -1;
}
return 0; return 0;
} }

View file

@ -378,4 +378,24 @@ static inline int wpa_drv_set_probe_req_ie(struct wpa_supplicant *wpa_s,
return -1; 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 */ #endif /* DRIVER_I_H */