From: Alan T. DeKok Date: Tue, 28 Feb 2023 21:07:09 +0000 (-0500) Subject: add BFD decoder X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fcd259213bdffbc5af05d84e54ea5512a7adef5f;p=thirdparty%2Ffreeradius-server.git add BFD decoder --- diff --git a/src/protocols/bfd/all.mk b/src/protocols/bfd/all.mk index 23b7badc4d9..7cac90134ef 100644 --- a/src/protocols/bfd/all.mk +++ b/src/protocols/bfd/all.mk @@ -1,5 +1,5 @@ TARGET := libfreeradius-bfd$(L) -SOURCES := base.c encode.c +SOURCES := base.c encode.c decode.c TGT_PREREQS := libfreeradius-util$(L) diff --git a/src/protocols/bfd/bfd.h b/src/protocols/bfd/bfd.h index 4f0462dc898..b72b1200b22 100644 --- a/src/protocols/bfd/bfd.h +++ b/src/protocols/bfd/bfd.h @@ -148,6 +148,9 @@ typedef struct { ssize_t fr_bfd_encode(uint8_t *packet, size_t packet_len, uint8_t const *original, char const *secret, size_t secret_len, fr_pair_list_t *vps); +ssize_t fr_bfd_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, + uint8_t const *packet, size_t packet_len, + char const *secret, size_t secret_len); int fr_bfd_init(void); void fr_bfd_free(void); diff --git a/src/protocols/bfd/decode.c b/src/protocols/bfd/decode.c new file mode 100644 index 00000000000..45465708488 --- /dev/null +++ b/src/protocols/bfd/decode.c @@ -0,0 +1,158 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * $Id$ + * + * @file protocols/bfd/decode.c + * @brief Functions to decode BFD packets + * + * @copyright 2023 Network RADIUS SAS (legal@networkradius.com) + */ +RCSID("$Id$") + +#include +#include +#include + +#include "attrs.h" + +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 const data_len, UNUSED void *decode_ctx) +{ + ssize_t slen; + fr_pair_t *vp; + + FR_PROTO_HEX_DUMP(data, data_len, "decode_value"); + + vp = fr_pair_afrom_da(ctx, parent); + if (!vp) return PAIR_DECODE_OOM; + + slen = fr_value_box_from_network(vp, &vp->data, vp->da->type, vp->da, + &FR_DBUFF_TMP(data, data_len), data_len, true); + if (slen < 0) { + talloc_free(vp); + return slen; + } + + fr_assert(vp != NULL); + + vp->vp_tainted = true; + fr_pair_append(out, vp); + + return data_len; +} + + +/** Decode a raw BFD packet into VPs. + * + */ +ssize_t fr_bfd_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, + uint8_t const *packet, size_t packet_len, + char const *secret, UNUSED size_t secret_len) +{ + ssize_t slen; + fr_bfd_ctx_t packet_ctx; + + packet_ctx.secret = secret; + + slen = fr_struct_from_network(ctx, out, attr_bfd_packet, packet, packet_len, true, + &packet_ctx, decode_value, NULL); + if (slen < 0) return slen; + + return slen; +} + +static int _test_ctx_free(UNUSED fr_bfd_ctx_t *ctx) +{ + fr_bfd_free(); + + return 0; +} + +static int decode_test_ctx(void **out, TALLOC_CTX *ctx) +{ + fr_bfd_ctx_t *test_ctx; + + if (fr_bfd_init() < 0) return -1; + + test_ctx = talloc_zero(ctx, fr_bfd_ctx_t); + test_ctx->secret = talloc_strdup(test_ctx, "testing123"); + test_ctx->tmp_ctx = talloc_zero(test_ctx, uint8_t); + talloc_set_destructor(test_ctx, _test_ctx_free); + + *out = test_ctx; + + return 0; +} + +static ssize_t fr_bfd_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, + uint8_t const *data, size_t data_len, void *proto_ctx) +{ + fr_pair_t *vp; + bfd_packet_t const *packet; + fr_bfd_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_bfd_ctx_t); + + if (data_len < FR_BFD_HEADER_LENGTH) { + fr_strerror_const("Packet is too small for BFD"); + return -1; + } + + packet = (bfd_packet_t const *) data; + + if (packet->length > data_len) { + fr_strerror_const("Packet.lenth is larger than received data"); + return -1; + } + + /* + * Get the packet type. + */ + vp = fr_pair_afrom_da(ctx, attr_packet_type); + if (!vp) { + fr_strerror_const("Failed creating Packet-Type"); + return -1; + } + + vp->vp_uint32 = packet->state; + fr_pair_append(out, vp); + +#if 0 + /* + * We always decode the packet as a nested VP. + */ + vp = fr_pair_afrom_da(ctx, attr_bfd_packet); + if (!vp) { + fr_strerror_const("Failed creating Packet"); + return -1; + } + fr_pair_append(out, vp); +#endif + + /* coverity[tainted_data] */ + return fr_bfd_decode(ctx, out, data, data_len, + test_ctx->secret, talloc_array_length(test_ctx->secret) - 1); +} + +/* + * Test points + */ +extern fr_test_point_proto_decode_t bfd_tp_decode_proto; +fr_test_point_proto_decode_t bfd_tp_decode_proto = { + .test_ctx = decode_test_ctx, + .func = fr_bfd_decode_proto +}; diff --git a/src/protocols/bfd/encode.c b/src/protocols/bfd/encode.c index ff6c3e41aef..44589f67374 100644 --- a/src/protocols/bfd/encode.c +++ b/src/protocols/bfd/encode.c @@ -30,8 +30,6 @@ RCSID("$Id$") #include #include "attrs.h" -extern fr_dict_attr_t const *attr_bfd_packet; - /** Encodes the data portion of an attribute * * @return diff --git a/src/tests/unit/protocols/bfd/base.txt b/src/tests/unit/protocols/bfd/base.txt index 754690ad217..ce015719024 100644 --- a/src/tests/unit/protocols/bfd/base.txt +++ b/src/tests/unit/protocols/bfd/base.txt @@ -12,5 +12,8 @@ fuzzer-out bfd encode-proto Packet = { version = 1, diagnostic = none, state = up, poll = false, final = false, control-plane-independent = false, auth-present = false, demand = false, multipoint = false, detect-multi = 3, my-discriminator = 0xdeadbeef, your-discriminator = 0x21126809, desired-min-tx-interval = 31us, required-min-tx-interval = 127us, required-min-echo-interval = 255us } match 20 c0 03 18 de ad be ef 21 12 68 09 00 00 00 1f 00 00 00 7f 00 00 00 ff +decode-proto - +match Packet-Type = Up, Packet = { version = 1, diagnostic = none, state = up, poll = no, final = no, control-plane-independent = no, auth-present = no, demand = no, multipoint = no, detect-multi = 3, length = 24, my-discriminator = 3735928559, your-discriminator = 554854409, desired-min-tx-interval = 31, required-min-tx-interval = 127, required-min-echo-interval = 255 } + count -match 5 +match 7