예제 #1
0
파일: dnsparser.c 프로젝트: GNUnet/gnunet
/**
 * Check if a label in UTF-8 format can be coded into valid IDNA.
 * This can fail if the ASCII-conversion becomes longer than 253 characters.
 *
 * @param name name to check (UTF-8 string)
 * @return #GNUNET_OK if the label can be converted to IDNA,
 *         #GNUNET_SYSERR if the label is not valid for DNS names
 */
int
GNUNET_DNSPARSER_check_name (const char *name)
{
  char *ldup;
  char *output;
  size_t slen;
  char *tok;

  ldup = GNUNET_strdup (name);
  for (tok = strtok (ldup, "."); NULL != tok; tok = strtok (NULL, "."))
    if (GNUNET_OK !=
	GNUNET_DNSPARSER_check_label (tok))
    {
      GNUNET_free (ldup);
      return GNUNET_SYSERR;
    }
  GNUNET_free (ldup);
  if (IDNA_SUCCESS !=
      idna_to_ascii_8z (name, &output, IDNA_ALLOW_UNASSIGNED))
    return GNUNET_SYSERR;
  slen = strlen (output);
#if WINDOWS
  idn_free (output);
#else
  free (output);
#endif
  return (slen > 253) ? GNUNET_SYSERR : GNUNET_OK;
}
예제 #2
0
wxString CControlSocket::ConvertDomainName(wxString const& domain)
{
#ifdef __WXMSW__
	int len = IdnToAscii(IDN_ALLOW_UNASSIGNED, domain, domain.size() + 1, 0, 0);
	if( !len ) {
		LogMessage(MessageType::Debug_Warning, _T("Could not convert domain name"));
		return domain;
	}

	wchar_t* output = new wchar_t[len];
	int res = IdnToAscii(IDN_ALLOW_UNASSIGNED, domain, domain.size() + 1, output, len);
	if( !res ) {
		LogMessage(MessageType::Debug_Warning, _T("Could not convert domain name"));
		return domain;
	}

	wxString ret(output);
	delete [] output;
	return ret;
#else

	wxScopedCharBuffer const utf8 = domain.utf8_str();

	char *output = 0;
	if (idna_to_ascii_8z(utf8, &output, IDNA_ALLOW_UNASSIGNED)) {
		LogMessage(MessageType::Debug_Warning, _T("Could not convert domain name"));
		return domain;
	}

	wxString result = wxConvCurrent->cMB2WX(output);
	idn_free(output);
	return result;
#endif
}
예제 #3
0
void
doit (void)
{
  int rc;
  char *out = NULL;
  size_t i;

  for (i = 0; i < sizeof (idna) / sizeof (idna[0]); i++)
    {
      rc = idna_to_unicode_8z8z (idna[i].in, &out, 0);
      if (rc != IDNA_SUCCESS)
	fail ("IDNA3[%ld] failed %d\n", i, rc);

      if (debug && rc == IDNA_SUCCESS)
	{
	  printf ("input:        %s\n", idna[i].in);
	  printf ("computed out: %s\n", out);
	  printf ("expected out: %s\n", idna[i].out);
	}

      if (strcmp (out, idna[i].out) != 0)
	fail ("IDNA3[%ld] failed\n", i);
      else if (debug)
	printf ("IDNA3[%ld] success\n", i);

      if (out)
	idn_free (out);
    }
}
예제 #4
0
wxString CControlSocket::ConvertDomainName(wxString domain)
{
	const wxWCharBuffer buffer = wxConvCurrent->cWX2WC(domain);

	int len = 0;
	while (buffer.data()[len])
		len++;

	char *utf8 = new char[len * 2 + 2];
	wxMBConvUTF8 conv;
	conv.WC2MB(utf8, buffer, len * 2 + 2);

	char *output;
	if (idna_to_ascii_8z(utf8, &output, IDNA_ALLOW_UNASSIGNED))
	{
		delete [] utf8;
		LogMessage(::Debug_Warning, _T("Could not convert domain name"));
		return domain;
	}
	delete [] utf8;

	wxString result = wxConvCurrent->cMB2WX(output);
	idn_free(output);
	return result;
}
예제 #5
0
파일: connect.c 프로젝트: Distrotech/wget
int
connect_to_ip (const ip_address *ip, int port, const char *print)
{
  struct sockaddr_storage ss;
  struct sockaddr *sa = (struct sockaddr *)&ss;
  int sock;

  /* If PRINT is non-NULL, print the "Connecting to..." line, with
     PRINT being the host name we're connecting to.  */
  if (print)
    {
      const char *txt_addr = print_address (ip);
      if (0 != strcmp (print, txt_addr))
        {
          char *str = NULL, *name;

          if (opt.enable_iri && (name = idn_decode ((char *) print)) != NULL)
            {
              int len = strlen (print) + strlen (name) + 4;
              str = xmalloc (len);
              snprintf (str, len, "%s (%s)", name, print);
              str[len-1] = '\0';
              idn_free (name);
            }

          logprintf (LOG_VERBOSE, _("Connecting to %s|%s|:%d... "),
                     str ? str : escnonprint_uri (print), txt_addr, port);

          xfree (str);
        }
      else
        {
           if (ip->family == AF_INET)
               logprintf (LOG_VERBOSE, _("Connecting to %s:%d... "), txt_addr, port);
#ifdef ENABLE_IPV6
           else if (ip->family == AF_INET6)
               logprintf (LOG_VERBOSE, _("Connecting to [%s]:%d... "), txt_addr, port);
#endif
        }
    }

  /* Store the sockaddr info to SA.  */
  sockaddr_set_data (sa, ip, port);

  /* Create the socket of the family appropriate for the address.  */
  sock = socket (sa->sa_family, SOCK_STREAM, 0);
  if (sock < 0)
    goto err;

#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY)
  if (opt.ipv6_only) {
    int on = 1;
    /* In case of error, we will go on anyway... */
    int err = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on));
    IF_DEBUG
      if (err < 0)
        DEBUGP (("Failed setting IPV6_V6ONLY: %s", strerror (errno)));
  }
