diff options
-rw-r--r-- | include/linux/netfilter.h | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter.c | 6 | ||||
-rw-r--r-- | net/ipv6/netfilter.c | 7 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_h323_main.c | 19 |
4 files changed, 27 insertions, 7 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index f42e4362d50d..9bfc7d4f5868 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
@@ -298,10 +298,12 @@ extern void nf_invalidate_cache(int pf); | |||
298 | Returns true or false. */ | 298 | Returns true or false. */ |
299 | extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len); | 299 | extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len); |
300 | 300 | ||
301 | struct flowi; | ||
301 | struct nf_afinfo { | 302 | struct nf_afinfo { |
302 | unsigned short family; | 303 | unsigned short family; |
303 | __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, | 304 | __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, |
304 | unsigned int dataoff, u_int8_t protocol); | 305 | unsigned int dataoff, u_int8_t protocol); |
306 | int (*route)(struct dst_entry **dst, struct flowi *fl); | ||
305 | void (*saveroute)(const struct sk_buff *skb, | 307 | void (*saveroute)(const struct sk_buff *skb, |
306 | struct nf_info *info); | 308 | struct nf_info *info); |
307 | int (*reroute)(struct sk_buff *skb, | 309 | int (*reroute)(struct sk_buff *skb, |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index d9022467e089..599d448ef57e 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -182,9 +182,15 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, | |||
182 | 182 | ||
183 | EXPORT_SYMBOL(nf_ip_checksum); | 183 | EXPORT_SYMBOL(nf_ip_checksum); |
184 | 184 | ||
185 | static int nf_ip_route(struct dst_entry **dst, struct flowi *fl) | ||
186 | { | ||
187 | return ip_route_output_key((struct rtable **)dst, fl); | ||
188 | } | ||
189 | |||
185 | static struct nf_afinfo nf_ip_afinfo = { | 190 | static struct nf_afinfo nf_ip_afinfo = { |
186 | .family = AF_INET, | 191 | .family = AF_INET, |
187 | .checksum = nf_ip_checksum, | 192 | .checksum = nf_ip_checksum, |
193 | .route = nf_ip_route, | ||
188 | .saveroute = nf_ip_saveroute, | 194 | .saveroute = nf_ip_saveroute, |
189 | .reroute = nf_ip_reroute, | 195 | .reroute = nf_ip_reroute, |
190 | .route_key_size = sizeof(struct ip_rt_info), | 196 | .route_key_size = sizeof(struct ip_rt_info), |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 175e19f80253..281f732e3c97 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -81,6 +81,12 @@ static int nf_ip6_reroute(struct sk_buff *skb, const struct nf_info *info) | |||
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
83 | 83 | ||
84 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) | ||
85 | { | ||
86 | *dst = ip6_route_output(NULL, fl); | ||
87 | return (*dst)->error; | ||
88 | } | ||
89 | |||
84 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, | 90 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, |
85 | unsigned int dataoff, u_int8_t protocol) | 91 | unsigned int dataoff, u_int8_t protocol) |
86 | { | 92 | { |
@@ -118,6 +124,7 @@ EXPORT_SYMBOL(nf_ip6_checksum); | |||
118 | static struct nf_afinfo nf_ip6_afinfo = { | 124 | static struct nf_afinfo nf_ip6_afinfo = { |
119 | .family = AF_INET6, | 125 | .family = AF_INET6, |
120 | .checksum = nf_ip6_checksum, | 126 | .checksum = nf_ip6_checksum, |
127 | .route = nf_ip6_route, | ||
121 | .saveroute = nf_ip6_saveroute, | 128 | .saveroute = nf_ip6_saveroute, |
122 | .reroute = nf_ip6_reroute, | 129 | .reroute = nf_ip6_reroute, |
123 | .route_key_size = sizeof(struct ip6_rt_info), | 130 | .route_key_size = sizeof(struct ip6_rt_info), |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index f23fd9598e19..c550257b5462 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -708,9 +708,15 @@ static int callforward_do_filter(union nf_conntrack_address *src, | |||
708 | union nf_conntrack_address *dst, | 708 | union nf_conntrack_address *dst, |
709 | int family) | 709 | int family) |
710 | { | 710 | { |
711 | struct nf_afinfo *afinfo; | ||
711 | struct flowi fl1, fl2; | 712 | struct flowi fl1, fl2; |
712 | int ret = 0; | 713 | int ret = 0; |
713 | 714 | ||
715 | /* rcu_read_lock()ed by nf_hook_slow() */ | ||
716 | afinfo = nf_get_afinfo(family); | ||
717 | if (!afinfo) | ||
718 | return 0; | ||
719 | |||
714 | memset(&fl1, 0, sizeof(fl1)); | 720 | memset(&fl1, 0, sizeof(fl1)); |
715 | memset(&fl2, 0, sizeof(fl2)); | 721 | memset(&fl2, 0, sizeof(fl2)); |
716 | 722 | ||
@@ -720,8 +726,8 @@ static int callforward_do_filter(union nf_conntrack_address *src, | |||
720 | 726 | ||
721 | fl1.fl4_dst = src->ip; | 727 | fl1.fl4_dst = src->ip; |
722 | fl2.fl4_dst = dst->ip; | 728 | fl2.fl4_dst = dst->ip; |
723 | if (ip_route_output_key(&rt1, &fl1) == 0) { | 729 | if (!afinfo->route((struct dst_entry **)&rt1, &fl1)) { |
724 | if (ip_route_output_key(&rt2, &fl2) == 0) { | 730 | if (!afinfo->route((struct dst_entry **)&rt2, &fl2)) { |
725 | if (rt1->rt_gateway == rt2->rt_gateway && | 731 | if (rt1->rt_gateway == rt2->rt_gateway && |
726 | rt1->u.dst.dev == rt2->u.dst.dev) | 732 | rt1->u.dst.dev == rt2->u.dst.dev) |
727 | ret = 1; | 733 | ret = 1; |
@@ -731,16 +737,15 @@ static int callforward_do_filter(union nf_conntrack_address *src, | |||
731 | } | 737 | } |
732 | break; | 738 | break; |
733 | } | 739 | } |
734 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 740 | #if defined(CONFIG_NF_CONNTRACK_IPV6) || \ |
741 | defined(CONFIG_NF_CONNTRACK_IPV6_MODULE) | ||
735 | case AF_INET6: { | 742 | case AF_INET6: { |
736 | struct rt6_info *rt1, *rt2; | 743 | struct rt6_info *rt1, *rt2; |
737 | 744 | ||
738 | memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst)); | 745 | memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst)); |
739 | memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst)); | 746 | memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst)); |
740 | rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1); | 747 | if (!afinfo->route((struct dst_entry **)&rt1, &fl1)) { |
741 | if (rt1) { | 748 | if (!afinfo->route((struct dst_entry **)&rt2, &fl2)) { |
742 | rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2); | ||
743 | if (rt2) { | ||
744 | if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, | 749 | if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, |
745 | sizeof(rt1->rt6i_gateway)) && | 750 | sizeof(rt1->rt6i_gateway)) && |
746 | rt1->u.dst.dev == rt2->u.dst.dev) | 751 | rt1->u.dst.dev == rt2->u.dst.dev) |