Coverage Report

Created: 2025-07-11 06:08

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