Commit 960ed256 authored by Natanael Copa's avatar Natanael Copa
Browse files

main/openvpn: upgrade to 2.3.0

fixes #797
parent 739d6978
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=openvpn
pkgver=2.2.2
pkgver=2.3.0
pkgrel=0
pkgdesc="A robust, and highly configurable VPN (Virtual Private Network)"
url="http://openvpn.sourceforge.net/"
arch="all"
license="custom"
subpackages="$pkgname-doc $pkgname-easy-rsa:easy_rsa"
subpackages="$pkgname-dev $pkgname-doc $pkgname-auth-pam:pam"
depends="iproute2"
makedepends="openssl-dev lzo-dev"
makedepends="openssl-dev lzo-dev linux-pam-dev"
install="$pkgname.pre-install"
source="http://swupdate.openvpn.net/community/releases/$pkgname-$pkgver.tar.gz
openvpn.initd
openvpn.confd
openvpn.up
openvpn.down
openvpn-2.2.2-ipv6.patch
"
_builddir="$srcdir"/$pkgname-$pkgver
......@@ -37,7 +36,7 @@ build() {
--sysconfdir=/etc/openvpn \
--enable-ssl \
--enable-crypto \
--disable-threads \
--enable-password-save \
--enable-iproute2
make || return 1
......@@ -50,14 +49,12 @@ package() {
cd "$_builddir"
make DESTDIR="$pkgdir" install || return 1
rm "$pkgdir"/usr/lib/openvpn/plugins/*.la || return 1
# install plugins
install -d "$pkgdir"/usr/lib/$pkgname
cp plugin/*/*.so "$pkgdir"/usr/lib/$pkgname
# install examples
mkdir -p "$pkgdir"/usr/share/doc/$pkgname/examples
cp -a sample-config-files "$pkgdir"/usr/share/doc/$pkgname/examples
# install samples
mkdir -p "$pkgdir"/usr/share/doc/$pkgname/samples
cp -a sample/sample-* "$pkgdir"/usr/share/doc/$pkgname/samples \
|| return 1
install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
# install init.d and conf.d
......@@ -70,27 +67,25 @@ package() {
}
easy_rsa() {
pkgdesc="OpenVPN RSA key management"
# easy rsa can by usefull on systems
# which do not have openvpn installed
depends="openssl"
# install easy-rsa
cd "$_builddir"
sed -i -e 's/--directory/-d/g; s/--mode=/-m/g' easy-rsa/2.0/Makefile
sed -i -e '1s|#!/bin/bash|#!/bin/sh|' easy-rsa/2.0/*
make -C easy-rsa/2.0 DESTDIR="$subpkgdir" \
PREFIX=usr/share/doc/openvpn/easy-rsa \
install
}
doc() {
default_doc
pam() {
pkgdesc="OpenVPN plugin for PAM authentication"
mkdir -p "$subpkgdir"/usr/lib/openvpn/plugins
mv "$pkgdir"/usr/lib/openvpn/plugins/*-auth-pam* \
"$subpkgdir"/usr/lib/openvpn/plugins/
}
md5sums="c5181e27b7945fa6276d21873329c5c7 openvpn-2.2.2.tar.gz
md5sums="56cffde5d5320e0b1ec364d3e486aca9 openvpn-2.3.0.tar.gz
ec99092827faa7226e9f548c2cd1d20c openvpn.initd
9eca88cac6294027ec1bb7be74185c3a openvpn.confd
dc72fecd1a1bcef937603057cd6574b1 openvpn.up
dc3ff0bae442b9aedd947b8ffda1687a openvpn.down
51b1ddade743505b84d27db9ebfd6c0a openvpn-2.2.2-ipv6.patch"
dc3ff0bae442b9aedd947b8ffda1687a openvpn.down"
sha256sums="4602a8d0f66dfa6ac10b7abfeba35260d7d4c570948f6eba5f8216ffa3a2c490 openvpn-2.3.0.tar.gz
4cc6e77384ddc41d0356ae0703c527c61f78d6ef89523f78944e75158b885e05 openvpn.initd
330149a83684ddabe413d134d4c8efad4c88b18c2ab67165014deff5f7fffad2 openvpn.confd
848da0929c37b2112769232fbbdf61961b6107c6726d4b74d1ceb034b39ad5dd openvpn.up
39debebcd8c899f20e6d355cbc8eaab46e28b83a9f6c33a94c065688a4f3d2c7 openvpn.down"
sha512sums="ebac619dd746406d6751d84391480f7eae2b6c442bbacf1ce6e3d21952ee85bccc7ca2d526fe04cb7ecde749d2a5abb4e787c0e63c349818c7129f5747a2769a openvpn-2.3.0.tar.gz
da7a29ad3d367d8bad5f20a63208418dc46f20916bb6a6dbd9e26765e7bb5193eab0465ab71b11d3957fec30610e612681ee1a1e3cbd9d7fc41cae6b8824f724 openvpn.initd
982ade883afbe2e656a9cbbe36c31c0e8b4f7bbbe5b63df9f7b834f02a9153032fb7445c85d3e91f62c68a7ddd13c3afbf420fb71cdd13d9c4b69f867bdd9f37 openvpn.confd
f904d6125ed1ddb48ea632c3b290a7a4a7a7436be0d46b323fc8c92f919f9d076fdc78ff7bed0dd65675f0bc3559e531e372b805fc11ef287efeeb4d54fe52f4 openvpn.up
5defd61edf11cc63f3f8f60bef7fa730c4bcdd2545d664bd94666dd3aea80bd9d190263d8835a555e4287a594f6fce0f52426aed49c60233ff637a2a6164a997 openvpn.down"
diff --git a/forward.c b/forward.c
index 87d05cc..1f3d435 100644
--- a/forward.c
+++ b/forward.c
@@ -262,7 +262,8 @@ send_control_channel_string (struct context *c, const char *str, int msglevel)
static void
check_add_routes_action (struct context *c, const bool errors)
{
- do_route (&c->options, c->c1.route_list, c->c1.tuntap, c->plugins, c->c2.es);
+ do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
+ c->c1.tuntap, c->plugins, c->c2.es);
update_time ();
event_timeout_clear (&c->c2.route_wakeup);
event_timeout_clear (&c->c2.route_wakeup_expire);
diff --git a/helper.c b/helper.c
index a9d7fd9..266b246 100644
--- a/helper.c
+++ b/helper.c
@@ -142,6 +142,55 @@ helper_client_server (struct options *o)
#if P2MP
#if P2MP_SERVER
+
+ /*
+ *
+ * HELPER DIRECTIVE for IPv6
+ *
+ * server-ipv6 2001:db8::/64
+ *
+ * EXPANDS TO:
+ *
+ * tun-ipv6
+ * push "tun-ipv6"
+ * ifconfig-ipv6 2001:db8::1 2001:db8::2
+ * if !nopool:
+ * ifconfig-ipv6-pool 2001:db8::1:0/64
+ *
+ */
+ if ( o->server_ipv6_defined )
+ {
+ if ( ! o->server_defined )
+ {
+ msg (M_USAGE, "--server-ipv6 must be used together with --server");
+ }
+ if ( o->server_flags & SF_NOPOOL )
+ {
+ msg( M_USAGE, "--server-ipv6 is incompatible with 'nopool' option" );
+ }
+ if ( o->ifconfig_ipv6_pool_defined )
+ {
+ msg( M_USAGE, "--server-ipv6 already defines an ifconfig-ipv6-pool, so you can't also specify --ifconfig-pool explicitly");
+ }
+
+ /* local ifconfig is "base address + 1" and "+2" */
+ o->ifconfig_ipv6_local =
+ print_in6_addr( add_in6_addr( o->server_network_ipv6, 1), 0, &o->gc );
+ o->ifconfig_ipv6_remote =
+ print_in6_addr( add_in6_addr( o->server_network_ipv6, 2), 0, &o->gc );
+
+ /* pool starts at "base address + 0x10000" */
+ ASSERT( o->server_netbits_ipv6 < 96 ); /* want 32 bits */
+ o->ifconfig_ipv6_pool_defined = true;
+ o->ifconfig_ipv6_pool_base =
+ add_in6_addr( o->server_network_ipv6, 0x10000 );
+ o->ifconfig_ipv6_pool_netbits = o->server_netbits_ipv6;
+
+ o->tun_ipv6 = true;
+
+ push_option( o, "tun-ipv6", M_USAGE );
+ }
+
/*
*
* HELPER DIRECTIVE:
diff --git a/init.c b/init.c
index d47a4ef..7fc8eb7 100644
--- a/init.c
+++ b/init.c
@@ -843,7 +843,7 @@ do_persist_tuntap (const struct options *options)
msg (M_FATAL|M_OPTERR,
"options --mktun or --rmtun should only be used together with --dev");
tuncfg (options->dev, options->dev_type, options->dev_node,
- options->tun_ipv6, options->persist_mode,
+ options->persist_mode,
options->username, options->groupname, &options->tuntap_options);
if (options->persist_mode && options->lladdr)
set_lladdr(options->dev, options->lladdr, NULL);
@@ -1066,6 +1066,8 @@ do_alloc_route_list (struct context *c)
{
if (c->options.routes && !c->c1.route_list)
c->c1.route_list = new_route_list (c->options.max_routes, &c->gc);
+ if (c->options.routes_ipv6 && !c->c1.route_ipv6_list)
+ c->c1.route_ipv6_list = new_route_ipv6_list (c->options.max_routes, &c->gc);
}
@@ -1108,6 +1110,45 @@ do_init_route_list (const struct options *options,
}
}
+static void
+do_init_route_ipv6_list (const struct options *options,
+ struct route_ipv6_list *route_ipv6_list,
+ bool fatal,
+ struct env_set *es)
+{
+ const char *gw = NULL;
+ int dev = dev_type_enum (options->dev, options->dev_type);
+ int metric = 0;
+
+ if (dev != DEV_TYPE_TUN )
+ msg( M_WARN, "IPv6 routes on TAP devices are going to fail on some platforms (need gateway spec)" ); /* TODO-GERT */
+
+ gw = options->ifconfig_ipv6_remote; /* default GW = remote end */
+#if 0 /* not yet done for IPv6 - TODO!*/
+ if ( options->route_ipv6_default_gateway ) /* override? */
+ gw = options->route_ipv6_default_gateway;
+#endif
+
+ if (options->route_default_metric)
+ metric = options->route_default_metric;
+
+ if (!init_route_ipv6_list (route_ipv6_list,
+ options->routes_ipv6,
+ gw,
+ metric,
+ es))
+ {
+ if (fatal)
+ openvpn_exit (OPENVPN_EXIT_STATUS_ERROR); /* exit point */
+ }
+ else
+ {
+ /* copy routes to environment */
+ setenv_routes_ipv6 (es, route_ipv6_list);
+ }
+}
+
+
/*
* Called after all initialization has been completed.
*/
@@ -1172,12 +1213,13 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
void
do_route (const struct options *options,
struct route_list *route_list,
+ struct route_ipv6_list *route_ipv6_list,
const struct tuntap *tt,
const struct plugin_list *plugins,
struct env_set *es)
{
- if (!options->route_noexec && route_list)
- add_routes (route_list, tt, ROUTE_OPTION_FLAGS (options), es);
+ if (!options->route_noexec && ( route_list || route_ipv6_list ) )
+ add_routes (route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS (options), es);
if (plugin_defined (plugins, OPENVPN_PLUGIN_ROUTE_UP))
{
@@ -1234,11 +1276,16 @@ do_init_tun (struct context *c)
c->options.topology,
c->options.ifconfig_local,
c->options.ifconfig_remote_netmask,
+ c->options.ifconfig_ipv6_local,
+ c->options.ifconfig_ipv6_remote,
addr_host (&c->c1.link_socket_addr.local),
addr_host (&c->c1.link_socket_addr.remote),
!c->options.ifconfig_nowarn,
c->c2.es);
+ /* flag tunnel for IPv6 config if --tun-ipv6 is set */
+ c->c1.tuntap->ipv6 = c->options.tun_ipv6;
+
init_tun_post (c->c1.tuntap,
&c->c2.frame,
&c->options.tuntap_options);
@@ -1270,6 +1317,8 @@ do_open_tun (struct context *c)
/* parse and resolve the route option list */
if (c->options.routes && c->c1.route_list && c->c2.link_socket)
do_init_route_list (&c->options, c->c1.route_list, &c->c2.link_socket->info, false, c->c2.es);
+ if (c->options.routes_ipv6 && c->c1.route_ipv6_list )
+ do_init_route_ipv6_list (&c->options, c->c1.route_ipv6_list, false, c->c2.es);
/* do ifconfig */
if (!c->options.ifconfig_noexec
@@ -1286,7 +1335,7 @@ do_open_tun (struct context *c)
/* open the tun device */
open_tun (c->options.dev, c->options.dev_type, c->options.dev_node,
- c->options.tun_ipv6, c->c1.tuntap);
+ c->c1.tuntap);
/* set the hardware address */
if (c->options.lladdr)
@@ -1315,7 +1364,8 @@ do_open_tun (struct context *c)
/* possibly add routes */
if (!c->options.route_delay_defined)
- do_route (&c->options, c->c1.route_list, c->c1.tuntap, c->plugins, c->c2.es);
+ do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
+ c->c1.tuntap, c->plugins, c->c2.es);
/*
* Did tun/tap driver give us an MTU?
@@ -1389,8 +1439,9 @@ do_close_tun (struct context *c, bool force)
#endif
/* delete any routes we added */
- if (c->c1.route_list)
- delete_routes (c->c1.route_list, c->c1.tuntap, ROUTE_OPTION_FLAGS (&c->options), c->c2.es);
+ if (c->c1.route_list || c->c1.route_ipv6_list )
+ delete_routes (c->c1.route_list, c->c1.route_ipv6_list,
+ c->c1.tuntap, ROUTE_OPTION_FLAGS (&c->options), c->c2.es);
/* actually close tun/tap device based on --down-pre flag */
if (!c->options.down_pre)
diff --git a/init.h b/init.h
index cf5ca8a..5a1d1dc 100644
--- a/init.h
+++ b/init.h
@@ -63,6 +63,7 @@ void init_instance (struct context *c, const struct env_set *env, const unsigned
void do_route (const struct options *options,
struct route_list *route_list,
+ struct route_ipv6_list *route_ipv6_list,
const struct tuntap *tt,
const struct plugin_list *plugins,
struct env_set *es);
diff --git a/misc.c b/misc.c
index 4067d85..9d351f4 100644
--- a/misc.c
+++ b/misc.c
@@ -1001,7 +1001,9 @@ setenv_str_ex (struct env_set *es,
{
const char *str = construct_name_value (name_tmp, val_tmp, &gc);
env_set_add (es, str);
- /*msg (M_INFO, "SETENV_ES '%s'", str);*/
+#if DEBUG_VERBOSE_SETENV
+ msg (M_INFO, "SETENV_ES '%s'", str);
+#endif
}
else
env_set_del (es, name_tmp);
diff --git a/mroute.c b/mroute.c
index 1b3488f..6cfec27 100644
--- a/mroute.c
+++ b/mroute.c
@@ -88,12 +88,33 @@ mroute_get_in_addr_t (struct mroute_addr *ma, const in_addr_t src, unsigned int
}
}
+static inline void
+mroute_get_in6_addr (struct mroute_addr *ma, const struct in6_addr src, unsigned int mask)
+{
+ if (ma)
+ {
+ ma->type = MR_ADDR_IPV6 | mask;
+ ma->netbits = 0;
+ ma->len = 16;
+ *(struct in6_addr *)ma->addr = src;
+ }
+}
+
static inline bool
mroute_is_mcast (const in_addr_t addr)
{
return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
}
+/* RFC 4291, 2.7, "binary 11111111 at the start of an address identifies
+ * the address as being a multicast address"
+ */
+static inline bool
+mroute_is_mcast_ipv6 (const struct in6_addr addr)
+{
+ return (addr.s6_addr[0] == 0xff);
+}
+
#ifdef ENABLE_PF
static unsigned int
@@ -157,13 +178,29 @@ mroute_extract_addr_ipv4 (struct mroute_addr *src,
}
break;
case 6:
- {
- if( !ipv6warned ) {
- msg (M_WARN, "IPv6 in tun mode is not supported in OpenVPN 2.2");
- ipv6warned = true;
- }
- break;
- }
+ if (BLEN (buf) >= (int) sizeof (struct openvpn_ipv6hdr))
+ {
+ const struct openvpn_ipv6hdr *ipv6 = (const struct openvpn_ipv6hdr *) BPTR (buf);
+#if 0 /* very basic debug */
+ struct gc_arena gc = gc_new ();
+ msg( M_INFO, "IPv6 packet! src=%s, dst=%s",
+ print_in6_addr( ipv6->saddr, 0, &gc ),
+ print_in6_addr( ipv6->daddr, 0, &gc ));
+ gc_free (&gc);
+#endif
+
+ mroute_get_in6_addr (src, ipv6->saddr, 0);
+ mroute_get_in6_addr (dest, ipv6->daddr, 0);
+
+ if (mroute_is_mcast_ipv6 (ipv6->daddr))
+ ret |= MROUTE_EXTRACT_MCAST;
+
+ ret |= MROUTE_EXTRACT_SUCCEEDED;
+ }
+ break;
+ default:
+ msg (M_WARN, "IP packet with unknown IP version=%d seen",
+ OPENVPN_IPH_GET_VER (*BPTR(buf)));
}
}
return ret;
@@ -257,14 +294,36 @@ bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
* Zero off the host bits in an address, leaving
* only the network bits, using the netbits member of
* struct mroute_addr as the controlling parameter.
+ *
+ * TODO: this is called for route-lookup for every yet-unhashed
+ * destination address, so for lots of active net-iroutes, this
+ * might benefit from some "zeroize 32 bit at a time" improvements
*/
void
mroute_addr_mask_host_bits (struct mroute_addr *ma)
{
in_addr_t addr = ntohl(*(in_addr_t*)ma->addr);
- ASSERT ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4);
- addr &= netbits_to_netmask (ma->netbits);
- *(in_addr_t*)ma->addr = htonl (addr);
+ if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4)
+ {
+ addr &= netbits_to_netmask (ma->netbits);
+ *(in_addr_t*)ma->addr = htonl (addr);
+ }
+ else if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV6)
+ {
+ int byte = ma->len-1; /* rightmost byte in address */
+ int bits_to_clear = 128 - ma->netbits;
+
+ while( byte >= 0 && bits_to_clear > 0 )
+ {
+ if ( bits_to_clear >= 8 )
+ { ma->addr[byte--] = 0; bits_to_clear -= 8; }
+ else
+ { ma->addr[byte--] &= (~0 << bits_to_clear); bits_to_clear = 0; }
+ }
+ ASSERT( bits_to_clear == 0 );
+ }
+ else
+ ASSERT(0);
}
/*
@@ -342,17 +401,24 @@ mroute_addr_print_ex (const struct mroute_addr *ma,
}
break;
case MR_ADDR_IPV6:
- buf_printf (&out, "IPV6");
- break;
- default:
- buf_printf (&out, "UNKNOWN");
- break;
- }
- return BSTR (&out);
- }
- else
- return "[NULL]";
-}
+ {
+ buf_printf (&out, "%s",
+ print_in6_addr( *(struct in6_addr*)&maddr.addr, 0, gc));
+ if (maddr.type & MR_WITH_NETBITS)
+ {
+ buf_printf (&out, "/%d", maddr.netbits);
+ }
+ }
+ break;
+ default:
+ buf_printf (&out, "UNKNOWN");
+ break;
+ }
+ return BSTR (&out);
+ }
+ else
+ return "[NULL]";
+ }
/*
* mroute_helper's main job is keeping track of
@@ -423,6 +489,40 @@ mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir)
}
}
+/* this is a bit inelegant, we really should have a helper to that
+ * is only passed the netbits value, and not the whole struct iroute *
+ * - thus one helper could do IPv4 and IPv6. For the sake of "not change
+ * code unrelated to IPv4" this is left for later cleanup, for now.
+ */
+void
+mroute_helper_add_iroute6 (struct mroute_helper *mh,
+ const struct iroute_ipv6 *ir6)
+{
+ if (ir6->netbits >= 0)
+ {
+ ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
+ ++mh->cache_generation;
+ ++mh->net_len_refcount[ir6->netbits];
+ if (mh->net_len_refcount[ir6->netbits] == 1)
+ mroute_helper_regenerate (mh);
+ }
+}
+
+void
+mroute_helper_del_iroute6 (struct mroute_helper *mh,
+ const struct iroute_ipv6 *ir6)
+{
+ if (ir6->netbits >= 0)
+ {
+ ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
+ ++mh->cache_generation;
+ --mh->net_len_refcount[ir6->netbits];
+ ASSERT (mh->net_len_refcount[ir6->netbits] >= 0);
+ if (!mh->net_len_refcount[ir6->netbits])
+ mroute_helper_regenerate (mh);
+ }
+}
+
void
mroute_helper_free (struct mroute_helper *mh)
{
diff --git a/mroute.h b/mroute.h
index 7265001..b72b5ff 100644
--- a/mroute.h
+++ b/mroute.h
@@ -85,7 +85,7 @@ struct mroute_addr {
/*
* Number of bits in an address. Should be raised for IPv6.
*/
-#define MR_HELPER_NET_LEN 32
+#define MR_HELPER_NET_LEN 129
/*
* Used to help maintain CIDR routing table.
@@ -127,6 +127,8 @@ struct mroute_helper *mroute_helper_init (int ageable_ttl_secs);
void mroute_helper_free (struct mroute_helper *mh);
void mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir);
void mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir);
+void mroute_helper_add_iroute6 (struct mroute_helper *mh, const struct iroute_ipv6 *ir6);
+void mroute_helper_del_iroute6 (struct mroute_helper *mh, const struct iroute_ipv6 *ir6);
/*
* Given a raw packet in buf, return the src and dest
diff --git a/multi.c b/multi.c
index 22c0a3f..f703b8d 100644
--- a/multi.c
+++ b/multi.c
@@ -316,25 +316,18 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa
*/
if (t->options.ifconfig_pool_defined)
{
- if (dev == DEV_TYPE_TAP)
- {
- m->ifconfig_pool = ifconfig_pool_init (IFCONFIG_POOL_INDIV,
- t->options.ifconfig_pool_start,
- t->options.ifconfig_pool_end,
- t->options.duplicate_cn);
- }
- else if (dev == DEV_TYPE_TUN)
- {
- m->ifconfig_pool = ifconfig_pool_init (
- (t->options.topology == TOP_NET30) ? IFCONFIG_POOL_30NET : IFCONFIG_POOL_INDIV,
- t->options.ifconfig_pool_start,
- t->options.ifconfig_pool_end,
- t->options.duplicate_cn);
- }
- else
- {
- ASSERT (0);
- }
+ int pool_type = IFCONFIG_POOL_INDIV;
+
+ if ( dev == DEV_TYPE_TUN && t->options.topology == TOP_NET30 )
+ pool_type = IFCONFIG_POOL_30NET;
+
+ m->ifconfig_pool = ifconfig_pool_init (pool_type,
+ t->options.ifconfig_pool_start,
+ t->options.ifconfig_pool_end,
+ t->options.duplicate_cn,
+ t->options.ifconfig_ipv6_pool_defined,
+ t->options.ifconfig_ipv6_pool_base,
+ t->options.ifconfig_ipv6_pool_netbits );
/* reload pool data from file */
if (t->c1.ifconfig_pool_persist)
@@ -429,10 +422,14 @@ multi_del_iroutes (struct multi_context *m,
struct multi_instance *mi)
{
const struct iroute *ir;
+ const struct iroute_ipv6 *ir6;
if (TUNNEL_TYPE (mi->context.c1.tuntap) == DEV_TYPE_TUN)
{
for (ir = mi->context.options.iroutes; ir != NULL; ir = ir->next)
mroute_helper_del_iroute (m->route_helper, ir);
+
+ for ( ir6 = mi->context.options.iroutes_ipv6; ir6 != NULL; ir6 = ir6->next )
+ mroute_helper_del_iroute6 (m->route_helper, ir6);
}
}
@@ -1078,6 +1075,37 @@ multi_learn_in_addr_t (struct multi_context *m,
}
}
+static struct multi_instance *
+multi_learn_in6_addr (struct multi_context *m,
+ struct multi_instance *mi,
+ struct in6_addr a6,
+ int netbits, /* -1 if host route, otherwise # of network bits in address */
+ bool primary)
+{
+ struct mroute_addr addr;
+
+ addr.len = 16;
+ addr.type = MR_ADDR_IPV6;
+ addr.netbits = 0;
+ memcpy( &addr.addr, &a6, sizeof(a6) );
+
+ if (netbits >= 0)
+ {
+ addr.type |= MR_WITH_NETBITS;
+ addr.netbits = (uint8_t) netbits;
+ mroute_addr_mask_host_bits( &addr );
+ }
+
+ {
+ struct multi_instance *owner = multi_learn_addr (m, mi, &addr, 0);
+#ifdef MANAGEMENT_DEF_AUTH
+ if (management && owner)
+ management_learn_addr (management, &mi->context.c2.mda_context, &addr, primary);
+#endif
+ return owner;