The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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: 046738f83460ed03b8d0c27582387190bf17c710 $
19 *
20 * @file protocols/dhcpv6/decode.c
21 * @brief Functions to decode DHCP options.
22 *
23 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24 *
25 * @copyright 2018 The FreeRADIUS server project
26 * @copyright 2018 NetworkRADIUS SARL (legal@networkradius.com)
27 */
28#include <stdint.h>
29#include <stddef.h>
30
31#include <freeradius-devel/io/test_point.h>
32#include <freeradius-devel/util/dns.h>
33#include <freeradius-devel/util/proto.h>
34#include <freeradius-devel/util/struct.h>
35
36#include "dhcpv6.h"
37#include "attrs.h"
38
39static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
41 uint8_t const *data, size_t const data_len, void *decode_ctx);
42
45 uint8_t const *data, size_t const data_len, void *decode_ctx)
46{
47 return fr_pair_tlvs_from_network(ctx, out, parent, data, data_len, decode_ctx, decode_option, NULL, true);
48}
49
50static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
52 uint8_t const *data, size_t const data_len, void *decode_ctx);
53
54/** Handle arrays of DNS labels for fr_struct_from_network()
55 *
56 */
59 uint8_t const *data, size_t const data_len, void *decode_ctx)
60{
62 return fr_pair_dns_labels_from_network(ctx, out, parent, data, data, data_len, NULL, false);
63 }
64
65 return decode_value(ctx, out, parent, data, data_len, decode_ctx);
66}
67
68
69static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
71 uint8_t const *data, size_t const data_len, void *decode_ctx)
72{
73 ssize_t slen;
74 fr_pair_t *vp = NULL;
75 fr_dict_attr_t const *ref;
76
77 FR_PROTO_HEX_DUMP(data, data_len, "decode_value");
78
79 switch (parent->type) {
80 case FR_TYPE_ATTR:
81 /*
82 * Force the length of the data to be two,
83 * otherwise the "from network" call complains.
84 * Because we pass in the enumv as the _parent_
85 * and not the da. The da is marked as "array",
86 * but the parent is not.
87 */
88 if (data_len < 2) goto raw;
89
90 fr_assert(parent->parent->flags.is_root);
91
93 if (!vp) return PAIR_DECODE_OOM;
95
96 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, parent->parent,
97 &FR_DBUFF_TMP(data, 2), 2, true);
98 if (slen <= 0) {
99 TALLOC_FREE(vp);
100 goto raw;
101 }
102
103 vp->vp_tainted = true;
105 return 2;
106
107 /*
108 * Address MAY be shorter than 16 bytes.
109 */
111 if (data_len == 0) {
112 raw:
113 return fr_pair_raw_from_network(ctx, out, parent, data, data_len);
114
115 }
116
117 vp = fr_pair_afrom_da(ctx, parent);
118 if (!vp) return PAIR_DECODE_OOM;
120
121 slen = fr_value_box_ipaddr_from_network(&vp->data, parent->type, parent,
122 data[0], data + 1, data_len - 1,
123 (parent->parent->type == FR_TYPE_STRUCT), true);
124 if (slen < 0) goto raw_free;
125
126 slen++; /* account for the prefix */
127 break;
128
129 /*
130 * A bool is encoded as an empty option if it's
131 * true. A bool is omitted entirely if it's
132 * false.
133 */
134 case FR_TYPE_BOOL:
135 if (data_len != 0) goto raw;
136 vp = fr_pair_afrom_da(ctx, parent);
137 if (!vp) return PAIR_DECODE_OOM;
139
140 vp->vp_bool = true;
141 slen = 0;
142 break;
143
144 /*
145 * A standard 32bit integer, but unlike normal UNIX timestamps
146 * starts from the 1st of January 2000.
147 *
148 * In the encoder we subtract 30 years to any values, so
149 * here we need to add that to the time here.
150 */
151 case FR_TYPE_DATE:
152 vp = fr_pair_afrom_da(ctx, parent);
153 if (!vp) return PAIR_DECODE_OOM;
155
156 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
157 &FR_DBUFF_TMP(data, data_len), data_len, true);
158 if (slen < 0) {
160 goto raw;
161 }
163 break;
164
165 case FR_TYPE_STRUCT:
166 slen = fr_struct_from_network(ctx, out, parent, data, data_len,
168 if (slen < 0) goto raw;
169
170 if (parent->flags.array) return slen;
171 return data_len;
172
173 case FR_TYPE_GROUP:
174 vp = fr_pair_afrom_da(ctx, parent);
175 if (!vp) return PAIR_DECODE_OOM;
177
179 if (ref && (ref->dict != dict_dhcpv6)) {
180 fr_dict_protocol_t const *proto;
181
182 proto = fr_dict_protocol(ref->dict);
183 fr_assert(proto != NULL);
184
185 if (!proto->decode) {
186 raw_free:
188 goto raw;
189 }
190
191 slen = proto->decode(vp, &vp->vp_group, data, data_len);
192 if (slen < 0) goto raw_free;
193
194 vp->vp_tainted = true;
195
196 } else {
197 if (!ref) ref = fr_dict_root(dict_dhcpv6);
198
199 /*
200 * Child VPs go into the child group, not in the main parent list. BUT, we start
201 * decoding attributes from the ref, and not from the group parent.
202 */
203 slen = fr_pair_tlvs_from_network(vp, &vp->vp_group, ref, data, data_len, decode_ctx, decode_option, NULL, false);
204 if (slen < 0) goto raw_free;
205 }
206
208 return data_len;
209
211 vp = fr_pair_afrom_da(ctx, parent);
212 if (!vp) return PAIR_DECODE_OOM;
214
215 slen = fr_value_box_ipaddr_from_network(&vp->data, parent->type, parent,
216 128, data, data_len,
217 true, true);
218 if (slen < 0) goto raw_free;
219 break;
220
221 default:
222 vp = fr_pair_afrom_da(ctx, parent);
223 if (!vp) return PAIR_DECODE_OOM;
225
226 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
227 &FR_DBUFF_TMP(data, data_len), data_len, true);
228 if (slen < 0) goto raw_free;
229 break;
230 }
231
232 /*
233 * The input is larger than the decoded value, re-do it as a raw attribute.
234 */
235 if (!parent->flags.array && ((size_t) slen < data_len)) {
237 goto raw;
238 }
239
240 fr_assert(vp != NULL);
241
242 vp->vp_tainted = true;
244
245 if (parent->flags.array) return slen;
246
247 return data_len;
248}
249
250
251static ssize_t decode_vsa(TALLOC_CTX *ctx, fr_pair_list_t *out,
252 fr_dict_attr_t const *parent,
253 uint8_t const *data, size_t const data_len, void *decode_ctx)
254{
255 uint32_t pen;
256 fr_dict_attr_t const *da;
257 fr_pair_t *vp;
258 fr_dhcpv6_decode_ctx_t *packet_ctx = decode_ctx;
259
260 FR_PROTO_HEX_DUMP(data, data_len, "decode_vsa");
261
263 "%s: Internal sanity check failed, attribute \"%s\" is not of type 'vsa'",
264 __FUNCTION__, parent->name)) return PAIR_DECODE_FATAL_ERROR;
265
266 /*
267 * Enterprise code plus at least one option header
268 */
269 if (data_len < 8) return fr_pair_raw_from_network(ctx, out, parent, data, data_len);
270
271 memcpy(&pen, data, sizeof(pen));
272 pen = htonl(pen);
273
274 /*
275 * Verify that the parent (which should be a VSA)
276 * contains a fake attribute representing the vendor.
277 *
278 * If it doesn't then this vendor is unknown, but we know
279 * vendor attributes have a standard format, so we can
280 * decode the data anyway.
281 */
283 if (!da) {
285
287 if (!n) return PAIR_DECODE_OOM;
288 da = n;
289 }
290
291 FR_PROTO_TRACE("decode context %s -> %s", parent->name, da->name);
292
293 vp = fr_pair_find_by_da(out, NULL, da);
294 if (vp) {
295 return fr_pair_tlvs_from_network(vp, &vp->vp_group, da, data + 4, data_len - 4, decode_ctx, decode_option, NULL, false);
296 }
297
298 return fr_pair_tlvs_from_network(ctx, out, da, data + 4, data_len - 4, decode_ctx, decode_option, NULL, true);
299}
300
301static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
302 fr_dict_attr_t const *parent,
303 uint8_t const *data, size_t const data_len, void *decode_ctx)
304{
305 unsigned int option;
306 size_t len;
307 ssize_t slen;
308 fr_dict_attr_t const *da;
309 fr_dhcpv6_decode_ctx_t *packet_ctx = decode_ctx;
310
311#ifdef STATIC_ANALYZER
312 if (!packet_ctx || !packet_ctx->tmp_ctx) return PAIR_DECODE_FATAL_ERROR;
313#endif
314
315 /*
316 * Must have at least an option header.
317 */
318 if (data_len < 4) {
319 fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
320 return -(data_len);
321 }
322
323 option = DHCPV6_GET_OPTION_NUM(data);
325 if (len > (data_len - 4)) {
326 fr_strerror_printf("%s: Option overflows input. "
327 "Optional length must be less than %zu bytes, got %zu bytes",
328 __FUNCTION__, data_len - 4, len);
330 }
331
332 da = fr_dict_attr_child_by_num(parent, option);
333 if (!da) {
334 da = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, parent, option);
335 if (!da) return PAIR_DECODE_FATAL_ERROR;
336 }
337 FR_PROTO_TRACE("decode context changed %s -> %s",da->parent->name, da->name);
338
339 /*
340 * Relay messages are weird, and contain complete DHCPv6
341 * packets, copied verbatim from the DHCPv6 client.
342 */
343 if (da == attr_relay_message) {
344 fr_pair_t *vp;
345
347 if (!vp) return PAIR_DECODE_FATAL_ERROR;
349
350 slen = fr_dhcpv6_decode(vp, &vp->vp_group, data + 4, len);
351 if (slen < 0) {
353 raw:
354 slen = fr_pair_raw_from_network(ctx, out, da, data + 4, len);
355 if (slen < 0) return slen;
356 return 4 + slen;
357 }
358
360
361 } else if ((da->type == FR_TYPE_STRING) && fr_dhcpv6_flag_any_dns_label(da)) {
362 slen = fr_pair_dns_labels_from_network(ctx, out, da, data + 4, data + 4, len, NULL, true);
363 if (slen < 0) return slen;
364
365 } else if (da->flags.array) {
366 slen = fr_pair_array_from_network(ctx, out, da, data + 4, len, decode_ctx, decode_value);
367
368 } else if (da->type == FR_TYPE_VSA) {
369 bool append = false;
370 fr_pair_t *vp;
371
372 vp = fr_pair_find_by_da(out, NULL, da);
373 if (!vp) {
374 vp = fr_pair_afrom_da(ctx, da);
375 if (!vp) return PAIR_DECODE_FATAL_ERROR;
377
378 append = true;
379 }
380
381 slen = decode_vsa(vp, &vp->vp_group, da, data + 4, len, decode_ctx);
382 if (append) {
383 if (slen < 0) {
384 TALLOC_FREE(vp);
385 } else {
387 }
388 }
389
390 } else if (da->type == FR_TYPE_TLV) {
391 slen = fr_pair_tlvs_from_network(ctx, out, da, data + 4, len, decode_ctx, decode_option, NULL, true);
392
393 } else {
394 slen = decode_value(ctx, out, da, data + 4, len, decode_ctx);
395 }
396
397 if (slen < 0) goto raw;
398
399 return len + 4;
400}
401
402
403/** Create a "normal" fr_pair_t from the given data
404 *
405 * 0 1 2 3
406 * 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
407 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
408 * | option-code | option-len |
409 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
410 */
412 uint8_t const *data, size_t data_len, void *decode_ctx)
413{
414 FR_PROTO_HEX_DUMP(data, data_len, "fr_dhcpv6_decode_pair");
415
416 /*
417 * The API changes, so we just bounce directly to the
418 * decode_option() function.
419 *
420 * All options including VSAs in DHCPv6 MUST follow the
421 * standard format.
422 */
423 return decode_option(ctx, out, fr_dict_root(dict_dhcpv6), data, data_len, decode_ctx);
424}
425
427 uint8_t const *data, size_t data_len)
428{
429 ssize_t slen;
430 uint8_t const *attr, *end;
431
432 fr_dhcpv6_decode_ctx_t decode_ctx = {};
433
434 fr_assert(dict_dhcpv6 != NULL);
435
436 decode_ctx.tmp_ctx = talloc(ctx, uint8_t);
437
438 attr = data;
439 end = data + data_len;
440
441 while (attr < end) {
442 slen = fr_dhcpv6_decode_option(ctx, out, attr, (end - attr), &decode_ctx);
443 if (slen < 0) {
444 talloc_free(decode_ctx.tmp_ctx);
445 return slen;
446 }
447
448 /*
449 * If slen is larger than the room in the packet,
450 * all kinds of bad things happen.
451 */
452 if (!fr_cond_assert(slen <= (end - attr))) {
453 talloc_free(decode_ctx.tmp_ctx);
454 return -slen - (attr - data);
455 }
456
457 attr += slen;
458 talloc_free_children(decode_ctx.tmp_ctx);
459 }
460
461 talloc_free(decode_ctx.tmp_ctx);
462 return data_len;
463}
464
465static int decode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict,
466 UNUSED fr_dict_attr_t const *root_da)
467{
468 fr_dhcpv6_decode_ctx_t *test_ctx;
469
470 test_ctx = talloc_zero(ctx, fr_dhcpv6_decode_ctx_t);
471 if (!test_ctx) return -1;
472
473 test_ctx->tmp_ctx = talloc(test_ctx, uint8_t);
474
475 *out = test_ctx;
476
477 return 0;
478}
479
480static ssize_t fr_dhcpv6_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, UNUSED void *proto_ctx)
481{
482 size_t packet_len = data_len;
483// fr_dhcpv6_decode_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_dhcpv6_decode_ctx_t);
484
485 if (!fr_dhcpv6_ok(data, packet_len, 200)) return -1;
486
487 return fr_dhcpv6_decode(ctx, out, data, packet_len);
488}
489
490
492 uint8_t const *data, size_t data_len, void *decode_ctx)
493{
495
496 return decode_option(ctx, out, fr_dict_root(dict_dhcpv6), data, data_len, decode_ctx);
497}
498
499/*
500 * Test points
501 */
507
int n
Definition acutest.h:579
#define NDEBUG_UNUSED
Definition build.h:328
#define UNUSED
Definition build.h:317
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:524
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:131
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:148
Implementation of the DHCPv6 protocol.
#define DHCPV6_GET_OPTION_NUM(_x)
Definition dhcpv6.h:47
#define DHCPV6_GET_OPTION_LEN(_x)
Definition dhcpv6.h:48
static bool fr_dhcpv6_flag_any_dns_label(fr_dict_attr_t const *da)
Definition dhcpv6.h:152
#define DHCPV6_DATE_OFFSET
Definition dhcpv6.h:124
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition dhcpv6.h:133
fr_dict_attr_decode_func_t decode
for decoding attributes.
Definition dict.h:488
static fr_dict_attr_t * fr_dict_attr_unknown_vendor_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int vendor)
Definition dict.h:609
fr_dict_protocol_t const * fr_dict_protocol(fr_dict_t const *dict)
Return the protocol descriptor for the dictionary.
Definition dict_util.c:5285
static fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Definition dict.h:616
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2704
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:3632
Protocol-specific callbacks in libfreeradius-PROTOCOL.
Definition dict.h:456
static fr_dict_attr_t const * fr_dict_attr_ref(fr_dict_attr_t const *da)
Return the reference associated with a group type attribute.
Definition dict_ext.h:178
#define PAIR_DECODE_OOM
Fatal error - Out of memory.
Definition pair.h:45
#define PAIR_DECODE_FATAL_ERROR
Fatal error - Failed decoding the packet.
Definition pair.h:49
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:149
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:246
ssize_t fr_pair_raw_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *da, uint8_t const *data, size_t data_len)
Create a "raw" pair from malformed network data.
Definition decode.c:79
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
talloc_free(reap)
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_GROUP
A grouping of other attributes.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:703
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:1348
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:289
static fr_dict_t const * dict_dhcpv6
static fr_dict_attr_t const * attr_relay_message
static int decode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict, UNUSED fr_dict_attr_t const *root_da)
Definition decode.c:102
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:454
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)
Handle arrays of DNS labels for fr_struct_from_network()
Definition decode.c:70
static ssize_t decode_vsa(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)
RFC 4243 Vendor Specific Suboptions.
Definition decode.c:369
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:57
bool fr_dhcpv6_ok(uint8_t const *packet, size_t packet_len, uint32_t max_attributes)
See if the data pointed to by PTR is a valid DHCPv6 packet.
Definition base.c:231
ssize_t fr_dhcpv6_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *packet, size_t packet_len)
Decode a DHCPv6 packet.
Definition base.c:582
ssize_t fr_dhcpv6_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, void *decode_ctx)
Create a "normal" fr_pair_t from the given data.
Definition decode.c:411
fr_test_point_pair_decode_t dhcpv6_tp_decode_pair
Definition decode.c:503
fr_test_point_proto_decode_t dhcpv6_tp_decode_proto
Definition decode.c:509
ssize_t fr_dhcpv6_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len)
Definition decode.c:426
static ssize_t fr_dhcpv6_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, UNUSED void *proto_ctx)
Definition decode.c:480
static ssize_t decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, NDEBUG_UNUSED fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx)
Definition decode.c:491
#define decode_value
Definition decode.c:411
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:38
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, 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:32
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:86
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition test_point.h:68
Entry point for pair decoders.
Definition test_point.h:85
Entry point for protocol decoders.
Definition test_point.h:67
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_unix_time_add(_a, _b)
Add a time/time delta together.
Definition time.h:324
#define PAIR_ALLOCED(_x)
Definition pair.h:212
static fr_slen_t parent
Definition pair.h:857
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition proto.h:42
#define FR_PROTO_TRACE(_fmt,...)
Definition proto.h:41
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
@ FR_TYPE_ATTR
A contains an attribute reference.
Definition types.h:84
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:1913
ssize_t fr_value_box_ipaddr_from_network(fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, int prefix_len, uint8_t const *data, size_t data_len, bool fixed, bool tainted)
Decode a fr_value_box_t of type IP address / prefix.
Definition value.c:2317
static fr_slen_t data
Definition value.h:1326
static size_t char ** out
Definition value.h:1023