ipv6: Add ip6_redirect() and ip6_sk_redirect() helper functions.
authorDavid S. Miller <davem@davemloft.net>
Thu, 12 Jul 2012 07:08:07 +0000 (00:08 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 12 Jul 2012 07:08:07 +0000 (00:08 -0700)
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip6_route.h
net/ipv6/route.c

index 5cedbd7688c61b9aa1c966e0db91f8fdbd556599..693940565d8ab7166b8f70101bfa569328ee068c 100644 (file)
@@ -139,6 +139,8 @@ extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
                            int oif, u32 mark);
 extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
                               __be32 mtu);
+extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
 
 struct netlink_callback;
 
index 545b1526c1434e0b6186316912602f7e37376a15..f52cf83bb1e01d3554a73a2480dd278401be3cc3 100644 (file)
@@ -1114,6 +1114,33 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
 }
 EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
 
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
+{
+       const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
+       struct dst_entry *dst;
+       struct flowi6 fl6;
+
+       memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_oif = oif;
+       fl6.flowi6_mark = mark;
+       fl6.flowi6_flags = 0;
+       fl6.daddr = iph->daddr;
+       fl6.saddr = iph->saddr;
+       fl6.flowlabel = (*(__be32 *) iph) & IPV6_FLOWINFO_MASK;
+
+       dst = ip6_route_output(net, NULL, &fl6);
+       if (!dst->error)
+               rt6_do_redirect(dst, skb);
+       dst_release(dst);
+}
+EXPORT_SYMBOL_GPL(ip6_redirect);
+
+void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
+{
+       ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
+}
+EXPORT_SYMBOL_GPL(ip6_sk_redirect);
+
 static unsigned int ip6_default_advmss(const struct dst_entry *dst)
 {
        struct net_device *dev = dst->dev;