From 2173e65aa098ab130bfdbc9b9cfe8ac2fc2ae086 Mon Sep 17 00:00:00 2001
From: Nishant Pandey <nishpand@codeaurora.org>
Date: Tue, 22 Sep 2020 14:23:08 +0530
Subject: [PATCH] mesh: Dynamic MAC ACL management over control interface

Extend support to modify MAC ACL and displayed it through
new control interface

commands:

ACCEPT_ACL <subcmd> [argument]
DENY_ACL <subcmd> [argument]
subcmd: ADD_MAC <addr> |DEL_MAC <addr>|SHOW|CLEAR

Signed-off-by: Nishant Pandey <nishpand@codeaurora.org>
---
 wpa_supplicant/ap.c             | 68 +++++++++++++++++++++++++++++++++++++++++
 wpa_supplicant/ap.h             |  5 +++
 wpa_supplicant/ctrl_iface.c     | 45 +++++++++++++++++++++++++++
 wpa_supplicant/events.c         |  1 +
 wpa_supplicant/mesh.c           |  1 +
 wpa_supplicant/wpa_cli.c        | 19 ++++++++++++
 wpa_supplicant/wpa_supplicant.c |  3 +-
 wpa_supplicant/wps_supplicant.c |  2 ++
 8 files changed, 143 insertions(+), 1 deletion(-)

--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -6,6 +6,7 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
+#include <stdbool.h>
 
 #include "utils/includes.h"
 
@@ -1616,6 +1617,73 @@ void wpas_ap_pmksa_cache_flush(struct wp
 		hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]);
 }
 
+#ifdef CONFIG_MESH
+
+int wpas_ap_acl_del_mac(struct wpa_supplicant *wpa_s, char *buf, bool accept)
+{
+	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+
+	if (accept) {
+		if (!hostapd_ctrl_iface_acl_del_mac(&hapd->conf->accept_mac,
+						    &hapd->conf->num_accept_mac,
+						    buf))
+			if (hostapd_disassoc_accept_mac(hapd))
+				return 1;
+	}
+
+	return hostapd_ctrl_iface_acl_del_mac(&hapd->conf->deny_mac,
+					      &hapd->conf->num_deny_mac,
+					      buf);
+}
+
+int wpas_ap_acl_add_mac(struct wpa_supplicant *wpa_s, char *buf, bool accept)
+{
+	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+
+	if (accept) {
+		return hostapd_ctrl_iface_acl_add_mac(&hapd->conf->accept_mac,
+						&hapd->conf->num_accept_mac,
+						buf);
+	} else {
+		if (!hostapd_ctrl_iface_acl_add_mac(&hapd->conf->deny_mac,
+					&hapd->conf->num_deny_mac, buf)) {
+			if (hostapd_disassoc_deny_mac(hapd))
+				return 1;
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+int wpas_ap_acl_show_mac(struct wpa_supplicant *wpa_s, char *reply,
+			 const int reply_size, bool accept)
+{
+	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+
+	if (accept)
+		return hostapd_ctrl_iface_acl_show_mac(
+					hapd->conf->accept_mac,
+					hapd->conf->num_accept_mac,
+					reply, reply_size);
+
+	return hostapd_ctrl_iface_acl_show_mac(
+				hapd->conf->deny_mac,
+				hapd->conf->num_deny_mac,
+				reply, reply_size);
+}
+
+void wpas_ap_deny_acl_clear_list(struct wpa_supplicant *wpa_s)
+{
+	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+
+
+	return hostapd_ctrl_iface_acl_clear_list(&hapd->conf->deny_mac,
+						 &hapd->conf->num_deny_mac);
+}
+
+#endif /* CONFIG_MESH */
+
 
 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
 #ifdef CONFIG_MESH
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -99,6 +99,11 @@ void wpas_ap_event_dfs_cac_aborted(struc
 				   struct dfs_event *radar);
 void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
 					struct dfs_event *radar);
+int wpas_ap_acl_del_mac(struct wpa_supplicant *wpa_s, char *buf, bool accept);
+int wpas_ap_acl_add_mac(struct wpa_supplicant *wpa_s, char *buf, bool accept);
+int wpas_ap_acl_show_mac(struct wpa_supplicant *wpa_s, char *reply,
+		const int reply_size, bool accept);
+void wpas_ap_deny_acl_clear_list(struct wpa_supplicant *wpa_s);
 
 void ap_periodic(struct wpa_supplicant *wpa_s);
 
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5,6 +5,7 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
+#include <stdbool.h>
 
 #include "utils/includes.h"
 #ifdef CONFIG_TESTING_OPTIONS
@@ -56,6 +57,7 @@
 #include "mesh.h"
 #include "dpp_supplicant.h"
 #include "sme.h"
+#include "ap/ieee802_11.h"
 
 #ifdef __NetBSD__
 #include <net/if_ether.h>
@@ -3284,6 +3286,18 @@ static int wpa_supplicant_ctrl_iface_mes
 	return wpas_mesh_peer_remove(wpa_s, addr);
 }
 
+static void wpas_ap_accept_acl_clear_list(struct wpa_supplicant *wpa_s)
+{
+	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+	struct mac_acl_entry **acl = &hapd->conf->accept_mac;
+	int *num = &hapd->conf->num_accept_mac;
+
+	while (*num) {
+		wpas_mesh_peer_remove(wpa_s, (*acl)[0].addr);
+		hostapd_remove_acl_mac(acl, num, (*acl)[0].addr);
+	}
+}
+
 
 static int wpa_supplicant_ctrl_iface_mesh_peer_add(
 	struct wpa_supplicant *wpa_s, char *cmd)
@@ -10655,6 +10669,38 @@ char * wpa_supplicant_ctrl_iface_process
 			reply_len = -1;
 #endif /* CONFIG_IBSS_RSN */
 #ifdef CONFIG_MESH
+	} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
+		if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
+			wpas_ap_acl_add_mac(wpa_s, buf + 19, 1);
+		} else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
+			reply_len = wpas_ap_acl_del_mac(wpa_s, buf + 19, 1);
+			if (reply_len == 1)
+				wpa_supplicant_ctrl_iface_mesh_peer_remove(
+							wpa_s, buf + 19);
+			else if (reply_len)
+				reply_len = -1;
+		} else if (os_strcmp(buf + 11, "SHOW") == 0) {
+			reply_len = wpas_ap_acl_show_mac(wpa_s, reply,
+							 reply_size, 1);
+		} else if (os_strcmp(buf + 11, "CLEAR") == 0) {
+			wpas_ap_accept_acl_clear_list(wpa_s);
+		}
+	} else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
+		if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
+			reply_len = wpas_ap_acl_add_mac(wpa_s, buf + 17, 0);
+			if (reply_len == 1)
+				wpa_supplicant_ctrl_iface_mesh_peer_remove(
+							wpa_s, buf + 17);
+			else if (reply_len)
+				reply_len = -1;
+		} else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
+			wpas_ap_acl_del_mac(wpa_s, buf + 17, 0);
+		} else if (os_strcmp(buf + 9, "SHOW") == 0) {
+			reply_len = wpas_ap_acl_show_mac(wpa_s, reply,
+							 reply_size, 0);
+		} else if (os_strcmp(buf + 9, "CLEAR") == 0) {
+			wpas_ap_deny_acl_clear_list(wpa_s);
+		}
 	} else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add(
 			wpa_s, buf + 19, reply, reply_size);
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -5,6 +5,7 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
+#include <stdbool.h>
 
 #include "includes.h"
 
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -5,6 +5,7 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
+#include <stdbool.h>
 
 #include "utils/includes.h"
 
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -2113,6 +2113,19 @@ static int wpa_cli_cmd_mesh_link_probe(s
 	return wpa_cli_cmd(ctrl, "MESH_LINK_PROBE", 1, argc, argv);
 }
 
