commit 182a78957d60a4c91c1ff8d1ff0f09b1b64b70ba
Author: Ondrej Zajicek <santiago@crfreenet.org>
Date:   Sun Apr 29 01:35:52 2012 +0200

    Allows some modifications of dest attribute in filters.

diff --git a/doc/bird.sgml b/doc/bird.sgml
index a94fb9e..3edd6e0 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -1072,7 +1072,16 @@ undefined value is regarded as empty clist for most purposes.
 	routes). Read-only.
 
 	<tag><m/enum/ dest</tag>
-	Type of destination the packets should be sent to (<cf/RTD_ROUTER/ for forwarding to a neighboring router, <cf/RTD_DEVICE/ for routing to a directly-connected network, <cf/RTD_BLACKHOLE/ for packets to be silently discarded, <cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that should be returned with ICMP host unreachable / ICMP administratively prohibited messages). Read-only.
+	Type of destination the packets should be sent to
+	(<cf/RTD_ROUTER/ for forwarding to a neighboring router,
+	<cf/RTD_DEVICE/ for routing to a directly-connected network,
+	<cf/RTD_MULTIPATH/ for multipath destinations,
+	<cf/RTD_BLACKHOLE/ for packets to be silently discarded,
+	<cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that
+	should be returned with ICMP host unreachable / ICMP
+	administratively prohibited messages). Can be changed, but
+	only to <cf/RTD_BLACKHOLE/, <cf/RTD_UNREACHABLE/ or
+	<cf/RTD_PROHIBIT/.
 
 	<tag><m/int/ igp_metric</tag>
 	The optional attribute that can be used to specify a distance
diff --git a/filter/config.Y b/filter/config.Y
index 2e8b522..0eeb2ce 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -703,7 +703,7 @@ static_attr:
  | SOURCE  { $$ = f_new_inst(); $$->aux = T_ENUM_RTS;   $$->a2.i = OFFSETOF(struct rta, source); }
  | SCOPE   { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope);  $$->a1.i = 1; }
  | CAST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTC;   $$->a2.i = OFFSETOF(struct rta, cast); }
- | DEST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTD;   $$->a2.i = OFFSETOF(struct rta, dest); }
+ | DEST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTD;   $$->a2.i = OFFSETOF(struct rta, dest);   $$->a1.i = 1; }
  ;
 
 term:
diff --git a/filter/filter.c b/filter/filter.c
index acdcfd2..49b6739 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -852,12 +852,25 @@ interpret(struct f_inst *what)
     {
       struct rta *rta = (*f_rte)->attrs;
       switch (what->aux) {
-      case T_ENUM:
-	* ((char *) rta + what->a2.i) = v1.val.i;
-	break;
+
       case T_IP:
 	* (ip_addr *) ((char *) rta + what->a2.i) = v1.val.px.ip;
 	break;
+
+      case T_ENUM_SCOPE:
+	rta->scope = v1.val.i;
+	break;
+
+      case T_ENUM_RTD:
+	i = v1.val.i;
+	if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
+	  runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
+	rta->dest = i;
+	rta->gw = IPA_NONE;
+	rta->iface = NULL;
+	rta->nexthops = NULL;
+	break;
+
       default:
 	bug( "Unknown type in set of static attribute" );
       }
