[PATCH] source ip selection for ipv6

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi folks

The attached patch implements source ip selection in routes for ipv6.

There a some issues left, which I can't solve:
- the route add code for ipv4 includes a check for loopback ips or so, I
  don't understand them and therefor can't convert it for ipv6.
- there is no check if the ip is local.

Bastian

Please cc.

-- 
Captain's Log, star date 21:34.5...
diff -ur linux-2.6.5.orig/include/linux/ipv6_route.h linux-2.6.5/include/linux/ipv6_route.h
--- linux-2.6.5.orig/include/linux/ipv6_route.h	2004-03-11 03:55:23.000000000 +0100
+++ linux-2.6.5/include/linux/ipv6_route.h	2004-04-16 19:17:26.000000000 +0200
@@ -30,6 +30,7 @@
 struct in6_rtmsg {
 	struct in6_addr		rtmsg_dst;
 	struct in6_addr		rtmsg_src;
+	struct in6_addr		rtmsg_prefsrc;
 	struct in6_addr		rtmsg_gateway;
 	__u32			rtmsg_type;
 	__u16			rtmsg_dst_len;
diff -ur linux-2.6.5.orig/include/net/ip6_fib.h linux-2.6.5/include/net/ip6_fib.h
--- linux-2.6.5.orig/include/net/ip6_fib.h	2004-03-11 03:55:37.000000000 +0100
+++ linux-2.6.5/include/net/ip6_fib.h	2004-04-16 19:53:08.000000000 +0200
@@ -71,6 +71,7 @@
 
 	struct rt6key			rt6i_dst;
 	struct rt6key			rt6i_src;
+	struct rt6key			rt6i_prefsrc;
 
 	u8				rt6i_protocol;
 };
diff -ur linux-2.6.5.orig/net/ipv6/ip6_output.c linux-2.6.5/net/ipv6/ip6_output.c
--- linux-2.6.5.orig/net/ipv6/ip6_output.c	2004-04-16 22:25:17.000000000 +0200
+++ linux-2.6.5/net/ipv6/ip6_output.c	2004-04-16 21:04:04.000000000 +0200
@@ -768,8 +768,13 @@
 	if ((err = (*dst)->error))
 		goto out_err_release;
 
 	if (ipv6_addr_any(&fl->fl6_src)) {
-		err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
+		struct rt6_info *rt = (struct rt6_info*)*dst;
+		/* XXX needs to check */
+		if (rt->rt6i_prefsrc.plen)
+			ipv6_addr_copy(&fl->fl6_src, &rt->rt6i_prefsrc.addr);
+		else
+			err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
 
 		if (err) {
 #if IP6_DEBUG >= 2
diff -ur linux-2.6.5.orig/net/ipv6/route.c linux-2.6.5/net/ipv6/route.c
--- linux-2.6.5.orig/net/ipv6/route.c	2004-03-11 03:55:37.000000000 +0100
+++ linux-2.6.5/net/ipv6/route.c	2004-04-16 21:40:42.000000000 +0200
@@ -702,7 +708,7 @@
 	struct rtattr **rta;
 	struct rt6_info *rt;
 	struct net_device *dev = NULL;
-	int addr_type;
+	int addr_type, i, j;
 
 	rta = (struct rtattr **) _rtattr;
 
@@ -758,6 +764,17 @@
 
 	rt->rt6i_metric = rtmsg->rtmsg_metric;
 
+	/* XXX is there another way to compare ipv6 addresses? */
+	for (i = 0, j = 0; i < 4; i++)
+		if (rtmsg->rtmsg_prefsrc.s6_addr32[i] != in6addr_any.s6_addr32[i])
+			j = 1;
+	if (j) {
+		memcpy(&rt->rt6i_prefsrc.addr, &rtmsg->rtmsg_prefsrc, 16);
+		rt->rt6i_prefsrc.plen = 128;
+	}
+	else
+		rt->rt6i_prefsrc.plen = 0;
+
 	/* We cannot add true routes via loopback here,
 	   they would result in kernel looping; promote them to reject routes
 	 */
@@ -837,6 +854,16 @@
 
 	rt->rt6i_flags = rtmsg->rtmsg_flags;
 
+	/* XXX: I don't understand this check */
+#if 0
+	if (rt->rt6i_prefsrc) {
+		if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
+				memcmp(&fi->fib_prefsrc, rta->rta_dst, 4))
+			if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
+				goto err_inval;
+	}
+#endif
+
 install_route:
 	if (rta && rta[RTA_METRICS-1]) {
 		int attrlen = RTA_PAYLOAD(rta[RTA_METRICS-1]);
@@ -1147,6 +1174,7 @@
 #ifdef CONFIG_IPV6_SUBTREES
 		memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
 #endif
+		memcpy(&rt->rt6i_prefsrc, &ort->rt6i_prefsrc, sizeof(struct rt6key));
 	}
 	return rt;
 }
@@ -1431,6 +1459,9 @@
 			return -EINVAL;
 		memcpy(&rtmsg->rtmsg_metric, RTA_DATA(rta[RTA_PRIORITY-1]), 4);
 	}
+	if (rta[RTA_PREFSRC-1]) {
+		memcpy(&rtmsg->rtmsg_prefsrc, RTA_DATA(rta[RTA_PREFSRC-1]), 16);
+	}
 	return 0;
 }
 
@@ -1523,11 +1554,9 @@
 #endif
 	if (iif)
 		RTA_PUT(skb, RTA_IIF, 4, &iif);
-	else if (dst) {
-		struct in6_addr saddr_buf;
-		if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
-			RTA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
-	}
+	if (rt->rt6i_prefsrc.plen)
+		RTA_PUT(skb, RTA_PREFSRC, 16, &rt->rt6i_prefsrc);
+
 	if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
 		goto rtattr_failure;
 	if (rt->u.dst.neighbour)

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux