Browse code

new feature: "ifconfig-ipv6-push" (from ccd/ config) affects options.h, options.c, multi.c benefit: static IPv6 address assignment from radiusplugin (etc) rewritten get_ipv6_addr() to handle IPv6 addresses with and without "/bits" affects route.c and mainly options.c benefit: ifconfig-ipv6, ifconfig-ipv6-pool can now be accept configurations with networks != /64 (the rest of the implementation is not yet completely there, but this is imporant preparation work to be able to add /bits to "push 'ifconfig-ipv6 ...'" later on without breaking clients do not try to add/delete IPv6 routes if no IPv6 on tunnel affects: route.c benefit: avoid error messages, and make IPv6 troubleshooting easier flag as "config error" if --ifconfig-ipv6-pool used without --ifconfig-ipv6 flag as "config error" if --ifconfig-ipv6-pool used without --server print warning if --ifconfig-ipv6 is used without --tun-ipv6 changes documented in more detail in ChangeLog.IPv6

* release patch set 20100114-1
(cherry picked from commit c04f774c7e9bed602818b1fe2ff4e83cf913d471)

Gert Doering authored on 2010/01/14 23:53:40
Showing 6 changed files
... ...
@@ -187,3 +187,45 @@ Mon Jan  4 17:46:58 CET 2010
187 187
     on the Solaris side via "ndpd.conf" (see ``man ifconfig'').
188 188
 
189 189
   * release as patch 20100104-1
190
+
191
+Fri Jan  8 10:00:50 CET 2010
192
+
193
+  * import into git repository
194
+
195
+  * options.c: add sanity checks for most typical error cases
196
+    (--ifconfig-ipv6-pool configured with no --ifconfig-ipv6, etc)
197
+
198
+  * options.c: modify get_ipv6_addr() to be more flexible about netbits
199
+    (optional now, default to /64) and to return the address-without-netbits
200
+    string now (-> for options that want the IPv6 address in printable
201
+    form, but without /nn)
202
+
203
+  * options.c: modify --ifconfig-ipv6 to optionally accept /netbits,
204
+    you can do now "ifconfig-ipv6 2001:df8::1/64 2001:df8::2" or just
205
+    "ifconfig-ipv6 2001:df8::5 2001:df8::7", defaulting to /64
206
+
207
+  * options.h: add necessary structure elements for --ifconfig-ipv6-push
208
+
209
+  * options.c: implement "parse options" side of --ifconfig-ipv6-push
210
+
211
+Tue Jan 12 22:42:09 CET 2010
212
+
213
+  * tun.c: in TARGET_NETBSD #ifdef, distinguish between "old" code
214
+    (IPv4 only, but unmodified read/write) and "new" code (multi-af, 
215
+    extra 32 bit AF on read/write of the tun interface) - pre-4.0
216
+    NetBSD systems don't have TUNSIFHEAD, no way to have common code.
217
+
218
+  * TEST SUCCESS: NetBSD 5.0/Sparc64: client-ipv6 with route-ipv6 (v4+v6)
219
+
220
+  * TEST SUCCESS: NetBSD 3.1/Sparc64: client-ipv6 with route-ipv6 (v4-only)
221
+
222
+Thu Jan 14 15:41:50 CET 2010
223
+
224
+  * multi.c: if "--ifconfig-push" is used together with "--ifconfig-ipv6-pool"
225
+    and no "--ifconfig-ipv6-push" is seen, issue warning - the current
226
+    implementation of pools has IPv6 tied to IPv4, so if v4 does not use
227
+    the pool, it breaks for IPv6.  Not a *big* problem (since there is 
228
+    enough v6, just give those users a static v6 address as well), but needs
229
+    to be pointed out clearly.
230
+
231
+  * release as patch 20100114-1
... ...
@@ -1237,6 +1237,17 @@ multi_select_virtual_addr (struct multi_context *m, struct multi_instance *mi)
1237 1237
       mi->context.c2.push_ifconfig_defined = true;
1238 1238
       mi->context.c2.push_ifconfig_local = mi->context.options.push_ifconfig_local;
1239 1239
       mi->context.c2.push_ifconfig_remote_netmask = mi->context.options.push_ifconfig_remote_netmask;
1240
+
1241
+      /* the current implementation does not allow "static IPv4, pool IPv6",
1242
+       * (see below) so issue a warning if that happens - don't break the
1243
+       * session, though, as we don't even know if this client WANTS IPv6
1244
+       */
1245
+      if ( mi->context.c1.tuntap->ipv6 &&
1246
+	   mi->context.options.ifconfig_ipv6_pool_defined &&
1247
+	   ! mi->context.options.push_ifconfig_ipv6_defined )
1248
+	{
1249
+	  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." );
1250
+	}
1240 1251
     }
