Coverage Report

Created: 2025-11-24 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/unbound/util/data/msgreply.c
Line
Count
Source
1
/*
2
 * util/data/msgreply.c - store message and reply data. 
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
/**
37
 * \file
38
 *
39
 * This file contains a data structure to store a message and its reply.
40
 */
41
42
#include "config.h"
43
#include "util/data/msgreply.h"
44
#include "util/storage/lookup3.h"
45
#include "util/log.h"
46
#include "util/alloc.h"
47
#include "util/netevent.h"
48
#include "util/net_help.h"
49
#include "util/data/dname.h"
50
#include "util/regional.h"
51
#include "util/data/msgparse.h"
52
#include "util/data/msgencode.h"
53
#include "sldns/sbuffer.h"
54
#include "sldns/wire2str.h"
55
#include "util/module.h"
56
#include "util/fptr_wlist.h"
57
58
/** MAX TTL default for messages and rrsets */
59
time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
60
/** MIN TTL default for messages and rrsets */
61
time_t MIN_TTL = 0;
62
/** MAX Negative TTL, for SOA records in authority section */
63
time_t MAX_NEG_TTL = 3600; /* one hour */
64
/** MIN Negative TTL, for SOA records in authority section */
65
time_t MIN_NEG_TTL = 0;
66
/** If we serve expired entries and prefetch them */
67
int SERVE_EXPIRED = 0;
68
/** Time to serve records after expiration */
69
time_t SERVE_EXPIRED_TTL = 86400;
70
/** Reset serve expired TTL after failed update attempt */
71
time_t SERVE_EXPIRED_TTL_RESET = 0;
72
/** TTL to use for expired records */
73
time_t SERVE_EXPIRED_REPLY_TTL = 30;
74
/** If we serve the original TTL or decrementing TTLs */
75
int SERVE_ORIGINAL_TTL = 0;
76
77
/** allocate qinfo, return 0 on error */
78
static int
79
parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg, 
80
  struct query_info* qinf, struct regional* region)
81
0
{
82
0
  if(msg->qname) {
83
0
    if(region)
84
0
      qinf->qname = (uint8_t*)regional_alloc(region, 
85
0
        msg->qname_len);
86
0
    else  qinf->qname = (uint8_t*)malloc(msg->qname_len);
87
0
    if(!qinf->qname) return 0;
88
0
    dname_pkt_copy(pkt, qinf->qname, msg->qname);
89
0
  } else qinf->qname = 0;
90
0
  qinf->qname_len = msg->qname_len;
91
0
  qinf->qtype = msg->qtype;
92
0
  qinf->qclass = msg->qclass;
93
0
  qinf->local_alias = NULL;
94
0
  return 1;
95
0
}
96
97
/** constructor for replyinfo */
98
struct reply_info*
99
construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd,
100
  time_t ttl, time_t prettl, time_t expttl, time_t norecttl, size_t an,
101
  size_t ns, size_t ar, size_t total, enum sec_status sec,
102
  sldns_ede_code reason_bogus)
103
0
{
104
0
  struct reply_info* rep;
105
  /* rrset_count-1 because the first ref is part of the struct. */
106
0
  size_t s = sizeof(struct reply_info) - sizeof(struct rrset_ref) +
107
0
    sizeof(struct ub_packed_rrset_key*) * total;
108
0
  if(total >= RR_COUNT_MAX) return NULL; /* sanity check on numRRS*/
109
0
  if(region)
110
0
    rep = (struct reply_info*)regional_alloc(region, s);
111
0
  else  rep = (struct reply_info*)malloc(s + 
112
0
      sizeof(struct rrset_ref) * (total));
113
0
  if(!rep) 
114
0
    return NULL;
115
0
  rep->flags = flags;
116
0
  rep->qdcount = qd;
117
0
  rep->ttl = ttl;
118
0
  rep->prefetch_ttl = prettl;
119
0
  rep->serve_expired_ttl = expttl;
120
0
  rep->serve_expired_norec_ttl = norecttl;
121
0
  rep->an_numrrsets = an;
122
0
  rep->ns_numrrsets = ns;
123
0
  rep->ar_numrrsets = ar;
124
0
  rep->rrset_count = total;
125
0
  rep->security = sec;
126
0
  rep->reason_bogus = reason_bogus;
127
  /* this is only allocated and used for caching on copy */
128
0
  rep->reason_bogus_str = NULL;
129
0
  rep->authoritative = 0;
130
  /* array starts after the refs */
131
0
  if(region)
132
0
    rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[0]);
133
0
  else  rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[total]);
134
  /* zero the arrays to assist cleanup in case of malloc failure */
135
0
  memset( rep->rrsets, 0, sizeof(struct ub_packed_rrset_key*) * total);
136
0
  if(!region)
137
0
    memset( &rep->ref[0], 0, sizeof(struct rrset_ref) * total);
138
0
  return rep;
139
0
}
140
141
/** allocate replyinfo, return 0 on error */
142
static int
143
parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep,
144
  struct regional* region)
145
0
{
146
0
  *rep = construct_reply_info_base(region, msg->flags, msg->qdcount, 0,
147
0
    0, 0, 0, msg->an_rrsets, msg->ns_rrsets, msg->ar_rrsets,
148
0
    msg->rrset_count, sec_status_unchecked, LDNS_EDE_NONE);
149
0
  if(!*rep)
150
0
    return 0;
151
0
  return 1;
152
0
}
153
154
int
155
reply_info_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc,
156
  struct regional* region)
157
0
{
158
0
  size_t i;
159
0
  for(i=0; i<rep->rrset_count; i++) {
160
0
    if(region) {
161
0
      rep->rrsets[i] = (struct ub_packed_rrset_key*)
162
0
        regional_alloc(region, 
163
0
        sizeof(struct ub_packed_rrset_key));
164
0
      if(rep->rrsets[i]) {
165
0
        memset(rep->rrsets[i], 0, 
166
0
          sizeof(struct ub_packed_rrset_key));
167
0
        rep->rrsets[i]->entry.key = rep->rrsets[i];
168
0
      }
169
0
    }
170
0
    else  rep->rrsets[i] = alloc_special_obtain(alloc);
171
0
    if(!rep->rrsets[i])
172
0
      return 0;
173
0
    rep->rrsets[i]->entry.data = NULL;
174
0
  }
175
0
  return 1;
176
0
}
177
178
int
179
reply_info_can_answer_expired(struct reply_info* rep, time_t timenow)
180
0
{
181
0
  log_assert(TTL_IS_EXPIRED(rep->ttl, timenow));
182
  /* Really expired */
183
0
  if(SERVE_EXPIRED_TTL && TTL_IS_EXPIRED(rep->serve_expired_ttl, timenow)) return 0;
184
  /* Ignore expired failure answers */
185
0
  if(FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR &&
186
0
    FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NXDOMAIN &&
187
0
    FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_YXDOMAIN) return 0;
188
0
  return 1;
189
0
}
190
191
int
192
reply_info_could_use_expired(struct reply_info* rep, time_t timenow)
193
0
{
194
0
  log_assert(TTL_IS_EXPIRED(rep->ttl, timenow));
195
  /* Really expired */
196
0
  if(SERVE_EXPIRED_TTL && TTL_IS_EXPIRED(rep->serve_expired_ttl, timenow)
197
0
    && !SERVE_EXPIRED_TTL_RESET) return 0;
198
  /* Ignore expired failure answers */
199
0
  if(FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR &&
200
0
    FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NXDOMAIN &&
201
0
    FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_YXDOMAIN) return 0;
202
0
  return 1;
203
0
}
204
205
struct reply_info *
206
make_new_reply_info(const struct reply_info* rep, struct regional* region,
207
  size_t an_numrrsets, size_t copy_rrsets)
