1 /* SPDX-License-Identifier: GPL-2.0 */
4 #include <linux/icmpv6.h>
5 #include <linux/kernel.h>
6 #include <net/addrconf.h>
8 #include <net/inet_frag.h>
10 enum ip6_defrag_users
{
11 IP6_DEFRAG_LOCAL_DELIVER
,
12 IP6_DEFRAG_CONNTRACK_IN
,
13 __IP6_DEFRAG_CONNTRACK_IN
= IP6_DEFRAG_CONNTRACK_IN
+ USHRT_MAX
,
14 IP6_DEFRAG_CONNTRACK_OUT
,
15 __IP6_DEFRAG_CONNTRACK_OUT
= IP6_DEFRAG_CONNTRACK_OUT
+ USHRT_MAX
,
16 IP6_DEFRAG_CONNTRACK_BRIDGE_IN
,
17 __IP6_DEFRAG_CONNTRACK_BRIDGE_IN
= IP6_DEFRAG_CONNTRACK_BRIDGE_IN
+ USHRT_MAX
,
21 * Equivalent of ipv4 struct ip
24 struct inet_frag_queue q
;
31 #if IS_ENABLED(CONFIG_IPV6)
32 static inline void ip6frag_init(struct inet_frag_queue
*q
, const void *a
)
34 struct frag_queue
*fq
= container_of(q
, struct frag_queue
, q
);
35 const struct frag_v6_compare_key
*key
= a
;
41 static inline u32
ip6frag_key_hashfn(const void *data
, u32 len
, u32 seed
)
44 sizeof(struct frag_v6_compare_key
) / sizeof(u32
), seed
);
47 static inline u32
ip6frag_obj_hashfn(const void *data
, u32 len
, u32 seed
)
49 const struct inet_frag_queue
*fq
= data
;
51 return jhash2((const u32
*)&fq
->key
.v6
,
52 sizeof(struct frag_v6_compare_key
) / sizeof(u32
), seed
);
56 ip6frag_obj_cmpfn(struct rhashtable_compare_arg
*arg
, const void *ptr
)
58 const struct frag_v6_compare_key
*key
= arg
->key
;
59 const struct inet_frag_queue
*fq
= ptr
;
61 return !!memcmp(&fq
->key
, key
, sizeof(*key
));
65 ip6frag_expire_frag_queue(struct net
*net
, struct frag_queue
*fq
)
67 struct net_device
*dev
= NULL
;
71 /* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
72 if (READ_ONCE(fq
->q
.fqdir
->dead
))
74 spin_lock(&fq
->q
.lock
);
76 if (fq
->q
.flags
& INET_FRAG_COMPLETE
)
79 fq
->q
.flags
|= INET_FRAG_DROP
;
80 inet_frag_kill(&fq
->q
);
82 dev
= dev_get_by_index_rcu(net
, fq
->iif
);
86 __IP6_INC_STATS(net
, __in6_dev_get(dev
), IPSTATS_MIB_REASMFAILS
);
87 __IP6_INC_STATS(net
, __in6_dev_get(dev
), IPSTATS_MIB_REASMTIMEOUT
);
89 /* Don't send error if the first segment did not arrive. */
90 if (!(fq
->q
.flags
& INET_FRAG_FIRST_IN
))
93 /* sk_buff::dev and sk_buff::rbnode are unionized. So we
94 * pull the head out of the tree in order to be able to
95 * deal with head->dev.
97 head
= inet_frag_pull_head(&fq
->q
);
102 spin_unlock(&fq
->q
.lock
);
104 icmpv6_send(head
, ICMPV6_TIME_EXCEED
, ICMPV6_EXC_FRAGTIME
, 0);
105 kfree_skb_reason(head
, SKB_DROP_REASON_FRAG_REASM_TIMEOUT
);
109 spin_unlock(&fq
->q
.lock
);
112 inet_frag_put(&fq
->q
);
115 /* Check if the upper layer header is truncated in the first fragment. */
117 ipv6frag_thdr_truncated(struct sk_buff
*skb
, int start
, u8
*nexthdrp
)
119 u8 nexthdr
= *nexthdrp
;
123 offset
= ipv6_skip_exthdr(skb
, start
, &nexthdr
, &frag_off
);
124 if (offset
< 0 || (frag_off
& htons(IP6_OFFSET
)))
128 offset
+= sizeof(struct tcphdr
);
131 offset
+= sizeof(struct udphdr
);
134 offset
+= sizeof(struct icmp6hdr
);
139 if (offset
> skb
->len
)