All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.linux.dev
Cc: James Prestwood <prestwoj@gmail.com>
Subject: [PATCH 4/4] wiphy: support country code override
Date: Wed,  7 Sep 2022 16:32:01 -0700	[thread overview]
Message-ID: <20220907233201.227577-4-prestwoj@gmail.com> (raw)
In-Reply-To: <20220907233201.227577-1-prestwoj@gmail.com>

Depending on the device the regulatory domain may never get
set on its own. This is worked around in wpa_supplicant by
allowing the user to supply a country code. The kernel
_should_ set this on its own based on the docs, but ultimately
will fall back to user defined if the driver doesn't set it.

IWD now needs to work around this problem by allowing users
to supply the country code in main.conf.

A few notes here:
 - Setting the country may not effect the actual regulatory
   domain. This is because the kernel still remains in control.
   Any request is merely a hint to the kernel.
 - This only applies to devices under the global regulatory
   domain. Self-managed devices will not allow setting the
   regdom.
---
 src/wiphy.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/wiphy.c b/src/wiphy.c
index af675694..b87cfefd 100644
--- a/src/wiphy.c
+++ b/src/wiphy.c
@@ -65,7 +65,9 @@ static char **whitelist_filter;
 static char **blacklist_filter;
 static int mac_randomize_bytes = 6;
 static unsigned int get_reg_id;
+static unsigned int set_reg_id;
 static char regdom_country[2];
+static char regdom_override[2];
 static uint32_t work_ids;
 static unsigned int wiphy_dump_id;
 
@@ -2090,6 +2092,14 @@ static void wiphy_get_reg_cb(struct l_genl_msg *msg, void *user_data)
 				NL80211_ATTR_UNSPEC) < 0;
 
 	wiphy_update_reg_domain(wiphy, global, msg);
+
+	if (global && regdom_override[0] && regdom_override[1]) {
+		if (regdom_override[0] != regdom_country[0] ||
+				regdom_override[1] != regdom_country[1])
+			l_warn("Regdom %c%c does not match override %c%c",
+				regdom_country[0], regdom_country[1],
+				regdom_override[0], regdom_override[1]);
+	}
 }
 
 static void wiphy_get_reg_domain(struct wiphy *wiphy)
@@ -2119,6 +2129,69 @@ static void wiphy_get_reg_domain(struct wiphy *wiphy)
 		get_reg_id = id;
 }
 
+static void wiphy_set_reg_cb(struct l_genl_msg *msg, void *user_data)
+{
+	int err = l_genl_msg_get_error(msg);
+
+	set_reg_id = 0;
+
+	/* Just warn if the CC was invalid, can't do much else here... */
+	if (err < 0)
+		l_warn("Error setting regulatory domain (%d)", err);
+
+	/*
+	 * Always get the regdom to see if the override actually worked. The
+	 * kernel may choose to ignore REQ_SET_REG requests. If so this will be
+	 * logged. Since this only applies to the global regdom do a global
+	 * GET_REG with wiphy set to NULL
+	 */
+	wiphy_get_reg_domain(NULL);
+}
+
+static void wiphy_set_reg_domain(const char *cc)
+{
+	struct l_genl_msg *msg;
+
+	regdom_override[0] = cc[0];
+	regdom_override[1] = cc[1];
+
+	msg = l_genl_msg_new(NL80211_CMD_REQ_SET_REG);
+	l_genl_msg_append_attr(msg, NL80211_ATTR_REG_ALPHA2, 2, cc);
+
+	set_reg_id = l_genl_family_send(nl80211, msg, wiphy_set_reg_cb,
+					NULL, NULL);
+	/* Could try getting the regdom, but that likely wouldn't work either */
+	if (L_WARN_ON(!set_reg_id))
+		return;
+
+	l_debug("Trying to set country to %s", cc);
+}
+
+static void wiphy_setup_reg_domain(struct wiphy *wiphy)
+{
+	const struct l_settings *config = iwd_get_config();
+	const char *cc = l_settings_get_value(config, "General", "Country");
+
+	/*
+	 * At least do basic validation. If this fails force a GET_REG but do
+	 * not try setting the domain.
+	 */
+	if (cc) {
+		if (strlen(cc) != 2 || !l_ascii_isalpha(cc[0]) ||
+					!l_ascii_isalpha(cc[1])) {
+			l_error("Invalid setting [General].Country=%s", cc);
+			cc = NULL;
+		}
+	}
+
+	if (!cc || wiphy->self_managed) {
+		wiphy_get_reg_domain(wiphy->self_managed ? wiphy : NULL);
+		return;
+	}
+
+	wiphy_set_reg_domain(cc);
+}
+
 void wiphy_create_complete(struct wiphy *wiphy)
 {
 	wiphy_register(wiphy);
@@ -2133,7 +2206,7 @@ void wiphy_create_complete(struct wiphy *wiphy)
 
 	wiphy_set_station_capability_bits(wiphy);
 	wiphy_setup_rm_enabled_capabilities(wiphy);
-	wiphy_get_reg_domain(wiphy->self_managed ? wiphy : NULL);
+	wiphy_setup_reg_domain(wiphy);
 
 	wiphy_print_basic_info(wiphy);
 }
@@ -2540,6 +2613,11 @@ static void wiphy_exit(void)
 		get_reg_id = 0;
 	}
 
+	if (set_reg_id) {
+		l_genl_family_cancel(nl80211, set_reg_id);
+		set_reg_id = 0;
+	}
+
 	l_queue_destroy(wiphy_list, wiphy_free);
 	wiphy_list = NULL;
 
-- 
2.34.3


  parent reply	other threads:[~2022-09-07 23:32 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-07 23:31 [PATCH 1/4] doc: document [General].Country main.conf option James Prestwood
2022-09-07 23:31 ` [PATCH 2/4] wiphy: remove nl80211 from wiphy object James Prestwood
2022-09-08 14:53   ` Denis Kenzior
2022-09-07 23:32 ` [PATCH 3/4] wiphy: only do global GET_REG once James Prestwood
2022-09-08 15:55   ` Denis Kenzior
2022-09-07 23:32 ` James Prestwood [this message]
2022-09-08 16:00   ` [PATCH 4/4] wiphy: support country code override Denis Kenzior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220907233201.227577-4-prestwoj@gmail.com \
    --to=prestwoj@gmail.com \
    --cc=iwd@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.