예제 #6
0
파일: tst_badutf8.c 프로젝트: guusdk/libidn
void
doit (void)
{
  char *badutf8 = strdup ("\x7e\x64\x61\x72\x10\x2f\x2f\xf9\x2b\x71"
			  "\x60\x79\x7b\x2e\x63\x75\x2b\x61\x65\x72"
			  "\x75\x65\x56\x66\x7f\x62\xc5\x76\xe5\x00");
  char *s = NULL;
  int rc;

  rc = idna_to_ascii_8z (badutf8, &s, 0);
  free (badutf8);
  if (rc != IDNA_ICONV_ERROR)
    fail ("rc %d\n", rc);

  idn_free (s);
}
예제 #7
0
파일: dnsparser.c 프로젝트: GNUnet/gnunet
/**
 * Check if a label in UTF-8 format can be coded into valid IDNA.
 * This can fail if the ASCII-conversion becomes longer than 63 characters.
 *
 * @param label label to check (UTF-8 string)
 * @return #GNUNET_OK if the label can be converted to IDNA,
 *         #GNUNET_SYSERR if the label is not valid for DNS names
 */
int
GNUNET_DNSPARSER_check_label (const char *label)
{
  char *output;
  size_t slen;

  if (NULL != strchr (label, '.'))
    return GNUNET_SYSERR; /* not a label! Did you mean GNUNET_DNSPARSER_check_name? */
  if (IDNA_SUCCESS !=
      idna_to_ascii_8z (label, &output, IDNA_ALLOW_UNASSIGNED))
    return GNUNET_SYSERR;
  slen = strlen (output);
#if WINDOWS
  idn_free (output);
#else
  free (output);
#endif
  return (slen > 63) ? GNUNET_SYSERR : GNUNET_OK;
}
예제 #8
0
/**
 * gnutls_server_name_set:
 * @session: is a #gnutls_session_t type.
 * @type: specifies the indicator type
 * @name: is a string that contains the server name.
 * @name_length: holds the length of name
 *
 * This function is to be used by clients that want to inform (via a
 * TLS extension mechanism) the server of the name they connected to.
 * This should be used by clients that connect to servers that do
 * virtual hosting.
 *
 * The value of @name depends on the @type type.  In case of
 * %GNUTLS_NAME_DNS, a UTF-8 null-terminated domain name string,
 * without the trailing dot, is expected.
 *
 * IPv4 or IPv6 addresses are not permitted.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_server_name_set(gnutls_session_t session,
		       gnutls_server_name_type_t type,
		       const void *name, size_t name_length)
{
	int server_names, ret;
	server_name_ext_st *priv;
	extension_priv_data_t epriv;
	char *idn_name = NULL;
	int set = 0, rc;

	if (session->security_parameters.entity == GNUTLS_SERVER) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if (name_length == 0) { /* unset extension */
		_gnutls_ext_unset_session_data(session, GNUTLS_EXTENSION_SERVER_NAME);
		return 0;
	}

