Exemplo n.º 1
0
static int
gevent_make_sockaddr(char* hostp, int port, int flowinfo, int scope_id, struct sockaddr_in6* sa6) {
    if ( ares_inet_pton(AF_INET, hostp, &((struct sockaddr_in*)sa6)->sin_addr.s_addr) > 0 ) {
        ((struct sockaddr_in*)sa6)->sin_family = AF_INET;
        ((struct sockaddr_in*)sa6)->sin_port = htons(port);
        return sizeof(struct sockaddr_in);
    }
    else if ( ares_inet_pton(AF_INET6, hostp, &sa6->sin6_addr.s6_addr) > 0 ) {
        sa6->sin6_family = AF_INET6;
        sa6->sin6_port = htons(port);
        sa6->sin6_flowinfo = flowinfo;
        sa6->sin6_scope_id = scope_id;
        return sizeof(struct sockaddr_in6);
    }
    return -1;
}
static PyObject *
Channel_func_getnameinfo(Channel *self, PyObject *args)
{
    char *addr;
    int port, flags, length;
    struct in_addr addr4;
    struct in6_addr addr6;
    struct sockaddr *sa;
    struct sockaddr_in sa4;
    struct sockaddr_in6 sa6;
    PyObject *callback;

    CHECK_CHANNEL(self);

    if (!PyArg_ParseTuple(args, "(si)iO:getnameinfo", &addr, &port, &flags, &callback)) {
        return NULL;
    }

    if (!PyCallable_Check(callback)) {
        PyErr_SetString(PyExc_TypeError, "a callable is required");
        return NULL;
    }

    if (port < 0 || port > 65535) {
        PyErr_SetString(PyExc_ValueError, "port must be between 0 and 65535");
        return NULL;
    }

    if (ares_inet_pton(AF_INET, addr, &addr4) == 1) {
        sa4 = uv_ip4_addr(addr, port);
        sa = (struct sockaddr *)&sa4;
        length = sizeof(struct sockaddr_in);
    } else if (ares_inet_pton(AF_INET6, addr, &addr6) == 1) {
        sa6 = uv_ip6_addr(addr, port);
        sa = (struct sockaddr *)&sa6;
        length = sizeof(struct sockaddr_in6);
    } else {
        PyErr_SetString(PyExc_ValueError, "invalid IP address");
        return NULL;
    }

    Py_INCREF(callback);
    ares_getnameinfo(self->channel, sa, length, flags, &nameinfo_cb, (void *)callback);

    Py_RETURN_NONE;
}
struct sockaddr_in6 uv_ip6_addr(const char* ip, int port) {
    struct sockaddr_in6 addr;

    memset(&addr, 0, sizeof(struct sockaddr_in6));

    addr.sin6_family = AF_INET6;
    addr.sin6_port = htons(port);
    ares_inet_pton(AF_INET6, ip, &addr.sin6_addr);

