]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Get vendor number by looking it up in the attribute hierarchy
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 23 Feb 2018 03:11:21 +0000 (09:11 +0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 23 Feb 2018 06:20:14 +0000 (12:20 +0600)
This is cleanup work that should have been done a while back.

Vendors are now represented in the dictionary hierarchy, so having a vendor field in attributes is superfluous.

44 files changed:
src/include/dict.h
src/lib/ldap/control.c
src/lib/util/dict.c
src/lib/util/pair.c
src/lib/util/pair_cursor.c
src/lib/util/proto.c
src/main/client.c
src/main/cond_eval.c
src/main/cond_tokenize.c
src/main/map.c
src/main/pair.c
src/main/radclient.c
src/main/unit_test_module.c
src/main/xlat_func.c
src/modules/proto_detail/proto_detail.c
src/modules/proto_dhcpv4/dhcpclient.c
src/modules/rlm_attr_filter/rlm_attr_filter.c
src/modules/rlm_cache/drivers/rlm_cache_redis/rlm_cache_redis.c
src/modules/rlm_cache/rlm_cache.c
src/modules/rlm_cache/serialize.c
src/modules/rlm_detail/rlm_detail.c
src/modules/rlm_dict/rlm_dict.c
src/modules/rlm_eap/lib/base/eap_chbind.c
src/modules/rlm_eap/lib/sim/decode.c
src/modules/rlm_eap/lib/sim/encode.c
src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c
src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c
src/modules/rlm_expr/paircmp.c
src/modules/rlm_files/rlm_files.c
src/modules/rlm_ldap/groups.c
src/modules/rlm_mschap/rlm_mschap.c
src/modules/rlm_pap/rlm_pap.c
src/modules/rlm_passwd/rlm_passwd.c
src/modules/rlm_radutmp/rlm_radutmp.c
src/modules/rlm_sql/rlm_sql.c
src/modules/rlm_sqlcounter/rlm_sqlcounter.c
src/modules/rlm_unix/rlm_unix.c
src/modules/rlm_winbind/rlm_winbind.c
src/protocols/dhcpv4/decode.c
src/protocols/dhcpv4/encode.c
src/protocols/dhcpv6/encode.c
src/protocols/radius/base.c
src/protocols/radius/decode.c
src/protocols/radius/encode.c

index e7b3cbf7ef88f333a8ece7711dbc5da82dc33cea..f4e2fa9ce03c420a9e388c4c245f88f73e719a9b 100644 (file)
@@ -88,7 +88,6 @@ extern fr_dict_t *fr_dict_internal;
 /** Dictionary attribute
  */
 struct dict_attr {
-       unsigned int            vendor;                         //!< Vendor that defines this attribute.
        unsigned int            attr;                           //!< Attribute number.
        fr_type_t               type;                           //!< Value type.
 
@@ -229,12 +228,50 @@ ssize_t                   fr_dict_attr_by_oid(fr_dict_t *dict, fr_dict_attr_t const **parent,
 /*
  *     Lookup
  */
+
+/** Return true if this attribute is parented directly off the dictionary root
+ *
+ * @param[in] da               to check.
+ * @return
+ *     - true if attribute is top level.
+ *     - false if attribute is not top level.
+ */
+static inline bool fr_dict_attr_is_top_level(fr_dict_attr_t const *da)
+{
+       if (unlikely(!da) || unlikely(!da->parent)) return false;
+       if (!da->parent->flags.is_root) return false;
+       return true;
+}
+
+/** Return the vendor number for an attribute
+ *
+ * @param[in] da               The dictionary attribute to find the
+ *                             vendor for.
+ * @return
+ *     - 0 this isn't a vendor specific attribute.
+ *     - The vendor PEN.
+ */
+static inline uint32_t fr_dict_vendor_num_by_da(fr_dict_attr_t const *da)
+{
+       fr_dict_attr_t const *da_p = da;
+
+       while (da_p->parent) {
+               if (da_p->type == FR_TYPE_VENDOR) break;
+               da_p = da_p->parent;
+       }
+       if (da_p->type != FR_TYPE_VENDOR) return 0;
+
+       return da_p->attr;
+}
+
 fr_dict_t              *fr_dict_by_da(fr_dict_attr_t const *da);
 
 int                    fr_dict_vendor_by_name(fr_dict_t const *dict, char const *name);
 
 fr_dict_vendor_t const *fr_dict_vendor_by_num(fr_dict_t const *dict, int vendor);
 
+fr_dict_vendor_t const *fr_dict_vendor_by_da(fr_dict_attr_t const *da);
+
 fr_dict_attr_t const   *fr_dict_vendor_attr_by_da(fr_dict_attr_t const *da);
 
 fr_dict_attr_t const   *fr_dict_vendor_attr_by_num(fr_dict_t const *dict,
index dbc7f9ada67e57054abb3b46b7795b27fb071da8..21dd89dd0bacccf0843b1732f746716f00b1e817 100644 (file)
@@ -189,7 +189,7 @@ int fr_ldap_control_add_session_tracking(fr_ldap_connection_t *conn, REQUEST *re
        for (vp = fr_pair_cursor_init(&cursor, &request->packet->vps);
             vp;
             vp = fr_pair_cursor_next(&cursor)) {
-               if (vp->da->vendor == 0) switch (vp->da->attr) {
+               if (fr_dict_attr_is_top_level(vp->da)) switch (vp->da->attr) {
                case FR_NAS_IP_ADDRESS:
                case FR_NAS_IPV6_ADDRESS:
                        fr_pair_value_snprint(ipaddress, sizeof(ipaddress), vp, '\0');
index fbcb55e63ded04b6d3f44b9826244ea6865ebe04..512c83166d72ff9960e85a9fec97a009b8be4fbe 100644 (file)
@@ -657,7 +657,7 @@ static inline int fr_dict_attr_child_add(fr_dict_attr_t *parent, fr_dict_attr_t
                }
 
                if (child_is_struct && !bin_is_struct) break;
-               else if (child->vendor <= (*bin)->vendor) break;        /* Prioritise RFC attributes */
+               else if (fr_dict_vendor_num_by_da(child) <= fr_dict_vendor_num_by_da(*bin)) break;      /* Prioritise RFC attributes */
                else if (child->attr <= (*bin)->attr) break;
 
                bin = &(*bin)->next;
@@ -762,7 +762,6 @@ static int fr_dict_attr_set_name(fr_dict_attr_t **da, char const *name)
  *                             the dictionary root.
  * @param[in] name             of the attribute.  If NULL an OID string
  *                             will be created and set as the name.
- * @param[in] vendor           of the attribute.  Deprecated.
  * @param[in] attr             number.
  * @param[in] type             of the attribute.
  * @param[in] flags            to assign.
@@ -772,7 +771,7 @@ static int fr_dict_attr_set_name(fr_dict_attr_t **da, char const *name)
  */
 static fr_dict_attr_t *fr_dict_attr_alloc(TALLOC_CTX *ctx,
                                          fr_dict_attr_t const *parent,
-                                         char const *name, unsigned int vendor, int attr,
+                                         char const *name, int attr,
                                          fr_type_t type, fr_dict_attr_flags_t const *flags)
 {
        fr_dict_attr_t *da;
@@ -787,7 +786,6 @@ static fr_dict_attr_t *fr_dict_attr_alloc(TALLOC_CTX *ctx,
        talloc_set_type(da, fr_dict_attr_t);
 
        da->attr = attr;
-       da->vendor = vendor;
        da->type = type;
        memcpy(&da->flags, flags, sizeof(*flags));
        da->parent = parent;
@@ -838,7 +836,6 @@ static fr_dict_attr_t *fr_dict_attr_alloc(TALLOC_CTX *ctx,
 static fr_dict_attr_t *fr_dict_attr_add_by_name(fr_dict_t *dict, fr_dict_attr_t const *parent,
                                                char const *name, int attr, fr_type_t type, fr_dict_attr_flags_t flags)
 {
-       unsigned int            vendor;
        size_t                  namelen;
        fr_dict_attr_t          *n;
        fr_dict_attr_t const    *v;
@@ -1405,16 +1402,7 @@ static fr_dict_attr_t *fr_dict_attr_add_by_name(fr_dict_t *dict, fr_dict_attr_t
                }
        }
 
-       /*
-        *      Propogate vendor down the attribute tree.
-        */
-       if (parent->type == FR_TYPE_VENDOR) {
-               vendor = parent->attr;
-       } else {
-               vendor = parent->vendor;
-       }
-
-       n = fr_dict_attr_alloc(dict->pool, parent, name, vendor, attr, type, &flags);
+       n = fr_dict_attr_alloc(dict->pool, parent, name, attr, type, &flags);
        if (!n) {
        oom:
                fr_strerror_printf("Out of memory");
@@ -2586,7 +2574,7 @@ static int _dict_from_file(dict_from_file_ctx_t *ctx,
                                        memset(&flags, 0, sizeof(flags));
 
                                        memcpy(&mutable, &ctx->parent, sizeof(mutable));
-                                       new = fr_dict_attr_alloc(mutable, fr_dict_root(ctx->dict), "Vendor-Specific", 0,
+                                       new = fr_dict_attr_alloc(mutable, fr_dict_root(ctx->dict), "Vendor-Specific",
                                                                 FR_VENDOR_SPECIFIC, FR_TYPE_VSA, &flags);
                                        fr_dict_attr_child_add(mutable, new);
                                        vsa_da = new;
@@ -2620,8 +2608,7 @@ static int _dict_from_file(dict_from_file_ctx_t *ctx,
                                }
 
                                memcpy(&mutable, &vsa_da, sizeof(mutable));
-                               new = fr_dict_attr_alloc(mutable, ctx->parent,
-                                                        argv[1], 0, vendor, FR_TYPE_VENDOR, &flags);
+                               new = fr_dict_attr_alloc(mutable, ctx->parent, argv[1], vendor, FR_TYPE_VENDOR, &flags);
                                fr_dict_attr_child_add(mutable, new);
 
                                vendor_da = new;
@@ -2797,7 +2784,7 @@ int fr_dict_from_file(TALLOC_CTX *ctx, fr_dict_t **out, char const *dir, char co
                        type_name = talloc_typed_asprintf(dict->pool, "Tmp-Cast-%s", p->name);
 
                        n = fr_dict_attr_alloc(dict->pool, dict->root, type_name,
-                                              0, FR_CAST_BASE + p->number, p->number, &flags);
+                                              FR_CAST_BASE + p->number, p->number, &flags);
                        if (!n) goto error;
 
                        if (!fr_hash_table_insert(dict->attributes_by_name, n)) goto error;
@@ -2939,7 +2926,7 @@ fr_dict_attr_t *fr_dict_unknown_acopy(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
                parent = da->parent;
        }
 
-       new = fr_dict_attr_alloc(ctx, parent, da->name, da->vendor, da->attr, da->type, &da->flags);
+       new = fr_dict_attr_alloc(ctx, parent, da->name, da->attr, da->type, &da->flags);
        new->parent = parent;
        new->depth = da->depth;
 
@@ -3001,7 +2988,7 @@ fr_dict_attr_t const *fr_dict_unknown_add(fr_dict_t *dict, fr_dict_attr_t const
 
                if (fr_dict_vendor_add(dict, old->name, old->attr) < 0) return NULL;
 
-               n = fr_dict_attr_alloc(dict->pool, parent, old->name, old->vendor, old->attr, old->type, &flags);
+               n = fr_dict_attr_alloc(dict->pool, parent, old->name, old->attr, old->type, &flags);
 
                /*
                 *      Setup parenting for the attribute
@@ -3065,7 +3052,7 @@ void fr_dict_unknown_free(fr_dict_attr_t const **da)
 
 /** Initialises an unknown attribute
  *
- * Initialises a dict attr for an unknown attribute/vendor/type without adding
+ * Initialises a dict attr for an unknown attribute/type without adding
  * it to dictionary pools/hashes.
  *
  * Unknown attributes are used to transparently pass undecodeable attributes
@@ -3078,8 +3065,7 @@ void fr_dict_unknown_free(fr_dict_attr_t const **da)
  * @param[in] vendor           number.
  * @return 0 on success.
  */
-static int fr_dict_unknown_from_fields(fr_dict_attr_t *da, fr_dict_attr_t const *parent,
-                                      unsigned int vendor, unsigned int attr)
+static int fr_dict_unknown_from_fields(fr_dict_attr_t *da, fr_dict_attr_t const *parent, unsigned int attr)
 {
        char *p;
        size_t len = 0;
@@ -3093,7 +3079,6 @@ static int fr_dict_unknown_from_fields(fr_dict_attr_t *da, fr_dict_attr_t const
        memset(da, 0, FR_DICT_ATTR_SIZE);
 
        da->attr = attr;
-       da->vendor = vendor;
        da->type = FR_TYPE_OCTETS;
        da->flags.is_unknown = true;
        da->flags.is_raw = true;
@@ -3183,7 +3168,7 @@ fr_dict_attr_t const *fr_dict_unknown_afrom_fields(TALLOC_CTX *ctx, fr_dict_attr
                return NULL;
        }
 
-       if (fr_dict_unknown_from_fields(n, parent, vendor, attr) < 0) {
+       if (fr_dict_unknown_from_fields(n, parent, attr) < 0) {
                talloc_free(p);
                parent = new_parent;    /* Stupid const rules */
                fr_dict_unknown_free(&parent);
@@ -3257,7 +3242,7 @@ int fr_dict_unknown_vendor_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t **out,
        case FR_TYPE_EVS:
                if (!fr_cond_assert(!parent->flags.is_unknown)) return -1;
 
-               *out = fr_dict_attr_alloc(ctx, parent, NULL, 0, vendor, FR_TYPE_VENDOR, &flags);
+               *out = fr_dict_attr_alloc(ctx, parent, NULL, vendor, FR_TYPE_VENDOR, &flags);
 
                return 0;
 
@@ -3309,7 +3294,7 @@ static int fr_dict_unknown_attr_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t **out,
 
        if (parent->type == FR_TYPE_VENDOR) vendor = parent->attr;
 
-       da = fr_dict_attr_alloc(ctx, parent, NULL, vendor, num, FR_TYPE_OCTETS, &flags);
+       da = fr_dict_attr_alloc(ctx, parent, NULL, num, FR_TYPE_OCTETS, &flags);
        if (!da) return -1;
 
        *out = da;
@@ -3635,7 +3620,7 @@ void fr_dict_print(fr_dict_attr_t const *da, int depth)
 
        printf("%u%.*s%s \"%s\" vendor: %x (%u), num: %x (%u), type: %s, flags: %s\n", da->depth, depth,
               "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t", name, da->name,
-              da->vendor, da->vendor, da->attr, da->attr,
+              fr_dict_vendor_num_by_da(da), fr_dict_vendor_num_by_da(da), da->attr, da->attr,
               fr_int2str(dict_attr_types, da->type, "?Unknown?"), buff);
 
        if (da->children) for (i = 0; i < talloc_array_length(da->children); i++) {
@@ -3902,6 +3887,28 @@ fr_dict_vendor_t const *fr_dict_vendor_by_num(fr_dict_t const *dict, int vendorp
        return fr_hash_table_finddata(dict->vendors_by_num, &dv);
 }
 
+/** Look up a vendor by its PEN
+ *
+ * @param[in] dict             of protocol context we're operating in.
+ *                             If NULL the internal dictionary will be used.
+ * @param[in] vendorpec                to search for.
+ * @return
+ *     - The vendor.
+ *     - NULL if no vendor with that number was regitered for this protocol.
+ */
+fr_dict_vendor_t const *fr_dict_vendor_by_da(fr_dict_attr_t const *da)
+{
+       fr_dict_t               *dict;
+       fr_dict_vendor_t        dv;
+
+       dv.vendorpec = fr_dict_vendor_num_by_da(da);
+       if (!dv.vendorpec) return NULL;
+
+       dict = fr_dict_by_da(da);
+
+       return fr_hash_table_finddata(dict->vendors_by_num, &dv);
+}
+
 /** Return the vendor that parents this attribute
  *
  * @note Uses the dictionary hierachy to determine the parent
@@ -4319,7 +4326,7 @@ void fr_dict_verify(char const *file, int line, fr_dict_attr_t const *da)
        if ((!da->flags.is_root) && (da->depth == 0)) {
                FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: fr_dict_attr_t %s vendor: %i, attr %i: "
                             "Is not root, but depth is 0",
-                            file, line, da->name, da->vendor, da->attr);
+                            file, line, da->name, fr_dict_vendor_num_by_da(da), da->attr);
 
                if (!fr_cond_assert(0)) fr_exit_now(1);
        }
@@ -4327,7 +4334,8 @@ void fr_dict_verify(char const *file, int line, fr_dict_attr_t const *da)
        if (da->depth > FR_DICT_MAX_TLV_STACK) {
                FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: fr_dict_attr_t %s vendor: %i, attr %i: "
                             "Indicated depth (%u) greater than TLV stack depth (%u)",
-                            file, line, da->name, da->vendor, da->attr, da->depth, FR_DICT_MAX_TLV_STACK);
+                            file, line, da->name, fr_dict_vendor_num_by_da(da), da->attr,
+                            da->depth, FR_DICT_MAX_TLV_STACK);
 
                if (!fr_cond_assert(0)) fr_exit_now(1);
        }
@@ -4340,7 +4348,7 @@ void fr_dict_verify(char const *file, int line, fr_dict_attr_t const *da)
                if (i != (int)da_p->depth) {
                        FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: fr_dict_attr_t %s vendor: %i, attr %i: "
                                     "Depth out of sequence, expected %i, got %u",
-                                    file, line, da->name, da->vendor, da->attr, i, da_p->depth);
+                                    file, line, da->name, fr_dict_vendor_num_by_da(da), da->attr, i, da_p->depth);
 
                        if (!fr_cond_assert(0)) fr_exit_now(1);
                }
index b59fdf264a08d1d1300cd08802de4cc5cc429db0..d5a8b20ea78e570be9fa02ab4ed563842827ec09 100644 (file)
@@ -187,7 +187,7 @@ VALUE_PAIR *fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *paren
                 *      also fine...
                 */
                vendor = fr_dict_vendor_attr_by_da(parent);
-               if (vendor) vendor_id = vendor->vendor;
+               if (vendor) vendor_id = vendor->attr;
 
                da = fr_dict_unknown_afrom_fields(ctx, parent,
                                                  vendor_id, attr);
@@ -545,7 +545,7 @@ int fr_pair_to_unknown(VALUE_PAIR *vp)
        VP_VERIFY(vp);
        if (vp->da->flags.is_unknown) return 0;
 
-       da = fr_dict_unknown_afrom_fields(vp, vp->da->parent, vp->da->vendor, vp->da->attr);
+       da = fr_dict_unknown_afrom_fields(vp, vp->da->parent, fr_dict_vendor_num_by_da(vp->da), vp->da->attr);
        if (!da) return -1;
 
        fr_dict_unknown_free(&vp->da);  /* Only frees unknown attributes */
@@ -832,9 +832,7 @@ void fr_pair_delete_by_num(VALUE_PAIR **head, unsigned int vendor, unsigned int
                for(i = *head; i; i = next) {
                        VP_VERIFY(i);
                        next = i->next;
-                       if (i->da->parent->flags.is_root &&
-                           (i->da->attr == attr) && (i->da->vendor == 0) &&
-                           ATTR_TAG_MATCH(i, tag)) {
+                       if (fr_dict_attr_is_top_level(i->da) && (i->da->attr == attr) && ATTR_TAG_MATCH(i, tag)) {
                                *last = next;
                                talloc_free(i);
                        } else {
@@ -846,7 +844,7 @@ void fr_pair_delete_by_num(VALUE_PAIR **head, unsigned int vendor, unsigned int
                        VP_VERIFY(i);
                        next = i->next;
                        if ((i->da->parent->type == FR_TYPE_VENDOR) &&
-                           (i->da->attr == attr) && (i->da->vendor == vendor) &&
+                           (i->da->attr == attr) && (fr_dict_vendor_num_by_da(i->da) == vendor) &&
                            ATTR_TAG_MATCH(i, tag)) {
                                *last = next;
                                talloc_free(i);
@@ -1597,7 +1595,7 @@ VALUE_PAIR *fr_pair_list_copy_by_num(TALLOC_CTX *ctx, VALUE_PAIR *from,
                        /*
                         *      It's a VSA: copy it over.
                         */
-                       if (vp->da->vendor != 0) goto do_copy;
+                       if (!fr_dict_attr_is_top_level(vp->da)) goto do_copy;
 
                        /*
                         *      It's Vendor-Specific: copy it over.
@@ -1611,13 +1609,10 @@ VALUE_PAIR *fr_pair_list_copy_by_num(TALLOC_CTX *ctx, VALUE_PAIR *from,
                }
 
                if (!vendor) {
-                       if (!vp->da->parent->flags.is_root ||
-                           (vp->da->attr != attr) || (vp->da->vendor != 0)) {
-                               continue;
-                       }
+                       if (!fr_dict_attr_is_top_level(vp->da) || (vp->da->attr != attr)) continue;
                } else {
                        if ((vp->da->parent->type != FR_TYPE_VENDOR) ||
-                           (vp->da->attr != attr) || (vp->da->vendor != vendor)) {
+                           (vp->da->attr != attr) || (fr_dict_vendor_num_by_da(vp->da) != vendor)) {
                                continue;
                        }
                }
@@ -1682,7 +1677,7 @@ void fr_pair_list_move(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
                /*
                 *      We never move Fall-Through.
                 */
-               if (!i->da->vendor && i->da->attr == FR_FALL_THROUGH && i->da->parent->flags.is_root) {
+               if (fr_dict_attr_is_top_level(i->da) && (i->da->attr == FR_FALL_THROUGH)) {
                        tail_from = &(i->next);
                        continue;
                }
@@ -1756,7 +1751,8 @@ void fr_pair_list_move(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
                         *      Delete *all* of the attributes
                         *      of the same number.
                         */
-                       fr_pair_delete_by_num(&found->next, found->da->vendor, found->da->attr, TAG_ANY);
+                       fr_pair_delete_by_num(&found->next,
+                                             fr_dict_vendor_num_by_da(found->da), found->da->attr, TAG_ANY);
 
                        /*
                         *      Remove this attribute from the
@@ -1863,7 +1859,7 @@ static void fr_pair_list_move_by_num_internal(TALLOC_CTX *ctx, VALUE_PAIR **to,
                        /*
                         *      It's a VSA: move it over.
                         */
-                       if (i->da->vendor != 0) goto move;
+                       if (!fr_dict_attr_is_top_level(i->da)) goto move;
 
                        /*
                         *      It's Vendor-Specific: move it over.
@@ -1881,14 +1877,13 @@ static void fr_pair_list_move_by_num_internal(TALLOC_CTX *ctx, VALUE_PAIR **to,
                 *      If it isn't an exact match, ignore it.
                 */
                if (!vendor) {
-                       if (!(i->da->parent->flags.is_root &&
-                             (i->da->attr == attr) && (i->da->vendor == 0))) {
+                       if (!(fr_dict_attr_is_top_level(i->da) && (i->da->attr == attr))) {
                                iprev = i;
                                continue;
                        }
                } else {
                        if (!((i->da->parent->type == FR_TYPE_VENDOR) &&
-                             (i->da->attr == attr) && (i->da->vendor == vendor))) {
+                             (i->da->attr == attr) && (fr_dict_vendor_num_by_da(i->da) == vendor))) {
                                iprev = i;
                                continue;
                        }
index a13883d7e18fd4e06c31581d2be4481670c12a60..969bfe427b7d3515ee2b7b346005eef569628b01 100644 (file)
@@ -210,9 +210,7 @@ VALUE_PAIR *fr_pair_cursor_next_by_num(vp_cursor_t *cursor, unsigned int vendor,
                     i != NULL;
                     i = i->next) {
                        VP_VERIFY(i);
-                       if (i->da->parent->flags.is_root &&
-                           (i->da->attr == attr) && (i->da->vendor == 0) &&
-                           ATTR_TAG_MATCH(i, tag)) {
+                       if (fr_dict_attr_is_top_level(i->da) && (i->da->attr == attr) && ATTR_TAG_MATCH(i, tag)) {
                                break;
                        }
                }
@@ -222,7 +220,7 @@ VALUE_PAIR *fr_pair_cursor_next_by_num(vp_cursor_t *cursor, unsigned int vendor,
                     i = i->next) {
                        VP_VERIFY(i);
                        if ((i->da->parent->type == FR_TYPE_VENDOR) &&
-                           (i->da->attr == attr) && (i->da->vendor == vendor) &&
+                           (i->da->attr == attr) && (fr_dict_vendor_num_by_da(i->da) == vendor) &&
                            ATTR_TAG_MATCH(i, tag)) {
                                break;
                        }
index 8ae9f9cc46970f3f8669c7d3f55d29f789d1e5a3..cfdf7769ffc50eea6a81dbcd1ec8b6b9876b5ca5 100644 (file)
@@ -84,7 +84,8 @@ void fr_proto_tlv_stack_print(char const *file, int line, char const *func, fr_d
                fprintf(fr_log_fp, "stk: %s%.*s: %s [%i] %s: %s, vendor: 0x%x (%u), attr: 0x%x (%u)\n",
                        prefix, (int)(proto_log_indent - len), spaces, (i == (int)depth) ? ">" : " ", i,
                        fr_int2str(dict_attr_types, tlv_stack[i]->type, "?Unknown?"),
-                       tlv_stack[i]->name, tlv_stack[i]->vendor, tlv_stack[i]->vendor,
+                       tlv_stack[i]->name,
+                       fr_dict_vendor_num_by_da(tlv_stack[i]), fr_dict_vendor_num_by_da(tlv_stack[i]),
                        tlv_stack[i]->attr, tlv_stack[i]->attr);
        }
        fprintf(fr_log_fp, "\n");
index e87f9a9be8bbe3640e07ba58bdc09a36ba5799b2..8af5cbb5dc9cbfcaf1f2bb62d205c8cce7b11c22 100644 (file)
@@ -924,7 +924,7 @@ RADCLIENT *client_afrom_request(TALLOC_CTX *ctx, REQUEST *request)
                char const      *value;
                char const      *attr;
 
-               if (vp->da->vendor != 0) continue;
+               if (!fr_dict_attr_is_top_level(vp->da)) continue;
 
                if ((vp->da->attr < FR_FREERADIUS_CLIENT_IP_ADDRESS) ||
                    (vp->da->attr > FR_FREERADIUS_CLIENT_NAS_TYPE)) {
index 4718a9f2ceceeca96da09a4e2f91dccae182112a..94761dc0a6a5c3ae7fdde9d040afea3f0962901a 100644 (file)
@@ -1063,7 +1063,7 @@ void radius_pairmove(REQUEST *request, VALUE_PAIR **to, VALUE_PAIR *from, bool d
                fixup->password = NULL;
 
                for (vp = fixup->packet->vps; vp != NULL; vp = vp->next) {
-                       if (vp->da->vendor) continue;
+                       if (!fr_dict_attr_is_top_level(vp->da)) continue;
 
                        if ((vp->da->attr == FR_USER_NAME) && !fixup->username) {
                                fixup->username = vp;
index 46c4c7c329afe6129a450530beff768fd69fb9f3..436a47545ec99b1229ad85ab5c838b44262952b5 100644 (file)
@@ -1099,24 +1099,27 @@ static ssize_t cond_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start,
                                                               c->cast ? NULL : c->data.map->lhs->tmpl_da) < 0) {
                                                fr_dict_attr_t const *da = c->data.map->lhs->tmpl_da;
 
-                                               if ((da->vendor == 0) &&
-                                                   ((da->attr == FR_AUTH_TYPE) ||
-                                                    (da->attr == FR_AUTZ_TYPE) ||
-                                                    (da->attr == FR_ACCT_TYPE) ||
-                                                    (da->attr == FR_SESSION_TYPE) ||
-                                                    (da->attr == FR_POST_AUTH_TYPE) ||
-                                                    (da->attr == FR_PRE_PROXY_TYPE) ||
-                                                    (da->attr == FR_POST_PROXY_TYPE) ||
-                                                    (da->attr == FR_PRE_ACCT_TYPE) ||
-                                                    (da->attr == FR_RECV_COA_TYPE) ||
-                                                    (da->attr == FR_SEND_COA_TYPE))) {
+                                               if (!fr_dict_attr_is_top_level(da)) goto bad_type;
+
+                                               switch (da->attr) {
+                                               case FR_AUTH_TYPE:
+                                               case FR_AUTZ_TYPE:
+                                               case FR_ACCT_TYPE:
+                                               case FR_SESSION_TYPE:
+                                               case FR_POST_AUTH_TYPE:
+                                               case FR_PRE_PROXY_TYPE:
+                                               case FR_POST_PROXY_TYPE:
+                                               case FR_PRE_ACCT_TYPE:
+                                               case FR_RECV_COA_TYPE:
+                                               case FR_SEND_COA_TYPE:
                                                        /*
                                                         *      The types for these attributes are dynamically allocated
                                                         *      by module.c, so we can't enforce strictness here.
                                                         */
                                                        c->pass2_fixup = PASS2_FIXUP_TYPE;
 
-                                               } else {
+                                               default:
+                                               bad_type:
                                                        return_rhs("Failed to parse value for attribute");
                                                }
                                        }
index d0c8e0c306ed9688042287bcc71a74a2a5e4418c..3822015180ecabc2b3ae8fe53062051948848d0f 100644 (file)
@@ -1963,8 +1963,7 @@ update:
                     vp;
                     vp = fr_cursor_next(&list)) {
 
-                       if (!vp->da->parent->flags.is_root) continue;
-                       if (vp->da->vendor != 0) continue;
+                       if (!fr_dict_attr_is_top_level(vp->da)) continue;
                        if (vp->da->flags.has_tag) continue;
                        if (vp->vp_type != FR_TYPE_STRING) continue;
 
@@ -2490,7 +2489,7 @@ int map_to_request(REQUEST *request, vp_map_t const *map, radius_map_getvalue_t
                 *      Wildcard: delete all of the matching ones, based on tag.
                 */
                if (map->lhs->tmpl_num == NUM_ANY) {
-                       fr_pair_delete_by_num(list, map->lhs->tmpl_da->vendor, map->lhs->tmpl_da->attr,
+                       fr_pair_delete_by_num(list, fr_dict_vendor_num_by_da(map->lhs->tmpl_da), map->lhs->tmpl_da->attr,
                                              map->lhs->tmpl_tag);
                        dst = NULL;
                /*
@@ -2689,9 +2688,7 @@ update:
                for (vp = fr_pair_cursor_init(&src_list, list);
                     vp;
                     vp = fr_pair_cursor_next(&src_list)) {
-
-                       if (!vp->da->parent->flags.is_root) continue;
-                       if (vp->da->vendor != 0) continue;
+                       if (!fr_dict_attr_is_top_level(vp->da)) continue;
                        if (vp->da->flags.has_tag) continue;
                        if (vp->vp_type != FR_TYPE_STRING) continue;
 
index 4b48fad73bf62b1d9e095c983761bb1dad753218..9f5f4316251afe8f84da3964c4ade4016af665e0 100644 (file)
@@ -502,7 +502,7 @@ int paircompare(REQUEST *request, VALUE_PAIR *req_list, VALUE_PAIR *check,
                        continue;
                }
 
-               if (!check_item->da->vendor) switch (check_item->da->attr) {
+               if (fr_dict_attr_is_top_level(check_item->da)) switch (check_item->da->attr) {
                /*
                 *      Attributes we skip during comparison.
                 *      These are "server" check items.
index 2ae83ce919a6aa06a6825157cfba840215c50ecd..08cbd04e908322c3bf875d9a3aed8d06ea3a8a6d 100644 (file)
@@ -409,7 +409,7 @@ static int radclient_init(TALLOC_CTX *ctx, rc_file_pair_t *files)
                                        vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
                                }
 
-                               if (vp->da->vendor == 0 ) switch (vp->da->attr) {
+                               if (fr_dict_attr_is_top_level(vp->da)) switch (vp->da->attr) {
                                case FR_RESPONSE_PACKET_TYPE:
                                case FR_PACKET_TYPE:
                                        vp = fr_cursor_remove(&cursor); /* so we don't break the filter */
@@ -445,7 +445,7 @@ static int radclient_init(TALLOC_CTX *ctx, rc_file_pair_t *files)
                                vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
                        }
 
-                       if (!vp->da->vendor) switch (vp->da->attr) {
+                       if (fr_dict_attr_is_top_level(vp->da)) switch (vp->da->attr) {
                        default:
                                break;
 
index c19166a44a22a2d39695bd106aba187a6c4288c3..4754f4fdf451ecfeaf2e0e781ee44e0177547eba 100644 (file)
@@ -176,7 +176,7 @@ static REQUEST *request_from_file(FILE *fp, fr_event_list_t *el, RADCLIENT *clie
                        vp->type = VT_DATA;
                }
 
-               if (!vp->da->vendor) switch (vp->da->attr) {
+               if (fr_dict_attr_is_top_level(vp->da)) switch (vp->da->attr) {
                default:
                        break;
 
index 89f69776dabfe2de291c49d3499da351998a779d..73a220514fd219450d64d21cd4cd9c48d801438f 100644 (file)
@@ -267,8 +267,9 @@ static ssize_t xlat_debug_attr(UNUSED TALLOC_CTX *ctx, UNUSED char **out, UNUSED
        for (vp = tmpl_cursor_init(NULL, &cursor, request, vpt);
             vp;
             vp = fr_cursor_next(&cursor)) {
-               FR_NAME_NUMBER const *type;
-               char *value;
+               fr_dict_vendor_t const  *vendor;
+               FR_NAME_NUMBER const    *type;
+               char                    *value;
 
                value = fr_pair_value_asprint(vp, vp, '\'');
                if (vp->da->flags.has_tag) {
@@ -289,12 +290,8 @@ static ssize_t xlat_debug_attr(UNUSED TALLOC_CTX *ctx, UNUSED char **out, UNUSED
 
                if (!RDEBUG_ENABLED3) continue;
 
-               if (vp->da->vendor) {
-                       fr_dict_vendor_t const *vendor;
-
-                       vendor = fr_dict_vendor_by_num(NULL, vp->da->vendor);
-                       RIDEBUG2("Vendor : %i (%s)", vp->da->vendor, vendor ? vendor->name : "unknown");
-               }
+               vendor = fr_dict_vendor_by_da(vp->da);
+               if (vendor) RIDEBUG2("Vendor : %i (%s)", vendor->vendorpec, vendor->name);
                RIDEBUG2("Type   : %s", fr_int2str(dict_attr_types, vp->vp_type, "<INVALID>"));
 
                switch (vp->vp_type) {
index 2c49e4f1bdfb26e00476fca367983eae186cc2ed..968a143de225c2820e840c54baee7e5e3586ac38 100644 (file)
@@ -305,8 +305,7 @@ static int mod_decode(void const *instance, REQUEST *request, uint8_t *const dat
                /*
                 *      Set the original src/dst ip/port
                 */
-               if (vp && (vp->da->vendor == 0) && (vp->da->attr >= FR_PACKET_SRC_IP_ADDRESS) &&
-                   (vp->da->attr <= FR_PACKET_DST_IPV6_ADDRESS)) switch (vp->da->attr) {
+               if (vp && fr_dict_attr_is_top_level(vp->da)) switch (vp->da->attr) {
                        default:
                                break;
 
index 04f1f3b107518207838edea9b13b388adb1b42eb..b1b77fb53f7c7d763ec325185f32bfc9b1ca259d 100644 (file)
@@ -149,9 +149,9 @@ static RADIUS_PACKET *request_init(char const *filename)
                /*
                 *      Allow to set packet type using DHCP-Message-Type
                 */
-               if (vp->da->vendor == DHCP_MAGIC_VENDOR && vp->da->attr == FR_DHCPV4_MESSAGE_TYPE) {
+               if ((fr_dict_vendor_num_by_da(vp->da) == DHCP_MAGIC_VENDOR) && vp->da->attr == FR_DHCPV4_MESSAGE_TYPE) {
                        request->code = vp->vp_uint32 + FR_DHCPV4_OFFSET;
-               } else if (!vp->da->vendor) switch (vp->da->attr) {
+               } else if (fr_dict_attr_is_top_level(vp->da)) switch (vp->da->attr) {
                /*
                 *      Allow it to set the packet type in
                 *      the attributes read from the file.
index f89630e51d138437c561201cc8da056af7606788..68388b14cd1031de6c8db342de2f38bfbaa30a92 100644 (file)
@@ -110,8 +110,7 @@ static int attr_filter_getfile(TALLOC_CTX *ctx, char const *filename, PAIR_LIST
                     * and we ignore Fall-Through,
                     * then bitch about it, giving a good warning message.
                     */
-                    if ((vp->da->vendor == 0) &&
-                        (vp->da->attr > 1000)) {
+                    if (fr_dict_attr_is_top_level(vp->da) && (vp->da->attr > 1000)) {
                        WARN("[%s]:%d Check item \"%s\"\n\tfound in filter list for realm \"%s\".\n",
                               filename, entry->lineno, vp->da->name, entry->name);
                    }
@@ -199,16 +198,21 @@ static rlm_rcode_t CC_HINT(nonnull(1,2)) attr_filter_common(void const *instance
                for (check_item = fr_pair_cursor_init(&check, &pl->check);
                     check_item;
                     check_item = fr_pair_cursor_next(&check)) {
-                       if (!check_item->da->vendor &&
-                           (check_item->da->attr == FR_FALL_THROUGH) &&
-                               (check_item->vp_uint32 == 1)) {
-                               fall_through = 1;
-                               continue;
-                       }
-                       else if (!check_item->da->vendor && check_item->da->attr == FR_RELAX_FILTER) {
+                       if (fr_dict_attr_is_top_level(vp->da)) switch (check_item->da->attr) {
+                       case FR_FALL_THROUGH:
+                               if (check_item->vp_uint32 == 1) {
+                                       fall_through = 1;
+                                       continue;
+                               }
+                               break;
+
+                       case FR_RELAX_FILTER:
                                relax_filter = check_item->vp_uint32;
                                continue;
-                       }
+
+                       default:
+                               break;
+                       }
 
                        /*
                         *    If it is a SET operator, add the attribute to
@@ -216,9 +220,8 @@ static rlm_rcode_t CC_HINT(nonnull(1,2)) attr_filter_common(void const *instance
                         */
                        if (check_item->op == T_OP_SET ) {
                                vp = fr_pair_copy(packet, check_item);
-                               if (!vp) {
-                                       goto error;
-                               }
+                               if (!vp) goto error;
+
                                xlat_eval_do(request, vp);
                                fr_pair_cursor_append(&out, vp);
                        }
@@ -247,7 +250,8 @@ static rlm_rcode_t CC_HINT(nonnull(1,2)) attr_filter_common(void const *instance
                                 *  Vendor-Specific is special, and matches any VSA if the
                                 *  comparison is always true.
                                 */
-                               if ((check_item->da->attr == FR_VENDOR_SPECIFIC) && (input_item->da->vendor != 0) &&
+                               if ((check_item->da->attr == FR_VENDOR_SPECIFIC) &&
+                                   (fr_dict_vendor_num_by_da(input_item->da) != 0) &&
                                    (check_item->op == T_OP_CMP_TRUE)) {
                                        pass++;
                                        continue;
index 0ca008294c939e84f76a22c598b0d0415e89d47a..cd8680b97c1d87f2f0d1360fe19b0a7c73863a04 100644 (file)
@@ -207,7 +207,7 @@ static cache_status_t cache_entry_find(rlm_cache_entry_t **out,
        /*
         *      Pull out the cache created date
         */
-       if ((head->lhs->tmpl_da->vendor == 0) && (head->lhs->tmpl_da->attr == FR_CACHE_CREATED)) {
+       if (fr_dict_attr_is_top_level(head->lhs->tmpl_da) && (head->lhs->tmpl_da->attr == FR_CACHE_CREATED)) {
                vp_map_t *map;
 
                c->created = head->rhs->tmpl_value.vb_date;
@@ -220,7 +220,7 @@ static cache_status_t cache_entry_find(rlm_cache_entry_t **out,
        /*
         *      Pull out the cache expires date
         */
-       if ((head->lhs->tmpl_da->vendor == 0) && (head->lhs->tmpl_da->attr == FR_CACHE_EXPIRES)) {
+       if (fr_dict_attr_is_top_level(head->lhs->tmpl_da) && (head->lhs->tmpl_da->attr == FR_CACHE_EXPIRES)) {
                vp_map_t *map;
 
                c->expires = head->rhs->tmpl_value.vb_date;
index 90b382251e64a120d534b3f156f6f2d74880bf4c..5f93db1cdd7a7255cbd5b5b47984f27a1b6e12d1 100644 (file)
@@ -771,7 +771,9 @@ finish:
             vp;
             vp = fr_cursor_next(&cursor)) {
             again:
-               if (vp->da->vendor == 0) switch (vp->da->attr) {
+               if (!fr_dict_attr_is_top_level(vp->da)) continue;
+
+               switch (vp->da->attr) {
                case FR_CACHE_TTL:
                case FR_CACHE_STATUS_ONLY:
                case FR_CACHE_ALLOW_MERGE:
index 0715b69ddddca493cfe5a6f765bc02ce61f912de..5c049bcd7a4e402785c5ed6dacc16fd9f4663909 100644 (file)
@@ -147,7 +147,7 @@ int cache_deserialize(rlm_cache_entry_t *c, char *in, ssize_t inlen)
                 *      Pull out the special attributes, and set the
                 *      relevant cache entry fields.
                 */
-               if (map->lhs->tmpl_da->vendor == 0) switch (map->lhs->tmpl_da->attr) {
+               if (fr_dict_attr_is_top_level(map->lhs->tmpl_da)) switch (map->lhs->tmpl_da->attr) {
                case FR_CACHE_CREATED:
                        c->created = map->rhs->tmpl_value.vb_date;
                        talloc_free(map);
index 0c58c920064cb57ae1cd8d6578d3fa5d68fcbcd6..f45d7c47f2f38dbe6ce1541a3913a8dc0df6405c 100644 (file)
@@ -307,7 +307,7 @@ static int detail_write(FILE *out, rlm_detail_t const *inst, REQUEST *request, R
                        /*
                         *      Don't print passwords in old format...
                         */
-                       if (compat && !vp->da->vendor && (vp->da->attr == FR_USER_PASSWORD)) continue;
+                       if (compat && fr_dict_attr_is_top_level(vp->da) && (vp->da->attr == FR_USER_PASSWORD)) continue;
 
                        /*
                         *      Print all of the attributes, operator should always be '='.
index 3f182d6a72bf6d550067664d4a0514ce543e072a..05aef66cff92beeafb1a3677e4d0fd8aaca7848e 100644 (file)
@@ -99,7 +99,7 @@ static ssize_t xlat_vendor(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen,
 
        if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) return 0;
 
-       vendor = fr_dict_vendor_by_num(NULL, vp->da->vendor);
+       vendor = fr_dict_vendor_by_da(vp->da);
        if (!vendor) return 0;
 
        *out = talloc_typed_strdup(ctx, vendor->name);
@@ -119,7 +119,7 @@ static ssize_t xlat_vendor_num(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen
 
        if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) return 0;
 
-       *out = talloc_typed_asprintf(ctx, "%i", vp->da->vendor);
+       *out = talloc_typed_asprintf(ctx, "%i", fr_dict_vendor_num_by_da(vp->da));
        return talloc_array_length(*out) - 1;
 }
 
index 400bf8e9dea58a15622b9f6ec66c3bdea597b1fa..07eba33efc11127fb707de3b59aa7d9f4db7077a 100644 (file)
@@ -42,7 +42,7 @@ static bool chbind_build_response(REQUEST *request, CHBIND_REQ *chbind)
                 *      Skip things which shouldn't be in channel bindings.
                 */
                if (vp->da->flags.encrypt != FLAG_ENCRYPT_NONE) continue;
-               if (!vp->da->vendor && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) continue;
+               if (fr_dict_attr_is_top_level(vp->da) && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) continue;
 
                total += 2 + vp->vp_length;
        }
@@ -93,7 +93,7 @@ static bool chbind_build_response(REQUEST *request, CHBIND_REQ *chbind)
                        fr_cursor_next(&cursor);
                        continue;
                }
-               if (!vp->da->vendor && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) goto next;
+               if (fr_dict_attr_is_top_level(vp->da) && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) goto next;
 
                length = fr_radius_encode_pair(ptr, end - ptr, &cursor, NULL);
                ptr += length;
index 40b7a6fa2101d2b08c8b80babd68983f391c425b..c13ceca3b3d6c3165f1ce04db20a89979c147c07 100644 (file)
@@ -487,7 +487,8 @@ static ssize_t sim_decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                        /*
                         *      Build an unknown attr
                         */
-                       unknown_child = fr_dict_unknown_afrom_fields(ctx, parent, parent->vendor, p[0]);
+                       unknown_child = fr_dict_unknown_afrom_fields(ctx, parent,
+                                                                    fr_dict_vendor_num_by_da(parent), p[0]);
                        if (!unknown_child) goto error;
                        child = unknown_child;
                }
@@ -696,7 +697,8 @@ static ssize_t sim_decode_pair_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_di
                 *      therefore of type "octets", and will be
                 *      handled below.
                 */
-               parent = fr_dict_unknown_afrom_fields(ctx, parent->parent, parent->vendor, parent->attr);
+               parent = fr_dict_unknown_afrom_fields(ctx, parent->parent,
+                                                     fr_dict_vendor_num_by_da(parent), parent->attr);
                if (!parent) {
                        fr_strerror_printf_push("%s[%d]: Internal sanity check failed", __FUNCTION__, __LINE__);
                        return -1;
index 36fcd9cc8a10cc89022987dfad232f28c7fdf2b7..4d2a907bd9d0205072bfa48a1c3a3284ac1f282c 100644 (file)
@@ -701,7 +701,7 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const
                return PAIR_ENCODE_ERROR;
 
        default:
-               if (((tlv_stack[depth]->vendor == 0) && (tlv_stack[depth]->attr == 0)) ||
+               if (((fr_dict_vendor_num_by_da(tlv_stack[depth]) == 0) && (tlv_stack[depth]->attr == 0)) ||
                    (tlv_stack[depth]->attr > 255)) {
                        fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__,
                                           tlv_stack[depth]->attr);
index 3065a7d5a577c99beaff5747bce42d658a61c249..40c17f0c010111d4649ac66f3b09135cd57b6eab 100644 (file)
@@ -505,7 +505,7 @@ static rlm_rcode_t CC_HINT(nonnull) process_reply(NDEBUG_UNUSED eap_session_t *e
                 * the rest to be cleaned up.
                 */
                for (vp = fr_pair_cursor_init(&cursor, &reply->vps); vp; vp = fr_pair_cursor_next(&cursor)) {
-                       if (vp->da->vendor != VENDORPEC_MICROSOFT) continue;
+                       if (fr_dict_vendor_num_by_da(vp->da) != VENDORPEC_MICROSOFT) continue;
 
                        /* FIXME must be a better way to capture/re-derive this later for ISK */
                        switch (vp->da->attr) {
index 6b577780a872af929c75a98bbaa2ce050e79e22b..4dd0a2ed3f27de6579fa6132c48f6dc182d0ecdb 100644 (file)
@@ -253,8 +253,9 @@ do_value:
                 *      challenge) But if the client gets the challenge correct,
                 *      we're not too worried about the Id.
                 */
-               if (((vp->da->vendor == 0) && (vp->da->attr == FR_CHAP_CHALLENGE)) ||
-                   ((vp->da->vendor == VENDORPEC_MICROSOFT) && (vp->da->attr == FR_MSCHAP_CHALLENGE))) {
+               if ((fr_dict_attr_is_top_level(vp->da) && (vp->da->attr == FR_CHAP_CHALLENGE)) ||
+                   ((fr_dict_vendor_num_by_da(vp->da) == VENDORPEC_MICROSOFT) && (vp->da->attr == FR_MSCHAP_CHALLENGE))
+                  ) {
                        uint8_t challenge[16];
                        uint8_t scratch[16];
 
@@ -329,7 +330,7 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
                 */
 
                length = vp->vp_length;
-               vendor = vp->da->vendor;
+               vendor = fr_dict_vendor_num_by_da(vp->da);
                if (vendor != 0) {
                        attr = vp->da->attr & 0xffff;
                        length |= ((uint32_t)1 << 31);
@@ -486,7 +487,7 @@ static rlm_rcode_t CC_HINT(nonnull) process_reply(NDEBUG_UNUSED eap_session_t *e
                for (vp = fr_cursor_init(&cursor, &reply->vps);
                     vp;
                     vp = fr_cursor_next(&cursor)) {
-                       switch (vp->da->vendor) {
+                       switch (fr_dict_vendor_num_by_da(vp->da)) {
                        case VENDORPEC_MICROSOFT:
                                if (vp->da->attr == FR_MSCHAP2_SUCCESS) {
                                        RDEBUG("Got MS-CHAP2-Success, tunneling it to the client in a challenge");
@@ -536,7 +537,7 @@ static rlm_rcode_t CC_HINT(nonnull) process_reply(NDEBUG_UNUSED eap_session_t *e
                for (vp = fr_cursor_init(&cursor, &reply->vps);
                     vp;
                     vp = fr_cursor_next(&cursor)) {
-                       switch (vp->da->vendor) {
+                       switch (fr_dict_vendor_num_by_da(vp->da)) {
                        case VENDORPEC_UKERNA:
                                if (vp->da->attr == FR_UKERNA_CHBIND) {
                                        fr_cursor_prepend(&to_tunnel, fr_pair_copy(tls_session, vp));
index 47f8a63e1fdecf12ad04ec9eaf88d8d659a5f41b..c75fa18a80265fe81383b9ce802935850ae73c9e 100644 (file)
@@ -81,7 +81,7 @@ static int presufcmp(UNUSED void *instance,
        RDEBUG3("Comparing name \"%s\" and check value \"%s\"", name, check->vp_strvalue);
 
        len = strlen(check->vp_strvalue);
-       if (check->da->vendor == 0) switch (check->da->attr) {
+       if (fr_dict_attr_is_top_level(check->da)) switch (check->da->attr) {
        case FR_PREFIX:
                ret = strncmp(name, check->vp_strvalue, len);
                if (ret == 0)
index 533566b7bce4e7c6095720c7359e5dd510b1daf0..ef067a71fca80f57c481782e1f15afb145d51f6b 100644 (file)
@@ -147,7 +147,7 @@ static int getusersfile(TALLOC_CTX *ctx, char const *filename, rbtree_t **ptree)
                                 *      or it's a wire protocol,
                                 *      ensure it has '=='.
                                 */
-                               if ((vp->da->vendor != 0) ||
+                               if ((fr_dict_vendor_num_by_da(vp->da) != 0) ||
                                    (vp->da->attr < 0x100)) {
                                        WARN("[%s]:%d Changing '%s =' to '%s =='\n\tfor comparing RADIUS attribute in check item list for user %s",
                                             filename, entry->lineno,
@@ -175,8 +175,7 @@ static int getusersfile(TALLOC_CTX *ctx, char const *filename, rbtree_t **ptree)
                                 *      then bitch about it, giving a
                                 *      good warning message.
                                 */
-                                if ((vp->da->vendor == 0) &&
-                                       (vp->da->attr > 1000)) {
+                                if (fr_dict_attr_is_top_level(vp->da) && (vp->da->attr > 1000)) {
                                        WARN("[%s]:%d Check item \"%s\"\n"
                                               "\tfound in reply item list for user \"%s\".\n"
                                               "\tThis attribute MUST go on the first line"
index ac6a98e04d4dc34210ba335a7494e703c9fbce7c..5a7d294432647bb6cbdba47e9a33838b9587e32e 100644 (file)
@@ -822,11 +822,13 @@ rlm_rcode_t rlm_ldap_check_cached(rlm_ldap_t const *inst, REQUEST *request, VALU
         *      We return RLM_MODULE_INVALID here as an indication
         *      the caller should try a dynamic group lookup instead.
         */
-       vp = fr_pair_cursor_next_by_num(&cursor, inst->cache_da->vendor, inst->cache_da->attr, TAG_ANY);
+       vp = fr_pair_cursor_next_by_num(&cursor, fr_dict_vendor_num_by_da(inst->cache_da),
+                                       inst->cache_da->attr, TAG_ANY);
        if (!vp) return RLM_MODULE_INVALID;
        fr_pair_cursor_first(&cursor);
 
-       while ((vp = fr_pair_cursor_next_by_num(&cursor, inst->cache_da->vendor, inst->cache_da->attr, TAG_ANY))) {
+       while ((vp = fr_pair_cursor_next_by_num(&cursor, fr_dict_vendor_num_by_da(inst->cache_da),
+                                               inst->cache_da->attr, TAG_ANY))) {
                ret = fr_pair_cmp_op(T_OP_CMP_EQ, vp, check);
                if (ret == 1) {
                        RDEBUG2("User found. Matched cached membership");
index a05d4eeef52f0895dd992cb35f93a1eed4255912..3bae76bf4b18435aa73751754d07003b81a85bae 100644 (file)
@@ -289,7 +289,7 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                 *      For MS-CHAPv1, the NT-Response exists only
                 *      if the second octet says so.
                 */
-               if ((response->da->vendor == VENDORPEC_MICROSOFT) &&
+               if ((fr_dict_vendor_num_by_da(response->da) == VENDORPEC_MICROSOFT) &&
                    (response->da->attr == FR_MSCHAP_RESPONSE) &&
                    ((response->vp_octets[1] & 0x01) == 0)) {
                        REDEBUG("No NT-Response in MS-CHAP-Response");
@@ -1139,8 +1139,7 @@ static int CC_HINT(nonnull (1, 2, 4, 5 , 6)) do_mschap(rlm_mschap_t const *inst,
                 *      then calculate the hash of the NT hash.  Doing this
                 *      here minimizes work for later.
                 */
-               if (!password->da->vendor &&
-                   (password->da->attr == FR_NT_PASSWORD)) {
+               if (fr_dict_attr_is_top_level(password->da) && (password->da->attr == FR_NT_PASSWORD)) {
                        fr_md4_calc(nthashhash, password->vp_octets, MD4_DIGEST_LENGTH);
                }
 
@@ -1672,11 +1671,9 @@ static rlm_rcode_t CC_HINT(nonnull) process_cpw_request(rlm_mschap_t const *inst
                for (nt_enc = fr_cursor_init(&cursor, &request->packet->vps);
                     nt_enc;
                     nt_enc = fr_cursor_next(&cursor)) {
-                       if (nt_enc->da->vendor != VENDORPEC_MICROSOFT)
-                               continue;
+                       if (fr_dict_vendor_num_by_da(nt_enc->da) != VENDORPEC_MICROSOFT) continue;
 
-                       if (nt_enc->da->attr != FR_MSCHAP_NT_ENC_PW)
-                               continue;
+                       if (nt_enc->da->attr != FR_MSCHAP_NT_ENC_PW) continue;
 
                        if (nt_enc->vp_length < 4) {
                                REDEBUG("MS-CHAP-NT-Enc-PW with invalid format");
index 9306236e987dd3759a21e1a90cac0683a5e8b4d2..8b90eb2563160579fdfa6a562bccc23a51db37c3 100644 (file)
@@ -1354,8 +1354,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, UNUSED void
        fr_cursor_t     cursor;
        rlm_rcode_t     (*auth_func)(rlm_pap_t const *, REQUEST *, VALUE_PAIR *) = NULL;
 
-       if (!request->password ||
-           (request->password->da->vendor != 0) ||
+       if (!request->password || !fr_dict_attr_is_top_level(request->password->da) ||
            (request->password->da->attr != FR_USER_PASSWORD)) {
                REDEBUG("You set 'Auth-Type = PAP' for a request that does not contain a User-Password attribute!");
                return RLM_MODULE_INVALID;
@@ -1384,7 +1383,9 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, UNUSED void
        for (vp = fr_cursor_init(&cursor, &request->control);
             vp;
             vp = fr_cursor_next(&cursor)) {
-               if (!vp->da->vendor) switch (vp->da->attr) {
+               if (!fr_dict_attr_is_top_level(vp->da)) continue;
+
+               switch (vp->da->attr) {
                case FR_CLEARTEXT_PASSWORD:
                        auth_func = &pap_auth_clear;
                        break;
index 7dc70c13d84e361355a08c316ad224923108789b..e7eec20878b96c84d7ea9cbdec55635662bb68a7 100644 (file)
@@ -537,7 +537,8 @@ static rlm_rcode_t CC_HINT(nonnull) mod_passwd_map(void *instance, UNUSED void *
 
        for (i = fr_pair_cursor_init(&cursor, &key);
             i;
-            i = fr_pair_cursor_next_by_num(&cursor, inst->keyattr->vendor, inst->keyattr->attr, TAG_ANY)) {
+            i = fr_pair_cursor_next_by_num(&cursor, fr_dict_vendor_num_by_da(inst->keyattr),
+                                           inst->keyattr->attr, TAG_ANY)) {
                /*
                 *      Ensure we have the string form of the attribute
                 */
index f13b2b85b9236ce19f48c9c06de29afd9ebb036b..8d972bb5832e5dcd11c1ec436de7d20efd44b4b4 100644 (file)
@@ -220,7 +220,9 @@ static rlm_rcode_t CC_HINT(nonnull) mod_accounting(void *instance, UNUSED void *
        for (vp = fr_cursor_init(&cursor, &request->packet->vps);
             vp;
             vp = fr_cursor_next(&cursor)) {
-               if (!vp->da->vendor) switch (vp->da->attr) {
+               if (!fr_dict_attr_is_top_level(vp->da)) continue;
+
+               switch (vp->da->attr) {
                case FR_LOGIN_IP_HOST:
                case FR_FRAMED_IP_ADDRESS:
                        ut.framed_address = vp->vp_ipv4addr;
index 55cb41049eb9b5e7cb5bc6de72ba1232429e3986..8378b2bfa379fdbaf6f628135b72242c7b27cf2a 100644 (file)
@@ -638,7 +638,7 @@ int sql_set_user(rlm_sql_t const *inst, REQUEST *request, char const *username)
        /*
         *      Delete any existing SQL-User-Name, and replace it with ours.
         */
-       fr_pair_delete_by_num(&request->packet->vps, vp->da->vendor, vp->da->attr, TAG_ANY);
+       fr_pair_delete_by_num(&request->packet->vps, fr_dict_vendor_num_by_da(vp->da), vp->da->attr, TAG_ANY);
        fr_pair_add(&request->packet->vps, vp);
 
        return 0;
@@ -647,7 +647,7 @@ int sql_set_user(rlm_sql_t const *inst, REQUEST *request, char const *username)
 /*
  *     Do a set/unset user, so it's a bit clearer what's going on.
  */
-#define sql_unset_user(_i, _r) fr_pair_delete_by_num(&_r->packet->vps, _i->sql_user->vendor, _i->sql_user->attr, TAG_ANY)
+#define sql_unset_user(_i, _r) fr_pair_delete_by_num(&_r->packet->vps, fr_dict_vendor_num_by_da(_i->sql_user), _i->sql_user->attr, TAG_ANY)
 
 static int sql_get_grouplist(rlm_sql_t const *inst, rlm_sql_handle_t **handle, REQUEST *request,
                             rlm_sql_grouplist_t **phead)
index 1fee1017380463072d31047e3d75baaeaf8b489e..4647335101597001d52f31fdfc71337ce1f4f91b 100644 (file)
@@ -409,7 +409,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, UNUSED void *t
         *      The REAL username, after stripping.
         */
        if ((inst->key_attr->tmpl_list == PAIR_LIST_REQUEST) &&
-           (inst->key_attr->tmpl_da->vendor == 0) && (inst->key_attr->tmpl_da->attr == FR_USER_NAME)) {
+           fr_dict_attr_is_top_level(inst->key_attr->tmpl_da) && (inst->key_attr->tmpl_da->attr == FR_USER_NAME)) {
                key_vp = request->username;
        } else {
                tmpl_find_vp(&key_vp, request, inst->key_attr);
@@ -482,7 +482,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, UNUSED void *t
                 *      limit, so that the user will not need to login
                 *      again.  Do this only for Session-Timeout.
                 */
-               if (((inst->reply_attr->tmpl_da->vendor == 0) &&
+               if ((fr_dict_attr_is_top_level(inst->reply_attr->tmpl_da) &&
                     (inst->reply_attr->tmpl_da->attr == FR_SESSION_TIMEOUT)) &&
                    inst->reset_time && (res >= (uint64_t)(inst->reset_time - request->packet->timestamp.tv_sec))) {
                        uint64_t to_reset = inst->reset_time - request->packet->timestamp.tv_sec;
index 91a0240a75b6cfbe062bb6536e1e4c3ee5fc8667..f59168e68db0b252fd3507f8489133b5131e59f3 100644 (file)
@@ -422,7 +422,9 @@ static rlm_rcode_t CC_HINT(nonnull) mod_accounting(void *instance, UNUSED void *
        for (vp = fr_cursor_init(&cursor, &request->packet->vps);
             vp;
             vp = fr_cursor_next(&cursor)) {
-               if (!vp->da->vendor) switch (vp->da->attr) {
+               if (!fr_dict_attr_is_top_level(vp->da)) continue;
+
+               switch (vp->da->attr) {
                case FR_USER_NAME:
                        if (vp->vp_length >= sizeof(ut.ut_name)) {
                                memcpy(ut.ut_name, vp->vp_strvalue, sizeof(ut.ut_name));
index d1cb8c450ac72219836b4d7788795c0a319d5a11..eaba50ce331a32525b3df069db48ec31b16cb6f3 100644 (file)
@@ -469,8 +469,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, UNUSED void
        /*
         *      Check the admin hasn't been silly
         */
-       if (!request->password ||
-           (request->password->da->vendor != 0) ||
+       if (!request->password || !fr_dict_attr_is_top_level(request->password->da) ||
            (request->password->da->attr != FR_USER_PASSWORD)) {
                REDEBUG("You set 'Auth-Type = winbind' for a request that does not contain a User-Password attribute!");
                return RLM_MODULE_INVALID;
index 837835149ab4e5054455b08dc10166afc8a7e88e..51160339d17ef62a37bdedea79c1e2154de72ea7 100644 (file)
@@ -279,7 +279,8 @@ static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dict_attr_t c
                        /*
                         *      Build an unknown attr
                         */
-                       unknown_child = fr_dict_unknown_afrom_fields(ctx, parent, parent->vendor, p[0]);
+                       unknown_child = fr_dict_unknown_afrom_fields(ctx, parent,
+                                                                    fr_dict_vendor_num_by_da(parent), p[0]);
                        if (!unknown_child) return -1;
                        child = unknown_child;
                }
index 570eb98e8947ec081e3e821628001ba3221ea99e..98166ae214c5050e295fd4042d9e177927da7f03 100644 (file)
@@ -289,7 +289,7 @@ ssize_t fr_dhcpv4_encode_option(uint8_t *out, size_t outlen, fr_cursor_t *cursor
        vp = fr_cursor_current(cursor);
        if (!vp) return -1;
 
-       if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next; /* not a DHCP option */
+       if (fr_dict_vendor_num_by_da(vp->da) != DHCP_MAGIC_VENDOR) goto next; /* not a DHCP option */
        if (vp->da->attr == FR_DHCPV4_MESSAGE_TYPE) goto next; /* already done */
        if ((vp->da->attr > 255) && (DHCP_BASE_ATTR(vp->da->attr) != FR_DHCPV4_OPTION_82)) {
        next:
index a9ecdd02043d44e4cddae2db3727f51ba58d1638..7d87e937664b988aed697698ca1c2052d3b886e4 100644 (file)
@@ -585,21 +585,6 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen,
 
        FR_PROTO_STACK_PRINT(tlv_stack, depth);
 
-       switch (da->type) {
-       case FR_TYPE_STRUCTURAL:
-               fr_strerror_printf("%s: Called with structural type %s", __FUNCTION__,
-                                  fr_int2str(dict_attr_types, da->type, "?Unknown?"));
-               return PAIR_ENCODE_ERROR;
-
-       default:
-               if (((da->vendor == 0) && (da->attr == 0)) || (da->attr > UINT16_MAX)) {
-                       fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__,
-                                          tlv_stack[depth]->attr);
-                       return PAIR_ENCODE_ERROR;
-               }
-               break;
-       }
-
        CHECK_FREESPACE(outlen, OPT_HDR_LEN);
 
        /*
index cbd564484fb9b29a661749f6bee7c371fd3aa784..3b6202c56018a9dd6cf902bab39d1ce31d1f1d44 100644 (file)
@@ -924,11 +924,8 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig
                /*
                 *      Ignore non-wire attributes, but allow extended
                 *      attributes.
-                *
-                *      @fixme We should be able to get rid of this check
-                *      and just look at da->flags.internal
                 */
-               if (vp->da->flags.internal || ((vp->da->vendor == 0) && (vp->da->attr >= 256))) {
+               if (vp->da->flags.internal) {
 #ifndef NDEBUG
                        /*
                         *      Permit the admin to send BADLY formatted
@@ -954,7 +951,7 @@ ssize_t fr_radius_encode(uint8_t *packet, size_t packet_len, uint8_t const *orig
                 *      Set the Message-Authenticator to the correct
                 *      length and initial value.
                 */
-               if (!vp->da->vendor && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) {
+               if (fr_dict_attr_is_top_level(vp->da) && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) {
                        last_len = 16;
                } else {
                        last_len = vp->vp_length;
index c718316ea29ef9fb128941a28bdfe732a75881b8..3a78cbb91c35cee0cb96282cdc53bba17df761f7 100644 (file)
@@ -426,7 +426,8 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                        /*
                         *      Build an unknown attr
                         */
-                       unknown_child = fr_dict_unknown_afrom_fields(ctx, parent, parent->vendor, p[0]);
+                       unknown_child = fr_dict_unknown_afrom_fields(ctx, parent,
+                                                                    fr_dict_vendor_num_by_da(parent), p[0]);
                        if (!unknown_child) {
                        error:
                                fr_pair_list_free(&head);
@@ -499,13 +500,15 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, fr_cursor_t *cursor,
                        /*
                         *      Build an unknown attr of the entire STRUCT.
                         */
-                       child = fr_dict_unknown_afrom_fields(ctx, parent->parent, parent->vendor, parent->attr);
+                       child = fr_dict_unknown_afrom_fields(ctx, parent->parent,
+                                                            fr_dict_vendor_num_by_da(parent), parent->attr);
                        if (!child) return -1;
 
                        /*
                         *      Decode the whole STRUCT as an unknown attribute
                         */
-                       child_len = fr_radius_decode_pair_value(ctx, &child_cursor, child, data, data_len, data_len, decoder_ctx);
+                       child_len = fr_radius_decode_pair_value(ctx, &child_cursor, child,
+                                                               data, data_len, data_len, decoder_ctx);
                        if (child_len < 0) return child_len;
                        break;
                }
@@ -1223,7 +1226,7 @@ ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dic
                child = fr_dict_attr_child_by_num(parent, p[0]);
                if (!child) {
                        if ((p[0] != FR_VENDOR_SPECIFIC) || (data_len < (3 + 4 + 1))) {
-                               /* da->attr < 255, da->vendor == 0 */
+                               /* da->attr < 255, fr_dict_vendor_num_by_da(da) == 0 */
                                child = fr_dict_unknown_afrom_fields(ctx, parent, 0, p[0]);
                        } else {
                                /*
@@ -1352,7 +1355,8 @@ ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_cursor_t *cursor, fr_dic
                 *      therefore of type "octets", and will be
                 *      handled below.
                 */
-               parent = fr_dict_unknown_afrom_fields(ctx, parent->parent, parent->vendor, parent->attr);
+               parent = fr_dict_unknown_afrom_fields(ctx, parent->parent,
+                                                     fr_dict_vendor_num_by_da(parent), parent->attr);
                if (!parent) {
                        fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__);
                        return -1;
index e3e198dd792159f62d9d3c95c4849e5c86c81731..256d36697148c209779c01eb59fc64e259e4927c 100644 (file)
@@ -1098,7 +1098,7 @@ static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen,
                return -1;
 
        default:
-               if (((tlv_stack[depth]->vendor == 0) && (tlv_stack[depth]->attr == 0)) ||
+               if (((fr_dict_vendor_num_by_da(tlv_stack[depth]) == 0) && (tlv_stack[depth]->attr == 0)) ||
                    (tlv_stack[depth]->attr > 255)) {
                        fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__,
                                           tlv_stack[depth]->attr);
@@ -1305,7 +1305,7 @@ static int encode_wimax_hdr(uint8_t *out, size_t outlen,
        out = start;
        out[0] = FR_VENDOR_SPECIFIC;
        out[1] = 9;
-       lvalue = htonl(vp->da->vendor);
+       lvalue = htonl(fr_dict_vendor_num_by_da(vp->da));
        memcpy(out + 2, &lvalue, 4);
 
        /*
@@ -1374,10 +1374,10 @@ static int encode_vsa_hdr(uint8_t *out, size_t outlen,
        }
 
        /*
-        *      Double-check for WiMAX format.
+        *      Double-check for WiMAX format
         */
-       if (da->vendor == VENDORPEC_WIMAX) {
-               return encode_wimax_hdr(out, outlen, tlv_stack, depth + 1, cursor, encoder_ctx);
+       if (fr_dict_vendor_num_by_da(tlv_stack[depth + 1]) == VENDORPEC_WIMAX) {
+               return encode_wimax_hdr(out, outlen, tlv_stack, depth, cursor, encoder_ctx);
        }
 
        /*
@@ -1450,7 +1450,7 @@ static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tl
                 *      Attribute 0 is fine as a TLV leaf, or VSA, but not
                 *      in the original standards space.
                 */
-               if (((tlv_stack[depth]->vendor == 0) && (tlv_stack[depth]->attr == 0)) ||
+               if (((fr_dict_vendor_num_by_da(tlv_stack[depth]) == 0) && (tlv_stack[depth]->attr == 0)) ||
                    (tlv_stack[depth]->attr > 255)) {
                        fr_strerror_printf("%s: Called with non-standard attribute %u", __FUNCTION__, vp->da->attr);
                        return -1;
@@ -1474,7 +1474,7 @@ static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tl
        /*
         *      Message-Authenticator is hard-coded.
         */
-       if (!vp->da->vendor && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) {
+       if (fr_dict_attr_is_top_level(vp->da) && (vp->da->attr == FR_MESSAGE_AUTHENTICATOR)) {
                if (outlen < 18) return -1;
 
                out[0] = FR_MESSAGE_AUTHENTICATOR;
@@ -1536,7 +1536,7 @@ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor,
         *      attributes.
         */
        if (fr_radius_attr_len(vp) == 0) {
-               if ((vp->da->vendor != 0) ||
+               if (!fr_dict_attr_is_top_level(vp->da) ||
                    ((vp->da->attr != FR_CHARGEABLE_USER_IDENTITY) &&
                     (vp->da->attr != FR_MESSAGE_AUTHENTICATOR))) {
                        next_encodable(cursor);
@@ -1584,7 +1584,7 @@ ssize_t fr_radius_encode_pair(uint8_t *out, size_t outlen, fr_cursor_t *cursor,
                break;
 
        case FR_TYPE_VSA:
-               if (vp->da->vendor == VENDORPEC_WIMAX) {
+               if (fr_dict_vendor_num_by_da(da) == VENDORPEC_WIMAX) {
                        /*
                         *      WiMAX has a non-standard format for
                         *      its VSAs.  And, it can do "long"