#ifdef HAVE_LIBIDN
	rc = idna_to_ascii_8z (name, &idn_name, IDNA_ALLOW_UNASSIGNED);
	if (rc != IDNA_SUCCESS) {
		 _gnutls_debug_log("unable to convert name %s to IDNA format: %s\n", (char*)name, idna_strerror(rc));
		 return GNUTLS_E_IDNA_ERROR;
	}
	name = idn_name;
	name_length = strlen(idn_name);
#endif

	if (name_length > MAX_SERVER_NAME_SIZE) {
		ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
		goto cleanup;
	}

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SERVER_NAME,
					 &epriv);
	if (ret < 0) {
		set = 1;
	}

	if (set != 0) {
		priv = gnutls_calloc(1, sizeof(*priv));
		if (priv == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}
		epriv = priv;
	} else
		priv = epriv;

	server_names = priv->server_names_size + 1;

	if (server_names > MAX_SERVER_NAME_EXTENSIONS)
		server_names = MAX_SERVER_NAME_EXTENSIONS;

	priv->server_names[server_names - 1].type = type;
	memcpy(priv->server_names[server_names - 1].name, name,
	       name_length);
	priv->server_names[server_names - 1].name_length = name_length;

	priv->server_names_size = server_names;

	if (set != 0)
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SERVER_NAME,
					     epriv);

	ret = 0;
 cleanup:
#ifdef HAVE_LIBIDN
	idn_free(idn_name);
#endif
	return ret;
}
예제 #9
0
/**
 * gnutls_server_name_get:
 * @session: is a #gnutls_session_t type.
 * @data: will hold the data
 * @data_length: will hold the data length. Must hold the maximum size of data.
 * @type: will hold the server name indicator type
 * @indx: is the index of the server_name
 *
 * This function will allow you to get the name indication (if any), a
 * client has sent.  The name indication may be any of the enumeration
 * gnutls_server_name_type_t.
 *
 * If @type is GNUTLS_NAME_DNS, then this function is to be used by
 * servers that support virtual hosting, and the data will be a null
 * terminated IDNA ACE string (prior to GnuTLS 3.4.0 it was a UTF-8 string).
 *
 * If @data has not enough size to hold the server name
 * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
 * hold the required size.
 *
 * @index is used to retrieve more than one server names (if sent by
 * the client).  The first server name has an index of 0, the second 1
 * and so on.  If no name with the given index exists
 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_server_name_get(gnutls_session_t session, void *data,
		       size_t * data_length,
		       unsigned int *type, unsigned int indx)
{
	char *_data = data;
	server_name_ext_st *priv;
	int ret;
#ifdef HAVE_LIBIDN
	int rc;
	char *idn_name = NULL;
#endif
	extension_priv_data_t epriv;
	gnutls_datum name;

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SERVER_NAME,
					 &epriv);
	if (ret < 0) {
		gnutls_assert();
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	priv = epriv;

	if (indx + 1 > priv->server_names_size) {
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	*type = priv->server_names[indx].type;

#ifdef HAVE_LIBIDN
	rc = idna_to_ascii_8z ((char*)priv->server_names[indx].name, &idn_name, IDNA_ALLOW_UNASSIGNED);
	if (rc != IDNA_SUCCESS) {
		 _gnutls_debug_log("unable to convert name %s to IDNA format: %s\n", (char*)priv->server_names[indx].name, idna_strerror(rc));
		 return GNUTLS_E_IDNA_ERROR;
	}
	name.data = (unsigned char*)idn_name;
	name.size = strlen(idn_name);
#else
	name.data = priv->server_names[indx].name;
	name.size = priv->server_names[indx].name_length;
#endif

	if (*data_length >	/* greater since we need one extra byte for the null */
	    name.size) {
		*data_length = name.size;
		memcpy(data, name.data, *data_length);

		if (*type == GNUTLS_NAME_DNS)	/* null terminate */
			_data[(*data_length)] = 0;

	} else {
		*data_length = name.size + 1;
		ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
		goto cleanup;
	}

	ret = 0;
 cleanup:
