]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - util/module.c
unbound: Vendor import 1.19.0
[FreeBSD/FreeBSD.git] / util / module.c
1 /*
2  * util/module.c - module interface
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * 
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  * 
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  * 
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 /**
36  * \file
37  * Implementation of module.h.
38  */
39
40 #include "config.h"
41 #include "util/module.h"
42 #include "sldns/wire2str.h"
43 #include "util/config_file.h"
44 #include "util/regional.h"
45 #include "util/data/dname.h"
46 #include "util/net_help.h"
47
48 const char* 
49 strextstate(enum module_ext_state s)
50 {
51         switch(s) {
52         case module_state_initial: return "module_state_initial";
53         case module_wait_reply: return "module_wait_reply";
54         case module_wait_module: return "module_wait_module";
55         case module_restart_next: return "module_restart_next";
56         case module_wait_subquery: return "module_wait_subquery";
57         case module_error: return "module_error";
58         case module_finished: return "module_finished";
59         }
60         return "bad_extstate_value";
61 }
62
63 const char* 
64 strmodulevent(enum module_ev e)
65 {
66         switch(e) {
67         case module_event_new: return "module_event_new";
68         case module_event_pass: return "module_event_pass";
69         case module_event_reply: return "module_event_reply";
70         case module_event_noreply: return "module_event_noreply";
71         case module_event_capsfail: return "module_event_capsfail";
72         case module_event_moddone: return "module_event_moddone";
73         case module_event_error: return "module_event_error";
74         }
75         return "bad_event_value";
76 }
77
78 void errinf(struct module_qstate* qstate, const char* str)
79 {
80         errinf_ede(qstate, str, LDNS_EDE_NONE);
81 }
82
83 void errinf_ede(struct module_qstate* qstate,
84         const char* str, sldns_ede_code reason_bogus)
85 {
86         struct errinf_strlist* p;
87         if(!str || (qstate->env->cfg->val_log_level < 2 &&
88                 !qstate->env->cfg->log_servfail)) {
89                 return;
90         }
91         p = (struct errinf_strlist*)regional_alloc(qstate->region, sizeof(*p));
92         if(!p) {
93                 log_err("malloc failure in validator-error-info string");
94                 return;
95         }
96         p->next = NULL;
97         p->str = regional_strdup(qstate->region, str);
98         p->reason_bogus = reason_bogus;
99         if(!p->str) {
100                 log_err("malloc failure in validator-error-info string");
101                 return;
102         }
103         /* add at end */
104         if(qstate->errinf) {
105                 struct errinf_strlist* q = qstate->errinf;
106                 while(q->next)
107                         q = q->next;
108                 q->next = p;
109         } else  qstate->errinf = p;
110 }
111
112 void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)
113 {
114         struct sock_list* p;
115         if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
116                 return;
117         for(p=origin; p; p=p->next) {
118                 char buf[256];
119                 if(p == origin)
120                         snprintf(buf, sizeof(buf), "from ");
121                 else    snprintf(buf, sizeof(buf), "and ");
122                 if(p->len == 0)
123                         snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), 
124                                 "cache");
125                 else 
126                         addr_to_str(&p->addr, p->len, buf+strlen(buf),
127                                 sizeof(buf)-strlen(buf));
128                 errinf(qstate, buf);
129         }
130 }
131
132 char* errinf_to_str_bogus(struct module_qstate* qstate)
133 {
134         char buf[20480];
135         char* p = buf;
136         size_t left = sizeof(buf);
137         struct errinf_strlist* s;
138         char dname[LDNS_MAX_DOMAINLEN+1];
139         char t[16], c[16];
140         sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
141         sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
142         dname_str(qstate->qinfo.qname, dname);
143         snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c);
144         left -= strlen(p); p += strlen(p);
145         if(!qstate->errinf)
146                 snprintf(p, left, " misc failure");
147         else for(s=qstate->errinf; s; s=s->next) {
148                 snprintf(p, left, " %s", s->str);
149                 left -= strlen(p); p += strlen(p);
150         }
151         p = strdup(buf);
152         if(!p)
153                 log_err("malloc failure in errinf_to_str");
154         return p;
155 }
156
157 /* Try to find the latest (most specific) dnssec failure */
158 sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate)
159 {
160         struct errinf_strlist* s;
161         sldns_ede_code ede = LDNS_EDE_NONE;
162         for(s=qstate->errinf; s; s=s->next) {
163                 if(s->reason_bogus == LDNS_EDE_NONE) continue;
164                 if(ede != LDNS_EDE_NONE
165                         && ede != LDNS_EDE_DNSSEC_BOGUS
166                         && s->reason_bogus == LDNS_EDE_DNSSEC_BOGUS) continue;
167                 ede = s->reason_bogus;
168         }
169         return ede;
170 }
171
172 char* errinf_to_str_servfail(struct module_qstate* qstate)
173 {
174         char buf[20480];
175         char* p = buf;
176         size_t left = sizeof(buf);
177         struct errinf_strlist* s;
178         char dname[LDNS_MAX_DOMAINLEN+1];
179         char t[16], c[16];
180         sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
181         sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
182         dname_str(qstate->qinfo.qname, dname);
183         snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c);
184         left -= strlen(p); p += strlen(p);
185         if(!qstate->errinf)
186                 snprintf(p, left, " misc failure");
187         else for(s=qstate->errinf; s; s=s->next) {
188                 snprintf(p, left, " %s", s->str);
189                 left -= strlen(p); p += strlen(p);
190         }
191         p = strdup(buf);
192         if(!p)
193                 log_err("malloc failure in errinf_to_str");
194         return p;
195 }
196
197 char* errinf_to_str_misc(struct module_qstate* qstate)
198 {
199         char buf[20480];
200         char* p = buf;
201         size_t left = sizeof(buf);
202         struct errinf_strlist* s;
203         if(!qstate->errinf)
204                 snprintf(p, left, "misc failure");
205         else for(s=qstate->errinf; s; s=s->next) {
206                 snprintf(p, left, "%s%s", (s==qstate->errinf?"":" "), s->str);
207                 left -= strlen(p); p += strlen(p);
208         }
209         p = strdup(buf);
210         if(!p)
211                 log_err("malloc failure in errinf_to_str");
212         return p;
213 }
214
215 void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
216 {
217         char buf[1024];
218         char dname[LDNS_MAX_DOMAINLEN+1];
219         char t[16], c[16];
220         if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !rr)
221                 return;
222         sldns_wire2str_type_buf(ntohs(rr->rk.type), t, sizeof(t));
223         sldns_wire2str_class_buf(ntohs(rr->rk.rrset_class), c, sizeof(c));
224         dname_str(rr->rk.dname, dname);
225         snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c);
226         errinf(qstate, buf);
227 }
228
229 void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname)
230 {
231         char b[1024];
232         char buf[LDNS_MAX_DOMAINLEN+1];
233         if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str || !dname)
234                 return;
235         dname_str(dname, buf);
236         snprintf(b, sizeof(b), "%s %s", str, buf);
237         errinf(qstate, b);
238 }
239
240 int
241 edns_known_options_init(struct module_env* env)
242 {
243         env->edns_known_options_num = 0;
244         env->edns_known_options = (struct edns_known_option*)calloc(
245                 MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option));
246         if(!env->edns_known_options) return 0;
247         return 1;
248 }
249
250 void
251 edns_known_options_delete(struct module_env* env)
252 {
253         free(env->edns_known_options);
254         env->edns_known_options = NULL;
255         env->edns_known_options_num = 0;
256 }
257
258 int
259 edns_register_option(uint16_t opt_code, int bypass_cache_stage,
260         int no_aggregation, struct module_env* env)
261 {
262         size_t i;
263         if(env->worker) {
264                 log_err("invalid edns registration: "
265                         "trying to register option after module init phase");
266                 return 0;
267         }
268
269         /**
270          * Checking if we are full first is faster but it does not provide
271          * the option to change the flags when the array is full.
272          * It only impacts unbound initialization, leave it for now.
273          */
274         /* Check if the option is already registered. */
275         for(i=0; i<env->edns_known_options_num; i++)
276                 if(env->edns_known_options[i].opt_code == opt_code)
277                         break;
278         /* If it is not yet registered check if we have space to add a new one. */
279         if(i == env->edns_known_options_num) {
280                 if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) {
281                         log_err("invalid edns registration: maximum options reached");
282                         return 0;
283                 }
284                 env->edns_known_options_num++;
285         }
286         env->edns_known_options[i].opt_code = opt_code;
287         env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage;
288         env->edns_known_options[i].no_aggregation = no_aggregation;
289         return 1;
290 }
291
292 int
293 inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
294         struct module_env* env, int id)
295 {
296         struct inplace_cb* callback;
297         struct inplace_cb** prevp;
298         if(env->worker) {
299                 log_err("invalid edns callback registration: "
300                         "trying to register callback after module init phase");
301                 return 0;
302         }
303
304         callback = (struct inplace_cb*)calloc(1, sizeof(*callback));
305         if(callback == NULL) {
306                 log_err("out of memory during edns callback registration.");
307                 return 0;
308         }
309         callback->id = id;
310         callback->next = NULL;
311         callback->cb = cb;
312         callback->cb_arg = cbarg;
313         
314         prevp = (struct inplace_cb**) &env->inplace_cb_lists[type];
315         /* append at end of list */
316         while(*prevp != NULL)
317                 prevp = &((*prevp)->next);
318         *prevp = callback;
319         return 1;
320 }
321
322 void
323 inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
324         int id)
325 {
326         struct inplace_cb* temp = env->inplace_cb_lists[type];
327         struct inplace_cb* prev = NULL;
328
329         while(temp) {
330                 if(temp->id == id) {
331                         if(!prev) {
332                                 env->inplace_cb_lists[type] = temp->next;
333                                 free(temp);
334                                 temp = env->inplace_cb_lists[type];
335                         }
336                         else {
337                                 prev->next = temp->next;
338                                 free(temp);
339                                 temp = prev->next;
340                         }
341                 }
342                 else {
343                         prev = temp;
344                         temp = temp->next;
345                 }
346         }
347 }
348
349 struct edns_known_option*
350 edns_option_is_known(uint16_t opt_code, struct module_env* env)
351 {
352         size_t i;
353         for(i=0; i<env->edns_known_options_num; i++)
354                 if(env->edns_known_options[i].opt_code == opt_code)
355                         return env->edns_known_options + i;
356         return NULL;
357 }
358
359 int
360 edns_bypass_cache_stage(struct edns_option* list, struct module_env* env)
361 {
362         size_t i;
363         for(; list; list=list->next)
364                 for(i=0; i<env->edns_known_options_num; i++)
365                         if(env->edns_known_options[i].opt_code == list->opt_code &&
366                                 env->edns_known_options[i].bypass_cache_stage == 1)
367                                         return 1;
368         return 0;
369 }
370
371 int
372 unique_mesh_state(struct edns_option* list, struct module_env* env)
373 {
374         size_t i;
375         if(env->unique_mesh)
376                 return 1;
377         for(; list; list=list->next)
378                 for(i=0; i<env->edns_known_options_num; i++)
379                         if(env->edns_known_options[i].opt_code == list->opt_code &&
380                                 env->edns_known_options[i].no_aggregation == 1)
381                                         return 1;
382         return 0;
383 }
384
385 void
386 log_edns_known_options(enum verbosity_value level, struct module_env* env)
387 {
388         size_t i;
389         char str[32], *s;
390         size_t slen;
391         if(env->edns_known_options_num > 0 && verbosity >= level) {
392                 verbose(level, "EDNS known options:");
393                 verbose(level, "  Code:    Bypass_cache_stage: Aggregate_mesh:");
394                 for(i=0; i<env->edns_known_options_num; i++) {
395                         s = str;
396                         slen = sizeof(str);
397                         (void)sldns_wire2str_edns_option_code_print(&s, &slen,
398                                 env->edns_known_options[i].opt_code);
399                         verbose(level, "  %-8.8s %-19s %-15s", str,
400                                 env->edns_known_options[i].bypass_cache_stage?"YES":"NO",
401                                 env->edns_known_options[i].no_aggregation?"NO":"YES");
402                 }
403         }
404 }
405
406 void
407 copy_state_to_super(struct module_qstate* qstate, int ATTR_UNUSED(id),
408         struct module_qstate* super)
409 {
410         /* Overwrite super's was_ratelimited only when it was not set */
411         if(!super->was_ratelimited) {
412                 super->was_ratelimited = qstate->was_ratelimited;
413         }
414 }