*
* @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.
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);