linux/net/wireless/reg.c

/*
 * Copyright 2002-2005, Instant802 Networks, Inc.
 * Copyright 2005-2006, Devicescape Software, Inc.
 * Copyright 2007	Johannes Berg <[email protected]>
 * Copyright 2008-2011	Luis R. Rodriguez <[email protected]>
 * Copyright 2013-2014  Intel Mobile Communications GmbH
 * Copyright      2017  Intel Deutschland GmbH
 * Copyright (C) 2018 - 2024 Intel Corporation
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */


/**
 * DOC: Wireless regulatory infrastructure
 *
 * The usual implementation is for a driver to read a device EEPROM to
 * determine which regulatory domain it should be operating under, then
 * looking up the allowable channels in a driver-local table and finally
 * registering those channels in the wiphy structure.
 *
 * Another set of compliance enforcement is for drivers to use their
 * own compliance limits which can be stored on the EEPROM. The host
 * driver or firmware may ensure these are used.
 *
 * In addition to all this we provide an extra layer of regulatory
 * conformance. For drivers which do not have any regulatory
 * information CRDA provides the complete regulatory solution.
 * For others it provides a community effort on further restrictions
 * to enhance compliance.
 *
 * Note: When number of rules --> infinity we will not be able to
 * index on alpha2 any more, instead we'll probably have to
 * rely on some SHA1 checksum of the regdomain for example.
 *
 */

#define pr_fmt(fmt)

#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/ctype.h>
#include <linux/nl80211.h>
#include <linux/platform_device.h>
#include <linux/verification.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/units.h>

#include <net/cfg80211.h>
#include "core.h"
#include "reg.h"
#include "rdev-ops.h"
#include "nl80211.h"

/*
 * Grace period we give before making sure all current interfaces reside on
 * channels allowed by the current regulatory domain.
 */
#define REG_ENFORCE_GRACE_MS

/**
 * enum reg_request_treatment - regulatory request treatment
 *
 * @REG_REQ_OK: continue processing the regulatory request
 * @REG_REQ_IGNORE: ignore the regulatory request
 * @REG_REQ_INTERSECT: the regulatory domain resulting from this request should
 *	be intersected with the current one.
 * @REG_REQ_ALREADY_SET: the regulatory request will not change the current
 *	regulatory settings, and no further processing is required.
 */
enum reg_request_treatment {};

static struct regulatory_request core_request_world =;

/*
 * Receipt of information from last regulatory request,
 * protected by RTNL (and can be accessed with RCU protection)
 */
static struct regulatory_request __rcu *last_request =;

/* To trigger userspace events and load firmware */
static struct platform_device *reg_pdev;

/*
 * Central wireless core regulatory domains, we only need two,
 * the current one and a world regulatory domain in case we have no
 * information to give us an alpha2.
 * (protected by RTNL, can be read under RCU)
 */
const struct ieee80211_regdomain __rcu *cfg80211_regdomain;

/*
 * Number of devices that registered to the core
 * that support cellular base station regulatory hints
 * (protected by RTNL)
 */
static int reg_num_devs_support_basehint;

/*
 * State variable indicating if the platform on which the devices
 * are attached is operating in an indoor environment. The state variable
 * is relevant for all registered devices.
 */
static bool reg_is_indoor;
static DEFINE_SPINLOCK(reg_indoor_lock);

/* Used to track the userspace process controlling the indoor setting */
static u32 reg_is_indoor_portid;

static void restore_regulatory_settings(bool reset_user, bool cached);
static void print_regdomain(const struct ieee80211_regdomain *rd);
static void reg_process_hint(struct regulatory_request *reg_request);

static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
{}

/*
 * Returns the regulatory domain associated with the wiphy.
 *
 * Requires any of RTNL, wiphy mutex or RCU protection.
 */
const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
{}
EXPORT_SYMBOL();

static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
{}

enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy)
{}

static void rcu_free_regdom(const struct ieee80211_regdomain *r)
{}

static struct regulatory_request *get_last_request(void)
{}

/* Used to queue up regulatory hints */
static LIST_HEAD(reg_requests_list);
static DEFINE_SPINLOCK(reg_requests_lock);

/* Used to queue up beacon hints for review */
static LIST_HEAD(reg_pending_beacons);
static DEFINE_SPINLOCK(reg_pending_beacons_lock);

