#include <net/ip6_route.h>
#include <net/xfrm.h>
#include <net/ip6_checksum.h>
+#include <net/netfilter/nf_queue.h>
int ip6_route_me_harder(struct sk_buff *skb)
{
.saddr = iph->saddr, } },
};
- dst = ip6_route_output(skb->sk, &fl);
+ dst = ip6_route_output(&init_net, skb->sk, &fl);
#ifdef CONFIG_XFRM
if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
struct in6_addr saddr;
};
-static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
+static void nf_ip6_saveroute(const struct sk_buff *skb,
+ struct nf_queue_entry *entry)
{
- struct ip6_rt_info *rt_info = nf_info_reroute(info);
+ struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
- if (info->hook == NF_IP6_LOCAL_OUT) {
+ if (entry->hook == NF_INET_LOCAL_OUT) {
struct ipv6hdr *iph = ipv6_hdr(skb);
rt_info->daddr = iph->daddr;
}
}
-static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip6_reroute(struct sk_buff *skb,
+ const struct nf_queue_entry *entry)
{
- struct ip6_rt_info *rt_info = nf_info_reroute(info);
+ struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
- if (info->hook == NF_IP6_LOCAL_OUT) {
- struct ipv6hdr *iph = ipv6_hdr(*pskb);
+ if (entry->hook == NF_INET_LOCAL_OUT) {
+ struct ipv6hdr *iph = ipv6_hdr(skb);
if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
!ipv6_addr_equal(&iph->saddr, &rt_info->saddr))
- return ip6_route_me_harder(*pskb);
+ return ip6_route_me_harder(skb);
}
return 0;
}
+static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl)
+{
+ *dst = ip6_route_output(&init_net, NULL, fl);
+ return (*dst)->error;
+}
+
__sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol)
{
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
- if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
+ if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN)
break;
if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
skb->len - dataoff, protocol,
}
return csum;
}
-
EXPORT_SYMBOL(nf_ip6_checksum);
-static struct nf_afinfo nf_ip6_afinfo = {
- .family = AF_INET6,
- .checksum = nf_ip6_checksum,
- .saveroute = nf_ip6_saveroute,
- .reroute = nf_ip6_reroute,
- .route_key_size = sizeof(struct ip6_rt_info),
+static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, unsigned int len,
+ u_int8_t protocol)
+{
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ __wsum hsum;
+ __sum16 csum = 0;
+
+ switch (skb->ip_summed) {
+ case CHECKSUM_COMPLETE:
+ if (len == skb->len - dataoff)
+ return nf_ip6_checksum(skb, hook, dataoff, protocol);
+ /* fall through */
+ case CHECKSUM_NONE:
+ hsum = skb_checksum(skb, 0, dataoff, 0);
+ skb->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr,
+ &ip6h->daddr,
+ skb->len - dataoff,
+ protocol,
+ csum_sub(0, hsum)));
+ skb->ip_summed = CHECKSUM_NONE;
+ csum = __skb_checksum_complete_head(skb, dataoff + len);
+ if (!csum)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+ return csum;
+};
+
+static const struct nf_afinfo nf_ip6_afinfo = {
+ .family = AF_INET6,
+ .checksum = nf_ip6_checksum,
+ .checksum_partial = nf_ip6_checksum_partial,
+ .route = nf_ip6_route,
+ .saveroute = nf_ip6_saveroute,
+ .reroute = nf_ip6_reroute,
+ .route_key_size = sizeof(struct ip6_rt_info),
};
int __init ipv6_netfilter_init(void)