1241 1252
   else if (m->ifconfig_pool && mi->vaddr_handle < 0) /* otherwise, choose a pool address */
1242 1253
     {
... ...
@@ -1294,6 +1305,30 @@ multi_select_virtual_addr (struct multi_context *m, struct multi_instance *mi)
1294 1294
 	  msg (D_MULTI_ERRORS, "MULTI: no free --ifconfig-pool addresses are available");
1295 1295
 	}
1296 1296
     }
1297
+
1298
+  /* IPv6 push_ifconfig is a bit problematic - since IPv6 shares the 
1299
+   * pool handling with IPv4, the combination "static IPv4, dynamic IPv6"
1300
+   * will fail (because no pool will be allocated in this case).
1301
+   * OTOH, this doesn't make too much sense in reality - and the other
1302
+   * way round ("dynamic IPv4, static IPv6") or "both static" makes sense
1303
+   * -> and so it's implemented right now
1304
+   */
1305
+  if ( mi->context.c1.tuntap->ipv6 &&
1306
+       mi->context.options.push_ifconfig_ipv6_defined )
1307
+    {
1308
+      mi->context.c2.push_ifconfig_ipv6_local = 
1309
+	    mi->context.options.push_ifconfig_ipv6_local;
1310
+      mi->context.c2.push_ifconfig_ipv6_remote = 
1311
+	    mi->context.options.push_ifconfig_ipv6_remote;
1312
+      mi->context.c2.push_ifconfig_ipv6_netbits = 
1313
+	    mi->context.options.push_ifconfig_ipv6_netbits;
1314
+      mi->context.c2.push_ifconfig_ipv6_defined = true;
1315
+
1316
+      msg( M_INFO, "MULTI_sva: push_ifconfig_ipv6 %s/%d", 
1317
+	    print_in6_addr( mi->context.c2.push_ifconfig_ipv6_local, 0, &gc ),
1318
+	    mi->context.c2.push_ifconfig_ipv6_netbits );
1319
+    }
1320
+
1297 1321
   gc_free (&gc);
1298 1322
 }
1299 1323
 
... ...
@@ -395,6 +395,10 @@ static const char usage_message[] =
395 395
   "--ifconfig-push local remote-netmask : Push an ifconfig option to remote,\n"
396 396
   "                  overrides --ifconfig-pool dynamic allocation.\n"
397 397
   "                  Only valid in a client-specific config file.\n"
398
+  "--ifconfig-ipv6-push local/bits remote : Push an ifconfig-ipv6 option to\n"
399
+  "                  remote, overrides --ifconfig-ipv6-pool allocation.\n"
400
+  "                  Only valid in a client-specific config file.\n"
401
+  "--iroute network [netmask] : Route subnet to client.\n"
398 402
   "--iroute network [netmask] : Route subnet to client.\n"
399 403
   "--iroute-ipv6 network/bits : Route IPv6 subnet to client.\n"
400 404
   "                  Sets up internal routes only.\n"
... ...
@@ -881,47 +885,67 @@ get_ip_addr (const char *ip_string, int msglevel, bool *error)
881 881
   return ret;
882 882
 }
883 883
 
884
-/* parse a text string containing an IPv6 address + netbits
884
+/* helper: parse a text string containing an IPv6 address + netbits
885 885
  * in "standard format" (2001:dba::/32)
886
+ * "/nn" is optional, default to /64 if missing
887
+ *
886 888
  * return true if parsing succeeded, modify *network and *netbits
889
+ * return address part without "/nn" in *printable_ipv6 (if != NULL)
887 890
  */
888 891
 bool
