Coverage Report

Created: 2024-08-28 06:17

/src/freeradius-server/src/protocols/bfd/decode.c
Line
Count
Source (jump to first uncovered line)
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
47
{
37
47
  ssize_t slen;
38
47
  fr_pair_t *vp;
39
40
47
  FR_PROTO_HEX_DUMP(data, data_len, "decode_value");
41
42
47
  vp = fr_pair_afrom_da(ctx, parent);
43
47
  if (!vp) return PAIR_DECODE_OOM;
44
45
47
  slen =  fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
46
47
            &FR_DBUFF_TMP(data, data_len), data_len, true);
47
47
  if (slen < 0) {
48
0
    talloc_free(vp);
49
0
    return slen;
50
0
  }
51
52
47
  fr_assert(vp != NULL);
53
54
47
  vp->vp_tainted = true;
55
47
  fr_pair_append(out, vp);
56
57
47
  return data_len;
58
47
}
59
60
61
/** Decode a raw BFD packet into VPs.
62
 *
63
 */
64
ssize_t fr_bfd_decode(TALLOC_CTX *ctx, fr_pair_list_t *out,
65
          uint8_t const *packet, size_t packet_len,
66
          char const *secret, UNUSED size_t secret_len)
67
6
{
68
6
  ssize_t     slen;
69
6
  fr_bfd_ctx_t    packet_ctx;
70
6
  bfd_packet_t const  *bfd;
71
6
  fr_pair_t   *vp;
72
6
  fr_dbuff_t    dbuff;
73
74
6
  packet_ctx.secret = secret;
75
76
6
  bfd = (bfd_packet_t const *) packet;
77
78
6
  slen = fr_struct_from_network(ctx, out, attr_bfd_packet, packet, bfd->length, true,
79
6
              &packet_ctx, decode_value, NULL);
80
6
  if (slen < 0) return slen;
81
82
6
  if (bfd->length == packet_len) return packet_len;
83
84
  /*
85
   *  Try to decode additional data.
86
   */
87
6
  vp = fr_pair_afrom_da(ctx, attr_bfd_additional_data);
88
6
  if (!vp) return packet_len;
89
90
6
  fr_dbuff_init(&dbuff, packet + slen, packet_len - slen);
91
92
6
  if ((fr_internal_decode_list_dbuff(vp, &vp->vp_group, fr_dict_root(dict_bfd), &dbuff, NULL) < 0) ||
93
6
      (fr_pair_list_num_elements(&vp->vp_group) == 0)) {
94
6
    TALLOC_FREE(vp);
95
6
  } else {
96
0
    fr_pair_append(out, vp);
97
0
  }
98
99
6
  return slen;
100
6
}
101
102
static int decode_test_ctx(void **out, TALLOC_CTX *ctx)
103
2.51k
{
104
2.51k
  fr_bfd_ctx_t  *test_ctx;
105
106
2.51k
  test_ctx = talloc_zero(ctx, fr_bfd_ctx_t);
107
2.51k
  test_ctx->secret = talloc_strdup(test_ctx, "testing123");
108
2.51k
  test_ctx->tmp_ctx = talloc_zero(test_ctx, uint8_t);
109
110
2.51k
  *out = test_ctx;
111
112
2.51k
  return 0;
113
2.51k
}
114
115
static ssize_t fr_bfd_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out,
116
           uint8_t const *data, size_t data_len, void *proto_ctx)
117
10
{
118
10
  fr_pair_t *vp;
119
10
  bfd_packet_t const *packet;
120
10
  fr_bfd_ctx_t  *test_ctx = talloc_get_type_abort(proto_ctx, fr_bfd_ctx_t);
121
122
10
  if (data_len < FR_BFD_HEADER_LENGTH) {
123
0
    fr_strerror_const("Packet is too small for BFD");
124
0
    return -1;
125
0
  }
126
127
10
  packet = (bfd_packet_t const *) data;
128
129
10
  if (packet->length > data_len) {
130
0
    fr_strerror_const("Packet.length is larger than received data");
131
0
    return -1;
132
0
  }
133
134
10
  if (packet->length < FR_BFD_HEADER_LENGTH) {
135
4
    fr_strerror_const("Packet.length is smaller then BFD header size");
136
4
    return -1;
137
4
  }
138
139
6
  if (packet->version != 1) {
140
0
    fr_strerror_const("Packet.version has invalid value");
141
0
    return -1;
142
0
  }
143
144
6
  if (packet->detect_multi == 0) {
145
0
    fr_strerror_const("Packet.detect-multi has invalid value zero");
146
0
    return -1;
147
0
  }
148
149
6
  if (packet->detect_multi == 0) {
150
0
    fr_strerror_const("Packet.detect-multi has invalid value zero");
151
0
    return -1;
152
0
  }
153
154
6
  if (packet->multipoint != 0) {
155
0
    fr_strerror_const("Packet.multipoint has invalid non-zero value");
156
0
    return -1;
157
0
  }
158
159
6
  if (packet->my_disc == 0) {
160
0
    fr_strerror_const("Packet.my-discriminator has invalid value zero");
161
0
    return -1;
162
0
  }
163
164
6
  if ((packet->your_disc == 0) &&
165
6
      !((packet->state == BFD_STATE_DOWN) ||
166
0
        (packet->state == BFD_STATE_ADMIN_DOWN))) {
167
0
    fr_strerror_const("Packet has invalid values for your-discriminator and state");
168
0
    return 0;
169
0
  }
170
171
  /*
172
   *  Get the packet type.
173
   */
174
6
  vp = fr_pair_afrom_da(ctx, attr_packet_type);
175
6
  if (!vp) {
176
0
    fr_strerror_const("Failed creating Packet-Type");
177
0
    return -1;
178
0
  }
179
180
6
  vp->vp_uint32 = packet->state;
181
6
  fr_pair_append(out, vp);
182
183
#if 0
184
  /*
185
   *  We always decode the packet as a nested VP.
186
   */
187
  vp = fr_pair_afrom_da(ctx, attr_bfd_packet);
188
  if (!vp) {
189
    fr_strerror_const("Failed creating Packet");
190
    return -1;
191
  }
192
  fr_pair_append(out, vp);
193
#endif
194
195
  /* coverity[tainted_data] */
196
6
  return fr_bfd_decode(ctx, out, data, data_len,
197
6
           test_ctx->secret, talloc_array_length(test_ctx->secret) - 1);
198
6
}
199
200
/*
201
 *  Test points
202
 */
203
extern fr_test_point_proto_decode_t bfd_tp_decode_proto;
204
fr_test_point_proto_decode_t bfd_tp_decode_proto = {
205
  .test_ctx = decode_test_ctx,
206
  .func   = fr_bfd_decode_proto
207
};