]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
encode foreign references
authorAlan T. DeKok <aland@freeradius.org>
Fri, 26 Jan 2024 03:04:20 +0000 (22:04 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 26 Jan 2024 16:35:47 +0000 (11:35 -0500)
src/protocols/radius/base.c
src/protocols/radius/encode.c

index 52c20a93018823fccdc993117ec6638a3a75849b..7238489e215bd16abd96a01ca490dce962b29a21 100644 (file)
@@ -1255,14 +1255,6 @@ static bool attr_valid(UNUSED fr_dict_t *dict, fr_dict_attr_t const *parent,
                return true;
        }
 
-       /*
-        *      The RADIUS encoder does not handle groups.
-        */
-       if ((type == FR_TYPE_GROUP) && !flags->internal) {
-               fr_strerror_const("The RADIUS protocol cannot encode attributes of type 'group'");
-               return false;
-       }
-
        if (flag_extended(flags)) {
                if (type != FR_TYPE_TLV) {
                        fr_strerror_const("The 'long' or 'extended' flag can only be used for attributes of type 'tlv'");
index c1f1ffeafa58e94349e9a24e3c64b4f5b282d11e..fd489fd50aa703348e59af3437acc587422d0de9 100644 (file)
@@ -801,6 +801,35 @@ static ssize_t encode_extended(fr_dbuff_t *dbuff,
        } else if (da->type == FR_TYPE_STRUCT) {
                slen = fr_struct_to_network(&work_dbuff, da_stack, my_depth, cursor, encode_ctx, encode_value, encode_child);
 
+       } else if (da->type == FR_TYPE_GROUP) {
+               fr_dict_attr_t const *ref;
+               fr_dict_protocol_t const *proto;
+
+               ref = fr_dict_attr_ref(da);
+               if (!ref) {
+                       fr_strerror_printf("Invalid attribute reference for %s", da->name);
+                       return PAIR_ENCODE_SKIPPED;
+               }
+
+               fr_assert(ref->dict != dict_radius);
+
+               proto = fr_dict_protocol(ref->dict);
+               fr_assert(proto != NULL);
+
+               if (!proto->encode) {
+                       fr_strerror_printf("Attribute %s -> %s does not have an encoder", da->name, ref->name);
+                       return PAIR_ENCODE_SKIPPED;
+               }
+
+               /*
+                *      The foreign functions don't take a cursor, so we have to update the cursor ourselves.
+                */
+               slen = proto->encode(&work_dbuff, &vp->vp_group);
+               if (slen > 0) {
+                       vp = fr_dcursor_next(cursor);
+                       fr_proto_da_stack_build(da_stack, vp ? vp->da : NULL);
+               }
+
        } else {
                fr_assert(da->type == FR_TYPE_TLV);