Bug Summary

File:src/sbin/unwind/resolver.c
Warning:line 1600, column 18
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name resolver.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/unwind/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/unwind -I /usr/src/sbin/unwind -I /usr/src/sbin/unwind/libunbound/libunbound -I /usr/src/sbin/unwind/libunbound -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/unwind/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/unwind/resolver.c
1/* $OpenBSD: resolver.c,v 1.154 2021/12/18 10:34:19 florian Exp $ */
2
3
4/*
5 * Copyright (c) 2018 Florian Obser <florian@openbsd.org>
6 * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
7 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
8 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
9 *
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <sys/types.h>
24#include <sys/queue.h>
25#include <sys/socket.h>
26#include <sys/syslog.h>
27#include <sys/time.h>
28
29#include <net/route.h>
30
31#include <errno(*__errno()).h>
32#include <event.h>
33#include <imsg.h>
34#include <limits.h>
35#include <netdb.h>
36#include <asr.h>
37#include <pwd.h>
38#include <signal.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <time.h>
43#include <tls.h>
44#include <unistd.h>
45
46#include "libunbound/config.h"
47#include "libunbound/libunbound/context.h"
48#include "libunbound/libunbound/libworker.h"
49#include "libunbound/libunbound/unbound.h"
50#include "libunbound/libunbound/unbound-event.h"
51#include "libunbound/services/cache/rrset.h"
52#include "libunbound/sldns/sbuffer.h"
53#include "libunbound/sldns/rrdef.h"
54#include "libunbound/sldns/pkthdr.h"
55#include "libunbound/sldns/wire2str.h"
56#include "libunbound/util/config_file.h"
57#include "libunbound/util/module.h"
58#include "libunbound/util/regional.h"
59#include "libunbound/util/storage/slabhash.h"
60#include "libunbound/validator/validator.h"
61#include "libunbound/validator/val_kcache.h"
62#include "libunbound/validator/val_neg.h"
63
64#include <openssl/crypto.h>
65
66#include "log.h"
67#include "frontend.h"
68#include "unwind.h"
69#include "resolver.h"
70
71#define TLS_DEFAULT_CA_CERT_FILE"/etc/ssl/cert.pem" "/etc/ssl/cert.pem"
72#define UB_LOG_VERBOSE4 4
73#define UB_LOG_BRIEF0 0
74
75/* maximum size of a libunbound forwarder definition: IP@PORT#AUTHNAME */
76#define FWD_MAX(46 + 256 + 2 + 5) (INET6_ADDRSTRLEN46 + NI_MAXHOST256 + 2 + 5)
77
78/*
79 * The prefered resolver type can be this many ms slower than the next
80 * best and still be picked
81 */
82#define PREF_RESOLVER_MEDIAN_SKEW200 200 /* 200 ms */
83#define NEXT_RES_MAX2000 2000 /* 2000 ms */
84
85#define DOUBT_NXDOMAIN_SEC(5 * 60) (5 * 60) /* 5 minutes */
86
87#define RESOLVER_CHECK_SEC1 1
88#define RESOLVER_CHECK_MAXSEC1024 1024 /* ~17 minutes */
89#define DECAY_PERIOD60 60
90#define DECAY_NOMINATOR9 9
91#define DECAY_DENOMINATOR10 10
92
93#define TRUST_ANCHOR_RETRY_INTERVAL8640 8640
94#define TRUST_ANCHOR_QUERY_INTERVAL43200 43200
95
96/* in libworker_event_done_cb() enum sec_status gets mapped to 0, 1 and 2 */
97#define INSECURE0 0
98#define BOGUS1 1
99#define SECURE2 2
100
101#define WKA1_FOUND1 1
102#define WKA2_FOUND2 2
103
104struct uw_resolver {
105 struct event check_ev;
106 struct event free_ev;
107 struct ub_ctx *ctx;
108 void *asr_ctx;
109 struct timeval check_tv;
110 int ref_cnt;
111 int stop;
112 enum uw_resolver_state state;
113 enum uw_resolver_type type;
114 int check_running;
115 int64_t median;
116 int64_t histogram[nitems(histogram_limits)(sizeof((histogram_limits)) / sizeof((histogram_limits)[0]))];
117 int64_t latest_histogram[nitems(histogram_limits)(sizeof((histogram_limits)) / sizeof((histogram_limits)[0]))];
118};
119
120struct running_query {
121 TAILQ_ENTRY(running_query)struct { struct running_query *tqe_next; struct running_query
**tqe_prev; }
entry;
122 struct query_imsg *query_imsg;
123 struct event timer_ev;
124 struct timespec tp;
125 struct resolver_preference res_pref;
126 int next_resolver;
127 int running;
128};
129
130TAILQ_HEAD(, running_query)struct { struct running_query *tqh_first; struct running_query
**tqh_last; }
running_queries;
131
132typedef void (*resolve_cb_t)(struct uw_resolver *, void *, int, void *, int,
133 int, char *);
134
135struct resolver_cb_data {
136 resolve_cb_t cb;
137 void *data;
138 struct uw_resolver *res;
139};
140
141__dead__attribute__((__noreturn__)) void resolver_shutdown(void);
142void resolver_sig_handler(int sig, short, void *);
143void resolver_dispatch_frontend(int, short, void *);
144void resolver_dispatch_main(int, short, void *);
145int sort_resolver_types(struct resolver_preference *);
146void setup_query(struct query_imsg *);
147struct running_query *find_running_query(uint64_t);
148void try_resolver_timo(int, short, void *);
149int try_next_resolver(struct running_query *);
150
151int resolve(struct uw_resolver *, const char*, int, int,
152 void*, resolve_cb_t);
153void resolve_done(struct uw_resolver *, void *, int, void *,
154 int, int, char *);
155void ub_resolve_done(void *, int, void *, int, int, char *,
156 int);
157void asr_resolve_done(struct asr_result *, void *);
158void new_resolver(enum uw_resolver_type,
159 enum uw_resolver_state);
160struct uw_resolver *create_resolver(enum uw_resolver_type);
161void setup_unified_caches(void);
162void set_unified_cache(struct uw_resolver *);
163void free_resolver(struct uw_resolver *);
164void set_forwarders(struct uw_resolver *,
165 struct uw_forwarder_head *, int);
166void resolver_check_timo(int, short, void *);
167void resolver_free_timo(int, short, void *);
168void check_resolver(struct uw_resolver *);
169void check_resolver_done(struct uw_resolver *, void *, int,
170 void *, int, int, char *);
171void schedule_recheck_all_resolvers(void);
172int check_forwarders_changed(struct uw_forwarder_head *,
173 struct uw_forwarder_head *);
174void replace_forwarders(struct uw_forwarder_head *,
175 struct uw_forwarder_head *);
176void resolver_ref(struct uw_resolver *);
177void resolver_unref(struct uw_resolver *);
178int resolver_cmp(const void *, const void *);
179void restart_ub_resolvers(int);
180void show_status(pid_t);
181void show_autoconf(pid_t);
182void show_mem(pid_t);
183void send_resolver_info(struct uw_resolver *, pid_t);
184void send_detailed_resolver_info(struct uw_resolver *,
185 pid_t);
186void trust_anchor_resolve(void);
187void trust_anchor_timo(int, short, void *);
188void trust_anchor_resolve_done(struct uw_resolver *, void *,
189 int, void *, int, int, char *);
190void replace_autoconf_forwarders(struct
191 imsg_rdns_proposal *);
192int force_tree_cmp(struct force_tree_entry *,
193 struct force_tree_entry *);
194int find_force(struct force_tree *, char *,
195 struct uw_resolver **);
196int64_t histogram_median(int64_t *);
197void decay_latest_histograms(int, short, void *);
198int running_query_cnt(void);
199int *resolvers_to_restart(struct uw_conf *,
200 struct uw_conf *);
201const char *query_imsg2str(struct query_imsg *);
202char *gen_resolv_conf(void);
203void check_dns64(void);
204void check_dns64_done(struct asr_result *, void *);
205int dns64_prefixlen(const struct in6_addr *,
206 const uint8_t *);
207void add_dns64_prefix(const struct in6_addr *, int,
208 struct dns64_prefix *, int, int);
209
210struct uw_conf *resolver_conf;
211static struct imsgev *iev_frontend;
212static struct imsgev *iev_main;
213struct uw_forwarder_head autoconf_forwarder_list;
214struct uw_resolver *resolvers[UW_RES_NONE];
215struct timespec last_network_change;
216
217struct event trust_anchor_timer;
218struct event decay_timer;
219
220static struct trust_anchor_head trust_anchors, new_trust_anchors;
221
222struct event_base *ev_base;
223
224RB_GENERATE(force_tree, force_tree_entry, entry, force_tree_cmp)void force_tree_RB_INSERT_COLOR(struct force_tree *head, struct
force_tree_entry *elm) { struct force_tree_entry *parent, *gparent
, *tmp; while ((parent = (elm)->entry.rbe_parent) &&
(parent)->entry.rbe_color == 1) { gparent = (parent)->
entry.rbe_parent; if (parent == (gparent)->entry.rbe_left)
{ tmp = (gparent)->entry.rbe_right; if (tmp && (tmp
)->entry.rbe_color == 1) { (tmp)->entry.rbe_color = 0; do
{ (parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); elm = gparent; continue; } if ((parent)->
entry.rbe_right == elm) { do { (tmp) = (parent)->entry.rbe_right
; if (((parent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = parent; parent = elm; elm
= tmp; } do { (parent)->entry.rbe_color = 0; (gparent)->
entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
entry.rbe_left; if (((gparent)->entry.rbe_left = (tmp)->
entry.rbe_right)) { ((tmp)->entry.rbe_right)->entry.rbe_parent
= (gparent); } do {} while (0); if (((tmp)->entry.rbe_parent
= (gparent)->entry.rbe_parent)) { if ((gparent) == ((gparent
)->entry.rbe_parent)->entry.rbe_left) ((gparent)->entry
.rbe_parent)->entry.rbe_left = (tmp); else ((gparent)->
entry.rbe_parent)->entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry.rbe_right = (gparent); (gparent
)->entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->
entry.rbe_parent)) do {} while (0); } while (0); } else { tmp
= (gparent)->entry.rbe_left; if (tmp && (tmp)->
entry.rbe_color == 1) { (tmp)->entry.rbe_color = 0; do { (
parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); elm = gparent; continue; } if ((parent)->
entry.rbe_left == elm) { do { (tmp) = (parent)->entry.rbe_left
; if (((parent)->entry.rbe_left = (tmp)->entry.rbe_right
)) { ((tmp)->entry.rbe_right)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = parent; parent = elm; elm
= tmp; } do { (parent)->entry.rbe_color = 0; (gparent)->
entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
entry.rbe_right; if (((gparent)->entry.rbe_right = (tmp)->
entry.rbe_left)) { ((tmp)->entry.rbe_left)->entry.rbe_parent
= (gparent); } do {} while (0); if (((tmp)->entry.rbe_parent
= (gparent)->entry.rbe_parent)) { if ((gparent) == ((gparent
)->entry.rbe_parent)->entry.rbe_left) ((gparent)->entry
.rbe_parent)->entry.rbe_left = (tmp); else ((gparent)->
entry.rbe_parent)->entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry.rbe_left = (gparent); (gparent
)->entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->
entry.rbe_parent)) do {} while (0); } while (0); } } (head->
rbh_root)->entry.rbe_color = 0; } void force_tree_RB_REMOVE_COLOR
(struct force_tree *head, struct force_tree_entry *parent, struct
force_tree_entry *elm) { struct force_tree_entry *tmp; while
((elm == ((void*)0) || (elm)->entry.rbe_color == 0) &&
elm != (head)->rbh_root) { if ((parent)->entry.rbe_left
== elm) { tmp = (parent)->entry.rbe_right; if ((tmp)->
entry.rbe_color == 1) { do { (tmp)->entry.rbe_color = 0; (
parent)->entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry.rbe_right; if (((parent)->entry.rbe_right = (tmp
)->entry.rbe_left)) { ((tmp)->entry.rbe_left)->entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry
.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent) ==
((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_left = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_right; } if (((tmp)->entry.rbe_left
== ((void*)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void*)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_right == ((void
*)0) || ((tmp)->entry.rbe_right)->entry.rbe_color == 0)
{ struct force_tree_entry *oleft; if ((oleft = (tmp)->entry
.rbe_left)) (oleft)->entry.rbe_color = 0; (tmp)->entry.
rbe_color = 1; do { (oleft) = (tmp)->entry.rbe_left; if ((
(tmp)->entry.rbe_left = (oleft)->entry.rbe_right)) { ((
oleft)->entry.rbe_right)->entry.rbe_parent = (tmp); } do
{} while (0); if (((oleft)->entry.rbe_parent = (tmp)->
entry.rbe_parent)) { if ((tmp) == ((tmp)->entry.rbe_parent
)->entry.rbe_left) ((tmp)->entry.rbe_parent)->entry.
rbe_left = (oleft); else ((tmp)->entry.rbe_parent)->entry
.rbe_right = (oleft); } else (head)->rbh_root = (oleft); (
oleft)->entry.rbe_right = (tmp); (tmp)->entry.rbe_parent
= (oleft); do {} while (0); if (((oleft)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->entry.rbe_right
; } (tmp)->entry.rbe_color = (parent)->entry.rbe_color;
(parent)->entry.rbe_color = 0; if ((tmp)->entry.rbe_right
) ((tmp)->entry.rbe_right)->entry.rbe_color = 0; do { (
tmp) = (parent)->entry.rbe_right; if (((parent)->entry.
rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->entry.rbe_left
)->entry.rbe_parent = (parent); } do {} while (0); if (((tmp
)->entry.rbe_parent = (parent)->entry.rbe_parent)) { if
((parent) == ((parent)->entry.rbe_parent)->entry.rbe_left
) ((parent)->entry.rbe_parent)->entry.rbe_left = (tmp);
else ((parent)->entry.rbe_parent)->entry.rbe_right = (
tmp); } else (head)->rbh_root = (tmp); (tmp)->entry.rbe_left
= (parent); (parent)->entry.rbe_parent = (tmp); do {} while
(0); if (((tmp)->entry.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } else { tmp = (parent
)->entry.rbe_left; if ((tmp)->entry.rbe_color == 1) { do
{ (tmp)->entry.rbe_color = 0; (parent)->entry.rbe_color
= 1; } while (0); do { (tmp) = (parent)->entry.rbe_left; if
(((parent)->entry.rbe_left = (tmp)->entry.rbe_right)) {
((tmp)->entry.rbe_right)->entry.rbe_parent = (parent);
} do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->entry.rbe_left
; } if (((tmp)->entry.rbe_left == ((void*)0) || ((tmp)->
entry.rbe_left)->entry.rbe_color == 0) && ((tmp)->
entry.rbe_right == ((void*)0) || ((tmp)->entry.rbe_right)->
entry.rbe_color == 0)) { (tmp)->entry.rbe_color = 1; elm =
parent; parent = (elm)->entry.rbe_parent; } else { if ((tmp
)->entry.rbe_left == ((void*)0) || ((tmp)->entry.rbe_left
)->entry.rbe_color == 0) { struct force_tree_entry *oright
; if ((oright = (tmp)->entry.rbe_right)) (oright)->entry
.rbe_color = 0; (tmp)->entry.rbe_color = 1; do { (oright) =
(tmp)->entry.rbe_right; if (((tmp)->entry.rbe_right = (
oright)->entry.rbe_left)) { ((oright)->entry.rbe_left)->
entry.rbe_parent = (tmp); } do {} while (0); if (((oright)->
entry.rbe_parent = (tmp)->entry.rbe_parent)) { if ((tmp) ==
((tmp)->entry.rbe_parent)->entry.rbe_left) ((tmp)->
entry.rbe_parent)->entry.rbe_left = (oright); else ((tmp)->
entry.rbe_parent)->entry.rbe_right = (oright); } else (head
)->rbh_root = (oright); (oright)->entry.rbe_left = (tmp
); (tmp)->entry.rbe_parent = (oright); do {} while (0); if
(((oright)->entry.rbe_parent)) do {} while (0); } while (
0); tmp = (parent)->entry.rbe_left; } (tmp)->entry.rbe_color
= (parent)->entry.rbe_color; (parent)->entry.rbe_color
= 0; if ((tmp)->entry.rbe_left) ((tmp)->entry.rbe_left
)->entry.rbe_color = 0; do { (tmp) = (parent)->entry.rbe_left
; if (((parent)->entry.rbe_left = (tmp)->entry.rbe_right
)) { ((tmp)->entry.rbe_right)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); elm = (head)->rbh_root; break
; } } } if (elm) (elm)->entry.rbe_color = 0; } struct force_tree_entry
* force_tree_RB_REMOVE(struct force_tree *head, struct force_tree_entry
*elm) { struct force_tree_entry *child, *parent, *old = elm;
int color; if ((elm)->entry.rbe_left == ((void*)0)) child
= (elm)->entry.rbe_right; else if ((elm)->entry.rbe_right
== ((void*)0)) child = (elm)->entry.rbe_left; else { struct
force_tree_entry *left; elm = (elm)->entry.rbe_right; while
((left = (elm)->entry.rbe_left)) elm = left; child = (elm
)->entry.rbe_right; parent = (elm)->entry.rbe_parent; color
= (elm)->entry.rbe_color; if (child) (child)->entry.rbe_parent
= parent; if (parent) { if ((parent)->entry.rbe_left == elm
) (parent)->entry.rbe_left = child; else (parent)->entry
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->entry.rbe_parent == old) parent = elm
; (elm)->entry = (old)->entry; if ((old)->entry.rbe_parent
) { if (((old)->entry.rbe_parent)->entry.rbe_left == old
) ((old)->entry.rbe_parent)->entry.rbe_left = elm; else
((old)->entry.rbe_parent)->entry.rbe_right = elm; do {
} while (0); } else (head)->rbh_root = elm; ((old)->entry
.rbe_left)->entry.rbe_parent = elm; if ((old)->entry.rbe_right
) ((old)->entry.rbe_right)->entry.rbe_parent = elm; if (
parent) { left = parent; do { do {} while (0); } while ((left
= (left)->entry.rbe_parent)); } goto color; } parent = (elm
)->entry.rbe_parent; color = (elm)->entry.rbe_color; if
(child) (child)->entry.rbe_parent = parent; if (parent) {
if ((parent)->entry.rbe_left == elm) (parent)->entry.rbe_left
= child; else (parent)->entry.rbe_right = child; do {} while
(0); } else (head)->rbh_root = child; color: if (color ==
0) force_tree_RB_REMOVE_COLOR(head, parent, child); return (
old); } struct force_tree_entry * force_tree_RB_INSERT(struct
force_tree *head, struct force_tree_entry *elm) { struct force_tree_entry
*tmp; struct force_tree_entry *parent = ((void*)0); int comp
= 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp; comp
= (force_tree_cmp)(elm, parent); if (comp < 0) tmp = (tmp
)->entry.rbe_left; else if (comp > 0) tmp = (tmp)->entry
.rbe_right; else return (tmp); } do { (elm)->entry.rbe_parent
= parent; (elm)->entry.rbe_left = (elm)->entry.rbe_right
= ((void*)0); (elm)->entry.rbe_color = 1; } while (0); if
(parent != ((void*)0)) { if (comp < 0) (parent)->entry
.rbe_left = elm; else (parent)->entry.rbe_right = elm; do {
} while (0); } else (head)->rbh_root = elm; force_tree_RB_INSERT_COLOR
(head, elm); return (((void*)0)); } struct force_tree_entry *
force_tree_RB_FIND(struct force_tree *head, struct force_tree_entry
*elm) { struct force_tree_entry *tmp = (head)->rbh_root; int
comp; while (tmp) { comp = force_tree_cmp(elm, tmp); if (comp
< 0) tmp = (tmp)->entry.rbe_left; else if (comp > 0
) tmp = (tmp)->entry.rbe_right; else return (tmp); } return
(((void*)0)); } struct force_tree_entry * force_tree_RB_NFIND
(struct force_tree *head, struct force_tree_entry *elm) { struct
force_tree_entry *tmp = (head)->rbh_root; struct force_tree_entry
*res = ((void*)0); int comp; while (tmp) { comp = force_tree_cmp
(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->entry
.rbe_left; } else if (comp > 0) tmp = (tmp)->entry.rbe_right
; else return (tmp); } return (res); } struct force_tree_entry
* force_tree_RB_NEXT(struct force_tree_entry *elm) { if ((elm
)->entry.rbe_right) { elm = (elm)->entry.rbe_right; while
((elm)->entry.rbe_left) elm = (elm)->entry.rbe_left; }
else { if ((elm)->entry.rbe_parent && (elm == ((elm
)->entry.rbe_parent)->entry.rbe_left)) elm = (elm)->
entry.rbe_parent; else { while ((elm)->entry.rbe_parent &&
(elm == ((elm)->entry.rbe_parent)->entry.rbe_right)) elm
= (elm)->entry.rbe_parent; elm = (elm)->entry.rbe_parent
; } } return (elm); } struct force_tree_entry * force_tree_RB_PREV
(struct force_tree_entry *elm) { if ((elm)->entry.rbe_left
) { elm = (elm)->entry.rbe_left; while ((elm)->entry.rbe_right
) elm = (elm)->entry.rbe_right; } else { if ((elm)->entry
.rbe_parent && (elm == ((elm)->entry.rbe_parent)->
entry.rbe_right)) elm = (elm)->entry.rbe_parent; else { while
((elm)->entry.rbe_parent && (elm == ((elm)->entry
.rbe_parent)->entry.rbe_left)) elm = (elm)->entry.rbe_parent
; elm = (elm)->entry.rbe_parent; } } return (elm); } struct
force_tree_entry * force_tree_RB_MINMAX(struct force_tree *head
, int val) { struct force_tree_entry *tmp = (head)->rbh_root
; struct force_tree_entry *parent = ((void*)0); while (tmp) {
parent = tmp; if (val < 0) tmp = (tmp)->entry.rbe_left
; else tmp = (tmp)->entry.rbe_right; } return (parent); }
225
226int val_id = -1;
227struct slabhash *unified_msg_cache;
228struct rrset_cache *unified_rrset_cache;
229struct key_cache *unified_key_cache;
230struct val_neg_cache *unified_neg_cache;
231
232int dns64_present;
233int available_afs = HAVE_IPV41 | HAVE_IPV62;
234
235static const char * const as112_zones[] = {
236 /* RFC1918 */
237 "10.in-addr.arpa. transparent",
238 "16.172.in-addr.arpa. transparent",
239 "31.172.in-addr.arpa. transparent",
240 "168.192.in-addr.arpa. transparent",
241
242 /* RFC3330 */
243 "0.in-addr.arpa. transparent",
244 "254.169.in-addr.arpa. transparent",
245 "2.0.192.in-addr.arpa. transparent",
246 "100.51.198.in-addr.arpa. transparent",
247 "113.0.203.in-addr.arpa. transparent",
248 "255.255.255.255.in-addr.arpa. transparent",
249
250 /* RFC6598 */
251 "64.100.in-addr.arpa. transparent",
252 "65.100.in-addr.arpa. transparent",
253 "66.100.in-addr.arpa. transparent",
254 "67.100.in-addr.arpa. transparent",
255 "68.100.in-addr.arpa. transparent",
256 "69.100.in-addr.arpa. transparent",
257 "70.100.in-addr.arpa. transparent",
258 "71.100.in-addr.arpa. transparent",
259 "72.100.in-addr.arpa. transparent",
260 "73.100.in-addr.arpa. transparent",
261 "74.100.in-addr.arpa. transparent",
262 "75.100.in-addr.arpa. transparent",
263 "76.100.in-addr.arpa. transparent",
264 "77.100.in-addr.arpa. transparent",
265 "78.100.in-addr.arpa. transparent",
266 "79.100.in-addr.arpa. transparent",
267 "80.100.in-addr.arpa. transparent",
268 "81.100.in-addr.arpa. transparent",
269 "82.100.in-addr.arpa. transparent",
270 "83.100.in-addr.arpa. transparent",
271 "84.100.in-addr.arpa. transparent",
272 "85.100.in-addr.arpa. transparent",
273 "86.100.in-addr.arpa. transparent",
274 "87.100.in-addr.arpa. transparent",
275 "88.100.in-addr.arpa. transparent",
276 "89.100.in-addr.arpa. transparent",
277 "90.100.in-addr.arpa. transparent",
278 "91.100.in-addr.arpa. transparent",
279 "92.100.in-addr.arpa. transparent",
280 "93.100.in-addr.arpa. transparent",
281 "94.100.in-addr.arpa. transparent",
282 "95.100.in-addr.arpa. transparent",
283 "96.100.in-addr.arpa. transparent",
284 "97.100.in-addr.arpa. transparent",
285 "98.100.in-addr.arpa. transparent",
286 "99.100.in-addr.arpa. transparent",
287 "100.100.in-addr.arpa. transparent",
288 "101.100.in-addr.arpa. transparent",
289 "102.100.in-addr.arpa. transparent",
290 "103.100.in-addr.arpa. transparent",
291 "104.100.in-addr.arpa. transparent",
292 "105.100.in-addr.arpa. transparent",
293 "106.100.in-addr.arpa. transparent",
294 "107.100.in-addr.arpa. transparent",
295 "108.100.in-addr.arpa. transparent",
296 "109.100.in-addr.arpa. transparent",
297 "110.100.in-addr.arpa. transparent",
298 "111.100.in-addr.arpa. transparent",
299 "112.100.in-addr.arpa. transparent",
300 "113.100.in-addr.arpa. transparent",
301 "114.100.in-addr.arpa. transparent",
302 "115.100.in-addr.arpa. transparent",
303 "116.100.in-addr.arpa. transparent",
304 "117.100.in-addr.arpa. transparent",
305 "118.100.in-addr.arpa. transparent",
306 "119.100.in-addr.arpa. transparent",
307 "120.100.in-addr.arpa. transparent",
308 "121.100.in-addr.arpa. transparent",
309 "122.100.in-addr.arpa. transparent",
310 "123.100.in-addr.arpa. transparent",
311 "124.100.in-addr.arpa. transparent",
312 "125.100.in-addr.arpa. transparent",
313 "126.100.in-addr.arpa. transparent",
314 "127.100.in-addr.arpa. transparent",
315
316 /* RFC4291 */
317 "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0."
318 "ip6.arpa. transparent",
319
320 /* RFC4193 */
321 "D.F.ip6.arpa. transparent",
322
323 /* RFC4291 */
324 "8.E.F.ip6.arpa. transparent",
325 "9.E.F.ip6.arpa. transparent",
326 "A.E.F.ip6.arpa. transparent",
327 "B.E.F.ip6.arpa. transparent",
328
329 /* RFC3849 */
330 "8.B.D.0.1.0.0.2.ip6.arpa. transparent"
331};
332
333const char bogus_past[] = "validation failure <. NS IN>: signature "
334 "expired";
335const char bogus_future[] = "validation failure <. NS IN>: signature "
336 "before inception date";
337
338void
339resolver_sig_handler(int sig, short event, void *arg)
340{
341 /*
342 * Normal signal handler rules don't apply because libevent
343 * decouples for us.
344 */
345
346 switch (sig) {
347 case SIGINT2:
348 case SIGTERM15:
349 resolver_shutdown();
350 default:
351 fatalx("unexpected signal");
352 }
353}
354
355void
356resolver(int debug, int verbose)
357{
358 struct event ev_sigint, ev_sigterm;
359 struct passwd *pw;
360 struct timeval tv = {DECAY_PERIOD60, 0};
361 struct alloc_cache cache_alloc_test;
362
363 resolver_conf = config_new_empty();
364
365 log_init(debug, LOG_DAEMON)uw_log_init(debug, (3<<3));
366 log_setverbose(verbose);
367
368 if ((pw = getpwnam(UNWIND_USER"_unwind")) == NULL((void*)0))
369 fatal("getpwnam");
370
371 setproctitle("%s", "resolver");
372 log_procinit("resolver");
373
374 if (setgroups(1, &pw->pw_gid) ||
375 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
376 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
377 fatal("can't drop privileges");
378
379 if (unveil(TLS_DEFAULT_CA_CERT_FILE"/etc/ssl/cert.pem", "r") == -1)
380 fatal("unveil %s", TLS_DEFAULT_CA_CERT_FILE"/etc/ssl/cert.pem");
381
382 if (pledge("stdio inet dns rpath recvfd", NULL((void*)0)) == -1)
383 fatal("pledge");
384
385 ev_base = event_init();
386
387 /* Setup signal handler(s). */
388 signal_set(&ev_sigint, SIGINT, resolver_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, resolver_sig_handler,
((void*)0))
;
389 signal_set(&ev_sigterm, SIGTERM, resolver_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, resolver_sig_handler
, ((void*)0))
;
390 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void*)0));
391 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void*)0));
392 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
393 signal(SIGHUP1, SIG_IGN(void (*)(int))1);
394
395 /* Setup pipe and event handler to the main process. */
396 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL((void*)0))
397 fatal(NULL((void*)0));
398
399 imsg_init(&iev_main->ibuf, 3);
400 iev_main->handler = resolver_dispatch_main;
401
402 /* Setup event handlers. */
403 iev_main->events = EV_READ0x02;
404 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
405 iev_main->handler, iev_main);
406 event_add(&iev_main->ev, NULL((void*)0));
407
408 evtimer_set(&trust_anchor_timer, trust_anchor_timo, NULL)event_set(&trust_anchor_timer, -1, 0, trust_anchor_timo, (
(void*)0))
;
409 evtimer_set(&decay_timer, decay_latest_histograms, NULL)event_set(&decay_timer, -1, 0, decay_latest_histograms, (
(void*)0))
;
410 evtimer_add(&decay_timer, &tv)event_add(&decay_timer, &tv);
411
412 clock_gettime(CLOCK_MONOTONIC3, &last_network_change);
413
414 alloc_init(&cache_alloc_test, NULL((void*)0), 0);
415 if (cache_alloc_test.max_reg_blocks != 10)
416 fatalx("local libunbound/util/alloc.c diff lost");
417 alloc_clear(&cache_alloc_test);
418
419 setup_unified_caches();
420
421 TAILQ_INIT(&autoconf_forwarder_list)do { (&autoconf_forwarder_list)->tqh_first = ((void*)0
); (&autoconf_forwarder_list)->tqh_last = &(&autoconf_forwarder_list
)->tqh_first; } while (0)
;
422 TAILQ_INIT(&trust_anchors)do { (&trust_anchors)->tqh_first = ((void*)0); (&trust_anchors
)->tqh_last = &(&trust_anchors)->tqh_first; } while
(0)
;
423 TAILQ_INIT(&new_trust_anchors)do { (&new_trust_anchors)->tqh_first = ((void*)0); (&
new_trust_anchors)->tqh_last = &(&new_trust_anchors
)->tqh_first; } while (0)
;
424 TAILQ_INIT(&running_queries)do { (&running_queries)->tqh_first = ((void*)0); (&
running_queries)->tqh_last = &(&running_queries)->
tqh_first; } while (0)
;
425
426 event_dispatch();
427
428 resolver_shutdown();
429}
430
431__dead__attribute__((__noreturn__)) void
432resolver_shutdown(void)
433{
434 /* Close pipes. */
435 msgbuf_clear(&iev_frontend->ibuf.w);
436 close(iev_frontend->ibuf.fd);
437 msgbuf_clear(&iev_main->ibuf.w);
438 close(iev_main->ibuf.fd);
439
440 config_clear(resolver_conf);
441
442 free(iev_frontend);
443 free(iev_main);
444
445 log_info("resolver exiting")uw_log_info("resolver exiting");
446 exit(0);
447}
448
449int
450resolver_imsg_compose_main(int type, pid_t pid, void *data, uint16_t datalen)
451{
452 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
453}
454
455int
456resolver_imsg_compose_frontend(int type, pid_t pid, void *data,
457 uint16_t datalen)
458{
459 return (imsg_compose_event(iev_frontend, type, 0, pid, -1,
460 data, datalen));
461}
462
463void
464resolver_dispatch_frontend(int fd, short event, void *bula)
465{
466 struct imsgev *iev = bula;
467 struct imsgbuf *ibuf;
468 struct imsg imsg;
469 struct query_imsg *query_imsg;
470 ssize_t n;
471 int shut = 0, verbose, i, new_available_afs;
472 char *ta;
473
474 ibuf = &iev->ibuf;
475
476 if (event & EV_READ0x02) {
477 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
478 fatal("imsg_read error");
479 if (n == 0) /* Connection closed. */
480 shut = 1;
481 }
482 if (event & EV_WRITE0x04) {
483 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
484 fatal("msgbuf_write");
485 if (n == 0) /* Connection closed. */
486 shut = 1;
487 }
488
489 for (;;) {
490 if ((n = imsg_get(ibuf, &imsg)) == -1)
491 fatal("%s: imsg_get error", __func__);
492 if (n == 0) /* No more messages. */
493 break;
494
495 switch (imsg.hdr.type) {
496 case IMSG_CTL_LOG_VERBOSE:
497 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) != sizeof(verbose))
498 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: "
499 "%lu", __func__,
500 IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
501 memcpy(&verbose, imsg.data, sizeof(verbose));
502 if (log_getdebug() && (log_getverbose() & OPT_VERBOSE30x00000004)
503 != (verbose & OPT_VERBOSE30x00000004))
504 restart_ub_resolvers(0);
505 log_setverbose(verbose);
506 break;
507 case IMSG_QUERY:
508 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) != sizeof(*query_imsg))
509 fatalx("%s: IMSG_QUERY wrong length: %lu",
510 __func__, IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
511 if ((query_imsg = malloc(sizeof(*query_imsg))) ==
512 NULL((void*)0)) {
513 log_warn("cannot allocate query")uw_log_warn("cannot allocate query");
514 break;
515 }
516 memcpy(query_imsg, imsg.data, sizeof(*query_imsg));
517 setup_query(query_imsg);
518 break;
519 case IMSG_CTL_STATUS:
520 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) != 0)
521 fatalx("%s: IMSG_CTL_STATUS wrong length: %lu",
522 __func__, IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
523 show_status(imsg.hdr.pid);
524 break;
525 case IMSG_CTL_AUTOCONF:
526 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) != 0)
527 fatalx("%s: IMSG_CTL_AUTOCONF wrong length: "
528 "%lu", __func__, IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
529 show_autoconf(imsg.hdr.pid);
530 break;
531 case IMSG_CTL_MEM:
532 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) != 0)
533 fatalx("%s: IMSG_CTL_AUTOCONF wrong length: "
534 "%lu", __func__, IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
535 show_mem(imsg.hdr.pid);
536 break;
537 case IMSG_NEW_TA:
538 if (((char *)imsg.data)[IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) - 1] !=
539 '\0')
540 fatalx("Invalid trust anchor");
541 ta = imsg.data;
542 add_new_ta(&new_trust_anchors, ta);
543 break;
544 case IMSG_NEW_TAS_ABORT:
545 free_tas(&new_trust_anchors);
546 break;
547 case IMSG_NEW_TAS_DONE:
548 if (merge_tas(&new_trust_anchors, &trust_anchors))
549 restart_ub_resolvers(1);
550 break;
551 case IMSG_NETWORK_CHANGED:
552 clock_gettime(CLOCK_MONOTONIC3, &last_network_change);
553 schedule_recheck_all_resolvers();
554 for (i = 0; i < UW_RES_NONE; i++) {
555 if (resolvers[i] == NULL((void*)0))
556 continue;
557 memset(resolvers[i]->latest_histogram, 0,
558 sizeof(resolvers[i]->latest_histogram));
559 resolvers[i]->median = histogram_median(
560 resolvers[i]->latest_histogram);
561 }
562
563 break;
564 case IMSG_REPLACE_DNS:
565 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) !=
566 sizeof(struct imsg_rdns_proposal))
567 fatalx("%s: IMSG_ADD_DNS wrong length: %lu",
568 __func__, IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
569 replace_autoconf_forwarders((struct
570 imsg_rdns_proposal *)imsg.data);
571 break;
572 case IMSG_CHANGE_AFS:
573 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) !=
574 sizeof(new_available_afs))
575 fatalx("%s: IMSG_CHANGE_AFS wrong length: %lu",
576 __func__, IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
577 memcpy(&new_available_afs, imsg.data,
578 sizeof(new_available_afs));
579 if (new_available_afs != available_afs) {
580 available_afs = new_available_afs;
581 restart_ub_resolvers(1);
582 }
583 break;
584 default:
585 log_debug("%s: unexpected imsg %d", __func__,
586 imsg.hdr.type);
587 break;
588 }
589 imsg_free(&imsg);
590 }
591 if (!shut)
592 imsg_event_add(iev);
593 else {
594 /* This pipe is dead. Remove its event handler. */
595 event_del(&iev->ev);
596 event_loopexit(NULL((void*)0));
597 }
598}
599
600void
601resolver_dispatch_main(int fd, short event, void *bula)
602{
603 static struct uw_conf *nconf;
604 struct imsg imsg;
605 struct imsgev *iev = bula;
606 struct imsgbuf *ibuf;
607 ssize_t n;
608 int shut = 0, i, *restart;
609
610 ibuf = &iev->ibuf;
611
612 if (event & EV_READ0x02) {
613 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
614 fatal("imsg_read error");
615 if (n == 0) /* Connection closed. */
616 shut = 1;
617 }
618 if (event & EV_WRITE0x04) {
619 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
620 fatal("msgbuf_write");
621 if (n == 0) /* Connection closed. */
622 shut = 1;
623 }
624
625 for (;;) {
626 if ((n = imsg_get(ibuf, &imsg)) == -1)
627 fatal("%s: imsg_get error", __func__);
628 if (n == 0) /* No more messages. */
629 break;
630
631 switch (imsg.hdr.type) {
632 case IMSG_SOCKET_IPC_FRONTEND:
633 /*
634 * Setup pipe and event handler to the frontend
635 * process.
636 */
637 if (iev_frontend)
638 fatalx("%s: received unexpected imsg fd "
639 "to resolver", __func__);
640
641 if ((fd = imsg.fd) == -1)
642 fatalx("%s: expected to receive imsg fd to "
643 "resolver but didn't receive any", __func__);
644
645 iev_frontend = malloc(sizeof(struct imsgev));
646 if (iev_frontend == NULL((void*)0))
647 fatal(NULL((void*)0));
648
649 imsg_init(&iev_frontend->ibuf, fd);
650 iev_frontend->handler = resolver_dispatch_frontend;
651 iev_frontend->events = EV_READ0x02;
652
653 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd,
654 iev_frontend->events, iev_frontend->handler,
655 iev_frontend);
656 event_add(&iev_frontend->ev, NULL((void*)0));
657 break;
658
659 case IMSG_STARTUP:
660 if (pledge("stdio inet dns rpath", NULL((void*)0)) == -1)
661 fatal("pledge");
662 break;
663 case IMSG_RECONF_CONF:
664 case IMSG_RECONF_BLOCKLIST_FILE:
665 case IMSG_RECONF_FORWARDER:
666 case IMSG_RECONF_DOT_FORWARDER:
667 case IMSG_RECONF_FORCE:
668 imsg_receive_config(&imsg, &nconf);
669 break;
670 case IMSG_RECONF_END:
671 if (nconf == NULL((void*)0))
672 fatalx("%s: IMSG_RECONF_END without "
673 "IMSG_RECONF_CONF", __func__);
674 restart = resolvers_to_restart(resolver_conf, nconf);
675 merge_config(resolver_conf, nconf);
676 nconf = NULL((void*)0);
677 for (i = 0; i < UW_RES_NONE; i++)
678 if (restart[i])
679 new_resolver(i, UNKNOWN);
680 break;
681 default:
682 log_debug("%s: unexpected imsg %d", __func__,
683 imsg.hdr.type);
684 break;
685 }
686 imsg_free(&imsg);
687 }
688 if (!shut)
689 imsg_event_add(iev);
690 else {
691 /* This pipe is dead. Remove its event handler. */
692 event_del(&iev->ev);
693 event_loopexit(NULL((void*)0));
694 }
695}
696
697int
698sort_resolver_types(struct resolver_preference *dst)
699{
700 memcpy(dst, &resolver_conf->res_pref, sizeof(*dst));
701
702 /*
703 * Sort by resolver quality, validating > resolving etc.
704 * mergesort is stable and keeps the configured preference order
705 */
706 return mergesort(dst->types, dst->len, sizeof(dst->types[0]),
707 resolver_cmp);
708}
709
710void
711setup_query(struct query_imsg *query_imsg)
712{
713 struct running_query *rq;
714 struct uw_resolver *res;
715
716 if (find_running_query(query_imsg->id) != NULL((void*)0)) {
717 free(query_imsg);
718 return;
719 }
720
721 if ((rq = calloc(1, sizeof(*rq))) == NULL((void*)0)) {
722 log_warnx(NULL((void*)0));
723 free(query_imsg);
724 return;
725 }
726
727 clock_gettime(CLOCK_MONOTONIC3, &rq->tp);
728 rq->query_imsg = query_imsg;
729 rq->next_resolver = 0;
730
731 find_force(&resolver_conf->force, query_imsg->qname, &res);
732
733 if (res != NULL((void*)0) && res->state != DEAD && res->state != UNKNOWN) {
734 rq->res_pref.len = 1;
735 rq->res_pref.types[0] = res->type;
736 } else if (sort_resolver_types(&rq->res_pref) == -1) {
737 log_warn("mergesort")uw_log_warn("mergesort");
738 free(rq->query_imsg);
739 free(rq);
740 return;
741 }
742
743 evtimer_set(&rq->timer_ev, try_resolver_timo, rq)event_set(&rq->timer_ev, -1, 0, try_resolver_timo, rq);
744
745 TAILQ_INSERT_TAIL(&running_queries, rq, entry)do { (rq)->entry.tqe_next = ((void*)0); (rq)->entry.tqe_prev
= (&running_queries)->tqh_last; *(&running_queries
)->tqh_last = (rq); (&running_queries)->tqh_last = &
(rq)->entry.tqe_next; } while (0)
;
746 try_next_resolver(rq);
747}
748
749struct running_query *
750find_running_query(uint64_t id)
751{
752 struct running_query *rq;
753
754 TAILQ_FOREACH(rq, &running_queries, entry)for((rq) = ((&running_queries)->tqh_first); (rq) != ((
void*)0); (rq) = ((rq)->entry.tqe_next))
{
755 if (rq->query_imsg->id == id)
756 return rq;
757 }
758 return NULL((void*)0);
759}
760
761void
762try_resolver_timo(int fd, short events, void *arg)
763{
764 struct running_query *rq = arg;
765
766 try_next_resolver(rq);
767}
768
769int
770try_next_resolver(struct running_query *rq)
771{
772 struct uw_resolver *res = NULL((void*)0);
773 struct query_imsg *query_imsg = NULL((void*)0);
774 struct timespec tp, elapsed;
775 struct timeval tv = {0, 0};
776 int64_t ms;
777 int i;
778
779 while(rq->next_resolver < rq->res_pref.len &&
780 ((res = resolvers[rq->res_pref.types[rq->next_resolver]]) == NULL((void*)0) ||
781 res->state == DEAD || res->state == UNKNOWN))
782 rq->next_resolver++;
783
784 if (res == NULL((void*)0)) {
785 evtimer_del(&rq->timer_ev)event_del(&rq->timer_ev); /* we are not going to find one */
786 log_debug("%s: could not find (any more) working resolvers",
787 __func__);
788 goto err;
789 }
790
791 rq->next_resolver++;
792 clock_gettime(CLOCK_MONOTONIC3, &tp);
793 timespecsub(&tp, &rq->tp, &elapsed)do { (&elapsed)->tv_sec = (&tp)->tv_sec - (&
rq->tp)->tv_sec; (&elapsed)->tv_nsec = (&tp)
->tv_nsec - (&rq->tp)->tv_nsec; if ((&elapsed
)->tv_nsec < 0) { (&elapsed)->tv_sec--; (&elapsed
)->tv_nsec += 1000000000L; } } while (0)
;
794 ms = elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
795
796 log_debug("%s[+%lldms]: %s[%s] %s", __func__, ms,
797 uw_resolver_type_str[res->type], uw_resolver_state_str[res->state],
798 query_imsg2str(rq->query_imsg));
799
800 if ((query_imsg = malloc(sizeof(*query_imsg))) == NULL((void*)0)) {
801 log_warnx("%s", __func__);
802 goto err;
803 }
804 memcpy(query_imsg, rq->query_imsg, sizeof(*query_imsg));
805 clock_gettime(CLOCK_MONOTONIC3, &query_imsg->tp);
806
807 ms = res->median;
808 if (ms > NEXT_RES_MAX2000)
809 ms = NEXT_RES_MAX2000;
810
811 /* skip over unavailable resolvers in preferences */
812 for (i = 0; i < resolver_conf->res_pref.len &&
813 resolvers[resolver_conf->res_pref.types[i]] == NULL((void*)0); i++)
814 ;
815 if (res->type == resolver_conf->res_pref.types[i])
816 tv.tv_usec = 1000 * (PREF_RESOLVER_MEDIAN_SKEW200 + ms);
817 else
818 tv.tv_usec = 1000 * ms;
819
820 while (tv.tv_usec >= 1000000) {
821 tv.tv_sec++;
822 tv.tv_usec -= 1000000;
823 }
824 evtimer_add(&rq->timer_ev, &tv)event_add(&rq->timer_ev, &tv);
825
826 rq->running++;
827 if (resolve(res, query_imsg->qname, query_imsg->t,
828 query_imsg->c, query_imsg, resolve_done) != 0) {
829 rq->running--;
830 goto err;
831 }
832
833 return 0;
834
835 err:
836 free(query_imsg);
837 if (rq->running == 0) {
838 TAILQ_REMOVE(&running_queries, rq, entry)do { if (((rq)->entry.tqe_next) != ((void*)0)) (rq)->entry
.tqe_next->entry.tqe_prev = (rq)->entry.tqe_prev; else (
&running_queries)->tqh_last = (rq)->entry.tqe_prev;
*(rq)->entry.tqe_prev = (rq)->entry.tqe_next; ; ; } while
(0)
;
839 evtimer_del(&rq->timer_ev)event_del(&rq->timer_ev);
840 free(rq->query_imsg);
841 free(rq);
842 }
843 return 1;
844}
845
846int
847resolve(struct uw_resolver *res, const char* name, int rrtype, int rrclass,
848 void *mydata, resolve_cb_t cb)
849{
850 struct resolver_cb_data *cb_data = NULL((void*)0);
851 struct asr_query *aq = NULL((void*)0);
852 int err;
853
854 resolver_ref(res);
855
856 if ((cb_data = malloc(sizeof(*cb_data))) == NULL((void*)0))
857 goto err;
858 cb_data->cb = cb;
859 cb_data->data = mydata;
860 cb_data->res = res;
861
862 switch(res->type) {
863 case UW_RES_ASR:
864 if ((aq = res_query_async(name, rrclass, rrtype, res->asr_ctx))
865 == NULL((void*)0)) {
866 log_warn("%s: res_query_async", __func__)uw_log_warn("%s: res_query_async", __func__);
867 goto err;
868 }
869 if (event_asr_run(aq, asr_resolve_done, cb_data) == NULL((void*)0)) {
870 log_warn("%s: res_query_async", __func__)uw_log_warn("%s: res_query_async", __func__);
871 goto err;
872 }
873 break;
874 case UW_RES_RECURSOR:
875 case UW_RES_AUTOCONF:
876 case UW_RES_ODOT_AUTOCONF:
877 case UW_RES_FORWARDER:
878 case UW_RES_ODOT_FORWARDER:
879 case UW_RES_DOT:
880 if ((err = ub_resolve_event(res->ctx, name, rrtype, rrclass,
881 cb_data, ub_resolve_done, NULL((void*)0))) != 0) {
882 log_warn("%s: ub_resolve_event: err: %d, %s", __func__,uw_log_warn("%s: ub_resolve_event: err: %d, %s", __func__, err
, ub_strerror(err))
883 err, ub_strerror(err))uw_log_warn("%s: ub_resolve_event: err: %d, %s", __func__, err
, ub_strerror(err))
;
884 goto err;
885 }
886 break;
887 default:
888 fatalx("unknown resolver type %d", res->type);
889 break;
890 }
891
892 return 0;
893 err:
894 free(cb_data);
895 free(aq);
896 resolver_unref(res);
897 return 1;
898}
899
900void
901resolve_done(struct uw_resolver *res, void *arg, int rcode,
902 void *answer_packet, int answer_len, int sec, char *why_bogus)
903{
904 struct uw_resolver *tmp_res;
905 struct ub_result *result = NULL((void*)0);
906 sldns_buffer *buf = NULL((void*)0);
907 struct regional *region = NULL((void*)0);
908 struct query_imsg *query_imsg;
909 struct answer_header *answer_header;
910 struct running_query *rq;
911 struct timespec tp, elapsed;
912 int64_t ms;
913 size_t i;
914 int running_res, asr_pref_pos, force_acceptbogus;
915 char *str;
916 char rcode_buf[16];
917 uint8_t *p, *data;
918 uint8_t answer_imsg[MAX_IMSGSIZE16384 - IMSG_HEADER_SIZEsizeof(struct imsg_hdr)];
919
920 clock_gettime(CLOCK_MONOTONIC3, &tp);
921
922 query_imsg = (struct query_imsg *)arg;
923
924 answer_header = (struct answer_header *)answer_imsg;
925 data = answer_imsg + sizeof(*answer_header);
926 answer_header->id = query_imsg->id;
927 answer_header->srvfail = 0;
928 answer_header->answer_len = 0;
929
930 timespecsub(&tp, &query_imsg->tp, &elapsed)do { (&elapsed)->tv_sec = (&tp)->tv_sec - (&
query_imsg->tp)->tv_sec; (&elapsed)->tv_nsec = (
&tp)->tv_nsec - (&query_imsg->tp)->tv_nsec; if
((&elapsed)->tv_nsec < 0) { (&elapsed)->tv_sec
--; (&elapsed)->tv_nsec += 1000000000L; } } while (0)
;
931
932 ms = elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
933
934 for (i = 0; i < nitems(histogram_limits)(sizeof((histogram_limits)) / sizeof((histogram_limits)[0])); i++) {
935 if (ms < histogram_limits[i])
936 break;
937 }
938 if (i == nitems(histogram_limits)(sizeof((histogram_limits)) / sizeof((histogram_limits)[0])))
939 log_debug("histogram bucket error");
940 else {
941 res->histogram[i]++;
942 /* latest_histogram is in units of 1000 to avoid rounding
943 down when decaying */
944 res->latest_histogram[i] += 1000;
945 res->median = histogram_median(res->latest_histogram);
946 }
947
948 if ((rq = find_running_query(query_imsg->id)) == NULL((void*)0))
949 goto out;
950
951 running_res = --rq->running;
952
953 if (answer_len < LDNS_HEADER_SIZE12) {
954 log_warnx("bad packet: too short");
955 goto servfail;
956 }
957
958 if (answer_len > UINT16_MAX0xffff) {
959 log_warnx("bad packet: too large: %d - %s", answer_len,
960 query_imsg2str(query_imsg));
961 goto servfail;
962 }
963 answer_header->answer_len = answer_len;
964
965 if (rcode == LDNS_RCODE_SERVFAIL) {
966 if (res->stop != 1)
967 check_resolver(res);
968 goto servfail;
969 }
970
971 if ((result = calloc(1, sizeof(*result))) == NULL((void*)0))
972 goto servfail;
973 if ((buf = sldns_buffer_new(answer_len)) == NULL((void*)0))
974 goto servfail;
975 if ((region = regional_create()) == NULL((void*)0))
976 goto servfail;
977
978 result->rcode = LDNS_RCODE_SERVFAIL;
979
980 sldns_buffer_clear(buf);
981 sldns_buffer_write(buf, answer_packet, answer_len);
982 sldns_buffer_flip(buf);
983 libworker_enter_result(result, buf, region, sec);
984 result->answer_packet = NULL((void*)0);
985 result->answer_len = 0;
986
987 sldns_wire2str_rcode_buf(result->rcode, rcode_buf, sizeof(rcode_buf));
988 log_debug("%s[%s]: %s rcode: %s[%d], elapsed: %lldms, running: %d",
989 __func__, uw_resolver_type_str[res->type],
990 query_imsg2str(query_imsg), rcode_buf, result->rcode, ms,
991 running_query_cnt());
992
993 force_acceptbogus = find_force(&resolver_conf->force, query_imsg->qname,
994 &tmp_res);
995 if (tmp_res != NULL((void*)0) && tmp_res->type != res->type)
996 force_acceptbogus = 0;
997
998 timespecsub(&tp, &last_network_change, &elapsed)do { (&elapsed)->tv_sec = (&tp)->tv_sec - (&
last_network_change)->tv_sec; (&elapsed)->tv_nsec =
(&tp)->tv_nsec - (&last_network_change)->tv_nsec
; if ((&elapsed)->tv_nsec < 0) { (&elapsed)->
tv_sec--; (&elapsed)->tv_nsec += 1000000000L; } } while
(0)
;
999 if (sec != SECURE2 && elapsed.tv_sec < DOUBT_NXDOMAIN_SEC(5 * 60) &&
1000 !force_acceptbogus && res->type != UW_RES_ASR &&
1001 (result->rcode == LDNS_RCODE_NXDOMAIN || sec == BOGUS1)) {
1002 /*
1003 * Doubt NXDOMAIN or BOGUS if we just switched networks, we
1004 * might be behind a captive portal.
1005 */
1006 log_debug("%s: doubt NXDOMAIN or BOGUS from %s, network change"
1007 " %llds ago", __func__, uw_resolver_type_str[res->type],
1008 elapsed.tv_sec);
1009
1010 /* search for ASR */
1011 asr_pref_pos = -1;
1012 for (i = 0; i < (size_t)rq->res_pref.len; i++)
1013 if (rq->res_pref.types[i] == UW_RES_ASR) {
1014 asr_pref_pos = i;
1015 break;
1016 }
1017
1018 if (asr_pref_pos != -1 && resolvers[UW_RES_ASR] != NULL((void*)0)) {
1019 /* go to ASR if not yet scheduled */
1020 if (asr_pref_pos >= rq->next_resolver) {
1021 rq->next_resolver = asr_pref_pos;
1022 try_next_resolver(rq);
1023 }
1024 goto out;
1025 }
1026 log_debug("%s: using NXDOMAIN or BOGUS, couldn't find working "
1027 "ASR", __func__);
1028 }
1029
1030 if (log_getverbose() & OPT_VERBOSE20x00000002 && (str =
1031 sldns_wire2str_pkt(answer_packet, answer_len)) != NULL((void*)0)) {
1032 log_debug("%s", str);
1033 free(str);
1034 }
1035
1036 if (result->rcode == LDNS_RCODE_SERVFAIL)
1037 goto servfail;
1038
1039 if (sec == SECURE2 && res->state != VALIDATING && res->stop != -1)
1040 check_resolver(res);
1041
1042 if (res->state == VALIDATING && sec == BOGUS1) {
1043 answer_header->bogus = !force_acceptbogus;
1044 if (answer_header->bogus && why_bogus != NULL((void*)0))
1045 log_warnx("%s", why_bogus);
1046 } else
1047 answer_header->bogus = 0;
1048
1049 p = answer_packet;
1050 do {
1051 int len;
1052
1053 if ((size_t)answer_len > sizeof(answer_imsg) -
1054 sizeof(*answer_header))
1055 len = sizeof(answer_imsg) - sizeof(*answer_header);
1056 else
1057 len = answer_len;
1058 memcpy(data, p, len);
1059 if (resolver_imsg_compose_frontend(IMSG_ANSWER, 0,
1060 &answer_imsg, sizeof(*answer_header) + len) == -1)
1061 fatalx("IMSG_ANSWER failed for \"%s\"",
1062 query_imsg2str(query_imsg));
1063 answer_len -= len;
1064 p += len;
1065 } while (answer_len > 0);
1066
1067 TAILQ_REMOVE(&running_queries, rq, entry)do { if (((rq)->entry.tqe_next) != ((void*)0)) (rq)->entry
.tqe_next->entry.tqe_prev = (rq)->entry.tqe_prev; else (
&running_queries)->tqh_last = (rq)->entry.tqe_prev;
*(rq)->entry.tqe_prev = (rq)->entry.tqe_next; ; ; } while
(0)
;
1068 evtimer_del(&rq->timer_ev)event_del(&rq->timer_ev);
1069 free(rq->query_imsg);
1070 free(rq);
1071 goto out;
1072
1073 servfail:
1074 /* try_next_resolver() might free rq */
1075 if (try_next_resolver(rq) != 0 && running_res == 0) {
1076 /* we are the last one, send SERVFAIL */
1077 answer_header->srvfail = 1;
1078 resolver_imsg_compose_frontend(IMSG_ANSWER, 0,
1079 answer_imsg, sizeof(*answer_header));
1080 }
1081 out:
1082 free(query_imsg);
1083 sldns_buffer_free(buf);
1084 regional_destroy(region);
1085 ub_resolve_free(result);
1086}
1087
1088void
1089new_resolver(enum uw_resolver_type type, enum uw_resolver_state state)
1090{
1091 free_resolver(resolvers[type]);
1092 resolvers[type] = NULL((void*)0);
1093
1094 if (!resolver_conf->enabled_resolvers[type])
1095 return;
1096
1097 switch (type) {
1098 case UW_RES_ASR:
1099 case UW_RES_AUTOCONF:
1100 case UW_RES_ODOT_AUTOCONF:
1101 if (TAILQ_EMPTY(&autoconf_forwarder_list)(((&autoconf_forwarder_list)->tqh_first) == ((void*)0)
)
)
1102 return;
1103 break;
1104 case UW_RES_RECURSOR:
1105 break;
1106 case UW_RES_FORWARDER:
1107 case UW_RES_ODOT_FORWARDER:
1108 if (TAILQ_EMPTY(&resolver_conf->uw_forwarder_list)(((&resolver_conf->uw_forwarder_list)->tqh_first) ==
((void*)0))
)
1109 return;
1110 break;
1111 case UW_RES_DOT:
1112 if (TAILQ_EMPTY(&resolver_conf->uw_dot_forwarder_list)(((&resolver_conf->uw_dot_forwarder_list)->tqh_first
) == ((void*)0))
)
1113 return;
1114 break;
1115 case UW_RES_NONE:
1116 fatalx("cannot create UW_RES_NONE resolver");
1117 }
1118
1119 switch (type) {
1120 case UW_RES_RECURSOR:
1121 case UW_RES_AUTOCONF:
1122 case UW_RES_ODOT_AUTOCONF:
1123 case UW_RES_FORWARDER:
1124 case UW_RES_ODOT_FORWARDER:
1125 case UW_RES_DOT:
1126 if (TAILQ_EMPTY(&trust_anchors)(((&trust_anchors)->tqh_first) == ((void*)0)))
1127 return;
1128 break;
1129 case UW_RES_ASR:
1130 break;
1131 case UW_RES_NONE:
1132 fatalx("cannot create UW_RES_NONE resolver");
1133 }
1134
1135 if ((resolvers[type] = create_resolver(type)) == NULL((void*)0))
1136 return;
1137
1138 switch (state) {
1139 case DEAD:
1140 case UNKNOWN:
1141 check_resolver(resolvers[type]);
1142 break;
1143 case VALIDATING:
1144 set_unified_cache(resolvers[type]);
1145 /* FALLTHROUGH */
1146 case RESOLVING:
1147 resolvers[type]->state = state;
1148 if (type == UW_RES_ASR)
1149 check_dns64();
1150 break;
1151 }
1152}
1153
1154void
1155set_unified_cache(struct uw_resolver *res)
1156{
1157 if (res == NULL((void*)0) || res->ctx == NULL((void*)0))
1158 return;
1159
1160 if (res->ctx->env->msg_cache != NULL((void*)0)) {
1161 /* XXX we are currently not using this */
1162 if (res->ctx->env->msg_cache != unified_msg_cache ||
1163 res->ctx->env->rrset_cache != unified_rrset_cache ||
1164 res->ctx->env->key_cache != unified_key_cache ||
1165 res->ctx->env->neg_cache != unified_neg_cache)
1166 fatalx("wrong unified cache set on resolver");
1167 else
1168 /* we are upgrading from UNKNOWN back to VALIDATING */
1169 return;
1170 }
1171
1172 res->ctx->env->msg_cache = unified_msg_cache;
1173 res->ctx->env->rrset_cache = unified_rrset_cache;
1174 res->ctx->env->key_cache = unified_key_cache;
1175 res->ctx->env->neg_cache = unified_neg_cache;
1176
1177 context_finalize(res->ctx);
1178
1179 if (res->ctx->env->msg_cache != unified_msg_cache ||
1180 res->ctx->env->rrset_cache != unified_rrset_cache ||
1181 res->ctx->env->key_cache != unified_key_cache ||
1182 res->ctx->env->neg_cache != unified_neg_cache)
1183 fatalx("failed to set unified caches, libunbound/validator/"
1184 "validator.c diff lost");
1185}
1186
1187static const struct {
1188 const char *name;
1189 const char *value;
1190} options[] = {
1191 { "aggressive-nsec:", "yes" },
1192 { "fast-server-permil:", "950" },
1193 { "edns-buffer-size:", "1232" },
1194 { "target-fetch-policy:", "0 0 0 0 0" },
1195 { "outgoing-range:", "64" },
1196 { "val-max-restart:", "0" },
1197};
1198
1199struct uw_resolver *
1200create_resolver(enum uw_resolver_type type)
1201{
1202 struct uw_resolver *res;
1203 struct trust_anchor *ta;
1204 size_t i;
1205 int err;
1206 char *resolv_conf;
1207
1208 if ((res = calloc(1, sizeof(*res))) == NULL((void*)0)) {
1209 log_warn("%s", __func__)uw_log_warn("%s", __func__);
1210 return (NULL((void*)0));
1211 }
1212
1213 res->type = type;
1214 res->state = UNKNOWN;
1215 res->check_tv.tv_sec = RESOLVER_CHECK_SEC1;
1216 res->check_tv.tv_usec = arc4random() % 1000000; /* modulo bias is ok */
1217
1218 switch (type) {
1219 case UW_RES_ASR:
1220 if (TAILQ_EMPTY(&autoconf_forwarder_list)(((&autoconf_forwarder_list)->tqh_first) == ((void*)0)
)
) {
1221 free(res);
1222 return (NULL((void*)0));
1223 }
1224 if ((resolv_conf = gen_resolv_conf()) == NULL((void*)0)) {
1225 free(res);
1226 log_warnx("could not create asr context");
1227 return (NULL((void*)0));
1228 }
1229 if ((res->asr_ctx = asr_resolver_from_string(resolv_conf)) ==
1230 NULL((void*)0)) {
1231 free(res);
1232 free(resolv_conf);
1233 log_warnx("could not create asr context");
1234 return (NULL((void*)0));
1235 }
1236 free(resolv_conf);
1237 break;
1238 case UW_RES_RECURSOR:
1239 case UW_RES_AUTOCONF:
1240 case UW_RES_ODOT_AUTOCONF:
1241 case UW_RES_FORWARDER:
1242 case UW_RES_ODOT_FORWARDER:
1243 case UW_RES_DOT:
1244 if ((res->ctx = ub_ctx_create_event(ev_base)) == NULL((void*)0)) {
1245 free(res);
1246 log_warnx("could not create unbound context");
1247 return (NULL((void*)0));
1248 }
1249
1250 ub_ctx_debuglevel(res->ctx, log_getverbose() & OPT_VERBOSE30x00000004 ?
1251 UB_LOG_VERBOSE4 : UB_LOG_BRIEF0);
1252
1253 TAILQ_FOREACH(ta, &trust_anchors, entry)for((ta) = ((&trust_anchors)->tqh_first); (ta) != ((void
*)0); (ta) = ((ta)->entry.tqe_next))
{
1254 if ((err = ub_ctx_add_ta(res->ctx, ta->ta)) != 0) {
1255 ub_ctx_delete(res->ctx);
1256 free(res);
1257 log_warnx("error adding trust anchor: %s",
1258 ub_strerror(err));
1259 return (NULL((void*)0));
1260 }
1261 }
1262
1263 for (i = 0; i < nitems(options)(sizeof((options)) / sizeof((options)[0])); i++) {
1264 if ((err = ub_ctx_set_option(res->ctx, options[i].name,
1265 options[i].value)) != 0) {
1266 ub_ctx_delete(res->ctx);
1267 free(res);
1268 log_warnx("error setting %s: %s: %s",
1269 options[i].name, options[i].value,
1270 ub_strerror(err));
1271 return (NULL((void*)0));
1272 }
1273 }
1274
1275 if (!(available_afs & HAVE_IPV41)) {
1276 if((err = ub_ctx_set_option(res->ctx, "do-ip4:",
1277 "no")) != 0) {
1278 ub_ctx_delete(res->ctx);
1279 free(res);
1280 log_warnx("error setting do-ip4: no: %s",
1281 ub_strerror(err));
1282 return (NULL((void*)0));
1283 }
1284 }
1285
1286 if (!(available_afs & HAVE_IPV62)) {
1287 if((err = ub_ctx_set_option(res->ctx, "do-ip6:",
1288 "no")) != 0) {
1289 ub_ctx_delete(res->ctx);
1290 free(res);
1291 log_warnx("error setting do-ip6: no: %s",
1292 ub_strerror(err));
1293 return (NULL((void*)0));
1294 }
1295 }
1296
1297 if (!log_getdebug()) {
1298 if((err = ub_ctx_set_option(res->ctx, "use-syslog:",
1299 "no")) != 0) {
1300 ub_ctx_delete(res->ctx);
1301 free(res);
1302 log_warnx("error setting use-syslog: no: %s",
1303 ub_strerror(err));
1304 return (NULL((void*)0));
1305 }
1306 ub_ctx_debugout(res->ctx, NULL((void*)0));
1307 }
1308
1309 break;
1310 default:
1311 fatalx("unknown resolver type %d", type);
1312 break;
1313 }
1314
1315 evtimer_set(&res->check_ev, resolver_check_timo, res)event_set(&res->check_ev, -1, 0, resolver_check_timo, res
)
;
1316
1317 switch(res->type) {
1318 case UW_RES_ASR:
1319 break;
1320 case UW_RES_RECURSOR:
1321 break;
1322 case UW_RES_AUTOCONF:
1323 set_forwarders(res, &autoconf_forwarder_list, 0);
1324 break;
1325 case UW_RES_ODOT_AUTOCONF:
1326 set_forwarders(res, &autoconf_forwarder_list, 853);
1327 ub_ctx_set_option(res->ctx, "tls-cert-bundle:",
1328 TLS_DEFAULT_CA_CERT_FILE"/etc/ssl/cert.pem");
1329 ub_ctx_set_tls(res->ctx, 1);
1330 break;
1331 case UW_RES_FORWARDER:
1332 set_forwarders(res, &resolver_conf->uw_forwarder_list, 0);
1333 break;
1334 case UW_RES_ODOT_FORWARDER:
1335 set_forwarders(res, &resolver_conf->uw_forwarder_list, 853);
1336 ub_ctx_set_option(res->ctx, "tls-cert-bundle:",
1337 TLS_DEFAULT_CA_CERT_FILE"/etc/ssl/cert.pem");
1338 ub_ctx_set_tls(res->ctx, 1);
1339 break;
1340 case UW_RES_DOT:
1341 set_forwarders(res, &resolver_conf->uw_dot_forwarder_list, 0);
1342 ub_ctx_set_option(res->ctx, "tls-cert-bundle:",
1343 TLS_DEFAULT_CA_CERT_FILE"/etc/ssl/cert.pem");
1344 ub_ctx_set_tls(res->ctx, 1);
1345 break;
1346 default:
1347 fatalx("unknown resolver type %d", type);
1348 break;
1349 }
1350
1351 /* for the forwarder cases allow AS112 zones */
1352 switch(res->type) {
1353 case UW_RES_AUTOCONF:
1354 case UW_RES_ODOT_AUTOCONF:
1355 case UW_RES_FORWARDER:
1356 case UW_RES_ODOT_FORWARDER:
1357 case UW_RES_DOT:
1358 for (i = 0; i < nitems(as112_zones)(sizeof((as112_zones)) / sizeof((as112_zones)[0])); i++) {
1359 if((err = ub_ctx_set_option(res->ctx, "local-zone:",
1360 as112_zones[i])) != 0) {
1361 ub_ctx_delete(res->ctx);
1362 free(res);
1363 log_warnx("error setting local-zone: %s: %s",
1364 as112_zones[i], ub_strerror(err));
1365 return (NULL((void*)0));
1366 }
1367 }
1368 break;
1369 default:
1370 break;
1371 }
1372
1373 return (res);
1374}
1375
1376void
1377free_resolver(struct uw_resolver *res)
1378{
1379 struct val_env *val_env;
1380
1381 if (res == NULL((void*)0))
1382 return;
1383
1384 if (res->ref_cnt > 0)
1385 res->stop = 1;
1386 else {
1387 evtimer_del(&res->check_ev)event_del(&res->check_ev);
1388 if (res->ctx != NULL((void*)0)) {
1389 if (res->ctx->env->msg_cache == unified_msg_cache) {
1390 val_env = (struct val_env*)
1391 res->ctx->env->modinfo[val_id];
1392 res->ctx->env->msg_cache = NULL((void*)0);
1393 res->ctx->env->rrset_cache = NULL((void*)0);
1394 val_env->kcache = NULL((void*)0);
1395 res->ctx->env->key_cache = NULL((void*)0);
1396 val_env->neg_cache = NULL((void*)0);
1397 res->ctx->env->neg_cache = NULL((void*)0);
1398 }
1399 }
1400 ub_ctx_delete(res->ctx);
1401 asr_resolver_free(res->asr_ctx);
1402 free(res);
1403 }
1404}
1405
1406void
1407setup_unified_caches(void)
1408{
1409 struct ub_ctx *ctx;
1410 struct val_env *val_env;
1411 size_t i;
1412 int err, j;
1413
1414 if ((ctx = ub_ctx_create_event(ev_base)) == NULL((void*)0))
1415 fatalx("could not create unbound context");
1416
1417 for (i = 0; i < nitems(options)(sizeof((options)) / sizeof((options)[0])); i++) {
1418 if ((err = ub_ctx_set_option(ctx, options[i].name,
1419 options[i].value)) != 0) {
1420 fatalx("error setting %s: %s: %s", options[i].name,
1421 options[i].value, ub_strerror(err));
1422 }
1423 }
1424
1425 context_finalize(ctx);
1426
1427 if (ctx->env->msg_cache == NULL((void*)0) || ctx->env->rrset_cache == NULL((void*)0) ||
1428 ctx->env->key_cache == NULL((void*)0) || ctx->env->neg_cache == NULL((void*)0))
1429 fatalx("could not setup unified caches");
1430
1431 unified_msg_cache = ctx->env->msg_cache;
1432 unified_rrset_cache = ctx->env->rrset_cache;
1433 unified_key_cache = ctx->env->key_cache;
1434 unified_neg_cache = ctx->env->neg_cache;
1435
1436 if (val_id == -1) {
1437 for (j = 0; j < ctx->mods.num; j++) {
1438 if (strcmp(ctx->mods.mod[j]->name, "validator") == 0) {
1439 val_id = j;
1440 break;
1441 }
1442 }
1443 if (val_id == -1)
1444 fatalx("cannot find validator module");
1445 }
1446
1447 val_env = (struct val_env*)ctx->env->modinfo[val_id];
1448 ctx->env->msg_cache = NULL((void*)0);
1449 ctx->env->rrset_cache = NULL((void*)0);
1450 ctx->env->key_cache = NULL((void*)0);
1451 val_env->kcache = NULL((void*)0);
1452 ctx->env->neg_cache = NULL((void*)0);
1453 val_env->neg_cache = NULL((void*)0);
1454 ub_ctx_delete(ctx);
1455}
1456
1457void
1458set_forwarders(struct uw_resolver *res, struct uw_forwarder_head
1459 *uw_forwarder_list, int port_override)
1460{
1461 struct uw_forwarder *uw_forwarder;
1462 int ret;
1463 char fwd[FWD_MAX(46 + 256 + 2 + 5)];
1464
1465 TAILQ_FOREACH(uw_forwarder, uw_forwarder_list, entry)for((uw_forwarder) = ((uw_forwarder_list)->tqh_first); (uw_forwarder
) != ((void*)0); (uw_forwarder) = ((uw_forwarder)->entry.tqe_next
))
{
1466 if (uw_forwarder->auth_name[0] != '\0')
1467 ret = snprintf(fwd, sizeof(fwd), "%s@%d#%s",
1468 uw_forwarder->ip, port_override ? port_override :
1469 uw_forwarder->port, uw_forwarder->auth_name);
1470 else
1471 ret = snprintf(fwd, sizeof(fwd), "%s@%d",
1472 uw_forwarder->ip, port_override ? port_override :
1473 uw_forwarder->port);
1474
1475 if (ret < 0 || (size_t)ret >= sizeof(fwd)) {
1476 log_warnx("forwarder too long");
1477 continue;
1478 }
1479
1480 ub_ctx_set_fwd(res->ctx, fwd);
1481 }
1482}
1483
1484void
1485resolver_check_timo(int fd, short events, void *arg)
1486{
1487 check_resolver((struct uw_resolver *)arg);
1488}
1489
1490void
1491resolver_free_timo(int fd, short events, void *arg)
1492{
1493 free_resolver((struct uw_resolver *)arg);
1494}
1495
1496void
1497check_resolver(struct uw_resolver *resolver_to_check)
1498{
1499 struct uw_resolver *res;
1500
1501 if (resolver_to_check == NULL((void*)0))
1502 return;
1503
1504 if (resolver_to_check->check_running)
1505 return;
1506
1507 if ((res = create_resolver(resolver_to_check->type)) == NULL((void*)0))
1508 return;
1509
1510 resolver_ref(resolver_to_check);
1511
1512 resolver_to_check->check_running++;
1513 if (resolve(res, ".", LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN,
1514 resolver_to_check, check_resolver_done) != 0) {
1515 resolver_to_check->check_running--;
1516 resolver_to_check->state = UNKNOWN;
1517 resolver_unref(resolver_to_check);
1518 resolver_to_check->check_tv.tv_sec = RESOLVER_CHECK_SEC1;
1519 evtimer_add(&resolver_to_check->check_ev,event_add(&resolver_to_check->check_ev, &resolver_to_check
->check_tv)
1520 &resolver_to_check->check_tv)event_add(&resolver_to_check->check_ev, &resolver_to_check
->check_tv)
;
1521 }
1522}
1523
1524void
1525check_resolver_done(struct uw_resolver *res, void *arg, int rcode,
1526 void *answer_packet, int answer_len, int sec, char *why_bogus)
1527{
1528 struct uw_resolver *checked_resolver = arg;
1529 struct timeval tv = {0, 1};
1530 enum uw_resolver_state prev_state;
1
'prev_state' declared without an initial value
1531 int bogus_time = 0;
1532 char *str;
1533
1534 checked_resolver->check_running--;
1535
1536 if (checked_resolver != resolvers[checked_resolver->type]) {
2
Assuming the condition is true
3
Taking true branch
1537 log_debug("%s: %s: ignoring late check result", __func__,
1538 uw_resolver_type_str[checked_resolver->type]);
1539 goto out;
4
Control jumps to line 1598
1540 }
1541
1542 prev_state = checked_resolver->state;
1543
1544 if (answer_len < LDNS_HEADER_SIZE12) {
1545 checked_resolver->state = DEAD;
1546 log_warnx("%s: bad packet: too short", __func__);
1547 goto out;
1548 }
1549
1550 if (rcode == LDNS_RCODE_SERVFAIL) {
1551 log_debug("%s: %s rcode: SERVFAIL", __func__,
1552 uw_resolver_type_str[checked_resolver->type]);
1553
1554 checked_resolver->state = DEAD;
1555 goto out;
1556 }
1557
1558 if (sec == SECURE2) {
1559 if (dns64_present && (res->type == UW_RES_AUTOCONF ||
1560 res->type == UW_RES_ODOT_AUTOCONF)) {
1561 /* do not upgrade to validating, DNS64 breaks DNSSEC */
1562 if (prev_state != RESOLVING)
1563 new_resolver(checked_resolver->type,
1564 RESOLVING);
1565 } else {
1566 if (prev_state != VALIDATING)
1567 new_resolver(checked_resolver->type,
1568 VALIDATING);
1569 if (!(evtimer_pending(&trust_anchor_timer, NULL)event_pending(&trust_anchor_timer, 0x01, ((void*)0))))
1570 evtimer_add(&trust_anchor_timer, &tv)event_add(&trust_anchor_timer, &tv);
1571 }
1572 } else if (rcode == LDNS_RCODE_NOERROR &&
1573 LDNS_RCODE_WIRE((uint8_t*)answer_packet)(*((uint8_t*)answer_packet+3) & 0x0fU) == LDNS_RCODE_NOERROR) {
1574 if (why_bogus) {
1575 bogus_time = strncmp(why_bogus, bogus_past,
1576 sizeof(bogus_past) - 1) == 0 || strncmp(why_bogus,
1577 bogus_future, sizeof(bogus_future) - 1) == 0;
1578
1579 log_warnx("%s: %s", uw_resolver_type_str[
1580 checked_resolver->type], why_bogus);
1581 }
1582 if (prev_state != RESOLVING)
1583 new_resolver(checked_resolver->type, RESOLVING);
1584 } else
1585 checked_resolver->state = DEAD; /* we know the root exists */
1586
1587 log_debug("%s: %s: %s", __func__,
1588 uw_resolver_type_str[checked_resolver->type],
1589 uw_resolver_state_str[checked_resolver->state]);
1590
1591 if (log_getverbose() & OPT_VERBOSE20x00000002 && (str =
1592 sldns_wire2str_pkt(answer_packet, answer_len)) != NULL((void*)0)) {
1593 log_debug("%s", str);
1594 free(str);
1595 }
1596
1597out:
1598 if (!checked_resolver->stop && (checked_resolver->state == DEAD ||
5
Assuming field 'stop' is 0
6
Assuming field 'state' is equal to DEAD
1599 bogus_time)) {
1600 if (prev_state == DEAD || bogus_time)
7
The left operand of '==' is a garbage value
1601 checked_resolver->check_tv.tv_sec *= 2;
1602 else
1603 checked_resolver->check_tv.tv_sec = RESOLVER_CHECK_SEC1;
1604
1605 if (checked_resolver->check_tv.tv_sec > RESOLVER_CHECK_MAXSEC1024)
1606 checked_resolver->check_tv.tv_sec =
1607 RESOLVER_CHECK_MAXSEC1024;
1608
1609 evtimer_add(&checked_resolver->check_ev,event_add(&checked_resolver->check_ev, &checked_resolver
->check_tv)
1610 &checked_resolver->check_tv)event_add(&checked_resolver->check_ev, &checked_resolver
->check_tv)
;
1611 }
1612
1613 resolver_unref(checked_resolver);
1614 res->stop = 1; /* do not free in callback */
1615}
1616
1617void
1618asr_resolve_done(struct asr_result *ar, void *arg)
1619{
1620 struct resolver_cb_data *cb_data = arg;
1621 cb_data->cb(cb_data->res, cb_data->data, ar->ar_rcode, ar->ar_data,
1622 ar->ar_datalen, 0, NULL((void*)0));
1623 free(ar->ar_data);
1624 resolver_unref(cb_data->res);
1625 free(cb_data);
1626}
1627
1628void
1629ub_resolve_done(void *arg, int rcode, void *answer_packet, int answer_len,
1630 int sec, char *why_bogus, int was_ratelimited)
1631{
1632 struct resolver_cb_data *cb_data = arg;
1633 cb_data->cb(cb_data->res, cb_data->data, rcode, answer_packet,
1634 answer_len, sec, why_bogus);
1635 resolver_unref(cb_data->res);
1636 free(cb_data);
1637}
1638
1639void
1640schedule_recheck_all_resolvers(void)
1641{
1642 struct timeval tv;
1643 int i;
1644
1645 tv.tv_sec = 0;
1646
1647 for (i = 0; i < UW_RES_NONE; i++) {
1648 if (resolvers[i] == NULL((void*)0))
1649 continue;
1650 tv.tv_usec = arc4random() % 1000000; /* modulo bias is ok */
1651 resolvers[i]->state = UNKNOWN;
1652 evtimer_add(&resolvers[i]->check_ev, &tv)event_add(&resolvers[i]->check_ev, &tv);
1653 }
1654}
1655
1656int
1657check_forwarders_changed(struct uw_forwarder_head *list_a,
1658 struct uw_forwarder_head *list_b)
1659{
1660 struct uw_forwarder *a, *b;
1661
1662 a = TAILQ_FIRST(list_a)((list_a)->tqh_first);
1663 b = TAILQ_FIRST(list_b)((list_b)->tqh_first);
1664
1665 while(a != NULL((void*)0) && b != NULL((void*)0)) {
1666 if (strcmp(a->ip, b->ip) != 0)
1667 return 1;
1668 if (a->port != b->port)
1669 return 1;
1670 if (strcmp(a->auth_name, b->auth_name) != 0)
1671 return 1;
1672 a = TAILQ_NEXT(a, entry)((a)->entry.tqe_next);
1673 b = TAILQ_NEXT(b, entry)((b)->entry.tqe_next);
1674 }
1675
1676 if (a != NULL((void*)0) || b != NULL((void*)0))
1677 return 1;
1678 return 0;
1679}
1680
1681void
1682resolver_ref(struct uw_resolver *res)
1683{
1684 if (res->ref_cnt == INT_MAX2147483647)
1685 fatalx("%s: INT_MAX references", __func__);
1686 res->ref_cnt++;
1687}
1688
1689void
1690resolver_unref(struct uw_resolver *res)
1691{
1692 struct timeval tv = { 0, 1};
1693
1694 if (res->ref_cnt == 0)
1695 fatalx("%s: unreferenced resolver", __func__);
1696
1697 res->ref_cnt--;
1698
1699 /*
1700 * Decouple from libunbound event callback.
1701 * If we free the ctx inside of resolve_done or check_resovler_done
1702 * we are cutting of the branch we are sitting on and hit a
1703 * user-after-free
1704 */
1705 if (res->stop && res->ref_cnt == 0) {
1706 evtimer_set(&res->free_ev, resolver_free_timo, res)event_set(&res->free_ev, -1, 0, resolver_free_timo, res
)
;
1707 evtimer_add(&res->free_ev, &tv)event_add(&res->free_ev, &tv);
1708 }
1709}
1710
1711void
1712replace_forwarders(struct uw_forwarder_head *new_list, struct
1713 uw_forwarder_head *old_list)
1714{
1715 struct uw_forwarder *uw_forwarder;
1716
1717 while ((uw_forwarder =
1718 TAILQ_FIRST(old_list)((old_list)->tqh_first)) != NULL((void*)0)) {
1719 TAILQ_REMOVE(old_list, uw_forwarder, entry)do { if (((uw_forwarder)->entry.tqe_next) != ((void*)0)) (
uw_forwarder)->entry.tqe_next->entry.tqe_prev = (uw_forwarder
)->entry.tqe_prev; else (old_list)->tqh_last = (uw_forwarder
)->entry.tqe_prev; *(uw_forwarder)->entry.tqe_prev = (uw_forwarder
)->entry.tqe_next; ; ; } while (0)
;
1720 free(uw_forwarder);
1721 }
1722
1723 TAILQ_CONCAT(old_list, new_list, entry)do { if (!(((new_list)->tqh_first) == ((void*)0))) { *(old_list
)->tqh_last = (new_list)->tqh_first; (new_list)->tqh_first
->entry.tqe_prev = (old_list)->tqh_last; (old_list)->
tqh_last = (new_list)->tqh_last; do { ((new_list))->tqh_first
= ((void*)0); ((new_list))->tqh_last = &((new_list))->
tqh_first; } while (0); } } while (0)
;
1724}
1725
1726int
1727resolver_cmp(const void *_a, const void *_b)
1728{
1729 const enum uw_resolver_type a = *(const enum uw_resolver_type *)_a;
1730 const enum uw_resolver_type b = *(const enum uw_resolver_type *)_b;
1731 int64_t a_median, b_median;
1732
1733 if (resolvers[a] == NULL((void*)0) && resolvers[b] == NULL((void*)0))
1734 return 0;
1735
1736 if (resolvers[b] == NULL((void*)0))
1737 return -1;
1738
1739 if (resolvers[a] == NULL((void*)0))
1740 return 1;
1741
1742 if (resolvers[a]->state < resolvers[b]->state)
1743 return 1;
1744 else if (resolvers[a]->state > resolvers[b]->state)
1745 return -1;
1746 else {
1747 a_median = resolvers[a]->median;
1748 b_median = resolvers[b]->median;
1749 if (resolvers[a]->type == resolver_conf->res_pref.types[0])
1750 a_median -= PREF_RESOLVER_MEDIAN_SKEW200;
1751 else if (resolvers[b]->type == resolver_conf->res_pref.types[0])
1752 b_median -= PREF_RESOLVER_MEDIAN_SKEW200;
1753 if (a_median < b_median)
1754 return -1;
1755 else if (a_median > b_median)
1756 return 1;
1757 else
1758 return 0;
1759 }
1760}
1761
1762void
1763restart_ub_resolvers(int recheck)
1764{
1765 int i;
1766 enum uw_resolver_state state;
1767
1768 for (i = 0; i < UW_RES_NONE; i++) {
1769 if (i == UW_RES_ASR)
1770 continue;
1771 if (recheck || resolvers[i] == NULL((void*)0))
1772 state = UNKNOWN;
1773 else
1774 state = resolvers[i]->state;
1775 new_resolver(i, state);
1776 }
1777}
1778
1779void
1780show_status(pid_t pid)
1781{
1782 struct resolver_preference res_pref;
1783 int i;
1784
1785 if (sort_resolver_types(&res_pref) == -1)
1786 log_warn("mergesort")uw_log_warn("mergesort");
1787
1788 for (i = 0; i < resolver_conf->res_pref.len; i++)
1789 send_resolver_info(resolvers[res_pref.types[i]], pid);
1790
1791 resolver_imsg_compose_frontend(IMSG_CTL_END, pid, NULL((void*)0), 0);
1792}
1793
1794void
1795show_autoconf(pid_t pid)
1796{
1797 struct uw_forwarder *uw_forwarder;
1798 struct ctl_forwarder_info cfi;
1799
1800 TAILQ_FOREACH(uw_forwarder, &autoconf_forwarder_list, entry)for((uw_forwarder) = ((&autoconf_forwarder_list)->tqh_first
); (uw_forwarder) != ((void*)0); (uw_forwarder) = ((uw_forwarder
)->entry.tqe_next))
{
1801 memset(&cfi, 0, sizeof(cfi));
1802 cfi.if_index = uw_forwarder->if_index;
1803 cfi.src = uw_forwarder->src;
1804 /* no truncation, structs are in sync */
1805 memcpy(cfi.ip, uw_forwarder->ip, sizeof(cfi.ip));
1806 resolver_imsg_compose_frontend(
1807 IMSG_CTL_AUTOCONF_RESOLVER_INFO,
1808 pid, &cfi, sizeof(cfi));
1809 }
1810
1811 resolver_imsg_compose_frontend(IMSG_CTL_END, pid, NULL((void*)0), 0);
1812}
1813
1814void
1815show_mem(pid_t pid)
1816{
1817 struct ctl_mem_info cmi;
1818
1819 memset(&cmi, 0, sizeof(cmi));
1820 cmi.msg_cache_used = slabhash_get_mem(unified_msg_cache);
1821 cmi.msg_cache_max = slabhash_get_size(unified_msg_cache);
1822 cmi.rrset_cache_used = slabhash_get_mem(&unified_rrset_cache->table);
1823 cmi.rrset_cache_max = slabhash_get_size(&unified_rrset_cache->table);
1824 cmi.key_cache_used = slabhash_get_mem(unified_key_cache->slab);
1825 cmi.key_cache_max = slabhash_get_size(unified_key_cache->slab);
1826 cmi.neg_cache_used = unified_neg_cache->use;
1827 cmi.neg_cache_max = unified_neg_cache->max;
1828 resolver_imsg_compose_frontend(IMSG_CTL_MEM_INFO, pid, &cmi,
1829 sizeof(cmi));
1830
1831}
1832
1833void
1834send_resolver_info(struct uw_resolver *res, pid_t pid)
1835{
1836 struct ctl_resolver_info cri;
1837 size_t i;
1838
1839 if (res == NULL((void*)0))
1840 return;
1841
1842 cri.state = res->state;
1843 cri.type = res->type;
1844 cri.median = res->median;
1845
1846 memcpy(cri.histogram, res->histogram, sizeof(cri.histogram));
1847 memcpy(cri.latest_histogram, res->latest_histogram,
1848 sizeof(cri.latest_histogram));
1849 for (i = 0; i < nitems(histogram_limits)(sizeof((histogram_limits)) / sizeof((histogram_limits)[0])); i++)
1850 cri.latest_histogram[i] =
1851 (cri.latest_histogram[i] + 500) / 1000;
1852
1853 resolver_imsg_compose_frontend(IMSG_CTL_RESOLVER_INFO, pid, &cri,
1854 sizeof(cri));
1855}
1856
1857void
1858trust_anchor_resolve(void)
1859{
1860 struct resolver_preference res_pref;
1861 struct uw_resolver *res;
1862 struct timeval tv = {TRUST_ANCHOR_RETRY_INTERVAL8640, 0};
1863
1864 if (sort_resolver_types(&res_pref) == -1)
1865 log_warn("mergesort")uw_log_warn("mergesort");
1866
1867 res = resolvers[res_pref.types[0]];
1868
1869 if (res == NULL((void*)0) || res->state < VALIDATING)
1870 goto err;
1871
1872 if (resolve(res, ".", LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, NULL((void*)0),
1873 trust_anchor_resolve_done) != 0)
1874 goto err;
1875
1876 return;
1877 err:
1878 evtimer_add(&trust_anchor_timer, &tv)event_add(&trust_anchor_timer, &tv);
1879}
1880
1881void
1882trust_anchor_timo(int fd, short events, void *arg)
1883{
1884 trust_anchor_resolve();
1885}
1886
1887void
1888trust_anchor_resolve_done(struct uw_resolver *res, void *arg, int rcode,
1889 void *answer_packet, int answer_len, int sec, char *why_bogus)
1890{
1891 struct ub_result *result = NULL((void*)0);
1892 sldns_buffer *buf = NULL((void*)0);
1893 struct regional *region = NULL((void*)0);
1894 struct timeval tv = {TRUST_ANCHOR_RETRY_INTERVAL8640, 0};
1895 int i, tas, n;
1896 uint16_t dnskey_flags;
1897 char rdata_buf[1024], *ta;
1898
1899 if (answer_len < LDNS_HEADER_SIZE12) {
1900 log_warnx("bad packet: too short");
1901 goto out;
1902 }
1903
1904 if ((result = calloc(1, sizeof(*result))) == NULL((void*)0))
1905 goto out;
1906
1907 if (sec != SECURE2)
1908 goto out;
1909
1910 if ((buf = sldns_buffer_new(answer_len)) == NULL((void*)0))
1911 goto out;
1912 if ((region = regional_create()) == NULL((void*)0))
1913 goto out;
1914 result->rcode = LDNS_RCODE_SERVFAIL;
1915
1916 sldns_buffer_clear(buf);
1917 sldns_buffer_write(buf, answer_packet, answer_len);
1918 sldns_buffer_flip(buf);
1919 libworker_enter_result(result, buf, region, sec);
1920 result->answer_packet = NULL((void*)0);
1921 result->answer_len = 0;
1922
1923 if (result->rcode != LDNS_RCODE_NOERROR)
1924 goto out;
1925
1926 i = 0;
1927 tas = 0;
1928 while(result->data[i] != NULL((void*)0)) {
1929 if (result->len[i] < 2) {
1930 if (tas > 0)
1931 resolver_imsg_compose_frontend(
1932 IMSG_NEW_TAS_ABORT, 0, NULL((void*)0), 0);
1933 goto out;
1934 }
1935 n = sldns_wire2str_rdata_buf(result->data[i], result->len[i],
1936 rdata_buf, sizeof(rdata_buf), LDNS_RR_TYPE_DNSKEY);
1937
1938 if (n < 0 || (size_t)n >= sizeof(rdata_buf)) {
1939 log_warnx("trust anchor buffer to small");
1940 resolver_imsg_compose_frontend(IMSG_NEW_TAS_ABORT, 0,
1941 NULL((void*)0), 0);
1942 goto out;
1943 }
1944
1945 memcpy(&dnskey_flags, result->data[i], 2);
1946 dnskey_flags = ntohs(dnskey_flags)(__uint16_t)(__builtin_constant_p(dnskey_flags) ? (__uint16_t
)(((__uint16_t)(dnskey_flags) & 0xffU) << 8 | ((__uint16_t
)(dnskey_flags) & 0xff00U) >> 8) : __swap16md(dnskey_flags
))
;
1947 if ((dnskey_flags & LDNS_KEY_SEP_KEY0x0001) && !(dnskey_flags &
1948 LDNS_KEY_REVOKE_KEY0x0080)) {
1949 asprintf(&ta, ".\t%d\tIN\tDNSKEY\t%s", ROOT_DNSKEY_TTL172800,
1950 rdata_buf);
1951 resolver_imsg_compose_frontend(IMSG_NEW_TA, 0, ta,
1952 strlen(ta) + 1);
1953 tas++;
1954 free(ta);
1955 }
1956 i++;
1957 }
1958 if (tas > 0) {
1959 resolver_imsg_compose_frontend(IMSG_NEW_TAS_DONE, 0, NULL((void*)0), 0);
1960 tv.tv_sec = TRUST_ANCHOR_QUERY_INTERVAL43200;
1961 }
1962out:
1963 sldns_buffer_free(buf);
1964 regional_destroy(region);
1965 ub_resolve_free(result);
1966 evtimer_add(&trust_anchor_timer, &tv)event_add(&trust_anchor_timer, &tv);
1967}
1968
1969void
1970replace_autoconf_forwarders(struct imsg_rdns_proposal *rdns_proposal)
1971{
1972 struct uw_forwarder_head new_forwarder_list;
1973 struct uw_forwarder *uw_forwarder, *tmp;
1974 size_t addrsz;
1975 int i, rdns_count, af, changed = 0;
1976 char hostbuf[INET6_ADDRSTRLEN46], *src;
1977
1978 TAILQ_INIT(&new_forwarder_list)do { (&new_forwarder_list)->tqh_first = ((void*)0); (&
new_forwarder_list)->tqh_last = &(&new_forwarder_list
)->tqh_first; } while (0)
;
1979 af = rdns_proposal->rtdns.sr_family;
1980 src = rdns_proposal->rtdns.sr_dns;
1981
1982 switch (af) {
1983 case AF_INET2:
1984 addrsz = sizeof(struct in_addr);
1985 break;
1986 case AF_INET624:
1987 addrsz = sizeof(struct in6_addr);
1988 break;
1989 default:
1990 log_warnx("%s: unsupported address family: %d", __func__, af);
1991 return;
1992 }
1993
1994 if ((rdns_proposal->rtdns.sr_len - 2) % addrsz != 0) {
1995 log_warnx("ignoring invalid RTM_PROPOSAL");
1996 return;
1997 }
1998 rdns_count = (rdns_proposal->rtdns.sr_len -
1999 offsetof(struct sockaddr_rtdns, sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns)) / addrsz;
2000
2001 for (i = 0; i < rdns_count; i++) {
2002 struct sockaddr_storage ss;
2003 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
2004 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
2005 int err;
2006
2007 memset(&ss, 0, sizeof(ss));
2008 ss.ss_family = af;
2009 switch (af) {
2010 case AF_INET2:
2011 memcpy(&sin->sin_addr, src, addrsz);
2012 if (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x7f000001))))
)
2013 goto skip;
2014 ss.ss_len = sizeof(*sin);
2015 break;
2016 case AF_INET624:
2017 memcpy(&sin6->sin6_addr, src, addrsz);
2018 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&sin6->sin6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&sin6->sin6_addr)->__u6_addr.__u6_addr8[8
]) == 0) && (*(const u_int32_t *)(const void *)(&
(&sin6->sin6_addr)->__u6_addr.__u6_addr8[12]) == (__uint32_t
)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t)(1) &
0xff) << 24 | ((__uint32_t)(1) & 0xff00) << 8
| ((__uint32_t)(1) & 0xff0000) >> 8 | ((__uint32_t
)(1) & 0xff000000) >> 24) : __swap32md(1))))
)
2019 goto skip;
2020 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))
)
2021 sin6->sin6_scope_id = rdns_proposal->if_index;
2022 ss.ss_len = sizeof(*sin6);
2023 break;
2024 }
2025 if ((err = getnameinfo((struct sockaddr *)&ss, ss.ss_len,
2026 hostbuf, sizeof(hostbuf), NULL((void*)0), 0, NI_NUMERICHOST1)) != 0) {
2027 log_warnx("getnameinfo: %s", gai_strerror(err));
2028 goto skip;
2029 }
2030
2031 if ((uw_forwarder = calloc(1, sizeof(struct uw_forwarder))) ==
2032 NULL((void*)0))
2033 fatal(NULL((void*)0));
2034 if (strlcpy(uw_forwarder->ip, hostbuf, sizeof(uw_forwarder->ip))
2035 >= sizeof(uw_forwarder->ip))
2036 fatalx("strlcpy");
2037 uw_forwarder->port = 53;
2038 uw_forwarder->if_index = rdns_proposal->if_index;
2039 uw_forwarder->src = rdns_proposal->src;
2040 TAILQ_INSERT_TAIL(&new_forwarder_list, uw_forwarder, entry)do { (uw_forwarder)->entry.tqe_next = ((void*)0); (uw_forwarder
)->entry.tqe_prev = (&new_forwarder_list)->tqh_last
; *(&new_forwarder_list)->tqh_last = (uw_forwarder); (
&new_forwarder_list)->tqh_last = &(uw_forwarder)->
entry.tqe_next; } while (0)
;
2041
2042skip:
2043 src += addrsz;
2044 }
2045
2046 TAILQ_FOREACH(tmp, &autoconf_forwarder_list, entry)for((tmp) = ((&autoconf_forwarder_list)->tqh_first); (
tmp) != ((void*)0); (tmp) = ((tmp)->entry.tqe_next))
{
2047 /*
2048 * if_index of zero signals to clear all proposals
2049 * src of zero signals interface gone
2050 */
2051 if ((rdns_proposal->src == 0 || rdns_proposal->src ==
2052 tmp->src) && (rdns_proposal->if_index == 0 ||
2053 rdns_proposal->if_index == tmp->if_index))
2054 continue;
2055 if ((uw_forwarder = calloc(1, sizeof(struct uw_forwarder))) ==
2056 NULL((void*)0))
2057 fatal(NULL((void*)0));
2058 if (strlcpy(uw_forwarder->ip, tmp->ip,
2059 sizeof(uw_forwarder->ip)) >= sizeof(uw_forwarder->ip))
2060 fatalx("strlcpy");
2061 uw_forwarder->port = tmp->port;
2062 uw_forwarder->src = tmp->src;
2063 uw_forwarder->if_index = tmp->if_index;
2064 TAILQ_INSERT_TAIL(&new_forwarder_list, uw_forwarder, entry)do { (uw_forwarder)->entry.tqe_next = ((void*)0); (uw_forwarder
)->entry.tqe_prev = (&new_forwarder_list)->tqh_last
; *(&new_forwarder_list)->tqh_last = (uw_forwarder); (
&new_forwarder_list)->tqh_last = &(uw_forwarder)->
entry.tqe_next; } while (0)
;
2065 }
2066
2067 changed = check_forwarders_changed(&new_forwarder_list,
2068 &autoconf_forwarder_list);
2069
2070 if (changed) {
2071 replace_forwarders(&new_forwarder_list,
2072 &autoconf_forwarder_list);
2073 new_resolver(UW_RES_ASR, UNKNOWN);
2074 new_resolver(UW_RES_AUTOCONF, UNKNOWN);
2075 new_resolver(UW_RES_ODOT_AUTOCONF, UNKNOWN);
2076 } else {
2077 while ((tmp = TAILQ_FIRST(&new_forwarder_list)((&new_forwarder_list)->tqh_first)) != NULL((void*)0)) {
2078 TAILQ_REMOVE(&new_forwarder_list, tmp, entry)do { if (((tmp)->entry.tqe_next) != ((void*)0)) (tmp)->
entry.tqe_next->entry.tqe_prev = (tmp)->entry.tqe_prev;
else (&new_forwarder_list)->tqh_last = (tmp)->entry
.tqe_prev; *(tmp)->entry.tqe_prev = (tmp)->entry.tqe_next
; ; ; } while (0)
;
2079 free(tmp);
2080 }
2081 }
2082}
2083
2084int
2085force_tree_cmp(struct force_tree_entry *a, struct force_tree_entry *b)
2086{
2087 return strcasecmp(a->domain, b->domain);
2088}
2089
2090int
2091find_force(struct force_tree *tree, char *qname, struct uw_resolver **res)
2092{
2093 struct force_tree_entry *n, e;
2094 char *p;
2095
2096 if (res)
2097 *res = NULL((void*)0);
2098 if (RB_EMPTY(tree)((tree)->rbh_root == ((void*)0)))
2099 return 0;
2100
2101 p = qname;
2102 do {
2103 if (strlcpy(e.domain, p, sizeof(e.domain)) >= sizeof(e.domain))
2104 fatal("qname too large");
2105 n = RB_FIND(force_tree, tree, &e)force_tree_RB_FIND(tree, &e);
2106 if (n != NULL((void*)0)) {
2107 log_debug("%s: %s -> %s[%s]", __func__, qname, p,
2108 uw_resolver_type_str[n->type]);
2109 if (res)
2110 *res = resolvers[n->type];
2111 return n->acceptbogus;
2112 }
2113 if (*p == '.')
2114 p++;
2115 p = strchr(p, '.');
2116 if (p != NULL((void*)0) && p[1] != '\0')
2117 p++;
2118 } while (p != NULL((void*)0));
2119 return 0;
2120
2121}
2122
2123int64_t
2124histogram_median(int64_t *histogram)
2125{
2126 size_t i;
2127 int64_t sample_count = 0, running_count = 0;
2128
2129 /* skip first bucket, it contains cache hits */
2130 for (i = 1; i < nitems(histogram_limits)(sizeof((histogram_limits)) / sizeof((histogram_limits)[0])); i++)
2131 sample_count += histogram[i];
2132
2133 if (sample_count == 0)
2134 return 0;
2135
2136 for (i = 1; i < nitems(histogram_limits)(sizeof((histogram_limits)) / sizeof((histogram_limits)[0])); i++) {
2137 running_count += histogram[i];
2138 if (running_count >= sample_count / 2)
2139 break;
2140 }
2141
2142 if (i >= nitems(histogram_limits)(sizeof((histogram_limits)) / sizeof((histogram_limits)[0])) - 1)
2143 return INT64_MAX0x7fffffffffffffffLL;
2144 return (histogram_limits[i - 1] + histogram_limits[i]) / 2;
2145}
2146
2147void
2148decay_latest_histograms(int fd, short events, void *arg)
2149{
2150 enum uw_resolver_type i;
2151 size_t j;
2152 struct uw_resolver *res;
2153 struct timeval tv = {DECAY_PERIOD60, 0};
2154
2155 for (i = 0; i < UW_RES_NONE; i++) {
2156 res = resolvers[i];
2157 if (res == NULL((void*)0))
2158 continue;
2159 for (j = 0; j < nitems(res->latest_histogram)(sizeof((res->latest_histogram)) / sizeof((res->latest_histogram
)[0]))
; j++)
2160 /* multiply then divide, avoiding truncating to 0 */
2161 res->latest_histogram[j] = res->latest_histogram[j] *
2162 DECAY_NOMINATOR9 / DECAY_DENOMINATOR10;
2163 res->median = histogram_median(res->latest_histogram);
2164 }
2165 evtimer_add(&decay_timer, &tv)event_add(&decay_timer, &tv);
2166}
2167
2168int
2169running_query_cnt(void)
2170{
2171 struct running_query *e;
2172 int cnt = 0;
2173
2174 TAILQ_FOREACH(e, &running_queries, entry)for((e) = ((&running_queries)->tqh_first); (e) != ((void
*)0); (e) = ((e)->entry.tqe_next))
2175 cnt++;
2176 return cnt;
2177}
2178
2179int *
2180resolvers_to_restart(struct uw_conf *oconf, struct uw_conf *nconf)
2181{
2182 static int restart[UW_RES_NONE];
2183 int i;
2184
2185 memset(&restart, 0, sizeof(restart));
2186 if (check_forwarders_changed(&oconf->uw_forwarder_list,
2187 &nconf->uw_forwarder_list)) {
2188 restart[UW_RES_FORWARDER] = 1;
2189 restart[UW_RES_ODOT_FORWARDER] = 1;
2190 }
2191 if (check_forwarders_changed(&oconf->uw_dot_forwarder_list,
2192 &nconf->uw_dot_forwarder_list)) {
2193 restart[UW_RES_DOT] = 1;
2194 }
2195
2196 for (i = 0; i < UW_RES_NONE; i++) {
2197 if (oconf->enabled_resolvers[i] != nconf->enabled_resolvers[i])
2198 restart[i] = 1;
2199 }
2200 return restart;
2201}
2202
2203const char *
2204query_imsg2str(struct query_imsg *query_imsg)
2205{
2206 static char buf[sizeof(query_imsg->qname) + 1 + 16 + 1 + 16];
2207 char qclass_buf[16];
2208 char qtype_buf[16];
2209
2210 sldns_wire2str_class_buf(query_imsg->c, qclass_buf, sizeof(qclass_buf));
2211 sldns_wire2str_type_buf(query_imsg->t, qtype_buf, sizeof(qtype_buf));
2212
2213 snprintf(buf, sizeof(buf), "%s %s %s", query_imsg->qname, qclass_buf,
2214 qtype_buf);
2215 return buf;
2216}
2217
2218char *
2219gen_resolv_conf()
2220{
2221 struct uw_forwarder *uw_forwarder;
2222 char *resolv_conf = NULL((void*)0), *tmp = NULL((void*)0);
2223
2224 TAILQ_FOREACH(uw_forwarder, &autoconf_forwarder_list, entry)for((uw_forwarder) = ((&autoconf_forwarder_list)->tqh_first
); (uw_forwarder) != ((void*)0); (uw_forwarder) = ((uw_forwarder
)->entry.tqe_next))
{
2225 tmp = resolv_conf;
2226 if (asprintf(&resolv_conf, "%snameserver %s\n", tmp ==
2227 NULL((void*)0) ? "" : tmp, uw_forwarder->ip) == -1) {
2228 free(tmp);
2229 return (NULL((void*)0));
2230 }
2231 free(tmp);
2232 }
2233 return resolv_conf;
2234}
2235
2236void
2237check_dns64(void)
2238{
2239 struct asr_query *aq = NULL((void*)0);
2240 char *resolv_conf;
2241 void *asr_ctx;
2242
2243 if (TAILQ_EMPTY(&autoconf_forwarder_list)(((&autoconf_forwarder_list)->tqh_first) == ((void*)0)
)
)
2244 return;
2245
2246 if ((resolv_conf = gen_resolv_conf()) == NULL((void*)0)) {
2247 log_warnx("could not create asr context");
2248 return;
2249 }
2250
2251 if ((asr_ctx = asr_resolver_from_string(resolv_conf)) != NULL((void*)0)) {
2252 if ((aq = res_query_async("ipv4only.arpa", LDNS_RR_CLASS_IN,
2253 LDNS_RR_TYPE_AAAA, asr_ctx)) == NULL((void*)0)) {
2254 log_warn("%s: res_query_async", __func__)uw_log_warn("%s: res_query_async", __func__);
2255 asr_resolver_free(asr_ctx);
2256 }
2257 if (event_asr_run(aq, check_dns64_done, asr_ctx) == NULL((void*)0)) {
2258 log_warn("%s: event_asr_run", __func__)uw_log_warn("%s: event_asr_run", __func__);
2259 free(aq);
2260 asr_resolver_free(asr_ctx);
2261 }
2262 } else
2263 log_warnx("%s: could not create asr context", __func__);
2264
2265 free(resolv_conf);
2266}
2267
2268void
2269check_dns64_done(struct asr_result *ar, void *arg)
2270{
2271 /* RFC 7050: ipv4only.arpa resolves to 192.0.0.170 and 192.9.0.171 */
2272 const uint8_t wka1[] = {192, 0, 0, 170};
2273 const uint8_t wka2[] = {192, 0, 0, 171};
2274 struct query_info skip, qinfo;
2275 struct reply_info *rinfo = NULL((void*)0);
2276 struct regional *region = NULL((void*)0);
2277 struct sldns_buffer *buf = NULL((void*)0);
2278 struct ub_packed_rrset_key *an_rrset = NULL((void*)0);
2279 struct packed_rrset_data *an_rrset_data;
2280 struct alloc_cache alloc;
2281 struct edns_data edns;
2282 struct dns64_prefix *prefixes = NULL((void*)0);
2283 size_t i;
2284 int preflen, count = 0;
2285 void *asr_ctx = arg;
2286
2287 memset(&qinfo, 0, sizeof(qinfo));
2288 alloc_init(&alloc, NULL((void*)0), 0);
2289
2290 if (ar->ar_datalen < LDNS_HEADER_SIZE12) {
2291 log_warnx("%s: bad packet: too short: %d", __func__,
2292 ar->ar_datalen);
2293 goto out;
2294 }
2295
2296 if (ar->ar_datalen > UINT16_MAX0xffff) {
2297 log_warnx("%s: bad packet: too large: %d", __func__,
2298 ar->ar_datalen);
2299 goto out;
2300 }
2301
2302 if (ar->ar_rcode == LDNS_RCODE_NXDOMAIN) {
2303 /* XXX this means that the autoconf resolver is broken */
2304 log_debug("%s: NXDOMAIN", __func__);
2305 goto out;
2306 }
2307
2308 if ((buf = sldns_buffer_new(ar->ar_datalen)) == NULL((void*)0))
2309 goto out;
2310
2311 if ((region = regional_create()) == NULL((void*)0))
2312 goto out;
2313
2314 sldns_buffer_write(buf, ar->ar_data, ar->ar_datalen);
2315 sldns_buffer_flip(buf);
2316
2317 /* read past query section, no memory is allocated */
2318 if (!query_info_parse(&skip, buf))
2319 goto out;
2320
2321 if (reply_info_parse(buf, &alloc, &qinfo, &rinfo, region, &edns) != 0)
2322 goto out;
2323
2324 if ((an_rrset = reply_find_answer_rrset(&qinfo, rinfo)) == NULL((void*)0))
2325 goto out;
2326
2327 an_rrset_data = (struct packed_rrset_data*)an_rrset->entry.data;
2328
2329 prefixes = calloc(an_rrset_data->count, sizeof(struct dns64_prefix));
2330 if (prefixes == NULL((void*)0))
2331 goto out;
2332
2333 for (i = 0; i < an_rrset_data->count; i++) {
2334 struct in6_addr in6;
2335
2336 /* check for AAAA record */
2337 if (an_rrset_data->rr_len[i] != 18) /* 2 + 128/8 */
2338 continue;
2339 if (an_rrset_data->rr_data[i][0] != 0 &&
2340 an_rrset_data->rr_data[i][1] != 16)
2341 continue;
2342
2343 memcpy(&in6, &an_rrset_data->rr_data[i][2],
2344 sizeof(in6));
2345 if ((preflen = dns64_prefixlen(&in6, wka1)) != -1)
2346 add_dns64_prefix(&in6, preflen, prefixes,
2347 an_rrset_data->count, WKA1_FOUND1);
2348 if ((preflen = dns64_prefixlen(&in6, wka2)) != -1)
2349 add_dns64_prefix(&in6, preflen, prefixes,
2350 an_rrset_data->count, WKA2_FOUND2);
2351 }
2352
2353 for (i = 0; i < an_rrset_data->count && prefixes[i].flags != 0; i++)
2354 if ((prefixes[i].flags & (WKA1_FOUND1 | WKA2_FOUND2)) ==
2355 (WKA1_FOUND1 | WKA2_FOUND2))
2356 count++;
2357
2358 dns64_present = count > 0;
2359
2360 if (dns64_present) {
2361 /* downgrade SLAAC resolvers, DNS64 breaks DNSSEC */
2362 if (resolvers[UW_RES_AUTOCONF] != NULL((void*)0) &&
2363 resolvers[UW_RES_AUTOCONF]->state == VALIDATING)
2364 new_resolver(UW_RES_AUTOCONF, RESOLVING);
2365 if (resolvers[UW_RES_ODOT_AUTOCONF] != NULL((void*)0) &&
2366 resolvers[UW_RES_ODOT_AUTOCONF]->state == VALIDATING)
2367 new_resolver(UW_RES_ODOT_AUTOCONF, RESOLVING);
2368 }
2369
2370 resolver_imsg_compose_frontend(IMSG_NEW_DNS64_PREFIXES_START, 0,
2371 &count, sizeof(count));
2372 for (i = 0; i < an_rrset_data->count && prefixes[i].flags != 0; i++) {
2373 if ((prefixes[i].flags & (WKA1_FOUND1 | WKA2_FOUND2)) ==
2374 (WKA1_FOUND1 | WKA2_FOUND2)) {
2375 resolver_imsg_compose_frontend(IMSG_NEW_DNS64_PREFIX,
2376 0, &prefixes[i], sizeof(struct dns64_prefix));
2377 }
2378 }
2379 resolver_imsg_compose_frontend(IMSG_NEW_DNS64_PREFIXES_DONE, 0, NULL((void*)0),
2380 0);
2381 out:
2382 free(prefixes);
2383 query_info_clear(&qinfo);
2384 reply_info_parsedelete(rinfo, &alloc);
2385 alloc_clear(&alloc);
2386 regional_destroy(region);
2387 sldns_buffer_free(buf);
2388 free(ar->ar_data);
2389 asr_resolver_free(asr_ctx);
2390}
2391
2392int
2393dns64_prefixlen(const struct in6_addr *in6, const uint8_t *wka)
2394{
2395 /* RFC 6052, 2.2 */
2396 static const int possible_prefixes[] = {32, 40, 48, 56, 64, 96};
2397 size_t i, j;
2398 int found, pos;
2399
2400 for (i = 0; i < nitems(possible_prefixes)(sizeof((possible_prefixes)) / sizeof((possible_prefixes)[0])
)
; i++) {
2401 pos = possible_prefixes[i] / 8;
2402 found = 1;
2403 for (j = 0; j < 4 && found; j++, pos++) {
2404 if (pos == 8) {
2405 if (in6->s6_addr__u6_addr.__u6_addr8[pos] != 0)
2406 found = 0;
2407 pos++;
2408 }
2409 if (in6->s6_addr__u6_addr.__u6_addr8[pos] != wka[j])
2410 found = 0;
2411 }
2412 if (found)
2413 return possible_prefixes[i];
2414 }
2415 return -1;
2416}
2417
2418void
2419add_dns64_prefix(const struct in6_addr *in6, int prefixlen,
2420 struct dns64_prefix *prefixes, int prefixes_size, int flag)
2421{
2422 struct in6_addr tmp;
2423 int i;
2424
2425 tmp = *in6;
2426
2427 for(i = prefixlen / 8; i < 16; i++)
2428 tmp.s6_addr__u6_addr.__u6_addr8[i] = 0;
2429
2430 for (i = 0; i < prefixes_size; i++) {
2431 if (prefixes[i].flags == 0) {
2432 prefixes[i].in6 = tmp;
2433 prefixes[i].prefixlen = prefixlen;
2434 prefixes[i].flags |= flag;
2435 break;
2436 } else if (prefixes[i].prefixlen == prefixlen &&
2437 memcmp(&prefixes[i].in6, &tmp, sizeof(tmp)) == 0) {
2438 prefixes[i].flags |= flag;
2439 break;
2440 }
2441 }
2442}