├── Makefile
├── QT_dhcpd.conf
├── README.md
├── ap_reset_config.conf
├── build_deb.sh
├── eloop.c
├── eloop.h
├── hs2_profile.h
├── indigo_api.c
├── indigo_api.h
├── indigo_api_callback.h
├── indigo_api_callback_dut.c
├── indigo_api_callback_sniffer.c
├── indigo_api_callback_tp.c
├── indigo_packet.c
├── indigo_packet.h
├── main.c
├── openwrt-controlappc-dut-makefile
├── openwrt-controlappc-tp-makefile
├── package.controlappc-dut.Makefile
├── package.controlappc-tp.Makefile
├── patch_nwmgr.sh
├── sta_reset_config.conf
├── test.py
├── utils.c
├── utils.h
├── vendor_specific.h
├── vendor_specific_dut.c
├── vendor_specific_sniffer.c
├── vendor_specific_tp.c
├── wpa_ctrl.c
└── wpa_ctrl.h
/Makefile:
--------------------------------------------------------------------------------
1 | # Type is laptop or openwrt
2 | TYPE = laptop
3 | # Role is dut or platform or sniffer
4 | ROLE = dut
5 | # Package Version
6 | VERSION = "2.3.0.238"
7 |
8 | OBJS = main.o eloop.o indigo_api.o indigo_packet.o utils.o wpa_ctrl.o
9 | CFLAGS += -g
10 |
11 | ifeq ($(TYPE),laptop)
12 | CC = gcc
13 | CFLAGS += -D_LAPTOP_
14 |
15 | else
16 | # upstream OPENWRT
17 | # 32 bit
18 | #CC = /openwrt/QCA_Sniffer_11ax/qsdk/staging_dir/toolchain-arm_cortex-a7_gcc-5.2.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-gcc
19 | #LD = /openwrt/QCA_Sniffer_11ax/qsdk/staging_dir/toolchain-arm_cortex-a7_gcc-5.2.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-ld
20 | # 64 bit
21 | #CC = /openwrt/11305r3/qsdk/staging_dir/toolchain-aarch64_cortex-a53_gcc-5.2.0_musl-1.1.16/bin/aarch64-openwrt-linux-gcc
22 | #LD = /openwrt/11305r3/qsdk/staging_dir/toolchain-aarch64_cortex-a53_gcc-5.2.0_musl-1.1.16/bin/aarch64-openwrt-linux-ld
23 | # Wi-Fi 7
24 | CC = /openwrt/qsdk/staging_dir/toolchain-aarch64/bin/aarch64-openwrt-linux-musl-gcc
25 | LD = /openwrt/qsdk/staging_dir/toolchain-aarch64/bin/aarch64-openwrt-linux-ld
26 | # _OPENWRT_: Use OPENWRT
27 | CFLAGS += -D_OPENWRT_
28 | CFLAGS += -DHOSTAPD_SUPPORT_MBSSID_WAR
29 | endif
30 |
31 | # Define the app is for DUT or platform
32 | ifeq ($(ROLE),dut)
33 | OBJS += indigo_api_callback_dut.o vendor_specific_dut.o
34 | CFLAGS += -D_DUT_
35 | else ifeq ($(ROLE), sniffer)
36 | OBJS += indigo_api_callback_sniffer.o vendor_specific_sniffer.o
37 | CFLAGS += -D_TEST_SNIFFER_
38 | else
39 | OBJS += indigo_api_callback_tp.o vendor_specific_tp.o
40 | CFLAGS += -DCONFIG_CTRL_IFACE_UDP
41 | CFLAGS += -D_TEST_PLATFORM_
42 | endif
43 |
44 | # Define the package version
45 | ifneq ($(VERSION),)
46 | CFLAGS += -D_VERSION_='$(VERSION)'
47 | endif
48 |
49 | all: app
50 |
51 | %.o: %.c
52 | $(CC) $(CFLAGS) -c -o $@ $<
53 |
54 | app: $(OBJS)
55 | $(CC) $(CFLAGS) -o $@ $^
56 |
57 | clean:
58 | rm -rf app *.o
59 |
--------------------------------------------------------------------------------
/QT_dhcpd.conf:
--------------------------------------------------------------------------------
1 | # dhcpd.conf
2 | #
3 | # Sample configuration file for ISC dhcpd
4 | #
5 | # Attention: If /etc/ltsp/dhcpd.conf exists, that will be used as
6 | # configuration file instead of this file.
7 | #
8 |
9 | # option definitions common to all supported networks...
10 | option domain-name "example.org";
11 | option domain-name-servers ns1.example.org, ns2.example.org;
12 |
13 | default-lease-time 600;
14 | max-lease-time 7200;
15 |
16 | # The ddns-updates-style parameter controls whether or not the server will
17 | # attempt to do a DNS update when a lease is confirmed. We default to the
18 | # behavior of the version 2 packages ('none', since DHCP v2 didn't
19 | # have support for DDNS.)
20 | ddns-update-style none;
21 |
22 | # If this DHCP server is the official DHCP server for the local
23 | # network, the authoritative directive should be uncommented.
24 | #authoritative;
25 |
26 | # Use this to send dhcp log messages to a different log file (you also
27 | # have to hack syslog.conf to complete the redirection).
28 | #log-facility local7;
29 |
30 | # No service will be given on this subnet, but declaring it helps the
31 | # DHCP server to understand the network topology.
32 |
33 | # This is a very basic subnet declaration.
34 |
35 | #subnet 10.254.239.0 netmask 255.255.255.224 {
36 | # range 10.254.239.10 10.254.239.20;
37 | # option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
38 | #}
39 |
40 | # This declaration allows BOOTP clients to get dynamic addresses,
41 | # which we don't really recommend.
42 |
43 | #subnet 10.254.239.32 netmask 255.255.255.224 {
44 | # range dynamic-bootp 10.254.239.40 10.254.239.60;
45 | # option broadcast-address 10.254.239.31;
46 | # option routers rtr-239-32-1.example.org;
47 | #}
48 |
49 | # A slightly different configuration for an internal subnet.
50 | #subnet 10.5.5.0 netmask 255.255.255.224 {
51 | # range 10.5.5.26 10.5.5.30;
52 | # option domain-name-servers ns1.internal.example.org;
53 | # option domain-name "internal.example.org";
54 | # option subnet-mask 255.255.255.224;
55 | # option routers 10.5.5.1;
56 | # option broadcast-address 10.5.5.31;
57 | # default-lease-time 600;
58 | # max-lease-time 7200;
59 | #}
60 |
61 | # Hosts which require special configuration options can be listed in
62 | # host statements. If no address is specified, the address will be
63 | # allocated dynamically (if possible), but the host-specific information
64 | # will still come from the host declaration.
65 |
66 | #host passacaglia {
67 | # hardware ethernet 0:0:c0:5d:bd:95;
68 | # filename "vmunix.passacaglia";
69 | # server-name "toccata.example.com";
70 | #}
71 |
72 | # Fixed IP addresses can also be specified for hosts. These addresses
73 | # should not also be listed as being available for dynamic assignment.
74 | # Hosts for which fixed IP addresses have been specified can boot using
75 | # BOOTP or DHCP. Hosts for which no fixed address is specified can only
76 | # be booted with DHCP, unless there is an address range on the subnet
77 | # to which a BOOTP client is connected which has the dynamic-bootp flag
78 | # set.
79 | #host fantasia {
80 | # hardware ethernet 08:00:07:26:c0:a5;
81 | # fixed-address fantasia.example.com;
82 | #}
83 |
84 | # You can declare a class of clients and then do address allocation
85 | # based on that. The example below shows a case where all clients
86 | # in a certain class get addresses on the 10.17.224/24 subnet, and all
87 | # other clients get addresses on the 10.0.29/24 subnet.
88 |
89 | #class "foo" {
90 | # match if substring (option vendor-class-identifier, 0, 4) = "SUNW";
91 | #}
92 |
93 | #shared-network 224-29 {
94 | # subnet 10.17.224.0 netmask 255.255.255.0 {
95 | # option routers rtr-224.example.org;
96 | # }
97 | # subnet 10.0.29.0 netmask 255.255.255.0 {
98 | # option routers rtr-29.example.org;
99 | # }
100 | # pool {
101 | # allow members of "foo";
102 | # range 10.17.224.10 10.17.224.250;
103 | # }
104 | # pool {
105 | # deny members of "foo";
106 | # range 10.0.29.10 10.0.29.230;
107 | # }
108 | #}
109 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | QuickTrack Control App
2 | ------------------------------------------------------------------------
3 |
4 | /* Copyright (c) 2020 Wi-Fi Alliance */
5 |
6 | /* Permission to use, copy, modify, and/or distribute this software for any */
7 | /* purpose with or without fee is hereby granted, provided that the above */
8 | /* copyright notice and this permission notice appear in all copies. */
9 |
10 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
11 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
12 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
13 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
14 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
15 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
16 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
17 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
18 | /* SOFTWARE. */
19 |
20 | ------------------------------------------------------------------------
21 | Build & Run
22 | ------------------------------------------------------------------------
23 | make clean ; make
24 | sudo ./app -p <port>
25 |
26 |
--------------------------------------------------------------------------------
/ap_reset_config.conf:
--------------------------------------------------------------------------------
1 | ctrl_interface=/var/run/hostapd
2 | ctrl_interface_group=0
3 | interface=wlan0
4 | ssid=QuickTrack
5 | channel=36
6 | hw_mode=a
7 | wpa_passphrase=12345678
8 | ieee80211n=1
9 | wpa=2
10 | wpa_key_mgmt=WPA-PSK
11 | rsn_pairwise=CCMP
12 |
--------------------------------------------------------------------------------
/build_deb.sh:
--------------------------------------------------------------------------------
1 | #!bin/bash
2 |
3 | package_name="WFA-QuickTrack-ControlAppC"
4 | version=""
5 | git_revision=""
6 | deb_name=${package_name}.deb
7 | control_file=${package_name}/DEBIAN/control
8 | postinst_file=${package_name}/DEBIAN/postinst
9 | prerm_file=${package_name}/DEBIAN/prerm
10 | postrm_file=${package_name}/DEBIAN/postrm
11 | source_folder=${package_name}/usr/local/bin/${package_name}/source
12 | installed_source_folder=/usr/local/bin/${package_name}/source
13 |
14 | create_source_folder() {
15 | rm -rf ${package_name}
16 | mkdir -p ${package_name}/DEBIAN
17 | mkdir -p ${source_folder}
18 | }
19 |
20 | copy_filter_source() {
21 | cp -rf *.c *.h Makefile ${source_folder}
22 | cp -rf patch_nwmgr.sh ${source_folder}
23 | cp -rf QT_dhcpd.conf ${source_folder}
24 | }
25 |
26 | create_control() {
27 | echo "Package: ${package_name}" >"$control_file"
28 | echo "Version: ${version}-${revision}" >>"$control_file"
29 | echo "Architecture: all" >>"$control_file"
30 | echo "Depends: build-essential, arping, isc-dhcp-server, iw" >>"$control_file"
31 | echo "Essential: no" >>"$control_file"
32 | echo "Conflicts: wfa-indigo-controlappc" >>"$control_file"
33 | echo "Priority: optional" >>"$control_file"
34 | echo "Maintainer: Wi-Fi Alliance" >>"$control_file"
35 | echo "Description: This Software is to control the DUT and test platform" >>"$control_file"
36 | echo "" >>"$control_file"
37 | }
38 |
39 | create_postinst() {
40 | echo "#!/bin/bash" >"$postinst_file"
41 | echo "echo \"Start the installation and compile the source code.\"" >>"$postinst_file"
42 | echo "cd ${installed_source_folder}" >>"$postinst_file"
43 | echo "sed -i 's/VERSION = /VERSION = \"${version}\"#VERSION = /' Makefile" >>"$postinst_file"
44 | echo "make clean >/dev/null" >>"$postinst_file"
45 | echo "make >/dev/null" >>"$postinst_file"
46 | echo "cp app ../app_dut" >>"$postinst_file"
47 | echo "make clean >/dev/null" >>"$postinst_file"
48 |
49 | echo "sed -i 's/ROLE = dut/ROLE = tp/' Makefile" >>"$postinst_file"
50 | echo "make >/dev/null" >>"$postinst_file"
51 | echo "cp app ../app_tp" >>"$postinst_file"
52 | echo "make clean >/dev/null" >>"$postinst_file"
53 |
54 | echo "sed -i 's/ROLE = tp/ROLE = sniffer/' Makefile" >>"$postinst_file"
55 | echo "make >/dev/null" >>"$postinst_file"
56 | echo "cp app ../app_sniffer" >>"$postinst_file"
57 | echo "make clean >/dev/null" >>"$postinst_file"
58 |
59 | echo "cp QT_dhcpd.conf ../QT_dhcpd.conf" >>"$postinst_file"
60 |
61 | echo "echo \"Test application version\"" >>"$postinst_file"
62 | echo "../app_dut -v" >>"$postinst_file"
63 | echo "../app_tp -v" >>"$postinst_file"
64 | echo "echo \"Complete the installation. If you would like to modify the source code for the platform-specific change, you can go to ${installed_source_folder}\"" >>"$postinst_file"
65 | echo "echo \"\"" >>"$postinst_file"
66 | echo "echo \"Start to patch NetworkManager to unmanage the wl* interface.\"" >>"$postinst_file"
67 | echo "/bin/bash ${installed_source_folder}/patch_nwmgr.sh bkup" >>"$postinst_file"
68 | chmod 755 "$postinst_file"
69 | }
70 |
71 | create_prerm() {
72 | echo "#!/bin/bash" >"$prerm_file"
73 | echo "sudo killall app_dut >/dev/null 2>/dev/null" >>"$prerm_file"
74 | echo "sudo killall app_tp >/dev/null 2>/dev/null" >>"$prerm_file"
75 | echo "sleep 3" >>"$prerm_file"
76 |
77 | echo "if [ -d \"/usr/local/bin/WFA-QuickTrack-ControlAppC/source\" ]" >>"$prerm_file"
78 | echo "then" >>"$prerm_file"
79 | echo "cd ${installed_source_folder}" >>"$prerm_file"
80 | echo "rm -rf /usr/local/bin/${package_name}/app_dut" >>"$prerm_file"
81 | echo "rm -rf /usr/local/bin/${package_name}/app_tp" >>"$prerm_file"
82 | echo "/bin/bash ${installed_source_folder}/patch_nwmgr.sh restore" >>"$prerm_file"
83 | echo "rm -rf /usr/local/bin/${package_name}/QT_dhcpd.conf" >>"$prerm_file"
84 | echo "fi" >>"$prerm_file"
85 |
86 | chmod 755 "$prerm_file"
87 | }
88 |
89 | create_deb() {
90 | dpkg -b ${package_name} >/dev/null
91 | }
92 |
93 | if [ -z "$1" ]
94 | then
95 | echo "Please specify the version. E.g., 1.0.10"
96 | exit
97 | else
98 | version="$1"
99 | revision=`git rev-parse --short HEAD`
100 | fi
101 | create_source_folder
102 | create_control
103 | copy_filter_source
104 | create_postinst
105 | create_prerm
106 | create_deb
107 |
108 | echo "Complete. Please reference to the following usage."
109 | echo "1. Please remove the package by \"sudo apt remove wfa-quicktrack-controlappc\""
110 | echo "2. Please install the package by \"sudo apt install ./WFA-QuickTrack-ControlAppC.deb\""
111 |
--------------------------------------------------------------------------------
/eloop.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Event loop based on select() loop
3 | * Copyright (c) 2002-2005, Jouni Malinen
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License version 2 as
7 | * published by the Free Software Foundation.
8 | *
9 | * Alternatively, this software may be distributed under the terms of BSD
10 | * license.
11 | *
12 | * See README and COPYING for more details.
13 | */
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #ifdef CONFIG_NATIVE_WINDOWS
25 | #include "common.h"
26 | #endif /* CONFIG_NATIVE_WINDOWS */
27 |
28 | #include "eloop.h"
29 |
30 | void vendor_deinit();
31 |
32 | struct eloop_sock {
33 | int sock;
34 | void *eloop_data;
35 | void *user_data;
36 | void (*handler)(int sock, void *eloop_ctx, void *sock_ctx);
37 | };
38 |
39 | struct eloop_timeout {
40 | struct timeval time;
41 | void *eloop_data;
42 | void *user_data;
43 | void (*handler)(void *eloop_ctx, void *sock_ctx);
44 | struct eloop_timeout *next;
45 | };
46 |
47 | struct eloop_signal {
48 | int sig;
49 | void *user_data;
50 | void (*handler)(int sig, void *eloop_ctx, void *signal_ctx);
51 | int signaled;
52 | };
53 |
54 | struct eloop_data {
55 | void *user_data;
56 |
57 | int max_sock, reader_count;
58 | struct eloop_sock *readers;
59 |
60 | struct eloop_timeout *timeout;
61 |
62 | int signal_count;
63 | struct eloop_signal *signals;
64 | int signaled;
65 | int pending_terminate;
66 |
67 | int terminate;
68 | };
69 |
70 | static struct eloop_data eloop;
71 |
72 |
73 | void eloop_init(void *user_data)
74 | {
75 | memset(&eloop, 0, sizeof(eloop));
76 | eloop.user_data = user_data;
77 | }
78 |
79 |
80 | int eloop_register_read_sock(int sock,
81 | void (*handler)(int sock, void *eloop_ctx,
82 | void *sock_ctx),
83 | void *eloop_data, void *user_data)
84 | {
85 | struct eloop_sock *tmp;
86 |
87 | tmp = (struct eloop_sock *)
88 | realloc(eloop.readers,
89 | (eloop.reader_count + 1) * sizeof(struct eloop_sock));
90 | if (tmp == NULL)
91 | return -1;
92 |
93 | tmp[eloop.reader_count].sock = sock;
94 | tmp[eloop.reader_count].eloop_data = eloop_data;
95 | tmp[eloop.reader_count].user_data = user_data;
96 | tmp[eloop.reader_count].handler = handler;
97 | eloop.reader_count++;
98 | eloop.readers = tmp;
99 | if (sock > eloop.max_sock)
100 | eloop.max_sock = sock;
101 |
102 | return 0;
103 | }
104 |
105 |
106 | void eloop_unregister_read_sock(int sock)
107 | {
108 | int i;
109 |
110 | if (eloop.readers == NULL || eloop.reader_count == 0)
111 | return;
112 |
113 | for (i = 0; i < eloop.reader_count; i++) {
114 | if (eloop.readers[i].sock == sock)
115 | break;
116 | }
117 | if (i == eloop.reader_count)
118 | return;
119 | if (i != eloop.reader_count - 1) {
120 | memmove(&eloop.readers[i], &eloop.readers[i + 1],
121 | (eloop.reader_count - i - 1) *
122 | sizeof(struct eloop_sock));
123 | }
124 | eloop.reader_count--;
125 | }
126 |
127 |
128 | int eloop_register_timeout(unsigned int secs, unsigned int usecs,
129 | void (*handler)(void *eloop_ctx, void *timeout_ctx),
130 | void *eloop_data, void *user_data)
131 | {
132 | struct eloop_timeout *timeout, *tmp, *prev;
133 |
134 | timeout = (struct eloop_timeout *) malloc(sizeof(*timeout));
135 | if (timeout == NULL)
136 | return -1;
137 | gettimeofday(&timeout->time, NULL);
138 | timeout->time.tv_sec += secs;
139 | timeout->time.tv_usec += usecs;
140 | while (timeout->time.tv_usec >= 1000000) {
141 | timeout->time.tv_sec++;
142 | timeout->time.tv_usec -= 1000000;
143 | }
144 | timeout->eloop_data = eloop_data;
145 | timeout->user_data = user_data;
146 | timeout->handler = handler;
147 | timeout->next = NULL;
148 |
149 | if (eloop.timeout == NULL) {
150 | eloop.timeout = timeout;
151 | return 0;
152 | }
153 |
154 | prev = NULL;
155 | tmp = eloop.timeout;
156 | while (tmp != NULL) {
157 | if (timercmp(&timeout->time, &tmp->time, <))
158 | break;
159 | prev = tmp;
160 | tmp = tmp->next;
161 | }
162 |
163 | if (prev == NULL) {
164 | timeout->next = eloop.timeout;
165 | eloop.timeout = timeout;
166 | } else {
167 | timeout->next = prev->next;
168 | prev->next = timeout;
169 | }
170 |
171 | return 0;
172 | }
173 |
174 |
175 | int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
176 | void *eloop_data, void *user_data)
177 | {
178 | struct eloop_timeout *timeout, *prev, *next;
179 | int removed = 0;
180 |
181 | prev = NULL;
182 | timeout = eloop.timeout;
183 | while (timeout != NULL) {
184 | next = timeout->next;
185 |
186 | if (timeout->handler == handler &&
187 | (timeout->eloop_data == eloop_data ||
188 | eloop_data == ELOOP_ALL_CTX) &&
189 | (timeout->user_data == user_data ||
190 | user_data == ELOOP_ALL_CTX)) {
191 | if (prev == NULL)
192 | eloop.timeout = next;
193 | else
194 | prev->next = next;
195 | free(timeout);
196 | removed++;
197 | } else
198 | prev = timeout;
199 |
200 | timeout = next;
201 | }
202 |
203 | return removed;
204 | }
205 |
206 |
207 | #ifndef CONFIG_NATIVE_WINDOWS
208 | static void eloop_handle_alarm(int sig)
209 | {
210 | fprintf(stderr, "eloop: could not process SIGINT or SIGTERM in two "
211 | "seconds. Looks like there\n"
212 | "is a bug that ends up in a busy loop that "
213 | "prevents clean shutdown.\n"
214 | "Killing program forcefully.\n");
215 | vendor_deinit();
216 | exit(1);
217 | }
218 | #endif /* CONFIG_NATIVE_WINDOWS */
219 |
220 |
221 | static void eloop_handle_signal(int sig)
222 | {
223 | int i;
224 |
225 | #ifndef CONFIG_NATIVE_WINDOWS
226 | if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
227 | /* Use SIGALRM to break out from potential busy loops that
228 | * would not allow the program to be killed. */
229 | eloop.pending_terminate = 1;
230 | signal(SIGALRM, eloop_handle_alarm);
231 | alarm(2);
232 | }
233 | #endif /* CONFIG_NATIVE_WINDOWS */
234 |
235 | eloop.signaled++;
236 | for (i = 0; i < eloop.signal_count; i++) {
237 | if (eloop.signals[i].sig == sig) {
238 | eloop.signals[i].signaled++;
239 | break;
240 | }
241 | }
242 | }
243 |
244 |
245 | static void eloop_process_pending_signals(void)
246 | {
247 | int i;
248 |
249 | if (eloop.signaled == 0)
250 | return;
251 | eloop.signaled = 0;
252 |
253 | if (eloop.pending_terminate) {
254 | #ifndef CONFIG_NATIVE_WINDOWS
255 | alarm(0);
256 | #endif /* CONFIG_NATIVE_WINDOWS */
257 | eloop.pending_terminate = 0;
258 | }
259 |
260 | for (i = 0; i < eloop.signal_count; i++) {
261 | if (eloop.signals[i].signaled) {
262 | eloop.signals[i].signaled = 0;
263 | eloop.signals[i].handler(eloop.signals[i].sig,
264 | eloop.user_data,
265 | eloop.signals[i].user_data);
266 | }
267 | }
268 | }
269 |
270 |
271 | int eloop_register_signal(int sig,
272 | void (*handler)(int sig, void *eloop_ctx,
273 | void *signal_ctx),
274 | void *user_data)
275 | {
276 | struct eloop_signal *tmp;
277 |
278 | tmp = (struct eloop_signal *)
279 | realloc(eloop.signals,
280 | (eloop.signal_count + 1) *
281 | sizeof(struct eloop_signal));
282 | if (tmp == NULL)
283 | return -1;
284 |
285 | tmp[eloop.signal_count].sig = sig;
286 | tmp[eloop.signal_count].user_data = user_data;
287 | tmp[eloop.signal_count].handler = handler;
288 | tmp[eloop.signal_count].signaled = 0;
289 | eloop.signal_count++;
290 | eloop.signals = tmp;
291 | signal(sig, eloop_handle_signal);
292 |
293 | return 0;
294 | }
295 |
296 |
297 | void eloop_run(void)
298 | {
299 | fd_set *rfds;
300 | int i, res;
301 | struct timeval tv, now;
302 |
303 | rfds = malloc(sizeof(*rfds));
304 | if (rfds == NULL) {
305 | printf("eloop_run - malloc failed\n");
306 | return;
307 | }
308 |
309 | while (!eloop.terminate &&
310 | (eloop.timeout || eloop.reader_count > 0)) {
311 | if (eloop.timeout) {
312 | gettimeofday(&now, NULL);
313 | if (timercmp(&now, &eloop.timeout->time, <))
314 | timersub(&eloop.timeout->time, &now, &tv);
315 | else
316 | tv.tv_sec = tv.tv_usec = 0;
317 | #if 0
318 | printf("next timeout in %lu.%06lu sec\n",
319 | tv.tv_sec, tv.tv_usec);
320 | #endif
321 | }
322 |
323 | FD_ZERO(rfds);
324 | for (i = 0; i < eloop.reader_count; i++)
325 | FD_SET(eloop.readers[i].sock, rfds);
326 | res = select(eloop.max_sock + 1, rfds, NULL, NULL,
327 | eloop.timeout ? &tv : NULL);
328 | if (res < 0 && errno != EINTR) {
329 | perror("select");
330 | free(rfds);
331 | return;
332 | }
333 | eloop_process_pending_signals();
334 |
335 | /* check if some registered timeouts have occurred */
336 | if (eloop.timeout) {
337 | struct eloop_timeout *tmp;
338 |
339 | gettimeofday(&now, NULL);
340 | if (!timercmp(&now, &eloop.timeout->time, <)) {
341 | tmp = eloop.timeout;
342 | eloop.timeout = eloop.timeout->next;
343 | tmp->handler(tmp->eloop_data,
344 | tmp->user_data);
345 | free(tmp);
346 | }
347 |
348 | }
349 |
350 | if (res <= 0)
351 | continue;
352 |
353 | for (i = 0; i < eloop.reader_count; i++) {
354 | if (FD_ISSET(eloop.readers[i].sock, rfds)) {
355 | eloop.readers[i].handler(
356 | eloop.readers[i].sock,
357 | eloop.readers[i].eloop_data,
358 | eloop.readers[i].user_data);
359 | }
360 | }
361 | }
362 |
363 | free(rfds);
364 | }
365 |
366 |
367 | void eloop_terminate(void)
368 | {
369 | eloop.terminate = 1;
370 | }
371 |
372 |
373 | void eloop_destroy(void)
374 | {
375 | struct eloop_timeout *timeout, *prev;
376 |
377 | timeout = eloop.timeout;
378 | while (timeout != NULL) {
379 | prev = timeout;
380 | timeout = timeout->next;
381 | free(prev);
382 | }
383 | free(eloop.readers);
384 | free(eloop.signals);
385 | }
386 |
387 |
388 | int eloop_terminated(void)
389 | {
390 | return eloop.terminate;
391 | }
392 |
--------------------------------------------------------------------------------
/eloop.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Event loop
3 | * Copyright (c) 2002-2005, Jouni Malinen
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License version 2 as
7 | * published by the Free Software Foundation.
8 | *
9 | * Alternatively, this software may be distributed under the terms of BSD
10 | * license.
11 | *
12 | * See README and COPYING for more details.
13 | *
14 | * This file defines an event loop interface that supports processing events
15 | * from registered timeouts (i.e., do something after N seconds), sockets
16 | * (e.g., a new packet available for reading), and signals. eloop.c is an
17 | * implementation of this interface using select() and sockets. This is
18 | * suitable for most UNIX/POSIX systems. When porting to other operating
19 | * systems, it may be necessary to replace that implementation with OS specific
20 | * mechanisms.
21 | */
22 |
23 | #ifndef ELOOP_H
24 | #define ELOOP_H
25 |
26 | /* Magic number for eloop_cancel_timeout() */
27 | #define ELOOP_ALL_CTX (void *) -1
28 |
29 | /**
30 | * eloop_init() - Initialize global event loop data
31 | * @user_data: Pointer to global data passed as eloop_ctx to signal handlers
32 | *
33 | * This function must be called before any other eloop_* function. user_data
34 | * can be used to configure a global (to the process) pointer that will be
35 | * passed as eloop_ctx parameter to signal handlers.
36 | */
37 | void eloop_init(void *user_data);
38 |
39 | /**
40 | * eloop_register_read_sock - Register handler for read events
41 | * @sock: File descriptor number for the socket
42 | * @handler: Callback function to be called when data is available for reading
43 | * @eloop_data: Callback context data (eloop_ctx)
44 | * @user_data: Callback context data (sock_ctx)
45 | * Returns: 0 on success, -1 on failure
46 | *
47 | * Register a read socket notifier for the given file descriptor. The handler
48 | * function will be called whenever data is available for reading from the
49 | * socket.
50 | */
51 | int eloop_register_read_sock(int sock,
52 | void (*handler)(int sock, void *eloop_ctx,
53 | void *sock_ctx),
54 | void *eloop_data, void *user_data);
55 |
56 | /**
57 | * eloop_unregister_read_sock - Unregister handler for read events
58 | * @sock: File descriptor number for the socket
59 | *
60 | * Unregister a read socket notifier that was previously registered with
61 | * eloop_register_read_sock().
62 | */
63 | void eloop_unregister_read_sock(int sock);
64 |
65 | /**
66 | * eloop_register_timeout - Register timeout
67 | * @secs: Number of seconds to the timeout
68 | * @usecs: Number of microseconds to the timeout
69 | * @handler: Callback function to be called when timeout occurs
70 | * @eloop_data: Callback context data (eloop_ctx)
71 | * @user_data: Callback context data (sock_ctx)
72 | * Returns: 0 on success, -1 on failure
73 | *
74 | * Register a timeout that will cause the handler function to be called after
75 | * given time.
76 | */
77 | int eloop_register_timeout(unsigned int secs, unsigned int usecs,
78 | void (*handler)(void *eloop_ctx, void *timeout_ctx),
79 | void *eloop_data, void *user_data);
80 |
81 | /**
82 | * eloop_cancel_timeout - Cancel timeouts
83 | * @handler: Matching callback function
84 | * @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all
85 | * @user_data: Matching user_data or %ELOOP_ALL_CTX to match all
86 | * Returns: Number of cancelled timeouts
87 | *
88 | * Cancel matching timeouts registered with
89 | * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for
90 | * cancelling all timeouts regardless of eloop_data/user_data.
91 | */
92 | int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
93 | void *eloop_data, void *user_data);
94 |
95 | /**
96 | * eloop_register_signal - Register handler for signals
97 | * @sig: Signal number (e.g., SIGHUP)
98 | * @handler: Callback function to be called when the signal is received
99 | * @user_data: Callback context data (signal_ctx)
100 | * Returns: 0 on success, -1 on failure
101 | *
102 | * Register a callback function that will be called when a signal is received.
103 | * The calback function is actually called only after the system signal handler
104 | * has returned. This means that the normal limits for sighandlers (i.e., only
105 | * "safe functions" allowed) do not apply for the registered callback.
106 | *
107 | * Signals are 'global' events and there is no local eloop_data pointer like
108 | * with other handlers. The global user_data pointer registered with
109 | * eloop_init() will be used as eloop_ctx for signal handlers.
110 | */
111 | int eloop_register_signal(int sig,
112 | void (*handler)(int sig, void *eloop_ctx,
113 | void *signal_ctx),
114 | void *user_data);
115 |
116 | /**
117 | * eloop_run - Start the event loop
118 | *
119 | * Start the event loop and continue running as long as there are any
120 | * registered event handlers. This function is run after event loop has been
121 | * initialized with event_init() and one or more events have been registered.
122 | */
123 | void eloop_run(void);
124 |
125 | /**
126 | * eloop_terminate - Terminate event loop
127 | *
128 | * Terminate event loop even if there are registered events. This can be used
129 | * to request the program to be terminated cleanly.
130 | */
131 | void eloop_terminate(void);
132 |
133 | /**
134 | * eloop_destroy - Free any resources allocated for the event loop
135 | *
136 | * After calling eloop_destoy(), other eloop_* functions must not be called
137 | * before re-running eloop_init().
138 | */
139 | void eloop_destroy(void);
140 |
141 | /**
142 | * eloop_terminated - Check whether event loop has been terminated
143 | * Returns: 1 = event loop terminate, 0 = event loop still running
144 | *
145 | * This function can be used to check whether eloop_terminate() has been called
146 | * to request termination of the event loop. This is normally used to abort
147 | * operations that may still be queued to be run when eloop_terminate() was
148 | * called.
149 | */
150 | int eloop_terminated(void);
151 |
152 | #endif /* ELOOP_H */
153 |
--------------------------------------------------------------------------------
/hs2_profile.h:
--------------------------------------------------------------------------------
1 |
2 | /* Copyright (c) 2021 Wi-Fi Alliance */
3 |
4 | /* Permission to use, copy, modify, and/or distribute this software for any */
5 | /* purpose with or without fee is hereby granted, provided that the above */
6 | /* copyright notice and this permission notice appear in all copies. */
7 |
8 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
9 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
10 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
11 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
12 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
13 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
14 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
15 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
16 | /* SOFTWARE. */
17 |
18 | #ifndef _HS2_PROFILE
19 | #define _HS2_PROFILE
20 |
21 | #define ARRAY_SIZE(x) ((sizeof x) / (sizeof *x))
22 |
23 | struct tlv_to_profile {
24 | unsigned short tlv_id;
25 | const char **profile;
26 | int size;
27 | };
28 |
29 | #define ADVICE_OF_CHARGE_1 \
30 | "bc01000000d200454e475553443c3f786d6c2076657273696f6e3d22312e30222065" \
31 | "6e636f64696e673d225554462d38223f3e3c506c616e20786d6c6e733d22687474703a2f2f77" \
32 | "77772e77692d66692e6f72672f73706563696669636174696f6e732f686f7473706f7432646f" \
33 | "74302f76312e302f616f637069223e3c4465736372697074696f6e3e57692d46692061636365" \
34 | "737320666f72203120686f75722c207768696c6520796f752077616974206174207468652067" \
35 | "6174652c2024302e39393c2f4465736372697074696f6e3e3c2f506c616e3ee3004652414341" \
36 | "443c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d38223f" \
37 | "3e3c506c616e20786d6c6e733d22687474703a2f2f7777772e77692d66692e6f72672f737065" \
38 | "63696669636174696f6e732f686f7473706f7432646f74302f76312e302f616f637069223e3c" \
39 | "4465736372697074696f6e3e416363c3a8732057692d46692070656e64616e74203120686575" \
40 | "72652c2070656e64616e742071756520766f757320617474656e64657a20c3a0206c6120706f" \
41 | "7274652c20302c393920243c2f4465736372697074696f6e3e3c2f506c616e3ea101010000c7" \
42 | "00454e475553443c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d2255" \
43 | "54462d38223f3e3c506c616e20786d6c6e733d22687474703a2f2f7777772e77692d66692e6f" \
44 | "72672f73706563696669636174696f6e732f686f7473706f7432646f74302f76312e302f616f" \
45 | "637069223e3c4465736372697074696f6e3e446f776e6c6f616420766964656f7320666f7220" \
46 | "796f757220666c696768742c2024322e393920666f7220313047423c2f446573637269707469" \
47 | "6f6e3e3c2f506c616e3ed3004652414341443c3f786d6c2076657273696f6e3d22312e302220" \
48 | "656e636f64696e673d225554462d38223f3e3c506c616e20786d6c6e733d22687474703a2f2f" \
49 | "7777772e77692d66692e6f72672f73706563696669636174696f6e732f686f7473706f743264" \
50 | "6f74302f76312e302f616f637069223e3c4465736372697074696f6e3e54c3a96cc3a9636861" \
51 | "7267657a2064657320766964c3a96f7320706f757220766f74726520766f6c2c20322c393920" \
52 | "2420706f757220313020476f3c2f4465736372697074696f6e3e3c2f506c616e3ee40003002b" \
53 | "736572766963652d70726f76696465722e636f6d3b66656465726174696f6e2e6578616d706c" \
54 | "652e636f6db400454e475553443c3f786d6c2076657273696f6e3d22312e302220656e636f64" \
55 | "696e673d225554462d38223f3e3c506c616e20786d6c6e733d22687474703a2f2f7777772e77" \
56 | "692d66692e6f72672f73706563696669636174696f6e732f686f7473706f7432646f74302f76" \
57 | "312e302f616f637069223e3c4465736372697074696f6e3e46726565207769746820796f7572" \
58 | "20737562736372697074696f6e213c2f4465736372697074696f6e3e3c2f506c616e3e"
59 |
60 | const char * nai_realm[] = {
61 | "",
62 | "nai_realm=0,mail.example.com,21[2:4][5:7]\nnai_realm=0,cisco.com,21[2:4][5:7]\nnai_realm=0,wi-fi.org,13[5:6],21[2:4][5:7]\nnai_realm=0,example.com,13[5:6]\n",
63 | "nai_realm=0,wi-fi.org,21[2:4][5:7]\n",
64 | "nai_realm=0,cisco.com,21[2:4][5:7]\nnai_realm=0,wi-fi.org,13[5:6],21[2:4][5:7]\nnai_realm=0,example.com,13[5:6]\n",
65 | "nai_realm=0,mail.example.com,13[5:6],21[2:4][5:7]\n",
66 | "nai_realm=0,wi-fi.org,21[2:4][5:7]\nnai_realm=0,ruckuswireless.com,21[2:4][5:7]\n",
67 | "nai_realm=0,wi-fi.org,21[2:4][5:7]\nnai_realm=0,mail.example.com,21[2:4][5:7]\n",
68 | "nai_realm=0,wi-fi.org,13[5:6],21[2:4][5:7]\n",
69 | };
70 |
71 | const char * oper_friendly_name[] = {
72 | "",
73 | "hs20_oper_friendly_name=eng:Wi-Fi Alliance\nhs20_oper_friendly_name=chi:Wi-Fi联盟\n",
74 | };
75 |
76 | const char * venue_name[] = {
77 | "",
78 | "venue_name=eng:Wi-Fi Alliance 3408 Garrett Drive Santa Clara, CA 950514, USA\nvenue_name=chi:Wi-Fi聯盟實驗室 三四零八 加洛路 聖克拉拉, 加利福尼亞 950514, 美國\n",
79 | "",
80 | "",
81 | };
82 |
83 | const char * network_auth_type[] = {
84 | "",
85 | "network_auth_type=00https://tandc-server.wi-fi.org\n",
86 | "network_auth_type=01\n",
87 | };
88 |
89 | const char * ipaddr_type_avail[] = {
90 | "",
91 | "ipaddr_type_availability=0c\n",
92 | };
93 |
94 | const char * hs20_wan_metrics[] = {
95 | "",
96 | "hs20_wan_metrics=01:2500:384:0:0:10\n",
97 | "hs20_wan_metrics=01:1500:384:20:20:10\n",
98 | "hs20_wan_metrics=01:2000:1000:20:20:10\n",
99 | "hs20_wan_metrics=01:8000:1000:20:20:10\n",
100 | "hs20_wan_metrics=01:9000:5000:20:20:10\n",
101 | };
102 |
103 | const char * hs20_conn_capab[] = {
104 | "",
105 | "hs20_conn_capab=6:20:1\nhs20_conn_capab=6:80:1\nhs20_conn_capab=6:443:1\nhs20_conn_capab=17:500:1\nhs20_conn_capab=50:0:1\n",
106 | "",
107 | "hs20_conn_capab=6:80:1\nhs20_conn_capab=6:443:1\n",
108 | "hs20_conn_capab=6:80:1\nhs20_conn_capab=6:443:1\nhs20_conn_capab=6:5060:1\nhs20_conn_capab=17:5060:1\n",
109 | "",
110 | };
111 |
112 | const char * operating_class_indication[] = {
113 | "",
114 | "hs20_operating_class=51\n",
115 | "hs20_operating_class=73\n",
116 | "hs20_operating_class=5173\n",
117 | };
118 |
119 | const char * osu_providers_list[] = {
120 | "",
121 | "osu_ssid=\"OSU\"\nosu_server_uri=https://osu-server.r2-testbed.wi-fi.org/\nosu_friendly_name=eng:SP Red Test Only\nosu_friendly_name=kor:SP 빨강 테스트 전용\nosu_method_list=1\nosu_icon=icon_red_eng.png\nosu_icon=icon_red_zxx.png\nosu_service_desc=eng:Free service for test purpose\nosu_service_desc=kor:테스트 목적으로 무료 서비스\n",
122 | "",
123 | "",
124 | "",
125 | "",
126 | };
127 |
128 | const char * osu_providers_nai_list[] = {
129 | "",
130 | "osu_nai2=anonymous@hotspot.net\n",
131 | "",
132 | "",
133 | "",
134 | };
135 |
136 | const char * bss_load[] = {
137 | "",
138 | "bss_load_test=1:50:65535\n",
139 | "bss_load_test=1:200:65535\n",
140 | "bss_load_test=1:75:65535\n",
141 | };
142 |
143 | const char * venue_url[] = {
144 | "",
145 | "venue_url=1:https://venue-server.r2m-testbed.wi-fi.org/floorplans/index.html\nvenue_url=1:https://venue-server.r2m-testbed.wi-fi.org/directory/index.html\n",
146 | "",
147 | };
148 |
149 | const char * operator_icon_metadata[] = {
150 | "",
151 | "operator_icon=icon_red_eng.png\n",
152 | };
153 |
154 | const char * advice_of_charge[] = {
155 | "",
156 | "anqp_elem=278:" ADVICE_OF_CHARGE_1 "\n",
157 | };
158 |
159 | // :::::
160 | const char * hs20_icon[] = {
161 | "hs20_icon=160:76:eng:image/png:icon_red_eng.png:/overlay/passpoint/icon_red_eng.png\n",
162 | "hs20_icon=128:61:zxx:image/png:icon_red_zxx.png:/overlay/passpoint/icon_red_zxx.png\n",
163 | };
164 |
165 | struct tlv_to_profile hs2_profile[] = {
166 | { TLV_VENUE_NAME, venue_name, ARRAY_SIZE(venue_name) },
167 | { TLV_NAI_REALM, nai_realm, ARRAY_SIZE(nai_realm) },
168 | { TLV_HS20_OPERATOR_FRIENDLY_NAME, oper_friendly_name, ARRAY_SIZE(oper_friendly_name) },
169 | { TLV_NETWORK_AUTH_TYPE, network_auth_type, ARRAY_SIZE(network_auth_type) },
170 | { TLV_IPADDR_TYPE_AVAILABILITY, ipaddr_type_avail, ARRAY_SIZE(ipaddr_type_avail) },
171 | { TLV_HS20_WAN_METRICS, hs20_wan_metrics, ARRAY_SIZE(hs20_wan_metrics) },
172 | { TLV_HS20_CONN_CAPABILITY, hs20_conn_capab, ARRAY_SIZE(hs20_conn_capab) },
173 | { TLV_OSU_PROVIDERS_LIST, osu_providers_list, ARRAY_SIZE(osu_providers_list) },
174 | { TLV_OSU_PROVIDERS_NAI_LIST, osu_providers_nai_list, ARRAY_SIZE(osu_providers_nai_list) },
175 | { TLV_VENUE_URL, venue_url, ARRAY_SIZE(venue_url) },
176 | { TLV_BSSLOAD_ENABLE, bss_load, ARRAY_SIZE(bss_load) },
177 | { TLV_OPERATOR_ICON_METADATA, operator_icon_metadata, ARRAY_SIZE(operator_icon_metadata) },
178 | { TLV_HS20_OPERATING_CLASS_INDICATION, operating_class_indication, ARRAY_SIZE(operating_class_indication) },
179 | { TLV_ADVICE_OF_CHARGE, advice_of_charge, ARRAY_SIZE(advice_of_charge) },
180 | };
181 |
182 | struct tlv_to_profile* find_tlv_hs2_profile(int tlv_id) {
183 | int i;
184 | for (i = 0; i < ARRAY_SIZE(hs2_profile); i++) {
185 | if (tlv_id == hs2_profile[i].tlv_id) {
186 | return &hs2_profile[i];
187 | }
188 | }
189 | return NULL;
190 | }
191 |
192 | void attach_hs20_icons(char * buffer) {
193 | int i;
194 | for (i = 0; i < ARRAY_SIZE(hs20_icon); i++) {
195 | strcat(buffer, hs20_icon[i]);
196 | }
197 | return;
198 | }
199 |
200 | #endif // _HS2_PROFILE
--------------------------------------------------------------------------------
/indigo_api.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include "vendor_specific.h"
22 | #include "indigo_api.h"
23 | #include "utils.h"
24 |
25 | /* Structure to initiate the API list and handlers */
26 | struct indigo_api indigo_api_list[] = {
27 | /* Common */
28 | { API_CMD_RESPONSE, "CMD_RESPONSE", NULL, NULL },
29 | { API_CMD_ACK, "CMD_ACK", NULL, NULL },
30 | /* AP specific */
31 | { API_AP_START_UP, "AP_START_UP", NULL, NULL },
32 | { API_AP_STOP, "AP_STOP", NULL, NULL },
33 | { API_AP_CONFIGURE, "AP_CONFIGURE", NULL, NULL },
34 | { API_AP_TRIGGER_CHANSWITCH, "AP_TRIGGER_CHANSWITCH", NULL, NULL },
35 | { API_AP_SEND_DISCONNECT, "AP_SEND_DISCONNECT", NULL, NULL },
36 | { API_AP_SET_PARAM, "API_AP_SET_PARAM", NULL, NULL },
37 | { API_AP_SEND_BTM_REQ, "API_AP_SEND_BTM_REQ", NULL, NULL },
38 | { API_AP_SEND_ARP_MSGS, "API_AP_SEND_ARP_MSGS", NULL, NULL },
39 | { API_AP_START_WPS, "AP_START_WPS", NULL, NULL },
40 | { API_AP_CONFIGURE_WSC, "AP_CONFIGURE_WSC", NULL, NULL },
41 | { API_AP_REKEY_GTK, "AP_REKEY_GTK", NULL, NULL },
42 | /* Station specific */
43 | { API_STA_START_UP, "STA_START_UP", NULL, NULL },
44 | { API_STA_ASSOCIATE, "STA_ASSOCIATE", NULL, NULL },
45 | { API_STA_CONFIGURE, "STA_CONFIGURE", NULL, NULL },
46 | { API_STA_DISCONNECT, "STA_DISCONNECT", NULL, NULL },
47 | { API_STA_SEND_DISCONNECT, "STA_SEND_DISCONNECT", NULL, NULL },
48 | { API_STA_REASSOCIATE, "STA_REASSOCIATE", NULL, NULL },
49 | { API_STA_SET_PARAM, "STA_SET_PARAM", NULL, NULL },
50 | { API_STA_SEND_BTM_QUERY, "STA_SEND_BTM_QUERY", NULL, NULL },
51 | { API_STA_SEND_ANQP_QUERY, "STA_SEND_ANQP_QUERY", NULL, NULL },
52 | { API_STA_SET_PHY_MODE, "STA_SET_PHY_MODE", NULL, NULL },
53 | { API_STA_SET_CHANNEL_WIDTH, "STA_SET_CHANNEL_WIDTH", NULL, NULL },
54 | { API_STA_POWER_SAVE, "STA_POWER_SAVE", NULL, NULL },
55 | { API_STA_SCAN, "STA_SCAN", NULL, NULL },
56 | { API_STA_HS2_ASSOCIATE, "API_STA_HS2_ASSOCIATE", NULL, NULL },
57 | { API_STA_INSTALL_PPSMO, "API_STA_INSTALL_PPSMO", NULL, NULL },
58 | { API_P2P_START_UP, "P2P_START_UP", NULL, NULL },
59 | { API_P2P_FIND, "P2P_FIND", NULL, NULL },
60 | { API_P2P_LISTEN, "P2P_LISTEN", NULL, NULL },
61 | { API_P2P_ADD_GROUP, "P2P_ADD_GROUP", NULL, NULL },
62 | { API_P2P_START_WPS, "P2P_START_WPS", NULL, NULL },
63 | { API_P2P_CONNECT, "P2P_CONNECT", NULL, NULL },
64 | { API_STA_ADD_CREDENTIAL, "API_STA_ADD_CREDENTIAL", NULL, NULL },
65 | { API_P2P_GET_INTENT_VALUE, "P2P_GET_INTENT_VALUE", NULL, NULL },
66 | { API_STA_START_WPS, "STA_START_WPS", NULL, NULL },
67 | { API_P2P_INVITE, "P2P_INVITE", NULL, NULL },
68 | { API_P2P_STOP_GROUP, "P2P_STOP_GROUP", NULL, NULL },
69 | { API_P2P_SET_SERV_DISC, "P2P_SET_SERV_DISC", NULL, NULL },
70 | { API_STA_SEND_ICON_REQ, "STA_SEND_ICON_REQ", NULL, NULL },
71 | { API_P2P_SET_EXT_LISTEN, "P2P_SET_EXT_LISTEN", NULL, NULL },
72 | { API_STA_ENABLE_WSC, "STA_ENABLE_WSC", NULL, NULL },
73 | { API_STA_INJECT_START, "STA_INJECT_START", NULL, NULL },
74 | { API_STA_INJECT_FRAME, "STA_INJECT_FRAME", NULL, NULL },
75 | { API_STA_INJECT_STOP, "STA_INJECT_STOP", NULL, NULL },
76 | { API_SNIFFER_START, "SNIFFER_START", NULL, NULL },
77 | { API_SNIFFER_STOP, "SNIFFER_STOP", NULL, NULL },
78 | { API_SNIFFER_UPLOAD_FILE, "SNIFFER_UPLOAD_FILE", NULL, NULL },
79 | { API_SNIFFER_FILTER, "SNIFFER_FILTER", NULL, NULL },
80 | /* Network operation. E.g., get/set IP address, get MAC address, send the UDP data and reset */
81 | { API_GET_IP_ADDR, "GET_IP_ADDR", NULL, NULL },
82 | { API_GET_MAC_ADDR, "GET_MAC_ADDR", NULL, NULL },
83 | { API_GET_CONTROL_APP_VERSION, "GET_CONTROL_APP_VERSION", NULL, NULL },
84 | { API_START_LOOP_BACK_SERVER, "START_LOOP_BACK_SERVER", NULL, NULL },
85 | { API_STOP_LOOP_BACK_SERVER, "STOP_LOOP_BACK_SERVER", NULL, NULL },
86 | { API_CREATE_NEW_INTERFACE_BRIDGE_NETWORK, "CREATE_NEW_INTERFACE_BRIDGE_NETWORK", NULL, NULL },
87 | { API_ASSIGN_STATIC_IP, "ASSIGN_STATIC_IP", NULL, NULL },
88 | { API_DEVICE_RESET, "DEVICE_RESET", NULL, NULL },
89 | { API_SEND_LOOP_BACK_DATA, "SEND_LOOP_BACK_DATA", NULL, NULL },
90 | { API_STOP_LOOP_BACK_DATA, "STOP_LOOP_BACK_DATA", NULL, NULL },
91 | { API_START_DHCP, "START_DHCP", NULL, NULL },
92 | { API_STOP_DHCP, "STOP_DHCP", NULL, NULL },
93 | { API_GET_WSC_PIN, "GET_WSC_PIN", NULL, NULL },
94 | { API_GET_WSC_CRED, "GET_WSC_CRED", NULL, NULL },
95 | };
96 |
97 | /* Structure to declare the TLV list */
98 | struct indigo_tlv indigo_tlv_list[] = {
99 | { TLV_SSID, "SSID" },
100 | { TLV_CHANNEL, "CHANNEL" },
101 | { TLV_WEP_KEY0, "WEP_KEY0" },
102 | { TLV_AUTH_ALGORITHM, "AUTH_ALGORITHM" },
103 | { TLV_WEP_DEFAULT_KEY, "WEP_DEFAULT_KEY" },
104 | { TLV_IEEE80211_D, "IEEE80211_D" },
105 | { TLV_IEEE80211_N, "IEEE80211_N" },
106 | { TLV_IEEE80211_AC, "IEEE80211_AC" },
107 | { TLV_COUNTRY_CODE, "COUNTRY_CODE" },
108 | { TLV_WMM_ENABLED, "WMM_ENABLED" },
109 | { TLV_WPA, "WPA" },
110 | { TLV_WPA_KEY_MGMT, "WPA_KEY_MGMT" },
111 | { TLV_RSN_PAIRWISE, "RSN_PAIRWISE" },
112 | { TLV_WPA_PASSPHRASE, "WPA_PASSPHRASE" },
113 | { TLV_WPA_PAIRWISE, "WPA_PAIRWISE" },
114 | { TLV_HT_CAPB, "HT_CAPB" },
115 | { TLV_IEEE80211_H, "IEEE80211_H" },
116 | { TLV_IEEE80211_W, "IEEE80211_W" },
117 | { TLV_VHT_OPER_CHWIDTH, "VHT_OPER_CHWIDTH" },
118 | { TLV_VHT_CAPB, "VHT_CAPB" },
119 | { TLV_IEEE8021_X, "IEEE8021_X" },
120 | { TLV_EAP_SERVER, "EAP_SERVER" },
121 | { TLV_AUTH_SERVER_ADDR, "AUTH_SERVER_ADDR" },
122 | { TLV_AUTH_SERVER_PORT, "AUTH_SERVER_PORT" },
123 | { TLV_AUTH_SERVER_SHARED_SECRET, "AUTH_SERVER_SHARED_SECRET" },
124 | { TLV_INTERFACE_NAME, "INTERFACE_NAME" },
125 | { TLV_NEW_INTERFACE_NAME, "NEW_INTERFACE_NAME" },
126 | { TLV_FREQUENCY, "FREQUENCY" },
127 | { TLV_BSS_IDENTIFIER, "BSS_IDENTIFIER" },
128 | { TLV_HW_MODE, "HW_MODE" },
129 | { TLV_VHT_OPER_CENTR_FREQ, "VHT_OPER_CENTR_FREQ" },
130 | { TLV_RESET_TYPE, "RESET_TYPE" },
131 | { APP_TYPE, "APP_TYPE" },
132 | { TLV_IE_OVERRIDE, "IE_OVERRIDE" },
133 | { TLV_HOME_FQDN, "HOME_FQDN"},
134 | { TLV_USERNAME, "USERNAME"},
135 | { TLV_PREFER, "PREFER"},
136 | { TLV_CREDENTIAL_TYPE, "CREDENTIAL_TYPE"},
137 | { TLV_ADDRESS, "ADDRESS" },
138 | { TLV_DISABLE_PMKSA_CACHING, "DISABLE_PMKSA_CACHING" },
139 | { TLV_SAE_ANTI_CLOGGING_THRESHOLD, "SAE_ANTI_CLOGGING_THRESHOLD" },
140 | { TLV_STA_SSID, "STA_SSID" },
141 | { TLV_KEY_MGMT, "KEY_MGMT" },
142 | { TLV_STA_WEP_KEY0, "STA_WEP_KEY0" },
143 | { TLV_WEP_TX_KEYIDX, "WEP_TX_KEYIDX" },
144 | { TLV_GROUP, "GROUP" },
145 | { TLV_PSK, "PSK" },
146 | { TLV_PROTO, "PROTO" },
147 | { TLV_STA_IEEE80211_W, "STA_IEEE80211_W" },
148 | { TLV_PAIRWISE, "PAIRWISE" },
149 | { TLV_EAP, "EAP" },
150 | { TLV_PHASE2, "PHASE2" },
151 | { TLV_IDENTITY, "IDENTITY" },
152 | { TLV_PASSWORD, "PASSWORD" },
153 | { TLV_CA_CERT, "CA_CERT" },
154 | { TLV_PHASE1, "PHASE1" },
155 | { TLV_CLIENT_CERT, "CLIENT_CERT" },
156 | { TLV_PRIVATE_KEY, "PRIVATE_KEY" },
157 | { TLV_EAPOL_M3_ELEMENTS, "EAPOL_M3_ELEMENTS" },
158 | { TLV_GTK_KDE_RANDOM_RESERVED_BITS, "GTK_KDE_RANDOM_RESERVED_BITS" },
159 | { TLV_STA_POWER_SAVE, "STA_POWER_SAVE" },
160 | { TLV_STATIC_IP, "STATIC_IP" },
161 | { TLV_DEBUG_LEVEL, "DEBUG_LEVEL" },
162 | { TLV_DUT_IP_ADDRESS, "DUT_IP_ADDRESS" },
163 | { TLV_HOSTAPD_FILE_NAME, "HOSTAPD_FILE_NAME" },
164 | { TLV_ROLE, "ROLE" },
165 | { TLV_BAND, "BAND" },
166 | { TLV_BSSID, "BSSID" },
167 | { TLV_ARP_TRANSMISSION_RATE, "ARP_TRANSMISSION_RATE" },
168 | { TLV_ARP_TARGET_IP, "ARP_TARGET_IP" },
169 | { TLV_ARP_FRAME_COUNT, "ARP_FRAME_COUNT" },
170 | { TLV_FRAME_TYPE, "FRAME_TYPE" },
171 | { TLV_ACTION_CATEGORY, "ACTION_CATEGORY" },
172 | { TLV_ACTION_CODE, "ACTION_CODE" },
173 | { TLV_PACKET_COUNT, "PACKET_COUNT" },
174 | { TLV_PACKET_TYPE, "PACKET_TYPE" },
175 | { TLV_PACKET_RATE, "PACKET_RATE" },
176 | { TLV_PHYMODE, "PHYMODE" },
177 | { TLV_CHANNEL_WIDTH, "CHANNEL_WIDTH" },
178 | { TLV_PAC_FILE, "PAC_FILE" },
179 | { TLV_STA_SAE_GROUPS, "STA_SAE_GROUPS" },
180 | { TLV_SAE_GROUPS, "SAE_GROUPS" },
181 | { TLV_IEEE80211_AX, "IEEE80211_AX" },
182 | { TLV_HE_OPER_CHWIDTH, "HE_OPER_CHWIDTH" },
183 | { TLV_HE_OPER_CENTR_FREQ, "HE_OPER_CENTR_FREQ" },
184 | { TLV_MBO, "MBO" },
185 | { TLV_MBO_CELL_DATA_CONN_PREF, "MBO_CELL_DATA_CONN_PREF" },
186 | { TLV_BSS_TRANSITION, "BSS_TRANSITION" },
187 | { TLV_INTERWORKING, "INTERWORKING" },
188 | { TLV_RRM_NEIGHBOR_REPORT, "RRM_NEIGHBOR_REPORT" },
189 | { TLV_RRM_BEACON_REPORT, "RRM_BEACON_REPORT" },
190 | { TLV_COUNTRY3, "COUNTRY3" },
191 | { TLV_MBO_CELL_CAPA, "MBO_CELL_CAPA" },
192 | { TLV_DOMAIN_MATCH, "TLV_DOMAIN_MATCH" },
193 | { TLV_DOMAIN_SUFFIX_MATCH, "TLV_DOMAIN_SUFFIX_MATCH" },
194 | { TLV_MBO_ASSOC_DISALLOW, "TLV_MBO_ASSOC_DISALLOW" },
195 | { TLV_DISASSOC_IMMINENT, "TLV_DISASSOC_IMMINENT" },
196 | { TLV_BSS_TERMINATION, "TLV_BSS_TERMINATION" },
197 | { TLV_DISASSOC_TIMER, "TLV_DISASSOC_TIMER" },
198 | { TLV_BSS_TERMINATION_TSF, "TLV_BSS_TERMINATION_TSF" },
199 | { TLV_BSS_TERMINATION_DURATION, "TLV_BSS_TERMINATION_DURATION" },
200 | { TLV_REASSOCIAITION_RETRY_DELAY, "TLV_REASSOCIAITION_RETRY_DELAY" },
201 | { TLV_BTMQUERY_REASON_CODE, "TLV_BTMQUERY_REASON_CODE" },
202 | { TLV_CANDIDATE_LIST, "TLV_CANDIDATE_LIST" },
203 | { TLV_ANQP_INFO_ID, "TLV_ANQP_INFO_ID" },
204 | { TLV_GAS_COMEBACK_DELAY, "TLV_GAS_COMEBACK_DELAY" },
205 | { TLV_SAE_PWE, "TLV_SAE_PWE" },
206 | { TLV_OWE_GROUPS, "TLV_OWE_GROUPS" },
207 | { TLV_STA_OWE_GROUP, "TLV_STA_OWE_GROUP" },
208 | { TLV_HE_MU_EDCA, "TLV_HE_MU_EDCA" },
209 | { TLV_PROTECTION_TYPE, "PROTECTION_TYPE" },
210 | { TLV_RSNXE_OVERRIDE_EAPOL, "TLV_RSNXE_OVERRIDE_EAPOL" },
211 | { TLV_TRANSITION_DISABLE, "TLV_TRANSITION_DISABLE" },
212 | { TLV_SAE_CONFIRM_IMMEDIATE, "SAE_CONFIRM_IMMEDIATE" },
213 | { TLV_SERVER_CERT, "SERVER_CERT" },
214 | { TLV_CONTROL_INTERFACE, "CONTROL_INTERFACE" },
215 | { TLV_PACKET_SIZE, "PACKET_SIZE" },
216 | { TLV_DUT_UDP_PORT, "DUT_UDP_PORT" },
217 | { TLV_OWE_TRANSITION_BSS_IDENTIFIER, "OWE_TRANSITION_BSS_IDENTIFIER" },
218 | { TLV_MESSAGE, "MESSAGE" },
219 | { TLV_STATUS, "STATUS" },
220 | { TLV_DUT_WLAN_IP_ADDR, "DUT_WLAN_IP_ADDR" },
221 | { TLV_DUT_MAC_ADDR, "DUT_MAC_ADDR" },
222 | { TLV_CONTROL_APP_VERSION, "CONTROL_APP_VERSION" },
223 | { TLV_FREQ_LIST, "FREQ_LIST" },
224 | { TLV_OP_CLASS, "OP_CLASS" },
225 | { TLV_HE_6G_ONLY, "HE_6G_ONLY"},
226 | { TLV_HE_UNSOL_PR_RESP_CADENCE, "UNSOL_PR_RESP_CADENCE" },
227 | { TLV_HE_FILS_DISCOVERY_TX, "FILS_DISCOERY_TX" },
228 | { TLV_SKIP_6G_BSS_SECURITY_CHECK, "SKIP_6G_BSS_SECURITY_CHECK" },
229 | { TLV_RAND_MAC_ADDR, "RAND_MAC_ADDR" },
230 | { TLV_PREASSOC_RAND_MAC_ADDR, "PREASSOC_RAND_MAC_ADDR" },
231 | { TLV_RAND_ADDR_LIFETIME, "RAND_ADDR_LIFETIME" },
232 | { TLV_HS20, "HS20" },
233 | { TLV_ACCESS_NETWORK_TYPE, "ACCESS_NETWORK_TYPE" },
234 | { TLV_INTERNET, "INTERNET" },
235 | { TLV_VENUE_GROUP, "VENUE_GROUP" },
236 | { TLV_VENUE_TYPE, "VENUE_TYPE" },
237 | { TLV_HESSID, "HESSID" },
238 | { TLV_ANQP_3GPP_CELL_NETWORK_INFO, "ANQP_3GPP_CELL_NETWORK_INFO" },
239 | { TLV_OSU_SSID, "OSU_SSID" },
240 | { TLV_PROXY_ARP, "PROXY_ARP" },
241 | { TLV_BSSLOAD_ENABLE, "BSSLOAD_ENABLE" },
242 | { TLV_ROAMING_CONSORTIUM, "ROAMING_CONSORTIUM" },
243 | { TLV_NETWORK_AUTH_TYPE, "NETWORK_AUTH_TYPE" },
244 | { TLV_DOMAIN_LIST, "DOMAIN_LIST" },
245 | { TLV_HS20_OPERATOR_FRIENDLY_NAME, "HS20_OPERATOR_FRIENDLY_NAME" },
246 | { TLV_NAI_REALM, "NAI_REALM" },
247 | { TLV_VENUE_NAME, "VENUE_NAME" },
248 | { TLV_IPADDR_TYPE_AVAILABILITY, "IPADDR_TYPE_AVAILABILITY" },
249 | { TLV_HS20_WAN_METRICS, "HS20_WAN_METRICS" },
250 | { TLV_HS20_CONN_CAPABILITY, "HS20_CONN_CAPABILITY"},
251 | { TLV_VENUE_URL, "VENUE_URL" },
252 | { TLV_OPERATOR_ICON_METADATA, "OPERATOR_ICON_METADATA" },
253 | { TLV_OSU_PROVIDERS_LIST, "OSU_PROVIDERS_LIST" },
254 | { TLV_OSU_PROVIDERS_NAI_LIST, "OSU_PROVIDERS_NAI_LIST" },
255 | { TLV_REALM, "REALM" },
256 | { TLV_IMSI, "IMSI" },
257 | { TLV_MILENAGE, "MILENAGE" },
258 | { TLV_BSSID_FILTER_LIST, "BSSID_FILTER_LIST" },
259 | { TLV_PPSMO_FILE, "PPSMO_FILE" },
260 | { TLV_OSU_SERVER_URI, "OSU_SERVER_URI" },
261 | { TLV_OSU_METHOD, "OSU_METHOD" },
262 | { TLV_GO_INTENT, "GO_INTENT" },
263 | { TLV_WSC_METHOD, "WSC_METHOD" },
264 | { TLV_PIN_METHOD, "PIN_METHOD" },
265 | { TLV_PIN_CODE, "PIN_CODE" },
266 | { TLV_P2P_CONN_TYPE, "P2P_CONN_TYPE" },
267 | { TLV_HS20_OPERATING_CLASS_INDICATION, "HS20_OPERATING_CLASS_INDICATION"},
268 | { TLV_WPS_ENABLE, "WPS_ENABLE" },
269 | { TLV_UPDATE_CONFIG, "UPDATE_CONFIG" },
270 | { TLV_EAP_FRAG_SIZE, "EAP_FRAG_SIZE" },
271 | { TLV_PERFORM_WPS_IE_FRAG, "PERFORM_WPS_IE_FRAG" },
272 | { TLV_ADVICE_OF_CHARGE, "ADVICE_OF_CHARGE"},
273 | { TLV_IGNORE_BROADCAST_SSID, "IGNORE_BROADCAST_SSID"},
274 | { TLV_PERSISTENT, "PERSISTENT_GROUP" },
275 | { TLV_WSC_CONFIG_ONLY, "WSC_CONFIG_ONLY" },
276 | { TLV_ICON_FILE, "ICON_FILE" },
277 | { TLV_P2P_DISABLED, "P2P_DISABLED" },
278 | { TLV_MANAGE_P2P, "MANAGE_P2P" },
279 | { TLV_AP_STA_COEXIST, "AP_STA_COEXIST" },
280 | { TLV_WPS_INDEPENDENT, "WPS_INDEPENDENT" },
281 | { TLV_LOCAL_PWR_CONST, "LOCAL_PWR_CONST" },
282 | { TLV_SPECTRUM_MGMT_REQ, "SPECTRUM_MGMT_REQ" },
283 | { TLV_CAPTURE_FILE, "CAPTURE_FILE" },
284 | { TLV_CAPTURE_FILTER, "CAPTURE_FILTER" },
285 | { TLV_CAPTURE_INFILE, "CAPTURE_INFILE" },
286 | { TLV_CAPTURE_OUTFILE, "CAPTURE_OUTFILE" },
287 | { TLV_TP_IP_ADDRESS, "TP_IP_ADDRESS" },
288 | { TLV_WPS_ER_SUPPORT, "WPS_ER_SUPPORT" },
289 | { TLV_TEST_PLATFORM_ID, "TEST_PLATFORM_ID" },
290 | { TLV_PMK, "PMK" },
291 | { TLV_GROUP_MGMT_CIPHER, "GROUP_MGMT_CIPHER" },
292 | { TLV_GROUP_MGMT, "GROUP_MGMT" },
293 | { TLV_OPENSSL_CIPHERS, "OPENSSL_CIPHERS" },
294 | { TLV_BEACON_PROT, "BEACON_PROTECTION" },
295 | { TLV_IEEE80211_BE, "IEEE80211_BE" },
296 | { TLV_MLD_AP, "MLD_AP" },
297 | { TLV_EHT_OPER_CHWIDTH, "EHT_OPER_CHWIDTH" },
298 | { TLV_EHT_OPER_CENTR_FREQ, "EHT_OPER_CENTR_FREQ" },
299 | { TLV_SAE_PASSWORD, "SAE_PASSWORD" },
300 | { TLV_SAE_PK_MODIFIER, "SAE_PK_MODIFIER" },
301 | { TLV_SAE_PK_FILE, "SAE_PK_FILE" },
302 | { TLV_WPA_GROUP_REKEY, "WPA_GROUP_REKEY" },
303 | { TLV_WPA_STRICT_REKEY, "WPA_STRICT_REKEY" },
304 | { TLV_OCV, "OCV" },
305 | { TLV_MLD_FORCE_SINGLE_LINK, "MLD_FORCE_SINGLE_LINK" },
306 | { TLV_MLD_CONNECT_BAND_PREF, "MLD_CONNECT_BAND_PREF" },
307 | };
308 |
309 | /* Find the type of the API stucture by the ID from the list */
310 | char* get_api_type_by_id(int id) {
311 | int i = 0;
312 | for (i = 0; i < sizeof(indigo_api_list)/sizeof(struct indigo_api); i++) {
313 | if (id == indigo_api_list[i].type) {
314 | return indigo_api_list[i].name;
315 | }
316 | }
317 | return "Unknown";
318 | }
319 |
320 | /* Find the API stucture by the ID from the list */
321 | struct indigo_api* get_api_by_id(int id) {
322 | int i = 0;
323 | for (i = 0; i < sizeof(indigo_api_list)/sizeof(struct indigo_api); i++) {
324 | if (id == indigo_api_list[i].type) {
325 | return &indigo_api_list[i];
326 | }
327 | }
328 | return NULL;
329 | }
330 |
331 | /* Find the TLV by the ID from the list */
332 | struct indigo_tlv* get_tlv_by_id(int id) {
333 | int i = 0;
334 |
335 | for (i = 0; i < sizeof(indigo_tlv_list)/sizeof(struct indigo_tlv); i++) {
336 | if (id == indigo_tlv_list[i].id) {
337 | return &indigo_tlv_list[i];
338 | }
339 | }
340 | return NULL;
341 | }
342 |
343 | /* The generic function generates the ACK/NACK response */
344 | /* seq: integer which should match the sequence of the request */
345 | /* status: 0 - ACK, 1 - NACK */
346 | /* reason: string for the reason code */
347 | void fill_wrapper_ack(struct packet_wrapper *wrapper, int seq, int status, char *reason) {
348 | wrapper->hdr.version = API_VERSION;
349 | wrapper->hdr.type = API_CMD_ACK;
350 | wrapper->hdr.seq = seq;
351 | wrapper->hdr.reserved = API_RESERVED_BYTE;
352 | wrapper->hdr.reserved2 = API_RESERVED_BYTE;
353 |
354 | wrapper->tlv_num = 2;
355 | wrapper->tlv[0] = malloc(sizeof(struct tlv_hdr));
356 | wrapper->tlv[0]->id = TLV_STATUS;
357 | wrapper->tlv[0]->len = 1;
358 | wrapper->tlv[0]->value = (char*)malloc(wrapper->tlv[0]->len);
359 | wrapper->tlv[0]->value[0] = status;
360 |
361 | wrapper->tlv[1] = malloc(sizeof(struct tlv_hdr));
362 | wrapper->tlv[1]->id = TLV_MESSAGE;
363 | wrapper->tlv[1]->len = strlen(reason);
364 | wrapper->tlv[1]->value = (char*)malloc(wrapper->tlv[1]->len);
365 | memcpy(wrapper->tlv[1]->value, reason, wrapper->tlv[1]->len);
366 | }
367 |
368 | /* Provide the function to register the API handler */
369 | void register_api(int id, api_callback_func verify, api_callback_func handle) {
370 | struct indigo_api *api = NULL;
371 |
372 | api = get_api_by_id(id);
373 | if (api) {
374 | api->verify = verify;
375 | api->handle = handle;
376 | } else {
377 | indigo_logger(LOG_LEVEL_ERROR, "API 0x%04x has no callback function", id);
378 | }
379 | }
380 |
381 | /* Fill the message header structure to the wrapper */
382 | void fill_wrapper_message_hdr(struct packet_wrapper *wrapper, int msg_type, int seq) {
383 | wrapper->hdr.version = API_VERSION;
384 | wrapper->hdr.type = msg_type;
385 | wrapper->hdr.seq = seq;
386 | wrapper->hdr.reserved = API_RESERVED_BYTE;
387 | wrapper->hdr.reserved2 = API_RESERVED_BYTE;
388 | }
389 |
390 | /* Fill the TLV structure to the wrapper (for one byte value) */
391 | void fill_wrapper_tlv_byte(struct packet_wrapper *wrapper, int id, char value) {
392 | wrapper->tlv[wrapper->tlv_num] = malloc(sizeof(struct tlv_hdr));
393 | wrapper->tlv[wrapper->tlv_num]->id = id;
394 | wrapper->tlv[wrapper->tlv_num]->len = 1;
395 | wrapper->tlv[wrapper->tlv_num]->value = (char*)malloc(1);
396 | wrapper->tlv[wrapper->tlv_num]->value[0] = value;
397 | wrapper->tlv_num++;
398 | }
399 |
400 | /* Fill the TLV structure to the wrapper (for multiple bytes value) */
401 | void fill_wrapper_tlv_bytes(struct packet_wrapper *wrapper, int id, int len, char* value) {
402 | wrapper->tlv[wrapper->tlv_num] = malloc(sizeof(struct tlv_hdr));
403 | wrapper->tlv[wrapper->tlv_num]->id = id;
404 | wrapper->tlv[wrapper->tlv_num]->len = len;
405 | wrapper->tlv[wrapper->tlv_num]->value = (char*)malloc(len);
406 | memcpy(wrapper->tlv[wrapper->tlv_num]->value, value, len);
407 | wrapper->tlv_num++;
408 | }
409 |
--------------------------------------------------------------------------------
/indigo_api.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #ifndef _INDIGO_API_
18 | #define _INDIGO_API_
19 | #include "indigo_packet.h"
20 |
21 | /* API */
22 | #define NAME_SIZE 64
23 |
24 | struct indigo_tlv {
25 | unsigned short id;
26 | char name[NAME_SIZE];
27 | };
28 |
29 | struct indigo_api {
30 | unsigned short type;
31 | char name[NAME_SIZE];
32 | int (*verify)(struct packet_wrapper *req, struct packet_wrapper *resp);
33 | int (*handle)(struct packet_wrapper *req, struct packet_wrapper *resp);
34 | };
35 |
36 | /* API definition */
37 | #define API_VERSION 0x01
38 | #define API_RESERVED_BYTE 0xff
39 |
40 | /* Message type definition */
41 | #define API_CMD_RESPONSE 0x0000
42 | #define API_CMD_ACK 0x0001
43 |
44 | #define API_AP_START_UP 0x1000
45 | #define API_AP_STOP 0x1001
46 | #define API_AP_CONFIGURE 0x1002
47 | #define API_AP_TRIGGER_CHANSWITCH 0x1003
48 | #define API_AP_SEND_DISCONNECT 0x1004
49 | #define API_AP_SET_PARAM 0x1005
50 | #define API_AP_SEND_BTM_REQ 0x1006
51 | #define API_AP_SEND_ARP_MSGS 0x1007
52 | #define API_AP_START_WPS 0x1008
53 | #define API_AP_CONFIGURE_WSC 0x1009
54 | #define API_AP_REKEY_GTK 0x100a
55 |
56 | #define API_STA_ASSOCIATE 0x2000
57 | #define API_STA_CONFIGURE 0x2001
58 | #define API_STA_DISCONNECT 0x2002
59 | #define API_STA_SEND_DISCONNECT 0x2003
60 | #define API_STA_REASSOCIATE 0x2004
61 | #define API_STA_SET_PARAM 0x2005
62 | #define API_STA_SEND_BTM_QUERY 0x2006
63 | #define API_STA_SEND_ANQP_QUERY 0x2007
64 | #define API_STA_START_UP 0x2008
65 | #define API_STA_SET_PHY_MODE 0x2009
66 | #define API_STA_SET_CHANNEL_WIDTH 0x200a
67 | #define API_STA_POWER_SAVE 0x200b
68 | #define API_P2P_START_UP 0x200c
69 | #define API_P2P_FIND 0x200d
70 | #define API_P2P_LISTEN 0x200e
71 | #define API_P2P_ADD_GROUP 0x200f
72 | #define API_P2P_START_WPS 0x2010
73 | #define API_P2P_CONNECT 0x2011
74 | #define API_STA_HS2_ASSOCIATE 0x2012
75 | #define API_STA_ADD_CREDENTIAL 0x2013
76 | #define API_STA_SCAN 0x2014
77 | #define API_P2P_GET_INTENT_VALUE 0x2015
78 | #define API_STA_START_WPS 0x2016
79 | #define API_STA_INSTALL_PPSMO 0x2017
80 | #define API_P2P_INVITE 0x2018
81 | #define API_P2P_STOP_GROUP 0x2019
82 | #define API_P2P_SET_SERV_DISC 0x201a
83 | #define API_STA_SEND_ICON_REQ 0x201b
84 | #define API_P2P_SET_EXT_LISTEN 0x201c
85 | #define API_STA_ENABLE_WSC 0x201d
86 | #define API_STA_INJECT_START 0x201e
87 | #define API_STA_INJECT_FRAME 0x201f
88 | #define API_STA_INJECT_STOP 0x2020
89 |
90 | #define API_SNIFFER_START 0x3000
91 | #define API_SNIFFER_STOP 0x3001
92 | #define API_SNIFFER_UPLOAD_FILE 0x3002
93 | #define API_SNIFFER_FILTER 0x3003
94 |
95 | #define API_GET_IP_ADDR 0x5000
96 | #define API_GET_MAC_ADDR 0x5001
97 | #define API_GET_CONTROL_APP_VERSION 0x5002
98 | #define API_START_LOOP_BACK_SERVER 0x5003
99 | #define API_STOP_LOOP_BACK_SERVER 0x5004
100 | #define API_CREATE_NEW_INTERFACE_BRIDGE_NETWORK 0x5005
101 | #define API_ASSIGN_STATIC_IP 0x5006
102 | #define API_DEVICE_RESET 0x5007
103 | #define API_SEND_LOOP_BACK_DATA 0x5008
104 | #define API_STOP_LOOP_BACK_DATA 0x5009
105 | #define API_START_DHCP 0x500a
106 | #define API_STOP_DHCP 0x500b
107 | #define API_GET_WSC_PIN 0x500c
108 | #define API_GET_WSC_CRED 0x500d
109 |
110 | /* TLV definition */
111 | #define TLV_SSID 0x0001
112 | #define TLV_CHANNEL 0x0002
113 | #define TLV_WEP_KEY0 0x0003
114 | #define TLV_AUTH_ALGORITHM 0x0004
115 | #define TLV_WEP_DEFAULT_KEY 0x0005
116 | #define TLV_IEEE80211_D 0x0006
117 | #define TLV_IEEE80211_N 0x0007
118 | #define TLV_IEEE80211_AC 0x0008
119 | #define TLV_COUNTRY_CODE 0x0009
120 | #define TLV_WMM_ENABLED 0x000a
121 | #define TLV_WPA 0x000b
122 | #define TLV_WPA_KEY_MGMT 0x000c
123 | #define TLV_RSN_PAIRWISE 0x000d
124 | #define TLV_WPA_PASSPHRASE 0x000e
125 | #define TLV_WPA_PAIRWISE 0x000f
126 | #define TLV_HT_CAPB 0x0010
127 | #define TLV_IEEE80211_H 0x0011
128 | #define TLV_IEEE80211_W 0x0012
129 | #define TLV_VHT_OPER_CHWIDTH 0x0013
130 | #define TLV_VHT_CAPB 0x0014
131 | #define TLV_IEEE8021_X 0x0015
132 | #define TLV_EAP_SERVER 0x0016
133 | #define TLV_AUTH_SERVER_ADDR 0x0017
134 | #define TLV_AUTH_SERVER_PORT 0x0018
135 | #define TLV_AUTH_SERVER_SHARED_SECRET 0x0019
136 | #define TLV_INTERFACE_NAME 0x001a
137 | #define TLV_NEW_INTERFACE_NAME 0x001b
138 | #define TLV_FREQUENCY 0x001c
139 | #define TLV_BSS_IDENTIFIER 0x001d
140 | #define TLV_HW_MODE 0x001e
141 | #define TLV_VHT_OPER_CENTR_FREQ 0x001f
142 | #define TLV_RESET_TYPE 0x0020
143 | #define APP_TYPE 0x0021
144 | #define TLV_OP_CLASS 0x0022
145 | #define TLV_IE_OVERRIDE 0x0023
146 | #define TLV_HOME_FQDN 0x0024
147 | #define TLV_USERNAME 0x0025
148 | #define TLV_PREFER 0x0026
149 | #define TLV_CREDENTIAL_TYPE 0x0027
150 | #define TLV_ADDRESS 0x0028
151 | #define TLV_DISABLE_PMKSA_CACHING 0x0033
152 | #define TLV_SAE_ANTI_CLOGGING_THRESHOLD 0x0034
153 | #define TLV_STA_SSID 0x0035
154 | #define TLV_KEY_MGMT 0x0036
155 | #define TLV_STA_WEP_KEY0 0x0037
156 | #define TLV_WEP_TX_KEYIDX 0x0038
157 | #define TLV_GROUP 0x0039
158 | #define TLV_PSK 0x003a
159 | #define TLV_PROTO 0x003b
160 | #define TLV_STA_IEEE80211_W 0x003c
161 | #define TLV_PAIRWISE 0x003d
162 | #define TLV_EAP 0x003e
163 | #define TLV_PHASE2 0x003f
164 | #define TLV_IDENTITY 0x0040
165 | #define TLV_PASSWORD 0x0041
166 | #define TLV_CA_CERT 0x0042
167 | #define TLV_PHASE1 0x0043
168 | #define TLV_CLIENT_CERT 0x0044
169 | #define TLV_PRIVATE_KEY 0x0045
170 | #define TLV_EAPOL_M3_ELEMENTS 0x0046
171 | #define TLV_GTK_KDE_RANDOM_RESERVED_BITS 0x0047
172 | #define TLV_STA_POWER_SAVE 0x0052
173 | #define TLV_STATIC_IP 0x0055
174 | #define TLV_DEBUG_LEVEL 0x0057
175 | #define TLV_DUT_IP_ADDRESS 0x0058
176 | #define TLV_HOSTAPD_FILE_NAME 0x0059
177 | #define TLV_ROLE 0x005c
178 | #define TLV_BAND 0x005d
179 | #define TLV_BSSID 0x005e
180 | #define TLV_ARP_TRANSMISSION_RATE 0x005f
181 | #define TLV_ARP_TARGET_IP 0x0060
182 | #define TLV_ARP_FRAME_COUNT 0x0062
183 | #define TLV_FRAME_TYPE 0x0063
184 | #define TLV_ACTION_CATEGORY 0x0064
185 | #define TLV_ACTION_CODE 0x0065
186 | #define TLV_PACKET_COUNT 0x0067
187 | #define TLV_PACKET_TYPE 0x0068
188 | #define TLV_PACKET_RATE 0x0069
189 | #define TLV_PHYMODE 0x006a
190 | #define TLV_CHANNEL_WIDTH 0x006b
191 | #define TLV_PAC_FILE 0x006d
192 | #define TLV_STA_SAE_GROUPS 0x006e
193 | #define TLV_SAE_GROUPS 0x0071
194 | #define TLV_IEEE80211_AX 0x0072
195 | #define TLV_HE_OPER_CHWIDTH 0x0073
196 | #define TLV_HE_OPER_CENTR_FREQ 0x0074
197 | #define TLV_MBO 0x0075
198 | #define TLV_MBO_CELL_DATA_CONN_PREF 0x0076
199 | #define TLV_BSS_TRANSITION 0x0077
200 | #define TLV_INTERWORKING 0x0078
201 | #define TLV_RRM_NEIGHBOR_REPORT 0x0079
202 | #define TLV_RRM_BEACON_REPORT 0x007a
203 | #define TLV_COUNTRY3 0x007b
204 | #define TLV_MBO_CELL_CAPA 0x007c
205 | #define TLV_DOMAIN_MATCH 0x007d
206 | #define TLV_DOMAIN_SUFFIX_MATCH 0x007e
207 | #define TLV_MBO_ASSOC_DISALLOW 0x007f
208 | #define TLV_DISASSOC_IMMINENT 0x0081
209 | #define TLV_BSS_TERMINATION 0x0082
210 | #define TLV_DISASSOC_TIMER 0x0083
211 | #define TLV_BSS_TERMINATION_TSF 0x0084
212 | #define TLV_BSS_TERMINATION_DURATION 0x0085
213 | #define TLV_REASSOCIAITION_RETRY_DELAY 0x0086
214 | #define TLV_BTMQUERY_REASON_CODE 0x0087
215 | #define TLV_CANDIDATE_LIST 0x0088
216 | #define TLV_ANQP_INFO_ID 0x0089
217 | #define TLV_GAS_COMEBACK_DELAY 0x008a
218 | #define TLV_SAE_PWE 0x008d
219 | #define TLV_OWE_GROUPS 0x008e
220 | #define TLV_STA_OWE_GROUP 0x008f
221 | #define TLV_HE_MU_EDCA 0x0090
222 | #define TLV_PROTECTION_TYPE 0x0091
223 | #define TLV_RSNXE_OVERRIDE_EAPOL 0x0092
224 | #define TLV_TRANSITION_DISABLE 0x0093
225 | #define TLV_SAE_CONFIRM_IMMEDIATE 0x0094
226 | #define TLV_RAND_MAC_ADDR 0x0095
227 | #define TLV_PREASSOC_RAND_MAC_ADDR 0x0096
228 | #define TLV_RAND_ADDR_LIFETIME 0x0097
229 | #define TLV_DROP_SA 0x0098
230 | #define TLV_SERVER_CERT 0x0099
231 |
232 | #define TLV_CONTROL_INTERFACE 0x009c
233 | #define TLV_PACKET_SIZE 0x009d
234 | #define TLV_DUT_UDP_PORT 0x009e
235 | #define TLV_SKIP_6G_BSS_SECURITY_CHECK 0x00a1
236 | #define TLV_OWE_TRANSITION_BSS_IDENTIFIER 0x00a2
237 | #define TLV_FREQ_LIST 0x00a3
238 | #define TLV_BSSID_FILTER_LIST 0x00a4
239 | #define TLV_HE_BEACON_TX_SU_PPDU 0x00a5
240 | #define TLV_HE_6G_ONLY 0x00a6
241 | #define TLV_HE_UNSOL_PR_RESP_CADENCE 0x00a7
242 | #define TLV_HE_FILS_DISCOVERY_TX 0x00a8
243 | #define TLV_HS20 0x00a9
244 | #define TLV_ACCESS_NETWORK_TYPE 0x00aa
245 | #define TLV_INTERNET 0x00ab
246 | #define TLV_VENUE_GROUP 0x00ac
247 | #define TLV_VENUE_TYPE 0x00ad
248 | #define TLV_HESSID 0x00ae
249 | #define TLV_OSU_SSID 0x00af
250 | #define TLV_ANQP_3GPP_CELL_NETWORK_INFO 0x00b0
251 | #define TLV_PROXY_ARP 0x00b1
252 | #define TLV_BSSLOAD_ENABLE 0x00b2
253 | #define TLV_ROAMING_CONSORTIUM 0x00b3
254 | #define TLV_NETWORK_AUTH_TYPE 0x00b4
255 | #define TLV_DOMAIN_LIST 0x00b5
256 | #define TLV_HS20_OPERATOR_FRIENDLY_NAME 0x00b6
257 | #define TLV_NAI_REALM 0x00b7
258 | #define TLV_VENUE_NAME 0x00b8
259 | #define TLV_IPADDR_TYPE_AVAILABILITY 0x00b9
260 | #define TLV_HS20_WAN_METRICS 0x00ba
261 | #define TLV_HS20_CONN_CAPABILITY 0x00bb
262 | #define TLV_VENUE_URL 0x00bc
263 | #define TLV_OPERATOR_ICON_METADATA 0x00bd
264 | #define TLV_OSU_PROVIDERS_LIST 0x00be
265 | #define TLV_OSU_PROVIDERS_NAI_LIST 0x00bf
266 | #define TLV_REALM 0x00c0
267 | #define TLV_IMSI 0x00c1
268 | #define TLV_MILENAGE 0x00c2
269 | #define TLV_PPSMO_FILE 0x00c3
270 | #define TLV_OSU_SERVER_URI 0x00c4
271 | #define TLV_OSU_METHOD 0x00c5
272 | #define TLV_GO_INTENT 0x00c6
273 | #define TLV_WSC_METHOD 0x00c7
274 | #define TLV_PIN_METHOD 0x00c8
275 | #define TLV_PIN_CODE 0x00c9
276 | #define TLV_P2P_CONN_TYPE 0x00ca
277 | #define TLV_HS20_OPERATING_CLASS_INDICATION 0x00cb
278 | #define TLV_WPS_ENABLE 0x00cc
279 | #define TLV_UPDATE_CONFIG 0x00cd
280 | #define TLV_EAP_FRAG_SIZE 0x00ce
281 | #define TLV_PERFORM_WPS_IE_FRAG 0x00cf
282 | #define TLV_ADVICE_OF_CHARGE 0x00d0
283 | #define TLV_IGNORE_BROADCAST_SSID 0x00d1
284 | #define TLV_PERSISTENT 0x00d2
285 | #define TLV_WSC_CONFIG_ONLY 0x00d3
286 | #define TLV_ICON_FILE 0x00d4
287 | #define TLV_P2P_DISABLED 0x00d5
288 | #define TLV_MANAGE_P2P 0x00d6
289 | #define TLV_AP_STA_COEXIST 0x00d7
290 | #define TLV_WPS_INDEPENDENT 0x00d8
291 | #define TLV_LOCAL_PWR_CONST 0x00d9
292 | #define TLV_SPECTRUM_MGMT_REQ 0x00da
293 | #define TLV_CAPTURE_FILE 0x00db
294 | #define TLV_CAPTURE_FILTER 0x00dc
295 | #define TLV_CAPTURE_INFILE 0x00dd
296 | #define TLV_CAPTURE_OUTFILE 0x00de
297 | #define TLV_TP_IP_ADDRESS 0x00df
298 | #define TLV_WPS_ER_SUPPORT 0x00e0
299 | #define TLV_TEST_PLATFORM_ID 0x00e1
300 | // 00e2 - 00e5: used by sniffer agent
301 | #define TLV_PMK 0x00e6
302 | #define TLV_GROUP_MGMT_CIPHER 0x00e7
303 | #define TLV_GROUP_MGMT 0x00e8
304 | #define TLV_OPENSSL_CIPHERS 0x00e9
305 | #define TLV_BEACON_PROT 0x00ea
306 | #define TLV_IEEE80211_BE 0x00eb
307 | #define TLV_MLD_AP 0x00ec
308 | #define TLV_EHT_OPER_CHWIDTH 0x00ed
309 | #define TLV_EHT_OPER_CENTR_FREQ 0x00ee
310 | #define TLV_SAE_PASSWORD 0x00ef
311 | #define TLV_SAE_PK_MODIFIER 0x00f0
312 | #define TLV_SAE_PK_FILE 0x00f1
313 | #define TLV_WPA_GROUP_REKEY 0x00f2
314 | #define TLV_WPA_STRICT_REKEY 0x00f3
315 | #define TLV_OCV 0x00f4
316 | #define TLV_MLD_FORCE_SINGLE_LINK 0x00f5
317 | #define TLV_MLD_CONNECT_BAND_PREF 0x00f6
318 |
319 | // class ResponseTLV
320 | // List of TLV used in the QuickTrack API response and ACK messages from the DUT
321 | #define TLV_MESSAGE 0xa000
322 | #define TLV_STATUS 0xa001
323 | #define TLV_DUT_WLAN_IP_ADDR 0xa002
324 | #define TLV_DUT_MAC_ADDR 0xa003
325 | #define TLV_CONTROL_APP_VERSION 0xa004
326 | #define TLV_LOOP_BACK_DATA_RECEIVED 0xa005
327 | #define TLV_LOOP_BACK_DATA_SENT 0xa006
328 | #define TLV_ARP_RECV_NUM 0xa007
329 | #define TLV_TEST_PLATFORM_APP_VERSION 0xa008
330 | #define TLV_LOOP_BACK_SERVER_PORT 0xa009
331 | #define TLV_WSC_PIN_CODE 0xa00a
332 | #define TLV_P2P_INTENT_VALUE 0xa00b
333 | #define TLV_WSC_SSID 0xa00c
334 | #define TLV_WSC_WPA_KEY_MGMT 0xa00d
335 | #define TLV_WSC_WPA_PASSPHRASE 0xa00e
336 | #define TLV_PASSPOINT_ICON_CHECKSUM 0xa00f
337 | #define TLV_TEST_SNIFFER_APP_VERSION 0xa010
338 | // a011 - a013: used by sniffer agent
339 | #define TLV_TEST_PLATFORM_WLAN_IP_ADDR 0xa014
340 |
341 | /* TLV Value */
342 | #define DUT_TYPE_STAUT 0x01
343 | #define DUT_TYPE_APUT 0x02
344 | #define DUT_TYPE_P2PUT 0x03
345 |
346 | #define TLV_BAND_24GHZ "2.4GHz"
347 | #define TLV_BAND_5GHZ "5GHz"
348 | #define TLV_BAND_6GHZ "6GHz"
349 |
350 | #define TLV_VALUE_APP_VERSION "v2.1"
351 | #define TLV_VALUE_OK "OK"
352 | #define TLV_VALUE_NOT_OK "Failed"
353 | #define TLV_VALUE_INSUFFICIENT_TLV "TLV is insufficient to run the command"
354 | #define TLV_VALUE_STATUS_OK 0x30
355 | #define TLV_VALUE_STATUS_NOT_OK 0x31
356 | #define TLV_VALUE_LOOP_BACK_STOP_OK "Loopback server in idle state"
357 | #define TLV_VALUE_HOSTAPD_STOP_OK "AP stop completed : Hostapd service is inactive."
358 | #define TLV_VALUE_HOSTAPD_STOP_NOT_OK "Failed to stop hostapd service."
359 | #define TLV_VALUE_WPA_SET_PARAMETER_OK "Set parameter action was successful."
360 | #define TLV_VALUE_WPA_SET_PARAMETER_NO_OK "Failed to set parameter."
361 | #define TLV_VALUE_WPA_PARAMETER_NOT_SUPPORT "The set parameter is not supported"
362 | #define TLV_VALUE_HOSTAPD_START_OK "AP is up : Hostapd service is active"
363 | #define TLV_VALUE_ASSIGN_STATIC_IP_OK "Static IP successfully assigned to wireless interface"
364 | #define TLV_VALUE_ASSIGN_STATIC_IP_NOT_OK "Static IP failed to be assigned to wireless interface"
365 | #define TLV_VALUE_LOOPBACK_SVR_START_OK "Loop back server initialized"
366 | #define TLV_VALUE_LOOPBACK_SVR_START_NOT_OK "Failed to initialise loop back server"
367 | #define TLV_VALUE_SEND_LOOPBACK_DATA_OK "Send Loop back data successful"
368 | #define TLV_VALUE_SEND_LOOPBACK_DATA_NOT_OK "Send Loop back data failed"
369 | #define TLV_VALUE_WIRELESS_INTERFACE_NOT_OK "Wireless interface is not available"
370 | #define TLV_VALUE_HOSTAPD_CTRL_NOT_OK "Failed to connect to hostapd control interface"
371 | #define TLV_VALUE_HOSTAPD_NOT_OK "Failed to find hostapd PID"
372 | #define TLV_VALUE_HOSTAPD_RESP_NOT_OK "Hostapd response is failed"
373 | #define TLV_VALUE_BROADCAST_ARP_TEST_OK "Broadcast ARP test successful"
374 | #define TLV_VALUE_BROADCAST_ARP_TEST_NOT_OK "Broadcast ARP test failed"
375 | #define TLV_VALUE_CREATE_BRIDGE_OK "Bridge network is created successfully"
376 | #define TLV_VALUE_CREATE_BRIDGE_NOT_OK "Failed to create bridge network"
377 | #define TLV_VALUE_START_DHCP_NOT_OK "Failed to start DHCP server or client"
378 |
379 | #define TLV_VALUE_WPA_S_START_UP_OK "wpa_supplicant is initialized successfully"
380 | #define TLV_VALUE_WPA_S_START_UP_NOT_OK "The wpa_supplicant was unable to initialize."
381 | #define TLV_VALUE_WPA_S_ADD_CRED_OK "Add credential to the STA successfully"
382 | #define TLV_VALUE_WPA_S_ADD_CRED_NOT_OK "Failed to add credential to the STA."
383 | #define TLV_VALUE_WPA_S_STOP_NOT_OK "Failed to stop wpa supplicant service."
384 | #define TLV_VALUE_WPA_S_STOP_OK "QuickTrack tool STA was successfully disconnected"
385 | #define TLV_VALUE_WPA_S_ASSOC_OK "STA is up: WPA supplicant associated"
386 | #define TLV_VALUE_WPA_S_ASSOC_NOT_OK "WPA supplicant cannot associate with AP"
387 | #define TLV_VALUE_WPA_S_DISCONNECT_OK "Sent DISCONNECT message"
388 | #define TLV_VALUE_WPA_S_DISCONNECT_NOT_OK "Failed to send DISCONNECT message"
389 | #define TLV_VALUE_WPA_S_RECONNECT_OK "Sent RECONNECT message"
390 | #define TLV_VALUE_WPA_S_RECONNECT_NOT_OK "Failed to send RECONNECT message"
391 | #define TLV_VALUE_WPA_S_CTRL_NOT_OK "Failed to connect to WPA supplicant control interface"
392 | #define TLV_VALUE_WPA_S_BTM_QUERY_OK "Sent WNM_BSS_QUERY"
393 | #define TLV_VALUE_WPA_S_BTM_QUERY_NOT_OK "Failed to WNM_BSS_QUERY"
394 | #define TLV_VALUE_WPA_S_SCAN_NOT_OK "Failed to trigger SCAN"
395 | #define TLV_VALUE_RESET_OK "Device reset successfully"
396 | #define TLV_VALUE_RESET_NOT_OK "Failed to run Device reset"
397 | #define TLV_VALUE_POWER_SAVE_OK "Set power save value successfully"
398 | #define TLV_VALUE_POWER_SAVE_NOT_OK "Failed to set power save value"
399 |
400 | #define TLV_VALUE_P2P_FIND_NOT_OK "Failed to trigger P2P find"
401 | #define TLV_VALUE_P2P_LISTEN_NOT_OK "Failed to trigger P2P listen"
402 | #define TLV_VALUE_P2P_ADD_GROUP_NOT_OK "Failed to add P2P group"
403 | #define TLV_VALUE_P2P_START_WPS_NOT_OK "Failed to start WPS on GO interface"
404 | #define TLV_VALUE_P2P_CONNECT_NOT_OK "Failed to trigger P2P connect"
405 | #define TLV_VALUE_P2P_INVITE_NOT_OK "Failed to invite P2P device"
406 | #define TLV_VALUE_P2P_SET_SERV_DISC_NOT_OK "Failed to set service discovery"
407 | #define TLV_VALUE_P2P_SET_EXT_LISTEN_NOT_OK "Failed to set extended listen timing"
408 |
409 | #define TLV_VALUE_HS2_INSTALL_PPSMO_OK "PPSMO file is installed"
410 | #define TLV_VALUE_HS2_INSTALL_PPSMO_NOT_OK "Failed to install PPSMO file"
411 |
412 | #define TLV_VALUE_AP_START_WPS_NOT_OK "Failed to start WPS on AP interface"
413 | #define TLV_VALUE_AP_WSC_PIN_CODE_NOT_OK "AP detects invalid PIN code"
414 |
415 | #define RESET_TYPE_INIT 0x01
416 | #define RESET_TYPE_TEARDOWN 0x02
417 | #define RESET_TYPE_RECONFIGURE 0x03
418 |
419 | #define WPA_CTRL_OK "OK"
420 | #define WPA_CTRL_FAIL "FAIL"
421 |
422 | #define P2P_CONN_TYPE_JOIN 0x01
423 | #define P2P_CONN_TYPE_AUTH 0x02
424 |
425 | #define WPS_ENABLE_NORMAL 0x01
426 | #define WPS_ENABLE_OOB 0x02
427 |
428 | struct indigo_api* get_api_by_id(int id);
429 | struct indigo_tlv* get_tlv_by_id(int id);
430 | char* get_api_type_by_id(int id);
431 |
432 | typedef int (*api_callback_func)(struct packet_wrapper *req, struct packet_wrapper *resp);
433 | void register_api(int id, api_callback_func verify, api_callback_func handle);
434 |
435 | void fill_wrapper_ack(struct packet_wrapper *wrapper, int seq, int status, char *reason);
436 |
437 | void register_api(int id, api_callback_func verify, api_callback_func handle);
438 | void fill_wrapper_message_hdr(struct packet_wrapper *wrapper, int msg_type, int seq);
439 | void fill_wrapper_tlv_byte(struct packet_wrapper *wrapper, int id, char value);
440 | void fill_wrapper_tlv_bytes(struct packet_wrapper *wrapper, int id, int len, char* value);
441 |
442 | /* Solution Vendor */
443 | void register_apis();
444 | #endif // __INDIGO_API_
445 |
--------------------------------------------------------------------------------
/indigo_api_callback.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #ifndef _INDIGO_API_CALLBACK
18 | #define _INDIGO_API_CALLBACK
19 |
20 |
21 | #define LOOPBACK_TIMEOUT 180
22 |
23 | struct tlv_to_config_name {
24 | unsigned short tlv_id;
25 | char config_name[NAME_SIZE];
26 | int quoted;
27 | };
28 |
29 | struct anqp_tlv_to_config_name {
30 | char element[NAME_SIZE];
31 | char config[NAME_SIZE];
32 | };
33 |
34 | struct tlv_to_config_name maps[] = {
35 | /* hapds */
36 | { TLV_SSID, "ssid", 0 },
37 | { TLV_CHANNEL, "channel", 0 },
38 | { TLV_WEP_KEY0, "wep_key0", 0 },
39 | { TLV_HW_MODE, "hw_mode", 0 },
40 | { TLV_AUTH_ALGORITHM, "auth_algs", 0 },
41 | { TLV_WEP_DEFAULT_KEY, "wep_default_key", 0 },
42 | { TLV_IEEE80211_D, "ieee80211d", 0 },
43 | { TLV_IEEE80211_N, "ieee80211n", 0 },
44 | { TLV_IEEE80211_AC, "ieee80211ac", 0 },
45 | { TLV_COUNTRY_CODE, "country_code", 0 },
46 | { TLV_WMM_ENABLED, "wmm_enabled", 0 },
47 | { TLV_WPA, "wpa", 0 },
48 | { TLV_WPA_KEY_MGMT, "wpa_key_mgmt", 0 },
49 | { TLV_RSN_PAIRWISE, "rsn_pairwise", 0 },
50 | { TLV_WPA_PASSPHRASE, "wpa_passphrase", 0 },
51 | { TLV_WPA_PAIRWISE, "wpa_pairwise", 0 },
52 | { TLV_HT_CAPB, "ht_capab", 0 },
53 | { TLV_IEEE80211_W, "ieee80211w", 0 },
54 | { TLV_IEEE80211_H, "ieee80211h", 0 },
55 | { TLV_VHT_OPER_CHWIDTH, "vht_oper_chwidth", 0 },
56 | { TLV_VHT_OPER_CENTR_FREQ, "vht_oper_centr_freq_seg0_idx", 0 },
57 | { TLV_VHT_CAPB, "vht_capab", 0 },
58 | { TLV_IEEE8021_X, "ieee8021x", 0 },
59 | { TLV_EAP_SERVER, "eap_server", 0 },
60 | { TLV_AUTH_SERVER_ADDR, "auth_server_addr", 0 },
61 | { TLV_AUTH_SERVER_PORT, "auth_server_port", 0 },
62 | { TLV_AUTH_SERVER_SHARED_SECRET, "auth_server_shared_secret", 0 },
63 | { TLV_IE_OVERRIDE, "own_ie_override", 0 }, // HostAPD Python Interface
64 | { TLV_SAE_ANTI_CLOGGING_THRESHOLD, "sae_anti_clogging_threshold", 0 }, // HostAPD Python Interface
65 | { TLV_DISABLE_PMKSA_CACHING, "disable_pmksa_caching", 0 }, // HostAPD Python Interface
66 | { TLV_EAPOL_M3_ELEMENTS, "eapol_m3_elements", 0 },
67 | { TLV_GTK_KDE_RANDOM_RESERVED_BITS, "gtk_kde_random_reserved_bits", 0 },
68 | { TLV_SAE_GROUPS, "sae_groups", 0 },
69 | { TLV_IEEE80211_AX, "ieee80211ax", 0 },
70 | { TLV_HE_OPER_CHWIDTH, "he_oper_chwidth", 0 },
71 | { TLV_HE_OPER_CENTR_FREQ, "he_oper_centr_freq_seg0_idx", 0 },
72 | { TLV_MBO, "mbo", 0 },
73 | { TLV_MBO_CELL_DATA_CONN_PREF, "mbo_cell_data_conn_pref", 0 },
74 | { TLV_BSS_TRANSITION, "bss_transition", 0 },
75 | { TLV_INTERWORKING, "interworking", 0 },
76 | { TLV_RRM_NEIGHBOR_REPORT, "rrm_neighbor_report", 0 },
77 | { TLV_RRM_BEACON_REPORT, "rrm_beacon_report", 0 },
78 | { TLV_COUNTRY3, "country3", 0 },
79 | { TLV_MBO_CELL_CAPA, "mbo_cell_capa", 0 },
80 | { TLV_MBO_ASSOC_DISALLOW, "mbo_assoc_disallow", 0 },
81 | { TLV_GAS_COMEBACK_DELAY, "gas_comeback_delay", 0 },
82 | { TLV_SAE_PWE, "sae_pwe", 0 },
83 | { TLV_OWE_GROUPS, "owe_groups", 0 },
84 | { TLV_HE_MU_EDCA, "he_mu_edca_qos_info_param_count", 0 },
85 | { TLV_TRANSITION_DISABLE, "transition_disable", 0 },
86 | { TLV_CONTROL_INTERFACE, "ctrl_interface", 0 },
87 | { TLV_RSNXE_OVERRIDE_EAPOL, "rsnxe_override_eapol", 0 },
88 | { TLV_SAE_CONFIRM_IMMEDIATE, "sae_confirm_immediate", 0 },
89 | { TLV_OWE_TRANSITION_BSS_IDENTIFIER, "owe_transition_ifname", 0 },
90 | { TLV_OP_CLASS, "op_class", 0 },
91 | { TLV_HE_UNSOL_PR_RESP_CADENCE, "unsol_bcast_probe_resp_interval", 0 },
92 | { TLV_HE_FILS_DISCOVERY_TX, "fils_discovery_max_interval", 0 },
93 | { TLV_SKIP_6G_BSS_SECURITY_CHECK, "skip_6g_bss_security_check", 0 },
94 | { TLV_HS20, "hs20", 0 },
95 | { TLV_ACCESS_NETWORK_TYPE, "access_network_type", 0 },
96 | { TLV_INTERNET, "internet", 0 },
97 | { TLV_VENUE_GROUP, "venue_group", 0 },
98 | { TLV_VENUE_TYPE, "venue_type", 0 },
99 | { TLV_HESSID, "hessid", 0 },
100 | { TLV_ANQP_3GPP_CELL_NETWORK_INFO, "anqp_3gpp_cell_net", 0 },
101 | { TLV_OSU_SSID, "osu_ssid", 0 },
102 | { TLV_PROXY_ARP, "proxy_arp", 0 },
103 | { TLV_OSU_SERVER_URI, "osu_server_uri", 0 },
104 | { TLV_OSU_METHOD, "osu_method_list", 0 },
105 | { TLV_DOMAIN_LIST, "domain_name", 0 },
106 | { TLV_IGNORE_BROADCAST_SSID, "ignore_broadcast_ssid", 0 },
107 | { TLV_MANAGE_P2P, "manage_p2p", 0 },
108 | { TLV_WPS_INDEPENDENT, "wps_independent", 0 },
109 | { TLV_LOCAL_PWR_CONST, "local_pwr_constraint", 0 },
110 | { TLV_SPECTRUM_MGMT_REQ, "spectrum_mgmt_required", 0 },
111 | { TLV_GROUP_MGMT_CIPHER, "group_mgmt_cipher", 0 },
112 | { TLV_IEEE80211_BE, "ieee80211be", 0 },
113 | { TLV_MLD_AP, "mld_ap", 0 },
114 | { TLV_EHT_OPER_CHWIDTH, "eht_oper_chwidth", 0 },
115 | { TLV_EHT_OPER_CENTR_FREQ, "eht_oper_centr_freq_seg0_idx", 0 },
116 | { TLV_WPA_GROUP_REKEY, "wpa_group_rekey", 0 },
117 | { TLV_WPA_STRICT_REKEY, "wpa_strict_rekey", 0 },
118 |
119 | /* wpas, seperate? */
120 | { TLV_STA_SSID, "ssid", 1 },
121 | { TLV_KEY_MGMT, "key_mgmt", 0 },
122 | { TLV_STA_WEP_KEY0, "wep_key0", 0 },
123 | { TLV_WEP_TX_KEYIDX, "wep_tx_keyidx", 0 },
124 | { TLV_GROUP, "group", 0 },
125 | { TLV_PSK, "psk", 1 },
126 | { TLV_PROTO, "proto", 0 },
127 | { TLV_STA_IEEE80211_W, "ieee80211w", 0 },
128 | { TLV_PAIRWISE, "pairwise", 0 },
129 | { TLV_EAP, "eap", 0 },
130 | { TLV_PHASE1, "phase1", 1 },
131 | { TLV_PHASE2, "phase2", 1 },
132 | { TLV_IDENTITY, "identity", 1 },
133 | { TLV_PASSWORD, "password", 1 },
134 | { TLV_CA_CERT, "ca_cert", 1 },
135 | { TLV_SERVER_CERT, "ca_cert", 1 },
136 | { TLV_PRIVATE_KEY, "private_key", 1 },
137 | { TLV_CLIENT_CERT, "client_cert", 1 },
138 | { TLV_DOMAIN_MATCH, "domain_match", 1 },
139 | { TLV_DOMAIN_SUFFIX_MATCH, "domain_suffix_match", 1 },
140 | { TLV_PAC_FILE, "pac_file", 1 },
141 | { TLV_STA_OWE_GROUP, "owe_group", 0 },
142 | { TLV_BSSID, "bssid", 0 },
143 | { TLV_REALM, "realm", 1 },
144 | { TLV_IMSI, "imsi", 1 },
145 | { TLV_MILENAGE, "milenage", 1 },
146 | { TLV_BSSID_FILTER_LIST, "bssid_filter", 0 },
147 | { TLV_USERNAME, "username", 1 },
148 | { TLV_HOME_FQDN, "domain", 1 },
149 | { TLV_PREFER, "priority", 0 },
150 | { TLV_GROUP_MGMT, "group_mgmt", 0 },
151 | { TLV_SAE_PASSWORD, "sae_password", 1 },
152 |
153 | /* hapd + wpas */
154 | { TLV_EAP_FRAG_SIZE, "fragment_size", 0 },
155 | { TLV_OPENSSL_CIPHERS, "openssl_ciphers", 1 },
156 | { TLV_BEACON_PROT, "beacon_prot", 0 },
157 | { TLV_OCV, "ocv", 0},
158 | };
159 |
160 | struct tlv_to_config_name semicolon_list[] = {
161 | { TLV_ROAMING_CONSORTIUM, "roaming_consortium", 0 },
162 | };
163 |
164 | struct anqp_tlv_to_config_name anqp_maps[] = {
165 | { "NeighborReportReq", "272" },
166 | { "QueryListWithCellPref", "mbo:2" },
167 | { "ANQPCapaList", "257" },
168 | { "VenueNameInfo", "258" },
169 | { "NetworkAuthTypeInfo", "260" },
170 | { "RoamingConsortium", "261" },
171 | { "IPAddrTypeInfo", "262" },
172 | { "NAIRealm", "263" },
173 | { "3GPPCellNetwork", "264" },
174 | { "DomainName", "268" },
175 | { "VenueUrl", "277" },
176 | { "AdviceOfCharge", "278" },
177 | { "HSCapaList", "hs20:2" },
178 | { "OperFriendlyName", "hs20:3" },
179 | { "WANMetrics", "hs20:4" },
180 | { "ConnCapa", "hs20:5" },
181 | { "NAIHomeRealm", "hs20:6" },
182 | { "OperatingClass", "hs20:7" },
183 | { "OSUProvidersList", "hs20:8" },
184 | { "IconReq", "hs20:10" },
185 | { "IconBinaryFile", "hs20:11" },
186 | { "OperatorIcon", "hs20:12" },
187 | { "OSUProvidersNaiList", "hs20:13" },
188 | };
189 |
190 | struct tlv_to_config_name wifi7_maps[] = {
191 | { TLV_IEEE80211_BE, "ieee80211be", 0 },
192 | { TLV_MLD_AP, "mld_ap", 0 },
193 | { TLV_EHT_OPER_CHWIDTH, "eht_oper_chwidth", 0 },
194 | { TLV_EHT_OPER_CENTR_FREQ, "eht_oper_centr_freq_seg0_idx", 0 },
195 | };
196 |
197 | char* find_tlv_config_name(int tlv_id) {
198 | int i;
199 | for (i = 0; i < sizeof(maps)/sizeof(struct tlv_to_config_name); i++) {
200 | if (tlv_id == maps[i].tlv_id) {
201 | return maps[i].config_name;
202 | }
203 | }
204 | return NULL;
205 | }
206 |
207 | struct tlv_to_config_name* find_tlv_config(int tlv_id) {
208 | int i;
209 | for (i = 0; i < sizeof(maps)/sizeof(struct tlv_to_config_name); i++) {
210 | if (tlv_id == maps[i].tlv_id) {
211 | return &maps[i];
212 | }
213 | }
214 | return NULL;
215 | }
216 |
217 | struct tlv_to_config_name* find_tlv_11be_config(int tlv_id) {
218 | int i;
219 | for (i = 0; i < sizeof(wifi7_maps)/sizeof(struct tlv_to_config_name); i++) {
220 | if (tlv_id == wifi7_maps[i].tlv_id) {
221 | return &wifi7_maps[i];
222 | }
223 | }
224 | return NULL;
225 | }
226 |
227 | struct tlv_to_config_name wpas_global_maps[] = {
228 | { TLV_STA_SAE_GROUPS, "sae_groups", 0 },
229 | { TLV_MBO_CELL_CAPA, "mbo_cell_capa", 0 },
230 | { TLV_SAE_PWE, "sae_pwe", 0 },
231 | { TLV_CONTROL_INTERFACE, "ctrl_interface", 0 },
232 | { TLV_RAND_MAC_ADDR, "mac_addr", 0 },
233 | { TLV_PREASSOC_RAND_MAC_ADDR, "preassoc_mac_addr", 0 },
234 | { TLV_RAND_ADDR_LIFETIME, "rand_addr_lifetime", 0 },
235 | { TLV_HS20, "hs20", 0 },
236 | { TLV_INTERWORKING, "interworking", 0 },
237 | { TLV_HESSID, "hessid", 0 },
238 | { TLV_ACCESS_NETWORK_TYPE, "access_network_type", 0 },
239 | { TLV_FREQ_LIST, "freq_list", 0 },
240 | { TLV_UPDATE_CONFIG, "update_config", 0 },
241 | { TLV_P2P_DISABLED, "p2p_disabled", 0 },
242 | { TLV_MLD_FORCE_SINGLE_LINK, "mld_force_single_link", 0 },
243 | { TLV_MLD_CONNECT_BAND_PREF, "mld_connect_band_pref", 0 },
244 | };
245 |
246 | struct tlv_to_config_name* find_wpas_global_config_name(int tlv_id) {
247 | int i;
248 | for (i = 0; i < sizeof(wpas_global_maps)/sizeof(struct tlv_to_config_name); i++) {
249 | if (tlv_id == wpas_global_maps[i].tlv_id) {
250 | return &wpas_global_maps[i];
251 | }
252 | }
253 | return NULL;
254 | }
255 |
256 | struct tlv_to_config_name* find_generic_tlv_config(int tlv_id, struct tlv_to_config_name* arr, int arr_size) {
257 | int i;
258 | for (i = 0; i < arr_size; i++) {
259 | if (tlv_id == (arr + i)->tlv_id) {
260 | return (arr + i);
261 | }
262 | }
263 | return NULL;
264 | }
265 |
266 | /* Basic */
267 | static int get_control_app_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
268 | static int start_loopback_server(struct packet_wrapper *req, struct packet_wrapper *resp);
269 | static int stop_loop_back_server_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
270 | static int send_loopback_data_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
271 | static int stop_loopback_data_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
272 | static int create_bridge_network_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
273 | static int assign_static_ip_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
274 | static int get_mac_addr_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
275 | static int get_ip_addr_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
276 | static int reset_device_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
277 | static int start_dhcp_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
278 | static int stop_dhcp_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
279 | static int get_wsc_pin_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
280 | static int get_wsc_cred_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
281 | /* AP */
282 | static int stop_ap_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
283 | static int configure_ap_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
284 | static int start_ap_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
285 | static int send_ap_disconnect_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
286 | static int set_ap_parameter_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
287 | static int send_ap_btm_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
288 | static int trigger_ap_channel_switch(struct packet_wrapper *req, struct packet_wrapper *resp);
289 | static int send_ap_arp_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
290 | static int start_wps_ap_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
291 | static int configure_ap_wsc_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
292 | static int rekey_ap_gtk_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
293 | /* STA */
294 | static int stop_sta_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
295 | static int configure_sta_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
296 | static int associate_sta_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
297 | static int start_up_sta_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
298 | static int send_sta_disconnect_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
299 | static int send_sta_reconnect_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
300 | static int send_sta_btm_query_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
301 | static int send_sta_anqp_query_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
302 | static int sta_scan_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
303 | static int set_sta_parameter_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
304 | static int set_sta_hs2_associate_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
305 | static int sta_add_credential_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
306 | static int set_sta_install_ppsmo_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
307 | static int set_sta_phy_mode_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
308 | static int set_sta_channel_width_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
309 | static int set_sta_power_save_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
310 | static int start_wps_sta_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
311 | static int send_sta_icon_req_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
312 | static int enable_wsc_sta_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
313 | static int set_sta_inject_start_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
314 | static int set_sta_inject_frame_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
315 | static int set_sta_inject_stop_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
316 | /* P2P */
317 | static int start_up_p2p_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
318 | static int p2p_find_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
319 | static int p2p_listen_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
320 | static int add_p2p_group_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
321 | static int stop_p2p_group_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
322 | static int p2p_start_wps_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
323 | static int p2p_connect_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
324 | static int get_p2p_intent_value_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
325 | static int p2p_invite_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
326 | static int set_p2p_serv_disc_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
327 | static int set_p2p_ext_listen_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
328 | /* Sniffer */
329 | static int sniffer_start_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
330 | static int sniffer_stop_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
331 | static int sniffer_filter_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
332 | static int sniffer_upload_file_handler(struct packet_wrapper *req, struct packet_wrapper *resp);
333 | #endif // __INDIGO_API_CALLBACK
334 |
--------------------------------------------------------------------------------
/indigo_api_callback_sniffer.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "indigo_api.h"
26 | #include "vendor_specific.h"
27 | #include "utils.h"
28 | #include "wpa_ctrl.h"
29 | #include "indigo_api_callback.h"
30 |
31 | extern struct sockaddr_in *tool_addr;
32 |
33 | void register_apis() {
34 | /* Basic */
35 | register_api(API_GET_CONTROL_APP_VERSION, NULL, get_control_app_handler);
36 | register_api(API_SNIFFER_START, NULL, sniffer_start_handler);
37 | register_api(API_SNIFFER_STOP, NULL, sniffer_stop_handler);
38 | register_api(API_SNIFFER_UPLOAD_FILE, NULL, sniffer_upload_file_handler);
39 | register_api(API_SNIFFER_FILTER, NULL, sniffer_filter_handler);
40 | }
41 |
42 | static int get_control_app_handler(struct packet_wrapper *req, struct packet_wrapper *resp) {
43 | char buffer[S_BUFFER_LEN];
44 | #ifdef _VERSION_
45 | snprintf(buffer, sizeof(buffer), "%s", _VERSION_);
46 | #else
47 | snprintf(buffer, sizeof(buffer), "%s", TLV_VALUE_APP_VERSION);
48 | #endif
49 | fill_wrapper_message_hdr(resp, API_CMD_RESPONSE, req->hdr.seq);
50 | fill_wrapper_tlv_byte(resp, TLV_STATUS, TLV_VALUE_STATUS_OK);
51 | fill_wrapper_tlv_bytes(resp, TLV_MESSAGE, strlen(TLV_VALUE_OK), TLV_VALUE_OK);
52 | fill_wrapper_tlv_bytes(resp, TLV_TEST_SNIFFER_APP_VERSION,
53 | strlen(buffer), buffer);
54 | return 0;
55 | }
56 |
57 | static int sniffer_start_handler(struct packet_wrapper *req, struct packet_wrapper *resp) {
58 | int status = TLV_VALUE_STATUS_NOT_OK;
59 | char *message = TLV_VALUE_NOT_OK;
60 | char buffer[S_BUFFER_LEN];
61 | char channel[8];
62 | char file_name[32];
63 | struct tlv_hdr *tlv = NULL;
64 |
65 | memset(channel, 0, sizeof(channel));
66 | tlv = find_wrapper_tlv_by_id(req, TLV_CHANNEL);
67 | if (tlv) {
68 | snprintf(buffer, sizeof(buffer), "ifconfig mon0 up");
69 | system(buffer);
70 | sleep(1);
71 | memcpy(channel, tlv->value, tlv->len);
72 | snprintf(buffer, sizeof(buffer), "iw dev mon0 set channel %s 80MHz", channel);
73 | system(buffer);
74 | } else {
75 | indigo_logger(LOG_LEVEL_ERROR, "TLV CHANNEL is missing");
76 | goto done;
77 | }
78 |
79 | memset(file_name, 0, sizeof(file_name));
80 | tlv = find_wrapper_tlv_by_id(req, TLV_CAPTURE_FILE);
81 | if (tlv) {
82 | memcpy(file_name, tlv->value, tlv->len);
83 | unlink(file_name);
84 | snprintf(buffer, sizeof(buffer), "tcpdump -i mon0 -w %s &", file_name);
85 | system(buffer);
86 | sleep(3);
87 | } else {
88 | indigo_logger(LOG_LEVEL_ERROR, "TLV CAPTURE_FILE is missing");
89 | goto done;
90 | }
91 |
92 | status = TLV_VALUE_STATUS_OK;
93 | message = TLV_VALUE_OK;
94 |
95 | done:
96 | fill_wrapper_message_hdr(resp, API_CMD_RESPONSE, req->hdr.seq);
97 | fill_wrapper_tlv_byte(resp, TLV_STATUS, status);
98 | fill_wrapper_tlv_bytes(resp, TLV_MESSAGE, strlen(message), message);
99 |
100 | return 0;
101 | }
102 |
103 | static int sniffer_stop_handler(struct packet_wrapper *req, struct packet_wrapper *resp) {
104 | int status = TLV_VALUE_STATUS_NOT_OK;
105 | char *message = TLV_VALUE_NOT_OK;
106 | char buffer[S_BUFFER_LEN];
107 |
108 | snprintf(buffer, sizeof(buffer), "killall tcpdump");
109 | if (system(buffer) != 0) {
110 | indigo_logger(LOG_LEVEL_ERROR, "Failed to shutdown tcpdump\n");
111 | goto done;
112 | }
113 |
114 | status = TLV_VALUE_STATUS_OK;
115 | message = TLV_VALUE_OK;
116 |
117 | done:
118 | fill_wrapper_message_hdr(resp, API_CMD_RESPONSE, req->hdr.seq);
119 | fill_wrapper_tlv_byte(resp, TLV_STATUS, status);
120 | fill_wrapper_tlv_bytes(resp, TLV_MESSAGE, strlen(message), message);
121 |
122 | return 0;
123 | }
124 |
125 | static int sniffer_filter_handler(struct packet_wrapper *req, struct packet_wrapper *resp) {
126 | int status = TLV_VALUE_STATUS_NOT_OK;
127 | char *message = TLV_VALUE_NOT_OK;
128 | char buffer[BUFFER_LEN];
129 | char filter[TLV_VALUE_SIZE];
130 | char infile_name[TLV_VALUE_SIZE];
131 | char outfile_name[TLV_VALUE_SIZE];
132 | struct tlv_hdr *tlv = NULL;
133 |
134 | tlv = find_wrapper_tlv_by_id(req, TLV_CAPTURE_FILTER);
135 | if (tlv) {
136 | memset(filter, 0, sizeof(filter));
137 | memcpy(filter, tlv->value, tlv->len);
138 |
139 | } else {
140 | indigo_logger(LOG_LEVEL_ERROR, "TLV CAPTURE_FILTER is missing");
141 | goto done;
142 | }
143 |
144 | tlv = find_wrapper_tlv_by_id(req, TLV_CAPTURE_INFILE);
145 | if (tlv) {
146 | memset(infile_name, 0, sizeof(infile_name));
147 | memcpy(infile_name, tlv->value, tlv->len);
148 | } else {
149 | indigo_logger(LOG_LEVEL_ERROR, "TLV CAPTURE_INFILE is missing");
150 | goto done;
151 | }
152 |
153 | tlv = find_wrapper_tlv_by_id(req, TLV_CAPTURE_OUTFILE);
154 | if (tlv) {
155 | memset(outfile_name, 0, sizeof(outfile_name));
156 | memcpy(outfile_name, tlv->value, tlv->len);
157 |
158 | snprintf(buffer, sizeof(buffer), "tshark -r %s -Y '%s' -w %s", infile_name, filter, outfile_name);
159 | indigo_logger(LOG_LEVEL_INFO, "Run: %s", buffer);
160 | system(buffer);
161 |
162 | if (!file_exists(outfile_name)) {
163 | indigo_logger(LOG_LEVEL_ERROR, "CAPTURE_OUTFILE file %s does not exist", outfile_name);
164 | goto done;
165 | }
166 |
167 | } else {
168 | indigo_logger(LOG_LEVEL_ERROR, "TLV CAPTURE_OUTFILE is missing");
169 | goto done;
170 | }
171 |
172 | status = TLV_VALUE_STATUS_OK;
173 | message = TLV_VALUE_OK;
174 |
175 | done:
176 | fill_wrapper_message_hdr(resp, API_CMD_RESPONSE, req->hdr.seq);
177 | fill_wrapper_tlv_byte(resp, TLV_STATUS, status);
178 | fill_wrapper_tlv_bytes(resp, TLV_MESSAGE, strlen(message), message);
179 |
180 | return 0;
181 | }
182 |
183 | static int sniffer_upload_file_handler(struct packet_wrapper *req, struct packet_wrapper *resp) {
184 | int status = TLV_VALUE_STATUS_NOT_OK;
185 | char *message = TLV_VALUE_NOT_OK;
186 | char buffer[BUFFER_LEN];
187 | char file_name[TLV_VALUE_SIZE];
188 | struct tlv_hdr *tlv = NULL;
189 |
190 | memset(file_name, 0, sizeof(file_name));
191 | tlv = find_wrapper_tlv_by_id(req, TLV_CAPTURE_FILE);
192 | if (tlv) {
193 | memcpy(file_name, tlv->value, tlv->len);
194 |
195 | if (!file_exists(file_name)) {
196 | indigo_logger(LOG_LEVEL_ERROR, "file %s does not exist", file_name);
197 | goto done;
198 | }
199 |
200 | if (tool_addr != NULL) {
201 | snprintf(buffer, sizeof(buffer), "curl -v -F TestArtifacts=@%s http://%s:%d%s", file_name, inet_ntoa(tool_addr->sin_addr), TOOL_POST_PORT, ARTIFACTS_UPLOAD_API);
202 | indigo_logger(LOG_LEVEL_INFO, "Run: %s", buffer);
203 | system(buffer);
204 | }
205 |
206 | } else {
207 | indigo_logger(LOG_LEVEL_ERROR, "TLV CAPTURE_FILE is missing");
208 | goto done;
209 | }
210 |
211 | status = TLV_VALUE_STATUS_OK;
212 | message = TLV_VALUE_OK;
213 |
214 | done:
215 | fill_wrapper_message_hdr(resp, API_CMD_RESPONSE, req->hdr.seq);
216 | fill_wrapper_tlv_byte(resp, TLV_STATUS, status);
217 | fill_wrapper_tlv_bytes(resp, TLV_MESSAGE, strlen(message), message);
218 |
219 | return 0;
220 | }
--------------------------------------------------------------------------------
/indigo_packet.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include "vendor_specific.h"
22 | #include "indigo_api.h"
23 | #include "utils.h"
24 |
25 | int capture_packet = 0, capture_count = 0; /* debug. Write the received packets to files */
26 | int debug_packet = 0; /* used by the packet hexstring print */
27 |
28 | /* Parse the QuickTrack message from the packet to the wrapper */
29 | int parse_packet(struct packet_wrapper *req, char *packet, int packet_len) {
30 | int i = 0, parser = 0, ret = 0;
31 | struct indigo_api *api = NULL;
32 | struct indigo_tlv *tlv = NULL;
33 |
34 | /* Print the debug message */
35 | if (debug_packet)
36 | print_hex(packet, packet_len);
37 |
38 | /* Parse the message header */
39 | ret = parse_message_hdr(&req->hdr, packet, packet_len);
40 | if (ret > 0) {
41 | if (debug_packet) {
42 | print_message_hdr(&req->hdr);
43 | }
44 | parser += ret;
45 | } else {
46 | return -1;
47 | }
48 |
49 | /* Parse the TLVs */
50 | while (packet_len - parser > 0) {
51 | req->tlv[req->tlv_num] = (struct tlv_hdr *)malloc(sizeof(struct tlv_hdr));
52 | memset(req->tlv[req->tlv_num], 0, sizeof(struct tlv_hdr));
53 |
54 | ret = parse_tlv(req->tlv[req->tlv_num], packet + parser, packet_len - parser);
55 | if (ret > 0) {
56 | if (debug_packet) {
57 | print_tlv(req->tlv[req->tlv_num]);
58 | }
59 |
60 | req->tlv_num++;
61 | parser += ret;
62 | } else {
63 | break;
64 | }
65 | }
66 |
67 | api = get_api_by_id(req->hdr.type);
68 | if (api) {
69 | if (!debug_packet)
70 | indigo_logger(LOG_LEVEL_INFO, "API: 0x%04x (%s)", api->type, api->name);
71 | } else {
72 | indigo_logger(LOG_LEVEL_WARNING, "API: 0x%04x Unknown", req->hdr.type);
73 | return -1;
74 | }
75 |
76 | for (i = 0; i < req->tlv_num; i++) {
77 | tlv = get_tlv_by_id(req->tlv[i]->id);
78 | if (tlv) {
79 | if (!debug_packet)
80 | indigo_logger(LOG_LEVEL_INFO, " TLV: 0x%04x (%s)", tlv->id, tlv->name);
81 | } else {
82 | indigo_logger(LOG_LEVEL_WARNING, " TLV: 0x%04x Unknown", req->tlv[i]->id);
83 | return -1;
84 | }
85 | }
86 |
87 | /* Only for the debug purpose. Write the received packet to files */
88 | if (capture_packet) {
89 | char fn[S_BUFFER_LEN], value[8];
90 | char *buffer;
91 | int buffer_len = packet_len*6;
92 | api = get_api_by_id(req->hdr.type);
93 | if (api) {
94 | sprintf(fn, "%02d_%s", capture_count++, api->name);
95 | }
96 | buffer = (char*)malloc(sizeof(char)*buffer_len);
97 | if (!buffer) {
98 | return 0;
99 | }
100 | memset(buffer, 0, buffer_len);
101 | for (i = 0; i < packet_len; i++) {
102 | memset(value, 0, sizeof(value));
103 | sprintf(value, "0x%02x%s", (unsigned char)(packet[i]&0x00ff), (itlv[i]) {
119 | if (wrapper->tlv[i]->id == id) {
120 | return wrapper->tlv[i];
121 | }
122 | }
123 | }
124 |
125 | return NULL;
126 | }
127 |
128 | /* Free the wrapper malloc's memory */
129 | int free_packet_wrapper(struct packet_wrapper *wrapper) {
130 | int i = 0;
131 |
132 | for (i = 0; i < TLV_NUM; i++) {
133 | if (wrapper->tlv[i]) {
134 | if (wrapper->tlv[i]->value) {
135 | free(wrapper->tlv[i]->value);
136 | }
137 | free(wrapper->tlv[i]);
138 | }
139 | }
140 | memset(wrapper, 0, sizeof(struct packet_wrapper));
141 |
142 | return 0;
143 | }
144 |
145 | /* Parse the message header */
146 | int parse_message_hdr(struct message_hdr *hdr, char *message, int message_len) {
147 | if (message_len < sizeof(struct message_hdr)) {
148 | return -1;
149 | }
150 |
151 | hdr->version = message[0];
152 | hdr->type = ((message[1] & 0x00ff) << 8) | (message[2] & 0x00ff);
153 | hdr->seq = ((message[3] & 0x00ff) << 8) | (message[4] & 0x00ff);
154 | hdr->reserved = message[5];
155 | hdr->reserved2 = message[6];
156 |
157 | return sizeof(struct message_hdr);
158 | }
159 |
160 | /* Convert the packet message header from the structure */
161 | int gen_message_hdr(char *message, int message_len, struct message_hdr *hdr) {
162 | int len = 0;
163 |
164 | if (message_len < sizeof(struct message_hdr)) {
165 | return -1;
166 | }
167 |
168 | message[len++] = hdr->version;
169 | message[len++] = (char) (hdr->type >> 8);
170 | message[len++] = (char) (hdr->type & 0x00ff);
171 | message[len++] = (char) (hdr->seq >> 8);
172 | message[len++] = (char) (hdr->seq & 0x00ff);
173 | message[len++] = hdr->reserved;
174 | message[len++] = hdr->reserved2;
175 |
176 | return sizeof(struct message_hdr);
177 | }
178 |
179 | /* Print the header */
180 | void print_message_hdr(struct message_hdr *hdr) {
181 | indigo_logger(LOG_LEVEL_INFO, "Version: %d", hdr->version);
182 | indigo_logger(LOG_LEVEL_INFO, "Type: 0x%04x (%s)", hdr->type, get_api_type_by_id(hdr->type));
183 | indigo_logger(LOG_LEVEL_INFO, "Sequence: 0x%04x", hdr->seq);
184 | indigo_logger(LOG_LEVEL_INFO, "Reserved: 0x%02x", hdr->reserved);
185 | indigo_logger(LOG_LEVEL_INFO, "Reserved2: 0x%02x", hdr->reserved2);
186 | }
187 |
188 | /* Print the hexstring of the specific range */
189 | int print_hex(char *message, int message_len) {
190 | int i;
191 | for(i = 0; i < message_len; i++) {
192 | printf("0x%02x ", (unsigned char)message[i]);
193 | }
194 | printf("\n\n");
195 | return 0;
196 | }
197 |
198 | /* Add the TLV to the wrapper */
199 | int add_wrapper_tlv(struct packet_wrapper *wrapper, int id, int len, char *value) {
200 | if (add_tlv(wrapper->tlv[wrapper->tlv_num], id, len, value) == 0) {
201 | wrapper->tlv_num++;
202 | return 0;
203 | }
204 | return 1;
205 | }
206 |
207 | /* Fill the TLV with the ID, length and value */
208 | int add_tlv(struct tlv_hdr *tlv, int id, int len, char *value) {
209 | if (!tlv)
210 | return 1;
211 | tlv->id = id;
212 | tlv->len = len;
213 | tlv->value = (char*)malloc(sizeof(char)*len);
214 | memcpy(tlv->value, value, len);
215 | return 0;
216 | }
217 |
218 | /* Parse the TLV from the packet to the structure */
219 | int parse_tlv(struct tlv_hdr *tlv, char *packet, int packet_len) {
220 | if (packet_len < 3) {
221 | return -1;
222 | }
223 |
224 | tlv->id = ((packet[0] & 0x00ff) << 8) | (packet[1] & 0x00ff);
225 | tlv->len = packet[2];
226 | tlv->value = (char*)malloc(sizeof(char) * tlv->len);
227 | memcpy(tlv->value, &packet[3], tlv->len);
228 |
229 | return tlv->len+3;
230 | }
231 |
232 | /* Convert the TLV structure to the packet */
233 | int gen_tlv(char *packet, int packet_size, struct tlv_hdr *t) {
234 | int len = 0;
235 |
236 | if (packet_size < t->len + 3) {
237 | return -1;
238 | }
239 |
240 | packet[len++] = (char) (t->id >> 8);
241 | packet[len++] = (char) (t->id & 0x00ff);
242 | packet[len++] = t->len;
243 | memcpy(&packet[len], t->value, t->len);
244 | len += t->len;
245 |
246 | return len;
247 | }
248 |
249 | /* Print the TLV */
250 | void print_tlv(struct tlv_hdr *t) {
251 | int i = 0;
252 | char buffer[S_BUFFER_LEN], value[S_BUFFER_LEN];
253 | struct indigo_tlv *tlv = get_tlv_by_id(t->id);
254 |
255 | memset(buffer, 0, sizeof(buffer));
256 | memset(value, 0, sizeof(value));
257 |
258 | indigo_logger(LOG_LEVEL_INFO, " ID: 0x%04x (%s)", t->id, tlv == NULL ? "Unknown" : tlv->name);
259 | indigo_logger(LOG_LEVEL_INFO, " Length: %d", t->len);
260 |
261 | if (t->len > 0) {
262 | sprintf(buffer, " Value: ");
263 | }
264 | for (i = 0; i < t->len; i++) {
265 | sprintf(value, "%02x ", t->value[i]);
266 | strcat(buffer, value);
267 | }
268 | indigo_logger(LOG_LEVEL_INFO, buffer);
269 | }
270 |
271 | /* Convert the wrapper to the packet includes the message header and all TLVs. Used by the ACK and resposne */
272 | int assemble_packet(char *packet, int packet_size, struct packet_wrapper *wrapper) {
273 | int i = 0, ret = 0, packet_len = 0;
274 |
275 | ret = gen_message_hdr(packet, packet_size, &wrapper->hdr);
276 | packet_len += ret;
277 |
278 | for (i = 0; i < wrapper->tlv_num; i++) {
279 | ret = gen_tlv(packet + packet_len, packet_size - packet_len, wrapper->tlv[i]);
280 | if (ret) {
281 | packet_len += ret;
282 | } else {
283 | break;
284 | }
285 | }
286 |
287 | if (debug_packet)
288 | print_hex(packet, packet_len);
289 |
290 | return packet_len;
291 | }
292 |
--------------------------------------------------------------------------------
/indigo_packet.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #ifndef _INDIGO_PACKET_
18 | #define _INDIGO_PACKET_
19 |
20 | #define TLV_NUM 128
21 | #define TLV_VALUE_SIZE 256
22 |
23 | /* Packet structure */
24 | struct __attribute__((__packed__)) message_hdr {
25 | unsigned char version;
26 | unsigned short type;
27 | unsigned short seq;
28 | unsigned char reserved;
29 | unsigned char reserved2;
30 | };
31 |
32 | struct __attribute__((__packed__)) tlv_hdr {
33 | unsigned short id;
34 | unsigned char len;
35 | unsigned char *value;
36 | };
37 |
38 | struct packet_wrapper {
39 | struct message_hdr hdr;
40 | struct tlv_hdr *tlv[TLV_NUM];
41 | int tlv_num;
42 | };
43 |
44 | /* API */
45 | int assemble_packet(char *packet, int packet_size, struct packet_wrapper *wrapper);
46 | int parse_packet(struct packet_wrapper *req, char *packet, int packet_len);
47 | int free_packet_wrapper(struct packet_wrapper *wrapper);
48 |
49 | /* Debug */
50 | int print_hex(char *message, int message_len);
51 |
52 | /* Message header */
53 | int parse_message_hdr(struct message_hdr *hdr, char *message, int message_len);
54 | int add_message_hdr(char *message, int message_len, struct message_hdr *hdr);
55 | void print_message_hdr(struct message_hdr *hdr);
56 |
57 | /* TLV header */
58 | int parse_tlv(struct tlv_hdr *tlv, char *message, int message_len);
59 | int gen_tlv(char *message, int message_len, struct tlv_hdr *t);
60 | void print_tlv(struct tlv_hdr *t);
61 | struct tlv_hdr *find_wrapper_tlv_by_id(struct packet_wrapper *wrapper, int id);
62 | int add_wrapper_tlv(struct packet_wrapper *wrapper, int id, int len, char *value);
63 |
64 | int add_tlv(struct tlv_hdr *tlv, int id, int len, char *value);
65 | #endif /* _INDIGO_PACKET_ */
66 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #include "vendor_specific.h"
33 | #include "eloop.h"
34 | #include "indigo_api.h"
35 | #include "utils.h"
36 |
37 |
38 | /* Internal functions */
39 | static void control_receive_message(int sock, void *eloop_ctx, void *sock_ctx);
40 | static int parse_parameters(int argc, char *argv[]);
41 | static void usage();
42 |
43 | /* External variables */
44 | extern int capture_packet; /* debug. Write the received packets to files */
45 | extern int debug_packet; /* used by the packet hexstring print */
46 |
47 | /* Initiate the service port. */
48 | static int control_socket_init(int port) {
49 | int s = -1;
50 | char cmd[S_BUFFER_LEN];
51 | struct sockaddr_in addr;
52 |
53 | /* Open UDP socket */
54 | s = socket(PF_INET, SOCK_DGRAM, 0);
55 | if (s < 0) {
56 | indigo_logger(LOG_LEVEL_ERROR, "Failed to open server socket: %s", strerror(errno));
57 | return -1;
58 | }
59 |
60 | /* Bind specific port */
61 | memset(&addr, 0, sizeof(addr));
62 | addr.sin_family = AF_INET;
63 | addr.sin_port = htons(port);
64 | if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
65 | indigo_logger(LOG_LEVEL_ERROR, "Failed to bind server socket: %s", strerror(errno));
66 | if (errno == EADDRINUSE) {
67 | sprintf(cmd, "netstat -lunatp | grep %d", port);
68 | system(cmd);
69 | }
70 | close(s);
71 | return -1;
72 | }
73 |
74 | /* Register to eloop and ready for the socket event */
75 | if (eloop_register_read_sock(s, control_receive_message, NULL, NULL)) {
76 | indigo_logger(LOG_LEVEL_ERROR, "Failed to initiate ControlAppC");
77 | close(s);
78 | return -1;
79 | }
80 | return s;
81 | }
82 |
83 | struct sockaddr_in *tool_addr; // For HTTP Post
84 | /* Callback function of the QuickTrack API. */
85 | static void control_receive_message(int sock, void *eloop_ctx, void *sock_ctx) {
86 | int ret; // return code
87 | int fromlen, len; // structure size and received length
88 | struct sockaddr_storage from; // source address of the message
89 | unsigned char buffer[BUFFER_LEN]; // buffer to receive the message
90 | struct packet_wrapper req, resp; // packet wrapper for the received message and response
91 | struct indigo_api *api = NULL; // used for API search, validation and handler call
92 |
93 | /* Receive request */
94 | fromlen = sizeof(from);
95 | len = recvfrom(sock, buffer, BUFFER_LEN, 0, (struct sockaddr *) &from, (socklen_t*)&fromlen);
96 | if (len < 0) {
97 | indigo_logger(LOG_LEVEL_ERROR, "Server: Failed to receive the packet");
98 | return ;
99 | } else {
100 | indigo_logger(LOG_LEVEL_DEBUG, "Server: Receive the packet");
101 | }
102 | tool_addr = (struct sockaddr_in *)&from;
103 |
104 | /* Parse request to HDR and TLV. Response NACK if parser fails. Otherwises, ACK. */
105 | memset(&req, 0, sizeof(struct packet_wrapper));
106 | memset(&resp, 0, sizeof(struct packet_wrapper));
107 | ret = parse_packet(&req, buffer, len);
108 | if (ret == 0) {
109 | indigo_logger(LOG_LEVEL_DEBUG, "Server: Parsed packet successfully");
110 | } else {
111 | indigo_logger(LOG_LEVEL_ERROR, "Server: Failed to parse the packet");
112 | fill_wrapper_ack(&resp, req.hdr.seq, 0x31, "Unable to parse the packet");
113 | len = assemble_packet(buffer, BUFFER_LEN, &resp);
114 |
115 | sendto(sock, (const char *)buffer, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
116 | goto done;
117 | }
118 |
119 | /* Find API by ID. If API is not supported, assemble NACK. */
120 | api = get_api_by_id(req.hdr.type);
121 | if (api) {
122 | indigo_logger(LOG_LEVEL_DEBUG, "API %s: Found handler", api->name);
123 | } else {
124 | indigo_logger(LOG_LEVEL_ERROR, "API Unknown (0x%04x): No registered handler", req.hdr.type);
125 | fill_wrapper_ack(&resp, req.hdr.seq, 0x31, "Unable to find the API handler");
126 | len = assemble_packet(buffer, BUFFER_LEN, &resp);
127 | sendto(sock, (const char *)buffer, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
128 | goto done;
129 | }
130 |
131 | /* Verify. Optional. If validation is failed, then return NACK. */
132 | if (api->verify == NULL || (api->verify && api->verify(&req, &resp) == 0)) {
133 | indigo_logger(LOG_LEVEL_INFO, "API %s: Return ACK", api->name);
134 | fill_wrapper_ack(&resp, req.hdr.seq, 0x30, "ACK: Command received");
135 | len = assemble_packet(buffer, BUFFER_LEN, &resp);
136 | sendto(sock, (const char *)buffer, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
137 | free_packet_wrapper(&resp);
138 | } else {
139 | indigo_logger(LOG_LEVEL_ERROR, "API %s: Failed to verify and return NACK", api->name);
140 | fill_wrapper_ack(&resp, req.hdr.seq, 1, "Unable to find the API handler");
141 | len = assemble_packet(buffer, BUFFER_LEN, &resp);
142 | sendto(sock, (const char *)buffer, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
143 | goto done;
144 | }
145 |
146 | /* Optional, use timer to handle the execution */
147 | /* Handle & Response. Call API handle(), assemble packet by response wrapper and send back to source address. */
148 | if (api->handle && api->handle(&req, &resp) == 0) {
149 | indigo_logger(LOG_LEVEL_INFO, "API %s: Return execution result", api->name);
150 | len = assemble_packet(buffer, BUFFER_LEN, &resp);
151 | sendto(sock, (const char *)buffer, len, MSG_CONFIRM, (const struct sockaddr *) &from, fromlen);
152 | } else {
153 | indigo_logger(LOG_LEVEL_DEBUG, "API %s (0x%04x): No handle function", api ? api->name : "Unknown", req.hdr.type);
154 | }
155 |
156 | done:
157 | /* Clean up resource */
158 | free_packet_wrapper(&req);
159 | free_packet_wrapper(&resp);
160 | indigo_logger(LOG_LEVEL_DEBUG, "API %s: Complete", api ? api->name : "Unknown");
161 | }
162 |
163 | /* Show the usage */
164 | static void usage() {
165 | printf("usage:\n");
166 | printf("app [-h] [-p] [-i|-i:[,:]] [-a] [-s]\n\n");
167 | printf("usage:\n");
168 | printf(" -a = specify hostapd path\n");
169 | printf(" -b = specify bridge name for wireless interfaces\n");
170 | printf(" -d = debug received and sent message\n");
171 | printf(" -i = specify the interface. E.g., -i wlan0. Or, :.\n band can be 2 for 2.4GHz, 5 for 5GHz and 6 for 6GHz. E.g., -i 2:wlan0,2:wlan1,5:wlan32,5:wlan33\n");
172 | printf(" -p = port number of the application\n");
173 | printf(" -s = specify wpa_supplicant path\n\n");
174 | }
175 |
176 | /* Show the welcome message with role and version */
177 | static void print_welcome() {
178 | #ifdef _DUT_
179 | printf("Welcome to use QuickTrack Control App DUT version");
180 | #elif defined(_TEST_SNIFFER_)
181 | printf("Welcome to use QuickTrack Control App Sniffer version");
182 | #else
183 | printf("Welcome to use Quicktrack Control App Platform version");
184 | #endif
185 |
186 | #ifdef _VERSION_
187 | printf(" %s.\n", _VERSION_);
188 | #else
189 | printf(".\n");
190 | #endif
191 | }
192 |
193 | /* Parse the commandline parameters */
194 | static int parse_parameters(int argc, char *argv[]) {
195 | int c, ifs_configured = 0, bridge_configured = 0;
196 | char buf[256];
197 |
198 | #ifdef _VERSION_
199 | while ((c = getopt(argc, argv, "a:b:s:i:hp:dcv")) != -1) {
200 | #else
201 | while ((c = getopt(argc, argv, "a:b:s:i:hp:dc")) != -1) {
202 | #endif
203 | switch (c) {
204 | case 'a':
205 | set_hapd_full_exec_path(optarg);
206 | break;
207 | case 'b':
208 | set_wlans_bridge(optarg);
209 | bridge_configured = 1;
210 | break;
211 | case 'c':
212 | capture_packet = 1;
213 | break;
214 | case 'd':
215 | debug_packet = 1;
216 | break;
217 | case 'h':
218 | usage();
219 | return 1;
220 | case 'i':
221 | if (set_wireless_interface(optarg) == 0) {
222 | ifs_configured = 1;
223 | }
224 | break;
225 | case 'p':
226 | set_service_port(atoi(optarg));
227 | break;
228 | case 's':
229 | set_wpas_full_exec_path(optarg);
230 | break;
231 | #ifdef _VERSION_
232 | case 'v':
233 | return 1;
234 | #endif
235 | }
236 | }
237 |
238 | if (optind < argc) {
239 | printf("\nInvalid option %s\n", argv[optind]);
240 | usage();
241 | return 1;
242 | }
243 |
244 | if (ifs_configured == 0) {
245 | #ifdef DEFAULT_APP_INTERFACES_PARAMS
246 | #ifdef _OPENWRT_
247 | if (detect_number_radio() != 2)
248 | snprintf(buf, sizeof(buf), "%s", DEFAULT_APP_6E_INTERFACES_PARAMS);
249 | else
250 | #endif
251 | snprintf(buf, sizeof(buf), "%s", DEFAULT_APP_INTERFACES_PARAMS);
252 | printf("\nUse default interface parameters %s.\n", buf);
253 | set_wireless_interface(buf);
254 | #else
255 | usage();
256 | printf("\nWe need to specify the interfaces with -i.\n");
257 | return 1;
258 | #endif
259 | }
260 |
261 | if (bridge_configured == 0) {
262 | set_wlans_bridge(BRIDGE_WLANS);
263 | }
264 |
265 | return 0;
266 | }
267 |
268 | static void handle_term(int sig, void *eloop_ctx, void *signal_ctx) {
269 | indigo_logger(LOG_LEVEL_INFO, "Signal %d received - terminating\n", sig);
270 | eloop_terminate();
271 | }
272 |
273 | static void handle_sighup(int sig, void *eloop_ctx, void *signal_ctx) {
274 | indigo_logger(LOG_LEVEL_INFO, "Signal %d received - hangup\n", sig);
275 | eloop_terminate();
276 | vendor_deinit();
277 | }
278 |
279 | int main(int argc, char* argv[]) {
280 | int service_socket = -1;
281 |
282 | /* Welcome message */
283 | print_welcome();
284 |
285 | /* Initiate the application */
286 | set_wireless_interface(WIRELESS_INTERFACE_DEFAULT); // Set default wireless interface information
287 | set_hapd_full_exec_path(HAPD_EXEC_FILE_DEFAULT); // Set default hostapd execution file path
288 | set_hapd_ctrl_path(HAPD_CTRL_PATH_DEFAULT); // Set default hostapd control interface path
289 | set_hapd_global_ctrl_path(HAPD_GLOBAL_CTRL_PATH_DEFAULT); // Set default hostapd global control interface path
290 | set_hapd_conf_file(HAPD_CONF_FILE_DEFAULT); // Set default hostapd configuration file path
291 | set_wpas_full_exec_path(WPAS_EXEC_FILE_DEFAULT); // Set default wap_supplicant execution file path
292 | set_wpas_ctrl_path(WPAS_CTRL_PATH_DEFAULT); // Set default wap_supplicant control interface path
293 | set_wpas_global_ctrl_path(WPAS_GLOBAL_CTRL_PATH_DEFAULT); // Set default wap_supplicant global control interface path
294 | set_wpas_conf_file(WPAS_CONF_FILE_DEFAULT); // Set default wap_supplicant configuration file path
295 |
296 | /* Parse the application arguments */
297 | if (parse_parameters(argc, argv)) {
298 | return 0;
299 | }
300 |
301 | #ifndef _OPENWRT_
302 | system("mkdir -p /etc/hostapd/");
303 | #endif
304 |
305 | /* Print the run-time information */
306 | indigo_logger(LOG_LEVEL_INFO, "QuickTrack control app running at: %d", get_service_port());
307 | indigo_logger(LOG_LEVEL_INFO, "Wireless Interface:" );
308 | show_wireless_interface_info();
309 | indigo_logger(LOG_LEVEL_INFO, "hostapd Path: %s (%s)", get_hapd_full_exec_path(), get_hapd_exec_file());
310 | indigo_logger(LOG_LEVEL_INFO, "wpa_supplicant Path: %s (%s)", get_wpas_full_exec_path(), get_wpas_exec_file());
311 |
312 | /*
313 | * The following information may not help anymore since
314 | * - we support multiple vaps
315 | * - remote udp port is known only when receive the control interface TLV
316 | indigo_logger(LOG_LEVEL_INFO, "Hostapd Global Control Interface: %s", get_hapd_global_ctrl_path());
317 | indigo_logger(LOG_LEVEL_INFO, "Hostapd Control Interface: %s", get_hapd_ctrl_path());
318 | indigo_logger(LOG_LEVEL_INFO, "WPA Supplicant Control Interface: %s", get_wpas_ctrl_path());
319 | */
320 |
321 | /* Register the callback */
322 | register_apis();
323 |
324 | /* Intiate the vendor's specific startup commands */
325 | vendor_init();
326 |
327 | /* Start eloop */
328 | eloop_init(NULL);
329 |
330 | /* Register SIGTERM */
331 | eloop_register_signal(SIGINT, handle_term, NULL);
332 | eloop_register_signal(SIGTERM, handle_term, NULL);
333 | eloop_register_signal(SIGHUP, handle_sighup, NULL);
334 |
335 | /* Bind the service port and register to eloop */
336 | service_socket = control_socket_init(get_service_port());
337 | if (service_socket >= 0) {
338 | eloop_run();
339 | } else {
340 | indigo_logger(LOG_LEVEL_INFO, "Failed to initiate the UDP socket");
341 | }
342 |
343 | /* Stop eloop */
344 | eloop_destroy();
345 | indigo_logger(LOG_LEVEL_INFO, "ControlAppC stops");
346 | if (service_socket >= 0) {
347 | indigo_logger(LOG_LEVEL_INFO, "Close service port: %d", get_service_port());
348 | close(service_socket);
349 | }
350 |
351 | vendor_deinit();
352 |
353 | return 0;
354 | }
355 |
--------------------------------------------------------------------------------
/openwrt-controlappc-dut-makefile:
--------------------------------------------------------------------------------
1 | # Type is laptop or openwrt
2 | TYPE = openwrt
3 | # Role is dut or platform
4 | ROLE = dut
5 |
6 | OBJS = main.o eloop.o indigo_api.o indigo_packet.o utils.o wpa_ctrl.o
7 | CFLAGS += -g
8 | CFLAGS += -D_OPENWRT_
9 | # CFLAGS += -D_WTS_OPENWRT_
10 | CFLAGS += -DHOSTAPD_SUPPORT_MBSSID_WAR
11 |
12 | VERSION = "1.0.8"
13 | # Define the package version
14 | ifneq ($(VERSION),)
15 | CFLAGS += -D_VERSION_='$(VERSION)'
16 | endif
17 |
18 | ifeq ($(ROLE),dut)
19 | OBJS += indigo_api_callback_dut.o vendor_specific_dut.o
20 | CFLAGS += -D_DUT_
21 | else
22 | OBJS += indigo_api_callback_tp.o vendor_specific_tp.o
23 | CFLAGS += -DCONFIG_CTRL_IFACE_UDP
24 | CFLAGS += -D_TEST_PLATFORM_
25 | endif
26 |
27 | all: app
28 |
29 | %.o: %.c
30 | $(CC) $(CFLAGS) -c -o $@ $<
31 |
32 | app: $(OBJS)
33 | $(CC) $(CFLAGS) -o $@ $^
34 |
35 | clean:
36 | rm -rf app *.o
37 |
--------------------------------------------------------------------------------
/openwrt-controlappc-tp-makefile:
--------------------------------------------------------------------------------
1 | # Type is laptop or openwrt
2 | TYPE = openwrt
3 | # Role is dut or platform
4 | ROLE = tp
5 |
6 | OBJS = main.o eloop.o indigo_api.o indigo_packet.o utils.o wpa_ctrl.o
7 | CFLAGS += -g
8 | CFLAGS += -D_OPENWRT_
9 | # CFLAGS += -D_WTS_OPENWRT_
10 |
11 | VERSION = "1.0.8"
12 | # Define the package version
13 | ifneq ($(VERSION),)
14 | CFLAGS += -D_VERSION_='$(VERSION)'
15 | endif
16 |
17 | ifeq ($(ROLE),dut)
18 | OBJS += indigo_api_callback_dut.o vendor_specific_dut.o
19 | CFLAGS += -D_DUT_
20 | else
21 | OBJS += indigo_api_callback_tp.o vendor_specific_tp.o
22 | CFLAGS += -DCONFIG_CTRL_IFACE_UDP
23 | CFLAGS += -D_TEST_PLATFORM_
24 | endif
25 |
26 | all: app
27 |
28 | %.o: %.c
29 | $(CC) $(CFLAGS) -c -o $@ $<
30 |
31 | app: $(OBJS)
32 | $(CC) $(CFLAGS) -o $@ $^
33 |
34 | clean:
35 | rm -rf app *.o
36 |
--------------------------------------------------------------------------------
/package.controlappc-dut.Makefile:
--------------------------------------------------------------------------------
1 | include $(TOPDIR)/rules.mk
2 |
3 | PKG_NAME:=controlappc-dut
4 | PKG_RELEASE:=1.0.6
5 |
6 | PKG_MAINTAINER:=WFA
7 | PKG_LICENSE:=WFA
8 |
9 | PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_RELEASE)
10 | PKG_BUILD_PARALLEL:=1
11 |
12 | TARGET_LDFLAGS_C:=$(TARGET_LDFLAGS)
13 |
14 | STAMP_CONFIGURED:=$(STAMP_CONFIGURED)_$(CONFIG_WPA_MSG_MIN_PRIORITY)
15 |
16 | DRIVER_MAKEOPTS=
17 |
18 | # Full
19 | include $(INCLUDE_DIR)/package.mk
20 |
21 | define Package/controlappc-dut/default
22 | SECTION:=net
23 | CATEGORY:=Network
24 | TITLE:=ControlAppC from Wi-Fi Alliance QuickTrack Project
25 | URL:=http://wi-fi.org/
26 | endef
27 |
28 | define Package/controlappc-dut
29 | $(call Package/controlappc-dut/default)
30 | TITLE+= (WFA)
31 | endef
32 |
33 | #define Build/Compile/hostapd-wfa
34 | define Build/Compile
35 | $(info ************ Build/Compile/controlappc-dut **********)
36 | $(call Build/RunMake, \
37 | )
38 | endef
39 |
40 | define Build/Prepare
41 | $(info ************ Build/Prepare **********)
42 | $(INSTALL_DIR) $(PKG_BUILD_DIR)
43 | cp -rf ./src/* $(PKG_BUILD_DIR)/
44 | endef
45 |
46 | define Build/RunMake
47 | $(info ************ Build/RunMake $(TARGET_CC) **********)
48 | CC=$(TARGET_CC) LD=$(TARGET_LD) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/$(1)
49 | $(2)
50 | endef
51 |
52 | define Package/controlappc-dut/install
53 | $(info ************ Package/controlappc-dut/install $(PKG_BUILD_DIR) **********)
54 | $(INSTALL_DIR) $(1)/usr/local/bin
55 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/app $(1)/usr/local/bin/controlappc-dut
56 | endef
57 |
58 | #Package/hostapd-wfa/install = $(Package/hostapd-wfa/install)
59 | $(eval $(call BuildPackage,controlappc-dut,))
60 |
--------------------------------------------------------------------------------
/package.controlappc-tp.Makefile:
--------------------------------------------------------------------------------
1 | include $(TOPDIR)/rules.mk
2 |
3 | PKG_NAME:=controlappc-tp
4 | PKG_RELEASE:=1.0.6
5 |
6 | PKG_MAINTAINER:=WFA
7 | PKG_LICENSE:=WFA
8 |
9 | PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_RELEASE)
10 | PKG_BUILD_PARALLEL:=1
11 |
12 | TARGET_LDFLAGS_C:=$(TARGET_LDFLAGS)
13 |
14 | STAMP_CONFIGURED:=$(STAMP_CONFIGURED)_$(CONFIG_WPA_MSG_MIN_PRIORITY)
15 |
16 | DRIVER_MAKEOPTS=
17 |
18 | # Full
19 | include $(INCLUDE_DIR)/package.mk
20 |
21 | define Package/controlappc-tp/default
22 | SECTION:=net
23 | CATEGORY:=Network
24 | TITLE:=ControlAppC from Wi-Fi Alliance QuickTrack Project
25 | URL:=http://wi-fi.org/
26 | endef
27 |
28 | define Package/controlappc-tp
29 | $(call Package/controlappc-tp/default)
30 | TITLE+= (WFA)
31 | endef
32 |
33 | #define Build/Compile/hostapd-wfa
34 | define Build/Compile
35 | $(info ************ Build/Compile/controlappc-tp **********)
36 | $(call Build/RunMake, \
37 | )
38 | endef
39 |
40 | define Build/Prepare
41 | $(info ************ Build/Prepare **********)
42 | $(INSTALL_DIR) $(PKG_BUILD_DIR)
43 | cp -rf ./src/* $(PKG_BUILD_DIR)/
44 | endef
45 |
46 | define Build/RunMake
47 | $(info ************ Build/RunMake $(TARGET_CC) **********)
48 | CC=$(TARGET_CC) LD=$(TARGET_LD) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/$(1)
49 | $(2)
50 | endef
51 |
52 | define Package/controlappc-tp/install
53 | $(info ************ Package/controlappc-tp/install $(PKG_BUILD_DIR) **********)
54 | $(INSTALL_DIR) $(1)/usr/local/bin
55 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/app $(1)/usr/local/bin/controlappc-tp
56 | endef
57 |
58 | #Package/hostapd-wfa/install = $(Package/hostapd-wfa/install)
59 | $(eval $(call BuildPackage,controlappc-tp,))
60 |
--------------------------------------------------------------------------------
/patch_nwmgr.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Local variable
4 | file="/etc/NetworkManager/NetworkManager.conf"
5 | bkup_file="/etc/NetworkManager/NetworkManager.conf.bkup"
6 | debug=0
7 | i=0
8 | array=()
9 | main_section=0
10 | keyfile_section=0
11 |
12 | # Error return
13 | error_exit() {
14 | echo "$1Please manually add the unmanaged-interface:wl* to ${file} and restart NetworkManager if Network Manager is enabled."
15 | exit 0
16 | }
17 |
18 | # Backup file
19 | backup() {
20 | if [ -f "$file" ]; then
21 | cp -rf "$file" "$bkup_file"
22 | fi
23 | }
24 |
25 | # Restore file from backup
26 | restore() {
27 | if [ -f "$bkup_file" ]; then
28 | cp -rf "$bkup_file" "$file"
29 | fi
30 | }
31 |
32 | # Read lines from configuration
33 | read_config() {
34 | # Return error if NetworkManager.conf doesn't exist
35 | if [ ! -f "${file}" ]; then
36 | error_exit "The patch script cannot find ${file}. "
37 | fi
38 | # Read to array
39 | # echo "Read lines from ${file}."
40 | while IFS= read -r line;
41 | do array+=("$line");
42 | done < "$file"
43 | # echo "Read lines completes. Total line number is ${#array[@]}."
44 | }
45 |
46 | # Save lines to configuration
47 | save_config() {
48 | printf "%s\n" "${array[@]}" >${file}
49 | }
50 |
51 | # Parse and update main section
52 | patch_main() {
53 | # Update [main] to include plugin=*,keyfile*
54 | echo "Patching main section."
55 | for (( i=0; i< ${#array[@]}; i++ ));
56 | do
57 | line="${array[$i]}"
58 | # Skip comment
59 | if [[ "$line" =~ \#.* ]]; then
60 | # echo "skip $line"
61 | continue
62 | fi
63 | # Start to check plugin after main section
64 | if [[ "$line" == "[main]" ]]; then
65 | main_section=1
66 | continue
67 | fi
68 | if [[ "$main_section" = "0" ]]; then
69 | continue
70 | fi
71 |
72 | # Find plugins
73 | if [[ "$line" =~ plugins=.*keyfile.* ]]; then
74 | echo "$line Found keyfile from plugins. Don't require to patch main section."
75 | break
76 | elif [[ "$line" =~ plugins=.* ]]; then
77 | echo "$line Found plugins but no keyfile. Append keyfile to plugin."
78 | array[$i]="$line,keyfile"
79 | break
80 | fi
81 | # Append plugins
82 | if [[ "$line" =~ \[.* ]]; then
83 | echo "End of main section. Unable to find plugins in main ${i}, append \"plugins=keyfile\"."
84 | array=( "${array[@]:0:$i}" "plugins=keyfile" "${array[@]:$i}")
85 | break
86 | fi
87 | done
88 |
89 | # Debug
90 | if [[ "${debug}" = 1 ]]; then
91 | echo "Debug main section..."
92 | for line in "${array[@]}"; do
93 | echo "(DEBUG) $line"
94 | done
95 | echo ""
96 | fi
97 |
98 | if [[ "$main_section" = 0 ]]; then
99 | error_exit "Unable to find the main section. "
100 | fi
101 | }
102 |
103 | # Parse and update keyfile section
104 | patch_keyfile() {
105 | # Update [keyfile] to include unmanaged-devices=interface-name:wl*
106 | echo "Patching keyfile section."
107 | for (( i=0; i< ${#array[@]}; i++ ));
108 | do
109 | line="${array[$i]}"
110 | # Skip comment
111 | if [[ "$line" =~ \#.* ]]; then
112 | # echo "skip $line"
113 | continue
114 | fi
115 | # Start to check unmanaged-devices after keyfile section
116 | if [[ "$line" == "[keyfile]" ]]; then
117 | keyfile_section=1
118 | continue
119 | fi
120 | if [[ "$keyfile_section" = "0" ]]; then
121 | continue
122 | fi
123 | # Find unmanaged-devices
124 | if [[ "$line" =~ unmanaged-devices=.*wl.* ]]; then
125 | echo "$line Found unmanaged-devices --> $line"
126 | break
127 | elif [[ "$line" =~ unmanaged-devices=.* ]]; then
128 | echo "$line Found unmanaged-devices but no wl*. Replace the configuration."
129 | array[$i]="unmanaged-devices=interface-name:wl*"
130 | break
131 | fi
132 | # Append unmanaged-devices to keyfile section if not existed
133 | if [[ "$line" =~ \[.* ]]; then
134 | echo "End of keyfile section. Unable to find unmanaged-devices in keyfile ${i}. Append \"unmanaged-devices=interface-name:wl*\""
135 | array=( "${array[@]:0:$i}" "unmanaged-devices=interface-name:wl*" "${array[@]:$i}")
136 | break
137 | fi
138 | done
139 | # Append keyfile and unmanaged-devices if not existed
140 | if [[ "$keyfile_section" = "0" ]]; then
141 | echo "Unable to find keyfile section. Append the section."
142 | array+=( "" "[keyfile]" "unmanaged-devices=interface-name:wl*")
143 | fi
144 |
145 | # Debug
146 | if [[ "${debug}" = 1 ]]; then
147 | echo "Debug keyfile section..."
148 | for line in "${array[@]}"; do
149 | echo "(DEBUG) $line"
150 | done
151 | echo ""
152 | fi
153 | }
154 |
155 | if [[ "$1" = "restore" ]]; then
156 | echo "Restore ${file} from ${bkup_file}"
157 | restore
158 | systemctl restart NetworkManager
159 | else
160 | echo "Start to patch ${file}"
161 | backup
162 | read_config
163 | patch_main
164 | patch_keyfile
165 | save_config
166 | echo "The original configuration is backup to ${bkup_file}. You can restore it if any problem."
167 | echo "sudo cp -rf ${bkup_file} ${file}"
168 | echo "sudo systemctl restart NetworkManager"
169 | systemctl stop wpa_supplicant
170 | systemctl restart NetworkManager
171 | echo "Patch complete"
172 | fi
173 | exit 0
174 |
--------------------------------------------------------------------------------
/sta_reset_config.conf:
--------------------------------------------------------------------------------
1 | ctrl_interface=/var/run/wpa_supplicant
2 | ap_scan=1
3 | network={
4 | ssid="QuickTrack"
5 | key_mgmt=WPA-PSK
6 | proto=RSN
7 | pairwise=CCMP
8 | psk="12345678"
9 | }
10 |
--------------------------------------------------------------------------------
/test.py:
--------------------------------------------------------------------------------
1 | import random, socket, string, sys, time
2 |
3 | class Tlv():
4 | def __init__(self, id, val):
5 | self.id = id
6 | self.val = val
7 | def to_bytes(self):
8 | raw = bytearray()
9 | raw.append(self.id >> 8)
10 | raw.append(self.id & 0x00ff)
11 | raw.append(len(self.val))
12 | raw += bytearray(self.val)
13 | return raw
14 |
15 | class Msg():
16 | version = 0x01
17 | reserved = 0xff
18 | def __init__(self, id):
19 | self.id = id
20 | self.seq = random.randint(0x0000, 0xffff)
21 | self.tlvs = []
22 | def append_tlv(self, tlv):
23 | self.tlvs.append(tlv)
24 | def to_bytes(self):
25 | raw = bytearray()
26 | raw.append(self.version)
27 | raw.append(self.id >> 8)
28 | raw.append(self.id & 0x00ff)
29 | raw.append(self.seq >> 8)
30 | raw.append(self.seq & 0x00ff)
31 | raw.append(self.reserved)
32 | raw.append(self.reserved)
33 | for t in self.tlvs:
34 | output = t.to_bytes()
35 | raw += output
36 |
37 | return raw
38 |
39 | def get_hexstring(input):
40 | hexstring = ""
41 | for b in bytearray(input):
42 | hexstring += "0x%02x " % b
43 | return hexstring.rstrip()
44 |
45 | def send_indigo_api(ip, port):
46 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
47 | server_address = (ip, port)
48 |
49 | for output in outputs:
50 | try:
51 | # Send Requset
52 | print('sending request')
53 | sent = sock.sendto(output, server_address)
54 |
55 | # Receive ACK
56 | print('waiting to receive ack')
57 | data, server = sock.recvfrom(4096)
58 | print('received "%s"' % get_hexstring(data))
59 |
60 | # Receive Response
61 | print('waiting to receive response')
62 | data, server = sock.recvfrom(4096)
63 | print('received "%s"' % get_hexstring(data))
64 | print('(ascii) "%s"' % (data))
65 | time.sleep(command_interval)
66 | except Exception as e:
67 | print(e)
68 | print("An exception occurred and closing socket")
69 | sock.close()
70 | break
71 |
72 | print("closing socket")
73 | sock.close()
74 |
75 | def send_indigo_api_raw(ip, port, raw):
76 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
77 | server_address = (ip, port)
78 |
79 | try:
80 | # Send Requset
81 | print('sending request')
82 | sent = sock.sendto(raw, server_address)
83 |
84 | # Receive ACK
85 | print('waiting to receive ack')
86 | data, server = sock.recvfrom(4096)
87 | print('received "%s"' % get_hexstring(data))
88 |
89 | # Receive Response
90 | print('waiting to receive response')
91 | data, server = sock.recvfrom(4096)
92 | print('received "%s"' % get_hexstring(data))
93 | print('(ascii) "%s"' % (data))
94 | time.sleep(command_interval)
95 | except Exception as e:
96 | print(e)
97 | print("An exception occurred and closing socket")
98 | sock.close()
99 |
100 | print("closing socket")
101 | sock.close()
102 |
103 | def test_get_control_app():
104 | m = Msg(0x5002)
105 | return m
106 |
107 | def test_loopback_start(lb_port=55501):
108 | m = Msg(0x5003)
109 | m.append_tlv(Tlv(0x0054, bytes(b'%d' % lb_port)))
110 | return m
111 |
112 | def test_loopback_stop():
113 | m = Msg(0x5004)
114 | return m
115 |
116 | def test_loopback_send_data():
117 | m = Msg(0x5008)
118 | m.append_tlv(Tlv(0x0058, bytes(b'10.252.10.32')))
119 | m.append_tlv(Tlv(0x0054, bytes(b'20480')))
120 | m.append_tlv(Tlv(0x0067, bytes(b'12')))
121 | m.append_tlv(Tlv(0x0069, bytes(b'1')))
122 | m.append_tlv(Tlv(0x00c0, bytes(b'1200')))
123 | return m
124 |
125 | def start_loopback_client(target_host, target_port=20480, count=10, size=1000):
126 | recv_count = 0
127 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
128 | server_address = (target_host, target_port)
129 |
130 | letters = string.ascii_lowercase
131 |
132 | for i in range(count):
133 | loopback_data = ''.join(random.choice(letters) for i in range(size))
134 | try:
135 | # Send Requset
136 | print('[count=%d] sending loopback data len=%d %s...' % (i, len(loopback_data), loopback_data[0:50]))
137 | sent = sock.sendto(loopback_data, server_address)
138 |
139 | # Receive Response
140 | data, server = sock.recvfrom(4096)
141 | print('[count=%d] received loopback data len=%d %s...' % (i, len(data), data[0:50]))
142 | recv_count = recv_count + 1
143 | except:
144 | print("[count=%d] failed to send socket")
145 |
146 | sock.close()
147 | print("Percentage: %d%%" % int((float(recv_count)/float(count))*100) )
148 |
149 |
150 | def test_ap_send_disassociate():
151 | m = Msg(0x1004)
152 | m.append_tlv(Tlv(0x0028, bytes(b'b8:5d:0a:62:b3:ee')))
153 | return m
154 |
155 | def test_sta_start_up():
156 | m = Msg(0x2008)
157 | m.append_tlv(Tlv(0x0097, bytes(b'udp:10240')))
158 | return m
159 |
160 | def test_sta_configure():
161 | m = Msg(0x2001)
162 | m.append_tlv(Tlv(0x0035, bytes(b'Indigo_1600155580'))) # SSID
163 | m.append_tlv(Tlv(0x003a, bytes(b'12345678'))) # PSK
164 | m.append_tlv(Tlv(0x003b, bytes(b'RSN'))) # PROTO
165 | m.append_tlv(Tlv(0x003d, bytes(b'CCMP'))) # PAIRWISE
166 | m.append_tlv(Tlv(0x003c, bytes(b'1'))) # STA_IEEE80211_W
167 | m.append_tlv(Tlv(0x0036, bytes(b'WPA-PSK'))) # KEY_MGMT
168 | return m
169 |
170 | def test_sta_associate():
171 | m = Msg(0x2000)
172 | return m
173 |
174 | def test_sta_disconnect():
175 | m = Msg(0x2002)
176 | return m
177 |
178 | def test_ap_start():
179 | m = Msg(0x1000)
180 | return m
181 |
182 | def test_ap_stop():
183 | m = Msg(0x1001)
184 | return m
185 |
186 | def test_get_mac_addr():
187 | m = Msg(0x5001)
188 | return m
189 |
190 | def test_ap_configure():
191 | # Bytes to DUT : 01 10 02 01 51 ff ff 00 01 11 49 6e 64 69 67 6f 5f 31 36 30 32 38 33 39 35 39 34
192 | # 00 07 01 31
193 | # 00 02 02 31 31
194 | # 00 1e 01 67
195 | # 00 0e 20 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66
196 | # 00 0b 01 32
197 | # 00 0c 03 53 41 45
198 | # 00 0d 04 43 43 4d 50
199 | m = Msg(0x1002)
200 | m.append_tlv(Tlv(0x0001, bytes(b'Indigo_1602839594')))
201 | m.append_tlv(Tlv(0x0007, bytes(b'1')))
202 | m.append_tlv(Tlv(0x0002, bytes(b'11')))
203 | m.append_tlv(Tlv(0x001e, bytes(b'g')))
204 | m.append_tlv(Tlv(0x000e, bytes(b'0123456789abcdef0123456789abcdef')))
205 | m.append_tlv(Tlv(0x000b, bytes(b'2')))
206 | m.append_tlv(Tlv(0x000c, bytes(b'SAE')))
207 | m.append_tlv(Tlv(0x000d, bytes(b'CCMP')))
208 | # m.append_tlv(Tlv(0x000d, [0x43, 0x43, 0x4d, 0x50] ))
209 | return m
210 |
211 | def test_assign_static_ip():
212 | # Bytes to DUT : 01 50 06 00 cc ff ff 00 55 0b 31 39 32 2e 31 36 38 2e 31 2e 31
213 | m = Msg(0x5006)
214 | m.append_tlv(Tlv(0x0055, bytes(b'192.168.1.1')))
215 | return m
216 |
217 | def test_device_reset():
218 | # REQ: 01 50 07 01 4f ff ff 00 5c 01 32 00 57 01 30
219 | # RSP: 01 00 01 01 4f ff ff a0 01 01 30 a0 00 15 41 43 4b 3a 20 43 6f 6d 6d 61 6e 64 20 72 65 63 65 69 76 65 64
220 | m = Msg(0x5007)
221 | m.append_tlv(Tlv(0x005c, bytes(0x32)))
222 | m.append_tlv(Tlv(0x0057, bytes(0x30)))
223 | return m
224 |
225 | def test_hex_file(ip, port, fn):
226 | raw = bytearray()
227 | f = open(fn, "r")
228 | txt = f.read()
229 | data = txt.split(", ")
230 | for d in data:
231 | hex_int = int(d, 16)
232 | raw.append(hex_int & 0x00ff)
233 | send_indigo_api_raw(ip, port, raw)
234 |
235 | command_interval = 1
236 | outputs = []
237 |
238 | # ContrlAppC ip and port
239 | peer_ip = '10.252.10.139'
240 | peer_port = 9004
241 |
242 | if len(sys.argv) == 1:
243 | m = test_get_control_app()
244 | outputs.append(m.to_bytes())
245 | elif len(sys.argv) >= 2:
246 | if sys.argv[1] == "get_control_app":
247 | m = test_get_control_app()
248 | outputs.append(m.to_bytes())
249 | elif sys.argv[1] == "loopback_start":
250 | if len(sys.argv) == 3:
251 | m = test_loopback_start(int(sys.argv[2]))
252 | else:
253 | m = test_loopback_start()
254 | outputs.append(m.to_bytes())
255 | elif sys.argv[1] == "loopback_test":
256 | start_loopback_client(peer_ip, 20480, 10, 1000)
257 | m = test_get_control_app()
258 | outputs.append(m.to_bytes())
259 | elif sys.argv[1] == "loopback_send_data":
260 | m = test_loopback_send_data()
261 | outputs.append(m.to_bytes())
262 | elif sys.argv[1] == "loopback_stop":
263 | m = test_loopback_stop()
264 | outputs.append(m.to_bytes())
265 | elif sys.argv[1] == "device_reset":
266 | m = test_device_reset()
267 | outputs.append(m.to_bytes())
268 | elif sys.argv[1] == "ap_start":
269 | m = test_ap_start()
270 | outputs.append(m.to_bytes())
271 | elif sys.argv[1] == "ap_stop":
272 | m = test_ap_stop()
273 | outputs.append(m.to_bytes())
274 | elif sys.argv[1] == "ap_configure":
275 | m = test_ap_configure()
276 | outputs.append(m.to_bytes())
277 | elif sys.argv[1] == "sta_start_up":
278 | m = test_sta_start_up()
279 | outputs.append(m.to_bytes())
280 | elif sys.argv[1] == "sta_disconnect":
281 | m = test_sta_disconnect()
282 | outputs.append(m.to_bytes())
283 | elif sys.argv[1] == "assign_static_ip":
284 | m = test_assign_static_ip()
285 | elif sys.argv[1] == "get_mac_addr":
286 | m = test_get_mac_addr()
287 | outputs.append(m.to_bytes())
288 | elif sys.argv[1] == "file":
289 | test_hex_file(peer_ip, peer_port, sys.argv[2])
290 | sys.exit()
291 | else:
292 | m = test_get_control_app()
293 | outputs.append(m.to_bytes())
294 |
295 | send_indigo_api(peer_ip, peer_port)
296 |
--------------------------------------------------------------------------------
/utils.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #ifndef _INDIGO_UTILS_
18 | #define _INDIGO_UTILS_ 1
19 |
20 | #include
21 |
22 | #define S_BUFFER_LEN 512
23 | #define BUFFER_LEN 1536
24 | #define L_BUFFER_LEN 8192
25 |
26 | #define TOOL_POST_PORT 8080
27 | #define HAPD_UPLOAD_API "/upload-platform-hapd-log"
28 | #define WPAS_UPLOAD_API "/upload-platform-wpas-log"
29 | #define ARTIFACTS_UPLOAD_API "/upload-test-artifacts"
30 | #ifdef _DUT_
31 | #define APP_LOG_FILE "controlappc_DUT.log"
32 | #else
33 | #define APP_LOG_FILE "controlappc_tool_platform.log"
34 | #endif
35 | #define UPLOAD_TC_APP_LOG 1
36 |
37 | /* Log */
38 | enum {
39 | LOG_LEVEL_DEBUG_VERBOSE = 0,
40 | LOG_LEVEL_DEBUG = 1,
41 | LOG_LEVEL_INFO = 2,
42 | LOG_LEVEL_NOTICE = 3,
43 | LOG_LEVEL_WARNING = 4,
44 | LOG_LEVEL_ERROR = 5
45 | };
46 |
47 | enum {
48 | BAND_24GHZ = 0,
49 | BAND_5GHZ = 1,
50 | BAND_6GHZ = 2
51 | };
52 |
53 | enum {
54 | PHYMODE_AUTO = 0,
55 | PHYMODE_11B = 1,
56 | PHYMODE_11BG = 2,
57 | PHYMODE_11BGN = 3,
58 | PHYMODE_11A = 4,
59 | PHYMODE_11NA = 5,
60 | PHYMODE_11AC = 6,
61 | PHYMODE_11AXG = 7,
62 | PHYMODE_11AXA = 8,
63 | PHYMODE_11AX = 9,
64 | PHYMODE_11BE = 10,
65 | };
66 |
67 | enum {
68 | CHWIDTH_AUTO = 0,
69 | CHWIDTH_20 = 1,
70 | CHWIDTH_40 = 2,
71 | CHWIDTH_80 = 3,
72 | CHWIDTH_80PLUS80 = 4,
73 | CHWIDTH_160 = 5
74 | };
75 |
76 | enum {
77 | DATA_TYPE_UDP = 0,
78 | DATA_TYPE_ICMP = 1
79 | };
80 |
81 | enum {
82 | OP_CLASS_6G_20 = 131,
83 | OP_CLASS_6G_40 = 132,
84 | OP_CLASS_6G_80 = 133,
85 | OP_CLASS_6G_160 = 134
86 | };
87 |
88 | enum wlan_fc_stype_mgmt {
89 | ASSOC_REQ = 0,
90 | ASSOC_RESP = 1,
91 | REASSOC_REQ = 2,
92 | REASSOC_RESP = 3,
93 | PROBE_REQ = 4,
94 | PROBE_RESP = 5,
95 | BEACON = 8,
96 | ATIM = 9,
97 | DISASSOC = 10,
98 | AUTH = 11,
99 | DEAUTH = 12,
100 | ACTION = 13
101 | };
102 |
103 | struct sta_platform_config {
104 | int phymode;
105 | int chwidth;
106 | bool phymode_isset;
107 | bool chwidth_isset;
108 | };
109 |
110 | struct channel_info {
111 | int channel;
112 | int freq;
113 | };
114 |
115 | #define UNUSED_IDENTIFIER -1
116 | struct interface_info {
117 | int identifier; // valid only for multiple VAPs case
118 | int band;
119 | int bssid;
120 | char ifname[16];
121 | char ssid[64];
122 | int mbssid_enable;
123 | int transmitter;
124 | int hapd_bss_id;
125 | char hapd_conf_file[64];
126 | char link_conf_file[64];
127 | int link_id;
128 | int link_band;
129 | };
130 |
131 | struct bss_identifier_info {
132 | int identifier;
133 | int band;
134 | int mbssid_enable;
135 | int transmitter;
136 | int mld_link;
137 | };
138 |
139 | struct loopback_info {
140 | int sock;
141 | double rate;
142 | int pkt_sent;
143 | int pkt_rcv;
144 | int pkt_type;
145 | int pkt_size;
146 | char target_ip[64];
147 | char message[1600];
148 | };
149 |
150 | /* log and file API */
151 | void indigo_logger(int level, const char *fmt, ...);
152 | int pipe_command(char *buffer, int buffer_size, char *cmd, char *parameter[]);
153 | char* read_file(char *fn);
154 | int write_file(char *fn, char *buffer, int len);
155 | int append_file(char *fn, char *buffer, int len);
156 | void open_tc_app_log();
157 | void close_tc_app_log();
158 |
159 | /* network interface and loopback API */
160 | int get_mac_address(char *buffer, int size, char *interface);
161 | int set_mac_address(char *ifname, char *mac);
162 | int find_interface_ip(char *ipaddr, int ipaddr_len, char *name);
163 | int loopback_server_start(char *local_ip, char *local_port, int timeout);
164 | int loopback_server_stop();
165 | int loopback_server_status();
166 | int send_udp_data(char *target_ip, int target_port, int packet_count, int packet_size, double rate);
167 | int stop_loopback_data(int *pkt_sent);
168 | int send_broadcast_arp(char *target_ip, int *send_count, int rate);
169 | int send_icmp_data(char *target_ip, int packet_count, int packet_size, double rate);
170 | char* get_wlans_bridge();
171 | int set_wlans_bridge(char* br);
172 | int is_bridge_created();
173 | int create_bridge(char *br);
174 | int add_interface_to_bridge(char *br, char *interface);
175 | int reset_bridge(char *br);
176 | int control_interface(char *ifname, char *op);
177 | int set_interface_ip(char *ifname, char *ip);
178 | int reset_interface_ip(char *ifname);
179 | int add_wireless_interface(char *ifname);
180 | int delete_wireless_interface(char *ifname);
181 | void bridge_init(char *br);
182 | void detect_del_arp_entry(char *ip);
183 | int add_arp_entry(char *ip, char *mac, char *ifname);
184 |
185 | #define DEBUG_LEVEL_DISABLE 0
186 | #define DEBUG_LEVEL_BASIC 1
187 | #define DEBUG_LEVEL_ADVANCED 2
188 | int get_debug_level(int value);
189 |
190 | /* hostapd API */
191 | char* get_hapd_exec_file();
192 | int set_hapd_exec_file(char* path);
193 | char* get_hapd_full_exec_path();
194 | int set_hapd_full_exec_path(char* path);
195 | char* get_hapd_ctrl_path_by_id(struct interface_info* wlan);
196 | char* get_hapd_ctrl_path();
197 | int set_hapd_ctrl_path(char* path);
198 | char* get_hapd_global_ctrl_path();
199 | int set_hapd_global_ctrl_path(char* path);
200 | char* get_hapd_conf_file();
201 | int set_hapd_conf_file(char* path);
202 | void set_hostapd_debug_level(int level);
203 | char* get_hostapd_debug_arguments();
204 |
205 | /* wpa_supplicant API */
206 | char* get_wpas_exec_file();
207 | int set_wpas_exec_file(char* path);
208 | char* get_wpas_full_exec_path();
209 | int set_wpas_full_exec_path(char* path);
210 | char* get_wpas_ctrl_path();
211 | char* get_wpas_if_ctrl_path(char* if_name);
212 | int set_wpas_ctrl_path(char* path);
213 | char* get_wpas_global_ctrl_path();
214 | int set_wpas_global_ctrl_path(char* path);
215 | char* get_wpas_conf_file();
216 | int set_wpas_conf_file(char* path);
217 | void set_wpas_debug_level(int level);
218 | char* get_wpas_debug_arguments();
219 |
220 | /* service and environment API */
221 | char* get_wireless_interface();
222 | int set_wireless_interface(char *name);
223 | int get_service_port();
224 | int set_service_port(int port);
225 | char* get_default_wireless_interface_info();
226 | int clear_interfaces_resource();
227 | char* get_all_hapd_conf_files(int *swap_hostapd);
228 |
229 | void parse_bss_identifier(int bss_identifier, struct bss_identifier_info* bss);
230 | struct interface_info* assign_wireless_interface_info(struct bss_identifier_info *bss);
231 | struct interface_info* get_wireless_interface_info(int band, int identifier);
232 | struct interface_info* get_first_configured_wireless_interface_info();
233 | int add_all_wireless_interface_to_bridge(char *br);
234 | void set_default_wireless_interface_info(int channel);
235 | int show_wireless_interface_info();
236 | void iterate_all_wlan_interfaces(void (*callback_fn)(void *));
237 | void get_server_cert_hash(char *pem_file, char *buffer);
238 | int insert_wpa_network_config(char *config);
239 | void remove_pac_file(char *path);
240 | int is_band_enabled(int band);
241 |
242 | /* misc */
243 | size_t strlcpy(char *dest, const char *src, size_t siz);
244 | int get_key_value(char *value, char *buffer, char *token);
245 | int verify_band_from_freq(int freq, int band);
246 | int get_center_freq_index(int channel, int width);
247 | int get_6g_center_freq_index(int channel, int width);
248 | int is_ht40plus_chan(int chan);
249 | int is_ht40minus_chan(int chan);
250 | int http_file_post(char *host, int port, char *path, char *file_name);
251 | int file_exists(const char *fname);
252 | #endif
253 |
--------------------------------------------------------------------------------
/vendor_specific.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #ifndef _VENDOR_SPECIFIC_
18 | #define _VENDOR_SPECIFIC_ 1
19 |
20 | /* hostapd definitions */
21 | #ifdef _DUT_
22 | #ifdef _OPENWRT_ /* DUT & OpenWRT */
23 | #define HAPD_EXEC_FILE_DEFAULT "/usr/sbin/hostapd"
24 | #else /* DUT & Laptop */
25 | #define HAPD_EXEC_FILE_DEFAULT "/usr/local/bin/WFA-Hostapd-Supplicant/hostapd"
26 | #endif /* _OPENWRT_ */
27 |
28 | #else /* Platform */
29 | #ifdef _OPENWRT_ /* Platform & OpenWRT */
30 | /* Only OpenWRT + Test Platform, the hostapd path is /usr/sbin/hostapd_udp. */
31 | #define HAPD_EXEC_FILE_DEFAULT "/usr/sbin/hostapd_udp"
32 | #else /* Platform & Laptop */
33 | #define HAPD_EXEC_FILE_DEFAULT "/usr/local/bin/WFA-Hostapd-Supplicant/hostapd_udp"
34 | #endif /* _OPENWRT_ */
35 | #endif /* _DUT_ */
36 | #define HAPD_CTRL_PATH_DEFAULT "/var/run/hostapd"
37 | #define HAPD_GLOBAL_CTRL_PATH_DEFAULT "/var/run/hostapd-global"
38 | #define HAPD_LOG_FILE "/var/log/hostapd.log"
39 |
40 | #ifdef _OPENWRT_
41 | #define HAPD_CONF_FILE_DEFAULT "/tmp/hostapd.conf"
42 | #define HAPD_CONF_FILE_DEFAULT_PATH "/tmp"
43 | #define WPAS_CONF_FILE_DEFAULT "/tmp/wpa_supplicant.conf"
44 | // 2(2.4G): first interface ath1, second interface ath11
45 | // 5(5G): first interface ath0, second interface ath01
46 | #define DEFAULT_APP_INTERFACES_PARAMS "2:ath1,2:ath11,2:ath12,2:ath13,5:ath0,5:ath01,5:ath02,5:ath03"
47 | #define DEFAULT_APP_6E_INTERFACES_PARAMS "6:ath0,6:ath01,6:ath02,6:ath03,5:ath1,5:ath11,5:ath12,5:ath13,2:ath2,2:ath21,2:ath22,2:ath23"
48 | #define WIFI7_PHY_INTERFACE "phy00"
49 |
50 | #else
51 | #define HAPD_CONF_FILE_DEFAULT "/etc/hostapd/hostapd.conf"
52 | #define HAPD_CONF_FILE_DEFAULT_PATH "/etc/hostapd"
53 | #define WPAS_CONF_FILE_DEFAULT "/etc/wpa_supplicant/wpa_supplicant.conf"
54 | // d(2.4G or 5G):Single band can work on 2G or 5G: first interface wlan0, second interface wlan1
55 | #define DEFAULT_APP_INTERFACES_PARAMS "2:wlan0,2:wlan1,5:wlan0,5:wlan1"
56 |
57 | #endif /* _OPENWRT_ */
58 |
59 | /* wpa_supplicant definitions */
60 | #ifdef _DUT_
61 | #define WPAS_EXEC_FILE_DEFAULT "/usr/local/bin/WFA-Hostapd-Supplicant/wpa_supplicant"
62 | #else /* Platform */
63 | #define WPAS_EXEC_FILE_DEFAULT "/usr/local/bin/WFA-Hostapd-Supplicant/wpa_supplicant_udp"
64 | #define WLANTEST_EXEC_FILE_DEFAULT "/usr/local/bin/WFA-Hostapd-Supplicant/wlantest"
65 | #define WLANTEST_CLI_EXEC_FILE_DEFAULT "/usr/local/bin/WFA-Hostapd-Supplicant/wlantest_cli"
66 | #define WLANTEST_LOG_FILE "/tmp/wlantest.log"
67 | #endif /* _DUT_ */
68 | #define WPAS_CTRL_PATH_DEFAULT "/var/run/wpa_supplicant"
69 | #define WPAS_GLOBAL_CTRL_PATH_DEFAULT "/var/run/wpa_supplicant/global" // not use wpas global before
70 | #define WPAS_LOG_FILE "/var/log/supplicant.log"
71 |
72 | #define HS20_OSU_CLIENT "/usr/local/bin/WFA-Hostapd-Supplicant/hs20-osu-client"
73 |
74 | #define WIRELESS_INTERFACE_DEFAULT "wlan0"
75 | #define MONITOR_INTERFACE_DEFAULT "mon0"
76 | #define SERVICE_PORT_DEFAULT 9004
77 |
78 | /* Default bridge for wireless interfaces */
79 | #define BRIDGE_WLANS "br-wlans"
80 |
81 | #ifdef _WTS_OPENWRT_
82 | #define HOSTAPD_SUPPORT_MBSSID 0
83 | #else
84 | /* hostapd support MBSSID with single hostapd conf
85 | * hostapd support "multiple_bssid" configuration
86 | */
87 | #define HOSTAPD_SUPPORT_MBSSID 1
88 |
89 | #endif
90 |
91 | /* Default Tool STA maximum number of cached scan results*/
92 | #define MAX_SCAN_ENTRY 1024
93 |
94 | /* Default DUT GO intent value */
95 | #define P2P_GO_INTENT 7
96 |
97 | #define DHCP_SERVER_IP "192.168.65.1"
98 | void vendor_init();
99 | void vendor_deinit();
100 | void vendor_device_reset();
101 |
102 | #define SAE_PK_FILE_PATH "/vendor/wfa/"
103 |
104 | /**
105 | * wps settings retrieved with vendor-specific operations.
106 | */
107 |
108 | #define WPS_OOB_SSID "ssid"
109 | #define WPS_OOB_AUTH_TYPE "wpa_key_mgmt"
110 | #define WPS_OOB_ENC_TYPE "wpa_pairwise"
111 | #define WPS_OOB_PSK "wpa_passphrase"
112 | #define WPS_OOB_WPA_VER "wpa"
113 | #define WPS_OOB_AP_PIN "ap_pin"
114 | #define WPS_OOB_STATE "wps_state"
115 | #define WPS_CONFIG "config_methods"
116 | #define WPS_DEV_NAME "device_name"
117 | #define WPS_DEV_TYPE "device_type"
118 | #define WPS_MANUFACTURER "manufacturer"
119 | #define WPS_MODEL_NAME "model_name"
120 | #define WPS_MODEL_NUMBER "model_number"
121 | #define WPS_SERIAL_NUMBER "serial_number"
122 |
123 | #define WPS_OOB_NOT_CONFIGURED "1"
124 | #define WPS_OOB_CONFIGURED "2"
125 |
126 | #define SUPPORTED_CONF_METHOD_AP "label keypad push_button virtual_push_button display virtual_display"
127 | #define SUPPORTED_CONF_METHOD_STA "keypad push_button virtual_push_button display virtual_display"
128 |
129 | #define WPS_OOB_ONLY "1"
130 | #define WPS_COMMON "2"
131 |
132 | enum wps_device_role {
133 | WPS_AP,
134 | WPS_STA
135 | };
136 |
137 | #define GROUP_NUM (3)
138 | #define AP_SETTING_NUM (14)
139 | #define STA_SETTING_NUM (6)
140 |
141 | typedef struct _wps_setting {
142 | /* key-value for each setting pair */
143 | char wkey[64];
144 | char value[512];
145 | char attr[64];
146 | } wps_setting;
147 |
148 | #ifdef _TEST_PLATFORM_
149 |
150 | /**
151 | * struct sta_driver_ops - Driver interface API wrapper definition
152 | *
153 | * This structure defines the API that each driver interface needs to implement
154 | * for indigo c control application.
155 | */
156 | struct sta_driver_ops {
157 | const char *name;
158 | int (*set_channel_width)(void);
159 | void (*set_phy_mode)(void);
160 | };
161 |
162 | extern const struct sta_driver_ops sta_driver_platform1_ops;
163 | extern const struct sta_driver_ops sta_driver_platform2_ops;
164 | extern const struct sta_driver_ops sta_driver_platform3_ops;
165 |
166 | /* Generic platform dependent APIs */
167 | int set_channel_width();
168 | void set_phy_mode();
169 | #endif
170 |
171 | #ifdef _OPENWRT_
172 | void openwrt_apply_radio_config(void);
173 | int detect_number_radio(void);
174 | #endif
175 |
176 | void create_sta_interface();
177 | void delete_sta_interface();
178 |
179 | void configure_ap_enable_mbssid();
180 | void configure_ap_radio_params(char *band, char *country, int channel, int chwidth);
181 | void start_ap_set_wlan_params(void *if_info);
182 |
183 | int get_p2p_mac_addr(char *mac_addr, size_t size);
184 | int get_p2p_group_if(char *if_name, size_t size);
185 | int get_p2p_dev_if(char *if_name, size_t size);
186 |
187 | void get_monitor_if(char *if_name, size_t size);
188 |
189 | void start_dhcp_server(char *if_name, char *ip_addr);
190 | void stop_dhcp_server();
191 | void start_dhcp_client(char *if_name);
192 | void stop_dhcp_client();
193 | wps_setting* get_vendor_wps_settings(enum wps_device_role);
194 |
195 | void get_mld_link_mac(char *mac_addr, size_t size, char *band);
196 | #endif
197 |
--------------------------------------------------------------------------------
/vendor_specific_dut.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include "vendor_specific.h"
24 | #include "utils.h"
25 |
26 | #ifdef HOSTAPD_SUPPORT_MBSSID_WAR
27 | extern int use_openwrt_wpad;
28 | #endif
29 |
30 | #if defined(_OPENWRT_)
31 | int detect_number_radio() {
32 | FILE *fp;
33 | char buffer[BUFFER_LEN];
34 | int number_radio = 0;
35 |
36 | fp = popen("iw dev", "r");
37 | if (fp) {
38 | while (fgets(buffer, sizeof(buffer), fp) != NULL) {
39 | if (strstr(buffer, "phy#0") || strstr(buffer, "phy#1") || strstr(buffer, "phy#2"))
40 | number_radio += 1;
41 | }
42 | pclose(fp);
43 | }
44 |
45 | return number_radio;
46 | }
47 | #endif
48 |
49 | void interfaces_init() {
50 | #if defined(_OPENWRT_) && !defined(_WTS_OPENWRT_)
51 | char buffer[BUFFER_LEN];
52 | char mac_addr[S_BUFFER_LEN];
53 | int number_radio = 0;
54 | char phy_name[16];
55 |
56 | number_radio = detect_number_radio();
57 |
58 | memset(buffer, 0, sizeof(buffer));
59 | if (number_radio == 1)
60 | sprintf(phy_name, WIFI7_PHY_INTERFACE);
61 | else
62 | sprintf(phy_name, "phy1");
63 | sprintf(buffer, "iw phy %s interface add ath1 type managed >/dev/null 2>/dev/null", phy_name);
64 | system(buffer);
65 | sprintf(buffer, "iw phy %s interface add ath11 type managed >/dev/null 2>/dev/null", phy_name);
66 | system(buffer);
67 | if (number_radio != 1)
68 | sprintf(phy_name, "phy0");
69 | sprintf(buffer, "iw phy %s interface add ath0 type managed >/dev/null 2>/dev/null", phy_name);
70 | system(buffer);
71 | sprintf(buffer, "iw phy %s interface add ath01 type managed >/dev/null 2>/dev/null", phy_name);
72 | system(buffer);
73 | if (number_radio == 1 || number_radio == 3) {
74 | if (number_radio != 1)
75 | sprintf(phy_name, "phy2");
76 | sprintf(buffer, "iw phy %s interface add ath2 type managed >/dev/null 2>/dev/null", phy_name);
77 | system(buffer);
78 | sprintf(buffer, "iw phy %s interface add ath21 type managed >/dev/null 2>/dev/null", phy_name);
79 | system(buffer);
80 | }
81 |
82 | memset(mac_addr, 0, sizeof(mac_addr));
83 | get_mac_address(mac_addr, sizeof(mac_addr), "ath1");
84 | control_interface("ath1", "down");
85 | mac_addr[16] = (char)'0';
86 | set_mac_address("ath1", mac_addr);
87 |
88 | control_interface("ath11", "down");
89 | mac_addr[16] = (char)'1';
90 | set_mac_address("ath11", mac_addr);
91 |
92 | memset(mac_addr, 0, sizeof(mac_addr));
93 | get_mac_address(mac_addr, sizeof(mac_addr), "ath0");
94 | control_interface("ath0", "down");
95 | if (number_radio == 1)
96 | mac_addr[16] = (char)'4';
97 | else
98 | mac_addr[16] = (char)'0';
99 | set_mac_address("ath0", mac_addr);
100 |
101 | control_interface("ath01", "down");
102 | if (number_radio == 1)
103 | mac_addr[16] = (char)'5';
104 | else
105 | mac_addr[16] = (char)'1';
106 | set_mac_address("ath01", mac_addr);
107 |
108 | if (number_radio == 1 || number_radio == 3) {
109 | memset(mac_addr, 0, sizeof(mac_addr));
110 | get_mac_address(mac_addr, sizeof(mac_addr), "ath2");
111 | control_interface("ath2", "down");
112 | mac_addr[16] = (char)'8';
113 | set_mac_address("ath2", mac_addr);
114 |
115 | control_interface("ath21", "down");
116 | mac_addr[16] = (char)'9';
117 | set_mac_address("ath21", mac_addr);
118 | }
119 | sleep(1);
120 | #endif
121 | }
122 | /* Be invoked when start controlApp */
123 | void vendor_init() {
124 | #if defined(_OPENWRT_) && !defined(_WTS_OPENWRT_)
125 | char buffer[BUFFER_LEN];
126 | char mac_addr[S_BUFFER_LEN];
127 |
128 | /* Vendor: add codes to let ControlApp have full control of hostapd */
129 | /* Avoid hostapd being invoked by procd */
130 | memset(buffer, 0, sizeof(buffer));
131 | sprintf(buffer, "/etc/init.d/wpad stop >/dev/null 2>/dev/null");
132 | system(buffer);
133 |
134 | interfaces_init();
135 | #if HOSTAPD_SUPPORT_MBSSID
136 | #ifdef HOSTAPD_SUPPORT_MBSSID_WAR
137 | system("cp /overlay/hostapd /usr/sbin/hostapd");
138 | use_openwrt_wpad = 0;
139 | #endif
140 | #endif
141 | #endif
142 | }
143 |
144 | /* Be invoked when terminate controlApp */
145 | void vendor_deinit() {
146 | char buffer[S_BUFFER_LEN];
147 | memset(buffer, 0, sizeof(buffer));
148 | sprintf(buffer, "killall %s 1>/dev/null 2>/dev/null", get_hapd_exec_file());
149 | system(buffer);
150 | sprintf(buffer, "killall %s 1>/dev/null 2>/dev/null", get_wpas_exec_file());
151 | system(buffer);
152 | }
153 |
154 | /* Called by reset_device_hander() */
155 | void vendor_device_reset() {
156 | #ifdef _WTS_OPENWRT_
157 | char buffer[S_BUFFER_LEN];
158 |
159 | /* Reset the country code */
160 | snprintf(buffer, sizeof(buffer), "uci -q delete wireless.wifi0.country");
161 | system(buffer);
162 |
163 | snprintf(buffer, sizeof(buffer), "uci -q delete wireless.wifi1.country");
164 | system(buffer);
165 | #endif
166 | #if HOSTAPD_SUPPORT_MBSSID
167 | /* interfaces may be destroyed by hostapd after done the MBSSID testing */
168 | interfaces_init();
169 | #ifdef HOSTAPD_SUPPORT_MBSSID_WAR
170 | if (use_openwrt_wpad > 0) {
171 | system("cp /overlay/hostapd /usr/sbin/hostapd");
172 | use_openwrt_wpad = 0;
173 | }
174 | #endif
175 | #endif
176 | }
177 |
178 | #ifdef _OPENWRT_
179 | void openwrt_apply_radio_config(void) {
180 | char buffer[S_BUFFER_LEN];
181 |
182 | #ifdef _WTS_OPENWRT_
183 | // Apply radio configurations
184 | memset(buffer, 0, sizeof(buffer));
185 | sprintf(buffer, "%s -g /var/run/hostapd/global -B -P /var/run/hostapd-global.pid",
186 | get_hapd_full_exec_path());
187 | system(buffer);
188 | sleep(1);
189 | system("wifi down >/dev/null 2>/dev/null");
190 | sleep(2);
191 | system("wifi up >/dev/null 2>/dev/null");
192 | sleep(3);
193 |
194 | memset(buffer, 0, sizeof(buffer));
195 | sprintf(buffer, "killall %s 1>/dev/null 2>/dev/null", get_hapd_exec_file());
196 | system(buffer);
197 | sleep(2);
198 | #endif
199 | }
200 | #endif
201 |
202 | /* Called by configure_ap_handler() */
203 | void configure_ap_enable_mbssid() {
204 | #ifdef _WTS_OPENWRT_
205 | /*
206 | * the following uci commands need to reboot openwrt
207 | * so it can not be configured by controlApp
208 | *
209 | * Manually enable MBSSID on OpenWRT when need to test MBSSID
210 | *
211 | system("uci set wireless.qcawifi=qcawifi");
212 | system("uci set wireless.qcawifi.mbss_ie_enable=1");
213 | system("uci commit");
214 | */
215 | #elif defined(_OPENWRT_)
216 | #ifdef HOSTAPD_SUPPORT_MBSSID_WAR
217 | system("cp /rom/usr/sbin/wpad /usr/sbin/hostapd");
218 | use_openwrt_wpad = 1;
219 | #endif
220 | #endif
221 | }
222 |
223 | void configure_ap_radio_params(char *band, char *country, int channel, int chwidth) {
224 | #ifdef _WTS_OPENWRT
225 | char buffer[S_BUFFER_LEN], wifi_name[16];
226 |
227 | if (!strncmp(band, "a", 1)) {
228 | snprintf(wifi_name, sizeof(wifi_name), "wifi0");
229 | } else {
230 | snprintf(wifi_name, sizeof(wifi_name), "wifi1");
231 | }
232 |
233 | if (strlen(country) > 0) {
234 | snprintf(buffer, sizeof(buffer), "uci set wireless.%s.country=\'%s\'", wifi_name, country);
235 | system(buffer);
236 | }
237 |
238 | snprintf(buffer, sizeof(buffer), "uci set wireless.%s.channel=\'%d\'", wifi_name, channel);
239 | system(buffer);
240 |
241 | if (!strncmp(band, "a", 1)) {
242 | if (channel == 165) { // Force 20M for CH 165
243 | snprintf(buffer, sizeof(buffer), "uci set wireless.wifi0.htmode=\'HT20\'");
244 | } else if (chwidth == 2) { // 160M test cases only
245 | snprintf(buffer, sizeof(buffer), "uci set wireless.wifi0.htmode=\'HT160\'");
246 | } else if (chwidth == 0) { // 11N only
247 | snprintf(buffer, sizeof(buffer), "uci set wireless.wifi0.htmode=\'HT40\'");
248 | } else { // 11AC or 11AX
249 | snprintf(buffer, sizeof(buffer), "uci set wireless.wifi0.htmode=\'HT80\'");
250 | }
251 | system(buffer);
252 | }
253 |
254 | system("uci commit");
255 | #endif
256 | }
257 |
258 | /* void (*callback_fn)(void *), callback of active wlans iterator
259 | *
260 | * Called by start_ap_handler() after invoking hostapd
261 | */
262 | void start_ap_set_wlan_params(void *if_info) {
263 | char buffer[S_BUFFER_LEN];
264 | struct interface_info *wlan = (struct interface_info *) if_info;
265 |
266 | memset(buffer, 0, sizeof(buffer));
267 | #ifdef _WTS_OPENWRT_
268 | /* Workaround: openwrt has IOT issue with intel AX210 AX mode */
269 | sprintf(buffer, "cfg80211tool %s he_ul_ofdma 0", wlan->ifname);
270 | system(buffer);
271 | /* Avoid target assert during channel switch */
272 | sprintf(buffer, "cfg80211tool %s he_ul_mimo 0", wlan->ifname);
273 | system(buffer);
274 | sprintf(buffer, "cfg80211tool %s twt_responder 0", wlan->ifname);
275 | system(buffer);
276 | #endif
277 | printf("set_wlan_params: %s\n", buffer);
278 | }
279 |
280 | /* Return addr of P2P-device if there is no GO or client interface */
281 | int get_p2p_mac_addr(char *mac_addr, size_t size) {
282 | FILE *fp;
283 | char buffer[S_BUFFER_LEN], *ptr, addr[32];
284 | int error = 1, match = 0;
285 |
286 | fp = popen("iw dev", "r");
287 | if (fp) {
288 | while (fgets(buffer, sizeof(buffer), fp) != NULL) {
289 | ptr = strstr(buffer, "addr");
290 | if (ptr != NULL) {
291 | sscanf(ptr, "%*s %s", addr);
292 | while (fgets(buffer, sizeof(buffer), fp) != NULL) {
293 | ptr = strstr(buffer, "type");
294 | if (ptr != NULL) {
295 | ptr += 5;
296 | if (!strncmp(ptr, "P2P-GO", 6) || !strncmp(ptr, "P2P-client", 10)) {
297 | snprintf(mac_addr, size, "%s", addr);
298 | error = 0;
299 | match = 1;
300 | } else if (!strncmp(ptr, "P2P-device", 10)) {
301 | snprintf(mac_addr, size, "%s", addr);
302 | error = 0;
303 | }
304 | break;
305 | }
306 | }
307 | if (match)
308 | break;
309 | }
310 | }
311 | pclose(fp);
312 | }
313 |
314 | return error;
315 | }
316 |
317 | /* Get the name of P2P Group(GO or Client) interface */
318 | int get_p2p_group_if(char *if_name, size_t size) {
319 | FILE *fp;
320 | char buffer[S_BUFFER_LEN], *ptr, name[32];
321 | int error = 1;
322 |
323 | fp = popen("iw dev", "r");
324 | if (fp) {
325 | while (fgets(buffer, sizeof(buffer), fp) != NULL) {
326 | ptr = strstr(buffer, "Interface");
327 | if (ptr != NULL) {
328 | sscanf(ptr, "%*s %s", name);
329 | while (fgets(buffer, sizeof(buffer), fp) != NULL) {
330 | ptr = strstr(buffer, "type");
331 | if (ptr != NULL) {
332 | ptr += 5;
333 | if (!strncmp(ptr, "P2P-GO", 6) || !strncmp(ptr, "P2P-client", 10)) {
334 | snprintf(if_name, size, "%s", name);
335 | error = 0;
336 | }
337 | break;
338 | }
339 | }
340 | if (!error)
341 | break;
342 | }
343 | }
344 | pclose(fp);
345 | }
346 |
347 | return error;
348 | }
349 |
350 | /* "iw dev" doesn't show the name of P2P device. The naming rule is based on wpa_supplicant */
351 | int get_p2p_dev_if(char *if_name, size_t size) {
352 | snprintf(if_name, size, "p2p-dev-%s", get_wireless_interface());
353 |
354 | return 0;
355 | }
356 |
357 | /* Append IP range config and start dhcpd */
358 | void start_dhcp_server(char *if_name, char *ip_addr)
359 | {
360 | char buffer[S_BUFFER_LEN];
361 | char ip_sub[32], *ptr;
362 | FILE *fp;
363 |
364 | /* Avoid using system dhcp server service
365 | snprintf(buffer, sizeof(buffer), "sed -i -e 's/INTERFACESv4=\".*\"/INTERFACESv4=\"%s\"/g' /etc/default/isc-dhcp-server", if_name);
366 | system(buffer);
367 | snprintf(buffer, sizeof(buffer), "systemctl restart isc-dhcp-server.service");
368 | system(buffer);
369 | */
370 | /* Sample command from isc-dhcp-server: dhcpd -user dhcpd -group dhcpd -f -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf p2p-wlp2s0-0 */
371 |
372 | /* Avoid apparmor check because we manually start dhcpd */
373 | memset(ip_sub, 0, sizeof(ip_sub));
374 | ptr = strrchr(ip_addr, '.');
375 | memcpy(ip_sub, ip_addr, ptr - ip_addr);
376 | system("cp QT_dhcpd.conf /etc/dhcp/QT_dhcpd.conf");
377 | fp = fopen("/etc/dhcp/QT_dhcpd.conf", "a");
378 | if (fp) {
379 | snprintf(buffer, sizeof(buffer), "\nsubnet %s.0 netmask 255.255.255.0 {\n", ip_sub);
380 | fputs(buffer, fp);
381 | snprintf(buffer, sizeof(buffer), " range %s.50 %s.200;\n", ip_sub, ip_sub);
382 | fputs(buffer, fp);
383 | fputs("}\n", fp);
384 | fclose(fp);
385 | }
386 | system("touch /var/lib/dhcp/dhcpd.leases_QT");
387 | snprintf(buffer, sizeof(buffer), "dhcpd -4 -cf /etc/dhcp/QT_dhcpd.conf -lf /var/lib/dhcp/dhcpd.leases_QT %s", if_name);
388 | system(buffer);
389 | }
390 |
391 | void stop_dhcp_server()
392 | {
393 | /* system("systemctl stop isc-dhcp-server.service"); */
394 | system("killall dhcpd 1>/dev/null 2>/dev/null");
395 | }
396 |
397 | void start_dhcp_client(char *if_name)
398 | {
399 | char buffer[S_BUFFER_LEN];
400 |
401 | snprintf(buffer, sizeof(buffer), "dhclient -4 %s &", if_name);
402 | system(buffer);
403 | }
404 |
405 | void stop_dhcp_client()
406 | {
407 | system("killall dhclient 1>/dev/null 2>/dev/null");
408 | }
409 |
410 | wps_setting *p_wps_setting = NULL;
411 | wps_setting customized_wps_settings_ap[AP_SETTING_NUM];
412 | wps_setting customized_wps_settings_sta[STA_SETTING_NUM];
413 |
414 | void save_wsc_setting(wps_setting *s, char *entry, int len)
415 | {
416 | char *p = NULL;
417 |
418 | p = strchr(entry, '\n');
419 | if (p)
420 | p++;
421 | else
422 | p = entry;
423 |
424 | sscanf(p, "%[^:]:%[^:]:%s", s->wkey, s->value, s->attr);
425 | }
426 |
427 | wps_setting* __get_wps_setting(int len, char *buffer, enum wps_device_role role)
428 | {
429 | char *token = strtok(buffer , ",");
430 | wps_setting *s = NULL;
431 | int i = 0;
432 |
433 | if (role == WPS_AP) {
434 | memset(customized_wps_settings_ap, 0, sizeof(customized_wps_settings_ap));
435 | p_wps_setting = customized_wps_settings_ap;
436 | while (token != NULL) {
437 | s = &p_wps_setting[i++];
438 | save_wsc_setting(s, token, strlen(token));
439 | token = strtok(NULL, ",");
440 | }
441 | } else {
442 | memset(customized_wps_settings_sta, 0, sizeof(customized_wps_settings_sta));
443 | p_wps_setting = customized_wps_settings_sta;
444 | while (token != NULL) {
445 | s = &p_wps_setting[i++];
446 | save_wsc_setting(s, token, strlen(token));
447 | token = strtok(NULL, ",");
448 | }
449 | }
450 | return p_wps_setting;
451 | }
452 |
453 | wps_setting* get_vendor_wps_settings(enum wps_device_role role)
454 | {
455 | /*
456 | * Please implement the vendor proprietary function to get WPS OOB and required settings.
457 | * */
458 | #define WSC_SETTINGS_FILE_AP "/tmp/wsc_settings_APUT"
459 | #define WSC_SETTINGS_FILE_STA "/tmp/wsc_settings_STAUT"
460 | int len = 0, is_valid = 0;
461 | char pipebuf[S_BUFFER_LEN];
462 | char *parameter_ap[] = {"cat", WSC_SETTINGS_FILE_AP, NULL, NULL};
463 | char *parameter_sta[] = {"cat", WSC_SETTINGS_FILE_STA, NULL, NULL};
464 |
465 | memset(pipebuf, 0, sizeof(pipebuf));
466 | if (role == WPS_AP) {
467 | if (0 == access(WSC_SETTINGS_FILE_AP, F_OK)) {
468 | // use customized ap wsc settings
469 | #ifdef _OPENWRT_
470 | len = pipe_command(pipebuf, sizeof(pipebuf), "/bin/cat", parameter_ap);
471 | #else
472 | len = pipe_command(pipebuf, sizeof(pipebuf), "/usr/bin/cat", parameter_ap);
473 | #endif
474 | if (len) {
475 | indigo_logger(LOG_LEVEL_INFO, "wsc settings APUT:\n %s", pipebuf);
476 | return __get_wps_setting(len, pipebuf, WPS_AP);
477 | } else {
478 | indigo_logger(LOG_LEVEL_INFO, "wsc settings APUT: no data");
479 | }
480 | } else {
481 | indigo_logger(LOG_LEVEL_ERROR, "APUT: WPS Erorr. Failed to get settings.");
482 | return NULL;
483 | }
484 | } else {
485 | if (0 == access(WSC_SETTINGS_FILE_STA, F_OK)) {
486 | // use customized sta wsc settings
487 | len = pipe_command(pipebuf, sizeof(pipebuf), "/usr/bin/cat", parameter_sta);
488 | if (len) {
489 | indigo_logger(LOG_LEVEL_INFO, "wsc settings STAUT:\n %s", pipebuf);
490 | return __get_wps_setting(len, pipebuf, WPS_STA);
491 | } else {
492 | indigo_logger(LOG_LEVEL_INFO, "wsc settings STAUT: no data");
493 | }
494 | } else {
495 | indigo_logger(LOG_LEVEL_ERROR, "STAUT: WPS Erorr. Failed to get settings.");
496 | return NULL;
497 | }
498 | }
499 | }
500 |
501 | void get_mld_link_mac(char *mac_addr, size_t size, char *band) {
502 | FILE *fp;
503 | char buffer[S_BUFFER_LEN], *ptr, name[32], addr[32];
504 | char *if_name;
505 | int band_id, freq;
506 |
507 | memset(mac_addr, 0, size);
508 | if (strcmp(band, "2.4GHz") == 0)
509 | band_id = BAND_24GHZ;
510 | else if (strcmp(band, "5GHz") == 0)
511 | band_id = BAND_5GHZ;
512 | else if (strcmp(band, "6GHz") == 0)
513 | band_id = BAND_6GHZ;
514 | if_name = get_wireless_interface();
515 |
516 | fp = popen("iw dev", "r");
517 | if (fp) {
518 | while (fgets(buffer, sizeof(buffer), fp) != NULL) {
519 | ptr = strstr(buffer, "Interface");
520 | if (ptr != NULL) {
521 | sscanf(ptr, "%*s %s", name);
522 | if (!strncmp(name, if_name, strlen(if_name))) {
523 | /* link 0:
524 | addr 00:03:7f:12:66:60
525 | channel 36 (5180 MHz), width: 80 MHz, center1: 5210 MHz
526 | txpower 28.00 dBm
527 | */
528 | while (fgets(buffer, sizeof(buffer), fp) != NULL) {
529 | ptr = strstr(buffer, "link");
530 | if (ptr != NULL) {
531 | fgets(buffer, sizeof(buffer), fp);
532 | sscanf(buffer, "%*s %s", addr);
533 | fgets(buffer, sizeof(buffer), fp);
534 | ptr = strchr(buffer, '(');
535 | sscanf(ptr+1, "%d", &freq);
536 | if (verify_band_from_freq(freq, band_id) == 0) {
537 | snprintf(mac_addr, size, "%s", addr);
538 | break;
539 | }
540 | }
541 | }
542 | if (mac_addr[0])
543 | break;
544 | }
545 | }
546 | }
547 | pclose(fp);
548 | }
549 |
550 | return;
551 | }
552 |
--------------------------------------------------------------------------------
/vendor_specific_sniffer.c:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 Wi-Fi Alliance */
2 |
3 | /* Permission to use, copy, modify, and/or distribute this software for any */
4 | /* purpose with or without fee is hereby granted, provided that the above */
5 | /* copyright notice and this permission notice appear in all copies. */
6 |
7 | /* THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL */
8 | /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
9 | /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL */
10 | /* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR */
11 | /* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING */
12 | /* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF */
13 | /* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT */
14 | /* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */
15 | /* SOFTWARE. */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include "vendor_specific.h"
24 | #include "utils.h"
25 |
26 | #ifdef _TEST_SNIFFER_
27 | /**
28 | * Generic platform dependent API implementation
29 | */
30 |
31 | void interfaces_init() {
32 | char buffer[BUFFER_LEN];
33 |
34 | memset(buffer, 0, sizeof(buffer));
35 | sprintf(buffer, "iw phy phy0 interface add mon0 type monitor >/dev/null 2>/dev/null");
36 | system(buffer);
37 |
38 | sleep(1);
39 | }
40 |
41 | /* Be invoked when start controlApp */
42 | void vendor_init() {
43 | interfaces_init();
44 | }
45 |
46 | /* Be invoked when terminate controlApp */
47 | void vendor_deinit() {
48 | char buffer[S_BUFFER_LEN];
49 | memset(buffer, 0, sizeof(buffer));
50 | system("iw dev mon0 del >/dev/null 2>/dev/null");
51 | }
52 |
53 | #endif /* _TEST_SNIFFER_ */
54 |
--------------------------------------------------------------------------------
/wpa_ctrl.c:
--------------------------------------------------------------------------------
1 | /*
2 | * wpa_supplicant/hostapd control interface library
3 | * Copyright (c) 2004-2005, Jouni Malinen
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License version 2 as
7 | * published by the Free Software Foundation.
8 | *
9 | * Alternatively, this software may be distributed under the terms of BSD
10 | * license.
11 | *
12 | * See README and COPYING for more details.
13 | */
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #ifndef CONFIG_NATIVE_WINDOWS
23 | #include
24 | #include
25 | #include
26 | #endif /* CONFIG_NATIVE_WINDOWS */
27 |
28 | #include "vendor_specific.h"
29 | #include "wpa_ctrl.h"
30 | #include "utils.h"
31 | #ifdef CONFIG_NATIVE_WINDOWS
32 | #include "common.h"
33 | #endif /* CONFIG_NATIVE_WINDOWS */
34 |
35 |
36 | /**
37 | * struct wpa_ctrl - Internal structure for control interface library
38 | *
39 | * This structure is used by the wpa_supplicant/hostapd control interface
40 | * library to store internal data. Programs using the library should not touch
41 | * this data directly. They can only use the pointer to the data structure as
42 | * an identifier for the control interface connection and use this as one of
43 | * the arguments for most of the control interface library functions.
44 | */
45 | struct wpa_ctrl {
46 | int s;
47 | #ifdef CONFIG_CTRL_IFACE_UDP
48 | struct sockaddr_in local;
49 | struct sockaddr_in dest;
50 | char *cookie;
51 | #else /* CONFIG_CTRL_IFACE_UDP */
52 | struct sockaddr_un local;
53 | struct sockaddr_un dest;
54 | #endif /* CONFIG_CTRL_IFACE_UDP */
55 | };
56 |
57 |
58 | struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
59 | {
60 | struct wpa_ctrl *ctrl;
61 | #ifndef CONFIG_CTRL_IFACE_UDP
62 | static int counter = 0;
63 | #else
64 | unsigned short port = 0;
65 | char buf[128];
66 | size_t len;
67 | #endif /* CONFIG_CTRL_IFACE_UDP */
68 |
69 | ctrl = malloc(sizeof(*ctrl));
70 | if (ctrl == NULL)
71 | return NULL;
72 | memset(ctrl, 0, sizeof(*ctrl));
73 |
74 | #ifdef CONFIG_CTRL_IFACE_UDP
75 | ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
76 | if (ctrl->s < 0) {
77 | perror("socket");
78 | free(ctrl);
79 | return NULL;
80 | }
81 |
82 | ctrl->local.sin_family = AF_INET;
83 | #ifdef CONFIG_CTRL_IFACE_UDP
84 | ctrl->local.sin_addr.s_addr = INADDR_ANY;
85 | #else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
86 | ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
87 | #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
88 | if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
89 | sizeof(ctrl->local)) < 0) {
90 | close(ctrl->s);
91 | free(ctrl);
92 | return NULL;
93 | }
94 |
95 | sscanf(ctrl_path, "udp:%hu", &port);
96 |
97 | ctrl->dest.sin_family = AF_INET;
98 | ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
99 | ctrl->dest.sin_port = htons(port);
100 | if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
101 | sizeof(ctrl->dest)) < 0) {
102 | perror("connect");
103 | close(ctrl->s);
104 | free(ctrl);
105 | return NULL;
106 | }
107 |
108 | len = sizeof(buf) - 1;
109 | if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
110 | buf[len] = '\0';
111 | ctrl->cookie = strdup(buf);
112 | printf("%s\n\n", ctrl->cookie);
113 | }
114 | #else /* CONFIG_CTRL_IFACE_UDP */
115 | ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
116 | if (ctrl->s < 0) {
117 | free(ctrl);
118 | return NULL;
119 | }
120 |
121 | ctrl->local.sun_family = AF_UNIX;
122 | snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
123 | "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
124 | if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
125 | sizeof(ctrl->local)) < 0) {
126 | close(ctrl->s);
127 | free(ctrl);
128 | return NULL;
129 | }
130 |
131 | ctrl->dest.sun_family = AF_UNIX;
132 | snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s",
133 | ctrl_path);
134 | if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
135 | sizeof(ctrl->dest)) < 0) {
136 | close(ctrl->s);
137 | unlink(ctrl->local.sun_path);
138 | free(ctrl);
139 | return NULL;
140 | }
141 | #endif /* CONFIG_CTRL_IFACE_UDP */
142 |
143 | return ctrl;
144 | }
145 |
146 |
147 | void wpa_ctrl_close(struct wpa_ctrl *ctrl)
148 | {
149 | #ifndef CONFIG_CTRL_IFACE_UDP
150 | unlink(ctrl->local.sun_path);
151 | #else
152 | if (ctrl->cookie)
153 | free(ctrl->cookie);
154 | #endif /* CONFIG_CTRL_IFACE_UDP */
155 | close(ctrl->s);
156 | free(ctrl);
157 | }
158 |
159 |
160 | int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
161 | char *reply, size_t *reply_len,
162 | void (*msg_cb)(char *msg, size_t len))
163 | {
164 | struct timeval tv;
165 | int res;
166 | fd_set rfds;
167 | const char *_cmd;
168 | char *cmd_buf = NULL;
169 | size_t _cmd_len;
170 |
171 | #ifdef CONFIG_CTRL_IFACE_UDP
172 | if (ctrl->cookie) {
173 | char *pos;
174 | _cmd_len = strlen(ctrl->cookie) + 1 + cmd_len;
175 | cmd_buf = malloc(_cmd_len);
176 | if (cmd_buf == NULL)
177 | return -1;
178 | _cmd = cmd_buf;
179 | pos = cmd_buf;
180 | strlcpy(pos, ctrl->cookie, _cmd_len);
181 | pos += strlen(ctrl->cookie);
182 | *pos++ = ' ';
183 | memcpy(pos, cmd, cmd_len);
184 | } else
185 | #endif /* CONFIG_CTRL_IFACE_UDP */
186 | {
187 | _cmd = cmd;
188 | _cmd_len = cmd_len;
189 | }
190 |
191 | if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
192 | return -1;
193 | }
194 |
195 | for (;;) {
196 | tv.tv_sec = 2;
197 | tv.tv_usec = 0;
198 | FD_ZERO(&rfds);
199 | FD_SET(ctrl->s, &rfds);
200 | res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
201 | if (FD_ISSET(ctrl->s, &rfds)) {
202 | res = recv(ctrl->s, reply, *reply_len, 0);
203 | if (res < 0 && errno == EINTR) {
204 | continue;
205 | }
206 | if (res < 0) {
207 | return res;
208 | }
209 | if (res > 0 && reply[0] == '<') {
210 | /* This is an unsolicited message from
211 | * wpa_supplicant, not the reply to the
212 | * request. Use msg_cb to report this to the
213 | * caller. */
214 | if (msg_cb) {
215 | /* Make sure the message is nul
216 | * terminated. */
217 | if ((size_t) res == *reply_len)
218 | res = (*reply_len) - 1;
219 | reply[res] = '\0';
220 | msg_cb(reply, res);
221 | }
222 | continue;
223 | }
224 | *reply_len = res;
225 | break;
226 | } else {
227 | return -2;
228 | }
229 | }
230 | return 0;
231 | }
232 |
233 |
234 | static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
235 | {
236 | char buf[10];
237 | int ret;
238 | size_t len = 10;
239 |
240 | ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
241 | buf, &len, NULL);
242 | if (ret < 0)
243 | return ret;
244 | if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
245 | return 0;
246 | return -1;
247 | }
248 |
249 |
250 | int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
251 | {
252 | return wpa_ctrl_attach_helper(ctrl, 1);
253 | }
254 |
255 |
256 | int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
257 | {
258 | return wpa_ctrl_attach_helper(ctrl, 0);
259 | }
260 |
261 |
262 | int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
263 | {
264 | int res;
265 |
266 | res = recv(ctrl->s, reply, *reply_len, 0);
267 | if (res < 0)
268 | return res;
269 | *reply_len = res;
270 | return 0;
271 | }
272 |
273 |
274 | int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
275 | {
276 | struct timeval tv;
277 | int res;
278 | fd_set rfds;
279 | tv.tv_sec = 0;
280 | tv.tv_usec = 0;
281 | FD_ZERO(&rfds);
282 | FD_SET(ctrl->s, &rfds);
283 | res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
284 | return FD_ISSET(ctrl->s, &rfds);
285 | }
286 |
287 |
288 | int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
289 | {
290 | return ctrl->s;
291 | }
292 |
--------------------------------------------------------------------------------
/wpa_ctrl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * wpa_supplicant/hostapd control interface library
3 | * Copyright (c) 2004-2005, Jouni Malinen
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License version 2 as
7 | * published by the Free Software Foundation.
8 | *
9 | * Alternatively, this software may be distributed under the terms of BSD
10 | * license.
11 | *
12 | * See README and COPYING for more details.
13 | */
14 |
15 | #ifndef WPA_CTRL_H
16 | #define WPA_CTRL_H
17 |
18 | #ifdef __cplusplus
19 | extern "C" {
20 | #endif
21 |
22 | /* wpa_supplicant control interface - fixed message prefixes */
23 |
24 | /** Interactive request for identity/password/pin */
25 | #define WPA_CTRL_REQ "CTRL-REQ-"
26 |
27 | /** Response to identity/password/pin request */
28 | #define WPA_CTRL_RSP "CTRL-RSP-"
29 |
30 | /* Event messages with fixed prefix */
31 | /** Authentication completed successfully and data connection enabled */
32 | #define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED "
33 | /** Disconnected, data connection is not available */
34 | #define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED "
35 | /** wpa_supplicant is exiting */
36 | #define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
37 | /** Password change was completed successfully */
38 | #define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED "
39 | /** EAP-Request/Notification received */
40 | #define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION "
41 | /** EAP authentication started (EAP-Request/Identity received) */
42 | #define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED "
43 | /** EAP method selected */
44 | #define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD "
45 | /** EAP authentication completed successfully */
46 | #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
47 | /** EAP authentication failed (EAP-Failure received) */
48 | #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
49 |
50 |
51 | /* wpa_supplicant/hostapd control interface access */
52 |
53 | /**
54 | * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd
55 | * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
56 | * Returns: Pointer to abstract control interface data or %NULL on failure
57 | *
58 | * This function is used to open a control interface to wpa_supplicant/hostapd.
59 | * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path
60 | * is configured in wpa_supplicant/hostapd and other programs using the control
61 | * interface need to use matching path configuration.
62 | */
63 | struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
64 |
65 |
66 | /**
67 | * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd
68 | * @ctrl: Control interface data from wpa_ctrl_open()
69 | *
70 | * This function is used to close a control interface.
71 | */
72 | void wpa_ctrl_close(struct wpa_ctrl *ctrl);
73 |
74 |
75 | /**
76 | * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd
77 | * @ctrl: Control interface data from wpa_ctrl_open()
78 | * @cmd: Command; usually, ASCII text, e.g., "PING"
79 | * @cmd_len: Length of the cmd in bytes
80 | * @reply: Buffer for the response
81 | * @reply_len: Reply buffer length
82 | * @msg_cb: Callback function for unsolicited messages or %NULL if not used
83 | * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout
84 | *
85 | * This function is used to send commands to wpa_supplicant/hostapd. Received
86 | * response will be written to reply and reply_len is set to the actual length
87 | * of the reply. This function will block for up to two seconds while waiting
88 | * for the reply. If unsolicited messages are received, the blocking time may
89 | * be longer.
90 | *
91 | * msg_cb can be used to register a callback function that will be called for
92 | * unsolicited messages received while waiting for the command response. These
93 | * messages may be received if wpa_ctrl_request() is called at the same time as
94 | * wpa_supplicant/hostapd is sending such a message. This can happen only if
95 | * the program has used wpa_ctrl_attach() to register itself as a monitor for
96 | * event messages. Alternatively to msg_cb, programs can register two control
97 | * interface connections and use one of them for commands and the other one for
98 | * receiving event messages, in other words, call wpa_ctrl_attach() only for
99 | * the control interface connection that will be used for event messages.
100 | */
101 | int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
102 | char *reply, size_t *reply_len,
103 | void (*msg_cb)(char *msg, size_t len));
104 |
105 |
106 | /**
107 | * wpa_ctrl_attach - Register as an event monitor for the control interface
108 | * @ctrl: Control interface data from wpa_ctrl_open()
109 | * Returns: 0 on success, -1 on failure, -2 on timeout
110 | *
111 | * This function registers the control interface connection as a monitor for
112 | * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the
113 | * control interface connection starts receiving event messages that can be
114 | * read with wpa_ctrl_recv().
115 | */
116 | int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
117 |
118 |
119 | /**
120 | * wpa_ctrl_detach - Unregister event monitor from the control interface
121 | * @ctrl: Control interface data from wpa_ctrl_open()
122 | * Returns: 0 on success, -1 on failure, -2 on timeout
123 | *
124 | * This function unregisters the control interface connection as a monitor for
125 | * wpa_supplicant/hostapd events, i.e., cancels the registration done with
126 | * wpa_ctrl_attach().
127 | */
128 | int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
129 |
130 |
131 | /**
132 | * wpa_ctrl_recv - Receive a pending control interface message
133 | * @ctrl: Control interface data from wpa_ctrl_open()
134 | * @reply: Buffer for the message data
135 | * @reply_len: Length of the reply buffer
136 | * Returns: 0 on success, -1 on failure
137 | *
138 | * This function will receive a pending control interface message. This
139 | * function will block if no messages are available. The received response will
140 | * be written to reply and reply_len is set to the actual length of the reply.
141 | * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach()
142 | * must have been used to register the control interface as an event monitor.
143 | */
144 | int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
145 |
146 |
147 | /**
148 | * wpa_ctrl_pending - Check whether there are pending event messages
149 | * @ctrl: Control interface data from wpa_ctrl_open()
150 | * Returns: Non-zero if there are pending messages
151 | *
152 | * This function will check whether there are any pending control interface
153 | * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is
154 | * only used for event messages, i.e., wpa_ctrl_attach() must have been used to
155 | * register the control interface as an event monitor.
156 | */
157 | int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
158 |
159 |
160 | /**
161 | * wpa_ctrl_get_fd - Get file descriptor used by the control interface
162 | * @ctrl: Control interface data from wpa_ctrl_open()
163 | * Returns: File descriptor used for the connection
164 | *
165 | * This function can be used to get the file descriptor that is used for the
166 | * control interface connection. The returned value can be used, e.g., with
167 | * select() while waiting for multiple events.
168 | *
169 | * The returned file descriptor must not be used directly for sending or
170 | * receiving packets; instead, the library functions wpa_ctrl_request() and
171 | * wpa_ctrl_recv() must be used for this.
172 | */
173 | int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
174 |
175 | #ifdef CONFIG_CTRL_IFACE_UDP
176 | #define WPA_CTRL_IFACE_PORT 9877
177 | #define WPA_GLOBAL_CTRL_IFACE_PORT 9878
178 | #endif /* CONFIG_CTRL_IFACE_UDP */
179 |
180 |
181 | #ifdef __cplusplus
182 | }
183 | #endif
184 |
185 | #endif /* WPA_CTRL_H */
186 |
--------------------------------------------------------------------------------