Permalink
Browse files

Support RFC 6106 by adding DNS search list option.

Patch from Pierre Ossman.
  • Loading branch information...
1 parent 2f041b5 commit e50b49f55d0cc1303c7e88698e01612d707f8eca psavola committed Dec 14, 2010
Showing with 360 additions and 18 deletions.
  1. +2 −1 CHANGES
  2. +17 −1 defaults.h
  3. +100 −1 gram.y
  4. +9 −1 interface.c
  5. +38 −1 process.c
  6. +16 −1 radvd.c
  7. +22 −1 radvd.conf.5.man
  8. +8 −0 radvd.conf.example
  9. +15 −2 radvd.h
  10. +49 −1 radvdump.c
  11. +9 −6 scanner.l
  12. +56 −1 send.c
  13. +19 −1 util.c
View
@@ -1,6 +1,7 @@
-$Id: CHANGES,v 1.104 2010/12/14 11:23:16 psavola Exp $
+$Id: CHANGES,v 1.105 2010/12/14 11:41:17 psavola Exp $
14/12/2010 Deprecate old, pre-RFC5006 parameters.
+ Support RFC6106 by adding DNS Search List support.
From Pierre Ossman.
14/12/2010 Integrate cleanup patches from Reuben Hawkins:
View
@@ -1,5 +1,5 @@
/*
- * $Id: defaults.h,v 1.23 2010/12/14 11:23:16 psavola Exp $
+ * $Id: defaults.h,v 1.24 2010/12/14 11:41:17 psavola Exp $
*
* Authors:
* Lars Fenneberg <lf@elemental.net>
@@ -65,6 +65,9 @@
/* RDNSS */
#define DFLT_AdvRDNSSLifetime(iface) (iface)->MaxRtrAdvInterval
+/* DNSSL */
+#define DFLT_AdvDNSSLLifetime(iface) (iface)->MaxRtrAdvInterval
+
/* Protocol (RFC4861) constants: */
/* Router constants: */
@@ -179,6 +182,19 @@ struct nd_opt_rdnss_info_local
#endif
#define ND_OPT_RDNSSI_PREF_MASK (0xf << ND_OPT_RDNSSI_PREF_SHIFT)
+#undef ND_OPT_DNSSL_INFORMATION
+#define ND_OPT_DNSSL_INFORMATION 31
+
+/* */
+struct nd_opt_dnssl_info_local
+{
+ uint8_t nd_opt_dnssli_type;
+ uint8_t nd_opt_dnssli_len;
+ uint16_t nd_opt_dnssli_reserved;
+ uint32_t nd_opt_dnssli_lifetime;
+ char nd_opt_dnssli_suffixes[];
+};
+
/* Flags */
#ifndef ND_RA_FLAG_HOME_AGENT
View
101 gram.y
@@ -1,5 +1,5 @@
/*
- * $Id: gram.y,v 1.24 2010/12/14 11:23:16 psavola Exp $
+ * $Id: gram.y,v 1.25 2010/12/14 11:41:17 psavola Exp $
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
@@ -24,6 +24,7 @@ struct Interface *iface = NULL;
struct AdvPrefix *prefix = NULL;
struct AdvRoute *route = NULL;
struct AdvRDNSS *rdnss = NULL;
+struct AdvDNSSL *dnssl = NULL;
extern char *conf_file;
extern int num_lines;
@@ -62,6 +63,7 @@ static void yyerror(char *msg);
%token T_PREFIX
%token T_ROUTE
%token T_RDNSS
+%token T_DNSSL
%token T_CLIENTS
%token <str> STRING
@@ -110,6 +112,8 @@ static void yyerror(char *msg);
%token T_AdvRDNSSOpenFlag
%token T_AdvRDNSSLifetime
+%token T_AdvDNSSLLifetime
+
%token T_AdvMobRtrSupportFlag
%token T_BAD_TOKEN
@@ -119,6 +123,7 @@ static void yyerror(char *msg);
%type <ainfo> clientslist v6addrlist
%type <rinfo> routedef
%type <rdnssinfo> rdnssdef
+%type <dnsslinfo> dnssldef
%type <num> number_or_infinity
%union {
@@ -130,6 +135,7 @@ static void yyerror(char *msg);
struct AdvPrefix *pinfo;
struct AdvRoute *rinfo;
struct AdvRDNSS *rdnssinfo;
+ struct AdvDNSSL *dnsslinfo;
struct Clients *ainfo;
};
@@ -217,6 +223,7 @@ ifaceparam : ifaceval
| clientslist { ADD_TO_LL(struct Clients, ClientList, $1); }
| routedef { ADD_TO_LL(struct AdvRoute, AdvRouteList, $1); }
| rdnssdef { ADD_TO_LL(struct AdvRDNSS, AdvRDNSSList, $1); }
+ | dnssldef { ADD_TO_LL(struct AdvDNSSL, AdvDNSSLList, $1); }
;
ifaceval : T_MinRtrAdvInterval NUMBER ';'
@@ -622,6 +629,90 @@ rdnssparms : T_AdvRDNSSPreference NUMBER ';'
}
;
+dnssldef : dnsslhead '{' optional_dnsslplist '}' ';'
+ {
+ $$ = dnssl;
+ dnssl = NULL;
+ }
+ ;
+
+dnsslsuffixes : dnsslsuffixes dnsslsuffix
+ | dnsslsuffix
+ ;
+
+dnsslsuffix : STRING
+ {
+ char *ch;
+ for (ch = $1;*ch != '\0';ch++) {
+ if (*ch >= 'A' && *ch <= 'Z')
+ continue;
+ if (*ch >= 'a' && *ch <= 'z')
+ continue;
+ if (*ch >= '0' && *ch <= '9')
+ continue;
+ if (*ch == '-' || *ch == '.')
+ continue;
+
+ flog(LOG_CRIT, "Invalid domain suffix specified");
+ ABORT;
+ }
+
+ if (!dnssl) {
+ /* first domain found */
+ dnssl = malloc(sizeof(struct AdvDNSSL));
+
+ if (dnssl == NULL) {
+ flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
+ ABORT;
+ }
+
+ dnssl_init_defaults(dnssl, iface);
+ }
+
+ dnssl->AdvDNSSLNumber++;
+ dnssl->AdvDNSSLSuffixes =
+ realloc(dnssl->AdvDNSSLSuffixes,
+ dnssl->AdvDNSSLNumber * sizeof(char*));
+ if (dnssl->AdvDNSSLSuffixes == NULL) {
+ flog(LOG_CRIT, "realloc failed: %s", strerror(errno));
+ ABORT;
+ }
+
+ dnssl->AdvDNSSLSuffixes[dnssl->AdvDNSSLNumber - 1] = strdup($1);
+ }
+ ;
+
+dnsslhead : T_DNSSL dnsslsuffixes
+ {
+ if (!dnssl) {
+ flog(LOG_CRIT, "No domain specified in DNSSL section");
+ ABORT;
+ }
+ }
+ ;
+
+optional_dnsslplist: /* empty */
+ | dnsslplist
+ ;
+
+dnsslplist : dnsslplist dnsslparms
+ | dnsslparms
+ ;
+
+
+dnsslparms : T_AdvDNSSLLifetime number_or_infinity ';'
+ {
+ if ($2 < iface->MaxRtrAdvInterval && $2 != 0) {
+ flog(LOG_ERR, "AdvDNSSLLifetime must be at least MaxRtrAdvInterval");
+ ABORT;
+ }
+ if ($2 > 2*(iface->MaxRtrAdvInterval))
+ flog(LOG_WARNING, "Warning: AdvDNSSLLifetime <= 2*MaxRtrAdvInterval would allow stale DNS suffixes to be deleted faster");
+
+ dnssl->AdvDNSSLLifetime = $2;
+ }
+ ;
+
number_or_infinity : NUMBER
{
$$ = $1;
@@ -648,6 +739,14 @@ void cleanup(void)
if (rdnss)
free(rdnss);
+
+ if (dnssl) {
+ int i;
+ for (i = 0;i < dnssl->AdvDNSSLNumber;i++)
+ free(dnssl->AdvDNSSLSuffixes[i]);
+ free(dnssl->AdvDNSSLSuffixes);
+ free(dnssl);
+ }
}
static void
View
@@ -1,5 +1,5 @@
/*
- * $Id: interface.c,v 1.20 2010/12/14 11:23:16 psavola Exp $
+ * $Id: interface.c,v 1.21 2010/12/14 11:41:17 psavola Exp $
*
* Authors:
* Lars Fenneberg <lf@elemental.net>
@@ -77,6 +77,14 @@ rdnss_init_defaults(struct AdvRDNSS *rdnss, struct Interface *iface)
rdnss->AdvRDNSSNumber = 0;
}
+void
+dnssl_init_defaults(struct AdvDNSSL *dnssl, struct Interface *iface)
+{
+ memset(dnssl, 0, sizeof(struct AdvDNSSL));
+
+ dnssl->AdvDNSSLLifetime = DFLT_AdvDNSSLLifetime(iface);
+}
+
int
check_iface(struct Interface *iface)
{
View
@@ -1,5 +1,5 @@
/*
- * $Id: process.c,v 1.19 2009/09/07 07:59:57 psavola Exp $
+ * $Id: process.c,v 1.20 2010/12/14 11:41:17 psavola Exp $
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
@@ -274,11 +274,14 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
int optlen;
struct nd_opt_prefix_info *pinfo;
struct nd_opt_rdnss_info_local *rdnssinfo;
+ struct nd_opt_dnssl_info_local *dnsslinfo;
struct nd_opt_mtu *mtu;
struct AdvPrefix *prefix;
struct AdvRDNSS *rdnss;
char prefix_str[INET6_ADDRSTRLEN];
char rdnss_str[INET6_ADDRSTRLEN];
+ char suffix[256];
+ int offset, label_len;
uint32_t preferred, valid, count;
if (len < 2)
@@ -409,6 +412,40 @@ process_ra(struct Interface *iface, unsigned char *msg, int len,
}
break;
+ case ND_OPT_DNSSL_INFORMATION:
+ dnsslinfo = (struct nd_opt_dnssl_info_local *) opt_str;
+ for (offset = 0; offset < (dnsslinfo->nd_opt_dnssli_len-1)*8;) {
+ label_len = dnsslinfo->nd_opt_dnssli_suffixes[offset++];
+
+ if (label_len == 0) {
+ /*
+ * Ignore empty suffixes. They're
+ * probably just padding...
+ */
+ if (suffix[0] == '\0')
+ continue;
+
+ if (!check_dnssl_presence(iface->AdvDNSSLList, suffix)) {
+ flog(LOG_WARNING, "DNSSL suffix %s received on %s from %s is not advertised by us",
+ suffix, iface->Name, addr_str);
+ }
+
+ suffix[0] = '\0';
+ continue;
+ }
+
+ if ((sizeof(suffix) - strlen(suffix)) < (label_len + 2)) {
+ flog(LOG_ERR, "oversized suffix in DNSSL option on %s from %s",
+ iface->Name, addr_str);
+ break;
+ }
+
+ if (suffix[0] != '\0')
+ strcat(suffix, ".");
+ strncat(suffix, &dnsslinfo->nd_opt_dnssli_suffixes[offset], label_len);
+ offset += label_len;
+ }
+ break;
default:
dlog(LOG_DEBUG, 1, "unknown option %d in RA on %s from %s",
(int)*opt_str, iface->Name, addr_str);
View
17 radvd.c
@@ -1,5 +1,5 @@
/*
- * $Id: radvd.c,v 1.44 2010/12/14 11:19:37 psavola Exp $
+ * $Id: radvd.c,v 1.45 2010/12/14 11:41:17 psavola Exp $
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
@@ -480,6 +480,7 @@ void reload_config(void)
struct AdvPrefix *prefix;
struct AdvRoute *route;
struct AdvRDNSS *rdnss;
+ struct AdvDNSSL *dnssl;
dlog(LOG_DEBUG, 4, "freeing interface %s", iface->Name);
@@ -510,6 +511,20 @@ void reload_config(void)
rdnss = next_rdnss;
}
+ dnssl = iface->AdvDNSSLList;
+ while (dnssl)
+ {
+ struct AdvDNSSL *next_dnssl = dnssl->next;
+ int i;
+
+ for (i = 0; i < dnssl->AdvDNSSLNumber; i++)
+ free(dnssl->AdvDNSSLSuffixes[i]);
+ free(dnssl->AdvDNSSLSuffixes);
+ free(dnssl);
+
+ dnssl = next_dnssl;
+ }
+
free(iface);
iface = next_iface;
}
View
@@ -1,5 +1,5 @@
.\"
-.\" $Id: radvd.conf.5.man,v 1.30 2010/12/14 11:23:16 psavola Exp $
+.\" $Id: radvd.conf.5.man,v 1.31 2010/12/14 11:41:17 psavola Exp $
.\"
.\" Authors:
.\" Lars Fenneberg <lf@elemental.net>
@@ -31,6 +31,7 @@ The file contains one or more interface definitions of the form:
list of clients (IPv6 addresses) to advertise to
list of route definitions
list of RDNSS definitions
+ list of DNSSL definitions
.B };
.fi
@@ -83,6 +84,14 @@ RDNSS (Recursive DNS server) definitions are of the form:
.B };
.fi
+DNSSL (DNS Search List) definitions are of the form:
+
+.nf
+.BR "DNSSL " "suffix [suffix] [suffix] [...] " {
+ list of dnssl specific options
+.B };
+.fi
+
By default radvd will send route advertisements so that every node on the link can use them.
The list of clients (IPv6 address) to advertise to, and accept route solicitations from can be configured.
If done, radvd does not send send messages to the multicast addresses but
@@ -490,6 +499,18 @@ RDNSS info gets removed in a timely fashion, this should not be greater than
Default: 2*MaxRtrAdvInterval
+.SH DNSSL SPECIFIC OPTIONS
+
+.TP
+.BR "AdvDNSSLLifetime " seconds | infinity;
+The maximum duration how long the DNSSL entries are used for name resolution.
+A value of 0 means the suffix should no longer be used.
+The value, if not 0, must be at least MaxRtrAdvInterval. To ensure stale
+DNSSL info gets removed in a timely fashion, this should not be greater than
+2*MaxRtrAdvInterval.
+
+Default: 2*MaxRtrAdvInterval
+
.SH EXAMPLES
.nf
View
@@ -111,6 +111,14 @@ interface eth0
AdvRDNSSLifetime 30;
};
+#
+# DNS Search Lists
+#
+ DNSSL branch.example.com example.com
+ {
+ AdvDNSSLLifetime 30;
+ };
+
};
Oops, something went wrong.

0 comments on commit e50b49f

Please sign in to comment.