Commit 74c7dfbe authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

mptcp: consolidate in_opt sub-options fields in a bitmask

This makes input options processing more consistent with
output ones and will simplify the next patch.

Also avoid clearing the suboption field after processing
it, since it's not needed.
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a086aeba
...@@ -81,11 +81,11 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -81,11 +81,11 @@ static void mptcp_parse_option(const struct sk_buff *skb,
* is if both hosts in their SYNs set A=0." * is if both hosts in their SYNs set A=0."
*/ */
if (flags & MPTCP_CAP_CHECKSUM_REQD) if (flags & MPTCP_CAP_CHECKSUM_REQD)
mp_opt->csum_reqd = 1; mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
mp_opt->deny_join_id0 = !!(flags & MPTCP_CAP_DENY_JOIN_ID0); mp_opt->deny_join_id0 = !!(flags & MPTCP_CAP_DENY_JOIN_ID0);
mp_opt->mp_capable = 1; mp_opt->suboptions |= OPTIONS_MPTCP_MPC;
if (opsize >= TCPOLEN_MPTCP_MPC_SYNACK) { if (opsize >= TCPOLEN_MPTCP_MPC_SYNACK) {
mp_opt->sndr_key = get_unaligned_be64(ptr); mp_opt->sndr_key = get_unaligned_be64(ptr);
ptr += 8; ptr += 8;
...@@ -100,7 +100,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -100,7 +100,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
* equivalent to those in a DSS option and can be used * equivalent to those in a DSS option and can be used
* interchangeably." * interchangeably."
*/ */
mp_opt->dss = 1; mp_opt->suboptions |= OPTION_MPTCP_DSS;
mp_opt->use_map = 1; mp_opt->use_map = 1;
mp_opt->mpc_map = 1; mp_opt->mpc_map = 1;
mp_opt->data_len = get_unaligned_be16(ptr); mp_opt->data_len = get_unaligned_be16(ptr);
...@@ -108,7 +108,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -108,7 +108,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
} }
if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM) { if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM) {
mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr); mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr);
mp_opt->csum_reqd = 1; mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
ptr += 2; ptr += 2;
} }
pr_debug("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d csum=%u", pr_debug("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d csum=%u",
...@@ -117,7 +117,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -117,7 +117,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
break; break;
case MPTCPOPT_MP_JOIN: case MPTCPOPT_MP_JOIN:
mp_opt->mp_join = 1; mp_opt->suboptions |= OPTIONS_MPTCP_MPJ;
if (opsize == TCPOLEN_MPTCP_MPJ_SYN) { if (opsize == TCPOLEN_MPTCP_MPJ_SYN) {
mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP; mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
mp_opt->join_id = *ptr++; mp_opt->join_id = *ptr++;
...@@ -143,7 +143,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -143,7 +143,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
memcpy(mp_opt->hmac, ptr, MPTCPOPT_HMAC_LEN); memcpy(mp_opt->hmac, ptr, MPTCPOPT_HMAC_LEN);
pr_debug("MP_JOIN hmac"); pr_debug("MP_JOIN hmac");
} else { } else {
mp_opt->mp_join = 0; mp_opt->suboptions &= ~OPTIONS_MPTCP_MPJ;
} }
break; break;
...@@ -191,8 +191,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -191,8 +191,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
opsize != expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM) opsize != expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM)
break; break;
mp_opt->dss = 1; mp_opt->suboptions |= OPTION_MPTCP_DSS;
if (mp_opt->use_ack) { if (mp_opt->use_ack) {
if (mp_opt->ack64) { if (mp_opt->ack64) {
mp_opt->data_ack = get_unaligned_be64(ptr); mp_opt->data_ack = get_unaligned_be64(ptr);
...@@ -221,14 +220,15 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -221,14 +220,15 @@ static void mptcp_parse_option(const struct sk_buff *skb,
ptr += 2; ptr += 2;
if (opsize == expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM) { if (opsize == expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM) {
mp_opt->csum_reqd = 1; mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr); mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr);
ptr += 2; ptr += 2;
} }
pr_debug("data_seq=%llu subflow_seq=%u data_len=%u csum=%d:%u", pr_debug("data_seq=%llu subflow_seq=%u data_len=%u csum=%d:%u",
mp_opt->data_seq, mp_opt->subflow_seq, mp_opt->data_seq, mp_opt->subflow_seq,
mp_opt->data_len, mp_opt->csum_reqd, mp_opt->csum); mp_opt->data_len, !!(mp_opt->suboptions & OPTION_MPTCP_CSUMREQD),
mp_opt->csum);
} }
break; break;
...@@ -259,7 +259,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -259,7 +259,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
break; break;
} }
mp_opt->add_addr = 1; mp_opt->suboptions |= OPTION_MPTCP_ADD_ADDR;
mp_opt->addr.id = *ptr++; mp_opt->addr.id = *ptr++;
mp_opt->addr.port = 0; mp_opt->addr.port = 0;
mp_opt->ahmac = 0; mp_opt->ahmac = 0;
...@@ -299,7 +299,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -299,7 +299,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
ptr++; ptr++;
mp_opt->rm_addr = 1; mp_opt->suboptions |= OPTION_MPTCP_RM_ADDR;
mp_opt->rm_list.nr = opsize - TCPOLEN_MPTCP_RM_ADDR_BASE; mp_opt->rm_list.nr = opsize - TCPOLEN_MPTCP_RM_ADDR_BASE;
for (i = 0; i < mp_opt->rm_list.nr; i++) for (i = 0; i < mp_opt->rm_list.nr; i++)
mp_opt->rm_list.ids[i] = *ptr++; mp_opt->rm_list.ids[i] = *ptr++;
...@@ -310,7 +310,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -310,7 +310,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
if (opsize != TCPOLEN_MPTCP_PRIO) if (opsize != TCPOLEN_MPTCP_PRIO)
break; break;
mp_opt->mp_prio = 1; mp_opt->suboptions |= OPTION_MPTCP_PRIO;
mp_opt->backup = *ptr++ & MPTCP_PRIO_BKUP; mp_opt->backup = *ptr++ & MPTCP_PRIO_BKUP;
pr_debug("MP_PRIO: prio=%d", mp_opt->backup); pr_debug("MP_PRIO: prio=%d", mp_opt->backup);
break; break;
...@@ -322,7 +322,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -322,7 +322,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
ptr += 2; ptr += 2;
mp_opt->rcvr_key = get_unaligned_be64(ptr); mp_opt->rcvr_key = get_unaligned_be64(ptr);
ptr += 8; ptr += 8;
mp_opt->fastclose = 1; mp_opt->suboptions |= OPTION_MPTCP_FASTCLOSE;
break; break;
case MPTCPOPT_RST: case MPTCPOPT_RST:
...@@ -331,7 +331,8 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -331,7 +331,8 @@ static void mptcp_parse_option(const struct sk_buff *skb,
if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST))
break; break;
mp_opt->reset = 1;
mp_opt->suboptions |= OPTION_MPTCP_RST;
flags = *ptr++; flags = *ptr++;
mp_opt->reset_transient = flags & MPTCP_RST_TRANSIENT; mp_opt->reset_transient = flags & MPTCP_RST_TRANSIENT;
mp_opt->reset_reason = *ptr; mp_opt->reset_reason = *ptr;
...@@ -342,7 +343,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, ...@@ -342,7 +343,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
break; break;
ptr += 2; ptr += 2;
mp_opt->mp_fail = 1; mp_opt->suboptions |= OPTION_MPTCP_FAIL;
mp_opt->fail_seq = get_unaligned_be64(ptr); mp_opt->fail_seq = get_unaligned_be64(ptr);
pr_debug("MP_FAIL: data_seq=%llu", mp_opt->fail_seq); pr_debug("MP_FAIL: data_seq=%llu", mp_opt->fail_seq);
break; break;
...@@ -361,16 +362,7 @@ void mptcp_get_options(const struct sock *sk, ...@@ -361,16 +362,7 @@ void mptcp_get_options(const struct sock *sk,
int length; int length;
/* initialize option status */ /* initialize option status */
mp_opt->mp_capable = 0; mp_opt->suboptions = 0;
mp_opt->mp_join = 0;
mp_opt->add_addr = 0;
mp_opt->fastclose = 0;
mp_opt->rm_addr = 0;
mp_opt->dss = 0;
mp_opt->mp_prio = 0;
mp_opt->reset = 0;
mp_opt->csum_reqd = 0;
mp_opt->mp_fail = 0;
length = (th->doff * 4) - sizeof(struct tcphdr); length = (th->doff * 4) - sizeof(struct tcphdr);
ptr = (const unsigned char *)(th + 1); ptr = (const unsigned char *)(th + 1);
...@@ -924,7 +916,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, ...@@ -924,7 +916,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
*/ */
if (TCP_SKB_CB(skb)->seq == subflow->ssn_offset + 1 && if (TCP_SKB_CB(skb)->seq == subflow->ssn_offset + 1 &&
TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq && TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq &&
subflow->mp_join && mp_opt->mp_join && subflow->mp_join && (mp_opt->suboptions & OPTIONS_MPTCP_MPJ) &&
READ_ONCE(msk->pm.server_side)) READ_ONCE(msk->pm.server_side))
tcp_send_ack(ssk); tcp_send_ack(ssk);
goto fully_established; goto fully_established;
...@@ -941,8 +933,8 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, ...@@ -941,8 +933,8 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
return subflow->mp_capable; return subflow->mp_capable;
} }
if ((mp_opt->dss && mp_opt->use_ack) || if (((mp_opt->suboptions & OPTION_MPTCP_DSS) && mp_opt->use_ack) ||
(mp_opt->add_addr && !mp_opt->echo)) { ((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) && !mp_opt->echo)) {
/* subflows are fully established as soon as we get any /* subflows are fully established as soon as we get any
* additional ack, including ADD_ADDR. * additional ack, including ADD_ADDR.
*/ */
...@@ -955,7 +947,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, ...@@ -955,7 +947,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
* then fallback to TCP. Fallback scenarios requires a reset for * then fallback to TCP. Fallback scenarios requires a reset for
* MP_JOIN subflows. * MP_JOIN subflows.
*/ */
if (!mp_opt->mp_capable) { if (!(mp_opt->suboptions & OPTIONS_MPTCP_MPC)) {
if (subflow->mp_join) if (subflow->mp_join)
goto reset; goto reset;
subflow->mp_capable = 0; subflow->mp_capable = 0;
...@@ -1119,13 +1111,13 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) ...@@ -1119,13 +1111,13 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
if (!check_fully_established(msk, sk, subflow, skb, &mp_opt)) if (!check_fully_established(msk, sk, subflow, skb, &mp_opt))
return sk->sk_state != TCP_CLOSE; return sk->sk_state != TCP_CLOSE;
if (mp_opt.fastclose && if ((mp_opt.suboptions & OPTION_MPTCP_FASTCLOSE) &&
msk->local_key == mp_opt.rcvr_key) { msk->local_key == mp_opt.rcvr_key) {
WRITE_ONCE(msk->rcv_fastclose, true); WRITE_ONCE(msk->rcv_fastclose, true);
mptcp_schedule_work((struct sock *)msk); mptcp_schedule_work((struct sock *)msk);
} }
if (mp_opt.add_addr && add_addr_hmac_valid(msk, &mp_opt)) { if ((mp_opt.suboptions & OPTION_MPTCP_ADD_ADDR) && add_addr_hmac_valid(msk, &mp_opt)) {
if (!mp_opt.echo) { if (!mp_opt.echo) {
mptcp_pm_add_addr_received(msk, &mp_opt.addr); mptcp_pm_add_addr_received(msk, &mp_opt.addr);
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
...@@ -1137,34 +1129,28 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) ...@@ -1137,34 +1129,28 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
if (mp_opt.addr.port) if (mp_opt.addr.port)
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_PORTADD); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_PORTADD);
mp_opt.add_addr = 0;
} }
if (mp_opt.rm_addr) { if (mp_opt.suboptions & OPTION_MPTCP_RM_ADDR)
mptcp_pm_rm_addr_received(msk, &mp_opt.rm_list); mptcp_pm_rm_addr_received(msk, &mp_opt.rm_list);
mp_opt.rm_addr = 0;
}
if (mp_opt.mp_prio) { if (mp_opt.suboptions & OPTION_MPTCP_PRIO) {
mptcp_pm_mp_prio_received(sk, mp_opt.backup); mptcp_pm_mp_prio_received(sk, mp_opt.backup);
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPPRIORX); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPPRIORX);
mp_opt.mp_prio = 0;
} }
if (mp_opt.mp_fail) { if (mp_opt.suboptions & OPTION_MPTCP_FAIL) {
mptcp_pm_mp_fail_received(sk, mp_opt.fail_seq); mptcp_pm_mp_fail_received(sk, mp_opt.fail_seq);
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILRX); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILRX);
mp_opt.mp_fail = 0;
} }
if (mp_opt.reset) { if (mp_opt.suboptions & OPTION_MPTCP_RST) {
subflow->reset_seen = 1; subflow->reset_seen = 1;
subflow->reset_reason = mp_opt.reset_reason; subflow->reset_reason = mp_opt.reset_reason;
subflow->reset_transient = mp_opt.reset_transient; subflow->reset_transient = mp_opt.reset_transient;
} }
if (!mp_opt.dss) if (!(mp_opt.suboptions & OPTION_MPTCP_DSS))
return true; return true;
/* we can't wait for recvmsg() to update the ack_seq, otherwise /* we can't wait for recvmsg() to update the ack_seq, otherwise
...@@ -1213,7 +1199,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) ...@@ -1213,7 +1199,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
} }
mpext->data_len = mp_opt.data_len; mpext->data_len = mp_opt.data_len;
mpext->use_map = 1; mpext->use_map = 1;
mpext->csum_reqd = mp_opt.csum_reqd; mpext->csum_reqd = !!(mp_opt.suboptions & OPTION_MPTCP_CSUMREQD);
if (mpext->csum_reqd) if (mpext->csum_reqd)
mpext->csum = mp_opt.csum; mpext->csum = mp_opt.csum;
......
...@@ -2832,7 +2832,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk, ...@@ -2832,7 +2832,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
msk->token = subflow_req->token; msk->token = subflow_req->token;
msk->subflow = NULL; msk->subflow = NULL;
WRITE_ONCE(msk->fully_established, false); WRITE_ONCE(msk->fully_established, false);
if (mp_opt->csum_reqd) if (mp_opt->suboptions & OPTION_MPTCP_CSUMREQD)
WRITE_ONCE(msk->csum_enabled, true); WRITE_ONCE(msk->csum_enabled, true);
msk->write_seq = subflow_req->idsn + 1; msk->write_seq = subflow_req->idsn + 1;
...@@ -2841,7 +2841,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk, ...@@ -2841,7 +2841,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
msk->wnd_end = msk->snd_nxt + req->rsk_rcv_wnd; msk->wnd_end = msk->snd_nxt + req->rsk_rcv_wnd;
msk->setsockopt_seq = mptcp_sk(sk)->setsockopt_seq; msk->setsockopt_seq = mptcp_sk(sk)->setsockopt_seq;
if (mp_opt->mp_capable) { if (mp_opt->suboptions & OPTIONS_MPTCP_MPC) {
msk->can_ack = true; msk->can_ack = true;
msk->remote_key = mp_opt->sndr_key; msk->remote_key = mp_opt->sndr_key;
mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq); mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq);
......
...@@ -29,6 +29,13 @@ ...@@ -29,6 +29,13 @@
#define OPTION_MPTCP_DSS BIT(11) #define OPTION_MPTCP_DSS BIT(11)
#define OPTION_MPTCP_FAIL BIT(12) #define OPTION_MPTCP_FAIL BIT(12)
#define OPTION_MPTCP_CSUMREQD BIT(13)
#define OPTIONS_MPTCP_MPC (OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | \
OPTION_MPTCP_MPC_ACK)
#define OPTIONS_MPTCP_MPJ (OPTION_MPTCP_MPJ_SYN | OPTION_MPTCP_MPJ_SYNACK | \
OPTION_MPTCP_MPJ_SYNACK)
/* MPTCP option subtypes */ /* MPTCP option subtypes */
#define MPTCPOPT_MP_CAPABLE 0 #define MPTCPOPT_MP_CAPABLE 0
#define MPTCPOPT_MP_JOIN 1 #define MPTCPOPT_MP_JOIN 1
...@@ -132,16 +139,7 @@ struct mptcp_options_received { ...@@ -132,16 +139,7 @@ struct mptcp_options_received {
u32 subflow_seq; u32 subflow_seq;
u16 data_len; u16 data_len;
__sum16 csum; __sum16 csum;
u16 mp_capable : 1, u16 suboptions;
mp_join : 1,
fastclose : 1,
reset : 1,
dss : 1,
add_addr : 1,
rm_addr : 1,
mp_prio : 1,
csum_reqd : 1,
mp_fail : 1;
u32 token; u32 token;
u32 nonce; u32 nonce;
u16 use_map:1, u16 use_map:1,
......
...@@ -141,6 +141,7 @@ static int subflow_check_req(struct request_sock *req, ...@@ -141,6 +141,7 @@ static int subflow_check_req(struct request_sock *req,
struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener); struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener);
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
struct mptcp_options_received mp_opt; struct mptcp_options_received mp_opt;
bool opt_mp_capable, opt_mp_join;
pr_debug("subflow_req=%p, listener=%p", subflow_req, listener); pr_debug("subflow_req=%p, listener=%p", subflow_req, listener);
...@@ -154,16 +155,18 @@ static int subflow_check_req(struct request_sock *req, ...@@ -154,16 +155,18 @@ static int subflow_check_req(struct request_sock *req,
mptcp_get_options(sk_listener, skb, &mp_opt); mptcp_get_options(sk_listener, skb, &mp_opt);
if (mp_opt.mp_capable) { opt_mp_capable = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPC);
opt_mp_join = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ);
if (opt_mp_capable) {
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE); SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE);
if (mp_opt.mp_join) if (opt_mp_join)
return 0; return 0;
} else if (mp_opt.mp_join) { } else if (opt_mp_join) {
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX); SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX);
} }
if (mp_opt.mp_capable && listener->request_mptcp) { if (opt_mp_capable && listener->request_mptcp) {
int err, retries = MPTCP_TOKEN_MAX_RETRIES; int err, retries = MPTCP_TOKEN_MAX_RETRIES;
subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq;
...@@ -194,7 +197,7 @@ static int subflow_check_req(struct request_sock *req, ...@@ -194,7 +197,7 @@ static int subflow_check_req(struct request_sock *req,
else else
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_TOKENFALLBACKINIT); SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_TOKENFALLBACKINIT);
} else if (mp_opt.mp_join && listener->request_mptcp) { } else if (opt_mp_join && listener->request_mptcp) {
subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq;
subflow_req->mp_join = 1; subflow_req->mp_join = 1;
subflow_req->backup = mp_opt.backup; subflow_req->backup = mp_opt.backup;
...@@ -243,15 +246,18 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req, ...@@ -243,15 +246,18 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req,
struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener); struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener);
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
struct mptcp_options_received mp_opt; struct mptcp_options_received mp_opt;
bool opt_mp_capable, opt_mp_join;
int err; int err;
subflow_init_req(req, sk_listener); subflow_init_req(req, sk_listener);
mptcp_get_options(sk_listener, skb, &mp_opt); mptcp_get_options(sk_listener, skb, &mp_opt);
if (mp_opt.mp_capable && mp_opt.mp_join) opt_mp_capable = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPC);
opt_mp_join = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ);
if (opt_mp_capable && opt_mp_join)
return -EINVAL; return -EINVAL;
if (mp_opt.mp_capable && listener->request_mptcp) { if (opt_mp_capable && listener->request_mptcp) {
if (mp_opt.sndr_key == 0) if (mp_opt.sndr_key == 0)
return -EINVAL; return -EINVAL;
...@@ -262,7 +268,7 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req, ...@@ -262,7 +268,7 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req,
subflow_req->mp_capable = 1; subflow_req->mp_capable = 1;
subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq - 1; subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq - 1;
} else if (mp_opt.mp_join && listener->request_mptcp) { } else if (opt_mp_join && listener->request_mptcp) {
if (!mptcp_token_join_cookie_init_state(subflow_req, skb)) if (!mptcp_token_join_cookie_init_state(subflow_req, skb))
return -EINVAL; return -EINVAL;
...@@ -394,7 +400,6 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) ...@@ -394,7 +400,6 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
subflow->icsk_af_ops->sk_rx_dst_set(sk, skb); subflow->icsk_af_ops->sk_rx_dst_set(sk, skb);
/* be sure no special action on any packet other than syn-ack */ /* be sure no special action on any packet other than syn-ack */
if (subflow->conn_finished) if (subflow->conn_finished)
return; return;
...@@ -407,7 +412,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) ...@@ -407,7 +412,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
mptcp_get_options(sk, skb, &mp_opt); mptcp_get_options(sk, skb, &mp_opt);
if (subflow->request_mptcp) { if (subflow->request_mptcp) {
if (!mp_opt.mp_capable) { if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC)) {
MPTCP_INC_STATS(sock_net(sk), MPTCP_INC_STATS(sock_net(sk),
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK); MPTCP_MIB_MPCAPABLEACTIVEFALLBACK);
mptcp_do_fallback(sk); mptcp_do_fallback(sk);
...@@ -415,7 +420,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) ...@@ -415,7 +420,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
goto fallback; goto fallback;
} }
if (mp_opt.csum_reqd) if (mp_opt.suboptions & OPTION_MPTCP_CSUMREQD)
WRITE_ONCE(mptcp_sk(parent)->csum_enabled, true); WRITE_ONCE(mptcp_sk(parent)->csum_enabled, true);
if (mp_opt.deny_join_id0) if (mp_opt.deny_join_id0)
WRITE_ONCE(mptcp_sk(parent)->pm.remote_deny_join_id0, true); WRITE_ONCE(mptcp_sk(parent)->pm.remote_deny_join_id0, true);
...@@ -430,7 +435,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) ...@@ -430,7 +435,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
} else if (subflow->request_join) { } else if (subflow->request_join) {
u8 hmac[SHA256_DIGEST_SIZE]; u8 hmac[SHA256_DIGEST_SIZE];
if (!mp_opt.mp_join) { if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ)) {
subflow->reset_reason = MPTCP_RST_EMPTCP; subflow->reset_reason = MPTCP_RST_EMPTCP;
goto do_reset; goto do_reset;
} }
...@@ -636,10 +641,10 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, ...@@ -636,10 +641,10 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn); pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn);
/* After child creation we must look for 'mp_capable' even when options /* After child creation we must look for MPC even when options
* are not parsed * are not parsed
*/ */
mp_opt.mp_capable = 0; mp_opt.suboptions = 0;
/* hopefully temporary handling for MP_JOIN+syncookie */ /* hopefully temporary handling for MP_JOIN+syncookie */
subflow_req = mptcp_subflow_rsk(req); subflow_req = mptcp_subflow_rsk(req);
...@@ -659,7 +664,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, ...@@ -659,7 +664,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
* options. * options.
*/ */
mptcp_get_options(sk, skb, &mp_opt); mptcp_get_options(sk, skb, &mp_opt);
if (!mp_opt.mp_capable) { if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC)) {
fallback = true; fallback = true;
goto create_child; goto create_child;
} }
...@@ -669,7 +674,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, ...@@ -669,7 +674,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
fallback = true; fallback = true;
} else if (subflow_req->mp_join) { } else if (subflow_req->mp_join) {
mptcp_get_options(sk, skb, &mp_opt); mptcp_get_options(sk, skb, &mp_opt);
if (!mp_opt.mp_join || !subflow_hmac_valid(req, &mp_opt) || if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ) ||
!subflow_hmac_valid(req, &mp_opt) ||
!mptcp_can_accept_new_subflow(subflow_req->msk)) { !mptcp_can_accept_new_subflow(subflow_req->msk)) {
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
fallback = true; fallback = true;
...@@ -726,7 +732,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, ...@@ -726,7 +732,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
/* with OoO packets we can reach here without ingress /* with OoO packets we can reach here without ingress
* mpc option * mpc option
*/ */
if (mp_opt.mp_capable) if (mp_opt.suboptions & OPTIONS_MPTCP_MPC)
mptcp_subflow_fully_established(ctx, &mp_opt); mptcp_subflow_fully_established(ctx, &mp_opt);
} else if (ctx->mp_join) { } else if (ctx->mp_join) {
struct mptcp_sock *owner; struct mptcp_sock *owner;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment