PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/common.c

https://gitlab.com/Codeaurora/platform_external_wpa_supplicant
C | 599 lines | 428 code | 76 blank | 95 comment | 104 complexity | 5f55aa8834b1c7795811e7f7c55bcb44 MD5 | raw file
  1. /*
  2. * wpa_supplicant/hostapd / common helper functions, etc.
  3. * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #ifdef CONFIG_DEBUG_FILE
  17. static FILE *out_file = NULL;
  18. #endif /* CONFIG_DEBUG_FILE */
  19. int wpa_debug_level = MSG_INFO;
  20. int wpa_debug_show_keys = 0;
  21. int wpa_debug_timestamp = 0;
  22. static int hex2num(char c)
  23. {
  24. if (c >= '0' && c <= '9')
  25. return c - '0';
  26. if (c >= 'a' && c <= 'f')
  27. return c - 'a' + 10;
  28. if (c >= 'A' && c <= 'F')
  29. return c - 'A' + 10;
  30. return -1;
  31. }
  32. static int hex2byte(const char *hex)
  33. {
  34. int a, b;
  35. a = hex2num(*hex++);
  36. if (a < 0)
  37. return -1;
  38. b = hex2num(*hex++);
  39. if (b < 0)
  40. return -1;
  41. return (a << 4) | b;
  42. }
  43. /**
  44. * hwaddr_aton - Convert ASCII string to MAC address
  45. * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
  46. * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
  47. * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
  48. */
  49. int hwaddr_aton(const char *txt, u8 *addr)
  50. {
  51. int i;
  52. for (i = 0; i < 6; i++) {
  53. int a, b;
  54. a = hex2num(*txt++);
  55. if (a < 0)
  56. return -1;
  57. b = hex2num(*txt++);
  58. if (b < 0)
  59. return -1;
  60. *addr++ = (a << 4) | b;
  61. if (i < 5 && *txt++ != ':')
  62. return -1;
  63. }
  64. return 0;
  65. }
  66. /**
  67. * hexstr2bin - Convert ASCII hex string into binary data
  68. * @hex: ASCII hex string (e.g., "01ab")
  69. * @buf: Buffer for the binary data
  70. * @len: Length of the text to convert in bytes (of buf); hex will be double
  71. * this size
  72. * Returns: 0 on success, -1 on failure (invalid hex string)
  73. */
  74. int hexstr2bin(const char *hex, u8 *buf, size_t len)
  75. {
  76. size_t i;
  77. int a;
  78. const char *ipos = hex;
  79. u8 *opos = buf;
  80. for (i = 0; i < len; i++) {
  81. a = hex2byte(ipos);
  82. if (a < 0)
  83. return -1;
  84. *opos++ = a;
  85. ipos += 2;
  86. }
  87. return 0;
  88. }
  89. /**
  90. * inc_byte_array - Increment arbitrary length byte array by one
  91. * @counter: Pointer to byte array
  92. * @len: Length of the counter in bytes
  93. *
  94. * This function increments the last byte of the counter by one and continues
  95. * rolling over to more significant bytes if the byte was incremented from
  96. * 0xff to 0x00.
  97. */
  98. void inc_byte_array(u8 *counter, size_t len)
  99. {
  100. int pos = len - 1;
  101. while (pos >= 0) {
  102. counter[pos]++;
  103. if (counter[pos] != 0)
  104. break;
  105. pos--;
  106. }
  107. }
  108. void wpa_get_ntp_timestamp(u8 *buf)
  109. {
  110. struct os_time now;
  111. u32 sec, usec;
  112. /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
  113. os_get_time(&now);
  114. sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */
  115. /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
  116. usec = now.usec;
  117. usec = host_to_be32(4295 * usec - (usec >> 5) - (usec >> 9));
  118. os_memcpy(buf, (u8 *) &sec, 4);
  119. os_memcpy(buf + 4, (u8 *) &usec, 4);
  120. }
  121. #ifndef CONFIG_NO_STDOUT_DEBUG
  122. void wpa_debug_print_timestamp(void)
  123. {
  124. struct os_time tv;
  125. if (!wpa_debug_timestamp)
  126. return;
  127. os_get_time(&tv);
  128. #ifdef CONFIG_DEBUG_FILE
  129. if (out_file) {
  130. fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
  131. (unsigned int) tv.usec);
  132. } else
  133. #endif /* CONFIG_DEBUG_FILE */
  134. printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
  135. }
  136. /**
  137. * wpa_printf - conditional printf
  138. * @level: priority level (MSG_*) of the message
  139. * @fmt: printf format string, followed by optional arguments
  140. *
  141. * This function is used to print conditional debugging and error messages. The
  142. * output may be directed to stdout, stderr, and/or syslog based on
  143. * configuration.
  144. *
  145. * Note: New line '\n' is added to the end of the text when printing to stdout.
  146. */
  147. void wpa_printf(int level, char *fmt, ...)
  148. {
  149. va_list ap;
  150. va_start(ap, fmt);
  151. if (level >= wpa_debug_level) {
  152. wpa_debug_print_timestamp();
  153. #ifdef CONFIG_DEBUG_FILE
  154. if (out_file) {
  155. vfprintf(out_file, fmt, ap);
  156. fprintf(out_file, "\n");
  157. } else {
  158. #endif /* CONFIG_DEBUG_FILE */
  159. vprintf(fmt, ap);
  160. printf("\n");
  161. #ifdef CONFIG_DEBUG_FILE
  162. }
  163. #endif /* CONFIG_DEBUG_FILE */
  164. }
  165. va_end(ap);
  166. }
  167. static void _wpa_hexdump(int level, const char *title, const u8 *buf,
  168. size_t len, int show)
  169. {
  170. size_t i;
  171. if (level < wpa_debug_level)
  172. return;
  173. wpa_debug_print_timestamp();
  174. #ifdef CONFIG_DEBUG_FILE
  175. if (out_file) {
  176. fprintf(out_file, "%s - hexdump(len=%lu):",
  177. title, (unsigned long) len);
  178. if (buf == NULL) {
  179. fprintf(out_file, " [NULL]");
  180. } else if (show) {
  181. for (i = 0; i < len; i++)
  182. fprintf(out_file, " %02x", buf[i]);
  183. } else {
  184. fprintf(out_file, " [REMOVED]");
  185. }
  186. fprintf(out_file, "\n");
  187. } else {
  188. #endif /* CONFIG_DEBUG_FILE */
  189. printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
  190. if (buf == NULL) {
  191. printf(" [NULL]");
  192. } else if (show) {
  193. for (i = 0; i < len; i++)
  194. printf(" %02x", buf[i]);
  195. } else {
  196. printf(" [REMOVED]");
  197. }
  198. printf("\n");
  199. #ifdef CONFIG_DEBUG_FILE
  200. }
  201. #endif /* CONFIG_DEBUG_FILE */
  202. }
  203. void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
  204. {
  205. _wpa_hexdump(level, title, buf, len, 1);
  206. }
  207. void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
  208. {
  209. _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
  210. }
  211. static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
  212. size_t len, int show)
  213. {
  214. size_t i, llen;
  215. const u8 *pos = buf;
  216. const size_t line_len = 16;
  217. if (level < wpa_debug_level)
  218. return;
  219. wpa_debug_print_timestamp();
  220. #ifdef CONFIG_DEBUG_FILE
  221. if (out_file) {
  222. if (!show) {
  223. fprintf(out_file,
  224. "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
  225. title, (unsigned long) len);
  226. return;
  227. }
  228. if (buf == NULL) {
  229. fprintf(out_file,
  230. "%s - hexdump_ascii(len=%lu): [NULL]\n",
  231. title, (unsigned long) len);
  232. return;
  233. }
  234. fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
  235. title, (unsigned long) len);
  236. while (len) {
  237. llen = len > line_len ? line_len : len;
  238. fprintf(out_file, " ");
  239. for (i = 0; i < llen; i++)
  240. fprintf(out_file, " %02x", pos[i]);
  241. for (i = llen; i < line_len; i++)
  242. fprintf(out_file, " ");
  243. fprintf(out_file, " ");
  244. for (i = 0; i < llen; i++) {
  245. if (isprint(pos[i]))
  246. fprintf(out_file, "%c", pos[i]);
  247. else
  248. fprintf(out_file, "_");
  249. }
  250. for (i = llen; i < line_len; i++)
  251. fprintf(out_file, " ");
  252. fprintf(out_file, "\n");
  253. pos += llen;
  254. len -= llen;
  255. }
  256. } else {
  257. #endif /* CONFIG_DEBUG_FILE */
  258. if (!show) {
  259. printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
  260. title, (unsigned long) len);
  261. return;
  262. }
  263. if (buf == NULL) {
  264. printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
  265. title, (unsigned long) len);
  266. return;
  267. }
  268. printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
  269. while (len) {
  270. llen = len > line_len ? line_len : len;
  271. printf(" ");
  272. for (i = 0; i < llen; i++)
  273. printf(" %02x", pos[i]);
  274. for (i = llen; i < line_len; i++)
  275. printf(" ");
  276. printf(" ");
  277. for (i = 0; i < llen; i++) {
  278. if (isprint(pos[i]))
  279. printf("%c", pos[i]);
  280. else
  281. printf("_");
  282. }
  283. for (i = llen; i < line_len; i++)
  284. printf(" ");
  285. printf("\n");
  286. pos += llen;
  287. len -= llen;
  288. }
  289. #ifdef CONFIG_DEBUG_FILE
  290. }
  291. #endif /* CONFIG_DEBUG_FILE */
  292. }
  293. void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
  294. {
  295. _wpa_hexdump_ascii(level, title, buf, len, 1);
  296. }
  297. void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
  298. size_t len)
  299. {
  300. _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
  301. }
  302. int wpa_debug_open_file(const char *path)
  303. {
  304. #ifdef CONFIG_DEBUG_FILE
  305. if (!path)
  306. return 0;
  307. out_file = fopen(path, "a");
  308. if (out_file == NULL) {
  309. wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
  310. "output file, using standard output");
  311. return -1;
  312. }
  313. #ifndef _WIN32
  314. setvbuf(out_file, NULL, _IOLBF, 0);
  315. #endif /* _WIN32 */
  316. #endif /* CONFIG_DEBUG_FILE */
  317. return 0;
  318. }
  319. void wpa_debug_close_file(void)
  320. {
  321. #ifdef CONFIG_DEBUG_FILE
  322. if (!out_file)
  323. return;
  324. fclose(out_file);
  325. out_file = NULL;
  326. #endif /* CONFIG_DEBUG_FILE */
  327. }
  328. #endif /* CONFIG_NO_STDOUT_DEBUG */
  329. #ifndef CONFIG_NO_WPA_MSG
  330. static wpa_msg_cb_func wpa_msg_cb = NULL;
  331. void wpa_msg_register_cb(wpa_msg_cb_func func)
  332. {
  333. wpa_msg_cb = func;
  334. }
  335. void wpa_msg(void *ctx, int level, char *fmt, ...)
  336. {
  337. va_list ap;
  338. char *buf;
  339. const int buflen = 2048;
  340. int len;
  341. buf = os_malloc(buflen);
  342. if (buf == NULL) {
  343. wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
  344. "buffer");
  345. return;
  346. }
  347. va_start(ap, fmt);
  348. len = vsnprintf(buf, buflen, fmt, ap);
  349. va_end(ap);
  350. wpa_printf(level, "%s", buf);
  351. if (wpa_msg_cb)
  352. wpa_msg_cb(ctx, level, buf, len);
  353. os_free(buf);
  354. }
  355. #endif /* CONFIG_NO_WPA_MSG */
  356. static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
  357. size_t len, int uppercase)
  358. {
  359. size_t i;
  360. char *pos = buf, *end = buf + buf_size;
  361. int ret;
  362. if (buf_size == 0)
  363. return 0;
  364. for (i = 0; i < len; i++) {
  365. ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
  366. data[i]);
  367. if (ret < 0 || ret >= end - pos) {
  368. end[-1] = '\0';
  369. return pos - buf;
  370. }
  371. pos += ret;
  372. }
  373. end[-1] = '\0';
  374. return pos - buf;
  375. }
  376. /**
  377. * wpa_snprintf_hex - Print data as a hex string into a buffer
  378. * @buf: Memory area to use as the output buffer
  379. * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
  380. * @data: Data to be printed
  381. * @len: Length of data in bytes
  382. * Returns: Number of bytes written
  383. */
  384. int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
  385. {
  386. return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
  387. }
  388. /**
  389. * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
  390. * @buf: Memory area to use as the output buffer
  391. * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
  392. * @data: Data to be printed
  393. * @len: Length of data in bytes
  394. * Returns: Number of bytes written
  395. */
  396. int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
  397. size_t len)
  398. {
  399. return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
  400. }
  401. #ifdef CONFIG_ANSI_C_EXTRA
  402. #ifdef _WIN32_WCE
  403. void perror(const char *s)
  404. {
  405. wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
  406. s, (int) GetLastError());
  407. }
  408. #endif /* _WIN32_WCE */
  409. int optind = 1;
  410. int optopt;
  411. char *optarg;
  412. int getopt(int argc, char *const argv[], const char *optstring)
  413. {
  414. static int optchr = 1;
  415. char *cp;
  416. if (optchr == 1) {
  417. if (optind >= argc) {
  418. /* all arguments processed */
  419. return EOF;
  420. }
  421. if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
  422. /* no option characters */
  423. return EOF;
  424. }
  425. }
  426. if (os_strcmp(argv[optind], "--") == 0) {
  427. /* no more options */
  428. optind++;
  429. return EOF;
  430. }
  431. optopt = argv[optind][optchr];
  432. cp = os_strchr(optstring, optopt);
  433. if (cp == NULL || optopt == ':') {
  434. if (argv[optind][++optchr] == '\0') {
  435. optchr = 1;
  436. optind++;
  437. }
  438. return '?';
  439. }
  440. if (cp[1] == ':') {
  441. /* Argument required */
  442. optchr = 1;
  443. if (argv[optind][optchr + 1]) {
  444. /* No space between option and argument */
  445. optarg = &argv[optind++][optchr + 1];
  446. } else if (++optind >= argc) {
  447. /* option requires an argument */
  448. return '?';
  449. } else {
  450. /* Argument in the next argv */
  451. optarg = argv[optind++];
  452. }
  453. } else {
  454. /* No argument */
  455. if (argv[optind][++optchr] == '\0') {
  456. optchr = 1;
  457. optind++;
  458. }
  459. optarg = NULL;
  460. }
  461. return *cp;
  462. }
  463. #endif /* CONFIG_ANSI_C_EXTRA */
  464. #ifdef CONFIG_NATIVE_WINDOWS
  465. /**
  466. * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
  467. * @str: Pointer to string to convert
  468. *
  469. * This function converts a unicode string to ASCII using the same
  470. * buffer for output. If UNICODE is not set, the buffer is not
  471. * modified.
  472. */
  473. void wpa_unicode2ascii_inplace(TCHAR *str)
  474. {
  475. #ifdef UNICODE
  476. char *dst = (char *) str;
  477. while (*str)
  478. *dst++ = (char) *str++;
  479. *dst = '\0';
  480. #endif /* UNICODE */
  481. }
  482. TCHAR * wpa_strdup_tchar(const char *str)
  483. {
  484. #ifdef UNICODE
  485. TCHAR *buf;
  486. buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
  487. if (buf == NULL)
  488. return NULL;
  489. wsprintf(buf, L"%S", str);
  490. return buf;
  491. #else /* UNICODE */
  492. return os_strdup(str);
  493. #endif /* UNICODE */
  494. }
  495. #endif /* CONFIG_NATIVE_WINDOWS */
  496. /**
  497. * wpa_ssid_txt - Convert SSID to a printable string
  498. * @ssid: SSID (32-octet string)
  499. * @ssid_len: Length of ssid in octets
  500. * Returns: Pointer to a printable string
  501. *
  502. * This function can be used to convert SSIDs into printable form. In most
  503. * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
  504. * does not limit the used character set, so anything could be used in an SSID.
  505. *
  506. * This function uses a static buffer, so only one call can be used at the
  507. * time, i.e., this is not re-entrant and the returned buffer must be used
  508. * before calling this again.
  509. */
  510. const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len)
  511. {
  512. static char ssid_txt[33];
  513. char *pos;
  514. if (ssid_len > 32)
  515. ssid_len = 32;
  516. os_memcpy(ssid_txt, ssid, ssid_len);
  517. ssid_txt[ssid_len] = '\0';
  518. for (pos = ssid_txt; *pos != '\0'; pos++) {
  519. if ((u8) *pos < 32 || (u8) *pos >= 127)
  520. *pos = '_';
  521. }
  522. return ssid_txt;
  523. }