Skip to content
ares_init.c 33.8 KiB
Newer Older
      begin = ++p;
      continue;
    }

    /* This is the part that actually sets the nameserver */
    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);