Пример #1
0
/*% performs a reverse lookup of address src which is len bytes long. af denotes the protocol family, typically #PF_INET or PF_INET6. */
struct hostent *
lwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
	struct hostent *he1, *he2;
	lwres_context_t *lwrctx = NULL;
	lwres_gnbaresponse_t *by = NULL;
	lwres_result_t n;
	union {
		const void *konst;
		struct in6_addr *in6;
	} u;

	/*
	 * Sanity checks.
	 */
	if (src == NULL) {
		*error_num = NO_RECOVERY;
		return (NULL);
	}

	switch (af) {
	case AF_INET:
		if (len != (unsigned int)INADDRSZ) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}
		break;
	case AF_INET6:
		if (len != (unsigned int)IN6ADDRSZ) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}
		break;
	default:
		*error_num = NO_RECOVERY;
		return (NULL);
	}

	/*
	 * The de-"const"-ing game is done because at least one
	 * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_*
	 * macros in such a way that they discard the const with
	 * internal casting, and gcc ends up complaining.  Rather
	 * than replacing their own (possibly optimized) definitions
	 * with our own, cleanly discarding the const is the easiest
	 * thing to do.
	 */
	u.konst = src;

	/*
	 * Look up IPv4 and IPv4 mapped/compatible addresses.
	 */
	if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) ||
	    (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) ||
	    (af == AF_INET)) {
		const unsigned char *cp = src;

		if (af == AF_INET6)
			cp += 12;
		n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
		if (n == LWRES_R_SUCCESS)
			(void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
		if (n == LWRES_R_SUCCESS)
			n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4,
						INADDRSZ, cp, &by);
		if (n != LWRES_R_SUCCESS) {
			lwres_conf_clear(lwrctx);
			lwres_context_destroy(&lwrctx);
			if (n == LWRES_R_NOTFOUND)
				*error_num = HOST_NOT_FOUND;
			else
				*error_num = NO_RECOVERY;
			return (NULL);
		}
		he1 = hostfromaddr(by, AF_INET, cp);
		lwres_gnbaresponse_free(lwrctx, &by);
		lwres_conf_clear(lwrctx);
		lwres_context_destroy(&lwrctx);
		if (af != AF_INET6)
			return (he1);

		/*
		 * Convert from AF_INET to AF_INET6.
		 */
		he2 = copyandmerge(he1, NULL, af, error_num);
		lwres_freehostent(he1);
		if (he2 == NULL)
			return (NULL);
		/*
		 * Restore original address.
		 */
		memcpy(he2->h_addr, src, len);
		return (he2);
	}

	/*
	 * Lookup IPv6 address.
	 */
	if (memcmp(src, &in6addr_any, IN6ADDRSZ) == 0) {
		*error_num = HOST_NOT_FOUND;
		return (NULL);
	}

	n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
	if (n == LWRES_R_SUCCESS)
		(void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
	if (n == LWRES_R_SUCCESS)
		n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ,
					src, &by);
	if (n != 0) {
		lwres_conf_clear(lwrctx);
		lwres_context_destroy(&lwrctx);

		if (n == LWRES_R_NOTFOUND)
		       *error_num = HOST_NOT_FOUND;
		else
		       *error_num = NO_RECOVERY;

		return (NULL);
	}

	he1 = hostfromaddr(by, AF_INET6, src);
	lwres_gnbaresponse_free(lwrctx, &by);
	if (he1 == NULL)
		*error_num = NO_RECOVERY;
	lwres_conf_clear(lwrctx);
	lwres_context_destroy(&lwrctx);
	return (he1);
}
Пример #2
0
struct hostent *
lwres_getipnodebyname(const char *name, int af, int flags, int *error_num) {
	int have_v4 = 1, have_v6 = 1;
	struct in_addr in4;
	struct in6_addr in6;
	struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL;
	int v4 = 0, v6 = 0;
	int tmp_err = 0;
	lwres_context_t *lwrctx = NULL;
	lwres_gabnresponse_t *by = NULL;
	int n;

	/*
	 * If we care about active interfaces then check.
	 */
	if ((flags & AI_ADDRCONFIG) != 0)
		if (scan_interfaces(&have_v4, &have_v6) == -1) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}

	/* Check for literal address. */
	if ((v4 = lwres_net_pton(AF_INET, name, &in4)) != 1)
		v6 = lwres_net_pton(AF_INET6, name, &in6);

	/*
	 * Impossible combination?
	 */
	if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
	    (af == AF_INET && v6 == 1) ||
	    (have_v4 == 0 && v4 == 1) ||
	    (have_v6 == 0 && v6 == 1) ||
	    (have_v4 == 0 && af == AF_INET) ||
	    (have_v6 == 0 && af == AF_INET6 &&
	     (((flags & AI_V4MAPPED) != 0 && have_v4) ||
	      (flags & AI_V4MAPPED) == 0))) {
		*error_num = HOST_NOT_FOUND;
		return (NULL);
	}

	/*
	 * Literal address?
	 */
	if (v4 == 1 || v6 == 1) {
		char *addr_list[2];
		char *aliases[1];
		char mappedname[sizeof("::ffff:123.123.123.123")];
		union {
			const char *const_name;
			char *deconst_name;
		} u;

		u.const_name = name;
		if (v4 == 1 && af == AF_INET6) {
			strcpy(mappedname, "::ffff:");
			lwres_net_ntop(AF_INET, (char *)&in4,
				       mappedname + sizeof("::ffff:") - 1,
				       sizeof(mappedname) - sizeof("::ffff:")
				       + 1);
			he.h_name = mappedname;
		} else
			he.h_name = u.deconst_name;
		he.h_addr_list = addr_list;
		he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
		he.h_addr_list[1] = NULL;
		he.h_aliases = aliases;
		he.h_aliases[0] = NULL;
		he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ;
		he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6;
		return (copyandmerge(&he, NULL, af, error_num));
	}

	n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
	if (n != 0) {
		*error_num = NO_RECOVERY;
		goto cleanup;
	}
	(void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
	tmp_err = NO_RECOVERY;
	if (have_v6 && af == AF_INET6) {
		n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by);
		if (n == 0) {
			he1 = hostfromname(by, AF_INET6);
			lwres_gabnresponse_free(lwrctx, &by);
			if (he1 == NULL) {
				*error_num = NO_RECOVERY;
				goto cleanup;
			}
		} else {
			if (n == LWRES_R_NOTFOUND)
				tmp_err = HOST_NOT_FOUND;
			else {
				*error_num = NO_RECOVERY;
				goto cleanup;
			}
		}
	}

	if (have_v4 &&
	    ((af == AF_INET) ||
	     (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&
	      (he1 == NULL || (flags & AI_ALL) != 0)))) {
		n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by);
		if (n == 0) {
			he2 = hostfromname(by, AF_INET);
			lwres_gabnresponse_free(lwrctx, &by);
			if (he2 == NULL) {
				*error_num = NO_RECOVERY;
				goto cleanup;
			}
		} else if (he1 == NULL) {
			if (n == LWRES_R_NOTFOUND)
				*error_num = HOST_NOT_FOUND;
			else
				*error_num = NO_RECOVERY;
			goto cleanup;
		}
	} else
		*error_num = tmp_err;

	he3 = copyandmerge(he1, he2, af, error_num);

 cleanup:
	if (he1 != NULL)
		lwres_freehostent(he1);
	if (he2 != NULL)
		lwres_freehostent(he2);
	if (lwrctx != NULL) {
		lwres_conf_clear(lwrctx);
		lwres_context_destroy(&lwrctx);
	}
	return (he3);
}
Пример #3
0
/*
 * AI_V4MAPPED + AF_INET6
 * If no IPv6 address then a query for IPv4 and map returned values.
 *
 * AI_ALL + AI_V4MAPPED + AF_INET6
 * Return IPv6 and IPv4 mapped.
 *
 * AI_ADDRCONFIG
 * Only return IPv6 / IPv4 address if there is an interface of that
 * type active.
 */
