The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
xlat_alloc.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: d2c9ccc7454fb1d258a48ddcf10d82e26a433328 $
19  *
20  * @file xlat_alloc.c
21  * @brief Functions to allocate different types of xlat nodes
22  */
23 
24 RCSID("$Id: d2c9ccc7454fb1d258a48ddcf10d82e26a433328 $")
25 
26 #include <freeradius-devel/server/base.h>
27 #include <freeradius-devel/unlang/xlat.h>
28 
29 #include <freeradius-devel/util/debug.h>
30 #include <freeradius-devel/util/types.h>
31 
32 #define _XLAT_PRIVATE
33 #include <freeradius-devel/unlang/xlat_priv.h>
34 
36 {
38 
39  MEM(head = talloc_zero(ctx, xlat_exp_head_t));
40 
41  fr_dlist_init(&head->dlist, xlat_exp_t, entry);
42  head->flags.pure = true;
43 #ifndef NDEBUG
44  head->file = file;
45  head->line = line;
46 #endif
47 
48  return head;
49 }
50 
51 /** Set the type of an xlat node
52  *
53  * Also initialises any xlat_exp_head necessary
54  *
55  * @param[in] node to set type for.
56  * @param[in] type to set.
57  */
59 {
60  /*
61  * Do nothing if it's the same type
62  */
63  if (node->type == type) return;
64 
65  /*
66  * Free existing lists if present
67  */
68  if (node->type != 0) switch (node->type) {
69  case XLAT_GROUP:
70  TALLOC_FREE(node->group);
71  break;
72 
73  case XLAT_FUNC:
75  if (type != XLAT_FUNC) {
76  TALLOC_FREE(node->call.args); /* Just switching from unresolved to resolved */
77  } else goto done;
78  break;
79 
80  default:
81  break;
82  }
83 
84  /*
85  * Alloc new lists to match the type
86  */
87  switch (type) {
88  case XLAT_GROUP:
89  node->group = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node);
90  break;
91 
92  case XLAT_FUNC:
94  node->call.args = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node);
95  break;
96 
97  default:
98  break;
99  }
100 
101 done:
102  node->type = type;
103 }
104 
105 static xlat_exp_t *xlat_exp_alloc_pool(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, unsigned int extra_hdrs, size_t extra)
106 {
107  xlat_exp_t *node;
108 
109  MEM(node = talloc_zero_pooled_object(ctx, xlat_exp_t, extra_hdrs, extra));
110  node->flags.pure = true; /* everything starts pure */
111  node->quote = T_BARE_WORD;
112 #ifndef NDEBUG
113  node->file = file;
114  node->line = line;
115 #endif
116 
117  return node;
118 }
119 
120 /** Allocate an xlat node with no name, and no type set
121  *
122  * @param[in] ctx to allocate node in.
123  * @return A new xlat node.
124  */
126 {
127  return xlat_exp_alloc_pool(NDEBUG_LOCATION_VALS ctx, 0, 0);
128 }
129 
130 /** Allocate an xlat node
131  *
132  * @param[in] ctx to allocate node in.
133  * @param[in] type of the node.
134  * @param[in] in original input string.
135  * @param[in] inlen the length of the original input string.
136  * @return A new xlat node.
137  */
138 xlat_exp_t *_xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen)
139 {
140  xlat_exp_t *node;
141  unsigned int extra_hdrs;
142  size_t extra;
143 
144  /*
145  * Figure out how much extra memory we
146  * need to allocate for this node type.
147  */
148  switch (type) {
149  case XLAT_GROUP:
150  extra_hdrs = 1;
151  extra = sizeof(xlat_exp_head_t);
152  break;
153 
154  case XLAT_FUNC:
155  extra_hdrs = 1;
156  extra = sizeof(xlat_exp_head_t);
157  break;
158 
159  default:
160  extra_hdrs = 0;
161  extra = 0;
162  }
163 
165  ctx,
166  (in != NULL) + extra_hdrs,
167  inlen + extra);
169 
170  if (!in) return node;
171 
172  node->fmt = talloc_bstrndup(node, in, inlen);
173  switch (type) {
174  case XLAT_BOX:
175  fr_value_box_strdup_shallow(&node->data, NULL, node->fmt, false);
176  break;
177 
178  default:
179  break;
180  }
181 
182  return node;
183 }
184 
185 /** Set the format string for an xlat node
186  *
187  * @param[in] node to set fmt for.
188  * @param[in] fmt talloced buffer to set as the fmt string.
189  * @param[in] len of fmt string.
190  */
191 void xlat_exp_set_name(xlat_exp_t *node, char const *fmt, size_t len)
192 {
193  if (node->fmt) talloc_const_free(node->fmt);
194  node->fmt = talloc_bstrndup(node, fmt, len);
195 }
196 
197 /** Set the format string for an xlat node, copying from a talloc'd buffer
198  *
199  * @param[in] node to set fmt for.
200  * @param[in] fmt talloced buffer to set as the fmt string.
201  */
202 void xlat_exp_set_name_buffer(xlat_exp_t *node, char const *fmt)
203 {
204  if (node->fmt) talloc_const_free(node->fmt);
205  node->fmt = talloc_typed_strdup_buffer(node, fmt);
206 }
207 
208 /** Set the format string for an xlat node from a pre-existing buffer
209  *
210  * @param[in] node to set fmt for.
211  * @param[in] fmt talloced buffer to set as the fmt string.
212  */
214 {
215  if (node->fmt) talloc_const_free(node->fmt);
216  node->fmt = talloc_get_type_abort_const(fmt, char);
217 }
218 
219 /** Copy all nodes in the input list to the output list
220  *
221  * @param[in] ctx to allocate new nodes in.
222  * @param[out] out Where to write new nodes.
223  * @param[in] in Input nodes.
224  * @return
225  * - 0 on success.
226  * - -1 on failure.
227  */
229 {
230  xlat_exp_head_t *head = NULL;
231 
232  xlat_flags_merge(&out->flags, &in->flags);
233 
234  /*
235  * Copy everything in the list of nodes
236  */
237  xlat_exp_foreach(in, p) {
238  xlat_exp_t *node;
239 
240  (void)talloc_get_type_abort(p, xlat_exp_t);
241 
242  /*
243  * Ensure the format string is valid... At this point
244  * they should all be talloc'd strings.
245  */
246  MEM(node = xlat_exp_alloc(ctx, p->type,
247  talloc_get_type_abort_const(p->fmt, char), talloc_array_length(p->fmt) - 1));
248 
249  node->quote = p->quote;
250  node->flags = p->flags;
251 
252  switch (p->type) {
253  case XLAT_INVALID:
254  fr_strerror_printf("Cannot copy xlat node of type \"invalid\"");
255  error:
256  talloc_free(head);
257  return -1;
258 
259  case XLAT_BOX:
260  if (unlikely(fr_value_box_copy(node, &node->data, &p->data) < 0)) goto error;
261  break;
262 
263  case XLAT_ONE_LETTER: /* Done with format */
266  break;
267 
268  case XLAT_VIRTUAL:
269  node->call.func = p->call.func;
270  node->call.dict = p->call.dict;
271  node->call.ephemeral = p->call.ephemeral;
272  break;
273 
274  case XLAT_FUNC:
275  /*
276  * Only copy the function pointer, and whether this
277  * is ephemeral.
278  *
279  * All instance data is specific to the xlat node and
280  * cannot be duplicated.
281  *
282  * The node xlat nodes will need to be registered in
283  * the xlat instantiation table later.
284  */
285  node->call.func = p->call.func;
286  node->call.dict = p->call.dict;
287  node->call.ephemeral = p->call.ephemeral;
289  node, node->call.args, p->call.args) < 0)) goto error;
290  break;
291 
292  case XLAT_TMPL:
293  node->vpt = tmpl_copy(node, p->vpt);
294  break;
295 
296 #ifdef HAVE_REGEX
297  case XLAT_REGEX:
298  node->regex_index = p->regex_index;
299  break;
300 #endif
301 
302  case XLAT_GROUP:
304  node, node->group, p->group) < 0)) goto error;
305  break;
306  }
307 
308  xlat_exp_insert_tail(out, node);
309  }
310 
311  return 0;
312 }
313 
315 {
316  int ret;
317 
318  if (!in) return 0;
319 
323 
324  return ret;
325 }
326 
327 #ifdef WITH_VERIFY_PTR
328 void xlat_exp_verify(xlat_exp_t const *node)
329 {
331 
332  switch (node->type) {
333  case XLAT_GROUP:
334  xlat_exp_head_verify(node->group);
335  (void)talloc_get_type_abort_const(node->fmt, char);
336  return;
337 
338  case XLAT_FUNC:
339  xlat_exp_head_verify(node->call.args);
340  (void)talloc_get_type_abort_const(node->fmt, char);
341  return;
342 
343  default:
344  break;
345  }
346 }
347 
348 /** Performs recursive validation of node lists
349  */
350 void xlat_exp_head_verify(xlat_exp_head_t const *head)
351 {
353 
354  xlat_exp_foreach(head, node) xlat_exp_verify(node);
355 }
356 #endif
int const char * file
Definition: acutest.h:702
static int const char * fmt
Definition: acutest.h:573
int const char int line
Definition: acutest.h:702
#define RCSID(id)
Definition: build.h:481
#define unlikely(_x)
Definition: build.h:379
#define NDEBUG_LOCATION_VALS
Definition: build.h:262
#define NDEBUG_LOCATION_ARGS
Pass caller information to the function.
Definition: build.h:261
static fr_slen_t in
Definition: dict.h:821
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition: dlist.h:260
talloc_free(reap)
static bool done
Definition: radclient.c:80
tmpl_t * tmpl_copy(TALLOC_CTX *ctx, tmpl_t const *in)
Copy a tmpl.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_aka_sim_id_type_t type
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition: talloc.c:564
char * talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
Call talloc_strndup, setting the type on the new chunk correctly.
Definition: talloc.c:469
#define talloc_get_type_abort_const
Definition: talloc.h:282
#define talloc_zero_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
Definition: talloc.h:177
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition: talloc.h:224
@ T_BARE_WORD
Definition: token.h:120
#define XLAT_HEAD_VERIFY(_head)
Definition: xlat.h:452
static fr_slen_t head
Definition: xlat.h:406
bool pure
has no external side effects, true for BOX, LITERAL, and some functions
Definition: xlat.h:112
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition: value.c:3740
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
Definition: value.c:4036
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:997
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:997
xlat_exp_t * _xlat_exp_alloc_null(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx)
Allocate an xlat node with no name, and no type set.
Definition: xlat_alloc.c:125
void xlat_exp_set_name(xlat_exp_t *node, char const *fmt, size_t len)
Set the format string for an xlat node.
Definition: xlat_alloc.c:191
static xlat_exp_t * xlat_exp_alloc_pool(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, unsigned int extra_hdrs, size_t extra)
Definition: xlat_alloc.c:105
xlat_exp_t * _xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen)
Allocate an xlat node.
Definition: xlat_alloc.c:138
xlat_exp_head_t * _xlat_exp_head_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx)
Definition: xlat_alloc.c:35
void xlat_exp_set_name_buffer(xlat_exp_t *node, char const *fmt)
Set the format string for an xlat node, copying from a talloc'd buffer.
Definition: xlat_alloc.c:202
int _xlat_copy(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in)
Definition: xlat_alloc.c:314
void xlat_exp_set_name_buffer_shallow(xlat_exp_t *node, char const *fmt)
Set the format string for an xlat node from a pre-existing buffer.
Definition: xlat_alloc.c:213
static int _xlat_copy_internal(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in)
Copy all nodes in the input list to the output list.
Definition: xlat_alloc.c:228
void _xlat_exp_set_type(NDEBUG_LOCATION_ARGS xlat_exp_t *node, xlat_type_t type)
Set the type of an xlat node.
Definition: xlat_alloc.c:58
struct xlat_exp_head_s xlat_exp_head_t
Definition: xlat_ctx.h:36
xlat_flags_t flags
Flags that control resolution and evaluation.
Definition: xlat_priv.h:157
int line
Line where the xlat was allocated.
Definition: xlat_priv.h:162
fr_token_t quote
Type of quoting around XLAT_GROUP types.
Definition: xlat_priv.h:155
xlat_type_t
Definition: xlat_priv.h:105
@ XLAT_ONE_LETTER
Special "one-letter" expansion.
Definition: xlat_priv.h:108
@ XLAT_BOX
fr_value_box_t
Definition: xlat_priv.h:107
@ XLAT_TMPL
xlat attribute
Definition: xlat_priv.h:113
@ XLAT_VIRTUAL_UNRESOLVED
virtual attribute needs resolution during pass2.
Definition: xlat_priv.h:112
@ XLAT_FUNC
xlat module
Definition: xlat_priv.h:109
@ XLAT_VIRTUAL
virtual attribute
Definition: xlat_priv.h:111
@ XLAT_GROUP
encapsulated string of xlats
Definition: xlat_priv.h:117
@ XLAT_FUNC_UNRESOLVED
func needs resolution during pass2.
Definition: xlat_priv.h:110
@ XLAT_INVALID
Bad expansion.
Definition: xlat_priv.h:106
static void xlat_flags_merge(xlat_flags_t *parent, xlat_flags_t const *child)
Merge flags from child to parent.
Definition: xlat_priv.h:227
char const *_CONST fmt
The original format string (a talloced buffer).
Definition: xlat_priv.h:154
xlat_type_t _CONST type
type of this expansion.
Definition: xlat_priv.h:158
char const *_CONST file
File where the xlat was allocated.
Definition: xlat_priv.h:161
#define xlat_exp_alloc(_ctx, _type, _in, _inlen)
Definition: xlat_priv.h:280
#define xlat_exp_foreach(_list_head, _iter)
Iterate over the contents of a list, only one level.
Definition: xlat_priv.h:220
static int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
Definition: xlat_priv.h:236
An xlat expansion node.
Definition: xlat_priv.h:151