diff mbox series

[RFC,1/5] hostapd: basic channel check for hostapd_cli chan_switch

Message ID 20200128150940.17018-2-sergey.matyukevich.os@quantenna.com
State Accepted
Headers show
Series hostapd: DFS channels in chan_switch command ane event | expand

Commit Message

Sergey Matyukevich Jan. 28, 2020, 3:09 p.m. UTC
Implement channel sanity check for hostapd_cli chan_switch command.
Verify provided values for bandwidth, frequencies, and secondary
channel offset. Reject requested channel switch operation if basic
constraints on frequencies and bandwidth are not fulfilled.

Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
---
 hostapd/ctrl_iface.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)
diff mbox series

Patch

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 090d4f0f6..4ea22e3d2 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2390,6 +2390,113 @@  static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
 
 #endif /* CONFIG_TESTING_OPTIONS */
 
+static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params)
+{
+	switch (params->bandwidth) {
+	case 0:
+		/* bandwidth not specified: use 20MHz by default */
+		/* fall-through */
+	case 20:
+		if (params->center_freq1 &&
+		    params->center_freq1 != params->freq)
+			return 1;
+
+		if (params->center_freq2)
+			return 1;
+
+		if (params->sec_channel_offset)
+			return 1;
+		break;
+	case 40:
+		if (!params->center_freq1)
+			return 1;
+
+		if (params->center_freq2)
+			return 1;
+
+		if (!params->sec_channel_offset)
+			return 1;
+
+		switch(params->sec_channel_offset) {
+		case 1:
+			if (params->freq + 10 != params->center_freq1)
+				return 1;
+			break;
+		case -1:
+			if (params->freq - 10 != params->center_freq1)
+				return 1;
+			break;
+		default:
+			return 1;
+		}
+
+		break;
+	case 80:
+		if (!params->center_freq1)
+			return 1;
+
+		if (!params->sec_channel_offset)
+			return 1;
+
+		switch(params->sec_channel_offset) {
+		case 1:
+			if ((params->freq - 10 != params->center_freq1) &&
+			    (params->freq + 30 != params->center_freq1))
+				return 1;
+			break;
+		case -1:
+			if ((params->freq + 10 != params->center_freq1) &&
+			    (params->freq - 30 != params->center_freq1))
+				return 1;
+			break;
+		default:
+			return 1;
+		}
+
+                /* adjacent and overlapped are not allowed for 80+80 */
+		if (params->center_freq2) {
+			if (params->center_freq1 - params->center_freq2 <= 80 &&
+			    params->center_freq2 - params->center_freq1 <= 80)
+                        return 1;
+		}
+
+		break;
+	case 160:
+		if (!params->center_freq1)
+			return 1;
+
+		if (params->center_freq2)
+			return 1;
+
+		if (!params->sec_channel_offset)
+			return 1;
+
+		switch(params->sec_channel_offset) {
+		case 1:
+			if ((params->freq + 70 != params->center_freq1) &&
+			    (params->freq + 30 != params->center_freq1) &&
+			    (params->freq - 10 != params->center_freq1) &&
+			    (params->freq - 50 != params->center_freq1))
+				return 1;
+			break;
+		case -1:
+			if ((params->freq + 50 != params->center_freq1) &&
+			    (params->freq + 10 != params->center_freq1) &&
+			    (params->freq - 30 != params->center_freq1) &&
+			    (params->freq - 70 != params->center_freq1))
+				return 1;
+			break;
+		default:
+			return 1;
+		}
+
+		break;
+	default:
+		return 1;
+	}
+
+	return 0;
+}
 
 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
 					  char *pos)
@@ -2403,6 +2510,12 @@  static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
 	if (ret)
 		return ret;
 
+	ret = hostapd_ctrl_check_freq_params(&settings.freq_params);
+	if (ret) {
+		wpa_printf(MSG_ERROR, "chanswitch: invalid frequency settings provided");
+		return ret;
+	}
+
 	for (i = 0; i < iface->num_bss; i++) {
 
 		/* Save CHAN_SWITCH VHT config */