Merge 571783a2a14ea85c38edadc9a9bd8663eab33281 on remote branch
Change-Id: I5d0c22b7fe23ccdfb21508f2f6ae2fcfcf1616bb
diff --git a/ap.c b/ap.c
index 8195013..0bfa56b 100644
--- a/ap.c
+++ b/ap.c
@@ -9721,6 +9721,9 @@
int ret = 0;
int ifindex;
+ if (!dut->main_ifname)
+ return -1;
+
ifindex = if_nametoindex(dut->main_ifname);
if (ifindex == 0) {
sigma_dut_print(dut, DUT_MSG_DEBUG,
@@ -9753,6 +9756,20 @@
return ret;
}
+
+void get_wiphy_capabilities(struct sigma_dut *dut)
+{
+ memset(&dut->hw_modes, 0, sizeof(struct dut_hw_modes));
+ if (get_driver_type(dut) == DRIVER_MAC80211 ||
+ get_driver_type(dut) == DRIVER_LINUX_WCN) {
+ if (mac80211_get_wiphy(dut))
+ sigma_dut_print(dut, DUT_MSG_DEBUG,
+ "Failed to get wiphy data from the driver");
+ else
+ dut->hw_modes.valid = true;
+ }
+}
+
#endif /* NL80211_SUPPORT */
@@ -10139,17 +10156,6 @@
dut->ap_dfs_mode = AP_DFS_MODE_ENABLED;
}
- memset(&dut->hw_modes, 0, sizeof(struct dut_hw_modes));
-#ifdef NL80211_SUPPORT
- if (get_driver_type(dut) == DRIVER_MAC80211 ||
- get_driver_type(dut) == DRIVER_LINUX_WCN) {
- if (mac80211_get_wiphy(dut))
- sigma_dut_print(dut, DUT_MSG_DEBUG,
- "Failed to get wiphy data from the driver");
- else
- dut->hw_modes.valid = true;
- }
-#endif /* NL80211_SUPPORT */
dut->ap_oper_chn = 0;
diff --git a/sigma_dut.c b/sigma_dut.c
index 1864ea1..c4d13aa 100644
--- a/sigma_dut.c
+++ b/sigma_dut.c
@@ -857,6 +857,9 @@
dut->user_config_ap_ocvc = -1;
dut->ap_sae_commit_status = -1;
dut->sta_async_twt_supp = -1;
+#ifdef ANDROID
+ dut->dscp_use_iptables = 1;
+#endif /* ANDROID */
}
@@ -1319,6 +1322,7 @@
#ifdef NL80211_SUPPORT
sigma_dut.nl_ctx = nl80211_init(&sigma_dut);
+ get_wiphy_capabilities(&sigma_dut);
#endif /* NL80211_SUPPORT */
sigma_dut_register_cmds();
diff --git a/sigma_dut.h b/sigma_dut.h
index ddb5d4d..60ce86c 100644
--- a/sigma_dut.h
+++ b/sigma_dut.h
@@ -393,6 +393,7 @@
int end_port;
enum ip_protocol protocol;
int dscp;
+ int granularity_score;
struct dscp_policy_data *next;
};
@@ -1039,6 +1040,7 @@
unsigned int num_dscp_status;
unsigned int prev_disable_scs_support;
unsigned int prev_disable_mscs_support;
+ int dscp_use_iptables;
};
@@ -1153,6 +1155,7 @@
int ap_wps_registration(struct sigma_dut *dut, struct sigma_conn *conn,
struct sigma_cmd *cmd);
const char * get_hostapd_ifname(struct sigma_dut *dut);
+void get_wiphy_capabilities(struct sigma_dut *dut);
/* sta.c */
void sta_register_cmds(void);
diff --git a/sta.c b/sta.c
index 008f102..2940757 100644
--- a/sta.c
+++ b/sta.c
@@ -3594,6 +3594,21 @@
}
+static char * protocol_to_str(int proto)
+{
+ switch (proto) {
+ case 6:
+ return "tcp";
+ case 17:
+ return "udp";
+ case 50:
+ return "esp";
+ default:
+ return "unknown";
+ }
+}
+
+
static int delete_nft_table(struct sigma_dut *dut, const char *table,
const char *ip_type)
{
@@ -3640,6 +3655,140 @@
}
+static int remove_iptable_rule(struct sigma_dut *dut,
+ struct dscp_policy_data *dscp_policy)
+{
+ char ip_cmd[1000];
+ char *pos;
+ int ret, len;
+ enum ip_version ip_ver = dscp_policy->ip_version;
+
+ pos = ip_cmd;
+ len = sizeof(ip_cmd);
+
+ ret = snprintf(pos, len,
+ "%s -t mangle -D OUTPUT -o %s",
+#ifdef ANDROID
+ ip_ver == IPV6 ? "/system/bin/ip6tables" : "/system/bin/iptables",
+#else /* ANDROID */
+ ip_ver == IPV6 ? "ip6tables" : "iptables",
+#endif /* ANDROID */
+ dut->station_ifname);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Failed to create delete iptables command %s",
+ ip_cmd);
+ return -1;
+ }
+
+ pos += ret;
+ len -= ret;
+
+ if (strlen(dscp_policy->src_ip)) {
+ ret = snprintf(pos, len, " -s %s", dscp_policy->src_ip);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding src_ip %s in delete command",
+ dscp_policy->src_ip);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (strlen(dscp_policy->dst_ip)) {
+ ret = snprintf(pos, len, " -d %s",
+ dscp_policy->dst_ip);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding dst_ip %s in delete cmd",
+ dscp_policy->dst_ip);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (dscp_policy->src_port || dscp_policy->dst_port ||
+ (dscp_policy->start_port && dscp_policy->end_port)) {
+ ret = snprintf(pos, len, " -p %s",
+ protocol_to_str(dscp_policy->protocol));
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding protocol %d in delete command",
+ dscp_policy->protocol);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (dscp_policy->src_port) {
+ ret = snprintf(pos, len, " --sport %d",
+ dscp_policy->src_port);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding src_port %d in delete command",
+ dscp_policy->src_port);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (dscp_policy->dst_port) {
+ ret = snprintf(pos, len, " --dport %d",
+ dscp_policy->dst_port);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding dst_port %d in delete command",
+ dscp_policy->dst_port);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (dscp_policy->start_port && dscp_policy->end_port) {
+ ret = snprintf(pos, len, " --match multiport --dports %d:%d",
+ dscp_policy->start_port,
+ dscp_policy->end_port);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding start:end port %d:%d in delete command",
+ dscp_policy->start_port,
+ dscp_policy->end_port);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ ret = snprintf(pos, len, " -j DSCP --set-dscp 0x%0x",
+ dscp_policy->dscp);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding dscp %0x in delete command",
+ dscp_policy->dscp);
+ return -1;
+ }
+ ret = system(ip_cmd);
+ sigma_dut_print(dut, DUT_MSG_DEBUG, "iptables rule: %s err: %d",
+ ip_cmd, ret);
+
+ return ret;
+}
+
+
+static int remove_dscp_policy_rule(struct sigma_dut *dut,
+ struct dscp_policy_data *dscp_policy)
+{
+ return dut->dscp_use_iptables ? remove_iptable_rule(dut, dscp_policy) :
+ remove_nft_rule(dut, dscp_policy->policy_id,
+ dscp_policy->ip_version);
+}
+
+
static int create_nft_table(struct sigma_dut *dut, int policy_id,
const char *table_name, enum ip_version ip_ver)
{
@@ -3679,21 +3828,6 @@
}
-static char * protocol_to_str(int proto)
-{
- switch (proto) {
- case 6:
- return "tcp";
- case 17:
- return "udp";
- case 50:
- return "esp";
- default:
- return "unknown";
- }
-}
-
-
static int remove_dscp_policy(struct sigma_dut *dut, u8 policy_id)
{
struct dscp_policy_data *dscp_policy = dut->dscp_policy_table;
@@ -3715,7 +3849,7 @@
return 0;
if (strlen(dscp_policy->domain_name) == 0 &&
- remove_nft_rule(dut, policy_id, dscp_policy->ip_version))
+ remove_dscp_policy_rule(dut, dscp_policy))
return -1;
if (prev)
@@ -3835,13 +3969,184 @@
}
+static int add_iptable_rule(struct sigma_dut *dut,
+ struct dscp_policy_data *dscp_policy)
+{
+ char ip_cmd[1000];
+ char *pos;
+ int ret, len;
+ enum ip_version ip_ver = dscp_policy->ip_version;
+ struct dscp_policy_data *active_policy = dut->dscp_policy_table;
+ int ipv4_rule_num = 1, ipv6_rule_num = 1;
+
+ pos = ip_cmd;
+ len = sizeof(ip_cmd);
+
+ /*
+ * DSCP target in the mangle table doesn't stop processing of rules
+ * so to make sure the most granular rule is applied last, add the new
+ * rules in granularity increasing order.
+ */
+ while (active_policy) {
+ /*
+ * Domain name rules are managed in sigma_dut thus don't count
+ * them while counting the number of active rules.
+ */
+ if (strlen(active_policy->domain_name)) {
+ active_policy = active_policy->next;
+ continue;
+ }
+
+ if (active_policy->granularity_score >
+ dscp_policy->granularity_score)
+ break;
+
+ if (active_policy->ip_version == IPV6)
+ ipv6_rule_num++;
+ else
+ ipv4_rule_num++;
+
+ active_policy = active_policy->next;
+ }
+
+ ret = snprintf(pos, len,
+ "%s -t mangle -I OUTPUT %d -o %s",
+#ifdef ANDROID
+ ip_ver == IPV6 ? "/system/bin/ip6tables" : "/system/bin/iptables",
+#else /* ANDROID */
+ ip_ver == IPV6 ? "ip6tables" : "iptables",
+#endif /* ANDROID */
+ ip_ver == IPV6 ? ipv6_rule_num : ipv4_rule_num,
+ dut->station_ifname);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Failed to create iptables command %s", ip_cmd);
+ return -1;
+ }
+
+ pos += ret;
+ len -= ret;
+
+ if (strlen(dscp_policy->src_ip)) {
+ ret = snprintf(pos, len, " -s %s", dscp_policy->src_ip);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding src_ip %s",
+ dscp_policy->src_ip);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (strlen(dscp_policy->dst_ip)) {
+ ret = snprintf(pos, len, " -d %s", dscp_policy->dst_ip);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding dst_ip %s",
+ dscp_policy->dst_ip);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (dscp_policy->src_port || dscp_policy->dst_port ||
+ (dscp_policy->start_port && dscp_policy->end_port)) {
+ ret = snprintf(pos, len, " -p %s",
+ protocol_to_str(dscp_policy->protocol));
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding protocol %d in add command",
+ dscp_policy->protocol);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (dscp_policy->src_port) {
+ ret = snprintf(pos, len, " --sport %d", dscp_policy->src_port);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding src_port %d",
+ dscp_policy->src_port);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (dscp_policy->dst_port) {
+ ret = snprintf(pos, len, " --dport %d", dscp_policy->dst_port);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding dst_port %d",
+ dscp_policy->dst_port);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ if (dscp_policy->start_port && dscp_policy->end_port) {
+ ret = snprintf(pos, len, " --match multiport --dports %d:%d",
+ dscp_policy->start_port, dscp_policy->end_port);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding start:end port %d:%d",
+ dscp_policy->start_port,
+ dscp_policy->end_port);
+ return -1;
+ }
+ pos += ret;
+ len -= ret;
+ }
+
+ ret = snprintf(pos, len, " -j DSCP --set-dscp 0x%0x",
+ dscp_policy->dscp);
+ if (snprintf_error(len, ret)) {
+ sigma_dut_print(dut, DUT_MSG_INFO,
+ "Error in adding dscp %0x", dscp_policy->dscp);
+ return -1;
+ }
+ ret = system(ip_cmd);
+ sigma_dut_print(dut, DUT_MSG_DEBUG, "iptables rule: %s err: %d",
+ ip_cmd, ret);
+
+ return ret;
+}
+
+
+static int add_dscp_policy_rule(struct sigma_dut *dut,
+ struct dscp_policy_data *dscp_policy)
+{
+ return dut->dscp_use_iptables ? add_iptable_rule(dut, dscp_policy) :
+ add_nft_rule(dut, dscp_policy);
+}
+
+
static void clear_all_dscp_policies(struct sigma_dut *dut)
{
free_dscp_policy_table(dut);
- if (system("nft flush ruleset") != 0)
- sigma_dut_print(dut, DUT_MSG_ERROR,
- "Failed to flush DSCP policy");
+ if (dut->dscp_use_iptables) {
+#ifdef ANDROID
+ if (system("/system/bin/iptables -t mangle -F && /system/bin/iptables -t mangle -X") != 0 ||
+ system("/system/bin/ip6tables -t mangle -F && /system/bin/ip6tables -t mangle -X") != 0)
+ sigma_dut_print(dut, DUT_MSG_ERROR,
+ "iptables: Failed to flush DSCP policy");
+#else /* ANDROID */
+ if (system("iptables -t mangle -F && iptables -t mangle -X") != 0 ||
+ system("ip6tables -t mangle -F && ip6tables -t mangle -X") != 0)
+ sigma_dut_print(dut, DUT_MSG_ERROR,
+ "iptables: Failed to flush DSCP policy");
+#endif /* ANDROID */
+ } else {
+ if (system("nft flush ruleset") != 0)
+ sigma_dut_print(dut, DUT_MSG_ERROR,
+ "nftables: Failed to flush DSCP policy");
+ }
}
@@ -3911,7 +4216,7 @@
int ret, policy_id;
struct wpa_ctrl *ctrl;
char buf[4096], *pos, *end;
- struct dscp_policy_data *policy = NULL, *policy_table;
+ struct dscp_policy_data *policy = NULL, *current_policy, *prev_policy;
struct dscp_policy_status status_list[10];
int num_status = 0;
const char *events[] = {
@@ -4038,6 +4343,8 @@
goto reject;
}
policy->ip_version = atoi(pos + 11);
+ if (policy->ip_version)
+ policy->granularity_score++;
pos = strstr(buf, "domain_name=");
if (pos) {
@@ -4051,6 +4358,7 @@
memcpy(policy->domain_name, pos, end - pos);
policy->domain_name[end - pos] = '\0';
+ policy->granularity_score++;
}
pos = strstr(buf, "start_port=");
@@ -4065,6 +4373,9 @@
policy->end_port = atoi(pos);
}
+ if (policy->start_port && policy->end_port)
+ policy->granularity_score++;
+
pos = strstr(buf, "src_ip=");
if (pos) {
pos += 7;
@@ -4077,6 +4388,7 @@
memcpy(policy->src_ip, pos, end - pos);
policy->src_ip[end - pos] = '\0';
+ policy->granularity_score++;
}
pos = strstr(buf, "dst_ip=");
@@ -4091,42 +4403,61 @@
memcpy(policy->dst_ip, pos, end - pos);
policy->dst_ip[end - pos] = '\0';
+ policy->granularity_score++;
}
pos = strstr(buf, "src_port=");
if (pos) {
pos += 9;
policy->src_port = atoi(pos);
+ policy->granularity_score++;
}
pos = strstr(buf, "dst_port=");
if (pos) {
pos += 9;
policy->dst_port = atoi(pos);
+ policy->granularity_score++;
}
pos = strstr(buf, "protocol=");
if (pos) {
pos += 9;
policy->protocol = atoi(pos);
+ policy->granularity_score++;
}
/*
* Skip adding nft rules for doman name policies.
* Domain name rules are applied in sigma_dut itself.
*/
- if (!strlen(policy->domain_name) && add_nft_rule(dut, policy))
+ if (!strlen(policy->domain_name) &&
+ add_dscp_policy_rule(dut, policy))
goto reject;
- if (dut->dscp_policy_table) {
- policy_table = dut->dscp_policy_table;
- while (policy_table->next != NULL)
- policy_table = policy_table->next;
+ /*
+ * Add the new policy in policy table in granularity increasing
+ * order.
+ */
+ current_policy = dut->dscp_policy_table;
+ prev_policy = NULL;
- policy_table->next = policy;
- } else
+ while (current_policy) {
+ if (current_policy->granularity_score >
+ policy->granularity_score)
+ break;
+
+ prev_policy = current_policy;
+ current_policy = current_policy->next;
+ }
+
+ if (prev_policy)
+ prev_policy->next = policy;
+ else
dut->dscp_policy_table = policy;
+ policy->next = current_policy;
+
success:
status_list[num_status].status = DSCP_POLICY_SUCCESS;
num_status++;
@@ -14283,6 +14614,9 @@
val = get_param(cmd, "TWT_Setup");
if (val) {
if (strcasecmp(val, "Request") == 0) {
+ if (set_power_save_wcn(dut, intf, 1) < 0)
+ sigma_dut_print(dut, DUT_MSG_ERROR,
+ "Failed to enable power save");
if (sta_twt_request(dut, conn, cmd)) {
send_resp(dut, conn, SIGMA_ERROR,
"ErrorCode,TWT setup failed");
diff --git a/utils.c b/utils.c
index a5c645c..cb69a99 100644
--- a/utils.c
+++ b/utils.c
@@ -418,6 +418,8 @@
void * nl80211_cmd(struct sigma_dut *dut, struct nl80211_ctx *ctx,
struct nl_msg *msg, int flags, uint8_t cmd)
{
+ if (!ctx)
+ return NULL;
return genlmsg_put(msg, 0, 0, ctx->netlink_familyid,
0, flags, cmd, 0);
}