The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 81e33fdf9ddf629533b7ee705542dd8d3cc817ed $
19  *
20  * @file protocols/bfd/decode.c
21  * @brief Functions to decode BFD packets
22  *
23  * @copyright 2023 Network RADIUS SAS (legal@networkradius.com)
24  */
25 RCSID("$Id: 81e33fdf9ddf629533b7ee705542dd8d3cc817ed $")
26 
27 #include <freeradius-devel/util/struct.h>
28 #include <freeradius-devel/io/test_point.h>
29 #include <freeradius-devel/internal/internal.h>
30 
31 #include "attrs.h"
32 
33 static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
34  fr_dict_attr_t const *parent,
35  uint8_t const *data, size_t const data_len, UNUSED void *decode_ctx)
36 {
37  ssize_t slen;
38  fr_pair_t *vp;
39 
40  FR_PROTO_HEX_DUMP(data, data_len, "decode_value");
41 
42  vp = fr_pair_afrom_da(ctx, parent);
43  if (!vp) return PAIR_DECODE_OOM;
44 
45  slen = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
46  &FR_DBUFF_TMP(data, data_len), data_len, true);
47  if (slen < 0) {
48  talloc_free(vp);
49  return slen;
50  }
51 
52  fr_assert(vp != NULL);
53 
54  vp->vp_tainted = true;
56 
57  return data_len;
58 }
59 
60 
61 /** Decode a raw BFD packet into VPs.
62  *
63  */
65  uint8_t const *packet, size_t packet_len,
66  char const *secret, UNUSED size_t secret_len)
67 {
68  ssize_t slen;
69  fr_bfd_ctx_t packet_ctx;
70  bfd_packet_t const *bfd;
71  fr_pair_t *vp;
72  fr_dbuff_t dbuff;
73 
74  packet_ctx.secret = secret;
75 
76  bfd = (bfd_packet_t const *) packet;
77 
78  slen = fr_struct_from_network(ctx, out, attr_bfd_packet, packet, bfd->length, true,
79  &packet_ctx, decode_value, NULL);
80  if (slen < 0) return slen;
81 
82  if (bfd->length == packet_len) return packet_len;
83 
84  /*
85  * Try to decode additional data.
86  */
88  if (!vp) return packet_len;
89 
90  fr_dbuff_init(&dbuff, packet + slen, packet_len - slen);
91 
92  if ((fr_internal_decode_list_dbuff(vp, &vp->vp_group, fr_dict_root(dict_bfd), &dbuff, NULL) < 0) ||
93  (fr_pair_list_num_elements(&vp->vp_group) == 0)) {
94  TALLOC_FREE(vp);
95  } else {
97  }
98 
99  return slen;
100 }
101 
102 static int decode_test_ctx(void **out, TALLOC_CTX *ctx)
103 {
104  fr_bfd_ctx_t *test_ctx;
105 
106  test_ctx = talloc_zero(ctx, fr_bfd_ctx_t);
107  test_ctx->secret = talloc_strdup(test_ctx, "testing123");
108  test_ctx->tmp_ctx = talloc_zero(test_ctx, uint8_t);
109 
110  *out = test_ctx;
111 
112  return 0;
113 }
114 
116  uint8_t const *data, size_t data_len, void *proto_ctx)
117 {
118  fr_pair_t *vp;
119  bfd_packet_t const *packet;
120  fr_bfd_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_bfd_ctx_t);
121 
122  if (data_len < FR_BFD_HEADER_LENGTH) {
123  fr_strerror_const("Packet is too small for BFD");
124  return -1;
125  }
126 
127  packet = (bfd_packet_t const *) data;
128 
129  if (packet->length > data_len) {
130  fr_strerror_const("Packet.length is larger than received data");
131  return -1;
132  }
133 
134  if (packet->length < FR_BFD_HEADER_LENGTH) {
135  fr_strerror_const("Packet.length is smaller then BFD header size");
136  return -1;
137  }
138 
139  if (packet->version != 1) {
140  fr_strerror_const("Packet.version has invalid value");
141  return -1;
142  }
143 
144  if (packet->detect_multi == 0) {
145  fr_strerror_const("Packet.detect-multi has invalid value zero");
146  return -1;
147  }
148 
149  if (packet->detect_multi == 0) {
150  fr_strerror_const("Packet.detect-multi has invalid value zero");
151  return -1;
152  }
153 
154  if (packet->multipoint != 0) {
155  fr_strerror_const("Packet.multipoint has invalid non-zero value");
156  return -1;
157  }
158 
159  if (packet->my_disc == 0) {
160  fr_strerror_const("Packet.my-discriminator has invalid value zero");
161  return -1;
162  }
163 
164  if ((packet->your_disc == 0) &&
165  !((packet->state == BFD_STATE_DOWN) ||
166  (packet->state == BFD_STATE_ADMIN_DOWN))) {
167  fr_strerror_const("Packet has invalid values for your-discriminator and state");
168  return 0;
169  }
170 
171  /*
172  * Get the packet type.
173  */
175  if (!vp) {
176  fr_strerror_const("Failed creating Packet-Type");
177  return -1;
178  }
179 
180  vp->vp_uint32 = packet->state;
182 
183 #if 0
184  /*
185  * We always decode the packet as a nested VP.
186  */
188  if (!vp) {
189  fr_strerror_const("Failed creating Packet");
190  return -1;
191  }
193 #endif
194 
195  /* coverity[tainted_data] */
196  return fr_bfd_decode(ctx, out, data, data_len,
197  test_ctx->secret, talloc_array_length(test_ctx->secret) - 1);
198 }
199 
200 /*
201  * Test points
202  */
206  .func = fr_bfd_decode_proto
207 };
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition: bfd.h:155
#define FR_BFD_HEADER_LENGTH
Definition: bfd.h:141
char const * secret
shared secret. MUST be talloc'd
Definition: bfd.h:156
@ BFD_STATE_DOWN
Definition: bfd.h:35
@ BFD_STATE_ADMIN_DOWN
Definition: bfd.h:34
#define RCSID(id)
Definition: build.h:444
#define UNUSED
Definition: build.h:313
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition: dbuff.h:354
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:509
static fr_dict_attr_t const * attr_packet_type
Definition: dhcpclient.c:89
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:1997
#define PAIR_DECODE_OOM
Fatal error - Out of memory.
Definition: pair.h:46
talloc_free(reap)
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
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:278
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:1340
static fr_dict_attr_t const * attr_bfd_packet
Definition: proto_bfd.c:69
static fr_dict_t const * dict_bfd
Definition: proto_bfd.c:60
HIDDEN fr_dict_attr_t const * attr_bfd_additional_data
Definition: base.c:52
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)
Decode a raw BFD packet into VPs.
Definition: decode.c:64
static int decode_test_ctx(void **out, TALLOC_CTX *ctx)
Definition: decode.c:102
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)
Definition: decode.c:115
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)
Definition: decode.c:33
fr_test_point_proto_decode_t bfd_tp_decode_proto
Definition: decode.c:204
ssize_t fr_internal_decode_list_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *dbuff, void *decode_ctx)
Retrieve all pairs from the dbuff.
Definition: decode.c:310
VQP attributes.
static char * secret
Definition: radclient-ng.c:69
fr_assert(0)
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, bool nested, 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:33
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:66
Entry point for protocol decoders.
Definition: test_point.h:65
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
Definition: pair_inline.c:151
static fr_slen_t parent
Definition: pair.h:844
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition: proto.h:41
#define fr_strerror_const(_msg)
Definition: strerror.h:223
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:1709
static fr_slen_t data
Definition: value.h:1259
static size_t char ** out
Definition: value.h:984