/* Used to keep track of processed beacon hints */
static LIST_HEAD(reg_beacon_list);

struct reg_beacon {};

static void reg_check_chans_work(struct work_struct *work);
static DECLARE_DELAYED_WORK(reg_check_chans, reg_check_chans_work);

static void reg_todo(struct work_struct *work);
static DECLARE_WORK(reg_work, reg_todo);

/* We keep a static world regulatory domain in case of the absence of CRDA */
static const struct ieee80211_regdomain world_regdom =;

/* protected by RTNL */
static const struct ieee80211_regdomain *cfg80211_world_regdom =;

static char *ieee80211_regdom =;
static char user_alpha2[2];
static const struct ieee80211_regdomain *cfg80211_user_regdom;

module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC();

static void reg_free_request(struct regulatory_request *request)
{}

static void reg_free_last_request(void)
{}

static void reg_update_last_request(struct regulatory_request *request)
{}

static void reset_regdomains(bool full_reset,
			     const struct ieee80211_regdomain *new_regdom)
{}

/*
 * Dynamic world regulatory domain requested by the wireless
 * core upon initialization
 */
static void update_world_regdomain(const struct ieee80211_regdomain *rd)
{}

bool is_world_regdom(const char *alpha2)
{}

static bool is_alpha2_set(const char *alpha2)
{}

static bool is_unknown_alpha2(const char *alpha2)
{}

static bool is_intersected_alpha2(const char *alpha2)
{}

static bool is_an_alpha2(const char *alpha2)
{}

static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y)
{}

static bool regdom_changes(const char *alpha2)
{}

/*
 * The NL80211_REGDOM_SET_BY_USER regdom alpha2 is cached, this lets
 * you know if a valid regulatory hint with NL80211_REGDOM_SET_BY_USER
 * has ever been issued.
 */
static bool is_user_regdom_saved(void)
{}

static const struct ieee80211_regdomain *
reg_copy_regd(const struct ieee80211_regdomain *src_regd)
{}

static void cfg80211_save_user_regdom(const struct ieee80211_regdomain *rd)
{}

struct reg_regdb_apply_request {};

static LIST_HEAD(reg_regdb_apply_list);
static DEFINE_MUTEX(reg_regdb_apply_mutex);

static void reg_regdb_apply(struct work_struct *work)
{}

static DECLARE_WORK(reg_regdb_work, reg_regdb_apply);

static int reg_schedule_apply(const struct ieee80211_regdomain *regdom)
{}

#ifdef CONFIG_CFG80211_CRDA_SUPPORT
/* Max number of consecutive attempts to communicate with CRDA  */
#define REG_MAX_CRDA_TIMEOUTS

static u32 reg_crda_timeouts;

static void crda_timeout_work(struct work_struct *work);
static DECLARE_DELAYED_WORK(crda_timeout, crda_timeout_work);

static void crda_timeout_work(struct work_struct *work)
{}

static void cancel_crda_timeout(void)
{}

static void cancel_crda_timeout_sync(void)
{}

static void reset_crda_timeouts(void)
{}

/*
 * This lets us keep regulatory code which is updated on a regulatory
 * basis in userspace.
 */
static int call_crda(const char *alpha2)
{}
#else
static inline void cancel_crda_timeout(void) {}
static inline void cancel_crda_timeout_sync(void) {}
static inline void reset_crda_timeouts(void) {}
static inline int call_crda(const char *alpha2)
{
	return -ENODATA;
}
#endif /* CONFIG_CFG80211_CRDA_SUPPORT */

/* code to directly load a firmware database through request_firmware */
static const struct fwdb_header *regdb;

struct fwdb_country {} __packed __aligned();

struct fwdb_collection {} __packed __aligned();

enum fwdb_flags {};

struct fwdb_wmm_ac {} __packed;

struct fwdb_wmm_rule {} __packed;

struct fwdb_rule {} __packed __aligned();

#define FWDB_MAGIC
#define FWDB_VERSION

struct fwdb_header {} __packed __aligned();

static int ecw2cw(int ecw)
{}

static bool valid_wmm(struct fwdb_wmm_rule *rule)
{}

static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
{}

