Authors of tunnel (or encapsulation) drivers should follow two
simple rules for the 2.4 kernel (as do the drivers inside the kernel,
like net/ipv4/ipip.c):
Release skb->nfct if you're going to make the packet unrecognisable
(ie. decapsulating/encapsulating). You don't need to do this if you
unwrap it into a *new* skb, but if you're going to do it in place, you
must do this.
Otherwise: the NAT code will use the old connection tracking
information to mangle the packet, with bad consequences.
Make sure the encapsulated packets go through the LOCAL_OUT
hook, and decapsulated packets go through the PRE_ROUTING hook (most
tunnels use ip_rcv(), which does this for you).
Otherwise: the user will not be able to filter as they expect to with
tunnels.
The canonical way to do the first is to insert code like the
following before you wrap or unwrap the packet:
/* Tell the netfilter framework that this packet is not the
same as the one before! */
#ifdef CONFIG_NETFILTER
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
#ifdef CONFIG_NETFILTER_DEBUG
skb->nf_debug = 0;
#endif
#endif
Usually, all you need to do for the second, is to find where the
newly encapsulated packet goes into "ip_send()", and replace it with
something like:
/* Send "new" packet from local host */
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, ip_send);
Following these rules means that the person setting up the packet
filtering rules on the tunnel box will see something like the
following sequence for a packet being tunnelled: