common.c revision 252726
1189251Ssam/* 2189251Ssam * wpa_supplicant/hostapd / common helper functions, etc. 3189251Ssam * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam 11189251Ssam#include "common.h" 12189251Ssam 13189251Ssam 14189251Ssamstatic int hex2num(char c) 15189251Ssam{ 16189251Ssam if (c >= '0' && c <= '9') 17189251Ssam return c - '0'; 18189251Ssam if (c >= 'a' && c <= 'f') 19189251Ssam return c - 'a' + 10; 20189251Ssam if (c >= 'A' && c <= 'F') 21189251Ssam return c - 'A' + 10; 22189251Ssam return -1; 23189251Ssam} 24189251Ssam 25189251Ssam 26252726Srpauloint hex2byte(const char *hex) 27189251Ssam{ 28189251Ssam int a, b; 29189251Ssam a = hex2num(*hex++); 30189251Ssam if (a < 0) 31189251Ssam return -1; 32189251Ssam b = hex2num(*hex++); 33189251Ssam if (b < 0) 34189251Ssam return -1; 35189251Ssam return (a << 4) | b; 36189251Ssam} 37189251Ssam 38189251Ssam 39189251Ssam/** 40214734Srpaulo * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) 41189251Ssam * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") 42189251Ssam * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 43189251Ssam * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 44189251Ssam */ 45189251Ssamint hwaddr_aton(const char *txt, u8 *addr) 46189251Ssam{ 47189251Ssam int i; 48189251Ssam 49189251Ssam for (i = 0; i < 6; i++) { 50189251Ssam int a, b; 51189251Ssam 52189251Ssam a = hex2num(*txt++); 53189251Ssam if (a < 0) 54189251Ssam return -1; 55189251Ssam b = hex2num(*txt++); 56189251Ssam if (b < 0) 57189251Ssam return -1; 58189251Ssam *addr++ = (a << 4) | b; 59189251Ssam if (i < 5 && *txt++ != ':') 60189251Ssam return -1; 61189251Ssam } 62189251Ssam 63189251Ssam return 0; 64189251Ssam} 65189251Ssam 66252726Srpaulo/** 67252726Srpaulo * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) 68252726Srpaulo * @txt: MAC address as a string (e.g., "001122334455") 69252726Srpaulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 70252726Srpaulo * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) 71252726Srpaulo */ 72252726Srpauloint hwaddr_compact_aton(const char *txt, u8 *addr) 73252726Srpaulo{ 74252726Srpaulo int i; 75189251Ssam 76252726Srpaulo for (i = 0; i < 6; i++) { 77252726Srpaulo int a, b; 78252726Srpaulo 79252726Srpaulo a = hex2num(*txt++); 80252726Srpaulo if (a < 0) 81252726Srpaulo return -1; 82252726Srpaulo b = hex2num(*txt++); 83252726Srpaulo if (b < 0) 84252726Srpaulo return -1; 85252726Srpaulo *addr++ = (a << 4) | b; 86252726Srpaulo } 87252726Srpaulo 88252726Srpaulo return 0; 89252726Srpaulo} 90252726Srpaulo 91189251Ssam/** 92214734Srpaulo * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) 93214734Srpaulo * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) 94214734Srpaulo * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) 95214734Srpaulo * Returns: Characters used (> 0) on success, -1 on failure 96214734Srpaulo */ 97214734Srpauloint hwaddr_aton2(const char *txt, u8 *addr) 98214734Srpaulo{ 99214734Srpaulo int i; 100214734Srpaulo const char *pos = txt; 101214734Srpaulo 102214734Srpaulo for (i = 0; i < 6; i++) { 103214734Srpaulo int a, b; 104214734Srpaulo 105214734Srpaulo while (*pos == ':' || *pos == '.' || *pos == '-') 106214734Srpaulo pos++; 107214734Srpaulo 108214734Srpaulo a = hex2num(*pos++); 109214734Srpaulo if (a < 0) 110214734Srpaulo return -1; 111214734Srpaulo b = hex2num(*pos++); 112214734Srpaulo if (b < 0) 113214734Srpaulo return -1; 114214734Srpaulo *addr++ = (a << 4) | b; 115214734Srpaulo } 116214734Srpaulo 117214734Srpaulo return pos - txt; 118214734Srpaulo} 119214734Srpaulo 120214734Srpaulo 121214734Srpaulo/** 122189251Ssam * hexstr2bin - Convert ASCII hex string into binary data 123189251Ssam * @hex: ASCII hex string (e.g., "01ab") 124189251Ssam * @buf: Buffer for the binary data 125189251Ssam * @len: Length of the text to convert in bytes (of buf); hex will be double 126189251Ssam * this size 127189251Ssam * Returns: 0 on success, -1 on failure (invalid hex string) 128189251Ssam */ 129189251Ssamint hexstr2bin(const char *hex, u8 *buf, size_t len) 130189251Ssam{ 131189251Ssam size_t i; 132189251Ssam int a; 133189251Ssam const char *ipos = hex; 134189251Ssam u8 *opos = buf; 135189251Ssam 136189251Ssam for (i = 0; i < len; i++) { 137189251Ssam a = hex2byte(ipos); 138189251Ssam if (a < 0) 139189251Ssam return -1; 140189251Ssam *opos++ = a; 141189251Ssam ipos += 2; 142189251Ssam } 143189251Ssam return 0; 144189251Ssam} 145189251Ssam 146189251Ssam 147189251Ssam/** 148189251Ssam * inc_byte_array - Increment arbitrary length byte array by one 149189251Ssam * @counter: Pointer to byte array 150189251Ssam * @len: Length of the counter in bytes 151189251Ssam * 152189251Ssam * This function increments the last byte of the counter by one and continues 153189251Ssam * rolling over to more significant bytes if the byte was incremented from 154189251Ssam * 0xff to 0x00. 155189251Ssam */ 156189251Ssamvoid inc_byte_array(u8 *counter, size_t len) 157189251Ssam{ 158189251Ssam int pos = len - 1; 159189251Ssam while (pos >= 0) { 160189251Ssam counter[pos]++; 161189251Ssam if (counter[pos] != 0) 162189251Ssam break; 163189251Ssam pos--; 164189251Ssam } 165189251Ssam} 166189251Ssam 167189251Ssam 168189251Ssamvoid wpa_get_ntp_timestamp(u8 *buf) 169189251Ssam{ 170189251Ssam struct os_time now; 171189251Ssam u32 sec, usec; 172189251Ssam be32 tmp; 173189251Ssam 174189251Ssam /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ 175189251Ssam os_get_time(&now); 176189251Ssam sec = now.sec + 2208988800U; /* Epoch to 1900 */ 177189251Ssam /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ 178189251Ssam usec = now.usec; 179189251Ssam usec = 4295 * usec - (usec >> 5) - (usec >> 9); 180189251Ssam tmp = host_to_be32(sec); 181189251Ssam os_memcpy(buf, (u8 *) &tmp, 4); 182189251Ssam tmp = host_to_be32(usec); 183189251Ssam os_memcpy(buf + 4, (u8 *) &tmp, 4); 184189251Ssam} 185189251Ssam 186189251Ssam 187189251Ssamstatic inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, 188189251Ssam size_t len, int uppercase) 189189251Ssam{ 190189251Ssam size_t i; 191189251Ssam char *pos = buf, *end = buf + buf_size; 192189251Ssam int ret; 193189251Ssam if (buf_size == 0) 194189251Ssam return 0; 195189251Ssam for (i = 0; i < len; i++) { 196189251Ssam ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", 197189251Ssam data[i]); 198189251Ssam if (ret < 0 || ret >= end - pos) { 199189251Ssam end[-1] = '\0'; 200189251Ssam return pos - buf; 201189251Ssam } 202189251Ssam pos += ret; 203189251Ssam } 204189251Ssam end[-1] = '\0'; 205189251Ssam return pos - buf; 206189251Ssam} 207189251Ssam 208189251Ssam/** 209189251Ssam * wpa_snprintf_hex - Print data as a hex string into a buffer 210189251Ssam * @buf: Memory area to use as the output buffer 211189251Ssam * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 212189251Ssam * @data: Data to be printed 213189251Ssam * @len: Length of data in bytes 214189251Ssam * Returns: Number of bytes written 215189251Ssam */ 216189251Ssamint wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) 217189251Ssam{ 218189251Ssam return _wpa_snprintf_hex(buf, buf_size, data, len, 0); 219189251Ssam} 220189251Ssam 221189251Ssam 222189251Ssam/** 223189251Ssam * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf 224189251Ssam * @buf: Memory area to use as the output buffer 225189251Ssam * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) 226189251Ssam * @data: Data to be printed 227189251Ssam * @len: Length of data in bytes 228189251Ssam * Returns: Number of bytes written 229189251Ssam */ 230189251Ssamint wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, 231189251Ssam size_t len) 232189251Ssam{ 233189251Ssam return _wpa_snprintf_hex(buf, buf_size, data, len, 1); 234189251Ssam} 235189251Ssam 236189251Ssam 237189251Ssam#ifdef CONFIG_ANSI_C_EXTRA 238189251Ssam 239189251Ssam#ifdef _WIN32_WCE 240189251Ssamvoid perror(const char *s) 241189251Ssam{ 242189251Ssam wpa_printf(MSG_ERROR, "%s: GetLastError: %d", 243189251Ssam s, (int) GetLastError()); 244189251Ssam} 245189251Ssam#endif /* _WIN32_WCE */ 246189251Ssam 247189251Ssam 248189251Ssamint optind = 1; 249189251Ssamint optopt; 250189251Ssamchar *optarg; 251189251Ssam 252189251Ssamint getopt(int argc, char *const argv[], const char *optstring) 253189251Ssam{ 254189251Ssam static int optchr = 1; 255189251Ssam char *cp; 256189251Ssam 257189251Ssam if (optchr == 1) { 258189251Ssam if (optind >= argc) { 259189251Ssam /* all arguments processed */ 260189251Ssam return EOF; 261189251Ssam } 262189251Ssam 263189251Ssam if (argv[optind][0] != '-' || argv[optind][1] == '\0') { 264189251Ssam /* no option characters */ 265189251Ssam return EOF; 266189251Ssam } 267189251Ssam } 268189251Ssam 269189251Ssam if (os_strcmp(argv[optind], "--") == 0) { 270189251Ssam /* no more options */ 271189251Ssam optind++; 272189251Ssam return EOF; 273189251Ssam } 274189251Ssam 275189251Ssam optopt = argv[optind][optchr]; 276189251Ssam cp = os_strchr(optstring, optopt); 277189251Ssam if (cp == NULL || optopt == ':') { 278189251Ssam if (argv[optind][++optchr] == '\0') { 279189251Ssam optchr = 1; 280189251Ssam optind++; 281189251Ssam } 282189251Ssam return '?'; 283189251Ssam } 284189251Ssam 285189251Ssam if (cp[1] == ':') { 286189251Ssam /* Argument required */ 287189251Ssam optchr = 1; 288189251Ssam if (argv[optind][optchr + 1]) { 289189251Ssam /* No space between option and argument */ 290189251Ssam optarg = &argv[optind++][optchr + 1]; 291189251Ssam } else if (++optind >= argc) { 292189251Ssam /* option requires an argument */ 293189251Ssam return '?'; 294189251Ssam } else { 295189251Ssam /* Argument in the next argv */ 296189251Ssam optarg = argv[optind++]; 297189251Ssam } 298189251Ssam } else { 299189251Ssam /* No argument */ 300189251Ssam if (argv[optind][++optchr] == '\0') { 301189251Ssam optchr = 1; 302189251Ssam optind++; 303189251Ssam } 304189251Ssam optarg = NULL; 305189251Ssam } 306189251Ssam return *cp; 307189251Ssam} 308189251Ssam#endif /* CONFIG_ANSI_C_EXTRA */ 309189251Ssam 310189251Ssam 311189251Ssam#ifdef CONFIG_NATIVE_WINDOWS 312189251Ssam/** 313189251Ssam * wpa_unicode2ascii_inplace - Convert unicode string into ASCII 314189251Ssam * @str: Pointer to string to convert 315189251Ssam * 316189251Ssam * This function converts a unicode string to ASCII using the same 317189251Ssam * buffer for output. If UNICODE is not set, the buffer is not 318189251Ssam * modified. 319189251Ssam */ 320189251Ssamvoid wpa_unicode2ascii_inplace(TCHAR *str) 321189251Ssam{ 322189251Ssam#ifdef UNICODE 323189251Ssam char *dst = (char *) str; 324189251Ssam while (*str) 325189251Ssam *dst++ = (char) *str++; 326189251Ssam *dst = '\0'; 327189251Ssam#endif /* UNICODE */ 328189251Ssam} 329189251Ssam 330189251Ssam 331189251SsamTCHAR * wpa_strdup_tchar(const char *str) 332189251Ssam{ 333189251Ssam#ifdef UNICODE 334189251Ssam TCHAR *buf; 335189251Ssam buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); 336189251Ssam if (buf == NULL) 337189251Ssam return NULL; 338189251Ssam wsprintf(buf, L"%S", str); 339189251Ssam return buf; 340189251Ssam#else /* UNICODE */ 341189251Ssam return os_strdup(str); 342189251Ssam#endif /* UNICODE */ 343189251Ssam} 344189251Ssam#endif /* CONFIG_NATIVE_WINDOWS */ 345189251Ssam 346189251Ssam 347252726Srpaulovoid printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) 348252726Srpaulo{ 349252726Srpaulo char *end = txt + maxlen; 350252726Srpaulo size_t i; 351252726Srpaulo 352252726Srpaulo for (i = 0; i < len; i++) { 353252726Srpaulo if (txt + 4 > end) 354252726Srpaulo break; 355252726Srpaulo 356252726Srpaulo switch (data[i]) { 357252726Srpaulo case '\"': 358252726Srpaulo *txt++ = '\\'; 359252726Srpaulo *txt++ = '\"'; 360252726Srpaulo break; 361252726Srpaulo case '\\': 362252726Srpaulo *txt++ = '\\'; 363252726Srpaulo *txt++ = '\\'; 364252726Srpaulo break; 365252726Srpaulo case '\e': 366252726Srpaulo *txt++ = '\\'; 367252726Srpaulo *txt++ = 'e'; 368252726Srpaulo break; 369252726Srpaulo case '\n': 370252726Srpaulo *txt++ = '\\'; 371252726Srpaulo *txt++ = 'n'; 372252726Srpaulo break; 373252726Srpaulo case '\r': 374252726Srpaulo *txt++ = '\\'; 375252726Srpaulo *txt++ = 'r'; 376252726Srpaulo break; 377252726Srpaulo case '\t': 378252726Srpaulo *txt++ = '\\'; 379252726Srpaulo *txt++ = 't'; 380252726Srpaulo break; 381252726Srpaulo default: 382252726Srpaulo if (data[i] >= 32 && data[i] <= 127) { 383252726Srpaulo *txt++ = data[i]; 384252726Srpaulo } else { 385252726Srpaulo txt += os_snprintf(txt, end - txt, "\\x%02x", 386252726Srpaulo data[i]); 387252726Srpaulo } 388252726Srpaulo break; 389252726Srpaulo } 390252726Srpaulo } 391252726Srpaulo 392252726Srpaulo *txt = '\0'; 393252726Srpaulo} 394252726Srpaulo 395252726Srpaulo 396252726Srpaulosize_t printf_decode(u8 *buf, size_t maxlen, const char *str) 397252726Srpaulo{ 398252726Srpaulo const char *pos = str; 399252726Srpaulo size_t len = 0; 400252726Srpaulo int val; 401252726Srpaulo 402252726Srpaulo while (*pos) { 403252726Srpaulo if (len == maxlen) 404252726Srpaulo break; 405252726Srpaulo switch (*pos) { 406252726Srpaulo case '\\': 407252726Srpaulo pos++; 408252726Srpaulo switch (*pos) { 409252726Srpaulo case '\\': 410252726Srpaulo buf[len++] = '\\'; 411252726Srpaulo pos++; 412252726Srpaulo break; 413252726Srpaulo case '"': 414252726Srpaulo buf[len++] = '"'; 415252726Srpaulo pos++; 416252726Srpaulo break; 417252726Srpaulo case 'n': 418252726Srpaulo buf[len++] = '\n'; 419252726Srpaulo pos++; 420252726Srpaulo break; 421252726Srpaulo case 'r': 422252726Srpaulo buf[len++] = '\r'; 423252726Srpaulo pos++; 424252726Srpaulo break; 425252726Srpaulo case 't': 426252726Srpaulo buf[len++] = '\t'; 427252726Srpaulo pos++; 428252726Srpaulo break; 429252726Srpaulo case 'e': 430252726Srpaulo buf[len++] = '\e'; 431252726Srpaulo pos++; 432252726Srpaulo break; 433252726Srpaulo case 'x': 434252726Srpaulo pos++; 435252726Srpaulo val = hex2byte(pos); 436252726Srpaulo if (val < 0) { 437252726Srpaulo val = hex2num(*pos); 438252726Srpaulo if (val < 0) 439252726Srpaulo break; 440252726Srpaulo buf[len++] = val; 441252726Srpaulo pos++; 442252726Srpaulo } else { 443252726Srpaulo buf[len++] = val; 444252726Srpaulo pos += 2; 445252726Srpaulo } 446252726Srpaulo break; 447252726Srpaulo case '0': 448252726Srpaulo case '1': 449252726Srpaulo case '2': 450252726Srpaulo case '3': 451252726Srpaulo case '4': 452252726Srpaulo case '5': 453252726Srpaulo case '6': 454252726Srpaulo case '7': 455252726Srpaulo val = *pos++ - '0'; 456252726Srpaulo if (*pos >= '0' && *pos <= '7') 457252726Srpaulo val = val * 8 + (*pos++ - '0'); 458252726Srpaulo if (*pos >= '0' && *pos <= '7') 459252726Srpaulo val = val * 8 + (*pos++ - '0'); 460252726Srpaulo buf[len++] = val; 461252726Srpaulo break; 462252726Srpaulo default: 463252726Srpaulo break; 464252726Srpaulo } 465252726Srpaulo break; 466252726Srpaulo default: 467252726Srpaulo buf[len++] = *pos++; 468252726Srpaulo break; 469252726Srpaulo } 470252726Srpaulo } 471252726Srpaulo 472252726Srpaulo return len; 473252726Srpaulo} 474252726Srpaulo 475252726Srpaulo 476189251Ssam/** 477189251Ssam * wpa_ssid_txt - Convert SSID to a printable string 478189251Ssam * @ssid: SSID (32-octet string) 479189251Ssam * @ssid_len: Length of ssid in octets 480189251Ssam * Returns: Pointer to a printable string 481189251Ssam * 482189251Ssam * This function can be used to convert SSIDs into printable form. In most 483189251Ssam * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard 484189251Ssam * does not limit the used character set, so anything could be used in an SSID. 485189251Ssam * 486189251Ssam * This function uses a static buffer, so only one call can be used at the 487189251Ssam * time, i.e., this is not re-entrant and the returned buffer must be used 488189251Ssam * before calling this again. 489189251Ssam */ 490189251Ssamconst char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) 491189251Ssam{ 492252726Srpaulo static char ssid_txt[32 * 4 + 1]; 493189251Ssam 494252726Srpaulo if (ssid == NULL) { 495252726Srpaulo ssid_txt[0] = '\0'; 496252726Srpaulo return ssid_txt; 497189251Ssam } 498252726Srpaulo 499252726Srpaulo printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); 500189251Ssam return ssid_txt; 501189251Ssam} 502209158Srpaulo 503209158Srpaulo 504209158Srpaulovoid * __hide_aliasing_typecast(void *foo) 505209158Srpaulo{ 506209158Srpaulo return foo; 507209158Srpaulo} 508252726Srpaulo 509252726Srpaulo 510252726Srpaulochar * wpa_config_parse_string(const char *value, size_t *len) 511252726Srpaulo{ 512252726Srpaulo if (*value == '"') { 513252726Srpaulo const char *pos; 514252726Srpaulo char *str; 515252726Srpaulo value++; 516252726Srpaulo pos = os_strrchr(value, '"'); 517252726Srpaulo if (pos == NULL || pos[1] != '\0') 518252726Srpaulo return NULL; 519252726Srpaulo *len = pos - value; 520252726Srpaulo str = os_malloc(*len + 1); 521252726Srpaulo if (str == NULL) 522252726Srpaulo return NULL; 523252726Srpaulo os_memcpy(str, value, *len); 524252726Srpaulo str[*len] = '\0'; 525252726Srpaulo return str; 526252726Srpaulo } else if (*value == 'P' && value[1] == '"') { 527252726Srpaulo const char *pos; 528252726Srpaulo char *tstr, *str; 529252726Srpaulo size_t tlen; 530252726Srpaulo value += 2; 531252726Srpaulo pos = os_strrchr(value, '"'); 532252726Srpaulo if (pos == NULL || pos[1] != '\0') 533252726Srpaulo return NULL; 534252726Srpaulo tlen = pos - value; 535252726Srpaulo tstr = os_malloc(tlen + 1); 536252726Srpaulo if (tstr == NULL) 537252726Srpaulo return NULL; 538252726Srpaulo os_memcpy(tstr, value, tlen); 539252726Srpaulo tstr[tlen] = '\0'; 540252726Srpaulo 541252726Srpaulo str = os_malloc(tlen + 1); 542252726Srpaulo if (str == NULL) { 543252726Srpaulo os_free(tstr); 544252726Srpaulo return NULL; 545252726Srpaulo } 546252726Srpaulo 547252726Srpaulo *len = printf_decode((u8 *) str, tlen + 1, tstr); 548252726Srpaulo os_free(tstr); 549252726Srpaulo 550252726Srpaulo return str; 551252726Srpaulo } else { 552252726Srpaulo u8 *str; 553252726Srpaulo size_t tlen, hlen = os_strlen(value); 554252726Srpaulo if (hlen & 1) 555252726Srpaulo return NULL; 556252726Srpaulo tlen = hlen / 2; 557252726Srpaulo str = os_malloc(tlen + 1); 558252726Srpaulo if (str == NULL) 559252726Srpaulo return NULL; 560252726Srpaulo if (hexstr2bin(value, str, tlen)) { 561252726Srpaulo os_free(str); 562252726Srpaulo return NULL; 563252726Srpaulo } 564252726Srpaulo str[tlen] = '\0'; 565252726Srpaulo *len = tlen; 566252726Srpaulo return (char *) str; 567252726Srpaulo } 568252726Srpaulo} 569252726Srpaulo 570252726Srpaulo 571252726Srpauloint is_hex(const u8 *data, size_t len) 572252726Srpaulo{ 573252726Srpaulo size_t i; 574252726Srpaulo 575252726Srpaulo for (i = 0; i < len; i++) { 576252726Srpaulo if (data[i] < 32 || data[i] >= 127) 577252726Srpaulo return 1; 578252726Srpaulo } 579252726Srpaulo return 0; 580252726Srpaulo} 581252726Srpaulo 582252726Srpaulo 583252726Srpaulosize_t merge_byte_arrays(u8 *res, size_t res_len, 584252726Srpaulo const u8 *src1, size_t src1_len, 585252726Srpaulo const u8 *src2, size_t src2_len) 586252726Srpaulo{ 587252726Srpaulo size_t len = 0; 588252726Srpaulo 589252726Srpaulo os_memset(res, 0, res_len); 590252726Srpaulo 591252726Srpaulo if (src1) { 592252726Srpaulo if (src1_len >= res_len) { 593252726Srpaulo os_memcpy(res, src1, res_len); 594252726Srpaulo return res_len; 595252726Srpaulo } 596252726Srpaulo 597252726Srpaulo os_memcpy(res, src1, src1_len); 598252726Srpaulo len += src1_len; 599252726Srpaulo } 600252726Srpaulo 601252726Srpaulo if (src2) { 602252726Srpaulo if (len + src2_len >= res_len) { 603252726Srpaulo os_memcpy(res + len, src2, res_len - len); 604252726Srpaulo return res_len; 605252726Srpaulo } 606252726Srpaulo 607252726Srpaulo os_memcpy(res + len, src2, src2_len); 608252726Srpaulo len += src2_len; 609252726Srpaulo } 610252726Srpaulo 611252726Srpaulo return len; 612252726Srpaulo} 613