889 892
 get_ipv6_addr( const char * prefix_str, struct in6_addr *network,
890
-	       unsigned int * netbits, int msglevel )
893
+	       unsigned int * netbits, char ** printable_ipv6, int msglevel )
891 894
 {
892 895
     int rc;
893 896
     char * sep, * endp;
894 897
     int bits;
898
+    struct in6_addr t_network;
895 899
 
896 900
     sep = strchr( prefix_str, '/' );
897 901
     if ( sep == NULL )
898
-    {
899
-      msg (msglevel, "IPv6 prefix '%s': missing '/'", prefix_str);
900
-      return false;
901
-    }
902
-
903
-    bits = strtol( sep+1, &endp, 10 );
904
-    if ( *endp != '\0' || bits < 0 || bits > 128 )
905
-    {
906
-      msg (msglevel, "IPv6 prefix '%s': invalid '/bits' spec", prefix_str);
907
-      return false;
908
-    }
902
+      {
903
+ 	bits = 64;
904
+      }
905
+    else
906
+      {
907
+	bits = strtol( sep+1, &endp, 10 );
908
+	if ( *endp != '\0' || bits < 0 || bits > 128 )
909
+	  {
910
+	    msg (msglevel, "IPv6 prefix '%s': invalid '/bits' spec", prefix_str);
911
+	    return false;
912
+	  }
913
+      }
909 914
 
910 915
     /* temporary replace '/' in caller-provided string with '\0', otherwise
911 916
      * inet_pton() will refuse prefix string
912 917
      * (alternative would be to strncpy() the prefix to temporary buffer)
913 918
      */
914 919
 
915
-    *sep = '\0';
916
-    rc = inet_pton( AF_INET6, prefix_str, network );
917
-    *sep = '/';
920
+    if ( sep != NULL ) *sep = '\0';
921
+
922
+    rc = inet_pton( AF_INET6, prefix_str, &t_network );
923
+
924
+    if ( rc == 1 && printable_ipv6 != NULL )
925
+      {
926
+	*printable_ipv6 = string_alloc( prefix_str, NULL );
927
+      }
928
+
929
+    if ( sep != NULL ) *sep = '/';
918 930
 
919 931
     if ( rc != 1 )
920
-    {
921
-      msg (msglevel, "IPv6 prefix '%s': invalid network part", prefix_str);
922
-      return false;
923
-    }
924
-    *netbits = bits;
932
+      {
933
+	msg (msglevel, "IPv6 prefix '%s': invalid IPv6 address", prefix_str);
934
+	return false;
935
+      }
936
+
937
+    if ( netbits != NULL )
938
+      {
939
+	*netbits = bits;
940
+      }
941
+    if ( network != NULL )
942
+      {
943
+	*network = t_network;
944
+      }
925 945
     return true;		/* parsing OK, values set */
926 946
 }
927 947
 
... ...
@@ -930,7 +954,7 @@ static bool ipv6_addr_safe_hexplusbits( const char * ipv6_prefix_spec )
930 930
     struct in6_addr t_addr;
931 931
     unsigned int t_bits;
932 932
 
933
-    return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, M_WARN );
933
+    return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, NULL, M_WARN );
934 934
 }
935 935
 
936 936
 static char *
... ...
@@ -1073,6 +1097,7 @@ show_p2mp_parms (const struct options *o)
1073 1073
   msg (D_SHOW_PARMS, "  ifconfig_pool_netmask = %s", print_in_addr_t (o->ifconfig_pool_netmask, 0, &gc));
1074 1074
   SHOW_STR (ifconfig_pool_persist_filename);
1075 1075
   SHOW_INT (ifconfig_pool_persist_refresh_freq);
1076
+  SHOW_BOOL (ifconfig_ipv6_pool_defined);
1076 1077
   msg (D_SHOW_PARMS, "  ifconfig_ipv6_pool_base = %s", print_in6_addr (o->ifconfig_ipv6_pool_base, 0, &gc));
1077 1078
   SHOW_INT (ifconfig_ipv6_pool_netbits);
1078 1079
   SHOW_INT (n_bcast_buf);
... ...
@@ -1088,6 +1113,9 @@ show_p2mp_parms (const struct options *o)
1088 1088
   SHOW_BOOL (push_ifconfig_defined);
