Changes in uspace/lib/c/generic/inet/addr.c [3495654:83781a22] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/inet/addr.c
r3495654 r83781a22 34 34 35 35 #include <errno.h> 36 #include <unistd.h> 37 #include <net/socket_codes.h> 36 38 #include <inet/addr.h> 39 #include <net/inet.h> 37 40 #include <stdio.h> 41 #include <malloc.h> 42 #include <bitops.h> 43 44 #define INET_PREFIXSTRSIZE 5 45 46 #if !(defined(__BE__) ^ defined(__LE__)) 47 #error The architecture must be either big-endian or little-endian. 48 #endif 49 50 const addr48_t addr48_broadcast = { 51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 52 }; 53 54 static const addr48_t inet_addr48_solicited_node = { 55 0x33, 0x33, 0xff, 0, 0, 0 56 }; 57 58 static const inet_addr_t inet_addr_any_addr = { 59 .family = AF_INET, 60 .addr = 0 61 }; 62 63 static const inet_addr_t inet_addr_any_addr6 = { 64 .family = AF_INET6, 65 .addr6 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 66 }; 67 68 void addr48(const addr48_t src, addr48_t dst) 69 { 70 memcpy(dst, src, 6); 71 } 72 73 void addr128(const addr128_t src, addr128_t dst) 74 { 75 memcpy(dst, src, 16); 76 } 77 78 int addr48_compare(const addr48_t a, const addr48_t b) 79 { 80 return memcmp(a, b, 6); 81 } 82 83 int addr128_compare(const addr128_t a, const addr128_t b) 84 { 85 return memcmp(a, b, 16); 86 } 87 88 /** Compute solicited node MAC multicast address from target IPv6 address 89 * 90 * @param ip Target IPv6 address 91 * @param mac Solicited MAC address to be assigned 92 * 93 */ 94 void addr48_solicited_node(const addr128_t ip, addr48_t mac) 95 { 96 memcpy(mac, inet_addr48_solicited_node, 3); 97 memcpy(mac + 3, ip + 13, 3); 98 } 99 100 void host2addr128_t_be(const addr128_t host, addr128_t be) 101 { 102 #ifdef __BE__ 103 memcpy(be, host, 16); 104 #else 105 be[0] = host[15]; 106 be[1] = host[14]; 107 be[2] = host[13]; 108 be[3] = host[12]; 109 be[4] = host[11]; 110 be[5] = host[10]; 111 be[6] = host[9]; 112 be[7] = host[8]; 113 be[8] = host[7]; 114 be[9] = host[6]; 115 be[10] = host[5]; 116 be[11] = host[4]; 117 be[12] = host[3]; 118 be[13] = host[2]; 119 be[14] = host[1]; 120 be[15] = host[0]; 121 #endif 122 } 123 124 void addr128_t_be2host(const addr128_t be, addr128_t host) 125 { 126 #ifdef __BE__ 127 memcpy(host, be, 16); 128 #else 129 host[0] = be[15]; 130 host[1] = be[14]; 131 host[2] = be[13]; 132 host[3] = be[12]; 133 host[4] = be[11]; 134 host[5] = be[10]; 135 host[6] = be[9]; 136 host[7] = be[8]; 137 host[8] = be[7]; 138 host[9] = be[6]; 139 host[10] = be[5]; 140 host[11] = be[4]; 141 host[12] = be[3]; 142 host[13] = be[2]; 143 host[14] = be[1]; 144 host[15] = be[0]; 145 #endif 146 } 147 148 void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d) 149 { 150 addr->family = AF_INET; 151 addr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) | 152 ((addr32_t) c << 8) | ((addr32_t) d); 153 } 154 155 void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d, 156 uint8_t prefix) 157 { 158 naddr->family = AF_INET; 159 naddr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) | 160 ((addr32_t) c << 8) | ((addr32_t) d); 161 naddr->prefix = prefix; 162 } 163 164 void inet_addr6(inet_addr_t *addr, uint16_t a, uint16_t b, uint16_t c, 165 uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h) 166 { 167 addr->family = AF_INET6; 168 addr->addr6[0] = (a >> 8) & 0xff; 169 addr->addr6[1] = a & 0xff; 170 addr->addr6[2] = (b >> 8) & 0xff; 171 addr->addr6[3] = b & 0xff; 172 addr->addr6[4] = (c >> 8) & 0xff; 173 addr->addr6[5] = c & 0xff; 174 addr->addr6[6] = (d >> 8) & 0xff; 175 addr->addr6[7] = d & 0xff; 176 addr->addr6[8] = (e >> 8) & 0xff; 177 addr->addr6[9] = e & 0xff; 178 addr->addr6[10] = (f >> 8) & 0xff; 179 addr->addr6[11] = f & 0xff; 180 addr->addr6[12] = (g >> 8) & 0xff; 181 addr->addr6[13] = g & 0xff; 182 addr->addr6[14] = (h >> 8) & 0xff; 183 addr->addr6[15] = h & 0xff; 184 } 185 186 void inet_naddr6(inet_naddr_t *naddr, uint16_t a, uint16_t b, uint16_t c, 187 uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h, uint8_t prefix) 188 { 189 naddr->family = AF_INET6; 190 naddr->addr6[0] = (a >> 8) & 0xff; 191 naddr->addr6[1] = a & 0xff; 192 naddr->addr6[2] = (b >> 8) & 0xff; 193 naddr->addr6[3] = b & 0xff; 194 naddr->addr6[4] = (c >> 8) & 0xff; 195 naddr->addr6[5] = c & 0xff; 196 naddr->addr6[6] = (d >> 8) & 0xff; 197 naddr->addr6[7] = d & 0xff; 198 naddr->addr6[8] = (e >> 8) & 0xff; 199 naddr->addr6[9] = e & 0xff; 200 naddr->addr6[10] = (f >> 8) & 0xff; 201 naddr->addr6[11] = f & 0xff; 202 naddr->addr6[12] = (g >> 8) & 0xff; 203 naddr->addr6[13] = g & 0xff; 204 naddr->addr6[14] = (h >> 8) & 0xff; 205 naddr->addr6[15] = h & 0xff; 206 naddr->prefix = prefix; 207 } 208 209 /** Parse network address family. 210 * 211 * @param text Network address in common notation. 212 * @param af Place to store network address family. 213 * 214 * @return EOK on success, EINVAL if input is not in valid format. 215 * 216 */ 217 int inet_addr_family(const char *text, uint16_t *af) 218 { 219 char *dot = str_chr(text, '.'); 220 if (dot != NULL) { 221 *af = AF_INET; 222 return EOK; 223 } 224 225 char *collon = str_chr(text, ':'); 226 if (collon != NULL) { 227 *af = AF_INET6; 228 return EOK; 229 } 230 231 return EINVAL; 232 } 233 234 void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr) 235 { 236 addr->family = naddr->family; 237 memcpy(addr->addr6, naddr->addr6, 16); 238 } 239 240 void inet_addr_naddr(const inet_addr_t *addr, uint8_t prefix, 241 inet_naddr_t *naddr) 242 { 243 naddr->family = addr->family; 244 memcpy(naddr->addr6, addr->addr6, 16); 245 naddr->prefix = prefix; 246 } 247 248 void inet_addr_any(inet_addr_t *addr) 249 { 250 addr->family = AF_NONE; 251 memset(addr->addr6, 0, 16); 252 } 253 254 void inet_naddr_any(inet_naddr_t *naddr) 255 { 256 naddr->family = AF_NONE; 257 memset(naddr->addr6, 0, 16); 258 naddr->prefix = 0; 259 } 260 261 int inet_addr_compare(const inet_addr_t *a, const inet_addr_t *b) 262 { 263 if (a->family != b->family) 264 return 0; 265 266 switch (a->family) { 267 case AF_INET: 268 return (a->addr == b->addr); 269 case AF_INET6: 270 return addr128_compare(a->addr6, b->addr6); 271 default: 272 return 0; 273 } 274 } 275 276 int inet_addr_is_any(const inet_addr_t *addr) 277 { 278 return ((addr->family == 0) || 279 (inet_addr_compare(addr, &inet_addr_any_addr)) || 280 (inet_addr_compare(addr, &inet_addr_any_addr6))); 281 } 282 283 int inet_naddr_compare(const inet_naddr_t *naddr, const inet_addr_t *addr) 284 { 285 if (naddr->family != addr->family) 286 return 0; 287 288 switch (naddr->family) { 289 case AF_INET: 290 return (naddr->addr == addr->addr); 291 case AF_INET6: 292 return addr128_compare(naddr->addr6, addr->addr6); 293 default: 294 return 0; 295 } 296 } 297 298 int inet_naddr_compare_mask(const inet_naddr_t *naddr, const inet_addr_t *addr) 299 { 300 if (naddr->family != addr->family) 301 return 0; 302 303 switch (naddr->family) { 304 case AF_INET: 305 if (naddr->prefix > 32) 306 return 0; 307 308 addr32_t mask = 309 BIT_RANGE(addr32_t, 31, 31 - (naddr->prefix - 1)); 310 return ((naddr->addr & mask) == (addr->addr & mask)); 311 case AF_INET6: 312 if (naddr->prefix > 128) 313 return 0; 314 315 size_t pos = 0; 316 for (size_t i = 0; i < 16; i++) { 317 /* Further bits do not matter */ 318 if (naddr->prefix < pos) 319 break; 320 321 if (naddr->prefix - pos > 8) { 322 /* Comparison without masking */ 323 if (naddr->addr6[i] != addr->addr6[i]) 324 return 0; 325 } else { 326 /* Comparison with masking */ 327 uint8_t mask = 328 BIT_RANGE(uint8_t, 8, 8 - (naddr->prefix - pos - 1)); 329 if ((naddr->addr6[i] & mask) != (addr->addr6[i] & mask)) 330 return 0; 331 } 332 333 pos += 8; 334 } 335 336 return 1; 337 default: 338 return 0; 339 } 340 } 341 342 /** Parse node address. 343 * 344 * @param text Network address in common notation. 345 * @param addr Place to store node address. 346 * 347 * @return EOK on success, EINVAL if input is not in valid format. 348 * 349 */ 350 int inet_addr_parse(const char *text, inet_addr_t *addr) 351 { 352 int rc = inet_addr_family(text, &addr->family); 353 if (rc != EOK) 354 return rc; 355 356 uint8_t buf[16]; 357 rc = inet_pton(addr->family, text, buf); 358 if (rc != EOK) 359 return rc; 360 361 switch (addr->family) { 362 case AF_INET: 363 addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | 364 buf[3]; 365 break; 366 case AF_INET6: 367 memcpy(addr->addr6, buf, 16); 368 break; 369 default: 370 return EINVAL; 371 } 372 373 return EOK; 374 } 38 375 39 376 /** Parse network address. 40 377 * 41 * @param text Network address in CIDR notation (a.b.c.d/w) 42 * @param naddr Place to store network address 43 * 44 * @return EOK on success, EINVAL if input is not in valid format 378 * @param text Network address in common notation. 379 * @param naddr Place to store network address. 380 * 381 * @return EOK on success, EINVAL if input is not in valid format. 382 * 45 383 */ 46 384 int inet_naddr_parse(const char *text, inet_naddr_t *naddr) 47 385 { 48 unsigned long a[4], bits; 49 char *cp = (char *)text; 50 int i; 51 52 for (i = 0; i < 3; i++) { 53 a[i] = strtoul(cp, &cp, 10); 54 if (*cp != '.') 386 char *slash = str_chr(text, '/'); 387 if (slash == NULL) 388 return EINVAL; 389 390 *slash = 0; 391 392 int rc = inet_addr_family(text, &naddr->family); 393 if (rc != EOK) 394 return rc; 395 396 uint8_t buf[16]; 397 rc = inet_pton(naddr->family, text, buf); 398 *slash = '/'; 399 400 if (rc != EOK) 401 return rc; 402 403 slash++; 404 uint8_t prefix; 405 406 switch (naddr->family) { 407 case AF_INET: 408 prefix = strtoul(slash, &slash, 10); 409 if (prefix > 32) 55 410 return EINVAL; 56 ++cp; 57 } 58 59 a[3] = strtoul(cp, &cp, 10); 60 if (*cp != '/') 61 return EINVAL; 62 ++cp; 63 64 bits = strtoul(cp, &cp, 10); 65 if (*cp != '\0') 66 return EINVAL; 67 68 naddr->ipv4 = 0; 69 for (i = 0; i < 4; i++) { 70 if (a[i] > 255) 411 412 naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | 413 buf[3]; 414 naddr->prefix = prefix; 415 416 break; 417 case AF_INET6: 418 prefix = strtoul(slash, &slash, 10); 419 if (prefix > 128) 71 420 return EINVAL; 72 naddr->ipv4 = (naddr->ipv4 << 8) | a[i]; 73 } 74 75 if (bits > 31) 76 return EINVAL; 77 78 naddr->bits = bits; 421 422 memcpy(naddr->addr6, buf, 16); 423 naddr->prefix = prefix; 424 425 break; 426 default: 427 return ENOTSUP; 428 } 429 79 430 return EOK; 80 431 } 81 432 82 /** Parse node address. 83 * 84 * @param text Network address in dot notation (a.b.c.d) 85 * @param addr Place to store node address 86 * 87 * @return EOK on success, EINVAL if input is not in valid format 88 */ 89 int inet_addr_parse(const char *text, inet_addr_t *addr) 90 { 91 unsigned long a[4]; 92 char *cp = (char *)text; 93 int i; 94 95 for (i = 0; i < 3; i++) { 96 a[i] = strtoul(cp, &cp, 10); 97 if (*cp != '.') 98 return EINVAL; 99 ++cp; 100 } 101 102 a[3] = strtoul(cp, &cp, 10); 103 if (*cp != '\0') 104 return EINVAL; 105 106 addr->ipv4 = 0; 107 for (i = 0; i < 4; i++) { 108 if (a[i] > 255) 109 return EINVAL; 110 addr->ipv4 = (addr->ipv4 << 8) | a[i]; 111 } 112 113 return EOK; 114 } 115 116 /** Format network address. 117 * 118 * @param naddr Network address 119 * @param bufp Place to store pointer to formatted string (CIDR notation) 120 * 121 * @return EOK on success, ENOMEM if out of memory. 122 */ 123 int inet_naddr_format(inet_naddr_t *naddr, char **bufp) 124 { 125 int rc; 126 127 rc = asprintf(bufp, "%d.%d.%d.%d/%d", naddr->ipv4 >> 24, 128 (naddr->ipv4 >> 16) & 0xff, (naddr->ipv4 >> 8) & 0xff, 129 naddr->ipv4 & 0xff, naddr->bits); 130 433 /** Format node address. 434 * 435 * @param addr Node address. 436 * @param bufp Place to store pointer to formatted string. 437 * 438 * @return EOK on success. 439 * @return ENOMEM if out of memory. 440 * @return ENOTSUP on unsupported address family. 441 * 442 */ 443 int inet_addr_format(const inet_addr_t *addr, char **bufp) 444 { 445 int rc = 0; 446 447 switch (addr->family) { 448 case AF_NONE: 449 rc = asprintf(bufp, "none"); 450 break; 451 case AF_INET: 452 rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff, 453 (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff, 454 addr->addr & 0xff); 455 break; 456 case AF_INET6: 457 *bufp = (char *) malloc(INET6_ADDRSTRLEN); 458 if (*bufp == NULL) 459 return ENOMEM; 460 461 return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN); 462 default: 463 return ENOTSUP; 464 } 465 131 466 if (rc < 0) 132 467 return ENOMEM; 133 468 134 469 return EOK; 135 470 } 136 471 137 /** Format node address. 138 * 139 * @param addr Node address 140 * @param bufp Place to store pointer to formatted string (dot notation) 141 * 142 * @return EOK on success, ENOMEM if out of memory. 143 */ 144 int inet_addr_format(inet_addr_t *addr, char **bufp) 145 { 146 int rc; 147 148 rc = asprintf(bufp, "%d.%d.%d.%d", addr->ipv4 >> 24, 149 (addr->ipv4 >> 16) & 0xff, (addr->ipv4 >> 8) & 0xff, 150 addr->ipv4 & 0xff); 151 472 /** Format network address. 473 * 474 * @param naddr Network address. 475 * @param bufp Place to store pointer to formatted string. 476 * 477 * @return EOK on success. 478 * @return ENOMEM if out of memory. 479 * @return ENOTSUP on unsupported address family. 480 * 481 */ 482 int inet_naddr_format(const inet_naddr_t *naddr, char **bufp) 483 { 484 int rc = 0; 485 char prefix[INET_PREFIXSTRSIZE]; 486 487 switch (naddr->family) { 488 case AF_NONE: 489 rc = asprintf(bufp, "none"); 490 break; 491 case AF_INET: 492 rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 493 "/%" PRIu8, (naddr->addr >> 24) & 0xff, 494 (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff, 495 naddr->addr & 0xff, naddr->prefix); 496 break; 497 case AF_INET6: 498 *bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE); 499 if (*bufp == NULL) 500 return ENOMEM; 501 502 rc = inet_ntop(AF_INET6, naddr->addr6, *bufp, 503 INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE); 504 if (rc != EOK) { 505 free(*bufp); 506 return rc; 507 } 508 509 rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8, 510 naddr->prefix); 511 if (rc < 0) { 512 free(*bufp); 513 return ENOMEM; 514 } 515 516 str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix); 517 518 break; 519 default: 520 return ENOTSUP; 521 } 522 152 523 if (rc < 0) 153 524 return ENOMEM; 154 525 155 526 return EOK; 156 527 } 157 528 529 uint16_t inet_addr_get(const inet_addr_t *addr, addr32_t *v4, addr128_t *v6) 530 { 531 switch (addr->family) { 532 case AF_INET: 533 if (v4 != NULL) 534 *v4 = addr->addr; 535 536 break; 537 case AF_INET6: 538 if (v6 != NULL) 539 memcpy(*v6, addr->addr6, 16); 540 541 break; 542 } 543 544 return addr->family; 545 } 546 547 uint16_t inet_naddr_get(const inet_naddr_t *naddr, addr32_t *v4, addr128_t *v6, 548 uint8_t *prefix) 549 { 550 switch (naddr->family) { 551 case AF_INET: 552 if (v4 != NULL) 553 *v4 = naddr->addr; 554 555 if (prefix != NULL) 556 *prefix = naddr->prefix; 557 558 break; 559 case AF_INET6: 560 if (v6 != NULL) 561 memcpy(*v6, naddr->addr6, 16); 562 563 if (prefix != NULL) 564 *prefix = naddr->prefix; 565 566 break; 567 } 568 569 return naddr->family; 570 } 571 572 void inet_addr_set(addr32_t v4, inet_addr_t *addr) 573 { 574 addr->family = AF_INET; 575 addr->addr = v4; 576 } 577 578 void inet_naddr_set(addr32_t v4, uint8_t prefix, inet_naddr_t *naddr) 579 { 580 naddr->family = AF_INET; 581 naddr->addr = v4; 582 naddr->prefix = prefix; 583 } 584 585 void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr) 586 { 587 addr->family = AF_INET; 588 addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr); 589 } 590 591 void inet_addr_set6(addr128_t v6, inet_addr_t *addr) 592 { 593 addr->family = AF_INET6; 594 memcpy(addr->addr6, v6, 16); 595 } 596 597 void inet_naddr_set6(addr128_t v6, uint8_t prefix, inet_naddr_t *naddr) 598 { 599 naddr->family = AF_INET6; 600 memcpy(naddr->addr6, v6, 16); 601 naddr->prefix = prefix; 602 } 603 604 void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6, 605 inet_addr_t *addr) 606 { 607 addr->family = AF_INET6; 608 addr128_t_be2host(sockaddr_in6->sin6_addr.s6_addr, addr->addr6); 609 } 610 611 uint16_t inet_addr_sockaddr_in(const inet_addr_t *addr, 612 sockaddr_in_t *sockaddr_in, sockaddr_in6_t *sockaddr_in6) 613 { 614 switch (addr->family) { 615 case AF_INET: 616 if (sockaddr_in != NULL) { 617 sockaddr_in->sin_family = AF_INET; 618 sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr); 619 } 620 621 break; 622 case AF_INET6: 623 if (sockaddr_in6 != NULL) { 624 sockaddr_in6->sin6_family = AF_INET6; 625 host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr); 626 } 627 628 break; 629 } 630 631 return addr->family; 632 } 633 158 634 /** @} 159 635 */
Note:
See TracChangeset
for help on using the changeset viewer.