+static int wpa_cli_cmd_accept_macacl(struct wpa_ctrl *ctrl, int argc,
+				     char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "ACCEPT_ACL", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_deny_macacl(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "DENY_ACL", 1, argc, argv);
+}
+
 #endif /* CONFIG_MESH */
 
 
@@ -3532,6 +3545,12 @@ static const struct wpa_cli_cmd wpa_cli_
 	{ "mesh_link_probe", wpa_cli_cmd_mesh_link_probe, NULL,
 	  cli_cmd_flag_none,
 	  "<addr> [payload=<hex dump of payload>] = Probe a mesh link for a given peer by injecting a frame." },
+	{ "accept_acl", wpa_cli_cmd_accept_macacl, NULL,
+	  cli_cmd_flag_none,
+	  "=Add/Delete/Show/Clear accept MAC ACL" },
+	{ "deny_acl", wpa_cli_cmd_deny_macacl, NULL,
+	  cli_cmd_flag_none,
+	  "=Add/Delete/Show/Clear deny MAC ACL" },
 #endif /* CONFIG_MESH */
 #ifdef CONFIG_P2P
 	{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -9,6 +9,7 @@
  * %wpa_supplicant interfaces. In addition, this file contains number of
  * functions for managing network connections.
  */
+#include <stdbool.h>
 
 #include "includes.h"
 #ifdef CONFIG_MATCH_IFACE
@@ -49,7 +50,6 @@
 #include "ibss_rsn.h"
 #include "sme.h"
 #include "gas_query.h"
-#include "ap.h"
 #include "p2p_supplicant.h"
 #include "wifi_display.h"
 #include "notify.h"
@@ -67,6 +67,7 @@
 #include "ap/ap_config.h"
 #include "ap/hostapd.h"
 #endif /* CONFIG_MESH */
+#include "ap.h"
 
 const char *const wpa_supplicant_version =
 "wpa_supplicant v" VERSION_STR "\n"
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -5,6 +5,7 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
+#include <stdbool.h>
 
 #include "includes.h"
 
@@ -21,6 +22,7 @@
 #include "eap_peer/eap.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "rsn_supp/wpa.h"
+#include "ap/hostapd.h"
 #include "wps/wps_attr_parse.h"
 #include "config.h"
 #include "wpa_supplicant_i.h"