#ifdef HAVE_LIBIDN
	idn_free(idn_name);
#endif
	return ret;
}
예제 #10
0
파일: dnsparser.c 프로젝트: GNUnet/gnunet
/**
 * Add a DNS name to the UDP packet at the given location, converting
 * the name to IDNA notation as necessary.
 *
 * @param dst where to write the name (UDP packet)
 * @param dst_len number of bytes in @a dst
 * @param off pointer to offset where to write the name (increment by bytes used)
 *            must not be changed if there is an error
 * @param name name to write
 * @return #GNUNET_SYSERR if @a name is invalid
 *         #GNUNET_NO if @a name did not fit
 *         #GNUNET_OK if @a name was added to @a dst
 */
int
GNUNET_DNSPARSER_builder_add_name (char *dst,
				   size_t dst_len,
				   size_t *off,
				   const char *name)
{
  const char *dot;
  const char *idna_name;
  char *idna_start;
  size_t start;
  size_t pos;
  size_t len;
  Idna_rc rc;

  if (NULL == name)
    return GNUNET_SYSERR;

  if (IDNA_SUCCESS !=
      (rc = idna_to_ascii_8z (name, &idna_start, IDNA_ALLOW_UNASSIGNED)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
		_("Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n"),
		name,
		idna_strerror (rc));
    return GNUNET_NO;
  }
  idna_name = idna_start;
  start = *off;
  if (start + strlen (idna_name) + 2 > dst_len)
    goto fail;
  pos = start;
  do
  {
    dot = strchr (idna_name, '.');
    if (NULL == dot)
      len = strlen (idna_name);
    else
      len = dot - idna_name;
    if ( (len >= 64) || (0 == len) )
    {
      GNUNET_break (0);
      goto fail; /* segment too long or empty */
    }
    dst[pos++] = (char) (uint8_t) len;
    GNUNET_memcpy (&dst[pos], idna_name, len);
    pos += len;
    idna_name += len + 1; /* also skip dot */
  }
  while (NULL != dot);
  dst[pos++] = '\0'; /* terminator */
  *off = pos;
#if WINDOWS
  idn_free (idna_start);
#else
  free (idna_start);
#endif
  return GNUNET_OK;
 fail:
#if WINDOWS
  idn_free (idna_start);
#else
  free (idna_start);
#endif
  return GNUNET_NO;
}
예제 #11
0
파일: dnsparser.c 프로젝트: GNUnet/gnunet
/**
 * Parse name inside of a DNS query or record.
 *
 * @param udp_payload entire UDP payload
 * @param udp_payload_length length of @a udp_payload
 * @param off pointer to the offset of the name to parse in the udp_payload (to be
 *                    incremented by the size of the name)
 * @param depth current depth of our recursion (to prevent stack overflow)
 * @return name as 0-terminated C string on success, NULL if the payload is malformed
 */
