Coverage Report

Created: 2024-05-20 06:10

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