u32 ir_mark;
union {
struct ip_options_rcu *opt;
- struct sk_buff *pktopts;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct {
+ struct ipv6_txoptions *ipv6_opt;
+ struct sk_buff *pktopts;
+ };
+#endif
};
};
skb = dccp_make_response(sk, dst, req);
if (skb != NULL) {
struct dccp_hdr *dh = dccp_hdr(skb);
+ struct ipv6_txoptions *opt;
dh->dccph_checksum = dccp_v6_csum_finish(skb,
&ireq->ir_v6_loc_addr,
&ireq->ir_v6_rmt_addr);
fl6.daddr = ireq->ir_v6_rmt_addr;
rcu_read_lock();
- err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt),
- np->tclass);
+ opt = ireq->ipv6_opt;
+ if (!opt)
+ opt = rcu_dereference(np->opt);
+ err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
rcu_read_unlock();
err = net_xmit_eval(err);
}
static void dccp_v6_reqsk_destructor(struct request_sock *req)
{
dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
+ kfree(inet_rsk(req)->ipv6_opt);
kfree_skb(inet_rsk(req)->pktopts);
}
* Yes, keeping reference count would be much more clever, but we make
* one more one thing there: reattach optmem to newsk.
*/
- opt = rcu_dereference(np->opt);
+ opt = ireq->ipv6_opt;
+ if (!opt)
+ opt = rcu_dereference(np->opt);
if (opt) {
opt = ipv6_dup_options(newsk, opt);
RCU_INIT_POINTER(newnp->opt, opt);
kmemcheck_annotate_bitfield(ireq, flags);
ireq->opt = NULL;
+#if IS_ENABLED(CONFIG_IPV6)
+ ireq->pktopts = NULL;
+#endif
atomic64_set(&ireq->ir_cookie, 0);
ireq->ireq_state = TCP_NEW_SYN_RECV;
write_pnet(&ireq->ireq_net, sock_net(sk_listener));
{
struct inet_request_sock *ireq = inet_rsk(req);
struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt;
struct flowi6 *fl6 = &fl->u.ip6;
struct sk_buff *skb;
int err = -ENOMEM;
fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
rcu_read_lock();
- err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
- np->tclass);
+ opt = ireq->ipv6_opt;
+ if (!opt)
+ opt = rcu_dereference(np->opt);
+ err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
rcu_read_unlock();
err = net_xmit_eval(err);
}
static void tcp_v6_reqsk_destructor(struct request_sock *req)
{
+ kfree(inet_rsk(req)->ipv6_opt);
kfree_skb(inet_rsk(req)->pktopts);
}
but we make one more one thing there: reattach optmem
to newsk.
*/
- opt = rcu_dereference(np->opt);
+ opt = ireq->ipv6_opt;
+ if (!opt)
+ opt = rcu_dereference(np->opt);
if (opt) {
opt = ipv6_dup_options(newsk, opt);
RCU_INIT_POINTER(newnp->opt, opt);