static char *
parse_name (const char *udp_payload,
	    size_t udp_payload_length,
	    size_t *off,
	    unsigned int depth)
{
  const uint8_t *input = (const uint8_t *) udp_payload;
  char *ret;
  char *tmp;
  char *xstr;
  uint8_t len;
  size_t xoff;
  char *utf8;
  Idna_rc rc;

  ret = GNUNET_strdup ("");
  while (1)
  {
    if (*off >= udp_payload_length)
    {
      GNUNET_break_op (0);
      goto error;
    }
    len = input[*off];
    if (0 == len)
    {
      (*off)++;
      break;
    }
    if (len < 64)
    {
      if (*off + 1 + len > udp_payload_length)
      {
	GNUNET_break_op (0);
	goto error;
      }
      GNUNET_asprintf (&tmp,
		       "%.*s",
		       (int) len,
		       &udp_payload[*off + 1]);
      if (IDNA_SUCCESS !=
	  (rc = idna_to_unicode_8z8z (tmp, &utf8, IDNA_ALLOW_UNASSIGNED)))
      {
	GNUNET_log (GNUNET_ERROR_TYPE_INFO,
		    _("Failed to convert DNS IDNA name `%s' to UTF-8: %s\n"),
		    tmp,
		    idna_strerror (rc));
	GNUNET_free (tmp);
	GNUNET_asprintf (&tmp,
			 "%s%.*s.",
			 ret,
			 (int) len,
			 &udp_payload[*off + 1]);
      }
      else
      {
	GNUNET_free (tmp);
	GNUNET_asprintf (&tmp,
			 "%s%s.",
			 ret,
			 utf8);
#if WINDOWS
	idn_free (utf8);
#else
	free (utf8);
#endif
      }
      GNUNET_free (ret);
      ret = tmp;
      *off += 1 + len;
    }
    else if ((64 | 128) == (len & (64 | 128)) )
    {
      if (depth > 32)
      {
	GNUNET_break_op (0);
	goto error; /* hard bound on stack to prevent "infinite" recursion, disallow! */
      }
      /* pointer to string */
      if (*off + 1 > udp_payload_length)
      {
	GNUNET_break_op (0);
	goto error;
      }
      xoff = ((len - (64 | 128)) << 8) + input[*off+1];
      xstr = parse_name (udp_payload,
			 udp_payload_length,
			 &xoff,
			 depth + 1);
      if (NULL == xstr)
      {
	GNUNET_break_op (0);
	goto error;
      }
      GNUNET_asprintf (&tmp,
		       "%s%s.",
		       ret,
		       xstr);
      GNUNET_free (ret);
      GNUNET_free (xstr);
      ret = tmp;
      if (strlen (ret) > udp_payload_length)
      {
	GNUNET_break_op (0);
	goto error; /* we are looping (building an infinite string) */
      }
      *off += 2;
      /* pointers always terminate names */
      break;
    }
    else
    {
      /* neither pointer nor inline string, not supported... */
      GNUNET_break_op (0);
      goto error;
    }
  }
  if (0 < strlen(ret))
    ret[strlen(ret)-1] = '\0'; /* eat tailing '.' */
  return ret;
 error:
  GNUNET_break_op (0);
  GNUNET_free (ret);
  return NULL;
}
예제 #12
0
파일: host.c 프로젝트: AOSC-Dev/wget
struct address_list *
lookup_host (const char *host, int flags)
{
  struct address_list *al;
  bool silent = !!(flags & LH_SILENT);
  bool use_cache;
  bool numeric_address = false;
  double timeout = opt.dns_timeout;

#ifndef ENABLE_IPV6
  /* If we're not using getaddrinfo, first check if HOST specifies a
     numeric IPv4 address.  Some implementations of gethostbyname
     (e.g. the Ultrix one and possibly Winsock) don't accept
     dotted-decimal IPv4 addresses.  */
  {
    uint32_t addr_ipv4 = (uint32_t)inet_addr (host);
    if (addr_ipv4 != (uint32_t) -1)
      {
        /* No need to cache host->addr relation, just return the
           address.  */
        char *vec[2];
        vec[0] = (char *)&addr_ipv4;
        vec[1] = NULL;
        return address_list_from_ipv4_addresses (vec);
      }
  }
#else  /* ENABLE_IPV6 */
  /* If we're using getaddrinfo, at least check whether the address is
     already numeric, in which case there is no need to print the
     "Resolving..." output.  (This comes at no additional cost since
     the is_valid_ipv*_address are already required for
     url_parse.)  */
  {
    const char *end = host + strlen (host);
    if (is_valid_ipv4_address (host, end) || is_valid_ipv6_address (host, end))
      numeric_address = true;
  }
#endif

  /* Cache is normally on, but can be turned off with --no-dns-cache.
     Don't cache passive lookups under IPv6.  */
  use_cache = opt.dns_cache;
#ifdef ENABLE_IPV6
  if ((flags & LH_BIND) || numeric_address)
    use_cache = false;
#endif

  /* Try to find the host in the cache so we don't need to talk to the
     resolver.  If LH_REFRESH is requested, remove HOST from the cache
     instead.  */
  if (use_cache)
    {
      if (!(flags & LH_REFRESH))
        {
          al = cache_query (host);
          if (al)
            return al;
        }
      else
        cache_remove (host);
    }

  /* No luck with the cache; resolve HOST. */

  if (!silent && !numeric_address)
    {
      char *str = NULL, *name;

      if (opt.enable_iri && (name = idn_decode ((char *) host)) != NULL)
        {
          int len = strlen (host) + strlen (name) + 4;
          str = xmalloc (len);
          snprintf (str, len, "%s (%s)", name, host);
          str[len-1] = '\0';
          idn_free (name);
        }

      logprintf (LOG_VERBOSE, _("Resolving %s... "),
                 quotearg_style (escape_quoting_style, str ? str : host));

      xfree (str);
    }

#ifdef ENABLE_IPV6
  {
    int err;
    struct addrinfo hints, *res;

    xzero (hints);
    hints.ai_socktype = SOCK_STREAM;
    if (opt.ipv4_only)
      hints.ai_family = AF_INET;
    else if (opt.ipv6_only)
      hints.ai_family = AF_INET6;
    else
      /* We tried using AI_ADDRCONFIG, but removed it because: it
         misinterprets IPv6 loopbacks, it is broken on AIX 5.1, and
         it's unneeded since we sort the addresses anyway.  */
        hints.ai_family = AF_UNSPEC;

    if (flags & LH_BIND)
      hints.ai_flags |= AI_PASSIVE;

#ifdef AI_NUMERICHOST
    if (numeric_address)
      {
        /* Where available, the AI_NUMERICHOST hint can prevent costly
           access to DNS servers.  */
        hints.ai_flags |= AI_NUMERICHOST;
        timeout = 0;            /* no timeout needed when "resolving"
                                   numeric hosts -- avoid setting up
                                   signal handlers and such. */
      }
#endif

    err = getaddrinfo_with_timeout (host, NULL, &hints, &res, timeout);
    if (err != 0 || res == NULL)
      {
        if (!silent)
          logprintf (LOG_VERBOSE, _("failed: %s.\n"),
                     err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno));
        return NULL;
      }
    al = address_list_from_addrinfo (res);
    freeaddrinfo (res);
    if (!al)
      {
        logprintf (LOG_VERBOSE,
                   _("failed: No IPv4/IPv6 addresses for host.\n"));
        return NULL;
      }

    /* Reorder addresses so that IPv4 ones (or IPv6 ones, as per
       --prefer-family) come first.  Sorting is stable so the order of
       the addresses with the same family is undisturbed.  */
    if (al->count > 1 && opt.prefer_family != prefer_none)
      stable_sort (al->addresses, al->count, sizeof (ip_address),
                   opt.prefer_family == prefer_ipv4
                   ? cmp_prefer_ipv4 : cmp_prefer_ipv6);
  }