    return addr;
}
static PyObject *
Channel_func_gethostbyaddr(Channel *self, PyObject *args)
{
    char *name;
    int family, length;
    void *address;
    struct in_addr addr4;
    struct in6_addr addr6;
    PyObject *callback;

    CHECK_CHANNEL(self);

    if (!PyArg_ParseTuple(args, "sO:gethostbyaddr", &name, &callback)) {
        return NULL;
    }

    if (!PyCallable_Check(callback)) {
        PyErr_SetString(PyExc_TypeError, "a callable is required");
        return NULL;
    }

    if (ares_inet_pton(AF_INET, name, &addr4) == 1) {
        length = sizeof(struct in_addr);
        address = (void *)&addr4;
        family = AF_INET;
    } else if (ares_inet_pton(AF_INET6, name, &addr6) == 1) {
        length = sizeof(struct in6_addr);
        address = (void *)&addr6;
        family = AF_INET6;
    } else {
        PyErr_SetString(PyExc_ValueError, "invalid IP address");
        return NULL;
    }

    Py_INCREF(callback);
    ares_gethostbyaddr(self->channel, address, length, family, &host_cb, (void *)callback);

    Py_RETURN_NONE;
}
static PyObject *
Channel_func_set_local_ip(Channel *self, PyObject *args)
{
    char *ip;
    struct in_addr addr4;
    struct in6_addr addr6;

    CHECK_CHANNEL(self);

    if (!PyArg_ParseTuple(args, "s:set_local_ip", &ip)) {
        return NULL;
    }

    if (ares_inet_pton(AF_INET, ip, &addr4) == 1) {
        ares_set_local_ip4(self->channel, ntohl(addr4.s_addr));
    } else if (ares_inet_pton(AF_INET6, ip, &addr6) == 1) {
        ares_set_local_ip6(self->channel, addr6.s6_addr);
    } else {
        PyErr_SetString(PyExc_ValueError, "invalid IP address");
        return NULL;
    }

    Py_RETURN_NONE;
}
Exemplo n.º 6
0
/* Incomming string format: host[:port][,host[:port]]... */
int ares_set_servers_csv(ares_channel channel,
                         const char* _csv)
{
  int i;
  char* csv = NULL;
  char* ptr;
  char* start_host;
  long port;
  bool found_port;
  int rv = ARES_SUCCESS;
  struct ares_addr_node *servers = NULL;
  struct ares_addr_node *last = NULL;

  if (ares_library_initialized() != ARES_SUCCESS)
    return ARES_ENOTINITIALIZED;

  if (!channel)
    return ARES_ENODATA;

  ares__destroy_servers_state(channel);

  i = strlen(_csv);
  if (i == 0)
     return ARES_SUCCESS; /* blank all servers */

  csv = malloc(i + 2);
  strcpy(csv, _csv);
  if (csv[i-1] != ',') { /* make parsing easier by ensuring ending ',' */
    csv[i] = ',';
    csv[i+1] = 0;
  }

  start_host = csv;
  found_port = false;
  for (ptr = csv; *ptr; ptr++) {
    if (*ptr == ',') {
      char* pp = ptr - 1;
      struct in_addr in4;
      struct ares_in6_addr in6;
      struct ares_addr_node *s = NULL;

      *ptr = 0; /* null terminate host:port string */
      /* Got an entry..see if port was specified. */
      while (pp > start_host) {
        if (*pp == ':')
          break; /* yes */
        if (!ISDIGIT(*pp)) {
          /* Found end of digits before we found :, so wasn't a port */
          pp = ptr;
          break;
        }
        pp--;
      }
      if ((pp != start_host) && ((pp + 1) < ptr)) {
        /* Found it. */
        found_port = true;
        port = strtol(pp + 1, NULL, 10);
        *pp = 0; /* null terminate host */
      }
      /* resolve host, try ipv4 first, rslt is in network byte order */
      rv = ares_inet_pton(AF_INET, start_host, &in4);
      if (!rv) {
        /* Ok, try IPv6 then */
        rv = ares_inet_pton(AF_INET6, start_host, &in6);
        if (!rv) {
          rv = ARES_EBADSTR;
          goto out;
        }
        /* was ipv6, add new server */
        s = malloc(sizeof(*s));
        if (!s) {
          rv = ARES_ENOMEM;
          goto out;
        }
        s->family = AF_INET6;
        memcpy(&s->addr, &in6, sizeof(struct ares_in6_addr));
      }
      else {
        /* was ipv4, add new server */
        s = malloc(sizeof(*s));
        if (!s) {
          rv = ARES_ENOMEM;
          goto out;
        }
        s->family = AF_INET;
        memcpy(&s->addr, &in4, sizeof(struct in_addr));
      }
      if (s) {
        /* TODO:  Add port to ares_addr_node and assign it here. */

        s->next = NULL;
        if (last) {
          last->next = s;
        }
        else {
          servers = s;
          last = s;
        }
      }

      /* Set up for next one */
      found_port = false;
      start_host = ptr + 1;
    }
  }

  rv = ares_set_servers(channel, servers);

  out:
  if (csv)
    free(csv);
  while (servers) {
    struct ares_addr_node *s = servers;
    servers = servers->next;
    free(s);
  }

  return rv;
}
static int
set_nameservers(Channel *self, PyObject *value)
{
    char *server;
    int i, r, length, ret;
    struct ares_addr_node *servers;
    Bool is_buffer;
    Py_buffer pbuf;
    PyObject *server_list, *item, *data_fast;

    is_buffer = False;
    servers = NULL;
    server_list = value;
    ret = 0;

    if ((data_fast = PySequence_Fast(server_list, "argument 1 must be an iterable")) == NULL) {
        return -1;
    }

    length = PySequence_Fast_GET_SIZE(data_fast);
    if (length > INT_MAX) {
        PyErr_SetString(PyExc_ValueError, "argument 1 is too long");
        Py_DECREF(data_fast);
        return -1;
    }

    if (length == 0) {
        /* c-ares doesn't do anything */
        return 0;
    }

    servers = PyMem_Malloc(sizeof(struct ares_addr_node) * length);
    if (!servers) {
        PyErr_NoMemory();
        ret = -1;
        goto end;
    }

    for (i = 0; i < length; i++) {
        item = PySequence_Fast_GET_ITEM(data_fast, i);
        if (!item || !PyArg_Parse(item, "s*;args contains a non-string value", &pbuf)) {
            Py_XDECREF(item);
            goto end;
        }
        Py_DECREF(item);
        server = pbuf.buf;

        if (ares_inet_pton(AF_INET, server, &servers[i].addr.addr4) == 1) {
            servers[i].family = AF_INET;
        } else if (ares_inet_pton(AF_INET6, server, &servers[i].addr.addr6) == 1) {
            servers[i].family = AF_INET6;
        } else {
            PyErr_SetString(PyExc_ValueError, "invalid IP address");
            PyBuffer_Release(&pbuf);
            ret = -1;
            goto end;
        }

        PyBuffer_Release(&pbuf);

        if (i > 0) {
            servers[i-1].next = &servers[i];
        }

    }

    if (servers) {
        servers[length-1].next = NULL;
    }

    r = ares_set_servers(self->channel, servers);
    if (r != ARES_SUCCESS) {
        RAISE_ARES_EXCEPTION(r);
        ret = -1;
    }

end:
    PyMem_Free(servers);
    return ret;
}
Exemplo n.º 8
0
/* IPv6 addresses with ports require square brackets [fe80::1%lo0]:53 */
static int set_servers_csv(ares_channel channel,
                           const char* _csv, int use_port)
{
  size_t i;
  char* csv = NULL;
  char* ptr;
  char* start_host;
  int cc = 0;
  int rv = ARES_SUCCESS;
  struct ares_addr_port_node *servers = NULL;
  struct ares_addr_port_node *last = NULL;

  if (ares_library_initialized() != ARES_SUCCESS)
    return ARES_ENOTINITIALIZED;  /* LCOV_EXCL_LINE: n/a on non-WinSock */

  if (!channel)
    return ARES_ENODATA;

  ares__destroy_servers_state(channel);

  i = strlen(_csv);
  if (i == 0)
     return ARES_SUCCESS; /* blank all servers */

  csv = ares_malloc(i + 2);
  if (!csv)
    return ARES_ENOMEM;

  strcpy(csv, _csv);
  if (csv[i-1] != ',') { /* make parsing easier by ensuring ending ',' */
    csv[i] = ',';
    csv[i+1] = 0;
  }

  start_host = csv;
  for (ptr = csv; *ptr; ptr++) {
    if (*ptr == ':') {
      /* count colons to determine if we have an IPv6 number or IPv4 with
         port */
      cc++;
    }
    else if (*ptr == '[') {
      /* move start_host if an open square bracket is found wrapping an IPv6
         address */
      start_host = ptr + 1;
    }
    else if (*ptr == ',') {
      char* pp = ptr - 1;
      char* p = ptr;
      int port = 0;
      struct in_addr in4;
      struct ares_in6_addr in6;
      struct ares_addr_port_node *s = NULL;

      *ptr = 0; /* null terminate host:port string */
      /* Got an entry..see if the port was specified. */
      if (cc > 0) {
        while (pp > start_host) {
          /* a single close square bracket followed by a colon, ']:' indicates
             an IPv6 address with port */
          if ((*pp == ']') && (*p == ':'))
            break; /* found port */
          /* a single colon, ':' indicates an IPv4 address with port */
          if ((*pp == ':') && (cc == 1))
            break; /* found port */
          if (!(ISDIGIT(*pp) || (*pp == ':'))) {
            /* Found end of digits before we found :, so wasn't a port */
            /* must allow ':' for IPv6 case of ']:' indicates we found a port */
            pp = p = ptr;
            break;
          }
          pp--;
          p--;
        }
        if ((pp != start_host) && ((pp + 1) < ptr)) {
          /* Found it. Parse over the port number */
          /* when an IPv6 address is wrapped with square brackets the port
             starts at pp + 2 */
          if (*pp == ']')
            p++; /* move p before ':' */
          /* p will point to the start of the port */
          port = (int)strtol(p, NULL, 10);
          *pp = 0; /* null terminate host */
        }
      }
      /* resolve host, try ipv4 first, rslt is in network byte order */
      rv = ares_inet_pton(AF_INET, start_host, &in4);
      if (!rv) {
        /* Ok, try IPv6 then */
        rv = ares_inet_pton(AF_INET6, start_host, &in6);
        if (!rv) {
          rv = ARES_EBADSTR;
          goto out;
        }
        /* was ipv6, add new server */
        s = ares_malloc(sizeof(*s));
        if (!s) {
          rv = ARES_ENOMEM;
          goto out;
        }
        s->family = AF_INET6;
        memcpy(&s->addr, &in6, sizeof(struct ares_in6_addr));
      }
      else {
        /* was ipv4, add new server */
        s = ares_malloc(sizeof(*s));
        if (!s) {
          rv = ARES_ENOMEM;
          goto out;
        }
        s->family = AF_INET;
        memcpy(&s->addr, &in4, sizeof(struct in_addr));
      }
      if (s) {
        s->udp_port = use_port ? port: 0;
        s->tcp_port = s->udp_port;
        s->next = NULL;
        if (last) {
          last->next = s;
          /* need to move last to maintain the linked list */
          last = last->next;
        }
        else {
          servers = s;
          last = s;
        }
      }

      /* Set up for next one */
      start_host = ptr + 1;
      cc = 0;
    }
  }

  rv = ares_set_servers_ports(channel, servers);

  out:
  if (csv)
    ares_free(csv);
  while (servers) {
    struct ares_addr_port_node *s = servers;
    servers = servers->next;
    ares_free(s);
  }

  return rv;
}
Exemplo n.º 9
0
int ares__get_hostent(FILE *fp, int family, struct hostent **host)
{
  char *line = NULL, *p, *q, **alias;
  char *txtaddr, *txthost, *txtalias;
  int status;
  size_t addrlen, linesize, naliases;
  struct ares_addr addr;
  struct hostent *hostent = NULL;

  *host = NULL; /* Assume failure */

  /* Validate family */
  switch (family) {
    case AF_INET:
    case AF_INET6:
    case AF_UNSPEC:
      break;
    default:
      return ARES_EBADFAMILY;
  }

  while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
    {

      /* Trim line comment. */
      p = line;
      while (*p && (*p != '#'))
        p++;
      *p = '\0';

      /* Trim trailing whitespace. */
      q = p - 1;
      while ((q >= line) && ISSPACE(*q))
        q--;
      *++q = '\0';

      /* Skip leading whitespace. */
      p = line;
      while (*p && ISSPACE(*p))
        p++;
      if (!*p)
        /* Ignore line if empty. */
        continue;

      /* Pointer to start of IPv4 or IPv6 address part. */
      txtaddr = p;

      /* Advance past address part. */
      while (*p && !ISSPACE(*p))
        p++;
      if (!*p)
        /* Ignore line if reached end of line. */
        continue;

      /* Null terminate address part. */
      *p = '\0';

      /* Advance to host name */
      p++;
      while (*p && ISSPACE(*p))
        p++;
      if (!*p)
        /* Ignore line if reached end of line. */
        continue;

      /* Pointer to start of host name. */
      txthost = p;

      /* Advance past host name. */
      while (*p && !ISSPACE(*p))
        p++;

      /* Pointer to start of first alias. */
      txtalias = NULL;
      if (*p)
        {
          q = p + 1;
          while (*q && ISSPACE(*q))
            q++;
          if (*q)
            txtalias = q;
        }

      /* Null terminate host name. */
      *p = '\0';

      /* find out number of aliases. */
      naliases = 0;
      if (txtalias)
        {
          p = txtalias;
          while (*p)
            {
              while (*p && !ISSPACE(*p))
                p++;
              while (*p && ISSPACE(*p))
                p++;
              naliases++;
            }
        }

      /* Convert address string to network address for the requested family. */
      addrlen = 0;
      addr.family = AF_UNSPEC;
      addr.addrV4.s_addr = INADDR_NONE;
      if ((family == AF_INET) || (family == AF_UNSPEC))
        {
          addr.addrV4.s_addr = inet_addr(txtaddr);
          if (addr.addrV4.s_addr != INADDR_NONE)
            {
              /* Actual network address family and length. */
              addr.family = AF_INET;
              addrlen = sizeof(addr.addrV4);
            }
        }
      if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen)))
        {
          if (ares_inet_pton(AF_INET6, txtaddr, &addr.addrV6) > 0)
            {
              /* Actual network address family and length. */
              addr.family = AF_INET6;
              addrlen = sizeof(addr.addrV6);
            }
        }
      if (!addrlen)
        /* Ignore line if invalid address string for the requested family. */
        continue;

      /*
      ** Actual address family possible values are AF_INET and AF_INET6 only.
      */

      /* Allocate memory for the hostent structure. */
      hostent = malloc(sizeof(struct hostent));
      if (!hostent)
        break;

      /* Initialize fields for out of memory condition. */
      hostent->h_aliases = NULL;
      hostent->h_addr_list = NULL;

      /* Copy official host name. */
      hostent->h_name = strdup(txthost);
      if (!hostent->h_name)
        break;

      /* Copy network address. */
      hostent->h_addr_list = malloc(2 * sizeof(char *));
      if (!hostent->h_addr_list)
        break;
      hostent->h_addr_list[1] = NULL;
      hostent->h_addr_list[0] = malloc(addrlen);
      if (!hostent->h_addr_list[0])
        break;
      if (addr.family == AF_INET)
        memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(addr.addrV4));
      else
        memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));

      /* Copy aliases. */
      hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
      if (!hostent->h_aliases)
        break;
      alias = hostent->h_aliases;
      while (naliases)
        *(alias + naliases--) = NULL;
      *alias = NULL;
      while (txtalias)
        {
          p = txtalias;
          while (*p && !ISSPACE(*p))
            p++;
          q = p;
          while (*q && ISSPACE(*q))
            q++;
          *p = '\0';
          if ((*alias = strdup(txtalias)) == NULL)
            break;
          alias++;
          txtalias = *q ? q : NULL;
        }
      if (txtalias)
        /* Alias memory allocation failure. */
        break;

      /* Copy actual network address family and length. */
      hostent->h_addrtype = addr.family;
      hostent->h_length = (int)addrlen;

      /* Free line buffer. */
      free(line);

      /* Return hostent successfully */
      *host = hostent;
      return ARES_SUCCESS;

    }

  /* If allocated, free line buffer. */
  if (line)
    free(line);

  if (status == ARES_SUCCESS)
    {
      /* Memory allocation failure; clean up. */
      if (hostent)
        {
          if (hostent->h_name)
            free((char *) hostent->h_name);
          if (hostent->h_aliases)
            {
              for (alias = hostent->h_aliases; *alias; alias++)
                free(*alias);
              free(hostent->h_aliases);
            }
          if (hostent->h_addr_list)
            {
              if (hostent->h_addr_list[0])
                free(hostent->h_addr_list[0]);
              free(hostent->h_addr_list);
            }
          free(hostent);
        }
      return ARES_ENOMEM;
    }

  return status;
}
Exemplo n.º 10
0
int main(int argc, char **argv)
{
  ares_channel channel;
  int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
  int status, nfds, count;
  struct ares_options options;
  struct hostent *hostent;
  fd_set read_fds, write_fds;
  struct timeval *tvp, tv;
  struct ares_addr_node *srvr, *servers = NULL;

#ifdef USE_WINSOCK
  WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
  WSADATA wsaData;
  WSAStartup(wVersionRequested, &wsaData);
#endif

  status = ares_library_init(ARES_LIB_INIT_ALL);
  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
      return 1;
    }

  options.flags = ARES_FLAG_NOCHECKRESP;
  options.servers = NULL;
  options.nservers = 0;
  while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
    {
      switch (c)
        {
        case 'd':
#ifdef WATT32
          dbug_init();
#endif
          break;

        case 'f':
          /* Add a flag. */
          for (i = 0; i < nflags; i++)
            {
              if (strcmp(flags[i].name, optarg) == 0)
                break;
            }
          if (i < nflags)
            options.flags |= flags[i].value;
          else
            usage();
          break;

        case 's':
          /* User-specified name servers override default ones. */
          srvr = malloc(sizeof(struct ares_addr_node));
          if (!srvr)
            {
              fprintf(stderr, "Out of memory!\n");
              destroy_addr_list(servers);
              return 1;
            }
          append_addr_list(&servers, srvr);
          if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
            srvr->family = AF_INET;
          else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0)
            srvr->family = AF_INET6;
          else
            {
              hostent = gethostbyname(optarg);
              if (!hostent)
                {
                  fprintf(stderr, "adig: server %s not found.\n", optarg);
                  destroy_addr_list(servers);
                  return 1;
                }
              switch (hostent->h_addrtype)
                {
                  case AF_INET:
                    srvr->family = AF_INET;
                    memcpy(&srvr->addr.addr4, hostent->h_addr,
                           sizeof(srvr->addr.addr4));
                    break;
                  case AF_INET6:
                    srvr->family = AF_INET6;
                    memcpy(&srvr->addr.addr6, hostent->h_addr,
                           sizeof(srvr->addr.addr6));
                    break;
                  default:
                    fprintf(stderr,
                      "adig: server %s unsupported address family.\n", optarg);
                    destroy_addr_list(servers);
                    return 1;
                }
            }
          /* Notice that calling ares_init_options() without servers in the
           * options struct and with ARES_OPT_SERVERS set simultaneously in
           * the options mask, results in an initialization with no servers.
           * When alternative name servers have been specified these are set
           * later calling ares_set_servers() overriding any existing server
           * configuration. To prevent initial configuration with default
           * servers that will be discarded later, ARES_OPT_SERVERS is set.
           * If this flag is not set here the result shall be the same but
           * ares_init_options() will do needless work. */
          optmask |= ARES_OPT_SERVERS;
          break;

        case 'c':
          /* Set the query class. */
          for (i = 0; i < nclasses; i++)
            {
              if (strcasecmp(classes[i].name, optarg) == 0)
                break;
            }
          if (i < nclasses)
            dnsclass = classes[i].value;
          else
            usage();
          break;

        case 't':
          /* Set the query type. */
          for (i = 0; i < ntypes; i++)
            {
              if (strcasecmp(types[i].name, optarg) == 0)
                break;
            }
          if (i < ntypes)
            type = types[i].value;
          else
            usage();
          break;

        case 'T':
          /* Set the TCP port number. */
          if (!ISDIGIT(*optarg))
            usage();
          options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
          optmask |= ARES_OPT_TCP_PORT;
          break;

        case 'U':
          /* Set the UDP port number. */
          if (!ISDIGIT(*optarg))
            usage();
          options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
          optmask |= ARES_OPT_UDP_PORT;
          break;
        }
    }
  argc -= optind;
  argv += optind;
  if (argc == 0)
    usage();

  status = ares_init_options(&channel, &options, optmask);

  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_init_options: %s\n",
              ares_strerror(status));
      return 1;
    }

  if(servers)
    {
      status = ares_set_servers(channel, servers);
      destroy_addr_list(servers);
      if (status != ARES_SUCCESS)
        {
          fprintf(stderr, "ares_init_options: %s\n",
                  ares_strerror(status));
          return 1;
        }
    }

  /* Initiate the queries, one per command-line argument.  If there is
   * only one query to do, supply NULL as the callback argument;
   * otherwise, supply the query name as an argument so we can
   * distinguish responses for the user when printing them out.
   */
  if (argc == 1)
    ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
  else
    {
      for (; *argv; argv++)
        ares_query(channel, *argv, dnsclass, type, callback, *argv);
    }

  /* Wait for all queries to complete. */
  for (;;)
    {
      FD_ZERO(&read_fds);
      FD_ZERO(&write_fds);
      nfds = ares_fds(channel, &read_fds, &write_fds);
      if (nfds == 0)
        break;
      tvp = ares_timeout(channel, NULL, &tv);
      count = select(nfds, &read_fds, &write_fds, NULL, tvp);
      if (count < 0 && SOCKERRNO != EINVAL)
        {
          perror("select");
          return 1;
        }
      ares_process(channel, &read_fds, &write_fds);
    }

  ares_destroy(channel);

  ares_library_cleanup();