static bool valid_country(const u8 *data, unsigned int size,
			  const struct fwdb_country *country)
{}

#ifdef CONFIG_CFG80211_REQUIRE_SIGNED_REGDB
#include <keys/asymmetric-type.h>

static struct key *builtin_regdb_keys;

static int __init load_builtin_regdb_keys(void)
{}

MODULE_FIRMWARE();

static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
{}

static void free_regdb_keyring(void)
{}
#else
static int load_builtin_regdb_keys(void)
{
	return 0;
}

static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
{
	return true;
}

static void free_regdb_keyring(void)
{
}
#endif /* CONFIG_CFG80211_REQUIRE_SIGNED_REGDB */

static bool valid_regdb(const u8 *data, unsigned int size)
{}

static void set_wmm_rule(const struct fwdb_header *db,
			 const struct fwdb_country *country,
			 const struct fwdb_rule *rule,
			 struct ieee80211_reg_rule *rrule)
{}

static int __regdb_query_wmm(const struct fwdb_header *db,
			     const struct fwdb_country *country, int freq,
			     struct ieee80211_reg_rule *rrule)
{}

int reg_query_regdb_wmm(char *alpha2, int freq, struct ieee80211_reg_rule *rule)
{}
EXPORT_SYMBOL();

static int regdb_query_country(const struct fwdb_header *db,
			       const struct fwdb_country *country)
{}

static int query_regdb(const char *alpha2)
{}

static void regdb_fw_cb(const struct firmware *fw, void *context)
{}

MODULE_FIRMWARE();

static int query_regdb_file(const char *alpha2)
{}

int reg_reload_regdb(void)
{}

static bool reg_query_database(struct regulatory_request *request)
{}

bool reg_is_valid_request(const char *alpha2)
{}

static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy)
{}

static unsigned int
reg_get_max_bandwidth_from_range(const struct ieee80211_regdomain *rd,
				 const struct ieee80211_reg_rule *rule)
{}

unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
				   const struct ieee80211_reg_rule *rule)
{}

/* Sanity check on a regulatory rule */
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
{}

static bool is_valid_rd(const struct ieee80211_regdomain *rd)
{}

/**
 * freq_in_rule_band - tells us if a frequency is in a frequency band
 * @freq_range: frequency rule we want to query
 * @freq_khz: frequency we are inquiring about
 *
 * This lets us know if a specific frequency rule is or is not relevant to
 * a specific frequency's band. Bands are device specific and artificial
 * definitions (the "2.4 GHz band", the "5 GHz band" and the "60GHz band"),
 * however it is safe for now to assume that a frequency rule should not be
 * part of a frequency's band if the start freq or end freq are off by more
 * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 20 GHz for the
 * 60 GHz band.
 * This resolution can be lowered and should be considered as we add
 * regulatory rule support for other "bands".
 *
 * Returns: whether or not the frequency is in the range
 */
static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
			      u32 freq_khz)
{}

/*
 * Later on we can perhaps use the more restrictive DFS
 * region but we don't have information for that yet so
 * for now simply disallow conflicts.
 */
static enum nl80211_dfs_regions
reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1,
			 const enum nl80211_dfs_regions dfs_region2)
{}

static void reg_wmm_rules_intersect(const struct ieee80211_wmm_ac *wmm_ac1,
				    const struct ieee80211_wmm_ac *wmm_ac2,
				    struct ieee80211_wmm_ac *intersect)
{}

/*
 * Helper for regdom_intersect(), this does the real
 * mathematical intersection fun
 */
static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
			       const struct ieee80211_regdomain *rd2,
			       const struct ieee80211_reg_rule *rule1,
			       const struct ieee80211_reg_rule *rule2,
			       struct ieee80211_reg_rule *intersected_rule)
{}

/* check whether old rule contains new rule */
static bool rule_contains(struct ieee80211_reg_rule *r1,
			  struct ieee80211_reg_rule *r2)
{}

/* add or extend current rules. do nothing if rule is already contained */
static void add_rule(struct ieee80211_reg_rule *rule,
		     struct ieee80211_reg_rule *reg_rules, u32 *n_rules)
{}

