From 344a2eeeaee7bd00ac6efa50ae612dac3db25c96 Mon Sep 17 00:00:00 2001
From: Noriaki Takamiya <takamiya@neon.(none)>
Date: Tue, 20 Feb 2007 12:02:21 +0900
Subject: [KERNELIF] MULTIPLETABLE: fixed the usage of multiple routing tables

* adds the flag while inserting the fib6_rule entry for RT6_TABLE_MIP6.
* deletes the source address of HoA while inserting the default route in the
  RT6_TABLE_MIP6.
---
 src/ha.c       |    4 ++--
 src/mn.c       |   16 +++++++++-------
 src/movement.c |   16 ++++++++--------
 src/rtnl.c     |   17 +++++++++--------
 src/rtnl.h     |    4 ++--
 5 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/src/ha.c b/src/ha.c
index 998f978..f6d5cda 100644
--- a/src/ha.c
+++ b/src/ha.c
@@ -985,7 +985,7 @@ int ha_init(void)
 		return -1;
 	if (rule_add(NULL, RT6_TABLE_MIP6,
 		     IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-		     &in6addr_any, 0, &in6addr_any, 0) < 0)
+		     &in6addr_any, 0, &in6addr_any, 0, 0) < 0)
 		return -1;
 	icmp6_handler_reg(ND_ROUTER_ADVERT, &ha_ra_handler);
 	mh_handler_reg(IP6_MH_TYPE_BU, &ha_bu_handler);
@@ -1003,7 +1003,7 @@ void ha_cleanup(void)
 	bcache_flush();
 	rule_del(NULL, RT6_TABLE_MIP6,
 		 IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-		 &in6addr_any, 0, &in6addr_any, 0);
+		 &in6addr_any, 0, &in6addr_any, 0, 0);
 	mpd_ha_cleanup();
 	dhaad_ha_cleanup();
 }
diff --git a/src/mn.c b/src/mn.c
index cf62a27..50fb79c 100644
--- a/src/mn.c
+++ b/src/mn.c
@@ -41,6 +41,8 @@
 #include <netinet/in.h>
 #include <netinet/ip6.h>
 
+#include <linux/fib_rules.h>
+
 #include "debug.h"
 #include "mipv6.h"
 #include "icmp6.h"
@@ -580,7 +582,7 @@ static int mn_tnl_state_add(struct home_addr_info *hai, int ifindex, int all)
 		if ((err = mn_ro_pol_add(hai, ifindex, all)) < 0)
 			return err;
 		if ((err = route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP, 0,
-				     IP6_RT_PRIO_MIP6_OUT, &hai->hoa.addr, 128,
+				     IP6_RT_PRIO_MIP6_OUT, &in6addr_any, 0,
 				     &in6addr_any, 0, NULL)) < 0) {
 			mn_ro_pol_del(hai, ifindex, all);
 		}
@@ -1221,10 +1223,10 @@ static void clean_home_addr_info(struct home_addr_info *hai)
 	bul_home_cleanup(&hai->bul);
 	rule_del(NULL, 0,
 		 IP6_RULE_PRIO_MIP6_BLOCK, RTN_BLACKHOLE,
-		 &hai->hoa.addr, 128, &in6addr_any, 0);
+		 &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR);
 	rule_del(NULL, RT6_TABLE_MIP6,
 		 IP6_RULE_PRIO_MIP6_HOA_OUT, RTN_UNICAST,
-		 &hai->hoa.addr, 128, &in6addr_any, 0);
+		 &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR);
 	tunnel_del(hai->if_tunnel, NULL, NULL);
 	dhaad_stop(hai);
 	free(hai);
@@ -1308,12 +1310,12 @@ static int conf_home_addr_info(struct home_addr_info *conf_hai)
 	}
 	if (rule_add(NULL, RT6_TABLE_MIP6,
 		     IP6_RULE_PRIO_MIP6_HOA_OUT, RTN_UNICAST,
-		     &hai->hoa.addr, 128, &in6addr_any, 0) < 0) {
+		     &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR) < 0) {
 		goto clean_err;
 	}
 	if (rule_add(NULL, 0,
 		     IP6_RULE_PRIO_MIP6_BLOCK, RTN_BLACKHOLE,
-		     &hai->hoa.addr, 128, &in6addr_any, 0) < 0) {
+		     &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR) < 0) {
 		goto clean_err;
 	}
 	if(bul_home_init(hai)) {
@@ -1488,14 +1490,14 @@ static inline void linklocal_rt_rules_del(void)
 {
 	rule_del(NULL, RT6_TABLE_MAIN,
 		 IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
-		 &linklocal_prefix, 64, &in6addr_any, 0);
+		 &linklocal_prefix, 64, &in6addr_any, 0, 0);
 }
 
 static inline int linklocal_rt_rules_add(void)
 {
 	return rule_add(NULL, RT6_TABLE_MAIN,
 			IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
-			&linklocal_prefix, 64, &in6addr_any, 0);
+			&linklocal_prefix, 64, &in6addr_any, 0, 0);
 }
 
 static int mn_ext_tunnel_ops(int request, int old_if, int new_if, void *data)
diff --git a/src/movement.c b/src/movement.c
index 8dda13c..2a5fb39 100644
--- a/src/movement.c
+++ b/src/movement.c
@@ -167,9 +167,9 @@ static void md_prefix_rule_del(struct prefix_list_entry *p)
 {
 	struct in6_addr prefix;
 	ipv6_addr_prefix(&prefix, &p->ple_prefix, p->ple_plen);
-	rule_del(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT, 
+	rule_del(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT,
 		 RTN_UNICAST, &prefix, p->ple_plen,
-		 &in6addr_any, 0);
+		 &in6addr_any, 0, 0);
 }
 
 static void __md_free_router(struct md_router *rtr)
