1 /* 2 * Copyright (c) 2018-2020 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 const char *qdf_opmode_str(const enum QDF_OPMODE opmode) 27 { 28 switch (opmode) { 29 case QDF_STA_MODE: 30 return "STA"; 31 case QDF_SAP_MODE: 32 return "SAP"; 33 case QDF_P2P_CLIENT_MODE: 34 return "P2P Client"; 35 case QDF_P2P_GO_MODE: 36 return "P2P GO"; 37 case QDF_FTM_MODE: 38 return "FTM"; 39 case QDF_IBSS_MODE: 40 return "IBSS"; 41 case QDF_MONITOR_MODE: 42 return "Monitor"; 43 case QDF_P2P_DEVICE_MODE: 44 return "P2P Device"; 45 case QDF_OCB_MODE: 46 return "OCB"; 47 case QDF_EPPING_MODE: 48 return "EPPing"; 49 case QDF_QVIT_MODE: 50 return "QVIT"; 51 case QDF_NDI_MODE: 52 return "NDI"; 53 case QDF_WDS_MODE: 54 return "WDS"; 55 case QDF_BTAMP_MODE: 56 return "BTAMP"; 57 case QDF_AHDEMO_MODE: 58 return "AHDEMO"; 59 case QDF_TDLS_MODE: 60 return "TDLS"; 61 case QDF_NAN_DISC_MODE: 62 return "NAN"; 63 default: 64 return "Invalid operating mode"; 65 } 66 } 67 68 static QDF_STATUS qdf_consume_char(const char **str, char c) 69 { 70 if ((*str)[0] != c) 71 return QDF_STATUS_E_FAILURE; 72 73 (*str)++; 74 75 return QDF_STATUS_SUCCESS; 76 } 77 78 static QDF_STATUS qdf_consume_dec(const char **str, uint8_t *out_digit) 79 { 80 uint8_t c = (*str)[0]; 81 82 if (c >= '0' && c <= '9') 83 *out_digit = c - '0'; 84 else 85 return QDF_STATUS_E_FAILURE; 86 87 (*str)++; 88 89 return QDF_STATUS_SUCCESS; 90 } 91 92 static QDF_STATUS qdf_consume_hex(const char **str, uint8_t *out_nibble) 93 { 94 uint8_t c = (*str)[0]; 95 96 if (c >= '0' && c <= '9') 97 *out_nibble = c - '0'; 98 else if (c >= 'a' && c <= 'f') 99 *out_nibble = c - 'a' + 10; 100 else if (c >= 'A' && c <= 'F') 101 *out_nibble = c - 'A' + 10; 102 else 103 return QDF_STATUS_E_FAILURE; 104 105 (*str)++; 106 107 return QDF_STATUS_SUCCESS; 108 } 109 110 static QDF_STATUS qdf_consume_octet_dec(const char **str, uint8_t *out_octet) 111 { 112 uint8_t len = 0; 113 uint16_t octet = 0; 114 int i; 115 116 /* consume up to 3 decimal digits */ 117 for (i = 0; i < 3; i++) { 118 uint8_t digit; 119 120 if (QDF_IS_STATUS_ERROR(qdf_consume_dec(str, &digit))) 121 break; 122 123 len++; 124 octet = octet * 10 + digit; 125 } 126 127 /* require at least 1 digit */ 128 if (!len) 129 return QDF_STATUS_E_FAILURE; 130 131 if (octet > 255) { 132 (*str) -= len; 133 return QDF_STATUS_E_FAILURE; 134 } 135 136 *out_octet = octet; 137 138 return QDF_STATUS_SUCCESS; 139 } 140 141 static QDF_STATUS qdf_consume_hex_pair(const char **str, uint8_t *out_byte) 142 { 143 QDF_STATUS status; 144 uint8_t hi, low; 145 146 status = qdf_consume_hex(str, &hi); 147 if (QDF_IS_STATUS_ERROR(status)) 148 return status; 149 150 status = qdf_consume_hex(str, &low); 151 if (QDF_IS_STATUS_ERROR(status)) { 152 (*str)--; 153 return status; 154 } 155 156 *out_byte = hi << 4 | low; 157 158 return QDF_STATUS_SUCCESS; 159 } 160 161 static QDF_STATUS qdf_consume_hextet(const char **str, uint16_t *out_hextet) 162 { 163 uint8_t len = 0; 164 uint16_t hextet = 0; 165 int i; 166 167 /* consume up to 4 hex digits */ 168 for (i = 0; i < 4; i++) { 169 uint8_t digit; 170 171 if (QDF_IS_STATUS_ERROR(qdf_consume_hex(str, &digit))) 172 break; 173 174 len++; 175 hextet = (hextet << 4) + digit; 176 } 177 178 /* require at least 1 digit */ 179 if (!len) 180 return QDF_STATUS_E_FAILURE; 181 182 /* no need to check for overflow */ 183 184 *out_hextet = hextet; 185 186 return QDF_STATUS_SUCCESS; 187 } 188 189 static QDF_STATUS qdf_consume_radix(const char **str, uint8_t *out_radix) 190 { 191 if ((*str)[0] == '0') { 192 switch ((*str)[1]) { 193 case 'b': 194 *out_radix = 2; 195 *str += 2; 196 break; 197 case 'o': 198 *out_radix = 8; 199 *str += 2; 200 break; 201 case 'x': 202 *out_radix = 16; 203 *str += 2; 204 break; 205 default: 206 *out_radix = 10; 207 break; 208 } 209 210 return QDF_STATUS_SUCCESS; 211 } 212 213 if (*str[0] >= '0' && *str[0] <= '9') { 214 *out_radix = 10; 215 return QDF_STATUS_SUCCESS; 216 } 217 218 return QDF_STATUS_E_FAILURE; 219 } 220 221 static QDF_STATUS 222 __qdf_int_parse_lazy(const char **int_str, uint64_t *out_int, bool *out_negate) 223 { 224 QDF_STATUS status; 225 bool negate = false; 226 uint8_t radix; 227 uint8_t digit; 228 uint64_t value = 0; 229 uint64_t next_value; 230 const char *str = *int_str; 231 232 str = qdf_str_left_trim(str); 233 234 status = qdf_consume_char(&str, '-'); 235 if (QDF_IS_STATUS_SUCCESS(status)) 236 negate = true; 237 else 238 qdf_consume_char(&str, '+'); 239 240 status = qdf_consume_radix(&str, &radix); 241 if (QDF_IS_STATUS_ERROR(status)) 242 return status; 243 244 while (QDF_IS_STATUS_SUCCESS(qdf_consume_hex(&str, &digit))) { 245 if (digit >= radix) 246 return QDF_STATUS_E_FAILURE; 247 248 next_value = value * radix + digit; 249 if (next_value < value) 250 return QDF_STATUS_E_RANGE; 251 252 value = next_value; 253 } 254 255 *int_str = str; 256 *out_negate = negate; 257 *out_int = value; 258 259 return QDF_STATUS_SUCCESS; 260 } 261 262 static QDF_STATUS 263 qdf_int_parse(const char *int_str, uint64_t *out_int, bool *out_negate) 264 { 265 QDF_STATUS status; 266 bool negate; 267 uint64_t value; 268 269 QDF_BUG(int_str); 270 if (!int_str) 271 return QDF_STATUS_E_INVAL; 272 273 QDF_BUG(out_int); 274 if (!out_int) 275 return QDF_STATUS_E_INVAL; 276 277 status = __qdf_int_parse_lazy(&int_str, &value, &negate); 278 if (QDF_IS_STATUS_ERROR(status)) 279 return status; 280 281 int_str = qdf_str_left_trim(int_str); 282 if (int_str[0] != '\0') 283 return QDF_STATUS_E_FAILURE; 284 285 *out_negate = negate; 286 *out_int = value; 287 288 return QDF_STATUS_SUCCESS; 289 } 290 291 QDF_STATUS qdf_int32_parse(const char *int_str, int32_t *out_int) 292 { 293 QDF_STATUS status; 294 int64_t value; 295 296 status = qdf_int64_parse(int_str, &value); 297 if (QDF_IS_STATUS_ERROR(status)) 298 return status; 299 300 if ((int32_t)value != value) 301 return QDF_STATUS_E_RANGE; 302 303 *out_int = value; 304 305 return QDF_STATUS_SUCCESS; 306 } 307 qdf_export_symbol(qdf_int32_parse); 308 309 QDF_STATUS qdf_uint32_parse(const char *int_str, uint32_t *out_int) 310 { 311 QDF_STATUS status; 312 uint64_t value; 313 314 status = qdf_uint64_parse(int_str, &value); 315 if (QDF_IS_STATUS_ERROR(status)) 316 return status; 317 318 if ((uint32_t)value != value) 319 return QDF_STATUS_E_RANGE; 320 321 *out_int = value; 322 323 return QDF_STATUS_SUCCESS; 324 } 325 qdf_export_symbol(qdf_uint32_parse); 326 327 QDF_STATUS qdf_int64_parse(const char *int_str, int64_t *out_int) 328 { 329 QDF_STATUS status; 330 bool negate = false; 331 uint64_t value = 0; 332 int64_t signed_value; 333 334 status = qdf_int_parse(int_str, &value, &negate); 335 if (QDF_IS_STATUS_ERROR(status)) 336 return status; 337 338 if (negate) { 339 signed_value = -value; 340 if (signed_value > 0) 341 return QDF_STATUS_E_RANGE; 342 } else { 343 signed_value = value; 344 if (signed_value < 0) 345 return QDF_STATUS_E_RANGE; 346 } 347 348 *out_int = signed_value; 349 350 return QDF_STATUS_SUCCESS; 351 } 352 qdf_export_symbol(qdf_int64_parse); 353 354 QDF_STATUS qdf_uint64_parse(const char *int_str, uint64_t *out_int) 355 { 356 QDF_STATUS status; 357 bool negate = false; 358 uint64_t value = 0; 359 360 status = qdf_int_parse(int_str, &value, &negate); 361 if (QDF_IS_STATUS_ERROR(status)) 362 return status; 363 364 if (negate) 365 return QDF_STATUS_E_RANGE; 366 367 *out_int = value; 368 369 return QDF_STATUS_SUCCESS; 370 } 371 qdf_export_symbol(qdf_uint64_parse); 372 373 QDF_STATUS qdf_bool_parse(const char *bool_str, bool *out_bool) 374 { 375 bool value; 376 377 QDF_BUG(bool_str); 378 if (!bool_str) 379 return QDF_STATUS_E_INVAL; 380 381 QDF_BUG(out_bool); 382 if (!out_bool) 383 return QDF_STATUS_E_INVAL; 384 385 bool_str = qdf_str_left_trim(bool_str); 386 387 switch (bool_str[0]) { 388 case '1': 389 case 'y': 390 case 'Y': 391 value = true; 392 break; 393 case '0': 394 case 'n': 395 case 'N': 396 value = false; 397 break; 398 default: 399 return QDF_STATUS_E_FAILURE; 400 } 401 402 bool_str++; 403 bool_str = qdf_str_left_trim(bool_str); 404 if (bool_str[0] != '\0') 405 return QDF_STATUS_E_FAILURE; 406 407 *out_bool = value; 408 409 return QDF_STATUS_SUCCESS; 410 } 411 qdf_export_symbol(qdf_bool_parse); 412 413 QDF_STATUS qdf_mac_parse(const char *mac_str, struct qdf_mac_addr *out_addr) 414 { 415 QDF_STATUS status; 416 struct qdf_mac_addr addr; 417 bool colons; 418 int i; 419 420 QDF_BUG(mac_str); 421 if (!mac_str) 422 return QDF_STATUS_E_INVAL; 423 424 QDF_BUG(out_addr); 425 if (!out_addr) 426 return QDF_STATUS_E_INVAL; 427 428 mac_str = qdf_str_left_trim(mac_str); 429 430 /* parse leading hex pair */ 431 status = qdf_consume_hex_pair(&mac_str, &addr.bytes[0]); 432 if (QDF_IS_STATUS_ERROR(status)) 433 return status; 434 435 /* dynamically detect colons */ 436 colons = mac_str[0] == ':'; 437 438 for (i = 1; i < QDF_MAC_ADDR_SIZE; i++) { 439 /* ensure colon separator if previously detected */ 440 if (colons) { 441 status = qdf_consume_char(&mac_str, ':'); 442 if (QDF_IS_STATUS_ERROR(status)) 443 return status; 444 } 445 446 /* parse next hex pair */ 447 status = qdf_consume_hex_pair(&mac_str, &addr.bytes[i]); 448 if (QDF_IS_STATUS_ERROR(status)) 449 return status; 450 } 451 452 mac_str = qdf_str_left_trim(mac_str); 453 if (mac_str[0] != '\0') 454 return QDF_STATUS_E_FAILURE; 455 456 *out_addr = addr; 457 458 return QDF_STATUS_SUCCESS; 459 } 460 qdf_export_symbol(qdf_mac_parse); 461 462 QDF_STATUS qdf_ipv4_parse(const char *ipv4_str, struct qdf_ipv4_addr *out_addr) 463 { 464 QDF_STATUS status; 465 struct qdf_ipv4_addr addr; 466 int i; 467 468 QDF_BUG(ipv4_str); 469 if (!ipv4_str) 470 return QDF_STATUS_E_INVAL; 471 472 QDF_BUG(out_addr); 473 if (!out_addr) 474 return QDF_STATUS_E_INVAL; 475 476 ipv4_str = qdf_str_left_trim(ipv4_str); 477 478 /* parse leading octet */ 479 status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[0]); 480 if (QDF_IS_STATUS_ERROR(status)) 481 return status; 482 483 for (i = 1; i < QDF_IPV4_ADDR_SIZE; i++) { 484 /* ensure dot separator */ 485 status = qdf_consume_char(&ipv4_str, '.'); 486 if (QDF_IS_STATUS_ERROR(status)) 487 return status; 488 489 /* parse next octet */ 490 status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[i]); 491 if (QDF_IS_STATUS_ERROR(status)) 492 return status; 493 } 494 495 ipv4_str = qdf_str_left_trim(ipv4_str); 496 if (ipv4_str[0] != '\0') 497 return QDF_STATUS_E_FAILURE; 498 499 *out_addr = addr; 500 501 return QDF_STATUS_SUCCESS; 502 } 503 qdf_export_symbol(qdf_ipv4_parse); 504 505 static inline void qdf_ipv6_apply_zero_comp(struct qdf_ipv6_addr *addr, 506 uint8_t hextets, 507 uint8_t zero_comp_index) 508 { 509 /* Given the following hypothetical ipv6 address: 510 * |---------------------------------------| 511 * | 01 | ab | cd | ef | | | | | 512 * |---------------------------------------| 513 * ^--- zero_comp_index (2) 514 * from -----^ 515 * to ---------------------------^ 516 * | hextets (4) | 517 * | zero comp size | 518 * | to move | 519 * 520 * We need to apply the zero compression such that we get: 521 * |---------------------------------------| 522 * | 01 | ab | 00 | 00 | 00 | 00 | cd | ef | 523 * |---------------------------------------| 524 * | zero comp | 525 * | moved | 526 */ 527 528 size_t zero_comp_size = (QDF_IPV6_ADDR_HEXTET_COUNT - hextets) * 2; 529 size_t bytes_to_move = (hextets - zero_comp_index) * 2; 530 uint8_t *from = &addr->bytes[zero_comp_index * 2]; 531 uint8_t *to = from + zero_comp_size; 532 533 if (bytes_to_move) 534 qdf_mem_move(to, from, bytes_to_move); 535 536 qdf_mem_zero(from, to - from); 537 } 538 539 QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr) 540 { 541 QDF_STATUS status; 542 struct qdf_ipv6_addr addr; 543 int8_t zero_comp = -1; 544 uint8_t hextets_found = 0; 545 546 QDF_BUG(ipv6_str); 547 if (!ipv6_str) 548 return QDF_STATUS_E_INVAL; 549 550 QDF_BUG(out_addr); 551 if (!out_addr) 552 return QDF_STATUS_E_INVAL; 553 554 ipv6_str = qdf_str_left_trim(ipv6_str); 555 556 /* check for leading zero-compression ("::") */ 557 status = qdf_consume_char(&ipv6_str, ':'); 558 if (QDF_IS_STATUS_SUCCESS(status)) { 559 status = qdf_consume_char(&ipv6_str, ':'); 560 if (QDF_IS_STATUS_SUCCESS(status)) 561 zero_comp = 0; 562 else 563 return QDF_STATUS_E_FAILURE; 564 } 565 566 while (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) { 567 uint16_t hextet; 568 569 /* parse hextet */ 570 status = qdf_consume_hextet(&ipv6_str, &hextet); 571 if (QDF_IS_STATUS_ERROR(status)) { 572 /* we must end with hextet or zero compression */ 573 if (hextets_found != zero_comp) 574 return QDF_STATUS_E_FAILURE; 575 576 break; 577 } 578 579 addr.bytes[hextets_found * 2] = hextet >> 8; 580 addr.bytes[hextets_found * 2 + 1] = hextet; 581 hextets_found++; 582 583 /* parse ':' char */ 584 status = qdf_consume_char(&ipv6_str, ':'); 585 if (QDF_IS_STATUS_ERROR(status)) 586 break; 587 588 /* check for zero compression ("::") */ 589 status = qdf_consume_char(&ipv6_str, ':'); 590 if (QDF_IS_STATUS_SUCCESS(status)) { 591 /* only one zero compression is allowed */ 592 if (zero_comp >= 0) 593 return QDF_STATUS_E_FAILURE; 594 595 zero_comp = hextets_found; 596 } 597 } 598 599 ipv6_str = qdf_str_left_trim(ipv6_str); 600 if (ipv6_str[0] != '\0') 601 return QDF_STATUS_E_FAILURE; 602 603 /* we must have max hextets or a zero compression, but not both */ 604 if (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) { 605 if (zero_comp < 0) 606 return QDF_STATUS_E_FAILURE; 607 608 qdf_ipv6_apply_zero_comp(&addr, hextets_found, zero_comp); 609 } else if (zero_comp > -1) { 610 return QDF_STATUS_E_FAILURE; 611 } 612 613 *out_addr = addr; 614 615 return QDF_STATUS_SUCCESS; 616 } 617 qdf_export_symbol(qdf_ipv6_parse); 618 619 QDF_STATUS qdf_uint32_array_parse(const char *in_str, uint32_t *out_array, 620 qdf_size_t array_size, qdf_size_t *out_size) 621 { 622 QDF_STATUS status; 623 bool negate; 624 qdf_size_t size = 0; 625 uint64_t value; 626 627 QDF_BUG(in_str); 628 if (!in_str) 629 return QDF_STATUS_E_INVAL; 630 631 QDF_BUG(out_array); 632 if (!out_array) 633 return QDF_STATUS_E_INVAL; 634 635 QDF_BUG(out_size); 636 if (!out_size) 637 return QDF_STATUS_E_INVAL; 638 639 while (size < array_size) { 640 status = __qdf_int_parse_lazy(&in_str, &value, &negate); 641 if (QDF_IS_STATUS_ERROR(status)) 642 return status; 643 644 if ((uint32_t)value != value || negate) 645 return QDF_STATUS_E_RANGE; 646 647 in_str = qdf_str_left_trim(in_str); 648 649 switch (in_str[0]) { 650 case ',': 651 out_array[size++] = value; 652 in_str++; 653 break; 654 case '\0': 655 out_array[size++] = value; 656 *out_size = size; 657 return QDF_STATUS_SUCCESS; 658 default: 659 return QDF_STATUS_E_FAILURE; 660 } 661 } 662 663 return QDF_STATUS_E_FAILURE; 664 } 665 666 qdf_export_symbol(qdf_uint32_array_parse); 667 668 QDF_STATUS qdf_uint16_array_parse(const char *in_str, uint16_t *out_array, 669 qdf_size_t array_size, qdf_size_t *out_size) 670 { 671 QDF_STATUS status; 672 bool negate; 673 qdf_size_t size = 0; 674 uint64_t value; 675 676 QDF_BUG(in_str); 677 if (!in_str) 678 return QDF_STATUS_E_INVAL; 679 680 QDF_BUG(out_array); 681 if (!out_array) 682 return QDF_STATUS_E_INVAL; 683 684 QDF_BUG(out_size); 685 if (!out_size) 686 return QDF_STATUS_E_INVAL; 687 688 while (size < array_size) { 689 status = __qdf_int_parse_lazy(&in_str, &value, &negate); 690 if (QDF_IS_STATUS_ERROR(status)) 691 return status; 692 693 if ((uint16_t)value != value || negate) 694 return QDF_STATUS_E_RANGE; 695 696 in_str = qdf_str_left_trim(in_str); 697 698 switch (in_str[0]) { 699 case ',': 700 out_array[size++] = value; 701 in_str++; 702 break; 703 case '\0': 704 out_array[size++] = value; 705 *out_size = size; 706 return QDF_STATUS_SUCCESS; 707 default: 708 return QDF_STATUS_E_FAILURE; 709 } 710 } 711 712 return QDF_STATUS_E_FAILURE; 713 } 714 715 qdf_export_symbol(qdf_uint16_array_parse); 716 717 QDF_STATUS qdf_uint8_array_parse(const char *in_str, uint8_t *out_array, 718 qdf_size_t array_size, qdf_size_t *out_size) 719 { 720 QDF_STATUS status; 721 bool negate; 722 qdf_size_t size = 0; 723 uint64_t value; 724 725 QDF_BUG(in_str); 726 if (!in_str) 727 return QDF_STATUS_E_INVAL; 728 729 QDF_BUG(out_array); 730 if (!out_array) 731 return QDF_STATUS_E_INVAL; 732 733 QDF_BUG(out_size); 734 if (!out_size) 735 return QDF_STATUS_E_INVAL; 736 737 while (size < array_size) { 738 status = __qdf_int_parse_lazy(&in_str, &value, &negate); 739 if (QDF_IS_STATUS_ERROR(status)) 740 return status; 741 742 if ((uint8_t)value != value || negate) 743 return QDF_STATUS_E_RANGE; 744 745 in_str = qdf_str_left_trim(in_str); 746 747 switch (in_str[0]) { 748 case ',': 749 out_array[size++] = value; 750 in_str++; 751 break; 752 case '\0': 753 out_array[size++] = value; 754 *out_size = size; 755 return QDF_STATUS_SUCCESS; 756 default: 757 return QDF_STATUS_E_FAILURE; 758 } 759 } 760 761 return QDF_STATUS_E_FAILURE; 762 } 763 764 qdf_export_symbol(qdf_uint8_array_parse); 765