From fc06fb62443c135773ee4c05ed83925cc47b046d Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sat, 7 Jul 2012 10:40:00 +0200 Subject: Implements RDNSS and DNSSL support for RAdv. --- proto/radv/packets.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 177 insertions(+), 4 deletions(-) (limited to 'proto/radv/packets.c') diff --git a/proto/radv/packets.c b/proto/radv/packets.c index ac59ce94..6fdfcaa3 100644 --- a/proto/radv/packets.c +++ b/proto/radv/packets.c @@ -24,8 +24,10 @@ struct radv_ra_packet #define OPT_RA_MANAGED 0x80 #define OPT_RA_OTHER_CFG 0x40 -#define OPT_PREFIX 3 -#define OPT_MTU 5 +#define OPT_PREFIX 3 +#define OPT_MTU 5 +#define OPT_RDNSS 25 +#define OPT_DNSSL 31 struct radv_opt_prefix { @@ -50,6 +52,25 @@ struct radv_opt_mtu u32 mtu; }; +struct radv_opt_rdnss +{ + u8 type; + u8 length; + u16 reserved; + u32 lifetime; + ip_addr servers[]; +}; + +struct radv_opt_dnssl +{ + u8 type; + u8 length; + u16 reserved; + u32 lifetime; + char domain[]; +}; + + static struct radv_prefix_config default_prefix = { .onlink = 1, .autonomous = 1, @@ -57,6 +78,7 @@ static struct radv_prefix_config default_prefix = { .preferred_lifetime = DEFAULT_PREFERRED_LIFETIME }; + static struct radv_prefix_config * radv_prefix_match(struct radv_iface *ifa, struct ifa *a) { @@ -78,10 +100,146 @@ radv_prefix_match(struct radv_iface *ifa, struct ifa *a) return &default_prefix; } +static int +radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *bufend) +{ + struct radv_rdnss_config *rcf = HEAD(*rdnss_list); + + while(NODE_VALID(rcf)) + { + struct radv_rdnss_config *rcf_base = rcf; + struct radv_opt_rdnss *op = (void *) *buf; + int max_i = (bufend - *buf - sizeof(struct radv_opt_rdnss)) / sizeof(ip_addr); + int i = 0; + + if (max_i < 1) + goto too_much; + + op->type = OPT_RDNSS; + op->reserved = 0; + + if (rcf->lifetime_mult) + op->lifetime = htonl(rcf->lifetime_mult * ifa->cf->max_ra_int); + else + op->lifetime = htonl(rcf->lifetime); + + while(NODE_VALID(rcf) && + (rcf->lifetime == rcf_base->lifetime) && + (rcf->lifetime_mult == rcf_base->lifetime_mult)) + { + if (i >= max_i) + goto too_much; + + op->servers[i] = rcf->server; + ipa_hton(op->servers[i]); + i++; + + rcf = NODE_NEXT(rcf); + } + + op->length = 1+2*i; + *buf += 8 * op->length; + } + + return 0; + + too_much: + log(L_WARN "%s: Too many RA options on interface %s", + ifa->ra->p.name, ifa->iface->name); + return -1; +} + +int +radv_process_domain(struct radv_dnssl_config *cf) +{ + /* Format of domain in search list is