@@ -24,7 +24,12 @@
const struct sk_buff *skb,
unsigned int dataoff,
struct ip_conntrack_tuple *tuple,
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ const struct ip_conntrack_protocol *protocol,
+ unsigned short vid);
+#else
const struct ip_conntrack_protocol *protocol);
+#endif
extern int
ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
@@ -79,15 +79,28 @@
/* The direction (for tuplehash) */
u_int8_t dir;
} dst;
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ __be16 vid;
+#endif
+
};
/* This is optimized opposed to a memset of the whole structure. Everything we
* really care about is the source/destination unions */
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
#define IP_CT_TUPLE_U_BLANK(tuple) \
do { \
(tuple)->src.u.all = 0; \
(tuple)->dst.u.all = 0; \
+ (tuple)->vid = 0; \
+ } while (0)
+#else
+#define IP_CT_TUPLE_U_BLANK(tuple) \
+ do { \
+ (tuple)->src.u.all = 0; \
+ (tuple)->dst.u.all = 0; \
} while (0)
+#endif
#ifdef __KERNEL__
@@ -125,10 +138,22 @@
&& t1->dst.protonum == t2->dst.protonum;
}
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+static inline int ip_ct_tuple_vlan_equal(const struct ip_conntrack_tuple *t1,
+ const struct ip_conntrack_tuple *t2)
+{
+ return t1->vid == t2->vid;
+}
+#endif
+
static inline int ip_ct_tuple_equal(const struct ip_conntrack_tuple *t1,
const struct ip_conntrack_tuple *t2)
{
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ return ip_ct_tuple_src_equal(t1, t2) && ip_ct_tuple_dst_equal(t1, t2) && ip_ct_tuple_vlan_equal(t1, t2);
+#else
return ip_ct_tuple_src_equal(t1, t2) && ip_ct_tuple_dst_equal(t1, t2);
+#endif
}
static inline int ip_ct_tuple_mask_cmp(const struct ip_conntrack_tuple *t,
@@ -45,6 +45,7 @@
#include <linux/percpu.h>
#include <linux/moduleparam.h>
#include <linux/notifier.h>
+#include <linux/if_vlan.h>
/* ip_conntrack_lock protects the main hash table, protocol/helper/expected
registrations, conntrack timers*/
@@ -181,7 +182,12 @@
const struct sk_buff *skb,
unsigned int dataoff,
struct ip_conntrack_tuple *tuple,
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ const struct ip_conntrack_protocol *protocol,
+ unsigned short vid)
+#else
const struct ip_conntrack_protocol *protocol)
+#endif
{
/* Never happen */
if (iph->frag_off & htons(IP_OFFSET)) {
@@ -194,6 +200,9 @@
tuple->dst.ip = iph->daddr;
tuple->dst.protonum = iph->protocol;
tuple->dst.dir = IP_CT_DIR_ORIGINAL;
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ tuple->vid = vid;
+#endif
return protocol->pkt_to_tuple(skb, dataoff, tuple);
}
@@ -206,6 +215,9 @@
inverse->src.ip = orig->dst.ip;
inverse->dst.ip = orig->src.ip;
inverse->dst.protonum = orig->dst.protonum;
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ inverse->vid = orig->vid;
+#endif
inverse->dst.dir = !orig->dst.dir;
return protocol->invert_tuple(inverse, orig);
@@ -779,11 +791,26 @@
struct ip_conntrack_tuple tuple;
struct ip_conntrack_tuple_hash *h;
struct ip_conntrack *ct;
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ struct vlan_ethhdr *vhdr;
+ unsigned short vlan_TCI, vid = 8192;
+
+ vhdr = vlan_eth_hdr(skb);
+ if (vhdr && vhdr->h_vlan_proto == __constant_htons(ETH_P_8021Q)){
+ vlan_TCI = ntohs(vhdr->h_vlan_TCI);
+ vid = (vlan_TCI & VLAN_VID_MASK);
+ }
+#endif
IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4,
+ &tuple,proto,vid))
+#else
+ if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4,
&tuple,proto))
+#endif
return NULL;
/* look for tuple match */
@@ -20,6 +20,7 @@
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+#include <linux/if_vlan.h>
unsigned int ip_ct_icmp_timeout __read_mostly = 30*HZ;
@@ -146,6 +147,16 @@
struct ip_conntrack_protocol *innerproto;
struct ip_conntrack_tuple_hash *h;
int dataoff;
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ struct vlan_ethhdr *vhdr;
+ unsigned short vlan_TCI, vid = 8192;
+
+ vhdr = vlan_eth_hdr(skb);
+ if (vhdr && vhdr->h_vlan_proto == __constant_htons(ETH_P_8021Q)){
+ vlan_TCI = ntohs(vhdr->h_vlan_TCI);
+ vid = (vlan_TCI & VLAN_VID_MASK);
+ }
+#endif
IP_NF_ASSERT(skb->nfct == NULL);
@@ -164,7 +175,11 @@
innerproto = ip_conntrack_proto_find_get(inside->ip.protocol);
dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp) + inside->ip.ihl*4;
/* Are they talking about one of our connections? */
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto, vid)) {
+#else
if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) {
+#endif
DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol);
ip_conntrack_proto_put(innerproto);
return -NF_ACCEPT;
@@ -23,6 +23,7 @@
#include <linux/icmp.h>
#include <linux/udp.h>
#include <linux/jhash.h>
+#include <linux/if_vlan.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -821,6 +822,17 @@
unsigned long statusbit;
enum ip_nat_manip_type manip = HOOK2MANIP(hooknum);
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ struct vlan_ethhdr *vhdr;
+ unsigned short vlan_TCI, vid = 8192;
+
+ vhdr = vlan_eth_hdr(*pskb);
+ if (vhdr && vhdr->h_vlan_proto == __constant_htons(ETH_P_8021Q)){
+ vlan_TCI = ntohs(vhdr->h_vlan_TCI);
+ vid = (vlan_TCI & VLAN_VID_MASK);
+ }
+#endif
+
if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
return 0;
@@ -853,7 +865,11 @@
if (!ip_ct_get_tuple(&inside->ip, *pskb, (*pskb)->nh.iph->ihl*4 +
sizeof(struct icmphdr) + inside->ip.ihl*4,
&inner,
+#ifdef CONFIG_IP_NF_CONNTRACK_VLAN
+ __ip_conntrack_proto_find(inside->ip.protocol), vid))
+#else
__ip_conntrack_proto_find(inside->ip.protocol)))
+#endif
return 0;
/* Change inner back to look like incoming packet. We do the