208
0
{
209
0
  struct reply_info* new_rep;
210
0
  size_t i;
211
212
  /* create a base struct.  we specify 'insecure' security status as
213
   * the modified response won't be DNSSEC-valid.  In our faked response
214
   * the authority and additional sections will be empty (except possible
215
   * EDNS0 OPT RR in the additional section appended on sending it out),
216
   * so the total number of RRsets is an_numrrsets. */
217
0
  new_rep = construct_reply_info_base(region, rep->flags,
218
0
    rep->qdcount, rep->ttl, rep->prefetch_ttl,
219
0
    rep->serve_expired_ttl, rep->serve_expired_norec_ttl,
220
0
    an_numrrsets, 0, 0, an_numrrsets,
221
0
    sec_status_insecure, LDNS_EDE_NONE);
222
0
  if(!new_rep)
223
0
    return NULL;
224
0
  if(!reply_info_alloc_rrset_keys(new_rep, NULL, region))
225
0
    return NULL;
226
0
  for(i=0; i<copy_rrsets; i++)
227
0
    new_rep->rrsets[i] = rep->rrsets[i];
228
229
0
  return new_rep;
230
0
}
231
232
/** find the minimumttl in the rdata of SOA record */
233
static uint32_t
234
soa_find_minttl(struct rr_parse* rr)
235
0
{
236
0
  uint16_t rlen = sldns_read_uint16(rr->ttl_data+4);
237
0
  if(rlen < 20)
238
0
    return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */
239
  /* minimum TTL is the last 32bit value in the rdata of the record */
240
  /* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/
241
0
  return sldns_read_uint32(rr->ttl_data+6+rlen-4);
242
0
}
243
244
/** do the rdata copy */
245
static int
246
rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, 
247
  struct rr_parse* rr, time_t* rr_ttl, uint16_t type,
248
  sldns_pkt_section section)
249
131k
{
250
131k
  uint16_t pkt_len;
251
131k
  uint32_t ttl;
252
131k
  const sldns_rr_descriptor* desc;
253
254
131k
  ttl = sldns_read_uint32(rr->ttl_data);
255
  /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */
256
  /* RFC 8767 Section 4. values with high-order bit as positive, not 0.
257
+  *  As such, it will be capped by MAX_TTL below. */
258
131k
  if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) {
259
    /* negative response. see if TTL of SOA record larger than the
260
     * minimum-ttl in the rdata of the SOA record */
261
0
    if(ttl > soa_find_minttl(rr)) ttl = soa_find_minttl(rr);
262
0
    if(!SERVE_ORIGINAL_TTL) {
263
      /* If MIN_NEG_TTL is configured skip setting MIN_TTL */
264
0
      if(MIN_NEG_TTL <= 0 && ttl < MIN_TTL) {
265
0
        ttl = MIN_TTL;
266
0
      }
267
0
      if(ttl > MAX_TTL) ttl = MAX_TTL;
268
0
    }
269
    /* MAX_NEG_TTL overrides the min and max ttl of everything
270
     * else; it is for a more specific record */
271
0
    if(ttl > MAX_NEG_TTL) ttl = MAX_NEG_TTL;
272
    /* MIN_NEG_TTL overrides the min and max ttl of everything
273
     * else if configured; it is for a more specific record */
274
0
    if(MIN_NEG_TTL > 0 && ttl < MIN_NEG_TTL) {
275
0
      ttl = MIN_NEG_TTL;
276
0
    }
277
131k
  } else if(!SERVE_ORIGINAL_TTL) {
278
131k
    if(ttl < MIN_TTL) ttl = MIN_TTL;
279
131k
    if(ttl > MAX_TTL) ttl = MAX_TTL;
280
131k
  }
281
131k
  if(ttl < data->ttl)
282
2.15k
    data->ttl = ttl;
283
  /* We have concluded the TTL checks */
284
131k
  *rr_ttl = (time_t)ttl;
285
286
131k
  if(rr->outside_packet) {
287
    /* uncompressed already, only needs copy */
288
0
    memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size);
289
0
    return 1;
290
0
  }
291
292
131k
  sldns_buffer_set_position(pkt, (size_t)
293
131k
    (rr->ttl_data - sldns_buffer_begin(pkt) + sizeof(uint32_t)));
294
  /* insert decompressed size into rdata len stored in memory */
295
  /* -2 because rdatalen bytes are not included. */
296
131k
  pkt_len = htons(rr->size - 2);
297
131k
  memmove(to, &pkt_len, sizeof(uint16_t));
298
131k
  to += 2;
299
  /* read packet rdata len */
300
131k
  pkt_len = sldns_buffer_read_u16(pkt);
301
131k
  if(sldns_buffer_remaining(pkt) < pkt_len)
302
0
    return 0;
303
131k
  desc = sldns_rr_descript(type);
304
131k
  if(pkt_len > 0 && desc && desc->_dname_count > 0) {
305
4.59k
    int count = (int)desc->_dname_count;
306
4.59k
    int rdf = 0;
307
4.59k
    size_t len;
308
4.59k
    size_t oldpos;
309
    /* decompress dnames. */
310
41.3k
    while(pkt_len > 0 && count) {
311
36.7k
      switch(desc->_wireformat[rdf]) {
312
4.59k
      case LDNS_RDF_TYPE_DNAME:
313
4.59k
        oldpos = sldns_buffer_position(pkt);
314
4.59k
        dname_pkt_copy(pkt, to, 
315
4.59k
          sldns_buffer_current(pkt));
316
4.59k
        to += pkt_dname_len(pkt);
317
4.59k
        pkt_len -= sldns_buffer_position(pkt)-oldpos;
318
4.59k
        count--;
319
4.59k
        len = 0;
320
4.59k
        break;
321
0
      case LDNS_RDF_TYPE_STR:
322
0
        len = sldns_buffer_current(pkt)[0] + 1;
323
0
        break;
324
32.1k
      default:
325
32.1k
        len = get_rdf_size(desc->_wireformat[rdf]);
326
32.1k
        break;
327
36.7k
      }
328
36.7k
      if(len) {
329
32.1k
        log_assert(len <= pkt_len);
330
32.1k
        memmove(to, sldns_buffer_current(pkt), len);
331
32.1k
        to += len;
332
32.1k
        sldns_buffer_skip(pkt, (ssize_t)len);
333
32.1k
        pkt_len -= len;
334
32.1k
      }
335
36.7k
      rdf++;
336
36.7k
    }
337
4.59k
  }
338
  /* copy remaining rdata */
339
131k
  if(pkt_len >  0)
340
127k
    memmove(to, sldns_buffer_current(pkt), pkt_len);
341
  
342
131k
  return 1;
343
131k
}
344
345
/** copy over the data into packed rrset */
346
static int
347
parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset, 
348
  struct packed_rrset_data* data)
349
9.46k
{
350
9.46k
  size_t i;
351
9.46k
  struct rr_parse* rr = pset->rr_first;
352
9.46k
  uint8_t* nextrdata;
353
9.46k
  size_t total = pset->rr_count + pset->rrsig_count;
354
9.46k
  data->ttl = MAX_TTL;
355
9.46k
  data->count = pset->rr_count;
356
9.46k
  data->rrsig_count = pset->rrsig_count;
357
9.46k
  data->trust = rrset_trust_none;
358
9.46k
  data->security = sec_status_unchecked;
359
  /* layout: struct - rr_len - rr_data - rr_ttl - rdata - rrsig */
360
9.46k
  data->rr_len = (size_t*)((uint8_t*)data + 
361
9.46k
    sizeof(struct packed_rrset_data));
362
9.46k
  data->rr_data = (uint8_t**)&(data->rr_len[total]);
363
9.46k
  data->rr_ttl = (time_t*)&(data->rr_data[total]);
364
9.46k
  nextrdata = (uint8_t*)&(data->rr_ttl[total]);
365
136k
  for(i=0; i<data->count; i++) {
366
126k
    data->rr_len[i] = rr->size;
367
126k
    data->rr_data[i] = nextrdata;
368
126k
    nextrdata += rr->size;
369
126k
    if(!rdata_copy(pkt, data, data->rr_data[i], rr, 
370
126k
      &data->rr_ttl[i], pset->type, pset->section))
371
0
      return 0;
372
126k
    rr = rr->next;
373
126k
  }
374
  /* if rrsig, its rdata is at nextrdata */
375
9.46k
  rr = pset->rrsig_first;
376
14.0k
  for(i=data->count; i<total; i++) {
377
4.59k
    data->rr_len[i] = rr->size;
378
4.59k
    data->rr_data[i] = nextrdata;
379
4.59k
    nextrdata += rr->size;
380
4.59k
    if(!rdata_copy(pkt, data, data->rr_data[i], rr, 
381
4.59k
      &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG, pset->section))
382
0
      return 0;
383
4.59k
    rr = rr->next;
384
4.59k
  }
385
9.46k
  return 1;
386
9.46k
}
387
388
/** create rrset return 0 on failure */
389
static int
390
parse_create_rrset(sldns_buffer* pkt, struct rrset_parse* pset,
391
  struct packed_rrset_data** data, struct regional* region)
