forked from Minki/linux
netfilter: flowtable: Support GRE
Support GREv0 without NAT. Signed-off-by: Toshiaki Makita <toshiaki.makita1@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
f1082dd31f
commit
4e8d9584d1
@ -39,8 +39,14 @@ flow_offload_fill_dir(struct flow_offload *flow,
|
||||
|
||||
ft->l3proto = ctt->src.l3num;
|
||||
ft->l4proto = ctt->dst.protonum;
|
||||
ft->src_port = ctt->src.u.tcp.port;
|
||||
ft->dst_port = ctt->dst.u.tcp.port;
|
||||
|
||||
switch (ctt->dst.protonum) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
ft->src_port = ctt->src.u.tcp.port;
|
||||
ft->dst_port = ctt->dst.u.tcp.port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct flow_offload *flow_offload_alloc(struct nf_conn *ct)
|
||||
|
@ -172,6 +172,7 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
|
||||
struct flow_ports *ports;
|
||||
unsigned int thoff;
|
||||
struct iphdr *iph;
|
||||
u8 ipproto;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(*iph) + offset))
|
||||
return -1;
|
||||
@ -185,13 +186,19 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
|
||||
|
||||
thoff += offset;
|
||||
|
||||
switch (iph->protocol) {
|
||||
ipproto = iph->protocol;
|
||||
switch (ipproto) {
|
||||
case IPPROTO_TCP:
|
||||
*hdrsize = sizeof(struct tcphdr);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
*hdrsize = sizeof(struct udphdr);
|
||||
break;
|
||||
#ifdef CONFIG_NF_CT_PROTO_GRE
|
||||
case IPPROTO_GRE:
|
||||
*hdrsize = sizeof(struct gre_base_hdr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -202,15 +209,29 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
|
||||
if (!pskb_may_pull(skb, thoff + *hdrsize))
|
||||
return -1;
|
||||
|
||||
switch (ipproto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
|
||||
tuple->src_port = ports->source;
|
||||
tuple->dst_port = ports->dest;
|
||||
break;
|
||||
case IPPROTO_GRE: {
|
||||
struct gre_base_hdr *greh;
|
||||
|
||||
greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff);
|
||||
if ((greh->flags & GRE_VERSION) != GRE_VERSION_0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iph = (struct iphdr *)(skb_network_header(skb) + offset);
|
||||
ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
|
||||
|
||||
tuple->src_v4.s_addr = iph->saddr;
|
||||
tuple->dst_v4.s_addr = iph->daddr;
|
||||
tuple->src_port = ports->source;
|
||||
tuple->dst_port = ports->dest;
|
||||
tuple->l3proto = AF_INET;
|
||||
tuple->l4proto = iph->protocol;
|
||||
tuple->l4proto = ipproto;
|
||||
tuple->iifidx = dev->ifindex;
|
||||
nf_flow_tuple_encap(skb, tuple);
|
||||
|
||||
@ -521,6 +542,7 @@ static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
|
||||
struct flow_ports *ports;
|
||||
struct ipv6hdr *ip6h;
|
||||
unsigned int thoff;
|
||||
u8 nexthdr;
|
||||
|
||||
thoff = sizeof(*ip6h) + offset;
|
||||
if (!pskb_may_pull(skb, thoff))
|
||||
@ -528,13 +550,19 @@ static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
|
||||
|
||||
ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
|
||||
|
||||
switch (ip6h->nexthdr) {
|
||||
nexthdr = ip6h->nexthdr;
|
||||
switch (nexthdr) {
|
||||
case IPPROTO_TCP:
|
||||
*hdrsize = sizeof(struct tcphdr);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
*hdrsize = sizeof(struct udphdr);
|
||||
break;
|
||||
#ifdef CONFIG_NF_CT_PROTO_GRE
|
||||
case IPPROTO_GRE:
|
||||
*hdrsize = sizeof(struct gre_base_hdr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@ -545,15 +573,29 @@ static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
|
||||
if (!pskb_may_pull(skb, thoff + *hdrsize))
|
||||
return -1;
|
||||
|
||||
switch (nexthdr) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
|
||||
tuple->src_port = ports->source;
|
||||
tuple->dst_port = ports->dest;
|
||||
break;
|
||||
case IPPROTO_GRE: {
|
||||
struct gre_base_hdr *greh;
|
||||
|
||||
greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff);
|
||||
if ((greh->flags & GRE_VERSION) != GRE_VERSION_0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
|
||||
ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
|
||||
|
||||
tuple->src_v6 = ip6h->saddr;
|
||||
tuple->dst_v6 = ip6h->daddr;
|
||||
tuple->src_port = ports->source;
|
||||
tuple->dst_port = ports->dest;
|
||||
tuple->l3proto = AF_INET6;
|
||||
tuple->l4proto = ip6h->nexthdr;
|
||||
tuple->l4proto = nexthdr;
|
||||
tuple->iifidx = dev->ifindex;
|
||||
nf_flow_tuple_encap(skb, tuple);
|
||||
|
||||
|
@ -170,6 +170,7 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
|
||||
match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_GRE:
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
@ -178,15 +179,22 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
|
||||
key->basic.ip_proto = tuple->l4proto;
|
||||
mask->basic.ip_proto = 0xff;
|
||||
|
||||
key->tp.src = tuple->src_port;
|
||||
mask->tp.src = 0xffff;
|
||||
key->tp.dst = tuple->dst_port;
|
||||
mask->tp.dst = 0xffff;
|
||||
|
||||
match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_META) |
|
||||
BIT(FLOW_DISSECTOR_KEY_CONTROL) |
|
||||
BIT(FLOW_DISSECTOR_KEY_BASIC) |
|
||||
BIT(FLOW_DISSECTOR_KEY_PORTS);
|
||||
BIT(FLOW_DISSECTOR_KEY_BASIC);
|
||||
|
||||
switch (tuple->l4proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
key->tp.src = tuple->src_port;
|
||||
mask->tp.src = 0xffff;
|
||||
key->tp.dst = tuple->dst_port;
|
||||
mask->tp.dst = 0xffff;
|
||||
|
||||
match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_PORTS);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -298,6 +298,19 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
break;
|
||||
#ifdef CONFIG_NF_CT_PROTO_GRE
|
||||
case IPPROTO_GRE: {
|
||||
struct nf_conntrack_tuple *tuple;
|
||||
|
||||
if (ct->status & IPS_NAT_MASK)
|
||||
goto out;
|
||||
tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
|
||||
/* No support for GRE v1 */
|
||||
if (tuple->src.u.gre.key || tuple->dst.u.gre.key)
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user