1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

Made sortlist support CIDR matching for IPv4

This commit is contained in:
Dominick Meglio 2005-04-09 16:49:47 +00:00
parent 634982840e
commit feec421744
5 changed files with 78 additions and 28 deletions

View File

@ -1,5 +1,9 @@
Changelog for the c-ares project Changelog for the c-ares project
* April 9
- Made sortlist support CIDR matching for IPv4.
* April 8 * April 8
- Added preliminary IPv6 support to ares_gethostbyname. Currently, sortlist - Added preliminary IPv6 support to ares_gethostbyname. Currently, sortlist

View File

@ -34,6 +34,7 @@
#include "ares.h" #include "ares.h"
#include "ares_private.h" #include "ares_private.h"
#include "inet_net_pton.h" #include "inet_net_pton.h"
#include "bitncmp.h"
#ifdef WATT32 #ifdef WATT32
#undef WIN32 #undef WIN32
@ -189,10 +190,7 @@ static void end_hquery(struct host_query *hquery, int status,
static int fake_hostent(const char *name, int family, ares_host_callback callback, static int fake_hostent(const char *name, int family, ares_host_callback callback,
void *arg) void *arg)
{ {
struct in_addr addr;
struct in6_addr addr6;
struct hostent hostent; struct hostent hostent;
const char *p;
char *aliases[1] = { NULL }; char *aliases[1] = { NULL };
char *addrs[2]; char *addrs[2];
int result = 0; int result = 0;
@ -333,8 +331,12 @@ static int get_address_index(struct in_addr *addr, struct apattern *sortlist,
for (i = 0; i < nsort; i++) for (i = 0; i < nsort; i++)
{ {
if ((addr->s_addr & sortlist[i].mask.s_addr) == sortlist[i].addr.s_addr) if (sortlist[i].type = PATTERN_MASK)
break; if ((addr->s_addr & sortlist[i].mask.addr.s_addr) == sortlist[i].addr.s_addr)
break;
else
if (!ares_bitncmp(&addr->s_addr, &sortlist[i].addr.s_addr, sortlist[i].mask.bits))
break;
} }
return i; return i;
} }

View File

@ -27,6 +27,10 @@
#include <sys/time.h> #include <sys/time.h>
#endif #endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
@ -47,6 +51,7 @@
#include <errno.h> #include <errno.h>
#include "ares.h" #include "ares.h"
#include "ares_private.h" #include "ares_private.h"
#include "inet_net_pton.h"
#ifdef WATT32 #ifdef WATT32
#undef WIN32 /* Redefined in MingW/MSVC headers */ #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_search(ares_channel channel, const char *str);
static int set_options(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 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 #ifndef WIN32
static int ip_addr(const char *s, int len, struct in_addr *addr); static int ip_addr(const char *s, int len, struct in_addr *addr);
static void natural_mask(struct apattern *pat); static void natural_mask(struct apattern *pat);
@ -830,30 +836,50 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
/* Add sortlist entries. */ /* Add sortlist entries. */
while (*str && *str != ';') while (*str && *str != ';')
{ {
int bits;
char ipbuf[16], ipbufpfx[32];
/* Find just the IP */
q = str; q = str;
while (*q && *q != '/' && *q != ';' && !isspace((unsigned char)*q)) while (*q && *q != '/' && *q != ';' && !isspace((unsigned char)*q))
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 == '/')
{ {
/* We have a pattern address; now determine the mask. */ const char *str2 = q+1;
if (*q == '/') 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)
{
if (ipbufpfx)
{ {
str = q + 1; memcpy(ipbuf, str, (int)(q-str));
while (*q && *q != ';' && !isspace((unsigned char)*q)) ipbuf[(int)(q-str)] = 0;
q++; if (ip_addr(ipbuf, (int)(q - str), &pat.mask.addr) != 0)
if (ip_addr(str, (int)(q - str), &pat.mask) != 0)
natural_mask(&pat); natural_mask(&pat);
} }
else else
natural_mask(&pat); natural_mask(&pat);
pat.type = PATTERN_MASK;
/* Add this pattern to our list. */ if (!sortlist_alloc(sortlist, nsort, &pat))
newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
if (!newsort)
return ARES_ENOMEM; return ARES_ENOMEM;
newsort[*nsort] = pat;
*sortlist = newsort;
(*nsort)++;
} }
else 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; return ((size_t)(q - p) > len && !strncmp(p, opt, len)) ? &p[len] : NULL;
} }
#ifndef WIN32 static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat)
static int ip_addr(const char *s, int len, struct in_addr *addr) {
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 *ipbuf, int len, struct in_addr *addr)
{ {
char ipbuf[16];
/* Four octets and three periods yields at most 15 characters. */ /* Four octets and three periods yields at most 15 characters. */
if (len > 15) if (len > 15)
return -1; return -1;
memcpy(ipbuf, s, len);
ipbuf[len] = 0;
addr->s_addr = inet_addr(ipbuf); addr->s_addr = inet_addr(ipbuf);
if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0) 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. * still rely on it.
*/ */
if (IN_CLASSA(addr.s_addr)) 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)) 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 else
pat->mask.s_addr = htonl(IN_CLASSC_NET); pat->mask.addr.s_addr = htonl(IN_CLASSC_NET);
} }
#endif #endif

View File

@ -124,9 +124,17 @@ struct query {
}; };
/* An IP address pattern; matches an IP address X if X & mask == addr */ /* An IP address pattern; matches an IP address X if X & mask == addr */
#define PATTERN_MASK 0x1
#define PATTERN_CIDR 0x2
struct apattern { struct apattern {
struct in_addr addr; struct in_addr addr;
struct in_addr mask; union
{
struct in_addr addr;
unsigned short bits;
} mask;
unsigned short type;
}; };
struct ares_channeldata { struct ares_channeldata {

View File

@ -19,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "bitncmp.h" #include "bitncmp.h"
/* /*