392
9.46k
{
393
  /* allocate */
394
9.46k
  size_t s;
395
9.46k
  if(pset->rr_count > RR_COUNT_MAX || pset->rrsig_count > RR_COUNT_MAX ||
396
9.46k
    pset->size > RR_COUNT_MAX)
397
0
    return 0; /* protect against integer overflow */
398
9.46k
  s = sizeof(struct packed_rrset_data) + 
399
9.46k
    (pset->rr_count + pset->rrsig_count) * 
400
9.46k
    (sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t)) + 
401
9.46k
    pset->size;
402
9.46k
  if(region)
403
0
    *data = regional_alloc_zero(region, s);
404
9.46k
  else  *data = calloc(1, s);
405
9.46k
  if(!*data)
406
0
    return 0;
407
  /* copy & decompress */
408
9.46k
  if(!parse_rr_copy(pkt, pset, *data)) {
409
0
    if(!region) {
410
0
      free(*data);
411
0
      *data = NULL;
412
0
    }
413
0
    return 0;
414
0
  }
415
9.46k
  return 1;
416
9.46k
}
417
418
/** get trust value for rrset */
419
static enum rrset_trust
420
get_rrset_trust(struct msg_parse* msg, struct rrset_parse* rrset)
421
9.46k
{
422
9.46k
  uint16_t AA = msg->flags & BIT_AA;
423
9.46k
  if(rrset->section == LDNS_SECTION_ANSWER) {
424
0
    if(AA) {
425
      /* RFC2181 says remainder of CNAME chain is nonauth*/
426
0
      if(msg->rrset_first && 
427
0
        msg->rrset_first->section==LDNS_SECTION_ANSWER
428
0
        && msg->rrset_first->type==LDNS_RR_TYPE_CNAME){
429
0
        if(rrset == msg->rrset_first)
430
0
          return rrset_trust_ans_AA;
431
0
        else  return rrset_trust_ans_noAA;
432
0
      }
433
0
      if(msg->rrset_first && 
434
0
        msg->rrset_first->section==LDNS_SECTION_ANSWER
435
0
        && msg->rrset_first->type==LDNS_RR_TYPE_DNAME){
436
0
        if(rrset == msg->rrset_first ||
437
0
           rrset == msg->rrset_first->rrset_all_next)
438
0
          return rrset_trust_ans_AA;
439
0
        else  return rrset_trust_ans_noAA;
440
0
      }
441
0
      return rrset_trust_ans_AA;
442
0
    }
443
0
    else  return rrset_trust_ans_noAA;
444
9.46k
  } else if(rrset->section == LDNS_SECTION_AUTHORITY) {
445
5.82k
    if(AA)  return rrset_trust_auth_AA;
446
3.99k
    else  return rrset_trust_auth_noAA;
447
5.82k
  } else {
448
    /* addit section */
449
3.63k
    if(AA)  return rrset_trust_add_AA;
450
1.97k
    else  return rrset_trust_add_noAA;
451
3.63k
  }
452
  /* NOTREACHED */
453
0
  return rrset_trust_none;
454
9.46k
}
455
456
int
457
parse_copy_decompress_rrset(sldns_buffer* pkt, struct msg_parse* msg,
458
  struct rrset_parse *pset, struct regional* region, 
459
  struct ub_packed_rrset_key* pk)
460
9.46k
{
461
9.46k
  struct packed_rrset_data* data;
462
9.46k
  pk->rk.flags = pset->flags;
463
9.46k
  pk->rk.dname_len = pset->dname_len;
464
9.46k
  if(region)
465
0
    pk->rk.dname = (uint8_t*)regional_alloc(
466
0
      region, pset->dname_len);
467
9.46k
  else  pk->rk.dname = 
468
9.46k
      (uint8_t*)malloc(pset->dname_len);
469
9.46k
  if(!pk->rk.dname)
470
0
    return 0;
471
  /** copy & decompress dname */
472
9.46k
  dname_pkt_copy(pkt, pk->rk.dname, pset->dname);
473
  /** copy over type and class */
474
9.46k
  pk->rk.type = htons(pset->type);
475
9.46k
  pk->rk.rrset_class = pset->rrset_class;
476
  /** read data part. */
477
9.46k
  if(!parse_create_rrset(pkt, pset, &data, region)) {
478
0
    if(!region) {
479
0
      free(pk->rk.dname);
480
0
      pk->rk.dname = NULL;
481
0
    }
482
0
    return 0;
483
0
  }
484
9.46k
  pk->entry.data = (void*)data;
485
9.46k
  pk->entry.key = (void*)pk;
486
9.46k
  pk->entry.hash = pset->hash;
487
9.46k
  data->trust = get_rrset_trust(msg, pset);
488
9.46k
  pk->rk.flags |= (data->ttl == 0) ? PACKED_RRSET_UPSTREAM_0TTL : 0;
489
9.46k
  return 1;
490
9.46k
}
491
492
/** 
493
 * Copy and decompress rrs
494
 * @param pkt: the packet for compression pointer resolution.
495
 * @param msg: the parsed message
496
 * @param rep: reply info to put rrs into.
497
 * @param region: if not NULL, used for allocation.
498
 * @return 0 on failure.
499
 */
500
static int
501
parse_copy_decompress(sldns_buffer* pkt, struct msg_parse* msg,
502
  struct reply_info* rep, struct regional* region)
503
0
{
504
0
  size_t i;
505
0
  struct rrset_parse *pset = msg->rrset_first;
506
0
  struct packed_rrset_data* data;
507
0
  log_assert(rep);
508
0
  rep->ttl = MAX_TTL;
509
0
  rep->security = sec_status_unchecked;
510
0
  if(rep->rrset_count == 0)
511
0
    rep->ttl = NORR_TTL;
512
513
0
  for(i=0; i<rep->rrset_count; i++) {
514
0
    if(!parse_copy_decompress_rrset(pkt, msg, pset, region,
515
0
      rep->rrsets[i]))
516
0
      return 0;
517
0
    data = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
518
0
    if(data->ttl < rep->ttl)
519
0
      rep->ttl = data->ttl;
520
521
0
    pset = pset->rrset_all_next;
522
0
  }
523
0
  rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl);
524
0
  rep->serve_expired_ttl = rep->ttl + SERVE_EXPIRED_TTL;
525
  /* rep->serve_expired_norec_ttl should stay at 0 */
526
0
  log_assert(rep->serve_expired_norec_ttl == 0);
527
0
  return 1;
528
0
}
529
530
int 
531
parse_create_msg(sldns_buffer* pkt, struct msg_parse* msg,
532
  struct alloc_cache* alloc, struct query_info* qinf, 
533
  struct reply_info** rep, struct regional* region)
534
0
{
535
0
  log_assert(pkt && msg);
536
0
  if(!parse_create_qinfo(pkt, msg, qinf, region))
537
0
    return 0;
538
0
  if(!parse_create_repinfo(msg, rep, region))
539
0
    return 0;
540
0
  if(!reply_info_alloc_rrset_keys(*rep, alloc, region)) {
541
0
    if(!region) reply_info_parsedelete(*rep, alloc);
542
0
    return 0;
543
0
  }
544
0
  if(!parse_copy_decompress(pkt, msg, *rep, region)) {
545
0
    if(!region) reply_info_parsedelete(*rep, alloc);
546
0
    return 0;
547
0
  }
548
0
  return 1;
549
0
}
550
551
int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
552
        struct query_info* qinf, struct reply_info** rep, 
553
  struct regional* region, struct edns_data* edns)
