The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
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: 655434c4f523480cd692a8f265f73a5a820da8e9 $
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
39/*
40 * RFC 8415 Section 21.7 defines option codes that MUST NOT appear
41 * in an Option Request option. We convert the attributes to a
42 * 64-bit number which can be easily checked.
43 */
44#define DHCPV6_ORO_FORBIDDEN \
45 ((1ULL << 1) | /* OPTION_CLIENTID */ \
46 (1ULL << 2) | /* OPTION_SERVERID */ \
47 (1ULL << 3) | /* OPTION_IA_NA */ \
48 (1ULL << 4) | /* OPTION_IA_TA */ \
49 (1ULL << 5) | /* OPTION_IAADDR */ \
50 (1ULL << 6) | /* OPTION_ORO */ \
51 (1ULL << 7) | /* OPTION_PREFERENCE */ \
52 (1ULL << 8) | /* OPTION_ELAPSED_TIME */ \
53 (1ULL << 9) | /* OPTION_RELAY_MSG */ \
54 (1ULL << 11) | /* OPTION_AUTH */ \
55 (1ULL << 12) | /* OPTION_UNICAST */ \
56 (1ULL << 13) | /* OPTION_STATUS_CODE */ \
57 (1ULL << 14) | /* OPTION_RAPID_COMMIT */ \
58 (1ULL << 15) | /* OPTION_USER_CLASS */ \
59 (1ULL << 16) | /* OPTION_VENDOR_CLASS */ \
60 (1ULL << 18) | /* OPTION_INTERFACE_ID */ \
61 (1ULL << 19) | /* OPTION_RECONF_MSG */ \
62 (1ULL << 20) | /* OPTION_RECONF_ACCEPT */ \
63 (1ULL << 25) | /* OPTION_IA_PD */ \
64 (1ULL << 26)) /* OPTION_IAPREFIX */
65
66static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
68 uint8_t const *data, size_t const data_len, void *decode_ctx);
69
72 uint8_t const *data, size_t const data_len, void *decode_ctx)
73{
74 return fr_pair_tlvs_from_network(ctx, out, parent, data, data_len, decode_ctx, decode_option, NULL, true);
75}
76
77static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
79 uint8_t const *data, size_t const data_len, void *decode_ctx);
80
81/** Handle arrays of DNS labels for fr_struct_from_network()
82 *
83 */
86 uint8_t const *data, size_t const data_len, void *decode_ctx)
87{
89 return fr_pair_dns_labels_from_network(ctx, out, parent, data, data, data_len, NULL, false);
90 }
91
92 return decode_value(ctx, out, parent, data, data_len, decode_ctx);
93}
94
95
96static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
98 uint8_t const *data, size_t const data_len, void *decode_ctx)
99{
100 ssize_t slen;
101 fr_pair_t *vp = NULL;
102 fr_dict_attr_t const *ref;
103
104 FR_PROTO_HEX_DUMP(data, data_len, "decode_value");
105
106 switch (parent->type) {
107 case FR_TYPE_ATTR:
108 /*
109 * Force the length of the data to be two,
110 * otherwise the "from network" call complains.
111 * Because we pass in the enumv as the _parent_
112 * and not the da. The da is marked as "array",
113 * but the parent is not.
114 */
115 if (data_len < 2) goto raw;
116
117 /*
118 * Run-time checks rather than assertions.
119 */
120 if (!parent->parent->flags.is_root) return -1;
121
122 vp = fr_pair_afrom_da(ctx, parent);
123 if (!vp) return PAIR_DECODE_OOM;
124
125 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, parent->parent,
126 &FR_DBUFF_TMP(data, 2), 2, true);
127 if (slen <= 0) {
128 TALLOC_FREE(vp);
129 goto raw;
130 }
131
132 vp->vp_tainted = true;
134 return 2;
135
136 /*
137 * Address MAY be shorter than 16 bytes.
138 */
140 if (data_len == 0) {
141 raw:
142 return fr_pair_raw_from_network(ctx, out, parent, data, data_len);
143
144 }
145
146 vp = fr_pair_afrom_da(ctx, parent);
147 if (!vp) return PAIR_DECODE_OOM;
149
150 slen = fr_value_box_ipaddr_from_network(&vp->data, parent->type, parent,
151 data[0], data + 1, data_len - 1,
152 (parent->parent->type == FR_TYPE_STRUCT), true);
153 if (slen < 0) goto raw_free;
154
155 slen++; /* account for the prefix */
156 break;
157
158 /*
159 * A bool is encoded as an empty option if it's
160 * true. A bool is omitted entirely if it's
161 * false.
162 */
163 case FR_TYPE_BOOL:
164 if (data_len != 0) goto raw;
165 vp = fr_pair_afrom_da(ctx, parent);
166 if (!vp) return PAIR_DECODE_OOM;
168
169 vp->vp_bool = true;
170 slen = 0;
171 break;
172
173 /*
174 * A standard 32bit integer, but unlike normal UNIX timestamps
175 * starts from the 1st of January 2000.
176 *
177 * In the encoder we subtract 30 years to any values, so
178 * here we need to add that to the time here.
179 */
180 case FR_TYPE_DATE:
181 vp = fr_pair_afrom_da(ctx, parent);
182 if (!vp) return PAIR_DECODE_OOM;
184
185 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
186 &FR_DBUFF_TMP(data, data_len), data_len, true);
187 if (slen < 0) {
189 goto raw;
190 }
192 break;
193
194 case FR_TYPE_STRUCT:
195 slen = fr_struct_from_network(ctx, out, parent, data, data_len,
197 if (slen < 0) goto raw;
198
199 if (parent->flags.array) return slen;
200 return data_len;
201
202 case FR_TYPE_GROUP:
203 vp = fr_pair_afrom_da(ctx, parent);
204 if (!vp) return PAIR_DECODE_OOM;
206
208 if (ref && (ref->dict != dict_dhcpv6)) {
209 fr_dict_protocol_t const *proto;
210
211 proto = fr_dict_protocol(ref->dict);
212 fr_assert(proto != NULL);
213
214 if (!proto->decode) {
215 raw_free:
217 goto raw;
218 }
219
220 slen = proto->decode(vp, &vp->vp_group, data, data_len);
221 if (slen < 0) goto raw_free;
222
223 vp->vp_tainted = true;
224
225 } else {
226 if (!ref) ref = fr_dict_root(dict_dhcpv6);
227
228 /*
229 * Child VPs go into the child group, not in the main parent list. BUT, we start
230 * decoding attributes from the ref, and not from the group parent.
231 */
232 slen = fr_pair_tlvs_from_network(vp, &vp->vp_group, ref, data, data_len, decode_ctx, decode_option, NULL, false);
233 if (slen < 0) goto raw_free;
234 }
235
237 return data_len;
238
240 vp = fr_pair_afrom_da(ctx, parent);
241 if (!vp) return PAIR_DECODE_OOM;
243
244 slen = fr_value_box_ipaddr_from_network(&vp->data, parent->type, parent,
245 128, data, data_len,
246 true, true);
247 if (slen < 0) goto raw_free;
248 break;
249
250 default:
251 vp = fr_pair_afrom_da(ctx, parent);
252 if (!vp) return PAIR_DECODE_OOM;
254
255 slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
256 &FR_DBUFF_TMP(data, data_len), data_len, true);
257 if (slen < 0) goto raw_free;
258 break;
259 }
260
261 /*
262 * The input is larger than the decoded value, re-do it as a raw attribute.
263 */
264 if (!parent->flags.array && ((size_t) slen < data_len)) {
266 goto raw;
267 }
268
269 fr_assert(vp != NULL);
270
271 vp->vp_tainted = true;
273
274 if (parent->flags.array) return slen;
275
276 return data_len;
277}
278
279
280static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
281 fr_dict_attr_t const *parent,
282 uint8_t const *data, size_t const data_len, void *decode_ctx)
283{
284 unsigned int option;
285 size_t len;
286 ssize_t slen;
287 fr_dict_attr_t const *da;
288 fr_dhcpv6_decode_ctx_t *packet_ctx = decode_ctx;
289
290#ifdef STATIC_ANALYZER
291 if (!packet_ctx || !packet_ctx->tmp_ctx) return PAIR_DECODE_FATAL_ERROR;
292#endif
293
294 /*
295 * Must have at least an option header.
296 */
297 if (data_len < 4) {
298 fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
299 return -(data_len);
300 }
301
302 option = DHCPV6_GET_OPTION_NUM(data);
304 if (len > (data_len - 4)) {
305 fr_strerror_printf("%s: Option overflows input. "
306 "Optional length must be less than %zu bytes, got %zu bytes",
307 __FUNCTION__, data_len - 4, len);
309 }
310
311 da = fr_dict_attr_child_by_num(parent, option);
312 if (!da) {
313 da = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, parent, option);
314 if (!da) return PAIR_DECODE_FATAL_ERROR;
315 }
316 FR_PROTO_TRACE("decode context changed %s -> %s",da->parent->name, da->name);
317
318 /*
319 * Relay messages are weird, and contain complete DHCPv6
320 * packets, copied verbatim from the DHCPv6 client.
321 */
322 if (da == attr_relay_message) {
323 fr_pair_t *vp;
324
326 if (!vp) return PAIR_DECODE_FATAL_ERROR;
328
329 /*
330 * Check if the relayed packet is OK. If not, it's an error.
331 */
332 if (!fr_dhcpv6_ok(data + 4, len, 200)) return -1;
333
334 slen = fr_dhcpv6_decode(vp, &vp->vp_group, data + 4, len);
335 if (slen < 0) {
337 raw:
338 slen = fr_pair_raw_from_network(ctx, out, da, data + 4, len);
339 if (slen < 0) return slen;
340 return 4 + slen;
341 }
342
344
345 } else if ((da->type == FR_TYPE_STRING) && fr_dhcpv6_flag_any_dns_label(da)) {
346 slen = fr_pair_dns_labels_from_network(ctx, out, da, data + 4, data + 4, len, NULL, true);
347 if (slen < 0) return slen;
348
349 } else if (da->flags.array) {
350 if (da == attr_option_request) {
351 uint8_t const *p;
352
353 if ((len < 2) || ((len & 0x01) != 0)) {
354 fr_strerror_const("Invalid Option-Request, length is not a multiple of 2");
355 return -1;
356 }
357
358 /*
359 * Check for the forbidden options.
360 */
361 for (p = data + 4; p < (data + 4 + len); p += 2) {
362 if (*p) continue;
363
364 if (*p > 26) continue;
365
366 if ((1 << *p) & DHCPV6_ORO_FORBIDDEN) {
367 fr_strerror_printf("Option %u is forbidden inside of Option-Request", *p);
368 return -1;
369 }
370 }
371 }
372
373 slen = fr_pair_array_from_network(ctx, out, da, data + 4, len, decode_ctx, decode_value);
374
375 } else if (da->type == FR_TYPE_VSA) {
376 bool append_vsa = false;
377 bool append_vp = false;
378 uint32_t pen;
379 fr_dict_attr_t const *vendor;
380 fr_pair_t *vsa, *vp;
381 fr_pair_list_t list;
382
383 /*
384 * Insufficient room for a 4-octet enterprise
385 * code, plus at least one option header.
386 */
387 if (len < 8) goto raw;
388
389 pen = fr_nbo_to_uint32(data + 4);
390
391 /*
392 * Verify that the VSA contains a vendor.
393 *
394 * If it doesn't then this vendor is unknown, but we know
395 * vendor attributes have a standard format, so we can
396 * decode the data anyway.
397 */
398 vendor = fr_dict_attr_child_by_num(da, pen);
399 if (!vendor) {
401
402 n = fr_dict_attr_unknown_vendor_afrom_num(packet_ctx->tmp_ctx, da, pen);
403 if (!n) return PAIR_DECODE_OOM;
404 vendor = n;
405 }
406
407 vsa = fr_pair_find_by_da(out, NULL, da);
408 if (!vsa) {
409 vsa = fr_pair_afrom_da(ctx, da);
410 if (!vsa) return PAIR_DECODE_FATAL_ERROR;
411 PAIR_ALLOCED(vsa);
412
413 append_vsa = true;
414 }
415
416 vp = NULL;
417 if (!append_vsa) vp = fr_pair_find_by_da(&vsa->vp_group, NULL, vendor);
418
419 if (!vp) {
420 vp = fr_pair_afrom_da(vsa, vendor);
421 if (!vp) return PAIR_DECODE_FATAL_ERROR;
423
424 append_vp = true;
425 }
426
427 fr_pair_list_init(&list);
428 slen = fr_pair_tlvs_from_network(vp, &vp->vp_group, vendor, data + 8, len - 4,
429 decode_ctx, decode_option, NULL, false);
430
431 if (slen < 0) {
432 fr_pair_list_free(&list);
433 if (append_vp) talloc_free(vp);
434 if (append_vsa) talloc_free(vsa);
435 goto raw;
436 }
437
438 /*
439 * The child list contains vendors, and we have to merge the vendors
440 */
441 fr_pair_list_append(&vp->vp_group, &list);
442 if (append_vp) fr_pair_append(&vsa->vp_group, vp);
443 if (append_vsa) fr_pair_append(out, vsa);
444
445 } else if (da->type == FR_TYPE_TLV) {
446 slen = fr_pair_tlvs_from_network(ctx, out, da, data + 4, len, decode_ctx, decode_option, NULL, true);
447
448 } else if (da == attr_auth) {
449 /*
450 * See RFC 8415 Section 18 (option format), and Section 20 (functionality).
451 *
452 * The Auth option can be sent from a server to client in a Reply message, and contains a
453 * 128-bit secret key that is recorded somewhere on the server side.
454 *
455 * The Auth option can be sent from a server to a client in a Reconfigure message, and
456 * contains an HMAC-MD5 of the packet and the secret key.
457 *
458 * We are not currently a DHCPv6 client, so we do not support the Auth option, or
459 * Reconfigure messages. See verify_to_client() in base.c.
460 */
461 fr_strerror_const("The 'Auth' option is not supported");
462 return -1;
463
464 } else {
465 slen = decode_value(ctx, out, da, data + 4, len, decode_ctx);
466 }
467
468 if (slen < 0) goto raw;
469
470 return len + 4;
471}
472
473
474/** Create a "normal" fr_pair_t from the given data
475 *
476 * 0 1 2 3
477 * 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
478 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
479 * | option-code | option-len |
480 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
481 */
483 uint8_t const *data, size_t data_len, void *decode_ctx)
484{
485 FR_PROTO_HEX_DUMP(data, data_len, "fr_dhcpv6_decode_pair");
486
487 /*
488 * The API changes, so we just bounce directly to the
489 * decode_option() function.
490 *
491 * All options including VSAs in DHCPv6 MUST follow the
492 * standard format.
493 */
494 return decode_option(ctx, out, fr_dict_root(dict_dhcpv6), data, data_len, decode_ctx);
495}
496
498 uint8_t const *data, size_t data_len)
499{
500 ssize_t slen;
501 uint8_t const *attr, *end;
502
503 fr_dhcpv6_decode_ctx_t decode_ctx = {};
504
505 fr_assert(dict_dhcpv6 != NULL);
506
507 decode_ctx.tmp_ctx = talloc(ctx, uint8_t);
508
509 attr = data;
510 end = data + data_len;
511
512 while (attr < end) {
513 slen = fr_dhcpv6_decode_option(ctx, out, attr, (end - attr), &decode_ctx);
514 if (slen < 0) {
515 talloc_free(decode_ctx.tmp_ctx);
516 return slen;
517 }
518
519 /*
520 * If slen is larger than the room in the packet,
521 * all kinds of bad things happen.
522 */
523 if (!fr_cond_assert(slen <= (end - attr))) {
524 talloc_free(decode_ctx.tmp_ctx);
525 return -slen - (attr - data);
526 }
527
528 attr += slen;
529 talloc_free_children(decode_ctx.tmp_ctx);
530 }
531
532 talloc_free(decode_ctx.tmp_ctx);
533 return data_len;
534}
535
536static int decode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict,
538{
539 fr_dhcpv6_decode_ctx_t *test_ctx;
540
541 test_ctx = talloc_zero(ctx, fr_dhcpv6_decode_ctx_t);
542 if (!test_ctx) return -1;
543
544 test_ctx->tmp_ctx = talloc(test_ctx, uint8_t);
545
546 *out = test_ctx;
547
548 return 0;
549}
550
551static 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)
552{
553 size_t packet_len = data_len;
554// fr_dhcpv6_decode_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_dhcpv6_decode_ctx_t);
555
556 if (!fr_dhcpv6_ok(data, packet_len, 200)) return -1;
557
558 return fr_dhcpv6_decode(ctx, out, data, packet_len);
559}
560
561
563 uint8_t const *data, size_t data_len, void *decode_ctx)
564{
566
567 return decode_option(ctx, out, fr_dict_root(dict_dhcpv6), data, data_len, decode_ctx);
568}
569
570/*
571 * Test points
572 */
578
int n
Definition acutest.h:577
#define NDEBUG_UNUSED
Definition build.h:395
#define UNUSED
Definition build.h:384
fr_dict_attr_t const * root_da
Definition common.c:32
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:522
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:177
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:511
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:628
fr_dict_protocol_t const * fr_dict_protocol(fr_dict_t const *dict)
Return the protocol descriptor for the dictionary.
Definition dict_util.c:5360
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:635
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2720
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:3668
Protocol-specific callbacks in libfreeradius-PROTOCOL.
Definition dict.h:479
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:149
Definition dwarf.c:424
talloc_free(hp)
#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:156
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:253
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:86
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
@ 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 uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
Read an unsigned 32bit integer from wire format (big endian)
Definition nbo.h:167
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:708
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:1298
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:291
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:47
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:481
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_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
HIDDEN fr_dict_attr_t const * attr_option_request
Definition base.c:55
HIDDEN fr_dict_attr_t const * attr_auth
Definition base.c:56
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:237
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:636
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:482
fr_test_point_pair_decode_t dhcpv6_tp_decode_pair
Definition decode.c:574
fr_test_point_proto_decode_t dhcpv6_tp_decode_proto
Definition decode.c:580
#define DHCPV6_ORO_FORBIDDEN
Definition decode.c:44
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:497
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:551
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:562
#define decode_value
Definition decode.c:411
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:37
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:213
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
#define FR_PAIR_APPEND
Definition pair.h:214
static fr_slen_t parent
Definition pair.h:860
#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
#define fr_strerror_const(_msg)
Definition strerror.h:223
@ 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:1908
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:2312
static fr_slen_t data
Definition value.h:1367
static size_t char ** out
Definition value.h:1062