1 /* 2 * wpa_supplicant/hostapd / common helper functions, etc. 3 * Copyright (c) 2002-2007, Jouni Malinen <j (at) 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 15 #include "includes.h" 16 17 #include "common.h" 18 19 20 static int hex2num(char c) 21 { 22 if (c >= '0' && c <= '9') 23 return c - '0'; 24 if (c >= 'a' && c <= 'f') 25 return c - 'a' + 10; 26 if (c >= 'A' && c <= 'F') 27 return c - 'A' + 10; 28 return -1; 29 } 30 31 32 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 45 /** 46 * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) 47 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 48 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 49 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 50 */ 51 int hwaddr_aton(const char *txt, u8 *addr) 52 { 53 int i; 54 55 for (i = 0; i < 6; i++) { 56 int a, b; 57 58 a = hex2num(*txt++); 59 if (a < 0) 60 return -1; 61 b = hex2num(*txt++); 62 if (b < 0) 63 return -1; 64 *addr++ = (a << 4) | b; 65 if (i < 5 && *txt++ != ':') 66 return -1; 67 } 68 69 return 0; 70 } 71 72 /** 73 * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) 74 * @txt: MAC address as a string (e.g., "001122334455") 75 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 76 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 77 */ 78 int hwaddr_compact_aton(const char *txt, u8 *addr) 79 { 80 int i; 81 82 for (i = 0; i < 6; i++) { 83 int a, b; 84 85 a = hex2num(*txt++); 86 if (a < 0) 87 return -1; 88 b = hex2num(*txt++); 89 if (b < 0) 90 return -1; 91 *addr++ = (a << 4) | b; 92 } 93 94 return 0; 95 } 96 97 /** 98 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) 99 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) 100 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 101 * Returns: Characters used (> 0) on success, -1 on failure 102 */ 103 int hwaddr_aton2(const char *txt, u8 *addr) 104 { 105 int i; 106 const char *pos = txt; 107 108 for (i = 0; i < 6; i++) { 109 int a, b; 110 111 while (*pos == ':' || *pos == '.' || *pos == '-') 112 pos++; 113 114 a = hex2num(*pos++); 115 if (a < 0) 116 return -1; 117 b = hex2num(*pos++); 118 if (b < 0) 119 return -1; 120 *addr++ = (a << 4) | b; 121 } 122 123 return pos - txt; 124 } 125 126 127 /** 128 * hexstr2bin - Convert ASCII hex string into binary data 129 * @hex: ASCII hex string (e.g., "01ab") 130 * @buf: Buffer for the binary data 131 * @len: Length of the text to convert in bytes (of buf); hex will be double 132 * this size 133 * Returns: 0 on success, -1 on failure (invalid hex string) 134 */ 135 int hexstr2bin(const char *hex, u8 *buf, size_t len) 136 { 137 size_t i; 138 int a; 139 const char *ipos = hex; 140 u8 *opos = buf; 141 142 for (i = 0; i < len; i++) { 143 a = hex2byte(ipos); 144 if (a < 0) 145 return -1; 146 *opos++ = a; 147 ipos += 2; 148 } 149 return 0; 150 } 151 152 153 /** 154 * inc_byte_array - Increment arbitrary length byte array by one 155 * @counter: Pointer to byte array 156 * @len: Length of the counter in bytes 157 * 158 * This function increments the last byte of the counter by one and continues 159 * rolling over to more significant bytes if the byte was incremented from 160 * 0xff to 0x00. 161 */ 162 void inc_byte_array(u8 *counter, size_t len) 163 { 164 int pos = len - 1; 165 while (pos >= 0) { 166 counter[pos]++; 167 if (counter[pos] != 0) 168 break; 169 pos--; 170 } 171 } 172 173 174 void wpa_get_ntp_timestamp(u8 *buf) 175 { 176 struct os_time now; 177 u32 sec, usec; 178 be32 tmp; 179 180 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 181 os_get_time(&now); 182 sec = now.sec + 2208988800U; /* Epoch to 1900 */ 183 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 184 usec = now.usec; 185 usec = 4295 * usec - (usec >> 5) - (usec >> 9); 186 tmp = host_to_be32(sec); 187 os_memcpy(buf, (u8 *) &tmp, 4); 188 tmp = host_to_be32(usec); 189 os_memcpy(buf + 4, (u8 *) &tmp, 4); 190 } 191 192 193 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 194 size_t len, int uppercase) 195 { 196 size_t i; 197 char *pos = buf, *end = buf + buf_size; 198 int ret; 199 if (buf_size == 0) 200 return 0; 201 for (i = 0; i < len; i++) { 202 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 203 data[i]); 204 if (ret < 0 || ret >= end - pos) { 205 end[-1] = '\0'; 206 return pos - buf; 207 } 208 pos += ret; 209 } 210 end[-1] = '\0'; 211 return pos - buf; 212 } 213 214 /** 215 * wpa_snprintf_hex - Print data as a hex string into a buffer 216 * @buf: Memory area to use as the output buffer 217 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 218 * @data: Data to be printed 219 * @len: Length of data in bytes 220 * Returns: Number of bytes written 221 */ 222 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 223 { 224 return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 225 } 226 227 228 /** 229 * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 230 * @buf: Memory area to use as the output buffer 231 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 232 * @data: Data to be printed 233 * @len: Length of data in bytes 234 * Returns: Number of bytes written 235 */ 236 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 237 size_t len) 238 { 239 return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 240 } 241 242 243 #ifdef CONFIG_ANSI_C_EXTRA 244 245 #ifdef _WIN32_WCE 246 void perror(const char *s) 247 { 248 wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 249 s, (int) GetLastError()); 250 } 251 #endif /* _WIN32_WCE */ 252 253 254 int optind = 1; 255 int optopt; 256 char *optarg; 257 258 int getopt(int argc, char *const argv[], const char *optstring) 259 { 260 static int optchr = 1; 261 char *cp; 262 263 if (optchr == 1) { 264 if (optind >= argc) { 265 /* all arguments processed */ 266 return EOF; 267 } 268 269 if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 270 /* no option characters */ 271 return EOF; 272 } 273 } 274 275 if (os_strcmp(argv[optind], "--") == 0) { 276 /* no more options */ 277 optind++; 278 return EOF; 279 } 280 281 optopt = argv[optind][optchr]; 282 cp = os_strchr(optstring, optopt); 283 if (cp == NULL || optopt == ':') { 284 if (argv[optind][++optchr] == '\0') { 285 optchr = 1; 286 optind++; 287 } 288 return '?'; 289 } 290 291 if (cp[1] == ':') { 292 /* Argument required */ 293 optchr = 1; 294 if (argv[optind][optchr + 1]) { 295 /* No space between option and argument */ 296 optarg = &argv[optind++][optchr + 1]; 297 } else if (++optind >= argc) { 298 /* option requires an argument */ 299 return '?'; 300 } else { 301 /* Argument in the next argv */ 302 optarg = argv[optind++]; 303 } 304 } else { 305 /* No argument */ 306 if (argv[optind][++optchr] == '\0') { 307 optchr = 1; 308 optind++; 309 } 310 optarg = NULL; 311 } 312 return *cp; 313 } 314 #endif /* CONFIG_ANSI_C_EXTRA */ 315 316 317 #ifdef CONFIG_NATIVE_WINDOWS 318 /** 319 * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 320 * @str: Pointer to string to convert 321 * 322 * This function converts a unicode string to ASCII using the same 323 * buffer for output. If UNICODE is not set, the buffer is not 324 * modified. 325 */ 326 void wpa_unicode2ascii_inplace(TCHAR *str) 327 { 328 #ifdef UNICODE 329 char *dst = (char *) str; 330 while (*str) 331 *dst++ = (char) *str++; 332 *dst = '\0'; 333 #endif /* UNICODE */ 334 } 335 336 337 TCHAR * wpa_strdup_tchar(const char *str) 338 { 339 #ifdef UNICODE 340 TCHAR *buf; 341 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 342 if (buf == NULL) 343 return NULL; 344 wsprintf(buf, L"%S", str); 345 return buf; 346 #else /* UNICODE */ 347 return os_strdup(str); 348 #endif /* UNICODE */ 349 } 350 #endif /* CONFIG_NATIVE_WINDOWS */ 351 352 353 /** 354 * wpa_ssid_txt - Convert SSID to a printable string 355 * @ssid: SSID (32-octet string) 356 * @ssid_len: Length of ssid in octets 357 * Returns: Pointer to a printable string 358 * 359 * This function can be used to convert SSIDs into printable form. In most 360 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 361 * does not limit the used character set, so anything could be used in an SSID. 362 * 363 * This function uses a static buffer, so only one call can be used at the 364 * time, i.e., this is not re-entrant and the returned buffer must be used 365 * before calling this again. 366 */ 367 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 368 { 369 static char ssid_txt[33]; 370 char *pos; 371 372 if (ssid_len > 32) 373 ssid_len = 32; 374 os_memcpy(ssid_txt, ssid, ssid_len); 375 ssid_txt[ssid_len] = '\0'; 376 for (pos = ssid_txt; *pos != '\0'; pos++) { 377 #ifndef WPA_UNICODE_SSID 378 if ((u8) *pos < 32 || (u8) *pos >= 127) 379 *pos = '_'; 380 #endif 381 } 382 return ssid_txt; 383 } 384 385 386 void * __hide_aliasing_typecast(void *foo) 387 { 388 return foo; 389 } 390