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.
/** Dictionary attribute
*/
struct dict_attr {
- unsigned int vendor; //!< Vendor that defines this attribute.
unsigned int attr; //!< Attribute number.
fr_type_t type; //!< Value type.
/*
* 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,
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');
}
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;
* 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.
*/
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;
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;
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;
}
}
- /*
- * 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");
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;
}
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;
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;
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;
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
/** 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
* @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;
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;
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);
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;
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;
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++) {
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
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);
}
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);
}
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);
}
* 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);
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 */
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 {
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);
/*
* 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.
}
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;
}
}
/*
* 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;
}
* 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
/*
* 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.
* 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;
}
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;
}
}
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;
}
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");
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)) {
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;
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");
}
}
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;
* 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;
/*
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;
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.
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 */
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;
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;
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) {
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) {
/*
* 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;
/*
* 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.
* 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);
}
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
*/
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);
}
* 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;
/*
* 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;
/*
* 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;
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:
* 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);
/*
* 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 '='.
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);
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;
}
* 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;
}
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;
/*
* 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;
}
* 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;
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);
* 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) {
* 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];
*/
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);
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");
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));
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)
* 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,
* 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"
* 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");
* 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");
* 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);
}
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");
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;
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;
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
*/
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;
/*
* 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;
/*
* 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)
* 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);
* 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;
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));
/*
* 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;
/*
* 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;
}
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:
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);
/*
/*
* 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
* 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;
/*
* 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);
/*
* 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;
}
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 {
/*
* 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;
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);
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);
/*
}
/*
- * 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);
}
/*
* 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;
/*
* 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;
* 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);
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"