blob: f86e2baaee4265aa4667a629c0c5c7423788b6c9 [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * Sigma Control API DUT (station/AP)
3 * Copyright (c) 2010, Atheros Communications, Inc.
Jouni Malinen9d7e31d2017-12-22 18:55:04 +02004 * Copyright (c) 2011-2014, 2016-2017, Qualcomm Atheros, Inc.
Jouni Malinen2feb9132021-11-16 00:53:06 +02005 * Copyright (c) 2019-2020, The Linux Foundation
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006 * All Rights Reserved.
7 * Licensed under the Clear BSD license. See README for more details.
8 */
9
10#include "sigma_dut.h"
11#ifdef __linux__
12#include <sys/stat.h>
Alexei Avshalom Lazar9b85c412019-01-31 15:20:52 +020013#include <linux/ethtool.h>
14#include <linux/netlink.h>
15#include <linux/sockios.h>
Jouni Malinencd4e3c32015-10-29 12:39:56 +020016#endif /* __linux__ */
17#include "wpa_helpers.h"
Alexei Avshalom Lazar9b85c412019-01-31 15:20:52 +020018#include <sys/ioctl.h>
Jouni Malinencd4e3c32015-10-29 12:39:56 +020019
20
Jouni Malinencd444902019-02-19 01:20:45 +020021static enum sigma_cmd_result cmd_ca_get_version(struct sigma_dut *dut,
22 struct sigma_conn *conn,
23 struct sigma_cmd *cmd)
Jouni Malinencd4e3c32015-10-29 12:39:56 +020024{
25 const char *info;
26
27 info = get_param(cmd, "TestInfo");
28 if (info) {
29 char buf[200];
30 snprintf(buf, sizeof(buf), "NOTE CAPI:TestInfo:%s", info);
Jouni Malinen016ae6c2019-11-04 17:00:01 +020031 wpa_command(get_main_ifname(dut), buf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +020032 }
33
34 send_resp(dut, conn, SIGMA_COMPLETE, "version,1.0");
Jouni Malinencd444902019-02-19 01:20:45 +020035 return STATUS_SENT;
Jouni Malinencd4e3c32015-10-29 12:39:56 +020036}
37
38
39#ifdef __linux__
40
41static void first_line(char *s)
42{
43 while (*s) {
44 if (*s == '\r' || *s == '\n') {
45 *s = '\0';
46 return;
47 }
48 s++;
49 }
50}
51
52
Jouni Malinenc54710d2019-01-23 12:34:21 +020053void get_ver(const char *cmd, char *buf, size_t buflen)
Jouni Malinencd4e3c32015-10-29 12:39:56 +020054{
55 FILE *f;
56 char *pos;
57
58 buf[0] = '\0';
59 f = popen(cmd, "r");
60 if (f == NULL)
61 return;
62 if (fgets(buf, buflen, f))
63 first_line(buf);
64 pclose(f);
65
66 pos = strstr(buf, " v");
67 if (pos == NULL)
68 buf[0] = '\0';
69 else
70 memmove(buf, pos + 1, strlen(pos));
71}
72
73#endif /* __linux__ */
74
75
Jouni Malinencd444902019-02-19 01:20:45 +020076static enum sigma_cmd_result cmd_device_get_info(struct sigma_dut *dut,
77 struct sigma_conn *conn,
78 struct sigma_cmd *cmd)
Jouni Malinencd4e3c32015-10-29 12:39:56 +020079{
Jouni Malinen5db3b102016-08-04 12:27:18 +030080 const char *vendor = "Qualcomm Atheros";
Jouni Malinencd4e3c32015-10-29 12:39:56 +020081 const char *model = "N/A";
82 const char *version = "N/A";
83#ifdef __linux__
84 char model_buf[128];
Vamsi Krishna5f4e0032019-11-18 22:35:57 +053085 char ver_buf[512];
Jouni Malinencd4e3c32015-10-29 12:39:56 +020086#endif /* __linux__ */
Jouni Malinen77dda642020-01-07 11:21:55 +020087 int res;
Pradeep Reddy Potteti551b9862017-01-24 17:09:44 +053088 char resp[512];
Jouni Malinencd4e3c32015-10-29 12:39:56 +020089
90#ifdef __linux__
91 {
Jouni Malinene39cd562019-05-29 23:39:56 +030092 char fname[128], path[128];
Jouni Malinencd4e3c32015-10-29 12:39:56 +020093 struct stat s;
94 FILE *f;
95 char compat_ver[128];
96 char wpa_supplicant_ver[128];
97 char hostapd_ver[128];
Pradeep Reddy Potteti551b9862017-01-24 17:09:44 +053098 char host_fw_ver[128];
Jouni Malinencd4e3c32015-10-29 12:39:56 +020099
100 snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211",
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200101 get_main_ifname(dut));
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200102 if (stat(path, &s) == 0) {
103 ssize_t res;
104 char *pos;
Jouni Malinene39cd562019-05-29 23:39:56 +0300105
106 res = snprintf(fname, sizeof(fname),
107 "/sys/class/net/%s/device/driver",
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200108 get_main_ifname(dut));
Jouni Malinene39cd562019-05-29 23:39:56 +0300109 if (res < 0 || res >= sizeof(fname)) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200110 model = "Linux/";
Jouni Malinene39cd562019-05-29 23:39:56 +0300111 } else if ((res = readlink(fname, path,
112 sizeof(path))) < 0) {
113 model = "Linux/";
114 } else {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200115 if (res >= (int) sizeof(path))
116 res = sizeof(path) - 1;
117 path[res] = '\0';
118 pos = strrchr(path, '/');
119 if (pos == NULL)
120 pos = path;
121 else
122 pos++;
Jouni Malinen77dda642020-01-07 11:21:55 +0200123 res = snprintf(model_buf, sizeof(model_buf),
124 "Linux/%s", pos);
125 if (res >= 0 && res < sizeof(model_buf))
126 model = model_buf;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200127 }
128 } else
129 model = "Linux";
130
131 /* TODO: get version from wpa_supplicant (+ driver via wpa_s)
132 */
133
134 f = fopen("/sys/module/compat/parameters/"
135 "backported_kernel_version", "r");
136 if (f == NULL)
137 f = fopen("/sys/module/compat/parameters/"
138 "compat_version", "r");
139 if (f) {
140 if (fgets(compat_ver, sizeof(compat_ver), f) == NULL)
141 compat_ver[0] = '\0';
142 else
143 first_line(compat_ver);
144 fclose(f);
145 } else
146 compat_ver[0] = '\0';
147
148 get_ver("./hostapd -v 2>&1", hostapd_ver, sizeof(hostapd_ver));
149 if (hostapd_ver[0] == '\0')
150 get_ver("hostapd -v 2>&1", hostapd_ver,
151 sizeof(hostapd_ver));
152 get_ver("./wpa_supplicant -v", wpa_supplicant_ver,
153 sizeof(wpa_supplicant_ver));
154 if (wpa_supplicant_ver[0] == '\0')
155 get_ver("wpa_supplicant -v", wpa_supplicant_ver,
156 sizeof(wpa_supplicant_ver));
157
Alexei Avshalom Lazar9b85c412019-01-31 15:20:52 +0200158 host_fw_ver[0] = '\0';
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200159 if (get_driver_type(dut) == DRIVER_WCN ||
160 get_driver_type(dut) == DRIVER_LINUX_WCN) {
Pradeep Reddy Potteti551b9862017-01-24 17:09:44 +0530161 get_ver("iwpriv wlan0 version", host_fw_ver,
162 sizeof(host_fw_ver));
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200163 } else if (get_driver_type(dut) == DRIVER_WIL6210) {
Alexei Avshalom Lazar9b85c412019-01-31 15:20:52 +0200164 struct ethtool_drvinfo drvinfo;
165 struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
166 int fd; /* socket suitable for ethtool ioctl */
Pradeep Reddy Potteti551b9862017-01-24 17:09:44 +0530167
Alexei Avshalom Lazar9b85c412019-01-31 15:20:52 +0200168 memset(&drvinfo, 0, sizeof(drvinfo));
169 drvinfo.cmd = ETHTOOL_GDRVINFO;
170
171 memset(&ifr, 0, sizeof(ifr));
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200172 strlcpy(ifr.ifr_name, get_main_ifname(dut),
Amarnath Hullur Subramanyam67212372019-05-30 18:27:24 -0700173 sizeof(ifr.ifr_name));
Alexei Avshalom Lazar9b85c412019-01-31 15:20:52 +0200174
175 fd = socket(AF_INET, SOCK_DGRAM, 0);
176 if (fd < 0)
177 fd = socket(AF_NETLINK, SOCK_RAW,
178 NETLINK_GENERIC);
179 if (fd >= 0) {
180 ifr.ifr_data = (void *) &drvinfo;
181 if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
182 strlcpy(host_fw_ver, drvinfo.fw_version,
183 sizeof(host_fw_ver));
184 close(fd);
185 }
186 }
Jouni Malinen3aa72862019-05-29 23:14:51 +0300187 res = snprintf(ver_buf, sizeof(ver_buf),
188 "drv=%s%s%s%s%s%s%s/sigma=" SIGMA_DUT_VER "%s%s",
189 compat_ver,
190 wpa_supplicant_ver[0] ? "/wpas=" : "",
191 wpa_supplicant_ver,
192 hostapd_ver[0] ? "/hapd=" : "",
193 hostapd_ver,
194 host_fw_ver[0] ? "/wlan=" : "",
195 host_fw_ver,
196 dut->version ? "@" : "",
197 dut->version ? dut->version : "");
198 if (res < 0 || res >= sizeof(ver_buf))
199 return ERROR_SEND_STATUS;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200200 version = ver_buf;
201 }
202#endif /* __linux__ */
203
Jouni Malinen5db3b102016-08-04 12:27:18 +0300204 if (dut->vendor_name)
205 vendor = dut->vendor_name;
206 if (dut->model_name)
207 model = dut->model_name;
208 if (dut->version_name)
209 version = dut->version_name;
Jouni Malinen77dda642020-01-07 11:21:55 +0200210 res = snprintf(resp, sizeof(resp), "vendor,%s,model,%s,version,%s",
211 vendor, model, version);
212 if (res < 0 || res >= sizeof(resp))
213 return ERROR_SEND_STATUS;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200214
215 send_resp(dut, conn, SIGMA_COMPLETE, resp);
Jouni Malinencd444902019-02-19 01:20:45 +0200216 return STATUS_SENT;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200217}
218
219
220static int check_device_list_interfaces(struct sigma_cmd *cmd)
221{
222 if (get_param(cmd, "interfaceType") == NULL)
223 return -1;
224 return 0;
225}
226
227
Jouni Malinencd444902019-02-19 01:20:45 +0200228static enum sigma_cmd_result cmd_device_list_interfaces(struct sigma_dut *dut,
229 struct sigma_conn *conn,
230 struct sigma_cmd *cmd)
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200231{
Jouni Malinenb21f0542019-11-04 17:53:38 +0200232 const char *type, *band;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200233 char resp[200];
234
235 type = get_param(cmd, "interfaceType");
236 if (type == NULL)
237 return -1;
238 sigma_dut_print(dut, DUT_MSG_DEBUG, "device_list_interfaces - "
239 "interfaceType=%s", type);
240 if (strcmp(type, "802.11") != 0)
Jouni Malinencd444902019-02-19 01:20:45 +0200241 return ERROR_SEND_STATUS;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200242
Jouni Malinenb21f0542019-11-04 17:53:38 +0200243 band = get_param(cmd, "band");
244 if (!band) {
245 } else if (strcasecmp(band, "24g") == 0) {
246 dut->use_5g = 0;
247 } else if (strcasecmp(band, "5g") == 0) {
248 dut->use_5g = 1;
249 } else {
250 send_resp(dut, conn, SIGMA_COMPLETE,
251 "errorCode,Unsupported band value");
252 return STATUS_SENT_ERROR;
253 }
Jouni Malinen016ae6c2019-11-04 17:00:01 +0200254 snprintf(resp, sizeof(resp), "interfaceType,802.11,interfaceID,%s",
255 get_main_ifname(dut));
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200256 send_resp(dut, conn, SIGMA_COMPLETE, resp);
Jouni Malinencd444902019-02-19 01:20:45 +0200257 return STATUS_SENT;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200258}
259
260
261void basic_register_cmds(void)
262{
263 sigma_dut_reg_cmd("ca_get_version", NULL, cmd_ca_get_version);
264 sigma_dut_reg_cmd("device_get_info", NULL, cmd_device_get_info);
265 sigma_dut_reg_cmd("device_list_interfaces",
266 check_device_list_interfaces,
267 cmd_device_list_interfaces);
268}