]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Make fr_pair_list_copy_by_num() work like ...move...()
authorAlan T. DeKok <aland@freeradius.org>
Wed, 14 Oct 2015 14:27:16 +0000 (10:27 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 14 Oct 2015 14:27:49 +0000 (10:27 -0400)
src/lib/pair.c

index ce5484fe95001ae74804dd3c21aaee1a51d64cb8..6533797ee186164a52a8d296c672c57b4cb7b794 100644 (file)
@@ -705,7 +705,10 @@ VALUE_PAIR *fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
  *
  * @param[in] ctx for talloc
  * @param[in] from whence to copy VALUE_PAIRs.
- * @param[in] attr to match, if 0 input list will not be filtered by attr.
+ * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
+ *     will match (and therefore copy) only VSAs.
+ *     If attribute 0 and vendor 0  will match (and therefore copy) all
+ *     attributes.
  * @param[in] vendor to match.
  * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
  * @return the head of the new VALUE_PAIR list or NULL on error.
@@ -723,14 +726,44 @@ VALUE_PAIR *fr_pair_list_copy_by_num(TALLOC_CTX *ctx, VALUE_PAIR *from,
             vp = fr_cursor_next(&src)) {
                VERIFY_VP(vp);
 
-               if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
+               if (vp->da->flags.has_tag && !TAG_EQ(tag, vp->tag)) {
                        continue;
                }
 
-               if (vp->da->flags.has_tag && !TAG_EQ(tag, vp->tag)) {
+               /*
+                *      Attr/vendor of 0 means "move them all".
+                *      It's better than "fr_pair_copy(foo,bar);bar=NULL"
+                */
+               if ((attr == 0) && (vendor == 0)) {
+                       goto do_copy;
+               }
+
+               /*
+                *      vendor=0, attr = PW_VENDOR_SPECIFIC means
+                *      "match any vendor attribute".
+                */
+               if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
+                       /*
+                        *      It's a VSA: copy it over.
+                        */
+                       if (vp->da->vendor != 0) goto do_copy;
+
+                       /*
+                        *      It's Vendor-Specific: copy it over.
+                        */
+                       if (vp->da->attr == attr) goto do_copy;
+
+                       /*
+                        *      It's not a VSA: ignore it.
+                        */
+                       continue;
+               }
+
+               if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
                        continue;
                }
 
+       do_copy:
                vp = fr_pair_copy(ctx, vp);
                if (!vp) {
                        fr_pair_list_free(&out);