1089 1089
   msg (D_SHOW_PARMS, "  push_ifconfig_local = %s", print_in_addr_t (o->push_ifconfig_local, 0, &gc));
1090 1090
   msg (D_SHOW_PARMS, "  push_ifconfig_remote_netmask = %s", print_in_addr_t (o->push_ifconfig_remote_netmask, 0, &gc));
1091
+  SHOW_BOOL (push_ifconfig_ipv6_defined);
1092
+  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 );
1093
+  msg (D_SHOW_PARMS, "  push_ifconfig_ipv6_remote = %s", print_in6_addr (o->push_ifconfig_ipv6_remote, 0, &gc));
1091 1094
   SHOW_BOOL (enable_c2c);
1092 1095
   SHOW_BOOL (duplicate_cn);
1093 1096
   SHOW_INT (cf_max);
... ...
@@ -1151,7 +1179,7 @@ option_iroute_ipv6 (struct options *o,
1151 1151
 
1152 1152
   ALLOC_OBJ_GC (ir, struct iroute_ipv6, &o->gc);
1153 1153
 
1154
-  if ( get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, msglevel ) < 0 )
1154
+  if ( get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, NULL, msglevel ) < 0 )
1155 1155
     {
1156 1156
       msg (msglevel, "in --iroute-ipv6 %s: Bad IPv6 prefix specification",
1157 1157
 	   prefix_str);
... ...
@@ -1296,6 +1324,7 @@ show_settings (const struct options *o)
1296 1296
   SHOW_BOOL (ifconfig_noexec);
1297 1297
   SHOW_BOOL (ifconfig_nowarn);
1298 1298
   SHOW_STR (ifconfig_ipv6_local);
1299
+  SHOW_INT (ifconfig_ipv6_netbits);
1299 1300
   SHOW_STR (ifconfig_ipv6_remote);
1300 1301
 
1301 1302
 #ifdef HAVE_GETTIMEOFDAY
... ...
@@ -1985,6 +2014,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
1985 1985
 	msg (M_USAGE, "--up-delay cannot be used with --mode server");
1986 1986
       if (!options->ifconfig_pool_defined && options->ifconfig_pool_persist_filename)
1987 1987
 	msg (M_USAGE, "--ifconfig-pool-persist must be used with --ifconfig-pool");
1988
+      if (options->ifconfig_ipv6_pool_defined && !options->ifconfig_ipv6_local )
1989
+	msg (M_USAGE, "--ifconfig-ipv6-pool needs --ifconfig-ipv6");
1990
+      if (options->ifconfig_ipv6_local && !options->tun_ipv6 )
1991
+	msg (M_INFO, "Warning: --ifconfig-ipv6 without --tun-ipv6 will not do IPv6");
1992
+
1988 1993
       if (options->auth_user_pass_file)
1989 1994
 	msg (M_USAGE, "--auth-user-pass cannot be used with --mode server (it should be used on the client side only)");
1990 1995
       if (options->ccd_exclusive && !options->client_config_dir)
... ...
@@ -2016,6 +2050,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
2016 2016
        */
2017 2017
       if (options->ifconfig_pool_defined || options->ifconfig_pool_persist_filename)
2018 2018
 	msg (M_USAGE, "--ifconfig-pool/--ifconfig-pool-persist requires --mode server");
2019
+      if (options->ifconfig_ipv6_pool_defined)
2020
+	msg (M_USAGE, "--ifconfig-ipv6-pool requires --mode server");
2019 2021
       if (options->real_hash_size != defaults.real_hash_size
2020 2022
 	  || options->virtual_hash_size != defaults.virtual_hash_size)
2021 2023
 	msg (M_USAGE, "--hash-size requires --mode server");
... ...
@@ -3894,11 +3930,20 @@ add_option (struct options *options,
3894 3894
     }
3895 3895
   else if (streq (p[0], "ifconfig-ipv6") && p[1] && p[2] )
3896 3896
     {
3897
+      unsigned int netbits;
3898
+      char * ipv6_local;
3899
+	
3897 3900
       VERIFY_PERMISSION (OPT_P_UP);
3898
-      /* TODO: should we accept address + netbits (2001:db8::1/64) here? */
3899
-      if ( ipv6_addr_safe( p[1] ) && ipv6_addr_safe( p[2] ) )
3901
+      if ( get_ipv6_addr( p[1], NULL, &netbits, &ipv6_local, msglevel ) &&
3902
+           ipv6_addr_safe( p[2] ) )
3900 3903
         {
3901
-	  options->ifconfig_ipv6_local = p[1];
3904
+	  if ( netbits < 64 || netbits > 124 )
3905
+	    {
3906
+	      msg( msglevel, "ifconfig-ipv6: /netbits must be between 64 and 124, not '/%d'", netbits );
3907
+	      goto err;
3908
+	    }
3909
+	  options->ifconfig_ipv6_local = ipv6_local;
3910
+	  options->ifconfig_ipv6_netbits = netbits;
3902 3911
 	  options->ifconfig_ipv6_remote = p[2];
3903 3912
         }
3904 3913
       else
... ...
@@ -4945,7 +4990,7 @@ add_option (struct options *options,
4945 4945
       unsigned int netbits = 0;
4946 4946
 
4947 4947
       VERIFY_PERMISSION (OPT_P_GENERAL);
4948
-      if ( ! get_ipv6_addr (p[1], &network, &netbits, lev) )
4948
+      if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev) )
4949 4949
 	{
4950 4950
 	  msg (msglevel, "error parsing --server-ipv6 parameter");
4951 4951
 	  goto err;
... ...
@@ -4961,7 +5006,7 @@ add_option (struct options *options,
4961 4961
 
4962 4962
       if (p[2])		/* no "nopool" options or similar for IPv6 */
4963 4963
 	{
4964
-	  msg (msglevel, "error parsing --server: %s is not a recognized flag", p[3]);
4964
+	  msg (msglevel, "error parsing --server-ipv6: %s is not a recognized flag", p[3]);
4965 4965
 	  goto err;
4966 4966
 	}
4967 4967
     }
... ...
@@ -5056,7 +5101,7 @@ add_option (struct options *options,
5056 5056
       unsigned int netbits = 0;
5057 5057
 
5058 5058
       VERIFY_PERMISSION (OPT_P_GENERAL);
5059
-      if ( ! get_ipv6_addr (p[1], &network, &netbits, lev ) )
5059
+      if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev ) )
5060 5060
 	{
5061 5061
 	  msg (msglevel, "error parsing --ifconfig-ipv6-pool parameters");
5062 5062
 	  goto err;
... ...
@@ -5309,6 +5354,43 @@ add_option (struct options *options,
5309 5309
 	  goto err;
5310 5310
 	}
5311 5311
     }
5312
+  else if (streq (p[0], "ifconfig-ipv6-push") && p[1] )
5313
+    {
5314
+      struct in6_addr local, remote;
5315
+      unsigned int netbits;
5316
+
5317
+      VERIFY_PERMISSION (OPT_P_INSTANCE);
5318
+
5319
+      if ( ! get_ipv6_addr( p[1], &local, &netbits, NULL, msglevel ) )
5320
+	{
5321
+	  msg (msglevel, "cannot parse --ifconfig-ipv6-push addresses");
5322
+	  goto err;
5323
+	}
5324
+
5325
+      if ( p[2] )
5326
+	{
5327
+	  if ( !get_ipv6_addr( p[2], &remote, NULL, NULL, msglevel ) )
5328
+	    {
5329
+	      msg( msglevel, "cannot parse --ifconfig-ipv6-push addresses");
5330
+	      goto err;
5331
+	    }
5332
+	}
5333
+      else
5334
+	{
5335
+	  if ( ! options->ifconfig_ipv6_local ||
5336
+	       ! get_ipv6_addr( options->ifconfig_ipv6_local, &remote, 
5337
+				NULL, NULL, msglevel ) )
5338
+	    {
5339
+	      msg( msglevel, "second argument to --ifconfig-ipv6-push missing and no global --ifconfig-ipv6 address set");
5340
+	      goto err;
5341
+	    }
5342
+	}
5343
+
5344
+      options->push_ifconfig_ipv6_defined = true;
5345
+      options->push_ifconfig_ipv6_local = local;
5346
+      options->push_ifconfig_ipv6_netbits = netbits;
5347
+      options->push_ifconfig_ipv6_remote = remote;
5348
+    }
5312 5349
   else if (streq (p[0], "disable"))
5313 5350
     {
5314 5351
       VERIFY_PERMISSION (OPT_P_INSTANCE);
... ...
@@ -206,6 +206,7 @@ struct options
206 206
   const char *ifconfig_local;
207 207
   const char *ifconfig_remote_netmask;
208 208
   const char *ifconfig_ipv6_local;
209
+  int         ifconfig_ipv6_netbits;
209 210
   const char *ifconfig_ipv6_remote;
210 211
   bool ifconfig_noexec;
211 212
   bool ifconfig_nowarn;
... ...
@@ -412,6 +413,10 @@ struct options
412 412
   bool push_ifconfig_constraint_defined;
413 413
   in_addr_t push_ifconfig_constraint_network;
414 414
   in_addr_t push_ifconfig_constraint_netmask;
415
+  bool            push_ifconfig_ipv6_defined;		/* IPv6 */
416
+  struct in6_addr push_ifconfig_ipv6_local;		/* IPv6 */
417
+  int 		  push_ifconfig_ipv6_netbits;		/* IPv6 */
418
+  struct in6_addr push_ifconfig_ipv6_remote;		/* IPv6 */
415 419
   bool enable_c2c;
416 420
   bool duplicate_cn;
417 421
   int cf_max;
... ...
@@ -735,7 +740,8 @@ void options_string_import (struct options *options,
735 735
 			    struct env_set *es);
736 736
 
737 737
 bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network,
738
-		    unsigned int * netbits, int msglevel );
738
+		    unsigned int * netbits, char ** printable_ipv6, 
739
+		    int msglevel );
739 740
 
