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