Name destructors correctly, remove unused/useless request_opaque_free destructor
[freeradius.git] / src / main / util.c
1 /*
2  * util.c       Various utility functions.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  */
22
23 RCSID("$Id$")
24
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/rad_assert.h>
27
28 #include <ctype.h>
29
30 #include <sys/stat.h>
31 #include <fcntl.h>
32
33 /*
34  *      The signal() function in Solaris 2.5.1 sets SA_NODEFER in
35  *      sa_flags, which causes grief if signal() is called in the
36  *      handler before the cause of the signal has been cleared.
37  *      (Infinite recursion).
38  *
39  *      The same problem appears on HPUX, so we avoid it, if we can.
40  *
41  *      Using sigaction() to reset the signal handler fixes the problem,
42  *      so where available, we prefer that solution.
43  */
44
45 void (*reset_signal(int signo, void (*func)(int)))(int)
46 {
47 #ifdef HAVE_SIGACTION
48         struct sigaction act, oact;
49
50         memset(&act, 0, sizeof(act));
51         act.sa_handler = func;
52         sigemptyset(&act.sa_mask);
53         act.sa_flags = 0;
54 #ifdef  SA_INTERRUPT            /* SunOS */
55         act.sa_flags |= SA_INTERRUPT;
56 #endif
57         if (sigaction(signo, &act, &oact) < 0)
58                 return SIG_ERR;
59         return oact.sa_handler;
60 #else
61
62         /*
63          *      re-set by calling the 'signal' function, which
64          *      may cause infinite recursion and core dumps due to
65          *      stack growth.
66          *
67          *      However, the system is too dumb to implement sigaction(),
68          *      so we don't have a choice.
69          */
70         signal(signo, func);
71
72         return NULL;
73 #endif
74 }
75
76 /*
77  *      Per-request data, added by modules...
78  */
79 struct request_data_t {
80         request_data_t  *next;
81
82         void            *unique_ptr;
83         int             unique_int;
84         void            *opaque;
85         bool            free_opaque;
86 };
87
88 /*
89  *      Add opaque data (with a "free" function) to a REQUEST.
90  *
91  *      The unique ptr is meant to be a module configuration,
92  *      and the unique integer allows the caller to have multiple
93  *      opaque data associated with a REQUEST.
94  */
95 int request_data_add(REQUEST *request,
96                      void *unique_ptr, int unique_int,
97                      void *opaque, bool free_opaque)
98 {
99         request_data_t *this, **last, *next;
100
101         /*
102          *      Some simple sanity checks.
103          */
104         if (!request || !opaque) return -1;
105
106         this = next = NULL;
107         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
108                 if (((*last)->unique_ptr == unique_ptr) &&
109                     ((*last)->unique_int == unique_int)) {
110                         this = *last;
111
112                         next = this->next;
113
114                         /*
115                          *      If caller requires custom behaviour on free
116                          *      they must set a destructor.
117                          */
118                         if (this->opaque && this->free_opaque) {
119                                 talloc_free(this->opaque);
120                         }
121                         break;                          /* replace the existing entry */
122                 }
123         }
124
125         if (!this) this = talloc_zero(request, request_data_t);
126
127         this->next = next;
128         this->unique_ptr = unique_ptr;
129         this->unique_int = unique_int;
130         this->opaque = opaque;
131         if (free_opaque) {
132                 this->free_opaque = free_opaque;
133         }
134
135         *last = this;
136
137         return 0;
138 }
139
140
141 /*
142  *      Get opaque data from a request.
143  */
144 void *request_data_get(REQUEST *request,
145                        void *unique_ptr, int unique_int)
146 {
147         request_data_t **last;
148
149         if (!request) return NULL;
150
151         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
152                 if (((*last)->unique_ptr == unique_ptr) &&
153                     ((*last)->unique_int == unique_int)) {
154                         request_data_t *this = *last;
155                         void *ptr = this->opaque;
156
157                         /*
158                          *      Remove the entry from the list, and free it.
159                          */
160                         *last = this->next;
161                         talloc_free(this);
162                         return ptr;             /* don't free it, the caller does that */
163                 }
164         }
165
166         return NULL;            /* wasn't found, too bad... */
167 }
168
169
170 /*
171  *      Get opaque data from a request without removing it.
172  */
173 void *request_data_reference(REQUEST *request,
174                        void *unique_ptr, int unique_int)
175 {
176         request_data_t **last;
177
178         for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
179                 if (((*last)->unique_ptr == unique_ptr) &&
180                     ((*last)->unique_int == unique_int)) {
181                         request_data_t *this = *last;
182                         void *ptr = this->opaque;
183
184                         return ptr;
185                 }
186         }
187
188         return NULL;            /* wasn't found, too bad... */
189 }
190
191 /*
192  *      Create possibly many directories.
193  *
194  *      Note that the input directory name is NOT a constant!
195  *      This is so that IF an error is returned, the 'directory' ptr
196  *      points to the name of the file which caused the error.
197  */
198 int rad_mkdir(char *directory, mode_t mode)
199 {
200         int rcode;
201         char *p;
202
203         /*
204          *      Try to make the directory.  If it exists, chmod it.
205          *      If a path doesn't exist, that's OK.  Otherwise
206          *      return with an error.
207          */
208         rcode = mkdir(directory, mode & 0777);
209         if (rcode < 0) {
210                 if (errno == EEXIST) {
211                         return chmod(directory, mode);
212                 }
213
214                 if (errno != ENOENT) {
215                         return rcode;
216                 }
217
218                 /*
219                  *      A component in the directory path doesn't
220                  *      exist.  Look for the LAST directory name.  Try
221                  *      to create that.  If there's an error, we leave
222                  *      the directory path as the one at which the
223                  *      error occured.
224                  */
225                 p = strrchr(directory, FR_DIR_SEP);
226                 if (!p || (p == directory)) return -1;
227
228                 *p = '\0';
229                 rcode = rad_mkdir(directory, mode);
230                 if (rcode < 0) return rcode;
231
232                 /*
233                  *      Reset the directory path, and try again to
234                  *      make the directory.
235                  */
236                 *p = FR_DIR_SEP;
237                 rcode = mkdir(directory, mode & 0777);
238                 if (rcode < 0) return rcode;
239         } /* else we successfully created the directory */
240
241         return chmod(directory, mode);
242 }
243
244
245 /*
246  *      Allocate memory, or exit.
247  *
248  *      This call ALWAYS succeeds!
249  */
250 void *rad_malloc(size_t size)
251 {
252         void *ptr = malloc(size);
253
254         if (ptr == NULL) {
255                 ERROR("no memory");
256                 fr_exit(1);
257         }
258
259         return ptr;
260 }
261
262
263 void rad_const_free(void const *ptr)
264 {
265         void *tmp;
266         if (!ptr) return;
267
268         memcpy(&tmp, &ptr, sizeof(tmp));
269         talloc_free(tmp);
270 }
271
272
273 /*
274  *      Logs an error message and aborts the program
275  *
276  */
277
278 void NEVER_RETURNS rad_assert_fail(char const *file, unsigned int line, char const *expr)
279 {
280         ERROR("ASSERT FAILED %s[%u]: %s", file, line, expr);
281         fr_fault(SIGABRT);
282         fr_exit_now(1);
283 }
284
285 /*
286  *      Free a REQUEST struct.
287  */
288 static int _request_free(REQUEST *request)
289 {
290         rad_assert(!request->in_request_hash);
291 #ifdef WITH_PROXY
292         rad_assert(!request->in_proxy_hash);
293 #endif
294         rad_assert(!request->ev);
295
296 #ifdef WITH_COA
297         if (request->coa) {
298                 request->coa->parent = NULL;
299         }
300
301         if (request->parent && (request->parent->coa == request)) {
302                 request->parent->coa = NULL;
303         }
304 #endif
305
306 #ifndef NDEBUG
307         request->magic = 0x01020304;    /* set the request to be nonsense */
308 #endif
309         request->client = NULL;
310 #ifdef WITH_PROXY
311         request->home_server = NULL;
312 #endif
313
314         return 0;
315 }
316
317 /*
318  *      Create a new REQUEST data structure.
319  */
320 REQUEST *request_alloc(TALLOC_CTX *ctx)
321 {
322         REQUEST *request;
323
324         request = talloc_zero(ctx, REQUEST);
325         talloc_set_destructor(request, _request_free);
326 #ifndef NDEBUG
327         request->magic = REQUEST_MAGIC;
328 #endif
329 #ifdef WITH_PROXY
330         request->proxy = NULL;
331 #endif
332         request->reply = NULL;
333 #ifdef WITH_PROXY
334         request->proxy_reply = NULL;
335 #endif
336         request->config_items = NULL;
337         request->username = NULL;
338         request->password = NULL;
339         request->timestamp = time(NULL);
340         request->log.lvl = debug_flag; /* Default to global debug level */
341
342         request->module = "";
343         request->component = "<core>";
344         request->log.func = vradlog_request;
345
346         return request;
347 }
348
349
350 /*
351  *      Create a new REQUEST, based on an old one.
352  *
353  *      This function allows modules to inject fake requests
354  *      into the server, for tunneled protocols like TTLS & PEAP.
355  */
356 REQUEST *request_alloc_fake(REQUEST *request)
357 {
358         REQUEST *fake;
359
360         fake = request_alloc(request);
361
362         fake->number = request->number;
363 #ifdef HAVE_PTHREAD_H
364         fake->child_pid = request->child_pid;
365 #endif
366         fake->parent = request;
367         fake->root = request->root;
368         fake->client = request->client;
369
370         /*
371          *      For new server support.
372          *
373          *      FIXME: Key instead off of a "virtual server" data structure.
374          *
375          *      FIXME: Permit different servers for inner && outer sessions?
376          */
377         fake->server = request->server;
378
379         fake->packet = rad_alloc(fake, 1);
380         if (!fake->packet) {
381                 talloc_free(fake);
382                 return NULL;
383         }
384
385         fake->reply = rad_alloc(fake, 0);
386         if (!fake->reply) {
387                 talloc_free(fake);
388                 return NULL;
389         }
390
391         fake->master_state = REQUEST_ACTIVE;
392         fake->child_state = REQUEST_RUNNING;
393
394         /*
395          *      Fill in the fake request.
396          */
397         fake->packet->sockfd = -1;
398         fake->packet->src_ipaddr = request->packet->src_ipaddr;
399         fake->packet->src_port = request->packet->src_port;
400         fake->packet->dst_ipaddr = request->packet->dst_ipaddr;
401         fake->packet->dst_port = 0;
402
403         /*
404          *      This isn't STRICTLY required, as the fake request MUST NEVER
405          *      be put into the request list.  However, it's still reasonable
406          *      practice.
407          */
408         fake->packet->id = fake->number & 0xff;
409         fake->packet->code = request->packet->code;
410         fake->timestamp = request->timestamp;
411         fake->packet->timestamp = request->packet->timestamp;
412
413         /*
414          *      Required for new identity support
415          */
416         fake->listener = request->listener;
417
418         /*
419          *      Fill in the fake reply, based on the fake request.
420          */
421         fake->reply->sockfd = fake->packet->sockfd;
422         fake->reply->src_ipaddr = fake->packet->dst_ipaddr;
423         fake->reply->src_port = fake->packet->dst_port;
424         fake->reply->dst_ipaddr = fake->packet->src_ipaddr;
425         fake->reply->dst_port = fake->packet->src_port;
426         fake->reply->id = fake->packet->id;
427         fake->reply->code = 0; /* UNKNOWN code */
428
429         /*
430          *      Copy debug information.
431          */
432         memcpy(&(fake->log), &(request->log), sizeof(fake->log));
433
434         return fake;
435 }
436
437 #ifdef WITH_COA
438 REQUEST *request_alloc_coa(REQUEST *request)
439 {
440         if (!request || request->coa) return NULL;
441
442         /*
443          *      Originate CoA requests only when necessary.
444          */
445         if ((request->packet->code != PW_CODE_ACCESS_REQUEST) &&
446             (request->packet->code != PW_CODE_ACCOUNTING_REQUEST)) return NULL;
447
448         request->coa = request_alloc_fake(request);
449         if (!request->coa) return NULL;
450
451         request->coa->packet->code = 0; /* unknown, as of yet */
452         request->coa->child_state = REQUEST_RUNNING;
453         request->coa->proxy = rad_alloc(request->coa, 0);
454         if (!request->coa->proxy) {
455                 TALLOC_FREE(request->coa);
456                 return NULL;
457         }
458
459         return request->coa;
460 }
461 #endif
462
463 /*
464  *      Copy a quoted string.
465  */
466 int rad_copy_string(char *to, char const *from)
467 {
468         int length = 0;
469         char quote = *from;
470
471         do {
472                 if (*from == '\\') {
473                         *(to++) = *(from++);
474                         length++;
475                 }
476                 *(to++) = *(from++);
477                 length++;
478         } while (*from && (*from != quote));
479
480         if (*from != quote) return -1; /* not properly quoted */
481
482         *(to++) = quote;
483         length++;
484         *to = '\0';
485
486         return length;
487 }
488
489 /*
490  *      Copy a quoted string but without the quotes. The length
491  *      returned is the number of chars written; the number of
492  *      characters consumed is 2 more than this.
493  */
494 int rad_copy_string_bare(char *to, char const *from)
495 {
496         int length = 0;
497         char quote = *from;
498
499         from++;
500         while (*from && (*from != quote)) {
501                 if (*from == '\\') {
502                         *(to++) = *(from++);
503                         length++;
504                 }
505                 *(to++) = *(from++);
506                 length++;
507         }
508
509         if (*from != quote) return -1; /* not properly quoted */
510
511         *to = '\0';
512
513         return length;
514 }
515
516
517 /*
518  *      Copy a %{} string.
519  */
520 int rad_copy_variable(char *to, char const *from)
521 {
522         int length = 0;
523         int sublen;
524
525         *(to++) = *(from++);
526         length++;
527
528         while (*from) {
529                 switch (*from) {
530                 case '"':
531                 case '\'':
532                         sublen = rad_copy_string(to, from);
533                         if (sublen < 0) return sublen;
534                         from += sublen;
535                         to += sublen;
536                         length += sublen;
537                         break;
538
539                 case '}':       /* end of variable expansion */
540                         *(to++) = *(from++);
541                         *to = '\0';
542                         length++;
543                         return length; /* proper end of variable */
544
545                 case '\\':
546                         *(to++) = *(from++);
547                         *(to++) = *(from++);
548                         length += 2;
549                         break;
550
551                 case '%':       /* start of variable expansion */
552                         if (from[1] == '{') {
553                                 *(to++) = *(from++);
554                                 length++;
555
556                                 sublen = rad_copy_variable(to, from);
557                                 if (sublen < 0) return sublen;
558                                 from += sublen;
559                                 to += sublen;
560                                 length += sublen;
561                                 break;
562                         } /* else FIXME: catch %%{ ?*/
563
564                         /* FALL-THROUGH */
565                 default:
566                         *(to++) = *(from++);
567                         length++;
568                         break;
569                 }
570         } /* loop over the input string */
571
572         /*
573          *      We ended the string before a trailing '}'
574          */
575
576         return -1;
577 }
578
579 #ifndef USEC
580 #define USEC 1000000
581 #endif
582
583 uint32_t rad_pps(uint32_t *past, uint32_t *present, time_t *then, struct timeval *now)
584 {
585         uint32_t pps;
586
587         if (*then != now->tv_sec) {
588                 *then = now->tv_sec;
589                 *past = *present;
590                 *present = 0;
591         }
592
593         /*
594          *      Bootstrap PPS by looking at a percentage of
595          *      the previous PPS.  This lets us take a moving
596          *      count, without doing a moving average.  If
597          *      we're a fraction "f" (0..1) into the current
598          *      second, we can get a good guess for PPS by
599          *      doing:
600          *
601          *      PPS = pps_now + pps_old * (1 - f)
602          *
603          *      It's an instantaneous measurement, rather than
604          *      a moving average.  This will hopefully let it
605          *      respond better to sudden spikes.
606          *
607          *      Doing the calculations by thousands allows us
608          *      to not overflow 2^32, AND to not underflow
609          *      when we divide by USEC.
610          */
611         pps = USEC - now->tv_usec; /* useconds left in previous second */
612         pps /= 1000;               /* scale to milliseconds */
613         pps *= *past;              /* multiply by past count to get fraction */
614         pps /= 1000;               /* scale to usec again */
615         pps += *present;           /* add in current count */
616
617         return pps;
618 }
619
620 /** Split string into words and expand each one
621  *
622  * @param request Current request.
623  * @param cmd string to split.
624  * @param max_argc the maximum number of arguments to split into.
625  * @param argv Where to write the pointers into argv_buf.
626  * @param can_fail If false, stop processing if any of the xlat expansions fail.
627  * @param argv_buflen size of argv_buf.
628  * @param argv_buf temporary buffer we used to mangle/expand cmd.
629  *      Pointers to offsets of this buffer will be written to argv.
630  * @return argc or -1 on failure.
631  */
632
633 int rad_expand_xlat(REQUEST *request, char const *cmd,
634                     int max_argc, char *argv[], bool can_fail,
635                     size_t argv_buflen, char *argv_buf)
636 {
637         char const *from;
638         char *to;
639         int argc = -1;
640         int i;
641         int left;
642
643         if (strlen(cmd) > (argv_buflen - 1)) {
644                 ERROR("rad_expand_xlat: Command line is too long");
645                 return -1;
646         }
647
648         /*
649          *      Check for bad escapes.
650          */
651         if (cmd[strlen(cmd) - 1] == '\\') {
652                 ERROR("rad_expand_xlat: Command line has final backslash, without a following character");
653                 return -1;
654         }
655
656         strlcpy(argv_buf, cmd, argv_buflen);
657
658         /*
659          *      Split the string into argv's BEFORE doing radius_xlat...
660          */
661         from = cmd;
662         to = argv_buf;
663         argc = 0;
664         while (*from) {
665                 int length;
666
667                 /*
668                  *      Skip spaces.
669                  */
670                 if ((*from == ' ') || (*from == '\t')) {
671                         from++;
672                         continue;
673                 }
674
675                 argv[argc] = to;
676                 argc++;
677
678                 if (argc >= (max_argc - 1)) break;
679
680                 /*
681                  *      Copy the argv over to our buffer.
682                  */
683                 while (*from && (*from != ' ') && (*from != '\t')) {
684                         if (to >= argv_buf + argv_buflen - 1) {
685                                 ERROR("rad_expand_xlat: Ran out of space in command line");
686                                 return -1;
687                         }
688
689                         switch (*from) {
690                         case '"':
691                         case '\'':
692                                 length = rad_copy_string_bare(to, from);
693                                 if (length < 0) {
694                                         ERROR("rad_expand_xlat: Invalid string passed as argument");
695                                         return -1;
696                                 }
697                                 from += length+2;
698                                 to += length;
699                                 break;
700
701                         case '%':
702                                 if (from[1] == '{') {
703                                         *(to++) = *(from++);
704
705                                         length = rad_copy_variable(to, from);
706                                         if (length < 0) {
707                                                 ERROR("rad_expand_xlat: Invalid variable expansion passed as argument");
708                                                 return -1;
709                                         }
710                                         from += length;
711                                         to += length;
712                                 } else { /* FIXME: catch %%{ ? */
713                                         *(to++) = *(from++);
714                                 }
715                                 break;
716
717                         case '\\':
718                                 if (from[1] == ' ') from++;
719                                 /* FALL-THROUGH */
720
721                         default:
722                                 *(to++) = *(from++);
723                         }
724                 } /* end of string, or found a space */
725
726                 *(to++) = '\0'; /* terminate the string */
727         }
728
729         /*
730          *      We have to have SOMETHING, at least.
731          */
732         if (argc <= 0) {
733                 ERROR("rad_expand_xlat: Empty command line");
734                 return -1;
735         }
736
737         /*
738          *      Expand each string, as appropriate.
739          */
740         left = argv_buf + argv_buflen - to;
741         for (i = 0; i < argc; i++) {
742                 int sublen;
743
744                 /*
745                  *      Don't touch argv's which won't be translated.
746                  */
747                 if (strchr(argv[i], '%') == NULL) continue;
748
749                 if (!request) continue;
750
751                 sublen = radius_xlat(to, left - 1, request, argv[i], NULL, NULL);
752                 if (sublen <= 0) {
753                         if (can_fail) {
754                                 /*
755                                  *      Fail to be backwards compatible.
756                                  *
757                                  *      It's yucky, but it won't break anything,
758                                  *      and it won't cause security problems.
759                                  */
760                                 sublen = 0;
761                         } else {
762                                 ERROR("rad_expand_xlat: xlat failed");
763                                 return -1;
764                         }
765                 }
766
767                 argv[i] = to;
768                 to += sublen;
769                 *(to++) = '\0';
770                 left -= sublen;
771                 left--;
772
773                 if (left <= 0) {
774                         ERROR("rad_expand_xlat: Ran out of space while expanding arguments");
775                         return -1;
776                 }
777         }
778         argv[argc] = NULL;
779
780         return argc;
781 }
782
783 const FR_NAME_NUMBER pair_lists[] = {
784         { "request",            PAIR_LIST_REQUEST },
785         { "reply",              PAIR_LIST_REPLY },
786         { "control",            PAIR_LIST_CONTROL },            /* New name should have priority */
787         { "config",             PAIR_LIST_CONTROL },
788 #ifdef WITH_PROXY
789         { "proxy-request",      PAIR_LIST_PROXY_REQUEST },
790         { "proxy-reply",        PAIR_LIST_PROXY_REPLY },
791 #endif
792 #ifdef WITH_COA
793         { "coa",                PAIR_LIST_COA },
794         { "coa-reply",          PAIR_LIST_COA_REPLY },
795         { "disconnect",         PAIR_LIST_DM },
796         { "disconnect-reply",   PAIR_LIST_DM_REPLY },
797 #endif
798         {  NULL , -1 }
799 };
800
801 const FR_NAME_NUMBER request_refs[] = {
802         { "outer",              REQUEST_OUTER },
803         { "current",            REQUEST_CURRENT },
804         { "parent",             REQUEST_PARENT },
805         {  NULL , -1 }
806 };
807
808
809 /** Resolve attribute name to a list.
810  *
811  * Check the name string for qualifiers that specify a list and return
812  * an pair_lists_t value for that list. This value may be passed to
813  * radius_list, along with the current request, to get a pointer to the
814  * actual list in the request.
815  *
816  * If qualifiers were consumed, write a new pointer into name to the
817  * char after the last qualifier to be consumed.
818  *
819  * radius_list_name should be called before passing a name string that
820  * may contain qualifiers to dict_attrbyname.
821  *
822  * @see dict_attrbyname
823  *
824  * @param[in,out] name of attribute.
825  * @param[in] default_list the list to return if no qualifiers were found.
826  * @return PAIR_LIST_UNKOWN if qualifiers couldn't be resolved to a list.
827  */
828 pair_lists_t radius_list_name(char const **name, pair_lists_t default_list)
829 {
830         char const *p = *name;
831         char const *q;
832         pair_lists_t output;
833
834         /* This should never be a NULL pointer or zero length string */
835         rad_assert(name && *name);
836
837         /*
838          *      Unfortunately, ':' isn't a definitive separator for
839          *      the list name.  We may have numeric tags, too.
840          */
841         q = strchr(p, ':');
842         if (q) {
843                 /*
844                  *      Check for tagged attributes.  They have
845                  *      "name:tag", where tag is a decimal number.
846                  *      Valid tags are invalid attributes, so that's
847                  *      OK.
848                  *
849                  *      Also allow "name:tag[#]" as a tag.
850                  *
851                  *      However, "request:" is allowed, too, and
852                  *      shouldn't be interpreted as a tag.
853                  *
854                  *      We do this check first rather than just
855                  *      looking up the request name, because this
856                  *      check is cheap, and looking up the request
857                  *      name is expensive.
858                  */
859                 if (isdigit((int) q[1])) {
860                         char const *d = q + 1;
861
862                         while (isdigit((int) *d)) {
863                                 d++;
864                         }
865
866                         /*
867                          *      Return the DEFAULT list as supplied by
868                          *      the caller.  This is usually
869                          *      PAIRLIST_REQUEST.
870                          */
871                         if (!*d || (*d == '[')) {
872                                 return default_list;
873                         }
874                 }
875
876                 /*
877                  *      If the first part is a list name, then treat
878                  *      it as a list.  This means that we CANNOT have
879                  *      an attribute which is named "request",
880                  *      "reply", etc.  Allowing a tagged attribute
881                  *      "request:3" would just be insane.
882                  */
883                 output = fr_substr2int(pair_lists, p, PAIR_LIST_UNKNOWN, (q - p));
884                 if (output != PAIR_LIST_UNKNOWN) {
885                         *name = (q + 1);        /* Consume the list and delimiter */
886                         return output;
887                 }
888
889                 /*
890                  *      It's not a known list, say so.
891                  */
892                 return PAIR_LIST_UNKNOWN;
893         }
894
895         /*
896          *      The input string may be just a list name,
897          *      e.g. "request".  Check for that.
898          */
899         q = (p + strlen(p));
900         output = fr_substr2int(pair_lists, p, PAIR_LIST_UNKNOWN, (q - p));
901         if (output != PAIR_LIST_UNKNOWN) {
902                 *name = q;
903                 return output;
904         }
905
906         /*
907          *      It's just an attribute name.  Return the default list
908          *      as supplied by the caller.
909          */
910         return default_list;
911 }
912
913
914 /** Resolve attribute name to a request.
915  *
916  * Check the name string for qualifiers that reference a parent request and
917  * write the pointer to this request to 'request'.
918  *
919  * If qualifiers were consumed, write a new pointer into name to the
920  * char after the last qualifier to be consumed.
921  *
922  * radius_ref_request should be called before radius_list_name.
923  *
924  * @see radius_list_name
925  * @param[in,out] name of attribute.
926  * @param[in] def default request ref to return if no request qualifier is present.
927  * @return one of the REQUEST_* definitions or REQUEST_UNKOWN
928  */
929 request_refs_t radius_request_name(char const **name, request_refs_t def)
930 {
931         char *p;
932         int request;
933
934         p = strchr(*name, '.');
935         if (!p) {
936                 return def;
937         }
938
939         /*
940          *      We may get passed "127.0.0.1".
941          */
942         request = fr_substr2int(request_refs, *name, REQUEST_UNKNOWN,
943                                 p - *name);
944
945         /*
946          *      If we get a valid name, skip it.
947          */
948         if (request != REQUEST_UNKNOWN) {
949                 *name = p + 1;
950                 return request;
951         }
952
953         /*
954          *      Otherwise leave it alone, and return the caller's
955          *      default.
956          */
957         return def;
958 }
959
960 /** Resolve request to a request.
961  *
962  * Resolve name to a current request.
963  *
964  * @see radius_list
965  * @param[in,out] context Base context to use, and to write the result back to.
966  * @param[in] name (request) to resolve to.
967  * @return 0 if request is valid in this context, else -1.
968  */
969 int radius_request(REQUEST **context, request_refs_t name)
970 {
971         REQUEST *request = *context;
972
973         switch (name) {
974                 case REQUEST_CURRENT:
975                         return 0;
976
977                 case REQUEST_PARENT:    /* for future use in request chaining */
978                 case REQUEST_OUTER:
979                         if (!request->parent) {
980                                 return -1;
981                         }
982                         *context = request->parent;
983                         break;
984
985                 case REQUEST_UNKNOWN:
986                 default:
987                         rad_assert(0);
988                         return -1;
989         }
990
991         return 0;
992 }
993
994 /** Adds subcapture values to request data
995  *
996  * Allows use of %{n} expansions.
997  *
998  * @param request Current request.
999  * @param compare Result returned by regexec.
1000  * @param value The original value.
1001  * @param rxmatch Pointers into value.
1002  */
1003 void rad_regcapture(REQUEST *request, int compare, char const *value, regmatch_t rxmatch[])
1004 {
1005         int i;
1006         char *p;
1007         size_t len;
1008
1009         if (compare == REG_NOMATCH) {
1010                 return;
1011         }
1012
1013         /*
1014          *      Add new %{0}, %{1}, etc.
1015          */
1016         for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
1017                 /*
1018                  *      Didn't match: delete old match, if it existed.
1019                  */
1020                 if (rxmatch[i].rm_so == -1) {
1021                         p = request_data_get(request, request, REQUEST_DATA_REGEX | i);
1022                         if (p) {
1023                                 RDEBUG4("%%{%i}: Clearing old value \"%s\"", i, p);
1024                                 talloc_free(p);
1025                         } else {
1026                                 RDEBUG4("%%{%i}: Was empty", i);
1027                         }
1028
1029                         continue;
1030                 }
1031
1032                 len = rxmatch[i].rm_eo - rxmatch[i].rm_so;
1033                 p = talloc_array(request, char, len + 1);
1034                 if (!p) {
1035                         ERROR("Out of memory");
1036                         return;
1037                 }
1038
1039                 memcpy(p, value + rxmatch[i].rm_so, len);
1040                 p[len] = '\0';
1041
1042                 RDEBUG4("%%{%i}: Inserting new value \"%s\"", i, p);
1043                 /*
1044                  *      Copy substring, and add it to
1045                  *      the request.
1046                  *
1047                  *      Note that we don't check
1048                  *      for out of memory, which is
1049                  *      the only error we can get...
1050                  */
1051                 request_data_add(request, request, REQUEST_DATA_REGEX | i, p, true);
1052         }
1053 }
1054
1055 #ifndef NDEBUG
1056 /*
1057  *      Verify a packet.
1058  */
1059 static void verify_packet(char const *file, int line, REQUEST *request, RADIUS_PACKET *packet)
1060 {
1061         TALLOC_CTX *parent;
1062
1063         if (!packet) {
1064                 fprintf(stderr, "CONSISTENCY CHECK FAILED %s[%u]: RADIUS_PACKET pointer was NULL", file, line);
1065                 fr_assert(0);
1066                 fr_exit_now(0);
1067         }
1068
1069         parent = talloc_parent(packet);
1070         if (parent != request) {
1071                 ERROR("CONSISTENCY CHECK FAILED %s[%u]: Expected RADIUS_PACKET to be parented by %p (%s), "
1072                       "but parented by %p (%s)", file, line, request, talloc_get_name(request),
1073                       parent, parent ? talloc_get_name(parent) : "NULL");
1074
1075                 fr_log_talloc_report(packet);
1076                 if (parent) fr_log_talloc_report(parent);
1077
1078                 rad_assert(0);
1079         }
1080
1081         VERIFY_PACKET(packet);
1082
1083         if (!packet->vps) return;
1084
1085 #ifdef WITH_VERIFY_PTR
1086         fr_verify_list(file, line, packet, packet->vps);
1087 #endif
1088 }
1089 /*
1090  *      Catch horrible talloc errors.
1091  */
1092 void verify_request(char const *file, int line, REQUEST *request)
1093 {
1094         if (!request) {
1095                 fprintf(stderr, "CONSISTENCY CHECK FAILED %s[%u]: REQUEST pointer was NULL", file, line);
1096                 fr_assert(0);
1097                 fr_exit_now(0);
1098         }
1099
1100         (void) talloc_get_type_abort(request, REQUEST);
1101
1102 #ifdef WITH_VERIFY_PTR
1103         fr_verify_list(file, line, request, request->config_items);
1104 #endif
1105
1106         if (request->packet) verify_packet(file, line, request, request->packet);
1107         if (request->reply) verify_packet(file, line, request, request->reply);
1108 #ifdef WITH_PROXY
1109         if (request->proxy) verify_packet(file, line, request, request->proxy);
1110         if (request->proxy_reply) verify_packet(file, line, request, request->proxy_reply);
1111 #endif
1112
1113 #ifdef WITH_COA
1114         if (request->coa) {
1115                 void *parent;
1116
1117                 (void) talloc_get_type_abort(request->coa, REQUEST);
1118                 parent = talloc_parent(request->coa);
1119
1120                 rad_assert(parent == request);
1121
1122                 verify_request(file, line, request->coa);
1123         }
1124 #endif
1125 }
1126 #endif