/src/freeradius-server/src/lib/unlang/xlat_pair.c
Line | Count | Source |
1 | | /* |
2 | | * This program is free software; you can redistribute it and/or modify |
3 | | * it under the terms of the GNU General Public License as published by |
4 | | * the Free Software Foundation; either version 2 of the License, or |
5 | | * (at your option) any later version. |
6 | | * |
7 | | * This program 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 |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * along with this program; 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: ac59457647299f86aedd3a2e3a677fefa62a5da4 $ |
19 | | * |
20 | | * @brief Protocol agnostic encode/decoders |
21 | | * @file unlang/xlat_pair.c |
22 | | * |
23 | | * @copyright 2021 Network RADIUS SAS (legal@networkradius.com) |
24 | | */ |
25 | | RCSID("$Id: ac59457647299f86aedd3a2e3a677fefa62a5da4 $") |
26 | | |
27 | | #include <freeradius-devel/unlang/xlat_priv.h> |
28 | | |
29 | | /** Keep decoding pairs until all of the data has been used. |
30 | | * |
31 | | * @param[in] ctx to allocate new pairs in. |
32 | | * @param[in] out the cursor to update |
33 | | * @param[in] parent to use as the root |
34 | | * @param[in] data to decode. |
35 | | * @param[in] data_len The length of the incoming data. |
36 | | * @param[in] decode_ctx Any decode specific data such as secrets or configurable. |
37 | | * @param[in] decode the function used to decode one specific pair. |
38 | | * @return |
39 | | * - <= 0 on error. May be the offset (as a negative value) where the error occurred. |
40 | | * - > 0 on success. How many bytes were decoded. |
41 | | */ |
42 | | static ssize_t fr_pair_decode_multi(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, |
43 | | uint8_t const *data, size_t data_len, void *decode_ctx, fr_pair_decode_t decode) |
44 | 0 | { |
45 | 0 | uint8_t const *p, *end; |
46 | 0 | fr_pair_list_t tmp; |
47 | | |
48 | | /* |
49 | | * Catch idiocies. |
50 | | */ |
51 | 0 | if (data_len == 0) return 0; |
52 | | |
53 | 0 | fr_pair_list_init(&tmp); |
54 | |
|
55 | 0 | p = data; |
56 | 0 | end = data + data_len; |
57 | |
|
58 | 0 | while (p < end) { |
59 | 0 | ssize_t len; |
60 | |
|
61 | 0 | len = decode(ctx, &tmp, parent, p, end - p, decode_ctx); |
62 | 0 | if (len <= 0) { |
63 | 0 | fr_pair_list_free(&tmp); |
64 | 0 | return len - (p - data); |
65 | 0 | } |
66 | 0 | p += len; |
67 | 0 | } |
68 | | |
69 | | /* |
70 | | * Add the pairs to the cursor |
71 | | */ |
72 | 0 | fr_pair_list_append(out, &tmp); |
73 | |
|
74 | 0 | return data_len; |
75 | 0 | } |
76 | | |
77 | | |
78 | | /** Decode all of the value boxes into the output cursor |
79 | | * |
80 | | * @param[in] ctx to allocate new pairs in. |
81 | | * @param[in] out the cursor to update |
82 | | * @param[in] request the request |
83 | | * @param[in] decode_ctx Any decode specific data such as secrets or configurable. |
84 | | * @param[in] decode the function used to decode one specific pair. |
85 | | * @param[in] in the list of value boxes to decode |
86 | | * @return |
87 | | * - <= 0 on error. May be the offset (as a negative value) where the error occurred. |
88 | | * - > 0 on success. How many value boxes were decoded |
89 | | */ |
90 | | int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out, |
91 | | request_t *request, void *decode_ctx, fr_pair_decode_t decode, |
92 | | fr_value_box_list_t *in) |
93 | 0 | { |
94 | 0 | int decoded = 0; |
95 | 0 | fr_pair_t *vp = NULL; |
96 | 0 | fr_dict_attr_t const *parent = fr_dict_root(request->proto_dict); |
97 | 0 | fr_pair_list_t head; |
98 | |
|
99 | 0 | fr_pair_list_init(&head); |
100 | |
|
101 | 0 | fr_value_box_list_foreach(in, vb) { |
102 | 0 | ssize_t len; |
103 | |
|
104 | 0 | if (vb->type != FR_TYPE_OCTETS) { |
105 | 0 | RWDEBUG("Skipping value \"%pR\", expected value of type %s, got type %s", |
106 | 0 | vb, |
107 | 0 | fr_type_to_str(FR_TYPE_OCTETS), |
108 | 0 | fr_type_to_str(vb->type)); |
109 | 0 | continue; |
110 | 0 | } |
111 | | |
112 | 0 | len = fr_pair_decode_multi(ctx, &head, parent, |
113 | 0 | vb->vb_octets, vb->vb_length, decode_ctx, decode); |
114 | 0 | if (len <= 0) { |
115 | 0 | fr_pair_list_free(&head); |
116 | 0 | return -decoded; |
117 | 0 | } |
118 | 0 | decoded++; /* one more VB, but there may be many pairs in the decoded vps. */ |
119 | 0 | } |
120 | | |
121 | 0 | if (RDEBUG_ENABLED2) { |
122 | 0 | char const *name = parent->name; |
123 | |
|
124 | 0 | while ((vp = fr_pair_list_next(&head, vp))) { |
125 | 0 | RDEBUG2("decode %s: %pP", name, vp); |
126 | 0 | } |
127 | 0 | } |
128 | |
|
129 | 0 | decoded = fr_pair_list_num_elements(&head); |
130 | |
|
131 | 0 | fr_pair_list_append(out, &head); |
132 | |
|
133 | 0 | return decoded; |
134 | 0 | } |