diff options
author | Eric Wong <normalperson@yhbt.net> | 2011-06-02 18:00:05 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-06-02 19:54:40 +0000 |
commit | 30b00d8bc02f2ae0fe871eb50fa342c53714751d (patch) | |
tree | 8938d360c1a3643d27d6e9f897f7f1a7a5d51568 | |
parent | 15f1cba7be8f505c72a5cea88f3ee2248f6e8b4a (diff) | |
download | rpatricia-30b00d8bc02f2ae0fe871eb50fa342c53714751d.tar.gz |
ascii2prefix is family agnostic
getaddrinfo will happily parse IPv6 or IPv4 addresses with AI_NUMERICHOST.
-rw-r--r-- | ext/rpatricia/patricia.c | 173 | ||||
-rw-r--r-- | ext/rpatricia/patricia.h | 2 | ||||
-rw-r--r-- | ext/rpatricia/rpatricia.c | 14 |
3 files changed, 67 insertions, 122 deletions
diff --git a/ext/rpatricia/patricia.c b/ext/rpatricia/patricia.c index 6583d4d..fcbb110 100644 --- a/ext/rpatricia/patricia.c +++ b/ext/rpatricia/patricia.c @@ -67,43 +67,6 @@ comp_with_mask (void *addr, void *dest, u_int mask) return (0); } -/* this allows imcomplete prefix */ -int -my_inet_pton (int af, const char *src, void *dst) -{ - if (af == AF_INET) { - int i, c, val; - u_char xp[4] = {0, 0, 0, 0}; - - for (i = 0; ; i++) { - c = *src++; - if (!isdigit (c)) - return (-1); - val = 0; - do { - val = val * 10 + c - '0'; - if (val > 255) - return (0); - c = *src++; - } while (c && isdigit (c)); - xp[i] = val; - if (c == '\0') - break; - if (c != '.') - return (0); - if (i >= 3) - return (0); - } - memcpy (dst, xp, 4); - return (1); - } else if (af == AF_INET6) { - return (inet_pton (af, src, dst)); - } else { - errno = EAFNOSUPPORT; - return -1; - } -} - /* * convert prefix information to ascii string with length * thread safe and re-entrant implementation @@ -154,36 +117,33 @@ prefix_toa2 (prefix_t *prefix, char *buff) prefix_t * New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) { - int dynamic_allocated = 0; - int default_bitlen = 32; - - if (family == AF_INET6) { - default_bitlen = 128; - if (prefix == NULL) { - prefix = calloc(1, sizeof (prefix_t)); - dynamic_allocated++; - } - memcpy (&prefix->add.sin6, dest, 16); - } - else - if (family == AF_INET) { - if (prefix == NULL) { - prefix = calloc(1, sizeof (prefix4_t)); - dynamic_allocated++; - } - memcpy (&prefix->add.sin, dest, 4); - } - else { - return (NULL); - } - - prefix->bitlen = (bitlen >= 0)? bitlen: default_bitlen; + prefix_t *orig_prefix = prefix; + int default_bitlen; + size_t size, addr_size; + + switch (family) { + case AF_INET6: + addr_size = sizeof(struct in6_addr); + size = sizeof(prefix_t); + break; + case AF_INET: + addr_size = sizeof(struct in_addr); + size = sizeof(prefix4_t); + break; + default: + return NULL; + } + default_bitlen = addr_size * CHAR_BIT; + if (bitlen > default_bitlen) + return NULL; + if (!orig_prefix) + prefix = calloc(1, size); + prefix->bitlen = bitlen >= 0 ? bitlen : default_bitlen; prefix->family = family; - prefix->ref_count = 0; - if (dynamic_allocated) { - prefix->ref_count++; - } - return (prefix); + prefix->ref_count = orig_prefix ? 0 : 1; + memcpy(&prefix->add.sin6, dest, addr_size); + + return prefix; } prefix_t * @@ -195,59 +155,44 @@ New_Prefix (int family, void *dest, int bitlen) /* ascii2prefix */ prefix_t * -ascii2prefix (int family, char *string) +ascii2prefix(char *string) { - u_long bitlen, maxbitlen = 0; - char *cp; - struct in_addr sin; - struct in6_addr sin6; + prefix_t *prefix; + long bitlen; + size_t maxbitlen; + void *dest; + char *slash, *end; int result; - char save[MAXLINE]; - - if (string == NULL) - return (NULL); - - /* easy way to handle both families */ - if (family == 0) { - family = AF_INET; - if (strchr (string, ':')) family = AF_INET6; + char save[INET6_ADDRSTRLEN]; + size_t len; + int family; + union { + struct in6_addr sin6; + struct in_addr sin; + } addr; + + assert(string && "string is NULL"); + len = strlen(string); + slash = memchr(string, '/', len); + if (slash) { + bitlen = strtol(slash + 1, &end, 10); + if (*end || (bitlen < 0) || ((slash - string) >= (int)sizeof(save))) + return NULL; + + /* copy the string to save. Avoid destroying the string */ + memcpy(save, string, slash - string); + save[slash - string] = '\0'; + string = save; + } else { + bitlen = -1; } - if (family == AF_INET) { - maxbitlen = 32; - } - else if (family == AF_INET6) { - maxbitlen = 128; - } + family = memchr(string, ':', len) ? AF_INET6 : AF_INET; + result = inet_pton(family, string, &addr); + if (result != 1) + return NULL; - if ((cp = strchr (string, '/')) != NULL) { - bitlen = atol (cp + 1); - /* *cp = '\0'; */ - /* copy the string to save. Avoid destroying the string */ - assert (cp - string < MAXLINE); - memcpy (save, string, cp - string); - save[cp - string] = '\0'; - string = save; - if (bitlen < 0 || bitlen > maxbitlen) - bitlen = maxbitlen; - } - else { - bitlen = maxbitlen; - } - - if (family == AF_INET) { - if ((result = my_inet_pton (AF_INET, string, &sin)) <= 0) - return (NULL); - return (New_Prefix (AF_INET, &sin, bitlen)); - } - - else if (family == AF_INET6) { - if ((result = inet_pton (AF_INET6, string, &sin6)) <= 0) - return (NULL); - return (New_Prefix (AF_INET6, &sin6, bitlen)); - } - else - return (NULL); + return New_Prefix2(family, &addr, bitlen, NULL); } prefix_t * diff --git a/ext/rpatricia/patricia.h b/ext/rpatricia/patricia.h index b66fe55..d4bb7ab 100644 --- a/ext/rpatricia/patricia.h +++ b/ext/rpatricia/patricia.h @@ -86,7 +86,7 @@ void patricia_process (patricia_tree_t *patricia, void_fn_t func); /* { from demo.c */ prefix_t * -ascii2prefix (int family, char *string); +ascii2prefix (char *string); /* } */ diff --git a/ext/rpatricia/rpatricia.c b/ext/rpatricia/rpatricia.c index ae018af..98b9b35 100644 --- a/ext/rpatricia/rpatricia.c +++ b/ext/rpatricia/rpatricia.c @@ -43,10 +43,10 @@ wrap_node(patricia_node_t *orig) } static prefix_t * -my_ascii2prefix(int family, VALUE str) +my_ascii2prefix(VALUE str) { char *cstr = StringValuePtr(str); - prefix_t *prefix = ascii2prefix(family, cstr); + prefix_t *prefix = ascii2prefix(cstr); if (!prefix) rb_raise(rb_eArgError, "invalid prefix: %s", cstr); @@ -66,7 +66,7 @@ p_add (int argc, VALUE *argv, VALUE self) return Qnil; Data_Get_Struct(self, patricia_tree_t, tree); - prefix = my_ascii2prefix(AF_INET, argv[0]); + prefix = my_ascii2prefix(argv[0]); node = patricia_lookup(tree, prefix); Deref_Prefix(prefix); @@ -93,7 +93,7 @@ p_remove (VALUE self, VALUE r_key) prefix_t *prefix; Data_Get_Struct(self, patricia_tree_t, tree); - prefix = my_ascii2prefix (AF_INET, r_key); + prefix = my_ascii2prefix(r_key); node = patricia_search_exact(tree, prefix); Deref_Prefix (prefix); @@ -113,7 +113,7 @@ p_match (VALUE self, VALUE r_key) prefix_t *prefix; Data_Get_Struct(self, patricia_tree_t, tree); - prefix = my_ascii2prefix (AF_INET, r_key); + prefix = my_ascii2prefix(r_key); node = patricia_search_best(tree, prefix); Deref_Prefix (prefix); @@ -128,7 +128,7 @@ p_include (VALUE self, VALUE r_key) prefix_t *prefix; Data_Get_Struct(self, patricia_tree_t, tree); - prefix = my_ascii2prefix (AF_INET, r_key); + prefix = my_ascii2prefix(r_key); node = patricia_search_best(tree, prefix); Deref_Prefix (prefix); @@ -143,7 +143,7 @@ p_match_exact (VALUE self, VALUE r_key) prefix_t *prefix; Data_Get_Struct(self, patricia_tree_t, tree); - prefix = my_ascii2prefix (AF_INET, r_key); + prefix = my_ascii2prefix(r_key); node = patricia_search_exact(tree, prefix); Deref_Prefix (prefix); |