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