netdev: modify netdev_send_action_frame for ft-over-ds

To support FT-over-DS this API needed some slight modifications:

- Instead of setting the DA to netdev->handshake->aa, it is just set to
  the same address as the 'to' parameter. The kernel actually requires
  and checks for these addresses to match. All occurences were passing
  the handshake->aa anyways so this change should have no adverse
  affects; and its actually required by ft-over-ds to pass in the
  previous BSSID, so hard coding handshake->aa will not work.

- The frequency is is also passed in now, as ft-over-ds needs to use
  the frequency of the currently connected AP (netdev->frequency get
  set to the new target in netdev_fast_transition. Previous frequency
  is also saved now).

- A new vector variant (netdev_send_action_framev) was added as well
  to support sending out the FT Request action frame since the FT
  TX authenticate function provides an iovec of the IEs. The existing
  function was already having to prepend the action frame header to
  the body, so its not any more or less copying to do the same thing
  with an iovec instead.
This commit is contained in:
James Prestwood 2019-05-09 11:16:27 -07:00 committed by Denis Kenzior
parent 1801262f2a
commit a432ceeee4
1 changed files with 54 additions and 34 deletions

View File

@ -2633,6 +2633,57 @@ int netdev_leave_adhoc(struct netdev *netdev, netdev_command_cb_t cb,
return 0;
}
static uint32_t netdev_send_action_framev(struct netdev *netdev,
const uint8_t *to,
struct iovec *iov, size_t iov_len,
uint32_t freq,
l_genl_msg_func_t callback)
{
struct l_genl_msg *msg;
struct iovec iovs[iov_len + 1];
const uint16_t frame_type = 0x00d0;
uint8_t action_frame[24];
uint32_t id;
memset(action_frame, 0, 24);
l_put_le16(frame_type, action_frame + 0);
memcpy(action_frame + 4, to, 6);
memcpy(action_frame + 10, netdev->addr, 6);
memcpy(action_frame + 16, to, 6);
iovs[0].iov_base = action_frame;
iovs[0].iov_len = sizeof(action_frame);
memcpy(iovs + 1, iov, sizeof(*iov) * iov_len);
msg = l_genl_msg_new_sized(NL80211_CMD_FRAME, 128 + 512);
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ, 4, &freq);
l_genl_msg_append_attrv(msg, NL80211_ATTR_FRAME, iovs, iov_len + 1);
id = l_genl_family_send(nl80211, msg, callback, netdev, NULL);
if (!id)
l_genl_msg_unref(msg);
return id;
}
static uint32_t netdev_send_action_frame(struct netdev *netdev,
const uint8_t *to,
const uint8_t *body, size_t body_len,
uint32_t freq,
l_genl_msg_func_t callback)
{
struct iovec iov[1];
iov[0].iov_base = (void *)body;
iov[0].iov_len = body_len;
return netdev_send_action_framev(netdev, to, iov, 1, freq, callback);
}
/*
* Build an FT Authentication Request frame according to 12.5.2 / 12.5.4:
* RSN or non-RSN Over-the-air FT Protocol, with the IE contents
@ -2850,40 +2901,6 @@ int netdev_preauthenticate(struct netdev *netdev, struct scan_bss *target_bss,
return 0;
}
static uint32_t netdev_send_action_frame(struct netdev *netdev,
const uint8_t *to,
const uint8_t *body, size_t body_len,
l_genl_msg_func_t callback)
{
struct l_genl_msg *msg;
const uint16_t frame_type = 0x00d0;
uint8_t action_frame[24 + body_len];
uint32_t id;
memset(action_frame, 0, 24);
l_put_le16(frame_type, action_frame + 0);
memcpy(action_frame + 4, to, 6);
memcpy(action_frame + 10, netdev->addr, 6);
memcpy(action_frame + 16, netdev->handshake->aa, 6);
memcpy(action_frame + 24, body, body_len);
msg = l_genl_msg_new_sized(NL80211_CMD_FRAME, 128 + body_len);
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ, 4,
&netdev->frequency);
l_genl_msg_append_attr(msg, NL80211_ATTR_FRAME, sizeof(action_frame),
action_frame);
id = l_genl_family_send(nl80211, msg, callback, netdev, NULL);
if (!id)
l_genl_msg_unref(msg);
return id;
}
static void netdev_neighbor_report_req_cb(struct l_genl_msg *msg,
void *user_data)
{
@ -2929,6 +2946,7 @@ int netdev_neighbor_report_req(struct netdev *netdev,
if (!netdev_send_action_frame(netdev, netdev->handshake->aa,
action_frame, sizeof(action_frame),
netdev->frequency,
netdev_neighbor_report_req_cb))
return -EIO;
@ -3008,6 +3026,7 @@ static void netdev_sa_query_req_frame_event(struct netdev *netdev,
if (!netdev_send_action_frame(netdev, netdev->handshake->aa,
sa_resp, sizeof(sa_resp),
netdev->frequency,
netdev_sa_query_resp_cb)) {
l_error("error sending SA Query response");
return;
@ -3141,6 +3160,7 @@ static void netdev_unprot_disconnect_event(struct l_genl_msg *msg,
if (!netdev_send_action_frame(netdev, netdev->handshake->aa,
action_frame, sizeof(action_frame),
netdev->frequency,
netdev_sa_query_req_cb)) {
l_error("error sending SA Query action frame");
return;