#else  /* not ENABLE_IPV6 */
  {
    struct hostent *hptr = gethostbyname_with_timeout (host, timeout);
    if (!hptr)
      {
        if (!silent)
          {
            if (errno != ETIMEDOUT)
              logprintf (LOG_VERBOSE, _("failed: %s.\n"),
                         host_errstr (h_errno));
            else
              logputs (LOG_VERBOSE, _("failed: timed out.\n"));
          }
        return NULL;
      }
    /* Do older systems have h_addr_list?  */
    al = address_list_from_ipv4_addresses (hptr->h_addr_list);
  }
#endif /* not ENABLE_IPV6 */

  /* Print the addresses determined by DNS lookup, but no more than
     three if show_all_dns_entries is not specified.  */
  if (!silent && !numeric_address)
    {
      int i;
      int printmax = al->count;

      if (!opt.show_all_dns_entries && printmax > 3)
          printmax = 3;

      for (i = 0; i < printmax; i++)
        {
          logputs (LOG_VERBOSE, print_address (al->addresses + i));
          if (i < printmax - 1)
            logputs (LOG_VERBOSE, ", ");
        }
      if (printmax != al->count)
        logputs (LOG_VERBOSE, ", ...");
      logputs (LOG_VERBOSE, "\n");
    }

  /* Cache the lookup information. */
  if (use_cache)
    cache_store (host, al);

  return al;
}
예제 #13
0
파일: hesiod.c 프로젝트: greghudson/hesiod
/* This function takes a hesiod (name, type) and returns a DNS
 * name which is to be resolved.
 */
