Binary files bird-1.3.6-/bird and bird-1.3.6/bird differ
Binary files bird-1.3.6-/obj/proto/rip/all.o and bird-1.3.6/obj/proto/rip/all.o differ
Binary files bird-1.3.6-/obj/proto/rip/rip.o and bird-1.3.6/obj/proto/rip/rip.o differ
diff -uprN bird-1.3.6-/proto/rip/rip.c bird-1.3.6/proto/rip/rip.c
--- bird-1.3.6-/proto/rip/rip.c	2012-01-10 13:42:47.000000000 +0100
+++ bird-1.3.6/proto/rip/rip.c	2012-02-18 12:48:50.000000000 +0100
@@ -281,7 +281,7 @@ rip_rte_update_if_better(rtable *tab, ne
  * bird core with this route.
  */
 static void
-advertise_entry( struct proto *p, struct rip_block *b, ip_addr whotoldme )
+advertise_entry( struct proto *p, struct rip_block *b, ip_addr whotoldme, struct iface *iface )
 {
   rta *a, A;
   rte *r;
@@ -309,7 +309,7 @@ advertise_entry( struct proto *p, struct
 
   /* No need to look if destination looks valid - ie not net 0 or 127 -- core will do for us. */
 
-  neighbor = neigh_find( p, &A.gw, 0 );
+  neighbor = neigh_find2( p, &A.gw, iface, 0 );
   if (!neighbor) {
     log( L_REMOTE "%s: %I asked me to route %I/%d using not-neighbor %I.", p->name, A.from, b->network, pxlen, A.gw );
     return;
@@ -353,7 +353,7 @@ advertise_entry( struct proto *p, struct
  * process_block - do some basic check and pass block to advertise_entry
  */
 static void
-process_block( struct proto *p, struct rip_block *block, ip_addr whotoldme )
+process_block( struct proto *p, struct rip_block *block, ip_addr whotoldme, struct iface *iface )
 {
 #ifndef IPV6
   int metric = ntohl( block->metric );
@@ -380,7 +380,7 @@ process_block( struct proto *p, struct r
     return;
   }
 
-  advertise_entry( p, block, whotoldme );
+  advertise_entry( p, block, whotoldme, iface );
 }
 
 #define BAD( x ) { log( L_REMOTE "%s: " x, p->name ); return 1; }
@@ -389,7 +389,7 @@ process_block( struct proto *p, struct r
  * rip_process_packet - this is main routine for incoming packets.
  */
 static int
-rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr whotoldme, int port )
+rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr whotoldme, int port, struct iface *iface )
 {
   int i;
   int authenticated = 0;
@@ -406,7 +406,7 @@ rip_process_packet( struct proto *p, str
 	  if (P_CF->honor == HO_NEVER)
 	    BAD( "They asked me to send routing table, but I was told not to do it" );
 
-	  if ((P_CF->honor == HO_NEIGHBOR) && (!neigh_find( p, &whotoldme, 0 )))
+	  if ((P_CF->honor == HO_NEIGHBOR) && (!neigh_find2( p, &whotoldme, iface, 0 )))
 	    BAD( "They asked me to send routing table, but he is not my neighbor" );
     	  rip_sendto( p, whotoldme, port, HEAD(P->interfaces) ); /* no broadcast */
           break;
@@ -416,7 +416,7 @@ rip_process_packet( struct proto *p, str
 	    return 1;
 	  }
 
-	  if (!(neighbor = neigh_find( p, &whotoldme, 0 )) || neighbor->scope == SCOPE_HOST) {
+	  if (!(neighbor = neigh_find2( p, &whotoldme, iface, 0 )) || neighbor->scope == SCOPE_HOST) {
 	    log( L_REMOTE "%s: %I send me routing info but he is not my neighbor", p->name, whotoldme );
 	    return 0;
 	  }
@@ -443,7 +443,7 @@ rip_process_packet( struct proto *p, str
 	    if (packet->heading.version == RIP_V1)	/* FIXME (nonurgent): switch to disable this? */
 	      block->netmask = ipa_class_mask(block->network);
 #endif
-	    process_block( p, block, whotoldme );
+	    process_block( p, block, whotoldme, iface );
 	  }
           break;
   case RIPCMD_TRACEON:
@@ -463,12 +463,20 @@ rip_rx(sock *s, int size)
 {
   struct rip_interface *i = s->data;
   struct proto *p = i->proto;
+  struct iface *iface = NULL;
   int num;
 
   /* In non-listening mode, just ignore packet */
   if (i->mode & IM_NOLISTEN)
     return 1;
 
+#ifdef IPV6
+  if (! i->iface || s->lifindex != i->iface->index)
+    return 1;
+
+  iface = i->iface;
+#endif
+
   CHK_MAGIC;
   DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, i->iface ? i->iface->name : "(dummy)" );
   size -= sizeof( struct rip_packet_heading );
@@ -477,17 +485,12 @@ rip_rx(sock *s, int size)
   num = size / sizeof( struct rip_block );
   if (num>PACKET_MAX) BAD( "Too many blocks" );
 
-#ifdef IPV6
-  /* Try to absolutize link scope addresses */
-  ipa_absolutize(&s->faddr, &i->iface->addr->ip);
-#endif
-
   if (ipa_equal(i->iface->addr->ip, s->faddr)) {
     DBG("My own packet\n");
     return 1;
   }
 
-  rip_process_packet( p, (struct rip_packet *) s->rbuf, num, s->faddr, s->fport );
+  rip_process_packet( p, (struct rip_packet *) s->rbuf, num, s->faddr, s->fport, iface );
   return 1;
 }
 
@@ -701,6 +704,7 @@ new_iface(struct proto *p, struct iface 
     {
       rif->sock->ttl = 1;
       rif->sock->tos = IP_PREC_INTERNET_CONTROL;
+      rif->sock->flags = SKF_LADDR_RX;
     }
 
   if (new) {
@@ -712,7 +716,6 @@ new_iface(struct proto *p, struct iface 
       rif->sock->daddr = ipa_from_u32(0xe0000009);
 #else
       rif->sock->daddr = ipa_build(0xff020000, 0, 0, 9);
-      rif->sock->saddr = new->addr->ip; /* Does not really work on Linux */
 #endif
     } else {
       rif->sock->daddr = new->addr->brd;
