The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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: eab30c4c1cfad29dc024fb283809123fb1a915ce $
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
39static 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
43static 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
47static 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
51static 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 */
70static 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
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 */
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 */
169 FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
170 break;
171
173 fr_strerror_const("invalid data type - ipv4prefix");
175
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 }
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;
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;
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);
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);
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) {
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
512static int encode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict)
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
526static 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 */
557
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:322
#define UNUSED
Definition build.h:315
#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_set(_dst, _src)
Set the 'current' position in a dbuff or marker using another dbuff or marker, a char pointer,...
Definition dbuff.h:1004
#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
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_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
#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
static ssize_t encode_value(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encodes the data portion of an attribute.
Definition encode.c:272
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:736
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 attribute header.
Definition encode.c:587
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
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
long int ssize_t
unsigned char uint8_t
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
static int encode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict)
Definition encode.c:165
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:358
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:71
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
fr_test_point_pair_encode_t dns_tp_encode_pair
Definition encode.c:553
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 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
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
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:38
return count
Definition module.c:163
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:93
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition test_point.h:75
Entry point for pair encoders.
Definition test_point.h:92
Entry point for protocol encoders.
Definition test_point.h:74
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:322
#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
#define fr_type_is_structural(_x)
Definition types.h:371
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:433
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