about summary refs log tree commit diff
path: root/src/core/supplicant
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2024-09-01 22:38:35 +0200
committerMichael Biebl <biebl@debian.org>2024-09-01 22:38:35 +0200
commitf9bfd1158b8d08d6a5ed3bb7cc1ba7a6455e5201 (patch)
tree10267dcf5b842b7c638a79bd6851549cd849b81d /src/core/supplicant
parent681dfc70ef98f6ed0c05bcb0fbff00e3fc0799ea (diff)
New upstream version 1.49.90 upstream/1.49.90
Diffstat (limited to 'src/core/supplicant')
-rw-r--r--src/core/supplicant/nm-supplicant-config.c84
-rw-r--r--src/core/supplicant/nm-supplicant-settings-verify.c3
2 files changed, 87 insertions, 0 deletions
diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c
index 7db614a2..4433e809 100644
--- a/src/core/supplicant/nm-supplicant-config.c
+++ b/src/core/supplicant/nm-supplicant-config.c
@@ -499,6 +499,52 @@ nm_supplicant_config_add_setting_macsec(NMSupplicantConfig    *self,
     return TRUE;
 }
 
+static void
+get_ap_params(guint                         freq,
+              NMSettingWirelessChannelWidth width,
+              guint                        *out_ht40,
+              int                          *out_max_oper_chwidth,
+              guint                        *out_center_freq)
+{
+    *out_ht40             = 0;
+    *out_max_oper_chwidth = -1;
+    *out_center_freq      = 0;
+
+    switch (width) {
+    case NM_SETTING_WIRELESS_CHANNEL_WIDTH_40MHZ:
+        *out_ht40             = 1;
+        *out_max_oper_chwidth = 0;
+        return;
+    case NM_SETTING_WIRELESS_CHANNEL_WIDTH_80MHZ:
+    {
+        guint channel;
+
+        if (freq < 5000) {
+            /* the setting is not valid */
+            nm_assert_not_reached();
+            return;
+        }
+
+        /* Determine the center channel according to the table at
+         * https://en.wikipedia.org/wiki/List_of_WLAN_channels */
+        channel = (freq - 5000) / 5;
+        channel = ((channel / 4 - 1) / 4) * 16 + 10;
+
+        *out_ht40             = 1;
+        *out_max_oper_chwidth = 1;
+        *out_center_freq      = 5000 + 5 * channel;
+
+        return;
+    }
+
+    case NM_SETTING_WIRELESS_CHANNEL_WIDTH_AUTO:
+    case NM_SETTING_WIRELESS_CHANNEL_WIDTH_20MHZ:
+    default:
+        /* in case of unknown enum value, fall back to the safest parameters */
+        return;
+    }
+}
+
 gboolean
 nm_supplicant_config_add_setting_wireless(NMSupplicantConfig *self,
                                           NMSettingWireless  *setting,
@@ -562,10 +608,48 @@ nm_supplicant_config_add_setting_wireless(NMSupplicantConfig *self,
 
     if ((is_adhoc || is_ap || is_mesh) && fixed_freq) {
         gs_free char *str_freq = NULL;
+        guint         ht40;
+        int           max_oper_chwidth;
+        guint         center_freq;
 
         str_freq = g_strdup_printf("%u", fixed_freq);
         if (!nm_supplicant_config_add_option(self, "frequency", str_freq, -1, NULL, error))
             return FALSE;
+
+        if (is_ap) {
+            get_ap_params(fixed_freq,
+                          nm_setting_wireless_get_channel_width(setting),
+                          &ht40,
+                          &max_oper_chwidth,
+                          &center_freq);
+
+            if (!nm_supplicant_config_add_option(self, "ht40", ht40 ? "1" : "0", -1, NULL, error))
+                return FALSE;
+
+            if (center_freq != 0) {
+                g_free(str_freq);
+                str_freq = g_strdup_printf("%u", center_freq);
+                if (!nm_supplicant_config_add_option(self,
+                                                     "vht_center_freq1",
+                                                     str_freq,
+                                                     -1,
+                                                     NULL,
+                                                     error))
+                    return FALSE;
+            }
+
+            if (max_oper_chwidth >= 0) {
+                g_free(str_freq);
+                str_freq = g_strdup_printf("%u", max_oper_chwidth);
+                if (!nm_supplicant_config_add_option(self,
+                                                     "max_oper_chwidth",
+                                                     str_freq,
+                                                     -1,
+                                                     NULL,
+                                                     error))
+                    return FALSE;
+            }
+        }
     }
 
     /* Except for Ad-Hoc, Hotspot and Mesh, request that the driver probe for the
diff --git a/src/core/supplicant/nm-supplicant-settings-verify.c b/src/core/supplicant/nm-supplicant-settings-verify.c
index 76328541..6e5e44d2 100644
--- a/src/core/supplicant/nm-supplicant-settings-verify.c
+++ b/src/core/supplicant/nm-supplicant-settings-verify.c
@@ -73,6 +73,7 @@ static const struct Opt opt_table[] = {
     OPT_KEYWORD("freq_list", NULL),
     OPT_INT("frequency", 2412, 5825),
     OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", "GCMP-256", )),
+    OPT_INT("ht40", 0, 1),
     OPT_BYTES("identity", 0),
     OPT_INT("ieee80211w", 0, 2),
     OPT_INT("ignore_broadcast_ssid", 0, 2),
@@ -99,6 +100,7 @@ static const struct Opt opt_table[] = {
     OPT_INT("macsec_offload", 0, 2),
     OPT_INT("macsec_policy", 0, 1),
     OPT_INT("macsec_port", 1, 65534),
+    OPT_INT("max_oper_chwidth", 0, 9),
     OPT_BYTES("mka_cak", 65536),
     OPT_BYTES("mka_ckn", 65536),
     OPT_BYTES("nai", 0),
@@ -155,6 +157,7 @@ static const struct Opt opt_table[] = {
     OPT_BYTES("ssid", 32),
     OPT_BYTES("subject_match", 0),
     OPT_BYTES("subject_match2", 0),
+    OPT_INT("vht_center_freq1", 0, 100000),
     OPT_BYTES("wep_key0", 0),
     OPT_BYTES("wep_key1", 0),
     OPT_BYTES("wep_key2", 0),