Hi,

So here's a new diff that incorporates the bug fix mentioned plus
debug printf line changes suggested by Stuart.

Please note that this is a diff on top of very recent current, i.e.
florian's work he committed today. That means that you need to be
up-to-date (including a recent libc update that was committed a few
days ago) to be able to test this version.

        -Otto

Index: sbin/unwind/parse.y
===================================================================
RCS file: /cvs/src/sbin/unwind/parse.y,v
retrieving revision 1.12
diff -u -p -r1.12 parse.y
--- sbin/unwind/parse.y 31 Oct 2019 12:51:43 -0000      1.12
+++ sbin/unwind/parse.y 31 Oct 2019 16:32:27 -0000
@@ -84,7 +84,6 @@ int    check_pref_uniq(enum uw_resolver_ty
 
 static struct uw_conf          *conf;
 static int                      errors;
-static struct uw_forwarder     *uw_forwarder;
 
 void                    clear_config(struct uw_conf *xconf);
 struct sockaddr_storage        *host_ip(const char *);
@@ -287,7 +286,9 @@ forwarderopts_l             : forwarderopts_l forwa
 
 forwarderoptsl         : STRING port authname dot {
                                int ret, port;
+                               struct uw_forwarder *uw_fwd;
                                struct sockaddr_storage *ss;
+
                                if ((ss = host_ip($1)) == NULL) {
                                        yyerror("%s is not an ip-address", $1);
                                        free($1);
@@ -305,37 +306,53 @@ forwarderoptsl            : STRING port authname d
                                else
                                        port = $2;
 
-                               if ((uw_forwarder = calloc(1,
-                                   sizeof(*uw_forwarder))) == NULL)
+                               if ($3 != NULL && $4 == 0) {
+                                       yyerror("authentication name can only "
+                                           "be used with DoT");
+                                       free($1);
+                                       YYERROR;
+                               }
+
+
+                               if ((uw_fwd = calloc(1,
+                                   sizeof(*uw_fwd))) == NULL)
                                        err(1, NULL);
 
-                               if ($3 == NULL)
-                                       ret = snprintf(uw_forwarder->name,
-                                           sizeof(uw_forwarder->name),
-                                           "%s@%d", $1, port);
-                               else
-                                       ret = snprintf(uw_forwarder->name,
-                                           sizeof(uw_forwarder->name),
-                                           "%s@%d#%s", $1, port, $3);
+                               if ($4 == DOT) {
+                                       if ($3 == NULL)
+                                               ret = snprintf(uw_fwd->name,
+                                                   sizeof(uw_fwd->name),
+                                                   "%s@%d", $1, port);
+                                       else
+                                               ret = snprintf(uw_fwd->name,
+                                                   sizeof(uw_fwd->name),
+                                                   "%s@%d#%s", $1, port, $3);
+                               } else {
+                                       uw_fwd->port = $2;
+                                       /* complete string wil be done later */
+                                       ret = snprintf(uw_fwd->name,
+                                           sizeof(uw_fwd->name), "%s", $1);
+                               }
                                if (ret < 0 || (size_t)ret >=
-                                   sizeof(uw_forwarder->name)) {
-                                       free(uw_forwarder);
+                                   sizeof(uw_fwd->name)) {
+                                       free(uw_fwd);
                                        yyerror("forwarder %s too long", $1);
                                        free($1);
                                        YYERROR;
                                }
-                               free($1);
 
                                if ($4 == DOT)
                                        SIMPLEQ_INSERT_TAIL(
                                            &conf->uw_dot_forwarder_list,
-                                           uw_forwarder, entry);
-                               else
+                                           uw_fwd, entry);
+                               else {
                                        SIMPLEQ_INSERT_TAIL(
                                            &conf->uw_forwarder_list,
-                                           uw_forwarder, entry);
+                                           uw_fwd, entry);
+                               }
+                               free($1);
                        }
-                       ;
+       ;
 
 port   :       PORT NUMBER     { $$ = $2; }
        |       /* empty */     { $$ = 0; }
