From feec4217446e8118f06c0bd0d8af4e553e617904 Mon Sep 17 00:00:00 2001 From: Dominick Meglio Date: Sat, 9 Apr 2005 16:49:47 +0000 Subject: Made sortlist support CIDR matching for IPv4 --- ares/ares_init.c | 77 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 21 deletions(-) (limited to 'ares/ares_init.c') diff --git a/ares/ares_init.c b/ares/ares_init.c index c9d1cd218..980e3d14e 100644 --- a/ares/ares_init.c +++ b/ares/ares_init.c @@ -27,6 +27,10 @@ #include #endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + #include #include #include @@ -47,6 +51,7 @@ #include #include "ares.h" #include "ares_private.h" +#include "inet_net_pton.h" #ifdef WATT32 #undef WIN32 /* Redefined in MingW/MSVC headers */ @@ -63,6 +68,7 @@ static int config_nameserver(struct server_state **servers, int *nservers, static int set_search(ares_channel channel, const char *str); static int set_options(ares_channel channel, const char *str); static const char *try_option(const char *p, const char *q, const char *opt); +static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat); #ifndef WIN32 static int ip_addr(const char *s, int len, struct in_addr *addr); static void natural_mask(struct apattern *pat); @@ -830,30 +836,50 @@ static int config_sortlist(struct apattern **sortlist, int *nsort, /* Add sortlist entries. */ while (*str && *str != ';') { + int bits; + char ipbuf[16], ipbufpfx[32]; + /* Find just the IP */ q = str; while (*q && *q != '/' && *q != ';' && !isspace((unsigned char)*q)) q++; - if (ip_addr(str, (int)(q - str), &pat.addr) == 0) + memcpy(ipbuf, str, (int)(q-str)); + ipbuf[(int)(q-str)] = 0; + /* Find the prefix */ + if (*q == '/') + { + const char *str2 = q+1; + while (*q && *q != ';' && !isspace((unsigned char)*q)) + q++; + memcpy(ipbufpfx, str, (int)(q-str)); + ipbufpfx[(int)(q-str)] = 0; + str = str2; + } + else + ipbufpfx[0] = 0; + /* Lets see if it is CIDR */ + if (ipbufpfx && + (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addr, sizeof(pat.addr))) > 0) + { + pat.type = PATTERN_CIDR; + pat.mask.bits = bits; + if (!sortlist_alloc(sortlist, nsort, &pat)) + return ARES_ENOMEM; + } + /* See if it is just a regular IP */ + else if (ip_addr(ipbuf, (int)(q-str), &pat.addr) == 0) { - /* We have a pattern address; now determine the mask. */ - if (*q == '/') + if (ipbufpfx) { - str = q + 1; - while (*q && *q != ';' && !isspace((unsigned char)*q)) - q++; - if (ip_addr(str, (int)(q - str), &pat.mask) != 0) + memcpy(ipbuf, str, (int)(q-str)); + ipbuf[(int)(q-str)] = 0; + if (ip_addr(ipbuf, (int)(q - str), &pat.mask.addr) != 0) natural_mask(&pat); } else natural_mask(&pat); - - /* Add this pattern to our list. */ - newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern)); - if (!newsort) + pat.type = PATTERN_MASK; + if (!sortlist_alloc(sortlist, nsort, &pat)) return ARES_ENOMEM; - newsort[*nsort] = pat; - *sortlist = newsort; - (*nsort)++; } else { @@ -971,16 +997,25 @@ static const char *try_option(const char *p, const char *q, const char *opt) return ((size_t)(q - p) > len && !strncmp(p, opt, len)) ? &p[len] : NULL; } +static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat) +{ + struct apattern *newsort; + newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern)); + if (!newsort) + return 0; + newsort[*nsort] = *pat; + *sortlist = newsort; + (*nsort)++; + return 1; +} + #ifndef WIN32 -static int ip_addr(const char *s, int len, struct in_addr *addr) +static int ip_addr(const char *ipbuf, int len, struct in_addr *addr) { - char ipbuf[16]; /* Four octets and three periods yields at most 15 characters. */ if (len > 15) return -1; - memcpy(ipbuf, s, len); - ipbuf[len] = 0; addr->s_addr = inet_addr(ipbuf); if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0) @@ -1001,10 +1036,10 @@ static void natural_mask(struct apattern *pat) * still rely on it. */ if (IN_CLASSA(addr.s_addr)) - pat->mask.s_addr = htonl(IN_CLASSA_NET); + pat->mask.addr.s_addr = htonl(IN_CLASSA_NET); else if (IN_CLASSB(addr.s_addr)) - pat->mask.s_addr = htonl(IN_CLASSB_NET); + pat->mask.addr.s_addr = htonl(IN_CLASSB_NET); else - pat->mask.s_addr = htonl(IN_CLASSC_NET); + pat->mask.addr.s_addr = htonl(IN_CLASSC_NET); } #endif -- cgit v1.2.3