740 741
 /*
741 742
  * inline functions
... ...
@@ -35,6 +35,7 @@
35 35
 #include "socket.h"
36 36
 #include "manage.h"
37 37
 #include "win32.h"
38
+#include "options.h"
38 39
 
39 40
 #include "memdbg.h"
40 41
 
... ...
@@ -338,7 +339,7 @@ init_route_ipv6 (struct route_ipv6 *r6,
338 338
   r6->option = r6o;
339 339
   r6->defined = false;
340 340
 
341
-  if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, M_WARN ))
341
+  if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, NULL, M_WARN ))
342 342
     goto fail;
343 343
 
344 344
   /* gateway */
... ...
@@ -1300,6 +1301,13 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla
1300 1300
   network = print_in6_addr( network_copy, 0, &gc);
1301 1301
   gateway = print_in6_addr( r6->gateway, 0, &gc);
1302 1302
 
1303
+  if ( !tt->ipv6 )
1304
+    {
1305
+      msg( M_INFO, "add_route_ipv6(): not adding %s/%d, no IPv6 on if %s",
1306
+		    network, r6->netbits, device );
1307
+      return;
1308
+    }
1309
+
1303 1310
   msg( M_INFO, "add_route_ipv6(%s/%d -> %s metric %d) dev %s",
1304 1311
 		network, r6->netbits, gateway, r6->metric, device );
1305 1312
 
... ...
@@ -1550,6 +1558,13 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne
1550 1550
   network = print_in6_addr( r6->network, 0, &gc);
1551 1551
   gateway = print_in6_addr( r6->gateway, 0, &gc);
1552 1552
 
1553
+  if ( !tt->ipv6 )
1554
+    {
1555
+      msg( M_INFO, "delete_route_ipv6(): not deleting %s/%d, no IPv6 on if %s",
1556
+		    network, r6->netbits, device );
1557
+      return;
1558
+    }
1559
+
1553 1560
   msg( M_INFO, "delete_route_ipv6(%s/%d)", network, r6->netbits );
1554 1561
 
1555 1562
 #if defined(TARGET_LINUX)
... ...
@@ -130,7 +130,7 @@ struct route_ipv6 {
130 130
   bool defined;
131 131
   const struct route_ipv6_option *option;
132 132
   struct in6_addr network;
133
-  int netbits;
133
+  unsigned int netbits;
134 134
   struct in6_addr gateway;
135 135
   bool metric_defined;
136 136
   int metric;