|
@@ -48,6 +48,7 @@
|
|
|
#include <linux/inet.h>
|
|
|
#include <linux/netfilter_ipv4.h>
|
|
|
#include <net/inet_ecn.h>
|
|
|
+#include <net/vrf.h>
|
|
|
|
|
|
/* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6
|
|
|
* code now. If you change something here, _PLEASE_ update ipv6/reassembly.c
|
|
@@ -77,6 +78,7 @@ struct ipq {
|
|
|
u8 ecn; /* RFC3168 support */
|
|
|
u16 max_df_size; /* largest frag with DF set seen */
|
|
|
int iif;
|
|
|
+ int vif; /* VRF device index */
|
|
|
unsigned int rid;
|
|
|
struct inet_peer *peer;
|
|
|
};
|
|
@@ -99,6 +101,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
|
|
|
struct ip4_create_arg {
|
|
|
struct iphdr *iph;
|
|
|
u32 user;
|
|
|
+ int vif;
|
|
|
};
|
|
|
|
|
|
static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
|
|
@@ -127,7 +130,8 @@ static bool ip4_frag_match(const struct inet_frag_queue *q, const void *a)
|
|
|
qp->saddr == arg->iph->saddr &&
|
|
|
qp->daddr == arg->iph->daddr &&
|
|
|
qp->protocol == arg->iph->protocol &&
|
|
|
- qp->user == arg->user;
|
|
|
+ qp->user == arg->user &&
|
|
|
+ qp->vif == arg->vif;
|
|
|
}
|
|
|
|
|
|
static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
|
|
@@ -144,6 +148,7 @@ static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
|
|
|
qp->ecn = ip4_frag_ecn(arg->iph->tos);
|
|
|
qp->saddr = arg->iph->saddr;
|
|
|
qp->daddr = arg->iph->daddr;
|
|
|
+ qp->vif = arg->vif;
|
|
|
qp->user = arg->user;
|
|
|
qp->peer = sysctl_ipfrag_max_dist ?
|
|
|
inet_getpeer_v4(net->ipv4.peers, arg->iph->saddr, 1) : NULL;
|
|
@@ -244,7 +249,8 @@ out:
|
|
|
/* Find the correct entry in the "incomplete datagrams" queue for
|
|
|
* this IP datagram, and create new one, if nothing is found.
|
|
|
*/
|
|
|
-static struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
|
|
|
+static struct ipq *ip_find(struct net *net, struct iphdr *iph,
|
|
|
+ u32 user, int vif)
|
|
|
{
|
|
|
struct inet_frag_queue *q;
|
|
|
struct ip4_create_arg arg;
|
|
@@ -252,6 +258,7 @@ static struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
|
|
|
|
|
|
arg.iph = iph;
|
|
|
arg.user = user;
|
|
|
+ arg.vif = vif;
|
|
|
|
|
|
hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
|
|
|
|
|
@@ -648,14 +655,15 @@ out_fail:
|
|
|
/* Process an incoming IP datagram fragment. */
|
|
|
int ip_defrag(struct sk_buff *skb, u32 user)
|
|
|
{
|
|
|
+ struct net_device *dev = skb->dev ? : skb_dst(skb)->dev;
|
|
|
+ int vif = vrf_master_ifindex_rcu(dev);
|
|
|
+ struct net *net = dev_net(dev);
|
|
|
struct ipq *qp;
|
|
|
- struct net *net;
|
|
|
|
|
|
- net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev);
|
|
|
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
|
|
|
|
|
|
/* Lookup (or create) queue header */
|
|
|
- qp = ip_find(net, ip_hdr(skb), user);
|
|
|
+ qp = ip_find(net, ip_hdr(skb), user, vif);
|
|
|
if (qp) {
|
|
|
int ret;
|
|
|
|