From c55e9562d64f381ba46b83a02503f6239e23d3ef Mon Sep 17 00:00:00 2001 From: Gert Doering Date: Fri, 3 Feb 2012 17:11:03 +0100 Subject: [PATCH] Implement IPv6 interface config with non-/64 prefix lengths. Add "ifconfig_ipv6_netbits_parm" parameter to init_tun(), use that to initialize tt->netbits_ipv6 (previously: always /64). Actual interface setup code already used tt->netbits_ipv6, so no changes needed there. Remove restrictions on "/netbits" value for --server-ipv6 config option (can now be /64.../112, previously had to be exactly /64). Supporting even smaller networks could cause problems with ipv6-pool handling and are only allowed for explicit "ifconfig-ipv6", not for "server-ipv6". Add /netbits to pushed "ifconfig-ipv6" values on server side (client side always accepted this, but ignored it so far, so this does not break compatibility). Tested on Linux/ifconfig, Linux/iproute2 and FreeBSD 7.4 Signed-off-by: Gert Doering Acked-by: David Sommerseth Signed-off-by: David Sommerseth --- TODO.IPv6 | 2 ++ helper.c | 8 +++++--- init.c | 1 + options.c | 5 +++-- push.c | 6 ++---- tun.c | 4 +++- tun.h | 1 + 7 files changed, 17 insertions(+), 10 deletions(-) diff --git a/TODO.IPv6 b/TODO.IPv6 index 87c47b3e..f23cce00 100644 --- a/TODO.IPv6 +++ b/TODO.IPv6 @@ -77,6 +77,8 @@ tun0: flags=8051 mtu 1500 of /netbits, and correctly ifconfig'ing this (default, if not specified: /64) + * done * 2012-02-03 + 11.) do not add ipv6-routes if tun-ipv6 is not set - complain instead * done * 12.1.10 diff --git a/helper.c b/helper.c index c7333f6e..22ea652d 100644 --- a/helper.c +++ b/helper.c @@ -184,12 +184,14 @@ helper_client_server (struct options *o) 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 ); + o->ifconfig_ipv6_netbits = o->server_netbits_ipv6; + + /* pool starts at "base address + 0x1000" - leave enough room */ + ASSERT( o->server_netbits_ipv6 <= 112 ); /* want 16 bits */ - /* 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 ); + add_in6_addr( o->server_network_ipv6, 0x1000 ); o->ifconfig_ipv6_pool_netbits = o->server_netbits_ipv6; o->tun_ipv6 = true; diff --git a/init.c b/init.c index b8cb84f7..525f4412 100644 --- a/init.c +++ b/init.c @@ -1415,6 +1415,7 @@ do_init_tun (struct context *c) c->options.ifconfig_local, c->options.ifconfig_remote_netmask, c->options.ifconfig_ipv6_local, + c->options.ifconfig_ipv6_netbits, c->options.ifconfig_ipv6_remote, addr_host (&c->c1.link_socket_addr.local), addr_host (&c->c1.link_socket_addr.remote), diff --git a/options.c b/options.c index 0fbe3689..cb9738a0 100644 --- a/options.c +++ b/options.c @@ -2926,6 +2926,7 @@ options_string (const struct options *o, o->ifconfig_local, o->ifconfig_remote_netmask, o->ifconfig_ipv6_local, + o->ifconfig_ipv6_netbits, o->ifconfig_ipv6_remote, (in_addr_t)0, (in_addr_t)0, @@ -5396,9 +5397,9 @@ add_option (struct options *options, msg (msglevel, "error parsing --server-ipv6 parameter"); goto err; } - if ( netbits != 64 ) + if ( netbits < 64 || netbits > 112 ) { - msg( msglevel, "--server-ipv6 settings: only /64 supported right now (not /%d)", netbits ); + msg( msglevel, "--server-ipv6 settings: only /64../112 supported right now (not /%d)", netbits ); goto err; } options->server_ipv6_defined = true; diff --git a/push.c b/push.c index a8ce3567..8a8779dc 100644 --- a/push.c +++ b/push.c @@ -242,11 +242,9 @@ send_push_reply (struct context *c) if ( c->c2.push_ifconfig_ipv6_defined ) { /* IPv6 is put into buffer first, could be lengthy */ - /* TODO: push "/netbits" as well, to allow non-/64 subnet sizes - * (needs changes in options.c, options.h, and other places) - */ - buf_printf( &buf, ",ifconfig-ipv6 %s %s", + buf_printf( &buf, ",ifconfig-ipv6 %s/%d %s", print_in6_addr( c->c2.push_ifconfig_ipv6_local, 0, &gc), + c->c2.push_ifconfig_ipv6_netbits, print_in6_addr( c->c2.push_ifconfig_ipv6_remote, 0, &gc) ); if (BLEN (&buf) >= safe_cap) { diff --git a/tun.c b/tun.c index c9af168d..1527ac81 100644 --- a/tun.c +++ b/tun.c @@ -404,6 +404,7 @@ init_tun (const char *dev, /* --dev option */ const char *ifconfig_local_parm, /* --ifconfig parm 1 */ const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */ const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 IPv6 */ + int ifconfig_ipv6_netbits_parm, const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 IPv6 */ in_addr_t local_public, in_addr_t remote_public, @@ -534,7 +535,7 @@ init_tun (const char *dev, /* --dev option */ { msg( M_FATAL, "init_tun: problem converting IPv6 ifconfig addresses %s and %s to binary", ifconfig_ipv6_local_parm, ifconfig_ipv6_remote_parm ); } - tt->netbits_ipv6 = 64; + tt->netbits_ipv6 = ifconfig_ipv6_netbits_parm; /* * Set ifconfig parameters @@ -548,6 +549,7 @@ init_tun (const char *dev, /* --dev option */ if (es) { setenv_str (es, "ifconfig_ipv6_local", ifconfig_ipv6_local); + setenv_int (es, "ifconfig_ipv6_netbits", tt->netbits_ipv6); setenv_str (es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote); } tt->did_ifconfig_ipv6_setup = true; diff --git a/tun.h b/tun.h index f28b8d81..c0785dd8 100644 --- a/tun.h +++ b/tun.h @@ -225,6 +225,7 @@ struct tuntap *init_tun (const char *dev, /* --dev option */ const char *ifconfig_local_parm, /* --ifconfig parm 1 */ const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */ const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 / IPv6 */ + int ifconfig_ipv6_netbits_parm, /* --ifconfig parm 1 / bits */ const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 / IPv6 */ in_addr_t local_public, in_addr_t remote_public,