The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
encode.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: 3acb03c834f7aa463a8b65296c1ddcbf65728f9e $
19  *
20  * @file protocols/dns/encode.c
21  * @brief Functions to encode DNS packets
22  *
23  * @author Alan DeKok (aland@freeradius.org)
24  *
25  * @copyright 2021 NetworkRADIUS SARL (legal@networkradius.com)
26  */
27 #include <freeradius-devel/io/test_point.h>
28 #include <freeradius-devel/util/dbuff.h>
29 #include <freeradius-devel/util/dns.h>
30 #include <freeradius-devel/util/proto.h>
31 #include <freeradius-devel/util/struct.h>
32 #include <freeradius-devel/util/encode.h>
33 
34 #include "dns.h"
35 #include "attrs.h"
36 
37 #define DNS_OPT_HDR_LEN (4)
38 
39 static ssize_t encode_value(fr_dbuff_t *dbuff,
40  fr_da_stack_t *da_stack, unsigned int depth,
41  fr_dcursor_t *cursor, void *encode_ctx);
42 
43 static ssize_t encode_rfc(fr_dbuff_t *dbuff,
44  fr_da_stack_t *da_stack, unsigned int depth,
45  fr_dcursor_t *cursor, void *encode_ctx);
46 
47 static ssize_t encode_tlv(fr_dbuff_t *dbuff,
48  fr_da_stack_t *da_stack, unsigned int depth,
49  fr_dcursor_t *cursor, void *encode_ctx);
50 
51 static ssize_t encode_child(fr_dbuff_t *dbuff,
52  fr_da_stack_t *da_stack, unsigned int depth,
53  fr_dcursor_t *cursor, void *encode_ctx);
54 
55 /** Macro-like function for encoding an option header
56  *
57  * 0 1 2 3
58  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
59  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60  * | option-code | option-len |
61  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62  *
63  * @param[out] m Where to write the 4 byte option header.
64  * @param[in] option The option number (host byte order).
65  * @param[in] data_len The length of the option (host byte order).
66  * @return
67  * - <0 How much data would have been required as a negative value.
68  * - 4 The length of data written.
69  */
70 static inline ssize_t encode_option_hdr(fr_dbuff_marker_t *m, uint16_t option, size_t data_len)
71 {
72  FR_DBUFF_IN_RETURN(m, option);
73  FR_DBUFF_IN_RETURN(m, (uint16_t) data_len);
74 
75  return sizeof(option) + sizeof(uint16_t);
76 }
77 
78 
80  fr_da_stack_t *da_stack, unsigned int depth,
81  fr_dcursor_t *cursor, void *encode_ctx)
82 {
83  ssize_t slen;
84  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
85  fr_pair_t const *vp = fr_dcursor_current(cursor);
86  fr_dict_attr_t const *da = da_stack->da[depth];
87  fr_dns_ctx_t *packet_ctx = encode_ctx;
88 
89  PAIR_VERIFY(vp);
90  FR_PROTO_STACK_PRINT(da_stack, depth);
91 
92  /*
93  * Nested structs
94  */
95  if (vp->vp_type == FR_TYPE_STRUCT) {
96  fr_dcursor_t child_cursor;
97 
98  fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
99 
100  slen = fr_struct_to_network(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx, encode_value, encode_child);
101  if (slen < 0) return slen;
102 
103  /*
104  * Rebuild the da_stack for the next option.
105  */
106  vp = fr_dcursor_next(cursor);
107  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
108  return fr_dbuff_set(dbuff, &work_dbuff);
109  }
110 
111  /*
112  * Flat-list
113  */
114  if (da->type == FR_TYPE_STRUCT) {
115  slen = fr_struct_to_network(&work_dbuff, da_stack, depth, cursor, encode_ctx, encode_value, encode_child);
116  if (slen <= 0) return slen;
117 
118  /*
119  * Rebuild the da_stack for the next option.
120  */
121  vp = fr_dcursor_current(cursor);
122  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
123  return fr_dbuff_set(dbuff, &work_dbuff);
124  }
125  /*
126  * If it's not a TLV, it should be a value type RFC
127  * attribute make sure that it is.
128  */
129  if (da_stack->da[depth + 1] != NULL) {
130  fr_strerror_printf("%s: Encoding value but not at top of stack", __FUNCTION__);
132  }
133 
134  if (vp->da != da) {
135  fr_strerror_printf("%s: Top of stack does not match vp->da", __FUNCTION__);
137  }
138 
139  switch (vp->vp_type) {
140  case FR_TYPE_TLV:
141  case FR_TYPE_VENDOR:
142  case FR_TYPE_VSA:
143  case FR_TYPE_GROUP:
144  fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__,
145  fr_type_to_str(da->type));
147 
148  case FR_TYPE_STRING:
149  /*
150  * DNS labels get a special encoder.
151  */
152  if (fr_dns_flag_dns_label_any(da)) {
153  fr_dbuff_marker_t last_byte, src;
154 
155  fr_dbuff_marker(&last_byte, &work_dbuff);
156  fr_dbuff_marker(&src, &work_dbuff);
157  FR_PROTO_TRACE("encode DNS label %s", vp->vp_strvalue);
159  &vp->data, packet_ctx->lb);
160  if (slen < 0) return slen;
161  break;
162  }
163  goto to_network;
164 
165  /*
166  * Common encoder might add scope byte, so we just copy the address portion
167  */
168  case FR_TYPE_IPV6_ADDR:
169  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
170  break;
171 
172  case FR_TYPE_IPV4_PREFIX:
173  fr_strerror_const("invalid data type - ipv4prefix");
175 
176  case FR_TYPE_IPV6_PREFIX:
177  fr_strerror_const("invalid data type - ipv4prefix");
179 
180  case FR_TYPE_BOOL:
181  /*
182  * Don't encode anything! The mere existence of
183  * the attribute signifies a "true" value.
184  */
185  break;
186 
187  /*
188  * The value_box functions will take care of fixed-width
189  * "string" and "octets" options.
190  */
191  to_network:
192  case FR_TYPE_OCTETS:
193  /*
194  * Hack until we find all places that don't set data.enumv
195  */
196  if (vp->da->flags.length && (vp->data.enumv != vp->da)) {
197  fr_dict_attr_t const * const *c = &vp->data.enumv;
198  fr_dict_attr_t **u;
199 
200  memcpy(&u, &c, sizeof(c)); /* const issues */
201  memcpy(u, &vp->da, sizeof(vp->da));
202  }
203  FALL_THROUGH;
204 
205  default:
206  slen = fr_value_box_to_network(&work_dbuff, &vp->data);
207  if (slen < 0) return PAIR_ENCODE_FATAL_ERROR;
208  break;
209  }
210 
211  /*
212  * Rebuilds the TLV stack for encoding the next attribute
213  */
214  vp = fr_dcursor_next(cursor);
215  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
216 
217  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "done value");
218 
219  return fr_dbuff_set(dbuff, &work_dbuff);
220 }
221 
223  fr_da_stack_t *da_stack, unsigned int depth,
224  fr_dcursor_t *cursor, void *encode_ctx)
225 {
226  ssize_t len;
227  fr_pair_t *vp = fr_dcursor_current(cursor);
228  fr_dcursor_t child_cursor;
229  fr_dbuff_t work_dbuff;
230 
231  if (da_stack->da[depth]) {
232  /*
233  * Determine the nested type and call the appropriate encoder
234  */
235  switch (da_stack->da[depth]->type) {
236  case FR_TYPE_TLV:
237  if (!da_stack->da[depth + 1]) break;
238 
239  return encode_tlv(dbuff, da_stack, depth, cursor, encode_ctx);
240 
241  case FR_TYPE_GROUP:
242  if (!da_stack->da[depth + 1]) break;
243  FALL_THROUGH;
244 
245  default:
246  return encode_rfc(dbuff, da_stack, depth, cursor, encode_ctx);
247  }
248  }
249 
251 
252  fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
253  work_dbuff = FR_DBUFF(dbuff);
254 
255  while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
256  fr_proto_da_stack_build(da_stack, vp->da);
257 
258  switch (da_stack->da[depth]->type) {
259  case FR_TYPE_TLV:
260  len = encode_tlv(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx);
261  break;
262 
263  default:
264  len = encode_rfc(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx);
265  break;
266  }
267 
268  if (len <= 0) return len;
269  }
270 
271  /*
272  * Skip over the attribute we just encoded.
273  */
274  vp = fr_dcursor_next(cursor);
275  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
276 
277  return fr_dbuff_set(dbuff, &work_dbuff);
278 }
279 
280 /** Encode an RFC format TLV.
281  *
282  * This could be a standard attribute, or a TLV data type.
283  * If it's a standard attribute, then vp->da->attr == attribute.
284  * Otherwise, attribute may be something else.
285  */
287  fr_da_stack_t *da_stack, unsigned int depth,
288  fr_dcursor_t *cursor, void *encode_ctx)
289 {
290  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
291  fr_dbuff_marker_t hdr;
292  fr_dict_attr_t const *da = da_stack->da[depth];
293  ssize_t len;
294 
295  FR_PROTO_STACK_PRINT(da_stack, depth);
296  fr_dbuff_marker(&hdr, &work_dbuff);
297 
298  /*
299  * Make space for the header...
300  */
302  fr_dbuff_advance(&work_dbuff, DNS_OPT_HDR_LEN);
303 
304  /*
305  * Write out the option's value
306  */
307  if (da->flags.array) {
308  len = fr_pair_array_to_network(&work_dbuff, da_stack, depth, cursor, encode_ctx, encode_value);
309  } else {
310  len = encode_value(&work_dbuff, da_stack, depth, cursor, encode_ctx);
311  }
312  if (len < 0) return len;
313 
314  /*
315  * Write out the option number and length (before the value we just wrote)
316  */
317  (void) encode_option_hdr(&hdr, (uint16_t)da->attr, (uint16_t) (fr_dbuff_used(&work_dbuff) - DNS_OPT_HDR_LEN));
318 
319  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "Done RFC header");
320 
321  return fr_dbuff_set(dbuff, &work_dbuff);
322 }
323 
325  fr_da_stack_t *da_stack, unsigned int depth,
326  fr_dcursor_t *cursor, void *encode_ctx)
327 {
328  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
329  fr_dbuff_marker_t hdr;
330  fr_dict_attr_t const *da = da_stack->da[depth];
331  ssize_t len;
332 
333  fr_dbuff_marker(&hdr, &work_dbuff);
335  FR_PROTO_STACK_PRINT(da_stack, depth);
336 
337  if (da_stack->da[depth]->type != FR_TYPE_TLV) {
338  fr_strerror_printf("%s: Expected type \"tlv\" got \"%s\"", __FUNCTION__,
339  fr_type_to_str(da_stack->da[depth]->type));
341  }
342 
343  if (!da_stack->da[depth + 1]) {
344  fr_assert(0);
345  fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__);
347  }
348 
349  FR_DBUFF_ADVANCE_RETURN(&work_dbuff, DNS_OPT_HDR_LEN); /* Make room for option header */
350 
351  len = fr_pair_cursor_to_network(&work_dbuff, da_stack, depth, cursor, encode_ctx, encode_child);
352  if (len < 0) return len;
353 
354  /*
355  * 0 1 2 3
356  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
357  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
358  * | option-code | option-len |
359  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
360  */
361  (void) encode_option_hdr(&hdr, (uint16_t)da->attr, (uint16_t) (fr_dbuff_used(&work_dbuff) - DNS_OPT_HDR_LEN));
362 
363  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "Done TLV header");
364 
365  return fr_dbuff_set(dbuff, &work_dbuff);
366 }
367 
368 
369 /** Encode a Dns option and any sub-options.
370  *
371  * @param[out] dbuff Where to write encoded DHCP attributes.
372  * @param[in] cursor with current VP set to the option to be encoded.
373  * Will be advanced to the next option to encode.
374  * @param[in] encode_ctx containing parameters for the encoder.
375  * @return
376  * - > 0 length of data written.
377  * - < 0 error.
378  */
380 {
381  ssize_t slen;
382  fr_pair_t *vp;
383  fr_da_stack_t da_stack;
384  fr_dbuff_t work_dbuff = FR_DBUFF_MAX(dbuff, UINT16_MAX);
385 
387  FR_PROTO_STACK_PRINT(&da_stack, 0);
388 
389  FR_PROTO_TRACE("encode_rr -- remaining %zd", fr_dbuff_remaining(&work_dbuff));
390 
391  vp = fr_dcursor_current(cursor);
392  if (vp->vp_type == FR_TYPE_STRUCT) {
393  fr_dcursor_t child_cursor;
394 
395  fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
396 
397  slen = fr_struct_to_network(&work_dbuff, &da_stack, 0, &child_cursor, encode_ctx, encode_value, encode_child);
398  if (slen <= 0) return slen;
399  (void) fr_dcursor_next(cursor);
400 
401  } else {
402  slen = fr_struct_to_network(&work_dbuff, &da_stack, 0, cursor, encode_ctx, encode_value, encode_child);
403  if (slen <= 0) return slen;
404  }
405 
406  FR_PROTO_TRACE("Complete rr is %zu byte(s)", fr_dbuff_used(&work_dbuff));
407  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), NULL);
408 
409  return fr_dbuff_set(dbuff, &work_dbuff);
410 }
411 
413  fr_dict_attr_t const *attr, fr_dns_ctx_t *packet_ctx, uint8_t *counter)
414 {
415  int count;
416  fr_pair_t *vp;
417  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
418  fr_dcursor_t cursor;
419 
420  vp = fr_pair_dcursor_by_da_init(&cursor, vps, attr);
421  if (!vp) {
422  FR_PROTO_TRACE(" %s not found in list", attr->name);
423  return 0;
424  }
425 
426  fr_proto_da_stack_build(da_stack, attr);
427 
428  count = 0;
429  while (count < 65535) {
430  ssize_t slen;
431  fr_dcursor_t child_cursor;
432 
433  fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
434  slen = fr_struct_to_network(&work_dbuff, da_stack, 0, &child_cursor, packet_ctx, encode_value, encode_child);
435  if (slen <= 0) return slen;
436 
437  count++;
438  vp = fr_dcursor_next(&cursor);
439  if (!vp) break;
440  }
441 
442  fr_nbo_from_uint16(counter, count);
443  FR_PROTO_TRACE(" %s encoded %d records", attr->name, count);
444 
445  return fr_dbuff_set(dbuff, &work_dbuff);
446 }
447 
448 /** Encode a DNS packet
449  *
450  */
452 {
453  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
454  ssize_t slen;
455  uint8_t *packet;
456  fr_pair_t *vp;
457  fr_dcursor_t cursor, child_cursor;
458  fr_da_stack_t da_stack;
459 
460  packet = fr_dbuff_current(&work_dbuff);
461  fr_assert(packet == packet_ctx->packet);
462 
463  /*
464  * @todo - find maximum packet length, and limit work_dbuff to that.
465  */
467  if (!vp) {
468  fr_pair_list_debug(vps);
469 
470  fr_strerror_const("attribute list does not include DNS packet header");
471  return -1;
472  }
473 
474  /*
475  * Encode the header.
476  */
477  fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
479 
480  slen = fr_struct_to_network(&work_dbuff, &da_stack, 0, &cursor, packet_ctx, encode_value, NULL);
481  if (slen <= 0) return slen;
482 
483  fr_assert(slen == DNS_HDR_LEN);
484 
485  /*
486  * Encode questions
487  */
488  slen = encode_record(&work_dbuff, &da_stack, vps, attr_dns_question, packet_ctx, packet + 4);
489  if (slen < 0) return slen - (fr_dbuff_current(&work_dbuff) - packet);
490 
491  /*
492  * Encode answers
493  */
494  slen = encode_record(&work_dbuff, &da_stack, vps, attr_dns_rr, packet_ctx, packet + 6);
495  if (slen < 0) return slen - (fr_dbuff_current(&work_dbuff) - packet);
496 
497  /*
498  * Encode NS records
499  */
500  slen = encode_record(&work_dbuff, &da_stack, vps, attr_dns_ns, packet_ctx, packet + 8);
501  if (slen < 0) return slen - (fr_dbuff_current(&work_dbuff) - packet);
502 
503  /*
504  * Encode additional records
505  */
506  slen = encode_record(&work_dbuff, &da_stack, vps, attr_dns_ar, packet_ctx, packet + 10);
507  if (slen < 0) return slen - (fr_dbuff_current(&work_dbuff) - packet);
508 
509  return fr_dbuff_set(dbuff, &work_dbuff);
510 }
511 
512 static int encode_test_ctx(void **out, TALLOC_CTX *ctx)
513 {
514  fr_dns_ctx_t *test_ctx;
515 
516  test_ctx = talloc_zero(ctx, fr_dns_ctx_t);
517  if (!test_ctx) return -1;
518 
519  test_ctx->tmp_ctx = talloc(test_ctx, uint8_t);
520 
521  *out = test_ctx;
522 
523  return 0;
524 }
525 
526 static ssize_t fr_dns_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len, void *proto_ctx)
527 {
528  ssize_t slen;
529  fr_dns_ctx_t *packet_ctx = (fr_dns_ctx_t *) proto_ctx;
530 
531  packet_ctx->packet = data;
532  packet_ctx->packet_len = data_len;
533  packet_ctx->lb = fr_dns_labels_get(data, data_len, false);
534  fr_assert(packet_ctx->lb != NULL);
535 
536  slen = fr_dns_encode(&FR_DBUFF_TMP(data, data_len), vps, packet_ctx);
537 
538 #ifndef NDEBUG
539  if (slen <= 0) return slen;
540 
541  if (fr_debug_lvl > 2) {
542 // fr_dns_print_hex(stdout, data, slen);
543  }
544 #endif
545 
546  return slen;
547 }
548 
549 /*
550  * Test points
551  */
555  .func = fr_dns_encode_rr,
556 };
557 
561  .func = fr_dns_encode_proto
562 };
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define UNUSED
Definition: build.h:313
#define fr_dbuff_advance(_dbuff_or_marker, _len)
Advance 'current' position in dbuff or marker by _len bytes.
Definition: dbuff.h:1072
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition: dbuff.h:767
#define FR_DBUFF_ADVANCE_RETURN(_dbuff_or_marker, _len)
Advance the 'current' position in dbuff or marker by _len bytes returning if _len is out of range.
Definition: dbuff.h:1088
#define FR_DBUFF_EXTEND_LOWAT_OR_RETURN(_dbuff_or_marker, _lowat)
Extend if we're below _lowat and return if we can't extend above _lowat.
Definition: dbuff.h:673
struct fr_dbuff_marker_s fr_dbuff_marker_t
A position marker associated with a dbuff.
Definition: dbuff.h:81
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
Definition: dbuff.h:911
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition: dbuff.h:898
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
Definition: dbuff.h:743
#define FR_DBUFF_IN_MEMCPY_RETURN(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into dbuff or marker returning if there's insufficient space.
Definition: dbuff.h:1382
#define FR_DBUFF_IN_RETURN(_dbuff_or_marker, _in)
Copy data from a fixed sized C type into a dbuff returning if there is insufficient space.
Definition: dbuff.h:1585
#define FR_DBUFF(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
Definition: dbuff.h:222
#define FR_DBUFF_MAX(_dbuff_or_marker, _max)
Limit the maximum number of bytes available in the dbuff when passing it to another function.
Definition: dbuff.h:301
static uint8_t * fr_dbuff_marker(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff)
Initialises a new marker pointing to the 'current' position of the dbuff.
Definition: dbuff.h:1192
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:514
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition: dcursor.h:288
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
Definition: dcursor.h:337
ssize_t fr_dns_label_from_value_box_dbuff(fr_dbuff_t *dbuff, bool compression, fr_value_box_t const *value, fr_dns_labels_t *lb)
Encode a single value box of type string, serializing its contents to a dns label in a dbuff.
Definition: dns.c:604
#define PAIR_ENCODE_FATAL_ERROR
Fatal encoding error.
Definition: pair.h:36
ssize_t fr_pair_array_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, int depth, fr_dcursor_t *cursor, void *encode_ctx, fr_encode_dbuff_t encode_value)
Encode an array of values from the network.
Definition: encode.c:42
ssize_t fr_pair_cursor_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx, fr_encode_dbuff_t encode_pair)
Definition: encode.c:71
int fr_debug_lvl
Definition: log.c:43
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
@ 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_VENDOR
Attribute that represents a vendor in the attribute tree.
Definition: merged_model.c:122
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
Definition: merged_model.c:88
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
Definition: merged_model.c:87
@ FR_TYPE_BOOL
A truth value.
Definition: merged_model.c:95
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
Definition: merged_model.c:121
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
@ 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 uint8_t depth(fr_minmax_heap_index_t i)
Definition: minmax_heap.c:83
static void fr_nbo_from_uint16(uint8_t out[static sizeof(uint16_t)], uint16_t num)
Write out an unsigned 16bit integer in wire format (big endian)
Definition: nbo.h:38
void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da)
Build a complete DA stack from the da back to the root.
Definition: proto.c:118
static fr_internal_encode_ctx_t encode_ctx
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:383
Implementation of the DNS protocol.
#define fr_dns_flag_dns_label(_da)
Definition: dns.h:151
size_t packet_len
Definition: dns.h:76
static bool fr_dns_flag_dns_label_any(fr_dict_attr_t const *da)
Definition: dns.h:144
#define DNS_HDR_LEN
Definition: dns.h:132
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition: dns.h:74
uint8_t const * packet
DNS labels can point anywhere in the packet :(.
Definition: dns.h:75
fr_dns_labels_t * lb
Definition: dns.h:77
fr_test_point_proto_encode_t dns_tp_encode_proto
Definition: encode.c:559
#define DNS_OPT_HDR_LEN
Definition: encode.c:37
static ssize_t encode_option_hdr(fr_dbuff_marker_t *m, uint16_t option, size_t data_len)
Macro-like function for encoding an option header.
Definition: encode.c:70
fr_test_point_pair_encode_t dns_tp_encode_pair
Definition: encode.c:553
static ssize_t encode_value(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Definition: encode.c:79
static ssize_t fr_dns_encode_rr(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx)
Encode a Dns option and any sub-options.
Definition: encode.c:379
static ssize_t encode_child(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Definition: encode.c:222
static ssize_t encode_tlv(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Definition: encode.c:324
static ssize_t fr_dns_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len, void *proto_ctx)
Definition: encode.c:526
static ssize_t encode_record(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, fr_pair_list_t *vps, fr_dict_attr_t const *attr, fr_dns_ctx_t *packet_ctx, uint8_t *counter)
Definition: encode.c:412
static int encode_test_ctx(void **out, TALLOC_CTX *ctx)
Definition: encode.c:512
ssize_t fr_dns_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_dns_ctx_t *packet_ctx)
Encode a DNS packet.
Definition: encode.c:451
static ssize_t encode_rfc(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encode an RFC format TLV.
Definition: encode.c:286
VQP attributes.
return count
Definition: module.c:163
fr_assert(0)
fr_pair_t * vp
ssize_t fr_struct_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *parent_cursor, void *encode_ctx, fr_encode_dbuff_t encode_value, fr_encode_dbuff_t encode_pair)
Definition: struct.c:470
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
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition: test_point.h:112
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition: test_point.h:94
Entry point for pair encoders.
Definition: test_point.h:111
Entry point for protocol encoders.
Definition: test_point.h:93
static fr_pair_t * fr_pair_dcursor_child_iter_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dcursor_t const *parent)
Initializes a child dcursor from a parent cursor, with an iteration function.
Definition: pair.h:611
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
Definition: pair.h:628
#define PAIR_VERIFY(_x)
Definition: pair.h:191
void fr_pair_list_debug(fr_pair_list_t const *list)
Dumps a list to the default logging destination - Useful for calling from debuggers.
Definition: pair_print.c:318
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition: pair.h:591
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition: proto.h:41
#define FR_PROTO_TRACE(_fmt,...)
Definition: proto.h:40
#define FR_PROTO_STACK_PRINT(_stack, _depth)
Definition: proto.h:43
fr_dict_attr_t const * da[FR_DICT_MAX_TLV_STACK+1]
The stack.
Definition: proto.h:56
Structure for holding the stack of dictionary attributes being encoded.
Definition: proto.h:54
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition: types.h:433
#define fr_type_is_structural(_x)
Definition: types.h:371
return fr_dbuff_set(dbuff, &our_dbuff)
ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
Encode a single value box, serializing its contents in generic network format.
Definition: value.c:1404
static fr_slen_t data
Definition: value.h:1265
static size_t char ** out
Definition: value.h:997