nl80211: Add new commands to support mesh interfaces
Create init_mesh, mesh_join, and mesh_leave actions to kernel. Signed-off-by: Javier Lopez <jlopex@gmail.com> Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: Jason Mobarak <x@jason.mobarak.name> Signed-off-by: Bob Copeland <me@bobcopeland.com>
This commit is contained in:
parent
24bd4e0be5
commit
6c1664f605
5 changed files with 223 additions and 0 deletions
|
@ -910,6 +910,30 @@ struct wpa_driver_ap_params {
|
|||
struct hostapd_freq_params *freq;
|
||||
};
|
||||
|
||||
struct wpa_driver_mesh_bss_params {
|
||||
#define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS 0x00000001
|
||||
/*
|
||||
* TODO: Other mesh configuration parameters would go here.
|
||||
* See NL80211_MESHCONF_* for all the mesh config parameters.
|
||||
*/
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct wpa_driver_mesh_join_params {
|
||||
const u8 *meshid;
|
||||
int meshid_len;
|
||||
const int *basic_rates;
|
||||
const u8 *ies;
|
||||
int ie_len;
|
||||
int freq;
|
||||
struct wpa_driver_mesh_bss_params conf;
|
||||
#define WPA_DRIVER_MESH_FLAG_USER_MPM 0x00000001
|
||||
#define WPA_DRIVER_MESH_FLAG_DRIVER_MPM 0x00000002
|
||||
#define WPA_DRIVER_MESH_FLAG_SAE_AUTH 0x00000004
|
||||
#define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_driver_capa - Driver capability information
|
||||
*/
|
||||
|
@ -3025,6 +3049,29 @@ struct wpa_driver_ops {
|
|||
*/
|
||||
int (*disable_transmit_sa)(void *priv, u32 channel, u8 an);
|
||||
#endif /* CONFIG_MACSEC */
|
||||
|
||||
/**
|
||||
* init_mesh - Driver specific initialization for mesh
|
||||
* @priv: Private driver interface data
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int (*init_mesh)(void *priv);
|
||||
|
||||
/**
|
||||
* join_mesh - Join a mesh network
|
||||
* @priv: Private driver interface data
|
||||
* @params: Mesh configuration parameters
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int (*join_mesh)(void *priv,
|
||||
struct wpa_driver_mesh_join_params *params);
|
||||
|
||||
/**
|
||||
* leave_mesh - Leave a mesh network
|
||||
* @priv: Private driver interface data
|
||||
* Returns 0 on success, -1 on failure
|
||||
*/
|
||||
int (*leave_mesh)(void *priv);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -12588,6 +12588,145 @@ static int nl80211_set_mac_addr(void *priv, const u8 *addr)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_MESH
|
||||
|
||||
static int wpa_driver_nl80211_init_mesh(void *priv)
|
||||
{
|
||||
if (wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_MESH_POINT)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"nl80211: Failed to set interface into mesh mode");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
wpa_driver_nl80211_join_mesh(void *priv,
|
||||
struct wpa_driver_mesh_join_params *params)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct nl_msg *msg;
|
||||
struct nlattr *container;
|
||||
int ret = 0;
|
||||
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg)
|
||||
return -1;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: mesh join (ifindex=%d)", drv->ifindex);
|
||||
nl80211_cmd(drv, msg, 0, NL80211_CMD_JOIN_MESH);
|
||||
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
||||
/* XXX: need chtype too in case we want HT */
|
||||
if (params->freq) {
|
||||
wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
|
||||
}
|
||||
|
||||
if (params->basic_rates) {
|
||||
u8 rates[NL80211_MAX_SUPP_RATES];
|
||||
u8 rates_len = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NL80211_MAX_SUPP_RATES; i++) {
|
||||
if (params->basic_rates[i] < 0)
|
||||
break;
|
||||
rates[rates_len++] = params->basic_rates[i] / 5;
|
||||
}
|
||||
|
||||
NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
|
||||
}
|
||||
|
||||
if (params->meshid) {
|
||||
wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
|
||||
params->meshid, params->meshid_len);
|
||||
NLA_PUT(msg, NL80211_ATTR_MESH_ID, params->meshid_len,
|
||||
params->meshid);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags);
|
||||
|
||||
container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP);
|
||||
if (!container)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (params->ies) {
|
||||
wpa_hexdump(MSG_DEBUG, " * IEs", params->ies, params->ie_len);
|
||||
NLA_PUT(msg, NL80211_MESH_SETUP_IE, params->ie_len,
|
||||
params->ies);
|
||||
}
|
||||
/* WPA_DRIVER_MESH_FLAG_OPEN_AUTH is treated as default by nl80211 */
|
||||
if (params->flags & WPA_DRIVER_MESH_FLAG_SAE_AUTH) {
|
||||
NLA_PUT_U8(msg, NL80211_MESH_SETUP_AUTH_PROTOCOL, 0x1);
|
||||
NLA_PUT_FLAG(msg, NL80211_MESH_SETUP_USERSPACE_AUTH);
|
||||
}
|
||||
if (params->flags & WPA_DRIVER_MESH_FLAG_AMPE)
|
||||
NLA_PUT_FLAG(msg, NL80211_MESH_SETUP_USERSPACE_AMPE);
|
||||
if (params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM)
|
||||
NLA_PUT_FLAG(msg, NL80211_MESH_SETUP_USERSPACE_MPM);
|
||||
nla_nest_end(msg, container);
|
||||
|
||||
container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
|
||||
if (!container)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (!(params->conf.flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS))
|
||||
NLA_PUT_U32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 0);
|
||||
nla_nest_end(msg, container);
|
||||
|
||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||
msg = NULL;
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
|
||||
ret, strerror(-ret));
|
||||
goto nla_put_failure;
|
||||
}
|
||||
ret = 0;
|
||||
bss->freq = params->freq;
|
||||
wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully");
|
||||
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_driver_nl80211_leave_mesh(void *priv)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct nl_msg *msg;
|
||||
int ret = 0;
|
||||
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg)
|
||||
return -1;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
|
||||
nl80211_cmd(drv, msg, 0, NL80211_CMD_LEAVE_MESH);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
|
||||
|
||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||
msg = NULL;
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
|
||||
ret, strerror(-ret));
|
||||
goto nla_put_failure;
|
||||
}
|
||||
ret = 0;
|
||||
wpa_printf(MSG_DEBUG, "nl80211: mesh leave request send successfully");
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
|
||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||
.name = "nl80211",
|
||||
.desc = "Linux nl80211/cfg80211",
|
||||
|
@ -12681,4 +12820,9 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||
.set_wowlan = nl80211_set_wowlan,
|
||||
.roaming = nl80211_roaming,
|
||||
.set_mac_addr = nl80211_set_mac_addr,
|
||||
#ifdef CONFIG_MESH
|
||||
.init_mesh = wpa_driver_nl80211_init_mesh,
|
||||
.join_mesh = wpa_driver_nl80211_join_mesh,
|
||||
.leave_mesh = wpa_driver_nl80211_leave_mesh,
|
||||
#endif /* CONFIG_MESH */
|
||||
};
|
||||
|
|
|
@ -195,6 +195,11 @@ NEED_SHA256=y
|
|||
NEED_AES_OMAC1=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_MESH
|
||||
NEED_80211_COMMON=y
|
||||
L_CFLAGS += -DCONFIG_MESH
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SAE
|
||||
L_CFLAGS += -DCONFIG_SAE
|
||||
OBJS += src/common/sae.c
|
||||
|
|
|
@ -198,6 +198,11 @@ NEED_SHA256=y
|
|||
NEED_AES_OMAC1=y
|
||||
endif
|
||||
|
||||
ifdef CONFIG_MESH
|
||||
NEED_80211_COMMON=y
|
||||
CFLAGS += -DCONFIG_MESH
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SAE
|
||||
CFLAGS += -DCONFIG_SAE
|
||||
OBJS += ../src/common/sae.o
|
||||
|
|
|
@ -65,6 +65,28 @@ static inline int wpa_drv_associate(struct wpa_supplicant *wpa_s,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpa_drv_init_mesh(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (wpa_s->driver->init_mesh)
|
||||
return wpa_s->driver->init_mesh(wpa_s->drv_priv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpa_drv_join_mesh(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_driver_mesh_join_params *params)
|
||||
{
|
||||
if (wpa_s->driver->join_mesh)
|
||||
return wpa_s->driver->join_mesh(wpa_s->drv_priv, params);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpa_drv_leave_mesh(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (wpa_s->driver->leave_mesh)
|
||||
return wpa_s->driver->leave_mesh(wpa_s->drv_priv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpa_drv_scan(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_driver_scan_params *params)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue