1 /* 2 * wpa_supplicant/hostapd / common helper functions, etc. 3 * Copyright (c) 2002-2007, 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 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 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 45 /** 46 * hwaddr_aton - Convert ASCII string to MAC address 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 /** 74 * hexstr2bin - Convert ASCII hex string into binary data 75 * @hex: ASCII hex string (e.g., "01ab") 76 * @buf: Buffer for the binary data 77 * @len: Length of the text to convert in bytes (of buf); hex will be double 78 * this size 79 * Returns: 0 on success, -1 on failure (invalid hex string) 80 */ 81 int hexstr2bin(const char *hex, u8 *buf, size_t len) 82 { 83 size_t i; 84 int a; 85 const char *ipos = hex; 86 u8 *opos = buf; 87 88 for (i = 0; i < len; i++) { 89 a = hex2byte(ipos); 90 if (a < 0) 91 return -1; 92 *opos++ = a; 93 ipos += 2; 94 } 95 return 0; 96 } 97 98 99 /** 100 * inc_byte_array - Increment arbitrary length byte array by one 101 * @counter: Pointer to byte array 102 * @len: Length of the counter in bytes 103 * 104 * This function increments the last byte of the counter by one and continues 105 * rolling over to more significant bytes if the byte was incremented from 106 * 0xff to 0x00. 107 */ 108 void inc_byte_array(u8 *counter, size_t len) 109 { 110 int pos = len - 1; 111 while (pos >= 0) { 112 counter[pos]++; 113 if (counter[pos] != 0) 114 break; 115 pos--; 116 } 117 } 118 119 120 void wpa_get_ntp_timestamp(u8 *buf) 121 { 122 struct os_time now; 123 u32 sec, usec; 124 be32 tmp; 125 126 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 127 os_get_time(&now); 128 sec = now.sec + 2208988800U; /* Epoch to 1900 */ 129 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 130 usec = now.usec; 131 usec = 4295 * usec - (usec >> 5) - (usec >> 9); 132 tmp = host_to_be32(sec); 133 os_memcpy(buf, (u8 *) &tmp, 4); 134 tmp = host_to_be32(usec); 135 os_memcpy(buf + 4, (u8 *) &tmp, 4); 136 } 137 138 139 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 140 size_t len, int uppercase) 141 { 142 size_t i; 143 char *pos = buf, *end = buf + buf_size; 144 int ret; 145 if (buf_size == 0) 146 return 0; 147 for (i = 0; i < len; i++) { 148 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 149 data[i]); 150 if (ret < 0 || ret >= end - pos) { 151 end[-1] = '\0'; 152 return pos - buf; 153 } 154 pos += ret; 155 } 156 end[-1] = '\0'; 157 return pos - buf; 158 } 159 160 /** 161 * wpa_snprintf_hex - Print data as a hex string into a buffer 162 * @buf: Memory area to use as the output buffer 163 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 164 * @data: Data to be printed 165 * @len: Length of data in bytes 166 * Returns: Number of bytes written 167 */ 168 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 169 { 170 return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 171 } 172 173 174 /** 175 * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 176 * @buf: Memory area to use as the output buffer 177 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 178 * @data: Data to be printed 179 * @len: Length of data in bytes 180 * Returns: Number of bytes written 181 */ 182 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 183 size_t len) 184 { 185 return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 186 } 187 188 189 #ifdef CONFIG_ANSI_C_EXTRA 190 191 #ifdef _WIN32_WCE 192 void perror(const char *s) 193 { 194 wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 195 s, (int) GetLastError()); 196 } 197 #endif /* _WIN32_WCE */ 198 199 200 int optind = 1; 201 int optopt; 202 char *optarg; 203 204 int getopt(int argc, char *const argv[], const char *optstring) 205 { 206 static int optchr = 1; 207 char *cp; 208 209 if (optchr == 1) { 210 if (optind >= argc) { 211 /* all arguments processed */ 212 return EOF; 213 } 214 215 if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 216 /* no option characters */ 217 return EOF; 218 } 219 } 220 221 if (os_strcmp(argv[optind], "--") == 0) { 222 /* no more options */ 223 optind++; 224 return EOF; 225 } 226 227 optopt = argv[optind][optchr]; 228 cp = os_strchr(optstring, optopt); 229 if (cp == NULL || optopt == ':') { 230 if (argv[optind][++optchr] == '\0') { 231 optchr = 1; 232 optind++; 233 } 234 return '?'; 235 } 236 237 if (cp[1] == ':') { 238 /* Argument required */ 239 optchr = 1; 240 if (argv[optind][optchr + 1]) { 241 /* No space between option and argument */ 242 optarg = &argv[optind++][optchr + 1]; 243 } else if (++optind >= argc) { 244 /* option requires an argument */ 245 return '?'; 246 } else { 247 /* Argument in the next argv */ 248 optarg = argv[optind++]; 249 } 250 } else { 251 /* No argument */ 252 if (argv[optind][++optchr] == '\0') { 253 optchr = 1; 254 optind++; 255 } 256 optarg = NULL; 257 } 258 return *cp; 259 } 260 #endif /* CONFIG_ANSI_C_EXTRA */ 261 262 263 #ifdef CONFIG_NATIVE_WINDOWS 264 /** 265 * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 266 * @str: Pointer to string to convert 267 * 268 * This function converts a unicode string to ASCII using the same 269 * buffer for output. If UNICODE is not set, the buffer is not 270 * modified. 271 */ 272 void wpa_unicode2ascii_inplace(TCHAR *str) 273 { 274 #ifdef UNICODE 275 char *dst = (char *) str; 276 while (*str) 277 *dst++ = (char) *str++; 278 *dst = '\0'; 279 #endif /* UNICODE */ 280 } 281 282 283 TCHAR * wpa_strdup_tchar(const char *str) 284 { 285 #ifdef UNICODE 286 TCHAR *buf; 287 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 288 if (buf == NULL) 289 return NULL; 290 wsprintf(buf, L"%S", str); 291 return buf; 292 #else /* UNICODE */ 293 return os_strdup(str); 294 #endif /* UNICODE */ 295 } 296 #endif /* CONFIG_NATIVE_WINDOWS */ 297 298 299 /** 300 * wpa_ssid_txt - Convert SSID to a printable string 301 * @ssid: SSID (32-octet string) 302 * @ssid_len: Length of ssid in octets 303 * Returns: Pointer to a printable string 304 * 305 * This function can be used to convert SSIDs into printable form. In most 306 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 307 * does not limit the used character set, so anything could be used in an SSID. 308 * 309 * This function uses a static buffer, so only one call can be used at the 310 * time, i.e., this is not re-entrant and the returned buffer must be used 311 * before calling this again. 312 */ 313 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 314 { 315 static char ssid_txt[33]; 316 char *pos; 317 318 if (ssid_len > 32) 319 ssid_len = 32; 320 os_memcpy(ssid_txt, ssid, ssid_len); 321 ssid_txt[ssid_len] = '\0'; 322 for (pos = ssid_txt; *pos != '\0'; pos++) { 323 if ((u8) *pos < 32 || (u8) *pos >= 127) 324 *pos = '_'; 325 } 326 return ssid_txt; 327 } 328