1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "qdf_mem.h" 20 #include "qdf_module.h" 21 #include "qdf_status.h" 22 #include "qdf_str.h" 23 #include "qdf_trace.h" 24 #include "qdf_types.h" 25 26 static QDF_STATUS qdf_consume_char(const char **str, char c) 27 { 28 if ((*str)[0] != c) 29 return QDF_STATUS_E_FAILURE; 30 31 (*str)++; 32 33 return QDF_STATUS_SUCCESS; 34 } 35 36 static QDF_STATUS qdf_consume_dec(const char **str, uint8_t *out_digit) 37 { 38 uint8_t c = (*str)[0]; 39 40 if (c >= '0' && c <= '9') 41 *out_digit = c - '0'; 42 else 43 return QDF_STATUS_E_FAILURE; 44 45 (*str)++; 46 47 return QDF_STATUS_SUCCESS; 48 } 49 50 static QDF_STATUS qdf_consume_hex(const char **str, uint8_t *out_nibble) 51 { 52 uint8_t c = (*str)[0]; 53 54 if (c >= '0' && c <= '9') 55 *out_nibble = c - '0'; 56 else if (c >= 'a' && c <= 'f') 57 *out_nibble = c - 'a' + 10; 58 else if (c >= 'A' && c <= 'F') 59 *out_nibble = c - 'A' + 10; 60 else 61 return QDF_STATUS_E_FAILURE; 62 63 (*str)++; 64 65 return QDF_STATUS_SUCCESS; 66 } 67 68 static QDF_STATUS qdf_consume_octet_dec(const char **str, uint8_t *out_octet) 69 { 70 uint8_t len = 0; 71 uint16_t octet = 0; 72 int i; 73 74 /* consume up to 3 decimal digits */ 75 for (i = 0; i < 3; i++) { 76 uint8_t digit; 77 78 if (QDF_IS_STATUS_ERROR(qdf_consume_dec(str, &digit))) 79 break; 80 81 len++; 82 octet = octet * 10 + digit; 83 } 84 85 /* require at least 1 digit */ 86 if (!len) 87 return QDF_STATUS_E_FAILURE; 88 89 if (octet > 255) { 90 (*str) -= len; 91 return QDF_STATUS_E_FAILURE; 92 } 93 94 *out_octet = octet; 95 96 return QDF_STATUS_SUCCESS; 97 } 98 99 static QDF_STATUS qdf_consume_hex_pair(const char **str, uint8_t *out_byte) 100 { 101 QDF_STATUS status; 102 uint8_t hi, low; 103 104 status = qdf_consume_hex(str, &hi); 105 if (QDF_IS_STATUS_ERROR(status)) 106 return status; 107 108 status = qdf_consume_hex(str, &low); 109 if (QDF_IS_STATUS_ERROR(status)) { 110 (*str)--; 111 return status; 112 } 113 114 *out_byte = hi << 4 | low; 115 116 return QDF_STATUS_SUCCESS; 117 } 118 119 static QDF_STATUS qdf_consume_hextet(const char **str, uint16_t *out_hextet) 120 { 121 uint8_t len = 0; 122 uint16_t hextet = 0; 123 int i; 124 125 /* consume up to 4 hex digits */ 126 for (i = 0; i < 4; i++) { 127 uint8_t digit; 128 129 if (QDF_IS_STATUS_ERROR(qdf_consume_hex(str, &digit))) 130 break; 131 132 len++; 133 hextet = (hextet << 4) + digit; 134 } 135 136 /* require at least 1 digit */ 137 if (!len) 138 return QDF_STATUS_E_FAILURE; 139 140 /* no need to check for overflow */ 141 142 *out_hextet = hextet; 143 144 return QDF_STATUS_SUCCESS; 145 } 146 147 static QDF_STATUS qdf_consume_radix(const char **str, uint8_t *out_radix) 148 { 149 if ((*str)[0] == '0') { 150 switch ((*str)[1]) { 151 case 'b': 152 *out_radix = 2; 153 *str += 2; 154 break; 155 case 'o': 156 *out_radix = 8; 157 *str += 2; 158 break; 159 case 'x': 160 *out_radix = 16; 161 *str += 2; 162 break; 163 default: 164 *out_radix = 10; 165 break; 166 } 167 168 return QDF_STATUS_SUCCESS; 169 } 170 171 if (*str[0] >= '0' && *str[0] <= '9') { 172 *out_radix = 10; 173 return QDF_STATUS_SUCCESS; 174 } 175 176 return QDF_STATUS_E_FAILURE; 177 } 178 179 static QDF_STATUS 180 __qdf_int_parse_lazy(const char **int_str, uint64_t *out_int, bool *out_negate) 181 { 182 QDF_STATUS status; 183 bool negate = false; 184 uint8_t radix; 185 uint8_t digit; 186 uint64_t value = 0; 187 uint64_t next_value; 188 const char *str = *int_str; 189 190 str = qdf_str_left_trim(str); 191 192 status = qdf_consume_char(&str, '-'); 193 if (QDF_IS_STATUS_SUCCESS(status)) 194 negate = true; 195 else 196 qdf_consume_char(&str, '+'); 197 198 status = qdf_consume_radix(&str, &radix); 199 if (QDF_IS_STATUS_ERROR(status)) 200 return status; 201 202 while (QDF_IS_STATUS_SUCCESS(qdf_consume_hex(&str, &digit))) { 203 if (digit >= radix) 204 return QDF_STATUS_E_FAILURE; 205 206 next_value = value * radix + digit; 207 if (next_value < value) 208 return QDF_STATUS_E_RANGE; 209 210 value = next_value; 211 } 212 213 *int_str = str; 214 *out_negate = negate; 215 *out_int = value; 216 217 return QDF_STATUS_SUCCESS; 218 } 219 220 static QDF_STATUS 221 qdf_int_parse(const char *int_str, uint64_t *out_int, bool *out_negate) 222 { 223 QDF_STATUS status; 224 bool negate; 225 uint64_t value; 226 227 QDF_BUG(int_str); 228 if (!int_str) 229 return QDF_STATUS_E_INVAL; 230 231 QDF_BUG(out_int); 232 if (!out_int) 233 return QDF_STATUS_E_INVAL; 234 235 status = __qdf_int_parse_lazy(&int_str, &value, &negate); 236 if (QDF_IS_STATUS_ERROR(status)) 237 return status; 238 239 int_str = qdf_str_left_trim(int_str); 240 if (int_str[0] != '\0') 241 return QDF_STATUS_E_FAILURE; 242 243 *out_negate = negate; 244 *out_int = value; 245 246 return QDF_STATUS_SUCCESS; 247 } 248 249 QDF_STATUS qdf_int32_parse(const char *int_str, int32_t *out_int) 250 { 251 QDF_STATUS status; 252 int64_t value; 253 254 status = qdf_int64_parse(int_str, &value); 255 if (QDF_IS_STATUS_ERROR(status)) 256 return status; 257 258 if ((int32_t)value != value) 259 return QDF_STATUS_E_RANGE; 260 261 *out_int = value; 262 263 return QDF_STATUS_SUCCESS; 264 } 265 qdf_export_symbol(qdf_int32_parse); 266 267 QDF_STATUS qdf_uint32_parse(const char *int_str, uint32_t *out_int) 268 { 269 QDF_STATUS status; 270 uint64_t value; 271 272 status = qdf_uint64_parse(int_str, &value); 273 if (QDF_IS_STATUS_ERROR(status)) 274 return status; 275 276 if ((uint32_t)value != value) 277 return QDF_STATUS_E_RANGE; 278 279 *out_int = value; 280 281 return QDF_STATUS_SUCCESS; 282 } 283 qdf_export_symbol(qdf_uint32_parse); 284 285 QDF_STATUS qdf_int64_parse(const char *int_str, int64_t *out_int) 286 { 287 QDF_STATUS status; 288 bool negate; 289 uint64_t value; 290 int64_t signed_value; 291 292 status = qdf_int_parse(int_str, &value, &negate); 293 if (QDF_IS_STATUS_ERROR(status)) 294 return status; 295 296 if (negate) { 297 signed_value = -value; 298 if (signed_value > 0) 299 return QDF_STATUS_E_RANGE; 300 } else { 301 signed_value = value; 302 if (signed_value < 0) 303 return QDF_STATUS_E_RANGE; 304 } 305 306 *out_int = signed_value; 307 308 return QDF_STATUS_SUCCESS; 309 } 310 qdf_export_symbol(qdf_int64_parse); 311 312 QDF_STATUS qdf_uint64_parse(const char *int_str, uint64_t *out_int) 313 { 314 QDF_STATUS status; 315 bool negate; 316 uint64_t value; 317 318 status = qdf_int_parse(int_str, &value, &negate); 319 if (QDF_IS_STATUS_ERROR(status)) 320 return status; 321 322 if (negate) 323 return QDF_STATUS_E_RANGE; 324 325 *out_int = value; 326 327 return QDF_STATUS_SUCCESS; 328 } 329 qdf_export_symbol(qdf_uint64_parse); 330 331 QDF_STATUS qdf_bool_parse(const char *bool_str, bool *out_bool) 332 { 333 bool value; 334 335 QDF_BUG(bool_str); 336 if (!bool_str) 337 return QDF_STATUS_E_INVAL; 338 339 QDF_BUG(out_bool); 340 if (!out_bool) 341 return QDF_STATUS_E_INVAL; 342 343 bool_str = qdf_str_left_trim(bool_str); 344 345 switch (bool_str[0]) { 346 case '1': 347 case 'y': 348 case 'Y': 349 value = true; 350 break; 351 case '0': 352 case 'n': 353 case 'N': 354 value = false; 355 break; 356 default: 357 return QDF_STATUS_E_FAILURE; 358 } 359 360 bool_str++; 361 bool_str = qdf_str_left_trim(bool_str); 362 if (bool_str[0] != '\0') 363 return QDF_STATUS_E_FAILURE; 364 365 *out_bool = value; 366 367 return QDF_STATUS_SUCCESS; 368 } 369 qdf_export_symbol(qdf_bool_parse); 370 371 QDF_STATUS qdf_mac_parse(const char *mac_str, struct qdf_mac_addr *out_addr) 372 { 373 QDF_STATUS status; 374 struct qdf_mac_addr addr; 375 bool colons; 376 int i; 377 378 QDF_BUG(mac_str); 379 if (!mac_str) 380 return QDF_STATUS_E_INVAL; 381 382 QDF_BUG(out_addr); 383 if (!out_addr) 384 return QDF_STATUS_E_INVAL; 385 386 mac_str = qdf_str_left_trim(mac_str); 387 388 /* parse leading hex pair */ 389 status = qdf_consume_hex_pair(&mac_str, &addr.bytes[0]); 390 if (QDF_IS_STATUS_ERROR(status)) 391 return status; 392 393 /* dynamically detect colons */ 394 colons = mac_str[0] == ':'; 395 396 for (i = 1; i < QDF_MAC_ADDR_SIZE; i++) { 397 /* ensure colon separator if previously detected */ 398 if (colons) { 399 status = qdf_consume_char(&mac_str, ':'); 400 if (QDF_IS_STATUS_ERROR(status)) 401 return status; 402 } 403 404 /* parse next hex pair */ 405 status = qdf_consume_hex_pair(&mac_str, &addr.bytes[i]); 406 if (QDF_IS_STATUS_ERROR(status)) 407 return status; 408 } 409 410 mac_str = qdf_str_left_trim(mac_str); 411 if (mac_str[0] != '\0') 412 return QDF_STATUS_E_FAILURE; 413 414 *out_addr = addr; 415 416 return QDF_STATUS_SUCCESS; 417 } 418 qdf_export_symbol(qdf_mac_parse); 419 420 QDF_STATUS qdf_ipv4_parse(const char *ipv4_str, struct qdf_ipv4_addr *out_addr) 421 { 422 QDF_STATUS status; 423 struct qdf_ipv4_addr addr; 424 int i; 425 426 QDF_BUG(ipv4_str); 427 if (!ipv4_str) 428 return QDF_STATUS_E_INVAL; 429 430 QDF_BUG(out_addr); 431 if (!out_addr) 432 return QDF_STATUS_E_INVAL; 433 434 ipv4_str = qdf_str_left_trim(ipv4_str); 435 436 /* parse leading octet */ 437 status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[0]); 438 if (QDF_IS_STATUS_ERROR(status)) 439 return status; 440 441 for (i = 1; i < QDF_IPV4_ADDR_SIZE; i++) { 442 /* ensure dot separator */ 443 status = qdf_consume_char(&ipv4_str, '.'); 444 if (QDF_IS_STATUS_ERROR(status)) 445 return status; 446 447 /* parse next octet */ 448 status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[i]); 449 if (QDF_IS_STATUS_ERROR(status)) 450 return status; 451 } 452 453 ipv4_str = qdf_str_left_trim(ipv4_str); 454 if (ipv4_str[0] != '\0') 455 return QDF_STATUS_E_FAILURE; 456 457 *out_addr = addr; 458 459 return QDF_STATUS_SUCCESS; 460 } 461 qdf_export_symbol(qdf_ipv4_parse); 462 463 QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr) 464 { 465 QDF_STATUS status; 466 struct qdf_ipv6_addr addr; 467 int8_t zero_comp = -1; 468 uint8_t hextets_found = 0; 469 470 QDF_BUG(ipv6_str); 471 if (!ipv6_str) 472 return QDF_STATUS_E_INVAL; 473 474 QDF_BUG(out_addr); 475 if (!out_addr) 476 return QDF_STATUS_E_INVAL; 477 478 ipv6_str = qdf_str_left_trim(ipv6_str); 479 480 /* check for leading zero-compression ("::") */ 481 status = qdf_consume_char(&ipv6_str, ':'); 482 if (QDF_IS_STATUS_SUCCESS(status)) { 483 status = qdf_consume_char(&ipv6_str, ':'); 484 if (QDF_IS_STATUS_SUCCESS(status)) 485 zero_comp = 0; 486 else 487 return QDF_STATUS_E_FAILURE; 488 } 489 490 while (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) { 491 uint16_t hextet; 492 493 /* parse hextet */ 494 status = qdf_consume_hextet(&ipv6_str, &hextet); 495 if (QDF_IS_STATUS_ERROR(status)) { 496 /* we must end with hextet or zero compression */ 497 if (hextets_found != zero_comp) 498 return QDF_STATUS_E_FAILURE; 499 500 break; 501 } 502 503 addr.bytes[hextets_found * 2] = hextet >> 8; 504 addr.bytes[hextets_found * 2 + 1] = hextet; 505 hextets_found++; 506 507 /* parse ':' char */ 508 status = qdf_consume_char(&ipv6_str, ':'); 509 if (QDF_IS_STATUS_ERROR(status)) 510 break; 511 512 /* check for zero compression ("::") */ 513 status = qdf_consume_char(&ipv6_str, ':'); 514 if (QDF_IS_STATUS_SUCCESS(status)) { 515 /* only one zero compression is allowed */ 516 if (zero_comp >= 0) 517 return QDF_STATUS_E_FAILURE; 518 519 zero_comp = hextets_found; 520 } 521 } 522 523 /* we must have max hextets or a zero compression */ 524 if (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT && zero_comp == -1) 525 return QDF_STATUS_E_FAILURE; 526 527 ipv6_str = qdf_str_left_trim(ipv6_str); 528 if (ipv6_str[0] != '\0') 529 return QDF_STATUS_E_FAILURE; 530 531 /* shift lower hextets if zero compressed */ 532 if (zero_comp >= 0) { 533 uint8_t shift = QDF_IPV6_ADDR_HEXTET_COUNT - hextets_found; 534 void *to = &addr.bytes[(zero_comp + shift) * 2]; 535 void *from = &addr.bytes[zero_comp * 2]; 536 537 qdf_mem_move(to, from, (hextets_found - zero_comp) * 2); 538 qdf_mem_set(from, shift * 2, 0); 539 } 540 541 *out_addr = addr; 542 543 return QDF_STATUS_SUCCESS; 544 } 545 qdf_export_symbol(qdf_ipv6_parse); 546 547 QDF_STATUS qdf_uint8_array_parse(const char *in_str, uint8_t *out_array, 548 qdf_size_t array_size, qdf_size_t *out_size) 549 { 550 QDF_STATUS status; 551 bool negate; 552 qdf_size_t size = 0; 553 uint64_t value; 554 555 QDF_BUG(in_str); 556 if (!in_str) 557 return QDF_STATUS_E_INVAL; 558 559 QDF_BUG(out_array); 560 if (!out_array) 561 return QDF_STATUS_E_INVAL; 562 563 QDF_BUG(out_size); 564 if (!out_size) 565 return QDF_STATUS_E_INVAL; 566 567 while (size < array_size) { 568 status = __qdf_int_parse_lazy(&in_str, &value, &negate); 569 if (QDF_IS_STATUS_ERROR(status)) 570 return status; 571 572 if ((uint8_t)value != value || negate) 573 return QDF_STATUS_E_RANGE; 574 575 in_str = qdf_str_left_trim(in_str); 576 577 switch (in_str[0]) { 578 case ',': 579 out_array[size++] = value; 580 in_str++; 581 break; 582 case '\0': 583 out_array[size++] = value; 584 *out_size = size; 585 return QDF_STATUS_SUCCESS; 586 default: 587 return QDF_STATUS_E_FAILURE; 588 } 589 } 590 591 return QDF_STATUS_E_FAILURE; 592 } 593 594 qdf_export_symbol(qdf_uint8_array_parse); 595