All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
map_proc.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
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: 20fb285d84cc93cc8799080aef0e94d39e8e8895 $
19  *
20  * @brief Map processor functions
21  * @file main/map_proc.c
22  *
23  * @copyright 2015 The FreeRADIUS server project
24  * @copyright 2015 Arran Cudbard-bell <a.cudbardb@freeradius.org>
25  */
26 
27 RCSID("$Id: 20fb285d84cc93cc8799080aef0e94d39e8e8895 $")
28 
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/rad_assert.h>
31 #include <freeradius-devel/map_proc.h>
32 
33 static rbtree_t *map_proc_root = NULL;
34 
35 /** Map processor registration
36  */
37 struct map_proc {
38  void *mod_inst; //!< Module instance.
39  char name[MAX_STRING_LEN]; //!< Name of the map function.
40  int length; //!< Length of name.
41 
42  map_proc_func_t evaluate; //!< Module's map processor function.
43  map_proc_instantiate_t instantiate; //!< Callback to create new instance struct.
44  xlat_escape_t escape; //!< Escape function to apply to expansions in the map
45  //!< query string.
46  size_t inst_size; //!< Size of map_proc instance data to allocate.
47 };
48 
49 /** Map processor instance
50  */
51 struct map_proc_inst {
52  map_proc_t const *proc; //!< Map processor.
53  vp_tmpl_t const *src; //!< Evaluated to provide source value for map processor.
54  vp_map_t const *maps; //!< Head of the map list.
55  void *data; //!< Instance data created by #map_proc_instantiate
56 };
57 
58 /** Compare two map_proc_t structs, based ONLY on the name
59  *
60  * @param[in] one First map struct.
61  * @param[in] two Second map struct.
62  * @return Integer specifying order of map func instances.
63  */
64 static int map_proc_cmp(void const *one, void const *two)
65 {
66  map_proc_t const *a = one;
67  map_proc_t const *b = two;
68 
69  if (a->length != b->length) return a->length - b->length;
70 
71  return memcmp(a->name, b->name, a->length);
72 }
73 
74 /** Unregister a map processor
75  *
76  * @param[in] proc to unregister.
77  */
79 {
80  map_proc_t find;
81  map_proc_t *found;
82 
83  strlcpy(find.name, proc->name, sizeof(find.name));
84  find.length = strlen(find.name);
85 
86  found = rbtree_finddata(map_proc_root, &find);
87  if (!found) return 0;
88 
89  rbtree_deletebydata(map_proc_root, found);
90 
91  return 0;
92 }
93 
94 /** Find a map processor by name
95  *
96  * @param[in] name of map processor.
97  * @return
98  * - #map_proc matching name.
99  * - NULL if none was found.
100  */
102 {
103  map_proc_t find;
104 
105  if (!map_proc_root) return NULL;
106 
107  strlcpy(find.name, name, sizeof(find.name));
108  find.length = strlen(find.name);
109 
110  return rbtree_finddata(map_proc_root, &find);
111 }
112 
113 void map_proc_free(void)
114 {
115  TALLOC_FREE(map_proc_root);
116 }
117 
118 /** Register a map processor
119  *
120  * This should be called by every module that provides a map processing function.
121  *
122  * @param[in] mod_inst of module registering the map_proc.
123  * @param[in] name of map processor. If processor already exists, it is replaced.
124  * @param[in] evaluate Module's map processor function.
125  * @param[in] escape function to sanitize any sub expansions in the map source query.
126  * @param[in] instantiate function (optional).
127  * @param[in] inst_size of talloc chunk to allocate for instance data (optional).
128  * @return
129  * - 0 on success.
130  * - -1 on failure.
131  */
132 int map_proc_register(void *mod_inst, char const *name,
133  map_proc_func_t evaluate,
134  xlat_escape_t escape,
135  map_proc_instantiate_t instantiate, size_t inst_size)
136 {
137  map_proc_t *proc;
138 
139  rad_assert(name && name[0]);
140 
141  if (!map_proc_root) {
142  map_proc_root = rbtree_create(NULL, map_proc_cmp, NULL, RBTREE_FLAG_REPLACE);
143  if (!map_proc_root) {
144  DEBUG("map_proc: Failed to create tree");
145  return -1;
146  }
147  }
148 
149  /*
150  * If it already exists, replace it.
151  */
152  proc = map_proc_find(name);
153  if (!proc) {
154  rbnode_t *node;
155 
156  proc = talloc_zero(mod_inst, map_proc_t);
157  strlcpy(proc->name, name, sizeof(proc->name));
158  proc->length = strlen(proc->name);
159 
160  node = rbtree_insert_node(map_proc_root, proc);
161  if (!node) {
162  talloc_free(proc);
163  return -1;
164  }
165 
166  talloc_set_destructor(proc, _map_proc_unregister);
167  }
168 
169  DEBUG3("map_proc_register: %s", proc->name);
170 
171  proc->mod_inst = mod_inst;
172  proc->evaluate = evaluate;
173  proc->escape = escape;
174  proc->instantiate = instantiate;
175  proc->inst_size = inst_size;
176 
177  return 0;
178 }
179 
180 /** Create a new map proc instance
181  *
182  * This should be called for every map {} section in the configuration.
183  *
184  * @param ctx to allocate proc instance in.
185  * @param proc resolved with #map_proc_find.
186  * @param src template.
187  * @param maps Head of the list of maps.
188  * @return
189  * - New #map_proc_inst_t on success.
190  * - NULL on error.
191  */
192 map_proc_inst_t *map_proc_instantiate(TALLOC_CTX *ctx, map_proc_t const *proc,
193  vp_tmpl_t const *src, vp_map_t const *maps)
194 {
196 
197  inst = talloc_zero(ctx, map_proc_inst_t);
198  inst->proc = proc;
199  inst->src = src;
200  inst->maps = maps;
201 
202  if (proc->instantiate) {
203  if (proc->inst_size > 0) {
204  inst->data = talloc_zero_array(inst, uint8_t, proc->inst_size);
205  if (!inst->data) return NULL;
206  }
207 
208  if (proc->instantiate(inst->data, proc->mod_inst, src, maps) < 0) {
209  talloc_free(inst);
210  return NULL;
211  }
212  }
213 
214  return inst;
215 }
216 
217 /** Evaluate a set of maps using the specified map processor
218  *
219  * Evaluate the map processor src template, then call a map processor function to do
220  * something with the expanded src template and map the result to attributes in the request.
221  *
222  * @param request The current request.
223  * @param inst of a map processor.
224  */
226 {
227  char *value;
228  rlm_rcode_t rcode;
229 
230  if (tmpl_aexpand(request, &value, request, inst->src, inst->proc->escape, inst->proc->mod_inst) < 0) {
231  return RLM_MODULE_FAIL;
232  }
233 
234  rcode = inst->proc->evaluate(inst->proc->mod_inst, inst->data, request, value, inst->maps);
235  talloc_free(value);
236 
237  return rcode;
238 }
#define DEBUG3(fmt,...)
Definition: log.h:177
bool rbtree_deletebydata(rbtree_t *tree, void const *data)
Delete a node from the tree, based on given data, which MUST have come from rbtree_finddata().
Definition: rbtree.c:496
rbnode_t * rbtree_insert_node(rbtree_t *tree, void *data)
Insert an element into the tree.
Definition: rbtree.c:258
static char const * name
static int _map_proc_unregister(map_proc_t *proc)
Unregister a map processor.
Definition: map_proc.c:78
#define RBTREE_FLAG_REPLACE
Definition: libradius.h:526
void map_proc_free(void)
Definition: map_proc.c:113
#define inst
void * rbtree_finddata(rbtree_t *tree, void const *data)
Find the user data.
Definition: rbtree.c:537
size_t(* xlat_escape_t)(REQUEST *request, char *out, size_t outlen, char const *in, void *arg)
Definition: xlat.h:36
vp_map_t const * maps
Head of the map list.
Definition: map_proc.c:54
#define rad_assert(expr)
Definition: rad_assert.h:38
char name[MAX_STRING_LEN]
Name of the map function.
Definition: map_proc.c:39
xlat_escape_t escape
Escape function to apply to expansions in the map query string.
Definition: map_proc.c:44
#define DEBUG(fmt,...)
Definition: log.h:175
rbtree_t * rbtree_create(TALLOC_CTX *ctx, rb_comparator_t compare, rb_free_t node_free, int flags)
Create a new RED-BLACK tree.
Definition: rbtree.c:112
int length
Length of name.
Definition: map_proc.c:40
static rbtree_t * map_proc_root
Definition: map_proc.c:33
map_proc_t const * proc
Map processor.
Definition: map_proc.c:52
rlm_rcode_t map_proc(REQUEST *request, map_proc_inst_t const *inst)
Evaluate a set of maps using the specified map processor.
Definition: map_proc.c:225
map_proc_t * map_proc_find(char const *name)
Find a map processor by name.
Definition: map_proc.c:101
ssize_t tmpl_aexpand(TALLOC_CTX *ctx, char **out, REQUEST *request, vp_tmpl_t const *vpt, xlat_escape_t escape, void *escape_ctx)
Expand a template to a string, allocing a new buffer to hold the string.
Definition: tmpl.c:1653
rlm_rcode_t(* map_proc_func_t)(void *mod_inst, void *proc_inst, REQUEST *request, char const *src, vp_map_t const *maps)
Function to evaluate the src string and map the result to server attributes.
Definition: map_proc.h:51
void * mod_inst
Module instance.
Definition: map_proc.c:38
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
map_proc_inst_t * map_proc_instantiate(TALLOC_CTX *ctx, map_proc_t const *proc, vp_tmpl_t const *src, vp_map_t const *maps)
Create a new map proc instance.
Definition: map_proc.c:192
Map processor registration.
Definition: map_proc.c:37
size_t inst_size
Size of map_proc instance data to allocate.
Definition: map_proc.c:46
Module failed, don't reply.
Definition: radiusd.h:90
vp_tmpl_t const * src
Evaluated to provide source value for map processor.
Definition: map_proc.c:53
static int map_proc_cmp(void const *one, void const *two)
Compare two map_proc_t structs, based ONLY on the name.
Definition: map_proc.c:64
void * data
Instance data created by map_proc_instantiate.
Definition: map_proc.c:55
int(* map_proc_instantiate_t)(void *proc_inst, void *mod_inst, vp_tmpl_t const *src, vp_map_t const *maps)
Allocate new instance data for a map processor.
Definition: map_proc.h:64
int map_proc_register(void *mod_inst, char const *name, map_proc_func_t evaluate, xlat_escape_t escape, map_proc_instantiate_t instantiate, size_t inst_size)
Register a map processor.
Definition: map_proc.c:132
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
Map processor instance.
Definition: map_proc.c:51
map_proc_instantiate_t instantiate
Callback to create new instance struct.
Definition: map_proc.c:43
#define MAX_STRING_LEN
Definition: libradius.h:120
#define RCSID(id)
Definition: build.h:135
Value pair map.
Definition: map.h:46
A source or sink of value data.
Definition: tmpl.h:187
map_proc_func_t evaluate
Module's map processor function.
Definition: map_proc.c:42