Commit feec4217 authored by Dominick Meglio's avatar Dominick Meglio
Browse files

Made sortlist support CIDR matching for IPv4

parent 63498284
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
  Changelog for the c-ares project

* April 9

- Made sortlist support CIDR matching for IPv4.

* April 8

- Added preliminary IPv6 support to ares_gethostbyname. Currently, sortlist
+7 −5
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include "ares.h"
#include "ares_private.h"
#include "inet_net_pton.h"
#include "bitncmp.h"

#ifdef WATT32
#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,
                        void *arg)
{
  struct in_addr addr;
  struct in6_addr addr6;
  struct hostent hostent;
  const char *p;
  char *aliases[1] = { NULL };
  char *addrs[2];
  int result = 0;
@@ -333,7 +331,11 @@ static int get_address_index(struct in_addr *addr, struct apattern *sortlist,

  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)
        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;
+56 −21
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -47,6 +51,7 @@
#include <errno.h>
#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)
        {
          /* We have a pattern address; now determine the mask. */
      memcpy(ipbuf, str, (int)(q-str));
      ipbuf[(int)(q-str)] = 0;      
      /* Find the prefix */
      if (*q == '/')
        {
              str = q + 1;
          const char *str2 = q+1;
          while (*q && *q != ';' && !isspace((unsigned char)*q))
            q++;
              if (ip_addr(str, (int)(q - str), &pat.mask) != 0)
          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)
            {
              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
+9 −1
Original line number Diff line number Diff line
@@ -124,9 +124,17 @@ struct query {
};

/* An IP address pattern; matches an IP address X if X & mask == addr */
#define PATTERN_MASK 0x1
#define PATTERN_CIDR 0x2

struct apattern {
  struct in_addr addr;
  struct in_addr mask;
  union
  {
    struct in_addr addr;
    unsigned short bits;
  } mask;
  unsigned short type;
};

struct ares_channeldata {
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include "bitncmp.h"

/*