Skip to content
ares_init.c 35.2 KiB
Newer Older
    addr.s_addr = inet_addr(begin);
    if (addr.s_addr == INADDR_NONE)
      continue;
    newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state));
    if (!newserv)
      return ARES_ENOMEM;
    newserv[*nservers].addr = addr;
    *servers = newserv;
    (*nservers)++;
  /* Add a nameserver entry, if this is a valid address. */
  addr.s_addr = inet_addr(str);
  if (addr.s_addr == INADDR_NONE)
    return ARES_SUCCESS;
  newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state));
  if (!newserv)
    return ARES_ENOMEM;
  newserv[*nservers].addr = addr;
  *servers = newserv;
  (*nservers)++;
static int config_sortlist(struct apattern **sortlist, int *nsort,
Daniel Stenberg's avatar
Daniel Stenberg committed
                           const char *str)
  const char *q;

  /* Add sortlist entries. */
  while (*str && *str != ';')
    {
      int bits;
      char ipbuf[16], ipbufpfx[32];
      /* Find just the IP */
      while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
Daniel Stenberg's avatar
Daniel Stenberg committed
        q++;
      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(*q))
            q++;
          memcpy(ipbufpfx, str, (int)(q-str));
          ipbufpfx[(int)(q-str)] = '\0';
      /* Lets see if it is CIDR */
      if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx ? ipbufpfx : ipbuf,
                                     &pat.addr.addr6,
                                     sizeof(pat.addr.addr6))) > 0)
        {
          pat.type = PATTERN_CIDR;
Yang Tse's avatar
Yang Tse committed
          pat.mask.bits = (unsigned short)bits;
          pat.family = AF_INET6;
          if (!sortlist_alloc(sortlist, nsort, &pat))
            return ARES_ENOMEM;
        }
      if (ipbufpfx &&
          (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addr.addr4,
        {
          pat.type = PATTERN_CIDR;
Yang Tse's avatar
Yang Tse committed
          pat.mask.bits = (unsigned short)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.addr4) == 0)
Daniel Stenberg's avatar
Daniel Stenberg committed
        {
Daniel Stenberg's avatar
Daniel Stenberg committed
            {
              memcpy(ipbuf, str, (int)(q-str));
              ipbuf[(int)(q-str)] = '\0';
              if (ip_addr(ipbuf, (int)(q - str), &pat.mask.addr.addr4) != 0)
Daniel Stenberg's avatar
Daniel Stenberg committed
                natural_mask(&pat);
            }
          else
            natural_mask(&pat);
          if (!sortlist_alloc(sortlist, nsort, &pat))
Daniel Stenberg's avatar
Daniel Stenberg committed
            return ARES_ENOMEM;
        }
Daniel Stenberg's avatar
Daniel Stenberg committed
        {
          while (*q && *q != ';' && !ISSPACE(*q))
Daniel Stenberg's avatar
Daniel Stenberg committed
            q++;
        }
      while (ISSPACE(*str))
Daniel Stenberg's avatar
Daniel Stenberg committed
        str++;

static int set_search(ares_channel channel, const char *str)
{
  int n;
  const char *p, *q;

  if(channel->ndomains != -1) {
    /* if we already have some domains present, free them first */
    for(n=0; n < channel->ndomains; n++)
      free(channel->domains[n]);
    free(channel->domains);
    channel->domains = NULL;
  /* Count the domains given. */
  n = 0;
  p = str;
  while (*p)
    {
      while (*p && !ISSPACE(*p))
Daniel Stenberg's avatar
Daniel Stenberg committed
        p++;
      while (ISSPACE(*p))
Daniel Stenberg's avatar
Daniel Stenberg committed
        p++;
  if (!n)
    {
      channel->ndomains = 0;
      return ARES_SUCCESS;
    }

  channel->domains = malloc(n * sizeof(char *));
  if (!channel->domains)
    return ARES_ENOMEM;

  /* Now copy the domains. */
  n = 0;
  p = str;
  while (*p)
    {
      channel->ndomains = n;
      q = p;
      while (*q && !ISSPACE(*q))
Daniel Stenberg's avatar
Daniel Stenberg committed
        q++;
      channel->domains[n] = malloc(q - p + 1);
      if (!channel->domains[n])
Daniel Stenberg's avatar
Daniel Stenberg committed
        return ARES_ENOMEM;
      memcpy(channel->domains[n], p, q - p);
      channel->domains[n][q - p] = 0;
      p = q;
      while (ISSPACE(*p))
Daniel Stenberg's avatar
Daniel Stenberg committed
        p++;
      n++;
    }
  channel->ndomains = n;

  return ARES_SUCCESS;
}

static int set_options(ares_channel channel, const char *str)
{
  const char *p, *q, *val;

  p = str;
  while (*p)
    {
      q = p;
      while (*q && !ISSPACE(*q))
Daniel Stenberg's avatar
Daniel Stenberg committed
        q++;
      val = try_option(p, q, "ndots:");
      if (val && channel->ndots == -1)
Daniel Stenberg's avatar
Daniel Stenberg committed
        channel->ndots = atoi(val);
      val = try_option(p, q, "retrans:");
      if (val && channel->timeout == -1)
Daniel Stenberg's avatar
Daniel Stenberg committed
        channel->timeout = atoi(val);
      val = try_option(p, q, "retry:");
      if (val && channel->tries == -1)
Daniel Stenberg's avatar
Daniel Stenberg committed
        channel->tries = atoi(val);
      while (ISSPACE(*p))
Daniel Stenberg's avatar
Daniel Stenberg committed
        p++;
static char *try_config(char *s, const char *opt)
  if (strncmp(s, opt, len) != 0 || !ISSPACE(s[len]))
    return NULL;
  s += len;
  while (ISSPACE(*s))
static const char *try_option(const char *p, const char *q, const char *opt)
{
  size_t len = strlen(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;
}

static int ip_addr(const char *ipbuf, int len, struct in_addr *addr)
{

  /* Four octets and three periods yields at most 15 characters. */
  if (len > 15)
    return -1;

  addr->s_addr = inet_addr(ipbuf);
  if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
    return -1;
  return 0;
}

static void natural_mask(struct apattern *pat)
{
  struct in_addr addr;

  /* Store a host-byte-order copy of pat in a struct in_addr.  Icky,
   * but portable.
   */
  addr.s_addr = ntohl(pat->addr.addr4.s_addr);

  /* This is out of date in the CIDR world, but some people might
   * still rely on it.
   */
  if (IN_CLASSA(addr.s_addr))
    pat->mask.addr.addr4.s_addr = htonl(IN_CLASSA_NET);
  else if (IN_CLASSB(addr.s_addr))
    pat->mask.addr.addr4.s_addr = htonl(IN_CLASSB_NET);
    pat->mask.addr.addr4.s_addr = htonl(IN_CLASSC_NET);
/* initialize an rc4 key. If possible a cryptographically secure random key
   is generated using a suitable function (for example win32's RtlGenRandom as
   described in
   http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
   otherwise the code defaults to cross-platform albeit less secure mechanism
   using rand
*/
static void randomize_key(unsigned char* key,int key_data_len)
{
  int randomized = 0;
#ifdef WIN32
  HMODULE lib=LoadLibrary("ADVAPI32.DLL");
  if (lib) {
    BOOLEAN (APIENTRY *pfn)(void*, ULONG) =
      (BOOLEAN (APIENTRY *)(void*,ULONG))GetProcAddress(lib,"SystemFunction036");
    if (pfn && pfn(key,key_data_len) )
      randomized = 1;

    FreeLibrary(lib);
  }
#endif

  if ( !randomized ) {
    int counter;
    for (counter=0;counter<key_data_len;counter++)
      key[counter]=rand() % 256;
  }
}

static void init_id_key(rc4_key* key,int key_data_len)
{
  unsigned char index1;
  unsigned char index2;
  unsigned char* state;
  short counter;
  unsigned char *key_data_ptr = 0;

  key_data_ptr = calloc(1,key_data_len);
  randomize_key(key->state,key_data_len);
  state = &key->state[0];
  for(counter = 0; counter < 256; counter++)
        state[counter] = counter;
  key->x = 0;
  key->y = 0;
  index1 = 0;
  index2 = 0;
  for(counter = 0; counter < 256; counter++)
  {
    index2 = (key_data_ptr[index1] + state[counter] +
              index2) % 256;
    ARES_SWAP_BYTE(&state[counter], &state[index2]);

    index1 = (index1 + 1) % key_data_len;
  }
  free(key_data_ptr);

}

short ares__generate_new_id(rc4_key* key)
{
  short r;
  ares__rc4(key, (unsigned char *)&r, sizeof(r));
  return r;
}