Re: [RFC v2 4/5] nl80211: Implement TX of control port frames

2018-01-16 Thread Johannes Berg
Hi,

> > > + switch (wdev->iftype) {
> > > + case NL80211_IFTYPE_STATION:
> > > + if (wdev->current_bss)
> > 
> > err, !current_bss?
> > 
> 
> Seems fine to me?  There's a break after that if statement.

Right, got confused, sorry.

johannes


Re: [RFC v2 4/5] nl80211: Implement TX of control port frames

2018-01-15 Thread Denis Kenzior

Hi Johannes,

On 01/15/2018 07:14 AM, Johannes Berg wrote:

Ok this is the interesting part :-)


+   int (*tx_control_port)(struct wiphy *wiphy,
+  struct net_device *dev,
+  const u8 *buf, size_t len,
+  const u8 *dest, const u16 proto,
+  const bool noencrypt);


(indentation seems off in both patchwork and my email, but whatever)


Yes, that was my fault.




+   wdev_lock(wdev);
+
+   switch (wdev->iftype) {
+   case NL80211_IFTYPE_STATION:
+   if (wdev->current_bss)


err, !current_bss?



Seems fine to me?  There's a break after that if statement.


+   buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
+   len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
+   dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
+   proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
+   noencrypt =
+   nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);


So this is the data we support here.

Jouni and I were talking about this and were thinking we might need
"use old key" or something like that. That's rather difficult to do
though, I'm not even sure we keep the old key around?

Jouni? Do you see how this could work?


The other thing we thought about was that maybe we should have "open
port after this frame", but since it's an in-band mechanism now you
could do that also just before the frame.

FWIW, I'm checking with our guy on what other specialities we might
want to add into this mix as far as workarounds are concerned.



Sure, I'll hold off on re-spinning these until I get more feedback.

Regards,
-Denis



Re: [RFC v2 4/5] nl80211: Implement TX of control port frames

2018-01-15 Thread Johannes Berg
Ok this is the interesting part :-)

> + int (*tx_control_port)(struct wiphy *wiphy,
> +struct net_device *dev,
> +const u8 *buf, size_t len,
> +const u8 *dest, const u16 proto,
> +const bool noencrypt);

(indentation seems off in both patchwork and my email, but whatever)

> + wdev_lock(wdev);
> +
> + switch (wdev->iftype) {
> + case NL80211_IFTYPE_STATION:
> + if (wdev->current_bss)

err, !current_bss?

> + buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
> + len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
> + dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
> + proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
> + noencrypt =
> + nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);

So this is the data we support here.

Jouni and I were talking about this and were thinking we might need
"use old key" or something like that. That's rather difficult to do
though, I'm not even sure we keep the old key around?

Jouni? Do you see how this could work?


The other thing we thought about was that maybe we should have "open
port after this frame", but since it's an in-band mechanism now you
could do that also just before the frame.

FWIW, I'm checking with our guy on what other specialities we might
want to add into this mix as far as workarounds are concerned.

johannes


[RFC v2 4/5] nl80211: Implement TX of control port frames

2018-01-10 Thread Denis Kenzior
This commit implements the TX side of NL80211_CMD_CONTROL_PORT_FRAME.
Userspace provides the raw EAPoL frame using NL80211_ATTR_FRAME.
Userspace should also provide the destination address and the protocol
type to use when sending the frame.  This is used to implement TX of
Pre-authentication frames.  If CONTROL_PORT_ETHERTYPE_NO_ENCRYPT is
specified, then the driver will be asked not to encrypt the outgoing
frame.

Signed-off-by: Denis Kenzior 
---
 include/net/cfg80211.h  |  9 
 net/wireless/nl80211.c  | 60 -
 net/wireless/rdev-ops.h | 15 +
 net/wireless/trace.h| 25 +
 4 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 84cba57dd8d0..5d1afe3579e7 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2924,6 +2924,9 @@ struct cfg80211_pmk_conf {
  * (invoked with the wireless_dev mutex held)
  * @del_pmk: delete the previously configured PMK for the given authenticator.
  * (invoked with the wireless_dev mutex held)
+ *
+ * @tx_control_port: TX a control port frame (EAPoL).  The noencrypt parameter
+ * tells the driver that the frame should not be encrypted.
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3217,6 +3220,12 @@ struct cfg80211_ops {
   const struct cfg80211_pmk_conf *conf);
int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev,
   const u8 *aa);
+
+   int (*tx_control_port)(struct wiphy *wiphy,
+  struct net_device *dev,
+  const u8 *buf, size_t len,
+  const u8 *dest, const u16 proto,
+  const bool noencrypt);
 };
 
 /*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c0f2bb24e7dd..2c1082c7b1ea 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12474,6 +12474,57 @@ static int nl80211_del_pmk(struct sk_buff *skb, struct 
genl_info *info)
return ret;
 }
 
+static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
+{
+   struct cfg80211_registered_device *rdev = info->user_ptr[0];
+   struct net_device *dev = info->user_ptr[1];
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+   const u8 *buf;
+   size_t len;
+   u8 *dest;
+   u16 proto;
+   bool noencrypt;
+   int err;
+
+   if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_OVER_NL80211) ||
+   !rdev->ops->tx_control_port)
+   return -EOPNOTSUPP;
+
+   if (!info->attrs[NL80211_ATTR_FRAME] ||
+   !info->attrs[NL80211_ATTR_MAC] ||
+   !info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE])
+   return -EINVAL;
+
+   wdev_lock(wdev);
+
+   switch (wdev->iftype) {
+   case NL80211_IFTYPE_STATION:
+   if (wdev->current_bss)
+   break;
+   err = -ENOTCONN;
+   goto out;
+   default:
+   err = -EOPNOTSUPP;
+   goto out;
+   }
+
+   wdev_unlock(wdev);
+
+   buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
+   len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
+   dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
+   proto = nla_get_u16(info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
+   noencrypt =
+   nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
+
+   return rdev_tx_control_port(rdev, dev, buf, len,
+   dest, cpu_to_be16(proto), noencrypt);
+
+ out:
+   wdev_unlock(wdev);
+   return err;
+}
+
 #define NL80211_FLAG_NEED_WIPHY0x01
 #define NL80211_FLAG_NEED_NETDEV   0x02
 #define NL80211_FLAG_NEED_RTNL 0x04
@@ -13369,7 +13420,14 @@ static const struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
  NL80211_FLAG_NEED_RTNL,
},
-
+   {
+   .cmd = NL80211_CMD_CONTROL_PORT_FRAME,
+   .doit = nl80211_tx_control_port,
+   .policy = nl80211_policy,
+   .flags = GENL_UNS_ADMIN_PERM,
+   .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+   },
 };
 
 static struct genl_family nl80211_fam __ro_after_init = {
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 0c06240d25af..fbd67e32bb91 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -714,6 +714,21 @@ static inline int rdev_mgmt_tx(struct 
cfg80211_registered_device *rdev,
return ret;
 }
 
+static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev,
+  struct