554
0
{
555
  /* use scratch pad region-allocator during parsing. */
556
0
  struct msg_parse* msg;
557
0
  int ret;
558
  
559
0
  qinf->qname = NULL;
560
0
  qinf->local_alias = NULL;
561
0
  *rep = NULL;
562
0
  if(!(msg = regional_alloc(region, sizeof(*msg)))) {
563
0
    return LDNS_RCODE_SERVFAIL;
564
0
  }
565
0
  memset(msg, 0, sizeof(*msg));
566
  
567
0
  sldns_buffer_set_position(pkt, 0);
568
0
  if((ret = parse_packet(pkt, msg, region)) != 0) {
569
0
    return ret;
570
0
  }
571
0
  if((ret = parse_extract_edns_from_response_msg(msg, edns, region)) != 0)
572
0
    return ret;
573
574
  /* parse OK, allocate return structures */
575
  /* this also performs dname decompression */
576
0
  if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) {
577
0
    query_info_clear(qinf);
578
0
    *rep = NULL;
579
0
    return LDNS_RCODE_SERVFAIL;
580
0
  }
581
0
  return 0;
582
0
}
583
584
/** helper compare function to sort in lock order */
585
static int
586
reply_info_sortref_cmp(const void* a, const void* b)
587
0
{
588
0
  struct rrset_ref* x = (struct rrset_ref*)a;
589
0
  struct rrset_ref* y = (struct rrset_ref*)b;
590
0
  if(x->key < y->key) return -1;
591
0
  if(x->key > y->key) return 1;
592
0
  return 0;
593
0
}
594
595
void 
596
reply_info_sortref(struct reply_info* rep)
597
0
{
598
0
  qsort(&rep->ref[0], rep->rrset_count, sizeof(struct rrset_ref),
599
0
    reply_info_sortref_cmp);
600
0
}
601
602
void 
603
reply_info_set_ttls(struct reply_info* rep, time_t timenow)
604
0
{
605
0
  size_t i, j;
606
0
  rep->ttl += timenow;
607
0
  rep->prefetch_ttl += timenow;
608
0
  rep->serve_expired_ttl += timenow;
609
  /* Don't set rep->serve_expired_norec_ttl; this should only be set
610
   * on cached records when encountering an error */
611
0
  log_assert(rep->serve_expired_norec_ttl == 0);
612
0
  for(i=0; i<rep->rrset_count; i++) {
613
0
    struct packed_rrset_data* data = (struct packed_rrset_data*)
614
0
      rep->ref[i].key->entry.data;
615
0
    if(i>0 && rep->ref[i].key == rep->ref[i-1].key)
616
0
      continue;
617
0
    data->ttl += timenow;
618
0
    for(j=0; j<data->count + data->rrsig_count; j++) {
619
0
      data->rr_ttl[j] += timenow;
620
0
    }
621
0
    data->ttl_add = timenow;
622
0
  }
623
0
}
624
625
void
626
reply_info_absolute_ttls(struct reply_info* rep, time_t ttl, time_t ttl_add)
627
0
{
628
0
  size_t i, j;
629
0
  rep->ttl = ttl;
630
0
  rep->prefetch_ttl = PREFETCH_TTL_CALC(ttl);
631
0
  rep->serve_expired_ttl = ttl + SERVE_EXPIRED_TTL;
632
  /* Don't set rep->serve_expired_norec_ttl; this should only be set
633
   * on cached records when encountering an error */
634
0
  log_assert(rep->serve_expired_norec_ttl == 0);
635
0
  for(i=0; i<rep->rrset_count; i++) {
636
0
    struct packed_rrset_data* data = (struct packed_rrset_data*)
637
0
      rep->ref[i].key->entry.data;
638
0
    if(i>0 && rep->ref[i].key == rep->ref[i-1].key)
639
0
      continue;
640
0
    data->ttl = ttl;
641
0
    for(j=0; j<data->count + data->rrsig_count; j++) {
642
0
      data->rr_ttl[j] = ttl;
643
0
    }
644
0
    data->ttl_add = ttl_add;
645
0
  }
646
0
}
647
648
void 
649
reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc)
650
0
{
651
0
  size_t i;
652
0
  if(!rep) 
653
0
    return;
654
  /* no need to lock, since not shared in hashtables. */
655
0
  for(i=0; i<rep->rrset_count; i++) {
656
0
    ub_packed_rrset_parsedelete(rep->rrsets[i], alloc);
657
0
  }
658
0
  if(rep->reason_bogus_str) {
659
0
    free(rep->reason_bogus_str);
660
0
    rep->reason_bogus_str = NULL;
661
0
  }
662
0
  free(rep);
663
0
}
664
665
int 
666
query_info_parse(struct query_info* m, sldns_buffer* query)
667
0
{
668
0
  uint8_t* q = sldns_buffer_begin(query);
669
  /* minimum size: header + \0 + qtype + qclass */
670
0
  if(sldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5)
671
0
    return 0;
672
0
  if((LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY && LDNS_OPCODE_WIRE(q) !=
673
0
    LDNS_PACKET_NOTIFY) || LDNS_QDCOUNT(q) != 1 ||
674
0
    sldns_buffer_position(query) != 0)
675
0
    return 0;
676
0
  sldns_buffer_skip(query, LDNS_HEADER_SIZE);
677
0
  m->qname = sldns_buffer_current(query);
678
0
  if((m->qname_len = query_dname_len(query)) == 0)
679
0
    return 0; /* parse error */
680
0
  if(sldns_buffer_remaining(query) < 4)
681
0
    return 0; /* need qtype, qclass */
682
0
  m->qtype = sldns_buffer_read_u16(query);
683
0
  m->qclass = sldns_buffer_read_u16(query);
684
0
  m->local_alias = NULL;
685
0
  return 1;
686
0
}
687
688
/** tiny subroutine for msgreply_compare */
689
#define COMPARE_IT(x, y) \
690
0
  if( (x) < (y) ) return -1; \
691
0
  else if( (x) > (y) ) return +1; \
692
0
  log_assert( (x) == (y) );
693
694
int 
695
query_info_compare(void* m1, void* m2)
696
0
{
697
0
  struct query_info* msg1 = (struct query_info*)m1;
698
0
  struct query_info* msg2 = (struct query_info*)m2;
699
0
  int mc;
700
  /* from most different to least different for speed */
701
0
  COMPARE_IT(msg1->qtype, msg2->qtype);
702
0
  if((mc = query_dname_compare(msg1->qname, msg2->qname)) != 0)
703
0
    return mc;
704
0
  log_assert(msg1->qname_len == msg2->qname_len);
705
0
  COMPARE_IT(msg1->qclass, msg2->qclass);
706
0
  return 0;
707
0
#undef COMPARE_IT
708
0
}
709
710
void 
711
query_info_clear(struct query_info* m)
712
0
{
713
0
  free(m->qname);
714
0
  m->qname = NULL;
715
0
}
716
717
size_t 
718
msgreply_sizefunc(void* k, void* d)
719
0
{
720
0
  struct msgreply_entry* q = (struct msgreply_entry*)k;
721
0
  struct reply_info* r = (struct reply_info*)d;
722
0
  size_t s = sizeof(struct msgreply_entry) + sizeof(struct reply_info)
723
0
    + q->key.qname_len + lock_get_mem(&q->entry.lock)
724
0
    - sizeof(struct rrset_ref);
725
0
  s += r->rrset_count * sizeof(struct rrset_ref);
726
0
  s += r->rrset_count * sizeof(struct ub_packed_rrset_key*);
727
0
  return s;
728
0
}
729
730
void 
731
query_entry_delete(void *k, void* ATTR_UNUSED(arg))
732
0
{
733
0
  struct msgreply_entry* q = (struct msgreply_entry*)k;
734
0
  lock_rw_destroy(&q->entry.lock);
735
0
  query_info_clear(&q->key);
736
0
  free(q);
737
0
}
738
739
void 
740
reply_info_delete(void* d, void* ATTR_UNUSED(arg))
741
0
{
742
0
  struct reply_info* r = (struct reply_info*)d;
743
0
  if(r->reason_bogus_str) {
744
0
    free(r->reason_bogus_str);
745
0
    r->reason_bogus_str = NULL;
746
0
  }
747
0
  free(r);
748
0
}
749
750
hashvalue_type
751
query_info_hash(struct query_info *q, uint16_t flags)
752
0
{
753
0
  hashvalue_type h = 0xab;
754
0
  h = hashlittle(&q->qtype, sizeof(q->qtype), h);
755
0
  if(q->qtype == LDNS_RR_TYPE_AAAA && (flags&BIT_CD))
756
0
    h++;
757
0
  h = hashlittle(&q->qclass, sizeof(q->qclass), h);
758
0
  h = dname_query_hash(q->qname, h);
759
0
  return h;
760
0
}
761
762
struct msgreply_entry* 
763
query_info_entrysetup(struct query_info* q, struct reply_info* r, 
764
  hashvalue_type h)
