00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <ctype.h>
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046
00047 #include "common/common_types.h"
00048 #include "common/string.h"
00049 #include "common/netaddr.h"
00050
00051 static const uint32_t _zero_addr[4] = { 0,0,0,0 };
00052
00053 static char *_mac_to_string(char *dst, void *bin,
00054 size_t dst_size, size_t bin_size, char separator);
00055 static int _mac_from_string(void *bin, size_t bin_size,
00056 const char *src, char separator);
00057 static int _subnetmask_to_prefixlen(const char *src);
00058 static int _read_hexdigit(const char c);
00059 static bool _binary_is_in_subnet(const struct netaddr *subnet,
00060 const void *bin);
00069 int
00070 netaddr_from_binary(struct netaddr *dst, void *binary, size_t len, uint8_t addr_type) {
00071 memset(dst->addr, 0, sizeof(dst->addr));
00072 if (addr_type == AF_INET && len >= 4) {
00073
00074 memcpy(dst->addr, binary, 4);
00075 dst->prefix_len = 32;
00076 }
00077 else if (addr_type == AF_INET6 && len >= 16){
00078
00079 memcpy(dst->addr, binary, 16);
00080 dst->prefix_len = 128;
00081 }
00082 else if (addr_type == AF_MAC48 && len >= 6) {
00083
00084 memcpy(&dst->addr, binary, 6);
00085 dst->prefix_len = 48;
00086 }
00087 else if (addr_type == AF_EUI64 && len >= 8) {
00088
00089 memcpy(dst->addr, binary, 8);
00090 dst->prefix_len = 64;
00091 }
00092 else {
00093
00094 return -1;
00095 }
00096
00097
00098 dst->type = addr_type;
00099
00100 return 0;
00101 }
00102
00110 int
00111 netaddr_to_binary(void *dst, struct netaddr *src, size_t len) {
00112 if (src->type == AF_INET && len >= 4) {
00113
00114 memcpy(dst, src->addr, 4);
00115 }
00116 else if (src->type == AF_INET6 && len >= 16) {
00117
00118 memcpy(dst, src->addr, 16);
00119 }
00120 else if (src->type == AF_MAC48 && len >= 6) {
00121
00122 memcpy(dst, src->addr, 6);
00123 }
00124 else if (src->type == AF_EUI64 && len >= 8) {
00125
00126 memcpy(dst, src->addr, 8);
00127 }
00128 else {
00129
00130 return -1;
00131 }
00132 return 0;
00133 }
00134
00142 int
00143 netaddr_from_socket(struct netaddr *dst, union netaddr_socket *src) {
00144 memset(dst->addr, 0, sizeof(dst->addr));
00145 if (src->std.sa_family == AF_INET) {
00146
00147 memcpy(dst->addr, &src->v4.sin_addr, 4);
00148 dst->prefix_len = 32;
00149 }
00150 else if (src->std.sa_family == AF_INET6){
00151
00152 memcpy(dst->addr, &src->v6.sin6_addr, 16);
00153 dst->prefix_len = 128;
00154 }
00155 else {
00156
00157 return -1;
00158 }
00159 dst->type = src->std.sa_family;
00160 return 0;
00161 }
00162
00170 int
00171 netaddr_to_socket(union netaddr_socket *dst, struct netaddr *src) {
00172
00173 dst->std.sa_family = src->type;
00174
00175 if (src->type == AF_INET) {
00176
00177 memcpy(&dst->v4.sin_addr, src->addr, 4);
00178 }
00179 else if (src->type == AF_INET6) {
00180
00181 memcpy(&dst->v6.sin6_addr, src->addr, 16);
00182 }
00183 else {
00184
00185 return -1;
00186 }
00187
00188
00189 dst->std.sa_family= src->type;
00190 return 0;
00191 }
00192
00193
00194 int
00195 netaddr_to_autobuf(struct autobuf *abuf, struct netaddr *src) {
00196 switch (src->type) {
00197 case AF_INET:
00198
00199 return abuf_memcpy(abuf, src->addr, 4);
00200
00201 case AF_INET6:
00202
00203 return abuf_memcpy(abuf, src->addr, 16);
00204
00205 case AF_MAC48:
00206
00207 return abuf_memcpy(abuf, src->addr, 6);
00208
00209 case AF_EUI64:
00210
00211 return abuf_memcpy(abuf, src->addr, 8);
00212
00213 default:
00214
00215 return -1;
00216 }
00217 }
00218
00226 int
00227 netaddr_socket_init(union netaddr_socket *combined, struct netaddr *addr, uint16_t port) {
00228
00229 memset(combined, 0, sizeof(*combined));
00230
00231 if (addr->type == AF_INET) {
00232
00233 memcpy(&combined->v4.sin_addr, addr->addr, 4);
00234 combined->v4.sin_port = htons(port);
00235 }
00236 else if (addr->type == AF_INET6) {
00237
00238 memcpy(&combined->v6.sin6_addr, addr->addr, 16);
00239 combined->v6.sin6_port = htons(port);
00240 }
00241 else {
00242
00243 return -1;
00244 }
00245
00246
00247 combined->std.sa_family = addr->type;
00248 return 0;
00249 }
00250
00255 uint16_t
00256 netaddr_socket_get_port(union netaddr_socket *sock) {
00257 switch (sock->std.sa_family) {
00258 case AF_INET:
00259 return ntohs(sock->v4.sin_port);
00260 case AF_INET6:
00261 return ntohs(sock->v6.sin6_port);
00262 }
00263 return 0;
00264 }
00265
00274 const char *
00275 netaddr_to_prefixstring(struct netaddr_str *dst, struct netaddr *src, bool forceprefix) {
00276 const char *result = NULL;
00277 int maxprefix;
00278
00279 if (src->type == AF_INET) {
00280 result = inet_ntop(AF_INET, src->addr, dst->buf, sizeof(*dst));
00281 maxprefix = 32;
00282 }
00283 else if (src->type == AF_INET6) {
00284 result = inet_ntop(AF_INET6, src->addr, dst->buf, sizeof(*dst));
00285 maxprefix = 128;
00286 }
00287 else if (src->type == AF_MAC48) {
00288 result = _mac_to_string(dst->buf, src->addr, sizeof(*dst), 6, ':');
00289 maxprefix = 48;
00290 }
00291 else if (src->type == AF_EUI64) {
00292 result = _mac_to_string(dst->buf, src->addr, sizeof(*dst), 8, '-');
00293 maxprefix = 64;
00294 }
00295
00296 if (result != NULL && (forceprefix || src->prefix_len < maxprefix)) {
00297
00298 snprintf(dst->buf + strlen(result), 5, "/%d", src->prefix_len);
00299 }
00300 return result;
00301 }
00302
00310 int
00311 netaddr_from_string(struct netaddr *dst, const char *src) {
00312 struct netaddr_str buf;
00313 unsigned int colon_count, minus_count, result;
00314 int prefix_len;
00315 bool has_coloncolon, has_point;
00316 bool last_was_colon;
00317 char *ptr1, *ptr2, *ptr3;
00318
00319 colon_count = 0;
00320 minus_count = 0;
00321 has_coloncolon = false;
00322 has_point = false;
00323
00324 last_was_colon = false;
00325
00326 result = -1;
00327 prefix_len = -1;
00328
00329
00330 strscpy(buf.buf, src, sizeof(buf));
00331 ptr1 = buf.buf;
00332
00333 str_trim(&ptr1);
00334
00335 ptr2 = ptr1;
00336 while (*ptr2 != 0 && !isspace(*ptr2) && *ptr2 != '/') {
00337 switch (*ptr2) {
00338 case ':':
00339 if (last_was_colon) {
00340 has_coloncolon = true;
00341 }
00342 colon_count++;
00343 break;
00344
00345 case '.':
00346 has_point = true;
00347 break;
00348
00349 case '-':
00350 minus_count++;
00351 break;
00352
00353 default:
00354 break;
00355 }
00356 last_was_colon = *ptr2++ == ':';
00357 }
00358
00359 memset(dst, 0, sizeof(*dst));
00360 if (*ptr2) {
00361
00362 while (isspace(*ptr2)) *ptr2++ = 0;
00363 if (*ptr2 == '/') {
00364 *ptr2++ = 0;
00365 }
00366 while (isspace(*ptr2)) *ptr2++ = 0;
00367
00368 if (*ptr2 == 0) {
00369
00370 return -1;
00371 }
00372
00373
00374 prefix_len = strtoul(ptr2, &ptr3, 10);
00375 if (ptr3 && *ptr3) {
00376
00377 prefix_len = -1;
00378 }
00379 }
00380
00381
00382 if ((colon_count == 5 || minus_count == 5)
00383 && (colon_count == 0 || minus_count == 0)
00384 && !has_point && !has_coloncolon) {
00385 dst->type = AF_MAC48;
00386 dst->prefix_len = 48;
00387 if (colon_count > 0) {
00388 result = _mac_from_string(dst->addr, 6, ptr1, ':');
00389 }
00390 else {
00391 result = _mac_from_string(dst->addr, 6, ptr1, '-');
00392 }
00393 }
00394 else if (colon_count == 0 && !has_point && minus_count == 7) {
00395 dst->type = AF_EUI64;
00396 dst->prefix_len = 64;
00397 dst->addr[7] = 2;
00398 result = _mac_from_string(dst->addr, 8, ptr1, '-');
00399 }
00400 else if (colon_count == 0 && has_point && minus_count == 0) {
00401 dst->type = AF_INET;
00402 dst->prefix_len = 32;
00403 result = inet_pton(AF_INET, ptr1, dst->addr) == 1 ? 0 : -1;
00404
00405 if (result == 0 && *ptr2 && prefix_len == -1) {
00406
00407 prefix_len = _subnetmask_to_prefixlen(ptr2);
00408 }
00409 }
00410 else if ((has_coloncolon || colon_count == 7) && minus_count == 0) {
00411 dst->type = AF_INET6;
00412 dst->prefix_len = 128;
00413 result = inet_pton(AF_INET6, ptr1, dst->addr) == 1 ? 0 : -1;
00414 }
00415
00416
00417 if (result) {
00418 return -1;
00419 }
00420
00421 if (*ptr2) {
00422 if (prefix_len < 0 || prefix_len > dst->prefix_len) {
00423
00424 return -1;
00425 }
00426
00427
00428 dst->prefix_len = prefix_len;
00429 }
00430 return result;
00431 }
00432
00439 const char *
00440 netaddr_socket_to_string(struct netaddr_str *dst, union netaddr_socket *src) {
00441 struct netaddr_str buf;
00442
00443 if (src->std.sa_family == AF_INET) {
00444 snprintf(dst->buf, sizeof(*dst), "%s:%d",
00445 inet_ntop(AF_INET, &src->v4.sin_addr, buf.buf, sizeof(buf)),
00446 ntohs(src->v4.sin_port));
00447 }
00448 else if (src->std.sa_family == AF_INET6) {
00449 snprintf(dst->buf, sizeof(*dst), "[%s]:%d",
00450 inet_ntop(AF_INET6, &src->v6.sin6_addr, buf.buf, sizeof(buf)),
00451 ntohs(src->v6.sin6_port));
00452 }
00453 else {
00454
00455 return NULL;
00456 }
00457
00458 return dst->buf;
00459 }
00460
00471 int
00472 netaddr_avlcmp(const void *k1, const void *k2, void *ptr __attribute__((unused))) {
00473 return netaddr_cmp(k1, k2);
00474 }
00475
00483 int
00484 netaddr_cmp_to_socket(const struct netaddr *a1, const union netaddr_socket *a2) {
00485 int result = 0;
00486
00487 result = (int)a1->type - (int)a2->std.sa_family;
00488 if (result) {
00489 return result;
00490 }
00491
00492 if (a1->type == AF_INET) {
00493 result = memcmp(a1->addr, &a2->v4.sin_addr, 4);
00494 }
00495 else if (a1->type == AF_INET6) {
00496
00497 result = memcmp(a1->addr, &a2->v6.sin6_addr, 16);
00498 }
00499
00500 if (result) {
00501 return result;
00502 }
00503
00504 return (int)a1->prefix_len - (a1->type == AF_INET ? 32 : 128);
00505 }
00506
00516 bool
00517 netaddr_isequal_binary(const struct netaddr *addr,
00518 const void *bin, size_t len, uint16_t af, uint8_t prefix_len) {
00519 if (addr->type != af || addr->prefix_len != prefix_len) {
00520 return false;
00521 }
00522
00523 if (af == AF_INET && len == 4) {
00524 return memcmp(addr->addr, bin, 4) == 0;
00525 }
00526 if (af == AF_INET6 && len == 16) {
00527 return memcmp(addr->addr, bin, 16) == 0;
00528 }
00529 if (af == AF_MAC48 && len == 6) {
00530 return memcmp(addr->addr, bin, 6) == 0;
00531 }
00532 if (af == AF_EUI64 && len == 8) {
00533 return memcmp(addr->addr, bin, 8) == 0;
00534 }
00535 return false;
00536 }
00537
00546 bool
00547 netaddr_binary_is_in_subnet(const struct netaddr *subnet,
00548 const void *bin, size_t len, uint8_t af_family) {
00549 if (subnet->type != af_family
00550 || netaddr_get_maxprefix(subnet) != len * 8) {
00551 return false;
00552 }
00553 return _binary_is_in_subnet(subnet, bin);
00554 }
00555
00563 bool
00564 netaddr_is_in_subnet(const struct netaddr *subnet,
00565 const struct netaddr *addr) {
00566 if (subnet->type != addr->type
00567 || subnet->prefix_len > addr->prefix_len) {
00568 return false;
00569 }
00570
00571 return _binary_is_in_subnet(subnet, addr->addr);
00572 }
00573
00579 uint8_t
00580 netaddr_get_maxprefix(const struct netaddr *addr) {
00581 switch (addr->type) {
00582 case AF_INET:
00583 return 32;
00584 break;
00585 case AF_INET6:
00586 return 128;
00587 case AF_MAC48:
00588 return 48;
00589 break;
00590 case AF_EUI64:
00591 return 64;
00592 break;
00593
00594 default:
00595 return 0;
00596 }
00597 }
00598
00599 #ifdef WIN32
00600
00609 const char *
00610 inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
00611 {
00612 if (af == AF_INET) {
00613 struct sockaddr_in in;
00614 memset(&in, 0, sizeof(in));
00615 in.sin_family = AF_INET;
00616 memcpy(&in.sin_addr, src, sizeof(struct in_addr));
00617 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
00618 dst, cnt, NULL, 0, NI_NUMERICHOST);
00619 return dst;
00620 }
00621 else if (af == AF_INET6) {
00622 struct sockaddr_in6 in;
00623 memset(&in, 0, sizeof(in));
00624 in.sin6_family = AF_INET6;
00625 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
00626 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
00627 dst, cnt, NULL, 0, NI_NUMERICHOST);
00628 return dst;
00629 }
00630 return NULL;
00631 }
00632
00642 int
00643 inet_pton(int af, const char *src, void *dst)
00644 {
00645 struct addrinfo hints, *res;
00646 union netaddr_socket *sock;
00647
00648 if (af != AF_INET && af != AF_INET6) {
00649 return -1;
00650 }
00651
00652 memset(&hints, 0, sizeof(struct addrinfo));
00653 hints.ai_family = af;
00654 hints.ai_flags = AI_NUMERICHOST;
00655
00656 if (getaddrinfo(src, NULL, &hints, &res) != 0)
00657 {
00658 return -1;
00659 }
00660
00661 if (res == NULL) {
00662 return 0;
00663 }
00664
00665 sock = (union netaddr_socket *)res->ai_addr;
00666 if (af == AF_INET) {
00667 memcpy(dst, &sock->v4.sin_addr, 4);
00668 }
00669 else {
00670 memcpy(dst, &sock->v6.sin6_addr, 16);
00671 }
00672
00673 freeaddrinfo(res);
00674 return 1;
00675 }
00676
00677 #endif
00678
00688 static char *
00689 _mac_to_string(char *dst, void *bin, size_t dst_size, size_t bin_size, char separator) {
00690 static const char hex[] = "0123456789abcdef";
00691 char *last_separator, *_dst;
00692 uint8_t *_bin;
00693
00694 _bin = bin;
00695 _dst = dst;
00696 last_separator = dst;
00697
00698 if (dst_size == 0) {
00699 return NULL;
00700 }
00701
00702 while (bin_size > 0 && dst_size >= 3) {
00703 *_dst++ = hex[(*_bin) >> 4];
00704 *_dst++ = hex[(*_bin) & 15];
00705
00706
00707 last_separator = _dst;
00708
00709
00710 *_dst++ = separator;
00711
00712
00713 _bin++;
00714 bin_size--;
00715
00716
00717 dst_size-=3;
00718 }
00719
00720 *last_separator = 0;
00721 return dst;
00722 }
00723
00732 static int
00733 _mac_from_string(void *bin, size_t bin_size, const char *src, char separator) {
00734 uint8_t *_bin;
00735 int num, digit_2;
00736
00737 _bin = bin;
00738
00739 while (bin_size > 0) {
00740 num = _read_hexdigit(*src++);
00741 if (num == -1) {
00742 return -1;
00743 }
00744 digit_2 = _read_hexdigit(*src);
00745 if (digit_2 >= 0) {
00746 num = (num << 4) + digit_2;
00747 src++;
00748 }
00749 *_bin++ = (uint8_t) num;
00750
00751 bin_size--;
00752
00753 if (*src == 0) {
00754 return bin_size ? -1 : 0;
00755 }
00756 if (*src++ != separator) {
00757 return -1;
00758 }
00759 }
00760 return -1;
00761 }
00762
00769 static int
00770 _read_hexdigit(const char c) {
00771 if (c >= '0' && c <= '9') {
00772 return c - '0';
00773 }
00774 if (c >= 'a' && c <= 'f') {
00775 return c - 'a' + 10;
00776 }
00777 if (c >= 'A' && c <= 'F') {
00778 return c - 'A' + 10;
00779 }
00780 return -1;
00781 }
00782
00789 static int
00790 _subnetmask_to_prefixlen(const char *src) {
00791 uint32_t v4, shift;
00792 int len;
00793
00794 if (inet_pton(AF_INET, src, &v4) != 1) {
00795 return -1;
00796 }
00797
00798
00799 v4 = ntohl(v4);
00800
00801 shift = 0xffffffff;
00802 for (len = 31; len >= 0; len--) {
00803 if (v4 == shift) {
00804 return len;
00805 }
00806 shift <<= 1;
00807 }
00808
00809
00810 return -1;
00811 }
00812
00821 static bool
00822 _binary_is_in_subnet(const struct netaddr *subnet, const void *bin) {
00823 int offset, shift;
00824 const uint8_t *_bin;
00825
00826 _bin = bin;
00827
00828 offset = subnet->prefix_len >> 3;
00829 shift = subnet->prefix_len & 7;
00830
00831 if (memcmp(subnet->addr, bin, offset) != 0) {
00832 return false;
00833 }
00834
00835 if (shift != 0) {
00836 return (subnet->addr[offset] >> shift)
00837 == (_bin[offset] >> shift);
00838 }
00839 return true;
00840 }