On 2018/08/03 14:58, Florian Obser wrote:
> sthen pointed out that it's better to overwrite dns options, not to merge
That works exactly how I'd expect - OK.
> diff --git engine.c engine.c
> index db31fb2a15b..93010cace51 100644
> --- engine.c
> +++ engine.c
> @@ -260,6 +260,7 @@ engine_dispatch_main(int fd, short event, void *bula)
> {
> static struct rad_conf *nconf;
> static struct ra_iface_conf *ra_iface_conf;
> + static struct ra_options_conf *ra_options;
> struct imsg imsg;
> struct imsgev *iev = bula;
> struct imsgbuf *ibuf;
> @@ -325,6 +326,9 @@ engine_dispatch_main(int fd, short event, void *bula)
> fatal(NULL);
> memcpy(nconf, imsg.data, sizeof(struct rad_conf));
> SIMPLEQ_INIT(&nconf->ra_iface_list);
> + SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list);
> + SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list);
> + ra_options = &nconf->ra_options;
> break;
> case IMSG_RECONF_RA_IFACE:
> if ((ra_iface_conf = malloc(sizeof(struct
> @@ -334,10 +338,11 @@ engine_dispatch_main(int fd, short event, void *bula)
> sizeof(struct ra_iface_conf));
> ra_iface_conf->autoprefix = NULL;
> SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list);
> - SIMPLEQ_INIT(&ra_iface_conf->ra_rdnss_list);
> - SIMPLEQ_INIT(&ra_iface_conf->ra_dnssl_list);
> + SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list);
> + SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list);
> SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list,
> ra_iface_conf, entry);
> + ra_options = &ra_iface_conf->ra_options;
> break;
> case IMSG_RECONF_RA_AUTOPREFIX:
> if ((ra_iface_conf->autoprefix = malloc(sizeof(struct
> @@ -361,7 +366,7 @@ engine_dispatch_main(int fd, short event, void *bula)
> fatal(NULL);
> memcpy(ra_rdnss_conf, imsg.data, sizeof(struct
> ra_rdnss_conf));
> - SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_rdnss_list,
> + SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list,
> ra_rdnss_conf, entry);
> break;
> case IMSG_RECONF_RA_DNSSL:
> @@ -370,7 +375,7 @@ engine_dispatch_main(int fd, short event, void *bula)
> fatal(NULL);
> memcpy(ra_dnssl_conf, imsg.data, sizeof(struct
> ra_dnssl_conf));
> - SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_dnssl_list,
> + SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list,
> ra_dnssl_conf, entry);
> break;
> case IMSG_RECONF_END:
> diff --git frontend.c frontend.c
> index e80879c67d5..7b7487f560b 100644
> --- frontend.c
> +++ frontend.c
> @@ -304,6 +304,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
> {
> static struct rad_conf *nconf;
> static struct ra_iface_conf *ra_iface_conf;
> + static struct ra_options_conf *ra_options;
> struct imsg imsg;
> struct imsgev *iev = bula;
> struct imsgbuf *ibuf = &iev->ibuf;
> @@ -367,6 +368,9 @@ frontend_dispatch_main(int fd, short event, void *bula)
> fatal(NULL);
> memcpy(nconf, imsg.data, sizeof(struct rad_conf));
> SIMPLEQ_INIT(&nconf->ra_iface_list);
> + SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list);
> + SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list);
> + ra_options = &nconf->ra_options;
> break;
> case IMSG_RECONF_RA_IFACE:
> if ((ra_iface_conf = malloc(sizeof(struct
> @@ -376,10 +380,11 @@ frontend_dispatch_main(int fd, short event, void *bula)
> ra_iface_conf));
> ra_iface_conf->autoprefix = NULL;
> SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list);
> - SIMPLEQ_INIT(&ra_iface_conf->ra_rdnss_list);
> - SIMPLEQ_INIT(&ra_iface_conf->ra_dnssl_list);
> + SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list);
> + SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list);
> SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list,
> ra_iface_conf, entry);
> + ra_options = &ra_iface_conf->ra_options;
> break;
> case IMSG_RECONF_RA_AUTOPREFIX:
> if ((ra_iface_conf->autoprefix = malloc(sizeof(struct
> @@ -403,7 +408,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
> fatal(NULL);
> memcpy(ra_rdnss_conf, imsg.data, sizeof(struct
> ra_rdnss_conf));
> - SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_rdnss_list,
> + SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list,
> ra_rdnss_conf, entry);
> break;
> case IMSG_RECONF_RA_DNSSL:
> @@ -412,7 +417,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
> fatal(NULL);
> memcpy(ra_dnssl_conf, imsg.data, sizeof(struct
> ra_dnssl_conf));
> - SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_dnssl_list,
> + SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list,
> ra_dnssl_conf, entry);
> break;
> case IMSG_RECONF_END:
> @@ -905,14 +910,15 @@ build_packet(struct ra_iface *ra_iface)
> if (ra_options_conf->mtu > 0)
> len += sizeof(*ndopt_mtu);
> len += sizeof(*ndopt_pi) * ra_iface->prefix_count;
> - if (ra_iface_conf->rdnss_count > 0)
> - len += sizeof(*ndopt_rdnss) + ra_iface_conf->rdnss_count *
> + if (ra_iface_conf->ra_options.rdnss_count > 0)
> + len += sizeof(*ndopt_rdnss) +
> + ra_iface_conf->ra_options.rdnss_count *
> sizeof(struct in6_addr);
>
> - if (ra_iface_conf->dnssl_len > 0)
> + if (ra_iface_conf->ra_options.dnssl_len > 0)
> /* round up to 8 byte boundary */
> - len += sizeof(*ndopt_dnssl) + ((ra_iface_conf->dnssl_len + 7)
> - & ~7);
> + len += sizeof(*ndopt_dnssl) +
> + ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7);
>
> if (len > sizeof(ra_iface->data))
> fatal("%s: packet too big", __func__); /* XXX send multiple */
> @@ -969,35 +975,35 @@ build_packet(struct ra_iface *ra_iface)
> p += sizeof(*ndopt_pi);
> }
>
> - if (ra_iface_conf->rdnss_count > 0) {
> + if (ra_iface_conf->ra_options.rdnss_count > 0) {
> ndopt_rdnss = (struct nd_opt_rdnss *)p;
> ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS;
> ndopt_rdnss->nd_opt_rdnss_len = 1 +
> - ra_iface_conf->rdnss_count * 2;
> + ra_iface_conf->ra_options.rdnss_count * 2;
> ndopt_rdnss->nd_opt_rdnss_reserved = 0;
> ndopt_rdnss->nd_opt_rdnss_lifetime =
> - htonl(ra_iface_conf->rdns_lifetime);
> + htonl(ra_iface_conf->ra_options.rdns_lifetime);
> p += sizeof(struct nd_opt_rdnss);
> - SIMPLEQ_FOREACH(ra_rdnss, &ra_iface_conf->ra_rdnss_list,
> - entry) {
> + SIMPLEQ_FOREACH(ra_rdnss,
> + &ra_iface_conf->ra_options.ra_rdnss_list, entry) {
> memcpy(p, &ra_rdnss->rdnss, sizeof(ra_rdnss->rdnss));
> p += sizeof(ra_rdnss->rdnss);
> }
> }
>
> - if (ra_iface_conf->dnssl_len > 0) {
> + if (ra_iface_conf->ra_options.dnssl_len > 0) {
> ndopt_dnssl = (struct nd_opt_dnssl *)p;
> ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL;
> /* round up to 8 byte boundary */
> ndopt_dnssl->nd_opt_dnssl_len = 1 +
> - ((ra_iface_conf->dnssl_len + 7) & ~7) / 8;
> + ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7) / 8;
> ndopt_dnssl->nd_opt_dnssl_reserved = 0;
> ndopt_dnssl->nd_opt_dnssl_lifetime =
> - htonl(ra_iface_conf->rdns_lifetime);
> + htonl(ra_iface_conf->ra_options.rdns_lifetime);
> p += sizeof(struct nd_opt_dnssl);
>
> - SIMPLEQ_FOREACH(ra_dnssl, &ra_iface_conf->ra_dnssl_list,
> - entry) {
> + SIMPLEQ_FOREACH(ra_dnssl,
> + &ra_iface_conf->ra_options.ra_dnssl_list, entry) {
> label_start = ra_dnssl->search;
> while ((label_end = strchr(label_start, '.')) != NULL) {
> label_len = label_end - label_start;
> diff --git parse.y parse.y
> index 8ffa90569de..32ac7498334 100644
> --- parse.y
> +++ parse.y
> @@ -100,6 +100,8 @@ static struct ra_prefix_conf *ra_prefix_conf;
>
> struct ra_prefix_conf *conf_get_ra_prefix(struct in6_addr*, int);
> struct ra_iface_conf *conf_get_ra_iface(char *);
> +void copy_dns_options(const struct ra_options_conf *,
> + struct ra_options_conf *);
>
> typedef struct {
> union {
> @@ -212,6 +214,7 @@ ra_opt_block : DEFAULT ROUTER yesno {
> | MTU NUMBER {
> ra_options->mtu = $2;
> }
> + | DNS dns_block
> ;
>
> optnl : '\n' optnl /* zero or more newlines */
> @@ -228,6 +231,7 @@ ra_iface : RA_IFACE STRING {
> ra_options = &ra_iface_conf->ra_options;
> } ra_iface_block {
> ra_iface_conf = NULL;
> + ra_options = &conf->ra_options;
> }
> ;
>
> @@ -269,7 +273,6 @@ ra_ifaceoptsl : NO AUTO PREFIX {
> } ra_prefix_block {
> ra_prefix_conf = NULL;
> }
> - | DNS dns_block
> | ra_opt_block
> ;
>
> @@ -305,7 +308,7 @@ dnsopts_l : dnsopts_l dnsoptsl nl
> ;
>
> dnsoptsl : LIFETIME NUMBER {
> - ra_iface_conf->rdns_lifetime = $2;
> + ra_options->rdns_lifetime = $2;
> }
> | NAMESERVER nserver_block
> | SEARCH search_block
> @@ -336,9 +339,9 @@ nserveroptsl : STRING {
> == NULL)
> err(1, "%s", __func__);
> memcpy(&ra_rdnss_conf->rdnss, &addr, sizeof(addr));
> - SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_rdnss_list,
> + SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list,
> ra_rdnss_conf, entry);
> - ra_iface_conf->rdnss_count++;
> + ra_options->rdnss_count++;
> }
> ;
> search_block : '{' optnl searchopts_l '}'
> @@ -375,9 +378,9 @@ searchoptsl : STRING {
> YYERROR;
> }
> }
> - SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_dnssl_list,
> + SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list,
> ra_dnssl_conf, entry);
> - ra_iface_conf->dnssl_len += len + 1;
> + ra_options->dnssl_len += len + 1;
> }
> ;
> %%
> @@ -793,7 +796,8 @@ popfile(void)
> struct rad_conf *
> parse_config(char *filename)
> {
> - struct sym *sym, *next;
> + struct sym *sym, *next;
> + struct ra_iface_conf *iface;
>
> conf = config_new_empty();
> ra_options = NULL;
> @@ -827,9 +831,44 @@ parse_config(char *filename)
> return (NULL);
> }
>
> + if (!SIMPLEQ_EMPTY(&conf->ra_options.ra_rdnss_list) ||
> + !SIMPLEQ_EMPTY(&conf->ra_options.ra_dnssl_list)) {
> + SIMPLEQ_FOREACH(iface, &conf->ra_iface_list, entry)
> + copy_dns_options(&conf->ra_options,
> + &iface->ra_options);
> + }
> +
> return (conf);
> }
>
> +void
> +copy_dns_options(const struct ra_options_conf *src, struct ra_options_conf
> *dst)
> +{
> + struct ra_rdnss_conf *ra_rdnss, *nra_rdnss;
> + struct ra_dnssl_conf *ra_dnssl, *nra_dnssl;
> +
> + if (SIMPLEQ_EMPTY(&dst->ra_rdnss_list)) {
> + SIMPLEQ_FOREACH(ra_rdnss, &src->ra_rdnss_list, entry) {
> + if ((nra_rdnss = calloc(1, sizeof(*nra_rdnss))) == NULL)
> + errx(1, "%s", __func__);
> + memcpy(nra_rdnss, ra_rdnss, sizeof(*nra_rdnss));
> + SIMPLEQ_INSERT_TAIL(&dst->ra_rdnss_list, nra_rdnss,
> + entry);
> + }
> + dst->rdnss_count = src->rdnss_count;
> + }
> + if (SIMPLEQ_EMPTY(&dst->ra_dnssl_list)) {
> + SIMPLEQ_FOREACH(ra_dnssl, &src->ra_dnssl_list, entry) {
> + if ((nra_dnssl = calloc(1, sizeof(*nra_dnssl))) == NULL)
> + errx(1, "%s", __func__);
> + memcpy(nra_dnssl, ra_dnssl, sizeof(*nra_dnssl));
> + SIMPLEQ_INSERT_TAIL(&dst->ra_dnssl_list, nra_dnssl,
> + entry);
> + }
> + dst->dnssl_len = src->dnssl_len;
> + }
> +}
> +
> int
> symset(const char *nam, const char *val, int persist)
> {
> @@ -963,11 +1002,11 @@ conf_get_ra_iface(char *name)
> /* Inherit attributes set in global section. */
> iface->ra_options = conf->ra_options;
>
> - iface->rdns_lifetime = DEFAULT_RDNS_LIFETIME;
> -
> SIMPLEQ_INIT(&iface->ra_prefix_list);
> - SIMPLEQ_INIT(&iface->ra_rdnss_list);
> - SIMPLEQ_INIT(&iface->ra_dnssl_list);
> + SIMPLEQ_INIT(&iface->ra_options.ra_rdnss_list);
> + iface->ra_options.rdnss_count = 0;
> + SIMPLEQ_INIT(&iface->ra_options.ra_dnssl_list);
> + iface->ra_options.dnssl_len = 0;
>
> SIMPLEQ_INSERT_TAIL(&conf->ra_iface_list, iface, entry);
>
> @@ -979,6 +1018,8 @@ clear_config(struct rad_conf *xconf)
> {
> struct ra_iface_conf *iface;
>
> + free_dns_options(&xconf->ra_options);
> +
> while((iface = SIMPLEQ_FIRST(&xconf->ra_iface_list)) != NULL) {
> SIMPLEQ_REMOVE_HEAD(&xconf->ra_iface_list, entry);
> free_ra_iface_conf(iface);
> diff --git printconf.c printconf.c
> index 1f9e1f72b1c..7623a486d93 100644
> --- printconf.c
> +++ printconf.c
> @@ -46,6 +46,10 @@ yesno(int flag)
> void
> print_ra_options(const char *indent, const struct ra_options_conf
> *ra_options)
> {
> + struct ra_rdnss_conf *ra_rdnss;
> + struct ra_dnssl_conf *ra_dnssl;
> + char buf[INET6_ADDRSTRLEN];
> +
> printf("%sdefault router %s\n", indent, yesno(ra_options->dfr));
> printf("%shop limit %d\n", indent, ra_options->cur_hl);
> printf("%smanaged address configuration %s\n", indent,
> @@ -56,6 +60,30 @@ print_ra_options(const char *indent, const struct
> ra_options_conf *ra_options)
> printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
> if (ra_options->mtu > 0)
> printf("%smtu %u\n", indent, ra_options->mtu);
> +
> + if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
> + !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> + printf("%sdns {\n", indent);
> + printf("%s\tlifetime %u\n", indent, ra_options->rdns_lifetime);
> + if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list)) {
> + printf("%s\tnameserver {\n", indent);
> + SIMPLEQ_FOREACH(ra_rdnss,
> + &ra_options->ra_rdnss_list, entry) {
> + inet_ntop(AF_INET6, &ra_rdnss->rdnss,
> + buf, sizeof(buf));
> + printf("%s\t\t%s\n", indent, buf);
> + }
> + printf("%s\t}\n", indent);
> + }
> + if (!SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> + printf("%s\tsearch {\n", indent);
> + SIMPLEQ_FOREACH(ra_dnssl,
> + &ra_options->ra_dnssl_list, entry)
> + printf("%s\t\t%s\n", indent, ra_dnssl->search);
> + printf("%s\t}\n", indent);
> + }
> + printf("%s}\n", indent);
> + }
> }
>
> void
> @@ -74,8 +102,6 @@ print_config(struct rad_conf *conf)
> {
> struct ra_iface_conf *iface;
> struct ra_prefix_conf *prefix;
> - struct ra_rdnss_conf *ra_rdnss;
> - struct ra_dnssl_conf *ra_dnssl;
> char buf[INET6_ADDRSTRLEN], *bufp;
>
> print_ra_options("", &conf->ra_options);
> @@ -101,30 +127,6 @@ print_config(struct rad_conf *conf)
> printf("\t}\n");
> }
>
> - if (!SIMPLEQ_EMPTY(&iface->ra_rdnss_list) ||
> - !SIMPLEQ_EMPTY(&iface->ra_dnssl_list)) {
> - printf("\tdns {\n");
> - printf("\t\tlifetime %u\n", iface->rdns_lifetime);
> - if (!SIMPLEQ_EMPTY(&iface->ra_rdnss_list)) {
> - printf("\t\tnameserver {\n");
> - SIMPLEQ_FOREACH(ra_rdnss,
> - &iface->ra_rdnss_list, entry) {
> - inet_ntop(AF_INET6, &ra_rdnss->rdnss,
> - buf, sizeof(buf));
> - printf("\t\t\t%s\n", buf);
> - }
> - printf("\t\t}\n");
> - }
> - if (!SIMPLEQ_EMPTY(&iface->ra_dnssl_list)) {
> - printf("\t\tsearch {\n");
> - SIMPLEQ_FOREACH(ra_dnssl,
> - &iface->ra_dnssl_list, entry)
> - printf("\t\t\t%s\n", ra_dnssl->search);
> - printf("\t\t}\n");
> - }
> - printf("\t}\n");
> - }
> -
> printf("}\n");
> }
> }
> diff --git rad.c rad.c
> index b741dd5120c..67c9f150d56 100644
> --- rad.c
> +++ rad.c
> @@ -604,6 +604,20 @@ main_imsg_send_config(struct rad_conf *xconf)
> if (main_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1)
> return (-1);
>
> + /* send global dns options to children */
> + SIMPLEQ_FOREACH(ra_rdnss_conf, &xconf->ra_options.ra_rdnss_list,
> + entry) {
> + if (main_sendboth(IMSG_RECONF_RA_RDNSS, ra_rdnss_conf,
> + sizeof(*ra_rdnss_conf)) == -1)
> + return (-1);
> + }
> + SIMPLEQ_FOREACH(ra_dnssl_conf, &xconf->ra_options.ra_dnssl_list,
> + entry) {
> + if (main_sendboth(IMSG_RECONF_RA_DNSSL, ra_dnssl_conf,
> + sizeof(*ra_dnssl_conf)) == -1)
> + return (-1);
> + }
> +
> /* Send the interface list to children. */
> SIMPLEQ_FOREACH(ra_iface_conf, &xconf->ra_iface_list, entry) {
> if (main_sendboth(IMSG_RECONF_RA_IFACE, ra_iface_conf,
> @@ -621,14 +635,14 @@ main_imsg_send_config(struct rad_conf *xconf)
> ra_prefix_conf, sizeof(*ra_prefix_conf)) == -1)
> return (-1);
> }
> - SIMPLEQ_FOREACH(ra_rdnss_conf, &ra_iface_conf->ra_rdnss_list,
> - entry) {
> + SIMPLEQ_FOREACH(ra_rdnss_conf,
> + &ra_iface_conf->ra_options.ra_rdnss_list, entry) {
> if (main_sendboth(IMSG_RECONF_RA_RDNSS, ra_rdnss_conf,
> sizeof(*ra_rdnss_conf)) == -1)
> return (-1);
> }
> - SIMPLEQ_FOREACH(ra_dnssl_conf, &ra_iface_conf->ra_dnssl_list,
> - entry) {
> + SIMPLEQ_FOREACH(ra_dnssl_conf,
> + &ra_iface_conf->ra_options.ra_dnssl_list, entry) {
> if (main_sendboth(IMSG_RECONF_RA_DNSSL, ra_dnssl_conf,
> sizeof(*ra_dnssl_conf)) == -1)
> return (-1);
> @@ -656,8 +670,6 @@ void
> free_ra_iface_conf(struct ra_iface_conf *ra_iface_conf)
> {
> struct ra_prefix_conf *prefix;
> - struct ra_rdnss_conf *ra_rdnss;
> - struct ra_dnssl_conf *ra_dnssl;
>
> if (!ra_iface_conf)
> return;
> @@ -670,33 +682,47 @@ free_ra_iface_conf(struct ra_iface_conf *ra_iface_conf)
> free(prefix);
> }
>
> - while ((ra_rdnss = SIMPLEQ_FIRST(&ra_iface_conf->ra_rdnss_list)) !=
> - NULL) {
> - SIMPLEQ_REMOVE_HEAD(&ra_iface_conf->ra_rdnss_list, entry);
> + free_dns_options(&ra_iface_conf->ra_options);
> +
> + free(ra_iface_conf);
> +}
> +
> +void
> +free_dns_options(struct ra_options_conf *ra_options)
> +{
> + struct ra_rdnss_conf *ra_rdnss;
> + struct ra_dnssl_conf *ra_dnssl;
> +
> + while ((ra_rdnss = SIMPLEQ_FIRST(&ra_options->ra_rdnss_list)) != NULL) {
> + SIMPLEQ_REMOVE_HEAD(&ra_options->ra_rdnss_list, entry);
> free(ra_rdnss);
> }
> + ra_options->rdnss_count = 0;
>
> - while ((ra_dnssl = SIMPLEQ_FIRST(&ra_iface_conf->ra_dnssl_list)) !=
> - NULL) {
> - SIMPLEQ_REMOVE_HEAD(&ra_iface_conf->ra_dnssl_list, entry);
> + while ((ra_dnssl = SIMPLEQ_FIRST(&ra_options->ra_dnssl_list)) != NULL) {
> + SIMPLEQ_REMOVE_HEAD(&ra_options->ra_dnssl_list, entry);
> free(ra_dnssl);
> }
> -
> - free(ra_iface_conf);
> + ra_options->dnssl_len = 0;
> }
>
> void
> merge_config(struct rad_conf *conf, struct rad_conf *xconf)
> {
> struct ra_iface_conf *ra_iface_conf;
> -
> - conf->ra_options = xconf->ra_options;
> + struct ra_rdnss_conf *ra_rdnss;
> + struct ra_dnssl_conf *ra_dnssl;
>
> /* Remove & discard existing interfaces. */
> while ((ra_iface_conf = SIMPLEQ_FIRST(&conf->ra_iface_list)) != NULL) {
> SIMPLEQ_REMOVE_HEAD(&conf->ra_iface_list, entry);
> free_ra_iface_conf(ra_iface_conf);
> }
> + free_dns_options(&conf->ra_options);
> +
> + conf->ra_options = xconf->ra_options;
> + SIMPLEQ_INIT(&conf->ra_options.ra_rdnss_list);
> + SIMPLEQ_INIT(&conf->ra_options.ra_dnssl_list);
>
> /* Add new interfaces. */
> while ((ra_iface_conf = SIMPLEQ_FIRST(&xconf->ra_iface_list)) != NULL) {
> @@ -704,6 +730,19 @@ merge_config(struct rad_conf *conf, struct rad_conf
> *xconf)
> SIMPLEQ_INSERT_TAIL(&conf->ra_iface_list, ra_iface_conf, entry);
> }
>
> + /* Add dns options */
> + while ((ra_rdnss = SIMPLEQ_FIRST(&xconf->ra_options.ra_rdnss_list))
> + != NULL) {
> + SIMPLEQ_REMOVE_HEAD(&xconf->ra_options.ra_rdnss_list, entry);
> + SIMPLEQ_INSERT_TAIL(&conf->ra_options.ra_rdnss_list, ra_rdnss,
> + entry);
> + }
> + while ((ra_dnssl = SIMPLEQ_FIRST(&xconf->ra_options.ra_dnssl_list))
> + != NULL) {
> + SIMPLEQ_REMOVE_HEAD(&xconf->ra_options.ra_dnssl_list, entry);
> + SIMPLEQ_INSERT_TAIL(&conf->ra_options.ra_dnssl_list, ra_dnssl,
> + entry);
> + }
> free(xconf);
> }
>
> @@ -726,6 +765,9 @@ config_new_empty(void)
> xconf->ra_options.reachable_time = 0;
> xconf->ra_options.retrans_timer = 0;
> xconf->ra_options.mtu = 0;
> + xconf->ra_options.rdns_lifetime = DEFAULT_RDNS_LIFETIME;
> + SIMPLEQ_INIT(&xconf->ra_options.ra_rdnss_list);
> + SIMPLEQ_INIT(&xconf->ra_options.ra_dnssl_list);
>
> return (xconf);
> }
> diff --git rad.conf.5 rad.conf.5
> index c07167a2378..eab6972d0d8 100644
> --- rad.conf.5
> +++ rad.conf.5
> @@ -92,6 +92,21 @@ The default is 1800 seconds.
> .\" XXX
> .\" .It Ic retrans timer Ar number
> .\" XXX
> +.It Ic dns Brq dns options
> +.Ic dns
> +options are as follows:
> +.Bl -tag -width Ds
> +.It Ic lifetime Ar seconds
> +The number of seconds the dns options are valid after receiving a router
> +advertisement message.
> +The default is 900 seconds.
> +.It Ic nameserver Pq Ar IP Ns | Ns { nameserver list }
> +IPv6 address or list of IPv6 addresses of DNS name servers.
> +.It Ic search Pq Ar domain Ns | Ns { domain list }
> +Domain or list of domains for the
> +.Xr resolv.conf 5
> +search list.
> +.El
> .El
> .Sh INTERFACES
> A list of interfaces to send advertisments on:
> @@ -130,26 +145,6 @@ The valid lifetime (vltime) in seconds for addresses
> generated from this
> prefix.
> The default is 2592000.
> .El
> -.Pp
> -Name servers are configured inside an interface block:
> -.Bd -unfilled -offset indent
> -.Ic dns Brq dns options
> -.Ed
> -.Pp
> -.Ic dns
> -options are as follows:
> -.Bl -tag -width Ds
> -.It Ic lifetime Ar seconds
> -The number of seconds the dns options are valid after receiving a router
> -advertisement message.
> -The default is 900 seconds.
> -.It Ic nameserver Pq Ar IP Ns | Ns { nameserver list }
> -IPv6 address or list of IPv6 addresses of DNS name servers.
> -.It Ic search Pq Ar domain Ns | Ns { domain list }
> -Domain or list of domains for the
> -.Xr resolv.conf 5
> -search list.
> -.El
> .Sh FILES
> .Bl -tag -width "/etc/rad.conf" -compact
> .It Pa /etc/rad.conf
> diff --git rad.h rad.h
> index 3feeb80dca9..ddd7d977321 100644
> --- rad.h
> +++ rad.h
> @@ -75,6 +75,16 @@ enum imsg_type {
> IMSG_SOCKET_IPC
> };
>
> +/* RFC 8106 */
> +struct ra_rdnss_conf {
> + SIMPLEQ_ENTRY(ra_rdnss_conf) entry;
> + struct in6_addr rdnss;
> +};
> +struct ra_dnssl_conf {
> + SIMPLEQ_ENTRY(ra_dnssl_conf) entry;
> + char search[MAX_SEARCH];
> +};
> +
> /* RFC 4861 Sections 4.2 and 4.6.4 */
> struct ra_options_conf {
> int dfr; /* is default router? */
> @@ -85,6 +95,11 @@ struct ra_options_conf {
> uint32_t reachable_time;
> uint32_t retrans_timer;
> uint32_t mtu;
> + uint32_t rdns_lifetime;
> + SIMPLEQ_HEAD(, ra_rdnss_conf) ra_rdnss_list;
> + int rdnss_count;
> + SIMPLEQ_HEAD(, ra_dnssl_conf) ra_dnssl_list;
> + int dnssl_len;
> };
>
> /* RFC 4861 Section 4.6.2 */
> @@ -98,27 +113,12 @@ struct ra_prefix_conf {
> int aflag; /* autonom. addr flag */
> };
>
> -/* RFC 8106 */
> -struct ra_rdnss_conf {
> - SIMPLEQ_ENTRY(ra_rdnss_conf) entry;
> - struct in6_addr rdnss;
> -};
> -struct ra_dnssl_conf {
> - SIMPLEQ_ENTRY(ra_dnssl_conf) entry;
> - char search[MAX_SEARCH];
> -};
> -
> struct ra_iface_conf {
> SIMPLEQ_ENTRY(ra_iface_conf) entry;
> struct ra_options_conf ra_options;
> struct ra_prefix_conf *autoprefix;
> SIMPLEQ_HEAD(ra_prefix_conf_head,
> ra_prefix_conf) ra_prefix_list;
> - uint32_t rdns_lifetime;
> - SIMPLEQ_HEAD(, ra_rdnss_conf) ra_rdnss_list;
> - int rdnss_count;
> - SIMPLEQ_HEAD(, ra_dnssl_conf) ra_dnssl_list;
> - int dnssl_len;
> char name[IF_NAMESIZE];
> };
>
> @@ -154,6 +154,7 @@ int imsg_compose_event(struct imsgev *, uint16_t,
> uint32_t, pid_t,
> struct rad_conf *config_new_empty(void);
> void config_clear(struct rad_conf *);
> void free_ra_iface_conf(struct ra_iface_conf *);
> +void free_dns_options(struct ra_options_conf *);
> void mask_prefix(struct in6_addr*, int len);
> const char *sin6_to_str(struct sockaddr_in6 *);
> const char *in6_to_str(struct in6_addr *);
>
> --
> I'm not entirely sure you are real.
>