Coverage Report

Created: 2024-08-28 06:17

/src/freeradius-server/src/lib/util/dict_validate.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *   This program is free software; you can redistribute it and/or modify
3
 *   it under the terms of the GNU General Public License as published by
4
 *   the Free Software Foundation; either version 2 of the License, or
5
 *   (at your option) any later version.
6
 *
7
 *   This program is distributed in the hope that it will be useful,
8
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 *   GNU General Public License for more details.
11
 *
12
 *   You should have received a copy of the GNU General Public License
13
 *   along with this program; if not, write to the Free Software
14
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15
 */
16
17
/** Validation framework to allow protocols to set custom validation rules
18
 *
19
 * @file src/lib/util/dict_validate.c
20
 *
21
 * @copyright 2019 The FreeRADIUS server project
22
 */
23
RCSID("$Id: 312858ec7b631038798ee2c34ca4ced2a0ad3465 $")
24
25
#include <freeradius-devel/util/dict_priv.h>
26
27
/** Validate a set of flags
28
 *
29
 * @param[in] dict    of protocol context we're operating in.
30
 *        If NULL the internal dictionary will be used.
31
 * @param[in] parent    to add attribute under.
32
 * @param[in] name    of the attribute.
33
 * @param[in] attr    number.
34
 * @param[in] type    of attribute.
35
 * @param[in] flags   to check in the attribute.
36
 * @return
37
 *  - true if attribute definition is valid.
38
 *  - false if attribute definition is not valid.
39
 */
40
bool dict_attr_flags_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
41
         char const *name, int *attr, fr_type_t type, fr_dict_attr_flags_t *flags)