struct hostent * W32_CALL
getipnodebyname (const char *name, int af, int flags, int *error)
{
  struct hostent *he1 = NULL;
  struct hostent *he2 = NULL;
  struct in_addr  in4;
  struct in6_addr in6;
  BOOL   have_v4 = TRUE, have_v6 = TRUE;
  BOOL   v4 = FALSE, v6 = FALSE;
  int    tmp_err;

  SOCK_DEBUGF (("\ngetipnodebyname: %s ", name));

  /* If we care about active interfaces then check.
   */
  if (flags & AI_ADDRCONFIG)
     scan_interface (&have_v4, &have_v6);

  /* Check for literal address.
   */
  v4 = inet_pton (AF_INET, name, &in4);
  if (!v4)
     v6 = inet_pton (AF_INET6, name, &in6);

  /* Impossible combination?
   */
  if ((af == AF_INET6 && !(flags & AI_V4MAPPED) && v4) ||
      (af == AF_INET && v6) ||
      (!have_v4 && v4) ||
      (!have_v6 && v6) ||
      (!have_v4 && af == AF_INET) ||
      ((!have_v6 && af == AF_INET6) && ((flags & AI_V4MAPPED) && have_v4)) ||
      !(flags & AI_V4MAPPED))
  {
    *error = HOST_NOT_FOUND;
    return (NULL);
  }

  /* Literal address?
   */
  if (v4 || v6)
  {
    struct hostent he;
    char  *addr_list[2];
    char  *aliases[1];

    he.h_name         = (char*) name;
    he.h_addr_list    = addr_list;
    he.h_addr_list[0] = (v4 ? (char*)&in4 : (char*)&in6);
    he.h_addr_list[1] = NULL;
    he.h_aliases      = aliases;
    he.h_aliases[0]   = NULL;
    he.h_length       = (v4 ? INADDRSZ : IN6ADDRSZ);
    he.h_addrtype     = (v4 ? AF_INET  : AF_INET6);
    return copyandmerge (&he, NULL, af, error);
  }

  tmp_err = NO_RECOVERY;
  if (have_v6 && af == AF_INET6)
  {
#if defined(USE_IPV6)
    he1 = gethostbyname6 (name);
#else
    he1 = NULL;
#endif
    if (!he1)
       tmp_err = HOST_NOT_FOUND;
  }

  if (have_v4 &&
      (af == AF_INET ||
       (af == AF_INET6 &&
        (flags & AI_V4MAPPED) && (!he1 || (flags & AI_ALL)))))
  {
    SOCK_ENTER_SCOPE();
    he2 = gethostbyname (name);
    SOCK_LEAVE_SCOPE();
    if (!he2 || !he1)
    {
      *error = HOST_NOT_FOUND;
      return (NULL);
    }
  }
  else
    *error = tmp_err;

  return copyandmerge (he1, he2, af, error);
}
Пример #4
0
struct hostent * W32_CALL
getipnodebyaddr (const void *src, size_t len, int af, int *error)
{
  struct hostent *he1, *he2;
  const  BYTE *cp = (const BYTE*) src;

  SOCK_DEBUGF (("\ngetipnodebyaddr: "));

  if (!src)
  {
    *error = NO_RECOVERY;
    return (NULL);
  }

  switch (af)
  {
    case AF_INET:
         if (len < INADDRSZ)
         {
           *error = NO_RECOVERY;
           return (NULL);
         }
         break;
#if defined(USE_IPV6)
    case AF_INET6:
         if (len < IN6ADDRSZ)
         {
           *error = NO_RECOVERY;
           return (NULL);
         }
         break;
#endif
    default:
         *error = NO_RECOVERY;
         return (NULL);
  }

  /* Look up IPv4 and IPv4 mapped/compatible addresses.
   */
  if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(cp)) ||
      (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(cp)) ||
      (af == AF_INET))
  {
    if (af == AF_INET6)
       cp += 12;

    SOCK_ENTER_SCOPE();
    he1 = gethostbyaddr ((const char*)cp, 4, AF_INET);
    SOCK_LEAVE_SCOPE();

    if (af == AF_INET)
       goto ret_copy;

    /* Convert from AF_INET to AF_INET6.
     */
    he2 = copyandmerge (he1, NULL, af, error);
    if (he2)
    {
      memcpy (he2->h_addr, src, len);  /* Restore original address */
      SOCK_DEBUGF (("%s", af == AF_INET ?
                    inet_ntoa(*(struct in_addr*)&he2->h_addr) :
                    _inet6_ntoa(he2->h_addr)));
    }
    return (he2);
  }

  he1 = gethostbyaddr (src, len, AF_INET6);   /* Lookup IPv6 address */

ret_copy:
  if (!he1)
  {
    *error = HOST_NOT_FOUND;
    return (NULL);
  }
  return copyandmerge (he1, NULL, af, error);
}
Пример #5
0
struct hostent *
getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
	struct hostent *he1, *he2;
	struct net_data *net_data = init();

	/* Sanity Checks. */
	if (src == NULL) {
		*error_num = NO_RECOVERY;
		return (NULL);
	}
		
	switch (af) {
	case AF_INET:
		if (len != (size_t)INADDRSZ) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}
		break;
	case AF_INET6:
		if (len != (size_t)IN6ADDRSZ) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}
		break;
	default:
		*error_num = NO_RECOVERY;
		return (NULL);
	}

	/*
	 * Lookup IPv4 and IPv4 mapped/compatible addresses
	 */
	if ((af == AF_INET6 &&
	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) ||
	    (af == AF_INET6 &&
	     IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) ||
	    (af == AF_INET)) {
		const char *cp = src;

		if (af == AF_INET6)
			cp += 12;
		he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data);
		if (he1 == NULL) {
			*error_num = net_data->res->res_h_errno;
			return (NULL);
		}
		he2 = copyandmerge(he1, NULL, af, error_num);
		if (he2 == NULL)
			return (NULL);
		/*
		 * Restore original address if mapped/compatible.
		 */
		if (af == AF_INET6)
			memcpy(he1->h_addr, src, len);
		return (he2);
	}

	/*
	 * Lookup IPv6 address.
	 */
	if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) {
		*error_num = HOST_NOT_FOUND;
		return (NULL);
	}

	he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data);
	if (he1 == NULL) {
		*error_num = net_data->res->res_h_errno;
		return (NULL);
	}
	return (copyandmerge(he1, NULL, af, error_num));
}
Пример #6
0
struct hostent *
getipnodebyname(const char *name, int af, int flags, int *error_num) {
	int have_v4 = 1, have_v6 = 1;
	struct in_addr in4;
	struct in6_addr in6;
	struct hostent he, *he1 = NULL, *he2 = NULL, *he3;
	int v4 = 0, v6 = 0;
	struct net_data *net_data = init();
	u_long options;
	int tmp_err;

	if (net_data == NULL) {
		*error_num = NO_RECOVERY;
		return (NULL);
	}

	/* If we care about active interfaces then check. */
	if ((flags & AI_ADDRCONFIG) != 0)
		if (scan_interfaces(&have_v4, &have_v6) == -1) {
			*error_num = NO_RECOVERY;
			return (NULL);
		}

	/* Check for literal address. */
	if ((v4 = inet_pton(AF_INET, name, &in4)) != 1)
		v6 = inet_pton(AF_INET6, name, &in6);

	/* Impossible combination? */
	 
	if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
	    (af == AF_INET && v6 == 1) ||
	    (have_v4 == 0 && v4 == 1) ||
	    (have_v6 == 0 && v6 == 1) ||
	    (have_v4 == 0 && af == AF_INET) ||
	    (have_v6 == 0 && af == AF_INET6)) {
		*error_num = HOST_NOT_FOUND;
		return (NULL);
	}

	/* Literal address? */
	if (v4 == 1 || v6 == 1) {
		char *addr_list[2];
		char *aliases[1];

		DE_CONST(name, he.h_name);
		he.h_addr_list = addr_list;
		he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
		he.h_addr_list[1] = NULL;
		he.h_aliases = aliases;
		he.h_aliases[0] = NULL;
		he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ;
		he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6;
		return (copyandmerge(&he, NULL, af, error_num));
	}

	options = net_data->res->options;
	net_data->res->options &= ~RES_USE_INET6;

	tmp_err = NO_RECOVERY;
	if (have_v6 && af == AF_INET6) {
		he2 = gethostbyname2_p(name, AF_INET6, net_data);
		if (he2 != NULL) {
			he1 = copyandmerge(he2, NULL, af, error_num);
			if (he1 == NULL)
				return (NULL);
			he2 = NULL;
		} else {
			tmp_err = net_data->res->res_h_errno;
		}
	}

	if (have_v4 &&
	    ((af == AF_INET) ||
	     (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&
	      (he1 == NULL || (flags & AI_ALL) != 0)))) {
		he2 = gethostbyname2_p(name, AF_INET, net_data);
		if (he1 == NULL && he2 == NULL) {
			*error_num = net_data->res->res_h_errno;
			return (NULL);
		} 
	} else
		*error_num = tmp_err;

	net_data->res->options = options;

	he3 = copyandmerge(he1, he2, af, error_num);

	if (he1 != NULL)
		freehostent(he1);
	return (he3);
}