Don't do \n --> CR mashing in xlat.c
[freeradius.git] / src / main / xlat.c
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$
19  *
20  * @file xlat.c
21  * @brief String expansion ("translation"). Implements %Attribute -> value
22  *
23  * @copyright 2000,2006  The FreeRADIUS server project
24  * @copyright 2000  Alan DeKok <aland@ox.org>
25  */
26
27 RCSID("$Id$")
28
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/parser.h>
31 #include <freeradius-devel/rad_assert.h>
32 #include <freeradius-devel/base64.h>
33
34 #include <ctype.h>
35
36 typedef struct xlat_t {
37         char                    name[MAX_STRING_LEN];   //!< Name of the xlat expansion.
38         int                     length;                 //!< Length of name.
39         void                    *instance;              //!< Module instance passed to xlat and escape functions.
40         RAD_XLAT_FUNC           func;                   //!< xlat function.
41         RADIUS_ESCAPE_STRING    escape;                 //!< Escape function to apply to dynamic input to func.
42         bool                    internal;               //!< If true, cannot be redefined.
43 } xlat_t;
44
45 typedef enum {
46         XLAT_LITERAL,           //!< Literal string
47         XLAT_PERCENT,           //!< Literal string with %v
48         XLAT_MODULE,            //!< xlat module
49         XLAT_VIRTUAL,           //!< virtual attribute
50         XLAT_ATTRIBUTE,         //!< xlat attribute
51 #ifdef HAVE_REGEX
52         XLAT_REGEX,             //!< regex reference
53 #endif
54         XLAT_ALTERNATE          //!< xlat conditional syntax :-
55 } xlat_state_t;
56
57 struct xlat_exp {
58         char const *fmt;        //!< The format string.
59         size_t len;             //!< Length of the format string.
60
61         xlat_state_t type;      //!< type of this expansion.
62         xlat_exp_t *next;       //!< Next in the list.
63
64         xlat_exp_t *child;      //!< Nested expansion.
65         xlat_exp_t *alternate;  //!< Alternative expansion if this one expanded to a zero length string.
66
67         value_pair_tmpl_t attr; //!< An attribute template.
68         xlat_t const *xlat;     //!< The xlat expansion to expand format with.
69 };
70
71 typedef struct xlat_out {
72         char const *out;        //!< Output data.
73         size_t len;             //!< Length of the output string.
74 } xlat_out_t;
75
76 static rbtree_t *xlat_root = NULL;
77
78 #ifdef WITH_UNLANG
79 static char const * const xlat_foreach_names[] = {"Foreach-Variable-0",
80                                                   "Foreach-Variable-1",
81                                                   "Foreach-Variable-2",
82                                                   "Foreach-Variable-3",
83                                                   "Foreach-Variable-4",
84                                                   "Foreach-Variable-5",
85                                                   "Foreach-Variable-6",
86                                                   "Foreach-Variable-7",
87                                                   "Foreach-Variable-8",
88                                                   "Foreach-Variable-9",
89                                                   NULL};
90 #endif
91
92 #if REQUEST_MAX_REGEX > 8
93 #  error Please fix the following line
94 #endif
95 static int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; /* up to 8 for regex */
96
97 char const *radiusd_short_version = RADIUSD_VERSION_STRING;
98
99 /** Print length of its RHS.
100  *
101  */
102 static ssize_t xlat_strlen(UNUSED void *instance, UNUSED REQUEST *request,
103                            char const *fmt, char *out, size_t outlen)
104 {
105         snprintf(out, outlen, "%u", (unsigned int) strlen(fmt));
106         return strlen(out);
107 }
108
109 /** Print the size of the attribute in bytes.
110  *
111  */
112 static ssize_t xlat_length(UNUSED void *instance, UNUSED REQUEST *request,
113                            char const *fmt, char *out, size_t outlen)
114 {
115         VALUE_PAIR *vp;
116         while (isspace((int) *fmt)) fmt++;
117
118         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
119                 *out = '\0';
120                 return 0;
121         }
122
123         snprintf(out, outlen, "%zu", vp->length);
124         return strlen(out);
125 }
126
127 /** Print data as integer, not as VALUE.
128  *
129  */
130 static ssize_t xlat_integer(UNUSED void *instance, REQUEST *request,
131                             char const *fmt, char *out, size_t outlen)
132 {
133         VALUE_PAIR      *vp;
134
135         uint64_t        int64 = 0;      /* Needs to be initialised to zero */
136         uint32_t        int32 = 0;      /* Needs to be initialised to zero */
137
138         while (isspace((int) *fmt)) fmt++;
139
140         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
141                 *out = '\0';
142                 return 0;
143         }
144
145         switch (vp->da->type) {
146         case PW_TYPE_OCTETS:
147         case PW_TYPE_STRING:
148                 if (vp->length > 8) {
149                         break;
150                 }
151
152                 if (vp->length > 4) {
153                         memcpy(&int64, vp->vp_octets, vp->length);
154                         return snprintf(out, outlen, "%" PRIu64, htonll(int64));
155                 }
156
157                 memcpy(&int32, vp->vp_octets, vp->length);
158                 return snprintf(out, outlen, "%i", htonl(int32));
159
160         case PW_TYPE_INTEGER64:
161                 return snprintf(out, outlen, "%" PRIu64, vp->vp_integer64);
162
163         /*
164          *      IP addresses are treated specially, as parsing functions assume the value
165          *      is bigendian and will convert it for us.
166          */
167         case PW_TYPE_IPV4_ADDR:
168                 return snprintf(out, outlen, "%u", htonl(vp->vp_ipaddr));
169
170         case PW_TYPE_IPV4_PREFIX:
171                 return snprintf(out, outlen, "%u", htonl((*(uint32_t *)(vp->vp_ipv4prefix + 2))));
172
173         case PW_TYPE_INTEGER:
174         case PW_TYPE_DATE:
175                 return snprintf(out, outlen, "%u", vp->vp_integer);
176         case PW_TYPE_BYTE:
177                 return snprintf(out, outlen, "%u", (unsigned int) vp->vp_byte);
178         case PW_TYPE_SHORT:
179                 return snprintf(out, outlen, "%u", (unsigned int) vp->vp_short);
180
181         /*
182          *      Ethernet is weird... It's network related, so we assume to it should be
183          *      bigendian.
184          */
185         case PW_TYPE_ETHERNET:
186                 memcpy(&int64, &vp->vp_ether, vp->length);
187                 return snprintf(out, outlen, "%" PRIu64, htonll(int64));
188
189         case PW_TYPE_SIGNED:
190                 return snprintf(out, outlen, "%i", vp->vp_signed);
191
192         case PW_TYPE_IPV6_ADDR:
193                 return fr_prints_uint128(out, outlen, ntohlll(*(uint128_t const *) &vp->vp_ipv6addr));
194
195         case PW_TYPE_IPV6_PREFIX:
196                 return fr_prints_uint128(out, outlen, ntohlll(*(uint128_t const *) &(vp->vp_ipv6prefix[2])));
197
198         default:
199                 break;
200         }
201
202         REDEBUG("Type '%s' of length %zu cannot be converted to integer",
203                 fr_int2str(dict_attr_types, vp->da->type, "???"), vp->length);
204         *out = '\0';
205
206         return -1;
207 }
208
209 /** Print data as hex, not as VALUE.
210  *
211  */
212 static ssize_t xlat_hex(UNUSED void *instance, REQUEST *request,
213                         char const *fmt, char *out, size_t outlen)
214 {
215         size_t i;
216         VALUE_PAIR *vp;
217         uint8_t const *p;
218         ssize_t ret;
219         size_t  len;
220
221         while (isspace((int) *fmt)) fmt++;
222
223         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
224                 *out = '\0';
225                 return -1;
226         }
227
228         ret = rad_vp2data(&p, vp);
229         if (ret < 0) {
230                 return ret;
231         }
232         len = (size_t) ret;
233
234         /*
235          *      Don't truncate the data.
236          */
237         if ((ret < 0 ) || (outlen < (len * 2))) {
238                 *out = 0;
239                 return 0;
240         }
241
242         for (i = 0; i < len; i++) {
243                 snprintf(out + 2*i, 3, "%02x", p[i]);
244         }
245
246         return len * 2;
247 }
248
249 /** Return the tag of an attribute reference
250  *
251  */
252 static ssize_t xlat_tag(UNUSED void *instance, REQUEST *request,
253                         char const *fmt, char *out, size_t outlen)
254 {
255         VALUE_PAIR *vp;
256
257         while (isspace((int) *fmt)) fmt++;
258
259         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
260                 *out = '\0';
261                 return 0;
262         }
263
264         if (!vp->da->flags.has_tag || !TAG_VALID(vp->tag)) {
265                 *out = '\0';
266                 return 0;
267         }
268
269         return snprintf(out, outlen, "%u", vp->tag);
270 }
271
272 /** Print out attribute info
273  *
274  * Prints out all instances of a current attribute, or all attributes in a list.
275  *
276  * At higher debugging levels, also prints out alternative decodings of the same
277  * value. This is helpful to determine types for unknown attributes of long
278  * passed vendors, or just crazy/broken NAS.
279  *
280  * It's also useful for exposing issues in the packet decoding functions, as in
281  * some cases they get fed random garbage data.
282  *
283  * This expands to a zero length string.
284  */
285 static ssize_t xlat_debug_attr(UNUSED void *instance, REQUEST *request, char const *fmt,
286                                char *out, UNUSED size_t outlen)
287 {
288         VALUE_PAIR *vp, **vps;
289         REQUEST *current;
290         vp_cursor_t cursor;
291         char buffer[1024];
292
293         value_pair_tmpl_t vpt;
294
295         if (!RDEBUG_ENABLED2) {
296                 *out = '\0';
297                 return -1;
298         }
299
300         while (isspace((int) *fmt)) fmt++;
301
302         if (tmpl_from_attr_str(&vpt, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST) <= 0) {
303                 RDEBUG("%s", fr_strerror());
304                 return -1;
305         }
306
307         current = request;
308         if (radius_request(&current, vpt.tmpl_request) < 0) return -2;
309
310         vps = radius_list(current, vpt.tmpl_list);
311         if (!vps) {
312                 return -2;
313         }
314
315         RIDEBUG("Attributes matching \"%s\"", fmt);
316         vp = fr_cursor_init(&cursor, vps);
317
318         if (vpt.tmpl_da) {
319                 vp = fr_cursor_next_by_da(&cursor, vpt.tmpl_da, TAG_ANY);
320         }
321         while (vp) {
322                 DICT_ATTR *dac = NULL;
323                 DICT_VENDOR *dv;
324
325                 vp_prints_value(buffer, sizeof(buffer), vp, '\'');
326
327                 RINDENT();
328                 if (vp->da->flags.has_tag) {
329                         RIDEBUG2("%s:%s:%i %s %s",
330                                 fr_int2str(pair_lists, vpt.tmpl_list, "<INVALID>"),
331                                 vp->da->name,
332                                 vp->tag,
333                                 fr_int2str(fr_tokens, vp->op, "<INVALID>"),
334                                 buffer);
335                 } else {
336                         RIDEBUG2("%s:%s %s %s",
337                                 fr_int2str(pair_lists, vpt.tmpl_list, "<INVALID>"),
338                                 vp->da->name,
339                                 fr_int2str(fr_tokens, vp->op, "<INVALID>"),
340                                 buffer);
341                 }
342                 REXDENT();
343
344                 if (!RDEBUG_ENABLED3) goto next_vp;
345
346                 RINDENT();
347                 RINDENT();
348                 if (vp->da->vendor) {
349                         dv = dict_vendorbyvalue(vp->da->vendor);
350                         RDEBUG3("Vendor : %i (%s)", vp->da->vendor, dv ? dv->name : "unknown");
351                 }
352                 RDEBUG3("Type   : %s", fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"));
353                 RDEBUG3("Length : %zu", vp->length);
354                 REXDENT();
355                 REXDENT();
356
357                 dac = talloc_memdup(request, vp->da, sizeof(DICT_ATTR));
358                 if (!dac) return -1;
359                 talloc_set_type(dac, DICT_ATTR);
360
361         next_vp:
362                 talloc_free(dac);
363
364                 if (vpt.tmpl_da) {
365                         vp = fr_cursor_next_by_da(&cursor, vpt.tmpl_da, TAG_ANY);
366                 } else {
367                         vp = fr_cursor_next(&cursor);
368                 }
369         }
370
371         *out = '\0';
372         return 0;
373 }
374
375 /** Prints the current module processing the request
376  *
377  */
378 static ssize_t xlat_module(UNUSED void *instance, REQUEST *request,
379                            UNUSED char const *fmt, char *out, size_t outlen)
380 {
381         strlcpy(out, request->module, outlen);
382
383         return strlen(out);
384 }
385
386 #ifdef WITH_UNLANG
387 /** Implements the Foreach-Variable-X
388  *
389  * @see modcall()
390  */
391 static ssize_t xlat_foreach(void *instance, REQUEST *request,
392                             UNUSED char const *fmt, char *out, size_t outlen)
393 {
394         VALUE_PAIR      **pvp;
395         size_t          len;
396
397         /*
398          *      See modcall, "FOREACH" for how this works.
399          */
400         pvp = (VALUE_PAIR **) request_data_reference(request, radius_get_vp, *(int*) instance);
401         if (!pvp || !*pvp) {
402                 *out = '\0';
403                 return 0;
404         }
405
406         len = vp_prints_value(out, outlen, *pvp, 0);
407         if (is_truncated(len, outlen)) {
408                 RDEBUG("Insufficient buffer space to write foreach value");
409                 return -1;
410         }
411
412         return len;
413 }
414 #endif
415
416 /** Print data as string, if possible.
417  *
418  * If attribute "Foo" is defined as "octets" it will normally
419  * be printed as 0x0a0a0a. The xlat "%{string:Foo}" will instead
420  * expand to "\n\n\n"
421  */
422 static ssize_t xlat_string(UNUSED void *instance, REQUEST *request,
423                            char const *fmt, char *out, size_t outlen)
424 {
425         size_t len;
426         ssize_t ret;
427         VALUE_PAIR *vp;
428         uint8_t const *p;
429
430         while (isspace((int) *fmt)) fmt++;
431
432         if (outlen < 3) {
433         nothing:
434                 *out = '\0';
435                 return 0;
436         }
437
438         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
439
440         ret = rad_vp2data(&p, vp);
441         if (ret < 0) {
442                 return ret;
443         }
444
445         switch (vp->da->type) {
446         case PW_TYPE_OCTETS:
447                 len = fr_print_string((char const *) p, vp->length, out, outlen, '\0');
448                 break;
449
450         case PW_TYPE_STRING:
451                 len = strlcpy(out, vp->vp_strvalue, outlen);
452                 break;
453
454         default:
455                 len = fr_print_string((char const *) p, ret, out, outlen, '\0');
456                 break;
457         }
458
459         return len;
460 }
461
462 /** xlat expand string attribute value
463  *
464  */
465 static ssize_t xlat_xlat(UNUSED void *instance, REQUEST *request,
466                         char const *fmt, char *out, size_t outlen)
467 {
468         VALUE_PAIR *vp;
469
470         while (isspace((int) *fmt)) fmt++;
471
472         if (outlen < 3) {
473         nothing:
474                 *out = '\0';
475                 return 0;
476         }
477
478         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
479
480         return radius_xlat(out, outlen, request, vp->vp_strvalue, NULL, NULL);
481 }
482
483 /** Dynamically change the debugging level for the current request
484  *
485  * Example %{debug:3}
486  */
487 static ssize_t xlat_debug(UNUSED void *instance, REQUEST *request,
488                           char const *fmt, char *out, size_t outlen)
489 {
490         int level = 0;
491
492         /*
493          *  Expand to previous (or current) level
494          */
495         snprintf(out, outlen, "%d", request->log.lvl & RAD_REQUEST_OPTION_DEBUG4);
496
497         /*
498          *  Assume we just want to get the current value and NOT set it to 0
499          */
500         if (!*fmt)
501                 goto done;
502
503         level = atoi(fmt);
504         if (level == 0) {
505                 request->log.lvl = RAD_REQUEST_OPTION_NONE;
506                 request->log.func = NULL;
507         } else {
508                 if (level > 4) level = 4;
509
510                 request->log.lvl = level;
511                 request->log.func = vradlog_request;
512         }
513
514         done:
515         return strlen(out);
516 }
517
518 /*
519  *      Compare two xlat_t structs, based ONLY on the module name.
520  */
521 static int xlat_cmp(void const *one, void const *two)
522 {
523         xlat_t const *a = one;
524         xlat_t const *b = two;
525
526         if (a->length != b->length) {
527                 return a->length - b->length;
528         }
529
530         return memcmp(a->name, b->name, a->length);
531 }
532
533
534 /*
535  *      find the appropriate registered xlat function.
536  */
537 static xlat_t *xlat_find(char const *name)
538 {
539         xlat_t my_xlat;
540
541         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
542         my_xlat.length = strlen(my_xlat.name);
543
544         return rbtree_finddata(xlat_root, &my_xlat);
545 }
546
547
548 /** Register an xlat function.
549  *
550  * @param[in] name xlat name.
551  * @param[in] func xlat function to be called.
552  * @param[in] escape function to sanitize any sub expansions passed to the xlat function.
553  * @param[in] instance of module that's registering the xlat function.
554  * @return 0 on success, -1 on failure
555  */
556 int xlat_register(char const *name, RAD_XLAT_FUNC func, RADIUS_ESCAPE_STRING escape, void *instance)
557 {
558         xlat_t   *c;
559         xlat_t   my_xlat;
560         rbnode_t *node;
561
562         if (!name || !*name) {
563                 DEBUG("xlat_register: Invalid xlat name");
564                 return -1;
565         }
566
567         /*
568          *      First time around, build up the tree...
569          *
570          *      FIXME: This code should be hoisted out of this function,
571          *      and into a global "initialization".  But it isn't critical...
572          */
573         if (!xlat_root) {
574 #ifdef WITH_UNLANG
575                 int i;
576 #endif
577
578                 xlat_root = rbtree_create(NULL, xlat_cmp, free, 0);
579                 if (!xlat_root) {
580                         DEBUG("xlat_register: Failed to create tree");
581                         return -1;
582                 }
583
584 #ifdef WITH_UNLANG
585                 for (i = 0; xlat_foreach_names[i] != NULL; i++) {
586                         xlat_register(xlat_foreach_names[i],
587                                       xlat_foreach, NULL, &xlat_inst[i]);
588                         c = xlat_find(xlat_foreach_names[i]);
589                         rad_assert(c != NULL);
590                         c->internal = true;
591                 }
592 #endif
593
594 #define XLAT_REGISTER(_x) xlat_register(STRINGIFY(_x), xlat_ ## _x, NULL, NULL); \
595                 c = xlat_find(STRINGIFY(_x)); \
596                 rad_assert(c != NULL); \
597                 c->internal = true
598
599                 XLAT_REGISTER(integer);
600                 XLAT_REGISTER(strlen);
601                 XLAT_REGISTER(length);
602                 XLAT_REGISTER(hex);
603                 XLAT_REGISTER(tag);
604                 XLAT_REGISTER(string);
605                 XLAT_REGISTER(xlat);
606                 XLAT_REGISTER(module);
607                 XLAT_REGISTER(debug_attr);
608
609                 xlat_register("debug", xlat_debug, NULL, &xlat_inst[0]);
610                 c = xlat_find("debug");
611                 rad_assert(c != NULL);
612                 c->internal = true;
613         }
614
615         /*
616          *      If it already exists, replace the instance.
617          */
618         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
619         my_xlat.length = strlen(my_xlat.name);
620         c = rbtree_finddata(xlat_root, &my_xlat);
621         if (c) {
622                 if (c->internal) {
623                         DEBUG("xlat_register: Cannot re-define internal xlat");
624                         return -1;
625                 }
626
627                 c->func = func;
628                 c->escape = escape;
629                 c->instance = instance;
630                 return 0;
631         }
632
633         /*
634          *      Doesn't exist.  Create it.
635          */
636         c = rad_malloc(sizeof(*c));
637         memset(c, 0, sizeof(*c));
638
639         c->func = func;
640         c->escape = escape;
641         strlcpy(c->name, name, sizeof(c->name));
642         c->length = strlen(c->name);
643         c->instance = instance;
644
645         node = rbtree_insert_node(xlat_root, c);
646         if (!node) {
647                 talloc_free(c);
648                 return -1;
649         }
650
651         return 0;
652 }
653
654 /** Unregister an xlat function
655  *
656  * We can only have one function to call per name, so the passing of "func"
657  * here is extraneous.
658  *
659  * @param[in] name xlat to unregister.
660  * @param[in] func unused.
661  * @param[in] instance data.
662  */
663 void xlat_unregister(char const *name, UNUSED RAD_XLAT_FUNC func, void *instance)
664 {
665         xlat_t  *c;
666         xlat_t          my_xlat;
667
668         if (!name) return;
669
670         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
671         my_xlat.length = strlen(my_xlat.name);
672
673         c = rbtree_finddata(xlat_root, &my_xlat);
674         if (!c) return;
675
676         if (c->instance != instance) return;
677
678         rbtree_deletebydata(xlat_root, c);
679 }
680
681
682 /** Crappy temporary function to add attribute ref support to xlats
683  *
684  * This needs to die, and hopefully will die, when xlat functions accept
685  * xlat node structures.
686  *
687  * Provides either a pointer to a buffer which contains the value of the reference VALUE_PAIR
688  * in an architecture independent format. Or a pointer to the start of the fmt string.
689  *
690  * The pointer is only guaranteed to be valid between calls to xlat_fmt_to_ref,
691  * and so long as the source VALUE_PAIR is not freed.
692  *
693  * @param out where to write a pointer to the buffer to the data the xlat function needs to work on.
694  * @param request current request.
695  * @param fmt string.
696  * @returns the length of the data or -1 on error.
697  */
698 ssize_t xlat_fmt_to_ref(uint8_t const **out, REQUEST *request, char const *fmt)
699 {
700         VALUE_PAIR *vp;
701
702         while (isspace((int) *fmt)) fmt++;
703
704         if (fmt[0] == '&') {
705                 if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
706                         *out = NULL;
707                         return -1;
708                 }
709
710                 return rad_vp2data(out, vp);
711         }
712
713         *out = (uint8_t const *)fmt;
714         return strlen(fmt);
715 }
716
717 /** De-register all xlat functions, used mainly for debugging.
718  *
719  */
720 void xlat_free(void)
721 {
722         rbtree_free(xlat_root);
723 }
724
725
726 #ifdef DEBUG_XLAT
727 #  define XLAT_DEBUG DEBUG3
728 #else
729 #  define XLAT_DEBUG(...)
730 #endif
731
732 static ssize_t xlat_tokenize_expansion(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
733                                        char const **error);
734 static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
735                                      int brace, char const **error);
736 static size_t xlat_process(char **out, REQUEST *request, xlat_exp_t const * const head,
737                            RADIUS_ESCAPE_STRING escape, void *escape_ctx);
738
739 static ssize_t xlat_tokenize_alternation(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
740                                          char const **error)
741 {
742         ssize_t slen;
743         char *p;
744         xlat_exp_t *node;
745
746         rad_assert(fmt[0] == '%');
747         rad_assert(fmt[1] == '{');
748         rad_assert(fmt[2] == '%');
749         rad_assert(fmt[3] == '{');
750
751         XLAT_DEBUG("ALTERNATE <-- %s", fmt);
752
753         node = talloc_zero(ctx, xlat_exp_t);
754         node->type = XLAT_ALTERNATE;
755
756         p = fmt + 2;
757         slen = xlat_tokenize_expansion(node, p, &node->child, error);
758         if (slen <= 0) {
759                 talloc_free(node);
760                 return slen - (p - fmt);
761         }
762         p += slen;
763
764         if (p[0] != ':') {
765                 talloc_free(node);
766                 *error = "Expected ':' after first expansion";
767                 return -(p - fmt);
768         }
769         p++;
770
771         if (p[0] != '-') {
772                 talloc_free(node);
773                 *error = "Expected '-' after ':'";
774                 return -(p - fmt);
775         }
776         p++;
777
778         /*
779          *      Allow the RHS to be empty as a special case.
780          */
781         if (*p == '}') {
782                 /*
783                  *      Hack up an empty string.
784                  */
785                 node->alternate = talloc_zero(node, xlat_exp_t);
786                 node->alternate->type = XLAT_LITERAL;
787                 node->alternate->fmt = talloc_typed_strdup(node->alternate, "");
788                 *(p++) = '\0';
789
790         } else {
791                 slen = xlat_tokenize_literal(node, p,  &node->alternate, true, error);
792                 if (slen <= 0) {
793                         talloc_free(node);
794                         return slen - (p - fmt);
795                 }
796
797                 if (!node->alternate) {
798                         talloc_free(node);
799                         *error = "Empty expansion is invalid";
800                         return -(p - fmt);
801                 }
802                 p += slen;
803         }
804
805         *head = node;
806         return p - fmt;
807 }
808
809 static ssize_t xlat_tokenize_expansion(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
810                                        char const **error)
811 {
812         ssize_t slen;
813         char *p, *q, *brace;
814         char const *attrname;
815         xlat_exp_t *node;
816
817         rad_assert(fmt[0] == '%');
818         rad_assert(fmt[1] == '{');
819
820         /*
821          *      %{%{...}:-bar}
822          */
823         if ((fmt[2] == '%') && (fmt[3] == '{')) {
824                 return xlat_tokenize_alternation(ctx, fmt, head, error);
825         }
826
827         XLAT_DEBUG("EXPANSION <-- %s", fmt);
828         node = talloc_zero(ctx, xlat_exp_t);
829         attrname = node->fmt = fmt + 2;
830         node->len = 0;
831
832 #ifdef HAVE_REGEX
833         /*
834          *      Handle regex's specially.
835          */
836         if (isdigit((int) fmt[2]) && (fmt[3] == '}')) {
837                 if (fmt[2] == '9') {
838                         talloc_free(node);
839                         *error = "Invalid regex reference";
840                         return -2;
841                 }
842
843                 XLAT_DEBUG("REGEX <-- %s", fmt);
844                 fmt[3] = '\0';
845                 node->attr.tmpl_num = fmt[2] - '0'; /* ASCII */
846
847                 node->type = XLAT_REGEX;
848                 *head = node;
849                 return 4;
850         }
851 #endif /* HAVE_REGEX */
852
853         /*
854          *      %{Attr-Name}
855          *      %{Attr-Name[#]}
856          *      %{Tunnel-Password:1}
857          *      %{Tunnel-Password:1[#]}
858          *      %{request:Attr-Name}
859          *      %{request:Tunnel-Password:1}
860          *      %{request:Tunnel-Password:1[#]}
861          *      %{mod:foo}
862          */
863          brace = NULL;
864         for (p = fmt + 2; *p != '\0'; p++) {
865                 if (*p == ':') break;
866
867                 if (isspace((int) *p)) break;
868
869                 if (*p == '[') break;
870
871                 if (*p == '}') break;
872         }
873
874         if (*p != ':') p = NULL;
875
876         /*
877          *      Might be a module name reference.
878          */
879         if (p) {
880                 *p = '\0';
881
882                 /*
883                  *      %{mod:foo}
884                  */
885                 node->xlat = xlat_find(node->fmt);
886                 if (node->xlat) {
887                         node->type = XLAT_MODULE;
888
889                         XLAT_DEBUG("MOD <-- %s ... %s", node->fmt, p + 1);
890
891                         slen = xlat_tokenize_literal(node, p + 1, &node->child, true, error);
892                         if (slen <= 0) {
893                                 talloc_free(node);
894                                 return slen - (p - fmt);
895                         }
896                         p += slen + 1;
897
898                         *head = node;
899                         rad_assert(node->next == NULL);
900                         return p - fmt;
901                 }
902
903                 /*
904                  *      Modules can have '}' in their RHS, so we
905                  *      didn't check for that until now.
906                  *
907                  *      As of now, node->fmt MUST be a reference to an
908                  *      attribute, however complicated.  So it MUST have a closing brace.
909                  */
910                 brace = strchr(p + 1, '}');
911                 if (!brace) goto no_brace;
912                 *brace = '\0';
913
914                 /*
915                  *      %{User-Name}
916                  *      %{User-Name[1]}
917                  *      %{Tunnel-Password:1}
918                  *      %{request:Tunnel-Password:1}
919                  *
920                  *      <sigh>  The syntax is fairly poor.
921                  */
922                 XLAT_DEBUG("Looking for list in '%s'", attrname);
923
924                 /*
925                  *      Not a module.  Has to be an attribute
926                  *      reference.
927                  *
928                  *      As of v3, we've removed %{request: ..>} as
929                  *      internally registered xlats.
930                  */
931                 *p = ':';
932                 node->attr.tmpl_request = radius_request_name(&attrname, REQUEST_CURRENT);
933                 rad_assert(node->attr.tmpl_request != REQUEST_UNKNOWN);
934
935                 node->attr.tmpl_list = radius_list_name(&attrname, PAIR_LIST_REQUEST);
936                 if (node->attr.tmpl_list == PAIR_LIST_UNKNOWN) {
937                         talloc_free(node);
938                         *error = "Unknown module";
939                         return -2;
940                 }
941
942                 /*
943                  *      Check for a trailing tag.
944                  */
945                 p = strchr(attrname, ':');
946                 if (p) *p = '\0';
947
948         } else {
949                 brace = strchr(attrname, '}');
950                 if (!brace) {
951                 no_brace:
952                         talloc_free(node);
953                         *error = "No matching closing brace";
954                         return -1;      /* second character of format string */
955                 }
956                 *brace = '\0';
957
958                 node->attr.tmpl_request = REQUEST_CURRENT;
959                 node->attr.tmpl_list = PAIR_LIST_REQUEST;
960         }
961
962         *brace = '\0';
963
964         XLAT_DEBUG("Looking for attribute name in %s", attrname);
965
966         /*
967          *      Allow for an array reference.  They come AFTER the
968          *      tag, if the tag exists.  Otherwise, they come after
969          *      the attribute name.
970          */
971         if (p) {
972                 q = strchr(p + 1, '[');
973         } else {
974                 q = strchr(attrname, '[');
975         }
976         if (q) *(q++) = '\0';
977
978         if (!*attrname) {
979                 talloc_free(node);
980                 *error = "Empty expression is invalid";
981                 return -(attrname - fmt);
982         }
983
984         /*
985          *      It's either an attribute name, or a Tunnel-Password:TAG
986          *      with the ':' already set to NULL.
987          */
988         node->attr.tmpl_da = dict_attrbyname(attrname);
989         if (!node->attr.tmpl_da) {
990                 /*
991                  *      Foreach.  Maybe other stuff, too.
992                  */
993                 node->xlat = xlat_find(attrname);
994                 if (node->xlat) {
995                         node->type = XLAT_VIRTUAL;
996                         node->fmt = attrname;
997
998                         XLAT_DEBUG("VIRTUAL <-- %s", node->fmt);
999                         *head = node;
1000                         rad_assert(node->next == NULL);
1001                         brace++;
1002                         return brace - fmt;
1003                 }
1004
1005                 talloc_free(node);
1006                 *error = "Unknown attribute";
1007                 return -(attrname - fmt);
1008         }
1009
1010         /*
1011          *      Parse the tag.
1012          */
1013         if (p) {
1014                 unsigned long tag;
1015                 char *end;
1016
1017                 if (!node->attr.tmpl_da->flags.has_tag) {
1018                         talloc_free(node);
1019                         *error = "Attribute cannot have a tag";
1020                         return - (p - fmt);
1021                 }
1022
1023                 tag = strtoul(p + 1, &end, 10);
1024                 p++;
1025
1026                 if (tag == ULONG_MAX) {
1027                         talloc_free(node);
1028                         *error = "Invalid tag value";
1029                         return - (p - fmt);
1030                 }
1031
1032                 node->attr.tmpl_tag = tag;
1033                 p = end;
1034
1035                 if (*p) {
1036                         talloc_free(node);
1037                         *error = "Unexpected text after tag";
1038                         return - (p - fmt);
1039                 }
1040
1041         } else {
1042                 node->attr.tmpl_tag = TAG_ANY;
1043                 /* leave p alone */
1044         }
1045
1046         /*
1047          *      Check for array reference
1048          */
1049         if (q) {
1050                 unsigned long num;
1051                 char *end;
1052
1053                 p = q;
1054                 if (*p== '#') {
1055                         node->attr.tmpl_num = NUM_COUNT;
1056                         p++;
1057
1058                 } else if (*p == '*') {
1059                         node->attr.tmpl_num = NUM_ALL;
1060                         p++;
1061
1062                 } else if (isdigit((int) *p)) {
1063                         num = strtoul(p, &end, 10);
1064                         if (num > 1000) {
1065                                 talloc_free(node);
1066                                 *error = "Invalid array index";
1067                                 return - (p - fmt);
1068                         }
1069                         p = end;
1070                         node->attr.tmpl_num = num;
1071
1072                 } else {
1073                         talloc_free(node);
1074                         *error = "Invalid array index";
1075                         return - (p - fmt);
1076                 }
1077
1078                 if (*p != ']') {
1079                         talloc_free(node);
1080                         *error = "Expected ']'";
1081                         return - (p - fmt);
1082                 }
1083
1084                 p++;
1085                 if (*p) {
1086                         talloc_free(node);
1087                         *error = "Unexpected text after array reference";
1088                         return - (p - fmt);
1089                 }
1090         } else {
1091                 node->attr.tmpl_num = NUM_ANY;
1092         }
1093
1094         rad_assert(!p || (p == brace));
1095
1096         node->type = XLAT_ATTRIBUTE;
1097         p = brace + 1;
1098
1099         *head = node;
1100         rad_assert(node->next == NULL);
1101         return p - fmt;
1102 }
1103
1104
1105 static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1106                                      int brace, char const **error)
1107 {
1108         char *p;
1109         xlat_exp_t *node;
1110
1111         if (!*fmt) return 0;
1112
1113         XLAT_DEBUG("LITERAL <-- %s", fmt);
1114
1115         node = talloc_zero(ctx, xlat_exp_t);
1116         node->fmt = fmt;
1117         node->len = 0;
1118         node->type = XLAT_LITERAL;
1119
1120         p = fmt;
1121
1122         while (*p) {
1123                 if (*p == '\\') {
1124                         if (!p[1]) {
1125                                 talloc_free(node);
1126                                 *error = "Invalid escape at end of string";
1127                                 return -(p - fmt);
1128                         }
1129                         p += 2;
1130                         continue;
1131                 }
1132
1133                 /*
1134                  *      Process the expansion.
1135                  */
1136                 if ((p[0] == '%') && (p[1] == '{')) {
1137                         ssize_t slen;
1138
1139                         XLAT_DEBUG("LITERAL <-- %s", node->fmt);
1140
1141                         slen = xlat_tokenize_expansion(node, p, &node->next, error);
1142                         if (slen <= 0) {
1143                                 talloc_free(node);
1144                                 return slen - (p - fmt);
1145                         }
1146                         *p = '\0'; /* end the literal */
1147                         p += slen;
1148
1149                         rad_assert(node->next != NULL);
1150
1151                         /*
1152                          *      Short-circuit the recursive call.
1153                          *      This saves another function call and
1154                          *      memory allocation.
1155                          */
1156                         if (!*p) break;
1157
1158                         /*
1159                          *      "foo %{User-Name} bar"
1160                          *      LITERAL         "foo "
1161                          *      EXPANSION       User-Name
1162                          *      LITERAL         " bar"
1163                          */
1164                         slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error);
1165                         rad_assert(slen != 0);
1166                         if (slen < 0) {
1167                                 talloc_free(node);
1168                                 return slen - (p - fmt);
1169                         }
1170
1171                         p += slen;
1172                         break;  /* stop processing the string */
1173                 }
1174
1175                 /*
1176                  *      Check for valid single-character expansions.
1177                  */
1178                 if (p[0] == '%') {
1179                         ssize_t slen;
1180                         xlat_exp_t *next;
1181
1182                         if (!p[1] || !strchr("%dlmtDGHISTYv", p[1])) {
1183                                         talloc_free(node);
1184                                         *error = "Invalid variable expansion";
1185                                         p++;
1186                                         return - (p - fmt);
1187                         }
1188
1189                         next = talloc_zero(node, xlat_exp_t);
1190                         next->len = 1;
1191
1192                         if (p[1] == '%') {
1193                                 next->fmt = talloc_typed_strdup(next, "%");
1194
1195                                 XLAT_DEBUG("LITERAL <-- %s", next->fmt);
1196                                 next->type = XLAT_LITERAL;
1197
1198                         } else {
1199                                 next->fmt = p + 1;
1200
1201                                 XLAT_DEBUG("PERCENT <-- %c", *next->fmt);
1202                                 next->type = XLAT_PERCENT;
1203                         }
1204
1205                         node->next = next;
1206                         *p = '\0';
1207                         p += 2;
1208
1209                         if (!*p) break;
1210
1211                         /*
1212                          *      And recurse.
1213                          */
1214                         slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error);
1215                         rad_assert(slen != 0);
1216                         if (slen < 0) {
1217                                 talloc_free(node);
1218                                 return slen - (p - fmt);
1219                         }
1220
1221                         p += slen;
1222                         break;  /* stop processing the string */
1223                 }
1224
1225                 /*
1226                  *      If required, eat the brace.
1227                  */
1228                 if (brace && (*p == '}')) {
1229                         *p = '\0';
1230                         p++;
1231                         break;
1232                 }
1233
1234                 p++;
1235                 node->len++;
1236         }
1237
1238         /*
1239          *      Squash zero-width literals
1240          */
1241         if (node->len > 0) {
1242                 *head = node;
1243         } else {
1244                 *head = talloc_steal(ctx, node->next);
1245                 talloc_free(node);
1246         }
1247
1248         return p - fmt;
1249 }
1250
1251
1252 static char const xlat_tabs[] = "                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ";
1253
1254 static void xlat_tokenize_debug(xlat_exp_t const *node, int lvl)
1255 {
1256         rad_assert(node != NULL);
1257
1258         if (lvl >= (int) sizeof(xlat_tabs)) lvl = sizeof(xlat_tabs);
1259
1260         while (node) {
1261                 switch (node->type) {
1262                 case XLAT_LITERAL:
1263                         DEBUG("%.*sliteral --> %s", lvl, xlat_tabs, node->fmt);
1264                         break;
1265
1266                 case XLAT_PERCENT:
1267                         DEBUG("%.*spercent --> %c", lvl, xlat_tabs, node->fmt[0]);
1268                         break;
1269
1270                 case XLAT_ATTRIBUTE:
1271                         rad_assert(node->attr.tmpl_da != NULL);
1272                         DEBUG("%.*sattribute --> %s", lvl, xlat_tabs, node->attr.tmpl_da->name);
1273                         rad_assert(node->child == NULL);
1274                         if ((node->attr.tmpl_tag != TAG_ANY) || (node->attr.tmpl_num != NUM_ANY)) {
1275                                 DEBUG("%.*s{", lvl, xlat_tabs);
1276
1277                                 DEBUG("%.*sref  %d", lvl + 1, xlat_tabs, node->attr.tmpl_request);
1278                                 DEBUG("%.*slist %d", lvl + 1, xlat_tabs, node->attr.tmpl_list);
1279
1280                                 if (node->attr.tmpl_tag != TAG_ANY) {
1281                                         DEBUG("%.*stag %d", lvl + 1, xlat_tabs, node->attr.tmpl_tag);
1282                                 }
1283                                 if (node->attr.tmpl_num != NUM_ANY) {
1284                                         if (node->attr.tmpl_num == NUM_COUNT) {
1285                                                 DEBUG("%.*s[#]", lvl + 1, xlat_tabs);
1286                                         } else if (node->attr.tmpl_num == NUM_ALL) {
1287                                                 DEBUG("%.*s[*]", lvl + 1, xlat_tabs);
1288                                         } else {
1289                                                 DEBUG("%.*s[%d]", lvl + 1, xlat_tabs, node->attr.tmpl_num);
1290                                         }
1291                                 }
1292
1293                                 DEBUG("%.*s}", lvl, xlat_tabs);
1294                         }
1295                         break;
1296
1297                 case XLAT_VIRTUAL:
1298                         rad_assert(node->fmt != NULL);
1299                         DEBUG("%.*svirtual --> %s", lvl, xlat_tabs, node->fmt);
1300                         break;
1301
1302                 case XLAT_MODULE:
1303                         rad_assert(node->xlat != NULL);
1304                         DEBUG("%.*sxlat --> %s", lvl, xlat_tabs, node->xlat->name);
1305                         if (node->child) {
1306                                 DEBUG("%.*s{", lvl, xlat_tabs);
1307                                 xlat_tokenize_debug(node->child, lvl + 1);
1308                                 DEBUG("%.*s}", lvl, xlat_tabs);
1309                         }
1310                         break;
1311
1312 #ifdef HAVE_REGEX
1313                 case XLAT_REGEX:
1314                         DEBUG("%.*sregex-var --> %d", lvl, xlat_tabs, node->attr.tmpl_num);
1315                         break;
1316 #endif
1317
1318                 case XLAT_ALTERNATE:
1319                         DEBUG("%.*sif {", lvl, xlat_tabs);
1320                         xlat_tokenize_debug(node->child, lvl + 1);
1321                         DEBUG("%.*s}", lvl, xlat_tabs);
1322                         DEBUG("%.*selse {", lvl, xlat_tabs);
1323                         xlat_tokenize_debug(node->alternate, lvl + 1);
1324                         DEBUG("%.*s}", lvl, xlat_tabs);
1325                         break;
1326                 }
1327                 node = node->next;
1328         }
1329 }
1330
1331 size_t xlat_sprint(char *buffer, size_t bufsize, xlat_exp_t const *node)
1332 {
1333         size_t len;
1334         char *p, *end;
1335
1336         if (!node) {
1337                 *buffer = '\0';
1338                 return 0;
1339         }
1340
1341         p = buffer;
1342         end = buffer + bufsize;
1343
1344         while (node) {
1345                 switch (node->type) {
1346                 case XLAT_LITERAL:
1347                         strlcpy(p, node->fmt, end - p);
1348                         p += strlen(p);
1349                         break;
1350
1351                 case XLAT_PERCENT:
1352                         p[0] = '%';
1353                         p[1] = node->fmt[0];
1354                         p += 2;
1355                         break;
1356
1357                 case XLAT_ATTRIBUTE:
1358                         *(p++) = '%';
1359                         *(p++) = '{';
1360
1361                         if (node->attr.tmpl_request != REQUEST_CURRENT) {
1362                                 strlcpy(p, fr_int2str(request_refs, node->attr.tmpl_request, "??"), end - p);
1363                                 p += strlen(p);
1364                                 *(p++) = '.';
1365                         }
1366
1367                         if ((node->attr.tmpl_request != REQUEST_CURRENT) ||
1368                             (node->attr.tmpl_list != PAIR_LIST_REQUEST)) {
1369                                 strlcpy(p, fr_int2str(pair_lists, node->attr.tmpl_list, "??"), end - p);
1370                                 p += strlen(p);
1371                                 *(p++) = ':';
1372                         }
1373
1374                         strlcpy(p, node->attr.tmpl_da->name, end - p);
1375                         p += strlen(p);
1376
1377                         if (node->attr.tmpl_tag != TAG_ANY) {
1378                                 *(p++) = ':';
1379                                 snprintf(p, end - p, "%u", node->attr.tmpl_tag);
1380                                 p += strlen(p);
1381                         }
1382
1383                         if (node->attr.tmpl_num != NUM_ANY) {
1384                                 *(p++) = '[';
1385                                 switch (node->attr.tmpl_num) {
1386                                 case NUM_COUNT:
1387                                         *(p++) = '#';
1388                                         break;
1389
1390                                 case NUM_ALL:
1391                                         *(p++) = '*';
1392                                         break;
1393
1394                                 default:
1395                                         snprintf(p, end - p, "%i", node->attr.tmpl_num);
1396                                         p += strlen(p);
1397                                 }
1398                                 *(p++) = ']';
1399                         }
1400                         *(p++) = '}';
1401                         break;
1402 #ifdef HAVE_REGEX
1403                 case XLAT_REGEX:
1404                         snprintf(p, end - p, "%%{%i}", node->attr.tmpl_num);
1405                         p += strlen(p);
1406                         break;
1407 #endif
1408                 case XLAT_VIRTUAL:
1409                         *(p++) = '%';
1410                         *(p++) = '{';
1411                         strlcpy(p, node->fmt, end - p);
1412                         p += strlen(p);
1413                         *(p++) = '}';
1414                         break;
1415
1416                 case XLAT_MODULE:
1417                         *(p++) = '%';
1418                         *(p++) = '{';
1419                         strlcpy(p, node->xlat->name, end - p);
1420                         p += strlen(p);
1421                         *(p++) = ':';
1422                         rad_assert(node->child != NULL);
1423                         len = xlat_sprint(p, end - p, node->child);
1424                         p += len;
1425                         *(p++) = '}';
1426                         break;
1427
1428                 case XLAT_ALTERNATE:
1429                         *(p++) = '%';
1430                         *(p++) = '{';
1431
1432                         len = xlat_sprint(p, end - p, node->child);
1433                         p += len;
1434
1435                         *(p++) = ':';
1436                         *(p++) = '-';
1437
1438                         len = xlat_sprint(p, end - p, node->alternate);
1439                         p += len;
1440
1441                         *(p++) = '}';
1442                         break;
1443                 }
1444
1445
1446                 if (p == end) break;
1447
1448                 node = node->next;
1449         }
1450
1451         *p = '\0';
1452
1453         return p - buffer;
1454 }
1455
1456 ssize_t xlat_tokenize(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1457                       char const **error)
1458 {
1459         return xlat_tokenize_literal(ctx, fmt, head, false, error);
1460 }
1461
1462
1463 /** Tokenize an xlat expansion
1464  *
1465  * @param[in] request the input request.  Memory will be attached here.
1466  * @param[in] fmt the format string to expand
1467  * @param[out] head the head of the xlat list / tree structure.
1468  */
1469 static ssize_t xlat_tokenize_request(REQUEST *request, char const *fmt, xlat_exp_t **head)
1470 {
1471         ssize_t slen;
1472         char *tokens;
1473         char const *error;
1474
1475         *head = NULL;
1476
1477         /*
1478          *      Copy the original format string to a buffer so that
1479          *      the later functions can mangle it in-place, which is
1480          *      much faster.
1481          */
1482         tokens = talloc_typed_strdup(request, fmt);
1483         if (!tokens) return -1;
1484
1485         slen = xlat_tokenize_literal(request, tokens, head, false, &error);
1486
1487         /*
1488          *      Zero length expansion, return a zero length node.
1489          */
1490         if (slen == 0) {
1491                 *head = talloc_zero(request, xlat_exp_t);
1492         }
1493
1494         /*
1495          *      Output something like:
1496          *
1497          *      "format string"
1498          *      "       ^ error was here"
1499          */
1500         if (slen < 0) {
1501                 talloc_free(tokens);
1502                 rad_assert(error != NULL);
1503
1504                 REMARKER(fmt, -slen, error);
1505                 return slen;
1506         }
1507
1508         if (*head && (debug_flag > 2)) {
1509                 DEBUG("%s", fmt);
1510                 DEBUG("Parsed xlat tree:");
1511                 xlat_tokenize_debug(*head, 0);
1512         }
1513
1514         /*
1515          *      All of the nodes point to offsets in the "tokens"
1516          *      string.  Let's ensure that free'ing head will free
1517          *      "tokens", too.
1518          */
1519         (void) talloc_steal(*head, tokens);
1520
1521         return slen;
1522 }
1523
1524
1525 static char *xlat_getvp(TALLOC_CTX *ctx, REQUEST *request, pair_lists_t list, DICT_ATTR const *da,
1526                         int8_t tag, int num, bool return_null)
1527 {
1528         VALUE_PAIR *vp, *vps = NULL, *myvp = NULL;
1529         RADIUS_PACKET *packet = NULL;
1530         DICT_VALUE *dv;
1531         char *ret = NULL;
1532
1533         /*
1534          *      Arg.  Too much abstraction is annoying.
1535          */
1536         switch (list) {
1537         default:
1538                 if (return_null) return NULL;
1539                 return vp_aprint_type(ctx, da->type);
1540
1541         case PAIR_LIST_CONTROL:
1542                 vps = request->config_items;
1543                 break;
1544
1545         case PAIR_LIST_REQUEST:
1546                 packet = request->packet;
1547                 if (packet) vps = packet->vps;
1548                 break;
1549
1550         case PAIR_LIST_REPLY:
1551                 packet = request->reply;
1552                 if (packet) vps = packet->vps;
1553                 break;
1554
1555 #ifdef WITH_PROXY
1556         case PAIR_LIST_PROXY_REQUEST:
1557                 packet = request->proxy;
1558                 if (packet) vps = packet->vps;
1559                 break;
1560
1561         case PAIR_LIST_PROXY_REPLY:
1562                 packet = request->proxy_reply;
1563                 if (packet) vps = packet->vps;
1564                 break;
1565 #endif
1566
1567 #ifdef WITH_COA
1568         case PAIR_LIST_COA:
1569         case PAIR_LIST_DM:
1570                 if (request->coa) packet = request->coa->packet;
1571                 if (packet) vps = packet->vps;
1572                 break;
1573
1574         case PAIR_LIST_COA_REPLY:
1575         case PAIR_LIST_DM_REPLY:
1576                 if (request->coa) packet = request->coa->reply;
1577                 if (packet) vps = packet->vps;
1578                 break;
1579
1580 #endif
1581         }
1582
1583         /*
1584          *      Now we have the list, check to see if we have an attribute in
1585          *      the request, if we do, it takes precedence over the virtual
1586          *      attributes.
1587          *
1588          *      This allows users to manipulate virtual attributes as if they
1589          *      were real ones.
1590          */
1591         vp = pairfind(vps, da->attr, da->vendor, tag);
1592         if (vp) goto do_print;
1593
1594         /*
1595          *      We didn't find the VP in a list.  It MIGHT be a
1596          *      virtual one, in which case we do lots more checks
1597          *      below.  However, if we're looking for a normal
1598          *      attribute, it must exist, and therefore not finding it
1599          *      means we return NULL.
1600          */
1601         if (!da->flags.virtual) return NULL;
1602
1603         /*
1604          *      Some non-packet expansions
1605          */
1606         switch (da->attr) {
1607         default:
1608                 break;          /* ignore them */
1609
1610         case PW_CLIENT_SHORTNAME:
1611                 if (num == NUM_COUNT) goto count;
1612                 if (request->client && request->client->shortname) {
1613                         return talloc_typed_strdup(ctx, request->client->shortname);
1614                 }
1615                 return talloc_typed_strdup(ctx, "<UNKNOWN-CLIENT>");
1616
1617         case PW_REQUEST_PROCESSING_STAGE:
1618                 if (num == NUM_COUNT) goto count;
1619                 if (request->component) {
1620                         return talloc_typed_strdup(ctx, request->component);
1621                 }
1622                 return talloc_typed_strdup(ctx, "server_core");
1623
1624         case PW_VIRTUAL_SERVER:
1625                 if (num == NUM_COUNT) goto count;
1626                 if (!request->server) return NULL;
1627                 return talloc_typed_strdup(ctx, request->server);
1628
1629         case PW_MODULE_RETURN_CODE:
1630                 if (num == NUM_COUNT) goto count;
1631                 if (!request->rcode) return NULL;
1632                 return talloc_typed_strdup(ctx, fr_int2str(modreturn_table, request->rcode, ""));
1633         }
1634
1635         /*
1636          *      All of the attributes must now refer to a packet.
1637          *      If there's no packet, we can't print any attribute
1638          *      referencing it.
1639          */
1640         if (!packet) {
1641                 if (return_null) return NULL;
1642                 return vp_aprint_type(ctx, da->type);
1643         }
1644
1645         vp = NULL;
1646         switch (da->attr) {
1647         default:
1648                 break;
1649
1650         case PW_PACKET_TYPE:
1651                 dv = dict_valbyattr(PW_PACKET_TYPE, 0, packet->code);
1652                 if (dv) return talloc_typed_strdup(ctx, dv->name);
1653                 return talloc_typed_asprintf(ctx, "%d", packet->code);
1654
1655         case PW_RESPONSE_PACKET_TYPE:
1656         {
1657                 int code = 0;
1658
1659 #ifdef WITH_PROXY
1660                 if (request->proxy_reply && (!request->reply || !request->reply->code)) {
1661                         code = request->proxy_reply->code;
1662                 } else
1663 #endif
1664                         if (request->reply) {
1665                                 code = request->reply->code;
1666                         }
1667
1668                 return talloc_typed_strdup(ctx, fr_packet_codes[code]);
1669         }
1670
1671         /*
1672          *      Virtual attributes which require a temporary VALUE_PAIR
1673          *      to be allocated. We can't use stack allocated memory
1674          *      because of the talloc checks sprinkled throughout the
1675          *      various VP functions.
1676          */
1677         case PW_PACKET_AUTHENTICATION_VECTOR:
1678                 myvp = pairalloc(ctx, da);
1679                 pairmemcpy(myvp, packet->vector, sizeof(packet->vector));
1680                 vp = myvp;
1681                 break;
1682
1683         case PW_CLIENT_IP_ADDRESS:
1684         case PW_PACKET_SRC_IP_ADDRESS:
1685                 if (packet->src_ipaddr.af == AF_INET) {
1686                         myvp = pairalloc(ctx, da);
1687                         myvp->vp_ipaddr = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
1688                         vp = myvp;
1689                 }
1690                 break;
1691
1692         case PW_PACKET_DST_IP_ADDRESS:
1693                 if (packet->dst_ipaddr.af == AF_INET) {
1694                         myvp = pairalloc(ctx, da);
1695                         myvp->vp_ipaddr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
1696                         vp = myvp;
1697                 }
1698                 break;
1699
1700         case PW_PACKET_SRC_IPV6_ADDRESS:
1701                 if (packet->src_ipaddr.af == AF_INET6) {
1702                         myvp = pairalloc(ctx, da);
1703                         memcpy(&myvp->vp_ipv6addr,
1704                                &packet->src_ipaddr.ipaddr.ip6addr,
1705                                sizeof(packet->src_ipaddr.ipaddr.ip6addr));
1706                         vp = myvp;
1707                 }
1708                 break;
1709
1710         case PW_PACKET_DST_IPV6_ADDRESS:
1711                 if (packet->dst_ipaddr.af == AF_INET6) {
1712                         myvp = pairalloc(ctx, da);
1713                         memcpy(&myvp->vp_ipv6addr,
1714                                &packet->dst_ipaddr.ipaddr.ip6addr,
1715                                sizeof(packet->dst_ipaddr.ipaddr.ip6addr));
1716                         vp = myvp;
1717                 }
1718                 break;
1719
1720         case PW_PACKET_SRC_PORT:
1721                 myvp = pairalloc(ctx, da);
1722                 myvp->vp_integer = packet->src_port;
1723                 vp = myvp;
1724                 break;
1725
1726         case PW_PACKET_DST_PORT:
1727                 myvp = pairalloc(ctx, da);
1728                 myvp->vp_integer = packet->dst_port;
1729                 vp = myvp;
1730                 break;
1731         }
1732
1733         /*
1734          *      Fake various operations for virtual attributes.
1735          */
1736         if (myvp) {
1737                 if (num != NUM_ANY) switch (num) {
1738                 /*
1739                  *      [n] is NULL (we only have [0])
1740                  */
1741                 default:
1742                         goto finish;
1743                 /*
1744                  *      [*] means only one.
1745                  */
1746                 case NUM_ALL:
1747                         break;
1748
1749                 /*
1750                  *      [#] means 1 (as there's only one)
1751                  */
1752                 case NUM_COUNT:
1753                 count:
1754                         ret = talloc_strdup(ctx, "1");
1755                         goto finish;
1756
1757                 /*
1758                  *      [0] is fine (get the first instance)
1759                  */
1760                 case 0:
1761                         break;
1762                 }
1763                 goto print;
1764         }
1765
1766 do_print:
1767         /*
1768          *      We want the N'th VP.
1769          */
1770         if (num != NUM_ANY) {
1771                 int count = 0;
1772                 vp_cursor_t cursor;
1773
1774                 switch (num) {
1775                 /*
1776                  *      Return a count of the VPs.
1777                  */
1778                 case NUM_COUNT:
1779                         fr_cursor_init(&cursor, &vp);
1780                         while (fr_cursor_next_by_da(&cursor, da, tag) != NULL) {
1781                                 count++;
1782                         }
1783                         return talloc_typed_asprintf(ctx, "%d", count);
1784
1785                 /*
1786                  *      Ugly, but working.
1787                  */
1788                 case NUM_ALL:
1789                 {
1790                         char *p, *q;
1791
1792                         (void) fr_cursor_init(&cursor, &vp);
1793                         vp = fr_cursor_next_by_da(&cursor, da, tag);
1794                         if (!vp) return NULL;
1795
1796                         p = vp_aprint_value(ctx, vp, '"');
1797                         if (!p) return NULL;
1798                         while ((vp = fr_cursor_next_by_da(&cursor, da, tag)) != NULL) {
1799                                 q = vp_aprint_value(ctx, vp, '"');
1800                                 if (!q) return NULL;
1801                                 p = talloc_strdup_append(p, ",");
1802                                 p = talloc_strdup_append(p, q);
1803                         }
1804
1805                         return p;
1806                 }
1807
1808                 default:
1809                         fr_cursor_init(&cursor, &vp);
1810                         while ((vp = fr_cursor_next_by_da(&cursor, da, tag)) != NULL) {
1811                                 if (count++ == num) break;
1812                         }
1813                         break;
1814                 }
1815         }
1816
1817         if (!vp) {
1818                 if (return_null) return NULL;
1819                 return vp_aprint_type(ctx, da->type);
1820         }
1821
1822 print:
1823         ret = vp_aprint_value(ctx, vp, '"');
1824
1825 finish:
1826         talloc_free(myvp);
1827         return ret;
1828 }
1829
1830 #ifdef DEBUG_XLAT
1831 static const char xlat_spaces[] = "                                                                                                                                                                                                                                                                ";
1832 #endif
1833
1834 static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, xlat_exp_t const * const node,
1835                          RADIUS_ESCAPE_STRING escape, void *escape_ctx, int lvl)
1836 {
1837         ssize_t rcode;
1838         char *str = NULL, *child;
1839         REQUEST *ref;
1840
1841         XLAT_DEBUG("%.*sxlat aprint %d", lvl, xlat_spaces, node->type);
1842
1843         switch (node->type) {
1844                 /*
1845                  *      Don't escape this.
1846                  */
1847         case XLAT_LITERAL:
1848                 XLAT_DEBUG("xlat_aprint LITERAL");
1849                 return talloc_typed_strdup(ctx, node->fmt);
1850
1851                 /*
1852                  *      Do a one-character expansion.
1853                  */
1854         case XLAT_PERCENT:
1855         {
1856                 char const *p;
1857                 char *nl;
1858                 size_t freespace = 256;
1859                 struct tm ts;
1860                 time_t when;
1861
1862                 XLAT_DEBUG("xlat_aprint PERCENT");
1863
1864                 str = talloc_array(ctx, char, freespace); /* @todo do better allocation */
1865                 p = node->fmt;
1866
1867                 when = request->timestamp;
1868                 if (request->packet) {
1869                         when = request->packet->timestamp.tv_sec;
1870                 }
1871
1872                 switch (*p) {
1873                 case '%':
1874                         str[0] = '%';
1875                         str[1] = '\0';
1876                         break;
1877
1878                 case 'd': /* request day */
1879                         (void) localtime_r(&when, &ts);
1880                         strftime(str, freespace, "%d", &ts);
1881                         break;
1882
1883                 case 'l': /* request timestamp */
1884                         snprintf(str, freespace, "%lu",
1885                                  (unsigned long) when);
1886                         break;
1887
1888                 case 'm': /* request month */
1889                         (void) localtime_r(&when, &ts);
1890                         strftime(str, freespace, "%m", &ts);
1891                         break;
1892
1893                 case 'n': /* Request Number*/
1894                         snprintf(str, freespace, "%u", request->number);
1895                         break;
1896
1897                 case 't': /* request timestamp */
1898                         CTIME_R(&when, str, freespace);
1899                         nl = strchr(str, '\n');
1900                         if (nl) *nl = '\0';
1901                         break;
1902
1903                 case 'D': /* request date */
1904                         (void) localtime_r(&when, &ts);
1905                         strftime(str, freespace, "%Y%m%d", &ts);
1906                         break;
1907
1908                 case 'G': /* request minute */
1909                         (void) localtime_r(&when, &ts);
1910                         strftime(str, freespace, "%M", &ts);
1911                         break;
1912
1913                 case 'H': /* request hour */
1914                         (void) localtime_r(&when, &ts);
1915                         strftime(str, freespace, "%H", &ts);
1916                         break;
1917
1918                 case 'I': /* Request ID */
1919                         if (request->packet) {
1920                                 snprintf(str, freespace, "%i", request->packet->id);
1921                         }
1922                         break;
1923
1924                 case 'S': /* request timestamp in SQL format*/
1925                         (void) localtime_r(&when, &ts);
1926                         strftime(str, freespace, "%Y-%m-%d %H:%M:%S", &ts);
1927                         break;
1928
1929                 case 'T': /* request timestamp */
1930                         (void) localtime_r(&when, &ts);
1931                         strftime(str, freespace, "%Y-%m-%d-%H.%M.%S.000000", &ts);
1932                         break;
1933
1934                 case 'Y': /* request year */
1935                         (void) localtime_r(&when, &ts);
1936                         strftime(str, freespace, "%Y", &ts);
1937                         break;
1938
1939                 case 'v': /* Version of code */
1940                         snprintf(str, freespace, "%s", radiusd_short_version);
1941                         break;
1942
1943                 default:
1944                         rad_assert(0 == 1);
1945                         break;
1946                 }
1947         }
1948                 break;
1949
1950         case XLAT_ATTRIBUTE:
1951                 XLAT_DEBUG("xlat_aprint ATTRIBUTE");
1952                 ref = request;
1953                 if (radius_request(&ref, node->attr.tmpl_request) < 0) {
1954                         return NULL;
1955                 }
1956
1957                 /*
1958                  *      Some attributes are virtual <sigh>
1959                  */
1960                 str = xlat_getvp(ctx, ref, node->attr.tmpl_list, node->attr.tmpl_da, node->attr.tmpl_tag, node->attr.tmpl_num, true);
1961                 if (str) {
1962                         XLAT_DEBUG("EXPAND attr %s", node->attr.tmpl_da->name);
1963                         XLAT_DEBUG("       ---> %s", str);
1964                 }
1965                 break;
1966
1967         case XLAT_VIRTUAL:
1968                 XLAT_DEBUG("xlat_aprint VIRTUAL");
1969                 str = talloc_array(ctx, char, 2048); /* FIXME: have the module call talloc_typed_asprintf */
1970                 rcode = node->xlat->func(node->xlat->instance, request, NULL, str, 2048);
1971                 if (rcode < 0) {
1972                         talloc_free(str);
1973                         return NULL;
1974                 }
1975                 break;
1976
1977         case XLAT_MODULE:
1978                 XLAT_DEBUG("xlat_aprint MODULE");
1979                 if (xlat_process(&child, request, node->child, node->xlat->escape, node->xlat->instance) == 0) {
1980                         return NULL;
1981                 }
1982
1983                 XLAT_DEBUG("%.*sEXPAND mod %s %s", lvl, xlat_spaces, node->fmt, node->child->fmt);
1984                 XLAT_DEBUG("%.*s      ---> %s", lvl, xlat_spaces, child);
1985
1986                 str = talloc_array(ctx, char, 2048); /* FIXME: have the module call talloc_typed_asprintf */
1987                 *str = '\0';    /* Be sure the string is NULL terminated, we now only free on error */
1988
1989                 /*
1990                  *      Convert \n --> CR if requested.
1991                  */
1992
1993                 rcode = node->xlat->func(node->xlat->instance, request, child, str, 2048);
1994                 talloc_free(child);
1995                 if (rcode < 0) {
1996                         talloc_free(str);
1997                         return NULL;
1998                 }
1999                 break;
2000
2001 #ifdef HAVE_REGEX
2002         case XLAT_REGEX:
2003                 XLAT_DEBUG("xlat_aprint REGEX");
2004                 child = request_data_reference(request, request,
2005                                                REQUEST_DATA_REGEX | node->attr.tmpl_num);
2006                 if (!child) return NULL;
2007
2008                 str = talloc_typed_strdup(ctx, child);
2009                 break;
2010 #endif
2011
2012         case XLAT_ALTERNATE:
2013                 XLAT_DEBUG("xlat_aprint ALTERNATE");
2014                 rad_assert(node->child != NULL);
2015                 rad_assert(node->alternate != NULL);
2016
2017                 str = xlat_aprint(ctx, request, node->child, escape, escape_ctx, lvl);
2018                 if (str) break;
2019
2020                 str = xlat_aprint(ctx, request, node->alternate, escape, escape_ctx, lvl);
2021                 break;
2022
2023         }
2024
2025         /*
2026          *      Escape the non-literals we found above.
2027          */
2028         if (str && escape) {
2029                 char *escaped;
2030
2031                 escaped = talloc_array(ctx, char, 2048); /* FIXME: do something intelligent */
2032                 escape(request, escaped, 2038, str, escape_ctx);
2033                 talloc_free(str);
2034                 str = escaped;
2035         }
2036
2037         return str;
2038 }
2039
2040
2041 static size_t xlat_process(char **out, REQUEST *request, xlat_exp_t const * const head,
2042                            RADIUS_ESCAPE_STRING escape, void *escape_ctx)
2043 {
2044         int i, list;
2045         size_t total;
2046         char **array, *answer;
2047         xlat_exp_t const *node;
2048
2049         *out = NULL;
2050
2051         /*
2052          *      There are no nodes to process, so the result is a zero
2053          *      length string.
2054          */
2055         if (!head) {
2056                 *out = talloc_zero_array(request, char, 1);
2057                 return 0;
2058         }
2059
2060         /*
2061          *      Hack for speed.  If it's one expansion, just allocate
2062          *      that and return, instead of allocating an intermediary
2063          *      array.
2064          */
2065         if (!head->next) {
2066                 /*
2067                  *      Pass the MAIN escape function.  Recursive
2068                  *      calls will call node-specific escape
2069                  *      functions.
2070                  */
2071                 answer = xlat_aprint(request, request, head, escape, escape_ctx, 0);
2072                 if (!answer) {
2073                         *out = talloc_zero_array(request, char, 1);
2074                         return 0;
2075                 }
2076                 *out = answer;
2077                 return strlen(answer);
2078         }
2079
2080         list = 0;               /* FIXME: calculate this once */
2081         for (node = head; node != NULL; node = node->next) {
2082                 list++;
2083         }
2084
2085         array = talloc_array(request, char *, list);
2086         if (!array) return -1;
2087
2088         for (node = head, i = 0; node != NULL; node = node->next, i++) {
2089                 array[i] = xlat_aprint(array, request, node, escape, escape_ctx, 0); /* may be NULL */
2090         }
2091
2092         total = 0;
2093         for (i = 0; i < list; i++) {
2094                 if (array[i]) total += strlen(array[i]); /* FIXME: calculate strlen once */
2095         }
2096
2097         if (!total) {
2098                 talloc_free(array);
2099                 *out = talloc_zero_array(request, char, 1);
2100                 return 0;
2101         }
2102
2103         answer = talloc_array(request, char, total + 1);
2104
2105         total = 0;
2106         for (i = 0; i < list; i++) {
2107                 size_t len;
2108
2109                 if (array[i]) {
2110                         len = strlen(array[i]);
2111                         memcpy(answer + total, array[i], len);
2112                         total += len;
2113                 }
2114         }
2115         answer[total] = '\0';
2116         talloc_free(array);     /* and child entries */
2117
2118         *out = answer;
2119         return total;
2120 }
2121
2122
2123 /** Replace %whatever in a string.
2124  *
2125  * See 'doc/variables.txt' for more information.
2126  *
2127  * @param[out] out Where to write pointer to output buffer.
2128  * @param[in] outlen Size of out.
2129  * @param[in] request current request.
2130  * @param[in] node the xlat structure to expand
2131  * @param[in] escape function to escape final value e.g. SQL quoting.
2132  * @param[in] escape_ctx pointer to pass to escape function.
2133  * @return length of string written @bug should really have -1 for failure
2134  */
2135 static ssize_t xlat_expand_struct(char **out, size_t outlen, REQUEST *request, xlat_exp_t const *node,
2136                                   RADIUS_ESCAPE_STRING escape, void *escape_ctx)
2137 {
2138         char *buff;
2139         ssize_t len;
2140
2141         rad_assert(node != NULL);
2142
2143         len = xlat_process(&buff, request, node, escape, escape_ctx);
2144         if ((len < 0) || !buff) {
2145                 rad_assert(buff == NULL);
2146                 if (*out) *out[0] = '\0';
2147                 return len;
2148         }
2149
2150         if (!*out) {
2151                 *out = buff;
2152         } else {
2153                 strlcpy(*out, buff, outlen);
2154                 talloc_free(buff);
2155         }
2156
2157         return strlen(*out);
2158 }
2159
2160 static ssize_t xlat_expand(char **out, size_t outlen, REQUEST *request, char const *fmt,
2161                            RADIUS_ESCAPE_STRING escape, void *escape_ctx) CC_HINT(nonnull (1, 3, 4));
2162
2163 /** Replace %whatever in a string.
2164  *
2165  * See 'doc/variables.txt' for more information.
2166  *
2167  * @param[out] out Where to write pointer to output buffer.
2168  * @param[in] outlen Size of out.
2169  * @param[in] request current request.
2170  * @param[in] fmt string to expand.
2171  * @param[in] escape function to escape final value e.g. SQL quoting.
2172  * @param[in] escape_ctx pointer to pass to escape function.
2173  * @return length of string written @bug should really have -1 for failure
2174  */
2175 static ssize_t CC_HINT(nonnull (1, 3, 4)) xlat_expand(char **out, size_t outlen, REQUEST *request, char const *fmt,
2176                                                       RADIUS_ESCAPE_STRING escape, void *escape_ctx)
2177 {
2178         ssize_t len;
2179         xlat_exp_t *node;
2180
2181         /*
2182          *      Give better errors than the old code.
2183          */
2184         len = xlat_tokenize_request(request, fmt, &node);
2185         if (len == 0) {
2186                 if (*out) {
2187                         *out[0] = '\0';
2188                 } else {
2189                         *out = talloc_zero_array(request, char, 1);
2190                 }
2191                 return 0;
2192         }
2193
2194         if (len < 0) {
2195                 if (*out) *out[0] = '\0';
2196                 return -1;
2197         }
2198
2199         len = xlat_expand_struct(out, outlen, request, node, escape, escape_ctx);
2200         talloc_free(node);
2201
2202         RDEBUG2("EXPAND %s", fmt);
2203         RDEBUG2("   --> %s", *out);
2204
2205         return len;
2206 }
2207
2208 /*
2209  *      Try to convert an xlat to a tmpl for efficiency
2210  */
2211 value_pair_tmpl_t *radius_xlat2tmpl(TALLOC_CTX *ctx, xlat_exp_t *node)
2212 {
2213         value_pair_tmpl_t *vpt;
2214
2215         if (node->next || (node->type != XLAT_ATTRIBUTE)) return NULL;
2216
2217         /*
2218          * @todo it should be possible to emulate the concat and count operations in the
2219          * map code.
2220          */
2221         if ((node->attr.tmpl_num == NUM_COUNT) || (node->attr.tmpl_num == NUM_ALL)) return NULL;
2222
2223         vpt = tmpl_alloc(ctx, TMPL_TYPE_ATTR, node->fmt, -1);
2224         if (!vpt) return NULL;
2225         vpt->tmpl_request = node->attr.tmpl_request;
2226         vpt->tmpl_list = node->attr.tmpl_list;
2227         vpt->tmpl_da = node->attr.tmpl_da;
2228         vpt->tmpl_num = node->attr.tmpl_num;
2229         vpt->tmpl_tag = node->attr.tmpl_tag;
2230
2231         VERIFY_TMPL(vpt);
2232
2233         return vpt;
2234 }
2235
2236 ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, RADIUS_ESCAPE_STRING escape, void *ctx)
2237 {
2238         return xlat_expand(&out, outlen, request, fmt, escape, ctx);
2239 }
2240
2241 ssize_t radius_axlat(char **out, REQUEST *request, char const *fmt, RADIUS_ESCAPE_STRING escape, void *ctx)
2242 {
2243         return xlat_expand(out, 0, request, fmt, escape, ctx);
2244 }
2245
2246 ssize_t radius_axlat_struct(char **out, REQUEST *request, xlat_exp_t const *xlat, RADIUS_ESCAPE_STRING escape, void *ctx)
2247 {
2248         return xlat_expand_struct(out, 0, request, xlat, escape, ctx);
2249 }