|
|
@@ -108,7 +108,10 @@ bool ip6_frag_match(const struct inet_frag_queue *q, const void *a)
|
|
|
return fq->id == arg->id &&
|
|
|
fq->user == arg->user &&
|
|
|
ipv6_addr_equal(&fq->saddr, arg->src) &&
|
|
|
- ipv6_addr_equal(&fq->daddr, arg->dst);
|
|
|
+ ipv6_addr_equal(&fq->daddr, arg->dst) &&
|
|
|
+ (arg->iif == fq->iif ||
|
|
|
+ !(ipv6_addr_type(arg->dst) & (IPV6_ADDR_MULTICAST |
|
|
|
+ IPV6_ADDR_LINKLOCAL)));
|
|
|
}
|
|
|
EXPORT_SYMBOL(ip6_frag_match);
|
|
|
|
|
|
@@ -180,7 +183,7 @@ static void ip6_frag_expire(unsigned long data)
|
|
|
|
|
|
static struct frag_queue *
|
|
|
fq_find(struct net *net, __be32 id, const struct in6_addr *src,
|
|
|
- const struct in6_addr *dst, u8 ecn)
|
|
|
+ const struct in6_addr *dst, int iif, u8 ecn)
|
|
|
{
|
|
|
struct inet_frag_queue *q;
|
|
|
struct ip6_create_arg arg;
|
|
|
@@ -190,6 +193,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src,
|
|
|
arg.user = IP6_DEFRAG_LOCAL_DELIVER;
|
|
|
arg.src = src;
|
|
|
arg.dst = dst;
|
|
|
+ arg.iif = iif;
|
|
|
arg.ecn = ecn;
|
|
|
|
|
|
hash = inet6_hash_frag(id, src, dst);
|
|
|
@@ -551,7 +555,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
|
|
|
}
|
|
|
|
|
|
fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr,
|
|
|
- ip6_frag_ecn(hdr));
|
|
|
+ skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr));
|
|
|
if (fq) {
|
|
|
int ret;
|
|
|
|