From patchwork Sat Jun 23 10:08:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 387 X-Patchwork-Delegate: gert@greenie.muc.de Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id W91EEiapLlssTgAAIUCqbw for ; Sat, 23 Jun 2018 16:10:14 -0400 Received: from proxy7.mail.ord1d.rsapps.net ([172.30.191.6]) by director8.mail.ord1d.rsapps.net (Dovecot) with LMTP id W6QPEiapLltGJgAAfY0hYg ; Sat, 23 Jun 2018 16:10:14 -0400 Received: from smtp38.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy7.mail.ord1d.rsapps.net with LMTP id aLvoESapLlvKZQAAMe1Fpw ; Sat, 23 Jun 2018 16:10:14 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp38.gate.ord1d.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 6ff14ff4-7721-11e8-9b68-525400f6a58b-1-1 Received: from [216.105.38.7] ([216.105.38.7:54803] helo=lists.sourceforge.net) by smtp38.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 55/D0-06735-529AE2B5; Sat, 23 Jun 2018 16:10:13 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fWoqP-00087P-Sf; Sat, 23 Jun 2018 20:09:13 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fWoqO-00087I-2f for openvpn-devel@lists.sourceforge.net; Sat, 23 Jun 2018 20:09:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=dXySypwy+qIvqNf0EAW32k6Z9VSoqgehQIZwyZwmS7Q=; b=mQq02wQu8FQLwCR+hC26CZUkFH PVVQlSeE6GkqYV49SdIhUIw2R3nRAh7iOh0cUqEilKgce9gCZL/m4+sUQG0CSWUDtAApe27HOtZsi Yr/KQUF0jK7N4leqcA14fcmrhzmk9QIpk1JIef1dFLO/TqLC6qhtmWawK8bzOs95nqdQ=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=dXySypwy+qIvqNf0EAW32k6Z9VSoqgehQIZwyZwmS7Q=; b=ZJSND1O8SLbLgBfO3wE4KAhrP8 AkMILRB3TZfg9pKQm8QcOX/+lItVNGkmDwPFx/RkPIlwcN2wTmev9LLIk7HxqjQ5zJcKGpLGlyAdu TQHyM+dr17qC7uO4CZwt4QNx5QbhfWYHRzPjQt55wjP4JBaQsgdydyQSOeQyCsCAYUcw=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fWoqL-006tuJ-PZ for openvpn-devel@lists.sourceforge.net; Sat, 23 Jun 2018 20:09:12 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Sun, 24 Jun 2018 04:08:44 +0800 Message-Id: <20180623200844.32598-1-a@unstable.cc> In-Reply-To: <20180608052017.6696-5-a@unstable.cc> References: <20180608052017.6696-5-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_PASS SPF: sender matches SPF record 0.1 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1fWoqL-006tuJ-PZ Subject: [Openvpn-devel] [PATCH v3 4/8] pool: allow to configure an IPv6-only ifconfig-pool X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Antonio Quartulli With this change a server is allowed to allocate an IPv6-only pool. This is required to make it capable of managing an IPv6-only tunnel. Trac: #208 Signed-off-by: Antonio Quartulli --- Changes from v2: - patchset rebased on top of current master - introduce missing condition in multi.c (it was previously added with patch 5/8) src/openvpn/multi.c | 10 +++- src/openvpn/pool.c | 139 ++++++++++++++++++++++++++++++-------------- src/openvpn/pool.h | 8 ++- 3 files changed, 109 insertions(+), 48 deletions(-) diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 3da8c110..dbc8f370 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -388,7 +388,8 @@ multi_init(struct multi_context *m, struct context *t, bool tcp_mode, int thread * differently based on whether a tun or tap style * tunnel. */ - if (t->options.ifconfig_pool_defined) + if (t->options.ifconfig_pool_defined + || t->options.ifconfig_ipv6_pool_defined) { int pool_type = IFCONFIG_POOL_INDIV; @@ -397,7 +398,8 @@ multi_init(struct multi_context *m, struct context *t, bool tcp_mode, int thread pool_type = IFCONFIG_POOL_30NET; } - m->ifconfig_pool = ifconfig_pool_init(pool_type, + m->ifconfig_pool = ifconfig_pool_init(t->options.ifconfig_pool_defined, + pool_type, t->options.ifconfig_pool_start, t->options.ifconfig_pool_end, t->options.duplicate_cn, @@ -1497,7 +1499,9 @@ multi_select_virtual_addr(struct multi_context *m, struct multi_instance *mi) const int tunnel_topology = TUNNEL_TOPOLOGY(mi->context.c1.tuntap); msg( M_INFO, "MULTI_sva: pool returned IPv4=%s, IPv6=%s", - print_in_addr_t( remote, 0, &gc ), + (mi->context.options.ifconfig_pool_defined + ? print_in_addr_t(remote, 0, &gc) + : "(Not enabled)"), (mi->context.options.ifconfig_ipv6_pool_defined ? print_in6_addr( remote_ipv6, 0, &gc ) : "(Not enabled)") ); diff --git a/src/openvpn/pool.c b/src/openvpn/pool.c index 5d503a33..08addc6f 100644 --- a/src/openvpn/pool.c +++ b/src/openvpn/pool.c @@ -58,6 +58,22 @@ ifconfig_pool_entry_free(struct ifconfig_pool_entry *ipe, bool hard) } } +static const int +ifconfig_pool_size(const struct ifconfig_pool *pool) +{ + /* at least one pool is enabled, but base logic on IPv4 if both are, because + * it is always smaller + */ + if (pool->ipv4.enabled) + { + return pool->ipv4.size; + } + else + { + return pool->ipv6.size; + } +} + static int ifconfig_pool_find(struct ifconfig_pool *pool, const char *common_name) { @@ -65,8 +81,11 @@ ifconfig_pool_find(struct ifconfig_pool *pool, const char *common_name) time_t earliest_release = 0; int previous_usage = -1; int new_usage = -1; + int pool_size; + + pool_size = ifconfig_pool_size(pool); - for (i = 0; i < pool->ipv4.size; ++i) + for (i = 0; i < pool_size; ++i) { struct ifconfig_pool_entry *ipe = &pool->list[i]; if (!ipe->in_use) @@ -147,34 +166,40 @@ ifconfig_pool_verify_range(const int msglevel, const in_addr_t start, const in_a } struct ifconfig_pool * -ifconfig_pool_init(enum pool_type type, in_addr_t start, in_addr_t end, - const bool duplicate_cn, +ifconfig_pool_init(const bool ipv4_pool, enum pool_type type, in_addr_t start, + in_addr_t end, const bool duplicate_cn, const bool ipv6_pool, const struct in6_addr ipv6_base, const int ipv6_netbits ) { struct gc_arena gc = gc_new(); struct ifconfig_pool *pool = NULL; + int pool_size = -1; ASSERT(start <= end && end - start < IFCONFIG_POOL_MAX); ALLOC_OBJ_CLEAR(pool, struct ifconfig_pool); - pool->ipv4.type = type; pool->duplicate_cn = duplicate_cn; - switch (pool->ipv4.type) + pool->ipv4.enabled = ipv4_pool; + + if (pool->ipv4.enabled) { - case IFCONFIG_POOL_30NET: - pool->ipv4.base = start & ~3; - pool->ipv4.size = (((end | 3) + 1) - pool->ipv4.base) >> 2; - break; + pool->ipv4.type = type; + switch (pool->ipv4.type) + { + case IFCONFIG_POOL_30NET: + pool->ipv4.base = start & ~3; + pool->ipv4.size = (((end | 3) + 1) - pool->ipv4.base) >> 2; + break; - case IFCONFIG_POOL_INDIV: - pool->ipv4.base = start; - pool->ipv4.size = end - start + 1; - break; + case IFCONFIG_POOL_INDIV: + pool->ipv4.base = start; + pool->ipv4.size = end - start + 1; + break; - default: - ASSERT(0); + default: + ASSERT(0); + } } /* IPv6 pools are always "INDIV" type */ @@ -189,19 +214,27 @@ ifconfig_pool_init(enum pool_type type, in_addr_t start, in_addr_t end, msg( D_IFCONFIG_POOL, "IFCONFIG POOL IPv6: (IPv4) size=%d, size_ipv6=%d, netbits=%d, base_ipv6=%s", pool->ipv4.size, pool->ipv6.size, ipv6_netbits, print_in6_addr(pool->ipv6.base, 0, &gc)); + } - /* the current code is very simple and assumes that the IPv6 - * pool is at least as big as the IPv4 pool, and we don't need - * to do separate math etc. for IPv6 - */ + /* the current code is very simple and assumes that the IPv6 + * pool is at least as big as the IPv4 pool, and we don't need + * to do separate math etc. for IPv6 + */ + if (pool->ipv4.enabled && pool->ipv6.enabled) + { ASSERT(pool->ipv4.size < pool->ipv6.size); } - ALLOC_ARRAY_CLEAR(pool->list, struct ifconfig_pool_entry, pool->ipv4.size); + pool_size = ifconfig_pool_size(pool); + + ALLOC_ARRAY_CLEAR(pool->list, struct ifconfig_pool_entry, pool_size); - msg(D_IFCONFIG_POOL, "IFCONFIG POOL: base=%s size=%d, ipv6=%d", - print_in_addr_t(pool->ipv4.base, 0, &gc), - pool->ipv4.size, pool->ipv6.enabled); + if (pool->ipv4.enabled) + { + msg(D_IFCONFIG_POOL, "IFCONFIG POOL: base=%s size=%d, ipv6=%d", + print_in_addr_t(pool->ipv4.base, 0, &gc), pool->ipv4.size, + pool->ipv6.enabled); + } gc_free(&gc); return pool; @@ -212,8 +245,11 @@ ifconfig_pool_free(struct ifconfig_pool *pool) { if (pool) { - int i; - for (i = 0; i < pool->ipv4.size; ++i) + int i, pool_size; + + pool_size = ifconfig_pool_size(pool); + + for (i = 0; i < pool_size; ++i) { ifconfig_pool_entry_free(&pool->list[i], true); } @@ -239,26 +275,29 @@ ifconfig_pool_acquire(struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *r ipe->common_name = string_alloc(common_name, NULL); } - switch (pool->ipv4.type) + if (pool->ipv4.enabled && local && remote) { - case IFCONFIG_POOL_30NET: + switch (pool->ipv4.type) { - in_addr_t b = pool->ipv4.base + (i << 2); - *local = b + 1; - *remote = b + 2; - break; - } + case IFCONFIG_POOL_30NET: + { + in_addr_t b = pool->ipv4.base + (i << 2); + *local = b + 1; + *remote = b + 2; + break; + } - case IFCONFIG_POOL_INDIV: - { - in_addr_t b = pool->ipv4.base + i; - *local = 0; - *remote = b; - break; - } + case IFCONFIG_POOL_INDIV: + { + in_addr_t b = pool->ipv4.base + i; + *local = 0; + *remote = b; + break; + } - default: - ASSERT(0); + default: + ASSERT(0); + } } /* IPv6 pools are always INDIV (--linear) */ @@ -274,7 +313,9 @@ bool ifconfig_pool_release(struct ifconfig_pool *pool, ifconfig_pool_handle hand, const bool hard) { bool ret = false; - if (pool && hand >= 0 && hand < pool->ipv4.size) + int pool_size = ifconfig_pool_size(pool); + + if (pool && hand >= 0 && hand < pool_size) { ifconfig_pool_entry_free(&pool->list[hand], hard); ret = true; @@ -286,6 +327,7 @@ ifconfig_pool_release(struct ifconfig_pool *pool, ifconfig_pool_handle hand, con * private access functions */ +/* currently handling IPv4 logic only */ static ifconfig_pool_handle ifconfig_pool_ip_base_to_handle(const struct ifconfig_pool *pool, const in_addr_t addr) { @@ -380,9 +422,9 @@ ifconfig_pool_list(const struct ifconfig_pool *pool, struct status_output *out) if (pool && out) { struct gc_arena gc = gc_new(); - int i; + int i, pool_size = ifconfig_pool_size(pool); - for (i = 0; i < pool->ipv4.size; ++i) + for (i = 0; i < pool_size; ++i) { const struct ifconfig_pool_entry *e = &pool->list[i]; if (e->common_name) @@ -475,6 +517,15 @@ ifconfig_pool_read(struct ifconfig_pool_persist *persist, struct ifconfig_pool * const int buf_size = 128; update_time(); + + /* IPv6 logic not implemented yet, therefore bail out if no IPv4 pool was + * configured + */ + if (pool && !pool->ipv4.enabled) + { + return; + } + if (persist && persist->file && pool) { struct gc_arena gc = gc_new(); diff --git a/src/openvpn/pool.h b/src/openvpn/pool.h index 73ea5599..6af04645 100644 --- a/src/openvpn/pool.h +++ b/src/openvpn/pool.h @@ -52,6 +52,7 @@ struct ifconfig_pool { bool duplicate_cn; struct { + bool enabled; enum pool_type type; in_addr_t base; int size; @@ -72,7 +73,12 @@ struct ifconfig_pool_persist typedef int ifconfig_pool_handle; -struct ifconfig_pool *ifconfig_pool_init(enum pool_type type, in_addr_t start, in_addr_t end, const bool duplicate_cn, const bool ipv6_pool, const struct in6_addr ipv6_base, const int ipv6_netbits ); +struct ifconfig_pool *ifconfig_pool_init(const bool ipv4_pool, + enum pool_type type, in_addr_t start, + in_addr_t end, const bool duplicate_cn, + const bool ipv6_pool, + const struct in6_addr ipv6_base, + const int ipv6_netbits); void ifconfig_pool_free(struct ifconfig_pool *pool);