#include <net/ipip.h>
#include <net/arp.h>
#include <net/checksum.h>
+#include <net/dsfield.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
#define tunnels_l (tunnels[1])
#define tunnels_wc (tunnels[0])
-static rwlock_t ipgre_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipgre_lock);
/* Given src, dst and key, find appropriate for input tunnel. */
}
-void ipgre_err(struct sk_buff *skb, u32 info)
+static void ipgre_err(struct sk_buff *skb, u32 info)
{
#ifndef I_WISH_WORLD_WERE_PERFECT
/* change mtu on this route */
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
- if (rel_info > dst_pmtu(skb2->dst)) {
+ if (rel_info > dst_mtu(skb2->dst)) {
kfree_skb(skb2);
return;
}
{
if (INET_ECN_is_ce(iph->tos)) {
if (skb->protocol == htons(ETH_P_IP)) {
- if (INET_ECN_is_not_ce(skb->nh.iph->tos))
- IP_ECN_set_ce(skb->nh.iph);
+ IP_ECN_set_ce(skb->nh.iph);
} else if (skb->protocol == htons(ETH_P_IPV6)) {
- if (INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
- IP6_ECN_set_ce(skb->nh.ipv6h);
+ IP6_ECN_set_ce(skb->nh.ipv6h);
}
}
}
if (skb->protocol == htons(ETH_P_IP))
inner = old_iph->tos;
else if (skb->protocol == htons(ETH_P_IPV6))
- inner = ip6_get_dsfield((struct ipv6hdr*)old_iph);
+ inner = ipv6_get_dsfield((struct ipv6hdr *)old_iph);
return INET_ECN_encapsulate(tos, inner);
}
-int ipgre_rcv(struct sk_buff *skb)
+static int ipgre_rcv(struct sk_buff *skb)
{
struct iphdr *iph;
u8 *h;
if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
secpath_reset(skb);
+ skb->protocol = *(u16*)(h + 2);
+ /* WCCP version 1 and 2 protocol decoding.
+ * - Change protocol to IP
+ * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
+ */
+ if (flags == 0 &&
+ skb->protocol == __constant_htons(ETH_P_WCCP)) {
+ skb->protocol = __constant_htons(ETH_P_IP);
+ if ((*(h + offset) & 0xF0) != 0x40)
+ offset += 4;
+ }
+
skb->mac.raw = skb->nh.raw;
skb->nh.raw = __pskb_pull(skb, offset);
+ skb_postpull_rcsum(skb, skb->mac.raw, offset);
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
- if (skb->ip_summed == CHECKSUM_HW)
- skb->csum = csum_sub(skb->csum,
- csum_partial(skb->mac.raw, skb->nh.raw-skb->mac.raw, 0));
- skb->protocol = *(u16*)(h + 2);
skb->pkt_type = PACKET_HOST;
#ifdef CONFIG_NET_IPGRE_BROADCAST
if (MULTICAST(iph->daddr)) {
skb->dev = tunnel->dev;
dst_release(skb->dst);
skb->dst = NULL;
-#ifdef CONFIG_NETFILTER
- nf_conntrack_put(skb->nfct);
- skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug = 0;
-#endif
-#endif
+ nf_reset(skb);
ipgre_ecn_decapsulate(iph, skb);
netif_rx(skb);
read_unlock(&ipgre_lock);
df = tiph->frag_off;
if (df)
- mtu = dst_pmtu(&rt->u.dst) - tunnel->hlen;
+ mtu = dst_mtu(&rt->u.dst) - tunnel->hlen;
else
- mtu = skb->dst ? dst_pmtu(skb->dst) : dev->mtu;
+ mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu;
if (skb->dst)
skb->dst->ops->update_pmtu(skb->dst, mtu);
else if (skb->protocol == htons(ETH_P_IPV6)) {
struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
- if (rt6 && mtu < dst_pmtu(skb->dst) && mtu >= IPV6_MIN_MTU) {
+ if (rt6 && mtu < dst_mtu(skb->dst) && mtu >= IPV6_MIN_MTU) {
if ((tunnel->parms.iph.daddr && !MULTICAST(tunnel->parms.iph.daddr)) ||
rt6->rt6i_dst.plen == 128) {
rt6->rt6i_flags |= RTF_MODIFIED;
}
}
-#ifdef CONFIG_NETFILTER
- nf_conntrack_put(skb->nfct);
- skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug = 0;
-#endif
-#endif
+ nf_reset(skb);
IPTUNNEL_XMIT();
tunnel->recursion--;
}
-static struct inet_protocol ipgre_protocol = {
+static struct net_protocol ipgre_protocol = {
.handler = ipgre_rcv,
.err_handler = ipgre_err,
};
static int __init ipgre_init(void)
{
- int err = -EINVAL;
+ int err;
printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
ipgre_tunnel_setup);
if (!ipgre_fb_tunnel_dev) {
err = -ENOMEM;
- goto fail;
+ goto err1;
}
ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init;
if ((err = register_netdev(ipgre_fb_tunnel_dev)))
- goto fail;
+ goto err2;
out:
return err;
-fail:
- inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+err2:
free_netdev(ipgre_fb_tunnel_dev);
+err1:
+ inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
goto out;
}
-void ipgre_fini(void)
+static void ipgre_fini(void)
{
if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
printk(KERN_INFO "ipgre close: can't remove protocol\n");