/**
 * regdom_intersect - do the intersection between two regulatory domains
 * @rd1: first regulatory domain
 * @rd2: second regulatory domain
 *
 * Use this function to get the intersection between two regulatory domains.
 * Once completed we will mark the alpha2 for the rd as intersected, "98",
 * as no one single alpha2 can represent this regulatory domain.
 *
 * Returns a pointer to the regulatory domain structure which will hold the
 * resulting intersection of rules between rd1 and rd2. We will
 * kzalloc() this structure for you.
 *
 * Returns: the intersected regdomain
 */
static struct ieee80211_regdomain *
regdom_intersect(const struct ieee80211_regdomain *rd1,
		 const struct ieee80211_regdomain *rd2)
{}

/*
 * XXX: add support for the rest of enum nl80211_reg_rule_flags, we may
 * want to just have the channel structure use these
 */
static u32 map_regdom_flags(u32 rd_flags)
{}

static const struct ieee80211_reg_rule *
freq_reg_info_regd(u32 center_freq,
		   const struct ieee80211_regdomain *regd, u32 bw)
{}

static const struct ieee80211_reg_rule *
__freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
{}

const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
					       u32 center_freq)
{}
EXPORT_SYMBOL();

const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
{}
EXPORT_SYMBOL();

static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd,
					  const struct ieee80211_reg_rule *reg_rule,
					  const struct ieee80211_channel *chan)
{}

static void handle_channel_single_rule(struct wiphy *wiphy,
				       enum nl80211_reg_initiator initiator,
				       struct ieee80211_channel *chan,
				       u32 flags,
				       struct regulatory_request *lr,
				       struct wiphy *request_wiphy,
				       const struct ieee80211_reg_rule *reg_rule)
{}

static void handle_channel_adjacent_rules(struct wiphy *wiphy,
					  enum nl80211_reg_initiator initiator,
					  struct ieee80211_channel *chan,
					  u32 flags,
					  struct regulatory_request *lr,
					  struct wiphy *request_wiphy,
					  const struct ieee80211_reg_rule *rrule1,
					  const struct ieee80211_reg_rule *rrule2,
					  struct ieee80211_freq_range *comb_range)
{}

/* Note that right now we assume the desired channel bandwidth
 * is always 20 MHz for each individual channel (HT40 uses 20 MHz
 * per channel, the primary and the extension channel).
 */
static void handle_channel(struct wiphy *wiphy,
			   enum nl80211_reg_initiator initiator,
			   struct ieee80211_channel *chan)
{}

static void handle_band(struct wiphy *wiphy,
			enum nl80211_reg_initiator initiator,
			struct ieee80211_supported_band *sband)
{}

static bool reg_request_cell_base(struct regulatory_request *request)
{}

bool reg_last_request_cell_base(void)
{}

#ifdef CONFIG_CFG80211_REG_CELLULAR_HINTS
/* Core specific check */
static enum reg_request_treatment
reg_ignore_cell_hint(struct regulatory_request *pending_request)
{}

/* Device specific check */
static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
{}
#else
static enum reg_request_treatment
reg_ignore_cell_hint(struct regulatory_request *pending_request)
{
	return REG_REQ_IGNORE;
}

static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
{
	return true;
}
#endif

static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy)
{}

static bool ignore_reg_update(struct wiphy *wiphy,
			      enum nl80211_reg_initiator initiator)
{}

static bool reg_is_world_roaming(struct wiphy *wiphy)
{}

static void reg_call_notifier(struct wiphy *wiphy,
			      struct regulatory_request *request)
{}

static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
			      struct reg_beacon *reg_beacon)
{}

/*
 * Called when a scan on a wiphy finds a beacon on
 * new channel
 */
static void wiphy_update_new_beacon(struct wiphy *wiphy,
				    struct reg_beacon *reg_beacon)
{}

/*
 * Called upon reg changes or a new wiphy is added
 */
static void wiphy_update_beacon_reg(struct wiphy *wiphy)
{}

/* Reap the advantages of previously found beacons */
static void reg_process_beacons(struct wiphy *wiphy)
{}

static bool is_ht40_allowed(struct ieee80211_channel *chan)
{}

static void reg_process_ht_flags_channel(struct wiphy *wiphy,
					 struct ieee80211_channel *channel)
{}

static void reg_process_ht_flags_band(struct wiphy *wiphy,
				      struct ieee80211_supported_band *sband)
{}

