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: 962463de50624e182ab24d1b7ae5073c0f4707f7 $
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 uint8_t prefix_len;
76 fr_dict_attr_t const *ref;
77
78 FR_PROTO_HEX_DUMP(data, data_len, "decode_value");
79
80 switch (parent->type) {
81 case FR_TYPE_ATTR:
82 /*
83 * Force the length of the data to be two,
84 * otherwise the "from network" call complains.
85 * Because we pass in the enumv as the _parent_
86 * and not the da. The da is marked as "array",
87 * but the parent is not.
88 */
89 if (data_len < 2) goto raw;
90
91 fr_assert(parent->parent->flags.is_root);
92
94 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 /*
118 * Structs used fixed length IPv6 addressews.
119 */
120 if (parent->parent->type == FR_TYPE_STRUCT) {
121 if (data_len != (1 + sizeof(vp->vp_ipv6addr))) {
122 goto raw;
123 }
124
125 vp = fr_pair_afrom_da(ctx, parent);
126 if (!vp) return PAIR_DECODE_OOM;
127
128 vp->vp_ip.af = AF_INET6;
129 vp->vp_ip.scope_id = 0;
130 vp->vp_ip.prefix = data[0];
131 memcpy(&vp->vp_ipv6addr, data + 1, sizeof(vp->vp_ipv6addr));
132 slen = 1 + sizeof(vp->vp_ipv6addr);
133 break;
134 }
135
136 /*
137 * No address, the prefix length MUST be zero.
138 */
139 if (data_len == 1) {
140 if (data[0] != 0) goto raw;
141
142 vp = fr_pair_afrom_da(ctx, parent);
143 if (!vp) return PAIR_DECODE_OOM;
144
145 vp->vp_ip.af = AF_INET6;
146 slen = 1;
147 break;
148 }
149
150 prefix_len = data[0];
151
152 /*
153 * If we have a /64 prefix but only 7 bytes of
154 * address, that's an error.
155 */
156 slen = fr_bytes_from_bits(prefix_len);
157 if ((size_t) slen > (data_len - 1)) {
158 goto raw;
159 }
160
161 vp = fr_pair_afrom_da(ctx, parent);
162 if (!vp) return PAIR_DECODE_OOM;
163
164 vp->vp_ip.af = AF_INET6;
165 vp->vp_ip.prefix = prefix_len;
166 memcpy(&vp->vp_ipv6addr, data + 1, slen);
167
168 slen++;
169 break;
170
171 /*
172 * A bool is encoded as an empty option if it's
173 * true. A bool is omitted entirely if it's
174 * false.
175 */
176 case FR_TYPE_BOOL:
177 if (data_len != 0) goto raw;
178 vp = fr_pair_afrom_da(ctx, parent);
179 if (!vp) return PAIR_DECODE_OOM;
180 vp->vp_bool = true;
181 slen = 0;
182 break;
183
184 /*
185 * A standard 32bit integer, but unlike normal UNIX timestamps
186 * starts from the 1st of January 2000.
187 *
188 * In the encoder we subtract 30 years to any values, so
189 * here we need to add that to the time here.
190 */
191 case FR_TYPE_DATE:
192 vp = fr_pair_afrom_da(ctx, parent);
193 if (!vp) return PAIR_DECODE_OOM;
194
195 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
196 &FR_DBUFF_TMP(data, data_len), data_len, true);
197 if (slen < 0) {
199 goto raw;
200 }
202 break;
203
204 case FR_TYPE_STRUCT:
205 slen = fr_struct_from_network(ctx, out, parent, data, data_len,
207 if (slen < 0) goto raw;
208
209 if (parent->flags.array) return slen;
210 return data_len;
211
212 case FR_TYPE_GROUP:
213 vp = fr_pair_afrom_da(ctx, parent);
214 if (!vp) return PAIR_DECODE_OOM;
215
217 if (ref && (ref->dict != dict_dhcpv6)) {
218 fr_dict_protocol_t const *proto;
219
220 proto = fr_dict_protocol(ref->dict);
221 fr_assert(proto != NULL);
222
223 if (!proto->decode) {
224 raw_free:
226 goto raw;
227 }
228
229 slen = proto->decode(vp, &vp->vp_group, data, data_len);
230 if (slen < 0) goto raw_free;
231
232 vp->vp_tainted = true;
233
234 } else {
235 if (!ref) ref = fr_dict_root(dict_dhcpv6);
236
237 /*
238 * Child VPs go into the child group, not in the main parent list. BUT, we start
239 * decoding attributes from the ref, and not from the group parent.
240 */
241 slen = fr_pair_tlvs_from_network(vp, &vp->vp_group, ref, data, data_len, decode_ctx, decode_option, NULL, false);
242 if (slen < 0) goto raw_free;
243 }
244
246 return data_len;
247
249 vp = fr_pair_afrom_da(ctx, parent);
250 if (!vp) return PAIR_DECODE_OOM;
251
252 /*
253 * Limit the IPv6 address to 16 octets, with no scope.
254 */
255 if (data_len < sizeof(vp->vp_ipv6addr)) goto raw;
256
257 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
258 &FR_DBUFF_TMP(data, sizeof(vp->vp_ipv6addr)), sizeof(vp->vp_ipv6addr), true);
259 if (slen < 0) goto raw_free;
260 break;
261
262 default:
263 vp = fr_pair_afrom_da(ctx, parent);
264 if (!vp) return PAIR_DECODE_OOM;
265
266 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
267 &FR_DBUFF_TMP(data, data_len), data_len, true);
268 if (slen < 0) goto raw_free;
269 break;
270 }
271
272 /*
273 * The input is larger than the decoded value, re-do it as a raw attribute.
274 */
275 if (!parent->flags.array && ((size_t) slen < data_len)) {
277 goto raw;
278 }
279
280 fr_assert(vp != NULL);
281
282 vp->vp_tainted = true;
284
285 if (parent->flags.array) return slen;
286
287 return data_len;
288}
289
290
291static ssize_t decode_vsa(TALLOC_CTX *ctx, fr_pair_list_t *out,
292 fr_dict_attr_t const *parent,
293 uint8_t const *data, size_t const data_len, void *decode_ctx)
294{
295 uint32_t pen;
296 fr_dict_attr_t const *da;
297 fr_pair_t *vp;
298 fr_dhcpv6_decode_ctx_t *packet_ctx = decode_ctx;
299
300 FR_PROTO_HEX_DUMP(data, data_len, "decode_vsa");
301
303 "%s: Internal sanity check failed, attribute \"%s\" is not of type 'vsa'",
304 __FUNCTION__, parent->name)) return PAIR_DECODE_FATAL_ERROR;
305
306 /*
307 * Enterprise code plus at least one option header
308 */
309 if (data_len < 8) return fr_pair_raw_from_network(ctx, out, parent, data, data_len);
310
311 memcpy(&pen, data, sizeof(pen));
312 pen = htonl(pen);
313
314 /*
315 * Verify that the parent (which should be a VSA)
316 * contains a fake attribute representing the vendor.
317 *
318 * If it doesn't then this vendor is unknown, but we know
319 * vendor attributes have a standard format, so we can
320 * decode the data anyway.
321 */
323 if (!da) {
325
327 if (!n) return PAIR_DECODE_OOM;
328 da = n;
329 }
330
331 FR_PROTO_TRACE("decode context %s -> %s", parent->name, da->name);
332
333 vp = fr_pair_find_by_da(out, NULL, da);
334 if (vp) {
335 return fr_pair_tlvs_from_network(vp, &vp->vp_group, da, data + 4, data_len - 4, decode_ctx, decode_option, NULL, false);
336 }
337
338 return fr_pair_tlvs_from_network(ctx, out, da, data + 4, data_len - 4, decode_ctx, decode_option, NULL, true);
339}
340
341static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
342 fr_dict_attr_t const *parent,
343 uint8_t const *data, size_t const data_len, void *decode_ctx)
344{
345 unsigned int option;
346 size_t len;
347 ssize_t slen;
348 fr_dict_attr_t const *da;
349 fr_dhcpv6_decode_ctx_t *packet_ctx = decode_ctx;
350
351#ifdef STATIC_ANALYZER
352 if (!packet_ctx || !packet_ctx->tmp_ctx) return PAIR_DECODE_FATAL_ERROR;
353#endif
354
355 /*
356 * Must have at least an option header.
357 */
358 if (data_len < 4) {
359 fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
360 return -(data_len);
361 }
362
363 option = DHCPV6_GET_OPTION_NUM(data);
365 if (len > (data_len - 4)) {
366 fr_strerror_printf("%s: Option overflows input. "
367 "Optional length must be less than %zu bytes, got %zu bytes",
368 __FUNCTION__, data_len - 4, len);
370 }
371
372 da = fr_dict_attr_child_by_num(parent, option);
373 if (!da) {
374 da = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, parent, option);
375 if (!da) return PAIR_DECODE_FATAL_ERROR;
376 }
377 FR_PROTO_TRACE("decode context changed %s -> %s",da->parent->name, da->name);
378
379 /*
380 * Relay messages are weird, and contain complete DHCPv6
381 * packets, copied verbatim from the DHCPv6 client.
382 */
383 if (da == attr_relay_message) {
384 fr_pair_t *vp;
385
387 if (!vp) return PAIR_DECODE_FATAL_ERROR;
388
389 slen = fr_dhcpv6_decode(vp, &vp->vp_group, data + 4, len);
390 if (slen < 0) {
392 raw:
393 slen = fr_pair_raw_from_network(ctx, out, da, data + 4, len);
394 if (slen < 0) return slen;
395 return 4 + slen;
396 }
397
399
400 } else if ((da->type == FR_TYPE_STRING) && fr_dhcpv6_flag_any_dns_label(da)) {
401 slen = fr_pair_dns_labels_from_network(ctx, out, da, data + 4, data + 4, len, NULL, true);
402 if (slen < 0) return slen;
403
404 } else if (da->flags.array) {
405 slen = fr_pair_array_from_network(ctx, out, da, data + 4, len, decode_ctx, decode_value);
406
407 } else if (da->type == FR_TYPE_VSA) {
408 bool append = false;
409 fr_pair_t *vp;
410
411 vp = fr_pair_find_by_da(out, NULL, da);
412 if (!vp) {
413 vp = fr_pair_afrom_da(ctx, da);
414 if (!vp) return PAIR_DECODE_FATAL_ERROR;
415
416 append = true;
417 }
418
419 slen = decode_vsa(vp, &vp->vp_group, da, data + 4, len, decode_ctx);
420 if (append) {
421 if (slen < 0) {
422 TALLOC_FREE(vp);
423 } else {
425 }
426 }
427
428 } else if (da->type == FR_TYPE_TLV) {
429 slen = fr_pair_tlvs_from_network(ctx, out, da, data + 4, len, decode_ctx, decode_option, NULL, true);
430
431 } else {
432 slen = decode_value(ctx, out, da, data + 4, len, decode_ctx);
433 }
434
435 if (slen < 0) goto raw;
436
437 return len + 4;
438}
439
440
441/** Create a "normal" fr_pair_t from the given data
442 *
443 * 0 1 2 3
444 * 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
445 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
446 * | option-code | option-len |
447 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
448 */
450 uint8_t const *data, size_t data_len, void *decode_ctx)
451{
452 FR_PROTO_HEX_DUMP(data, data_len, "fr_dhcpv6_decode_pair");
453
454 /*
455 * The API changes, so we just bounce directly to the
456 * decode_option() function.
457 *
458 * All options including VSAs in DHCPv6 MUST follow the
459 * standard format.
460 */
461 return decode_option(ctx, out, fr_dict_root(dict_dhcpv6), data, data_len, decode_ctx);
462}
463
465 uint8_t const *data, size_t data_len)
466{
467 ssize_t slen;
468 uint8_t const *attr, *end;
469
470 fr_dhcpv6_decode_ctx_t decode_ctx = {};
471
472 fr_assert(dict_dhcpv6 != NULL);
473
474 decode_ctx.tmp_ctx = talloc(ctx, uint8_t);
475
476 attr = data;
477 end = data + data_len;
478
479 while (attr < end) {
480 slen = fr_dhcpv6_decode_option(ctx, out, attr, (end - attr), &decode_ctx);
481 if (slen < 0) {
482 talloc_free(decode_ctx.tmp_ctx);
483 return slen;
484 }
485
486 /*
487 * If slen is larger than the room in the packet,
488 * all kinds of bad things happen.
489 */
490 if (!fr_cond_assert(slen <= (end - attr))) {
491 talloc_free(decode_ctx.tmp_ctx);
492 return -slen - (attr - data);
493 }
494
495 attr += slen;
496 talloc_free_children(decode_ctx.tmp_ctx);
497 }
498
499 talloc_free(decode_ctx.tmp_ctx);
500 return data_len;
501}
502
503static int decode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict)
504{
505 fr_dhcpv6_decode_ctx_t *test_ctx;
506
507 test_ctx = talloc_zero(ctx, fr_dhcpv6_decode_ctx_t);
508 if (!test_ctx) return -1;
509
510 test_ctx->tmp_ctx = talloc(test_ctx, uint8_t);
511
512 *out = test_ctx;
513
514 return 0;
515}
516
517static 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)
518{
519 size_t packet_len = data_len;
520// fr_dhcpv6_decode_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_dhcpv6_decode_ctx_t);
521
522 if (!fr_dhcpv6_ok(data, packet_len, 200)) return -1;
523
524 return fr_dhcpv6_decode(ctx, out, data, packet_len);
525}
526
527
529 uint8_t const *data, size_t data_len, void *decode_ctx)
530{
532
533 return decode_option(ctx, out, fr_dict_root(dict_dhcpv6), data, data_len, decode_ctx);
534}
535
536/*
537 * Test points
538 */
544
int n
Definition acutest.h:577
#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:514
#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:466
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:580
fr_dict_protocol_t const * fr_dict_protocol(fr_dict_t const *dict)
Return the protocol descriptor for the dictionary.
Definition dict_util.c:4994
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:587
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2403
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:3331
Protocol-specific callbacks in libfreeradius-PROTOCOL.
Definition dict.h:434
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:184
#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: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_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
static unsigned int fr_bytes_from_bits(unsigned int bits)
Convert bits (as in prefix length) to bytes, rounding up.
Definition nbo.h:237
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:698
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:1343
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:287
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)
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:452
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:368
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:449
fr_test_point_pair_decode_t dhcpv6_tp_decode_pair
Definition decode.c:540
fr_test_point_proto_decode_t dhcpv6_tp_decode_proto
Definition decode.c:546
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:464
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:517
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:528
#define decode_value
Definition decode.c:410
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:85
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition test_point.h:67
Entry point for pair decoders.
Definition test_point.h:84
Entry point for protocol decoders.
Definition test_point.h:66
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
static fr_slen_t parent
Definition pair.h:841
#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:83
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:1917
static fr_slen_t data
Definition value.h:1291
static size_t char ** out
Definition value.h:1023