[radvd-devel-l] RDNSS Option
Pekka Savola
pekkas at netcore.fi
Wed Mar 29 07:38:18 EST 2006
Hi,
On Tue, 28 Mar 2006, Mickaël Guérin wrote:
> I'm still alive ;)
>
> I've completed the path.
> The parser has been modified so you can now use "RDNSS ip [ip] [ip] { ... }"
> syntax. I have also deleted the grouping of rdnss ip : it can be done in the
> configuration file by hand.
> (radvdump now supports the rdnss option)
Thanks a lot. I've added this to the CVS. I made some minor changes and
fixes, mainly to the documentation (e.g., the example used 'rdnss ip ...' while
the syntax was 'RDNSS ip ...'. (see attached.)
The only thing missing seems to be an implementation of this (if you could
patch this if it makes sense -- great; if not, I'll just take a look at it
myself) :
Lifetime SHOULD be bounded as
follows:
MaxRtrAdvInterval<=Lifetime<=2*MaxRtrAdvInterval.
If you have some spare time, you might also consider submitting a dissector
(now or at a later phase, e.g., when the doc has been approved for publication)
to the tcpdump/ethereal communities.
--
Pekka Savola "You each name yourselves king, yet the
Netcore Oy kingdom bleeds."
Systems. Networks. Security. -- George R.R. Martin: A Clash of Kings
-------------- next part --------------
Index: CHANGES
===================================================================
RCS file: /work/cvsroot/radvd/CHANGES,v
retrieving revision 1.56
diff -u -r1.56 CHANGES
--- CHANGES 6 Mar 2006 09:29:15 -0000 1.56
+++ CHANGES 29 Mar 2006 12:30:57 -0000
@@ -1,5 +1,8 @@
$Id: CHANGES,v 1.56 2006/03/06 09:29:15 psavola Exp $
+03/29/2006 Implement RDNSS draft, using non-allocated
+ IANA ND type value 25, by Mickaël Guérin.
+
03/06/2006 Exit when sending RAs if the interface no longer
exists unless IgnoreIfMissing is defined. Fix
the default STDERR+syslog logging methods, so
Index: defaults.h
===================================================================
RCS file: /work/cvsroot/radvd/defaults.h,v
retrieving revision 1.15
diff -u -r1.15 defaults.h
--- defaults.h 18 Oct 2005 19:17:29 -0000 1.15
+++ defaults.h 29 Mar 2006 12:30:58 -0000
@@ -62,6 +62,11 @@
#define DFLT_AdvRoutePreference 0 /* medium*/
+/* RDNSS */
+#define DFLT_AdvRDNSSPreference 8 /* medium */
+#define DFLT_AdvRDNSSOpenFlag 0
+#define DFLT_AdvRDNSSLifetime 30 /* seconds */
+
/* Protocol (RFC2461) constants: */
/* Router constants: */
@@ -148,6 +153,28 @@
#define ND_OPT_RI_PRF_SHIFT 3
#define ND_OPT_RI_PRF_MASK (3 << ND_OPT_RI_PRF_SHIFT) /* 00011000 = 0x18 */
+#undef ND_OPT_RDNSS_INFORMATION
+#define ND_OPT_RDNSS_INFORMATION 25
+
+/* */
+struct nd_opt_rdnss_info_local
+{
+ uint8_t nd_opt_rdnssi_type;
+ uint8_t nd_opt_rdnssi_len;
+ uint16_t nd_opt_rdnssi_pref_flag_reserved;
+ uint32_t nd_opt_rdnssi_lifetime;
+ struct in6_addr nd_opt_rdnssi_adrr1;
+ struct in6_addr nd_opt_rdnssi_adrr2;
+ struct in6_addr nd_opt_rdnssi_adrr3;
+};
+/* pref/flag/reserved field : yyyyx00000000000 (big endian) - 00000000yyyyx000 (little indian); where yyyy = pref, x = flag */
+#if BYTE_ORDER == BIG_ENDIAN
+#define ND_OPT_RDNSSI_PREF_SHIFT 12
+#else
+#define ND_OPT_RDNSSI_PREF_SHIFT 4
+#endif
+#define ND_OPT_RDNSSI_PREF_MASK (0xf << ND_OPT_RDNSSI_PREF_SHIFT)
+
/* Flags */
#ifndef ND_RA_FLAG_HOME_AGENT
@@ -156,6 +183,13 @@
#ifndef ND_OPT_PI_FLAG_RADDR
#define ND_OPT_PI_FLAG_RADDR 0x20
#endif
+#ifndef ND_OPT_RDNSSI_FLAG_S
+#if BYTE_ORDER == BIG_ENDIAN
+#define ND_OPT_RDNSSI_FLAG_S 0x0800
+#else
+#define ND_OPT_RDNSSI_FLAG_S 0x0008
+#endif
+#endif
/* Configurable values */
Index: gram.y
===================================================================
RCS file: /work/cvsroot/radvd/gram.y,v
retrieving revision 1.14
diff -u -r1.14 gram.y
--- gram.y 30 Dec 2005 15:13:11 -0000 1.14
+++ gram.y 29 Mar 2006 12:30:58 -0000
@@ -23,6 +23,7 @@
struct Interface *iface = NULL;
struct AdvPrefix *prefix = NULL;
struct AdvRoute *route = NULL;
+struct AdvRDNSS *rdnss = NULL;
extern char *conf_file;
extern int num_lines;
@@ -48,6 +49,7 @@
%token T_INTERFACE
%token T_PREFIX
%token T_ROUTE
+%token T_RDNSS
%token <str> STRING
%token <num> NUMBER
@@ -91,6 +93,10 @@
%token T_AdvRoutePreference
%token T_AdvRouteLifetime
+%token T_AdvRDNSSPreference
+%token T_AdvRDNSSOpenFlag
+%token T_AdvRDNSSLifetime
+
%token T_AdvMobRtrSupportFlag
%token T_BAD_TOKEN
@@ -98,7 +104,9 @@
%type <str> name
%type <pinfo> optional_prefixlist prefixdef prefixlist
%type <rinfo> optional_routelist routedef routelist
+%type <rdnssinfo> optional_rdnsslist rdnssdef rdnsslist
%type <num> number_or_infinity
+%type <addr> rdnssaddrs
%union {
unsigned int num;
@@ -109,6 +117,7 @@
char *str;
struct AdvPrefix *pinfo;
struct AdvRoute *rinfo;
+ struct AdvRDNSS *rdnssinfo;
};
%%
@@ -183,10 +192,11 @@
}
;
-ifaceparams : optional_ifacevlist optional_prefixlist optional_routelist
+ifaceparams : optional_ifacevlist optional_prefixlist optional_routelist optional_rdnsslist
{
iface->AdvPrefixList = $2;
iface->AdvRouteList = $3;
+ iface->AdvRDNSSList = $4;
}
;
@@ -207,6 +217,13 @@
}
| routelist
;
+
+optional_rdnsslist: /* empty */
+ {
+ $$ = NULL;
+ }
+ | rdnsslist
+ ;
ifacevlist : ifacevlist ifaceval
| ifaceval
@@ -472,7 +489,92 @@
route->AdvRouteLifetime = $2;
}
;
+
+rdnsslist : rdnssdef
+ {
+ $$ = $1;
+ }
+ | rdnsslist rdnssdef
+ {
+ $2->next = $1;
+ $$ = $2;
+ }
+ ;
+
+rdnssdef : rdnsshead '{' optional_rdnssplist '}' ';'
+ {
+ $$ = rdnss;
+ rdnss = NULL;
+ }
+ ;
+rdnssaddrs: /* empty */
+ | rdnssaddrs IPV6ADDR
+ {
+ if (!rdnss) {
+ /* first IP found */
+ rdnss = malloc(sizeof(struct AdvRDNSS));
+
+ if (rdnss == NULL) {
+ flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
+ ABORT;
+ }
+
+ rdnss_init_defaults(rdnss, iface);
+ }
+
+ switch (rdnss->AdvRDNSSNumber) {
+ case 0:
+ memcpy(&rdnss->AdvRDNSSAddr1, $2, sizeof(struct in6_addr));
+ rdnss->AdvRDNSSNumber++;
+ break;
+ case 1:
+ memcpy(&rdnss->AdvRDNSSAddr2, $2, sizeof(struct in6_addr));
+ rdnss->AdvRDNSSNumber++;
+ break;
+ case 2:
+ memcpy(&rdnss->AdvRDNSSAddr3, $2, sizeof(struct in6_addr));
+ rdnss->AdvRDNSSNumber++;
+ break;
+ default:
+ flog(LOG_CRIT, "Too many addresses in RDNSS section");
+ ABORT;
+ }
+
+ }
+ ;
+
+rdnsshead : T_RDNSS rdnssaddrs
+ {
+ if (!rdnss) {
+ flog(LOG_CRIT, "No address specified in RDNSS section");
+ ABORT;
+ }
+ }
+ ;
+
+optional_rdnssplist: /* empty */
+ | rdnssplist
+ ;
+
+rdnssplist : rdnssplist rdnssparms
+ | rdnssparms
+ ;
+
+
+rdnssparms : T_AdvRDNSSPreference NUMBER ';'
+ {
+ rdnss->AdvRDNSSPreference = $2;
+ }
+ | T_AdvRDNSSOpenFlag SWITCH ';'
+ {
+ rdnss->AdvRDNSSOpenFlag = $2;
+ }
+ | T_AdvRDNSSLifetime number_or_infinity ';'
+ {
+ rdnss->AdvRDNSSLifetime = $2;
+ }
+ ;
number_or_infinity : NUMBER
{
Index: interface.c
===================================================================
RCS file: /work/cvsroot/radvd/interface.c,v
retrieving revision 1.14
diff -u -r1.14 interface.c
--- interface.c 18 Jan 2006 16:06:00 -0000 1.14
+++ interface.c 29 Mar 2006 12:30:58 -0000
@@ -67,6 +67,17 @@
route->AdvRoutePreference = DFLT_AdvRoutePreference;
}
+void
+rdnss_init_defaults(struct AdvRDNSS *rdnss, struct Interface *iface)
+{
+ memset(rdnss, 0, sizeof(struct AdvRDNSS));
+
+ rdnss->AdvRDNSSPreference = DFLT_AdvRDNSSPreference;
+ rdnss->AdvRDNSSOpenFlag = DFLT_AdvRDNSSOpenFlag;
+ rdnss->AdvRDNSSLifetime = DFLT_AdvRDNSSLifetime;
+ rdnss->AdvRDNSSNumber = 0;
+}
+
int
check_iface(struct Interface *iface)
{
Index: radvd.c
===================================================================
RCS file: /work/cvsroot/radvd/radvd.c,v
retrieving revision 1.26
diff -u -r1.26 radvd.c
--- radvd.c 6 Mar 2006 09:29:15 -0000 1.26
+++ radvd.c 29 Mar 2006 12:30:58 -0000
@@ -397,6 +397,7 @@
struct Interface *next_iface = iface->next;
struct AdvPrefix *prefix;
struct AdvRoute *route;
+ struct AdvRDNSS *rdnss;
dlog(LOG_DEBUG, 4, "freeing interface %s", iface->Name);
@@ -416,7 +417,16 @@
free(route);
route = next_route;
- }
+ }
+
+ rdnss = iface->AdvRDNSSList;
+ while (rdnss)
+ {
+ struct AdvRDNSS *next_rdnss = rdnss->next;
+
+ free(rdnss);
+ rdnss = next_rdnss;
+ }
free(iface);
iface = next_iface;
Index: radvd.conf.5.man
===================================================================
RCS file: /work/cvsroot/radvd/radvd.conf.5.man,v
retrieving revision 1.17
diff -u -r1.17 radvd.conf.5.man
--- radvd.conf.5.man 6 Mar 2006 09:26:56 -0000 1.17
+++ radvd.conf.5.man 29 Mar 2006 12:30:59 -0000
@@ -29,6 +29,7 @@
list of interface specific options
list of prefix definitions
list of route definitions
+ list of RDNSS definitions
.B };
.fi
@@ -65,6 +66,14 @@
The prefix of a route definition should be network prefix; it can be used to
advertise more specific routes to the hosts.
+RDNSS (Recursive DNS server) definitions are of the form:
+
+.nf
+.BR "RDNSS " "ip [ip] [ip] " {
+ list of rdnss specific options
+.B };
+.fi
+
.SH INTERFACE SPECIFIC OPTIONS
.TP
@@ -426,6 +435,29 @@
Default: medium
+.SH RDNSS SPECIFIC OPTIONS
+
+.TP
+.BR "AdvRDNSSPreference " integer;
+
+The preference of the DNS server, compared to other DNS servers advertised and used.
+0 to 7 means less important than manually configured nameservers in resolv.conf, while 12 to 15 means more important.
+
+Default: 8
+
+.TP
+.BR "AdvRDNSSOpen " on | off;
+
+"Service Open" flag. When set, indicates that RDNSS continues to be available to hosts even if they moved to a different subnet.
+
+Default: off
+
+.TP
+.BR "AdvRDNSSLifetime " seconds | infinity;
+The maximum duration how long the RDNSS entries are used for name resolution. A value of 0 means the nameserver should no longer be used.
+
+Default: 30 seconds
+
.SH EXAMPLES
.nf
@@ -541,6 +573,9 @@
.PP
Devarapalli, V., Wakikawa, R., Petrescu, A., and P. Thubert "Network Mobility (NEMO) Basic Support Protocol",
RFC 3963, January 2005.
+.PP
+J. Jeong, L. Beloeil, and S. Madanapalli, "IPv6 Router Advertisement Option for DNS Configuration",
+IETF Draft v08 (January 18, 2006).
.SH "SEE ALSO"
Index: radvd.conf.example
===================================================================
RCS file: /work/cvsroot/radvd/radvd.conf.example,v
retrieving revision 1.7
diff -u -r1.7 radvd.conf.example
--- radvd.conf.example 8 Jul 2005 11:44:46 -0000 1.7
+++ radvd.conf.example 29 Mar 2006 12:30:59 -0000
@@ -50,16 +50,6 @@
};
#
-# example of a more specific route
-# NOTE: This feature is still being specified and is not widely supported!
-#
- route 2001:db0:fff::/48
- {
- AdvRoutePreference high;
- AdvRouteLifetime 3600;
- };
-
-#
# example of a 6to4 prefix
#
# Note that the first 48 bits are specified here as zeros. These will be
@@ -101,5 +91,27 @@
AdvPreferredLifetime 120;
AdvValidLifetime 300;
};
+#
+# example of a more specific route
+# NOTE: This feature is still being specified and is not widely supported!
+#
+ route 2001:db0:fff::/48
+ {
+ AdvRoutePreference high;
+ AdvRouteLifetime 3600;
+ };
+
+#
+# RDNSS
+# NOTE: This feature is still a draft has no IANA number type for the moment
+#
+ RDNSS 2001:db8::1 2001:db8::2
+ {
+ AdvRDNSSPreference 8;
+ AdvRDNSSOpen off;
+ AdvRDNSSLifetime 30;
+ };
+
};
+
Index: radvd.h
===================================================================
RCS file: /work/cvsroot/radvd/radvd.h,v
retrieving revision 1.19
diff -u -r1.19 radvd.h
--- radvd.h 18 Jan 2006 16:21:16 -0000 1.19
+++ radvd.h 29 Mar 2006 12:30:59 -0000
@@ -83,11 +83,11 @@
struct AdvPrefix *AdvPrefixList;
struct AdvRoute *AdvRouteList;
+ struct AdvRDNSS *AdvRDNSSList;
struct timer_lst tm;
- time_t last_multicast_sec;
- suseconds_t last_multicast_usec;
+ time_t last_multicast_sec;
+ suseconds_t last_multicast_usec;
struct Interface *next;
-
};
struct AdvPrefix {
@@ -100,7 +100,7 @@
uint32_t AdvPreferredLifetime;
/* Mobile IPv6 extensions */
- int AdvRouterAddr;
+ int AdvRouterAddr;
/* 6to4 extensions */
char if6to4[IFNAMSIZ];
@@ -121,6 +121,19 @@
struct AdvRoute *next;
};
+/* Option for DNS configuration */
+struct AdvRDNSS {
+ int AdvRDNSSNumber;
+ uint8_t AdvRDNSSPreference;
+ int AdvRDNSSOpenFlag;
+ uint32_t AdvRDNSSLifetime;
+ struct in6_addr AdvRDNSSAddr1;
+ struct in6_addr AdvRDNSSAddr2;
+ struct in6_addr AdvRDNSSAddr3;
+
+ struct AdvRDNSS *next;
+};
+
/* Mobile IPv6 extensions */
struct AdvInterval {
@@ -178,6 +191,7 @@
void iface_init_defaults(struct Interface *);
void prefix_init_defaults(struct AdvPrefix *);
void route_init_defaults(struct AdvRoute *, struct Interface *);
+void rdnss_init_defaults(struct AdvRDNSS *, struct Interface *);
int check_iface(struct Interface *);
/* socket.c */
Index: radvdump.c
===================================================================
RCS file: /work/cvsroot/radvd/radvdump.c,v
retrieving revision 1.13
diff -u -r1.13 radvdump.c
--- radvdump.c 30 Dec 2005 16:12:23 -0000 1.13
+++ radvdump.c 29 Mar 2006 12:30:59 -0000
@@ -281,6 +281,8 @@
break;
case ND_OPT_ROUTE_INFORMATION:
break;
+ case ND_OPT_RDNSS_INFORMATION:
+ break;
default:
dlog(LOG_DEBUG, 1, "unknown option %d in RA",
(int)*opt_str);
@@ -303,6 +305,7 @@
int optlen;
struct nd_opt_prefix_info *pinfo;
struct nd_opt_route_info_local *rinfo;
+ struct nd_opt_rdnss_info_local *rdnss_info;
char prefix_str[INET6_ADDRSTRLEN];
if (orig_len < 2)
@@ -390,6 +393,45 @@
printf("\t\tAdvRouteLifetime infinity; # (0xffffffff)\n");
else
printf("\t\tAdvRouteLifetime %u;\n", ntohl(rinfo->nd_opt_ri_lifetime));
+
+ printf("\t}; # End of route definition\n\n");
+ break;
+ case ND_OPT_RDNSS_INFORMATION:
+ rdnss_info = (struct nd_opt_rdnss_info_local *) opt_str;
+
+ printf("\n\tRDNSS");
+
+ print_addr(&rdnss_info->nd_opt_rdnssi_adrr1, prefix_str);
+ printf(" %s", prefix_str);
+
+ if (rdnss_info->nd_opt_rdnssi_len >= 5) {
+ print_addr(&rdnss_info->nd_opt_rdnssi_adrr2, prefix_str);
+ printf(" %s", prefix_str);
+ }
+ if (rdnss_info->nd_opt_rdnssi_len >= 7) {
+ print_addr(&rdnss_info->nd_opt_rdnssi_adrr3, prefix_str);
+ printf(" %s", prefix_str);
+ }
+
+ printf("\n\t{\n");
+ if (!edefs
+ || ((rdnss_info->nd_opt_rdnssi_pref_flag_reserved & ND_OPT_RDNSSI_PREF_MASK) >> ND_OPT_RDNSSI_PREF_SHIFT) != DFLT_AdvRDNSSPreference)
+ printf("\t\tAdvRDNSSPreference %d;\n",
+ (rdnss_info->nd_opt_rdnssi_pref_flag_reserved & ND_OPT_RDNSSI_PREF_MASK) >> ND_OPT_RDNSSI_PREF_SHIFT);
+
+ if (!edefs
+ || ((rdnss_info->nd_opt_rdnssi_pref_flag_reserved & ND_OPT_RDNSSI_FLAG_S) == 0 ) == DFLT_AdvRDNSSOpenFlag)
+ printf("\t\tAdvRDNSSOpen %s;\n", rdnss_info->nd_opt_rdnssi_pref_flag_reserved & ND_OPT_RDNSSI_FLAG_S ? "on" : "off");
+ if (!edefs
+ || ntohl(rdnss_info->nd_opt_rdnssi_lifetime) != DFLT_AdvRDNSSLifetime ) {
+ if (ntohl(rdnss_info->nd_opt_rdnssi_lifetime) == 0xffffffff)
+ printf("\t\tAdvRDNSSLifetime infinity; # (0xffffffff)\n");
+ else
+ printf("\t\tAdvRDNSSLifetime %u;\n", ntohl(rdnss_info->nd_opt_rdnssi_lifetime));
+ }
+
+ printf("\t}; # End of RDNSS definition\n\n");
+ break;
default:
break;
}
Index: scanner.l
===================================================================
RCS file: /work/cvsroot/radvd/scanner.l,v
retrieving revision 1.11
diff -u -r1.11 scanner.l
--- scanner.l 18 Oct 2005 19:17:29 -0000 1.11
+++ scanner.l 29 Mar 2006 12:30:59 -0000
@@ -44,6 +44,7 @@
interface { return T_INTERFACE; }
prefix { return T_PREFIX; }
route { return T_ROUTE; }
+RDNSS { return T_RDNSS; }
IgnoreIfMissing { return T_IgnoreIfMissing; }
AdvSendAdvert { return T_AdvSendAdvert; }
@@ -78,6 +79,10 @@
AdvRoutePreference { return T_AdvRoutePreference; }
AdvRouteLifetime { return T_AdvRouteLifetime; }
+AdvRDNSSPreference { return T_AdvRDNSSPreference; }
+AdvRDNSSOpen { return T_AdvRDNSSOpenFlag; }
+AdvRDNSSLifetime { return T_AdvRDNSSLifetime; }
+
MinDelayBetweenRAs { return T_MinDelayBetweenRAs; }
AdvMobRtrSupportFlag { return T_AdvMobRtrSupportFlag; }
Index: send.c
===================================================================
RCS file: /work/cvsroot/radvd/send.c,v
retrieving revision 1.21
diff -u -r1.21 send.c
--- send.c 6 Mar 2006 09:26:56 -0000 1.21
+++ send.c 29 Mar 2006 12:30:59 -0000
@@ -31,6 +31,7 @@
struct nd_router_advert *radvert;
struct AdvPrefix *prefix;
struct AdvRoute *route;
+ struct AdvRDNSS *rdnss;
unsigned char buff[MSG_SIZE];
int len = 0;
int err;
@@ -160,6 +161,38 @@
route = route->next;
}
+ rdnss = iface->AdvRDNSSList;
+
+ /*
+ * add rdnss options
+ */
+
+ while(rdnss)
+ {
+ struct nd_opt_rdnss_info_local *rdnssinfo;
+
+ rdnssinfo = (struct nd_opt_rdnss_info_local *) (buff + len);
+
+ rdnssinfo->nd_opt_rdnssi_type = ND_OPT_RDNSS_INFORMATION;
+ rdnssinfo->nd_opt_rdnssi_len = 1 + 2*rdnss->AdvRDNSSNumber;
+ rdnssinfo->nd_opt_rdnssi_pref_flag_reserved =
+ ((rdnss->AdvRDNSSPreference << ND_OPT_RDNSSI_PREF_SHIFT) & ND_OPT_RDNSSI_PREF_MASK);
+ rdnssinfo->nd_opt_rdnssi_pref_flag_reserved |=
+ ((rdnss->AdvRDNSSOpenFlag)?ND_OPT_RDNSSI_FLAG_S:0);
+
+ rdnssinfo->nd_opt_rdnssi_lifetime = htonl(rdnss->AdvRDNSSLifetime);
+
+ memcpy(&rdnssinfo->nd_opt_rdnssi_adrr1, &rdnss->AdvRDNSSAddr1,
+ sizeof(struct in6_addr));
+ memcpy(&rdnssinfo->nd_opt_rdnssi_adrr2, &rdnss->AdvRDNSSAddr2,
+ sizeof(struct in6_addr));
+ memcpy(&rdnssinfo->nd_opt_rdnssi_adrr3, &rdnss->AdvRDNSSAddr3,
+ sizeof(struct in6_addr));
+ len += sizeof(*rdnssinfo) - (3-rdnss->AdvRDNSSNumber)*sizeof(struct in6_addr);
+
+ rdnss = rdnss->next;
+ }
+
/*
* add MTU option
*/
More information about the radvd-devel-l
mailing list