27 #include <freeradius-devel/io/test_point.h>
28 #include <freeradius-devel/util/proto.h>
29 #include <freeradius-devel/util/struct.h>
30 #include <freeradius-devel/util/dns.h>
39 uint8_t const *
data,
size_t const data_len,
void *decode_ctx);
47 if ((end - p) < 2)
return false;
49 if ((p + p[1]) > end)
return false;
59 uint8_t const *
data,
size_t const data_len,
void *decode_ctx)
65 uint8_t const *
data,
size_t data_len,
void *decode_ctx);
72 uint8_t const *
data,
size_t const data_len,
void *decode_ctx)
90 uint8_t const *
data,
size_t data_len,
void *decode_ctx)
96 bool exact = !da->flags.array;
98 FR_PROTO_TRACE(
"%s called to parse %zu bytes from %s", __FUNCTION__, data_len, da->name);
107 if (slen < 0)
return slen;
109 if (!exact)
return slen;
117 if (da->flags.is_unknown) {
142 switch (
vp->vp_type) {
147 if ((
size_t) (end - p) <
sizeof(
vp->vp_ipv6addr))
goto raw;
149 if (exact && ((
size_t) (end - p) >
sizeof(
vp->vp_ipv6addr)))
goto raw;
151 memcpy(&
vp->vp_ipv6addr, p,
sizeof(
vp->vp_ipv6addr));
152 vp->vp_ip.af = AF_INET6;
153 vp->vp_ip.scope_id = 0;
154 vp->vp_ip.prefix = 128;
155 vp->vp_tainted =
true;
156 p +=
sizeof(
vp->vp_ipv6addr);
160 if ((
size_t) (end - (p + 1)) <
sizeof(
vp->vp_ipv6addr))
goto raw;
162 if (exact && ((
size_t) (end - p) >
sizeof(
vp->vp_ipv6addr)))
goto raw;
164 memcpy(&
vp->vp_ipv6addr, p + 1,
sizeof(
vp->vp_ipv6addr));
165 vp->vp_ip.af = AF_INET6;
166 vp->vp_ip.scope_id = 0;
167 vp->vp_ip.prefix = p[0];
168 vp->vp_tainted =
true;
169 p +=
sizeof(
vp->vp_ipv6addr) + 1;
179 vp->vp_ip.af = AF_INET;
188 if (data_len < 8)
goto raw;
215 mask <<= (32 -
vp->vp_ip.prefix);
217 vp->vp_ipv4addr = htonl(ipaddr &
mask);
224 if ((data_len == 0) || (*p > 32))
goto raw;
226 needs = 1 + ((*p + 0x07) >> 3);
227 if (data_len < needs)
goto raw;
233 vp->vp_ip.prefix = *p;
238 if (
vp->vp_ip.prefix) {
242 mask <<= (32 -
vp->vp_ip.prefix);
247 }
else if (*p > 16) {
260 vp->vp_ipv4addr = htonl(ipaddr &
mask);
282 if (exact && (slen != (end - p))) {
291 FR_PROTO_TRACE(
"decoding value complete, adding new pair and returning %zu byte(s)", p -
data);
350 uint8_t const *
data,
size_t const data_len,
void *decode_ctx)
363 "%s: Internal sanity check failed, attribute \"%s\" is not of type 'vsa'",
372 if ((
size_t)(end - p) < (
sizeof(
uint32_t) + 1 + 1)) {
399 if ((p + 1 + option_len) > end) {
401 if (len < 0)
return len;
410 if (option_len == 0)
goto next;
421 if (len < 0)
return len;
424 if (p < end)
goto next;
435 uint8_t const *
data,
size_t const data_len,
void *decode_ctx)
443 #ifdef STATIC_ANALYZER
462 if ((data_len == 1) && ((
data[0] == 0) || (
data[1] == 255)))
return data_len;
474 if (len > (data_len - 2)) {
476 "Optional length must be less than %zu bytes, got %zu bytes",
477 __FUNCTION__, data_len - 2, len);
491 }
else if (da->flags.array) {
524 if (slen < 0)
return slen;
539 uint8_t const *
data,
size_t data_len,
void *decode_ctx)
546 FR_PROTO_TRACE(
"%s called to parse %zu byte(s)", __FUNCTION__, data_len);
548 if (data_len == 0)
return 0;
558 while ((p < end) && (p[0] == 0)) {
564 if (p[0] == 255)
return data_len;
569 if ((data_len < 2) || ((
size_t) (
data[1] + 2) > data_len)) {
600 if ((end -
next) < 2)
return -1;
602 if ((
next + 2 +
next[1]) > end)
return -1;
626 }
else if (da->flags.array) {
632 if (slen < 0)
return slen;
637 FR_PROTO_TRACE(
"decoding option complete, %zu decoded, returning %zu byte(s)", slen, (
size_t) (
next -
data));
642 if (slen < 0)
return slen;
644 FR_PROTO_TRACE(
"decoding option complete, %zu decoded, returning %u byte(s)", slen,
data[1] + 2);
661 end =
data + data_len;
676 return -slen - (attr -
data);
680 talloc_free_children(decode_ctx.
tmp_ctx);
714 uint8_t const *
data,
size_t data_len,
void *decode_ctx)
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
static fr_dict_t const * dict_dhcpv4
Implementation of the DHCPv4 protocol.
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
#define fr_dhcpv4_flag_prefix_bits(_da)
#define fr_dhcpv4_flag_dns_label(_da)
#define fr_dhcpv4_flag_prefix_split(_da)
int fr_dhcpv4_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, unsigned int *code)
static fr_dict_attr_t * fr_dict_attr_unknown_vendor_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int vendor)
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
static fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
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.
#define PAIR_DECODE_OOM
Fatal error - Out of memory.
#define PAIR_DECODE_FATAL_ERROR
Fatal error - Failed decoding the packet.
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.
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.
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.
ssize_t fr_pair_raw_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len)
Create a "raw" pair from the network data.
@ 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_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.
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
static uint32_t fr_nbo_to_uint24(uint8_t const data[static 3])
Read an unsigned 24bit integer from wire format (big endian)
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)
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.
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.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
int fr_pair_raw_afrom_pair(fr_pair_t *vp, uint8_t const *data, size_t data_len)
Mark malformed attribute as raw.
bool fr_dhcpv4_ok(uint8_t const *data, ssize_t data_len, uint8_t *message_type, uint32_t *xid)
Check received DHCP request is valid and build fr_packet_t structure if it is.
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)
fr_test_point_pair_decode_t dhcpv4_tp_decode_pair
fr_test_point_proto_decode_t dhcpv4_tp_decode_proto
static _Thread_local uint8_t concat_buffer[1500]
static ssize_t fr_dhcpv4_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, UNUSED void *proto_ctx)
static int decode_test_ctx(void **out, TALLOC_CTX *ctx)
static ssize_t decode_value(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)
static bool verify_tlvs(uint8_t const *data, size_t data_len)
ssize_t fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, void *decode_ctx)
Decode DHCP option.
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()
static ssize_t decode_option_wrapper(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)
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.
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)
ssize_t fr_dhcpv4_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len)
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.
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Entry point for pair decoders.
Entry point for protocol decoders.
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
#define FR_PROTO_TRACE(_fmt,...)
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define FR_TYPE_STRUCTURAL
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.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out