Changes in uspace/lib/c/generic/inet/addr.c [83781a22:3495654] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/inet/addr.c
r83781a22 r3495654 34 34 35 35 #include <errno.h> 36 #include <unistd.h>37 #include <net/socket_codes.h>38 36 #include <inet/addr.h> 39 #include <net/inet.h>40 37 #include <stdio.h> 41 #include <malloc.h>42 #include <bitops.h>43 38 44 #define INET_PREFIXSTRSIZE 5 39 /** Parse network address. 40 * 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 45 */ 46 int inet_naddr_parse(const char *text, inet_naddr_t *naddr) 47 { 48 unsigned long a[4], bits; 49 char *cp = (char *)text; 50 int i; 45 51 46 #if !(defined(__BE__) ^ defined(__LE__)) 47 #error The architecture must be either big-endian or little-endian. 48 #endif 52 for (i = 0; i < 3; i++) { 53 a[i] = strtoul(cp, &cp, 10); 54 if (*cp != '.') 55 return EINVAL; 56 ++cp; 57 } 49 58 50 const addr48_t addr48_broadcast = { 51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 52 }; 59 a[3] = strtoul(cp, &cp, 10); 60 if (*cp != '/') 61 return EINVAL; 62 ++cp; 53 63 54 static const addr48_t inet_addr48_solicited_node = { 55 0x33, 0x33, 0xff, 0, 0, 056 };64 bits = strtoul(cp, &cp, 10); 65 if (*cp != '\0') 66 return EINVAL; 57 67 58 static const inet_addr_t inet_addr_any_addr = { 59 .family = AF_INET, 60 .addr = 0 61 }; 68 naddr->ipv4 = 0; 69 for (i = 0; i < 4; i++) { 70 if (a[i] > 255) 71 return EINVAL; 72 naddr->ipv4 = (naddr->ipv4 << 8) | a[i]; 73 } 62 74 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 }; 75 if (bits > 31) 76 return EINVAL; 67 77 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 } 78 naddr->bits = bits; 79 return EOK; 340 80 } 341 81 342 82 /** Parse node address. 343 83 * 344 * @param text Network address in common notation.345 * @param addr Place to store node address.84 * @param text Network address in dot notation (a.b.c.d) 85 * @param addr Place to store node address 346 86 * 347 * @return EOK on success, EINVAL if input is not in valid format. 348 * 87 * @return EOK on success, EINVAL if input is not in valid format 349 88 */ 350 89 int inet_addr_parse(const char *text, inet_addr_t *addr) 351 90 { 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: 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') 370 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]; 371 111 } 372 112 373 113 return EOK; 374 114 } 375 115 376 /** Parsenetwork address.116 /** Format network address. 377 117 * 378 * @param text Network address in common notation.379 * @param naddr Place to store network address.118 * @param naddr Network address 119 * @param bufp Place to store pointer to formatted string (CIDR notation) 380 120 * 381 * @return EOK on success, EINVAL if input is not in valid format. 382 * 121 * @return EOK on success, ENOMEM if out of memory. 383 122 */ 384 int inet_naddr_ parse(const char *text, inet_naddr_t *naddr)123 int inet_naddr_format(inet_naddr_t *naddr, char **bufp) 385 124 { 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) 410 return EINVAL; 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) 420 return EINVAL; 421 422 memcpy(naddr->addr6, buf, 16); 423 naddr->prefix = prefix; 424 425 break; 426 default: 427 return ENOTSUP; 428 } 429 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 131 if (rc < 0) 132 return ENOMEM; 133 430 134 return EOK; 431 135 } … … 433 137 /** Format node address. 434 138 * 435 * @param addr Node address.436 * @param bufp Place to store pointer to formatted string.139 * @param addr Node address 140 * @param bufp Place to store pointer to formatted string (dot notation) 437 141 * 438 * @return EOK on success. 439 * @return ENOMEM if out of memory. 440 * @return ENOTSUP on unsupported address family. 441 * 142 * @return EOK on success, ENOMEM if out of memory. 442 143 */ 443 int inet_addr_format( constinet_addr_t *addr, char **bufp)144 int inet_addr_format(inet_addr_t *addr, char **bufp) 444 145 { 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 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 466 152 if (rc < 0) 467 153 return ENOMEM; 468 154 469 155 return EOK; 470 }471 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 ".%" PRIu8493 "/%" 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 523 if (rc < 0)524 return ENOMEM;525 526 return EOK;527 }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 156 } 633 157
Note:
See TracChangeset
for help on using the changeset viewer.