The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
map.c
Go to the documentation of this file.
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 (at
5 * 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: 38ef7b9b56f393de5e913a069c6722e6f3f3980d $
19 * @file src/lib/ldap/map.c
20 * @brief Functions for mapping between LDAP and FreeRADIUS attributes.
21 *
22 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 * @copyright 2013 Network RADIUS SAS (legal@networkradius.com)
24 * @copyright 2013 The FreeRADIUS Server Project.
25 */
26RCSID("$Id: 38ef7b9b56f393de5e913a069c6722e6f3f3980d $")
27
29
30#include <freeradius-devel/util/debug.h>
31#include <freeradius-devel/ldap/base.h>
32
33/** Callback for map_to_request
34 *
35 * Performs exactly the same job as map_to_vp, but pulls attribute values from LDAP entries
36 *
37 * @see map_to_vp
38 */
39int fr_ldap_map_getvalue(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
40{
41 fr_ldap_result_t *self = uctx;
44 int i;
45
47
48 fr_assert(map->lhs->type == TMPL_TYPE_ATTR);
49
50 /*
51 * This is a mapping in the form of:
52 * <list>. += <ldap attr>
53 *
54 * Where <ldap attr> is:
55 * <list>.<attr> <op> <value>
56 *
57 * It is to allow for legacy installations which stored
58 * RADIUS control and reply attributes in separate LDAP
59 * attributes.
60 */
61 if (tmpl_is_list(map->lhs)) {
62 for (i = 0; i < self->count; i++) {
63 map_t *attr = NULL;
64 char *attr_str;
65
66 tmpl_rules_t lhs_rules = {
67 .attr = {
68 .dict_def = request->local_dict,
69 .request_def = tmpl_request(map->lhs),
70 .list_def = tmpl_list(map->lhs),
71 },
72 .xlat = {
73 .runtime_el = unlang_interpret_event_list(request),
74 },
75 .at_runtime = true,
76 };
77
78 tmpl_rules_t rhs_rules = {
79 .attr = {
80 .dict_def = request->local_dict
81 },
82 .xlat = {
83 .runtime_el = lhs_rules.xlat.runtime_el,
84 },
85 .at_runtime = true,
86 };
87
88 RDEBUG3("Parsing valuepair string \"%pV\"",
89 fr_box_strvalue_len(self->values[i]->bv_val, self->values[i]->bv_len));
90
91 /*
92 * bv_val is NOT \0 terminated, so we need to make it
93 * safe (\0 terminate it) before passing it to any
94 * functions which take C strings and no lengths.
95 */
96 attr_str = talloc_bstrndup(NULL, self->values[i]->bv_val, self->values[i]->bv_len);
97 if (!attr_str) {
98 RWDEBUG("Failed making attribute string safe");
99 continue;
100 }
101
102 if (map_afrom_attr_str(ctx, &attr,
103 attr_str,
104 &lhs_rules, &rhs_rules) < 0) {
105 RPWDEBUG("Failed parsing \"%pV\" as valuepair, skipping...",
106 fr_box_strvalue_len(self->values[i]->bv_val, self->values[i]->bv_len));
107 talloc_free(attr_str);
108 continue;
109 }
110
111 talloc_free(attr_str);
112
113 if (tmpl_is_data_unresolved(attr->lhs)) {
114 RWDEBUG("Failed parsing left side of \"%pV\", skipping...",
115 fr_box_strvalue_len(self->values[i]->bv_val, self->values[i]->bv_len));
116 talloc_free(attr);
117 continue;
118 }
119
120 if (tmpl_request_ref_list_cmp(tmpl_request(attr->lhs), tmpl_request(map->lhs)) != 0) {
121 char *attr_request;
122 char *map_request;
123
124 tmpl_request_ref_list_aprint(NULL, &attr_request, tmpl_request(attr->lhs));
125 tmpl_request_ref_list_aprint(NULL, &map_request, tmpl_request(map->lhs));
126
127 RWDEBUG("valuepair \"%pV\" has conflicting request qualifier (%s vs %s), skipping...",
128 fr_box_strvalue_len(self->values[i]->bv_val, self->values[i]->bv_len),
129 attr_request, map_request);
130
131 talloc_free(attr_request);
132 talloc_free(map_request);
133
134 next_pair:
135 talloc_free(attr);
136 continue;
137 }
138
139 if ((tmpl_list(attr->lhs) != tmpl_list(map->lhs))) {
140 RWDEBUG("valuepair \"%pV\" has conflicting list qualifier (%s vs %s), skipping...",
141 fr_box_strvalue_len(self->values[i]->bv_val, self->values[i]->bv_len),
142 tmpl_list_name(tmpl_list(attr->lhs), "<INVALID>"),
143 tmpl_list_name(tmpl_list(map->lhs), "<INVALID>"));
144 goto next_pair;
145 }
146
147 if (map_to_request(request, attr, map_to_vp, NULL) < 0) {
148 RWDEBUG("Failed creating attribute for valuepair \"%pV\", skipping...",
149 fr_box_strvalue_len(self->values[i]->bv_val, self->values[i]->bv_len));
150 goto next_pair;
151 }
152
153 talloc_free(attr);
154
155 /*
156 * Only process the first value, unless the operator is +=
157 */
158 if (map->op != T_OP_ADD_EQ) break;
159 }
160 goto finish;
161 }
162
163 /*
164 * Iterate over all the retrieved values,
165 * don't try and be clever about changing operators
166 * just use whatever was set in the attribute map.
167 */
168 for (i = 0; i < self->count; i++) {
169 if (!self->values[i]->bv_len) continue;
170
172
173 if (fr_pair_value_from_str(vp, self->values[i]->bv_val,
174 self->values[i]->bv_len, NULL, true) < 0) {
175 RPWDEBUG("Failed parsing value \"%pV\" for attribute %s",
176 fr_box_strvalue_len(self->values[i]->bv_val, self->values[i]->bv_len),
177 tmpl_attr_tail_da(map->lhs)->name);
178
180 continue;
181 }
182
184
185 /*
186 * Only process the first value, unless the operator is +=
187 */
188 if (map->op != T_OP_ADD_EQ) break;
189 }
190
191finish:
193
194 return 0;
195}
196
197/** Callback for map_to_request
198 *
199 * Performs exactly the same job as map_to_vp, but pulls value from the entry DN.
200 *
201 * @see map_to_vp
202 */
203static int fr_ldap_map_getdn(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
204{
205 char const *dn = uctx;
206 fr_pair_t *vp;
207
208 fr_assert(map->lhs->type == TMPL_TYPE_ATTR);
209 switch (tmpl_attr_tail_da(map->lhs)->type) {
210 case FR_TYPE_STRING:
211 case FR_TYPE_OCTETS:
212 break;
213
214 default:
215 RERROR("Cannot store DN in %s",
216 fr_table_str_by_value(fr_type_table, tmpl_attr_tail_da(map->lhs)->type, "<INVALID>"));
217 return -1;
218 }
219
221
222 if (fr_pair_value_from_str(vp, dn, strlen(dn), NULL, true) < 0) {
223 RPWDEBUG("Failed parsing value \"%pV\" for attribute %s", dn,
224 tmpl_attr_tail_da(map->lhs)->name);
226 return 0;
227 }
228
230
231 return 0;
232}
233
234int fr_ldap_map_verify(map_t *map, UNUSED void *instance)
235{
236 /*
237 * Destinations where we can put the fr_pair_ts we
238 * create using LDAP values.
239 */
240 switch (map->lhs->type) {
241 case TMPL_TYPE_ATTR:
242 break;
243
245 cf_log_err(map->ci, "Unknown attribute %s", tmpl_attr_tail_unresolved(map->lhs));
246 return -1;
247
248 default:
249 cf_log_err(map->ci, "Left hand side of map must be an attribute or list, not a %s",
250 tmpl_type_to_str(map->lhs->type));
251 return -1;
252 }
253
254 /*
255 * Sources we can use to get the name of the attribute
256 * we're retrieving from LDAP.
257 */
258 switch (map->rhs->type) {
260 case TMPL_TYPE_ATTR:
261 case TMPL_TYPE_EXEC:
262 case TMPL_TYPE_DATA:
263 break;
264
266 cf_log_err(map->ci, "Unknown attribute %s", tmpl_attr_tail_unresolved(map->rhs));
267 return -1;
268
270 if (tmpl_resolve(map->rhs, NULL) < 0) {
271 cf_log_err(map->ci, "Invalid data %s", map->rhs->name);
272 return -1;
273 }
274 break;
275
276 default:
277 cf_log_err(map->ci, "Right hand side of map must be an xlat, attribute, exec, or literal, not a %s",
278 tmpl_type_to_str(map->rhs->type));
279 return -1;
280 }
281
282 /*
283 * Only =, :=, += and -= operators are supported for LDAP mappings.
284 */
285 switch (map->op) {
286 case T_OP_SET:
287 case T_OP_EQ:
288 case T_OP_SUB_EQ:
289 case T_OP_ADD_EQ:
290 break;
291
292 default:
293 cf_log_err(map->ci, "Operator \"%s\" not allowed for LDAP mappings",
294 fr_table_str_by_value(fr_tokens_table, map->op, "<INVALID>"));
295 return -1;
296 }
297
298 return 0;
299}
300
301/** Expand values in an attribute map where needed
302 *
303 * @param[in] ctx o allocate any dynamic expansions in.
304 * @param[out] expanded array of attributes. Need not be initialised (we'll initialise).
305 * @param[in] request The current request.
306 * @param[in] maps to expand.
307 * @param[in] generic_attr name to append to the attribute list.
308 * @param[in] check_attr name to append to the attribute list.
309 * @param[in] fallthrough_attr name to append to the attribute list.
310 * @return
311 * - 0 on success.
312 * - -1 on failure.
313 */
314int fr_ldap_map_expand(TALLOC_CTX *ctx, fr_ldap_map_exp_t *expanded, request_t *request, map_list_t const *maps,
315 char const *generic_attr, char const *check_attr, char const *fallthrough_attr)
316{
317 map_t const *map = NULL;
318 unsigned int total = 0;
319
320 TALLOC_CTX *our_ctx = NULL;
321 char const *attr;
322 char attr_buff[1024 + 1]; /* X.501 says we need to support at least 1024 chars for attr names */
323
324 while ((map = map_list_next(maps, map))) {
325 if (tmpl_expand(&attr, attr_buff, sizeof(attr_buff), request, map->rhs) < 0) {
326 REDEBUG("Expansion of LDAP attribute \"%s\" failed", map->rhs->name);
327 TALLOC_FREE(our_ctx);
328 return -1;
329 }
330
331 /*
332 * Dynamic value
333 */
334 if (attr == attr_buff) {
335 if (!our_ctx) our_ctx = talloc_new(ctx);
336 expanded->attrs[total++] = talloc_strdup(our_ctx, attr_buff);
337 continue;
338 }
339 expanded->attrs[total++] = attr;
340 }
341
342 if (generic_attr) expanded->attrs[total++] = generic_attr;
343 if (check_attr) expanded->attrs[total++] = check_attr;
344 if (fallthrough_attr) expanded->attrs[total++] = fallthrough_attr;
345
346 expanded->attrs[total] = NULL;
347 expanded->count = total;
348 expanded->maps = maps;
349
350 return 0;
351}
352
353
354/** Convert attribute map into valuepairs
355 *
356 * Use the attribute map built earlier to convert LDAP values into valuepairs and insert them into whichever
357 * list they need to go into.
358 *
359 * This is *NOT* atomic, but there's no condition for which we should error out...
360 *
361 * @param[in] request Current request.
362 * @param[in] check_attr Treat attribute with this name as a condition to process the map.
363 * @param[in] valuepair_attr Treat attribute with this name as holding complete AVP definitions.
364 * @param[in] expanded attributes (rhs of map).
365 * @param[in] entry to retrieve attributes from.
366 * @return
367 * - Number of maps successfully applied.
368 * - -1 on failure.
369 */
370int fr_ldap_map_do(request_t *request, char const *check_attr,
371 char const *valuepair_attr, fr_ldap_map_exp_t const *expanded, LDAPMessage *entry)
372{
373 map_t const *map = NULL;
374 unsigned int total = 0;
375 int applied = 0; /* How many maps have been applied to the current request */
376
377 fr_ldap_result_t result;
378 char const *name;
379 LDAP *handle = fr_ldap_handle_thread_local();
380
381 if (check_attr) {
382 struct berval **values;
383 int count, i;
384 tmpl_rules_t const parse_rules = {
385 .attr = {
386 .dict_def = request->local_dict,
387 .list_def = request_attr_request,
388 },
389 .xlat = {
390 .runtime_el = unlang_interpret_event_list(request),
391 },
392 .at_runtime = true,
393 };
394
395 values = ldap_get_values_len(handle, entry, check_attr);
396 count = ldap_count_values_len(values);
397
398 for (i = 0; i < count; i++) {
399 char *value = fr_ldap_berval_to_string(request, values[i]);
400 xlat_exp_head_t *cond_expr = NULL;
401 fr_value_box_list_t res;
402
403 RDEBUG3("Parsing condition %s", value);
404
405 if (xlat_tokenize_expression(request, &cond_expr,
407 NULL, &parse_rules) < 0) {
408 RPEDEBUG("Failed parsing '%s' value \"%s\"", check_attr, value);
409 fail:
410 applied = -1;
411 free:
412 talloc_free(cond_expr);
414 ldap_value_free_len(values);
415 return applied;
416 }
417
418 if (xlat_impure_func(cond_expr)) {
419 fr_strerror_const("Condition expression cannot depend on functions which call external databases");
420 goto fail;
421 }
422
423 RDEBUG2("Checking condition %s", value);
424 fr_value_box_list_init(&res);
425 if (unlang_xlat_eval(request, &res, request, cond_expr) < 0) {
426 RPEDEBUG("Failed evaluating condition");
427 goto fail;
428 }
429 if (!fr_value_box_list_head(&res) || !fr_value_box_is_truthy(fr_value_box_list_head(&res))) {
430 RDEBUG2("Failed match: skipping this profile");
431 fr_value_box_list_talloc_free(&res);
432 goto free;
433 }
435 talloc_free(cond_expr);
436 fr_value_box_list_talloc_free(&res);
437 }
438 ldap_value_free_len(values);
439 }
440
441 while ((map = map_list_next(expanded->maps, map))) {
442 int ret;
443
444 name = expanded->attrs[total++];
445
446 /*
447 * Binary safe
448 */
449 result.values = ldap_get_values_len(handle, entry, name);
450 if (!result.values) {
451 /*
452 * dn is different - it's not (normally) an LDAP attribute
453 * so requires special handling.
454 */
455 if (strcmp(name, "dn") == 0) {
456 char *dn = ldap_get_dn(handle, entry);
458 ret = map_to_request(request, map, fr_ldap_map_getdn, dn);
459 ldap_memfree(dn);
460 if (ret == -1) return -1;
461 applied++;
462 continue;
463 }
464
465 RDEBUG3("Attribute \"%s\" not found in LDAP object", name);
466
467 goto next;
468 }
469
470 /*
471 * Find out how many values there are for the
472 * attribute and extract all of them.
473 */
474 result.count = ldap_count_values_len(result.values);
475
476 /*
477 * If something bad happened, just skip, this is probably
478 * a case of the dst being incorrect for the current
479 * request context
480 */
481 ret = map_to_request(request, map, fr_ldap_map_getvalue, &result);
482 if (ret == -1) return -1; /* Fail */
483
484 /*
485 * How many maps we've processed
486 */
487 applied++;
488
489 next:
490 if (result.values) ldap_value_free_len(result.values);
491 }
492
493
494 /*
495 * Retrieve any valuepair attributes from the result, these are generic values specifying
496 * a radius list, operator and value.
497 */
498 if (valuepair_attr) {
499 struct berval **values;
500 int count, i;
501
502 values = ldap_get_values_len(handle, entry, valuepair_attr);
503 count = ldap_count_values_len(values);
504
505 for (i = 0; i < count; i++) {
506 map_t *attr;
507 char *value;
508
509 tmpl_rules_t const parse_rules = {
510 .attr = {
511 .dict_def = request->local_dict,
512 .list_def = request_attr_request,
513 },
514 .xlat = {
515 .runtime_el = unlang_interpret_event_list(request),
516 },
517 .at_runtime = true,
518 };
519
520 value = fr_ldap_berval_to_string(request, values[i]);
521 RDEBUG3("Parsing attribute string '%s'", value);
522 if (map_afrom_attr_str(request, &attr, value,
523 &parse_rules, &parse_rules) < 0) {
524 RPWDEBUG("Failed parsing '%s' value \"%s\" as valuepair, skipping...",
525 valuepair_attr, value);
527 continue;
528 }
529 if (map_to_request(request, attr, map_to_vp, NULL) < 0) {
530 RWDEBUG("Failed adding \"%s\" to request, skipping...", value);
531 } else {
532 applied++;
533 }
534 talloc_free(attr);
536 }
537 ldap_value_free_len(values);
538 }
539
540 return applied;
541}
#define USES_APPLE_DEPRECATED_API
Definition build.h:499
#define RCSID(id)
Definition build.h:512
#define UNUSED
Definition build.h:336
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:345
#define MEM(x)
Definition debug.h:36
Test enumeration values.
Definition dict_test.h:92
free(array)
talloc_free(hp)
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:2411
size_t fr_ldap_util_normalise_dn(char *out, char const *in)
Normalise escape sequences in a DN.
Definition util.c:561
struct berval ** values
libldap struct containing bv_val (char *) and length bv_len.
Definition base.h:361
int count
Index on next free element.
Definition base.h:375
map_list_t const * maps
Head of list of maps we expanded the RHS of.
Definition base.h:371
char * fr_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in)
Convert a berval to a talloced string.
Definition util.c:512
int count
Number of values.
Definition base.h:363
char const * attrs[LDAP_MAX_ATTRMAP+LDAP_MAP_RESERVED+1]
Reserve some space for access attributes.
Definition base.h:372
Result of expanding the RHS of a set of maps.
Definition base.h:370
Contains a collection of values.
Definition base.h:360
LDAP * fr_ldap_handle_thread_local(void)
Get a thread local dummy LDAP handle.
Definition base.c:1129
int fr_ldap_map_do(request_t *request, char const *check_attr, char const *valuepair_attr, fr_ldap_map_exp_t const *expanded, LDAPMessage *entry)
Convert attribute map into valuepairs.
Definition map.c:370
static int fr_ldap_map_getdn(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
Callback for map_to_request.
Definition map.c:203
USES_APPLE_DEPRECATED_API int fr_ldap_map_getvalue(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, void *uctx)
Callback for map_to_request.
Definition map.c:39
int fr_ldap_map_verify(map_t *map, UNUSED void *instance)
Definition map.c:234
int fr_ldap_map_expand(TALLOC_CTX *ctx, fr_ldap_map_exp_t *expanded, request_t *request, map_list_t const *maps, char const *generic_attr, char const *check_attr, char const *fallthrough_attr)
Expand values in an attribute map where needed.
Definition map.c:314
#define RWDEBUG(fmt,...)
Definition log.h:373
#define RDEBUG3(fmt,...)
Definition log.h:355
#define RERROR(fmt,...)
Definition log.h:310
#define RPEDEBUG(fmt,...)
Definition log.h:388
#define RPWDEBUG(fmt,...)
Definition log.h:378
int map_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, UNUSED void *uctx)
Convert a map to a fr_pair_t.
Definition map.c:1604
int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert map_t to fr_pair_t (s) and add them to a request_t.
Definition map.c:1884
int map_afrom_attr_str(TALLOC_CTX *ctx, map_t **out, char const *vp_str, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules)
Convert a value pair string to valuepair map.
Definition map.c:1433
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_OCTETS
Raw octets.
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, UNUSED bool tainted)
Convert string value to native attribute value.
Definition pair.c:2617
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:1352
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:290
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
fr_dict_attr_t const * request_attr_request
Definition request.c:43
static char const * name
#define FR_SBUFF_IN(_start, _len_or_end)
int8_t tmpl_request_ref_list_cmp(FR_DLIST_HEAD(tmpl_request_list) const *a, FR_DLIST_HEAD(tmpl_request_list) const *b)
Compare a list of request qualifiers.
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
Definition tmpl.h:638
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
Definition tmpl.h:904
static fr_slen_t tmpl_request_ref_list_aprint(TALLOC_CTX *ctx, char **out, FR_DLIST_HEAD(tmpl_request_list) const *rql) 1(tmpl_request_ref_list_print
@ TMPL_TYPE_ATTR_UNRESOLVED
An attribute reference that we couldn't resolve but looked valid.
Definition tmpl.h:185
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition tmpl.h:142
@ TMPL_TYPE_EXEC
Callout to an external script or program.
Definition tmpl.h:150
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:138
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
Definition tmpl.h:179
@ TMPL_TYPE_XLAT_UNRESOLVED
A xlat expansion with unresolved xlat functions or attribute references.
Definition tmpl.h:193
tmpl_xlat_rules_t xlat
Rules/data for parsing xlats.
Definition tmpl.h:340
static char const * tmpl_attr_tail_unresolved(tmpl_t const *vpt)
Return the last attribute reference unresolved da.
Definition tmpl.h:869
static bool tmpl_is_list(tmpl_t const *vpt)
Definition tmpl.h:920
#define tmpl_expand(_out, _buff, _buff_len, _request, _vpt)
Expand a tmpl to a C type, using existing storage to hold variably sized types.
Definition tmpl.h:1054
#define tmpl_is_data_unresolved(vpt)
Definition tmpl.h:217
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:339
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:801
static char const * tmpl_list_name(fr_dict_attr_t const *list, char const *def)
Return the name of a tmpl list or def if list not provided.
Definition tmpl.h:915
fr_event_list_t * runtime_el
The eventlist to use for runtime instantiation of xlats.
Definition tmpl.h:328
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
return count
Definition module.c:155
fr_pair_t * vp
Value pair map.
Definition map.h:77
fr_token_t op
The operator that controls insertion of the dst attribute.
Definition map.h:82
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
Definition map.h:78
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Definition map.h:79
CONF_ITEM * ci
Config item that the map was created from.
Definition map.h:85
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:273
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition talloc.c:618
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
fr_table_num_ordered_t const fr_tokens_table[]
Definition token.c:33
@ T_OP_SUB_EQ
Definition token.h:68
@ T_OP_EQ
Definition token.h:81
@ T_OP_SET
Definition token.h:82
@ T_OP_ADD_EQ
Definition token.h:67
int unlang_xlat_eval(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *xlat)
Evaluate a "pure" (or not impure) xlat.
Definition xlat.c:711
bool xlat_impure_func(xlat_exp_head_t const *head)
static fr_slen_t head
Definition xlat.h:420
fr_slen_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Definition xlat_expr.c:3163
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
#define fr_strerror_const(_msg)
Definition strerror.h:223
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
Definition types.c:31
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition value.c:7390
#define fr_box_strvalue_len(_val, _len)
Definition value.h:309
static size_t char ** out
Definition value.h:1030