aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2018-03-26 13:52:41 -0400
committerJohannes Berg <johannes.berg@intel.com>2018-03-29 07:44:04 -0400
commit6a671a50f8199b3e1fe49fa8afff0fc8335da79c (patch)
tree2c363b4dadd770bd6cac7d6e37a0ec4d688c873f
parent4d191c75365a0067a9d5b8c8746b1bd9310c5a70 (diff)
nl80211: Add CMD_CONTROL_PORT_FRAME API
This 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, NL80211_CMD_ASSOCIATE, NL80211_CMD_START_AP or IBSS/mesh join. Signed-off-by: Denis Kenzior <denkenz@gmail.com> [johannes: fix return value of cfg80211_rx_control_port()] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h22
-rw-r--r--include/uapi/linux/nl80211.h13
-rw-r--r--net/wireless/nl80211.c58
-rw-r--r--net/wireless/trace.h21
4 files changed, 114 insertions, 0 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bfe174896fcf..df145f76adad 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5722,6 +5722,28 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
5722 5722
5723 5723
5724/** 5724/**
5725 * cfg80211_rx_control_port - notification about a received control port frame
5726 * @dev: The device the frame matched to
5727 * @buf: control port frame
5728 * @len: length of the frame data
5729 * @addr: The peer from which the frame was received
5730 * @proto: frame protocol, typically PAE or Pre-authentication
5731 * @unencrypted: Whether the frame was received unencrypted
5732 *
5733 * This function is used to inform userspace about a received control port
5734 * frame. It should only be used if userspace indicated it wants to receive
5735 * control port frames over nl80211.
5736 *
5737 * The frame is the data portion of the 802.3 or 802.11 data frame with all
5738 * network layer headers removed (e.g. the raw EAPoL frame).
5739 *
5740 * Return: %true if the frame was passed to userspace
5741 */
5742bool cfg80211_rx_control_port(struct net_device *dev,
5743 const u8 *buf, size_t len,
5744 const u8 *addr, u16 proto, bool unencrypted);
5745
5746/**
5725 * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event 5747 * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event
5726 * @dev: network device 5748 * @dev: network device
5727 * @rssi_event: the triggered RSSI event 5749 * @rssi_event: the triggered RSSI event
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9ea3d6039eca..6a3cc7a635b5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -990,6 +990,17 @@
990 * &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed 990 * &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed
991 * &NL80211_CMD_DISCONNECT should be indicated instead. 991 * &NL80211_CMD_DISCONNECT should be indicated instead.
992 * 992 *
993 * @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request
994 * and RX notification. This command is used both as a request to transmit
995 * a control port frame and as a notification that a control port frame
996 * has been received. %NL80211_ATTR_FRAME is used to specify the
997 * frame contents. The frame is the raw EAPoL data, without ethernet or
998 * 802.11 headers.
999 * When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
1000 * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added
1001 * indicating the protocol type of the received frame; whether the frame
1002 * was received unencrypted and the MAC address of the peer respectively.
1003 *
993 * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. 1004 * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
994 * 1005 *
995 * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host 1006 * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host
@@ -1228,6 +1239,8 @@ enum nl80211_commands {
1228 1239
1229 NL80211_CMD_STA_OPMODE_CHANGED, 1240 NL80211_CMD_STA_OPMODE_CHANGED,
1230 1241
1242 NL80211_CMD_CONTROL_PORT_FRAME,
1243
1231 /* add new commands above here */ 1244 /* add new commands above here */
1232 1245
1233 /* used to define NL80211_CMD_MAX below */ 1246 /* used to define NL80211_CMD_MAX below */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cfaf2aeb9783..0870447fbd55 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14553,6 +14553,64 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
14553} 14553}
14554EXPORT_SYMBOL(cfg80211_mgmt_tx_status); 14554EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
14555 14555
14556static int __nl80211_rx_control_port(struct net_device *dev,
14557 const u8 *buf, size_t len,
14558 const u8 *addr, u16 proto,
14559 bool unencrypted, gfp_t gfp)
14560{
14561 struct wireless_dev *wdev = dev->ieee80211_ptr;
14562 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
14563 struct sk_buff *msg;
14564 void *hdr;
14565 u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid);
14566
14567 if (!nlportid)
14568 return -ENOENT;
14569
14570 msg = nlmsg_new(100 + len, gfp);
14571 if (!msg)
14572 return -ENOMEM;
14573
14574 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CONTROL_PORT_FRAME);
14575 if (!hdr) {
14576 nlmsg_free(msg);
14577 return -ENOBUFS;
14578 }
14579
14580 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
14581 nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
14582 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
14583 NL80211_ATTR_PAD) ||
14584 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
14585 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
14586 nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
14587 (unencrypted && nla_put_flag(msg,
14588 NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
14589 goto nla_put_failure;
14590
14591 genlmsg_end(msg, hdr);
14592
14593 return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
14594
14595 nla_put_failure:
14596 nlmsg_free(msg);
14597 return -ENOBUFS;
14598}
14599
14600bool cfg80211_rx_control_port(struct net_device *dev,
14601 const u8 *buf, size_t len,
14602 const u8 *addr, u16 proto, bool unencrypted)
14603{
14604 int ret;
14605
14606 trace_cfg80211_rx_control_port(dev, buf, len, addr, proto, unencrypted);
14607 ret = __nl80211_rx_control_port(dev, buf, len, addr, proto,
14608 unencrypted, GFP_ATOMIC);
14609 trace_cfg80211_return_bool(ret == 0);
14610 return ret == 0;
14611}
14612EXPORT_SYMBOL(cfg80211_rx_control_port);
14613
14556static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev, 14614static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
14557 const char *mac, gfp_t gfp) 14615 const char *mac, gfp_t gfp)
14558{ 14616{
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 5152938b358d..42fd338f879e 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2600,6 +2600,27 @@ TRACE_EVENT(cfg80211_mgmt_tx_status,
2600 WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack)) 2600 WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))
2601); 2601);
2602 2602
2603TRACE_EVENT(cfg80211_rx_control_port,
2604 TP_PROTO(struct net_device *netdev, const u8 *buf, size_t len,
2605 const u8 *addr, u16 proto, bool unencrypted),
2606 TP_ARGS(netdev, buf, len, addr, proto, unencrypted),
2607 TP_STRUCT__entry(
2608 NETDEV_ENTRY
2609 MAC_ENTRY(addr)
2610 __field(u16, proto)
2611 __field(bool, unencrypted)
2612 ),
2613 TP_fast_assign(
2614 NETDEV_ASSIGN;
2615 MAC_ASSIGN(addr, addr);
2616 __entry->proto = proto;
2617 __entry->unencrypted = unencrypted;
2618 ),
2619 TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT " proto: 0x%x, unencrypted: %s",
2620 NETDEV_PR_ARG, MAC_PR_ARG(addr),
2621 __entry->proto, BOOL_TO_STR(__entry->unencrypted))
2622);
2623
2603TRACE_EVENT(cfg80211_cqm_rssi_notify, 2624TRACE_EVENT(cfg80211_cqm_rssi_notify,
2604 TP_PROTO(struct net_device *netdev, 2625 TP_PROTO(struct net_device *netdev,
2605 enum nl80211_cqm_rssi_threshold_event rssi_event, 2626 enum nl80211_cqm_rssi_threshold_event rssi_event,