diff options
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r-- | net/wireless/core.c | 162 |
1 files changed, 160 insertions, 2 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 7e995ac06a0c..a910cd2d0fd1 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -13,12 +13,14 @@ | |||
13 | #include <linux/debugfs.h> | 13 | #include <linux/debugfs.h> |
14 | #include <linux/notifier.h> | 14 | #include <linux/notifier.h> |
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/list.h> | ||
16 | #include <net/genetlink.h> | 17 | #include <net/genetlink.h> |
17 | #include <net/cfg80211.h> | 18 | #include <net/cfg80211.h> |
18 | #include <net/wireless.h> | 19 | #include <net/wireless.h> |
19 | #include "nl80211.h" | 20 | #include "nl80211.h" |
20 | #include "core.h" | 21 | #include "core.h" |
21 | #include "sysfs.h" | 22 | #include "sysfs.h" |
23 | #include "reg.h" | ||
22 | 24 | ||
23 | /* name for sysfs, %d is appended */ | 25 | /* name for sysfs, %d is appended */ |
24 | #define PHY_NAME "phy" | 26 | #define PHY_NAME "phy" |
@@ -27,6 +29,107 @@ MODULE_AUTHOR("Johannes Berg"); | |||
27 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
28 | MODULE_DESCRIPTION("wireless configuration support"); | 30 | MODULE_DESCRIPTION("wireless configuration support"); |
29 | 31 | ||
32 | struct list_head regulatory_requests; | ||
33 | |||
34 | /* Central wireless core regulatory domains, we only need two, | ||
35 | * the current one and a world regulatory domain in case we have no | ||
36 | * information to give us an alpha2 */ | ||
37 | struct ieee80211_regdomain *cfg80211_regdomain; | ||
38 | |||
39 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | ||
40 | const struct ieee80211_regdomain world_regdom = { | ||
41 | .n_reg_rules = 1, | ||
42 | .alpha2 = "00", | ||
43 | .reg_rules = { | ||
44 | REG_RULE(2402, 2472, 40, 6, 20, | ||
45 | NL80211_RRF_PASSIVE_SCAN | | ||
46 | NL80211_RRF_NO_IBSS), | ||
47 | } | ||
48 | }; | ||
49 | |||
50 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
51 | /* All this fucking static junk will be removed soon, so | ||
52 | * don't fucking count on it !@#$ */ | ||
53 | |||
54 | static char *ieee80211_regdom = "US"; | ||
55 | module_param(ieee80211_regdom, charp, 0444); | ||
56 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | ||
57 | |||
58 | /* We assume 40 MHz bandwidth for the old regulatory work. | ||
59 | * We make emphasis we are using the exact same frequencies | ||
60 | * as before */ | ||
61 | |||
62 | const struct ieee80211_regdomain us_regdom = { | ||
63 | .n_reg_rules = 6, | ||
64 | .alpha2 = "US", | ||
65 | .reg_rules = { | ||
66 | /* IEEE 802.11b/g, channels 1..11 */ | ||
67 | REG_RULE(2412-20, 2462+20, 40, 6, 27, 0), | ||
68 | /* IEEE 802.11a, channel 36 */ | ||
69 | REG_RULE(5180-20, 5180+20, 40, 6, 23, 0), | ||
70 | /* IEEE 802.11a, channel 40 */ | ||
71 | REG_RULE(5200-20, 5200+20, 40, 6, 23, 0), | ||
72 | /* IEEE 802.11a, channel 44 */ | ||
73 | REG_RULE(5220-20, 5220+20, 40, 6, 23, 0), | ||
74 | /* IEEE 802.11a, channels 48..64 */ | ||
75 | REG_RULE(5240-20, 5320+20, 40, 6, 23, 0), | ||
76 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
77 | REG_RULE(5745-20, 5825+20, 40, 6, 30, 0), | ||
78 | } | ||
79 | }; | ||
80 | |||
81 | const struct ieee80211_regdomain jp_regdom = { | ||
82 | .n_reg_rules = 3, | ||
83 | .alpha2 = "JP", | ||
84 | .reg_rules = { | ||
85 | /* IEEE 802.11b/g, channels 1..14 */ | ||
86 | REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), | ||
87 | /* IEEE 802.11a, channels 34..48 */ | ||
88 | REG_RULE(5170-20, 5240+20, 40, 6, 20, | ||
89 | NL80211_RRF_PASSIVE_SCAN), | ||
90 | /* IEEE 802.11a, channels 52..64 */ | ||
91 | REG_RULE(5260-20, 5320+20, 40, 6, 20, | ||
92 | NL80211_RRF_NO_IBSS | | ||
93 | NL80211_RRF_DFS), | ||
94 | } | ||
95 | }; | ||
96 | |||
97 | const struct ieee80211_regdomain eu_regdom = { | ||
98 | .n_reg_rules = 6, | ||
99 | /* This alpha2 is bogus, we leave it here just for stupid | ||
100 | * backward compatibility */ | ||
101 | .alpha2 = "EU", | ||
102 | .reg_rules = { | ||
103 | /* IEEE 802.11b/g, channels 1..13 */ | ||
104 | REG_RULE(2412-20, 2472+20, 40, 6, 20, 0), | ||
105 | /* IEEE 802.11a, channel 36 */ | ||
106 | REG_RULE(5180-20, 5180+20, 40, 6, 23, | ||
107 | NL80211_RRF_PASSIVE_SCAN), | ||
108 | /* IEEE 802.11a, channel 40 */ | ||
109 | REG_RULE(5200-20, 5200+20, 40, 6, 23, | ||
110 | NL80211_RRF_PASSIVE_SCAN), | ||
111 | /* IEEE 802.11a, channel 44 */ | ||
112 | REG_RULE(5220-20, 5220+20, 40, 6, 23, | ||
113 | NL80211_RRF_PASSIVE_SCAN), | ||
114 | /* IEEE 802.11a, channels 48..64 */ | ||
115 | REG_RULE(5240-20, 5320+20, 40, 6, 20, | ||
116 | NL80211_RRF_NO_IBSS | | ||
117 | NL80211_RRF_DFS), | ||
118 | /* IEEE 802.11a, channels 100..140 */ | ||
119 | REG_RULE(5500-20, 5700+20, 40, 6, 30, | ||
120 | NL80211_RRF_NO_IBSS | | ||
121 | NL80211_RRF_DFS), | ||
122 | } | ||
123 | }; | ||
124 | |||
125 | #endif | ||
126 | |||
127 | struct ieee80211_regdomain *cfg80211_world_regdom = | ||
128 | (struct ieee80211_regdomain *) &world_regdom; | ||
129 | |||
130 | LIST_HEAD(regulatory_requests); | ||
131 | DEFINE_MUTEX(cfg80211_reg_mutex); | ||
132 | |||
30 | /* RCU might be appropriate here since we usually | 133 | /* RCU might be appropriate here since we usually |
31 | * only read the list, and that can happen quite | 134 | * only read the list, and that can happen quite |
32 | * often because we need to do it for each command */ | 135 | * often because we need to do it for each command */ |
@@ -302,7 +405,9 @@ int wiphy_register(struct wiphy *wiphy) | |||
302 | ieee80211_set_bitrate_flags(wiphy); | 405 | ieee80211_set_bitrate_flags(wiphy); |
303 | 406 | ||
304 | /* set up regulatory info */ | 407 | /* set up regulatory info */ |
305 | wiphy_update_regulatory(wiphy); | 408 | mutex_lock(&cfg80211_reg_mutex); |
409 | wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE); | ||
410 | mutex_unlock(&cfg80211_reg_mutex); | ||
306 | 411 | ||
307 | mutex_lock(&cfg80211_drv_mutex); | 412 | mutex_lock(&cfg80211_drv_mutex); |
308 | 413 | ||
@@ -409,9 +514,35 @@ static struct notifier_block cfg80211_netdev_notifier = { | |||
409 | .notifier_call = cfg80211_netdev_notifier_call, | 514 | .notifier_call = cfg80211_netdev_notifier_call, |
410 | }; | 515 | }; |
411 | 516 | ||
517 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
518 | const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
519 | { | ||
520 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
521 | return &us_regdom; | ||
522 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
523 | return &jp_regdom; | ||
524 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
525 | return &eu_regdom; | ||
526 | /* Default, as per the old rules */ | ||
527 | return &us_regdom; | ||
528 | } | ||
529 | #endif | ||
530 | |||
412 | static int cfg80211_init(void) | 531 | static int cfg80211_init(void) |
413 | { | 532 | { |
414 | int err = wiphy_sysfs_init(); | 533 | int err; |
534 | |||
535 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
536 | cfg80211_regdomain = | ||
537 | (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom); | ||
538 | /* Used during reset_regdomains_static() */ | ||
539 | cfg80211_world_regdom = cfg80211_regdomain; | ||
540 | #else | ||
541 | cfg80211_regdomain = | ||
542 | (struct ieee80211_regdomain *) cfg80211_world_regdom; | ||
543 | #endif | ||
544 | |||
545 | err = wiphy_sysfs_init(); | ||
415 | if (err) | 546 | if (err) |
416 | goto out_fail_sysfs; | 547 | goto out_fail_sysfs; |
417 | 548 | ||
@@ -425,8 +556,33 @@ static int cfg80211_init(void) | |||
425 | 556 | ||
426 | ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL); | 557 | ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL); |
427 | 558 | ||
559 | err = regulatory_init(); | ||
560 | if (err) | ||
561 | goto out_fail_reg; | ||
562 | |||
563 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
564 | printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n"); | ||
565 | print_regdomain_info(cfg80211_regdomain); | ||
566 | /* The old code still requests for a new regdomain and if | ||
567 | * you have CRDA you get it updated, otherwise you get | ||
568 | * stuck with the static values. We ignore "EU" code as | ||
569 | * that is not a valid ISO / IEC 3166 alpha2 */ | ||
570 | if (ieee80211_regdom[0] != 'E' && | ||
571 | ieee80211_regdom[1] != 'U') | ||
572 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | ||
573 | ieee80211_regdom, NULL); | ||
574 | #else | ||
575 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | ||
576 | if (err) | ||
577 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | ||
578 | "unable to update world regulatory domain, " | ||
579 | "using static definition\n"); | ||
580 | #endif | ||
581 | |||
428 | return 0; | 582 | return 0; |
429 | 583 | ||
584 | out_fail_reg: | ||
585 | debugfs_remove(ieee80211_debugfs_dir); | ||
430 | out_fail_nl80211: | 586 | out_fail_nl80211: |
431 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); | 587 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); |
432 | out_fail_notifier: | 588 | out_fail_notifier: |
@@ -434,6 +590,7 @@ out_fail_notifier: | |||
434 | out_fail_sysfs: | 590 | out_fail_sysfs: |
435 | return err; | 591 | return err; |
436 | } | 592 | } |
593 | |||
437 | subsys_initcall(cfg80211_init); | 594 | subsys_initcall(cfg80211_init); |
438 | 595 | ||
439 | static void cfg80211_exit(void) | 596 | static void cfg80211_exit(void) |
@@ -442,5 +599,6 @@ static void cfg80211_exit(void) | |||
442 | nl80211_exit(); | 599 | nl80211_exit(); |
443 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); | 600 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); |
444 | wiphy_sysfs_exit(); | 601 | wiphy_sysfs_exit(); |
602 | regulatory_exit(); | ||
445 | } | 603 | } |
446 | module_exit(cfg80211_exit); | 604 | module_exit(cfg80211_exit); |