aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c034c2418cb3..9e1318d1d4bb 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -111,6 +111,11 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
111 .len = IEEE80211_MAX_DATA_LEN }, 111 .len = IEEE80211_MAX_DATA_LEN },
112 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED }, 112 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
113 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED }, 113 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
114
115 [NL80211_ATTR_SSID] = { .type = NLA_BINARY,
116 .len = IEEE80211_MAX_SSID_LEN },
117 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
118 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
114}; 119};
115 120
116/* message building helper */ 121/* message building helper */
@@ -265,6 +270,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
265 CMD(set_mesh_params, SET_MESH_PARAMS); 270 CMD(set_mesh_params, SET_MESH_PARAMS);
266 CMD(change_bss, SET_BSS); 271 CMD(change_bss, SET_BSS);
267 CMD(set_mgmt_extra_ie, SET_MGMT_EXTRA_IE); 272 CMD(set_mgmt_extra_ie, SET_MGMT_EXTRA_IE);
273 CMD(auth, AUTHENTICATE);
274 CMD(assoc, ASSOCIATE);
275 CMD(deauth, DEAUTHENTICATE);
276 CMD(disassoc, DISASSOCIATE);
268 277
269#undef CMD 278#undef CMD
270 nla_nest_end(msg, nl_cmds); 279 nla_nest_end(msg, nl_cmds);
@@ -2646,6 +2655,228 @@ static int nl80211_dump_scan(struct sk_buff *skb,
2646 return err; 2655 return err;
2647} 2656}
2648 2657
2658static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
2659{
2660 struct cfg80211_registered_device *drv;
2661 struct net_device *dev;
2662 struct cfg80211_auth_request req;
2663 struct wiphy *wiphy;
2664 int err;
2665
2666 rtnl_lock();
2667
2668 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2669 if (err)
2670 goto unlock_rtnl;
2671
2672 if (!drv->ops->auth) {
2673 err = -EOPNOTSUPP;
2674 goto out;
2675 }
2676
2677 if (!info->attrs[NL80211_ATTR_MAC]) {
2678 err = -EINVAL;
2679 goto out;
2680 }
2681
2682 wiphy = &drv->wiphy;
2683 memset(&req, 0, sizeof(req));
2684
2685 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2686
2687 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
2688 req.chan = ieee80211_get_channel(
2689 wiphy,
2690 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
2691 if (!req.chan) {
2692 err = -EINVAL;
2693 goto out;
2694 }
2695 }
2696
2697 if (info->attrs[NL80211_ATTR_SSID]) {
2698 req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
2699 req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
2700 }
2701
2702 if (info->attrs[NL80211_ATTR_IE]) {
2703 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
2704 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2705 }
2706
2707 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
2708 req.auth_type =
2709 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
2710 }
2711
2712 err = drv->ops->auth(&drv->wiphy, dev, &req);
2713
2714out:
2715 cfg80211_put_dev(drv);
2716 dev_put(dev);
2717unlock_rtnl:
2718 rtnl_unlock();
2719 return err;
2720}
2721
2722static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
2723{
2724 struct cfg80211_registered_device *drv;
2725 struct net_device *dev;
2726 struct cfg80211_assoc_request req;
2727 struct wiphy *wiphy;
2728 int err;
2729
2730 rtnl_lock();
2731
2732 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2733 if (err)
2734 goto unlock_rtnl;
2735
2736 if (!drv->ops->assoc) {
2737 err = -EOPNOTSUPP;
2738 goto out;
2739 }
2740
2741 if (!info->attrs[NL80211_ATTR_MAC] ||
2742 !info->attrs[NL80211_ATTR_SSID]) {
2743 err = -EINVAL;
2744 goto out;
2745 }
2746
2747 wiphy = &drv->wiphy;
2748 memset(&req, 0, sizeof(req));
2749
2750 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2751
2752 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
2753 req.chan = ieee80211_get_channel(
2754 wiphy,
2755 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
2756 if (!req.chan) {
2757 err = -EINVAL;
2758 goto out;
2759 }
2760 }
2761
2762 if (nla_len(info->attrs[NL80211_ATTR_SSID]) > IEEE80211_MAX_SSID_LEN) {
2763 err = -EINVAL;
2764 goto out;
2765 }
2766 req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
2767 req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
2768
2769 if (info->attrs[NL80211_ATTR_IE]) {
2770 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
2771 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2772 }
2773
2774 err = drv->ops->assoc(&drv->wiphy, dev, &req);
2775
2776out:
2777 cfg80211_put_dev(drv);
2778 dev_put(dev);
2779unlock_rtnl:
2780 rtnl_unlock();
2781 return err;
2782}
2783
2784static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
2785{
2786 struct cfg80211_registered_device *drv;
2787 struct net_device *dev;
2788 struct cfg80211_deauth_request req;
2789 struct wiphy *wiphy;
2790 int err;
2791
2792 rtnl_lock();
2793
2794 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2795 if (err)
2796 goto unlock_rtnl;
2797
2798 if (!drv->ops->deauth) {
2799 err = -EOPNOTSUPP;
2800 goto out;
2801 }
2802
2803 if (!info->attrs[NL80211_ATTR_MAC]) {
2804 err = -EINVAL;
2805 goto out;
2806 }
2807
2808 wiphy = &drv->wiphy;
2809 memset(&req, 0, sizeof(req));
2810
2811 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2812
2813 if (info->attrs[NL80211_ATTR_REASON_CODE])
2814 req.reason_code =
2815 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
2816
2817 if (info->attrs[NL80211_ATTR_IE]) {
2818 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
2819 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2820 }
2821
2822 err = drv->ops->deauth(&drv->wiphy, dev, &req);
2823
2824out:
2825 cfg80211_put_dev(drv);
2826 dev_put(dev);
2827unlock_rtnl:
2828 rtnl_unlock();
2829 return err;
2830}
2831
2832static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
2833{
2834 struct cfg80211_registered_device *drv;
2835 struct net_device *dev;
2836 struct cfg80211_disassoc_request req;
2837 struct wiphy *wiphy;
2838 int err;
2839
2840 rtnl_lock();
2841
2842 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2843 if (err)
2844 goto unlock_rtnl;
2845
2846 if (!drv->ops->disassoc) {
2847 err = -EOPNOTSUPP;
2848 goto out;
2849 }
2850
2851 if (!info->attrs[NL80211_ATTR_MAC]) {
2852 err = -EINVAL;
2853 goto out;
2854 }
2855
2856 wiphy = &drv->wiphy;
2857 memset(&req, 0, sizeof(req));
2858
2859 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2860
2861 if (info->attrs[NL80211_ATTR_REASON_CODE])
2862 req.reason_code =
2863 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
2864
2865 if (info->attrs[NL80211_ATTR_IE]) {
2866 req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
2867 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2868 }
2869
2870 err = drv->ops->disassoc(&drv->wiphy, dev, &req);
2871
2872out:
2873 cfg80211_put_dev(drv);
2874 dev_put(dev);
2875unlock_rtnl:
2876 rtnl_unlock();
2877 return err;
2878}
2879
2649static struct genl_ops nl80211_ops[] = { 2880static struct genl_ops nl80211_ops[] = {
2650 { 2881 {
2651 .cmd = NL80211_CMD_GET_WIPHY, 2882 .cmd = NL80211_CMD_GET_WIPHY,
@@ -2829,6 +3060,30 @@ static struct genl_ops nl80211_ops[] = {
2829 .policy = nl80211_policy, 3060 .policy = nl80211_policy,
2830 .dumpit = nl80211_dump_scan, 3061 .dumpit = nl80211_dump_scan,
2831 }, 3062 },
3063 {
3064 .cmd = NL80211_CMD_AUTHENTICATE,
3065 .doit = nl80211_authenticate,
3066 .policy = nl80211_policy,
3067 .flags = GENL_ADMIN_PERM,
3068 },
3069 {
3070 .cmd = NL80211_CMD_ASSOCIATE,
3071 .doit = nl80211_associate,
3072 .policy = nl80211_policy,
3073 .flags = GENL_ADMIN_PERM,
3074 },
3075 {
3076 .cmd = NL80211_CMD_DEAUTHENTICATE,
3077 .doit = nl80211_deauthenticate,
3078 .policy = nl80211_policy,
3079 .flags = GENL_ADMIN_PERM,
3080 },
3081 {
3082 .cmd = NL80211_CMD_DISASSOCIATE,
3083 .doit = nl80211_disassociate,
3084 .policy = nl80211_policy,
3085 .flags = GENL_ADMIN_PERM,
3086 },
2832}; 3087};
2833static struct genl_multicast_group nl80211_mlme_mcgrp = { 3088static struct genl_multicast_group nl80211_mlme_mcgrp = {
2834 .name = "mlme", 3089 .name = "mlme",