42
80.8k
{
43
80.8k
  int bit;
44
80.8k
  uint32_t all_flags;
45
80.8k
  uint32_t shift_is_root, shift_internal;
46
80.8k
  uint32_t shift_array, shift_has_value;
47
80.8k
  uint32_t shift_subtype, shift_extra;
48
80.8k
  uint32_t shift_counter;
49
80.8k
  fr_dict_attr_t const *v;
50
51
  /*
52
   *  Convert the 1-bit fields into bits numbers, so that we
53
   *  can check them in parallel.
54
   */
55
80.8k
  all_flags = 0;
56
80.8k
  bit = -1;
57
58
566k
#define SET_FLAG(_flag) do { shift_ ## _flag = 1 << ++bit; if (flags->_flag) all_flags |= (1 << bit); } while (0)
59
80.8k
  SET_FLAG(is_root);
60
80.8k
  SET_FLAG(internal);
61
80.8k
  SET_FLAG(array);
62
80.8k
  SET_FLAG(has_value);
63
80.8k
  SET_FLAG(extra);
64
80.8k
  SET_FLAG(counter);
65
80.8k
  SET_FLAG(subtype);
66
67
80.8k
#define FORBID_OTHER_FLAGS(_flag) do { if (all_flags & ~shift_ ## _flag) { fr_strerror_printf("The '" STRINGIFY(_flag) "' flag cannot be used with any other flag"); return false; } } while (0)
68
80.8k
#define ALLOW_FLAG(_flag) do { all_flags &= ~shift_ ## _flag; } while (0)
69
70
  // is_root
71
  // is_unknown
72
  // internal
73
  // array
74
  // has_value
75
  // extra
76
  // encrypt
77
  // length
78
  // type_size
79
80
80.8k
  if (flags->is_root) {
81
0
    FORBID_OTHER_FLAGS(is_root);
82
0
  }
83
84
80.8k
  if (flags->is_unknown) {
85
0
    fr_strerror_const("The 'unknown' flag cannot be set for attributes in the dictionary.");
86
0
    return false;
87
0
  }
88
89
  /*
90
   *  Only some data types can be in arrays, because we need
91
   *  to be able to decode the various array members.
92
   */
93
80.8k
  if (flags->array) {
94
452
    if (!flags->is_known_width) switch (type) {
95
0
    default:
96
0
      fr_strerror_printf("The 'array' flag cannot be used with attributes of type '%s'",
97
0
             fr_type_to_str(type));
98
0
      return false;
99
100
240
    case FR_TYPE_IPV4_ADDR:
101
246
    case FR_TYPE_IPV4_PREFIX:
102
308
    case FR_TYPE_IPV6_ADDR:
103
308
    case FR_TYPE_IPV6_PREFIX:
104
314
    case FR_TYPE_UINT8:
105
348
    case FR_TYPE_UINT16:
106
348
    case FR_TYPE_UINT32:
107
348
    case FR_TYPE_DATE:
108
348
    case FR_TYPE_TIME_DELTA:
109
348
      break;
110
111
0
    case FR_TYPE_STRING:
112
0
    case FR_TYPE_OCTETS:
113
0
      if (!flags->length) {
114
0
        fr_strerror_const("Variable length attributes cannot be marked as 'array'");
115
0
        return false;
116
0
      }
117
118
0
      flags->is_known_width = 1;
119
0
      break;
120
121
0
    case FR_TYPE_STRUCT:
122
      /*
123
       *  If we have arrays of structs, then the structure MUST be known width.
124
       */
125
0
      flags->is_known_width = 1;
126
0
      break;
127
348
    }
128
129
    /*
130
     *  DHCPv6 has arrays of string / octets, prefixed
131
     *  with a uint16 field of "length".  Also, arrays of dns_labels.
132
     */
133
452
    ALLOW_FLAG(extra);
134
452
    ALLOW_FLAG(subtype);
135
136
452
    FORBID_OTHER_FLAGS(array);
137
452
  }
138
139
  /*
140
   *  'has_value' should only be set internally.  If the
141
   *  caller sets it, we still sanity check it.
142
   */
143
80.8k
  if (flags->has_value) {
144
0
    if (type != FR_TYPE_UINT32) {
145
0
      fr_strerror_printf("The 'has_value' flag can only be used with attributes "
146
0
             "of type 'integer'");
147
0
      return false;
148
0
    }
149
150
0
    FORBID_OTHER_FLAGS(has_value);
151
0
  }
152
153
  /*
154
   *  The "extra" flag is a grab-bag of stuff, depending on
155
   *  the data type.
156
   */
157
80.8k
  if (flags->extra) {
158
824
    if ((flags->subtype != FLAG_KEY_FIELD) && (flags->subtype != FLAG_BIT_FIELD) &&
159
824
        (flags->subtype != FLAG_LENGTH_UINT8) && (flags->subtype != FLAG_LENGTH_UINT16)) {
160
0
      fr_strerror_const("The 'key' and 'length' flags cannot be used with any other flags.");
161
0
      return false;
162
0
    }
163
164
824
    switch (type) {
165
440
    case FR_TYPE_BOOL:
166
644
    case FR_TYPE_UINT8:
167
698
    case FR_TYPE_UINT16:
168
730
    case FR_TYPE_UINT32:
169
770
    case FR_TYPE_UINT64:
170
770
      if ((flags->subtype != FLAG_KEY_FIELD) && (flags->subtype != FLAG_BIT_FIELD)) {
171
0
        fr_strerror_const("Invalid type (not 'key' field or 'bit' field) for extra flag.");
172
0
        return false;
173
0
      }
174
175
770
      if (parent->type != FR_TYPE_STRUCT) {
176
0
        fr_strerror_const("The 'key' flag can only be used inside of a 'struct'.");
177
0
        return false;
178
0
      }
179
180
770
      ALLOW_FLAG(extra);
181
770
      ALLOW_FLAG(subtype);
182
770
      break;
183
184
8
    case FR_TYPE_OCTETS:
185
18
    case FR_TYPE_STRING:
186
18
      if (flags->length != 0) {
187
0
        fr_strerror_const("Cannot use [..] and length=uint...");
188
0
        return false;
189
0
      }
190
191
      /*
192
       *  We can do arrays of variable-length types, so long as they have a "length="
193
       *  modifier.
194
       *
195
       *  But any other modifier is foridden, including the use of "length=" outside of
196
       *  the context of arrays.
197
       */
198
18
      if (flags->array) {
199
18
        ALLOW_FLAG(array);
200
201
18
        if ((flags->subtype != FLAG_LENGTH_UINT8) && (flags->subtype != FLAG_LENGTH_UINT16)) goto invalid_extra;
202
18
      } else if (flags->subtype) {
203
0
      invalid_extra:
204
0
        fr_strerror_const("Invalid type (not 'length=...') for extra flag.");
205
0
        return false;
206
0
      }
207
208
18
      ALLOW_FLAG(extra);
209
18
      ALLOW_FLAG(subtype);
210
18
      break;
211
212
36
    case FR_TYPE_STRUCT:
213
36
      if ((flags->subtype != FLAG_LENGTH_UINT8) && (flags->subtype != FLAG_LENGTH_UINT16)) {
214
0
        fr_strerror_const("Invalid type (not 'length=...') for extra flag.");
215
0
        return false;
216
0
      }
217
218
36
      ALLOW_FLAG(extra);
219
36
      ALLOW_FLAG(subtype);
220
36
      ALLOW_FLAG(array);
221
36
      break;
222
223
0
    case FR_TYPE_TLV:
224
0
      ALLOW_FLAG(extra);
225
      /* @todo - allow arrays of struct? */
226
0
      ALLOW_FLAG(subtype);
227
0
      break;
228
229
0
    default:
230
0
      fr_strerror_printf("Type %s cannot hold extra flags",
231
0
             fr_type_to_str(type));
232
0
      return false;
233
824
    }
234
235
824
    if (((flags->subtype == FLAG_LENGTH_UINT8) || (flags->subtype == FLAG_LENGTH_UINT16)) &&
236
824
        ((type != FR_TYPE_STRING) && (type != FR_TYPE_OCTETS) && (type != FR_TYPE_STRUCT))) {
237
0
      fr_strerror_printf("The 'length' flag cannot be used used with type %s",
238
0
             fr_type_to_str(type));
239
0
      return false;
240
0
    }
241
242
824
    FORBID_OTHER_FLAGS(extra);
243
824
  }
244
245
  /*
246
   *  Force "length" for fixed-size data types which aren't
247
   *  bit fields.  Check / set "length" and "type_size" for
248
   *  other types.
249
   */
250
80.8k
  if (!flags->extra || (flags->subtype != FLAG_BIT_FIELD)) switch (type) {
251
1.92k
  case FR_TYPE_UINT8:
252
2.61k
  case FR_TYPE_BOOL:
253
2.61k
    flags->length = 1;
254
2.61k
    break;
255
256
1.33k
  case FR_TYPE_UINT16:
257
1.33k
    flags->length = 2;
258
1.33k
    break;
259
260
1.08k
  case FR_TYPE_DATE:
261
1.76k
  case FR_TYPE_TIME_DELTA:
262
1.76k
    if (!flags->length) flags->length = 4;
263
264
1.76k
    if ((flags->length != 2) && (flags->length != 4) && (flags->length != 8)) {
265
0
      fr_strerror_printf("Invalid length %u for attribute of type '%s'",
266
0
             flags->length, fr_type_to_str(type));
267
0
      return false;
268
0
    }
269
1.76k
    break;
270
271
3.53k
  case FR_TYPE_IPV4_ADDR:
272
28.9k
  case FR_TYPE_UINT32:
273
29.3k
  case FR_TYPE_INT32:
274
29.7k
  case FR_TYPE_FLOAT32:
275
29.7k
    flags->length = 4;
276
29.7k
    break;
277
278
1.28k
  case FR_TYPE_UINT64:
279
1.28k
  case FR_TYPE_FLOAT64:
280
1.28k
    flags->length = 8;
281
1.28k
    break;
282
283
0
  case FR_TYPE_SIZE:
284
0
    flags->length = sizeof(size_t);
285
0
    break;
286
287
432
  case FR_TYPE_ETHERNET:
288
432
    flags->length = 6;
289
432
    break;
290
291
72
  case FR_TYPE_IFID:
292
72
    flags->length = 8;
293
72
    break;
294
295
786
  case FR_TYPE_IPV6_ADDR:
296
906
  case FR_TYPE_COMBO_IP_ADDR:
297
906
    flags->length = 16;
298
906
    break;
299
300
188
  case FR_TYPE_IPV6_PREFIX:
301
188
  case FR_TYPE_COMBO_IP_PREFIX:
302
188
    flags->length = 17;
303
188
    break;
304
305
1.25k
  case FR_TYPE_STRUCT:
306
1.25k
    ALLOW_FLAG(internal);
307
1.25k
    ALLOW_FLAG(array);
308
1.25k
    if (all_flags) {
309
0
      fr_strerror_const("Invalid flag for attribute of type 'struct'");
310
0
      return false;
311
0
    }
312
1.25k
    break;
313
314
4.29k
  case FR_TYPE_VENDOR:
315
4.29k
    if (parent->type != FR_TYPE_VSA) {
316
0
      fr_strerror_printf("Attributes of type 'vendor' MUST have a parent of type 'vsa' "
317
0
             "instead of '%s'",
318
0
             fr_type_to_str(parent->type));
319
0
      return false;
320
0
    }
321
322
4.29k
    if (flags->length) {
323
0
      if ((flags->length != 1) &&
324
0
          (flags->length != 2) &&
325
0
          (flags->length != 4)) {
326
0
        fr_strerror_const("The 'length' flag can only be used for attributes of type 'vendor' with lengths of 1,2 or 4");
327
0
        return false;
328
0
      }
329
330
0
      break;
331
0
    }
332
333
    /*
334
     *  Set the length / type_size of vendor
335
     *  attributes from the vendor definition.
336
     */
337
4.29k
    flags->type_size = 1;
338
4.29k
    flags->length = 1;
339
4.29k
    if (attr) {
340
4.29k
      fr_dict_vendor_t const *dv;
341
342
4.29k
      dv = fr_dict_vendor_by_num(dict, *attr);
343
4.29k
      if (dv) {
344
4.29k
        flags->type_size = dv->type;
345
4.29k
        flags->length = dv->length;
346
4.29k
      }
347
4.29k
    }
348
4.29k
    break;
349
350
994
  case FR_TYPE_TLV:
351
994
    if (flags->length) {
352
466
      if ((flags->length != 1) &&
353
466
          (flags->length != 2) &&
354
466
          (flags->length != 4)) {
355
0
        fr_strerror_const("The 'length' flag can only be used for attributes of type 'tlv' with lengths of 1,2 or 4");
356
0
        return false;
357
0
      }
358
359
466
      break;
360
466
    }
361
362
    /*
363
     *  Find an appropriate parent to copy the
364
     *  TLV-specific fields from.
365
     */
366
540
    for (v = parent; v != NULL; v = v->parent) {
367
540
      if ((v->type == FR_TYPE_TLV) || (v->type == FR_TYPE_VENDOR)) {
368
528
        break;
369
528
      }
370
540
    }
371
372
    /*
373
     *  root is always FR_TYPE_TLV, so we're OK.
374
     */
375
528
    if (!v) {
376
0
      fr_strerror_printf("Attributes of type '%s' require a parent attribute",
377
0
             fr_type_to_str(type));
378
0
      return false;
379
0
    }
380
381
    /*
382
     *  Over-ride whatever was there before, so we
383
     *  don't have multiple formats of VSAs.
384
     */
385
528
    flags->type_size = v->flags.type_size;
386
528
    flags->length = v->flags.length;
387
528
    break;
388
389
    /*
390
     *  'octets[n]' can only be used in a few limited situations.
391
     */
392
6.53k
  case FR_TYPE_OCTETS:
393
6.53k
    if (flags->length) {
394
      /*
395
       *  Internal attributes can use octets[n]
396
       *  MS-MPPE-Keys use octets[18],encrypt=1
397
       *  EAP-SIM-RAND uses array
398
       */
399
430
      ALLOW_FLAG(internal);
400
430
      ALLOW_FLAG(subtype);
401
430
      ALLOW_FLAG(array);
402
403
430
      if (all_flags) {
404
0
        fr_strerror_const("The 'octets[...]' syntax cannot be used any other flag");
405
0
        return false;
406
0
      }
407
408
430
      if (flags->length > 253) {
409
0
        fr_strerror_printf("Invalid length %d", flags->length);
410
0
        return false;
411
0
      }
412
430
    }
413
6.53k
    break;
414
415
6.53k
  case FR_TYPE_NULL:
416
0
    fr_strerror_printf("Attributes of type '%s' cannot be used in dictionaries",
417
0
           fr_type_to_str(type));
418
0
    return false;
419
420
28.7k
  default:
421
28.7k
    break;
422
80.1k
  }
423
424
  /*
425
   *  type_size is used to limit the maximum attribute number, so it's checked first.
426
   */
427
80.8k
  if (flags->type_size) {
428
6.12k
    if ((type == FR_TYPE_DATE) || (type == FR_TYPE_TIME_DELTA)) {
429
      /*
430
       *  Allow all time res here
431
       */
432
5.93k
    } else if (!flags->extra) {
433
5.28k
      if ((type != FR_TYPE_TLV) && (type != FR_TYPE_VENDOR)) {
434
0
        fr_strerror_const("The 'format=' flag can only be used with attributes of type 'tlv'");
435
0
        return false;
436
0
      }
437
438
5.28k
      if ((flags->type_size != 1) &&
439
5.28k
          (flags->type_size != 2) &&
440
5.28k
          (flags->type_size != 4)) {
441
0
        fr_strerror_const("The 'format=' flag can only be used with attributes of type size 1,2 or 4");
442
0
        return false;
443
0
      }
444
5.28k
    }
445
6.12k
  }
446
447
  /*
448
   *  Counters can be time deltas, or unsigned integers.
449
   *  For other data types, we don't know how to
450
   *  automatically add two counters.
451
   */
452
80.8k
  if (flags->counter) {
453
0
    if ((type == FR_TYPE_TIME_DELTA) || (fr_type_is_integer(type) && !fr_type_is_signed(type))) {
454
0
      ALLOW_FLAG(counter);
455
0
    } else {
456
0
      fr_strerror_printf("The 'counter' flag cannot be used with '%s'", fr_type_to_str(type));
457
0
      return false;
458
0
    }
459
0
  }
460
461
  /*
462
   *  Check flags against the parent attribute.
463
   */
464
80.8k
  switch (parent->type) {
465
3.91k
  case FR_TYPE_STRUCT:
466
3.91k
    ALLOW_FLAG(extra);
467
3.91k
    ALLOW_FLAG(subtype);
468
469
3.91k
    if (parent->flags.is_known_width && !flags->is_known_width && !flags->length) {
470
0
      fr_strerror_const("Variable-sized fields cannot be used within a 'struct' which is 'array'");
471
0
      return false;
472
0
    }
473
474
3.91k
    if (flags->array) {
475
38
      switch (type) {
476
18
      case FR_TYPE_FIXED_SIZE:
477
18
        ALLOW_FLAG(array);
478
18
        break;
479
480
20
      default:
481
20
        if (flags->is_known_width) ALLOW_FLAG(array);
482
20
        break;
483
38
      }
484
38
    }
485
486
3.91k
    if (all_flags) {
487
0
      fr_strerror_const("Invalid flag for attribute inside of a 'struct'");
488
0
      return false;
489
0
    }
490
491
3.91k
    if (!attr) break;
492
493
    /*
494
     *  If we have keyed structs, then the first
495
     *  member can be variable length.
496
     *
497
     *  For subsequent children, have each one check
498
     *  the previous child.
499
     */
500
2.01k
    if (*attr != 1) {
501
1.25k
      int i;
502
1.25k
      fr_dict_attr_t const *sibling;
503
504
1.25k
      sibling = fr_dict_attr_child_by_num(parent, (*attr) - 1);
505
1.25k
      if (!sibling) {
506
0
        fr_strerror_printf("Child \"%s\" of 'struct' attribute \"%s\" MUST be "
507
0
               "numbered consecutively %u.",
508
0
               name, parent->name, *attr);
509
0
        return false;
510
0
      }
511
512
      /*
513
       *  Variable sized elements cannot have anything after them in a struct.
514
       */
515
1.25k
      if (!sibling->flags.length && !sibling->flags.is_known_width) {
516
0
        fr_strerror_const("No other field can follow a struct MEMBER which is variable sized");
517
0
        return false;
518
0
      }
519
520
      /*
521
       *  The same goes for arrays.
522
       */
523
1.25k
      if (sibling->flags.array) {
524
0
        fr_strerror_const("No other field can follow a struct MEMBER which is 'array'");
525
0
        return false;
526
0
      }
527
528
      /*
529
       *  Check for bad key fields, or multiple
530
       *  key fields.  Yes, this is O(N^2), but
531
       *  the structs are small.
532
       */
533
1.25k
      if (flags->extra && (flags->subtype == FLAG_KEY_FIELD)) {
534
50
        for (i = 1; i < *attr; i++) {
535
40
          sibling = fr_dict_attr_child_by_num(parent, i);
536
40
          if (!sibling) {
537
0
            fr_strerror_printf("Child %d of 'struct' type attribute %s does not exist.",
538
0
                   i, parent->name);
539
0
            return false;
540
0
          }
541
542
40
          if (!fr_dict_attr_is_key_field(sibling)) continue;
543
544
0
          fr_strerror_printf("Duplicate key attributes '%s' and '%s' in 'struct' type attribute %s are forbidden",
545
0
                 name, sibling->name, parent->name);
546
0
          return false;
547
40
        }
548
10
      }
549
1.25k
    }
550
2.01k
    break;
551
552
4.29k
  case FR_TYPE_VSA:
553
4.29k
    if ((type != FR_TYPE_VENDOR) && !flags->internal) {
554
0
      fr_strerror_printf("Attributes of type '%s' cannot be children of the 'vsa' type",
555
0
             fr_type_to_str(type));
556
0
      return false;
557
0
    }
558
4.29k
    break;
559
560
21.2k
  case FR_TYPE_TLV:
561
72.4k
  case FR_TYPE_VENDOR:
562
72.4k
    break;
563
564
    /*
565
     *  "key" fields inside of a STRUCT can have
566
     *  children, even if they are integer data type.
567
     */
568
52
  case FR_TYPE_UINT8:
569
252
  case FR_TYPE_UINT16:
570
252
  case FR_TYPE_UINT32:
571
252
    if (fr_dict_attr_is_key_field(parent)) break;
572
252
    FALL_THROUGH;
573
574
0
  default:
575
0
    fr_strerror_printf("Attributes of type '%s' cannot have child attributes",
576
0
           fr_type_to_str(parent->type));
577
0
    return false;
578
80.8k
  }
579
580
80.8k
  return true;
581
80.8k
}
582
583
584
/** Validate a new attribute definition
585
 *
586
 * @todo we need to check length of none vendor attributes.
587
 *
588
 * @param[in] dict    of protocol context we're operating in.
589
 *        If NULL the internal dictionary will be used.
590
 * @param[in] parent    to add attribute under.
591
 * @param[in] name    of the attribute.
592
 * @param[in] attr    number.
593
 * @param[in] type    of attribute.
594
 * @param[in] flags   to set in the attribute.
595
 * @return
596
 *  - true if attribute definition is valid.
597
 *  - false if attribute definition is not valid.
598
 */