static void reg_process_ht_flags(struct wiphy *wiphy)
{}

static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
{}

static void reg_leave_invalid_chans(struct wiphy *wiphy)
{}

static void reg_check_chans_work(struct work_struct *work)
{}

void reg_check_channels(void)
{}

static void wiphy_update_regulatory(struct wiphy *wiphy,
				    enum nl80211_reg_initiator initiator)
{}

static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
{}

static void handle_channel_custom(struct wiphy *wiphy,
				  struct ieee80211_channel *chan,
				  const struct ieee80211_regdomain *regd,
				  u32 min_bw)
{}

static void handle_band_custom(struct wiphy *wiphy,
			       struct ieee80211_supported_band *sband,
			       const struct ieee80211_regdomain *regd)
{}

/* Used by drivers prior to wiphy registration */
void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
				   const struct ieee80211_regdomain *regd)
{}
EXPORT_SYMBOL();

static void reg_set_request_processed(void)
{}

/**
 * reg_process_hint_core - process core regulatory requests
 * @core_request: a pending core regulatory request
 *
 * The wireless subsystem can use this function to process
 * a regulatory request issued by the regulatory core.
 *
 * Returns: %REG_REQ_OK or %REG_REQ_IGNORE, indicating if the
 *	hint was processed or ignored
 */
static enum reg_request_treatment
reg_process_hint_core(struct regulatory_request *core_request)
{}

static enum reg_request_treatment
__reg_process_hint_user(struct regulatory_request *user_request)
{}

/**
 * reg_process_hint_user - process user regulatory requests
 * @user_request: a pending user regulatory request
 *
 * The wireless subsystem can use this function to process
 * a regulatory request initiated by userspace.
 *
 * Returns: %REG_REQ_OK or %REG_REQ_IGNORE, indicating if the
 *	hint was processed or ignored
 */
static enum reg_request_treatment
reg_process_hint_user(struct regulatory_request *user_request)
{}

static enum reg_request_treatment
__reg_process_hint_driver(struct regulatory_request *driver_request)
{}

/**
 * reg_process_hint_driver - process driver regulatory requests
 * @wiphy: the wireless device for the regulatory request
 * @driver_request: a pending driver regulatory request
 *
 * The wireless subsystem can use this function to process
 * a regulatory request issued by an 802.11 driver.
 *
 * Returns: one of the different reg request treatment values.
 */
static enum reg_request_treatment
reg_process_hint_driver(struct wiphy *wiphy,
			struct regulatory_request *driver_request)
{}

static enum reg_request_treatment
__reg_process_hint_country_ie(struct wiphy *wiphy,
			      struct regulatory_request *country_ie_request)
{}

/**
 * reg_process_hint_country_ie - process regulatory requests from country IEs
 * @wiphy: the wireless device for the regulatory request
 * @country_ie_request: a regulatory request from a country IE
 *
 * The wireless subsystem can use this function to process
 * a regulatory request issued by a country Information Element.
 *
 * Returns: one of the different reg request treatment values.
 */
static enum reg_request_treatment
reg_process_hint_country_ie(struct wiphy *wiphy,
			    struct regulatory_request *country_ie_request)
{}

bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2)
{}

static void reg_copy_dfs_chan_state(struct ieee80211_channel *dst_chan,
				    struct ieee80211_channel *src_chan)
{}

static void wiphy_share_dfs_chan_state(struct wiphy *dst_wiphy,
				       struct wiphy *src_wiphy)
{}

static void wiphy_all_share_dfs_chan_state(struct wiphy *wiphy)
{}

/* This processes *all* regulatory hints */
static void reg_process_hint(struct regulatory_request *reg_request)
{}

static void notify_self_managed_wiphys(struct regulatory_request *request)
{}

/*
 * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_*
 * Regulatory hints come on a first come first serve basis and we
 * must process each one atomically.
 */
static void reg_process_pending_hints(void)
{}

/* Processes beacon hints -- this has nothing to do with country IEs */
static void reg_process_pending_beacon_hints(void)
{}

static void reg_process_self_managed_hint(struct wiphy *wiphy)
{}

static void reg_process_self_managed_hints(void)
{}

static void reg_todo(struct work_struct *work)
{}

