aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVince Busam <vbusam@google.com>2008-09-02 09:55:52 -0400
committerSimon Horman <horms@verge.net.au>2008-09-04 21:17:12 -0400
commit09571c7ae30865adfa79dccd12a822a65d2c4b5a (patch)
tree4a6b129d70b8dab77bb8f80fff98d9827a5a06ef /net
parenta0eb662f9ec8962928d937a185ad128db12c4637 (diff)
IPVS: Add function to determine if IPv6 address is local
Add __ip_vs_addr_is_local_v6() to find out if an IPv6 address belongs to a local interface. Use this function to decide whether to set the IP_VS_CONN_F_LOCALNODE flag for IPv6 destinations. Signed-off-by: Vince Busam <vbusam@google.com> Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c56
1 files changed, 49 insertions, 7 deletions
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 25d9e98e31fa..640203a153c6 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -35,6 +35,10 @@
35 35
36#include <net/net_namespace.h> 36#include <net/net_namespace.h>
37#include <net/ip.h> 37#include <net/ip.h>
38#ifdef CONFIG_IP_VS_IPV6
39#include <net/ipv6.h>
40#include <net/ip6_route.h>
41#endif
38#include <net/route.h> 42#include <net/route.h>
39#include <net/sock.h> 43#include <net/sock.h>
40#include <net/genetlink.h> 44#include <net/genetlink.h>
@@ -91,6 +95,26 @@ int ip_vs_get_debug_level(void)
91} 95}
92#endif 96#endif
93 97
98#ifdef CONFIG_IP_VS_IPV6
99/* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */
100static int __ip_vs_addr_is_local_v6(const struct in6_addr *addr)
101{
102 struct rt6_info *rt;
103 struct flowi fl = {
104 .oif = 0,
105 .nl_u = {
106 .ip6_u = {
107 .daddr = *addr,
108 .saddr = { .s6_addr32 = {0, 0, 0, 0} }, } },
109 };
110
111 rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
112 if (rt && rt->rt6i_dev && (rt->rt6i_dev->flags & IFF_LOOPBACK))
113 return 1;
114
115 return 0;
116}
117#endif
94/* 118/*
95 * update_defense_level is called from keventd and from sysctl, 119 * update_defense_level is called from keventd and from sysctl,
96 * so it needs to protect itself from softirqs 120 * so it needs to protect itself from softirqs
@@ -751,10 +775,18 @@ __ip_vs_update_dest(struct ip_vs_service *svc,
751 conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE; 775 conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE;
752 776
753 /* check if local node and update the flags */ 777 /* check if local node and update the flags */
754 if (inet_addr_type(&init_net, udest->addr.ip) == RTN_LOCAL) { 778#ifdef CONFIG_IP_VS_IPV6
755 conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK) 779 if (svc->af == AF_INET6) {
756 | IP_VS_CONN_F_LOCALNODE; 780 if (__ip_vs_addr_is_local_v6(&udest->addr.in6)) {
757 } 781 conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
782 | IP_VS_CONN_F_LOCALNODE;
783 }
784 } else
785#endif
786 if (inet_addr_type(&init_net, udest->addr.ip) == RTN_LOCAL) {
787 conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
788 | IP_VS_CONN_F_LOCALNODE;
789 }
758 790
759 /* set the IP_VS_CONN_F_NOOUTPUT flag if not masquerading/NAT */ 791 /* set the IP_VS_CONN_F_NOOUTPUT flag if not masquerading/NAT */
760 if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != 0) { 792 if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != 0) {
@@ -803,9 +835,19 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
803 835
804 EnterFunction(2); 836 EnterFunction(2);
805 837
806 atype = inet_addr_type(&init_net, udest->addr.ip); 838#ifdef CONFIG_IP_VS_IPV6
807 if (atype != RTN_LOCAL && atype != RTN_UNICAST) 839 if (svc->af == AF_INET6) {
808 return -EINVAL; 840 atype = ipv6_addr_type(&udest->addr.in6);
841 if (!(atype & IPV6_ADDR_UNICAST) &&
842 !__ip_vs_addr_is_local_v6(&udest->addr.in6))
843 return -EINVAL;
844 } else
845#endif
846 {
847 atype = inet_addr_type(&init_net, udest->addr.ip);
848 if (atype != RTN_LOCAL && atype != RTN_UNICAST)
849 return -EINVAL;
850 }
809 851
810 dest = kzalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC); 852 dest = kzalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC);
811 if (dest == NULL) { 853 if (dest == NULL) {