599
bool dict_attr_fields_valid(fr_dict_t *dict, fr_dict_attr_t const *parent,
600
          char const *name, int *attr, fr_type_t type, fr_dict_attr_flags_t *flags)
601
43.4k
{
602
43.4k
  fr_dict_attr_t const  *v;
603
43.4k
  fr_dict_attr_t *mutable;
604
605
43.4k
  if (!fr_cond_assert(parent)) return false;
606
607
43.4k
  if (fr_dict_valid_name(name, -1) <= 0) return false;
608
609
43.4k
  mutable = UNCONST(fr_dict_attr_t *, parent);
610
611
  /******************** sanity check attribute number ********************/
612
613
  /*
614
   *  The value -1 is the special flag for "self
615
   *  allocated" numbers.  i.e. we want an
616
   *  attribute, but we don't care what the number
617
   *  is.
618
   */
619
43.4k
  if (*attr == -1) {
620
    /*
621
     *  If we don't care about the number, then this attribute is almost always
622
     *  an internal one.  Unless it's a "name only" attribute for string-based
623
     *  protocols.
624
     *
625
     *  We can use DEFINE in number-based protocol dictionaries, and the attributes will be
626
     *  marked up as "internal".
627
     */
628
74
    flags->internal |= !flags->name_only | !dict->string_based;
629
630
74
    v = fr_dict_attr_by_name(NULL, parent, name);
631
74
    if (v) {
632
0
      fr_dict_attr_flags_t cmp;
633
634
      /*
635
       *  Exact duplicates are allowed.  The caller will take care of
636
       *  not inserting the duplicate attribute.
637
       */
638
0
      if (v->type != type) {
639
0
        fr_strerror_printf("Conflicting type (asked %s, found %s) for re-definition for attribute %s",
640
0
               fr_type_to_str(type), fr_type_to_str(v->type), name);
641
0
        return false;
642
0
      }
643
644
      /*
645
       *  'has_value' is set if we define VALUEs for it.  But the new definition doesn't
646
       *  know that yet.
647
       */
648
0
      cmp = v->flags;
649
0
      cmp.has_value = 0;
650
651
0
      if (memcmp(&cmp, flags, sizeof(*flags)) != 0) {
652
0
        fr_strerror_printf("Conflicting flags for re-definition for attribute %s", name);
653
0
        return false;
654
0
      }
655
656
0
      return true;
657
0
    }
658
659
74
    *attr = ++mutable->last_child_attr;
660
661
43.3k
  } else if (*attr < 0) {
662
0
    fr_strerror_printf("ATTRIBUTE number %i is invalid, must be greater than zero", *attr);
663
0
    return false;
664
665
43.3k
  } else if ((unsigned int) *attr > mutable->last_child_attr) {
666
0
    mutable->last_child_attr = *attr;
667
668
    /*
669
     *  If the attribute is outside of the bounds of
670
     *  the type size, then it MUST be an internal
671
     *  attribute.  Set the flag in this attribute, so
672
     *  that the encoder doesn't have to do complex
673
     *  checks.
674
     */
675
0
    if ((uint64_t) *attr >= (((uint64_t)1) << (8 * parent->flags.type_size))) flags->internal = true;
676
0
  }
677
678
  /*
679
   *  Initialize the length field, which is needed for the attr_valid() callback.
680
   */
681
43.4k
  if (!flags->length && fr_type_is_leaf(type) && !fr_type_is_variable_size(type)) {
682
770
    fr_value_box_t box;
683
684
770
    fr_value_box_init(&box, type, NULL, false);
685
770
    flags->length = fr_value_box_network_length(&box);
686
770
  }
687
688
43.4k
  if (type == FR_TYPE_STRUCT) flags->is_known_width |= flags->array;
689
690
  /*
691
   *  Run protocol-specific validation functions, BEFORE we
692
   *  do the rest of the checks.
693
   */
694
43.4k
  if (dict->attr_valid && !dict->attr_valid(dict, parent, name, *attr, type, flags)) return false;
695
696
  /*
697
   *  Check the flags, data types, and parent data types and flags.
698
   */
699
43.4k
  if (!dict_attr_flags_valid(dict, parent, name, attr, type, flags)) return false;
700
701
43.4k
  return true;
702
43.4k
}