EAPoL over NL80211
Subsystems (2)
v2 cover EAPoL over NL80211
This patchset adds support for running 802.11 authentication mechanisms (e.g. 802.1X, 4-Way Handshake, etc) over NL80211 instead of putting them onto the network device. This has the advantage of fixing several long-standing race conditions that result from userspace operating on multiple transports in order to manage a 802.11 connection (e.g. NL80211 and wireless netdev, wlan0, etc).
For example, userspace would sometimes see 4-Way handshake packets before NL80211 signaled that the connection has been established. Leading to ugly hacks or having the STA wait for retransmissions from the AP.
This also provides a way to mitigate a particularly nasty race condition where the encryption key could be set prior to the 4-way handshake packet 4/4 being sent. This would result in the packet being sent encrypted and discarded by the peer. The mitigation strategy for this race is for userspace to explicitly tell the kernel that a particular EAPoL packet should not be encrypted.
To make this possible this patchset introduces a new NL80211 command and several new attributes. A userspace that is capable of processing EAPoL packets over NL80211 includes a new NL80211_ATTR_CONTROL_PORT_OVER_NL80211 attribute in its NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT requests being sent to the kernel. The previously added NL80211_ATTR_SOCKET_OWNER attribute must also be included. The latter is used by the kernel to send NL80211_CMD_CONTROL_PORT_FRAME notifications back to userspace via a netlink unicast. If the NL80211_ATTR_CONTROL_PORT_OVER_NL80211 attribute is not specified, then legacy behavior is kept and control port packets continue to flow over the network interface.
If control port over nl80211 transport is requested, then control port packets
are intercepted just prior to being handed to the network device and sent over
netlink via the NL80211_CMD_CONTROL_PORT_FRAME notification. NL80211_ATTR_CONTROL_PORT_ETHERTYPE and NL80211_ATTR_MAC are included to specify the control port frame protocol and source address respectively. If the control port frame was
received unencrypted then NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT flag is also
included. NL80211_ATTR_FRAME attribute contains the raw control port frame with
all transport layer headers stripped (e.g. this would be the raw EAPoL frame).
Userspace can reply to control port frames either via legacy methods (by sending frames to the network device) or via NL80211_CMD_CONTROL_PORT_FRAME request. Userspace would included NL80211_ATTR_FRAME with the raw control port frame as well as NL80211_Attr_MAC and NL80211_ATTR_CONTROL_PORT_ETHERTYPE attributes to specify the destination address and protocol respectively. This allows Pre-Authentication (protocol 0x88c7) frames to be sent via this mechanism as well. Finally, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT flag can be included to tell the driver to send the frame unencrypted, e.g. for 4-Way handshake 4/4 frames.
The proposed patchset has been tested in a mac80211_hwsim based environment with hostapd and iwd.
ChangeLog
v2
- Added WIPHY_FLAG_CONTROL_PORT_OVER_NL80211 flag. This is a capability flag used by the drivers, e.g. that the driver supports control port over nl80211 capability. This capability is now checked when CONTROL_PORT_OVER_NL80211 is requested.
- mac80211 rx path now forwards Pre-Authentication frames over NL80211 as well, if requested. Tweaked the signature of cfg80211_rx_control_port.
- TX path reworked completely. tx_control_port method has been introduced to cfg80211_ops. An implementation of tx_control_port for mac80211 was added.
Denis Kenzior (5):
nl80211: Add CONTROL_PORT_OVER_NL80211 attribute
nl80211: Add CMD_CONTROL_PORT_FRAME API
mac80211: Send control port frames over nl80211
nl80211: Implement TX of control port frames
mac80211: Add support for tx_control_port
include/net/cfg80211.h | 32 ++++++++++ include/uapi/linux/nl80211.h | 29 ++++++++- net/mac80211/cfg.c | 3 + net/mac80211/ieee80211_i.h | 4 ++ net/mac80211/main.c | 1 + net/mac80211/mlme.c | 2 + net/mac80211/rx.c | 31 +++++++++- net/mac80211/tx.c | 46 ++++++++++++++ net/wireless/nl80211.c | 139 ++++++++++++++++++++++++++++++++++++++++++- net/wireless/rdev-ops.h | 15 +++++ net/wireless/trace.h | 46 ++++++++++++++ 11 files changed, 343 insertions(+), 5 deletions(-)
Signature · 1 line
2.13.5
RFC v2 1/5 nl80211: Add CONTROL_PORT_OVER_NL80211 attribute
--- include/net/cfg80211.h | 6 ++++++ include/uapi/linux/nl80211.h | 14 +++++++++++++- net/wireless/nl80211.c | 20 ++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-)
include/net/cfg80211.h +6 -0
@@ -646,6 +646,8 @@ struct survey_info {* allowed through even on unauthorized ports * @control_port_no_encrypt: TRUE to prevent encryption of control port * protocol frames. +* @control_port_over_nl80211: TRUE if userspace expects to exchange control +* port frames over NL80211 instead of the network interface. * @wep_keys: static WEP keys, if not NULL points to an array of * CFG80211_MAX_WEP_KEYS WEP keys * @wep_tx_key: key index (0..3) of the default TX static WEP key
@@ -661,6 +663,7 @@ struct cfg80211_crypto_settings {bool control_port;__be16 control_port_ethertype;bool control_port_no_encrypt; +bool control_port_over_nl80211;struct key_params *wep_keys;int wep_tx_key;const u8 *psk;
@@ -3236,6 +3239,8 @@ struct cfg80211_ops {* @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the * control port protocol ethertype. The device also honours the * control_port_no_encrypt flag. +* @WIPHY_FLAG_CONTROL_PORT_OVER_NL80211: This device supports sending and +* receiving control port frames over NL80211 instead of the netdevice. * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
@@ -3288,6 +3293,7 @@ enum wiphy_flags {WIPHY_FLAG_SUPPORTS_5_10_MHZ =BIT (22 ),WIPHY_FLAG_HAS_CHANNEL_SWITCH =BIT (23 ),WIPHY_FLAG_HAS_STATIC_WEP =BIT (24 ), + WIPHY_FLAG_CONTROL_PORT_OVER_NL80211 = BIT(25), };/**
include/uapi/linux/nl80211.h +13 -1
@@ -542,7 +542,8 @@* IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, -* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, %NL80211_ATTR_MAC_HINT, and +* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, +* %NL80211_ATTR_CONTROL_PORT_OVER_NL80211, %NL80211_ATTR_MAC_HINT, and * %NL80211_ATTR_WIPHY_FREQ_HINT. * If included, %NL80211_ATTR_MAC and %NL80211_ATTR_WIPHY_FREQ are * restrictions on BSS selection, i.e., they effectively prevent roaming
@@ -1445,6 +1446,15 @@ enum nl80211_commands {* @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom * ethertype frames used for key negotiation must not be encrypted. +* @NL80211_ATTR_CONTROL_PORT_OVER_NL80211: A flag indicating whether control +* port frames (e.g. of type given in %NL80211_ATTR_CONTROL_PORT_ETHERTYPE) +* will be sent directly to the network interface or sent via the NL80211 +* socket. If this attribute is missing, then legacy behavior of sending +* control port frames directly to the network interface is used. If the +* flag is included, then control port frames are sent over NL80211 instead +* using %CMD_CONTROL_PORT_FRAME. If control port routing over NL80211 is +* to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER +* flag. * * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. * We recommend using nested, driver-specific attributes within this.
@@ -2579,6 +2589,8 @@ enum nl80211_attrs {NL80211_ATTR_PMKR0_NAME ,NL80211_ATTR_PORT_AUTHORIZED , +NL80211_ATTR_CONTROL_PORT_OVER_NL80211 , +/* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST,
net/wireless/nl80211.c +20 -0
@@ -286,6 +286,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG }, [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 }, [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG }, + [NL80211_ATTR_CONTROL_PORT_OVER_NL80211] = { .type = NLA_FLAG }, [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
@@ -1547,6 +1548,13 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) goto nla_put_failure; +if (rdev->wiphy.flags &WIPHY_FLAG_CONTROL_PORT_OVER_NL80211 ) { +int type =NL80211_ATTR_CONTROL_PORT_OVER_NL80211 ; + +if (nla_put_flag (msg, type)) + goto nla_put_failure; + } +if (nla_put_u32 (msg,NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX , rdev->wiphy.available_antennas_tx) || nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
@@ -8209,6 +8217,18 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, }else settings->control_port_ethertype =cpu_to_be16 (ETH_P_PAE ); +if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211 ]) { +if (!info->attrs[NL80211_ATTR_SOCKET_OWNER ]) +return -EINVAL ; + +if (!(rdev->wiphy.flags &WIPHY_FLAG_CONTROL_PORT_OVER_NL80211 )) +return -EOPNOTSUPP ; + + settings->control_port_over_nl80211 = true; + }else { + settings->control_port_over_nl80211 = false; + } +if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE ]) {void *data;int len, i;
Signature · 1 line
2.13.5
Johannes Berg
maintainerRe: [RFC v2 1/5] nl80211: Add CONTROL_PORT_OVER_NL80211 attribute
include/net/cfg80211.h enum wiphy_flags { · line 3296
Quoted 2 lines · Denis Kenzior
include/net/cfg80211.h +1
-0+ WIPHY_FLAG_CONTROL_PORT_OVER_NL80211 = BIT(25),
I think it'd be easier for everyone to just use an nl80211 extended feature flag for this, then you also don't need this code:
net/wireless/nl80211.c static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, · line 8230
Quoted 11 lines
net/wireless/nl80211.c +11
-0+if (info->attrs[NL80211_ATTR_CONTROL_PORT_OVER_NL80211 ]) { +if (!info->attrs[NL80211_ATTR_SOCKET_OWNER ]) +return -EINVAL ; + +if (!(rdev->wiphy.flags &WIPHY_FLAG_CONTROL_PORT_OVER_NL80211 )) +return -EOPNOTSUPP ; + + settings->control_port_over_nl80211 = true; + }else { + settings->control_port_over_nl80211 = false; + }
Nit: you don't really need the else branch.
johannes
RFC v2 2/5 nl80211: Add CMD_CONTROL_PORT_FRAME API
In reply to Denis KenziorThis commit also adds cfg80211_rx_control_port function. This is used to generate a CMD_CONTROL_PORT_FRAME event out to userspace. The conn_owner_nlportid is used as the unicast destination. This means that userspace must specify NL80211_ATTR_SOCKET_OWNER flag if control port over nl80211 routing is requested in NL80211_CMD_CONNECT or NL80211_CMD_ASSOCIATE
--- include/net/cfg80211.h | 17 +++++++++++++ include/uapi/linux/nl80211.h | 15 +++++++++++ net/wireless/nl80211.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ net/wireless/trace.h | 21 ++++++++++++++++ 4 files changed, 112 insertions(+)
include/net/cfg80211.h +17 -0
@@ -5629,6 +5629,23 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,/** +* cfg80211_rx_control_port - inform userspace about a received control port +* frame, e.g. EAPoL. This is used if userspace has specified it wants to +* receive control port frames over NL80211. +* @dev: The device the frame matched to +* @buf: control port frame +* @len: length of the frame data +* @addr: The peer from which the frame was received +* @proto: frame protocol, typically PAE or Pre-authentication +* @unencrypted: Whether the frame was received unencrypted +* +* Return: %true if the frame was passed to userspace +*/ +bool cfg80211_rx_control_port (struct net_device *dev, +const u8 *buf,size_t len, +const u8 *addr,u16 proto,bool unencrypted); + +/** * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event * @dev: network device * @rssi_event: the triggered RSSI event
include/uapi/linux/nl80211.h +15 -0
@@ -991,6 +991,17 @@* &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed * &NL80211_CMD_DISCONNECT should be indicated instead. * +* @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request +* and RX notification. This command is used both as a request to transmit +* a control port frame and as a notification that a control port frame +* has been received. %NL80211_ATTR_FRAME is used to specify the +* frame contents. The frame is the raw EAPoL data, without ethernet or +* 802.11 headers. +* When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, +* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added +* indicating the protocol type of the received frame; whether the frame +* was received unencrypted and the MAC address of the peer respectively. +* * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. * * @NL80211_CMD_MAX: highest used command number
@@ -1199,6 +1210,8 @@ enum nl80211_commands {NL80211_CMD_RELOAD_REGDB , + NL80211_CMD_CONTROL_PORT_FRAME, +/* add new commands above here */ /* used to define NL80211_CMD_MAX below */
@@ -1446,6 +1459,8 @@ enum nl80211_commands {* @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom * ethertype frames used for key negotiation must not be encrypted. +* When included in %NL80211_CMD_CONTROL_PORT_FRAME it means that the +* control port frame was received unencrypted. * @NL80211_ATTR_CONTROL_PORT_OVER_NL80211: A flag indicating whether control * port frames (e.g. of type given in %NL80211_ATTR_CONTROL_PORT_ETHERTYPE) * will be sent directly to the network interface or sent via the NL80211
net/wireless/nl80211.c +59 -0
65 lines not on this page · raw message
net/wireless/trace.h +21 -0
@@ -2577,6 +2577,27 @@ TRACE_EVENT(cfg80211_mgmt_tx_status, WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack)) ); +TRACE_EVENT (cfg80211_rx_control_port, + TP_PROTO(struct net_device *netdev, const u8 *buf, size_t len, + const u8 *addr, u16 proto, bool unencrypted), +TP_ARGS (netdev, buf, len, addr, proto, unencrypted), +TP_STRUCT__entry ( + NETDEV_ENTRY + MAC_ENTRY(addr) + __field(u16, proto) +__field (bool, unencrypted) + ), +TP_fast_assign ( + NETDEV_ASSIGN; + MAC_ASSIGN(addr, addr); + __entry->proto = proto; + __entry->unencrypted = unencrypted; + ), +TP_printk (NETDEV_PR_FMT ", " MAC_PR_FMT " proto: %x, unencrypted: %s" , +NETDEV_PR_ARG ,MAC_PR_ARG (addr), + __entry->proto,BOOL_TO_STR (__entry->unencrypted)) +); + TRACE_EVENT(cfg80211_cqm_rssi_notify, TP_PROTO(struct net_device *netdev, enum nl80211_cqm_rssi_threshold_event rssi_event,
Signature · 1 line
2.13.5
Johannes Berg
maintainerRe: [RFC v2 2/5] nl80211: Add CMD_CONTROL_PORT_FRAME API
Can only nitpick on this patch ...
net/wireless/nl80211.c void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, · line 14506
Quoted 4 lines
net/wireless/nl80211.c +4
-0+static int __nl80211_control_port (struct net_device *dev, +const u8 *buf,size_t len, +const u8 *addr,u16 proto, +bool unencrypted,gfp_t gfp)
but that could use an "rx" in the function name :)
johannes
RFC v2 3/5 mac80211: Send control port frames over nl80211
In reply to Denis KenziorIf userspace requested control port frames to go over 80211, then do so. The control packets are intercepted just prior to delivery of the packet to the underlying network device.
Pre-authentication type frames (protocol: 0x88c7) are also forwarded over nl80211.
--- net/mac80211/cfg.c | 2 ++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 2 ++ net/mac80211/rx.c | 31 ++++++++++++++++++++++++++++--- 4 files changed, 33 insertions(+), 3 deletions(-)
net/mac80211/cfg.c +2 -0
@@ -925,6 +925,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,*/ sdata->control_port_protocol = params->crypto.control_port_ethertype; sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; + sdata->control_port_over_nl80211 = false; sdata->encrypt_headroom =ieee80211_cs_headroom (sdata->local, ¶ms->crypto, sdata->vif.type);
@@ -934,6 +935,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, params->crypto.control_port_ethertype; vlan->control_port_no_encrypt = params->crypto.control_port_no_encrypt; + vlan->control_port_over_nl80211 = false; vlan->encrypt_headroom = ieee80211_cs_headroom(sdata->local, ¶ms->crypto,
net/mac80211/ieee80211_i.h +1 -0
@@ -899,6 +899,7 @@ struct ieee80211_sub_if_data {u16 sequence_number;__be16 control_port_protocol;bool control_port_no_encrypt; +bool control_port_over_nl80211;int encrypt_headroom;atomic_t num_tx_queued;
net/mac80211/mlme.c +2 -0
@@ -4830,6 +4830,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sdata->control_port_protocol = req->crypto.control_port_ethertype; sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; + sdata->control_port_over_nl80211 = + req->crypto.control_port_over_nl80211; sdata->encrypt_headroom =ieee80211_cs_headroom (local, &req->crypto, sdata->vif.type);
net/mac80211/rx.c +28 -3
@@ -2326,16 +2326,41 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) }#endif -if (skb) { +if (!skb) + goto try_xmit; + + skb->protocol =eth_type_trans (skb, dev); +memset (skb->cb,0 ,sizeof (skb->cb)); + +if (unlikely ((skb->protocol == sdata->control_port_protocol || + skb->protocol ==cpu_to_be16 (0x88c7 )) && + sdata->control_port_over_nl80211)) { +struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb); +bool noencrypt; + + ehdr =eth_hdr (skb); + +if (status->flag &RX_FLAG_DECRYPTED ) + noencrypt = false; +else + noencrypt = true; + +if (!cfg80211_rx_control_port (dev, skb->data, skb->len, + ehdr->h_source, +be16_to_cpu (skb->protocol), + noencrypt)) { +dev_kfree_skb (skb); + skb =NULL ; + } + }else {/* deliver to local stack */ - skb->protocol =eth_type_trans (skb, dev); -memset (skb->cb,0 ,sizeof (skb->cb));if (rx->napi)napi_gro_receive (rx->napi, skb);else netif_receive_skb (skb); } +try_xmit:if (xmit_skb) {/* * Send to wireless media and increase priority by 256 to
Signature · 1 line
2.13.5
Johannes Berg
maintainerRe: [RFC v2 3/5] mac80211: Send control port frames over nl80211
Quoted 2 lines · Denis Kenzior
Pre-authentication type frames (protocol:
0x88c7) are also forwarded over nl80211.
Interesting - maybe userspace should be able to configure a(n) (list of) ethertype(s)?
Quoted 13 lines
Signed-off-by Denis Kenzior <[email protected]>--- net/mac80211/cfg.c | 2 ++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 2 ++ net/mac80211/rx.c | 31 ++++++++++++++++++++++++++++--- 4 files changed, 33 insertions(+), 3 deletions(-)net/mac80211/cfg.c +0
-0
net/mac80211/cfg.c static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, · line 928
Quoted 4 lines
net/mac80211/cfg.c +1
-0@@ -925,6 +925,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,*/ sdata->control_port_protocol = params->crypto.control_port_ethertype; sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; + sdata->control_port_over_nl80211 = false;
It's probably better to reset this at interface type switching, if it's not done anyway (we zero a lot of memory there, but not sure precisely what)
Otherwise we'll surely forget this in some place like mesh or OCB ...
Initially it must be false (0) anyway.
net/mac80211/cfg.c static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
Quoted 4 lines
net/mac80211/cfg.c +2
-0sdata->control_port_protocol = req->crypto.control_port_ethertype; sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; + sdata->control_port_over_nl80211 = + req->crypto.control_port_over_nl80211;
Heh. One of the cases where the 80 cols line is just dumb :-)
Quoted 8 lines
net/mac80211/cfg.c +0
-0sdata->encrypt_headroom =ieee80211_cs_headroom (local, &req->crypto, sdata->vif.type);net/mac80211/rx.c +0
-0
net/mac80211/rx.c ieee80211_deliver_skb(struct ieee80211_rx_data *rx) · line 2330
Quoted 6 lines
net/mac80211/rx.c +2
-1@@ -2326,16 +2326,41 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) }#endif -if (skb) { +if (!skb) + goto try_xmit;
Seems this could be better without the goto, perhaps pulling the code into a helper function?
Quoted 5 lines
net/mac80211/rx.c +5
-0+ skb->protocol =eth_type_trans (skb, dev); +memset (skb->cb,0 ,sizeof (skb->cb)); + + if (unlikely((skb->protocol == sdata->control_port_protocol || + skb->protocol == cpu_to_be16(0x88c7)) &&
net/mac80211/rx.c ieee80211_deliver_skb(struct ieee80211_rx_data *rx) · line 2346
Quoted 10 lines
net/mac80211/rx.c +10
-0+ sdata->control_port_over_nl80211)) { +struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb); +bool noencrypt; + + ehdr =eth_hdr (skb); + +if (status->flag &RX_FLAG_DECRYPTED ) + noencrypt = false; +else + noencrypt = true;
noencrypt = status->flags & RX_FLAG_DECRYPTED;
? It's a bool, after all, and you could even roll it into the declaration.
johannes
Re: [RFC v2 3/5] mac80211: Send control port frames over nl80211
Hi Johannes,
Quoted 8 lines · Johannes Berg
Quoted 2 lines · Denis Kenzior
Pre-authentication type frames (protocol:
0x88c7) are also forwarded over nl80211.Interesting - maybe userspace should be able to configure a(n) (list of) ethertype(s)?
I'm not so sure. Preauthentication is different from EAPoL frames and most of the special-case checks for control_port_ethertype inside mac80211 do not apply to it. I think it might be safer to carry it as a special case to the special case :P
Quoted 22 lines
Quoted 13 lines
Signed-off-by Denis Kenzior <[email protected]>--- net/mac80211/cfg.c | 2 ++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 2 ++ net/mac80211/rx.c | 31 ++++++++++++++++++++++++++++--- 4 files changed, 33 insertions(+), 3 deletions(-)net/mac80211/cfg.c +0
-0net/mac80211/cfg.c static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, · line 928
Quoted 4 lines
net/mac80211/cfg.c +1
-0@@ -925,6 +925,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,*/ sdata->control_port_protocol = params->crypto.control_port_ethertype; sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; + sdata->control_port_over_nl80211 = false;It's probably better to reset this at interface type switching, if it's not done anyway (we zero a lot of memory there, but not sure precisely what)
Quoted 4 lines
Otherwise we'll surely forget this in some place like mesh or OCB ...
Initially it must be false (0) anyway.
Where do I look? Right now I'm mostly following the precedent of other control_port_* stuff.
Regards,
-Denis
Johannes Berg
maintainerRe: [RFC v2 3/5] mac80211: Send control port frames over nl80211
Quoted 11 lines · Denis Kenzior
Quoted 8 lines
It's probably better to reset this at interface type switching, if it's not done anyway (we zero a lot of memory there, but not sure precisely what)
Otherwise we'll surely forget this in some place like mesh or OCB ...
Initially it must be false (0) anyway.
Where do I look? Right now I'm mostly following the precedent of other control_port_* stuff.
Oh, interesting. I was thinking of things like sdata->noack_map that get reset in ieee80211_setup_sdata().
johannes
RFC v2 4/5 nl80211: Implement TX of control port frames
In reply to Denis KenziorThis 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.
--- 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(-)
include/net/cfg80211.h +9 -0
@@ -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); };/*
net/wireless/nl80211.c +59 -1
72 lines not on this page · raw message
net/wireless/rdev-ops.h +15 -0
@@ -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 net_device *dev, +const void *buf,size_t len, +const u8 *dest,u16 proto, +const bool noencrypt) +{ +int ret; +trace_rdev_tx_control_port (&rdev->wiphy, dev, buf, len, + dest, proto, noencrypt); + ret = rdev->ops->tx_control_port (&rdev->wiphy, dev, buf, len, + dest, proto, noencrypt); +trace_rdev_return_int (&rdev->wiphy, ret); +return ret; +} +static inline int rdev_mgmt_tx_cancel_wait (struct cfg80211_registered_device *rdev,struct wireless_dev *wdev,u64 cookie)
net/wireless/trace.h +25 -0
@@ -1882,6 +1882,31 @@ TRACE_EVENT(rdev_mgmt_tx, BOOL_TO_STR(__entry->dont_wait_for_ack)) ); +TRACE_EVENT (rdev_tx_control_port, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, + const u8 *buf, size_t len, const u8 *dest, u16 proto, + bool unencrypted), +TP_ARGS (wiphy, netdev, buf, len, dest, proto, unencrypted), +TP_STRUCT__entry ( + WIPHY_ENTRY + NETDEV_ENTRY + MAC_ENTRY(dest) + __field(u16, proto) +__field (bool, unencrypted) + ), +TP_fast_assign ( + WIPHY_ASSIGN; + NETDEV_ASSIGN; + MAC_ASSIGN(dest, dest); + __entry->proto = proto; + __entry->unencrypted = unencrypted; + ), +TP_printk (WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT "," +" proto: %x, unencrypted: %s" , +WIPHY_PR_ARG ,NETDEV_PR_ARG ,MAC_PR_ARG (dest), + __entry->proto,BOOL_TO_STR (__entry->unencrypted)) +); + TRACE_EVENT(rdev_set_noack_map, TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u16 noack_map),
Signature · 1 line
2.13.5
Johannes Berg
maintainerRe: [RFC v2 4/5] nl80211: Implement TX of control port frames
Ok this is the interesting part :-)
include/net/cfg80211.h struct cfg80211_ops { · line 3228
Quoted 5 lines
include/net/cfg80211.h +5
-0+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)
net/wireless/nl80211.c static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info) · line 12502
Quoted 5 lines
net/wireless/nl80211.c +5
-0+wdev_lock (wdev); + +switch (wdev->iftype) { +case NL80211_IFTYPE_STATION : +if (wdev->current_bss)
err, !current_bss?
net/wireless/nl80211.c static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info) · line 12518
Quoted 6 lines
net/wireless/nl80211.c +6
-0+ 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
Re: [RFC v2 4/5] nl80211: Implement TX of control port frames
Hi Johannes,
Quoted 9 lines · Johannes Berg
Ok this is the interesting part :-)
include/net/cfg80211.h struct cfg80211_ops { · line 3228
Quoted 5 lines
include/net/cfg80211.h +5
-0+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.
Quoted 9 lines
net/wireless/nl80211.c static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info) · line 12502
Quoted 6 lines
net/wireless/nl80211.c +5
-0+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.
Quoted 16 lines
net/wireless/nl80211.c static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info) · line 12518
Quoted 6 lines
net/wireless/nl80211.c +6
-0+ 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?
Quoted 7 lines
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
Johannes Berg
maintainerRe: [RFC v2 4/5] nl80211: Implement TX of control port frames
Hi,
Quoted 8 lines
Quoted 6 lines
net/wireless/nl80211.c static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info) · line 12502
Quoted 3 lines
net/wireless/nl80211.c +3
-0+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
RFC v2 5/5 mac80211: Add support for tx_control_port
In reply to Denis Kenzior--- net/mac80211/cfg.c | 1 + net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/main.c | 1 + net/mac80211/tx.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+)
net/mac80211/cfg.c +1 -0
@@ -3787,4 +3787,5 @@ const struct cfg80211_ops mac80211_config_ops = { .add_nan_func = ieee80211_add_nan_func, .del_nan_func = ieee80211_del_nan_func, .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast, + .tx_control_port = ieee80211_tx_control_port, };
net/mac80211/ieee80211_i.h +3 -0
@@ -1735,6 +1735,9 @@ void ieee80211_check_fast_xmit(struct sta_info *sta);void ieee80211_check_fast_xmit_all (struct ieee80211_local *local);void ieee80211_check_fast_xmit_iface (struct ieee80211_sub_if_data *sdata);void ieee80211_clear_fast_xmit (struct sta_info *sta); +int ieee80211_tx_control_port (struct wiphy *wiphy,struct net_device *dev, +const u8 *buf,size_t len, +const u8 *dest,u16 proto,bool unencrypted);/* HT */ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
net/mac80211/main.c +1 -0
@@ -976,6 +976,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)/* mac80211 supports control port protocol changing */ local->hw.wiphy->flags |=WIPHY_FLAG_CONTROL_PORT_PROTOCOL ; + local->hw.wiphy->flags |=WIPHY_FLAG_CONTROL_PORT_OVER_NL80211 ;if (ieee80211_hw_check (&local->hw,SIGNAL_DBM )) { local->hw.wiphy->signal_type =CFG80211_SIGNAL_TYPE_MBM ;
net/mac80211/tx.c +46 -0
49 lines not on this page · raw message
Signature · 1 line
2.13.5
Johannes Berg
maintainerRe: [RFC v2 5/5] mac80211: Add support for tx_control_port
This looks straight-forward.
Again, question about which ethertype.
And you should probably add a define for 0x88c7 (and yeah, I'm willing to take that through my tree)
johannes