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