Coverage Report

Created: 2024-02-11 06:17

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