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