common.c revision 214734
1189251Ssam/* 2189251Ssam * wpa_supplicant/hostapd / common helper functions, etc. 3189251Ssam * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> 4189251Ssam * 5189251Ssam * This program is free software; you can redistribute it and/or modify 6189251Ssam * it under the terms of the GNU General Public License version 2 as 7189251Ssam * published by the Free Software Foundation. 8189251Ssam * 9189251Ssam * Alternatively, this software may be distributed under the terms of BSD 10189251Ssam * license. 11189251Ssam * 12189251Ssam * See README and COPYING for more details. 13189251Ssam */ 14189251Ssam 15189251Ssam#include "includes.h" 16189251Ssam 17189251Ssam#include "common.h" 18189251Ssam 19189251Ssam 20189251Ssamstatic int hex2num(char c) 21189251Ssam{ 22189251Ssam if (c >= '0' && c <= '9') 23189251Ssam return c - '0'; 24189251Ssam if (c >= 'a' && c <= 'f') 25189251Ssam return c - 'a' + 10; 26189251Ssam if (c >= 'A' && c <= 'F') 27189251Ssam return c - 'A' + 10; 28189251Ssam return -1; 29189251Ssam} 30189251Ssam 31189251Ssam 32189251Ssamstatic int hex2byte(const char *hex) 33189251Ssam{ 34189251Ssam int a, b; 35189251Ssam a = hex2num(*hex++); 36189251Ssam if (a < 0) 37189251Ssam return -1; 38189251Ssam b = hex2num(*hex++); 39189251Ssam if (b < 0) 40189251Ssam return -1; 41189251Ssam return (a << 4) | b; 42189251Ssam} 43189251Ssam 44189251Ssam 45189251Ssam/** 46214734Srpaulo * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) 47189251Ssam * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 48189251Ssam * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 49189251Ssam * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 50189251Ssam */ 51189251Ssamint hwaddr_aton(const char *txt, u8 *addr) 52189251Ssam{ 53189251Ssam int i; 54189251Ssam 55189251Ssam for (i = 0; i < 6; i++) { 56189251Ssam int a, b; 57189251Ssam 58189251Ssam a = hex2num(*txt++); 59189251Ssam if (a < 0) 60189251Ssam return -1; 61189251Ssam b = hex2num(*txt++); 62189251Ssam if (b < 0) 63189251Ssam return -1; 64189251Ssam *addr++ = (a << 4) | b; 65189251Ssam if (i < 5 && *txt++ != ':') 66189251Ssam return -1; 67189251Ssam } 68189251Ssam 69189251Ssam return 0; 70189251Ssam} 71189251Ssam 72189251Ssam 73189251Ssam/** 74214734Srpaulo * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) 75214734Srpaulo * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) 76214734Srpaulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 77214734Srpaulo * Returns: Characters used (> 0) on success, -1 on failure 78214734Srpaulo */ 79214734Srpauloint hwaddr_aton2(const char *txt, u8 *addr) 80214734Srpaulo{ 81214734Srpaulo int i; 82214734Srpaulo const char *pos = txt; 83214734Srpaulo 84214734Srpaulo for (i = 0; i < 6; i++) { 85214734Srpaulo int a, b; 86214734Srpaulo 87214734Srpaulo while (*pos == ':' || *pos == '.' || *pos == '-') 88214734Srpaulo pos++; 89214734Srpaulo 90214734Srpaulo a = hex2num(*pos++); 91214734Srpaulo if (a < 0) 92214734Srpaulo return -1; 93214734Srpaulo b = hex2num(*pos++); 94214734Srpaulo if (b < 0) 95214734Srpaulo return -1; 96214734Srpaulo *addr++ = (a << 4) | b; 97214734Srpaulo } 98214734Srpaulo 99214734Srpaulo return pos - txt; 100214734Srpaulo} 101214734Srpaulo 102214734Srpaulo 103214734Srpaulo/** 104189251Ssam * hexstr2bin - Convert ASCII hex string into binary data 105189251Ssam * @hex: ASCII hex string (e.g., "01ab") 106189251Ssam * @buf: Buffer for the binary data 107189251Ssam * @len: Length of the text to convert in bytes (of buf); hex will be double 108189251Ssam * this size 109189251Ssam * Returns: 0 on success, -1 on failure (invalid hex string) 110189251Ssam */ 111189251Ssamint hexstr2bin(const char *hex, u8 *buf, size_t len) 112189251Ssam{ 113189251Ssam size_t i; 114189251Ssam int a; 115189251Ssam const char *ipos = hex; 116189251Ssam u8 *opos = buf; 117189251Ssam 118189251Ssam for (i = 0; i < len; i++) { 119189251Ssam a = hex2byte(ipos); 120189251Ssam if (a < 0) 121189251Ssam return -1; 122189251Ssam *opos++ = a; 123189251Ssam ipos += 2; 124189251Ssam } 125189251Ssam return 0; 126189251Ssam} 127189251Ssam 128189251Ssam 129189251Ssam/** 130189251Ssam * inc_byte_array - Increment arbitrary length byte array by one 131189251Ssam * @counter: Pointer to byte array 132189251Ssam * @len: Length of the counter in bytes 133189251Ssam * 134189251Ssam * This function increments the last byte of the counter by one and continues 135189251Ssam * rolling over to more significant bytes if the byte was incremented from 136189251Ssam * 0xff to 0x00. 137189251Ssam */ 138189251Ssamvoid inc_byte_array(u8 *counter, size_t len) 139189251Ssam{ 140189251Ssam int pos = len - 1; 141189251Ssam while (pos >= 0) { 142189251Ssam counter[pos]++; 143189251Ssam if (counter[pos] != 0) 144189251Ssam break; 145189251Ssam pos--; 146189251Ssam } 147189251Ssam} 148189251Ssam 149189251Ssam 150189251Ssamvoid wpa_get_ntp_timestamp(u8 *buf) 151189251Ssam{ 152189251Ssam struct os_time now; 153189251Ssam u32 sec, usec; 154189251Ssam be32 tmp; 155189251Ssam 156189251Ssam /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 157189251Ssam os_get_time(&now); 158189251Ssam sec = now.sec + 2208988800U; /* Epoch to 1900 */ 159189251Ssam /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 160189251Ssam usec = now.usec; 161189251Ssam usec = 4295 * usec - (usec >> 5) - (usec >> 9); 162189251Ssam tmp = host_to_be32(sec); 163189251Ssam os_memcpy(buf, (u8 *) &tmp, 4); 164189251Ssam tmp = host_to_be32(usec); 165189251Ssam os_memcpy(buf + 4, (u8 *) &tmp, 4); 166189251Ssam} 167189251Ssam 168189251Ssam 169189251Ssamstatic inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 170189251Ssam size_t len, int uppercase) 171189251Ssam{ 172189251Ssam size_t i; 173189251Ssam char *pos = buf, *end = buf + buf_size; 174189251Ssam int ret; 175189251Ssam if (buf_size == 0) 176189251Ssam return 0; 177189251Ssam for (i = 0; i < len; i++) { 178189251Ssam ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 179189251Ssam data[i]); 180189251Ssam if (ret < 0 || ret >= end - pos) { 181189251Ssam end[-1] = '\0'; 182189251Ssam return pos - buf; 183189251Ssam } 184189251Ssam pos += ret; 185189251Ssam } 186189251Ssam end[-1] = '\0'; 187189251Ssam return pos - buf; 188189251Ssam} 189189251Ssam 190189251Ssam/** 191189251Ssam * wpa_snprintf_hex - Print data as a hex string into a buffer 192189251Ssam * @buf: Memory area to use as the output buffer 193189251Ssam * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 194189251Ssam * @data: Data to be printed 195189251Ssam * @len: Length of data in bytes 196189251Ssam * Returns: Number of bytes written 197189251Ssam */ 198189251Ssamint wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 199189251Ssam{ 200189251Ssam return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 201189251Ssam} 202189251Ssam 203189251Ssam 204189251Ssam/** 205189251Ssam * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 206189251Ssam * @buf: Memory area to use as the output buffer 207189251Ssam * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 208189251Ssam * @data: Data to be printed 209189251Ssam * @len: Length of data in bytes 210189251Ssam * Returns: Number of bytes written 211189251Ssam */ 212189251Ssamint wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 213189251Ssam size_t len) 214189251Ssam{ 215189251Ssam return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 216189251Ssam} 217189251Ssam 218189251Ssam 219189251Ssam#ifdef CONFIG_ANSI_C_EXTRA 220189251Ssam 221189251Ssam#ifdef _WIN32_WCE 222189251Ssamvoid perror(const char *s) 223189251Ssam{ 224189251Ssam wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 225189251Ssam s, (int) GetLastError()); 226189251Ssam} 227189251Ssam#endif /* _WIN32_WCE */ 228189251Ssam 229189251Ssam 230189251Ssamint optind = 1; 231189251Ssamint optopt; 232189251Ssamchar *optarg; 233189251Ssam 234189251Ssamint getopt(int argc, char *const argv[], const char *optstring) 235189251Ssam{ 236189251Ssam static int optchr = 1; 237189251Ssam char *cp; 238189251Ssam 239189251Ssam if (optchr == 1) { 240189251Ssam if (optind >= argc) { 241189251Ssam /* all arguments processed */ 242189251Ssam return EOF; 243189251Ssam } 244189251Ssam 245189251Ssam if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 246189251Ssam /* no option characters */ 247189251Ssam return EOF; 248189251Ssam } 249189251Ssam } 250189251Ssam 251189251Ssam if (os_strcmp(argv[optind], "--") == 0) { 252189251Ssam /* no more options */ 253189251Ssam optind++; 254189251Ssam return EOF; 255189251Ssam } 256189251Ssam 257189251Ssam optopt = argv[optind][optchr]; 258189251Ssam cp = os_strchr(optstring, optopt); 259189251Ssam if (cp == NULL || optopt == ':') { 260189251Ssam if (argv[optind][++optchr] == '\0') { 261189251Ssam optchr = 1; 262189251Ssam optind++; 263189251Ssam } 264189251Ssam return '?'; 265189251Ssam } 266189251Ssam 267189251Ssam if (cp[1] == ':') { 268189251Ssam /* Argument required */ 269189251Ssam optchr = 1; 270189251Ssam if (argv[optind][optchr + 1]) { 271189251Ssam /* No space between option and argument */ 272189251Ssam optarg = &argv[optind++][optchr + 1]; 273189251Ssam } else if (++optind >= argc) { 274189251Ssam /* option requires an argument */ 275189251Ssam return '?'; 276189251Ssam } else { 277189251Ssam /* Argument in the next argv */ 278189251Ssam optarg = argv[optind++]; 279189251Ssam } 280189251Ssam } else { 281189251Ssam /* No argument */ 282189251Ssam if (argv[optind][++optchr] == '\0') { 283189251Ssam optchr = 1; 284189251Ssam optind++; 285189251Ssam } 286189251Ssam optarg = NULL; 287189251Ssam } 288189251Ssam return *cp; 289189251Ssam} 290189251Ssam#endif /* CONFIG_ANSI_C_EXTRA */ 291189251Ssam 292189251Ssam 293189251Ssam#ifdef CONFIG_NATIVE_WINDOWS 294189251Ssam/** 295189251Ssam * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 296189251Ssam * @str: Pointer to string to convert 297189251Ssam * 298189251Ssam * This function converts a unicode string to ASCII using the same 299189251Ssam * buffer for output. If UNICODE is not set, the buffer is not 300189251Ssam * modified. 301189251Ssam */ 302189251Ssamvoid wpa_unicode2ascii_inplace(TCHAR *str) 303189251Ssam{ 304189251Ssam#ifdef UNICODE 305189251Ssam char *dst = (char *) str; 306189251Ssam while (*str) 307189251Ssam *dst++ = (char) *str++; 308189251Ssam *dst = '\0'; 309189251Ssam#endif /* UNICODE */ 310189251Ssam} 311189251Ssam 312189251Ssam 313189251SsamTCHAR * wpa_strdup_tchar(const char *str) 314189251Ssam{ 315189251Ssam#ifdef UNICODE 316189251Ssam TCHAR *buf; 317189251Ssam buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 318189251Ssam if (buf == NULL) 319189251Ssam return NULL; 320189251Ssam wsprintf(buf, L"%S", str); 321189251Ssam return buf; 322189251Ssam#else /* UNICODE */ 323189251Ssam return os_strdup(str); 324189251Ssam#endif /* UNICODE */ 325189251Ssam} 326189251Ssam#endif /* CONFIG_NATIVE_WINDOWS */ 327189251Ssam 328189251Ssam 329189251Ssam/** 330189251Ssam * wpa_ssid_txt - Convert SSID to a printable string 331189251Ssam * @ssid: SSID (32-octet string) 332189251Ssam * @ssid_len: Length of ssid in octets 333189251Ssam * Returns: Pointer to a printable string 334189251Ssam * 335189251Ssam * This function can be used to convert SSIDs into printable form. In most 336189251Ssam * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 337189251Ssam * does not limit the used character set, so anything could be used in an SSID. 338189251Ssam * 339189251Ssam * This function uses a static buffer, so only one call can be used at the 340189251Ssam * time, i.e., this is not re-entrant and the returned buffer must be used 341189251Ssam * before calling this again. 342189251Ssam */ 343189251Ssamconst char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 344189251Ssam{ 345189251Ssam static char ssid_txt[33]; 346189251Ssam char *pos; 347189251Ssam 348189251Ssam if (ssid_len > 32) 349189251Ssam ssid_len = 32; 350189251Ssam os_memcpy(ssid_txt, ssid, ssid_len); 351189251Ssam ssid_txt[ssid_len] = '\0'; 352189251Ssam for (pos = ssid_txt; *pos != '\0'; pos++) { 353189251Ssam if ((u8) *pos < 32 || (u8) *pos >= 127) 354189251Ssam *pos = '_'; 355189251Ssam } 356189251Ssam return ssid_txt; 357189251Ssam} 358209158Srpaulo 359209158Srpaulo 360209158Srpaulovoid * __hide_aliasing_typecast(void *foo) 361209158Srpaulo{ 362209158Srpaulo return foo; 363209158Srpaulo} 364