Changeset 683e584 in mainline
- Timestamp:
- 2015-05-15T18:19:26Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bf7587b0
- Parents:
- d6ff08a0
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/inet/addr.c
rd6ff08a0 r683e584 1 1 /* 2 2 * Copyright (c) 2013 Jiri Svoboda 3 * Copyright (c) 2013 Martin Decky 3 4 * All rights reserved. 4 5 * … … 233 234 if (naddr->version != addr->version) 234 235 return 0; 235 236 236 237 switch (naddr->version) { 237 238 case ip_v4: … … 260 261 if (naddr->prefix > 128) 261 262 return 0; 262 263 263 264 size_t pos = 0; 264 265 for (size_t i = 0; i < 16; i++) { … … 266 267 if (naddr->prefix < pos) 267 268 break; 268 269 269 270 if (naddr->prefix - pos > 8) { 270 271 /* Comparison without masking */ … … 278 279 return 0; 279 280 } 280 281 281 282 pos += 8; 282 283 } 283 284 284 285 return 1; 285 286 default: … … 305 306 i++; 306 307 307 if (*cur == 0)308 if (*cur == '\0') 308 309 break; 309 310 … … 321 322 } 322 323 323 if (i != 4 || (*cur != 0))324 if (i != 4 || (*cur != '\0')) 324 325 return EINVAL; 325 326 … … 332 333 static int inet_addr_parse_v6(const char *str, inet_addr_t *raddr, int *prefix) 333 334 { 334 /* XXX */ 335 return EINVAL; 335 uint8_t data[16]; 336 337 memset(data, 0, 16); 338 339 const char *cur = str; 340 size_t i = 0; 341 size_t wildcard_pos = (size_t) -1; 342 size_t wildcard_size = 0; 343 344 /* Handle initial wildcard */ 345 if ((str[0] == ':') && (str[1] == ':')) { 346 cur = str + 2; 347 wildcard_pos = 0; 348 wildcard_size = 16; 349 350 /* Handle the unspecified address */ 351 if (*cur == '\0') 352 goto success; 353 } 354 355 while (i < 16) { 356 uint16_t bioctet; 357 int rc = str_uint16_t(cur, &cur, 16, false, &bioctet); 358 if (rc != EOK) 359 return rc; 360 361 data[i] = (bioctet >> 8) & 0xff; 362 data[i + 1] = bioctet & 0xff; 363 364 if (wildcard_pos != (size_t) -1) { 365 if (wildcard_size < 2) 366 return EINVAL; 367 368 wildcard_size -= 2; 369 } 370 371 i += 2; 372 373 if (*cur != ':') 374 break; 375 376 if (i < 16) { 377 cur++; 378 379 /* Handle wildcard */ 380 if (*cur == ':') { 381 if (wildcard_pos != (size_t) -1) 382 return EINVAL; 383 384 wildcard_pos = i; 385 wildcard_size = 16 - i; 386 cur++; 387 388 if (*cur == '\0' || *cur == '/') 389 break; 390 } 391 } 392 } 393 394 if (prefix != NULL) { 395 if (*cur != '/') 396 return EINVAL; 397 cur++; 398 399 *prefix = strtoul(cur, (char **)&cur, 10); 400 if (*prefix > 128) 401 return EINVAL; 402 } 403 404 if (*cur != '\0') 405 return EINVAL; 406 407 /* Create wildcard positions */ 408 if ((wildcard_pos != (size_t) -1) && (wildcard_size > 0)) { 409 size_t wildcard_shift = 16 - wildcard_size; 410 411 for (i = wildcard_pos + wildcard_shift; i > wildcard_pos; i--) { 412 size_t j = i - 1; 413 data[j + wildcard_size] = data[j]; 414 data[j] = 0; 415 } 416 } 417 418 success: 419 raddr->version = ip_v6; 420 memcpy(raddr->addr6, data, 16); 421 return EOK; 336 422 } 337 423 … … 388 474 } 389 475 390 static int inet_ntop6(const uint8_t *data, char *address, size_t length) 391 { 392 /* Check output buffer size */ 393 if (length < INET6_ADDRSTRLEN) 476 static int inet_addr_format_v4(addr32_t addr, char **bufp) 477 { 478 int rc; 479 480 rc = asprintf(bufp, "%u.%u.%u.%u", (addr >> 24) & 0xff, 481 (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); 482 if (rc < 0) 394 483 return ENOMEM; 395 484 485 return EOK; 486 } 487 488 static int inet_addr_format_v6(const addr128_t addr, char **bufp) 489 { 490 *bufp = (char *) malloc(INET6_ADDRSTRLEN); 491 if (*bufp == NULL) 492 return ENOMEM; 493 396 494 /* Find the longest zero subsequence */ 397 495 398 496 uint16_t zeroes[8]; 399 497 uint16_t bioctets[8]; 400 498 401 499 for (size_t i = 8; i > 0; i--) { 402 500 size_t j = i - 1; 403 404 bioctets[j] = ( data[j << 1] << 8) | data[(j << 1) + 1];405 501 502 bioctets[j] = (addr[j << 1] << 8) | addr[(j << 1) + 1]; 503 406 504 if (bioctets[j] == 0) { 407 505 zeroes[j] = 1; … … 411 509 zeroes[j] = 0; 412 510 } 413 511 414 512 size_t wildcard_pos = (size_t) -1; 415 513 size_t wildcard_size = 0; 416 514 417 515 for (size_t i = 0; i < 8; i++) { 418 516 if (zeroes[i] > wildcard_size) { … … 421 519 } 422 520 } 423 424 char *cur = address;425 size_t rest = length;521 522 char *cur = *bufp; 523 size_t rest = INET6_ADDRSTRLEN; 426 524 bool tail_zero = false; 427 525 int ret; 428 526 429 527 for (size_t i = 0; i < 8; i++) { 430 528 if ((i == wildcard_pos) && (wildcard_size > 1)) { … … 439 537 tail_zero = false; 440 538 } 441 539 442 540 if (ret < 0) 443 541 return EINVAL; 444 542 445 543 cur += ret; 446 544 rest -= ret; 447 545 } 448 449 if (tail_zero) { 450 ret = snprintf(cur, rest, ":"); 451 if (ret < 0) 452 return EINVAL; 453 } 454 546 547 if (tail_zero) 548 (void) snprintf(cur, rest, ":"); 549 455 550 return EOK; 456 551 } 457 458 552 459 553 /** Format node address. … … 469 563 int inet_addr_format(const inet_addr_t *addr, char **bufp) 470 564 { 471 int rc = 0; 472 565 int rc; 566 567 rc = ENOTSUP; 568 473 569 switch (addr->version) { 474 570 case ip_any: 475 571 rc = asprintf(bufp, "none"); 572 if (rc < 0) 573 return ENOMEM; 574 rc = EOK; 476 575 break; 477 576 case ip_v4: 478 rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff, 479 (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff, 480 addr->addr & 0xff); 577 rc = inet_addr_format_v4(addr->addr, bufp); 481 578 break; 482 579 case ip_v6: 483 *bufp = (char *) malloc(INET6_ADDRSTRLEN); 484 if (*bufp == NULL) 485 return ENOMEM; 486 487 return inet_ntop6(addr->addr6, *bufp, INET6_ADDRSTRLEN); 488 default: 489 asprintf(bufp, "<ver=%d>", addr->version); 490 return ENOTSUP; 491 } 492 493 if (rc < 0) 494 return ENOMEM; 495 496 return EOK; 580 rc = inet_addr_format_v6(addr->addr6, bufp); 581 break; 582 } 583 584 return rc; 497 585 } 498 586 … … 509 597 int inet_naddr_format(const inet_naddr_t *naddr, char **bufp) 510 598 { 511 int rc = 0; 512 char prefix[INET_PREFIXSTRSIZE]; 513 599 int rc; 600 char *astr; 601 602 rc = ENOTSUP; 603 514 604 switch (naddr->version) { 515 605 case ip_any: 516 606 rc = asprintf(bufp, "none"); 607 if (rc < 0) 608 return ENOMEM; 609 rc = EOK; 517 610 break; 518 611 case ip_v4: 519 rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 520 "/%" PRIu8, (naddr->addr >> 24) & 0xff, 521 (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff, 522 naddr->addr & 0xff, naddr->prefix); 523 break; 524 case ip_v6: 525 *bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE); 526 if (*bufp == NULL) 612 rc = inet_addr_format_v4(naddr->addr, &astr); 613 if (rc != EOK) 527 614 return ENOMEM; 528 529 rc = inet_ntop6(naddr->addr6, *bufp, 530 INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE); 531 if (rc != EOK) { 532 free(*bufp); 533 return rc; 534 } 535 536 rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8, 537 naddr->prefix); 615 616 rc = asprintf(bufp, "%s/%" PRIu8, astr, naddr->prefix); 538 617 if (rc < 0) { 539 free( *bufp);618 free(astr); 540 619 return ENOMEM; 541 620 } 542 543 str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix); 544 545 break; 546 default: 547 return ENOTSUP; 548 } 549 550 if (rc < 0) 551 return ENOMEM; 552 553 return EOK; 621 622 rc = EOK; 623 break; 624 case ip_v6: 625 rc = inet_addr_format_v6(naddr->addr6, &astr); 626 if (rc != EOK) 627 return ENOMEM; 628 629 rc = asprintf(bufp, "%s/%" PRIu8, astr, naddr->prefix); 630 if (rc < 0) { 631 free(astr); 632 return ENOMEM; 633 } 634 635 rc = EOK; 636 break; 637 } 638 639 return rc; 554 640 } 555 641
Note:
See TracChangeset
for help on using the changeset viewer.