From patchwork Fri Feb 10 03:36:07 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Antonio Quartulli
X-Patchwork-Id: 10
X-Patchwork-Delegate: gert@greenie.muc.de
Return-Path:
Delivered-To: patchwork@openvpn.net
Delivered-To: patchwork@openvpn.net
Received: from director3.mail.ord1d.rsapps.net ([172.30.157.9])
by backend31.mail.ord1d.rsapps.net (Dovecot) with LMTP id
SDRMEi4f1VkHbAAAgoeIoA
for ; Wed, 04 Oct 2017 13:49:34 -0400
Received: from director3.mail.ord1c.rsapps.net ([172.28.140.3])
by director3.mail.ord1d.rsapps.net (Dovecot) with LMTP id
1i7rA5To1FlXNwAAkXNnRw
; Wed, 04 Oct 2017 13:49:34 -0400
Received: from smtp42.gate.ord1c ([172.28.255.1])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
by director3.mail.ord1c.rsapps.net (Dovecot) with LMTP id
RxE0HfcT1VkyPgAAdSFV8w
; Wed, 04 Oct 2017 13:49:34 -0400
X-Spam-Threshold: 95
X-Spam-Score: 0
X-Spam-Flag: NO
Authentication-Results: smtp42.gate.ord1c.rsapps.net x-tls.subject="/OU=Domain
Control Validated/CN=www.neomailbox.net";
auth=pass (cipher=DHE-RSA-AES256-GCM-SHA384)
X-Virus-Scanned: OK
X-MessageSniffer-Scan-Result: 0
X-MessageSniffer-Rules: 0-0-0-18171-c
X-CMAE-Scan-Result: 0
X-CNFS-Analysis: v=2.2 cv=KPQYNxNo c=1 sm=1 tr=0
a=7mfUwURtZ2JVSadOwpfSCg==:117 a=7mfUwURtZ2JVSadOwpfSCg==:17
a=kj9zAlcOel0A:10 a=MKtGQD3n3ToA:10 a=1oJP67jkp3AA:10 a=5ExyEf0gzOwA:10
a=WiVod9pSvdkA:10 a=ZZnuYtJkoWoA:10 a=9sSjY8p1AAAA:8 a=P_JWiMecAAAA:8
a=FP58Ms26AAAA:8 a=p9nSlrJrq98JOfEPj_sA:9 a=bjhPGSVf4rMSFykC:21
a=ictTcrSkTpM8Fehb:21 a=CjuIK1q_8ugA:10 a=-FEs8UIgK8oA:10 a=NWVoK91CQyQA:10
a=ub54wNWiXv_DzeFsgEJW:22 a=D0-HAvA3Hk9NMREbgwuX:22
X-Orig-To: patchwork@openvpn.net
X-Originating-Ip: [5.148.176.60]
Authentication-Results: smtp42.gate.ord1c.rsapps.net;
iprev=pass policy.iprev="5.148.176.60";
spf=permerror smtp.mailfrom="a@unstable.cc" smtp.helo="s2.neomailbox.net";
dkim=none (message not signed) header.d=none; dmarc=none (p=nil;
dis=none) header.from=unstable.cc
X-Classification-ID: 6061fd54-a92c-11e7-bfd9-b8ca3a655ab8-1-1
Received: from [5.148.176.60] ([5.148.176.60:32617] helo=s2.neomailbox.net)
by smtp42.gate.ord1c.rsapps.net (envelope-from )
(ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS
(cipher=DHE-RSA-AES256-GCM-SHA384
subject="/OU=Domain Control Validated/CN=www.neomailbox.net")
id 76/9E-17544-D2F15D95; Wed, 04 Oct 2017 13:49:34 -0400
Resent-From: Antonio Quartulli
Resent-To: patchwork@openvpn.net
Resent-Date: Thu, 5 Oct 2017 01:47:42 +0800
Resent-Message-ID: <7a07ede7-2634-54f5-2834-876a0a3b4516@unstable.cc>
Resent-User-Agent: Mozilla/5.0 (X11; Linux x86_64;
rv:52.0) Gecko/20100101 Thunderbird/52.3.0
From: Antonio Quartulli
To: openvpn-devel@lists.sourceforge.net
Date: Fri, 10 Feb 2017 22:36:07 +0800
Message-Id: <20170210143607.19454-1-a@unstable.cc>
X-Spam-Report: Spam Filtering performed by mx.sourceforge.net.
See http://spamassassin.org/tag/ for more details.
-0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/,
no trust [5.148.176.60 listed in list.dnswl.org]
-0.0 SPF_HELO_PASS SPF: HELO matches SPF record
0.0 AWL AWL: Adjusted score from AWL reputation of From: address
X-Headers-End: 1ccCJU-0004E9-OS
Cc: Antonio Quartulli
Subject: [Openvpn-devel] [PATCH] ifconfig-ipv6(-push): allow using hostnames
X-BeenThere: openvpn-devel@lists.sourceforge.net
X-Mailman-Version: 2.1.9
Precedence: list
List-Id:
List-Unsubscribe:
,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
MIME-Version: 1.0
Errors-To: openvpn-devel-bounces@lists.sourceforge.net
X-SA-Score: -4.9
X-getmail-retrieved-from-mailbox: Inbox
Similarly to ifconfig(-push), its IPv6 counterpart is now able to
accept hostnames as well instead of IP addresses in numeric form.
Basically this means that the user is now allowed to specify
something like this:
ifconfig-ipv6-push my.hostname.cx/64
This is exactly the same behaviour that we already have with
ifconfig(-push).
The generic code introduced in this patch will be later used to
implement the /bits parsing support for IPv4 addresses.
Trac: #808
Signed-off-by: Antonio Quartulli
---
src/openvpn/options.c | 61 ------------------------
src/openvpn/options.h | 4 --
src/openvpn/socket.c | 126 +++++++++++++++++++++++++++++++++++++++++++++-----
src/openvpn/socket.h | 12 +++++
4 files changed, 126 insertions(+), 77 deletions(-)
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 17bf5a44..817fd54d 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -1026,67 +1026,6 @@ get_ip_addr(const char *ip_string, int msglevel, bool *error)
return ret;
}
-/* helper: parse a text string containing an IPv6 address + netbits
- * in "standard format" (2001:dba::/32)
- * "/nn" is optional, default to /64 if missing
- *
- * return true if parsing succeeded, modify *network and *netbits
- */
-bool
-get_ipv6_addr( const char *prefix_str, struct in6_addr *network,
- unsigned int *netbits, int msglevel)
-{
- char *sep, *endp;
- int bits;
- struct in6_addr t_network;
-
- sep = strchr( prefix_str, '/' );
- if (sep == NULL)
- {
- bits = 64;
- }
- else
- {
- bits = strtol( sep+1, &endp, 10 );
- if (*endp != '\0' || bits < 0 || bits > 128)
- {
- msg(msglevel, "IPv6 prefix '%s': invalid '/bits' spec", prefix_str);
- return false;
- }
- }
-
- /* temporary replace '/' in caller-provided string with '\0', otherwise
- * inet_pton() will refuse prefix string
- * (alternative would be to strncpy() the prefix to temporary buffer)
- */
-
- if (sep != NULL)
- {
- *sep = '\0';
- }
-
- if (inet_pton( AF_INET6, prefix_str, &t_network ) != 1)
- {
- msg(msglevel, "IPv6 prefix '%s': invalid IPv6 address", prefix_str);
- return false;
- }
-
- if (sep != NULL)
- {
- *sep = '/';
- }
-
- if (netbits != NULL)
- {
- *netbits = bits;
- }
- if (network != NULL)
- {
- *network = t_network;
- }
- return true; /* parsing OK, values set */
-}
-
/**
* Returns newly allocated string containing address part without "/nn".
*
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index dc63aeda..5186f24a 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -811,8 +811,4 @@ void options_string_import(struct options *options,
unsigned int *option_types_found,
struct env_set *es);
-bool get_ipv6_addr( const char *prefix_str, struct in6_addr *network,
- unsigned int *netbits, int msglevel );
-
-
#endif /* ifndef OPTIONS_H */
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 82d0967d..55ff7737 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -75,12 +75,102 @@ sf2gaf(const unsigned int getaddr_flags,
/*
* Functions related to the translation of DNS names to IP addresses.
*/
+static int
+get_addr_generic(sa_family_t af, unsigned int flags, const char *hostname,
+ void *network, unsigned int *netbits,
+ int resolve_retry_seconds, volatile int *signal_received,
+ int msglevel)
+{
+ char *endp, *sep, *var_host;
+ uint8_t bits, max_bits;
+ struct addrinfo *ai;
+ int ret = -1;
+
+ ASSERT(hostname);
+
+ /* assign family specific default values */
+ switch (af)
+ {
+ case AF_INET:
+ bits = 0;
+ max_bits = sizeof(in_addr_t) * 8;
+ break;
+ case AF_INET6:
+ bits = 64;
+ max_bits = sizeof(struct in6_addr) * 8;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ /* we need to modify the hostname received as input, but we don't want to
+ * touch it directly as it might be a constant string.
+ *
+ * Therefore, we clone the string here and free it at the end of the
+ * function */
+ var_host = strdup(hostname);
+ ASSERT(var_host);
+
+ /* check if this hostname has a /bits suffix */
+ sep = strchr(var_host , '/');
+ if (sep)
+ {
+ bits = strtoul(sep + 1, &endp, 10);
+ if ((*endp != '\0') || (bits > max_bits))
+ {
+ msg(msglevel, "IP prefix '%s': invalid '/bits' spec", hostname);
+ goto out;
+ }
+ /* temporary truncate string at '/'. This allows the IP
+ * parsing routines to properly work. Will be restored later.
+ */
+ *sep = '\0';
+ }
+
+ ret = openvpn_getaddrinfo(flags & ~GETADDR_HOST_ORDER, var_host, NULL,
+ resolve_retry_seconds, signal_received, af, &ai);
+ if ((ret == 0) && network)
+ {
+ struct in6_addr *ip6;
+ in_addr_t *ip4;
+
+ switch (af)
+ {
+ case AF_INET:
+ ip4 = network;
+ *ip4 = ((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr;
+
+ if (flags & GETADDR_HOST_ORDER)
+ {
+ *ip4 = ntohl(*ip4);
+ }
+ break;
+ case AF_INET6:
+ ip6 = network;
+ *ip6 = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
+ break;
+ default:
+ ASSERT(0);
+ }
+ freeaddrinfo(ai);
+ }
+
+ if (netbits)
+ {
+ *netbits = bits;
+ }
+
+ /* restore '/' separator, if any */
+ if (sep)
+ {
+ *sep = '/';
+ }
+out:
+ free(var_host);
+
+ return ret;
+}
-/*
- * Translate IP addr or hostname to in_addr_t.
- * If resolve error, try again for
- * resolve_retry_seconds seconds.
- */
in_addr_t
getaddr(unsigned int flags,
const char *hostname,
@@ -88,20 +178,19 @@ getaddr(unsigned int flags,
bool *succeeded,
volatile int *signal_received)
{
- struct addrinfo *ai;
+ in_addr_t addr;
int status;
- status = openvpn_getaddrinfo(flags & ~GETADDR_HOST_ORDER, hostname, NULL,
- resolve_retry_seconds, signal_received, AF_INET, &ai);
+
+ status = get_addr_generic(AF_INET, flags, hostname, &addr, NULL,
+ resolve_retry_seconds, signal_received,
+ M_WARN);
if (status==0)
{
- struct in_addr ia;
if (succeeded)
{
*succeeded = true;
}
- ia = ((struct sockaddr_in *)ai->ai_addr)->sin_addr;
- freeaddrinfo(ai);
- return (flags & GETADDR_HOST_ORDER) ? ntohl(ia.s_addr) : ia.s_addr;
+ return addr;
}
else
{
@@ -113,6 +202,19 @@ getaddr(unsigned int flags,
}
}
+bool
+get_ipv6_addr(const char *hostname, struct in6_addr *network,
+ unsigned int *netbits, int msglevel)
+{
+ if (get_addr_generic(AF_INET6, GETADDR_RESOLVE, hostname, network, netbits,
+ 0, NULL, msglevel) < 0)
+ {
+ return false;
+ }
+
+ return true; /* parsing OK, values set */
+}
+
static inline bool
streqnull(const char *a, const char *b)
{
diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h
index 3d96aab0..5e525fe7 100644
--- a/src/openvpn/socket.h
+++ b/src/openvpn/socket.h
@@ -533,12 +533,24 @@ bool unix_socket_get_peer_uid_gid(const socket_descriptor_t sd, int *uid, int *g
#define GETADDR_CACHE_MASK (GETADDR_DATAGRAM|GETADDR_PASSIVE)
+/**
+ * Translate an IPv4 addr or hostname from string form to in_addr_t
+ *
+ * In case of resolve error, it will try again for
+ * resolve_retry_seconds seconds.
+ */
in_addr_t getaddr(unsigned int flags,
const char *hostname,
int resolve_retry_seconds,
bool *succeeded,
volatile int *signal_received);
+/**
+ * Translate an IPv6 addr or hostname from string form to in6_addr
+ */
+bool get_ipv6_addr(const char *hostname, struct in6_addr *network,
+ unsigned int *netbits, int msglevel);
+
int openvpn_getaddrinfo(unsigned int flags,
const char *hostname,
const char *servname,