aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c639
1 files changed, 560 insertions, 79 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2456e4ee445e..b1fc98225fd1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -61,6 +61,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, 61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, 62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, 63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
64 [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
65 [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
66 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
67 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
64 68
65 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 69 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
66 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 70 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -116,8 +120,40 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
116 .len = IEEE80211_MAX_SSID_LEN }, 120 .len = IEEE80211_MAX_SSID_LEN },
117 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 }, 121 [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
118 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, 122 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
123 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
124 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
119}; 125};
120 126
127/* IE validation */
128static bool is_valid_ie_attr(const struct nlattr *attr)
129{
130 const u8 *pos;
131 int len;
132
133 if (!attr)
134 return true;
135
136 pos = nla_data(attr);
137 len = nla_len(attr);
138
139 while (len) {
140 u8 elemlen;
141
142 if (len < 2)
143 return false;
144 len -= 2;
145
146 elemlen = pos[1];
147 if (elemlen > len)
148 return false;
149
150 len -= elemlen;
151 pos += 2 + elemlen;
152 }
153
154 return true;
155}
156
121/* message building helper */ 157/* message building helper */
122static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, 158static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
123 int flags, u8 cmd) 159 int flags, u8 cmd)
@@ -126,6 +162,30 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
126 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd); 162 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
127} 163}
128 164
165static int nl80211_msg_put_channel(struct sk_buff *msg,
166 struct ieee80211_channel *chan)
167{
168 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
169 chan->center_freq);
170
171 if (chan->flags & IEEE80211_CHAN_DISABLED)
172 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
173 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
174 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
175 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
176 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
177 if (chan->flags & IEEE80211_CHAN_RADAR)
178 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
179
180 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
181 DBM_TO_MBM(chan->max_power));
182
183 return 0;
184
185 nla_put_failure:
186 return -ENOBUFS;
187}
188
129/* netlink command implementations */ 189/* netlink command implementations */
130 190
131static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, 191static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
@@ -149,8 +209,24 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
149 209
150 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); 210 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
151 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 211 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
212
213 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
214 dev->wiphy.retry_short);
215 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
216 dev->wiphy.retry_long);
217 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
218 dev->wiphy.frag_threshold);
219 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
220 dev->wiphy.rts_threshold);
221
152 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, 222 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
153 dev->wiphy.max_scan_ssids); 223 dev->wiphy.max_scan_ssids);
224 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
225 dev->wiphy.max_scan_ie_len);
226
227 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
228 sizeof(u32) * dev->wiphy.n_cipher_suites,
229 dev->wiphy.cipher_suites);
154 230
155 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 231 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
156 if (!nl_modes) 232 if (!nl_modes)
@@ -202,20 +278,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
202 goto nla_put_failure; 278 goto nla_put_failure;
203 279
204 chan = &dev->wiphy.bands[band]->channels[i]; 280 chan = &dev->wiphy.bands[band]->channels[i];
205 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
206 chan->center_freq);
207
208 if (chan->flags & IEEE80211_CHAN_DISABLED)
209 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
210 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
211 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
212 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
213 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
214 if (chan->flags & IEEE80211_CHAN_RADAR)
215 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
216 281
217 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, 282 if (nl80211_msg_put_channel(msg, chan))
218 DBM_TO_MBM(chan->max_power)); 283 goto nla_put_failure;
219 284
220 nla_nest_end(msg, nl_freq); 285 nla_nest_end(msg, nl_freq);
221 } 286 }
@@ -273,6 +338,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
273 CMD(assoc, ASSOCIATE); 338 CMD(assoc, ASSOCIATE);
274 CMD(deauth, DEAUTHENTICATE); 339 CMD(deauth, DEAUTHENTICATE);
275 CMD(disassoc, DISASSOCIATE); 340 CMD(disassoc, DISASSOCIATE);
341 CMD(join_ibss, JOIN_IBSS);
276 342
277#undef CMD 343#undef CMD
278 nla_nest_end(msg, nl_cmds); 344 nla_nest_end(msg, nl_cmds);
@@ -365,6 +431,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
365 struct cfg80211_registered_device *rdev; 431 struct cfg80211_registered_device *rdev;
366 int result = 0, rem_txq_params = 0; 432 int result = 0, rem_txq_params = 0;
367 struct nlattr *nl_txq_params; 433 struct nlattr *nl_txq_params;
434 u32 changed;
435 u8 retry_short = 0, retry_long = 0;
436 u32 frag_threshold = 0, rts_threshold = 0;
368 437
369 rtnl_lock(); 438 rtnl_lock();
370 439
@@ -479,6 +548,84 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
479 goto bad_res; 548 goto bad_res;
480 } 549 }
481 550
551 changed = 0;
552
553 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
554 retry_short = nla_get_u8(
555 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
556 if (retry_short == 0) {
557 result = -EINVAL;
558 goto bad_res;
559 }
560 changed |= WIPHY_PARAM_RETRY_SHORT;
561 }
562
563 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
564 retry_long = nla_get_u8(
565 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
566 if (retry_long == 0) {
567 result = -EINVAL;
568 goto bad_res;
569 }
570 changed |= WIPHY_PARAM_RETRY_LONG;
571 }
572
573 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
574 frag_threshold = nla_get_u32(
575 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
576 if (frag_threshold < 256) {
577 result = -EINVAL;
578 goto bad_res;
579 }
580 if (frag_threshold != (u32) -1) {
581 /*
582 * Fragments (apart from the last one) are required to
583 * have even length. Make the fragmentation code
584 * simpler by stripping LSB should someone try to use
585 * odd threshold value.
586 */
587 frag_threshold &= ~0x1;
588 }
589 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
590 }
591
592 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
593 rts_threshold = nla_get_u32(
594 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
595 changed |= WIPHY_PARAM_RTS_THRESHOLD;
596 }
597
598 if (changed) {
599 u8 old_retry_short, old_retry_long;
600 u32 old_frag_threshold, old_rts_threshold;
601
602 if (!rdev->ops->set_wiphy_params) {
603 result = -EOPNOTSUPP;
604 goto bad_res;
605 }
606
607 old_retry_short = rdev->wiphy.retry_short;
608 old_retry_long = rdev->wiphy.retry_long;
609 old_frag_threshold = rdev->wiphy.frag_threshold;
610 old_rts_threshold = rdev->wiphy.rts_threshold;
611
612 if (changed & WIPHY_PARAM_RETRY_SHORT)
613 rdev->wiphy.retry_short = retry_short;
614 if (changed & WIPHY_PARAM_RETRY_LONG)
615 rdev->wiphy.retry_long = retry_long;
616 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
617 rdev->wiphy.frag_threshold = frag_threshold;
618 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
619 rdev->wiphy.rts_threshold = rts_threshold;
620
621 result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
622 if (result) {
623 rdev->wiphy.retry_short = old_retry_short;
624 rdev->wiphy.retry_long = old_retry_long;
625 rdev->wiphy.frag_threshold = old_frag_threshold;
626 rdev->wiphy.rts_threshold = old_rts_threshold;
627 }
628 }
482 629
483 bad_res: 630 bad_res:
484 mutex_unlock(&rdev->mtx); 631 mutex_unlock(&rdev->mtx);
@@ -489,6 +636,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
489 636
490 637
491static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, 638static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
639 struct cfg80211_registered_device *rdev,
492 struct net_device *dev) 640 struct net_device *dev)
493{ 641{
494 void *hdr; 642 void *hdr;
@@ -498,6 +646,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
498 return -1; 646 return -1;
499 647
500 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); 648 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
649 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
501 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); 650 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
502 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); 651 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
503 return genlmsg_end(msg, hdr); 652 return genlmsg_end(msg, hdr);
@@ -532,7 +681,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
532 } 681 }
533 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, 682 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
534 cb->nlh->nlmsg_seq, NLM_F_MULTI, 683 cb->nlh->nlmsg_seq, NLM_F_MULTI,
535 wdev->netdev) < 0) { 684 dev, wdev->netdev) < 0) {
536 mutex_unlock(&dev->devlist_mtx); 685 mutex_unlock(&dev->devlist_mtx);
537 goto out; 686 goto out;
538 } 687 }
@@ -566,7 +715,8 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
566 if (!msg) 715 if (!msg)
567 goto out_err; 716 goto out_err;
568 717
569 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0) 718 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
719 dev, netdev) < 0)
570 goto out_free; 720 goto out_free;
571 721
572 dev_put(netdev); 722 dev_put(netdev);
@@ -616,7 +766,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
616 struct cfg80211_registered_device *drv; 766 struct cfg80211_registered_device *drv;
617 struct vif_params params; 767 struct vif_params params;
618 int err, ifindex; 768 int err, ifindex;
619 enum nl80211_iftype type; 769 enum nl80211_iftype otype, ntype;
620 struct net_device *dev; 770 struct net_device *dev;
621 u32 _flags, *flags = NULL; 771 u32 _flags, *flags = NULL;
622 bool change = false; 772 bool change = false;
@@ -630,30 +780,27 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
630 goto unlock_rtnl; 780 goto unlock_rtnl;
631 781
632 ifindex = dev->ifindex; 782 ifindex = dev->ifindex;
633 type = dev->ieee80211_ptr->iftype; 783 otype = ntype = dev->ieee80211_ptr->iftype;
634 dev_put(dev); 784 dev_put(dev);
635 785
636 if (info->attrs[NL80211_ATTR_IFTYPE]) { 786 if (info->attrs[NL80211_ATTR_IFTYPE]) {
637 enum nl80211_iftype ntype;
638
639 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); 787 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
640 if (type != ntype) 788 if (otype != ntype)
641 change = true; 789 change = true;
642 type = ntype; 790 if (ntype > NL80211_IFTYPE_MAX) {
643 if (type > NL80211_IFTYPE_MAX) {
644 err = -EINVAL; 791 err = -EINVAL;
645 goto unlock; 792 goto unlock;
646 } 793 }
647 } 794 }
648 795
649 if (!drv->ops->change_virtual_intf || 796 if (!drv->ops->change_virtual_intf ||
650 !(drv->wiphy.interface_modes & (1 << type))) { 797 !(drv->wiphy.interface_modes & (1 << ntype))) {
651 err = -EOPNOTSUPP; 798 err = -EOPNOTSUPP;
652 goto unlock; 799 goto unlock;
653 } 800 }
654 801
655 if (info->attrs[NL80211_ATTR_MESH_ID]) { 802 if (info->attrs[NL80211_ATTR_MESH_ID]) {
656 if (type != NL80211_IFTYPE_MESH_POINT) { 803 if (ntype != NL80211_IFTYPE_MESH_POINT) {
657 err = -EINVAL; 804 err = -EINVAL;
658 goto unlock; 805 goto unlock;
659 } 806 }
@@ -663,7 +810,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
663 } 810 }
664 811
665 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { 812 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
666 if (type != NL80211_IFTYPE_MONITOR) { 813 if (ntype != NL80211_IFTYPE_MONITOR) {
667 err = -EINVAL; 814 err = -EINVAL;
668 goto unlock; 815 goto unlock;
669 } 816 }
@@ -678,12 +825,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
678 825
679 if (change) 826 if (change)
680 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, 827 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
681 type, flags, &params); 828 ntype, flags, &params);
682 else 829 else
683 err = 0; 830 err = 0;
684 831
685 dev = __dev_get_by_index(&init_net, ifindex); 832 dev = __dev_get_by_index(&init_net, ifindex);
686 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); 833 WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != ntype));
834
835 if (dev && !err && (ntype != otype)) {
836 if (otype == NL80211_IFTYPE_ADHOC)
837 cfg80211_clear_ibss(dev, false);
838 }
687 839
688 unlock: 840 unlock:
689 cfg80211_put_dev(drv); 841 cfg80211_put_dev(drv);
@@ -934,7 +1086,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
934static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) 1086static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
935{ 1087{
936 struct cfg80211_registered_device *drv; 1088 struct cfg80211_registered_device *drv;
937 int err; 1089 int err, i;
938 struct net_device *dev; 1090 struct net_device *dev;
939 struct key_params params; 1091 struct key_params params;
940 u8 key_idx = 0; 1092 u8 key_idx = 0;
@@ -1003,6 +1155,14 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
1003 if (err) 1155 if (err)
1004 goto unlock_rtnl; 1156 goto unlock_rtnl;
1005 1157
1158 for (i = 0; i < drv->wiphy.n_cipher_suites; i++)
1159 if (params.cipher == drv->wiphy.cipher_suites[i])
1160 break;
1161 if (i == drv->wiphy.n_cipher_suites) {
1162 err = -EINVAL;
1163 goto out;
1164 }
1165
1006 if (!drv->ops->add_key) { 1166 if (!drv->ops->add_key) {
1007 err = -EOPNOTSUPP; 1167 err = -EOPNOTSUPP;
1008 goto out; 1168 goto out;
@@ -1069,6 +1229,9 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
1069 struct beacon_parameters params; 1229 struct beacon_parameters params;
1070 int haveinfo = 0; 1230 int haveinfo = 0;
1071 1231
1232 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
1233 return -EINVAL;
1234
1072 rtnl_lock(); 1235 rtnl_lock();
1073 1236
1074 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 1237 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2442,6 +2605,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2442 enum ieee80211_band band; 2605 enum ieee80211_band band;
2443 size_t ie_len; 2606 size_t ie_len;
2444 2607
2608 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
2609 return -EINVAL;
2610
2445 rtnl_lock(); 2611 rtnl_lock();
2446 2612
2447 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2613 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2492,6 +2658,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2492 else 2658 else
2493 ie_len = 0; 2659 ie_len = 0;
2494 2660
2661 if (ie_len > wiphy->max_scan_ie_len) {
2662 err = -EINVAL;
2663 goto out;
2664 }
2665
2495 request = kzalloc(sizeof(*request) 2666 request = kzalloc(sizeof(*request)
2496 + sizeof(*ssid) * n_ssids 2667 + sizeof(*ssid) * n_ssids
2497 + sizeof(channel) * n_channels 2668 + sizeof(channel) * n_channels
@@ -2554,7 +2725,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2554 2725
2555 if (info->attrs[NL80211_ATTR_IE]) { 2726 if (info->attrs[NL80211_ATTR_IE]) {
2556 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 2727 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2557 memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]), 2728 memcpy((void *)request->ie,
2729 nla_data(info->attrs[NL80211_ATTR_IE]),
2558 request->ie_len); 2730 request->ie_len);
2559 } 2731 }
2560 2732
@@ -2710,6 +2882,15 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
2710 struct wiphy *wiphy; 2882 struct wiphy *wiphy;
2711 int err; 2883 int err;
2712 2884
2885 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
2886 return -EINVAL;
2887
2888 if (!info->attrs[NL80211_ATTR_MAC])
2889 return -EINVAL;
2890
2891 if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
2892 return -EINVAL;
2893
2713 rtnl_lock(); 2894 rtnl_lock();
2714 2895
2715 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2896 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2731,11 +2912,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
2731 goto out; 2912 goto out;
2732 } 2913 }
2733 2914
2734 if (!info->attrs[NL80211_ATTR_MAC]) {
2735 err = -EINVAL;
2736 goto out;
2737 }
2738
2739 wiphy = &drv->wiphy; 2915 wiphy = &drv->wiphy;
2740 memset(&req, 0, sizeof(req)); 2916 memset(&req, 0, sizeof(req));
2741 2917
@@ -2761,13 +2937,10 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
2761 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 2937 req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2762 } 2938 }
2763 2939
2764 if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { 2940 req.auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
2765 req.auth_type = 2941 if (!nl80211_valid_auth_type(req.auth_type)) {
2766 nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); 2942 err = -EINVAL;
2767 if (!nl80211_valid_auth_type(req.auth_type)) { 2943 goto out;
2768 err = -EINVAL;
2769 goto out;
2770 }
2771 } 2944 }
2772 2945
2773 err = drv->ops->auth(&drv->wiphy, dev, &req); 2946 err = drv->ops->auth(&drv->wiphy, dev, &req);
@@ -2788,6 +2961,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
2788 struct wiphy *wiphy; 2961 struct wiphy *wiphy;
2789 int err; 2962 int err;
2790 2963
2964 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
2965 return -EINVAL;
2966
2967 if (!info->attrs[NL80211_ATTR_MAC] ||
2968 !info->attrs[NL80211_ATTR_SSID])
2969 return -EINVAL;
2970
2791 rtnl_lock(); 2971 rtnl_lock();
2792 2972
2793 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 2973 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2809,12 +2989,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
2809 goto out; 2989 goto out;
2810 } 2990 }
2811 2991
2812 if (!info->attrs[NL80211_ATTR_MAC] ||
2813 !info->attrs[NL80211_ATTR_SSID]) {
2814 err = -EINVAL;
2815 goto out;
2816 }
2817
2818 wiphy = &drv->wiphy; 2992 wiphy = &drv->wiphy;
2819 memset(&req, 0, sizeof(req)); 2993 memset(&req, 0, sizeof(req));
2820 2994
@@ -2856,6 +3030,15 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
2856 struct wiphy *wiphy; 3030 struct wiphy *wiphy;
2857 int err; 3031 int err;
2858 3032
3033 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3034 return -EINVAL;
3035
3036 if (!info->attrs[NL80211_ATTR_MAC])
3037 return -EINVAL;
3038
3039 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3040 return -EINVAL;
3041
2859 rtnl_lock(); 3042 rtnl_lock();
2860 3043
2861 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 3044 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2877,24 +3060,16 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
2877 goto out; 3060 goto out;
2878 } 3061 }
2879 3062
2880 if (!info->attrs[NL80211_ATTR_MAC]) {
2881 err = -EINVAL;
2882 goto out;
2883 }
2884
2885 wiphy = &drv->wiphy; 3063 wiphy = &drv->wiphy;
2886 memset(&req, 0, sizeof(req)); 3064 memset(&req, 0, sizeof(req));
2887 3065
2888 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 3066 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2889 3067
2890 if (info->attrs[NL80211_ATTR_REASON_CODE]) { 3068 req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
2891 req.reason_code = 3069 if (req.reason_code == 0) {
2892 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); 3070 /* Reason Code 0 is reserved */
2893 if (req.reason_code == 0) { 3071 err = -EINVAL;
2894 /* Reason Code 0 is reserved */ 3072 goto out;
2895 err = -EINVAL;
2896 goto out;
2897 }
2898 } 3073 }
2899 3074
2900 if (info->attrs[NL80211_ATTR_IE]) { 3075 if (info->attrs[NL80211_ATTR_IE]) {
@@ -2920,6 +3095,15 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
2920 struct wiphy *wiphy; 3095 struct wiphy *wiphy;
2921 int err; 3096 int err;
2922 3097
3098 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3099 return -EINVAL;
3100
3101 if (!info->attrs[NL80211_ATTR_MAC])
3102 return -EINVAL;
3103
3104 if (!info->attrs[NL80211_ATTR_REASON_CODE])
3105 return -EINVAL;
3106
2923 rtnl_lock(); 3107 rtnl_lock();
2924 3108
2925 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 3109 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
@@ -2941,24 +3125,16 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
2941 goto out; 3125 goto out;
2942 } 3126 }
2943 3127
2944 if (!info->attrs[NL80211_ATTR_MAC]) {
2945 err = -EINVAL;
2946 goto out;
2947 }
2948
2949 wiphy = &drv->wiphy; 3128 wiphy = &drv->wiphy;
2950 memset(&req, 0, sizeof(req)); 3129 memset(&req, 0, sizeof(req));
2951 3130
2952 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 3131 req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
2953 3132
2954 if (info->attrs[NL80211_ATTR_REASON_CODE]) { 3133 req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
2955 req.reason_code = 3134 if (req.reason_code == 0) {
2956 nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); 3135 /* Reason Code 0 is reserved */
2957 if (req.reason_code == 0) { 3136 err = -EINVAL;
2958 /* Reason Code 0 is reserved */ 3137 goto out;
2959 err = -EINVAL;
2960 goto out;
2961 }
2962 } 3138 }
2963 3139
2964 if (info->attrs[NL80211_ATTR_IE]) { 3140 if (info->attrs[NL80211_ATTR_IE]) {
@@ -2976,6 +3152,124 @@ unlock_rtnl:
2976 return err; 3152 return err;
2977} 3153}
2978 3154
3155static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3156{
3157 struct cfg80211_registered_device *drv;
3158 struct net_device *dev;
3159 struct cfg80211_ibss_params ibss;
3160 struct wiphy *wiphy;
3161 int err;
3162
3163 memset(&ibss, 0, sizeof(ibss));
3164
3165 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3166 return -EINVAL;
3167
3168 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
3169 !info->attrs[NL80211_ATTR_SSID] ||
3170 !nla_len(info->attrs[NL80211_ATTR_SSID]))
3171 return -EINVAL;
3172
3173 ibss.beacon_interval = 100;
3174
3175 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
3176 ibss.beacon_interval =
3177 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
3178 if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000)
3179 return -EINVAL;
3180 }
3181
3182 rtnl_lock();
3183
3184 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
3185 if (err)
3186 goto unlock_rtnl;
3187
3188 if (!drv->ops->join_ibss) {
3189 err = -EOPNOTSUPP;
3190 goto out;
3191 }
3192
3193 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
3194 err = -EOPNOTSUPP;
3195 goto out;
3196 }
3197
3198 if (!netif_running(dev)) {
3199 err = -ENETDOWN;
3200 goto out;
3201 }
3202
3203 wiphy = &drv->wiphy;
3204
3205 if (info->attrs[NL80211_ATTR_MAC])
3206 ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
3207 ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3208 ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
3209
3210 if (info->attrs[NL80211_ATTR_IE]) {
3211 ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
3212 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
3213 }
3214
3215 ibss.channel = ieee80211_get_channel(wiphy,
3216 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
3217 if (!ibss.channel ||
3218 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
3219 ibss.channel->flags & IEEE80211_CHAN_DISABLED) {
3220 err = -EINVAL;
3221 goto out;
3222 }
3223
3224 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
3225
3226 err = cfg80211_join_ibss(drv, dev, &ibss);
3227
3228out:
3229 cfg80211_put_dev(drv);
3230 dev_put(dev);
3231unlock_rtnl:
3232 rtnl_unlock();
3233 return err;
3234}
3235
3236static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
3237{
3238 struct cfg80211_registered_device *drv;
3239 struct net_device *dev;
3240 int err;
3241
3242 rtnl_lock();
3243
3244 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
3245 if (err)
3246 goto unlock_rtnl;
3247
3248 if (!drv->ops->leave_ibss) {
3249 err = -EOPNOTSUPP;
3250 goto out;
3251 }
3252
3253 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) {
3254 err = -EOPNOTSUPP;
3255 goto out;
3256 }
3257
3258 if (!netif_running(dev)) {
3259 err = -ENETDOWN;
3260 goto out;
3261 }
3262
3263 err = cfg80211_leave_ibss(drv, dev, false);
3264
3265out:
3266 cfg80211_put_dev(drv);
3267 dev_put(dev);
3268unlock_rtnl:
3269 rtnl_unlock();
3270 return err;
3271}
3272
2979static struct genl_ops nl80211_ops[] = { 3273static struct genl_ops nl80211_ops[] = {
2980 { 3274 {
2981 .cmd = NL80211_CMD_GET_WIPHY, 3275 .cmd = NL80211_CMD_GET_WIPHY,
@@ -3177,6 +3471,18 @@ static struct genl_ops nl80211_ops[] = {
3177 .policy = nl80211_policy, 3471 .policy = nl80211_policy,
3178 .flags = GENL_ADMIN_PERM, 3472 .flags = GENL_ADMIN_PERM,
3179 }, 3473 },
3474 {
3475 .cmd = NL80211_CMD_JOIN_IBSS,
3476 .doit = nl80211_join_ibss,
3477 .policy = nl80211_policy,
3478 .flags = GENL_ADMIN_PERM,
3479 },
3480 {
3481 .cmd = NL80211_CMD_LEAVE_IBSS,
3482 .doit = nl80211_leave_ibss,
3483 .policy = nl80211_policy,
3484 .flags = GENL_ADMIN_PERM,
3485 },
3180}; 3486};
3181static struct genl_multicast_group nl80211_mlme_mcgrp = { 3487static struct genl_multicast_group nl80211_mlme_mcgrp = {
3182 .name = "mlme", 3488 .name = "mlme",
@@ -3375,22 +3681,197 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
3375 nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE); 3681 nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE);
3376} 3682}
3377 3683
3378void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev, 3684void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
3379 struct net_device *netdev, const u8 *buf, 3685 struct net_device *netdev, const u8 *buf, size_t len)
3380 size_t len)
3381{ 3686{
3382 nl80211_send_mlme_event(rdev, netdev, buf, len, 3687 nl80211_send_mlme_event(rdev, netdev, buf, len,
3383 NL80211_CMD_DEAUTHENTICATE); 3688 NL80211_CMD_DEAUTHENTICATE);
3384} 3689}
3385 3690
3386void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev, 3691void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
3387 struct net_device *netdev, const u8 *buf, 3692 struct net_device *netdev, const u8 *buf,
3388 size_t len) 3693 size_t len)
3389{ 3694{
3390 nl80211_send_mlme_event(rdev, netdev, buf, len, 3695 nl80211_send_mlme_event(rdev, netdev, buf, len,
3391 NL80211_CMD_DISASSOCIATE); 3696 NL80211_CMD_DISASSOCIATE);
3392} 3697}
3393 3698
3699void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
3700 struct net_device *netdev, int cmd,
3701 const u8 *addr)
3702{
3703 struct sk_buff *msg;
3704 void *hdr;
3705
3706 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
3707 if (!msg)
3708 return;
3709
3710 hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
3711 if (!hdr) {
3712 nlmsg_free(msg);
3713 return;
3714 }
3715
3716 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3717 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3718 NLA_PUT_FLAG(msg, NL80211_ATTR_TIMED_OUT);
3719 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
3720
3721 if (genlmsg_end(msg, hdr) < 0) {
3722 nlmsg_free(msg);
3723 return;
3724 }
3725
3726 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
3727 return;
3728
3729 nla_put_failure:
3730 genlmsg_cancel(msg, hdr);
3731 nlmsg_free(msg);
3732}
3733
3734void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
3735 struct net_device *netdev, const u8 *addr)
3736{
3737 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
3738 addr);
3739}
3740
3741void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
3742 struct net_device *netdev, const u8 *addr)
3743{
3744 nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE, addr);
3745}
3746
3747void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
3748 struct net_device *netdev, const u8 *bssid,
3749 gfp_t gfp)
3750{
3751 struct sk_buff *msg;
3752 void *hdr;
3753
3754 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
3755 if (!msg)
3756 return;
3757
3758 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS);
3759 if (!hdr) {
3760 nlmsg_free(msg);
3761 return;
3762 }
3763
3764 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3765 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3766 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
3767
3768 if (genlmsg_end(msg, hdr) < 0) {
3769 nlmsg_free(msg);
3770 return;
3771 }
3772
3773 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
3774 return;
3775
3776 nla_put_failure:
3777 genlmsg_cancel(msg, hdr);
3778 nlmsg_free(msg);
3779}
3780
3781void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
3782 struct net_device *netdev, const u8 *addr,
3783 enum nl80211_key_type key_type, int key_id,
3784 const u8 *tsc)
3785{
3786 struct sk_buff *msg;
3787 void *hdr;
3788
3789 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3790 if (!msg)
3791 return;
3792
3793 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE);
3794 if (!hdr) {
3795 nlmsg_free(msg);
3796 return;
3797 }
3798
3799 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
3800 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
3801 if (addr)
3802 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
3803 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type);
3804 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id);
3805 if (tsc)
3806 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc);
3807
3808 if (genlmsg_end(msg, hdr) < 0) {
3809 nlmsg_free(msg);
3810 return;
3811 }
3812
3813 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL);
3814 return;
3815
3816 nla_put_failure:
3817 genlmsg_cancel(msg, hdr);
3818 nlmsg_free(msg);
3819}
3820
3821void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
3822 struct ieee80211_channel *channel_before,
3823 struct ieee80211_channel *channel_after)
3824{
3825 struct sk_buff *msg;
3826 void *hdr;
3827 struct nlattr *nl_freq;
3828
3829 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
3830 if (!msg)
3831 return;
3832
3833 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT);
3834 if (!hdr) {
3835 nlmsg_free(msg);
3836 return;
3837 }
3838
3839 /*
3840 * Since we are applying the beacon hint to a wiphy we know its
3841 * wiphy_idx is valid
3842 */
3843 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy));
3844
3845 /* Before */
3846 nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE);
3847 if (!nl_freq)
3848 goto nla_put_failure;
3849 if (nl80211_msg_put_channel(msg, channel_before))
3850 goto nla_put_failure;
3851 nla_nest_end(msg, nl_freq);
3852
3853 /* After */
3854 nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER);
3855 if (!nl_freq)
3856 goto nla_put_failure;
3857 if (nl80211_msg_put_channel(msg, channel_after))
3858 goto nla_put_failure;
3859 nla_nest_end(msg, nl_freq);
3860
3861 if (genlmsg_end(msg, hdr) < 0) {
3862 nlmsg_free(msg);
3863 return;
3864 }
3865
3866 genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_ATOMIC);
3867
3868 return;
3869
3870nla_put_failure:
3871 genlmsg_cancel(msg, hdr);
3872 nlmsg_free(msg);
3873}
3874
3394/* initialisation/exit functions */ 3875/* initialisation/exit functions */
3395 3876
3396int nl80211_init(void) 3877int nl80211_init(void)