sta_set_rts: Add nl80211 support to set RTS threshold

Previous implementation used only the ioctl() path to set RTS threshold.
This operation fails for the drivers which have obsoleted the support
for the SIOCSIWRTS ioctl() command.

Try to set RTS threshold via netlink path if NL80211_SUPPORT is enabled.
If RTS threshold configuration fails via the netlink path try the
ioctl() path to maintain backwards compatibility with old drivers.

If NL80211_SUPPORT is not enabled continue as per previous
implementation, i.e., try to set RTS threshold only via the ioctl()
path.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
diff --git a/sta.c b/sta.c
index 3033c5b..3284d71 100644
--- a/sta.c
+++ b/sta.c
@@ -5124,6 +5124,63 @@
 }
 
 
+#ifdef NL80211_SUPPORT
+static int nl80211_sta_set_rts(struct sigma_dut *dut, const char *intf, int val)
+{
+	struct nl_msg *msg;
+	int ret = 0;
+	int ifindex;
+
+	ifindex = if_nametoindex(intf);
+	if (ifindex == 0) {
+		sigma_dut_print(dut, DUT_MSG_ERROR,
+				"%s: Index for interface %s failed",
+				__func__, intf);
+		return -1;
+	}
+
+	if (!(msg = nl80211_drv_msg(dut, dut->nl_ctx, ifindex, 0,
+				    NL80211_CMD_SET_WIPHY)) ||
+	    nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val)) {
+		sigma_dut_print(dut, DUT_MSG_ERROR,
+				"%s: err in adding RTS threshold",
+				__func__);
+		nlmsg_free(msg);
+		return -1;
+	}
+
+	ret = send_and_recv_msgs(dut, dut->nl_ctx, msg, NULL, NULL);
+	if (ret) {
+		sigma_dut_print(dut, DUT_MSG_ERROR,
+				"%s: err in send_and_recv_msgs, ret=%d",
+				__func__, ret);
+	}
+	return ret;
+}
+#endif /* NL80211_SUPPORT */
+
+
+static int sta_set_rts(struct sigma_dut *dut, const char *intf, int val)
+{
+	char buf[100];
+
+#ifdef NL80211_SUPPORT
+	if (nl80211_sta_set_rts(dut, intf, val) == 0)
+		return 0;
+	sigma_dut_print(dut, DUT_MSG_DEBUG,
+			"Fall back to using iwconfig for setting RTS threshold");
+#endif /* NL80211_SUPPORT */
+
+	snprintf(buf, sizeof(buf), "iwconfig %s rts %d", intf, val);
+	if (system(buf) != 0) {
+		sigma_dut_print(dut, DUT_MSG_ERROR,
+				"Failed to set RTS threshold %d", val);
+		return -1;
+	}
+	return 0;
+}
+
+
 static int cmd_sta_set_wireless_common(const char *intf, struct sigma_dut *dut,
 				       struct sigma_conn *conn,
 				       struct sigma_cmd *cmd)
@@ -5362,8 +5419,7 @@
 	if (val) {
 		novap_reset(dut, intf);
 		if (strcasecmp(val, "Enable") == 0) {
-			snprintf(buf, sizeof(buf), "iwconfig %s rts 64", intf);
-			if (system(buf) != 0) {
+			if (sta_set_rts(dut, intf, 64) != 0) {
 				sigma_dut_print(dut, DUT_MSG_ERROR,
 						"Failed to set RTS_FORCE 64");
 			}
@@ -5374,9 +5430,7 @@
 						"wifitool beeliner_fw_test 100 1 failed");
 			}
 		} else if (strcasecmp(val, "Disable") == 0) {
-			snprintf(buf, sizeof(buf), "iwconfig %s rts 2347",
-				 intf);
-			if (system(buf) != 0) {
+			if (sta_set_rts(dut, intf, 2347) != 0) {
 				sigma_dut_print(dut, DUT_MSG_ERROR,
 						"Failed to set RTS_FORCE 2347");
 			}