char *hesiod_to_bind(void *context, const char *name, const char *type)
{
  struct hesiod_p *ctx = (struct hesiod_p *) context;
  char bindname[MAXDNAME], *p, *ret, *idn_ret, **rhs_list = NULL;
  const char *rhs;
  int len, rc;

  if (strlen(name) > sizeof(bindname) - 1)
    {
      errno = EMSGSIZE;
      return NULL;
    }
  strcpy(bindname, name);

  /* Find the right right hand side to use, possibly truncating bindname. */
  p = strchr(bindname, '@');
  if (p)
    {
      *p++ = 0;
      if (strchr(p, '.'))
	rhs = name + (p - bindname);
      else
	{
	  rhs_list = hesiod_resolve(context, p, "rhs-extension");
	  if (rhs_list)
	    rhs = *rhs_list;
	  else
	    {
	      errno = ENOENT;
	      return NULL;
	    }
	}
    } else
      rhs = ctx->rhs;

  /* See if we have enough room. */
  len = strlen(bindname) + 1 + strlen(type);
  if (ctx->lhs)
    len += strlen(ctx->lhs) + ((ctx->lhs[0] != '.') ? 1 : 0);
  len += strlen(rhs) + ((rhs[0] != '.') ? 1 : 0);
  if (len > sizeof(bindname) - 1)
    {
      if (rhs_list)
	hesiod_free_list(context, rhs_list);
      errno = EMSGSIZE;
      return NULL;
    }

  /* Put together the rest of the domain. */
  strcat(bindname, ".");
  strcat(bindname, type);
  if (ctx->lhs)
    {
      if (ctx->lhs[0] != '.')
	strcat(bindname, ".");
      strcat(bindname, ctx->lhs);
    }
  if (rhs[0] != '.')
    strcat(bindname, ".");
  strcat(bindname, rhs);

  /* rhs_list is no longer needed, since we're done with rhs. */
  if (rhs_list)
    hesiod_free_list(context, rhs_list);

  /* Make a copy of the result and return it to the caller. */
#ifdef HAVE_LIBIDN
  rc = idna_to_ascii_lz(bindname, &idn_ret, 0);
  if (rc != IDNA_SUCCESS)
    {
      errno = EINVAL;
      return NULL;
    }
  ret = strdup(idn_ret);
  idn_free(idn_ret);
#else
  ret = strdup(bindname);
#endif
  if (!ret)
    {
      errno = ENOMEM;
      return NULL;
    }
  return ret;
}