#ifdef USE_WINSOCK
  WSACleanup();
#endif

  return 0;
}
Exemplo n.º 11
0
int main(int argc, char **argv)
{
  struct ares_options options;
  int optmask = 0;
  ares_channel channel;
  int status, nfds, c, addr_family = AF_INET;
  fd_set read_fds, write_fds;
  struct timeval *tvp, tv;
  struct in_addr addr4;
  struct ares_in6_addr addr6;

#ifdef USE_WINSOCK
  WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
  WSADATA wsaData;
  WSAStartup(wVersionRequested, &wsaData);
#endif

  memset(&options, 0, sizeof(options));

  status = ares_library_init(ARES_LIB_INIT_ALL);
  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
      return 1;
    }

  while ((c = ares_getopt(argc,argv,"dt:hs:")) != -1)
    {
      switch (c)
        {
        case 'd':
#ifdef WATT32
          dbug_init();
#endif
          break;
        case 's':
          optmask |= ARES_OPT_DOMAINS;
          options.ndomains++;
          options.domains = realloc(options.domains,
                                    options.ndomains * sizeof(char *));
          options.domains[options.ndomains - 1] = strdup(optarg);
          break;
        case 't':
          if (!strcasecmp(optarg,"a"))
            addr_family = AF_INET;
          else if (!strcasecmp(optarg,"aaaa"))
            addr_family = AF_INET6;
          else if (!strcasecmp(optarg,"u"))
            addr_family = AF_UNSPEC;
          else
            usage();
          break;
        case 'h':
        default:
          usage();
          break;
        }
    }

  argc -= optind;
  argv += optind;
  if (argc < 1)
    usage();

  status = ares_init_options(&channel, &options, optmask);
  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_init: %s\n", ares_strerror(status));
      return 1;
    }

  /* Initiate the queries, one per command-line argument. */
  for ( ; *argv; argv++)
    {
      if (ares_inet_pton(AF_INET, *argv, &addr4) == 1)
        {
          ares_gethostbyaddr(channel, &addr4, sizeof(addr4), AF_INET, callback,
                             *argv);
        }
      else if (ares_inet_pton(AF_INET6, *argv, &addr6) == 1)
        {
          ares_gethostbyaddr(channel, &addr6, sizeof(addr6), AF_INET6, callback,
                             *argv);
        }
      else
        {
          ares_gethostbyname(channel, *argv, addr_family, callback, *argv);
        }
    }

  /* Wait for all queries to complete. */
  for (;;)
    {
      int res;
      FD_ZERO(&read_fds);
      FD_ZERO(&write_fds);
      nfds = ares_fds(channel, &read_fds, &write_fds);
      if (nfds == 0)
        break;
      tvp = ares_timeout(channel, NULL, &tv);
      res = select(nfds, &read_fds, &write_fds, NULL, tvp);
      if (-1 == res)
        break;
      ares_process(channel, &read_fds, &write_fds);
    }

  ares_destroy(channel);

  ares_library_cleanup();

