/src/freeradius-server/src/lib/unlang/xlat_priv.h
Line | Count | Source |
1 | | #pragma once |
2 | | /* |
3 | | * This program is free software; you can redistribute it and/or modify |
4 | | * it under the terms of the GNU General Public License as published by |
5 | | * the Free Software Foundation; either version 2 of the License, or |
6 | | * (at your option) any later version. |
7 | | * |
8 | | * This program is distributed in the hope that it will be useful, |
9 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | | * GNU General Public License for more details. |
12 | | * |
13 | | * You should have received a copy of the GNU General Public License |
14 | | * along with this program; if not, write to the Free Software |
15 | | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
16 | | */ |
17 | | |
18 | | /** |
19 | | * $Id: 78ae83297f879229ffdaf1a777d8b0e7f4bd5eef $ |
20 | | * |
21 | | * @file src/lib/unlang/xlat_priv.h |
22 | | * @brief String expansion ("translation"). Implements %Attribute -> value |
23 | | * |
24 | | * Private structures for the xlat tokenizer and xlat eval code. |
25 | | * |
26 | | * @copyright 2000,2006 The FreeRADIUS server project |
27 | | * @copyright 2000 Alan DeKok (aland@freeradius.org) |
28 | | */ |
29 | | #ifdef __cplusplus |
30 | | extern "C" { |
31 | | #endif |
32 | | |
33 | | #include <freeradius-devel/unlang/xlat_ctx.h> |
34 | | #include <freeradius-devel/unlang/xlat.h> |
35 | | #include <freeradius-devel/unlang/xlat_func.h> |
36 | | #include <freeradius-devel/server/module_ctx.h> |
37 | | #include <freeradius-devel/io/pair.h> |
38 | | #include <freeradius-devel/util/talloc.h> |
39 | | #include <freeradius-devel/build.h> |
40 | | |
41 | | #ifdef DEBUG_XLAT |
42 | | # define XLAT_DEBUG RDEBUG3 |
43 | | #else |
44 | | # define XLAT_DEBUG(...) |
45 | | #endif |
46 | | |
47 | | /* |
48 | | * Allow public and private versions of the same structures |
49 | | */ |
50 | | #ifdef _CONST |
51 | | # error _CONST can only be defined in the local header |
52 | | #endif |
53 | | #ifndef _XLAT_PRIVATE |
54 | | # define _CONST const |
55 | | #else |
56 | | # define _CONST |
57 | | #endif |
58 | | |
59 | | typedef struct xlat_s { |
60 | | fr_rb_node_t func_node; //!< Entry in the xlat function tree. |
61 | | fr_dlist_t mi_entry; //!< Entry in the list of functions |
62 | | ///< registered to a module instance. |
63 | | |
64 | | char const *name; //!< Name of xlat function. |
65 | | xlat_func_t func; //!< async xlat function (async unsafe). |
66 | | |
67 | | bool internal; //!< If true, cannot be redefined. |
68 | | bool deprecated; //!< this function was deprecated |
69 | | char const *replaced_with; //!< this function was replaced with something else |
70 | | fr_token_t token; //!< for expressions |
71 | | |
72 | | module_inst_ctx_t *mctx; //!< Original module instantiation ctx if this |
73 | | ///< xlat was registered by a module. |
74 | | |
75 | | xlat_instantiate_t instantiate; //!< Instantiation function. |
76 | | xlat_detach_t detach; //!< Destructor for when xlat instances are freed. |
77 | | char const *inst_type; //!< C type of instance structure. |
78 | | size_t inst_size; //!< Size of instance data to pre-allocate. |
79 | | void *uctx; //!< uctx to pass to instantiation functions. |
80 | | |
81 | | xlat_thread_instantiate_t thread_instantiate; //!< Thread instantiation function. |
82 | | xlat_thread_detach_t thread_detach; //!< Destructor for when xlat thread instance data |
83 | | ///< is freed. |
84 | | char const *thread_inst_type; //!< C type of thread instance structure. |
85 | | size_t thread_inst_size; //!< Size of the thread instance data to pre-allocate. |
86 | | void *thread_uctx; //!< uctx to pass to instantiation functions. |
87 | | |
88 | | xlat_print_t print; //!< function to call when printing |
89 | | xlat_resolve_t resolve; //!< function to call when resolving |
90 | | xlat_purify_t purify; //!< function to call when purifying the node. |
91 | | |
92 | | xlat_flags_t flags; //!< various flags |
93 | | |
94 | | xlat_arg_parser_t const *args; //!< Definition of args consumed. |
95 | | |
96 | | call_env_method_t const *call_env_method; //!< Optional tmpl expansions performed before calling the |
97 | | ///< xlat. Typically used for xlats which refer to tmpls |
98 | | ///< in their module config. |
99 | | |
100 | | fr_value_box_safe_for_t return_safe_for; //!< Escaped value to set in output boxes. |
101 | | fr_type_t return_type; //!< Function is guaranteed to return one or more boxes |
102 | | ///< of this type. If the return type is FR_TYPE_VOID |
103 | | ///< then the xlat function can return any type of output. |
104 | | } xlat_t; |
105 | | |
106 | | typedef enum { |
107 | | XLAT_INVALID = 0x0000, //!< Bad expansion |
108 | | XLAT_BOX = 0x0001, //!< #fr_value_box_t |
109 | | XLAT_ONE_LETTER = 0x0002, //!< Special "one-letter" expansion |
110 | | XLAT_FUNC = 0x0004, //!< xlat module |
111 | | XLAT_FUNC_UNRESOLVED = 0x0008, //!< func needs resolution during pass2. |
112 | | XLAT_TMPL = 0x0010, //!< xlat attribute |
113 | | #ifdef HAVE_REGEX |
114 | | XLAT_REGEX = 0x0020, //!< regex reference %{1}, etc. |
115 | | #endif |
116 | | XLAT_GROUP = 0x0100 //!< encapsulated string of xlats |
117 | | } xlat_type_t; |
118 | | |
119 | | /** An xlat function call |
120 | | * |
121 | | */ |
122 | | typedef struct { |
123 | | uint64_t id; //!< Identifier unique to each permanent xlat node. |
124 | | ///< This is used by the instantiation code to order |
125 | | ///< nodes by the time they were created. |
126 | | |
127 | | xlat_t const *func; //!< The xlat expansion to expand format with. |
128 | | xlat_exp_head_t *args; //!< arguments to the function call |
129 | | |
130 | | fr_dict_t const *dict; //!< Records the namespace this xlat call was created in. |
131 | | ///< Used by the purify code to run fake requests in |
132 | | ///< the correct namespace, and accessible to instantiation |
133 | | ///< functions in case the xlat needs to perform runtime |
134 | | ///< resolution of attributes (as with %eval()). |
135 | | |
136 | | xlat_inst_t *inst; //!< Instance data for the #xlat_t. |
137 | | xlat_thread_inst_t *thread_inst; //!< Thread specific instance. |
138 | | ///< ONLY USED FOR EPHEMERAL XLATS. |
139 | | |
140 | | bool ephemeral; //!< Instance data is ephemeral (not inserted) |
141 | | ///< into the instance tree. |
142 | | } xlat_call_t; |
143 | | |
144 | | /** An xlat expansion node |
145 | | * |
146 | | * These nodes form a tree which represents one or more nested expansions. |
147 | | */ |
148 | | struct xlat_exp_s { |
149 | | fr_dlist_t entry; |
150 | | |
151 | | char const * _CONST fmt; //!< The original format string (a talloced buffer). |
152 | | fr_token_t quote; //!< Type of quoting around XLAT_GROUP types. |
153 | | |
154 | | xlat_flags_t flags; //!< Flags that control resolution and evaluation. |
155 | | xlat_type_t _CONST type; //!< type of this expansion. |
156 | | |
157 | | #ifndef NDEBUG |
158 | | char const * _CONST file; //!< File where the xlat was allocated. |
159 | | int line; //!< Line where the xlat was allocated. |
160 | | #endif |
161 | | |
162 | | union { |
163 | | struct { |
164 | | xlat_exp_head_t *group; //!< children of a group |
165 | | unsigned int hoist : 1; //!< it's a group, but we need to hoist the results |
166 | | }; |
167 | | |
168 | | /** An tmpl_t reference |
169 | | * |
170 | | * May be an attribute to expand, or an exec reference, or a value-box, ... |
171 | | */ |
172 | | tmpl_t *vpt; |
173 | | |
174 | | /** A capture group, i.e. for %{1} and friends |
175 | | */ |
176 | | int regex_index; |
177 | | |
178 | | /** An xlat function call |
179 | | */ |
180 | | xlat_call_t call; |
181 | | |
182 | | /** A value box |
183 | | */ |
184 | | fr_value_box_t data; |
185 | | }; |
186 | | }; |
187 | | |
188 | | struct xlat_exp_head_s { |
189 | | fr_dlist_head_t dlist; |
190 | | xlat_flags_t flags; //!< Flags that control resolution and evaluation. |
191 | | unsigned int instantiated : 1; //!< temporary flag until we fix more things |
192 | | unsigned int is_argv : 1; //!< this thing holds function arguments |
193 | | unsigned int cursor : 1; //!< otherwise it's too hard to pass xlat_arg_parser_t to the evaluation function. |
194 | | unsigned int is_attr : 1; //!< the argument is an attribute reference |
195 | | |
196 | | #ifndef NDEBUG |
197 | | char const * _CONST file; //!< File where the xlat was allocated. |
198 | | int line; //!< Line where the xlat was allocated. |
199 | | #endif |
200 | | }; |
201 | | |
202 | | typedef struct { |
203 | | char const *out; //!< Output data. |
204 | | size_t len; //!< Length of the output string. |
205 | | } xlat_out_t; |
206 | | /* |
207 | | * Helper functions |
208 | | */ |
209 | | |
210 | | static inline xlat_exp_t *xlat_exp_head(xlat_exp_head_t const *head) |
211 | 0 | { |
212 | 0 | if (!head) return NULL; |
213 | 0 |
|
214 | 0 | return fr_dlist_head(&head->dlist); |
215 | 0 | } Unexecuted instantiation: foreach.c:xlat_exp_head Unexecuted instantiation: switch.c:xlat_exp_head |
216 | | |
217 | | /** Iterate over the contents of a list, only one level |
218 | | * |
219 | | * @param[in] _list_head to iterate over. |
220 | | * @param[in] _iter Name of iteration variable. |
221 | | * Will be declared in the scope of the loop. |
222 | | */ |
223 | | #define xlat_exp_foreach(_list_head, _iter) fr_dlist_foreach(&((_list_head)->dlist), xlat_exp_t, _iter) |
224 | | |
225 | | /** Merge flags from child to parent |
226 | | * |
227 | | * For pass2, if either the parent or child is marked up for pass2, then the parent |
228 | | * is marked up for pass2. |
229 | | */ |
230 | | static inline CC_HINT(nonnull) void xlat_flags_merge(xlat_flags_t *parent, xlat_flags_t const *child) |
231 | 0 | { |
232 | 0 | parent->needs_resolving |= child->needs_resolving; |
233 | 0 | parent->pure &= child->pure; /* purity can only be removed, never added */ |
234 | 0 | parent->can_purify |= child->can_purify; /* there is SOME node under us which can be purified */ |
235 | 0 | parent->constant &= child->constant; |
236 | 0 | parent->impure_func |= child->impure_func; |
237 | 0 | } Unexecuted instantiation: foreach.c:xlat_flags_merge Unexecuted instantiation: switch.c:xlat_flags_merge |
238 | | |
239 | | static inline CC_HINT(nonnull) int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node) |
240 | 0 | { |
241 | 0 | XLAT_VERIFY(node); |
242 | 0 |
|
243 | 0 | xlat_flags_merge(&head->flags, &node->flags); |
244 | 0 | return fr_dlist_insert_tail(&head->dlist, node); |
245 | 0 | } Unexecuted instantiation: foreach.c:xlat_exp_insert_tail Unexecuted instantiation: switch.c:xlat_exp_insert_tail |
246 | | |
247 | | static inline xlat_exp_t *xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node) |
248 | 0 | { |
249 | 0 | if (!head) return NULL; |
250 | 0 |
|
251 | 0 | return fr_dlist_next(&head->dlist, node); |
252 | 0 | } Unexecuted instantiation: foreach.c:xlat_exp_next Unexecuted instantiation: switch.c:xlat_exp_next |
253 | | |
254 | | /* |
255 | | * xlat_purify.c |
256 | | */ |
257 | | int xlat_purify_list(xlat_exp_head_t *head, request_t *request); |
258 | | |
259 | | /** Walker callback for xlat_walk() |
260 | | * |
261 | | * @param[in] exp being evaluated. |
262 | | * @param[in] uctx passed to xlat_walk. |
263 | | * @return |
264 | | * - 1 for "prune walk here". |
265 | | * - 0 on success. |
266 | | * - <0 if node evaluation failed. Causes xlat_walk to return the negative integer. |
267 | | */ |
268 | | typedef int (*xlat_walker_t)(xlat_exp_t *exp, void *uctx); |
269 | | |
270 | | /* |
271 | | * xlat_alloc.c |
272 | | */ |
273 | | xlat_exp_head_t *_xlat_exp_head_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx); |
274 | | #define xlat_exp_head_alloc(_ctx) _xlat_exp_head_alloc(NDEBUG_LOCATION_EXP _ctx) |
275 | | |
276 | | void _xlat_exp_set_type(NDEBUG_LOCATION_ARGS xlat_exp_t *node, xlat_type_t type); |
277 | | #define xlat_exp_set_type(_node, _type) _xlat_exp_set_type(NDEBUG_LOCATION_EXP _node, _type) |
278 | | |
279 | | xlat_exp_t *_xlat_exp_alloc_null(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx); |
280 | | #define xlat_exp_alloc_null(_ctx) _xlat_exp_alloc_null(NDEBUG_LOCATION_EXP _ctx) |
281 | | |
282 | | xlat_exp_t *_xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen); |
283 | | #define xlat_exp_alloc(_ctx, _type, _in, _inlen) _xlat_exp_alloc(NDEBUG_LOCATION_EXP _ctx, _type, _in, _inlen) |
284 | | |
285 | | void xlat_exp_set_name(xlat_exp_t *node, char const *fmt, size_t len) CC_HINT(nonnull); |
286 | | void xlat_exp_set_name_shallow(xlat_exp_t *node, char const *fmt) CC_HINT(nonnull); |
287 | | void xlat_exp_set_name_buffer(xlat_exp_t *node, char const *fmt) CC_HINT(nonnull); |
288 | | |
289 | | void xlat_exp_set_vpt(xlat_exp_t *node, tmpl_t *vpt) CC_HINT(nonnull); |
290 | | void xlat_exp_set_func(xlat_exp_t *node, xlat_t const *func, fr_dict_t const *dict) CC_HINT(nonnull(1,2)); |
291 | | void xlat_exp_finalize_func(xlat_exp_t *node) CC_HINT(nonnull); |
292 | | |
293 | | /* |
294 | | * xlat_func.c |
295 | | */ |
296 | | xlat_t *xlat_func_find(char const *name, ssize_t namelen); |
297 | | |
298 | | /* |
299 | | * xlat_eval.c |
300 | | */ |
301 | | extern fr_dict_attr_t const *attr_expr_bool_enum; |
302 | | extern fr_dict_attr_t const *attr_module_return_code; |
303 | | extern fr_dict_attr_t const *attr_cast_base; |
304 | | |
305 | | fr_dict_attr_t const *xlat_time_res_attr(char const *res); |
306 | | |
307 | | /* |
308 | | * xlat_tokenize.c |
309 | | */ |
310 | | extern bool const xlat_func_chars[SBUFF_CHAR_CLASS]; |
311 | | |
312 | | int xlat_tokenize_regex(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in, fr_sbuff_marker_t *m_s) CC_HINT(nonnull); |
313 | | |
314 | | void xlat_signal(xlat_func_signal_t signal, xlat_exp_t const *exp, |
315 | | request_t *request, void *rctx, fr_signal_t action); |
316 | | |
317 | | xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, |
318 | | xlat_exp_head_t const **child, |
319 | | request_t *request, xlat_exp_head_t const *head, xlat_exp_t const **in, |
320 | | fr_value_box_list_t *result, xlat_func_t resume, void *rctx); |
321 | | |
322 | | xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_dcursor_t *out, |
323 | | xlat_exp_head_t const **child, |
324 | | request_t *request, xlat_exp_head_t const *head, xlat_exp_t const **in, |
325 | | void *env_data, fr_value_box_list_t *result) CC_HINT(nonnull(1,2,3,4)); |
326 | | |
327 | | xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_head_t const **child, |
328 | | request_t *request, xlat_exp_head_t const *head, xlat_exp_t const **in); |
329 | | |
330 | | int xlat_eval_walk(xlat_exp_head_t *head, xlat_walker_t walker, xlat_type_t type, void *uctx); |
331 | | |
332 | | int xlat_eval_init(void); |
333 | | |
334 | | void xlat_eval_free(void); |
335 | | |
336 | | void unlang_xlat_init(void); |
337 | | |
338 | | int unlang_xlat_push_node(TALLOC_CTX *ctx, unlang_result_t *p_result, fr_value_box_list_t *out, |
339 | | request_t *request, xlat_exp_t *node); |
340 | | |
341 | | int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out, |
342 | | request_t *request, void *decode_ctx, fr_pair_decode_t decode, |
343 | | fr_value_box_list_t *in); |
344 | | /* |
345 | | * xlat_expr.c |
346 | | */ |
347 | | int xlat_register_expressions(void); |
348 | | |
349 | | /* |
350 | | * xlat_tokenize.c |
351 | | */ |
352 | | ssize_t xlat_print_node(fr_sbuff_t *out, xlat_exp_head_t const *head, xlat_exp_t const *node, |
353 | | fr_sbuff_escape_rules_t const *e_rules, char c); |
354 | | |
355 | | fr_slen_t xlat_tokenize_word(TALLOC_CTX *ctx, xlat_exp_t **out, fr_sbuff_t *in, fr_token_t quote, |
356 | | fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules) CC_HINT(nonnull); |
357 | | |
358 | | #ifdef __cplusplus |
359 | | } |
360 | | #endif |