Remove redundant file from freeradius-abfab list.
[freeradius.git] / src / lib / pair.c
1 /*
2  * pair.c       Functions to handle VALUE_PAIRs
3  *
4  * Version:     $Id$
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library 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 GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; 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/libradius.h>
26 #include <freeradius-devel/regex.h>
27
28 #include <ctype.h>
29
30 /** Free a VALUE_PAIR
31  *
32  * @note Do not call directly, use talloc_free instead.
33  *
34  * @param vp to free.
35  * @return 0
36  */
37 static int _fr_pair_free(VALUE_PAIR *vp) {
38 #ifndef NDEBUG
39         vp->vp_integer = 0xf4eef4ee;
40 #endif
41
42 #ifdef TALLOC_DEBUG
43         talloc_report_depth_cb(NULL, 0, -1, fr_talloc_verify_cb, NULL);
44 #endif
45         return 0;
46 }
47
48 /** Dynamically allocate a new attribute
49  *
50  * Allocates a new attribute and a new dictionary attr if no DA is provided.
51  *
52  * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
53  * @param[in] da Specifies the dictionary attribute to build the VP from.
54  * @return a new value pair or NULL if an error occurred.
55  */
56 VALUE_PAIR *fr_pair_afrom_da(TALLOC_CTX *ctx, DICT_ATTR const *da)
57 {
58         VALUE_PAIR *vp;
59
60         /*
61          *      Caller must specify a da else we don't know what the attribute type is.
62          */
63         if (!da) {
64                 fr_strerror_printf("Invalid arguments");
65                 return NULL;
66         }
67
68         vp = talloc_zero(ctx, VALUE_PAIR);
69         if (!vp) {
70                 fr_strerror_printf("Out of memory");
71                 return NULL;
72         }
73
74         vp->da = da;
75         vp->op = T_OP_EQ;
76         vp->tag = TAG_ANY;
77         vp->type = VT_NONE;
78
79         vp->vp_length = da->flags.length;
80
81         talloc_set_destructor(vp, _fr_pair_free);
82
83         return vp;
84 }
85
86 /** Create a new valuepair
87  *
88  * If attr and vendor match a dictionary entry then a VP with that DICT_ATTR
89  * will be returned.
90  *
91  * If attr or vendor are uknown will call dict_attruknown to create a dynamic
92  * DICT_ATTR of PW_TYPE_OCTETS.
93  *
94  * Which type of DICT_ATTR the VALUE_PAIR was created with can be determined by
95  * checking @verbatim vp->da->flags.is_unknown @endverbatim.
96  *
97  * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
98  * @param[in] attr number.
99  * @param[in] vendor number.
100  * @return the new valuepair or NULL on error.
101  */
102 VALUE_PAIR *fr_pair_afrom_num(TALLOC_CTX *ctx, unsigned int attr, unsigned int vendor)
103 {
104         DICT_ATTR const *da;
105
106         da = dict_attrbyvalue(attr, vendor);
107         if (!da) {
108                 da = dict_unknown_afrom_fields(ctx, attr, vendor);
109                 if (!da) {
110                         return NULL;
111                 }
112         }
113
114         return fr_pair_afrom_da(ctx, da);
115 }
116
117 /** Free memory used by a valuepair list.
118  *
119  * @todo TLV: needs to free all dependents of each VP freed.
120  */
121 void fr_pair_list_free(VALUE_PAIR **vps)
122 {
123         VALUE_PAIR      *vp;
124         vp_cursor_t     cursor;
125
126         if (!vps || !*vps) {
127                 return;
128         }
129
130         for (vp = fr_cursor_init(&cursor, vps);
131              vp;
132              vp = fr_cursor_next(&cursor)) {
133                 VERIFY_VP(vp);
134                 talloc_free(vp);
135         }
136
137         *vps = NULL;
138 }
139
140 /** Mark malformed or unrecognised attributed as unknown
141  *
142  * @param vp to change DICT_ATTR of.
143  * @return 0 on success (or if already unknown) else -1 on error.
144  */
145 int fr_pair_to_unknown(VALUE_PAIR *vp)
146 {
147         DICT_ATTR const *da;
148
149         VERIFY_VP(vp);
150         if (vp->da->flags.is_unknown) {
151                 return 0;
152         }
153
154         da = dict_unknown_afrom_fields(vp, vp->da->attr, vp->da->vendor);
155         if (!da) {
156                 return -1;
157         }
158
159         vp->da = da;
160
161         return 0;
162 }
163
164 /** Find the pair with the matching DAs
165  *
166  */
167 VALUE_PAIR *fr_pair_find_by_da(VALUE_PAIR *vp, DICT_ATTR const *da, int8_t tag)
168 {
169         vp_cursor_t     cursor;
170
171         if(!fr_assert(da)) {
172                  return NULL;
173         }
174
175         (void) fr_cursor_init(&cursor, &vp);
176         return fr_cursor_next_by_da(&cursor, da, tag);
177 }
178
179
180 /** Find the pair with the matching attribute
181  *
182  * @todo should take DAs and do a pointer comparison.
183  */
184 VALUE_PAIR *fr_pair_find_by_num(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor, int8_t tag)
185 {
186         vp_cursor_t     cursor;
187
188         /* List head may be NULL if it contains no VPs */
189         if (!vp) return NULL;
190
191         VERIFY_LIST(vp);
192
193         (void) fr_cursor_init(&cursor, &vp);
194         return fr_cursor_next_by_num(&cursor, attr, vendor, tag);
195 }
196
197 /** Delete matching pairs
198  *
199  * Delete matching pairs from the attribute list.
200  *
201  * @param[in,out] first VP in list.
202  * @param[in] attr to match.
203  * @param[in] vendor to match.
204  * @param[in] tag to match. TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
205  *
206  * @todo should take DAs and do a point comparison.
207  */
208 void fr_pair_delete_by_num(VALUE_PAIR **first, unsigned int attr, unsigned int vendor, int8_t tag)
209 {
210         VALUE_PAIR *i, *next;
211         VALUE_PAIR **last = first;
212
213         for(i = *first; i; i = next) {
214                 VERIFY_VP(i);
215                 next = i->next;
216                 if ((i->da->attr == attr) && (i->da->vendor == vendor) &&
217                     (!i->da->flags.has_tag || TAG_EQ(tag, i->tag))) {
218                         *last = next;
219                         talloc_free(i);
220                 } else {
221                         last = &i->next;
222                 }
223         }
224 }
225
226 /** Add a VP to the end of the list.
227  *
228  * Locates the end of 'first', and links an additional VP 'add' at the end.
229  *
230  * @param[in] first VP in linked list. Will add new VP to the end of this list.
231  * @param[in] add VP to add to list.
232  */
233 void fr_pair_add(VALUE_PAIR **first, VALUE_PAIR *add)
234 {
235         VALUE_PAIR *i;
236
237         if (!add) return;
238
239         VERIFY_VP(add);
240
241         if (*first == NULL) {
242                 *first = add;
243                 return;
244         }
245
246         for (i = *first; i->next; i = i->next) {
247 #ifdef WITH_VERIFY_PTR
248                 VERIFY_VP(i);
249                 /*
250                  *      The same VP should never by added multiple times
251                  *      to the same list.
252                  */
253                 fr_assert(i != add);
254 #endif
255         }
256
257         i->next = add;
258 }
259
260 /** Replace all matching VPs
261  *
262  * Walks over 'first', and replaces the first VP that matches 'replace'.
263  *
264  * @note Memory used by the VP being replaced will be freed.
265  * @note Will not work with unknown attributes.
266  *
267  * @param[in,out] first VP in linked list. Will search and replace in this list.
268  * @param[in] replace VP to replace.
269  */
270 void fr_pair_replace(VALUE_PAIR **first, VALUE_PAIR *replace)
271 {
272         VALUE_PAIR *i, *next;
273         VALUE_PAIR **prev = first;
274
275         VERIFY_VP(replace);
276
277         if (*first == NULL) {
278                 *first = replace;
279                 return;
280         }
281
282         /*
283          *      Not an empty list, so find item if it is there, and
284          *      replace it. Note, we always replace the first one, and
285          *      we ignore any others that might exist.
286          */
287         for(i = *first; i; i = next) {
288                 VERIFY_VP(i);
289                 next = i->next;
290
291                 /*
292                  *      Found the first attribute, replace it,
293                  *      and return.
294                  */
295                 if ((i->da == replace->da) && (!i->da->flags.has_tag || TAG_EQ(replace->tag, i->tag))) {
296                         *prev = replace;
297
298                         /*
299                          *      Should really assert that replace->next == NULL
300                          */
301                         replace->next = next;
302                         talloc_free(i);
303                         return;
304                 }
305
306                 /*
307                  *      Point to where the attribute should go.
308                  */
309                 prev = &i->next;
310         }
311
312         /*
313          *      If we got here, we didn't find anything to replace, so
314          *      stopped at the last item, which we just append to.
315          */
316         *prev = replace;
317 }
318
319 int8_t fr_pair_cmp_by_da_tag(void const *a, void const *b)
320 {
321         VALUE_PAIR const *my_a = a;
322         VALUE_PAIR const *my_b = b;
323
324         VERIFY_VP(my_a);
325         VERIFY_VP(my_b);
326
327         uint8_t cmp;
328
329         cmp = fr_pointer_cmp(my_a->da, my_b->da);
330         if (cmp != 0) return cmp;
331
332         if (my_a->tag < my_b->tag) return -1;
333
334         if (my_a->tag > my_b->tag) return 1;
335
336         return 0;
337 }
338
339 static void fr_pair_list_sort_split(VALUE_PAIR *source, VALUE_PAIR **front, VALUE_PAIR **back)
340 {
341         VALUE_PAIR *fast;
342         VALUE_PAIR *slow;
343
344         /*
345          *      Stopping condition - no more elements left to split
346          */
347         if (!source || !source->next) {
348                 *front = source;
349                 *back = NULL;
350
351                 return;
352         }
353
354         /*
355          *      Fast advances twice as fast as slow, so when it gets to the end,
356          *      slow will point to the middle of the linked list.
357          */
358         slow = source;
359         fast = source->next;
360
361         while (fast) {
362                 fast = fast->next;
363                 if (fast) {
364                         slow = slow->next;
365                         fast = fast->next;
366                 }
367         }
368
369         *front = source;
370         *back = slow->next;
371         slow->next = NULL;
372 }
373
374 static VALUE_PAIR *fr_pair_list_sort_merge(VALUE_PAIR *a, VALUE_PAIR *b, fr_cmp_t cmp)
375 {
376         VALUE_PAIR *result = NULL;
377
378         if (!a) return b;
379         if (!b) return a;
380
381         /*
382          *      Compare the DICT_ATTRs and tags
383          */
384         if (cmp(a, b) <= 0) {
385                 result = a;
386                 result->next = fr_pair_list_sort_merge(a->next, b, cmp);
387         } else {
388                 result = b;
389                 result->next = fr_pair_list_sort_merge(a, b->next, cmp);
390         }
391
392         return result;
393 }
394
395 /** Sort a linked list of VALUE_PAIRs using merge sort
396  *
397  * @param[in,out] vps List of VALUE_PAIRs to sort.
398  * @param[in] cmp to sort with
399  */
400 void fr_pair_list_sort(VALUE_PAIR **vps, fr_cmp_t cmp)
401 {
402         VALUE_PAIR *head = *vps;
403         VALUE_PAIR *a;
404         VALUE_PAIR *b;
405
406         /*
407          *      If there's 0-1 elements it must already be sorted.
408          */
409         if (!head || !head->next) {
410                 return;
411         }
412
413         fr_pair_list_sort_split(head, &a, &b);  /* Split into sublists */
414         fr_pair_list_sort(&a, cmp);             /* Traverse left */
415         fr_pair_list_sort(&b, cmp);             /* Traverse right */
416
417         /*
418          *      merge the two sorted lists together
419          */
420         *vps = fr_pair_list_sort_merge(a, b, cmp);
421 }
422
423 /** Write an error to the library errorbuff detailing the mismatch
424  *
425  * Retrieve output with fr_strerror();
426  *
427  * @todo add thread specific talloc contexts.
428  *
429  * @param ctx a hack until we have thread specific talloc contexts.
430  * @param failed pair of attributes which didn't match.
431  */
432 void fr_pair_validate_debug(TALLOC_CTX *ctx, VALUE_PAIR const *failed[2])
433 {
434         VALUE_PAIR const *filter = failed[0];
435         VALUE_PAIR const *list = failed[1];
436
437         char *value, *str;
438
439         (void) fr_strerror();   /* Clear any existing messages */
440
441         if (!fr_assert(!(!filter && !list))) return;
442
443         if (!list) {
444                 if (!filter) return;
445                 fr_strerror_printf("Attribute \"%s\" not found in list", filter->da->name);
446                 return;
447         }
448
449         if (!filter || (filter->da != list->da)) {
450                 fr_strerror_printf("Attribute \"%s\" not found in filter", list->da->name);
451                 return;
452         }
453
454         if (!TAG_EQ(filter->tag, list->tag)) {
455                 fr_strerror_printf("Attribute \"%s\" tag \"%i\" didn't match filter tag \"%i\"",
456                                    list->da->name, list->tag, filter->tag);
457                 return;
458         }
459
460
461         value = vp_aprints_value(ctx, list, '"');
462         str = vp_aprints(ctx, filter, '"');
463
464         fr_strerror_printf("Attribute value \"%s\" didn't match filter: %s", value, str);
465
466         talloc_free(str);
467         talloc_free(value);
468
469         return;
470 }
471
472 /** Uses fr_pair_cmp to verify all VALUE_PAIRs in list match the filter defined by check
473  *
474  * @note will sort both filter and list in place.
475  *
476  * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
477  *        May be NULL.
478  * @param filter attributes to check list against.
479  * @param list attributes, probably a request or reply
480  */
481 bool fr_pair_validate(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
482 {
483         vp_cursor_t filter_cursor;
484         vp_cursor_t list_cursor;
485
486         VALUE_PAIR *check, *match;
487
488         if (!filter && !list) {
489                 return true;
490         }
491
492         /*
493          *      This allows us to verify the sets of validate and reply are equal
494          *      i.e. we have a validate rule which matches every reply attribute.
495          *
496          *      @todo this should be removed one we have sets and lists
497          */
498         fr_pair_list_sort(&filter, fr_pair_cmp_by_da_tag);
499         fr_pair_list_sort(&list, fr_pair_cmp_by_da_tag);
500
501         check = fr_cursor_init(&filter_cursor, &filter);
502         match = fr_cursor_init(&list_cursor, &list);
503         while (match || check) {
504                 /*
505                  *      Lists are of different lengths
506                  */
507                 if (!match || !check) goto mismatch;
508
509                 /*
510                  *      The lists are sorted, so if the first
511                  *      attributes aren't of the same type, then we're
512                  *      done.
513                  */
514                 if (!ATTRIBUTE_EQ(check, match)) goto mismatch;
515
516                 /*
517                  *      They're of the same type, but don't have the
518                  *      same values.  This is a problem.
519                  *
520                  *      Note that the RFCs say that for attributes of
521                  *      the same type, order is important.
522                  */
523                 if (fr_pair_cmp(check, match) != 1) goto mismatch;
524
525                 check = fr_cursor_next(&filter_cursor);
526                 match = fr_cursor_next(&list_cursor);
527         }
528
529         return true;
530
531 mismatch:
532         if (failed) {
533                 failed[0] = check;
534                 failed[1] = match;
535         }
536         return false;
537 }
538
539 /** Uses fr_pair_cmp to verify all VALUE_PAIRs in list match the filter defined by check
540  *
541  * @note will sort both filter and list in place.
542  *
543  * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
544  *        May be NULL.
545  * @param filter attributes to check list against.
546  * @param list attributes, probably a request or reply
547  */
548 bool fr_pair_validate_relaxed(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
549 {
550         vp_cursor_t filter_cursor;
551         vp_cursor_t list_cursor;
552
553         VALUE_PAIR *check, *last_check = NULL, *match = NULL;
554
555         if (!filter && !list) {
556                 return true;
557         }
558
559         /*
560          *      This allows us to verify the sets of validate and reply are equal
561          *      i.e. we have a validate rule which matches every reply attribute.
562          *
563          *      @todo this should be removed one we have sets and lists
564          */
565         fr_pair_list_sort(&filter, fr_pair_cmp_by_da_tag);
566         fr_pair_list_sort(&list, fr_pair_cmp_by_da_tag);
567
568         fr_cursor_init(&list_cursor, &list);
569         for (check = fr_cursor_init(&filter_cursor, &filter);
570              check;
571              check = fr_cursor_next(&filter_cursor)) {
572                 /*
573                  *      Were processing check attributes of a new type.
574                  */
575                 if (!ATTRIBUTE_EQ(last_check, check)) {
576                         /*
577                          *      Record the start of the matching attributes in the pair list
578                          *      For every other operator we require the match to be present
579                          */
580                         match = fr_cursor_next_by_da(&list_cursor, check->da, check->tag);
581                         if (!match) {
582                                 if (check->op == T_OP_CMP_FALSE) continue;
583                                 goto mismatch;
584                         }
585
586                         fr_cursor_init(&list_cursor, &match);
587                         last_check = check;
588                 }
589
590                 /*
591                  *      Now iterate over all attributes of the same type.
592                  */
593                 for (match = fr_cursor_first(&list_cursor);
594                      ATTRIBUTE_EQ(match, check);
595                      match = fr_cursor_next(&list_cursor)) {
596                         /*
597                          *      This attribute passed the filter
598                          */
599                         if (!fr_pair_cmp(check, match)) goto mismatch;
600                 }
601         }
602
603         return true;
604
605 mismatch:
606         if (failed) {
607                 failed[0] = check;
608                 failed[1] = match;
609         }
610         return false;
611 }
612
613 /** Copy a single valuepair
614  *
615  * Allocate a new valuepair and copy the da from the old vp.
616  *
617  * @param[in] ctx for talloc
618  * @param[in] vp to copy.
619  * @return a copy of the input VP or NULL on error.
620  */
621 VALUE_PAIR *fr_pair_copy(TALLOC_CTX *ctx, VALUE_PAIR const *vp)
622 {
623         VALUE_PAIR *n;
624
625         if (!vp) return NULL;
626
627         VERIFY_VP(vp);
628
629         n = fr_pair_afrom_da(ctx, vp->da);
630         if (!n) return NULL;
631
632         memcpy(n, vp, sizeof(*n));
633
634         /*
635          *      If the DA is unknown, steal "n" to "ctx".  This does
636          *      nothing for "n", but will also copy the unknown "da".
637          */
638         if (n->da->flags.is_unknown) {
639                 fr_pair_steal(ctx, n);
640         }
641
642         n->next = NULL;
643
644         /*
645          *      If it's an xlat, copy the raw string and return early,
646          *      so we don't pre-expand or otherwise mangle the VALUE_PAIR.
647          */
648         if (vp->type == VT_XLAT) {
649                 n->value.xlat = talloc_typed_strdup(n, n->value.xlat);
650                 return n;
651         }
652
653         switch (vp->da->type) {
654         case PW_TYPE_OCTETS:
655                 n->vp_octets = NULL;    /* else fr_pair_value_memcpy will free vp's value */
656                 fr_pair_value_memcpy(n, vp->vp_octets, n->vp_length);
657                 break;
658
659         case PW_TYPE_STRING:
660                 n->vp_strvalue = NULL;  /* else pairstrnpy will free vp's value */
661                 fr_pair_value_bstrncpy(n, vp->vp_strvalue, n->vp_length);
662                 break;
663
664         default:
665                 break;
666         }
667
668         return n;
669 }
670
671 /** Copy a pairlist.
672  *
673  * Copy all pairs from 'from' regardless of tag, attribute or vendor.
674  *
675  * @param[in] ctx for new VALUE_PAIRs to be allocated in.
676  * @param[in] from whence to copy VALUE_PAIRs.
677  * @return the head of the new VALUE_PAIR list or NULL on error.
678  */
679 VALUE_PAIR *fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
680 {
681         vp_cursor_t src, dst;
682
683         VALUE_PAIR *out = NULL, *vp;
684
685         fr_cursor_init(&dst, &out);
686         for (vp = fr_cursor_init(&src, &from);
687              vp;
688              vp = fr_cursor_next(&src)) {
689                 VERIFY_VP(vp);
690                 vp = fr_pair_copy(ctx, vp);
691                 if (!vp) {
692                         fr_pair_list_free(&out);
693                         return NULL;
694                 }
695                 fr_cursor_insert(&dst, vp); /* fr_pair_list_copy sets next pointer to NULL */
696         }
697
698         return out;
699 }
700
701 /** Copy matching pairs
702  *
703  * Copy pairs of a matching attribute number, vendor number and tag from the
704  * the input list to a new list, and returns the head of this list.
705  *
706  * @param[in] ctx for talloc
707  * @param[in] from whence to copy VALUE_PAIRs.
708  * @param[in] attr to match, if 0 input list will not be filtered by attr.
709  * @param[in] vendor to match.
710  * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
711  * @return the head of the new VALUE_PAIR list or NULL on error.
712  */
713 VALUE_PAIR *fr_pair_list_copy_by_num(TALLOC_CTX *ctx, VALUE_PAIR *from,
714                                      unsigned int attr, unsigned int vendor, int8_t tag)
715 {
716         vp_cursor_t src, dst;
717
718         VALUE_PAIR *out = NULL, *vp;
719
720         fr_cursor_init(&dst, &out);
721         for (vp = fr_cursor_init(&src, &from);
722              vp;
723              vp = fr_cursor_next(&src)) {
724                 VERIFY_VP(vp);
725
726                 if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
727                         continue;
728                 }
729
730                 if (vp->da->flags.has_tag && !TAG_EQ(tag, vp->tag)) {
731                         continue;
732                 }
733
734                 vp = fr_pair_copy(ctx, vp);
735                 if (!vp) {
736                         fr_pair_list_free(&out);
737                         return NULL;
738                 }
739                 fr_cursor_insert(&dst, vp);
740         }
741
742         return out;
743 }
744
745 /** Steal one VP
746  *
747  * @param[in] ctx to move VALUE_PAIR into
748  * @param[in] vp VALUE_PAIR to move into the new context.
749  */
750 void fr_pair_steal(TALLOC_CTX *ctx, VALUE_PAIR *vp)
751 {
752         (void) talloc_steal(ctx, vp);
753
754         /*
755          *      The DA may be unknown.  If we're stealing the VPs to a
756          *      different context, copy the unknown DA.  We use the VP
757          *      as a context here instead of "ctx", so that when the
758          *      VP is freed, so is the DA.
759          *
760          *      Since we have no introspection into OTHER VPs using
761          *      the same DA, we can't have multiple VPs use the same
762          *      DA.  So we might as well tie it to this VP.
763          */
764         if (vp->da->flags.is_unknown) {
765                 DICT_ATTR *da;
766                 char *p;
767                 size_t size;
768
769                 size = talloc_get_size(vp->da);
770
771                 p = talloc_zero_array(vp, char, size);
772                 da = (DICT_ATTR *) p;
773                 talloc_set_type(p, DICT_ATTR);
774                 memcpy(da, vp->da, size);
775                 vp->da = da;
776         }
777 }
778
779 /** Move pairs from source list to destination list respecting operator
780  *
781  * @note This function does some additional magic that's probably not needed
782  *       in most places. Consider using radius_pairmove in server code.
783  *
784  * @note fr_pair_list_free should be called on the head of the source list to free
785  *       unmoved attributes (if they're no longer needed).
786  *
787  * @note Does not respect tags when matching.
788  *
789  * @param[in] ctx for talloc
790  * @param[in,out] to destination list.
791  * @param[in,out] from source list.
792  *
793  * @see radius_pairmove
794  */
795 void fr_pair_list_move(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
796 {
797         VALUE_PAIR *i, *found;
798         VALUE_PAIR *head_new, **tail_new;
799         VALUE_PAIR **tail_from;
800
801         if (!to || !from || !*from) return;
802
803         /*
804          *      We're editing the "to" list while we're adding new
805          *      attributes to it.  We don't want the new attributes to
806          *      be edited, so we create an intermediate list to hold
807          *      them during the editing process.
808          */
809         head_new = NULL;
810         tail_new = &head_new;
811
812         /*
813          *      We're looping over the "from" list, moving some
814          *      attributes out, but leaving others in place.
815          */
816         tail_from = from;
817         while ((i = *tail_from) != NULL) {
818                 VALUE_PAIR *j;
819
820                 VERIFY_VP(i);
821
822                 /*
823                  *      We never move Fall-Through.
824                  */
825                 if (!i->da->vendor && i->da->attr == PW_FALL_THROUGH) {
826                         tail_from = &(i->next);
827                         continue;
828                 }
829
830                 /*
831                  *      Unlike previous versions, we treat all other
832                  *      attributes as normal.  i.e. there's no special
833                  *      treatment for passwords or Hint.
834                  */
835
836                 switch (i->op) {
837                 /*
838                  *      Anything else are operators which
839                  *      shouldn't occur.  We ignore them, and
840                  *      leave them in place.
841                  */
842                 default:
843                         tail_from = &(i->next);
844                         continue;
845
846                 /*
847                  *      Add it to the "to" list, but only if
848                  *      it doesn't already exist.
849                  */
850                 case T_OP_EQ:
851                         found = fr_pair_find_by_da(*to, i->da, TAG_ANY);
852                         if (!found) goto do_add;
853
854                         tail_from = &(i->next);
855                         continue;
856
857                 /*
858                  *      Add it to the "to" list, and delete any attribute
859                  *      of the same vendor/attr which already exists.
860                  */
861                 case T_OP_SET:
862                         found = fr_pair_find_by_da(*to, i->da, TAG_ANY);
863                         if (!found) goto do_add;
864
865                         /*
866                          *      Do NOT call fr_pair_delete_by_num() here,
867                          *      due to issues with re-writing
868                          *      "request->username".
869                          *
870                          *      Everybody calls fr_pair_move, and
871                          *      expects it to work.  We can't
872                          *      update request->username here,
873                          *      so instead we over-write the
874                          *      vp that it's pointing to.
875                          */
876                         switch (found->da->type) {
877                         default:
878                                 j = found->next;
879                                 memcpy(found, i, sizeof(*found));
880                                 found->next = j;
881                                 break;
882
883                         case PW_TYPE_OCTETS:
884                                 fr_pair_value_memsteal(found, i->vp_octets);
885                                 i->vp_octets = NULL;
886                                 break;
887
888                         case PW_TYPE_STRING:
889                                 fr_pair_value_strsteal(found, i->vp_strvalue);
890                                 i->vp_strvalue = NULL;
891                                 found->tag = i->tag;
892                                 break;
893                         }
894
895                         /*
896                          *      Delete *all* of the attributes
897                          *      of the same number.
898                          */
899                         fr_pair_delete_by_num(&found->next,
900                                    found->da->attr,
901                                    found->da->vendor, TAG_ANY);
902
903                         /*
904                          *      Remove this attribute from the
905                          *      "from" list.
906                          */
907                         *tail_from = i->next;
908                         i->next = NULL;
909                         fr_pair_list_free(&i);
910                         continue;
911
912                 /*
913                  *      Move it from the old list and add it
914                  *      to the new list.
915                  */
916                 case T_OP_ADD:
917         do_add:
918                         *tail_from = i->next;
919                         i->next = NULL;
920                         *tail_new = i;
921                         fr_pair_steal(ctx, i);
922                         tail_new = &(i->next);
923                         continue;
924                 }
925         } /* loop over the "from" list. */
926
927         /*
928          *      Take the "new" list, and append it to the "to" list.
929          */
930         fr_pair_add(to, head_new);
931 }
932
933 /** Move matching pairs between VALUE_PAIR lists
934  *
935  * Move pairs of a matching attribute number, vendor number and tag from the
936  * the input list to the output list.
937  *
938  * @note fr_pair_list_free should be called on the head of the old list to free unmoved
939          attributes (if they're no longer needed).
940  *
941  * @param[in] ctx for talloc
942  * @param[in,out] to destination list.
943  * @param[in,out] from source list.
944  * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
945  *      will match (and therefore copy) only VSAs.
946  *      If attribute 0 and vendor 0  will match (and therefore copy) all
947  *      attributes.
948  * @param[in] vendor to match.
949  * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
950  * @param[in] move if set to "true", VPs are moved.  If set to "false", VPs are copied, and the old one deleted.
951  */
952 static void fr_pair_list_move_by_num_internal(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from,
953                                               unsigned int attr, unsigned int vendor, int8_t tag,
954                                               bool move)
955 {
956         VALUE_PAIR *to_tail, *i, *next, *this;
957         VALUE_PAIR *iprev = NULL;
958
959         /*
960          *      Find the last pair in the "to" list and put it in "to_tail".
961          *
962          *      @todo: replace the "if" with "VALUE_PAIR **tail"
963          */
964         if (*to != NULL) {
965                 to_tail = *to;
966                 for(i = *to; i; i = i->next) {
967                         VERIFY_VP(i);
968                         to_tail = i;
969                 }
970         } else
971                 to_tail = NULL;
972
973         /*
974          *      Attr/vendor of 0 means "move them all".
975          *      It's better than "fr_pair_add(foo,bar);bar=NULL"
976          */
977         if ((vendor == 0) && (attr == 0)) {
978                 if (*to) {
979                         to_tail->next = *from;
980                 } else {
981                         *to = *from;
982                 }
983
984                 for (i = *from; i; i = i->next) {
985                         fr_pair_steal(ctx, i);
986                 }
987
988                 *from = NULL;
989                 return;
990         }
991
992         for(i = *from; i; i = next) {
993                 VERIFY_VP(i);
994                 next = i->next;
995
996                 if (i->da->flags.has_tag && !TAG_EQ(tag, i->tag)) {
997                         iprev = i;
998                         continue;
999                 }
1000
1001                 /*
1002                  *      vendor=0, attr = PW_VENDOR_SPECIFIC means
1003                  *      "match any vendor attribute".
1004                  */
1005                 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
1006                         /*
1007                          *      It's a VSA: move it over.
1008                          */
1009                         if (i->da->vendor != 0) goto move;
1010
1011                         /*
1012                          *      It's Vendor-Specific: move it over.
1013                          */
1014                         if (i->da->attr == attr) goto move;
1015
1016                         /*
1017                          *      It's not a VSA: ignore it.
1018                          */
1019                         iprev = i;
1020                         continue;
1021                 }
1022
1023                 /*
1024                  *      If it isn't an exact match, ignore it.
1025                  */
1026                 if (!((i->da->vendor == vendor) && (i->da->attr == attr))) {
1027                         iprev = i;
1028                         continue;
1029                 }
1030
1031         move:
1032                 /*
1033                  *      Remove the attribute from the "from" list.
1034                  */
1035                 if (iprev)
1036                         iprev->next = next;
1037                 else
1038                         *from = next;
1039
1040                 if (move) {
1041                         this = i;
1042                 } else {
1043                         this = fr_pair_copy(ctx, i);
1044                 }
1045
1046                 /*
1047                  *      Add the attribute to the "to" list.
1048                  */
1049                 if (to_tail)
1050                         to_tail->next = this;
1051                 else
1052                         *to = this;
1053                 to_tail = this;
1054                 this->next = NULL;
1055
1056                 if (move) {
1057                         fr_pair_steal(ctx, i);
1058                 } else {
1059                         talloc_free(i);
1060                 }
1061         }
1062 }
1063
1064
1065 /** Move matching pairs between VALUE_PAIR lists
1066  *
1067  * Move pairs of a matching attribute number, vendor number and tag from the
1068  * the input list to the output list.
1069  *
1070  * @note pairs which are moved have their parent changed to ctx.
1071  *
1072  * @note fr_pair_list_free should be called on the head of the old list to free unmoved
1073          attributes (if they're no longer needed).
1074  *
1075  * @param[in] ctx for talloc
1076  * @param[in,out] to destination list.
1077  * @param[in,out] from source list.
1078  * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
1079  *      will match (and therefore copy) only VSAs.
1080  *      If attribute 0 and vendor 0  will match (and therefore copy) all
1081  *      attributes.
1082  * @param[in] vendor to match.
1083  * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
1084  */
1085 void fr_pair_list_move_by_num(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from,
1086                               unsigned int attr, unsigned int vendor, int8_t tag)
1087 {
1088         fr_pair_list_move_by_num_internal(ctx, to, from, attr, vendor, tag, true);
1089 }
1090
1091
1092 /** Copy / delete matching pairs between VALUE_PAIR lists
1093  *
1094  * Move pairs of a matching attribute number, vendor number and tag from the
1095  * the input list to the output list.  Like fr_pair_list_move_by_num(), but
1096  * instead does copy / delete.
1097  *
1098  * @note The pair is NOT reparented.  It is copied and deleted.
1099  *
1100  * @note fr_pair_list_free should be called on the head of the old list to free unmoved
1101          attributes (if they're no longer needed).
1102  *
1103  * @param[in] ctx for talloc
1104  * @param[in,out] to destination list.
1105  * @param[in,out] from source list.
1106  * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
1107  *      will match (and therefore copy) only VSAs.
1108  *      If attribute 0 and vendor 0  will match (and therefore copy) all
1109  *      attributes.
1110  * @param[in] vendor to match.
1111  * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
1112  */
1113 void fr_pair_list_mcopy_by_num(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from,
1114                               unsigned int attr, unsigned int vendor, int8_t tag)
1115 {
1116         fr_pair_list_move_by_num_internal(ctx, to, from, attr, vendor, tag, false);
1117 }
1118
1119
1120 /** Convert string value to native attribute value
1121  *
1122  * @param vp to assign value to.
1123  * @param value string to convert. Binary safe for variable length values if len is provided.
1124  * @param inlen may be < 0 in which case strlen(len) is used to determine length, else inline
1125  *        should be the length of the string or sub string to parse.
1126  * @return 0 on success -1 on error.
1127  */
1128 int fr_pair_value_from_str(VALUE_PAIR *vp, char const *value, size_t inlen)
1129 {
1130         ssize_t ret;
1131         PW_TYPE type;
1132         VERIFY_VP(vp);
1133
1134         if (!value) return -1;
1135
1136         type = vp->da->type;
1137
1138         /*
1139          *      We presume that the input data is from a double quoted
1140          *      string, and needs escaping
1141          */
1142         ret = value_data_from_str(vp, &vp->data, &type, vp->da, value, inlen, '"');
1143         if (ret < 0) return -1;
1144
1145         /*
1146          *      If we parsed to a different type than the DA associated with
1147          *      the VALUE_PAIR we now need to fixup the DA.
1148          */
1149         if (type != vp->da->type) {
1150                 DICT_ATTR const *da;
1151
1152                 da = dict_attrbytype(vp->da->attr, vp->da->vendor, type);
1153                 if (!da) {
1154                         fr_strerror_printf("Cannot find %s variant of attribute \"%s\"",
1155                                            fr_int2str(dict_attr_types, type, "<INVALID>"), vp->da->name);
1156                         return -1;
1157                 }
1158                 vp->da = da;
1159         }
1160
1161         vp->vp_length = ret;
1162         vp->type = VT_DATA;
1163
1164         VERIFY_VP(vp);
1165
1166         return 0;
1167 }
1168
1169 /** Use simple heuristics to create an VALUE_PAIR from an unknown address string
1170  *
1171  * If a DICT_ATTR is not provided for the address type, parsing will fail with
1172  * and error.
1173  *
1174  * @param ctx to allocate VP in.
1175  * @param value IPv4/IPv6 address/prefix string.
1176  * @param ipv4 dictionary attribute to use for an IPv4 address.
1177  * @param ipv6 dictionary attribute to use for an IPv6 address.
1178  * @param ipv4_prefix dictionary attribute to use for an IPv4 prefix.
1179  * @param ipv6_prefix dictionary attribute to use for an IPv6 prefix.
1180  * @return NULL on error, or new VALUE_PAIR.
1181  */
1182 VALUE_PAIR *fr_pair_afrom_ip_str(TALLOC_CTX *ctx, char const *value, DICT_ATTR *ipv4, DICT_ATTR *ipv6,
1183                                  DICT_ATTR *ipv4_prefix, DICT_ATTR *ipv6_prefix)
1184 {
1185         VALUE_PAIR *vp;
1186         DICT_ATTR *da = NULL;
1187
1188         if (!fr_assert(ipv4 || ipv6 || ipv4_prefix || ipv6_prefix)) {
1189                 return NULL;
1190         }
1191
1192         /* No point in repeating the work of fr_pair_value_from_str */
1193         if (strchr(value, ':')) {
1194                 if (strchr(value, '/')) {
1195                         da = ipv6_prefix;
1196                         goto finish;
1197                 }
1198
1199                 da = ipv6;
1200                 goto finish;
1201         }
1202
1203         if (strchr(value, '/')) {
1204                 da = ipv4_prefix;
1205                 goto finish;
1206         }
1207
1208         if (ipv4) {
1209                 da = ipv4;
1210                 goto finish;
1211         }
1212
1213         fr_strerror_printf("Invalid IP value specified, allowed types are %s%s%s%s",
1214                            ipv4 ? "ipaddr " : "", ipv6 ? "ipv6addr " : "",
1215                            ipv4_prefix ? "ipv4prefix " : "", ipv6_prefix ? "ipv6prefix" : "");
1216
1217 finish:
1218         vp = fr_pair_afrom_da(ctx, da);
1219         if (!vp) return NULL;
1220         if (fr_pair_value_from_str(vp, value, -1) < 0) {
1221                 talloc_free(vp);
1222                 return NULL;
1223         }
1224
1225         return vp;
1226 }
1227
1228
1229 static VALUE_PAIR *fr_pair_from_unkown(VALUE_PAIR *vp, DICT_ATTR const *da)
1230 {
1231         ssize_t len;
1232         VALUE_PAIR *vp2;
1233
1234         len = data2vp(NULL, NULL, NULL, NULL, da,
1235                       vp->vp_octets, vp->vp_length, vp->vp_length,
1236                       &vp2);
1237         if (len < 0) return vp; /* it's really unknown */
1238
1239         if (vp2->da->flags.is_unknown) {
1240                 fr_pair_list_free(&vp2);
1241                 return vp;
1242         }
1243
1244         /*
1245          *      Didn't parse all of it.  Return the "unknown" one.
1246          *
1247          *      FIXME: it COULD have parsed 2 attributes and
1248          *      then not the third, so returning 2 "knowns"
1249          *      and 1 "unknown" is likely preferable.
1250          */
1251         if ((size_t) len < vp->vp_length) {
1252                 fr_pair_list_free(&vp2);
1253                 return vp;
1254         }
1255
1256         fr_pair_steal(talloc_parent(vp), vp2);
1257         fr_pair_list_free(&vp);
1258         return vp2;
1259 }
1260
1261 /** Create a valuepair from an ASCII attribute and value
1262  *
1263  * Where the attribute name is in the form:
1264  *  - Attr-%d
1265  *  - Attr-%d.%d.%d...
1266  *  - Vendor-%d-Attr-%d
1267  *  - VendorName-Attr-%d
1268  *
1269  * @param ctx for talloc
1270  * @param attribute name to parse.
1271  * @param value to parse (must be a hex string).
1272  * @param op to assign to new valuepair.
1273  * @return new valuepair or NULL on error.
1274  */
1275 static VALUE_PAIR *fr_pair_make_unknown(TALLOC_CTX *ctx,
1276                                         char const *attribute, char const *value,
1277                                         FR_TOKEN op)
1278 {
1279         VALUE_PAIR      *vp;
1280         DICT_ATTR const *da;
1281
1282         uint8_t         *data;
1283         size_t          size;
1284
1285         da = dict_unknown_afrom_str(ctx, attribute);
1286         if (!da) return NULL;
1287
1288         /*
1289          *      Unknown attributes MUST be of type 'octets'
1290          */
1291         if (value && (strncasecmp(value, "0x", 2) != 0)) {
1292                 fr_strerror_printf("Unknown attribute \"%s\" requires a hex "
1293                                    "string, not \"%s\"", attribute, value);
1294
1295                 dict_attr_free(&da);
1296                 return NULL;
1297         }
1298
1299         /*
1300          *      We've now parsed the attribute properly, Let's create
1301          *      it.  This next stop also looks the attribute up in the
1302          *      dictionary, and creates the appropriate type for it.
1303          */
1304         vp = fr_pair_afrom_da(ctx, da);
1305         if (!vp) {
1306                 dict_attr_free(&da);
1307                 return NULL;
1308         }
1309
1310         vp->op = (op == 0) ? T_OP_EQ : op;
1311
1312         if (!value) return vp;
1313
1314         size = strlen(value + 2);
1315         vp->vp_length = size >> 1;
1316         data = talloc_array(vp, uint8_t, vp->vp_length);
1317
1318         if (fr_hex2bin(data, vp->vp_length, value + 2, size) != vp->vp_length) {
1319                 fr_strerror_printf("Invalid hex string");
1320                 talloc_free(vp);
1321                 return NULL;
1322         }
1323
1324         vp->vp_octets = data;
1325         vp->type = VT_DATA;
1326
1327         /*
1328          *      Convert unknowns to knowns
1329          */
1330         da = dict_attrbyvalue(vp->da->attr, vp->da->vendor);
1331         if (da) {
1332                 return fr_pair_from_unkown(vp, da);
1333         }
1334
1335         return vp;
1336 }
1337
1338
1339 /** Create a VALUE_PAIR from ASCII strings
1340  *
1341  * Converts an attribute string identifier (with an optional tag qualifier)
1342  * and value string into a VALUE_PAIR.
1343  *
1344  * The string value is parsed according to the type of VALUE_PAIR being created.
1345  *
1346  * @param[in] ctx for talloc
1347  * @param[in] vps list where the attribute will be added (optional)
1348  * @param[in] attribute name.
1349  * @param[in] value attribute value (may be NULL if value will be set later).
1350  * @param[in] op to assign to new VALUE_PAIR.
1351  * @return a new VALUE_PAIR.
1352  */
1353 VALUE_PAIR *fr_pair_make(TALLOC_CTX *ctx, VALUE_PAIR **vps,
1354                         char const *attribute, char const *value, FR_TOKEN op)
1355 {
1356         DICT_ATTR const *da;
1357         VALUE_PAIR      *vp;
1358         char            *tc, *ts;
1359         int8_t          tag;
1360         bool            found_tag;
1361         char            buffer[256];
1362         char const      *attrname = attribute;
1363
1364         /*
1365          *    Check for tags in 'Attribute:Tag' format.
1366          */
1367         found_tag = false;
1368         tag = TAG_ANY;
1369
1370         ts = strrchr(attribute, ':');
1371         if (ts && !ts[1]) {
1372                 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1373                 return NULL;
1374         }
1375
1376         if (ts && ts[1]) {
1377                 strlcpy(buffer, attribute, sizeof(buffer));
1378                 attrname = buffer;
1379                 ts = strrchr(attrname, ':');
1380                 if (!ts) return NULL;
1381
1382                  /* Colon found with something behind it */
1383                  if (ts[1] == '*' && ts[2] == 0) {
1384                          /* Wildcard tag for check items */
1385                          tag = TAG_ANY;
1386                          *ts = '\0';
1387                  } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1388                          /* It's not a wild card tag */
1389                          tag = strtol(ts + 1, &tc, 0);
1390                          if (tc && !*tc && TAG_VALID_ZERO(tag))
1391                                  *ts = '\0';
1392                          else tag = TAG_ANY;
1393                  } else {
1394                          fr_strerror_printf("Invalid tag for attribute %s", attribute);
1395                          return NULL;
1396                  }
1397                  found_tag = true;
1398         }
1399
1400         /*
1401          *      It's not found in the dictionary, so we use
1402          *      another method to create the attribute.
1403          */
1404         da = dict_attrbyname(attrname);
1405         if (!da) {
1406                 vp = fr_pair_make_unknown(ctx, attrname, value, op);
1407                 if (vp && vps) fr_pair_add(vps, vp);
1408                 return vp;
1409         }
1410
1411         /*      Check for a tag in the 'Merit' format of:
1412          *      :Tag:Value.  Print an error if we already found
1413          *      a tag in the Attribute.
1414          */
1415
1416         if (value && (*value == ':' && da->flags.has_tag)) {
1417                 /* If we already found a tag, this is invalid */
1418                 if(found_tag) {
1419                         fr_strerror_printf("Duplicate tag %s for attribute %s",
1420                                    value, da->name);
1421                         DEBUG("Duplicate tag %s for attribute %s\n",
1422                                    value, da->name);
1423                         return NULL;
1424                 }
1425                 /* Colon found and attribute allows a tag */
1426                 if (value[1] == '*' && value[2] == ':') {
1427                        /* Wildcard tag for check items */
1428                        tag = TAG_ANY;
1429                        value += 3;
1430                 } else {
1431                        /* Real tag */
1432                        tag = strtol(value + 1, &tc, 0);
1433                        if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1434                             value = tc + 1;
1435                        else tag = 0;
1436                 }
1437         }
1438
1439         vp = fr_pair_afrom_da(ctx, da);
1440         if (!vp) return NULL;
1441         vp->op = (op == 0) ? T_OP_EQ : op;
1442         vp->tag = tag;
1443
1444         switch (vp->op) {
1445         case T_OP_CMP_TRUE:
1446         case T_OP_CMP_FALSE:
1447                 vp->vp_strvalue = NULL;
1448                 vp->vp_length = 0;
1449                 value = NULL;   /* ignore it! */
1450                 break;
1451
1452                 /*
1453                  *      Regular expression comparison of integer attributes
1454                  *      does a STRING comparison of the names of their
1455                  *      integer attributes.
1456                  */
1457         case T_OP_REG_EQ:       /* =~ */
1458         case T_OP_REG_NE:       /* !~ */
1459         {
1460 #ifndef HAVE_REGEX
1461                 fr_strerror_printf("Regular expressions are not supported");
1462                 return NULL;
1463 #else
1464                 ssize_t slen;
1465                 regex_t *preg;
1466
1467                 /*
1468                  *      Someone else will fill in the value.
1469                  */
1470                 if (!value) break;
1471
1472                 talloc_free(vp);
1473
1474                 slen = regex_compile(ctx, &preg, value, strlen(value), false, false, false, true);
1475                 if (slen <= 0) {
1476                         fr_strerror_printf("Error at offset %zu compiling regex for %s: %s", -slen,
1477                                            attribute, fr_strerror());
1478                         return NULL;
1479                 }
1480                 talloc_free(preg);
1481
1482                 vp = fr_pair_make(ctx, NULL, attribute, NULL, op);
1483                 if (!vp) return NULL;
1484
1485                 if (fr_pair_mark_xlat(vp, value) < 0) {
1486                         talloc_free(vp);
1487                         return NULL;
1488                 }
1489
1490                 value = NULL;   /* ignore it */
1491                 break;
1492 #endif
1493         }
1494         default:
1495                 break;
1496         }
1497
1498         /*
1499          *      We allow this for stupidity, but it's really a bad idea.
1500          */
1501         if (vp->da->type == PW_TYPE_TLV) {
1502                 ssize_t len;
1503                 DICT_ATTR const *unknown;
1504                 VALUE_PAIR *head = NULL;
1505                 VALUE_PAIR **tail = &head;
1506
1507                 if (!value) {
1508                         talloc_free(vp);
1509                         return NULL;
1510                 }
1511
1512                 unknown = dict_unknown_afrom_fields(vp, vp->da->attr, vp->da->vendor);
1513                 if (!unknown) {
1514                         talloc_free(vp);
1515                         return NULL;
1516                 }
1517
1518                 vp->da = unknown;
1519
1520                 /*
1521                  *      Parse it as an unknown type, i.e. octets.
1522                  */
1523                 if (fr_pair_value_from_str(vp, value, -1) < 0) {
1524                         talloc_free(vp);
1525                         return NULL;
1526                 }
1527
1528                 /*
1529                  *      It's badly formatted.  Treat it as unknown.
1530                  */
1531                 if (rad_tlv_ok(vp->vp_octets, vp->vp_length, 1, 1) < 0) {
1532                         goto do_add;
1533                 }
1534
1535                 /*
1536                  *      Decode the TLVs
1537                  */
1538                 len = rad_data2vp_tlvs(ctx, NULL, NULL, NULL, da, vp->vp_octets,
1539                                        vp->vp_length, tail);
1540                 if (len < 0) {
1541                         goto do_add;
1542                 }
1543
1544                 talloc_free(vp);
1545                 vp = head;
1546                 goto do_add;
1547         }
1548
1549         /*
1550          *      FIXME: if (strcasecmp(attribute, vp->da->name) != 0)
1551          *      then the user MAY have typed in the attribute name
1552          *      as Vendor-%d-Attr-%d, and the value MAY be octets.
1553          *
1554          *      We probably want to fix fr_pair_value_from_str to accept
1555          *      octets as values for any attribute.
1556          */
1557         if (value && (fr_pair_value_from_str(vp, value, -1) < 0)) {
1558                 talloc_free(vp);
1559                 return NULL;
1560         }
1561
1562 do_add:
1563         if (vps) fr_pair_add(vps, vp);
1564         return vp;
1565 }
1566
1567 /** Mark a valuepair for xlat expansion
1568  *
1569  * Copies xlat source (unprocessed) string to valuepair value,
1570  * and sets value type.
1571  *
1572  * @param vp to mark for expansion.
1573  * @param value to expand.
1574  * @return 0 if marking succeeded or -1 if vp already had a value, or OOM.
1575  */
1576 int fr_pair_mark_xlat(VALUE_PAIR *vp, char const *value)
1577 {
1578         char *raw;
1579
1580         /*
1581          *      valuepair should not already have a value.
1582          */
1583         if (vp->type != VT_NONE) {
1584                 return -1;
1585         }
1586
1587         raw = talloc_typed_strdup(vp, value);
1588         if (!raw) {
1589                 return -1;
1590         }
1591
1592         vp->type = VT_XLAT;
1593         vp->value.xlat = raw;
1594         vp->vp_length = 0;
1595
1596         return 0;
1597 }
1598
1599
1600 /** Read a single valuepair from a buffer, and advance the pointer
1601  *
1602  *  Returns T_EOL if end of line was encountered.
1603  *
1604  * @param[in,out] ptr to read from and update.
1605  * @param[out] raw The struct to write the raw VALUE_PAIR to.
1606  * @return the last token read.
1607  */
1608 FR_TOKEN fr_pair_raw_from_str(char const **ptr, VALUE_PAIR_RAW *raw)
1609 {
1610         char const      *p;
1611         char *q;
1612         FR_TOKEN        ret = T_INVALID, next, quote;
1613         char            buf[8];
1614
1615         if (!ptr || !*ptr || !raw) {
1616                 fr_strerror_printf("Invalid arguments");
1617                 return T_INVALID;
1618         }
1619
1620         /*
1621          *      Skip leading spaces
1622          */
1623         p = *ptr;
1624         while ((*p == ' ') || (*p == '\t')) p++;
1625
1626         if (!*p) {
1627                 fr_strerror_printf("No token read where we expected "
1628                                    "an attribute name");
1629                 return T_INVALID;
1630         }
1631
1632         if (*p == '#') return T_HASH;
1633
1634         /*
1635          *      Try to get the attribute name.
1636          */
1637         q = raw->l_opand;
1638         *q = '\0';
1639         while (*p) {
1640                 uint8_t const *t = (uint8_t const *) p;
1641
1642                 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
1643                 too_long:
1644                         fr_strerror_printf("Attribute name too long");
1645                         return T_INVALID;
1646                 }
1647
1648                 /*
1649                  *      This is arguably easier than trying to figure
1650                  *      out which operators come after the attribute
1651                  *      name.  Yes, our "lexer" is bad.
1652                  */
1653                 if (!dict_attr_allowed_chars[(unsigned int) *t]) {
1654                         break;
1655                 }
1656
1657                 /*
1658                  *      Attribute:=value is NOT
1659                  *
1660                  *      Attribute:
1661                  *      =
1662                  *      value
1663                  */
1664                 if ((*p == ':') && (!isdigit((int) p[1]))) {
1665                         break;
1666                 }
1667
1668                 *(q++) = *(p++);
1669         }
1670
1671         /*
1672          *      Haven't found any valid characters in the name.
1673          */
1674         if (!*raw->l_opand) {
1675                 fr_strerror_printf("Invalid attribute name");
1676                 return T_INVALID;
1677         }
1678
1679         /*
1680          *      Look for tag (:#).  This is different from :=, which
1681          *      is an operator.
1682          */
1683         if ((*p == ':') && (isdigit((int) p[1]))) {
1684                 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
1685                         goto too_long;
1686                 }
1687                 *(q++) = *(p++);
1688
1689                 while (isdigit((int) *p)) {
1690                         if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
1691                                 goto too_long;
1692                         }
1693                         *(q++) = *(p++);
1694                 }
1695         }
1696
1697         *q = '\0';
1698         *ptr = p;
1699
1700         /* Now we should have an operator here. */
1701         raw->op = gettoken(ptr, buf, sizeof(buf), false);
1702         if (raw->op  < T_EQSTART || raw->op  > T_EQEND) {
1703                 fr_strerror_printf("Expecting operator");
1704
1705                 return T_INVALID;
1706         }
1707
1708         /*
1709          *      Read value.  Note that empty string values are allowed
1710          */
1711         quote = gettoken(ptr, raw->r_opand, sizeof(raw->r_opand), false);
1712         if (quote == T_EOL) {
1713                 fr_strerror_printf("Failed to get value");
1714
1715                 return T_INVALID;
1716         }
1717
1718         /*
1719          *      Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1720          */
1721         p = *ptr;
1722
1723         next = gettoken(&p, buf, sizeof(buf), false);
1724         switch (next) {
1725         case T_HASH:
1726                 next = T_EOL;
1727                 break;
1728
1729         case T_EOL:
1730                 break;
1731
1732         case T_COMMA:
1733                 *ptr = p;
1734                 break;
1735
1736         default:
1737                 fr_strerror_printf("Expected end of line or comma");
1738                 return T_INVALID;
1739         }
1740         ret = next;
1741
1742         switch (quote) {
1743         /*
1744          *      Perhaps do xlat's
1745          */
1746         case T_DOUBLE_QUOTED_STRING:
1747                 /*
1748                  *      Only report as double quoted if it contained valid
1749                  *      a valid xlat expansion.
1750                  */
1751                 p = strchr(raw->r_opand, '%');
1752                 if (p && (p[1] == '{')) {
1753                         raw->quote = quote;
1754                 } else {
1755                         raw->quote = T_SINGLE_QUOTED_STRING;
1756                 }
1757
1758                 break;
1759
1760         case T_SINGLE_QUOTED_STRING:
1761         case T_BACK_QUOTED_STRING:
1762         case T_BARE_WORD:
1763                 raw->quote = quote;
1764                 break;
1765
1766         default:
1767                 fr_strerror_printf("Failed to find expected value on right hand side");
1768                 return T_INVALID;
1769         }
1770
1771         return ret;
1772 }
1773
1774 /** Read one line of attribute/value pairs into a list.
1775  *
1776  * The line may specify multiple attributes separated by commas.
1777  *
1778  * @note If the function returns T_INVALID, an error has occurred and
1779  * @note the valuepair list should probably be freed.
1780  *
1781  * @param ctx for talloc
1782  * @param buffer to read valuepairs from.
1783  * @param list where the parsed VALUE_PAIRs will be appended.
1784  * @return the last token parsed, or T_INVALID
1785  */
1786 FR_TOKEN fr_pair_list_afrom_str(TALLOC_CTX *ctx, char const *buffer, VALUE_PAIR **list)
1787 {
1788         VALUE_PAIR      *vp, *head, **tail;
1789         char const      *p;
1790         FR_TOKEN        last_token = T_INVALID;
1791         VALUE_PAIR_RAW  raw;
1792
1793         /*
1794          *      We allow an empty line.
1795          */
1796         if (buffer[0] == 0) {
1797                 return T_EOL;
1798         }
1799
1800         head = NULL;
1801         tail = &head;
1802
1803         p = buffer;
1804         do {
1805                 raw.l_opand[0] = '\0';
1806                 raw.r_opand[0] = '\0';
1807
1808                 last_token = fr_pair_raw_from_str(&p, &raw);
1809
1810                 /*
1811                  *      JUST a hash.  Don't try to create a VP.
1812                  *      Let the caller determine if an empty list is OK.
1813                  */
1814                 if (last_token == T_HASH) {
1815                         last_token = T_EOL;
1816                         break;
1817                 }
1818                 if (last_token == T_INVALID) break;
1819
1820                 if (raw.quote == T_DOUBLE_QUOTED_STRING) {
1821                         vp = fr_pair_make(ctx, NULL, raw.l_opand, NULL, raw.op);
1822                         if (!vp) {
1823                                 last_token = T_INVALID;
1824                                 break;
1825                         }
1826                         if (fr_pair_mark_xlat(vp, raw.r_opand) < 0) {
1827                                 talloc_free(vp);
1828                                 last_token = T_INVALID;
1829                                 break;
1830                         }
1831                 } else {
1832                         vp = fr_pair_make(ctx, NULL, raw.l_opand, raw.r_opand, raw.op);
1833                         if (!vp) {
1834                                 last_token = T_INVALID;
1835                                 break;
1836                         }
1837                 }
1838
1839                 *tail = vp;
1840                 tail = &((*tail)->next);
1841         } while (*p && (last_token == T_COMMA));
1842
1843         if (last_token == T_INVALID) {
1844                 fr_pair_list_free(&head);
1845         } else {
1846                 fr_pair_add(list, head);
1847         }
1848
1849         /*
1850          *      And return the last token which we read.
1851          */
1852         return last_token;
1853 }
1854
1855 /*
1856  *      Read valuepairs from the fp up to End-Of-File.
1857  */
1858 int fr_pair_list_afrom_file(TALLOC_CTX *ctx, VALUE_PAIR **out, FILE *fp, bool *pfiledone)
1859 {
1860         char buf[8192];
1861         FR_TOKEN last_token = T_EOL;
1862
1863         vp_cursor_t cursor;
1864
1865         VALUE_PAIR *vp = NULL;
1866         fr_cursor_init(&cursor, out);
1867
1868         while (fgets(buf, sizeof(buf), fp) != NULL) {
1869                 /*
1870                  *      If we get a '\n' by itself, we assume that's
1871                  *      the end of that VP
1872                  */
1873                 if (buf[0] == '\n') {
1874                         if (vp) {
1875                                 *pfiledone = false;
1876                                 return 0;
1877                         }
1878                         continue;
1879                 }
1880
1881                 /*
1882                  *      Comments get ignored
1883                  */
1884                 if (buf[0] == '#') continue;
1885
1886                 /*
1887                  *      Read all of the attributes on the current line.
1888                  */
1889                 vp = NULL;
1890                 last_token = fr_pair_list_afrom_str(ctx, buf, &vp);
1891                 if (!vp) {
1892                         if (last_token != T_EOL) goto error;
1893                         break;
1894                 }
1895
1896                 fr_cursor_merge(&cursor, vp);
1897                 buf[0] = '\0';
1898         }
1899         *pfiledone = true;
1900
1901         return 0;
1902
1903 error:
1904         *pfiledone = false;
1905         vp = fr_cursor_first(&cursor);
1906         if (vp) fr_pair_list_free(&vp);
1907
1908         return -1;
1909 }
1910
1911 /** Compare two pairs, using the operator from "a"
1912  *
1913  *      i.e. given two attributes, it does:
1914  *
1915  *      (b->data) (a->operator) (a->data)
1916  *
1917  *      e.g. "foo" != "bar"
1918  *
1919  * @param[in] a the first attribute
1920  * @param[in] b the second attribute
1921  * @return 1 if true, 0 if false, -1 on error.
1922  */
1923 int fr_pair_cmp(VALUE_PAIR *a, VALUE_PAIR *b)
1924 {
1925         if (!a) return -1;
1926
1927         VERIFY_VP(a);
1928         if (b) VERIFY_VP(b);
1929
1930         switch (a->op) {
1931         case T_OP_CMP_TRUE:
1932                 return (b != NULL);
1933
1934         case T_OP_CMP_FALSE:
1935                 return (b == NULL);
1936
1937                 /*
1938                  *      a is a regex, compile it, print b to a string,
1939                  *      and then do string comparisons.
1940                  */
1941         case T_OP_REG_EQ:
1942         case T_OP_REG_NE:
1943 #ifndef HAVE_REGEX
1944                 return -1;
1945 #else
1946                 if (!b) return false;
1947
1948                 {
1949                         ssize_t slen;
1950                         regex_t *preg;
1951                         char    *value;
1952
1953                         if (!fr_assert(a->da->type == PW_TYPE_STRING)) return -1;
1954
1955                         slen = regex_compile(NULL, &preg, a->vp_strvalue, a->vp_length, false, false, false, true);
1956                         if (slen <= 0) {
1957                                 fr_strerror_printf("Error at offset %zu compiling regex for %s: %s",
1958                                                    -slen, a->da->name, fr_strerror());
1959                                 return -1;
1960                         }
1961                         value = vp_aprints_value(NULL, b, '\0');
1962                         if (!value) {
1963                                 talloc_free(preg);
1964                                 return -1;
1965                         }
1966
1967                         /*
1968                          *      Don't care about substring matches, oh well...
1969                          */
1970                         slen = regex_exec(preg, value, talloc_array_length(value) - 1, NULL, NULL);
1971                         talloc_free(preg);
1972                         talloc_free(value);
1973
1974                         if (slen < 0) return -1;
1975                         if (a->op == T_OP_REG_EQ) return (int)slen;
1976                         return !slen;
1977                 }
1978 #endif
1979
1980         default:                /* we're OK */
1981                 if (!b) return false;
1982                 break;
1983         }
1984
1985         return fr_pair_cmp_op(a->op, b, a);
1986 }
1987
1988 /** Determine equality of two lists
1989  *
1990  * This is useful for comparing lists of attributes inserted into a binary tree.
1991  *
1992  * @param a first list of VALUE_PAIRs.
1993  * @param b second list of VALUE_PAIRs.
1994  * @return -1 if a < b, 0 if the two lists are equal, 1 if a > b, -2 on error.
1995  */
1996 int fr_pair_list_cmp(VALUE_PAIR *a, VALUE_PAIR *b)
1997 {
1998         vp_cursor_t a_cursor, b_cursor;
1999         VALUE_PAIR *a_p, *b_p;
2000         int ret;
2001
2002         for (a_p = fr_cursor_init(&a_cursor, &a), b_p = fr_cursor_init(&b_cursor, &b);
2003              a_p && b_p;
2004              a_p = fr_cursor_next(&a_cursor), b_p = fr_cursor_next(&b_cursor)) {
2005                 /* Same VP, no point doing expensive checks */
2006                 if (a_p == b_p) {
2007                         continue;
2008                 }
2009
2010                 if (a_p->da < b_p->da) {
2011                         return -1;
2012                 }
2013                 if (a_p->da > b_p->da) {
2014                         return 1;
2015                 }
2016
2017                 if (a_p->tag < b_p->tag) {
2018                         return -1;
2019                 }
2020                 if (a_p->tag > b_p->tag) {
2021                         return 1;
2022                 }
2023
2024                 ret = value_data_cmp(a_p->da->type, &a_p->data, a_p->vp_length,
2025                                      b_p->da->type, &b_p->data, b_p->vp_length);
2026                 if (ret != 0) {
2027                         fr_assert(ret >= -1);   /* Comparison error */
2028                         return ret;
2029                 }
2030         }
2031
2032         if (!a_p && !b_p) {
2033                 return 0;
2034         }
2035
2036         if (!a_p) {
2037                 return -1;
2038         }
2039
2040         /* if(!b_p) */
2041         return 1;
2042 }
2043
2044 /** Set the type of the VALUE_PAIR value buffer to match it's DICT_ATTR
2045  *
2046  * @param vp to fixup.
2047  */
2048 static void fr_pair_value_set_type(VALUE_PAIR *vp)
2049 {
2050         if (!vp->data.ptr) return;
2051
2052         switch (vp->da->type) {
2053         case PW_TYPE_OCTETS:
2054                 talloc_set_type(vp->data.ptr, uint8_t);
2055                 return;
2056
2057         case PW_TYPE_STRING:
2058                 talloc_set_type(vp->data.ptr, char);
2059                 return;
2060
2061         default:
2062                 return;
2063         }
2064 }
2065
2066 /** Copy data into an "octets" data type.
2067  *
2068  * @param[in,out] vp to update
2069  * @param[in] src data to copy
2070  * @param[in] size of the data, may be 0 in which case previous value will be freed.
2071  */
2072 void fr_pair_value_memcpy(VALUE_PAIR *vp, uint8_t const *src, size_t size)
2073 {
2074         uint8_t *p = NULL, *q;
2075
2076         VERIFY_VP(vp);
2077
2078         if (size > 0) {
2079                 p = talloc_memdup(vp, src, size);
2080                 if (!p) return;
2081                 talloc_set_type(p, uint8_t);
2082         }
2083
2084         memcpy(&q, &vp->vp_octets, sizeof(q));
2085         TALLOC_FREE(q);
2086
2087         vp->vp_octets = p;
2088         vp->vp_length = size;
2089
2090         if (size > 0) fr_pair_value_set_type(vp);
2091 }
2092
2093 /** Reparent an allocated octet buffer to a VALUE_PAIR
2094  *
2095  * @param[in,out] vp to update
2096  * @param[in] src buffer to steal.
2097  */
2098 void fr_pair_value_memsteal(VALUE_PAIR *vp, uint8_t const *src)
2099 {
2100         uint8_t *q;
2101
2102         VERIFY_VP(vp);
2103
2104         memcpy(&q, &vp->vp_octets, sizeof(q));
2105         talloc_free(q);
2106
2107         vp->vp_octets = talloc_steal(vp, src);
2108         vp->type = VT_DATA;
2109         vp->vp_length = talloc_array_length(vp->vp_strvalue);
2110         fr_pair_value_set_type(vp);
2111 }
2112
2113 /** Reparent an allocated char buffer to a VALUE_PAIR
2114  *
2115  * @param[in,out] vp to update
2116  * @param[in] src buffer to steal.
2117  */
2118 void fr_pair_value_strsteal(VALUE_PAIR *vp, char const *src)
2119 {
2120         uint8_t *q;
2121
2122         VERIFY_VP(vp);
2123
2124         memcpy(&q, &vp->vp_octets, sizeof(q));
2125         talloc_free(q);
2126
2127         vp->vp_strvalue = talloc_steal(vp, src);
2128         vp->type = VT_DATA;
2129         vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
2130         fr_pair_value_set_type(vp);
2131 }
2132
2133 /** Copy data into an "string" data type.
2134  *
2135  * @param[in,out] vp to update
2136  * @param[in] src data to copy
2137  */
2138 void fr_pair_value_strcpy(VALUE_PAIR *vp, char const *src)
2139 {
2140         char *p, *q;
2141
2142         VERIFY_VP(vp);
2143
2144         p = talloc_strdup(vp, src);
2145
2146         if (!p) return;
2147
2148         memcpy(&q, &vp->vp_strvalue, sizeof(q));
2149         talloc_free(q);
2150
2151         vp->vp_strvalue = p;
2152         vp->type = VT_DATA;
2153         vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
2154         fr_pair_value_set_type(vp);
2155 }
2156
2157 /** Copy data into an "string" data type.
2158  *
2159  * @note unlike the original strncpy, this function does not stop
2160  *      if it finds \0 bytes embedded in the string.
2161  *
2162  * @param[in,out] vp to update.
2163  * @param[in] src data to copy.
2164  * @param[in] len of data to copy.
2165  */
2166 void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
2167 {
2168         char *p, *q;
2169
2170         VERIFY_VP(vp);
2171
2172         p = talloc_array(vp, char, len + 1);
2173         if (!p) return;
2174
2175         memcpy(p, src, len);    /* embdedded \0 safe */
2176         p[len] = '\0';
2177
2178         memcpy(&q, &vp->vp_strvalue, sizeof(q));
2179         talloc_free(q);
2180
2181         vp->vp_strvalue = p;
2182         vp->type = VT_DATA;
2183         vp->vp_length = len;
2184         fr_pair_value_set_type(vp);
2185 }
2186
2187 /** Print data into an "string" data type.
2188  *
2189  * @param[in,out] vp to update
2190  * @param[in] fmt the format string
2191  */
2192 void fr_pair_value_sprintf(VALUE_PAIR *vp, char const *fmt, ...)
2193 {
2194         va_list ap;
2195         char *p, *q;
2196
2197         VERIFY_VP(vp);
2198
2199         va_start(ap, fmt);
2200         p = talloc_vasprintf(vp, fmt, ap);
2201         va_end(ap);
2202
2203         if (!p) return;
2204
2205         memcpy(&q, &vp->vp_strvalue, sizeof(q));
2206         talloc_free(q);
2207
2208         vp->vp_strvalue = p;
2209         vp->type = VT_DATA;
2210
2211         vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
2212         fr_pair_value_set_type(vp);
2213 }
2214
2215 #ifdef WITH_VERIFY_PTR
2216 /*
2217  *      Verify a VALUE_PAIR
2218  */
2219 inline void fr_pair_verify(char const *file, int line, VALUE_PAIR const *vp)
2220 {
2221         if (!vp) {
2222                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR pointer was NULL", file, line);
2223                 fr_assert(0);
2224                 fr_exit_now(1);
2225         }
2226
2227         (void) talloc_get_type_abort(vp, VALUE_PAIR);
2228
2229         if (!vp->da) {
2230                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR da pointer was NULL", file, line);
2231                 fr_assert(0);
2232                 fr_exit_now(1);
2233         }
2234
2235         if (vp->data.ptr) switch (vp->da->type) {
2236         case PW_TYPE_OCTETS:
2237         {
2238                 size_t len;
2239                 TALLOC_CTX *parent;
2240
2241                 if (!talloc_get_type(vp->data.ptr, uint8_t)) {
2242                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" data buffer type should be "
2243                                      "uint8_t but is %s\n", file, line, vp->da->name, talloc_get_name(vp->data.ptr));
2244                         (void) talloc_get_type_abort(vp->data.ptr, uint8_t);
2245                 }
2246
2247                 len = talloc_array_length(vp->vp_octets);
2248                 if (vp->vp_length > len) {
2249                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" length %zu is greater than "
2250                                      "uint8_t data buffer length %zu\n", file, line, vp->da->name, vp->vp_length, len);
2251                         fr_assert(0);
2252                         fr_exit_now(1);
2253                 }
2254
2255                 parent = talloc_parent(vp->data.ptr);
2256                 if (parent != vp) {
2257                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" char buffer is not "
2258                                      "parented by VALUE_PAIR %p, instead parented by %p (%s)\n",
2259                                      file, line, vp->da->name,
2260                                      vp, parent, parent ? talloc_get_name(parent) : "NULL");
2261                         fr_assert(0);
2262                         fr_exit_now(1);
2263                 }
2264         }
2265                 break;
2266
2267         case PW_TYPE_STRING:
2268         {
2269                 size_t len;
2270                 TALLOC_CTX *parent;
2271
2272                 if (!talloc_get_type(vp->data.ptr, char)) {
2273                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" data buffer type should be "
2274                                      "char but is %s\n", file, line, vp->da->name, talloc_get_name(vp->data.ptr));
2275                         (void) talloc_get_type_abort(vp->data.ptr, char);
2276                 }
2277
2278                 len = (talloc_array_length(vp->vp_strvalue) - 1);
2279                 if (vp->vp_length > len) {
2280                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" length %zu is greater than "
2281                                      "char buffer length %zu\n", file, line, vp->da->name, vp->vp_length, len);
2282                         fr_assert(0);
2283                         fr_exit_now(1);
2284                 }
2285
2286                 if (vp->vp_strvalue[vp->vp_length] != '\0') {
2287                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" char buffer not \\0 "
2288                                      "terminated\n", file, line, vp->da->name);
2289                         fr_assert(0);
2290                         fr_exit_now(1);
2291                 }
2292
2293                 parent = talloc_parent(vp->data.ptr);
2294                 if (parent != vp) {
2295                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" char buffer is not "
2296                                      "parented by VALUE_PAIR %p, instead parented by %p (%s)\n",
2297                                      file, line, vp->da->name,
2298                                      vp, parent, parent ? talloc_get_name(parent) : "NULL");
2299                         fr_assert(0);
2300                         fr_exit_now(1);
2301                 }
2302         }
2303                 break;
2304
2305         default:
2306                 break;
2307         }
2308
2309         if (vp->da->flags.is_unknown) {
2310                 (void) talloc_get_type_abort(vp->da, DICT_ATTR);
2311         } else {
2312                 DICT_ATTR const *da;
2313
2314                 /*
2315                  *      Attribute may be present with multiple names
2316                  */
2317                 da = dict_attrbyname(vp->da->name);
2318                 if (!da) {
2319                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR attribute %p \"%s\" (%s) "
2320                                      "not found in global dictionary",
2321                                      file, line, vp->da, vp->da->name,
2322                                      fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"));
2323                         fr_assert(0);
2324                         fr_exit_now(1);
2325                 }
2326
2327                 if (da->type == PW_TYPE_COMBO_IP_ADDR) {
2328                         da = dict_attrbytype(vp->da->attr, vp->da->vendor, vp->da->type);
2329                         if (!da) {
2330                                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR attribute %p \"%s\" "
2331                                              "variant (%s) not found in global dictionary",
2332                                              file, line, vp->da, vp->da->name,
2333                                              fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"));
2334                                 fr_assert(0);
2335                                 fr_exit_now(1);
2336                         }
2337                 }
2338
2339
2340                 if (da != vp->da) {
2341                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR "
2342                                      "dictionary pointer %p \"%s\" (%s) "
2343                                      "and global dictionary pointer %p \"%s\" (%s) differ",
2344                                      file, line, vp->da, vp->da->name,
2345                                      fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"),
2346                                      da, da->name, fr_int2str(dict_attr_types, da->type, "<INVALID>"));
2347                         fr_assert(0);
2348                         fr_exit_now(1);
2349                 }
2350         }
2351 }
2352
2353 /*
2354  *      Verify a pair list
2355  */
2356 void fr_pair_list_verify(char const *file, int line, TALLOC_CTX *expected, VALUE_PAIR *vps)
2357 {
2358         vp_cursor_t cursor;
2359         VALUE_PAIR *vp;
2360         TALLOC_CTX *parent;
2361
2362         for (vp = fr_cursor_init(&cursor, &vps);
2363              vp;
2364              vp = fr_cursor_next(&cursor)) {
2365                 VERIFY_VP(vp);
2366
2367                 parent = talloc_parent(vp);
2368                 if (expected && (parent != expected)) {
2369                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: Expected VALUE_PAIR \"%s\" to be parented "
2370                                      "by %p (%s), instead parented by %p (%s)\n",
2371                                      file, line, vp->da->name,
2372                                      expected, talloc_get_name(expected),
2373                                      parent, parent ? talloc_get_name(parent) : "NULL");
2374
2375                         fr_log_talloc_report(expected);
2376                         if (parent) fr_log_talloc_report(parent);
2377
2378                         fr_assert(0);
2379                         fr_exit_now(1);
2380                 }
2381
2382         }
2383 }
2384 #endif