1189251Ssam/* 2189251Ssam * wpa_supplicant/hostapd / common helper functions, etc. 3346981Scy * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam 11289549Srpaulo#include "common/ieee802_11_defs.h" 12189251Ssam#include "common.h" 13189251Ssam 14189251Ssam 15189251Ssamstatic int hex2num(char c) 16189251Ssam{ 17189251Ssam if (c >= '0' && c <= '9') 18189251Ssam return c - '0'; 19189251Ssam if (c >= 'a' && c <= 'f') 20189251Ssam return c - 'a' + 10; 21189251Ssam if (c >= 'A' && c <= 'F') 22189251Ssam return c - 'A' + 10; 23189251Ssam return -1; 24189251Ssam} 25189251Ssam 26189251Ssam 27252726Srpauloint hex2byte(const char *hex) 28189251Ssam{ 29189251Ssam int a, b; 30189251Ssam a = hex2num(*hex++); 31189251Ssam if (a < 0) 32189251Ssam return -1; 33189251Ssam b = hex2num(*hex++); 34189251Ssam if (b < 0) 35189251Ssam return -1; 36189251Ssam return (a << 4) | b; 37189251Ssam} 38189251Ssam 39189251Ssam 40281806Srpaulostatic const char * hwaddr_parse(const char *txt, u8 *addr) 41281806Srpaulo{ 42281806Srpaulo size_t i; 43281806Srpaulo 44281806Srpaulo for (i = 0; i < ETH_ALEN; i++) { 45281806Srpaulo int a; 46281806Srpaulo 47281806Srpaulo a = hex2byte(txt); 48281806Srpaulo if (a < 0) 49281806Srpaulo return NULL; 50281806Srpaulo txt += 2; 51281806Srpaulo addr[i] = a; 52281806Srpaulo if (i < ETH_ALEN - 1 && *txt++ != ':') 53281806Srpaulo return NULL; 54281806Srpaulo } 55281806Srpaulo return txt; 56281806Srpaulo} 57281806Srpaulo 58281806Srpaulo 59189251Ssam/** 60214734Srpaulo * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) 61189251Ssam * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 62189251Ssam * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 63189251Ssam * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 64189251Ssam */ 65189251Ssamint hwaddr_aton(const char *txt, u8 *addr) 66189251Ssam{ 67281806Srpaulo return hwaddr_parse(txt, addr) ? 0 : -1; 68281806Srpaulo} 69189251Ssam 70189251Ssam 71281806Srpaulo/** 72281806Srpaulo * hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format) 73281806Srpaulo * @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00") 74281806Srpaulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 75281806Srpaulo * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes) 76281806Srpaulo * @maskable: Flag to indicate whether a mask is allowed 77281806Srpaulo * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 78281806Srpaulo */ 79281806Srpauloint hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable) 80281806Srpaulo{ 81281806Srpaulo const char *r; 82281806Srpaulo 83281806Srpaulo /* parse address part */ 84281806Srpaulo r = hwaddr_parse(txt, addr); 85281806Srpaulo if (!r) 86281806Srpaulo return -1; 87281806Srpaulo 88281806Srpaulo /* check for optional mask */ 89337817Scy if (*r == '\0' || isspace((unsigned char) *r)) { 90281806Srpaulo /* no mask specified, assume default */ 91281806Srpaulo os_memset(mask, 0xff, ETH_ALEN); 92281806Srpaulo } else if (maskable && *r == '/') { 93281806Srpaulo /* mask specified and allowed */ 94281806Srpaulo r = hwaddr_parse(r + 1, mask); 95281806Srpaulo /* parser error? */ 96281806Srpaulo if (!r) 97189251Ssam return -1; 98281806Srpaulo } else { 99281806Srpaulo /* mask specified but not allowed or trailing garbage */ 100281806Srpaulo return -1; 101189251Ssam } 102189251Ssam 103189251Ssam return 0; 104189251Ssam} 105189251Ssam 106281806Srpaulo 107252726Srpaulo/** 108252726Srpaulo * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) 109252726Srpaulo * @txt: MAC address as a string (e.g., "001122334455") 110252726Srpaulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 111252726Srpaulo * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 112252726Srpaulo */ 113252726Srpauloint hwaddr_compact_aton(const char *txt, u8 *addr) 114252726Srpaulo{ 115252726Srpaulo int i; 116189251Ssam 117252726Srpaulo for (i = 0; i < 6; i++) { 118252726Srpaulo int a, b; 119252726Srpaulo 120252726Srpaulo a = hex2num(*txt++); 121252726Srpaulo if (a < 0) 122252726Srpaulo return -1; 123252726Srpaulo b = hex2num(*txt++); 124252726Srpaulo if (b < 0) 125252726Srpaulo return -1; 126252726Srpaulo *addr++ = (a << 4) | b; 127252726Srpaulo } 128252726Srpaulo 129252726Srpaulo return 0; 130252726Srpaulo} 131252726Srpaulo 132189251Ssam/** 133214734Srpaulo * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) 134214734Srpaulo * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) 135214734Srpaulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 136214734Srpaulo * Returns: Characters used (> 0) on success, -1 on failure 137214734Srpaulo */ 138214734Srpauloint hwaddr_aton2(const char *txt, u8 *addr) 139214734Srpaulo{ 140214734Srpaulo int i; 141214734Srpaulo const char *pos = txt; 142214734Srpaulo 143214734Srpaulo for (i = 0; i < 6; i++) { 144214734Srpaulo int a, b; 145214734Srpaulo 146214734Srpaulo while (*pos == ':' || *pos == '.' || *pos == '-') 147214734Srpaulo pos++; 148214734Srpaulo 149214734Srpaulo a = hex2num(*pos++); 150214734Srpaulo if (a < 0) 151214734Srpaulo return -1; 152214734Srpaulo b = hex2num(*pos++); 153214734Srpaulo if (b < 0) 154214734Srpaulo return -1; 155214734Srpaulo *addr++ = (a << 4) | b; 156214734Srpaulo } 157214734Srpaulo 158214734Srpaulo return pos - txt; 159214734Srpaulo} 160214734Srpaulo 161214734Srpaulo 162214734Srpaulo/** 163189251Ssam * hexstr2bin - Convert ASCII hex string into binary data 164189251Ssam * @hex: ASCII hex string (e.g., "01ab") 165189251Ssam * @buf: Buffer for the binary data 166189251Ssam * @len: Length of the text to convert in bytes (of buf); hex will be double 167189251Ssam * this size 168189251Ssam * Returns: 0 on success, -1 on failure (invalid hex string) 169189251Ssam */ 170189251Ssamint hexstr2bin(const char *hex, u8 *buf, size_t len) 171189251Ssam{ 172189251Ssam size_t i; 173189251Ssam int a; 174189251Ssam const char *ipos = hex; 175189251Ssam u8 *opos = buf; 176189251Ssam 177189251Ssam for (i = 0; i < len; i++) { 178189251Ssam a = hex2byte(ipos); 179189251Ssam if (a < 0) 180189251Ssam return -1; 181189251Ssam *opos++ = a; 182189251Ssam ipos += 2; 183189251Ssam } 184189251Ssam return 0; 185189251Ssam} 186189251Ssam 187189251Ssam 188281806Srpauloint hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask) 189281806Srpaulo{ 190281806Srpaulo size_t i; 191281806Srpaulo int print_mask = 0; 192281806Srpaulo int res; 193281806Srpaulo 194281806Srpaulo for (i = 0; i < ETH_ALEN; i++) { 195281806Srpaulo if (mask[i] != 0xff) { 196281806Srpaulo print_mask = 1; 197281806Srpaulo break; 198281806Srpaulo } 199281806Srpaulo } 200281806Srpaulo 201281806Srpaulo if (print_mask) 202281806Srpaulo res = os_snprintf(buf, len, MACSTR "/" MACSTR, 203281806Srpaulo MAC2STR(addr), MAC2STR(mask)); 204281806Srpaulo else 205281806Srpaulo res = os_snprintf(buf, len, MACSTR, MAC2STR(addr)); 206281806Srpaulo if (os_snprintf_error(len, res)) 207281806Srpaulo return -1; 208281806Srpaulo return res; 209281806Srpaulo} 210281806Srpaulo 211281806Srpaulo 212189251Ssam/** 213189251Ssam * inc_byte_array - Increment arbitrary length byte array by one 214189251Ssam * @counter: Pointer to byte array 215189251Ssam * @len: Length of the counter in bytes 216189251Ssam * 217189251Ssam * This function increments the last byte of the counter by one and continues 218189251Ssam * rolling over to more significant bytes if the byte was incremented from 219189251Ssam * 0xff to 0x00. 220189251Ssam */ 221189251Ssamvoid inc_byte_array(u8 *counter, size_t len) 222189251Ssam{ 223189251Ssam int pos = len - 1; 224189251Ssam while (pos >= 0) { 225189251Ssam counter[pos]++; 226189251Ssam if (counter[pos] != 0) 227189251Ssam break; 228189251Ssam pos--; 229189251Ssam } 230189251Ssam} 231189251Ssam 232189251Ssam 233351611Scyvoid buf_shift_right(u8 *buf, size_t len, size_t bits) 234351611Scy{ 235351611Scy size_t i; 236351611Scy 237351611Scy for (i = len - 1; i > 0; i--) 238351611Scy buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits); 239351611Scy buf[0] >>= bits; 240351611Scy} 241351611Scy 242351611Scy 243189251Ssamvoid wpa_get_ntp_timestamp(u8 *buf) 244189251Ssam{ 245189251Ssam struct os_time now; 246189251Ssam u32 sec, usec; 247189251Ssam be32 tmp; 248189251Ssam 249189251Ssam /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 250189251Ssam os_get_time(&now); 251189251Ssam sec = now.sec + 2208988800U; /* Epoch to 1900 */ 252189251Ssam /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 253189251Ssam usec = now.usec; 254189251Ssam usec = 4295 * usec - (usec >> 5) - (usec >> 9); 255189251Ssam tmp = host_to_be32(sec); 256189251Ssam os_memcpy(buf, (u8 *) &tmp, 4); 257189251Ssam tmp = host_to_be32(usec); 258189251Ssam os_memcpy(buf + 4, (u8 *) &tmp, 4); 259189251Ssam} 260189251Ssam 261281806Srpaulo/** 262281806Srpaulo * wpa_scnprintf - Simpler-to-use snprintf function 263281806Srpaulo * @buf: Output buffer 264281806Srpaulo * @size: Buffer size 265281806Srpaulo * @fmt: format 266281806Srpaulo * 267281806Srpaulo * Simpler snprintf version that doesn't require further error checks - the 268281806Srpaulo * return value only indicates how many bytes were actually written, excluding 269281806Srpaulo * the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough). 270281806Srpaulo */ 271281806Srpauloint wpa_scnprintf(char *buf, size_t size, const char *fmt, ...) 272281806Srpaulo{ 273281806Srpaulo va_list ap; 274281806Srpaulo int ret; 275189251Ssam 276281806Srpaulo if (!size) 277281806Srpaulo return 0; 278281806Srpaulo 279281806Srpaulo va_start(ap, fmt); 280281806Srpaulo ret = vsnprintf(buf, size, fmt, ap); 281281806Srpaulo va_end(ap); 282281806Srpaulo 283281806Srpaulo if (ret < 0) 284281806Srpaulo return 0; 285281806Srpaulo if ((size_t) ret >= size) 286281806Srpaulo return size - 1; 287281806Srpaulo 288281806Srpaulo return ret; 289281806Srpaulo} 290281806Srpaulo 291289549Srpaulo 292289549Srpauloint wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, 293289549Srpaulo char sep) 294289549Srpaulo{ 295289549Srpaulo size_t i; 296289549Srpaulo char *pos = buf, *end = buf + buf_size; 297289549Srpaulo int ret; 298289549Srpaulo 299289549Srpaulo if (buf_size == 0) 300289549Srpaulo return 0; 301289549Srpaulo 302289549Srpaulo for (i = 0; i < len; i++) { 303289549Srpaulo ret = os_snprintf(pos, end - pos, "%02x%c", 304289549Srpaulo data[i], sep); 305289549Srpaulo if (os_snprintf_error(end - pos, ret)) { 306289549Srpaulo end[-1] = '\0'; 307289549Srpaulo return pos - buf; 308289549Srpaulo } 309289549Srpaulo pos += ret; 310289549Srpaulo } 311289549Srpaulo pos[-1] = '\0'; 312289549Srpaulo return pos - buf; 313289549Srpaulo} 314289549Srpaulo 315289549Srpaulo 316189251Ssamstatic inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 317189251Ssam size_t len, int uppercase) 318189251Ssam{ 319189251Ssam size_t i; 320189251Ssam char *pos = buf, *end = buf + buf_size; 321189251Ssam int ret; 322189251Ssam if (buf_size == 0) 323189251Ssam return 0; 324189251Ssam for (i = 0; i < len; i++) { 325189251Ssam ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 326189251Ssam data[i]); 327281806Srpaulo if (os_snprintf_error(end - pos, ret)) { 328189251Ssam end[-1] = '\0'; 329189251Ssam return pos - buf; 330189251Ssam } 331189251Ssam pos += ret; 332189251Ssam } 333189251Ssam end[-1] = '\0'; 334189251Ssam return pos - buf; 335189251Ssam} 336189251Ssam 337189251Ssam/** 338189251Ssam * wpa_snprintf_hex - Print data as a hex string into a buffer 339189251Ssam * @buf: Memory area to use as the output buffer 340189251Ssam * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 341189251Ssam * @data: Data to be printed 342189251Ssam * @len: Length of data in bytes 343189251Ssam * Returns: Number of bytes written 344189251Ssam */ 345189251Ssamint wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 346189251Ssam{ 347189251Ssam return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 348189251Ssam} 349189251Ssam 350189251Ssam 351189251Ssam/** 352189251Ssam * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 353189251Ssam * @buf: Memory area to use as the output buffer 354189251Ssam * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 355189251Ssam * @data: Data to be printed 356189251Ssam * @len: Length of data in bytes 357189251Ssam * Returns: Number of bytes written 358189251Ssam */ 359189251Ssamint wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 360189251Ssam size_t len) 361189251Ssam{ 362189251Ssam return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 363189251Ssam} 364189251Ssam 365189251Ssam 366189251Ssam#ifdef CONFIG_ANSI_C_EXTRA 367189251Ssam 368189251Ssam#ifdef _WIN32_WCE 369189251Ssamvoid perror(const char *s) 370189251Ssam{ 371189251Ssam wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 372189251Ssam s, (int) GetLastError()); 373189251Ssam} 374189251Ssam#endif /* _WIN32_WCE */ 375189251Ssam 376189251Ssam 377189251Ssamint optind = 1; 378189251Ssamint optopt; 379189251Ssamchar *optarg; 380189251Ssam 381189251Ssamint getopt(int argc, char *const argv[], const char *optstring) 382189251Ssam{ 383189251Ssam static int optchr = 1; 384189251Ssam char *cp; 385189251Ssam 386189251Ssam if (optchr == 1) { 387189251Ssam if (optind >= argc) { 388189251Ssam /* all arguments processed */ 389189251Ssam return EOF; 390189251Ssam } 391189251Ssam 392189251Ssam if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 393189251Ssam /* no option characters */ 394189251Ssam return EOF; 395189251Ssam } 396189251Ssam } 397189251Ssam 398189251Ssam if (os_strcmp(argv[optind], "--") == 0) { 399189251Ssam /* no more options */ 400189251Ssam optind++; 401189251Ssam return EOF; 402189251Ssam } 403189251Ssam 404189251Ssam optopt = argv[optind][optchr]; 405189251Ssam cp = os_strchr(optstring, optopt); 406189251Ssam if (cp == NULL || optopt == ':') { 407189251Ssam if (argv[optind][++optchr] == '\0') { 408189251Ssam optchr = 1; 409189251Ssam optind++; 410189251Ssam } 411189251Ssam return '?'; 412189251Ssam } 413189251Ssam 414189251Ssam if (cp[1] == ':') { 415189251Ssam /* Argument required */ 416189251Ssam optchr = 1; 417189251Ssam if (argv[optind][optchr + 1]) { 418189251Ssam /* No space between option and argument */ 419189251Ssam optarg = &argv[optind++][optchr + 1]; 420189251Ssam } else if (++optind >= argc) { 421189251Ssam /* option requires an argument */ 422189251Ssam return '?'; 423189251Ssam } else { 424189251Ssam /* Argument in the next argv */ 425189251Ssam optarg = argv[optind++]; 426189251Ssam } 427189251Ssam } else { 428189251Ssam /* No argument */ 429189251Ssam if (argv[optind][++optchr] == '\0') { 430189251Ssam optchr = 1; 431189251Ssam optind++; 432189251Ssam } 433189251Ssam optarg = NULL; 434189251Ssam } 435189251Ssam return *cp; 436189251Ssam} 437189251Ssam#endif /* CONFIG_ANSI_C_EXTRA */ 438189251Ssam 439189251Ssam 440189251Ssam#ifdef CONFIG_NATIVE_WINDOWS 441189251Ssam/** 442189251Ssam * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 443189251Ssam * @str: Pointer to string to convert 444189251Ssam * 445189251Ssam * This function converts a unicode string to ASCII using the same 446189251Ssam * buffer for output. If UNICODE is not set, the buffer is not 447189251Ssam * modified. 448189251Ssam */ 449189251Ssamvoid wpa_unicode2ascii_inplace(TCHAR *str) 450189251Ssam{ 451189251Ssam#ifdef UNICODE 452189251Ssam char *dst = (char *) str; 453189251Ssam while (*str) 454189251Ssam *dst++ = (char) *str++; 455189251Ssam *dst = '\0'; 456189251Ssam#endif /* UNICODE */ 457189251Ssam} 458189251Ssam 459189251Ssam 460189251SsamTCHAR * wpa_strdup_tchar(const char *str) 461189251Ssam{ 462189251Ssam#ifdef UNICODE 463189251Ssam TCHAR *buf; 464189251Ssam buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 465189251Ssam if (buf == NULL) 466189251Ssam return NULL; 467189251Ssam wsprintf(buf, L"%S", str); 468189251Ssam return buf; 469189251Ssam#else /* UNICODE */ 470189251Ssam return os_strdup(str); 471189251Ssam#endif /* UNICODE */ 472189251Ssam} 473189251Ssam#endif /* CONFIG_NATIVE_WINDOWS */ 474189251Ssam 475189251Ssam 476252726Srpaulovoid printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) 477252726Srpaulo{ 478252726Srpaulo char *end = txt + maxlen; 479252726Srpaulo size_t i; 480252726Srpaulo 481252726Srpaulo for (i = 0; i < len; i++) { 482281806Srpaulo if (txt + 4 >= end) 483252726Srpaulo break; 484252726Srpaulo 485252726Srpaulo switch (data[i]) { 486252726Srpaulo case '\"': 487252726Srpaulo *txt++ = '\\'; 488252726Srpaulo *txt++ = '\"'; 489252726Srpaulo break; 490252726Srpaulo case '\\': 491252726Srpaulo *txt++ = '\\'; 492252726Srpaulo *txt++ = '\\'; 493252726Srpaulo break; 494281806Srpaulo case '\033': 495252726Srpaulo *txt++ = '\\'; 496252726Srpaulo *txt++ = 'e'; 497252726Srpaulo break; 498252726Srpaulo case '\n': 499252726Srpaulo *txt++ = '\\'; 500252726Srpaulo *txt++ = 'n'; 501252726Srpaulo break; 502252726Srpaulo case '\r': 503252726Srpaulo *txt++ = '\\'; 504252726Srpaulo *txt++ = 'r'; 505252726Srpaulo break; 506252726Srpaulo case '\t': 507252726Srpaulo *txt++ = '\\'; 508252726Srpaulo *txt++ = 't'; 509252726Srpaulo break; 510252726Srpaulo default: 511337817Scy if (data[i] >= 32 && data[i] <= 126) { 512252726Srpaulo *txt++ = data[i]; 513252726Srpaulo } else { 514252726Srpaulo txt += os_snprintf(txt, end - txt, "\\x%02x", 515252726Srpaulo data[i]); 516252726Srpaulo } 517252726Srpaulo break; 518252726Srpaulo } 519252726Srpaulo } 520252726Srpaulo 521252726Srpaulo *txt = '\0'; 522252726Srpaulo} 523252726Srpaulo 524252726Srpaulo 525252726Srpaulosize_t printf_decode(u8 *buf, size_t maxlen, const char *str) 526252726Srpaulo{ 527252726Srpaulo const char *pos = str; 528252726Srpaulo size_t len = 0; 529252726Srpaulo int val; 530252726Srpaulo 531252726Srpaulo while (*pos) { 532281806Srpaulo if (len + 1 >= maxlen) 533252726Srpaulo break; 534252726Srpaulo switch (*pos) { 535252726Srpaulo case '\\': 536252726Srpaulo pos++; 537252726Srpaulo switch (*pos) { 538252726Srpaulo case '\\': 539252726Srpaulo buf[len++] = '\\'; 540252726Srpaulo pos++; 541252726Srpaulo break; 542252726Srpaulo case '"': 543252726Srpaulo buf[len++] = '"'; 544252726Srpaulo pos++; 545252726Srpaulo break; 546252726Srpaulo case 'n': 547252726Srpaulo buf[len++] = '\n'; 548252726Srpaulo pos++; 549252726Srpaulo break; 550252726Srpaulo case 'r': 551252726Srpaulo buf[len++] = '\r'; 552252726Srpaulo pos++; 553252726Srpaulo break; 554252726Srpaulo case 't': 555252726Srpaulo buf[len++] = '\t'; 556252726Srpaulo pos++; 557252726Srpaulo break; 558252726Srpaulo case 'e': 559281806Srpaulo buf[len++] = '\033'; 560252726Srpaulo pos++; 561252726Srpaulo break; 562252726Srpaulo case 'x': 563252726Srpaulo pos++; 564252726Srpaulo val = hex2byte(pos); 565252726Srpaulo if (val < 0) { 566252726Srpaulo val = hex2num(*pos); 567252726Srpaulo if (val < 0) 568252726Srpaulo break; 569252726Srpaulo buf[len++] = val; 570252726Srpaulo pos++; 571252726Srpaulo } else { 572252726Srpaulo buf[len++] = val; 573252726Srpaulo pos += 2; 574252726Srpaulo } 575252726Srpaulo break; 576252726Srpaulo case '0': 577252726Srpaulo case '1': 578252726Srpaulo case '2': 579252726Srpaulo case '3': 580252726Srpaulo case '4': 581252726Srpaulo case '5': 582252726Srpaulo case '6': 583252726Srpaulo case '7': 584252726Srpaulo val = *pos++ - '0'; 585252726Srpaulo if (*pos >= '0' && *pos <= '7') 586252726Srpaulo val = val * 8 + (*pos++ - '0'); 587252726Srpaulo if (*pos >= '0' && *pos <= '7') 588252726Srpaulo val = val * 8 + (*pos++ - '0'); 589252726Srpaulo buf[len++] = val; 590252726Srpaulo break; 591252726Srpaulo default: 592252726Srpaulo break; 593252726Srpaulo } 594252726Srpaulo break; 595252726Srpaulo default: 596252726Srpaulo buf[len++] = *pos++; 597252726Srpaulo break; 598252726Srpaulo } 599252726Srpaulo } 600281806Srpaulo if (maxlen > len) 601281806Srpaulo buf[len] = '\0'; 602252726Srpaulo 603252726Srpaulo return len; 604252726Srpaulo} 605252726Srpaulo 606252726Srpaulo 607189251Ssam/** 608189251Ssam * wpa_ssid_txt - Convert SSID to a printable string 609189251Ssam * @ssid: SSID (32-octet string) 610189251Ssam * @ssid_len: Length of ssid in octets 611189251Ssam * Returns: Pointer to a printable string 612189251Ssam * 613189251Ssam * This function can be used to convert SSIDs into printable form. In most 614189251Ssam * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 615189251Ssam * does not limit the used character set, so anything could be used in an SSID. 616189251Ssam * 617189251Ssam * This function uses a static buffer, so only one call can be used at the 618189251Ssam * time, i.e., this is not re-entrant and the returned buffer must be used 619189251Ssam * before calling this again. 620189251Ssam */ 621189251Ssamconst char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 622189251Ssam{ 623289549Srpaulo static char ssid_txt[SSID_MAX_LEN * 4 + 1]; 624189251Ssam 625252726Srpaulo if (ssid == NULL) { 626252726Srpaulo ssid_txt[0] = '\0'; 627252726Srpaulo return ssid_txt; 628189251Ssam } 629252726Srpaulo 630252726Srpaulo printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); 631189251Ssam return ssid_txt; 632189251Ssam} 633209158Srpaulo 634209158Srpaulo 635209158Srpaulovoid * __hide_aliasing_typecast(void *foo) 636209158Srpaulo{ 637209158Srpaulo return foo; 638209158Srpaulo} 639252726Srpaulo 640252726Srpaulo 641252726Srpaulochar * wpa_config_parse_string(const char *value, size_t *len) 642252726Srpaulo{ 643252726Srpaulo if (*value == '"') { 644252726Srpaulo const char *pos; 645252726Srpaulo char *str; 646252726Srpaulo value++; 647252726Srpaulo pos = os_strrchr(value, '"'); 648252726Srpaulo if (pos == NULL || pos[1] != '\0') 649252726Srpaulo return NULL; 650252726Srpaulo *len = pos - value; 651281806Srpaulo str = dup_binstr(value, *len); 652252726Srpaulo if (str == NULL) 653252726Srpaulo return NULL; 654252726Srpaulo return str; 655252726Srpaulo } else if (*value == 'P' && value[1] == '"') { 656252726Srpaulo const char *pos; 657252726Srpaulo char *tstr, *str; 658252726Srpaulo size_t tlen; 659252726Srpaulo value += 2; 660252726Srpaulo pos = os_strrchr(value, '"'); 661252726Srpaulo if (pos == NULL || pos[1] != '\0') 662252726Srpaulo return NULL; 663252726Srpaulo tlen = pos - value; 664281806Srpaulo tstr = dup_binstr(value, tlen); 665252726Srpaulo if (tstr == NULL) 666252726Srpaulo return NULL; 667252726Srpaulo 668252726Srpaulo str = os_malloc(tlen + 1); 669252726Srpaulo if (str == NULL) { 670252726Srpaulo os_free(tstr); 671252726Srpaulo return NULL; 672252726Srpaulo } 673252726Srpaulo 674252726Srpaulo *len = printf_decode((u8 *) str, tlen + 1, tstr); 675252726Srpaulo os_free(tstr); 676252726Srpaulo 677252726Srpaulo return str; 678252726Srpaulo } else { 679252726Srpaulo u8 *str; 680252726Srpaulo size_t tlen, hlen = os_strlen(value); 681252726Srpaulo if (hlen & 1) 682252726Srpaulo return NULL; 683252726Srpaulo tlen = hlen / 2; 684252726Srpaulo str = os_malloc(tlen + 1); 685252726Srpaulo if (str == NULL) 686252726Srpaulo return NULL; 687252726Srpaulo if (hexstr2bin(value, str, tlen)) { 688252726Srpaulo os_free(str); 689252726Srpaulo return NULL; 690252726Srpaulo } 691252726Srpaulo str[tlen] = '\0'; 692252726Srpaulo *len = tlen; 693252726Srpaulo return (char *) str; 694252726Srpaulo } 695252726Srpaulo} 696252726Srpaulo 697252726Srpaulo 698252726Srpauloint is_hex(const u8 *data, size_t len) 699252726Srpaulo{ 700252726Srpaulo size_t i; 701252726Srpaulo 702252726Srpaulo for (i = 0; i < len; i++) { 703252726Srpaulo if (data[i] < 32 || data[i] >= 127) 704252726Srpaulo return 1; 705252726Srpaulo } 706252726Srpaulo return 0; 707252726Srpaulo} 708252726Srpaulo 709252726Srpaulo 710337817Scyint has_ctrl_char(const u8 *data, size_t len) 711337817Scy{ 712337817Scy size_t i; 713337817Scy 714337817Scy for (i = 0; i < len; i++) { 715337817Scy if (data[i] < 32 || data[i] == 127) 716337817Scy return 1; 717337817Scy } 718337817Scy return 0; 719337817Scy} 720337817Scy 721337817Scy 722337817Scyint has_newline(const char *str) 723337817Scy{ 724337817Scy while (*str) { 725337817Scy if (*str == '\n' || *str == '\r') 726337817Scy return 1; 727337817Scy str++; 728337817Scy } 729337817Scy return 0; 730337817Scy} 731337817Scy 732337817Scy 733252726Srpaulosize_t merge_byte_arrays(u8 *res, size_t res_len, 734252726Srpaulo const u8 *src1, size_t src1_len, 735252726Srpaulo const u8 *src2, size_t src2_len) 736252726Srpaulo{ 737252726Srpaulo size_t len = 0; 738252726Srpaulo 739252726Srpaulo os_memset(res, 0, res_len); 740252726Srpaulo 741252726Srpaulo if (src1) { 742252726Srpaulo if (src1_len >= res_len) { 743252726Srpaulo os_memcpy(res, src1, res_len); 744252726Srpaulo return res_len; 745252726Srpaulo } 746252726Srpaulo 747252726Srpaulo os_memcpy(res, src1, src1_len); 748252726Srpaulo len += src1_len; 749252726Srpaulo } 750252726Srpaulo 751252726Srpaulo if (src2) { 752252726Srpaulo if (len + src2_len >= res_len) { 753252726Srpaulo os_memcpy(res + len, src2, res_len - len); 754252726Srpaulo return res_len; 755252726Srpaulo } 756252726Srpaulo 757252726Srpaulo os_memcpy(res + len, src2, src2_len); 758252726Srpaulo len += src2_len; 759252726Srpaulo } 760252726Srpaulo 761252726Srpaulo return len; 762252726Srpaulo} 763281806Srpaulo 764281806Srpaulo 765281806Srpaulochar * dup_binstr(const void *src, size_t len) 766281806Srpaulo{ 767281806Srpaulo char *res; 768281806Srpaulo 769281806Srpaulo if (src == NULL) 770281806Srpaulo return NULL; 771281806Srpaulo res = os_malloc(len + 1); 772281806Srpaulo if (res == NULL) 773281806Srpaulo return NULL; 774281806Srpaulo os_memcpy(res, src, len); 775281806Srpaulo res[len] = '\0'; 776281806Srpaulo 777281806Srpaulo return res; 778281806Srpaulo} 779281806Srpaulo 780281806Srpaulo 781281806Srpauloint freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) 782281806Srpaulo{ 783281806Srpaulo struct wpa_freq_range *freq = NULL, *n; 784281806Srpaulo unsigned int count = 0; 785281806Srpaulo const char *pos, *pos2, *pos3; 786281806Srpaulo 787281806Srpaulo /* 788281806Srpaulo * Comma separated list of frequency ranges. 789281806Srpaulo * For example: 2412-2432,2462,5000-6000 790281806Srpaulo */ 791281806Srpaulo pos = value; 792281806Srpaulo while (pos && pos[0]) { 793281806Srpaulo n = os_realloc_array(freq, count + 1, 794281806Srpaulo sizeof(struct wpa_freq_range)); 795281806Srpaulo if (n == NULL) { 796281806Srpaulo os_free(freq); 797281806Srpaulo return -1; 798281806Srpaulo } 799281806Srpaulo freq = n; 800281806Srpaulo freq[count].min = atoi(pos); 801281806Srpaulo pos2 = os_strchr(pos, '-'); 802281806Srpaulo pos3 = os_strchr(pos, ','); 803281806Srpaulo if (pos2 && (!pos3 || pos2 < pos3)) { 804281806Srpaulo pos2++; 805281806Srpaulo freq[count].max = atoi(pos2); 806281806Srpaulo } else 807281806Srpaulo freq[count].max = freq[count].min; 808281806Srpaulo pos = pos3; 809281806Srpaulo if (pos) 810281806Srpaulo pos++; 811281806Srpaulo count++; 812281806Srpaulo } 813281806Srpaulo 814281806Srpaulo os_free(res->range); 815281806Srpaulo res->range = freq; 816281806Srpaulo res->num = count; 817281806Srpaulo 818281806Srpaulo return 0; 819281806Srpaulo} 820281806Srpaulo 821281806Srpaulo 822281806Srpauloint freq_range_list_includes(const struct wpa_freq_range_list *list, 823281806Srpaulo unsigned int freq) 824281806Srpaulo{ 825281806Srpaulo unsigned int i; 826281806Srpaulo 827281806Srpaulo if (list == NULL) 828281806Srpaulo return 0; 829281806Srpaulo 830281806Srpaulo for (i = 0; i < list->num; i++) { 831281806Srpaulo if (freq >= list->range[i].min && freq <= list->range[i].max) 832281806Srpaulo return 1; 833281806Srpaulo } 834281806Srpaulo 835281806Srpaulo return 0; 836281806Srpaulo} 837281806Srpaulo 838281806Srpaulo 839281806Srpaulochar * freq_range_list_str(const struct wpa_freq_range_list *list) 840281806Srpaulo{ 841281806Srpaulo char *buf, *pos, *end; 842281806Srpaulo size_t maxlen; 843281806Srpaulo unsigned int i; 844281806Srpaulo int res; 845281806Srpaulo 846281806Srpaulo if (list->num == 0) 847281806Srpaulo return NULL; 848281806Srpaulo 849281806Srpaulo maxlen = list->num * 30; 850281806Srpaulo buf = os_malloc(maxlen); 851281806Srpaulo if (buf == NULL) 852281806Srpaulo return NULL; 853281806Srpaulo pos = buf; 854281806Srpaulo end = buf + maxlen; 855281806Srpaulo 856281806Srpaulo for (i = 0; i < list->num; i++) { 857281806Srpaulo struct wpa_freq_range *range = &list->range[i]; 858281806Srpaulo 859281806Srpaulo if (range->min == range->max) 860281806Srpaulo res = os_snprintf(pos, end - pos, "%s%u", 861281806Srpaulo i == 0 ? "" : ",", range->min); 862281806Srpaulo else 863281806Srpaulo res = os_snprintf(pos, end - pos, "%s%u-%u", 864281806Srpaulo i == 0 ? "" : ",", 865281806Srpaulo range->min, range->max); 866281806Srpaulo if (os_snprintf_error(end - pos, res)) { 867281806Srpaulo os_free(buf); 868281806Srpaulo return NULL; 869281806Srpaulo } 870281806Srpaulo pos += res; 871281806Srpaulo } 872281806Srpaulo 873281806Srpaulo return buf; 874281806Srpaulo} 875281806Srpaulo 876281806Srpaulo 877281806Srpauloint int_array_len(const int *a) 878281806Srpaulo{ 879281806Srpaulo int i; 880281806Srpaulo for (i = 0; a && a[i]; i++) 881281806Srpaulo ; 882281806Srpaulo return i; 883281806Srpaulo} 884281806Srpaulo 885281806Srpaulo 886281806Srpaulovoid int_array_concat(int **res, const int *a) 887281806Srpaulo{ 888281806Srpaulo int reslen, alen, i; 889281806Srpaulo int *n; 890281806Srpaulo 891281806Srpaulo reslen = int_array_len(*res); 892281806Srpaulo alen = int_array_len(a); 893281806Srpaulo 894281806Srpaulo n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); 895281806Srpaulo if (n == NULL) { 896281806Srpaulo os_free(*res); 897281806Srpaulo *res = NULL; 898281806Srpaulo return; 899281806Srpaulo } 900281806Srpaulo for (i = 0; i <= alen; i++) 901281806Srpaulo n[reslen + i] = a[i]; 902281806Srpaulo *res = n; 903281806Srpaulo} 904281806Srpaulo 905281806Srpaulo 906281806Srpaulostatic int freq_cmp(const void *a, const void *b) 907281806Srpaulo{ 908281806Srpaulo int _a = *(int *) a; 909281806Srpaulo int _b = *(int *) b; 910281806Srpaulo 911281806Srpaulo if (_a == 0) 912281806Srpaulo return 1; 913281806Srpaulo if (_b == 0) 914281806Srpaulo return -1; 915281806Srpaulo return _a - _b; 916281806Srpaulo} 917281806Srpaulo 918281806Srpaulo 919281806Srpaulovoid int_array_sort_unique(int *a) 920281806Srpaulo{ 921281806Srpaulo int alen; 922281806Srpaulo int i, j; 923281806Srpaulo 924281806Srpaulo if (a == NULL) 925281806Srpaulo return; 926281806Srpaulo 927281806Srpaulo alen = int_array_len(a); 928281806Srpaulo qsort(a, alen, sizeof(int), freq_cmp); 929281806Srpaulo 930281806Srpaulo i = 0; 931281806Srpaulo j = 1; 932281806Srpaulo while (a[i] && a[j]) { 933281806Srpaulo if (a[i] == a[j]) { 934281806Srpaulo j++; 935281806Srpaulo continue; 936281806Srpaulo } 937281806Srpaulo a[++i] = a[j++]; 938281806Srpaulo } 939281806Srpaulo if (a[i]) 940281806Srpaulo i++; 941281806Srpaulo a[i] = 0; 942281806Srpaulo} 943281806Srpaulo 944281806Srpaulo 945281806Srpaulovoid int_array_add_unique(int **res, int a) 946281806Srpaulo{ 947281806Srpaulo int reslen; 948281806Srpaulo int *n; 949281806Srpaulo 950281806Srpaulo for (reslen = 0; *res && (*res)[reslen]; reslen++) { 951281806Srpaulo if ((*res)[reslen] == a) 952281806Srpaulo return; /* already in the list */ 953281806Srpaulo } 954281806Srpaulo 955281806Srpaulo n = os_realloc_array(*res, reslen + 2, sizeof(int)); 956281806Srpaulo if (n == NULL) { 957281806Srpaulo os_free(*res); 958281806Srpaulo *res = NULL; 959281806Srpaulo return; 960281806Srpaulo } 961281806Srpaulo 962281806Srpaulo n[reslen] = a; 963281806Srpaulo n[reslen + 1] = 0; 964281806Srpaulo 965281806Srpaulo *res = n; 966281806Srpaulo} 967281806Srpaulo 968281806Srpaulo 969281806Srpaulovoid str_clear_free(char *str) 970281806Srpaulo{ 971281806Srpaulo if (str) { 972281806Srpaulo size_t len = os_strlen(str); 973351611Scy forced_memzero(str, len); 974281806Srpaulo os_free(str); 975281806Srpaulo } 976281806Srpaulo} 977281806Srpaulo 978281806Srpaulo 979281806Srpaulovoid bin_clear_free(void *bin, size_t len) 980281806Srpaulo{ 981281806Srpaulo if (bin) { 982351611Scy forced_memzero(bin, len); 983281806Srpaulo os_free(bin); 984281806Srpaulo } 985281806Srpaulo} 986281806Srpaulo 987281806Srpaulo 988281806Srpauloint random_mac_addr(u8 *addr) 989281806Srpaulo{ 990281806Srpaulo if (os_get_random(addr, ETH_ALEN) < 0) 991281806Srpaulo return -1; 992281806Srpaulo addr[0] &= 0xfe; /* unicast */ 993281806Srpaulo addr[0] |= 0x02; /* locally administered */ 994281806Srpaulo return 0; 995281806Srpaulo} 996281806Srpaulo 997281806Srpaulo 998281806Srpauloint random_mac_addr_keep_oui(u8 *addr) 999281806Srpaulo{ 1000281806Srpaulo if (os_get_random(addr + 3, 3) < 0) 1001281806Srpaulo return -1; 1002281806Srpaulo addr[0] &= 0xfe; /* unicast */ 1003281806Srpaulo addr[0] |= 0x02; /* locally administered */ 1004281806Srpaulo return 0; 1005281806Srpaulo} 1006281806Srpaulo 1007281806Srpaulo 1008281806Srpaulo/** 1009289549Srpaulo * cstr_token - Get next token from const char string 1010289549Srpaulo * @str: a constant string to tokenize 1011289549Srpaulo * @delim: a string of delimiters 1012289549Srpaulo * @last: a pointer to a character following the returned token 1013289549Srpaulo * It has to be set to NULL for the first call and passed for any 1014337817Scy * further call. 1015289549Srpaulo * Returns: a pointer to token position in str or NULL 1016289549Srpaulo * 1017289549Srpaulo * This function is similar to str_token, but it can be used with both 1018289549Srpaulo * char and const char strings. Differences: 1019289549Srpaulo * - The str buffer remains unmodified 1020289549Srpaulo * - The returned token is not a NULL terminated string, but a token 1021289549Srpaulo * position in str buffer. If a return value is not NULL a size 1022289549Srpaulo * of the returned token could be calculated as (last - token). 1023289549Srpaulo */ 1024289549Srpauloconst char * cstr_token(const char *str, const char *delim, const char **last) 1025289549Srpaulo{ 1026289549Srpaulo const char *end, *token = str; 1027289549Srpaulo 1028289549Srpaulo if (!str || !delim || !last) 1029289549Srpaulo return NULL; 1030289549Srpaulo 1031289549Srpaulo if (*last) 1032289549Srpaulo token = *last; 1033289549Srpaulo 1034289549Srpaulo while (*token && os_strchr(delim, *token)) 1035289549Srpaulo token++; 1036289549Srpaulo 1037289549Srpaulo if (!*token) 1038289549Srpaulo return NULL; 1039289549Srpaulo 1040289549Srpaulo end = token + 1; 1041289549Srpaulo 1042289549Srpaulo while (*end && !os_strchr(delim, *end)) 1043289549Srpaulo end++; 1044289549Srpaulo 1045289549Srpaulo *last = end; 1046289549Srpaulo return token; 1047289549Srpaulo} 1048289549Srpaulo 1049289549Srpaulo 1050289549Srpaulo/** 1051281806Srpaulo * str_token - Get next token from a string 1052281806Srpaulo * @buf: String to tokenize. Note that the string might be modified. 1053281806Srpaulo * @delim: String of delimiters 1054281806Srpaulo * @context: Pointer to save our context. Should be initialized with 1055281806Srpaulo * NULL on the first call, and passed for any further call. 1056281806Srpaulo * Returns: The next token, NULL if there are no more valid tokens. 1057281806Srpaulo */ 1058281806Srpaulochar * str_token(char *str, const char *delim, char **context) 1059281806Srpaulo{ 1060289549Srpaulo char *token = (char *) cstr_token(str, delim, (const char **) context); 1061281806Srpaulo 1062289549Srpaulo if (token && **context) 1063289549Srpaulo *(*context)++ = '\0'; 1064281806Srpaulo 1065289549Srpaulo return token; 1066281806Srpaulo} 1067281806Srpaulo 1068281806Srpaulo 1069281806Srpaulosize_t utf8_unescape(const char *inp, size_t in_size, 1070281806Srpaulo char *outp, size_t out_size) 1071281806Srpaulo{ 1072281806Srpaulo size_t res_size = 0; 1073281806Srpaulo 1074281806Srpaulo if (!inp || !outp) 1075281806Srpaulo return 0; 1076281806Srpaulo 1077281806Srpaulo if (!in_size) 1078281806Srpaulo in_size = os_strlen(inp); 1079281806Srpaulo 1080281806Srpaulo /* Advance past leading single quote */ 1081281806Srpaulo if (*inp == '\'' && in_size) { 1082281806Srpaulo inp++; 1083281806Srpaulo in_size--; 1084281806Srpaulo } 1085281806Srpaulo 1086346981Scy while (in_size) { 1087346981Scy in_size--; 1088281806Srpaulo if (res_size >= out_size) 1089281806Srpaulo return 0; 1090281806Srpaulo 1091281806Srpaulo switch (*inp) { 1092281806Srpaulo case '\'': 1093281806Srpaulo /* Terminate on bare single quote */ 1094281806Srpaulo *outp = '\0'; 1095281806Srpaulo return res_size; 1096281806Srpaulo 1097281806Srpaulo case '\\': 1098346981Scy if (!in_size) 1099281806Srpaulo return 0; 1100346981Scy in_size--; 1101281806Srpaulo inp++; 1102281806Srpaulo /* fall through */ 1103281806Srpaulo 1104281806Srpaulo default: 1105281806Srpaulo *outp++ = *inp++; 1106281806Srpaulo res_size++; 1107281806Srpaulo } 1108281806Srpaulo } 1109281806Srpaulo 1110281806Srpaulo /* NUL terminate if space allows */ 1111281806Srpaulo if (res_size < out_size) 1112281806Srpaulo *outp = '\0'; 1113281806Srpaulo 1114281806Srpaulo return res_size; 1115281806Srpaulo} 1116281806Srpaulo 1117281806Srpaulo 1118281806Srpaulosize_t utf8_escape(const char *inp, size_t in_size, 1119281806Srpaulo char *outp, size_t out_size) 1120281806Srpaulo{ 1121281806Srpaulo size_t res_size = 0; 1122281806Srpaulo 1123281806Srpaulo if (!inp || !outp) 1124281806Srpaulo return 0; 1125281806Srpaulo 1126281806Srpaulo /* inp may or may not be NUL terminated, but must be if 0 size 1127281806Srpaulo * is specified */ 1128281806Srpaulo if (!in_size) 1129281806Srpaulo in_size = os_strlen(inp); 1130281806Srpaulo 1131346981Scy while (in_size) { 1132346981Scy in_size--; 1133281806Srpaulo if (res_size++ >= out_size) 1134281806Srpaulo return 0; 1135281806Srpaulo 1136281806Srpaulo switch (*inp) { 1137281806Srpaulo case '\\': 1138281806Srpaulo case '\'': 1139281806Srpaulo if (res_size++ >= out_size) 1140281806Srpaulo return 0; 1141281806Srpaulo *outp++ = '\\'; 1142281806Srpaulo /* fall through */ 1143281806Srpaulo 1144281806Srpaulo default: 1145281806Srpaulo *outp++ = *inp++; 1146281806Srpaulo break; 1147281806Srpaulo } 1148281806Srpaulo } 1149281806Srpaulo 1150281806Srpaulo /* NUL terminate if space allows */ 1151281806Srpaulo if (res_size < out_size) 1152281806Srpaulo *outp = '\0'; 1153281806Srpaulo 1154281806Srpaulo return res_size; 1155281806Srpaulo} 1156289549Srpaulo 1157289549Srpaulo 1158289549Srpauloint is_ctrl_char(char c) 1159289549Srpaulo{ 1160289549Srpaulo return c > 0 && c < 32; 1161289549Srpaulo} 1162337817Scy 1163337817Scy 1164337817Scy/** 1165337817Scy * ssid_parse - Parse a string that contains SSID in hex or text format 1166337817Scy * @buf: Input NULL terminated string that contains the SSID 1167337817Scy * @ssid: Output SSID 1168337817Scy * Returns: 0 on success, -1 otherwise 1169337817Scy * 1170337817Scy * The SSID has to be enclosed in double quotes for the text format or space 1171337817Scy * or NULL terminated string of hex digits for the hex format. buf can include 1172337817Scy * additional arguments after the SSID. 1173337817Scy */ 1174337817Scyint ssid_parse(const char *buf, struct wpa_ssid_value *ssid) 1175337817Scy{ 1176337817Scy char *tmp, *res, *end; 1177337817Scy size_t len; 1178337817Scy 1179337817Scy ssid->ssid_len = 0; 1180337817Scy 1181337817Scy tmp = os_strdup(buf); 1182337817Scy if (!tmp) 1183337817Scy return -1; 1184337817Scy 1185337817Scy if (*tmp != '"') { 1186337817Scy end = os_strchr(tmp, ' '); 1187337817Scy if (end) 1188337817Scy *end = '\0'; 1189337817Scy } else { 1190337817Scy end = os_strchr(tmp + 1, '"'); 1191337817Scy if (!end) { 1192337817Scy os_free(tmp); 1193337817Scy return -1; 1194337817Scy } 1195337817Scy 1196337817Scy end[1] = '\0'; 1197337817Scy } 1198337817Scy 1199337817Scy res = wpa_config_parse_string(tmp, &len); 1200337817Scy if (res && len <= SSID_MAX_LEN) { 1201337817Scy ssid->ssid_len = len; 1202337817Scy os_memcpy(ssid->ssid, res, len); 1203337817Scy } 1204337817Scy 1205337817Scy os_free(tmp); 1206337817Scy os_free(res); 1207337817Scy 1208337817Scy return ssid->ssid_len ? 0 : -1; 1209337817Scy} 1210337817Scy 1211337817Scy 1212337817Scyint str_starts(const char *str, const char *start) 1213337817Scy{ 1214337817Scy return os_strncmp(str, start, os_strlen(start)) == 0; 1215337817Scy} 1216346981Scy 1217346981Scy 1218346981Scy/** 1219346981Scy * rssi_to_rcpi - Convert RSSI to RCPI 1220346981Scy * @rssi: RSSI to convert 1221346981Scy * Returns: RCPI corresponding to the given RSSI value, or 255 if not available. 1222346981Scy * 1223346981Scy * It's possible to estimate RCPI based on RSSI in dBm. This calculation will 1224346981Scy * not reflect the correct value for high rates, but it's good enough for Action 1225346981Scy * frames which are transmitted with up to 24 Mbps rates. 1226346981Scy */ 1227346981Scyu8 rssi_to_rcpi(int rssi) 1228346981Scy{ 1229346981Scy if (!rssi) 1230346981Scy return 255; /* not available */ 1231346981Scy if (rssi < -110) 1232346981Scy return 0; 1233346981Scy if (rssi > 0) 1234346981Scy return 220; 1235346981Scy return (rssi + 110) * 2; 1236346981Scy} 1237346981Scy 1238346981Scy 1239346981Scychar * get_param(const char *cmd, const char *param) 1240346981Scy{ 1241346981Scy const char *pos, *end; 1242346981Scy char *val; 1243346981Scy size_t len; 1244346981Scy 1245346981Scy pos = os_strstr(cmd, param); 1246346981Scy if (!pos) 1247346981Scy return NULL; 1248346981Scy 1249346981Scy pos += os_strlen(param); 1250346981Scy end = os_strchr(pos, ' '); 1251346981Scy if (end) 1252346981Scy len = end - pos; 1253346981Scy else 1254346981Scy len = os_strlen(pos); 1255346981Scy val = os_malloc(len + 1); 1256346981Scy if (!val) 1257346981Scy return NULL; 1258346981Scy os_memcpy(val, pos, len); 1259346981Scy val[len] = '\0'; 1260346981Scy return val; 1261346981Scy} 1262351611Scy 1263351611Scy 1264351611Scy/* Try to prevent most compilers from optimizing out clearing of memory that 1265351611Scy * becomes unaccessible after this function is called. This is mostly the case 1266351611Scy * for clearing local stack variables at the end of a function. This is not 1267351611Scy * exactly perfect, i.e., someone could come up with a compiler that figures out 1268351611Scy * the pointer is pointing to memset and then end up optimizing the call out, so 1269351611Scy * try go a bit further by storing the first octet (now zero) to make this even 1270351611Scy * a bit more difficult to optimize out. Once memset_s() is available, that 1271351611Scy * could be used here instead. */ 1272351611Scystatic void * (* const volatile memset_func)(void *, int, size_t) = memset; 1273351611Scystatic u8 forced_memzero_val; 1274351611Scy 1275351611Scyvoid forced_memzero(void *ptr, size_t len) 1276351611Scy{ 1277351611Scy memset_func(ptr, 0, len); 1278351611Scy if (len) 1279351611Scy forced_memzero_val = ((u8 *) ptr)[0]; 1280351611Scy} 1281