The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
decode.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 218693a62d08117aaddcd56c87bfdaa4cef4860f $
19  *
20  * @file protocols/dns/decode.c
21  * @brief Functions to decode DNS packets.
22  *
23  * @author Alan DeKok (aland@freeradius.org)
24  *
25  * @copyright 2021 The FreeRADIUS server project
26  * @copyright 2021 NetworkRADIUS SARL (legal@networkradius.com)
27  */
28 #include <freeradius-devel/io/test_point.h>
29 #include <freeradius-devel/util/dns.h>
30 #include <freeradius-devel/util/proto.h>
31 #include <freeradius-devel/util/struct.h>
32 
33 #include "dns.h"
34 #include "attrs.h"
35 
36 static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
37  fr_dict_attr_t const *parent,
38  uint8_t const *data, size_t const data_len, void *decode_ctx);
39 
40 static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
41  fr_dict_attr_t const *parent,
42  uint8_t const *data, size_t const data_len, void *decode_ctx);
43 
45  fr_dict_attr_t const *parent,
46  uint8_t const *data, size_t const data_len, void *decode_ctx)
47 {
48  return fr_pair_tlvs_from_network(ctx, out, parent, data, data_len, decode_ctx, decode_option, NULL, true);
49 }
50 
51 
53  fr_dict_attr_t const *parent,
54  uint8_t const *data, size_t const data_len, void *decode_ctx)
55 {
56  if ((parent->type == FR_TYPE_STRING) && !parent->flags.extra && parent->flags.subtype) {
57  fr_dns_ctx_t *packet_ctx = decode_ctx;
58 
59  return fr_pair_dns_labels_from_network(ctx, out, parent, packet_ctx->packet, data, data_len, packet_ctx->lb, false);
60  }
61 
62  return decode_value(ctx, out, parent, data, data_len, decode_ctx);
63 }
64 
65 
66 static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
67  fr_dict_attr_t const *parent,
68  uint8_t const *data, size_t const data_len, void *decode_ctx)
69 {
70  ssize_t slen;
71  fr_pair_t *vp;
72  uint8_t prefix_len;
73 
74  FR_PROTO_HEX_DUMP(data, data_len, "decode_value");
75 
76  switch (parent->type) {
77  /*
78  * Address MAY be shorter than 16 bytes.
79  */
81  if ((data_len == 0) || (data_len > (1 + sizeof(vp->vp_ipv6addr)))) {
82  raw:
83  return fr_pair_raw_from_network(ctx, out, parent, data, data_len);
84 
85  }
86 
87  /*
88  * Structs used fixed length fields
89  */
90  if (parent->parent->type == FR_TYPE_STRUCT) {
91  if (data_len != (1 + sizeof(vp->vp_ipv6addr))) goto raw;
92 
93  vp = fr_pair_afrom_da(ctx, parent);
94  if (!vp) return PAIR_DECODE_OOM;
95 
96  vp->vp_ip.af = AF_INET6;
97  vp->vp_ip.prefix = data[0];
98  memcpy(&vp->vp_ipv6addr, data + 1, data_len - 1);
99  break;
100  }
101 
102  /*
103  * No address, the prefix length MUST be zero.
104  */
105  if (data_len == 1) {
106  if (data[0] != 0) goto raw;
107 
108  vp = fr_pair_afrom_da(ctx, parent);
109  if (!vp) return PAIR_DECODE_OOM;
110 
111  vp->vp_ip.af = AF_INET6;
112  break;
113  }
114 
115  prefix_len = data[0];
116 
117  /*
118  * If we have a /64 prefix but only 7 bytes of
119  * address, that's an error.
120  */
121  if (fr_bytes_from_bits(prefix_len) > (data_len - 1)) goto raw;
122 
123  vp = fr_pair_afrom_da(ctx, parent);
124  if (!vp) return PAIR_DECODE_OOM;
125 
126  vp->vp_ip.af = AF_INET6;
127  vp->vp_ip.prefix = prefix_len;
128  memcpy(&vp->vp_ipv6addr, data + 1, data_len - 1);
129  break;
130 
131  /*
132  * A bool is encoded as an empty option if it's
133  * true. A bool is omitted entirely if it's
134  * false.
135  */
136  case FR_TYPE_BOOL:
137  if (data_len != 0) goto raw;
138  vp = fr_pair_afrom_da(ctx, parent);
139  if (!vp) return PAIR_DECODE_OOM;
140  vp->vp_bool = true;
141  break;
142 
143  case FR_TYPE_STRUCT:
144  slen = fr_struct_from_network(ctx, out, parent, data, data_len, true,
145  decode_ctx, decode_value_trampoline, NULL);
146  if (slen < 0) return slen;
147  return data_len;
148 
149  case FR_TYPE_GROUP:
150  return PAIR_DECODE_FATAL_ERROR; /* not supported */
151 
152  default:
153  vp = fr_pair_afrom_da(ctx, parent);
154  if (!vp) return PAIR_DECODE_OOM;
155 
156  if (fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
157  &FR_DBUFF_TMP(data, data_len), data_len, true) < 0) {
158  FR_PROTO_TRACE("failed decoding?");
159  talloc_free(vp);
160  goto raw;
161  }
162  break;
163  }
164 
165  vp->vp_tainted = true;
167  return data_len;
168 }
169 
170 
171 #define DNS_GET_OPTION_NUM(_x) fr_nbo_to_uint16(_x)
172 #define DNS_GET_OPTION_LEN(_x) fr_nbo_to_uint16((_x) + 2)
173 
174 static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
175  fr_dict_attr_t const *parent,
176  uint8_t const *data, size_t const data_len, void *decode_ctx)
177 {
178  unsigned int option;
179  size_t len;
180  ssize_t slen;
181  fr_dict_attr_t const *da;
182  fr_dns_ctx_t *packet_ctx = decode_ctx;
183 
184 #ifdef STATIC_ANALYZER
185  if (!packet_ctx || !packet_ctx->tmp_ctx) return PAIR_DECODE_FATAL_ERROR;
186 #endif
187 
188  /*
189  * Must have at least an option header.
190  */
191  if (data_len < 4) {
192  fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
193  return -(data_len);
194  }
195 
196  option = DNS_GET_OPTION_NUM(data);
197  len = DNS_GET_OPTION_LEN(data);
198  if (len > (data_len - 4)) {
199  fr_strerror_printf("%s: Option overflows input. "
200  "Optional length must be less than %zu bytes, got %zu bytes",
201  __FUNCTION__, data_len - 4, len);
203  }
204 
205  FR_PROTO_HEX_DUMP(data, len + 4, "decode_option");
206 
207  da = fr_dict_attr_child_by_num(parent, option);
208  if (!da) {
209  da = fr_dict_unknown_attr_afrom_num(packet_ctx->tmp_ctx, parent, option);
210  if (!da) return PAIR_DECODE_FATAL_ERROR;
211  }
212  FR_PROTO_TRACE("decode context changed %s -> %s",da->parent->name, da->name);
213 
214  if ((da->type == FR_TYPE_STRING) && !da->flags.extra && da->flags.subtype) {
215  slen = fr_pair_dns_labels_from_network(ctx, out, da, packet_ctx->packet, data + 4, len, packet_ctx->lb, true);
216 
217  } else if (da->flags.array) {
218  slen = fr_pair_array_from_network(ctx, out, da, data + 4, len, decode_ctx, decode_value);
219 
220  } else {
221  slen = decode_value(ctx, out, da, data + 4, len, decode_ctx);
222  }
224 
225  if (slen < 0) return slen;
226 
227  return len + 4;
228 }
229 
230 static ssize_t decode_record(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *attr,
231  uint8_t const *rr, uint8_t const *end,
232  fr_dns_ctx_t *packet_ctx, uint8_t const *counter)
233 {
234  int i, count;
235  uint8_t const *p = rr;
236 
237  /*
238  * The header has a count of how many records we need to decode.
239  */
240  count = fr_nbo_to_uint16(counter);
241  FR_PROTO_TRACE("Decoding %u of %s", count, attr->name);
242 
243  /* coverity[tainted_data] */
244  for (i = 0; (i < count) && (p < end); i++) {
245  ssize_t slen;
246 
247  FR_PROTO_HEX_DUMP(p, end - p, "fr_dns_decode - %s %d/%d", attr->name, i, count);
248 
249  slen = fr_struct_from_network(ctx, out, attr, p, end - p, true,
251  if (slen < 0) return slen;
252  if (!slen) break;
253 
254  fr_assert(slen <= (end - p));
255 
256  p += slen;
257  }
258 
259  return p - rr;
260 }
261 
262 /** Decode a DNS packet
263  *
264  */
265 ssize_t fr_dns_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *packet, size_t packet_len, fr_dns_ctx_t *packet_ctx)
266 {
267  ssize_t slen;
268  uint8_t const *p, *end;
269 
270  if (packet_len < DNS_HDR_LEN) return 0;
271 
272  /*
273  * @todo - synthesize Packet-Type from the various fields.
274  */
275 
276  FR_PROTO_HEX_DUMP(packet, packet_len, "fr_dns_decode");
277 
278  /*
279  * Decode the header.
280  */
281  slen = fr_struct_from_network(ctx, out, attr_dns_packet, packet, DNS_HDR_LEN, true,
282  packet_ctx, decode_value_trampoline, NULL); /* no TLVs in the header */
283  if (slen < 0) {
284  fr_strerror_printf("Failed decoding DNS header - %s", fr_strerror());
285  return slen;
286  }
287  fr_assert(slen == DNS_HDR_LEN);
288 
289  p = packet + DNS_HDR_LEN;
290  end = packet + packet_len;
291  FR_PROTO_HEX_DUMP(p, end - p, "fr_dns_decode - after header");
292 
293  slen = decode_record(ctx, out, attr_dns_question, p, end, packet_ctx, packet + 4);
294  if (slen < 0) {
295  fr_strerror_printf("Failed decoding questions - %s", fr_strerror());
296  return slen;
297  }
298  p += slen;
299  FR_PROTO_HEX_DUMP(p, end - p, "fr_dns_decode - after %zd bytes of questions", slen);
300 
301  slen = decode_record(ctx, out, attr_dns_rr, p, end, packet_ctx, packet + 6);
302  if (slen < 0) {
303  fr_strerror_printf("Failed decoding RRs - %s", fr_strerror());
304  return slen - (p - packet);
305  }
306  p += slen;
307  FR_PROTO_HEX_DUMP(p, end - p, "fr_dns_decode - after %zd bytes of RRs", slen);
308 
309  slen = decode_record(ctx, out, attr_dns_ns, p, end, packet_ctx, packet + 8);
310  if (slen < 0) {
311  fr_strerror_printf("Failed decoding NS - %s", fr_strerror());
312  return slen - (p - packet);
313  }
314  p += slen;
315  FR_PROTO_HEX_DUMP(p, end - p, "fr_dns_decode - after %zd bytes of NS", slen);
316 
317  slen = decode_record(ctx, out, attr_dns_ar, p, end, packet_ctx, packet + 10);
318  if (slen < 0) {
319  fr_strerror_printf("Failed decoding additional records - %s", fr_strerror());
320  return slen - (p - packet);
321  }
322  FR_PROTO_HEX_DUMP(p, end - p, "fr_dns_decode - after %zd bytes of additional records", slen);
323 
324 // p += slen;
325 
326  return packet_len;
327 }
328 
329 /** Decode DNS RR
330  *
331  * @param[in] ctx context to alloc new attributes in.
332  * @param[in,out] out Where to write the decoded options.
333  * @param[in] parent to lookup attributes in.
334  * @param[in] data to parse.
335  * @param[in] data_len of data to parse.
336  * @param[in] decode_ctx Unused.
337  */
338 static ssize_t decode_rr(TALLOC_CTX *ctx, fr_pair_list_t *out, UNUSED fr_dict_attr_t const *parent,
339  uint8_t const *data, size_t data_len, void *decode_ctx)
340 {
341  ssize_t slen;
342  fr_dns_ctx_t *packet_ctx = (fr_dns_ctx_t *) decode_ctx;
343 
344  FR_PROTO_TRACE("%s called to parse %zu byte(s)", __FUNCTION__, data_len);
345 
346  if (data_len == 0) return 0;
347 
348  /*
349  * This function is only used for testing, so update decode_ctx
350  */
351  packet_ctx->packet = data;
352  packet_ctx->packet_len = data_len;
353 
354  FR_PROTO_HEX_DUMP(data, data_len, NULL);
355 
356  /*
357  * There should be at least room for the RR header
358  */
359  if (data_len < 9) {
360  fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
361  return -1;
362  }
363 
364  slen = fr_struct_from_network(ctx, out, attr_dns_rr, data, data_len, true,
366  if (slen < 0) return slen;
367 
368  FR_PROTO_TRACE("decoding option complete, returning %zd byte(s)", slen);
369  return slen;
370 }
371 
372 /*
373  * Test points
374  */
375 static int decode_test_ctx(void **out, TALLOC_CTX *ctx)
376 {
377  fr_dns_ctx_t *test_ctx;
378 
379  test_ctx = talloc_zero(ctx, fr_dns_ctx_t);
380 
381  test_ctx->tmp_ctx = talloc(test_ctx, uint8_t);
382  *out = test_ctx;
383 
384  return 0;
385 }
386 
388  { L("none"), FR_DNS_DECODE_FAIL_NONE },
389  { L("packet is smaller than DNS header"), FR_DNS_DECODE_FAIL_MIN_LENGTH_PACKET },
390  { L("packet is larger than 65535"), FR_DNS_DECODE_FAIL_MAX_LENGTH_PACKET },
391  { L("expected query / answer, got answer / query"), FR_DNS_DECODE_FAIL_UNEXPECTED },
392  { L("no 'questions' in query packet"), FR_DNS_DECODE_FAIL_NO_QUESTIONS },
393  { L("unexprected answers in query packet"), FR_DNS_DECODE_FAIL_ANSWERS_IN_QUESTION },
394  { L("unexpected NS records in query packet"), FR_DNS_DECODE_FAIL_NS_IN_QUESTION },
395  { L("invalid label for resource record"), FR_DNS_DECODE_FAIL_INVALID_RR_LABEL },
396  { L("missing resource record header"), FR_DNS_DECODE_FAIL_MISSING_RR_HEADER },
397  { L("missing resource record length field"), FR_DNS_DECODE_FAIL_MISSING_RR_LEN },
398  { L("resource record length field is zero"), FR_DNS_DECODE_FAIL_ZERO_RR_LEN },
399  { L("resource record length overflows the packet"), FR_DNS_DECODE_FAIL_RR_OVERFLOWS_PACKET },
400  { L("more resource records than indicated in header"), FR_DNS_DECODE_FAIL_TOO_MANY_RRS },
401  { L("fewer resource records than indicated in header"), FR_DNS_DECODE_FAIL_TOO_FEW_RRS },
402  { L("pointer overflows packet"), FR_DNS_DECODE_FAIL_POINTER_OVERFLOWS_PACKET },
403  { L("pointer points to packet header"), FR_DNS_DECODE_FAIL_POINTER_TO_HEADER },
404  { L("pointer does not point to a label"), FR_DNS_DECODE_FAIL_POINTER_TO_NON_LABEL },
405  { L("pointer creates a loop"), FR_DNS_DECODE_FAIL_POINTER_LOOPS },
406  { L("invalid pointer"), FR_DNS_DECODE_FAIL_INVALID_POINTER },
407  { L("label overflows the packet"), FR_DNS_DECODE_FAIL_LABEL_OVERFLOWS_PACKET },
408  { L("too many characters in label"), FR_DNS_DECODE_FAIL_LABEL_TOO_LONG },
409  { L("query record header is missing"), FR_DNS_DECODE_FAIL_MISSING_QD_HEADER },
410  { L("missing TLV header in OPT RR"), FR_DNS_DECODE_FAIL_MISSING_TLV_HEADER },
411  { L("TLV overflows enclosing RR"), FR_DNS_DECODE_FAIL_TLV_OVERFLOWS_RR },
412 };
414 
415 static ssize_t decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, void *proto_ctx)
416 {
417  fr_dns_ctx_t *packet_ctx = proto_ctx;
418  fr_dns_decode_fail_t reason;
419 
420  if (data_len > 65535) return -1; /* packet is too big */
421 
422  /*
423  * Allow queries or answers
424  */
425  if (!fr_dns_packet_ok(data, data_len, true, &reason)) {
426  if (reason != FR_DNS_DECODE_FAIL_UNEXPECTED) goto fail;
427 
428  if (!fr_dns_packet_ok(data, data_len, false, &reason)) {
429  fail:
430  fr_strerror_printf("DNS packet malformed - %s",
431  fr_table_str_by_value(fr_dns_reason_fail_table, reason, "<INVALID>"));
432  return -1;
433  }
434  }
435 
436  packet_ctx->packet = data;
437  packet_ctx->packet_len = data_len;
438  packet_ctx->lb = fr_dns_labels_get(data, data_len, true);
439  fr_assert(packet_ctx->lb != NULL);
440 
441  return fr_dns_decode(ctx, out, data, data_len, packet_ctx);
442 }
443 
444 /*
445  * Test points
446  */
450  .func = decode_rr
451 };
452 
456  .func = decode_proto
457 };
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define UNUSED
Definition: build.h:313
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:509
void fr_dict_unknown_free(fr_dict_attr_t const **da)
Free dynamically allocated (unknown attributes)
Definition: dict_unknown.c:148
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition: dict_util.c:2925
fr_dict_attr_t * fr_dict_unknown_attr_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int num))
Initialise a fr_dict_attr_t from a number.
Definition: dict_unknown.c:345
#define PAIR_DECODE_OOM
Fatal error - Out of memory.
Definition: pair.h:46
#define PAIR_DECODE_FATAL_ERROR
Fatal error - Failed decoding the packet.
Definition: pair.h:50
ssize_t fr_pair_tlvs_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx, fr_pair_decode_value_t decode_tlv, fr_pair_tlvs_verify_t verify_tlvs, bool nested)
Decode a list of pairs from the network.
Definition: decode.c:148
ssize_t fr_pair_dns_labels_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *start, uint8_t const *data, size_t const data_len, fr_dns_labels_t *lb, bool exact)
Decode a DNS label or a list of DNS labels from the network.
Definition: decode.c:237
ssize_t fr_pair_array_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx, fr_pair_decode_value_t decode_value)
Decode an array of values from the network.
Definition: decode.c:41
ssize_t fr_pair_raw_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len)
Create a "raw" pair from the network data.
Definition: decode.c:79
talloc_free(reap)
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
Definition: merged_model.c:89
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
Definition: merged_model.c:119
@ FR_TYPE_BOOL
A truth value.
Definition: merged_model.c:95
@ FR_TYPE_GROUP
A grouping of other attributes.
Definition: merged_model.c:124
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
static unsigned int fr_bytes_from_bits(unsigned int bits)
Convert bits (as in prefix length) to bytes, rounding up.
Definition: nbo.h:228
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition: nbo.h:137
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition: pair.c:278
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition: pair.c:1340
HIDDEN fr_dict_attr_t const * attr_dns_ar
Definition: base.c:55
HIDDEN fr_dict_attr_t const * attr_dns_ns
Definition: base.c:54
HIDDEN fr_dict_attr_t const * attr_dns_packet
Definition: base.c:51
HIDDEN fr_dict_attr_t const * attr_dns_question
Definition: base.c:52
HIDDEN fr_dict_attr_t const * attr_dns_rr
Definition: base.c:53
fr_dns_labels_t * fr_dns_labels_get(uint8_t const *packet, size_t packet_len, bool init_mark)
Definition: base.c:375
bool fr_dns_packet_ok(uint8_t const *packet, size_t packet_len, bool query, fr_dns_decode_fail_t *reason)
Definition: base.c:100
fr_test_point_pair_decode_t dns_tp_decode_pair
Definition: decode.c:448
static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
Definition: decode.c:174
static ssize_t decode_rr(TALLOC_CTX *ctx, fr_pair_list_t *out, UNUSED fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx)
Decode DNS RR.
Definition: decode.c:338
#define DNS_GET_OPTION_LEN(_x)
Definition: decode.c:172
ssize_t fr_dns_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *packet, size_t packet_len, fr_dns_ctx_t *packet_ctx)
Decode a DNS packet.
Definition: decode.c:265
size_t fr_dns_reason_fail_table_len
Definition: decode.c:413
static int decode_test_ctx(void **out, TALLOC_CTX *ctx)
Definition: decode.c:375
static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
Definition: decode.c:66
static ssize_t decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, void *proto_ctx)
Definition: decode.c:415
static ssize_t decode_value_trampoline(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
Definition: decode.c:52
fr_table_num_ordered_t fr_dns_reason_fail_table[]
Definition: decode.c:387
#define DNS_GET_OPTION_NUM(_x)
Definition: decode.c:171
static ssize_t decode_record(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *attr, uint8_t const *rr, uint8_t const *end, fr_dns_ctx_t *packet_ctx, uint8_t const *counter)
Definition: decode.c:230
fr_test_point_proto_decode_t dns_tp_decode_proto
Definition: decode.c:454
static ssize_t decode_tlv_trampoline(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
Definition: decode.c:44
Implementation of the DNS protocol.
size_t packet_len
Definition: dns.h:85
#define DNS_HDR_LEN
Definition: dns.h:141
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition: dns.h:83
uint8_t const * packet
DNS labels can point anywhere in the packet :(.
Definition: dns.h:84
fr_dns_decode_fail_t
Definition: dns.h:111
@ FR_DNS_DECODE_FAIL_ANSWERS_IN_QUESTION
Definition: dns.h:117
@ FR_DNS_DECODE_FAIL_TOO_MANY_RRS
Definition: dns.h:124
@ FR_DNS_DECODE_FAIL_RR_OVERFLOWS_PACKET
Definition: dns.h:123
@ FR_DNS_DECODE_FAIL_INVALID_RR_LABEL
Definition: dns.h:119
@ FR_DNS_DECODE_FAIL_POINTER_TO_NON_LABEL
Definition: dns.h:126
@ FR_DNS_DECODE_FAIL_INVALID_POINTER
Definition: dns.h:130
@ FR_DNS_DECODE_FAIL_POINTER_OVERFLOWS_PACKET
Definition: dns.h:127
@ FR_DNS_DECODE_FAIL_LABEL_OVERFLOWS_PACKET
Definition: dns.h:131
@ FR_DNS_DECODE_FAIL_MISSING_TLV_HEADER
Definition: dns.h:134
@ FR_DNS_DECODE_FAIL_UNEXPECTED
Definition: dns.h:115
@ FR_DNS_DECODE_FAIL_POINTER_TO_HEADER
Definition: dns.h:128
@ FR_DNS_DECODE_FAIL_ZERO_RR_LEN
Definition: dns.h:122
@ FR_DNS_DECODE_FAIL_LABEL_TOO_LONG
Definition: dns.h:132
@ FR_DNS_DECODE_FAIL_TOO_FEW_RRS
Definition: dns.h:125
@ FR_DNS_DECODE_FAIL_MISSING_RR_LEN
Definition: dns.h:121
@ FR_DNS_DECODE_FAIL_MISSING_QD_HEADER
Definition: dns.h:133
@ FR_DNS_DECODE_FAIL_MAX_LENGTH_PACKET
Definition: dns.h:114
@ FR_DNS_DECODE_FAIL_NS_IN_QUESTION
Definition: dns.h:118
@ FR_DNS_DECODE_FAIL_NO_QUESTIONS
Definition: dns.h:116
@ FR_DNS_DECODE_FAIL_NONE
Definition: dns.h:112
@ FR_DNS_DECODE_FAIL_TLV_OVERFLOWS_RR
Definition: dns.h:135
@ FR_DNS_DECODE_FAIL_POINTER_LOOPS
Definition: dns.h:129
@ FR_DNS_DECODE_FAIL_MISSING_RR_HEADER
Definition: dns.h:120
@ FR_DNS_DECODE_FAIL_MIN_LENGTH_PACKET
Definition: dns.h:113
fr_dns_labels_t * lb
Definition: dns.h:86
VQP attributes.
return count
Definition: module.c:175
fr_assert(0)
fr_pair_t * vp
ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, bool nested, void *decode_ctx, fr_pair_decode_value_t decode_value, fr_pair_decode_value_t decode_tlv)
Convert a STRUCT to one or more VPs.
Definition: struct.c:33
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition: pair.h:69
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:253
An element in an arbitrarily ordered array of name to num mappings.
Definition: table.h:53
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition: test_point.h:84
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition: test_point.h:66
Entry point for pair decoders.
Definition: test_point.h:83
Entry point for protocol decoders.
Definition: test_point.h:65
static fr_slen_t parent
Definition: pair.h:844
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition: proto.h:41
#define FR_PROTO_TRACE(_fmt,...)
Definition: proto.h:40
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Decode a fr_value_box_t from serialized binary data.
Definition: value.c:1709
static fr_slen_t data
Definition: value.h:1259
static size_t char ** out
Definition: value.h:984