Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: l2: wifi: Add support for W-Fi mode setting and selection #62201

Merged

Conversation

VivekUppunda
Copy link
Contributor

This change brings in support for setting various Wi-Fi modes and enables a specific Wi-Fi interface to be also placed into a sniffer operation via monitor mode and promiscuous mode. A raw TX- packet Injection mode is also introduced

subsys/net/l2/wifi/wifi_shell.c Show resolved Hide resolved
subsys/net/l2/wifi/wifi_shell.c Outdated Show resolved Hide resolved
subsys/net/l2/wifi/wifi_shell.c Outdated Show resolved Hide resolved
@VivekUppunda VivekUppunda force-pushed the promiscuous_code_change branch 4 times, most recently from c054b40 to b3c189e Compare September 8, 2023 07:34
Copy link
Member

@jukkar jukkar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me clarify what I meant. With these changes we never get a mixup of user supplied if_index and the iface that we send the commands to, they will always be correct.

diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c
index f42f5d0df1..1808d68cff 100644
--- a/subsys/net/l2/wifi/wifi_shell.c
+++ b/subsys/net/l2/wifi/wifi_shell.c
@@ -1270,7 +1270,7 @@ void parse_mode_args_to_params(const struct shell *sh, int argc,
 	int opt;
 	int option_index = 0;
 
-	static struct option long_options[] = {{"if_index", required_argument, 0, 'i'},
+	static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'},
 					       {"sta", no_argument, 0, 's'},
 					       {"monitor", no_argument, 0, 'm'},
 					       {"TX-injection", no_argument, 0, 't'},
@@ -1338,11 +1338,15 @@ static int cmd_wifi_mode(const struct shell *sh, size_t argc, char *argv[])
 		 * lower layer
 		 */
 
-		if ((mode_info.if_index < WIFI_INTERFACE_INDEX_MIN) ||
-		    (mode_info.if_index > WIFI_INTERFACE_INDEX_MAX)) {
-			shell_fprintf(sh, SHELL_ERROR,
-					"if_index value is out of bounds. Range is (1-255)\n");
-			return -ENOEXEC;
+		if (mode_info.if_index == 0) {
+			mode_info.if_index = net_if_get_by_iface(iface);
+		} else {
+			iface = net_if_get_by_index(mode_info.if_index);
+			if (iface == NULL) {
+				shell_fprintf(sh, SHELL_ERROR,
+					      "Cannot find interface for if_index %d\n", mode_info.if_index);
+				return -ENOEXEC;
+			}
 		}
 
 		ret = net_mgmt(NET_REQUEST_WIFI_MODE, iface, &mode_info, sizeof(mode_info));
@@ -1370,7 +1374,7 @@ void parse_channel_args_to_params(const struct shell *sh, int argc,
 	int opt;
 	int option_index = 0;
 
-	static struct option long_options[] = {{"if_index", required_argument, 0, 'i'},
+	static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'},
 					       {"channel", required_argument, 0, 'c'},
 					       {"get", no_argument, 0, 'g'},
 					       {"help", no_argument, 0, 'h'},
@@ -1421,11 +1425,15 @@ static int cmd_wifi_channel(const struct shell *sh, size_t argc, char *argv[])
 		 * the lower layer.
 		 */
 
-		if ((channel_info.if_index < WIFI_INTERFACE_INDEX_MIN) ||
-		    (channel_info.if_index > WIFI_INTERFACE_INDEX_MAX)) {
-			shell_fprintf(sh, SHELL_ERROR,
-					"if_index value is out of bounds. Range is (1-255)\n");
-			return -ENOEXEC;
+		if (channel_info.if_index == 0) {
+			channel_info.if_index = net_if_get_by_iface(iface);
+		} else {
+			iface = net_if_get_by_index(channel_info.if_index);
+			if (iface == NULL) {
+				shell_fprintf(sh, SHELL_ERROR,
+					      "Cannot find interface for if_index %d\n", channel_info.if_index);
+				return -ENOEXEC;
+			}
 		}
 
 		if (channel_info.oper == WIFI_MGMT_SET) {
@@ -1465,7 +1473,7 @@ void parse_filter_args_to_params(const struct shell *sh, int argc,
 	int opt;
 	int option_index = 0;
 
-	static struct option long_options[] = {{"if_index", required_argument, 0, 'i'},
+	static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'},
 					       {"capture_len", required_argument, 0, 'b'},
 					       {"all", no_argument, 0, 'a'},
 					       {"mgmt", no_argument, 0, 'm'},
@@ -1533,11 +1541,15 @@ static int cmd_wifi_packet_filter(const struct shell *sh, size_t argc, char *arg
 		 * value to be verified by the lower layer.
 		 */
 
-		if ((packet_filter.if_index < WIFI_INTERFACE_INDEX_MIN) ||
-		    (packet_filter.if_index > WIFI_INTERFACE_INDEX_MAX)) {
-			shell_fprintf(sh, SHELL_ERROR,
-					"if_index value is out of bounds. Range is (1-255)\n");
-			return -ENOEXEC;
+		if (packet_filter.if_index == 0) {
+			packet_filter.if_index = net_if_get_by_iface(iface);
+		} else {
+			iface = net_if_get_by_index(packet_filter.if_index);
+			if (iface == NULL) {
+				shell_fprintf(sh, SHELL_ERROR,
+					      "Cannot find interface for if_index %d\n", packet_filter.if_index);
+				return -ENOEXEC;
+			}
 		}
 
 		ret = net_mgmt(NET_REQUEST_WIFI_PACKET_FILTER, iface,

I did not test the diff so it might not fully work yet.
Bonus point if done like this is that we do not need to give the interface index if there is only one wifi network interface in the system.

@jukkar
Copy link
Member

jukkar commented Sep 8, 2023

Also just noticed that we need to fix the initial iface value

diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c
index 1808d68cff..bba7301438 100644
--- a/subsys/net/l2/wifi/wifi_shell.c
+++ b/subsys/net/l2/wifi/wifi_shell.c
@@ -1320,7 +1320,7 @@ void parse_mode_args_to_params(const struct shell *sh, int argc,
 
 static int cmd_wifi_mode(const struct shell *sh, size_t argc, char *argv[])
 {
-       struct net_if *iface = net_if_get_default();
+       struct net_if *iface = net_if_get_first_wifi();
        struct wifi_mode_info mode_info = {0};
        int ret;
        bool do_mode_oper = true;
@@ -1404,7 +1404,7 @@ void parse_channel_args_to_params(const struct shell *sh, int argc,
 
 static int cmd_wifi_channel(const struct shell *sh, size_t argc, char *argv[])
 {
-       struct net_if *iface = net_if_get_default();
+       struct net_if *iface = net_if_get_first_wifi();
        struct wifi_channel_info channel_info = {0};
        int ret;
        bool do_channel_oper = true;
@@ -1519,7 +1519,7 @@ void parse_filter_args_to_params(const struct shell *sh, int argc,
 
 static int cmd_wifi_packet_filter(const struct shell *sh, size_t argc, char *argv[])
 {
-       struct net_if *iface = net_if_get_default();
+       struct net_if *iface = net_if_get_first_wifi();
        struct wifi_filter_info packet_filter = {0};
        int ret;
        bool do_filter_oper = true;

Please change that too.

@VivekUppunda
Copy link
Contributor Author

Also just noticed that we need to fix the initial iface value

diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c
index 1808d68cff..bba7301438 100644
--- a/subsys/net/l2/wifi/wifi_shell.c
+++ b/subsys/net/l2/wifi/wifi_shell.c
@@ -1320,7 +1320,7 @@ void parse_mode_args_to_params(const struct shell *sh, int argc,
 
 static int cmd_wifi_mode(const struct shell *sh, size_t argc, char *argv[])
 {
-       struct net_if *iface = net_if_get_default();
+       struct net_if *iface = net_if_get_first_wifi();
        struct wifi_mode_info mode_info = {0};
        int ret;
        bool do_mode_oper = true;
@@ -1404,7 +1404,7 @@ void parse_channel_args_to_params(const struct shell *sh, int argc,
 
 static int cmd_wifi_channel(const struct shell *sh, size_t argc, char *argv[])
 {
-       struct net_if *iface = net_if_get_default();
+       struct net_if *iface = net_if_get_first_wifi();
        struct wifi_channel_info channel_info = {0};
        int ret;
        bool do_channel_oper = true;
@@ -1519,7 +1519,7 @@ void parse_filter_args_to_params(const struct shell *sh, int argc,
 
 static int cmd_wifi_packet_filter(const struct shell *sh, size_t argc, char *argv[])
 {
-       struct net_if *iface = net_if_get_default();
+       struct net_if *iface = net_if_get_first_wifi();
        struct wifi_filter_info packet_filter = {0};
        int ret;
        bool do_filter_oper = true;

Please change that too.

I see that net_if_get_default internally invokes - iface = net_if_get_first_wifi(); for Wifi. I will check this too

@VivekUppunda
Copy link
Contributor Author

Let me clarify what I meant. With these changes we never get a mixup of user supplied if_index and the iface that we send the commands to, they will always be correct.

diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c
index f42f5d0df1..1808d68cff 100644
--- a/subsys/net/l2/wifi/wifi_shell.c
+++ b/subsys/net/l2/wifi/wifi_shell.c
@@ -1270,7 +1270,7 @@ void parse_mode_args_to_params(const struct shell *sh, int argc,
 	int opt;
 	int option_index = 0;
 
-	static struct option long_options[] = {{"if_index", required_argument, 0, 'i'},
+	static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'},
 					       {"sta", no_argument, 0, 's'},
 					       {"monitor", no_argument, 0, 'm'},
 					       {"TX-injection", no_argument, 0, 't'},
@@ -1338,11 +1338,15 @@ static int cmd_wifi_mode(const struct shell *sh, size_t argc, char *argv[])
 		 * lower layer
 		 */
 
-		if ((mode_info.if_index < WIFI_INTERFACE_INDEX_MIN) ||
-		    (mode_info.if_index > WIFI_INTERFACE_INDEX_MAX)) {
-			shell_fprintf(sh, SHELL_ERROR,
-					"if_index value is out of bounds. Range is (1-255)\n");
-			return -ENOEXEC;
+		if (mode_info.if_index == 0) {
+			mode_info.if_index = net_if_get_by_iface(iface);
+		} else {
+			iface = net_if_get_by_index(mode_info.if_index);
+			if (iface == NULL) {
+				shell_fprintf(sh, SHELL_ERROR,
+					      "Cannot find interface for if_index %d\n", mode_info.if_index);
+				return -ENOEXEC;
+			}
 		}
 
 		ret = net_mgmt(NET_REQUEST_WIFI_MODE, iface, &mode_info, sizeof(mode_info));
@@ -1370,7 +1374,7 @@ void parse_channel_args_to_params(const struct shell *sh, int argc,
 	int opt;
 	int option_index = 0;
 
-	static struct option long_options[] = {{"if_index", required_argument, 0, 'i'},
+	static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'},
 					       {"channel", required_argument, 0, 'c'},
 					       {"get", no_argument, 0, 'g'},
 					       {"help", no_argument, 0, 'h'},
@@ -1421,11 +1425,15 @@ static int cmd_wifi_channel(const struct shell *sh, size_t argc, char *argv[])
 		 * the lower layer.
 		 */
 
-		if ((channel_info.if_index < WIFI_INTERFACE_INDEX_MIN) ||
-		    (channel_info.if_index > WIFI_INTERFACE_INDEX_MAX)) {
-			shell_fprintf(sh, SHELL_ERROR,
-					"if_index value is out of bounds. Range is (1-255)\n");
-			return -ENOEXEC;
+		if (channel_info.if_index == 0) {
+			channel_info.if_index = net_if_get_by_iface(iface);
+		} else {
+			iface = net_if_get_by_index(channel_info.if_index);
+			if (iface == NULL) {
+				shell_fprintf(sh, SHELL_ERROR,
+					      "Cannot find interface for if_index %d\n", channel_info.if_index);
+				return -ENOEXEC;
+			}
 		}
 
 		if (channel_info.oper == WIFI_MGMT_SET) {
@@ -1465,7 +1473,7 @@ void parse_filter_args_to_params(const struct shell *sh, int argc,
 	int opt;
 	int option_index = 0;
 
-	static struct option long_options[] = {{"if_index", required_argument, 0, 'i'},
+	static struct option long_options[] = {{"if_index", optional_argument, 0, 'i'},
 					       {"capture_len", required_argument, 0, 'b'},
 					       {"all", no_argument, 0, 'a'},
 					       {"mgmt", no_argument, 0, 'm'},
@@ -1533,11 +1541,15 @@ static int cmd_wifi_packet_filter(const struct shell *sh, size_t argc, char *arg
 		 * value to be verified by the lower layer.
 		 */
 
-		if ((packet_filter.if_index < WIFI_INTERFACE_INDEX_MIN) ||
-		    (packet_filter.if_index > WIFI_INTERFACE_INDEX_MAX)) {
-			shell_fprintf(sh, SHELL_ERROR,
-					"if_index value is out of bounds. Range is (1-255)\n");
-			return -ENOEXEC;
+		if (packet_filter.if_index == 0) {
+			packet_filter.if_index = net_if_get_by_iface(iface);
+		} else {
+			iface = net_if_get_by_index(packet_filter.if_index);
+			if (iface == NULL) {
+				shell_fprintf(sh, SHELL_ERROR,
+					      "Cannot find interface for if_index %d\n", packet_filter.if_index);
+				return -ENOEXEC;
+			}
 		}
 
 		ret = net_mgmt(NET_REQUEST_WIFI_PACKET_FILTER, iface,

I did not test the diff so it might not fully work yet. Bonus point if done like this is that we do not need to give the interface index if there is only one wifi network interface in the system.

changed the parameter to optional

Copy link
Member

@jukkar jukkar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, minor nit about setting the iface variable value

subsys/net/l2/wifi/wifi_shell.c Outdated Show resolved Hide resolved
subsys/net/l2/wifi/wifi_shell.c Outdated Show resolved Hide resolved
subsys/net/l2/wifi/wifi_shell.c Outdated Show resolved Hide resolved
This change brings in support for setting various Wi-Fi modes and
enables a specific Wi-Fi interface to be also placed into a sniffer
operation via monitor mode and promiscuous mode. A raw TX- packet
Injection mode is also introduced

Signed-off-by: Vivekananda Uppunda <vivekananda.uppunda@nordicsemi.no>
@carlescufi carlescufi merged commit 450dbb1 into zephyrproject-rtos:main Sep 13, 2023
18 checks passed
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @VivekUppunda!
Congratulations on getting your very first Zephyr pull request merged 🎉🥳. This is a fantastic achievement, and we're thrilled to have you as part of our community!

To celebrate this milestone and showcase your contribution, we'd love to award you the Zephyr Technical Contributor badge. If you're interested, please claim your badge by filling out this form: Claim Your Zephyr Badge.

Thank you for your valuable input, and we look forward to seeing more of your contributions in the future! 🪁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants