libreswan/SOURCES/libreswan-4.4-getaddrinfo.p...

169 lines
5.3 KiB
Diff

diff -up ./lib/libswan/ttoaddress.c.getaddrinfo ./lib/libswan/ttoaddress.c
--- ./lib/libswan/ttoaddress.c.getaddrinfo 2021-04-22 17:24:33.000000000 +0200
+++ ./lib/libswan/ttoaddress.c 2021-07-22 13:16:19.073745043 +0200
@@ -20,6 +20,7 @@
#include <netdb.h> /* for gethostbyname2() */
#include "ip_address.h"
+#include "ip_sockaddr.h"
#include "ip_info.h"
#include "lswalloc.h" /* for alloc_things(), pfree() */
#include "lswlog.h" /* for pexpect() */
@@ -75,56 +76,6 @@ static err_t ttoaddr_base(shunk_t src,
}
/*
- * tryname - try it as a name
- *
- * Error return is intricate because we cannot compose a static string.
- */
-static err_t tryname(const char *p,
- int af,
- int suggested_af, /* kind(s) of numeric addressing tried */
- ip_address *dst)
-{
- struct hostent *h = gethostbyname2(p, af);
- if (h != NULL) {
- if (h->h_addrtype != af) {
- return "address-type mismatch from gethostbyname2!!!";
- }
-
- return data_to_address(h->h_addr, h->h_length, aftoinfo(af), dst);
- }
-
- if (af == AF_INET6) {
- if (suggested_af == AF_INET6) {
- return "not a numeric IPv6 address and name lookup failed (no validation performed)";
- } else /* AF_UNSPEC */ {
- return "not a numeric IPv4 or IPv6 address and name lookup failed (no validation performed)";
- }
- }
-
- pexpect(af == AF_INET);
-
- /* like, windows even has an /etc/networks? */
- struct netent *ne = getnetbyname(p);
- if (ne == NULL) {
- /* intricate because we cannot compose a static string */
- if (suggested_af == AF_INET) {
- return "not a numeric IPv4 address and name lookup failed (no validation performed)";
- } else {
- return "not a numeric IPv4 or IPv6 address and name lookup failed (no validation performed)";
- }
- }
-
- if (ne->n_addrtype != af) {
- return "address-type mismatch from getnetbyname!!!";
- }
-
- /* apparently .n_net is in host order */
- struct in_addr in = { htonl(ne->n_net), };
- *dst = address_from_in_addr(&in);
- return NULL;
-}
-
-/*
* tryhex - try conversion as an eight-digit hex number (AF_INET only)
*/
@@ -401,57 +352,56 @@ err_t getpiece(const char **srcp, /* *sr
err_t ttoaddress_dns(shunk_t src, const struct ip_info *afi, ip_address *dst)
{
+ char *name = clone_hunk_as_string(src, "ttoaddress_dns"); /* must free */
+ struct addrinfo *res = NULL;
+ const struct addrinfo hints = (struct addrinfo) {
+ .ai_family = afi == NULL ? AF_UNSPEC : afi->af,
+ };
*dst = unset_address;
- if (src.len == 0) {
- return "empty string";
- }
-
- bool was_numeric = true;
- err_t err = ttoaddr_base(src, afi, &was_numeric, dst);
- if (was_numeric) {
- /* no-point in continuing */
- return err;
- }
- /* err == non-numeric */
+ int eai = getaddrinfo(name, NULL, &hints, &res);
+ err_t err = NULL;
- for (const char *cp = src.ptr, *end = cp + src.len; cp < end; cp++) {
+ if (eai != 0) {
/*
- * Legal ASCII characters in a domain name.
- * Underscore technically is not, but is a common
- * misunderstanding. Non-ASCII characters are simply
- * exempted from checking at the moment, to allow for
- * UTF-8 encoded stuff; the purpose of this check is
- * merely to catch blatant errors.
- *
- * XXX: Suspect the ISASCII() check can be dropped -
- * utf-8 isn't allowed in DNS names and without a
- * utf-8 parser the check is flawed.
+ * return system-supplied diagnostic
+ * except where it is particularly confusing.
+ * "Name or service not unknown." is terrible.
*/
- static const char namechars[] =
- "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
-#define ISASCII(c) (((c) & 0x80) == 0)
- if (ISASCII(*cp) && strchr(namechars, *cp) == NULL) {
- return "illegal (non-DNS-name) character in name";
+ err = eai == EAI_NONAME ? "NAME is unknown" : gai_strerror(eai);
+ } else if (res == NULL) {
+ err = "not a numeric IP address and name lookup failed (no validation performed)";
+ } else {
+ /* always choose IPv4 result if there is one */
+ struct addrinfo *winner = res;
+
+ for (struct addrinfo *r = res; r!= NULL; r = r->ai_next) {
+ if (r->ai_family == AF_INET) {
+ winner = r;
+ break;
+ }
+ }
+
+ ip_port mbz = { .hport = 0 };
+ ip_sockaddr sa = {
+ .len = winner->ai_addrlen,
+ };
+ passert(sizeof(sa.sa) >= winner->ai_addrlen);
+ memcpy(&sa.sa, winner->ai_addr, winner->ai_addrlen);
+ passert(sa.sa.sa.sa_family == winner->ai_family);
+ /* boneheaded getaddrinfo(3) leaves port field uninitialized */
+ if (winner->ai_family == AF_INET) {
+ sa.sa.sin.sin_port = 0;
+ } else if (winner->ai_family == AF_INET6) {
+ sa.sa.sin6.sin6_port = 0;
+ } else {
+ bad_case(winner->ai_family);
}
+ err = sockaddr_to_address_port(sa, dst, &mbz);
+ passert(hport(mbz) == 0);
}
- /*
- * need a guarenteed null terminated string
- */
- char *name = clone_hunk_as_string(src, "ttoaddress_dns"); /* must free */
- int suggested_af = afi == NULL ? AF_UNSPEC : afi->af;
- err_t v4err = NULL, v6err = NULL;
- if (err && (suggested_af == AF_UNSPEC || suggested_af == AF_INET)) {
- err = v4err = tryname(name, AF_INET, suggested_af, dst);
- }
- if (err && (suggested_af == AF_UNSPEC || suggested_af == AF_INET6)) {
- err = v6err = tryname(name, AF_INET6, suggested_af, dst);
- }
- /* prefer the IPv4 error */
- if (err != NULL && v4err != NULL) {
- err = v4err;
- }
+ freeaddrinfo(res);
pfree(name);
return err;
}