ra-advrouter mode for RFC-3775 mobile IPv6 support.
diff --git a/CHANGELOG b/CHANGELOG
index e0d2fed..62019ff 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+version 2.71
+	   Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
+
+
 version 2.70
             Fix crash, introduced in 2.69, on TCP request when dnsmasq
 	    compiled with DNSSEC support, but running without DNSSEC
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 6658f16..f25119d 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -794,7 +794,7 @@
 for details.)
 
 For IPv6, the mode may be some combination of
-.B ra-only, slaac, ra-names, ra-stateless.
+.B ra-only, slaac, ra-names, ra-stateless, ra-advrouter.
 
 .B ra-only
 tells dnsmasq to offer Router Advertisement only on this subnet,
@@ -829,6 +829,11 @@
 and
 .B slaac.
 
+.B ra-advrouter
+enables a mode where router address(es) rather than prefix(es) are included in the advertisements.
+This is described in RFC-3775 section 7.2 and is used in mobile IPv6. In this mode the interval option
+is also included, as described in RFC-3775 section 7.3.
+
 .TP
 .B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
 Specify per host parameters for the DHCP server. This allows a machine
diff --git a/src/dhcp6.c b/src/dhcp6.c
index 3a83c18..bc48fdd 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -727,8 +727,7 @@
      
       if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
 	{
-	  if ((context->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) ||
-	      option_bool(OPT_RA))
+	  if ((context->flags & CONTEXT_RA) || option_bool(OPT_RA))
 	    {
 	      /* previously constructed context has gone. advertise it's demise */
 	      context->flags |= CONTEXT_OLD;
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 3032546..e11fad4 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -823,7 +823,7 @@
 #define CONTEXT_NETMASK        (1u<<1)
 #define CONTEXT_BRDCAST        (1u<<2)
 #define CONTEXT_PROXY          (1u<<3)
-#define CONTEXT_RA_ONLY        (1u<<4)
+#define CONTEXT_RA_ROUTER      (1u<<4)
 #define CONTEXT_RA_DONE        (1u<<5)
 #define CONTEXT_RA_NAME        (1u<<6)
 #define CONTEXT_RA_STATELESS   (1u<<7)
@@ -838,7 +838,6 @@
 #define CONTEXT_OLD            (1u<<16)
 #define CONTEXT_V6             (1u<<17)
 
-
 struct ping_result {
   struct in_addr addr;
   time_t time;
diff --git a/src/option.c b/src/option.c
index daa728f..a0a6e46 100644
--- a/src/option.c
+++ b/src/option.c
@@ -2583,9 +2583,11 @@
 		if (strcmp(a[leasepos], "static") == 0)
 		  new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
 		else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
-		  new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
+		  new->flags |= CONTEXT_RA;
 		else if (strcmp(a[leasepos], "ra-names") == 0)
 		  new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
+		else if (strcmp(a[leasepos], "ra-advrouter") == 0)
+		  new->flags |= CONTEXT_RA_ROUTER | CONTEXT_RA;
 		else if (strcmp(a[leasepos], "ra-stateless") == 0)
 		  new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
 		else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
@@ -2615,7 +2617,7 @@
 	    
 	    if (new->prefix != 64)
 	      {
-		if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
+		if (new->flags & CONTEXT_RA)
 		  ret_err(_("prefix length must be exactly 64 for RA subnets"));
 		else if (new->flags & CONTEXT_TEMPLATE)
 		  ret_err(_("prefix length must be exactly 64 for subnet constructors"));
diff --git a/src/radv-protocol.h b/src/radv-protocol.h
index 9e53d8e..e576012 100644
--- a/src/radv-protocol.h
+++ b/src/radv-protocol.h
@@ -49,6 +49,7 @@
 #define ICMP6_OPT_SOURCE_MAC   1
 #define ICMP6_OPT_PREFIX       3
 #define ICMP6_OPT_MTU          5
+#define ICMP6_OPT_ADV_INTERVAL 7
 #define ICMP6_OPT_RDNSS       25
 #define ICMP6_OPT_DNSSL       31
 
diff --git a/src/radv.c b/src/radv.c
index 84d4a3e..f5b517b 100644
--- a/src/radv.c
+++ b/src/radv.c
@@ -28,7 +28,7 @@
 
 struct ra_param {
   time_t now;
-  int ind, managed, other, found_context, first;
+  int ind, managed, other, found_context, first, adv_router;
   char *if_name;
   struct dhcp_netid *tags;
   struct in6_addr link_local, link_global, ula;
@@ -226,6 +226,7 @@
   parm.managed = 0;
   parm.other = 0;
   parm.found_context = 0;
+  parm.adv_router = 0;
   parm.if_name = iface_name;
   parm.first = 1;
   parm.now = now;
@@ -286,8 +287,7 @@
 	      setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU));
 	     
 	      
-	      if ((context->flags & 
-		   (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
+	      if (context->flags & CONTEXT_RA)
 		{
 		  do_slaac = 1;
 		  if (context->flags & CONTEXT_DHCP)
@@ -339,6 +339,17 @@
   if (!old_prefix && !parm.found_context)
     return; 
   
+  /* If we're sending router address instead of prefix in at least on prefix,
+     include the advertisement interval option. */
+  if (parm.adv_router)
+    {
+      put_opt6_char(ICMP6_OPT_ADV_INTERVAL);
+      put_opt6_char(1);
+      put_opt6_short(0);
+      /* interval value is in milliseconds */
+      put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
+    }
+
 #ifdef HAVE_LINUX_NETWORK
   /* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
      available from SIOCGIFMTU */
@@ -500,6 +511,7 @@
 	  int do_slaac = 0;
 	  int deprecate  = 0;
 	  int constructed = 0;
+	  int adv_router = 0;
 	  unsigned int time = 0xffffffff;
 	  struct dhcp_context *context;
 	  
@@ -511,8 +523,7 @@
 	      {
 		context->saved_valid = valid;
 
-		if ((context->flags & 
-		     (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
+		if (context->flags & CONTEXT_RA) 
 		  {
 		    do_slaac = 1;
 		    if (context->flags & CONTEXT_DHCP)
@@ -530,7 +541,17 @@
 		    param->managed = 1;
 		    param->other = 1;
 		  }
-		
+
+		/* Configured to advertise router address, not prefix. See RFC 3775 7.2 
+		 In this case we do all addresses associated with a context, 
+		 hence the real_prefix setting here. */
+		if (context->flags & CONTEXT_RA_ROUTER)
+		  {
+		    adv_router = 1;
+		    param->adv_router = 1;
+		    real_prefix = context->prefix;
+		  }
+
 		/* find floor time, don't reduce below 3 * RA interval. */
 		if (time > context->lease_time)
 		  {
@@ -556,7 +577,7 @@
 		/* subsequent prefixes on the same interface 
 		   and subsequent instances of this prefix don't need timers.
 		   Be careful not to find the same prefix twice with different
-		   addresses. */
+		   addresses unless we're advertising the actual addresses. */
 		if (!(context->flags & CONTEXT_RA_DONE))
 		  {
 		    if (!param->first)
@@ -607,13 +628,18 @@
 	      if ((opt = expand(sizeof(struct prefix_opt))))
 		{
 		  /* zero net part of address */
-		  setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
+		  if (!adv_router)
+		    setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
 		  
 		  opt->type = ICMP6_OPT_PREFIX;
 		  opt->len = 4;
 		  opt->prefix_len = real_prefix;
 		  /* autonomous only if we're not doing dhcp, always set "on-link" */
-		  opt->flags = do_slaac ? 0xC0 : 0x80;
+		  opt->flags = 0x80;
+		  if (do_slaac)
+		    opt->flags |= 0x40;
+		  if (adv_router)
+		    opt->flags |= 0x20;
 		  opt->valid_lifetime = htonl(valid);
 		  opt->preferred_lifetime = htonl(preferred);
 		  opt->reserved = 0;