static void queue_regulatory_request(struct regulatory_request *request)
{}

/*
 * Core regulatory hint -- happens during cfg80211_init()
 * and when we restore regulatory settings.
 */
static int regulatory_hint_core(const char *alpha2)
{}

/* User hints */
int regulatory_hint_user(const char *alpha2,
			 enum nl80211_user_reg_hint_type user_reg_hint_type)
{}

void regulatory_hint_indoor(bool is_indoor, u32 portid)
{}

void regulatory_netlink_notify(u32 portid)
{}

/* Driver hints */
int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
{}
EXPORT_SYMBOL();

void regulatory_hint_country_ie(struct wiphy *wiphy, enum nl80211_band band,
				const u8 *country_ie, u8 country_ie_len)
{}

static void restore_alpha2(char *alpha2, bool reset_user)
{}

static void restore_custom_reg_settings(struct wiphy *wiphy)
{}

/*
 * Restoring regulatory settings involves ignoring any
 * possibly stale country IE information and user regulatory
 * settings if so desired, this includes any beacon hints
 * learned as we could have traveled outside to another country
 * after disconnection. To restore regulatory settings we do
 * exactly what we did at bootup:
 *
 *   - send a core regulatory hint
 *   - send a user regulatory hint if applicable
 *
 * Device drivers that send a regulatory hint for a specific country
 * keep their own regulatory domain on wiphy->regd so that does
 * not need to be remembered.
 */
static void restore_regulatory_settings(bool reset_user, bool cached)
{}

static bool is_wiphy_all_set_reg_flag(enum ieee80211_regulatory_flags flag)
{}

void regulatory_hint_disconnect(void)
{}

static bool freq_is_chan_12_13_14(u32 freq)
{}

static bool pending_reg_beacon(struct ieee80211_channel *beacon_chan)
{}

void regulatory_hint_found_beacon(struct wiphy *wiphy,
				  struct ieee80211_channel *beacon_chan,
				  gfp_t gfp)
{}

static void print_rd_rules(const struct ieee80211_regdomain *rd)
{}

bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region)
{}

static void print_regdomain(const struct ieee80211_regdomain *rd)
{}

static void print_regdomain_info(const struct ieee80211_regdomain *rd)
{}

static int reg_set_rd_core(const struct ieee80211_regdomain *rd)
{}

static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
			   struct regulatory_request *user_request)
{}

static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
			     struct regulatory_request *driver_request)
{}

static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
				 struct regulatory_request *country_ie_request)
{}

/*
 * Use this call to set the current regulatory domain. Conflicts with
 * multiple drivers can be ironed out later. Caller must've already
 * kmalloc'd the rd structure.
 */
int set_regdom(const struct ieee80211_regdomain *rd,
	       enum ieee80211_regd_source regd_src)
{}

static int __regulatory_set_wiphy_regd(struct wiphy *wiphy,
				       struct ieee80211_regdomain *rd)
{}

int regulatory_set_wiphy_regd(struct wiphy *wiphy,
			      struct ieee80211_regdomain *rd)
{}
EXPORT_SYMBOL();

int regulatory_set_wiphy_regd_sync(struct wiphy *wiphy,
				   struct ieee80211_regdomain *rd)
{}
EXPORT_SYMBOL();

void wiphy_regulatory_register(struct wiphy *wiphy)
{}

void wiphy_regulatory_deregister(struct wiphy *wiphy)
{}

/*
 * See FCC notices for UNII band definitions
 *  5GHz: https://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii
 *  6GHz: https://www.fcc.gov/document/fcc-proposes-more-spectrum-unlicensed-use-0
 */
int cfg80211_get_unii(int freq)
{}

bool regulatory_indoor_allowed(void)
{}

bool regulatory_pre_cac_allowed(struct wiphy *wiphy)
{}
EXPORT_SYMBOL();

static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
{}

void regulatory_propagate_dfs_state(struct wiphy *wiphy,
				    struct cfg80211_chan_def *chandef,
				    enum nl80211_dfs_state dfs_state,
				    enum nl80211_radar_event event)
{}

static int __init regulatory_init_db(void)
{}
#ifndef MODULE
late_initcall(regulatory_init_db);
#endif

int __init regulatory_init(void)
{}

void regulatory_exit(void)
{}