nl80211 hostapd driver: clean up netlink code
Put it into a single place instead of having it all over. Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
This commit is contained in:
parent
6773de39b1
commit
cafe38cae0
1 changed files with 139 additions and 282 deletions
|
@ -135,15 +135,60 @@ static int have_ifidx(struct i802_driver_data *drv, int ifidx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* helper for netlink get routines */
|
/* nl80211 code */
|
||||||
static int ack_wait_handler(struct nl_msg *msg, void *arg)
|
static int ack_handler(struct nl_msg *msg, void *arg)
|
||||||
{
|
{
|
||||||
int *finished = arg;
|
int *err = arg;
|
||||||
|
*err = 0;
|
||||||
*finished = 1;
|
|
||||||
return NL_STOP;
|
return NL_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int finish_handler(struct nl_msg *msg, void *arg)
|
||||||
|
{
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
int *ret = arg;
|
||||||
|
*ret = err->error;
|
||||||
|
return NL_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_and_recv_msgs(struct i802_driver_data *drv,
|
||||||
|
struct nl_msg *msg,
|
||||||
|
int (*valid_handler)(struct nl_msg *, void *),
|
||||||
|
void *valid_data)
|
||||||
|
{
|
||||||
|
struct nl_cb *cb;
|
||||||
|
int err = -ENOMEM;
|
||||||
|
|
||||||
|
cb = nl_cb_clone(drv->nl_cb);
|
||||||
|
if (!cb)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
err = nl_send_auto_complete(drv->nl_handle, msg);
|
||||||
|
if (err < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
err = 1;
|
||||||
|
|
||||||
|
nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
|
||||||
|
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, NULL);
|
||||||
|
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
|
||||||
|
|
||||||
|
if (valid_handler)
|
||||||
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
|
||||||
|
valid_handler, valid_data);
|
||||||
|
|
||||||
|
while (err > 0)
|
||||||
|
nl_recvmsgs(drv->nl_handle, cb);
|
||||||
|
out:
|
||||||
|
nl_cb_put(cb);
|
||||||
|
nlmsg_free(msg);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int hostapd_set_iface_flags(struct i802_driver_data *drv,
|
static int hostapd_set_iface_flags(struct i802_driver_data *drv,
|
||||||
const char *ifname, int dev_up)
|
const char *ifname, int dev_up)
|
||||||
|
@ -182,12 +227,11 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv,
|
||||||
size_t key_len, int txkey)
|
size_t key_len, int txkey)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
int ret;
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (strcmp(alg, "none") == 0) {
|
if (strcmp(alg, "none") == 0) {
|
||||||
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
|
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
|
||||||
|
@ -212,7 +256,8 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv,
|
||||||
else {
|
else {
|
||||||
wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
|
wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
|
||||||
"algorithm '%s'", __func__, alg);
|
"algorithm '%s'", __func__, alg);
|
||||||
goto out;
|
nlmsg_free(msg);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,28 +266,20 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv,
|
||||||
NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
|
NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
(err = nl_wait_for_ack(drv->nl_handle)) < 0) {
|
if (ret == -ENOENT)
|
||||||
if (err != -ENOENT) {
|
ret = 0;
|
||||||
ret = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we need to set the default TX key we do that below,
|
* If we failed or don't need to set the default TX key (below),
|
||||||
* otherwise we're done here.
|
* we're done here.
|
||||||
*/
|
*/
|
||||||
if (!txkey || addr) {
|
if (ret || !txkey || addr)
|
||||||
ret = 0;
|
return ret;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
nlmsg_free(msg);
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_KEY, 0);
|
0, NL80211_CMD_SET_KEY, 0);
|
||||||
|
@ -257,20 +294,12 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv,
|
||||||
NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
|
NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
|
||||||
#endif /* NL80211_MFP_PENDING */
|
#endif /* NL80211_MFP_PENDING */
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
(err = nl_wait_for_ack(drv->nl_handle)) < 0) {
|
if (ret == -ENOENT)
|
||||||
if (err != -ENOENT) {
|
ret = 0;
|
||||||
ret = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
nla_put_failure:
|
|
||||||
nlmsg_free(msg);
|
|
||||||
return ret;
|
return ret;
|
||||||
|
nla_put_failure:
|
||||||
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,14 +358,10 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
struct nl_cb *cb = NULL;
|
|
||||||
int ret = -1;
|
|
||||||
int err = 0;
|
|
||||||
int finished = 0;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_GET_KEY, 0);
|
0, NL80211_CMD_GET_KEY, 0);
|
||||||
|
@ -346,33 +371,11 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
|
||||||
NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
|
NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
|
||||||
|
|
||||||
cb = nl_cb_clone(drv->nl_cb);
|
|
||||||
if (!cb)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
memset(seq, 0, 6);
|
memset(seq, 0, 6);
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
|
return send_and_recv_msgs(drv, msg, get_key_handler, seq);
|
||||||
goto out;
|
|
||||||
|
|
||||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_key_handler, seq);
|
|
||||||
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
|
|
||||||
|
|
||||||
err = nl_recvmsgs(drv->nl_handle, cb);
|
|
||||||
|
|
||||||
if (!finished)
|
|
||||||
err = nl_wait_for_ack(drv->nl_handle);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
nl_cb_put(cb);
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
return -ENOBUFS;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -602,11 +605,10 @@ static int i802_flush(void *priv)
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -1;
|
||||||
|
|
||||||
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_DEL_STATION, 0);
|
0, NL80211_CMD_DEL_STATION, 0);
|
||||||
|
@ -617,18 +619,9 @@ static int i802_flush(void *priv)
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
|
||||||
if_nametoindex(drv->iface));
|
if_nametoindex(drv->iface));
|
||||||
|
|
||||||
ret = 0;
|
return send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0) {
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
return -ENOBUFS;
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -680,14 +673,10 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
struct nl_cb *cb = NULL;
|
|
||||||
int ret = -1;
|
|
||||||
int err = 0;
|
|
||||||
int finished = 0;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_GET_STATION, 0);
|
0, NL80211_CMD_GET_STATION, 0);
|
||||||
|
@ -695,32 +684,9 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
|
||||||
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
|
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
|
||||||
|
|
||||||
cb = nl_cb_clone(drv->nl_cb);
|
return send_and_recv_msgs(drv, msg, get_sta_handler, data);
|
||||||
if (!cb)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_sta_handler, data);
|
|
||||||
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
|
|
||||||
|
|
||||||
err = nl_recvmsgs(drv->nl_handle, cb);
|
|
||||||
|
|
||||||
if (!finished)
|
|
||||||
err = nl_wait_for_ack(drv->nl_handle);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
nl_cb_put(cb);
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
return -ENOBUFS;
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -797,11 +763,11 @@ static int i802_sta_add2(const char *ifname, void *priv,
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
int ret = -ENOBUFS;
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_NEW_STATION, 0);
|
0, NL80211_CMD_NEW_STATION, 0);
|
||||||
|
@ -825,19 +791,10 @@ static int i802_sta_add2(const char *ifname, void *priv,
|
||||||
#endif /* NL80211_ATTR_HT_CAPABILITY */
|
#endif /* NL80211_ATTR_HT_CAPABILITY */
|
||||||
#endif /* CONFIG_IEEE80211N */
|
#endif /* CONFIG_IEEE80211N */
|
||||||
|
|
||||||
ret = nl_send_auto_complete(drv->nl_handle, msg);
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
if (ret < 0)
|
if (ret == -EEXIST)
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
ret = nl_wait_for_ack(drv->nl_handle);
|
|
||||||
/* ignore EEXIST, this happens if a STA associates while associated */
|
|
||||||
if (ret == -EEXIST || ret >= 0)
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,11 +803,11 @@ static int i802_sta_remove(void *priv, const u8 *addr)
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
int ret;
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_DEL_STATION, 0);
|
0, NL80211_CMD_DEL_STATION, 0);
|
||||||
|
@ -859,18 +816,12 @@ static int i802_sta_remove(void *priv, const u8 *addr)
|
||||||
if_nametoindex(drv->iface));
|
if_nametoindex(drv->iface));
|
||||||
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
|
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
|
||||||
|
|
||||||
ret = 0;
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
|
if (ret == -ENOENT)
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
return 0;
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0) {
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
nla_put_failure:
|
|
||||||
nlmsg_free(msg);
|
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
|
nla_put_failure:
|
||||||
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -879,15 +830,16 @@ static int i802_sta_set_flags(void *priv, const u8 *addr,
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg, *flags = NULL;
|
struct nl_msg *msg, *flags = NULL;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
flags = nlmsg_alloc();
|
flags = nlmsg_alloc();
|
||||||
if (!flags)
|
if (!flags) {
|
||||||
goto free_msg;
|
nlmsg_free(msg);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
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_STATION, 0);
|
0, NL80211_CMD_SET_STATION, 0);
|
||||||
|
@ -913,21 +865,12 @@ static int i802_sta_set_flags(void *priv, const u8 *addr,
|
||||||
if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
|
if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0) {
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
nla_put_failure:
|
|
||||||
nlmsg_free(flags);
|
nlmsg_free(flags);
|
||||||
|
|
||||||
free_msg:
|
return send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
nlmsg_free(msg);
|
nla_put_failure:
|
||||||
|
nlmsg_free(flags);
|
||||||
out:
|
return -ENOBUFS;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -966,11 +909,11 @@ static void nl80211_remove_iface(struct i802_driver_data *drv, int ifidx)
|
||||||
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_DEL_INTERFACE, 0);
|
0, NL80211_CMD_DEL_INTERFACE, 0);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0)
|
if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
|
||||||
nla_put_failure:
|
return;
|
||||||
printf("Failed to remove interface.\n");
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
printf("Failed to remove interface.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -983,6 +926,7 @@ static int nl80211_create_iface(struct i802_driver_data *drv,
|
||||||
int ifidx;
|
int ifidx;
|
||||||
struct ifreq ifreq;
|
struct ifreq ifreq;
|
||||||
struct iwreq iwr;
|
struct iwreq iwr;
|
||||||
|
int ret = -ENOBUFS;
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
|
@ -1012,16 +956,13 @@ static int nl80211_create_iface(struct i802_driver_data *drv,
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0) {
|
if (ret) {
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
printf("Failed to create interface %s.\n", ifname);
|
printf("Failed to create interface %s.\n", ifname);
|
||||||
nlmsg_free(msg);
|
return ret;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nlmsg_free(msg);
|
|
||||||
|
|
||||||
ifidx = if_nametoindex(ifname);
|
ifidx = if_nametoindex(ifname);
|
||||||
|
|
||||||
if (ifidx <= 0)
|
if (ifidx <= 0)
|
||||||
|
@ -1096,11 +1037,11 @@ static int i802_set_beacon(const char *iface, void *priv,
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
u8 cmd = NL80211_CMD_NEW_BEACON;
|
u8 cmd = NL80211_CMD_NEW_BEACON;
|
||||||
int ret = -1;
|
int ret;
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (drv->beacon_set)
|
if (drv->beacon_set)
|
||||||
cmd = NL80211_CMD_SET_BEACON;
|
cmd = NL80211_CMD_SET_BEACON;
|
||||||
|
@ -1116,44 +1057,30 @@ static int i802_set_beacon(const char *iface, void *priv,
|
||||||
drv->dtim_period = 2;
|
drv->dtim_period = 2;
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
|
NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0)
|
if (!ret)
|
||||||
goto out;
|
drv->beacon_set = 1;
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
drv->beacon_set = 1;
|
|
||||||
|
|
||||||
out:
|
|
||||||
nla_put_failure:
|
|
||||||
nlmsg_free(msg);
|
|
||||||
return ret;
|
return ret;
|
||||||
|
nla_put_failure:
|
||||||
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int i802_del_beacon(struct i802_driver_data *drv)
|
static int i802_del_beacon(struct i802_driver_data *drv)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_DEL_BEACON, 0);
|
0, NL80211_CMD_DEL_BEACON, 0);
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
return send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
return -ENOBUFS;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1197,7 +1124,6 @@ static int i802_set_beacon_int(void *priv, int value)
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
drv->beacon_int = value;
|
drv->beacon_int = value;
|
||||||
|
|
||||||
|
@ -1206,7 +1132,7 @@ static int i802_set_beacon_int(void *priv, int value)
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_BEACON, 0);
|
0, NL80211_CMD_SET_BEACON, 0);
|
||||||
|
@ -1214,16 +1140,9 @@ static int i802_set_beacon_int(void *priv, int value)
|
||||||
|
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value);
|
NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value);
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
return send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
return -ENOBUFS;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1231,11 +1150,10 @@ static int i802_set_dtim_period(const char *iface, void *priv, int value)
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_BEACON, 0);
|
0, NL80211_CMD_SET_BEACON, 0);
|
||||||
|
@ -1244,16 +1162,9 @@ static int i802_set_dtim_period(const char *iface, void *priv, int value)
|
||||||
drv->dtim_period = value;
|
drv->dtim_period = value;
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
|
NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
return send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
return -ENOBUFS;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1262,11 +1173,10 @@ static int i802_set_bss(void *priv, int cts, int preamble, int slot)
|
||||||
#ifdef NL80211_CMD_SET_BSS
|
#ifdef NL80211_CMD_SET_BSS
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
|
genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
|
||||||
NL80211_CMD_SET_BSS, 0);
|
NL80211_CMD_SET_BSS, 0);
|
||||||
|
@ -1278,21 +1188,12 @@ static int i802_set_bss(void *priv, int cts, int preamble, int slot)
|
||||||
if (slot >= 0)
|
if (slot >= 0)
|
||||||
NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
|
NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
/* TODO: multi-BSS support */
|
/* TODO: multi-BSS support */
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
return send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0) {
|
nla_put_failure:
|
||||||
ret = -1;
|
return -ENOBUFS;
|
||||||
}
|
|
||||||
|
|
||||||
nla_put_failure:
|
|
||||||
nlmsg_free(msg);
|
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
#else /* NL80211_CMD_SET_BSS */
|
#else /* NL80211_CMD_SET_BSS */
|
||||||
return -1;
|
return -1;
|
||||||
#endif /* NL80211_CMD_SET_BSS */
|
#endif /* NL80211_CMD_SET_BSS */
|
||||||
|
@ -1358,7 +1259,6 @@ static int i802_if_remove(void *priv, enum hostapd_driver_if_type type,
|
||||||
struct phy_info_arg {
|
struct phy_info_arg {
|
||||||
u16 *num_modes;
|
u16 *num_modes;
|
||||||
struct hostapd_hw_modes *modes;
|
struct hostapd_hw_modes *modes;
|
||||||
int error;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int phy_info_handler(struct nl_msg *msg, void *arg)
|
static int phy_info_handler(struct nl_msg *msg, void *arg)
|
||||||
|
@ -1497,8 +1397,6 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
phy_info->error = 0;
|
|
||||||
|
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1508,13 +1406,9 @@ static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv,
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int err = -1;
|
|
||||||
struct nl_cb *cb = NULL;
|
|
||||||
int finished = 0;
|
|
||||||
struct phy_info_arg result = {
|
struct phy_info_arg result = {
|
||||||
.num_modes = num_modes,
|
.num_modes = num_modes,
|
||||||
.modes = NULL,
|
.modes = NULL,
|
||||||
.error = 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
*num_modes = 0;
|
*num_modes = 0;
|
||||||
|
@ -1529,33 +1423,10 @@ static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv,
|
||||||
|
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
|
||||||
|
|
||||||
cb = nl_cb_clone(drv->nl_cb);
|
if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0)
|
||||||
if (!cb)
|
return result.modes;
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, phy_info_handler, &result);
|
|
||||||
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
|
|
||||||
|
|
||||||
err = nl_recvmsgs(drv->nl_handle, cb);
|
|
||||||
|
|
||||||
if (!finished)
|
|
||||||
err = nl_wait_for_ack(drv->nl_handle);
|
|
||||||
|
|
||||||
if (err < 0 || result.error) {
|
|
||||||
hostapd_free_hw_features(result.modes, *num_modes);
|
|
||||||
result.modes = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
nl_cb_put(cb);
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
if (err)
|
return NULL;
|
||||||
fprintf(stderr, "failed to get information: %d\n", err);
|
|
||||||
nlmsg_free(msg);
|
|
||||||
return result.modes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1564,11 +1435,10 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
|
||||||
{
|
{
|
||||||
struct i802_driver_data *drv = priv;
|
struct i802_driver_data *drv = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
|
|
||||||
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_STATION, 0);
|
0, NL80211_CMD_SET_STATION, 0);
|
||||||
|
@ -1579,18 +1449,9 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
|
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
|
||||||
if_nametoindex(ifname));
|
if_nametoindex(ifname));
|
||||||
|
|
||||||
ret = 0;
|
return send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
|
||||||
(errno = nl_wait_for_ack(drv->nl_handle) < 0)) {
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free(msg);
|
return -ENOBUFS;
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1931,10 +1792,11 @@ static int nl80211_set_master_mode(struct i802_driver_data *drv,
|
||||||
const char *ifname)
|
const char *ifname)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
|
int ret = -ENOBUFS;
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
msg = nlmsg_alloc();
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
|
|
||||||
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);
|
||||||
|
@ -1942,18 +1804,13 @@ static int nl80211_set_master_mode(struct i802_driver_data *drv,
|
||||||
if_nametoindex(ifname));
|
if_nametoindex(ifname));
|
||||||
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP);
|
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP);
|
||||||
|
|
||||||
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
nl_wait_for_ack(drv->nl_handle) < 0) {
|
if (!ret)
|
||||||
|
return 0;
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
wpa_printf(MSG_ERROR, "Failed to set interface %s to master "
|
wpa_printf(MSG_ERROR, "Failed to set interface %s to master "
|
||||||
"mode.", ifname);
|
"mode.", ifname);
|
||||||
nlmsg_free(msg);
|
return ret;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
nlmsg_free(msg);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue