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