Initial step in adding simple AP mode support into wpa_supplicant
This version is adding the configuration option (mode=2) for this and driver capability reporting to figure out whether AP mode can be used. However, this does not actually implement any real functionality yet.
This commit is contained in:
parent
17449e213f
commit
1581b38b67
7 changed files with 130 additions and 6 deletions
|
@ -396,6 +396,8 @@ struct wpa_driver_capa {
|
||||||
/* Driver provides separate commands for authentication and association (SME in
|
/* Driver provides separate commands for authentication and association (SME in
|
||||||
* wpa_supplicant). */
|
* wpa_supplicant). */
|
||||||
#define WPA_DRIVER_FLAGS_SME 0x00000020
|
#define WPA_DRIVER_FLAGS_SME 0x00000020
|
||||||
|
/* Driver supports AP mode */
|
||||||
|
#define WPA_DRIVER_FLAGS_AP 0x00000040
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
int max_scan_ssids;
|
int max_scan_ssids;
|
||||||
|
|
|
@ -1274,6 +1274,7 @@ nla_put_failure:
|
||||||
|
|
||||||
struct wiphy_info_data {
|
struct wiphy_info_data {
|
||||||
int max_scan_ssids;
|
int max_scan_ssids;
|
||||||
|
int ap_supported;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1290,6 +1291,18 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
||||||
info->max_scan_ssids =
|
info->max_scan_ssids =
|
||||||
nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
|
nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
|
||||||
|
|
||||||
|
if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) {
|
||||||
|
struct nlattr *nl_mode;
|
||||||
|
int i;
|
||||||
|
nla_for_each_nested(nl_mode,
|
||||||
|
tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {
|
||||||
|
if (nl_mode->nla_type == NL80211_IFTYPE_AP) {
|
||||||
|
info->ap_supported = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1325,6 +1338,8 @@ static void wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
|
||||||
return;
|
return;
|
||||||
drv->has_capability = 1;
|
drv->has_capability = 1;
|
||||||
drv->capa.max_scan_ssids = info.max_scan_ssids;
|
drv->capa.max_scan_ssids = info.max_scan_ssids;
|
||||||
|
if (info.ap_supported)
|
||||||
|
drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1536,6 +1551,7 @@ static void wpa_driver_nl80211_deinit(void *priv)
|
||||||
|
|
||||||
if (wpa_driver_nl80211_get_ifflags(drv, &flags) == 0)
|
if (wpa_driver_nl80211_get_ifflags(drv, &flags) == 0)
|
||||||
(void) wpa_driver_nl80211_set_ifflags(drv, flags & ~IFF_UP);
|
(void) wpa_driver_nl80211_set_ifflags(drv, flags & ~IFF_UP);
|
||||||
|
wpa_driver_nl80211_set_mode(drv, 0);
|
||||||
|
|
||||||
close(drv->wext_event_sock);
|
close(drv->wext_event_sock);
|
||||||
close(drv->ioctl_sock);
|
close(drv->ioctl_sock);
|
||||||
|
@ -2311,6 +2327,48 @@ nla_put_failure:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_AP
|
||||||
|
static int wpa_driver_nl80211_set_freq2(
|
||||||
|
struct wpa_driver_nl80211_data *drv,
|
||||||
|
struct wpa_driver_associate_params *params)
|
||||||
|
{
|
||||||
|
struct nl_msg *msg;
|
||||||
|
|
||||||
|
msg = nlmsg_alloc();
|
||||||
|
if (!msg)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
|
||||||
|
NL80211_CMD_SET_WIPHY, 0);
|
||||||
|
|
||||||
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
||||||
|
|
||||||
|
/* TODO: proper channel configuration */
|
||||||
|
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, 2437);
|
||||||
|
|
||||||
|
if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
|
||||||
|
return 0;
|
||||||
|
nla_put_failure:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
|
||||||
|
struct wpa_driver_associate_params *params)
|
||||||
|
{
|
||||||
|
if (wpa_driver_nl80211_set_mode(drv, params->mode) ||
|
||||||
|
wpa_driver_nl80211_set_freq2(drv, params))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_AP */
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_nl80211_associate(
|
static int wpa_driver_nl80211_associate(
|
||||||
void *priv, struct wpa_driver_associate_params *params)
|
void *priv, struct wpa_driver_associate_params *params)
|
||||||
{
|
{
|
||||||
|
@ -2318,6 +2376,11 @@ static int wpa_driver_nl80211_associate(
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
|
|
||||||
|
#ifdef CONFIG_AP
|
||||||
|
if (params->mode == 2)
|
||||||
|
return wpa_driver_nl80211_ap(drv, params);
|
||||||
|
#endif /* CONFIG_AP */
|
||||||
|
|
||||||
wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED,
|
wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED,
|
||||||
params->drop_unencrypted);
|
params->drop_unencrypted);
|
||||||
|
|
||||||
|
@ -2390,6 +2453,21 @@ static int wpa_driver_nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
|
||||||
{
|
{
|
||||||
int ret = -1, flags;
|
int ret = -1, flags;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
|
int nlmode;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 0:
|
||||||
|
nlmode = NL80211_IFTYPE_STATION;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
nlmode = NL80211_IFTYPE_ADHOC;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
nlmode = NL80211_IFTYPE_AP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
|
@ -2398,8 +2476,7 @@ static int wpa_driver_nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
|
||||||
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
|
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
|
||||||
0, NL80211_CMD_SET_INTERFACE, 0);
|
0, NL80211_CMD_SET_INTERFACE, 0);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE,
|
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, nlmode);
|
||||||
mode ? NL80211_IFTYPE_ADHOC : NL80211_IFTYPE_STATION);
|
|
||||||
|
|
||||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -2428,9 +2505,7 @@ try_again:
|
||||||
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
|
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
|
||||||
0, NL80211_CMD_SET_INTERFACE, 0);
|
0, NL80211_CMD_SET_INTERFACE, 0);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE,
|
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, nlmode);
|
||||||
mode ? NL80211_IFTYPE_ADHOC :
|
|
||||||
NL80211_IFTYPE_STATION);
|
|
||||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_ERROR, "Failed to set interface %s "
|
wpa_printf(MSG_ERROR, "Failed to set interface %s "
|
||||||
|
|
|
@ -620,6 +620,10 @@ LIBS += -ldl -rdynamic
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_AP
|
||||||
|
CFLAGS += -DCONFIG_AP
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_EAP_SERVER
|
ifdef CONFIG_EAP_SERVER
|
||||||
CFLAGS += -DEAP_SERVER
|
CFLAGS += -DEAP_SERVER
|
||||||
OBJS_h += ../src/eap_server/eap.o
|
OBJS_h += ../src/eap_server/eap.o
|
||||||
|
|
|
@ -1366,7 +1366,7 @@ static const struct parse_data ssid_fields[] = {
|
||||||
{ STRe(pac_file) },
|
{ STRe(pac_file) },
|
||||||
{ INTe(fragment_size) },
|
{ INTe(fragment_size) },
|
||||||
#endif /* IEEE8021X_EAPOL */
|
#endif /* IEEE8021X_EAPOL */
|
||||||
{ INT_RANGE(mode, 0, 1) },
|
{ INT_RANGE(mode, 0, 2) },
|
||||||
{ INT_RANGE(proactive_key_caching, 0, 1) },
|
{ INT_RANGE(proactive_key_caching, 0, 1) },
|
||||||
{ INT_RANGE(disabled, 0, 1) },
|
{ INT_RANGE(disabled, 0, 1) },
|
||||||
{ STR(id_str) },
|
{ STR(id_str) },
|
||||||
|
|
|
@ -271,6 +271,8 @@ struct wpa_ssid {
|
||||||
*
|
*
|
||||||
* 1 = IBSS (ad-hoc, peer-to-peer)
|
* 1 = IBSS (ad-hoc, peer-to-peer)
|
||||||
*
|
*
|
||||||
|
* 2 = AP (access point)
|
||||||
|
*
|
||||||
* Note: IBSS can only be used with key_mgmt NONE (plaintext and
|
* Note: IBSS can only be used with key_mgmt NONE (plaintext and
|
||||||
* static WEP) and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In
|
* static WEP) and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In
|
||||||
* addition, ap_scan has to be set to 2 for IBSS. WPA-None requires
|
* addition, ap_scan has to be set to 2 for IBSS. WPA-None requires
|
||||||
|
|
|
@ -919,6 +919,31 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_AP
|
||||||
|
static void wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_ssid *ssid)
|
||||||
|
{
|
||||||
|
struct wpa_driver_associate_params params;
|
||||||
|
|
||||||
|
if (ssid->ssid == NULL || ssid->ssid_len == 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "No SSID configured for AP mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_AP */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_supplicant_associate - Request association
|
* wpa_supplicant_associate - Request association
|
||||||
* @wpa_s: Pointer to wpa_supplicant data
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
|
@ -940,6 +965,21 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_driver_capa capa;
|
struct wpa_driver_capa capa;
|
||||||
int assoc_failed = 0;
|
int assoc_failed = 0;
|
||||||
|
|
||||||
|
if (ssid->mode == 2) {
|
||||||
|
#ifdef CONFIG_AP
|
||||||
|
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
|
||||||
|
wpa_printf(MSG_INFO, "Driver does not support AP "
|
||||||
|
"mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_supplicant_create_ap(wpa_s, ssid);
|
||||||
|
#else /* CONFIG_AP */
|
||||||
|
wpa_printf(MSG_ERROR, "AP mode support not included in the "
|
||||||
|
"build");
|
||||||
|
#endif /* CONFIG_AP */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
|
||||||
sme_authenticate(wpa_s, bss, ssid);
|
sme_authenticate(wpa_s, bss, ssid);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -242,6 +242,7 @@ fast_reauth=1
|
||||||
# mode: IEEE 802.11 operation mode
|
# mode: IEEE 802.11 operation mode
|
||||||
# 0 = infrastructure (Managed) mode, i.e., associate with an AP (default)
|
# 0 = infrastructure (Managed) mode, i.e., associate with an AP (default)
|
||||||
# 1 = IBSS (ad-hoc, peer-to-peer)
|
# 1 = IBSS (ad-hoc, peer-to-peer)
|
||||||
|
# 2 = AP (access point)
|
||||||
# Note: IBSS can only be used with key_mgmt NONE (plaintext and static WEP)
|
# Note: IBSS can only be used with key_mgmt NONE (plaintext and static WEP)
|
||||||
# and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In addition, ap_scan has
|
# and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In addition, ap_scan has
|
||||||
# to be set to 2 for IBSS. WPA-None requires following network block options:
|
# to be set to 2 for IBSS. WPA-None requires following network block options:
|
||||||
|
|
Loading…
Reference in a new issue