diff options
Diffstat (limited to '')
-rw-r--r-- | ChangeLog.IPv6 | 42 | ||||
-rw-r--r-- | multi.c | 35 | ||||
-rw-r--r-- | options.c | 140 | ||||
-rw-r--r-- | options.h | 8 | ||||
-rw-r--r-- | route.c | 17 | ||||
-rw-r--r-- | route.h | 2 |
6 files changed, 212 insertions, 32 deletions
diff --git a/ChangeLog.IPv6 b/ChangeLog.IPv6 index 7c39fc3..4881578 100644 --- a/ChangeLog.IPv6 +++ b/ChangeLog.IPv6 @@ -187,3 +187,45 @@ Mon Jan 4 17:46:58 CET 2010 on the Solaris side via "ndpd.conf" (see ``man ifconfig''). * release as patch 20100104-1 + +Fri Jan 8 10:00:50 CET 2010 + + * import into git repository + + * options.c: add sanity checks for most typical error cases + (--ifconfig-ipv6-pool configured with no --ifconfig-ipv6, etc) + + * options.c: modify get_ipv6_addr() to be more flexible about netbits + (optional now, default to /64) and to return the address-without-netbits + string now (-> for options that want the IPv6 address in printable + form, but without /nn) + + * options.c: modify --ifconfig-ipv6 to optionally accept /netbits, + you can do now "ifconfig-ipv6 2001:df8::1/64 2001:df8::2" or just + "ifconfig-ipv6 2001:df8::5 2001:df8::7", defaulting to /64 + + * options.h: add necessary structure elements for --ifconfig-ipv6-push + + * options.c: implement "parse options" side of --ifconfig-ipv6-push + +Tue Jan 12 22:42:09 CET 2010 + + * tun.c: in TARGET_NETBSD #ifdef, distinguish between "old" code + (IPv4 only, but unmodified read/write) and "new" code (multi-af, + extra 32 bit AF on read/write of the tun interface) - pre-4.0 + NetBSD systems don't have TUNSIFHEAD, no way to have common code. + + * TEST SUCCESS: NetBSD 5.0/Sparc64: client-ipv6 with route-ipv6 (v4+v6) + + * TEST SUCCESS: NetBSD 3.1/Sparc64: client-ipv6 with route-ipv6 (v4-only) + +Thu Jan 14 15:41:50 CET 2010 + + * multi.c: if "--ifconfig-push" is used together with "--ifconfig-ipv6-pool" + and no "--ifconfig-ipv6-push" is seen, issue warning - the current + implementation of pools has IPv6 tied to IPv4, so if v4 does not use + the pool, it breaks for IPv6. Not a *big* problem (since there is + enough v6, just give those users a static v6 address as well), but needs + to be pointed out clearly. + + * release as patch 20100114-1 @@ -1237,6 +1237,17 @@ multi_select_virtual_addr (struct multi_context *m, struct multi_instance *mi) mi->context.c2.push_ifconfig_defined = true; mi->context.c2.push_ifconfig_local = mi->context.options.push_ifconfig_local; mi->context.c2.push_ifconfig_remote_netmask = mi->context.options.push_ifconfig_remote_netmask; + + /* the current implementation does not allow "static IPv4, pool IPv6", + * (see below) so issue a warning if that happens - don't break the + * session, though, as we don't even know if this client WANTS IPv6 + */ + if ( mi->context.c1.tuntap->ipv6 && + mi->context.options.ifconfig_ipv6_pool_defined && + ! mi->context.options.push_ifconfig_ipv6_defined ) + { + msg( M_INFO, "MULTI_sva: WARNING: if --ifconfig-push is used for IPv4, automatic IPv6 assignment from --ifconfig-ipv6-pool does not work. Use --ifconfig-ipv6-push for IPv6 then." ); + } } else if (m->ifconfig_pool && mi->vaddr_handle < 0) /* otherwise, choose a pool address */ { @@ -1294,6 +1305,30 @@ multi_select_virtual_addr (struct multi_context *m, struct multi_instance *mi) msg (D_MULTI_ERRORS, "MULTI: no free --ifconfig-pool addresses are available"); } } + + /* IPv6 push_ifconfig is a bit problematic - since IPv6 shares the + * pool handling with IPv4, the combination "static IPv4, dynamic IPv6" + * will fail (because no pool will be allocated in this case). + * OTOH, this doesn't make too much sense in reality - and the other + * way round ("dynamic IPv4, static IPv6") or "both static" makes sense + * -> and so it's implemented right now + */ + if ( mi->context.c1.tuntap->ipv6 && + mi->context.options.push_ifconfig_ipv6_defined ) + { + mi->context.c2.push_ifconfig_ipv6_local = + mi->context.options.push_ifconfig_ipv6_local; + mi->context.c2.push_ifconfig_ipv6_remote = + mi->context.options.push_ifconfig_ipv6_remote; + mi->context.c2.push_ifconfig_ipv6_netbits = + mi->context.options.push_ifconfig_ipv6_netbits; + mi->context.c2.push_ifconfig_ipv6_defined = true; + + msg( M_INFO, "MULTI_sva: push_ifconfig_ipv6 %s/%d", + print_in6_addr( mi->context.c2.push_ifconfig_ipv6_local, 0, &gc ), + mi->context.c2.push_ifconfig_ipv6_netbits ); + } + gc_free (&gc); } @@ -395,6 +395,10 @@ static const char usage_message[] = "--ifconfig-push local remote-netmask : Push an ifconfig option to remote,\n" " overrides --ifconfig-pool dynamic allocation.\n" " Only valid in a client-specific config file.\n" + "--ifconfig-ipv6-push local/bits remote : Push an ifconfig-ipv6 option to\n" + " remote, overrides --ifconfig-ipv6-pool allocation.\n" + " Only valid in a client-specific config file.\n" + "--iroute network [netmask] : Route subnet to client.\n" "--iroute network [netmask] : Route subnet to client.\n" "--iroute-ipv6 network/bits : Route IPv6 subnet to client.\n" " Sets up internal routes only.\n" @@ -881,47 +885,67 @@ get_ip_addr (const char *ip_string, int msglevel, bool *error) return ret; } -/* parse a text string containing an IPv6 address + netbits +/* 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 + * return address part without "/nn" in *printable_ipv6 (if != NULL) */ bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network, - unsigned int * netbits, int msglevel ) + unsigned int * netbits, char ** printable_ipv6, int msglevel ) { int rc; char * sep, * endp; int bits; + struct in6_addr t_network; sep = strchr( prefix_str, '/' ); if ( sep == NULL ) - { - msg (msglevel, "IPv6 prefix '%s': missing '/'", prefix_str); - return false; - } - - 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; - } + { + 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) */ - *sep = '\0'; - rc = inet_pton( AF_INET6, prefix_str, network ); - *sep = '/'; + if ( sep != NULL ) *sep = '\0'; + + rc = inet_pton( AF_INET6, prefix_str, &t_network ); + + if ( rc == 1 && printable_ipv6 != NULL ) + { + *printable_ipv6 = string_alloc( prefix_str, NULL ); + } + + if ( sep != NULL ) *sep = '/'; if ( rc != 1 ) - { - msg (msglevel, "IPv6 prefix '%s': invalid network part", prefix_str); - return false; - } - *netbits = bits; + { + msg (msglevel, "IPv6 prefix '%s': invalid IPv6 address", prefix_str); + return false; + } + + if ( netbits != NULL ) + { + *netbits = bits; + } + if ( network != NULL ) + { + *network = t_network; + } return true; /* parsing OK, values set */ } @@ -930,7 +954,7 @@ static bool ipv6_addr_safe_hexplusbits( const char * ipv6_prefix_spec ) struct in6_addr t_addr; unsigned int t_bits; - return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, M_WARN ); + return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, NULL, M_WARN ); } static char * @@ -1073,6 +1097,7 @@ show_p2mp_parms (const struct options *o) msg (D_SHOW_PARMS, " ifconfig_pool_netmask = %s", print_in_addr_t (o->ifconfig_pool_netmask, 0, &gc)); SHOW_STR (ifconfig_pool_persist_filename); SHOW_INT (ifconfig_pool_persist_refresh_freq); + SHOW_BOOL (ifconfig_ipv6_pool_defined); msg (D_SHOW_PARMS, " ifconfig_ipv6_pool_base = %s", print_in6_addr (o->ifconfig_ipv6_pool_base, 0, &gc)); SHOW_INT (ifconfig_ipv6_pool_netbits); SHOW_INT (n_bcast_buf); @@ -1088,6 +1113,9 @@ show_p2mp_parms (const struct options *o) SHOW_BOOL (push_ifconfig_defined); msg (D_SHOW_PARMS, " push_ifconfig_local = %s", print_in_addr_t (o->push_ifconfig_local, 0, &gc)); msg (D_SHOW_PARMS, " push_ifconfig_remote_netmask = %s", print_in_addr_t (o->push_ifconfig_remote_netmask, 0, &gc)); + SHOW_BOOL (push_ifconfig_ipv6_defined); + msg (D_SHOW_PARMS, " push_ifconfig_ipv6_local = %s/%d", print_in6_addr (o->push_ifconfig_ipv6_local, 0, &gc), o->push_ifconfig_ipv6_netbits ); + msg (D_SHOW_PARMS, " push_ifconfig_ipv6_remote = %s", print_in6_addr (o->push_ifconfig_ipv6_remote, 0, &gc)); SHOW_BOOL (enable_c2c); SHOW_BOOL (duplicate_cn); SHOW_INT (cf_max); @@ -1151,7 +1179,7 @@ option_iroute_ipv6 (struct options *o, ALLOC_OBJ_GC (ir, struct iroute_ipv6, &o->gc); - if ( get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, msglevel ) < 0 ) + if ( get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, NULL, msglevel ) < 0 ) { msg (msglevel, "in --iroute-ipv6 %s: Bad IPv6 prefix specification", prefix_str); @@ -1296,6 +1324,7 @@ show_settings (const struct options *o) SHOW_BOOL (ifconfig_noexec); SHOW_BOOL (ifconfig_nowarn); SHOW_STR (ifconfig_ipv6_local); + SHOW_INT (ifconfig_ipv6_netbits); SHOW_STR (ifconfig_ipv6_remote); #ifdef HAVE_GETTIMEOFDAY @@ -1985,6 +2014,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne msg (M_USAGE, "--up-delay cannot be used with --mode server"); if (!options->ifconfig_pool_defined && options->ifconfig_pool_persist_filename) msg (M_USAGE, "--ifconfig-pool-persist must be used with --ifconfig-pool"); + if (options->ifconfig_ipv6_pool_defined && !options->ifconfig_ipv6_local ) + msg (M_USAGE, "--ifconfig-ipv6-pool needs --ifconfig-ipv6"); + if (options->ifconfig_ipv6_local && !options->tun_ipv6 ) + msg (M_INFO, "Warning: --ifconfig-ipv6 without --tun-ipv6 will not do IPv6"); + if (options->auth_user_pass_file) msg (M_USAGE, "--auth-user-pass cannot be used with --mode server (it should be used on the client side only)"); if (options->ccd_exclusive && !options->client_config_dir) @@ -2016,6 +2050,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne */ if (options->ifconfig_pool_defined || options->ifconfig_pool_persist_filename) msg (M_USAGE, "--ifconfig-pool/--ifconfig-pool-persist requires --mode server"); + if (options->ifconfig_ipv6_pool_defined) + msg (M_USAGE, "--ifconfig-ipv6-pool requires --mode server"); if (options->real_hash_size != defaults.real_hash_size || options->virtual_hash_size != defaults.virtual_hash_size) msg (M_USAGE, "--hash-size requires --mode server"); @@ -3894,11 +3930,20 @@ add_option (struct options *options, } else if (streq (p[0], "ifconfig-ipv6") && p[1] && p[2] ) { + unsigned int netbits; + char * ipv6_local; + VERIFY_PERMISSION (OPT_P_UP); - /* TODO: should we accept address + netbits (2001:db8::1/64) here? */ - if ( ipv6_addr_safe( p[1] ) && ipv6_addr_safe( p[2] ) ) + if ( get_ipv6_addr( p[1], NULL, &netbits, &ipv6_local, msglevel ) && + ipv6_addr_safe( p[2] ) ) { - options->ifconfig_ipv6_local = p[1]; + if ( netbits < 64 || netbits > 124 ) + { + msg( msglevel, "ifconfig-ipv6: /netbits must be between 64 and 124, not '/%d'", netbits ); + goto err; + } + options->ifconfig_ipv6_local = ipv6_local; + options->ifconfig_ipv6_netbits = netbits; options->ifconfig_ipv6_remote = p[2]; } else @@ -4945,7 +4990,7 @@ add_option (struct options *options, unsigned int netbits = 0; VERIFY_PERMISSION (OPT_P_GENERAL); - if ( ! get_ipv6_addr (p[1], &network, &netbits, lev) ) + if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev) ) { msg (msglevel, "error parsing --server-ipv6 parameter"); goto err; @@ -4961,7 +5006,7 @@ add_option (struct options *options, if (p[2]) /* no "nopool" options or similar for IPv6 */ { - msg (msglevel, "error parsing --server: %s is not a recognized flag", p[3]); + msg (msglevel, "error parsing --server-ipv6: %s is not a recognized flag", p[3]); goto err; } } @@ -5056,7 +5101,7 @@ add_option (struct options *options, unsigned int netbits = 0; VERIFY_PERMISSION (OPT_P_GENERAL); - if ( ! get_ipv6_addr (p[1], &network, &netbits, lev ) ) + if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev ) ) { msg (msglevel, "error parsing --ifconfig-ipv6-pool parameters"); goto err; @@ -5309,6 +5354,43 @@ add_option (struct options *options, goto err; } } + else if (streq (p[0], "ifconfig-ipv6-push") && p[1] ) + { + struct in6_addr local, remote; + unsigned int netbits; + + VERIFY_PERMISSION (OPT_P_INSTANCE); + + if ( ! get_ipv6_addr( p[1], &local, &netbits, NULL, msglevel ) ) + { + msg (msglevel, "cannot parse --ifconfig-ipv6-push addresses"); + goto err; + } + + if ( p[2] ) + { + if ( !get_ipv6_addr( p[2], &remote, NULL, NULL, msglevel ) ) + { + msg( msglevel, "cannot parse --ifconfig-ipv6-push addresses"); + goto err; + } + } + else + { + if ( ! options->ifconfig_ipv6_local || + ! get_ipv6_addr( options->ifconfig_ipv6_local, &remote, + NULL, NULL, msglevel ) ) + { + msg( msglevel, "second argument to --ifconfig-ipv6-push missing and no global --ifconfig-ipv6 address set"); + goto err; + } + } + + options->push_ifconfig_ipv6_defined = true; + options->push_ifconfig_ipv6_local = local; + options->push_ifconfig_ipv6_netbits = netbits; + options->push_ifconfig_ipv6_remote = remote; + } else if (streq (p[0], "disable")) { VERIFY_PERMISSION (OPT_P_INSTANCE); @@ -206,6 +206,7 @@ struct options const char *ifconfig_local; const char *ifconfig_remote_netmask; const char *ifconfig_ipv6_local; + int ifconfig_ipv6_netbits; const char *ifconfig_ipv6_remote; bool ifconfig_noexec; bool ifconfig_nowarn; @@ -412,6 +413,10 @@ struct options bool push_ifconfig_constraint_defined; in_addr_t push_ifconfig_constraint_network; in_addr_t push_ifconfig_constraint_netmask; + bool push_ifconfig_ipv6_defined; /* IPv6 */ + struct in6_addr push_ifconfig_ipv6_local; /* IPv6 */ + int push_ifconfig_ipv6_netbits; /* IPv6 */ + struct in6_addr push_ifconfig_ipv6_remote; /* IPv6 */ bool enable_c2c; bool duplicate_cn; int cf_max; @@ -735,7 +740,8 @@ void options_string_import (struct options *options, struct env_set *es); bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network, - unsigned int * netbits, int msglevel ); + unsigned int * netbits, char ** printable_ipv6, + int msglevel ); /* * inline functions @@ -35,6 +35,7 @@ #include "socket.h" #include "manage.h" #include "win32.h" +#include "options.h" #include "memdbg.h" @@ -338,7 +339,7 @@ init_route_ipv6 (struct route_ipv6 *r6, r6->option = r6o; r6->defined = false; - if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, M_WARN )) + if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, NULL, M_WARN )) goto fail; /* gateway */ @@ -1300,6 +1301,13 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla network = print_in6_addr( network_copy, 0, &gc); gateway = print_in6_addr( r6->gateway, 0, &gc); + if ( !tt->ipv6 ) + { + msg( M_INFO, "add_route_ipv6(): not adding %s/%d, no IPv6 on if %s", + network, r6->netbits, device ); + return; + } + msg( M_INFO, "add_route_ipv6(%s/%d -> %s metric %d) dev %s", network, r6->netbits, gateway, r6->metric, device ); @@ -1550,6 +1558,13 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne network = print_in6_addr( r6->network, 0, &gc); gateway = print_in6_addr( r6->gateway, 0, &gc); + if ( !tt->ipv6 ) + { + msg( M_INFO, "delete_route_ipv6(): not deleting %s/%d, no IPv6 on if %s", + network, r6->netbits, device ); + return; + } + msg( M_INFO, "delete_route_ipv6(%s/%d)", network, r6->netbits ); #if defined(TARGET_LINUX) @@ -130,7 +130,7 @@ struct route_ipv6 { bool defined; const struct route_ipv6_option *option; struct in6_addr network; - int netbits; + unsigned int netbits; struct in6_addr gateway; bool metric_defined; int metric; |