765
0
{
766
0
  struct msgreply_entry* e = (struct msgreply_entry*)malloc( 
767
0
    sizeof(struct msgreply_entry));
768
0
  if(!e) return NULL;
769
0
  memcpy(&e->key, q, sizeof(*q));
770
0
  e->entry.hash = h;
771
0
  e->entry.key = e;
772
0
  e->entry.data = r;
773
0
  lock_rw_init(&e->entry.lock);
774
0
  lock_protect(&e->entry.lock, &e->key.qname, sizeof(e->key.qname));
775
0
  lock_protect(&e->entry.lock, &e->key.qname_len, sizeof(e->key.qname_len));
776
0
  lock_protect(&e->entry.lock, &e->key.qtype, sizeof(e->key.qtype));
777
0
  lock_protect(&e->entry.lock, &e->key.qclass, sizeof(e->key.qclass));
778
0
  lock_protect(&e->entry.lock, &e->key.local_alias, sizeof(e->key.local_alias));
779
0
  lock_protect(&e->entry.lock, &e->entry.hash, sizeof(e->entry.hash));
780
0
  lock_protect(&e->entry.lock, &e->entry.key, sizeof(e->entry.key));
781
0
  lock_protect(&e->entry.lock, &e->entry.data, sizeof(e->entry.data));
782
0
  lock_protect(&e->entry.lock, e->key.qname, e->key.qname_len);
783
0
  q->qname = NULL;
784
0
  return e;
785
0
}
786
787
/** copy rrsets from replyinfo to dest replyinfo */
788
static int
789
repinfo_copy_rrsets(struct reply_info* dest, struct reply_info* from, 
790
  struct regional* region)
791
0
{
792
0
  size_t i, s;
793
0
  struct packed_rrset_data* fd, *dd;
794
0
  struct ub_packed_rrset_key* fk, *dk;
795
0
  for(i=0; i<dest->rrset_count; i++) {
796
0
    fk = from->rrsets[i];
797
0
    dk = dest->rrsets[i];
798
0
    fd = (struct packed_rrset_data*)fk->entry.data;
799
0
    dk->entry.hash = fk->entry.hash;
800
0
    dk->rk = fk->rk;
801
0
    if(region) {
802
0
      dk->id = fk->id;
803
0
      dk->rk.dname = (uint8_t*)regional_alloc_init(region,
804
0
        fk->rk.dname, fk->rk.dname_len);
805
0
    } else 
806
0
      dk->rk.dname = (uint8_t*)memdup(fk->rk.dname, 
807
0
        fk->rk.dname_len);
808
0
    if(!dk->rk.dname)
809
0
      return 0;
810
0
    s = packed_rrset_sizeof(fd);
811
0
    if(region)
812
0
      dd = (struct packed_rrset_data*)regional_alloc_init(
813
0
        region, fd, s);
814
0
    else  dd = (struct packed_rrset_data*)memdup(fd, s);
815
0
    if(!dd) 
816
0
      return 0;
817
0
    packed_rrset_ptr_fixup(dd);
818
0
    dk->entry.data = (void*)dd;
819
0
  }
820
0
  return 1;
821
0
}
822
823
struct reply_info*
824
reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc,
825
  struct regional* region)
826
0
{
827
0
  struct reply_info* cp;
828
0
  cp = construct_reply_info_base(region, rep->flags, rep->qdcount,
829
0
    rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
830
0
    rep->serve_expired_norec_ttl,
831
0
    rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
832
0
    rep->rrset_count, rep->security, rep->reason_bogus);
833
0
  if(!cp)
834
0
    return NULL;
835
836
0
  if(rep->reason_bogus_str && *rep->reason_bogus_str != 0) {
837
0
    if(region) {
838
0
      cp->reason_bogus_str = (char*)regional_alloc(region,
839
0
        sizeof(char)
840
0
        * (strlen(rep->reason_bogus_str)+1));
841
0
    } else {
842
0
      cp->reason_bogus_str = malloc(sizeof(char)
843
0
        * (strlen(rep->reason_bogus_str)+1));
844
0
    }
845
0
    if(!cp->reason_bogus_str) {
846
0
      if(!region)
847
0
        reply_info_parsedelete(cp, alloc);
848
0
      return NULL;
849
0
    }
850
0
    memcpy(cp->reason_bogus_str, rep->reason_bogus_str,
851
0
      strlen(rep->reason_bogus_str)+1);
852
0
  }
853
854
  /* allocate ub_key structures special or not */
855
0
  if(!reply_info_alloc_rrset_keys(cp, alloc, region)) {
856
0
    if(!region)
857
0
      reply_info_parsedelete(cp, alloc);
858
0
    return NULL;
859
0
  }
860
0
  if(!repinfo_copy_rrsets(cp, rep, region)) {
861
0
    if(!region)
862
0
      reply_info_parsedelete(cp, alloc);
863
0
    return NULL;
864
0
  }
865
0
  return cp;
866
0
}
867
868
uint8_t* 
869
reply_find_final_cname_target(struct query_info* qinfo, struct reply_info* rep)
870
0
{
871
0
  uint8_t* sname = qinfo->qname;
872
0
  size_t snamelen = qinfo->qname_len;
873
0
  size_t i;
874
0
  for(i=0; i<rep->an_numrrsets; i++) {
875
0
    struct ub_packed_rrset_key* s = rep->rrsets[i];
876
    /* follow CNAME chain (if any) */
877
0
    if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && 
878
0
      ntohs(s->rk.rrset_class) == qinfo->qclass && 
879
0
      snamelen == s->rk.dname_len &&
880
0
      query_dname_compare(sname, s->rk.dname) == 0) {
881
0
      get_cname_target(s, &sname, &snamelen);
882
0
    }
883
0
  }
884
0
  if(sname != qinfo->qname)
885
0
    return sname;
886
0
  return NULL;
887
0
}
888
889
struct ub_packed_rrset_key* 
890
reply_find_answer_rrset(struct query_info* qinfo, struct reply_info* rep)
891
0
{
892
0
  uint8_t* sname = qinfo->qname;
893
0
  size_t snamelen = qinfo->qname_len;
894
0
  size_t i;
895
0
  for(i=0; i<rep->an_numrrsets; i++) {
896
0
    struct ub_packed_rrset_key* s = rep->rrsets[i];
897
    /* first match type, for query of qtype cname */
898
0
    if(ntohs(s->rk.type) == qinfo->qtype && 
899
0
      ntohs(s->rk.rrset_class) == qinfo->qclass && 
900
0
      snamelen == s->rk.dname_len &&
901
0
      query_dname_compare(sname, s->rk.dname) == 0) {
902
0
      return s;
903
0
    }
904
    /* follow CNAME chain (if any) */
905
0
    if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && 
906
0
      ntohs(s->rk.rrset_class) == qinfo->qclass && 
907
0
      snamelen == s->rk.dname_len &&
908
0
      query_dname_compare(sname, s->rk.dname) == 0) {
909
0
      get_cname_target(s, &sname, &snamelen);
910
0
    }
911
0
  }
912
0
  return NULL;
913
0
}
914
915
struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep,
916
  uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
917
0
{
918
0
  size_t i;
919
0
  for(i=0; i<rep->an_numrrsets; i++) {
920
0
    struct ub_packed_rrset_key* s = rep->rrsets[i];
921
0
    if(ntohs(s->rk.type) == type && 
922
0
      ntohs(s->rk.rrset_class) == dclass && 
923
0
      namelen == s->rk.dname_len &&
924
0
      query_dname_compare(name, s->rk.dname) == 0) {
925
0
      return s;
926
0
    }
927
0
  }
928
0
  return NULL;
929
0
}
930
931
struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep,
932
  uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
933
0
{
934
0
  size_t i;
935
0
  for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
936
0
    struct ub_packed_rrset_key* s = rep->rrsets[i];
937
0
    if(ntohs(s->rk.type) == type && 
938
0
      ntohs(s->rk.rrset_class) == dclass && 
939
0
      namelen == s->rk.dname_len &&
940
0
      query_dname_compare(name, s->rk.dname) == 0) {
941
0
      return s;
942
0
    }
943
0
  }
