|
@@ -420,6 +420,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|
|
[NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
|
|
|
[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
|
|
|
[NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
|
|
|
+ [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
|
|
|
};
|
|
|
|
|
|
/* policy for the key attributes */
|
|
@@ -9161,6 +9162,15 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
|
|
|
+ if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
|
|
|
+ GENL_SET_ERR_MSG(info,
|
|
|
+ "external auth requires connection ownership");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
|
|
|
+ }
|
|
|
+
|
|
|
wdev_lock(dev->ieee80211_ptr);
|
|
|
|
|
|
err = cfg80211_connect(rdev, dev, &connect, connkeys,
|
|
@@ -12469,6 +12479,41 @@ static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int nl80211_external_auth(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 cfg80211_external_auth_params params;
|
|
|
+
|
|
|
+ if (rdev->ops->external_auth)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (!info->attrs[NL80211_ATTR_SSID])
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (!info->attrs[NL80211_ATTR_BSSID])
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (!info->attrs[NL80211_ATTR_STATUS_CODE])
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ memset(¶ms, 0, sizeof(params));
|
|
|
+
|
|
|
+ params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
|
|
|
+ if (params.ssid.ssid_len == 0 ||
|
|
|
+ params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
|
|
|
+ return -EINVAL;
|
|
|
+ memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]),
|
|
|
+ params.ssid.ssid_len);
|
|
|
+
|
|
|
+ memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
|
|
|
+ ETH_ALEN);
|
|
|
+
|
|
|
+ params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
|
|
|
+
|
|
|
+ return rdev_external_auth(rdev, dev, ¶ms);
|
|
|
+}
|
|
|
+
|
|
|
#define NL80211_FLAG_NEED_WIPHY 0x01
|
|
|
#define NL80211_FLAG_NEED_NETDEV 0x02
|
|
|
#define NL80211_FLAG_NEED_RTNL 0x04
|
|
@@ -13364,6 +13409,14 @@ static const struct genl_ops nl80211_ops[] = {
|
|
|
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
|
|
NL80211_FLAG_NEED_RTNL,
|
|
|
},
|
|
|
+ {
|
|
|
+ .cmd = NL80211_CMD_EXTERNAL_AUTH,
|
|
|
+ .doit = nl80211_external_auth,
|
|
|
+ .policy = nl80211_policy,
|
|
|
+ .flags = GENL_ADMIN_PERM,
|
|
|
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
|
|
+ NL80211_FLAG_NEED_RTNL,
|
|
|
+ },
|
|
|
|
|
|
};
|
|
|
|
|
@@ -15375,6 +15428,47 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev)
|
|
|
nlmsg_free(msg);
|
|
|
}
|
|
|
|
|
|
+int cfg80211_external_auth_request(struct net_device *dev,
|
|
|
+ struct cfg80211_external_auth_params *params,
|
|
|
+ gfp_t gfp)
|
|
|
+{
|
|
|
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
|
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
|
|
+ struct sk_buff *msg;
|
|
|
+ void *hdr;
|
|
|
+
|
|
|
+ if (!wdev->conn_owner_nlportid)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
|
|
|
+ if (!msg)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
|
|
|
+ if (!hdr)
|
|
|
+ goto nla_put_failure;
|
|
|
+
|
|
|
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
|
|
|
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
|
|
|
+ nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
|
|
|
+ nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
|
|
|
+ params->action) ||
|
|
|
+ nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
|
|
|
+ nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
|
|
|
+ params->ssid.ssid))
|
|
|
+ goto nla_put_failure;
|
|
|
+
|
|
|
+ genlmsg_end(msg, hdr);
|
|
|
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
|
|
|
+ wdev->conn_owner_nlportid);
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ nla_put_failure:
|
|
|
+ nlmsg_free(msg);
|
|
|
+ return -ENOBUFS;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(cfg80211_external_auth_request);
|
|
|
+
|
|
|
/* initialisation/exit functions */
|
|
|
|
|
|
int __init nl80211_init(void)
|