@@ -874,12 +891,14 @@ symget(const char *nam)
 void
 clear_config(struct uw_conf *xconf)
 {
-       while((uw_forwarder = SIMPLEQ_FIRST(&xconf->uw_forwarder_list)) !=
+       struct uw_forwarder     *uw_forwarder;
+
+       while ((uw_forwarder = SIMPLEQ_FIRST(&xconf->uw_forwarder_list)) !=
            NULL) {
                SIMPLEQ_REMOVE_HEAD(&xconf->uw_forwarder_list, entry);
                free(uw_forwarder);
        }
-       while((uw_forwarder = SIMPLEQ_FIRST(&xconf->uw_dot_forwarder_list)) !=
+       while ((uw_forwarder = SIMPLEQ_FIRST(&xconf->uw_dot_forwarder_list)) !=
            NULL) {
                SIMPLEQ_REMOVE_HEAD(&xconf->uw_dot_forwarder_list, entry);
                free(uw_forwarder);
Index: sbin/unwind/resolver.c
===================================================================
RCS file: /cvs/src/sbin/unwind/resolver.c,v
retrieving revision 1.48
diff -u -p -r1.48 resolver.c
--- sbin/unwind/resolver.c      31 Oct 2019 12:54:40 -0000      1.48
+++ sbin/unwind/resolver.c      31 Oct 2019 16:32:27 -0000
@@ -115,6 +115,8 @@ struct uw_resolver  *create_resolver(enum
 void                    free_resolver(struct uw_resolver *);
 void                    set_forwarders(struct uw_resolver *,
                             struct uw_forwarder_head *);
+void                    set_forwarders_oppdot(struct uw_resolver *,
+                            struct uw_forwarder_head *, int);
 void                    resolver_check_timo(int, short, void *);
 void                    resolver_free_timo(int, short, void *);
 void                    check_resolver(struct uw_resolver *);
@@ -164,6 +166,7 @@ struct event_base           *ev_base;
 
 enum uw_resolver_state          global_state = DEAD;
 enum captive_portal_state       captive_portal_state = PORTAL_UNCHECKED;
+int                             dhcp_oppdot, forw_oppdot;
 
 void
 resolver_sig_handler(int sig, short event, void *arg)
@@ -607,6 +610,7 @@ resolver_dispatch_main(int fd, short eve
                        nconf = NULL;
                        if (forwarders_changed) {
                                log_debug("static forwarders changed");
+                               forw_oppdot = 1;
                                new_static_forwarders();
                        }
                        if (dot_forwarders_changed) {
@@ -768,7 +772,7 @@ parse_dhcp_forwarders(char *forwarders)
        if (forwarders != NULL) {
                while((ns = strsep(&forwarders, ",")) != NULL) {
                        log_debug("%s: %s", __func__, ns);
-                       if ((uw_forwarder = malloc(sizeof(struct
+                       if ((uw_forwarder = calloc(1, sizeof(struct
                            uw_forwarder))) == NULL)
                                fatal(NULL);
                        if (strlcpy(uw_forwarder->name, ns,
@@ -782,6 +786,7 @@ parse_dhcp_forwarders(char *forwarders)
 
        if (check_forwarders_changed(&new_forwarder_list,
            &dhcp_forwarder_list)) {
+               dhcp_oppdot = 1;
                replace_forwarders(&new_forwarder_list, &dhcp_forwarder_list);
                new_forwarders();
                new_asr_forwarders();
@@ -985,10 +990,24 @@ create_resolver(enum uw_resolver_type ty
        case UW_RES_RECURSOR:
                break;
        case UW_RES_DHCP:
-               set_forwarders(res, &dhcp_forwarder_list);
+               if (dhcp_oppdot) {
+                       set_forwarders_oppdot(res, &dhcp_forwarder_list, 853);
+                       ub_ctx_set_option(res->ctx, "tls-cert-bundle:",
+                           tls_default_ca_cert_file());
+                       ub_ctx_set_tls(res->ctx, 1);
+               } else
+                       set_forwarders_oppdot(res, &dhcp_forwarder_list, 53);
                break;
        case UW_RES_FORWARDER:
-               set_forwarders(res, &resolver_conf->uw_forwarder_list);
+               if (forw_oppdot) {
+                       set_forwarders_oppdot(res,
+                           &resolver_conf->uw_forwarder_list, 853);
+                       ub_ctx_set_option(res->ctx, "tls-cert-bundle:",
+                           tls_default_ca_cert_file());
+                       ub_ctx_set_tls(res->ctx, 1);
+               } else
+                       set_forwarders_oppdot(res,
+                           &resolver_conf->uw_forwarder_list, 53);
                break;
        case UW_RES_DOT:
                set_forwarders(res, &resolver_conf->uw_dot_forwarder_list);
@@ -1034,6 +1053,22 @@ set_forwarders(struct uw_resolver *res, 
 }
 
 void
+set_forwarders_oppdot(struct uw_resolver *res, struct uw_forwarder_head
+    *uw_forwarder_list, int def_port)
+{
+       struct uw_forwarder     *uw_forwarder;
+
+       SIMPLEQ_FOREACH(uw_forwarder, uw_forwarder_list, entry) {
+               char name[1024];
+               int port = uw_forwarder->port;
+               if (port == 0)
+                       port = def_port;
+               snprintf(name, sizeof(name), "%s@%d", uw_forwarder->name, port);
+               ub_ctx_set_fwd(res->ctx, name);
+       }
+}
+
+void
 resolver_check_timo(int fd, short events, void *arg)
 {
        check_resolver((struct uw_resolver *)arg);
@@ -1089,7 +1124,7 @@ check_resolver_done(void *arg, int rcode
 
        data = (struct check_resolver_data *)arg;
 
-       log_debug("%s: rcode: %d", __func__, rcode);
+       log_debug("%s: %s rcode: %d", __func__, 
uw_resolver_type_str[data->res->type], rcode);
 
        prev_state = data->res->state;
 
@@ -1101,6 +1136,25 @@ check_resolver_done(void *arg, int rcode
 
        if (rcode == LDNS_RCODE_SERVFAIL) {
                data->res->state = DEAD;
+
+               switch (data->res->type) {
+               case UW_RES_DHCP:
+                       if (dhcp_oppdot) {
+                               dhcp_oppdot = 0;
+                               log_debug("disabling DHCP OppDoT");
+                               new_forwarders();
+                       }
+                       break;
+               case UW_RES_FORWARDER:
+                       if (forw_oppdot) {
+                               forw_oppdot = 0;
+                               log_debug("disabling forwarder OppDoT");
+                               new_static_forwarders();
+                       }
+                       break;
+               default:
+                       break;
+               }
                goto out;
        }
 
@@ -1259,9 +1313,9 @@ struct uw_resolver*
 best_resolver(void)
 {
        struct uw_resolver      *res = NULL;
-       int                      i;
+       int                      i, oppdot;
 
-       log_debug("%s: %s: %s, %s: %s, %s: %s, %s: %s, %s: %s, "
+       log_debug("%s: %s: %s, %s: %s%s, %s: %s%s, %s: %s, %s: %s, "
            "captive_portal: %s",
            __func__,
            uw_resolver_type_str[UW_RES_RECURSOR], resolvers[UW_RES_RECURSOR]
@@ -1269,9 +1323,11 @@ best_resolver(void)
            : "NA",
            uw_resolver_type_str[UW_RES_DHCP], resolvers[UW_RES_DHCP] != NULL ?
            uw_resolver_state_str[resolvers[UW_RES_DHCP]->state] : "NA",
+           dhcp_oppdot ? " (OppDot)" : "",
            uw_resolver_type_str[UW_RES_FORWARDER],
            resolvers[UW_RES_FORWARDER] != NULL ?
            uw_resolver_state_str[resolvers[UW_RES_FORWARDER]->state] : "NA",
+           forw_oppdot ? " (OppDot)" : "",
            uw_resolver_type_str[UW_RES_DOT],
            resolvers[UW_RES_DOT] != NULL ?
            uw_resolver_state_str[resolvers[UW_RES_DOT]->state] : "NA",
@@ -1295,8 +1351,10 @@ best_resolver(void)
                    resolvers[resolver_conf->res_pref[i]]) < 0)
                        res = resolvers[resolver_conf->res_pref[i]];
 out:
-       log_debug("%s: %s state: %s", __func__, uw_resolver_type_str[res->type],
-           uw_resolver_state_str[res->state]);
+       oppdot = (res->type == UW_RES_DHCP && dhcp_oppdot) ||
+           (res->type == UW_RES_FORWARDER && forw_oppdot);
+       log_debug("%s: %s state: %s%s", __func__, 
uw_resolver_type_str[res->type],
+           uw_resolver_state_str[res->state], oppdot ? " (OppDoT)" : "");
        return (res);
 }
 
@@ -1376,6 +1434,12 @@ send_resolver_info(struct uw_resolver *r
        cri.state = res->state;
        cri.type = res->type;
        cri.selected = selected;
+       if (cri.type == UW_RES_DHCP && dhcp_oppdot)
+               cri.oppdot = 1;
+       else if (cri.type == UW_RES_FORWARDER && forw_oppdot)
+               cri.oppdot = 1;
+       else
+               cri.oppdot = 0;
        resolver_imsg_compose_frontend(IMSG_CTL_RESOLVER_INFO, pid, &cri,
            sizeof(cri));
 }
Index: sbin/unwind/resolver.h
===================================================================
RCS file: /cvs/src/sbin/unwind/resolver.h,v
retrieving revision 1.6
diff -u -p -r1.6 resolver.h
--- sbin/unwind/resolver.h      2 Apr 2019 07:47:23 -0000       1.6
+++ sbin/unwind/resolver.h      31 Oct 2019 16:32:27 -0000
@@ -51,6 +51,7 @@ struct ctl_resolver_info {
        enum uw_resolver_state   state;
        enum uw_resolver_type    type;
        int                      selected;
+       int                      oppdot;
 };
 
 void    resolver(int, int);
Index: sbin/unwind/unwind.h
===================================================================
RCS file: /cvs/src/sbin/unwind/unwind.h,v
retrieving revision 1.20
diff -u -p -r1.20 unwind.h
--- sbin/unwind/unwind.h        31 Oct 2019 12:54:40 -0000      1.20
+++ sbin/unwind/unwind.h        31 Oct 2019 16:32:27 -0000
@@ -126,6 +126,7 @@ enum imsg_type {
 struct uw_forwarder {
        SIMPLEQ_ENTRY(uw_forwarder)              entry;
        char                                     name[1024]; /* XXX */
+       uint16_t                                 port;
 };
 
 SIMPLEQ_HEAD(uw_forwarder_head, uw_forwarder);
Index: usr.sbin/unwindctl/parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/unwindctl/parser.c,v
retrieving revision 1.4
diff -u -p -r1.4 parser.c
--- usr.sbin/unwindctl/parser.c 31 Oct 2019 12:51:43 -0000      1.4
+++ usr.sbin/unwindctl/parser.c 31 Oct 2019 16:32:27 -0000
@@ -72,7 +72,7 @@ static const struct token t_status[] = {
        {NOTOKEN,       "",             NONE,                   NULL},
        {KEYWORD,       "recursor",     STATUS_RECURSOR,        NULL},
        {KEYWORD,       "dhcp",         STATUS_DHCP,            NULL},
-       {KEYWORD,       "static",       STATUS_STATIC,          NULL},
+       {KEYWORD,       "forwarder",    STATUS_STATIC,          NULL},
        {KEYWORD,       "DoT",          STATUS_DOT,             NULL},
        {KEYWORD,       "asr",          STATUS_ASR,             NULL},
        {ENDTOKEN,      "",             STATUS,                 NULL}
Index: usr.sbin/unwindctl/unwindctl.8
===================================================================
RCS file: /cvs/src/usr.sbin/unwindctl/unwindctl.8,v
retrieving revision 1.4
diff -u -p -r1.4 unwindctl.8
--- usr.sbin/unwindctl/unwindctl.8      5 Feb 2019 20:41:12 -0000       1.4
+++ usr.sbin/unwindctl/unwindctl.8      31 Oct 2019 16:32:27 -0000
@@ -55,14 +55,14 @@ Enable very noisy debug logging.
 Reload the configuration file.
 .It Cm recheck portal
 Run the captive portal detection.
-.It Cm status Op Cm recursor | dhcp | DoT | static
+.It Cm status Op Cm recursor | dhcp | DoT | forwarder
 Show a status summary.
 If one of
 .Cm recursor ,
 .Cm dhcp ,
 .Cm DoT ,
 or
-.Cm static
+.Cm forwarder
 is specified, more detailed information about that type of resolver is given
 including reasons why DNSSEC validation might be failing and a query time
 histogram.
Index: usr.sbin/unwindctl/unwindctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/unwindctl/unwindctl.c,v
retrieving revision 1.7
diff -u -p -r1.7 unwindctl.c
--- usr.sbin/unwindctl/unwindctl.c      31 Oct 2019 12:51:43 -0000      1.7
+++ usr.sbin/unwindctl/unwindctl.c      31 Oct 2019 16:32:27 -0000
@@ -247,9 +247,10 @@ show_status_msg(struct imsg *imsg)
                break;
        case IMSG_CTL_RESOLVER_INFO:
                cri = imsg->data;
-               printf("%8s %16s %s\n", cri->selected ? "*" : " ",
+               printf("%8s %16s %s%s\n", cri->selected ? "*" : " ",
                    uw_resolver_type_str[cri->type],
-                   uw_resolver_state_str[cri->state]);
+                   uw_resolver_state_str[cri->state],
+                   cri->oppdot ? " (OppDoT)" : "");
                break;
        case IMSG_CTL_RESOLVER_WHY_BOGUS:
                /* make sure this is a string */

Reply via email to