944
0
  return NULL;
945
0
}
946
947
struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep,
948
  uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
949
0
{
950
0
  size_t i;
951
0
  for(i=0; i<rep->rrset_count; i++) {
952
0
    struct ub_packed_rrset_key* s = rep->rrsets[i];
953
0
    if(ntohs(s->rk.type) == type && 
954
0
      ntohs(s->rk.rrset_class) == dclass && 
955
0
      namelen == s->rk.dname_len &&
956
0
      query_dname_compare(name, s->rk.dname) == 0) {
957
0
      return s;
958
0
    }
959
0
  }
960
0
  return NULL;
961
0
}
962
963
void 
964
log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
965
0
{
966
  /* not particularly fast but flexible, make wireformat and print */
967
0
  sldns_buffer* buf = sldns_buffer_new(65535);
968
0
  struct regional* region = regional_create();
969
0
  if(!(buf && region)) {
970
0
    log_err("%s: log_dns_msg: out of memory", str);
971
0
    sldns_buffer_free(buf);
972
0
    regional_destroy(region);
973
0
    return;
974
0
  }
975
0
  if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0,
976
0
    region, 65535, 1, 0)) {
977
0
    log_err("%s: log_dns_msg: out of memory", str);
978
0
  } else {
979
0
    char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf),
980
0
      sldns_buffer_limit(buf));
981
0
    if(!s) {
982
0
      log_info("%s: log_dns_msg: ldns tostr failed", str);
983
0
    } else {
984
0
      log_info("%s %s", str, s);
985
0
    }
986
0
    free(s);
987
0
  }
988
0
  sldns_buffer_free(buf);
989
0
  regional_destroy(region);
990
0
}
991
992
void
993
log_reply_info(enum verbosity_value v, struct query_info *qinf,
994
  struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur,
995
  int cached, struct sldns_buffer *rmsg, struct sockaddr_storage* daddr,
996
  enum comm_point_type tp, void* ssl)
997
0
{
998
0
  char clientip_buf[128];
999
0
  char rcode_buf[16];
1000
0
  char dest_buf[160];
1001
0
  uint16_t rcode = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(rmsg, 2));
1002
1003
0
  if(verbosity < v)
1004
0
    return;
1005
1006
0
  sldns_wire2str_rcode_buf((int)rcode, rcode_buf, sizeof(rcode_buf));
1007
0
  addr_to_str(addr, addrlen, clientip_buf, sizeof(clientip_buf));
1008
0
  if(daddr) {
1009
0
    char da[128];
1010
0
    int port = 0;
1011
0
    char* comm;
1012
0
    if(daddr->ss_family == AF_INET6) {
1013
0
      struct sockaddr_in6 *d = (struct sockaddr_in6 *)daddr;
1014
0
      if(inet_ntop(d->sin6_family, &d->sin6_addr, da,
1015
0
        sizeof(da)) == 0)
1016
0
        snprintf(dest_buf, sizeof(dest_buf),
1017
0
          "(inet_ntop_error)");
1018
0
      port = ntohs(d->sin6_port);
1019
0
    } else if(daddr->ss_family == AF_INET) {
1020
0
      struct sockaddr_in *d = (struct sockaddr_in *)daddr;
1021
0
      if(inet_ntop(d->sin_family, &d->sin_addr, da,
1022
0
        sizeof(da)) == 0)
1023
0
        snprintf(dest_buf, sizeof(dest_buf),
1024
0
          "(inet_ntop_error)");
1025
0
      port = ntohs(d->sin_port);
1026
0
    } else {
1027
0
      snprintf(da, sizeof(da), "socket%d",
1028
0
        (int)daddr->ss_family);
1029
0
    }
1030
0
    comm = "udp";
1031
0
    if(tp == comm_tcp) comm = (ssl?"dot":"tcp");
1032
0
    else if(tp == comm_tcp_accept) comm = (ssl?"dot":"tcp");
1033
0
    else if(tp == comm_http) comm = "doh";
1034
0
    else if(tp == comm_local) comm = "unix";
1035
0
    else if(tp == comm_raw) comm = "raw";
1036
0
    snprintf(dest_buf, sizeof(dest_buf), " on %s %s %d",
1037
0
      comm, da, port);
1038
0
  } else {
1039
0
    dest_buf[0]=0;
1040
0
  }
1041
0
  if(rcode == LDNS_RCODE_FORMERR)
1042
0
  {
1043
0
    if(LOG_TAG_QUERYREPLY)
1044
0
      log_reply("%s - - - %s - - -%s", clientip_buf,
1045
0
        rcode_buf, dest_buf);
1046
0
    else  log_info("%s - - - %s - - -%s", clientip_buf,
1047
0
        rcode_buf, dest_buf);
1048
0
  } else {
1049
0
    char qname_buf[LDNS_MAX_DOMAINLEN];
1050
0
    char type_buf[16];
1051
0
    char class_buf[16];
1052
0
    size_t pktlen;
1053
0
    if(qinf->qname)
1054
0
      dname_str(qinf->qname, qname_buf);
1055
0
    else  snprintf(qname_buf, sizeof(qname_buf), "null");
1056
0
    pktlen = sldns_buffer_limit(rmsg);
1057
0
    sldns_wire2str_type_buf(qinf->qtype, type_buf, sizeof(type_buf));
1058
0
    sldns_wire2str_class_buf(qinf->qclass, class_buf, sizeof(class_buf));
1059
0
    if(LOG_TAG_QUERYREPLY)
1060
0
         log_reply("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d%s",
1061
0
      clientip_buf, qname_buf, type_buf, class_buf,
1062
0
      rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec,
1063
0
      cached, (int)pktlen, dest_buf);
1064
0
    else log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d%s",
1065
0
      clientip_buf, qname_buf, type_buf, class_buf,
1066
0
      rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec,
1067
0
      cached, (int)pktlen, dest_buf);
1068
0
  }
1069
0
}
1070
1071
void
1072
log_query_info(enum verbosity_value v, const char* str, 
1073
  struct query_info* qinf)
1074
0
{
1075
0
  log_nametypeclass(v, str, qinf->qname, qinf->qtype, qinf->qclass);
1076
0
}
1077
1078
int
1079
reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep) 
1080
0
{
1081
  /* check only answer section rrs for matching cname chain.
1082
   * the cache may return changed rdata, but owner names are untouched.*/
1083
0
  size_t i;
1084
0
  uint8_t* sname = qinfo->qname;
1085
0
  size_t snamelen = qinfo->qname_len;
1086
0
  for(i=0; i<rep->an_numrrsets; i++) {
1087
0
    uint16_t t = ntohs(rep->rrsets[i]->rk.type);
1088
0
    if(t == LDNS_RR_TYPE_DNAME)
1089
0
      continue; /* skip dnames; note TTL 0 not cached */
1090
    /* verify that owner matches current sname */
1091
0
    if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){
1092
      /* cname chain broken */
1093
0
      return 0;
1094
0
    }
1095
    /* if this is a cname; move on */
1096
0
    if(t == LDNS_RR_TYPE_CNAME) {
1097
0
      get_cname_target(rep->rrsets[i], &sname, &snamelen);
1098
0
    }
1099
0
  }
1100
0
  return 1;
1101
0
}
1102
1103
int
1104
reply_all_rrsets_secure(struct reply_info* rep) 
1105
0
{
1106
0
  size_t i;
1107
0
  for(i=0; i<rep->rrset_count; i++) {
1108
0
    if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data)
1109
0
      ->security != sec_status_secure )
1110
0
    return 0;
1111
0
  }
1112
0
  return 1;
1113
0
}
1114
1115
struct reply_info*
1116
parse_reply_in_temp_region(sldns_buffer* pkt, struct regional* region,
1117
  struct query_info* qi)
1118
0
{
1119
0
  struct reply_info* rep;
1120
0
  struct msg_parse* msg;
1121
0
  if(!(msg = regional_alloc(region, sizeof(*msg)))) {
1122
0
    return NULL;
1123
0
  }
1124
0
  memset(msg, 0, sizeof(*msg));
1125
0
  sldns_buffer_set_position(pkt, 0);
1126
0
  if(parse_packet(pkt, msg, region) != 0){
1127
0
    return 0;
1128
0
  }
1129
0
  if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) {
1130
0
    return 0;
1131
0
  }
