1 /* 2 * wpa_supplicant/hostapd / common helper functions, etc. 3 * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 13 14 static int hex2num(char c) 15 { 16 if (c >= '0' && c <= '9') 17 return c - '0'; 18 if (c >= 'a' && c <= 'f') 19 return c - 'a' + 10; 20 if (c >= 'A' && c <= 'F') 21 return c - 'A' + 10; 22 return -1; 23 } 24 25 26 int hex2byte(const char *hex) 27 { 28 int a, b; 29 a = hex2num(*hex++); 30 if (a < 0) 31 return -1; 32 b = hex2num(*hex++); 33 if (b < 0) 34 return -1; 35 return (a << 4) | b; 36 } 37 38 39 /** 40 * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) 41 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 42 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 43 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 44 */ 45 int hwaddr_aton(const char *txt, u8 *addr) 46 { 47 int i; 48 49 for (i = 0; i < 6; i++) { 50 int a, b; 51 52 a = hex2num(*txt++); 53 if (a < 0) 54 return -1; 55 b = hex2num(*txt++); 56 if (b < 0) 57 return -1; 58 *addr++ = (a << 4) | b; 59 if (i < 5 && *txt++ != ':') 60 return -1; 61 } 62 63 return 0; 64 } 65 66 /** 67 * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) 68 * @txt: MAC address as a string (e.g., "001122334455") 69 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 70 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 71 */ 72 int hwaddr_compact_aton(const char *txt, u8 *addr) 73 { 74 int i; 75 76 for (i = 0; i < 6; i++) { 77 int a, b; 78 79 a = hex2num(*txt++); 80 if (a < 0) 81 return -1; 82 b = hex2num(*txt++); 83 if (b < 0) 84 return -1; 85 *addr++ = (a << 4) | b; 86 } 87 88 return 0; 89 } 90 91 /** 92 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) 93 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) 94 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 95 * Returns: Characters used (> 0) on success, -1 on failure 96 */ 97 int hwaddr_aton2(const char *txt, u8 *addr) 98 { 99 int i; 100 const char *pos = txt; 101 102 for (i = 0; i < 6; i++) { 103 int a, b; 104 105 while (*pos == ':' || *pos == '.' || *pos == '-') 106 pos++; 107 108 a = hex2num(*pos++); 109 if (a < 0) 110 return -1; 111 b = hex2num(*pos++); 112 if (b < 0) 113 return -1; 114 *addr++ = (a << 4) | b; 115 } 116 117 return pos - txt; 118 } 119 120 121 /** 122 * hexstr2bin - Convert ASCII hex string into binary data 123 * @hex: ASCII hex string (e.g., "01ab") 124 * @buf: Buffer for the binary data 125 * @len: Length of the text to convert in bytes (of buf); hex will be double 126 * this size 127 * Returns: 0 on success, -1 on failure (invalid hex string) 128 */ 129 int hexstr2bin(const char *hex, u8 *buf, size_t len) 130 { 131 size_t i; 132 int a; 133 const char *ipos = hex; 134 u8 *opos = buf; 135 136 for (i = 0; i < len; i++) { 137 a = hex2byte(ipos); 138 if (a < 0) 139 return -1; 140 *opos++ = a; 141 ipos += 2; 142 } 143 return 0; 144 } 145 146 147 /** 148 * inc_byte_array - Increment arbitrary length byte array by one 149 * @counter: Pointer to byte array 150 * @len: Length of the counter in bytes 151 * 152 * This function increments the last byte of the counter by one and continues 153 * rolling over to more significant bytes if the byte was incremented from 154 * 0xff to 0x00. 155 */ 156 void inc_byte_array(u8 *counter, size_t len) 157 { 158 int pos = len - 1; 159 while (pos >= 0) { 160 counter[pos]++; 161 if (counter[pos] != 0) 162 break; 163 pos--; 164 } 165 } 166 167 168 void wpa_get_ntp_timestamp(u8 *buf) 169 { 170 struct os_time now; 171 u32 sec, usec; 172 be32 tmp; 173 174 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 175 os_get_time(&now); 176 sec = now.sec + 2208988800U; /* Epoch to 1900 */ 177 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 178 usec = now.usec; 179 usec = 4295 * usec - (usec >> 5) - (usec >> 9); 180 tmp = host_to_be32(sec); 181 os_memcpy(buf, (u8 *) &tmp, 4); 182 tmp = host_to_be32(usec); 183 os_memcpy(buf + 4, (u8 *) &tmp, 4); 184 } 185 186 187 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 188 size_t len, int uppercase) 189 { 190 size_t i; 191 char *pos = buf, *end = buf + buf_size; 192 int ret; 193 if (buf_size == 0) 194 return 0; 195 for (i = 0; i < len; i++) { 196 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 197 data[i]); 198 if (ret < 0 || ret >= end - pos) { 199 end[-1] = '\0'; 200 return pos - buf; 201 } 202 pos += ret; 203 } 204 end[-1] = '\0'; 205 return pos - buf; 206 } 207 208 /** 209 * wpa_snprintf_hex - Print data as a hex string into a buffer 210 * @buf: Memory area to use as the output buffer 211 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 212 * @data: Data to be printed 213 * @len: Length of data in bytes 214 * Returns: Number of bytes written 215 */ 216 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 217 { 218 return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 219 } 220 221 222 /** 223 * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 224 * @buf: Memory area to use as the output buffer 225 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 226 * @data: Data to be printed 227 * @len: Length of data in bytes 228 * Returns: Number of bytes written 229 */ 230 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 231 size_t len) 232 { 233 return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 234 } 235 236 237 #ifdef CONFIG_ANSI_C_EXTRA 238 239 #ifdef _WIN32_WCE 240 void perror(const char *s) 241 { 242 wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 243 s, (int) GetLastError()); 244 } 245 #endif /* _WIN32_WCE */ 246 247 248 int optind = 1; 249 int optopt; 250 char *optarg; 251 252 int getopt(int argc, char *const argv[], const char *optstring) 253 { 254 static int optchr = 1; 255 char *cp; 256 257 if (optchr == 1) { 258 if (optind >= argc) { 259 /* all arguments processed */ 260 return EOF; 261 } 262 263 if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 264 /* no option characters */ 265 return EOF; 266 } 267 } 268 269 if (os_strcmp(argv[optind], "--") == 0) { 270 /* no more options */ 271 optind++; 272 return EOF; 273 } 274 275 optopt = argv[optind][optchr]; 276 cp = os_strchr(optstring, optopt); 277 if (cp == NULL || optopt == ':') { 278 if (argv[optind][++optchr] == '\0') { 279 optchr = 1; 280 optind++; 281 } 282 return '?'; 283 } 284 285 if (cp[1] == ':') { 286 /* Argument required */ 287 optchr = 1; 288 if (argv[optind][optchr + 1]) { 289 /* No space between option and argument */ 290 optarg = &argv[optind++][optchr + 1]; 291 } else if (++optind >= argc) { 292 /* option requires an argument */ 293 return '?'; 294 } else { 295 /* Argument in the next argv */ 296 optarg = argv[optind++]; 297 } 298 } else { 299 /* No argument */ 300 if (argv[optind][++optchr] == '\0') { 301 optchr = 1; 302 optind++; 303 } 304 optarg = NULL; 305 } 306 return *cp; 307 } 308 #endif /* CONFIG_ANSI_C_EXTRA */ 309 310 311 #ifdef CONFIG_NATIVE_WINDOWS 312 /** 313 * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 314 * @str: Pointer to string to convert 315 * 316 * This function converts a unicode string to ASCII using the same 317 * buffer for output. If UNICODE is not set, the buffer is not 318 * modified. 319 */ 320 void wpa_unicode2ascii_inplace(TCHAR *str) 321 { 322 #ifdef UNICODE 323 char *dst = (char *) str; 324 while (*str) 325 *dst++ = (char) *str++; 326 *dst = '\0'; 327 #endif /* UNICODE */ 328 } 329 330 331 TCHAR * wpa_strdup_tchar(const char *str) 332 { 333 #ifdef UNICODE 334 TCHAR *buf; 335 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 336 if (buf == NULL) 337 return NULL; 338 wsprintf(buf, L"%S", str); 339 return buf; 340 #else /* UNICODE */ 341 return os_strdup(str); 342 #endif /* UNICODE */ 343 } 344 #endif /* CONFIG_NATIVE_WINDOWS */ 345 346 347 void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) 348 { 349 char *end = txt + maxlen; 350 size_t i; 351 352 for (i = 0; i < len; i++) { 353 if (txt + 4 > end) 354 break; 355 356 switch (data[i]) { 357 case '\"': 358 *txt++ = '\\'; 359 *txt++ = '\"'; 360 break; 361 case '\\': 362 *txt++ = '\\'; 363 *txt++ = '\\'; 364 break; 365 case '\e': 366 *txt++ = '\\'; 367 *txt++ = 'e'; 368 break; 369 case '\n': 370 *txt++ = '\\'; 371 *txt++ = 'n'; 372 break; 373 case '\r': 374 *txt++ = '\\'; 375 *txt++ = 'r'; 376 break; 377 case '\t': 378 *txt++ = '\\'; 379 *txt++ = 't'; 380 break; 381 default: 382 if (data[i] >= 32 && data[i] <= 127) { 383 *txt++ = data[i]; 384 } else { 385 txt += os_snprintf(txt, end - txt, "\\x%02x", 386 data[i]); 387 } 388 break; 389 } 390 } 391 392 *txt = '\0'; 393 } 394 395 396 size_t printf_decode(u8 *buf, size_t maxlen, const char *str) 397 { 398 const char *pos = str; 399 size_t len = 0; 400 int val; 401 402 while (*pos) { 403 if (len == maxlen) 404 break; 405 switch (*pos) { 406 case '\\': 407 pos++; 408 switch (*pos) { 409 case '\\': 410 buf[len++] = '\\'; 411 pos++; 412 break; 413 case '"': 414 buf[len++] = '"'; 415 pos++; 416 break; 417 case 'n': 418 buf[len++] = '\n'; 419 pos++; 420 break; 421 case 'r': 422 buf[len++] = '\r'; 423 pos++; 424 break; 425 case 't': 426 buf[len++] = '\t'; 427 pos++; 428 break; 429 case 'e': 430 buf[len++] = '\e'; 431 pos++; 432 break; 433 case 'x': 434 pos++; 435 val = hex2byte(pos); 436 if (val < 0) { 437 val = hex2num(*pos); 438 if (val < 0) 439 break; 440 buf[len++] = val; 441 pos++; 442 } else { 443 buf[len++] = val; 444 pos += 2; 445 } 446 break; 447 case '0': 448 case '1': 449 case '2': 450 case '3': 451 case '4': 452 case '5': 453 case '6': 454 case '7': 455 val = *pos++ - '0'; 456 if (*pos >= '0' && *pos <= '7') 457 val = val * 8 + (*pos++ - '0'); 458 if (*pos >= '0' && *pos <= '7') 459 val = val * 8 + (*pos++ - '0'); 460 buf[len++] = val; 461 break; 462 default: 463 break; 464 } 465 break; 466 default: 467 buf[len++] = *pos++; 468 break; 469 } 470 } 471 472 return len; 473 } 474 475 476 /** 477 * wpa_ssid_txt - Convert SSID to a printable string 478 * @ssid: SSID (32-octet string) 479 * @ssid_len: Length of ssid in octets 480 * Returns: Pointer to a printable string 481 * 482 * This function can be used to convert SSIDs into printable form. In most 483 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 484 * does not limit the used character set, so anything could be used in an SSID. 485 * 486 * This function uses a static buffer, so only one call can be used at the 487 * time, i.e., this is not re-entrant and the returned buffer must be used 488 * before calling this again. 489 */ 490 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 491 { 492 static char ssid_txt[32 * 4 + 1]; 493 494 if (ssid == NULL) { 495 ssid_txt[0] = '\0'; 496 return ssid_txt; 497 } 498 499 printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); 500 return ssid_txt; 501 } 502 503 504 void * __hide_aliasing_typecast(void *foo) 505 { 506 return foo; 507 } 508 509 510 char * wpa_config_parse_string(const char *value, size_t *len) 511 { 512 if (*value == '"') { 513 const char *pos; 514 char *str; 515 value++; 516 pos = os_strrchr(value, '"'); 517 if (pos == NULL || pos[1] != '\0') 518 return NULL; 519 *len = pos - value; 520 str = os_malloc(*len + 1); 521 if (str == NULL) 522 return NULL; 523 os_memcpy(str, value, *len); 524 str[*len] = '\0'; 525 return str; 526 } else if (*value == 'P' && value[1] == '"') { 527 const char *pos; 528 char *tstr, *str; 529 size_t tlen; 530 value += 2; 531 pos = os_strrchr(value, '"'); 532 if (pos == NULL || pos[1] != '\0') 533 return NULL; 534 tlen = pos - value; 535 tstr = os_malloc(tlen + 1); 536 if (tstr == NULL) 537 return NULL; 538 os_memcpy(tstr, value, tlen); 539 tstr[tlen] = '\0'; 540 541 str = os_malloc(tlen + 1); 542 if (str == NULL) { 543 os_free(tstr); 544 return NULL; 545 } 546 547 *len = printf_decode((u8 *) str, tlen + 1, tstr); 548 os_free(tstr); 549 550 return str; 551 } else { 552 u8 *str; 553 size_t tlen, hlen = os_strlen(value); 554 if (hlen & 1) 555 return NULL; 556 tlen = hlen / 2; 557 str = os_malloc(tlen + 1); 558 if (str == NULL) 559 return NULL; 560 if (hexstr2bin(value, str, tlen)) { 561 os_free(str); 562 return NULL; 563 } 564 str[tlen] = '\0'; 565 *len = tlen; 566 return (char *) str; 567 } 568 } 569 570 571 int is_hex(const u8 *data, size_t len) 572 { 573 size_t i; 574 575 for (i = 0; i < len; i++) { 576 if (data[i] < 32 || data[i] >= 127) 577 return 1; 578 } 579 return 0; 580 } 581 582 583 size_t merge_byte_arrays(u8 *res, size_t res_len, 584 const u8 *src1, size_t src1_len, 585 const u8 *src2, size_t src2_len) 586 { 587 size_t len = 0; 588 589 os_memset(res, 0, res_len); 590 591 if (src1) { 592 if (src1_len >= res_len) { 593 os_memcpy(res, src1, res_len); 594 return res_len; 595 } 596 597 os_memcpy(res, src1, src1_len); 598 len += src1_len; 599 } 600 601 if (src2) { 602 if (len + src2_len >= res_len) { 603 os_memcpy(res + len, src2, res_len - len); 604 return res_len; 605 } 606 607 os_memcpy(res + len, src2, src2_len); 608 len += src2_len; 609 } 610 611 return len; 612 } 613