History

cfg80211: support reloading regulatory database

If the regulatory database is loaded, and then updated, it may be necessary to reload it. Add an nl80211 command to do this. Note that this just reloads the database, it doesn't re-apply the rules from it immediately.

Johannes Berg committed 9 years ago

Commit 1ea4ff31 parent 007f6c54 files · +81 −20Browse files

Unified · Split

4 files
  1. include/uapi/linux/nl80211.h +4 −0
  2. net/wireless/nl80211.c +11 −0
  3. net/wireless/reg.c +60 −20
  4. net/wireless/reg.h +6 −0
include/uapi/linux/nl80211.h+4−0
@@ -990,6 +990,8 @@ · 989 unmodified lines
990 * &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed990 * &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_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
994 *
993 * @NL80211_CMD_MAX: highest used command number995 * @NL80211_CMD_MAX: highest used command number
994 * @__NL80211_CMD_AFTER_LAST: internal use996 * @__NL80211_CMD_AFTER_LAST: internal use
995 */997 */
@@ -1194,6 +1196,8 @@ enum nl80211_commands { · 198 unmodified lines
1194 1196
1195 NL80211_CMD_PORT_AUTHORIZED,1197 NL80211_CMD_PORT_AUTHORIZED,
1196 1198
1199 NL80211_CMD_RELOAD_REGDB,
1200
1197 /* add new commands above here */1201 /* add new commands above here */
1198 1202
1199 /* used to define NL80211_CMD_MAX below */1203 /* used to define NL80211_CMD_MAX below */
net/wireless/nl80211.c+11−0
@@ -5678,6 +5678,11 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) · 5677 unmodified lines
5678 }5678 }
5679}5679}
5680 5680
5681static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
5682{
5683 return reg_reload_regdb();
5684}
5685
5681static int nl80211_get_mesh_config(struct sk_buff *skb,5686static int nl80211_get_mesh_config(struct sk_buff *skb,
5682 struct genl_info *info)5687 struct genl_info *info)
5683{5688{
@@ -12708,6 +12713,12 @@ static const struct genl_ops nl80211_ops[] = { · 7024 unmodified lines
12708 .policy = nl80211_policy,12713 .policy = nl80211_policy,
12709 .flags = GENL_ADMIN_PERM,12714 .flags = GENL_ADMIN_PERM,
12710 },12715 },
12716 {
12717 .cmd = NL80211_CMD_RELOAD_REGDB,
12718 .doit = nl80211_reload_regdb,
12719 .policy = nl80211_policy,
12720 .flags = GENL_ADMIN_PERM,
12721 },
12711 {12722 {
12712 .cmd = NL80211_CMD_GET_MESH_CONFIG,12723 .cmd = NL80211_CMD_GET_MESH_CONFIG,
12713 .doit = nl80211_get_mesh_config,12724 .doit = nl80211_get_mesh_config,
net/wireless/reg.c+60−20
@@ -781,6 +781,8 @@ static int query_regdb(const char *alpha2) · 780 unmodified lines
781 const struct fwdb_header *hdr = regdb;781 const struct fwdb_header *hdr = regdb;
782 const struct fwdb_country *country;782 const struct fwdb_country *country;
783 783
784 ASSERT_RTNL();
785
784 if (IS_ERR(regdb))786 if (IS_ERR(regdb))
785 return PTR_ERR(regdb);787 return PTR_ERR(regdb);
786 788
@@ -796,41 +798,47 @@ static int query_regdb(const char *alpha2) · 9 unmodified lines
796 798
797static void regdb_fw_cb(const struct firmware *fw, void *context)799static void regdb_fw_cb(const struct firmware *fw, void *context)
798{800{
801 int set_error = 0;
802 bool restore = true;
799 void *db;803 void *db;
800 804
801 if (!fw) {805 if (!fw) {
802 pr_info("failed to load regulatory.db\n");806 pr_info("failed to load regulatory.db\n");
803 regdb = ERR_PTR(-ENODATA);807 set_error = -ENODATA;
804 goto restore;808 } else if (!valid_regdb(fw->data, fw->size)) {
805 }
806
807 if (!valid_regdb(fw->data, fw->size)) {
808 pr_info("loaded regulatory.db is malformed\n");809 pr_info("loaded regulatory.db is malformed\n");
809 release_firmware(fw);810 set_error = -EINVAL;
810 regdb = ERR_PTR(-EINVAL);
811 goto restore;
812 }811 }
813 812
814 db = kmemdup(fw->data, fw->size, GFP_KERNEL);813 rtnl_lock();
815 release_firmware(fw);814 if (WARN_ON(regdb && !IS_ERR(regdb))) {
815 /* just restore and free new db */
816 } else if (set_error) {
817 regdb = ERR_PTR(set_error);
818 } else if (fw) {
819 db = kmemdup(fw->data, fw->size, GFP_KERNEL);
820 if (db) {
821 regdb = db;
822 restore = context && query_regdb(context);
823 } else {
824 restore = true;
825 }
826 }
816 827
817 if (!db)828 if (restore)
818 goto restore;829 restore_regulatory_settings(true);
819 regdb = db;
820 830
821 if (query_regdb(context))
822 goto restore;
823 goto free;
824 restore:
825 rtnl_lock();
826 restore_regulatory_settings(true);
827 rtnl_unlock();831 rtnl_unlock();
828 free:832
829 kfree(context);833 kfree(context);
834
835 release_firmware(fw);
830}836}
831 837
832static int query_regdb_file(const char *alpha2)838static int query_regdb_file(const char *alpha2)
833{839{
840 ASSERT_RTNL();
841
834 if (regdb)842 if (regdb)
835 return query_regdb(alpha2);843 return query_regdb(alpha2);
836 844
@@ -843,6 +851,38 @@ static int query_regdb_file(const char *alpha2) · 6 unmodified lines
843 (void *)alpha2, regdb_fw_cb);851 (void *)alpha2, regdb_fw_cb);
844}852}
845 853
854int reg_reload_regdb(void)
855{
856 const struct firmware *fw;
857 void *db;
858 int err;
859
860 err = request_firmware(&fw, "regulatory.db", &reg_pdev->dev);
861 if (err)
862 return err;
863
864 if (!valid_regdb(fw->data, fw->size)) {
865 err = -ENODATA;
866 goto out;
867 }
868
869 db = kmemdup(fw->data, fw->size, GFP_KERNEL);
870 if (!db) {
871 err = -ENOMEM;
872 goto out;
873 }
874
875 rtnl_lock();
876 if (!IS_ERR_OR_NULL(regdb))
877 kfree(regdb);
878 regdb = db;
879 rtnl_unlock();
880
881 out:
882 release_firmware(fw);
883 return err;
884}
885
846static bool reg_query_database(struct regulatory_request *request)886static bool reg_query_database(struct regulatory_request *request)
847{887{
848 /* query internal regulatory database (if it exists) */888 /* query internal regulatory database (if it exists) */
net/wireless/reg.h+6−0
@@ -179,4 +179,10 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy, · 178 unmodified lines
179 * @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1179 * @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1
180 */180 */
181bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);181bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);
182
183/**
184 * reg_reload_regdb - reload the regulatory.db firmware file
185 */
186int reg_reload_regdb(void);
187
182#endif /* __NET_WIRELESS_REG_H */188#endif /* __NET_WIRELESS_REG_H */