1132
0
  return rep;
1133
0
}
1134
1135
int edns_opt_list_append_ede(struct edns_option** list, struct regional* region,
1136
  sldns_ede_code code, const char *txt)
1137
0
{
1138
0
  struct edns_option** prevp;
1139
0
  struct edns_option* opt;
1140
0
  size_t txt_len = txt ? strlen(txt) : 0;
1141
1142
  /* allocate new element */
1143
0
  opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
1144
0
  if(!opt)
1145
0
    return 0;
1146
0
  opt->next = NULL;
1147
0
  opt->opt_code = LDNS_EDNS_EDE;
1148
0
  opt->opt_len = txt_len + sizeof(uint16_t);
1149
0
  opt->opt_data = regional_alloc(region, txt_len + sizeof(uint16_t));
1150
0
  if(!opt->opt_data)
1151
0
    return 0;
1152
0
  sldns_write_uint16(opt->opt_data, (uint16_t)code);
1153
0
  if (txt_len)
1154
0
    memmove(opt->opt_data + 2, txt, txt_len);
1155
1156
  /* append at end of list */
1157
0
  prevp = list;
1158
0
  while(*prevp != NULL)
1159
0
    prevp = &((*prevp)->next);
1160
0
  verbose(VERB_ALGO, "attached EDE code: %d with message: '%s'", code, (txt?txt:""));
1161
0
  *prevp = opt;
1162
0
  return 1;
1163
0
}
1164
1165
int edns_opt_list_append_keepalive(struct edns_option** list, int msec,
1166
  struct regional* region)
1167
0
{
1168
0
  uint8_t data[2]; /* For keepalive value */
1169
0
  data[0] = (uint8_t)((msec >> 8) & 0xff);
1170
0
  data[1] = (uint8_t)(msec & 0xff);
1171
0
  return edns_opt_list_append(list, LDNS_EDNS_KEEPALIVE, sizeof(data),
1172
0
    data, region);
1173
0
}
1174
1175
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
1176
  uint8_t* data, struct regional* region)
1177
14.0k
{
1178
14.0k
  struct edns_option** prevp;
1179
14.0k
  struct edns_option* opt;
1180
1181
  /* allocate new element */
1182
14.0k
  opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
1183
14.0k
  if(!opt)
1184
0
    return 0;
1185
14.0k
  opt->next = NULL;
1186
14.0k
  opt->opt_code = code;
1187
14.0k
  opt->opt_len = len;
1188
14.0k
  opt->opt_data = NULL;
1189
14.0k
  if(len > 0) {
1190
1.04k
    opt->opt_data = regional_alloc_init(region, data, len);
1191
1.04k
    if(!opt->opt_data)
1192
0
      return 0;
1193
1.04k
  }
1194
1195
  /* append at end of list */
1196
14.0k
  prevp = list;
1197
21.3M
  while(*prevp != NULL) {
1198
21.3M
    prevp = &((*prevp)->next);
1199
21.3M
  }
1200
14.0k
  *prevp = opt;
1201
14.0k
  return 1;
1202
14.0k
}
1203
1204
int edns_opt_list_remove(struct edns_option** list, uint16_t code)
1205
0
{
1206
  /* The list should already be allocated in a region. Freeing the
1207
   * allocated space in a region is not possible. We just unlink the
1208
   * required elements and they will be freed together with the region. */
1209
1210
0
  struct edns_option* prev;
1211
0
  struct edns_option* curr;
1212
0
  if(!list || !(*list)) return 0;
1213
1214
  /* Unlink and repoint if the element(s) are first in list */
1215
0
  while(list && *list && (*list)->opt_code == code) {
1216
0
    *list = (*list)->next;
1217
0
  }
1218
1219
0
  if(!list || !(*list)) return 1;
1220
  /* Unlink elements and reattach the list */
1221
0
  prev = *list;
1222
0
  curr = (*list)->next;
1223
0
  while(curr != NULL) {
1224
0
    if(curr->opt_code == code) {
1225
0
      prev->next = curr->next;
1226
0
      curr = curr->next;
1227
0
    } else {
1228
0
      prev = curr;
1229
0
      curr = curr->next;
1230
0
    }
1231
0
  }
1232
0
  return 1;
1233
0
}
1234
1235
static int inplace_cb_reply_call_generic(
1236
    struct inplace_cb* callback_list, enum inplace_cb_list_type type,
1237
  struct query_info* qinfo, struct module_qstate* qstate,
1238
  struct reply_info* rep, int rcode, struct edns_data* edns,
1239
  struct comm_reply* repinfo, struct regional* region,
1240
  struct timeval* start_time)
1241
0
{
1242
0
  struct inplace_cb* cb;
1243
0
  struct edns_option* opt_list_out = NULL;
1244
#if defined(EXPORT_ALL_SYMBOLS)
1245
  (void)type; /* param not used when fptr_ok disabled */
1246
#endif
1247
0
  if(qstate)
1248
0
    opt_list_out = qstate->edns_opts_front_out;
1249
0
  for(cb=callback_list; cb; cb=cb->next) {
1250
0
    fptr_ok(fptr_whitelist_inplace_cb_reply_generic(
1251
0
      (inplace_cb_reply_func_type*)cb->cb, type));
1252
0
    (void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep,
1253
0
      rcode, edns, &opt_list_out, repinfo, region, start_time, cb->id, cb->cb_arg);
1254
0
  }
1255
0
  edns->opt_list_inplace_cb_out = opt_list_out;
1256
0
  return 1;
1257
0
}
1258
1259
int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
1260
  struct module_qstate* qstate, struct reply_info* rep, int rcode,
1261
  struct edns_data* edns, struct comm_reply* repinfo, struct regional* region,
1262
  struct timeval* start_time)
1263
0
{
1264
0
  return inplace_cb_reply_call_generic(
1265
0
    env->inplace_cb_lists[inplace_cb_reply], inplace_cb_reply, qinfo,
1266
0
    qstate, rep, rcode, edns, repinfo, region, start_time);
1267
0
}
1268
1269
int inplace_cb_reply_cache_call(struct module_env* env,
1270
  struct query_info* qinfo, struct module_qstate* qstate,
1271
  struct reply_info* rep, int rcode, struct edns_data* edns,
1272
  struct comm_reply* repinfo, struct regional* region,
1273
  struct timeval* start_time)
1274
0
{
1275
0
  return inplace_cb_reply_call_generic(
1276
0
    env->inplace_cb_lists[inplace_cb_reply_cache], inplace_cb_reply_cache,
1277
0
    qinfo, qstate, rep, rcode, edns, repinfo, region, start_time);
1278
0
}
1279
1280
int inplace_cb_reply_local_call(struct module_env* env,
1281
  struct query_info* qinfo, struct module_qstate* qstate,
1282
  struct reply_info* rep, int rcode, struct edns_data* edns,
1283
  struct comm_reply* repinfo, struct regional* region,
1284
  struct timeval* start_time)
1285
0
{
1286
0
  return inplace_cb_reply_call_generic(
1287
0
    env->inplace_cb_lists[inplace_cb_reply_local], inplace_cb_reply_local,
1288
0
    qinfo, qstate, rep, rcode, edns, repinfo, region, start_time);
1289
0
}
1290
1291
int inplace_cb_reply_servfail_call(struct module_env* env,
1292
  struct query_info* qinfo, struct module_qstate* qstate,
1293
  struct reply_info* rep, int rcode, struct edns_data* edns,
1294
  struct comm_reply* repinfo, struct regional* region,
1295
  struct timeval* start_time)
1296
0
{
1297
  /* We are going to servfail. Remove any potential edns options. */
1298
0
  if(qstate)
1299
0
    qstate->edns_opts_front_out = NULL;
1300
0
  return inplace_cb_reply_call_generic(
1301
0
    env->inplace_cb_lists[inplace_cb_reply_servfail],
1302
0
    inplace_cb_reply_servfail, qinfo, qstate, rep, rcode, edns, repinfo,
1303
0
    region, start_time);
1304
0
}
1305
1306
int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
1307
  uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen,
1308
  uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
1309
  struct regional* region)
