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.
> 

Reply via email to