1 /* 2 * Sigma Control API DUT (station/AP) 3 * Copyright (c) 2014-2017, Qualcomm Atheros, Inc. 4 * Copyright (c) 2018, The Linux Foundation 5 * All Rights Reserved. 6 * Licensed under the Clear BSD license. See README for more details. 7 */ 8 9 #include "sigma_dut.h" 10 #include <sys/stat.h> 11 #include "wpa_helpers.h" 12 13 enum driver_type wifi_chip_type = DRIVER_NOT_SET; 14 enum openwrt_driver_type openwrt_chip_type = OPENWRT_DRIVER_NOT_SET; 15 16 17 int file_exists(const char *fname) 18 { 19 struct stat s; 20 return stat(fname, &s) == 0; 21 } 22 23 24 int set_wifi_chip(const char *chip_type) 25 { 26 if (!strncmp(chip_type, "WCN", strlen("WCN"))) 27 wifi_chip_type = DRIVER_WCN; 28 else if (!strncmp(chip_type, "ATHEROS", strlen("ATHEROS"))) 29 wifi_chip_type = DRIVER_ATHEROS; 30 else if (!strncmp(chip_type, "AR6003", strlen("AR6003"))) 31 wifi_chip_type = DRIVER_AR6003; 32 else if (strcmp(chip_type, "MAC80211") == 0) 33 wifi_chip_type = DRIVER_MAC80211; 34 else if (strcmp(chip_type, "QNXNTO") == 0) 35 wifi_chip_type = DRIVER_QNXNTO; 36 else if (strcmp(chip_type, "OPENWRT") == 0) 37 wifi_chip_type = DRIVER_OPENWRT; 38 else if (!strncmp(chip_type, "LINUX-WCN", strlen("LINUX-WCN"))) 39 wifi_chip_type = DRIVER_LINUX_WCN; 40 else 41 return -1; 42 43 return 0; 44 } 45 46 47 enum driver_type get_driver_type(void) 48 { 49 struct stat s; 50 if (wifi_chip_type == DRIVER_NOT_SET) { 51 /* Check for 60G driver */ 52 ssize_t len; 53 char link[256]; 54 char buf[256]; 55 char *ifname = get_station_ifname(); 56 57 snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver", 58 ifname); 59 len = readlink(buf, link, sizeof(link) - 1); 60 if (len >= 0) { 61 link[len] = '\0'; 62 if (strstr(link, DRIVER_NAME_60G)) 63 return DRIVER_WIL6210; 64 } 65 66 if (stat("/sys/module/mac80211", &s) == 0) 67 return DRIVER_MAC80211; 68 return DRIVER_ATHEROS; 69 } 70 return wifi_chip_type; 71 } 72 73 74 enum openwrt_driver_type get_openwrt_driver_type(void) 75 { 76 struct stat s; 77 78 if (openwrt_chip_type == OPENWRT_DRIVER_NOT_SET) { 79 if (stat("/sys/module/umac", &s) == 0 || 80 stat("/sys/module/atd", &s) == 0) 81 openwrt_chip_type = OPENWRT_DRIVER_ATHEROS; 82 } 83 84 return openwrt_chip_type; 85 } 86 87 88 enum sigma_program sigma_program_to_enum(const char *prog) 89 { 90 if (prog == NULL) 91 return PROGRAM_UNKNOWN; 92 93 if (strcasecmp(prog, "TDLS") == 0) 94 return PROGRAM_TDLS; 95 if (strcasecmp(prog, "HS2") == 0) 96 return PROGRAM_HS2; 97 if (strcasecmp(prog, "HS2_R2") == 0 || 98 strcasecmp(prog, "HS2-R2") == 0) 99 return PROGRAM_HS2_R2; 100 if (strcasecmp(prog, "HS2-R3") == 0) 101 return PROGRAM_HS2_R3; 102 if (strcasecmp(prog, "WFD") == 0) 103 return PROGRAM_WFD; 104 if (strcasecmp(prog, "DisplayR2") == 0) 105 return PROGRAM_DISPLAYR2; 106 if (strcasecmp(prog, "PMF") == 0) 107 return PROGRAM_PMF; 108 if (strcasecmp(prog, "WPS") == 0) 109 return PROGRAM_WPS; 110 if (strcasecmp(prog, "11n") == 0) 111 return PROGRAM_HT; 112 if (strcasecmp(prog, "VHT") == 0) 113 return PROGRAM_VHT; 114 if (strcasecmp(prog, "60GHZ") == 0) 115 return PROGRAM_60GHZ; 116 if (strcasecmp(prog, "NAN") == 0) 117 return PROGRAM_NAN; 118 if (strcasecmp(prog, "LOC") == 0) 119 return PROGRAM_LOC; 120 if (strcasecmp(prog, "MBO") == 0) 121 return PROGRAM_MBO; 122 if (strcasecmp(prog, "IoTLP") == 0) 123 return PROGRAM_IOTLP; 124 if (strcasecmp(prog, "DPP") == 0) 125 return PROGRAM_DPP; 126 if (strcasecmp(prog, "OCE") == 0) 127 return PROGRAM_OCE; 128 if (strcasecmp(prog, "WPA3") == 0) 129 return PROGRAM_WPA3; 130 if (strcasecmp(prog, "HE") == 0) 131 return PROGRAM_HE; 132 133 return PROGRAM_UNKNOWN; 134 } 135 136 137 static int parse_hex(char c) 138 { 139 if (c >= '0' && c <= '9') 140 return c - '0'; 141 if (c >= 'a' && c <= 'f') 142 return c - 'a' + 10; 143 if (c >= 'A' && c <= 'F') 144 return c - 'A' + 10; 145 return -1; 146 } 147 148 149 static int hex_byte(const char *str) 150 { 151 int res1, res2; 152 153 res1 = parse_hex(str[0]); 154 if (res1 < 0) 155 return -1; 156 res2 = parse_hex(str[1]); 157 if (res2 < 0) 158 return -1; 159 return (res1 << 4) | res2; 160 } 161 162 163 int parse_hexstr(const char *hex, unsigned char *buf, size_t buflen) 164 { 165 size_t i; 166 const char *pos = hex; 167 168 for (i = 0; i < buflen; i++) { 169 int val; 170 171 if (*pos == '\0') 172 break; 173 val = hex_byte(pos); 174 if (val < 0) 175 return -1; 176 buf[i] = val; 177 pos += 2; 178 } 179 180 return i; 181 } 182 183 184 int parse_mac_address(struct sigma_dut *dut, const char *arg, 185 unsigned char *addr) 186 { 187 int i; 188 const char *pos = arg; 189 190 if (strlen(arg) != 17) 191 goto fail; 192 193 for (i = 0; i < ETH_ALEN; i++) { 194 int val; 195 196 val = hex_byte(pos); 197 if (val < 0) 198 goto fail; 199 addr[i] = val; 200 if (i + 1 < ETH_ALEN) { 201 pos += 2; 202 if (*pos != ':') 203 goto fail; 204 pos++; 205 } 206 } 207 208 return 0; 209 210 fail: 211 sigma_dut_print(dut, DUT_MSG_ERROR, 212 "Invalid MAC address %s (expected format xx:xx:xx:xx:xx:xx)", 213 arg); 214 return -1; 215 } 216 217 218 unsigned int channel_to_freq(unsigned int channel) 219 { 220 if (channel >= 1 && channel <= 13) 221 return 2407 + 5 * channel; 222 if (channel == 14) 223 return 2484; 224 if (channel >= 36 && channel <= 165) 225 return 5000 + 5 * channel; 226 227 return 0; 228 } 229 230 231 unsigned int freq_to_channel(unsigned int freq) 232 { 233 if (freq >= 2412 && freq <= 2472) 234 return (freq - 2407) / 5; 235 if (freq == 2484) 236 return 14; 237 if (freq >= 5180 && freq <= 5825) 238 return (freq - 5000) / 5; 239 return 0; 240 } 241 242 243 void convert_mac_addr_to_ipv6_lladdr(u8 *mac_addr, char *ipv6_buf, 244 size_t buf_len) 245 { 246 u8 temp = mac_addr[0] ^ 0x02; 247 248 snprintf(ipv6_buf, buf_len, "fe80::%02x%02x:%02xff:fe%02x:%02x%02x", 249 temp, mac_addr[1], mac_addr[2], 250 mac_addr[3], mac_addr[4], mac_addr[5]); 251 } 252 253 254 #ifndef ANDROID 255 256 size_t strlcpy(char *dest, const char *src, size_t siz) 257 { 258 const char *s = src; 259 size_t left = siz; 260 261 if (left) { 262 /* Copy string up to the maximum size of the dest buffer */ 263 while (--left != 0) { 264 if ((*dest++ = *s++) == '\0') 265 break; 266 } 267 } 268 269 if (left == 0) { 270 /* Not enough room for the string; force NUL-termination */ 271 if (siz != 0) 272 *dest = '\0'; 273 while (*s++) 274 ; /* determine total src string length */ 275 } 276 277 return s - src - 1; 278 } 279 280 281 size_t strlcat(char *dst, const char *str, size_t size) 282 { 283 char *pos; 284 size_t dstlen, srclen, copy; 285 286 srclen = strlen(str); 287 for (pos = dst; pos - dst < size && *dst; pos++) 288 ; 289 dstlen = pos - dst; 290 if (*dst) 291 return dstlen + srclen; 292 if (dstlen + srclen + 1 > size) 293 copy = size - dstlen - 1; 294 else 295 copy = srclen; 296 memcpy(pos, str, copy); 297 pos[copy] = '\0'; 298 return dstlen + srclen; 299 } 300 301 #endif /* ANDROID */ 302 303 304 void hex_dump(struct sigma_dut *dut, u8 *data, size_t len) 305 { 306 char buf[1024]; 307 size_t index; 308 u8 *ptr; 309 int pos; 310 311 memset(buf, 0, sizeof(buf)); 312 ptr = data; 313 pos = 0; 314 for (index = 0; index < len; index++) { 315 pos += snprintf(&(buf[pos]), sizeof(buf) - pos, 316 "%02x ", *ptr++); 317 if (pos > 1020) 318 break; 319 } 320 sigma_dut_print(dut, DUT_MSG_INFO, "HEXDUMP len=[%d]", (int) len); 321 sigma_dut_print(dut, DUT_MSG_INFO, "buf:%s", buf); 322 } 323 324 325 #ifdef NL80211_SUPPORT 326 327 void * nl80211_cmd(struct sigma_dut *dut, struct nl80211_ctx *ctx, 328 struct nl_msg *msg, int flags, uint8_t cmd) 329 { 330 return genlmsg_put(msg, 0, 0, ctx->netlink_familyid, 331 0, flags, cmd, 0); 332 } 333 334 335 static struct nl_msg * 336 nl80211_ifindex_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx, int ifindex, 337 int flags, uint8_t cmd) 338 { 339 struct nl_msg *msg; 340 341 msg = nlmsg_alloc(); 342 if (!msg) { 343 sigma_dut_print(dut, DUT_MSG_ERROR, 344 "Failed to allocate NL message"); 345 return NULL; 346 } 347 348 if (!nl80211_cmd(dut, ctx, msg, flags, cmd) || 349 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) { 350 nlmsg_free(msg); 351 return NULL; 352 } 353 354 return msg; 355 } 356 357 358 struct nl_msg * nl80211_drv_msg(struct sigma_dut *dut, struct nl80211_ctx *ctx, 359 int ifindex, int flags, uint8_t cmd) 360 { 361 return nl80211_ifindex_msg(dut, ctx, ifindex, flags, cmd); 362 } 363 364 365 static int ack_handler(struct nl_msg *msg, void *arg) 366 { 367 int *err = arg; 368 *err = 0; 369 return NL_STOP; 370 } 371 372 373 static int finish_handler(struct nl_msg *msg, void *arg) 374 { 375 int *ret = arg; 376 *ret = 0; 377 return NL_SKIP; 378 } 379 380 381 static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, 382 void *arg) 383 { 384 int *ret = arg; 385 *ret = err->error; 386 return NL_SKIP; 387 } 388 389 390 int send_and_recv_msgs(struct sigma_dut *dut, struct nl80211_ctx *ctx, 391 struct nl_msg *nlmsg, 392 int (*valid_handler)(struct nl_msg *, void *), 393 void *valid_data) 394 { 395 struct nl_cb *cb; 396 int err = -ENOMEM; 397 398 if (!nlmsg) 399 return -ENOMEM; 400 401 cb = nl_cb_alloc(NL_CB_DEFAULT); 402 if (!cb) 403 goto out; 404 405 err = nl_send_auto_complete(ctx->sock, nlmsg); 406 if (err < 0) { 407 sigma_dut_print(dut, DUT_MSG_ERROR, 408 "nl80211: failed to send err=%d", err); 409 goto out; 410 } 411 412 err = 1; 413 414 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); 415 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); 416 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); 417 418 if (valid_handler) 419 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, 420 valid_handler, valid_data); 421 422 while (err > 0) { 423 int res = nl_recvmsgs(ctx->sock, cb); 424 425 if (res < 0) { 426 sigma_dut_print(dut, DUT_MSG_ERROR, 427 "nl80211: %s->nl_recvmsgs failed: res=%d, err=%d", 428 __func__, res, err); 429 } 430 } 431 out: 432 nl_cb_put(cb); 433 if (!valid_handler && valid_data == (void *) -1) { 434 if (nlmsg) { 435 struct nlmsghdr *hdr = nlmsg_hdr(nlmsg); 436 void *data = nlmsg_data(hdr); 437 int len = hdr->nlmsg_len - NLMSG_HDRLEN; 438 439 memset(data, 0, len); 440 } 441 } 442 443 nlmsg_free(nlmsg); 444 return err; 445 } 446 447 448 struct nl80211_ctx * nl80211_init(struct sigma_dut *dut) 449 { 450 struct nl80211_ctx *ctx; 451 452 ctx = calloc(1, sizeof(struct nl80211_ctx)); 453 if (!ctx) { 454 sigma_dut_print(dut, DUT_MSG_ERROR, 455 "Failed to alloc nl80211_ctx"); 456 return NULL; 457 } 458 459 ctx->sock = nl_socket_alloc(); 460 if (!ctx->sock) { 461 sigma_dut_print(dut, DUT_MSG_ERROR, 462 "Failed to create NL socket, err: %s", 463 strerror(errno)); 464 goto cleanup; 465 } 466 467 if (nl_connect(ctx->sock, NETLINK_GENERIC)) { 468 sigma_dut_print(dut, DUT_MSG_ERROR, 469 "Could not connect socket, err: %s", 470 strerror(errno)); 471 goto cleanup; 472 } 473 474 if (nl_socket_set_buffer_size(ctx->sock, SOCK_BUF_SIZE, 0) < 0) { 475 sigma_dut_print(dut, DUT_MSG_INFO, 476 "Could not set nl_socket RX buffer size for sock: %s", 477 strerror(errno)); 478 } 479 480 ctx->netlink_familyid = genl_ctrl_resolve(ctx->sock, "nl80211"); 481 if (ctx->netlink_familyid < 0) { 482 sigma_dut_print(dut, DUT_MSG_ERROR, 483 "Could not resolve nl80211 family id"); 484 goto cleanup; 485 } 486 487 ctx->nlctrl_familyid = genl_ctrl_resolve(ctx->sock, "nlctrl"); 488 if (ctx->nlctrl_familyid < 0) { 489 sigma_dut_print(dut, DUT_MSG_ERROR, 490 "net link family nlctrl is not present: %d err:%s", 491 ctx->nlctrl_familyid, strerror(errno)); 492 goto cleanup; 493 } 494 495 return ctx; 496 497 cleanup: 498 if (ctx->sock) 499 nl_socket_free(ctx->sock); 500 501 free(ctx); 502 return NULL; 503 } 504 505 506 void nl80211_deinit(struct sigma_dut *dut, struct nl80211_ctx *ctx) 507 { 508 if (!ctx || !ctx->sock) { 509 sigma_dut_print(dut, DUT_MSG_ERROR, "%s: ctx/sock is NULL", 510 __func__); 511 return; 512 } 513 nl_socket_free(ctx->sock); 514 free(ctx); 515 } 516 517 #endif /* NL80211_SUPPORT */ 518