1cd4e3c3eSJouni Malinen /* 2cd4e3c3eSJouni Malinen * Sigma Control API DUT (station/AP) 3659a34c4SAmarnath Hullur Subramanyam * Copyright (c) 2014-2017, Qualcomm Atheros, Inc. 4cd4e3c3eSJouni Malinen * All Rights Reserved. 5cd4e3c3eSJouni Malinen * Licensed under the Clear BSD license. See README for more details. 6cd4e3c3eSJouni Malinen */ 7cd4e3c3eSJouni Malinen 8cd4e3c3eSJouni Malinen #include "sigma_dut.h" 9cd4e3c3eSJouni Malinen #include <sys/stat.h> 10cd4e3c3eSJouni Malinen #include "wpa_helpers.h" 11cd4e3c3eSJouni Malinen 12cd4e3c3eSJouni Malinen enum driver_type wifi_chip_type = DRIVER_NOT_SET; 13cd4e3c3eSJouni Malinen enum openwrt_driver_type openwrt_chip_type = OPENWRT_DRIVER_NOT_SET; 14cd4e3c3eSJouni Malinen 15cd4e3c3eSJouni Malinen 16cd4e3c3eSJouni Malinen int file_exists(const char *fname) 17cd4e3c3eSJouni Malinen { 18cd4e3c3eSJouni Malinen struct stat s; 19cd4e3c3eSJouni Malinen return stat(fname, &s) == 0; 20cd4e3c3eSJouni Malinen } 21cd4e3c3eSJouni Malinen 22cd4e3c3eSJouni Malinen 23cd4e3c3eSJouni Malinen int set_wifi_chip(const char *chip_type) 24cd4e3c3eSJouni Malinen { 25cd4e3c3eSJouni Malinen if (!strncmp(chip_type, "WCN", strlen("WCN"))) 26cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_WCN; 27cd4e3c3eSJouni Malinen else if (!strncmp(chip_type, "ATHEROS", strlen("ATHEROS"))) 28cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_ATHEROS; 29cd4e3c3eSJouni Malinen else if (!strncmp(chip_type, "AR6003", strlen("AR6003"))) 30cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_AR6003; 31cd4e3c3eSJouni Malinen else if (strcmp(chip_type, "MAC80211") == 0) 32cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_MAC80211; 33cd4e3c3eSJouni Malinen else if (strcmp(chip_type, "QNXNTO") == 0) 34cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_QNXNTO; 35cd4e3c3eSJouni Malinen else if (strcmp(chip_type, "OPENWRT") == 0) 36cd4e3c3eSJouni Malinen wifi_chip_type = DRIVER_OPENWRT; 37b692f107SSreelakshmi Konamki else if (!strncmp(chip_type, "LINUX-WCN", strlen("LINUX-WCN"))) 38b692f107SSreelakshmi Konamki wifi_chip_type = DRIVER_LINUX_WCN; 39cd4e3c3eSJouni Malinen else 40cd4e3c3eSJouni Malinen return -1; 41cd4e3c3eSJouni Malinen 42cd4e3c3eSJouni Malinen return 0; 43cd4e3c3eSJouni Malinen } 44cd4e3c3eSJouni Malinen 45cd4e3c3eSJouni Malinen 46cd4e3c3eSJouni Malinen enum driver_type get_driver_type(void) 47cd4e3c3eSJouni Malinen { 48cd4e3c3eSJouni Malinen struct stat s; 49cd4e3c3eSJouni Malinen if (wifi_chip_type == DRIVER_NOT_SET) { 50cd4e3c3eSJouni Malinen /* Check for 60G driver */ 51cd4e3c3eSJouni Malinen ssize_t len; 52cd4e3c3eSJouni Malinen char link[256]; 53cd4e3c3eSJouni Malinen char buf[256]; 54cd4e3c3eSJouni Malinen char *ifname = get_station_ifname(); 55cd4e3c3eSJouni Malinen 56cd4e3c3eSJouni Malinen snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver", 57cd4e3c3eSJouni Malinen ifname); 58cd4e3c3eSJouni Malinen len = readlink(buf, link, sizeof(link) - 1); 59cd4e3c3eSJouni Malinen if (len >= 0) { 60cd4e3c3eSJouni Malinen link[len] = '\0'; 61cd4e3c3eSJouni Malinen if (strstr(link, DRIVER_NAME_60G)) 62cd4e3c3eSJouni Malinen return DRIVER_WIL6210; 63cd4e3c3eSJouni Malinen } 64cd4e3c3eSJouni Malinen 65cd4e3c3eSJouni Malinen if (stat("/sys/module/mac80211", &s) == 0) 66cd4e3c3eSJouni Malinen return DRIVER_MAC80211; 67cd4e3c3eSJouni Malinen return DRIVER_ATHEROS; 68cd4e3c3eSJouni Malinen } 69cd4e3c3eSJouni Malinen return wifi_chip_type; 70cd4e3c3eSJouni Malinen } 71cd4e3c3eSJouni Malinen 72cd4e3c3eSJouni Malinen 73cd4e3c3eSJouni Malinen enum openwrt_driver_type get_openwrt_driver_type(void) 74cd4e3c3eSJouni Malinen { 75cd4e3c3eSJouni Malinen struct stat s; 76cd4e3c3eSJouni Malinen 77cd4e3c3eSJouni Malinen if (openwrt_chip_type == OPENWRT_DRIVER_NOT_SET) { 78a62e20abSSarvepalli, Rajesh Babu if (stat("/sys/module/umac", &s) == 0) 79cd4e3c3eSJouni Malinen openwrt_chip_type = OPENWRT_DRIVER_ATHEROS; 80cd4e3c3eSJouni Malinen } 81cd4e3c3eSJouni Malinen 82cd4e3c3eSJouni Malinen return openwrt_chip_type; 83cd4e3c3eSJouni Malinen } 84cd4e3c3eSJouni Malinen 85cd4e3c3eSJouni Malinen 86cd4e3c3eSJouni Malinen enum sigma_program sigma_program_to_enum(const char *prog) 87cd4e3c3eSJouni Malinen { 88cd4e3c3eSJouni Malinen if (prog == NULL) 89cd4e3c3eSJouni Malinen return PROGRAM_UNKNOWN; 90cd4e3c3eSJouni Malinen 91cd4e3c3eSJouni Malinen if (strcasecmp(prog, "TDLS") == 0) 92cd4e3c3eSJouni Malinen return PROGRAM_TDLS; 93cd4e3c3eSJouni Malinen if (strcasecmp(prog, "HS2") == 0) 94cd4e3c3eSJouni Malinen return PROGRAM_HS2; 95cd4e3c3eSJouni Malinen if (strcasecmp(prog, "HS2_R2") == 0 || 96cd4e3c3eSJouni Malinen strcasecmp(prog, "HS2-R2") == 0) 97cd4e3c3eSJouni Malinen return PROGRAM_HS2_R2; 98cd4e3c3eSJouni Malinen if (strcasecmp(prog, "WFD") == 0) 99cd4e3c3eSJouni Malinen return PROGRAM_WFD; 100659a34c4SAmarnath Hullur Subramanyam if (strcasecmp(prog, "DisplayR2") == 0) 101659a34c4SAmarnath Hullur Subramanyam return PROGRAM_DISPLAYR2; 102cd4e3c3eSJouni Malinen if (strcasecmp(prog, "PMF") == 0) 103cd4e3c3eSJouni Malinen return PROGRAM_PMF; 104cd4e3c3eSJouni Malinen if (strcasecmp(prog, "WPS") == 0) 105cd4e3c3eSJouni Malinen return PROGRAM_WPS; 106cd4e3c3eSJouni Malinen if (strcasecmp(prog, "11n") == 0) 107cd4e3c3eSJouni Malinen return PROGRAM_HT; 108cd4e3c3eSJouni Malinen if (strcasecmp(prog, "VHT") == 0) 109cd4e3c3eSJouni Malinen return PROGRAM_VHT; 110cd4e3c3eSJouni Malinen if (strcasecmp(prog, "60GHZ") == 0) 111cd4e3c3eSJouni Malinen return PROGRAM_60GHZ; 112cd4e3c3eSJouni Malinen if (strcasecmp(prog, "NAN") == 0) 113cd4e3c3eSJouni Malinen return PROGRAM_NAN; 11412dd4145Spriyadharshini gowthaman if (strcasecmp(prog, "LOC") == 0) 11512dd4145Spriyadharshini gowthaman return PROGRAM_LOC; 116b4e05fc1Spriyadharshini gowthaman if (strcasecmp(prog, "MBO") == 0) 117b4e05fc1Spriyadharshini gowthaman return PROGRAM_MBO; 11833ea287aSAdil Saeed Musthafa if (strcasecmp(prog, "IoTLP") == 0) 11933ea287aSAdil Saeed Musthafa return PROGRAM_IOTLP; 1205c3813a7SJouni Malinen if (strcasecmp(prog, "DPP") == 0) 1215c3813a7SJouni Malinen return PROGRAM_DPP; 122*a2cb567bSAnkita Bajaj if (strcasecmp(prog, "OCE") == 0) 123*a2cb567bSAnkita Bajaj return PROGRAM_OCE; 124cd4e3c3eSJouni Malinen 125cd4e3c3eSJouni Malinen return PROGRAM_UNKNOWN; 126cd4e3c3eSJouni Malinen } 12772462ef3Spriyadharshini gowthaman 12872462ef3Spriyadharshini gowthaman 12972462ef3Spriyadharshini gowthaman static int parse_hex(char c) 13072462ef3Spriyadharshini gowthaman { 13172462ef3Spriyadharshini gowthaman if (c >= '0' && c <= '9') 13272462ef3Spriyadharshini gowthaman return c - '0'; 13372462ef3Spriyadharshini gowthaman if (c >= 'a' && c <= 'f') 13472462ef3Spriyadharshini gowthaman return c - 'a' + 10; 13572462ef3Spriyadharshini gowthaman if (c >= 'A' && c <= 'F') 13672462ef3Spriyadharshini gowthaman return c - 'A' + 10; 13772462ef3Spriyadharshini gowthaman return -1; 13872462ef3Spriyadharshini gowthaman } 13972462ef3Spriyadharshini gowthaman 14072462ef3Spriyadharshini gowthaman 14172462ef3Spriyadharshini gowthaman static int hex_byte(const char *str) 14272462ef3Spriyadharshini gowthaman { 14372462ef3Spriyadharshini gowthaman int res1, res2; 14472462ef3Spriyadharshini gowthaman 14572462ef3Spriyadharshini gowthaman res1 = parse_hex(str[0]); 14672462ef3Spriyadharshini gowthaman if (res1 < 0) 14772462ef3Spriyadharshini gowthaman return -1; 14872462ef3Spriyadharshini gowthaman res2 = parse_hex(str[1]); 14972462ef3Spriyadharshini gowthaman if (res2 < 0) 15072462ef3Spriyadharshini gowthaman return -1; 15172462ef3Spriyadharshini gowthaman return (res1 << 4) | res2; 15272462ef3Spriyadharshini gowthaman } 15372462ef3Spriyadharshini gowthaman 15472462ef3Spriyadharshini gowthaman 15508cf231dSJouni Malinen int parse_hexstr(const char *hex, unsigned char *buf, size_t buflen) 15608cf231dSJouni Malinen { 15708cf231dSJouni Malinen size_t i; 15808cf231dSJouni Malinen const char *pos = hex; 15908cf231dSJouni Malinen 16008cf231dSJouni Malinen for (i = 0; i < buflen; i++) { 16108cf231dSJouni Malinen int val; 16208cf231dSJouni Malinen 16308cf231dSJouni Malinen if (*pos == '\0') 16408cf231dSJouni Malinen break; 16508cf231dSJouni Malinen val = hex_byte(pos); 16608cf231dSJouni Malinen if (val < 0) 16708cf231dSJouni Malinen return -1; 16808cf231dSJouni Malinen buf[i] = val; 16908cf231dSJouni Malinen pos += 2; 17008cf231dSJouni Malinen } 17108cf231dSJouni Malinen 17208cf231dSJouni Malinen return i; 17308cf231dSJouni Malinen } 17408cf231dSJouni Malinen 17508cf231dSJouni Malinen 17672462ef3Spriyadharshini gowthaman int parse_mac_address(struct sigma_dut *dut, const char *arg, 17772462ef3Spriyadharshini gowthaman unsigned char *addr) 17872462ef3Spriyadharshini gowthaman { 17972462ef3Spriyadharshini gowthaman int i; 18072462ef3Spriyadharshini gowthaman const char *pos = arg; 18172462ef3Spriyadharshini gowthaman 18272462ef3Spriyadharshini gowthaman if (strlen(arg) != 17) 18372462ef3Spriyadharshini gowthaman goto fail; 18472462ef3Spriyadharshini gowthaman 18572462ef3Spriyadharshini gowthaman for (i = 0; i < ETH_ALEN; i++) { 18672462ef3Spriyadharshini gowthaman int val; 18772462ef3Spriyadharshini gowthaman 18872462ef3Spriyadharshini gowthaman val = hex_byte(pos); 18972462ef3Spriyadharshini gowthaman if (val < 0) 19072462ef3Spriyadharshini gowthaman goto fail; 19172462ef3Spriyadharshini gowthaman addr[i] = val; 19272462ef3Spriyadharshini gowthaman if (i + 1 < ETH_ALEN) { 19372462ef3Spriyadharshini gowthaman pos += 2; 19472462ef3Spriyadharshini gowthaman if (*pos != ':') 19572462ef3Spriyadharshini gowthaman goto fail; 19672462ef3Spriyadharshini gowthaman pos++; 19772462ef3Spriyadharshini gowthaman } 19872462ef3Spriyadharshini gowthaman } 19972462ef3Spriyadharshini gowthaman 20072462ef3Spriyadharshini gowthaman return 0; 20172462ef3Spriyadharshini gowthaman 20272462ef3Spriyadharshini gowthaman fail: 20372462ef3Spriyadharshini gowthaman sigma_dut_print(dut, DUT_MSG_ERROR, 20472462ef3Spriyadharshini gowthaman "Invalid MAC address %s (expected format xx:xx:xx:xx:xx:xx)", 20572462ef3Spriyadharshini gowthaman arg); 20672462ef3Spriyadharshini gowthaman return -1; 20772462ef3Spriyadharshini gowthaman } 2087192dc42SRakesh Sunki 2097192dc42SRakesh Sunki 2107192dc42SRakesh Sunki unsigned int channel_to_freq(unsigned int channel) 2117192dc42SRakesh Sunki { 2127192dc42SRakesh Sunki if (channel >= 1 && channel <= 13) 2137192dc42SRakesh Sunki return 2407 + 5 * channel; 2147192dc42SRakesh Sunki if (channel == 14) 2157192dc42SRakesh Sunki return 2484; 2167192dc42SRakesh Sunki if (channel >= 36 && channel <= 165) 2177192dc42SRakesh Sunki return 5000 + 5 * channel; 2187192dc42SRakesh Sunki 2197192dc42SRakesh Sunki return 0; 2207192dc42SRakesh Sunki } 2217192dc42SRakesh Sunki 2227192dc42SRakesh Sunki 2237192dc42SRakesh Sunki unsigned int freq_to_channel(unsigned int freq) 2247192dc42SRakesh Sunki { 2257192dc42SRakesh Sunki if (freq >= 2412 && freq <= 2472) 2267192dc42SRakesh Sunki return (freq - 2407) / 5; 2277192dc42SRakesh Sunki if (freq == 2484) 2287192dc42SRakesh Sunki return 14; 2297192dc42SRakesh Sunki if (freq >= 5180 && freq <= 5825) 2307192dc42SRakesh Sunki return (freq - 5000) / 5; 2317192dc42SRakesh Sunki return 0; 2327192dc42SRakesh Sunki } 233769731a2SPeng Xu 234769731a2SPeng Xu 2358f8e74b5SRakesh Sunki void convert_mac_addr_to_ipv6_lladdr(u8 *mac_addr, char *ipv6_buf, 2368f8e74b5SRakesh Sunki size_t buf_len) 2378f8e74b5SRakesh Sunki { 2388f8e74b5SRakesh Sunki u8 temp = mac_addr[0] ^ 0x02; 2398f8e74b5SRakesh Sunki 2408f8e74b5SRakesh Sunki snprintf(ipv6_buf, buf_len, "fe80::%02x%02x:%02xff:fe%02x:%02x%02x", 2418f8e74b5SRakesh Sunki temp, mac_addr[1], mac_addr[2], 2428f8e74b5SRakesh Sunki mac_addr[3], mac_addr[4], mac_addr[5]); 2438f8e74b5SRakesh Sunki } 2448f8e74b5SRakesh Sunki 2458f8e74b5SRakesh Sunki 246769731a2SPeng Xu #ifndef ANDROID 247769731a2SPeng Xu 248769731a2SPeng Xu size_t strlcpy(char *dest, const char *src, size_t siz) 249769731a2SPeng Xu { 250769731a2SPeng Xu const char *s = src; 251769731a2SPeng Xu size_t left = siz; 252769731a2SPeng Xu 253769731a2SPeng Xu if (left) { 254769731a2SPeng Xu /* Copy string up to the maximum size of the dest buffer */ 255769731a2SPeng Xu while (--left != 0) { 256769731a2SPeng Xu if ((*dest++ = *s++) == '\0') 257769731a2SPeng Xu break; 258769731a2SPeng Xu } 259769731a2SPeng Xu } 260769731a2SPeng Xu 261769731a2SPeng Xu if (left == 0) { 262769731a2SPeng Xu /* Not enough room for the string; force NUL-termination */ 263769731a2SPeng Xu if (siz != 0) 264769731a2SPeng Xu *dest = '\0'; 265769731a2SPeng Xu while (*s++) 266769731a2SPeng Xu ; /* determine total src string length */ 267769731a2SPeng Xu } 268769731a2SPeng Xu 269769731a2SPeng Xu return s - src - 1; 270769731a2SPeng Xu } 271769731a2SPeng Xu 272769731a2SPeng Xu 273769731a2SPeng Xu size_t strlcat(char *dst, const char *str, size_t size) 274769731a2SPeng Xu { 275769731a2SPeng Xu char *pos; 276769731a2SPeng Xu size_t dstlen, srclen, copy; 277769731a2SPeng Xu 278769731a2SPeng Xu srclen = strlen(str); 279769731a2SPeng Xu for (pos = dst; pos - dst < size && *dst; pos++) 280769731a2SPeng Xu ; 281769731a2SPeng Xu dstlen = pos - dst; 282769731a2SPeng Xu if (*dst) 283769731a2SPeng Xu return dstlen + srclen; 284769731a2SPeng Xu if (dstlen + srclen + 1 > size) 285769731a2SPeng Xu copy = size - dstlen - 1; 286769731a2SPeng Xu else 287769731a2SPeng Xu copy = srclen; 288769731a2SPeng Xu memcpy(pos, str, copy); 289769731a2SPeng Xu pos[copy] = '\0'; 290769731a2SPeng Xu return dstlen + srclen; 291769731a2SPeng Xu } 292769731a2SPeng Xu 293769731a2SPeng Xu #endif /* ANDROID */ 294