The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
struct.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /** Functions to encode / decode structures on the wire
18  *
19  * @file src/lib/util/struct.c
20  *
21  * @copyright 2018 The FreeRADIUS server project
22  * @copyright 2018 Alan DeKok (aland@freeradius.org)
23  */
24 RCSID("$Id: 58d177f4a5c915654c28117a115b7503fef4f233 $")
25 
26 #include <freeradius-devel/util/struct.h>
27 #include <freeradius-devel/util/encode.h>
28 #include <freeradius-devel/io/pair.h>
29 
30 /** Convert a STRUCT to one or more VPs
31  *
32  */
34  fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
35  bool nested, void *decode_ctx,
37 {
38  unsigned int child_num;
39  uint8_t const *p = data, *end = data + data_len;
40  fr_dict_attr_t const *child;
41  fr_pair_list_t child_list_head;
42  fr_pair_list_t *child_list;
43  fr_pair_t *vp, *key_vp, *struct_vp = NULL;
44  unsigned int offset = 0;
45  TALLOC_CTX *child_ctx;
46  ssize_t slen;
47 
48  if (data_len == 0) {
49  fr_strerror_const("struct decoder was passed zero bytes of data");
50  return -1; /* at least one byte of data */
51  }
52 
53  FR_PROTO_HEX_DUMP(data, data_len, "fr_struct_from_network");
54 
55  /*
56  * Start a child list.
57  */
58  if (!nested) {
59  fr_pair_list_init(&child_list_head);
60  child_list = &child_list_head;
61  child_ctx = ctx;
62  } else {
64 
65  struct_vp = fr_pair_afrom_da(ctx, parent);
66  if (!struct_vp) {
67  fr_strerror_const("out of memory");
68  return -1;
69  }
70 
71  fr_pair_list_init(&child_list_head); /* still used elsewhere */
72  child_list = &struct_vp->vp_group;
73  child_ctx = struct_vp;
74  }
75  child_num = 1;
76  key_vp = NULL;
77 
78  /*
79  * Decode structs with length prefixes.
80  */
82  size_t struct_len, need, new_len;
83 
84  if (parent->flags.subtype == FLAG_LENGTH_UINT8) {
85  need = 1;
86  } else {
87  need = 2;
88  }
89 
90  if ((size_t) (end - p) < need) {
91  FR_PROTO_TRACE("Insufficient room for length header");
92  goto unknown;
93  }
94 
95  struct_len = p[0];
96  if (need > 1) {
97  struct_len <<= 8;
98  struct_len |= p[1];
99  }
100 
101  if (struct_len < da_length_offset(parent)) {
102  FR_PROTO_TRACE("Length header (%zu) is smaller than minimum value (%u)",
103  struct_len, parent->flags.type_size);
104  goto unknown;
105  }
106 
107  if ((p + struct_len + need - da_length_offset(parent)) > end) {
108  FR_PROTO_TRACE("Length header (%zu) is larger than remaining data (%zu)",
109  struct_len + need, (end - p));
110  goto unknown;
111  }
112 
113  /*
114  * Skip the length field, and tell the decoder to
115  * stop at the end of the data we're supposed to decode.
116  */
117  p += need;
118  end = p + struct_len;
119  new_len = struct_len + need - offset;
120  if (new_len > data_len) goto unknown;
121 
122  data_len = new_len;
123  }
124 
125  /*
126  * @todo - If the struct is truncated on a MEMBER boundary, we silently omit
127  * the trailing members. Maybe this should be an error?
128  */
129  while (p < end) {
130  size_t child_length;
131 
132  /*
133  * Go to the next child. If it doesn't exist, we're done.
134  */
135  child = fr_dict_attr_child_by_num(parent, child_num);
136  if (!child) break;
137 
138  FR_PROTO_HEX_DUMP(p, (end - p), "fr_struct_from_network - child %s (%d)", child->name, child->attr);
139 
140  /*
141  * Check for bit fields.
142  */
143  if (da_is_bit_field(child)) {
144  uint8_t array[8];
145  unsigned int num_bits;
146  uint64_t value;
147 
148  num_bits = offset + child->flags.length;
149  if ((size_t)(end - p) < fr_bytes_from_bits(num_bits)) {
150  FR_PROTO_TRACE("not enough data for bit decoder?");
151  goto unknown;
152  }
153 
154  memset(array, 0, sizeof(array));
155  memcpy(&array[0], p, fr_bytes_from_bits(num_bits));
156 
157  if (offset > 0) array[0] &= (1 << (8 - offset)) - 1; /* mask off bits we don't care about */
158 
159  memcpy(&value, &array[0], sizeof(value));
160  value = htonll(value);
161  value >>= (8 - offset); /* move it to the lower bits */
162  value >>= (56 - child->flags.length);
163 
164  vp = fr_pair_afrom_da(child_ctx, child);
165  if (!vp) {
166  FR_PROTO_TRACE("fr_struct_from_network - failed allocating child VP");
167  return PAIR_DECODE_OOM;
168  }
169 
170  switch (child->type) {
171  case FR_TYPE_BOOL:
172  vp->vp_bool = value;
173  break;
174 
175  case FR_TYPE_UINT8:
176  vp->vp_uint8 = value;
177  break;
178 
179  case FR_TYPE_UINT16:
180  vp->vp_uint16 = value;
181  break;
182 
183  case FR_TYPE_UINT32:
184  vp->vp_uint32 = value;
185  break;
186 
187  case FR_TYPE_UINT64:
188  vp->vp_uint64 = value;
189  break;
190 
191  default:
192  FR_PROTO_TRACE("Can't decode unknown type?");
193  goto unknown;
194  }
195 
196  vp->vp_tainted = true;
197  fr_pair_append(child_list, vp);
198  p += (num_bits >> 3); /* go to the LAST bit, not the byte AFTER the last bit */
199  offset = num_bits & 0x07;
200  child_num++;
201  continue;
202  }
203  offset = 0; /* reset for non-bit-field attributes */
204 
205  /*
206  * Decode child TLVs, according to the parent attribute.
207  */
208  if (child->type == FR_TYPE_TLV) {
209  fr_assert(!key_vp);
210 
211  if (!decode_tlv) {
212  fr_strerror_const("Decoding TLVs requires a decode_tlv() function to be passed");
213  return -(p - data);
214  }
215 
216  /*
217  * Decode EVERYTHING as a TLV.
218  */
219  while (p < end) {
220  slen = decode_tlv(child_ctx, child_list, child, p, end - p, decode_ctx);
221  if (slen < 0) {
222  FR_PROTO_TRACE("failed decoding TLV?");
223  goto unknown;
224  }
225  p += slen;
226  }
227 
228  goto done;
229  }
230 
231  child_length = child->flags.length;
232 
233  /*
234  * If this field overflows the input, then *all*
235  * of the input is suspect.
236  */
237  if (child_length > (size_t) (end - p)) {
238  FR_PROTO_TRACE("fr_struct_from_network - child length %zd overflows buffer", child_length);
239  goto unknown;
240  }
241 
242  /*
243  * The child is variable sized, OR it's an array.
244  * Eat up the rest of the data.
245  */
246  if (!child_length || (child->flags.array)) {
247  child_length = (end - p);
248 
249  } else if ((size_t) (end - p) < child_length) {
250  goto unknown;
251  }
252 
253  /*
254  * Magic values get the callback called.
255  *
256  * @todo - if this is an array of DNS labels, we
257  * need to do decompression checks on the entire
258  * block, and then decode each field
259  * individually.
260  */
261  if (decode_value) {
262  if (child->flags.array) {
263  slen = fr_pair_array_from_network(child_ctx, child_list, child, p, child_length, decode_ctx, decode_value);
264  } else {
265  slen = decode_value(child_ctx, child_list, child, p, child_length, decode_ctx);
266  }
267  if (slen < 0) {
268  FR_PROTO_TRACE("Failed decoding value");
269  goto unknown;
270  }
271 
272  p += slen; /* not always the same as child->flags.length */
273  child_num++; /* go to the next child */
274  if (fr_dict_attr_is_key_field(child)) key_vp = fr_pair_list_tail(child_list);
275  continue;
276  }
277 
278  /*
279  * We only allow a limited number of data types
280  * inside of a struct.
281  */
282  switch (child->type) {
283  default:
284  FR_PROTO_TRACE("fr_struct_from_network - unknown child type");
285  goto unknown;
286 
287  case FR_TYPE_LEAF:
288  break;
289  }
290 
291  /*
292  * We don't handle this yet here.
293  */
294  fr_assert(!child->flags.array);
295 
296  vp = fr_pair_afrom_da(child_ctx, child);
297  if (!vp) {
298  FR_PROTO_TRACE("fr_struct_from_network - failed allocating child VP");
299  goto unknown;
300  }
301 
302  /*
303  * No protocol-specific data types here (yet).
304  *
305  * If we can't decode this field, then the entire
306  * structure is treated as a raw blob.
307  */
308  if (fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
309  &FR_DBUFF_TMP(p, child_length), child_length, true) < 0) {
310  FR_PROTO_TRACE("fr_struct_from_network - failed decoding child VP %s", vp->da->name);
311  talloc_free(vp);
312  unknown:
313  if (nested) {
314  TALLOC_FREE(struct_vp);
315  } else {
316  fr_pair_list_free(child_list);
317  }
318 
319  slen = fr_pair_raw_from_network(ctx, out, parent, data, data_len);
320  if (slen < 0) return slen;
321  return data_len;
322  }
323 
324  vp->vp_tainted = true;
325  fr_pair_append(child_list, vp);
326 
327  if (fr_dict_attr_is_key_field(vp->da)) key_vp = vp;
328 
329  /*
330  * Note that we're decoding fixed fields here.
331  * So we skip the input based on the *known*
332  * length, and not on the *decoded* length.
333  */
334  p += child_length;
335  child_num++; /* go to the next child */
336  }
337 
338  /*
339  * Is there a substructure after this one? If so, go
340  * decode it.
341  */
342  if (key_vp) {
343  fr_dict_enum_value_t const *enumv;
344  child = NULL;
345 
346  FR_PROTO_HEX_DUMP(p, (end - p), "fr_struct_from_network - substruct");
347 
348  /*
349  * Nothing more to decode, don't decode it.
350  */
351  if (p >= end) {
352  FR_PROTO_TRACE("Expected substruct, but there is none. We're done decoding this structure");
353  goto done;
354  }
355 
356  enumv = fr_dict_enum_by_value(key_vp->da, &key_vp->data);
357  if (enumv) child = enumv->child_struct[0];
358 
359  if (!child) {
360  unknown_child:
361  /*
362  * Always encode the unknown child as
363  * attribute number 0. Since the unknown
364  * children have no "real" number, and
365  * are all unique da's, they are
366  * incomparable. And thus can all be
367  * given the same number.
368  */
369  child = fr_dict_unknown_attr_afrom_num(child_ctx, key_vp->da, 0);
370  if (!child) {
371  FR_PROTO_TRACE("failed allocating unknown child for key VP %s", key_vp->da->name);
372  goto unknown;
373  }
374 
375  slen = fr_pair_raw_from_network(child_ctx, child_list, child, p, end - p);
376  if (slen < 0) {
377  FR_PROTO_TRACE("Failed creating raw VP from malformed or unknown substruct for child %s", child->name);
378  fr_dict_unknown_free(&child);
379  return slen;
380  }
381 
382  p = end;
383  } else {
384  fr_assert(child->type == FR_TYPE_STRUCT);
385 
386  slen = fr_struct_from_network(child_ctx, child_list, child, p, end - p, nested,
387  decode_ctx, decode_value, decode_tlv);
388  if (slen <= 0) {
389  FR_PROTO_TRACE("substruct %s decoding failed", child->name);
390  goto unknown_child;
391  }
392  p += slen;
393  }
394 
395  fr_dict_unknown_free(&child);
396  }
397 
398 done:
399  if (!nested) {
400  fr_pair_list_append(out, child_list); /* Wind to the end of the new pairs */
401  } else {
402  fr_assert(struct_vp != NULL);
403  fr_pair_append(out, struct_vp);
404  }
405 
406  FR_PROTO_TRACE("used %zd bytes", data_len);
407  return p - data;
408 }
409 
410 
411 /** Put bits into an output dbuff
412  *
413  * @param dbuff where the bytes go
414  * @param p where leftover bits go
415  * @param start_bit start bit in the dbuff where the data goes, 0..7
416  * @param num_bits number of bits to write to the output, 0..55
417  * @param data data to write, all in the lower "num_bits" of the uint64_t variable
418  * @return
419  * >= 0 the next value to pass in for start_bit
420  * < 0 no space or invalid start_bit or num_bits parameter
421  */
422 static int put_bits_dbuff(fr_dbuff_t *dbuff, uint8_t *p, int start_bit, uint8_t num_bits, uint64_t data)
423 {
424  uint64_t used_bits;
425 
426  if (start_bit < 0 || start_bit > 7) return -1;
427  if (num_bits < 1 || num_bits > 56) return -1;
428 
429  /* Get bits buffered in *p */
430  used_bits = *p & (-256 >> start_bit);
431 
432  /* Mask out all but the least significant num_bits bits of data */
433  data &= (((uint64_t) 1) << num_bits) - 1;
434 
435  /* Move it towards the most significant end and put used_bits at the top */
436  data <<= (64 - (start_bit + num_bits));
437  data |= used_bits << 56;
438 
439  data = htonll(data);
440 
441  start_bit += num_bits;
442  if (start_bit > 7) FR_DBUFF_IN_MEMCPY_RETURN(dbuff, (uint8_t const *) &data, (size_t)(start_bit / 8));
443 
444  *p = ((uint8_t *) &data)[start_bit / 8];
445  return start_bit % 8;
446 }
447 
448 static int8_t pair_sort_increasing(void const *a, void const *b)
449 {
450  fr_pair_t const *my_a = a;
451  fr_pair_t const *my_b = b;
452  int rcode;
453 
454  /*
455  * Deeper attributes come later in the list.
456  */
457  rcode = CMP_PREFER_SMALLER(my_a->da->depth, my_b->da->depth);
458  if (rcode != 0) return rcode;
459 
460  return CMP_PREFER_SMALLER(my_a->da->attr, my_b->da->attr);
461 }
462 
463 static void *struct_next_encodable(fr_dlist_head_t *list, void *current, void *uctx)
464 {
465  fr_pair_t *c = current;
466  fr_dict_attr_t *parent = talloc_get_type_abort(uctx, fr_dict_attr_t);
467 
468  while ((c = fr_dlist_next(list, c))) {
469  PAIR_VERIFY(c);
470 
471  if (c->da->dict != parent->dict || c->da->flags.internal) continue;
472  break;
473  }
474 
475  return c;
476 }
477 
479  fr_da_stack_t *da_stack, unsigned int depth,
480  fr_dcursor_t *parent_cursor, void *encode_ctx,
482 {
483  fr_dbuff_t work_dbuff;
484  fr_dbuff_marker_t hdr;
485  int offset = 0;
486  unsigned int child_num = 1;
487  bool do_length = false;
488  uint8_t bit_buffer = 0;
489  fr_pair_t const *vp = fr_dcursor_current(parent_cursor);
490  fr_dict_attr_t const *key_da, *parent, *tlv = NULL;
491  fr_dcursor_t child_cursor, *cursor;
492 
493  if (!vp) {
494  fr_strerror_printf("%s: Can't encode empty struct", __FUNCTION__);
496  }
497 
498  PAIR_VERIFY(vp);
499  parent = da_stack->da[depth];
500 
501  if (parent->type != FR_TYPE_STRUCT) {
502  fr_strerror_printf("%s: Expected type \"struct\" got \"%s\"", __FUNCTION__,
503  fr_type_to_str(parent->type));
505  }
506 
507  /*
508  * If we get passed a struct VP, sort its children.
509  */
510  if (vp->vp_type == FR_TYPE_STRUCT) {
511  fr_pair_t *sorted = fr_dcursor_current(parent_cursor); /* NOT const */
512 
513  fr_pair_list_sort(&sorted->vp_group, pair_sort_increasing);
514  fr_pair_dcursor_iter_init(&child_cursor, &sorted->vp_group, struct_next_encodable, parent);
515 
516  /*
517  * Build the da_stack for the new structure.
518  */
519  vp = fr_dcursor_current(&child_cursor);
520  fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
521 
522  FR_PROTO_TRACE("fr_struct_to_network encoding nested with parent %s", parent->name);
523  cursor = &child_cursor;
524  } else {
525  FR_PROTO_TRACE("fr_struct_to_network encoding flat");
526  cursor = parent_cursor;
527  }
528 
529  /*
530  * @todo - if we get a child which *eventually* has the
531  * given parent, then allow encoding of that struct, too.
532  * This allows us to encode structures automatically,
533  * even if key fields are omitted.
534  *
535  * Note that this check catches TLVs which are "flat" and
536  * not nested. We could fix that by adding a special
537  * case, but it's better to just fix everything to handle
538  * nested attributes.
539  */
540  if (vp && (vp->da->parent != parent)) {
541  fr_strerror_printf("%s: Asked to encode %s, but its parent %s is not the expected parent %s",
542  __FUNCTION__, vp->da->name, vp->da->parent->name, parent->name);
544  }
545 
546  key_da = NULL;
547 
548  /*
549  * Some structs are prefixed by a 16-bit length.
550  */
551  if (!da_is_length_field(parent)) {
552  work_dbuff = FR_DBUFF(dbuff);
553  } else {
554  if (parent->flags.subtype == FLAG_LENGTH_UINT8) {
555  work_dbuff = FR_DBUFF_MAX(dbuff, 256);
556  fr_dbuff_marker(&hdr, &work_dbuff);
557 
558  FR_DBUFF_ADVANCE_RETURN(&work_dbuff, 1);
559  } else {
560  work_dbuff = FR_DBUFF_MAX(dbuff, 65536);
561  fr_dbuff_marker(&hdr, &work_dbuff);
562 
563  FR_DBUFF_ADVANCE_RETURN(&work_dbuff, 2);
564  }
565  do_length = true;
566  }
567 
568  for (;;) {
569  fr_dict_attr_t const *child;
570 
571  /*
572  * The child attributes should be in order. If
573  * they're not, we fill the struct with zeroes.
574  *
575  * The caller will encode TLVs.
576  */
577  child = fr_dict_attr_child_by_num(parent, child_num);
578  if (!child) break;
579 
580  FR_PROTO_TRACE("fr_struct_to_network child %s", child->name);
581 
582  /*
583  * Encode child TLVs at the end of a struct.
584  *
585  * In order to encode the child TLVs, we need to
586  * know the length of "T" and "L", and we don't.
587  * So just let the caller do the work.
588  */
589  if (child->type == FR_TYPE_TLV) {
590  if (offset != 0) goto leftover_bits;
591 
592  fr_assert(!key_da);
593 
594  tlv = child;
595  goto done;
596  }
597 
598  /*
599  * The MEMBER may be raw, in which case it is encoded as octets.
600  *
601  * This can happen for the last MEMBER of a struct, such as when the last member is a TLV
602  * or GROUP, and the contents are malformed.
603  *
604  * It can also happen if a middle MEMBER has the right length, but the wrong contents.
605  * e.g. when the contents have to be a well-formed IP prefix, but the prefix values are
606  * out of the permitted range.
607  */
608  if (vp && (vp->da != child) && (vp->da->parent == parent) && (vp->da->attr == child_num)) {
609  fr_assert(vp->vp_raw);
610  fr_assert(vp->vp_type == FR_TYPE_OCTETS);
611  fr_assert(!da_is_bit_field(child));
612 
613  goto raw;
614  }
615 
616  /*
617  * Skipped a VP, or left one off at the end, fill the struct with zeros.
618  */
619  if (!vp || (vp->da != child)) {
620  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), " no child %s", child->name);
621 
622  /*
623  * Zero out the bit field.
624  */
625  if (da_is_bit_field(child)) {
626  offset = put_bits_dbuff(&work_dbuff, &bit_buffer, offset, child->flags.length, 0);
627  if (offset < 0) {
628  fr_strerror_printf("Failed encoding bit field %s", child->name);
629  return offset;
630  }
631  child_num++;
632  continue;
633  }
634 
635  if (fr_dict_attr_is_key_field(child)) {
636  key_da = child;
637  }
638 
639  /*
640  * Zero out the unused field.
641  */
642  FR_DBUFF_MEMSET_RETURN(&work_dbuff, 0, child->flags.length);
643  child_num++;
644  continue;
645  }
646 
647  /*
648  * The 'struct' encoder handles bit fields.
649  * They're just integers, so there's no need to
650  * call the protocol encoder.
651  *
652  * This limitation means that we can't have
653  * encrypted bit fields, but that's fine.
654  */
655  if (da_is_bit_field(child)) {
656  uint64_t value;
657 
658  switch (child->type) {
659  case FR_TYPE_BOOL:
660  value = vp->vp_bool;
661  break;
662 
663  case FR_TYPE_UINT8:
664  value = vp->vp_uint8;
665  break;
666 
667  case FR_TYPE_UINT16:
668  value = vp->vp_uint16;
669  break;
670 
671  case FR_TYPE_UINT32:
672  value = vp->vp_uint32;
673  break;
674 
675  case FR_TYPE_UINT64:
676  value = vp->vp_uint64;
677  break;
678 
679  default:
680  fr_strerror_const("Invalid bit field");
682  }
683 
684  offset = put_bits_dbuff(&work_dbuff, &bit_buffer, offset, child->flags.length, value);
685  if (offset < 0) {
686  fr_strerror_printf("Failed encoding bit field %s", child->name);
687  return offset;
688  }
689 
690  vp = fr_dcursor_next(cursor);
691  /* We need to continue, there may be more fields to encode */
692 
693  goto next;
694  }
695 
696  /* Not a bit field; insist that no buffered bits remain. */
697  if (offset != 0) {
698  leftover_bits:
699  fr_strerror_const("leftover bits");
701  }
702 
703  /*
704  * Remember key_da before we do any encoding.
705  */
706  if (fr_dict_attr_is_key_field(child)) {
707  key_da = child;
708  }
709 
710  if (encode_value) {
711  ssize_t len;
712  /*
713  * Call the protocol encoder for non-bit fields.
714  */
715  fr_proto_da_stack_build(da_stack, child);
716 
717  if (child->flags.array) {
718  len = fr_pair_array_to_network(&work_dbuff, da_stack, depth + 1, cursor, encode_ctx, encode_value);
719  } else {
720  len = encode_value(&work_dbuff, da_stack, depth + 1, cursor, encode_ctx);
721  }
722  if (len < 0) return len;
723  vp = fr_dcursor_current(cursor);
724 
725  } else {
726  redo:
727  /*
728  * Hack until we find all places that don't set data.enumv
729  */
730  if (vp->da->flags.length && (vp->data.enumv != vp->da)) {
731  fr_dict_attr_t const * const *c = &vp->data.enumv;
732  fr_dict_attr_t **u;
733 
734  memcpy(&u, &c, sizeof(c)); /* const issues */
735  memcpy(u, &vp->da, sizeof(vp->da));
736  }
737 
738  /*
739  * Determine the nested type and call the appropriate encoder
740  */
741  raw:
742  if (fr_value_box_to_network(&work_dbuff, &vp->data) <= 0) return PAIR_ENCODE_FATAL_ERROR;
743 
744  vp = fr_dcursor_next(cursor);
745  if (!vp) break;
746 
747  if (child->flags.array && (vp->da == child)) goto redo;
748  }
749 
750  next:
751  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "fr_struct_to_network after child %s", child->name);
752  child_num++;
753  }
754 
755  /* Check for leftover bits */
756  if (offset != 0) goto leftover_bits;
757 
758  /*
759  * Check for keyed data to encode.
760  */
761  if (vp && key_da) {
762  FR_PROTO_TRACE("fr_struct_to_network encoding key %s", key_da->name);
763 
764  /*
765  * If our parent is a struct, AND its parent is
766  * the key_da, then we have a keyed struct for
767  * the child. Go encode it.
768  *
769  * This check is really for "nested" VPs.
770  */
771  if ((vp->da->parent == key_da) &&
772  (vp->vp_type == FR_TYPE_STRUCT)) {
773  ssize_t len;
774  fr_proto_da_stack_build(da_stack, vp->da);
775 
776  len = fr_struct_to_network(&work_dbuff, da_stack, depth + 2, /* note + 2 !!! */
777  cursor, encode_ctx, encode_value, encode_pair);
778  if (len < 0) return len;
779  goto done;
780  }
781 
782  /*
783  * If our parent is a struct, AND its parent is
784  * the key_da, then we have a keyed struct for
785  * the child. Go encode it.
786  *
787  * This check is really for "flat" VPs.
788  */
789  if ((vp->da->parent->parent == key_da) &&
790  (vp->da->parent->type == FR_TYPE_STRUCT)) {
791  ssize_t len;
792  fr_proto_da_stack_build(da_stack, vp->da->parent);
793 
794  len = fr_struct_to_network(&work_dbuff, da_stack, depth + 2, /* note + 2 !!! */
795  cursor, encode_ctx, encode_value, encode_pair);
796  if (len < 0) return len;
797  goto done;
798  }
799 
800  /*
801  * The next VP is likely octets and unknown.
802  */
803  if ((vp->da->parent == key_da) &&
804  (vp->vp_type != FR_TYPE_TLV)) {
805  if (fr_value_box_to_network(&work_dbuff, &vp->data) <= 0) return PAIR_ENCODE_FATAL_ERROR;
806  (void) fr_dcursor_next(cursor);
807  goto done;
808  }
809 
810  /*
811  * We have no idea what to do. Ignore it.
812  */
813  }
814 
815 done:
816  vp = fr_dcursor_current(cursor);
817  if (tlv && vp && (vp->da == tlv) && encode_pair) {
818  ssize_t slen;
819  fr_dcursor_t tlv_cursor;
820 
821  if (!encode_pair) {
822  fr_strerror_printf("Asked to encode child attribute %s, but we were not passed an encoding function",
823  tlv->name);
825  }
826 
828 
829  vp = fr_pair_dcursor_init(&tlv_cursor, &vp->vp_group);
830  if (vp) {
831  FR_PROTO_TRACE("fr_struct_to_network trailing TLVs of %s", tlv->name);
832  fr_proto_da_stack_build(da_stack, vp->da);
833  FR_PROTO_STACK_PRINT(da_stack, depth);
834 
835  slen = fr_pair_cursor_to_network(&work_dbuff, da_stack, depth + 1, &tlv_cursor, encode_ctx, encode_pair);
836  if (slen < 0) return slen;
837  }
838  }
839 
840  if (do_length) {
841  size_t length = fr_dbuff_used(&work_dbuff);
842 
843  if (parent->flags.subtype == FLAG_LENGTH_UINT8) {
844  length -= 1;
845 
846  length += da_length_offset(parent);
847 
848  if (length > UINT8_MAX) return PAIR_ENCODE_FATAL_ERROR;
849 
850  (void) fr_dbuff_in(&hdr, (uint8_t) length);
851  } else {
852  length -= 2;
853 
854  length += da_length_offset(parent);
855 
856  if (length > UINT16_MAX) return PAIR_ENCODE_FATAL_ERROR;
857 
858  (void) fr_dbuff_in(&hdr, (uint16_t) length);
859  }
860  }
861 
862  /*
863  * We've encoded the children, so tell the parent cursor
864  * that we've encoded the parent.
865  */
866  if (cursor != parent_cursor) (void) fr_dcursor_next(parent_cursor);
867 
868  FR_PROTO_HEX_DUMP(fr_dbuff_start(&work_dbuff), fr_dbuff_used(&work_dbuff), "Done fr_struct_to_network");
869 
870  return fr_dbuff_set(dbuff, &work_dbuff);
871 }
#define RCSID(id)
Definition: build.h:444
#define CMP_PREFER_SMALLER(_a, _b)
Evaluates to +1 for a > b, and -1 for a < b.
Definition: build.h:102
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition: dbuff.h:762
#define FR_DBUFF_ADVANCE_RETURN(_dbuff_or_marker, _len)
Advance the 'current' position in dbuff or marker by _len bytes returning if _len is out of range.
Definition: dbuff.h:1083
struct fr_dbuff_marker_s fr_dbuff_marker_t
A position marker associated with a dbuff.
Definition: dbuff.h:81
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition: dbuff.h:893
#define FR_DBUFF_MEMSET_RETURN(_dbuff_or_marker, _c, _inlen)
Set _inlen bytes of a dbuff or marker to _c returning if there is insufficient space.
Definition: dbuff.h:1503
#define FR_DBUFF_IN_MEMCPY_RETURN(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into dbuff or marker returning if there's insufficient space.
Definition: dbuff.h:1377
#define fr_dbuff_in(_dbuff_or_marker, _in)
Copy data from a fixed sized C type into a dbuff or marker.
Definition: dbuff.h:1562
#define FR_DBUFF(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
Definition: dbuff.h:222
#define FR_DBUFF_MAX(_dbuff_or_marker, _max)
Limit the maximum number of bytes available in the dbuff when passing it to another function.
Definition: dbuff.h:301
static uint8_t * fr_dbuff_marker(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff)
Initialises a new marker pointing to the 'current' position of the dbuff.
Definition: dbuff.h:1187
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:509
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition: dcursor.h:287
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
Definition: dcursor.h:336
ssize_t(* fr_pair_decode_value_t)(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
Decode a value from the network into an output fr_pair_list_t.
Definition: decode.h:45
void fr_dict_unknown_free(fr_dict_attr_t const **da)
Free dynamically allocated (unknown attributes)
Definition: dict_unknown.c:148
#define da_length_offset(_da)
Definition: dict.h:152
@ FLAG_LENGTH_UINT8
string / octets type is prefixed by uint8 of length
Definition: dict.h:145
fr_dict_enum_value_t * fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the structure representing an enum value in a fr_dict_attr_t.
Definition: dict_util.c:2946
#define da_is_bit_field(_da)
Definition: dict.h:150
#define da_is_length_field(_da)
Definition: dict.h:151
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition: dict_util.c:2925
#define fr_dict_attr_is_key_field(_da)
Definition: dict.h:149
fr_dict_attr_t * fr_dict_unknown_attr_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int num))
Initialise a fr_dict_attr_t from a number.
Definition: dict_unknown.c:345
fr_dict_attr_t const * child_struct[]
for key fields
Definition: dict.h:217
Value of an enumerated attribute.
Definition: dict.h:209
Test enumeration values.
Definition: dict_test.h:92
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Definition: dlist.h:555
Head of a doubly linked list.
Definition: dlist.h:51
ssize_t(* fr_encode_dbuff_t)(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx)
Typedefs for simplifying the use and declaration of protocol encoders.
Definition: encode.h:37
#define PAIR_DECODE_OOM
Fatal error - Out of memory.
Definition: pair.h:46
#define PAIR_ENCODE_FATAL_ERROR
Fatal encoding error.
Definition: pair.h:37
static ssize_t encode_value(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, int depth, fr_dcursor_t *cursor, void *encode_ctx)
Encodes the data portion of an attribute.
Definition: encode.c:272
ssize_t fr_pair_array_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx, fr_pair_decode_value_t decode_value)
Decode an array of values from the network.
Definition: decode.c:41
ssize_t fr_pair_raw_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len)
Create a "raw" pair from the network data.
Definition: decode.c:79
ssize_t fr_pair_array_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, int depth, fr_dcursor_t *cursor, void *encode_ctx, fr_encode_dbuff_t encode_value)
Encode an array of values from the network.
Definition: encode.c:42
ssize_t fr_pair_cursor_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, void *encode_ctx, fr_encode_dbuff_t encode_pair)
Definition: encode.c:71
talloc_free(reap)
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_UINT8
8 Bit unsigned integer.
Definition: merged_model.c:97
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
Definition: merged_model.c:119
@ FR_TYPE_UINT64
64 Bit unsigned integer.
Definition: merged_model.c:100
@ FR_TYPE_BOOL
A truth value.
Definition: merged_model.c:95
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
#define UINT8_MAX
Definition: merged_model.c:32
static size_t array[MY_ARRAY_SIZE]
static uint8_t depth(fr_minmax_heap_index_t i)
Definition: minmax_heap.c:83
static unsigned int fr_bytes_from_bits(unsigned int bits)
Convert bits (as in prefix length) to bytes, rounding up.
Definition: nbo.h:228
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition: pair.c:278
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition: pair.c:1340
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition: pair.c:46
void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da)
Build a complete DA stack from the da back to the root.
Definition: proto.c:118
static fr_internal_encode_ctx_t encode_ctx
#define decode_value
Definition: decode.c:410
static rc_request_t * current
Definition: radclient-ng.c:97
static bool done
Definition: radclient.c:80
fr_assert(0)
fr_pair_t * vp
static void * struct_next_encodable(fr_dlist_head_t *list, void *current, void *uctx)
Definition: struct.c:463
ssize_t fr_struct_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *parent_cursor, void *encode_ctx, fr_encode_dbuff_t encode_value, fr_encode_dbuff_t encode_pair)
Definition: struct.c:478
static int8_t pair_sort_increasing(void const *a, void const *b)
Definition: struct.c:448
static int put_bits_dbuff(fr_dbuff_t *dbuff, uint8_t *p, int start_bit, uint8_t num_bits, uint64_t data)
Put bits into an output dbuff.
Definition: struct.c:422
ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, bool nested, void *decode_ctx, fr_pair_decode_value_t decode_value, fr_pair_decode_value_t decode_tlv)
Convert a STRUCT to one or more VPs.
Definition: struct.c:33
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition: pair.h:69
#define fr_pair_dcursor_iter_init(_cursor, _list, _iter, _uctx)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition: pair.h:568
fr_pair_t * fr_pair_list_tail(fr_pair_list_t const *list)
Get the tail of a valuepair list.
Definition: pair_inline.c:56
#define PAIR_VERIFY(_x)
Definition: pair.h:190
void fr_pair_list_sort(fr_pair_list_t *list, fr_cmp_t cmp)
Sort a doubly linked list of fr_pair_ts using merge sort.
Definition: pair_inline.c:140
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
Definition: pair_inline.c:113
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
Definition: pair_inline.c:182
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition: pair.h:590
static fr_slen_t parent
Definition: pair.h:844
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition: proto.h:41
#define FR_PROTO_TRACE(_fmt,...)
Definition: proto.h:40
#define FR_PROTO_STACK_PRINT(_stack, _depth)
Definition: proto.h:43
fr_dict_attr_t const * da[FR_DICT_MAX_TLV_STACK+1]
The stack.
Definition: proto.h:56
Structure for holding the stack of dictionary attributes being encoded.
Definition: proto.h:54
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition: types.h:433
#define fr_type_is_structural(_x)
Definition: types.h:371
#define FR_TYPE_LEAF
Definition: types.h:297
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Decode a fr_value_box_t from serialized binary data.
Definition: value.c:1709
return fr_dbuff_set(dbuff, &our_dbuff)
ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
Encode a single value box, serializing its contents in generic network format.
Definition: value.c:1359
static fr_slen_t data
Definition: value.h:1259
static size_t char ** out
Definition: value.h:984