@@ -287,9 +287,9 @@ static void md_expire_router(struct md_inet6_iface *iface,
 static void md_block_rule_del(struct md_inet6_iface *iface)
 {
 	rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK, RTN_BLACKHOLE,
-		 &in6addr_any, 0, &in6addr_any, 0);
+		 &in6addr_any, 0, &in6addr_any, 0, 0);
 	rule_del(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
-		 &in6addr_any, 128, &in6addr_any, 0);
+		 &in6addr_any, 128, &in6addr_any, 0, 0);
 	iface->iface_flags &= ~MD_BLOCK_TRAFFIC;
 }
 
@@ -1254,9 +1254,9 @@ static void md_prefix_rule_add(struct prefix_list_entry *p)
 {
 	struct in6_addr prefix;
 	ipv6_addr_prefix(&prefix, &p->ple_prefix, p->ple_plen);
-	rule_add(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT, 
+	rule_add(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT,
 		 RTN_UNICAST, &prefix, p->ple_plen,
-		 &in6addr_any, 0);
+		 &in6addr_any, 0, 0);
 }
 
 static void md_update_router(struct md_router *new, struct md_router *old)
@@ -1327,13 +1327,13 @@ static int md_block_rule_add(struct md_inet6_iface *iface)
 	/* Allow DAD probes and RS messages */
 	rule_add(NULL, RT6_TABLE_MAIN,
 		 IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
-		 &in6addr_any, 128, &in6addr_any, 0);	
+		 &in6addr_any, 128, &in6addr_any, 0, 0);
 	/* drop outgoing global traffic until DAD has been performed
 	   on CoA to make routing and tunnel end-point updates atomic
 	   during handoff */
 	return rule_add(NULL, 0,
 			IP6_RULE_PRIO_MIP6_BLOCK, RTN_BLACKHOLE,
-			&in6addr_any, 0, &in6addr_any, 0);
+			&in6addr_any, 0, &in6addr_any, 0, 0);
 }
 
 static void md_add_default_router(struct md_inet6_iface *iface,
diff --git a/src/rtnl.c b/src/rtnl.c
index 98cbb65..48fa10d 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -298,10 +298,10 @@ int route_del(int oif, uint8_t table, uint32_t metric,
 			 0, metric, src, src_plen, dst, dst_plen, gateway);
 }
 
-static int rule_mod(const char *iface, int cmd, uint8_t table, 
+static int rule_mod(const char *iface, int cmd, uint8_t table,
 		    uint32_t priority, uint8_t action,
 		    const struct in6_addr *src, int src_plen,
-		    const struct in6_addr *dst, int dst_plen)
+		    const struct in6_addr *dst, int dst_plen, int flags)
 {
 	uint8_t buf[512];
 	struct nlmsghdr *n;
@@ -324,6 +324,7 @@ static int rule_mod(const char *iface, int cmd, uint8_t table,
 	rtm->rtm_table = table;
 	rtm->rtm_scope = RT_SCOPE_UNIVERSE;
 	rtm->rtm_type = action;
+	rtm->rtm_flags = flags;
 
 	addattr_l(n, sizeof(buf), RTA_DST, dst, sizeof(*dst));
 	if (src)
@@ -350,11 +351,11 @@ static int rule_mod(const char *iface, int cmd, uint8_t table,
 int rule_add(const char *iface, uint8_t table,
 	     uint32_t priority, uint8_t action,
 	     const struct in6_addr *src, int src_plen,
-	     const struct in6_addr *dst, int dst_plen)
+	     const struct in6_addr *dst, int dst_plen, int flags)
 {
-	return rule_mod(iface, RTM_NEWRULE, table, 
+	return rule_mod(iface, RTM_NEWRULE, table,
 			priority, action,
-			src, src_plen, dst, dst_plen);
+			src, src_plen, dst, dst_plen, flags);
 }
 
 /**
@@ -371,11 +372,11 @@ int rule_add(const char *iface, uint8_t table,
 int rule_del(const char *iface, uint8_t table,
 	     uint32_t priority, uint8_t action,
 	     const struct in6_addr *src, int src_plen,
-	     const struct in6_addr *dst, int dst_plen)
+	     const struct in6_addr *dst, int dst_plen, int flags)
 {
-	return rule_mod(iface, RTM_DELRULE, table, 
+	return rule_mod(iface, RTM_DELRULE, table,
 			priority, action,
-			src, src_plen, dst, dst_plen);
+			src, src_plen, dst, dst_plen, flags);
 }
 
 int rtnl_iterate(int proto, int type, rtnl_filter_t func, void *extarg)
diff --git a/src/rtnl.h b/src/rtnl.h
index d6c3f93..26cd452 100644
--- a/src/rtnl.h
+++ b/src/rtnl.h
@@ -74,12 +74,12 @@ int route_del(int oif, uint8_t table, uint32_t metric,
 int rule_add(const char *iface, uint8_t table,
 	     uint32_t priority, uint8_t action,
 	     const struct in6_addr *src, int src_plen,
-	     const struct in6_addr *dst, int dst_plen);
+	     const struct in6_addr *dst, int dst_plen, int flags);
 
 int rule_del(const char *iface, uint8_t table,
 	     uint32_t priority, uint8_t action,
 	     const struct in6_addr *src, int src_plen,
-	     const struct in6_addr *dst, int dst_plen);
+	     const struct in6_addr *dst, int dst_plen,int flags);
 
 int rtnl_iterate(int proto, int type, rtnl_filter_t func, void *extarg);
 
-- 
1.5.0.3