1310
0
{
1311
0
  struct inplace_cb* cb = env->inplace_cb_lists[inplace_cb_query];
1312
0
  for(; cb; cb=cb->next) {
1313
0
    fptr_ok(fptr_whitelist_inplace_cb_query(
1314
0
      (inplace_cb_query_func_type*)cb->cb));
1315
0
    (void)(*(inplace_cb_query_func_type*)cb->cb)(qinfo, flags,
1316
0
      qstate, addr, addrlen, zone, zonelen, region,
1317
0
      cb->id, cb->cb_arg);
1318
0
  }
1319
0
  return 1;
1320
0
}
1321
1322
int inplace_cb_edns_back_parsed_call(struct module_env* env, 
1323
  struct module_qstate* qstate)
1324
0
{
1325
0
  struct inplace_cb* cb =
1326
0
    env->inplace_cb_lists[inplace_cb_edns_back_parsed];
1327
0
  for(; cb; cb=cb->next) {
1328
0
    fptr_ok(fptr_whitelist_inplace_cb_edns_back_parsed(
1329
0
      (inplace_cb_edns_back_parsed_func_type*)cb->cb));
1330
0
    (void)(*(inplace_cb_edns_back_parsed_func_type*)cb->cb)(qstate,
1331
0
      cb->id, cb->cb_arg);
1332
0
  }
1333
0
  return 1;
1334
0
}
1335
1336
int inplace_cb_query_response_call(struct module_env* env,
1337
0
  struct module_qstate* qstate, struct dns_msg* response) {
1338
0
  struct inplace_cb* cb =
1339
0
    env->inplace_cb_lists[inplace_cb_query_response];
1340
0
  for(; cb; cb=cb->next) {
1341
0
    fptr_ok(fptr_whitelist_inplace_cb_query_response(
1342
0
      (inplace_cb_query_response_func_type*)cb->cb));
1343
0
    (void)(*(inplace_cb_query_response_func_type*)cb->cb)(qstate,
1344
0
      response, cb->id, cb->cb_arg);
1345
0
  }
1346
0
  return 1;
1347
0
}
1348
1349
struct edns_option* edns_opt_copy_region(struct edns_option* list,
1350
  struct regional* region)
1351
0
{
1352
0
  struct edns_option* result = NULL, *cur = NULL, *s;
1353
0
  while(list) {
1354
    /* copy edns option structure */
1355
0
    s = regional_alloc_init(region, list, sizeof(*list));
1356
0
    if(!s) return NULL;
1357
0
    s->next = NULL;
1358
1359
    /* copy option data */
1360
0
    if(s->opt_data) {
1361
0
      s->opt_data = regional_alloc_init(region, s->opt_data,
1362
0
        s->opt_len);
1363
0
      if(!s->opt_data)
1364
0
        return NULL;
1365
0
    }
1366
1367
    /* link into list */
1368
0
    if(cur)
1369
0
      cur->next = s;
1370
0
    else  result = s;
1371
0
    cur = s;
1372
1373
    /* examine next element */
1374
0
    list = list->next;
1375
0
  }
1376
0
  return result;
1377
0
}
1378
1379
struct edns_option* edns_opt_copy_filter_region(struct edns_option* list,
1380
  uint16_t* filter_list, size_t filter_list_len, struct regional* region)
1381
0
{
1382
0
  struct edns_option* result = NULL, *cur = NULL, *s;
1383
0
  size_t i;
1384
0
  while(list) {
1385
0
    for(i=0; i<filter_list_len; i++)
1386
0
      if(filter_list[i] == list->opt_code) goto found;
1387
0
    if(i == filter_list_len) goto next;
1388
0
found:
1389
    /* copy edns option structure */
1390
0
    s = regional_alloc_init(region, list, sizeof(*list));
1391
0
    if(!s) return NULL;
1392
0
    s->next = NULL;
1393
1394
    /* copy option data */
1395
0
    if(s->opt_data) {
1396
0
      s->opt_data = regional_alloc_init(region, s->opt_data,
1397
0
        s->opt_len);
1398
0
      if(!s->opt_data)
1399
0
        return NULL;
1400
0
    }
1401
1402
    /* link into list */
1403
0
    if(cur)
1404
0
      cur->next = s;
1405
0
    else  result = s;
1406
0
    cur = s;
1407
1408
0
next:
1409
    /* examine next element */
1410
0
    list = list->next;
1411
0
  }
1412
0
  return result;
1413
0
}
1414
1415
int edns_opt_compare(struct edns_option* p, struct edns_option* q)
1416
0
{
1417
0
  if(!p && !q) return 0;
1418
0
  if(!p) return -1;
1419
0
  if(!q) return 1;
1420
0
  log_assert(p && q);
1421
0
  if(p->opt_code != q->opt_code)
1422
0
    return (int)q->opt_code - (int)p->opt_code;
1423
0
  if(p->opt_len != q->opt_len)
1424
0
    return (int)q->opt_len - (int)p->opt_len;
1425
0
  if(p->opt_len != 0)
1426
0
    return memcmp(p->opt_data, q->opt_data, p->opt_len);
1427
0
  return 0;
1428
0
}
1429
1430
int edns_opt_list_compare(struct edns_option* p, struct edns_option* q)
1431
0
{
1432
0
  int r;
1433
0
  while(p && q) {
1434
0
    r = edns_opt_compare(p, q);
1435
0
    if(r != 0)
1436
0
      return r;
1437
0
    p = p->next;
1438
0
    q = q->next;
1439
0
  }
1440
0
  if(p || q) {
1441
    /* uneven length lists */
1442
0
    if(p) return 1;
1443
0
    if(q) return -1;
1444
0
  }
1445
0
  return 0;
1446
0
}
1447
1448
void edns_opt_list_free(struct edns_option* list)
1449
0
{
1450
0
  struct edns_option* n;
1451
0
  while(list) {
1452
0
    free(list->opt_data);
1453
0
    n = list->next;
1454
0
    free(list);
1455
0
    list = n;
1456
0
  }
1457
0
}
1458
1459
struct edns_option* edns_opt_copy_alloc(struct edns_option* list)
1460
0
{
1461
0
  struct edns_option* result = NULL, *cur = NULL, *s;
1462
0
  while(list) {
1463
    /* copy edns option structure */
1464
0
    s = memdup(list, sizeof(*list));
1465
0
    if(!s) {
1466
0
      edns_opt_list_free(result);
1467
0
      return NULL;
1468
0
    }
1469
0
    s->next = NULL;
1470
1471
    /* copy option data */
1472
0
    if(s->opt_data) {
1473
0
      s->opt_data = memdup(s->opt_data, s->opt_len);
1474
0
      if(!s->opt_data) {
1475
0
        free(s);
1476
0
        edns_opt_list_free(result);
1477
0
        return NULL;
1478
0
      }
1479
0
    }
1480
1481
    /* link into list */
1482
0
    if(cur)
1483
0
      cur->next = s;
1484
0
    else  result = s;
1485
0
    cur = s;
1486
1487
    /* examine next element */
1488
0
    list = list->next;
1489
0
  }
1490
0
  return result;
1491
0
}
1492
1493
struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code)
1494
0
{
1495
0
  struct edns_option* p;
1496
0
  for(p=list; p; p=p->next) {
1497
0
    if(p->opt_code == code)
1498
0
      return p;
1499
0
  }
1500
0
  return NULL;
1501
0
}
1502
1503
int local_alias_shallow_copy_qname(struct local_rrset* local_alias, uint8_t** qname,
1504
  size_t* qname_len)
1505
0
{
1506
0
  struct ub_packed_rrset_key* rrset = local_alias->rrset;
1507
0
  struct packed_rrset_data* d = rrset->entry.data;
1508
1509
  /* Sanity check: our current implementation only supports
1510
      * a single CNAME RRset as a local alias. */
1511
0
  if(local_alias->next ||
1512
0
    rrset->rk.type != htons(LDNS_RR_TYPE_CNAME) ||
1513
0
    d->count != 1) {
1514
0
    log_err("assumption failure: unexpected local alias");
1515
0
    return 0;
1516
0
  }
1517
0
  *qname = d->rr_data[0] + 2;
1518
0
  *qname_len = d->rr_len[0] - 2;
1519
0
  return 1;
1520
0
}