#ifdef USE_WINSOCK
  WSACleanup();
#endif

  return 0;
}
Exemplo n.º 12
0
static int config_nameserver(struct server_state **servers, int *nservers,
                             char *str)
{
  struct ares_addr host;
  struct server_state *newserv;
  char *p, *txtaddr;
  /* On Windows, there may be more than one nameserver specified in the same
   * registry key, so we parse input as a space or comma seperated list.
   */
  for (p = str; p;)
    {
      /* Skip whitespace and commas. */
      while (*p && (ISSPACE(*p) || (*p == ',')))
        p++;
      if (!*p)
        /* No more input, done. */
        break;

      /* Pointer to start of IPv4 or IPv6 address part. */
      txtaddr = p;

      /* Advance past this address. */
      while (*p && !ISSPACE(*p) && (*p != ','))
        p++;
      if (*p)
        /* Null terminate this address. */
        *p++ = '\0';
      else
        /* Reached end of input, done when this address is processed. */
        p = NULL;

      /* Convert textual address to binary format. */
      if (ares_inet_pton(AF_INET, txtaddr, &host.addrV4) == 1)
        host.family = AF_INET;
      else if (ares_inet_pton(AF_INET6, txtaddr, &host.addrV6) == 1)
        host.family = AF_INET6;
      else
        continue;

      /* Resize servers state array. */
      newserv = realloc(*servers, (*nservers + 1) *
                        sizeof(struct server_state));
      if (!newserv)
        return ARES_ENOMEM;

      /* Store address data. */
      newserv[*nservers].addr.family = host.family;
      if (host.family == AF_INET)
        memcpy(&newserv[*nservers].addr.addrV4, &host.addrV4,
               sizeof(host.addrV4));
      else
        memcpy(&newserv[*nservers].addr.addrV6, &host.addrV6,
               sizeof(host.addrV6));

      /* Update arguments. */
      *servers = newserv;
      *nservers += 1;
    }

  return ARES_SUCCESS;
}
Exemplo n.º 13
0
/* If the name looks like an IP address, fake up a host entry, end the
 * query immediately, and return true.  Otherwise return false.
 */
