/*
* The destination is an attribute
- *
- * It's a remove operation, or a filter, or an add or a set.
*/
switch (map->op) {
-
+ default:
+ break;
/*
* !* - Remove all attributes which match dst in the specified list.
* This doesn't use attributes returned by the func(), and immediately frees them.
* Check that the User-Name and User-Password
* caches point to the correct attribute.
*/
- break;
- /*
- * = - Set only if not already set
- */
- case T_OP_EQ:
- if (dst) {
- RDEBUG3("Refusing to overwrite (use :=)");
- pairfree(&head);
- return 0;
- }
-
- /* Insert first instance (if multiple) */
- fr_cursor_first(&src_list);
- fr_cursor_insert(&dst_list, fr_cursor_remove(&src_list));
- /* Free any we didn't insert */
- pairfree(&head);
- break;
-
- /*
- * := - Overwrite existing attribute with last src_list attribute
- */
- case T_OP_SET:
- /* Wind to last instance */
- fr_cursor_last(&src_list);
- if (dst) {
- dst = fr_cursor_remove(&dst_list);
- DEBUG_OVERWRITE(dst, fr_cursor_current(&src_list));
- pairfree(&dst);
- }
- fr_cursor_insert(&dst_list, fr_cursor_remove(&src_list));
- /* Free any we didn't insert */
- pairfree(&head);
- break;
-
- /*
- * += - Add all src_list attributes to the destination
- */
- case T_OP_ADD:
- /* Insert all the instances! (if multiple) */
- pairadd(list, head);
- head = NULL;
- break;
+ goto finish;
/*
* -= - Delete attributes in the dst list which match any of the
* against each of the src_list attributes.
*/
case T_OP_SUB:
- {
/* We didn't find any attributes earlier */
if (!dst) {
pairfree(&head);
}
pairfree(&head);
if (!found) return 0;
- break;
+ goto finish;
}
+ /*
+ * Another fixup pass to set tags on attributes were about to insert
+ */
+ if (map->dst->vpt_tag != TAG_ANY) {
+ for (vp = fr_cursor_init(&src_list, &head);
+ vp;
+ vp = fr_cursor_next(&src_list)) {
+ vp->tag = map->dst->vpt_tag;
+ }
+ }
+
+ switch (map->op) {
+ /*
+ * = - Set only if not already set
+ */
+ case T_OP_EQ:
+ if (dst) {
+ RDEBUG3("Refusing to overwrite (use :=)");
+ pairfree(&head);
+ return 0;
+ }
+
+ /* Insert first instance (if multiple) */
+ fr_cursor_first(&src_list);
+ fr_cursor_insert(&dst_list, fr_cursor_remove(&src_list));
+ /* Free any we didn't insert */
+ pairfree(&head);
+ break;
+
+ /*
+ * := - Overwrite existing attribute with last src_list attribute
+ */
+ case T_OP_SET:
+ /* Wind to last instance */
+ fr_cursor_last(&src_list);
+ if (dst) {
+ dst = fr_cursor_remove(&dst_list);
+ DEBUG_OVERWRITE(dst, fr_cursor_current(&src_list));
+ pairfree(&dst);
+ }
+ fr_cursor_insert(&dst_list, fr_cursor_remove(&src_list));
+ /* Free any we didn't insert */
+ pairfree(&head);
+ break;
+
+ /*
+ * += - Add all src_list attributes to the destination
+ */
+ case T_OP_ADD:
+ /* Insert all the instances! (if multiple) */
+ pairadd(list, head);
+ head = NULL;
+ break;
/*
* Filtering operators
--- /dev/null
+#
+# PRE: update
+#
+# Remove all attributes in a list
+#
+update {
+ control:Cleartext-Password := 'hello'
+ reply:Filter-Id := 'filter'
+}
+
+update request {
+ Tunnel-Server-Endpoint:0 := 192.0.1.1 # Should not be tagged
+ Tunnel-Server-Endpoint:0 += 192.0.1.1 # Should not be tagged
+ Tunnel-Server-Endpoint:1 := 192.0.2.1
+ Tunnel-Server-Endpoint:1 += 192.0.2.1
+ Tunnel-Server-Endpoint:2 := 192.0.3.2
+ Tunnel-Server-Endpoint:2 += 192.0.3.2
+}
+
+update request {
+ Tmp-Integer-0 := "%{debug_attr:request:}"
+}
+
+# Check that access attributes by tag works first
+if ("%{Tunnel-Server-Endpoint:2}" != 192.0.3.2) {
+ update {
+ reply:Filter-Id += 'fail 1'
+ }
+}
+
+if ("%{Tunnel-Server-Endpoint:2}" == 192.0.3.1) {
+ update {
+ reply:Filter-Id += 'fail 2'
+ }
+}
+
+if ("%{Tunnel-Server-Endpoint:1}" != 192.0.2.1) {
+ update {
+ reply:Filter-Id += 'fail 3'
+ }
+}