static int fake_hostent(const char *name, int family,
                        ares_host_callback callback, void *arg)
{
  struct hostent hostent;
  char *aliases[1] = { NULL };
  char *addrs[2];
  int result = 0;
  struct in_addr in;
  struct ares_in6_addr in6;

  if (family == AF_INET || family == AF_INET6)
    {
      /* It only looks like an IP address if it's all numbers and dots. */
      int numdots = 0, valid = 1;
      const char *p;
      for (p = name; *p; p++)
        {
          if (!ISDIGIT(*p) && *p != '.') {
            valid = 0;
            break;
          } else if (*p == '.') {
            numdots++;
          }
        }

      /* if we don't have 3 dots, it is illegal
       * (although inet_addr doesn't think so).
       */
      if (numdots != 3 || !valid)
        result = 0;
      else
        result = ((in.s_addr = inet_addr(name)) == INADDR_NONE ? 0 : 1);

      if (result)
        family = AF_INET;
    }
  if (family == AF_INET6)
    result = (ares_inet_pton(AF_INET6, name, &in6) < 1 ? 0 : 1);

  if (!result)
    return 0;

  if (family == AF_INET)
    {
      hostent.h_length = (int)sizeof(struct in_addr);
      addrs[0] = (char *)&in;
    }
  else if (family == AF_INET6)
    {
      hostent.h_length = (int)sizeof(struct ares_in6_addr);
      addrs[0] = (char *)&in6;
    }
  /* Duplicate the name, to avoid a constness violation. */
  hostent.h_name = ares_strdup(name);
  if (!hostent.h_name)
    {
      callback(arg, ARES_ENOMEM, 0, NULL);
      return 1;
    }

  /* Fill in the rest of the host structure and terminate the query. */
  addrs[1] = NULL;
  hostent.h_aliases = aliases;
  hostent.h_addrtype = aresx_sitoss(family);
  hostent.h_addr_list = addrs;
  callback(arg, ARES_SUCCESS, 0, &hostent);

  ares_free((char *)(hostent.h_name));
  return 1;
}
Exemplo n.º 14
0
int main(int argc, char **argv)
{
  ares_channel channel;
  int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
  int status, nfds, count;
  struct ares_options options;
  struct hostent *hostent;
  fd_set read_fds, write_fds;
  struct timeval *tvp, tv;

#ifdef USE_WINSOCK
  WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
  WSADATA wsaData;
  WSAStartup(wVersionRequested, &wsaData);
#endif

  options.flags = ARES_FLAG_NOCHECKRESP;
  options.servers = NULL;
  options.nservers = 0;
  while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
    {
      switch (c)
        {
        case 'd':
#ifdef WATT32
          dbug_init();
#endif
          break;

        case 'f':
          /* Add a flag. */
          for (i = 0; i < nflags; i++)
            {
              if (strcmp(flags[i].name, optarg) == 0)
                break;
            }
          if (i == nflags)
            usage();
          options.flags |= flags[i].value;
          break;

        case 's':
          /* Add a server, and specify servers in the option mask. */
          if (ares_inet_pton(AF_INET, optarg, &inaddr) <= 0)
            {
              hostent = gethostbyname(optarg);
              if (!hostent || hostent->h_addrtype != AF_INET)
                {
                  fprintf(stderr, "adig: server %s not found.\n", optarg);
                  return 1;
                }
              memcpy(&inaddr, hostent->h_addr, sizeof(struct in_addr));
            }
          options.servers = realloc(options.servers, (options.nservers + 1)
                                    * sizeof(struct in_addr));
          if (!options.servers)
            {
              fprintf(stderr, "Out of memory!\n");
              return 1;
            }
          memcpy(&options.servers[options.nservers], &inaddr,
                 sizeof(struct in_addr));
          options.nservers++;
          optmask |= ARES_OPT_SERVERS;
          break;

        case 'c':
          /* Set the query class. */
          for (i = 0; i < nclasses; i++)
            {
              if (strcasecmp(classes[i].name, optarg) == 0)
                break;
            }
          if (i == nclasses)
            usage();
          dnsclass = classes[i].value;
          break;

        case 't':
          /* Set the query type. */
          for (i = 0; i < ntypes; i++)
            {
              if (strcasecmp(types[i].name, optarg) == 0)
                break;
            }
          if (i == ntypes)
            usage();
          type = types[i].value;
          break;

        case 'T':
          /* Set the TCP port number. */
          if (!ISDIGIT(*optarg))
            usage();
          options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
          optmask |= ARES_OPT_TCP_PORT;
          break;

        case 'U':
          /* Set the UDP port number. */
          if (!ISDIGIT(*optarg))
            usage();
          options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
          optmask |= ARES_OPT_UDP_PORT;
          break;
        }
    }
  argc -= optind;
  argv += optind;
  if (argc == 0)
    usage();

  status = ares_init_options(&channel, &options, optmask);

  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_init_options: %s\n",
              ares_strerror(status));
      return 1;
    }

  /* Initiate the queries, one per command-line argument.  If there is
   * only one query to do, supply NULL as the callback argument;
   * otherwise, supply the query name as an argument so we can
   * distinguish responses for the user when printing them out.
   */
  if (argc == 1)
    ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
  else
    {
      for (; *argv; argv++)
        ares_query(channel, *argv, dnsclass, type, callback, *argv);
    }

  /* Wait for all queries to complete. */
  while (1)
    {
      FD_ZERO(&read_fds);
      FD_ZERO(&write_fds);
      nfds = ares_fds(channel, &read_fds, &write_fds);
      if (nfds == 0)
        break;
      tvp = ares_timeout(channel, NULL, &tv);
      count = select(nfds, &read_fds, &write_fds, NULL, tvp);
      if (count < 0 && SOCKERRNO != EINVAL)
        {
          perror("select");
          return 1;
        }
      ares_process(channel, &read_fds, &write_fds);
    }

  ares_destroy(channel);

#ifdef USE_WINSOCK
  WSACleanup();
#endif

  return 0;
}