X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4d15aeb193b2c68f1d38666c317f8d3734f5f083..5ba3f43ea354af8ad55bea84372a2bc834d8757c:/bsd/netinet/mptcp_opt.c?ds=sidebyside diff --git a/bsd/netinet/mptcp_opt.c b/bsd/netinet/mptcp_opt.c index d2aec1750..8aa8a9a4e 100644 --- a/bsd/netinet/mptcp_opt.c +++ b/bsd/netinet/mptcp_opt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Apple Inc. All rights reserved. + * Copyright (c) 2012-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -53,29 +53,22 @@ #include -/* - * SYSCTL for enforcing 64 bit dsn - */ -int32_t force_64bit_dsn = 0; -SYSCTL_INT(_net_inet_mptcp, OID_AUTO, force_64bit_dsn, - CTLFLAG_RW|CTLFLAG_LOCKED, &force_64bit_dsn, 0, - "Force MPTCP 64bit dsn"); - - static int mptcp_validate_join_hmac(struct tcpcb *, u_char*, int); static int mptcp_snd_mpprio(struct tcpcb *tp, u_char *cp, int optlen); +static void mptcp_send_remaddr_opt(struct tcpcb *, struct mptcp_remaddr_opt *); /* * MPTCP Options Output Processing */ static unsigned -mptcp_setup_first_subflow_syn_opts(struct socket *so, int flags, u_char *opt, - unsigned optlen) +mptcp_setup_first_subflow_syn_opts(struct socket *so, u_char *opt, unsigned optlen) { + struct mptcp_mpcapable_opt_common mptcp_opt; struct tcpcb *tp = sototcpcb(so); - struct mptcb *mp_tp = NULL; - mp_tp = tptomptp(tp); + struct mptcb *mp_tp = tptomptp(tp); + + mpte_lock_assert_held(mp_tp->mpt_mpte); /* * Avoid retransmitting the MP_CAPABLE option. @@ -93,72 +86,32 @@ mptcp_setup_first_subflow_syn_opts(struct socket *so, int flags, u_char *opt, return (optlen); } - if ((flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) { - struct mptcp_mpcapable_opt_rsp mptcp_opt; - mptcp_key_t mp_localkey = 0; + bzero(&mptcp_opt, sizeof (struct mptcp_mpcapable_opt_common)); - mp_localkey = mptcp_get_localkey(mp_tp); - if (mp_localkey == 0) { - /* an embryonic connection was closed from above */ - return (optlen); - } - bzero(&mptcp_opt, - sizeof (struct mptcp_mpcapable_opt_rsp)); - mptcp_opt.mmc_common.mmco_kind = TCPOPT_MULTIPATH; - mptcp_opt.mmc_common.mmco_len = - sizeof (struct mptcp_mpcapable_opt_rsp); - mptcp_opt.mmc_common.mmco_subtype = MPO_CAPABLE; - MPT_LOCK_SPIN(mp_tp); - mptcp_opt.mmc_common.mmco_version = mp_tp->mpt_version; - mptcp_opt.mmc_common.mmco_flags |= MPCAP_PROPOSAL_SBIT; - if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) - mptcp_opt.mmc_common.mmco_flags |= - MPCAP_CHECKSUM_CBIT; - MPT_UNLOCK(mp_tp); - mptcp_opt.mmc_localkey = mp_localkey; - memcpy(opt + optlen, &mptcp_opt, - mptcp_opt.mmc_common.mmco_len); - optlen += mptcp_opt.mmc_common.mmco_len; - } else { - /* Only the SYN flag is set */ - struct mptcp_mpcapable_opt_common mptcp_opt; - mptcp_key_t mp_localkey = 0; - mp_localkey = mptcp_get_localkey(mp_tp); - so->so_flags |= SOF_MPTCP_CLIENT; - if (mp_localkey == 0) { - /* an embryonic connection was closed */ - return (optlen); - } - bzero(&mptcp_opt, - sizeof (struct mptcp_mpcapable_opt_common)); - mptcp_opt.mmco_kind = TCPOPT_MULTIPATH; - mptcp_opt.mmco_len = - sizeof (struct mptcp_mpcapable_opt_common) + - sizeof (mptcp_key_t); - mptcp_opt.mmco_subtype = MPO_CAPABLE; - MPT_LOCK_SPIN(mp_tp); - mptcp_opt.mmco_version = mp_tp->mpt_version; - mptcp_opt.mmco_flags |= MPCAP_PROPOSAL_SBIT; - if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) - mptcp_opt.mmco_flags |= MPCAP_CHECKSUM_CBIT; - MPT_UNLOCK(mp_tp); - (void) memcpy(opt + optlen, &mptcp_opt, - sizeof (struct mptcp_mpcapable_opt_common)); - optlen += sizeof (struct mptcp_mpcapable_opt_common); - (void) memcpy(opt + optlen, &mp_localkey, - sizeof (mptcp_key_t)); - optlen += sizeof (mptcp_key_t); - } + mptcp_opt.mmco_kind = TCPOPT_MULTIPATH; + mptcp_opt.mmco_len = + sizeof (struct mptcp_mpcapable_opt_common) + + sizeof (mptcp_key_t); + mptcp_opt.mmco_subtype = MPO_CAPABLE; + mptcp_opt.mmco_version = mp_tp->mpt_version; + mptcp_opt.mmco_flags |= MPCAP_PROPOSAL_SBIT; + if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) + mptcp_opt.mmco_flags |= MPCAP_CHECKSUM_CBIT; + memcpy(opt + optlen, &mptcp_opt, sizeof (struct mptcp_mpcapable_opt_common)); + optlen += sizeof (struct mptcp_mpcapable_opt_common); + memcpy(opt + optlen, &mp_tp->mpt_localkey, sizeof (mptcp_key_t)); + optlen += sizeof (mptcp_key_t); return (optlen); } static unsigned -mptcp_setup_join_subflow_syn_opts(struct socket *so, int flags, u_char *opt, - unsigned optlen) +mptcp_setup_join_subflow_syn_opts(struct socket *so, u_char *opt, unsigned optlen) { + struct mptcp_mpjoin_opt_req mpjoin_req; struct inpcb *inp = sotoinpcb(so); struct tcpcb *tp = NULL; + struct mptsub *mpts; if (!inp) return (optlen); @@ -167,61 +120,37 @@ mptcp_setup_join_subflow_syn_opts(struct socket *so, int flags, u_char *opt, if (!tp) return (optlen); - if (!tp->t_mptcb) - return (optlen); + mpts = tp->t_mpsub; - if ((flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) { - struct mptcp_mpjoin_opt_rsp mpjoin_rsp; - struct mptcb *mp_tp = tptomptp(tp); + VERIFY(tptomptp(tp)); + mpte_lock_assert_held(tptomptp(tp)->mpt_mpte); - if (mp_tp == NULL) - return (optlen); + bzero(&mpjoin_req, sizeof (mpjoin_req)); + mpjoin_req.mmjo_kind = TCPOPT_MULTIPATH; + mpjoin_req.mmjo_len = sizeof (mpjoin_req); + mpjoin_req.mmjo_subtype_bkp = MPO_JOIN << 4; - MPT_LOCK(mp_tp); - if (mptcp_get_localkey(mp_tp) == 0) { - MPT_UNLOCK(mp_tp); - return (optlen); - } - MPT_UNLOCK(mp_tp); - bzero(&mpjoin_rsp, sizeof (mpjoin_rsp)); - mpjoin_rsp.mmjo_kind = TCPOPT_MULTIPATH; - mpjoin_rsp.mmjo_len = sizeof (mpjoin_rsp); - mpjoin_rsp.mmjo_subtype_bkp = MPO_JOIN << 4; - if (tp->t_mpflags & TMPF_BACKUP_PATH) - mpjoin_rsp.mmjo_subtype_bkp |= MPTCP_BACKUP; - mpjoin_rsp.mmjo_addr_id = tp->t_local_aid; - mptcp_get_rands(tp->t_local_aid, tptomptp(tp), - &mpjoin_rsp.mmjo_rand, NULL); - mpjoin_rsp.mmjo_mac = mptcp_get_trunced_hmac(tp->t_local_aid, - mp_tp); - memcpy(opt + optlen, &mpjoin_rsp, mpjoin_rsp.mmjo_len); - optlen += mpjoin_rsp.mmjo_len; + if (tp->t_mpflags & TMPF_BACKUP_PATH) { + mpjoin_req.mmjo_subtype_bkp |= MPTCP_BACKUP; + } else if (inp->inp_boundifp && IFNET_IS_CELLULAR(inp->inp_boundifp) && + mpts->mpts_mpte->mpte_svctype != MPTCP_SVCTYPE_AGGREGATE) { + mpjoin_req.mmjo_subtype_bkp |= MPTCP_BACKUP; + tp->t_mpflags |= TMPF_BACKUP_PATH; } else { - struct mptcp_mpjoin_opt_req mpjoin_req; - - bzero(&mpjoin_req, sizeof (mpjoin_req)); - mpjoin_req.mmjo_kind = TCPOPT_MULTIPATH; - mpjoin_req.mmjo_len = sizeof (mpjoin_req); - mpjoin_req.mmjo_subtype_bkp = MPO_JOIN << 4; - if (tp->t_mpflags & TMPF_BACKUP_PATH) - mpjoin_req.mmjo_subtype_bkp |= MPTCP_BACKUP; - mpjoin_req.mmjo_addr_id = tp->t_local_aid; - mpjoin_req.mmjo_peer_token = mptcp_get_remotetoken(tp->t_mptcb); - if (mpjoin_req.mmjo_peer_token == 0) { - mptcplog((LOG_DEBUG, "MPTCP Socket: %s: peer token 0", - __func__), - MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); - } - mptcp_get_rands(tp->t_local_aid, tptomptp(tp), - &mpjoin_req.mmjo_rand, NULL); - memcpy(opt + optlen, &mpjoin_req, mpjoin_req.mmjo_len); - optlen += mpjoin_req.mmjo_len; - /* send an event up, if Fast Join is requested */ - if (mptcp_zerortt_fastjoin && - (so->so_flags & SOF_MPTCP_FASTJOIN)) { - soevent(so, (SO_FILT_HINT_LOCKED | SO_FILT_HINT_MPFASTJ)); - } + mpts->mpts_flags |= MPTSF_PREFERRED; + } + + mpjoin_req.mmjo_addr_id = tp->t_local_aid; + mpjoin_req.mmjo_peer_token = tptomptp(tp)->mpt_remotetoken; + if (mpjoin_req.mmjo_peer_token == 0) { + mptcplog((LOG_DEBUG, "%s: peer token 0", __func__), + MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); } + mptcp_get_rands(tp->t_local_aid, tptomptp(tp), + &mpjoin_req.mmjo_rand, NULL); + memcpy(opt + optlen, &mpjoin_req, mpjoin_req.mmjo_len); + optlen += mpjoin_req.mmjo_len; + return (optlen); } @@ -241,30 +170,22 @@ mptcp_setup_join_ack_opts(struct tcpcb *tp, u_char *opt, unsigned optlen) join_rsp2.mmjo_len = sizeof (struct mptcp_mpjoin_opt_rsp2); join_rsp2.mmjo_subtype = MPO_JOIN; mptcp_get_hmac(tp->t_local_aid, tptomptp(tp), - (u_char*)&join_rsp2.mmjo_mac, - sizeof (join_rsp2.mmjo_mac)); + (u_char*)&join_rsp2.mmjo_mac); memcpy(opt + optlen, &join_rsp2, join_rsp2.mmjo_len); new_optlen = optlen + join_rsp2.mmjo_len; - tp->t_mpflags |= TMPF_FASTJOINBY2_SEND; return (new_optlen); } unsigned -mptcp_setup_syn_opts(struct socket *so, int flags, u_char *opt, unsigned optlen) +mptcp_setup_syn_opts(struct socket *so, u_char *opt, unsigned optlen) { unsigned new_optlen; - if (!(so->so_flags & SOF_MP_SEC_SUBFLOW)) { - new_optlen = mptcp_setup_first_subflow_syn_opts(so, flags, opt, - optlen); - } else { - /* - * To simulate SYN_ACK with no join opt, comment this line on - * OS X server side. This serves as a testing hook. - */ - new_optlen = mptcp_setup_join_subflow_syn_opts(so, flags, opt, - optlen); - } + if (!(so->so_flags & SOF_MP_SEC_SUBFLOW)) + new_optlen = mptcp_setup_first_subflow_syn_opts(so, opt, optlen); + else + new_optlen = mptcp_setup_join_subflow_syn_opts(so, opt, optlen); + return (new_optlen); } @@ -284,15 +205,15 @@ mptcp_send_mpfail(struct tcpcb *tp, u_char *opt, unsigned int optlen) return (optlen); } + mpte_lock_assert_held(mp_tp->mpt_mpte); + /* if option space low give up */ if ((MAX_TCPOPTLEN - optlen) < sizeof (struct mptcp_mpfail_opt)) { tp->t_mpflags &= ~TMPF_SND_MPFAIL; return (optlen); } - MPT_LOCK(mp_tp); dsn = mp_tp->mpt_rcvnxt; - MPT_UNLOCK(mp_tp); bzero(&fail_opt, sizeof (fail_opt)); fail_opt.mfail_kind = TCPOPT_MULTIPATH; @@ -302,7 +223,7 @@ mptcp_send_mpfail(struct tcpcb *tp, u_char *opt, unsigned int optlen) memcpy(opt + optlen, &fail_opt, len); optlen += len; tp->t_mpflags &= ~TMPF_SND_MPFAIL; - mptcplog((LOG_DEBUG, "MPTCP Socket: %s: %d \n", __func__, + mptcplog((LOG_DEBUG, "%s: %d \n", __func__, tp->t_local_aid), (MPTCP_SOCKET_DBG | MPTCP_SENDER_DBG), MPTCP_LOGLVL_LOG); return (optlen); @@ -315,7 +236,6 @@ mptcp_send_infinite_mapping(struct tcpcb *tp, u_char *opt, unsigned int optlen) struct mptcb *mp_tp = NULL; size_t len = sizeof (struct mptcp_dsn_opt); struct socket *so = tp->t_inpcb->inp_socket; - int error = 0; int csum_len = 0; if (!so) @@ -325,15 +245,15 @@ mptcp_send_infinite_mapping(struct tcpcb *tp, u_char *opt, unsigned int optlen) if (mp_tp == NULL) return (optlen); - MPT_LOCK(mp_tp); + mpte_lock_assert_held(mp_tp->mpt_mpte); + if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) csum_len = 2; /* try later */ - if ((MAX_TCPOPTLEN - optlen) < (len + csum_len)) { - MPT_UNLOCK(mp_tp); + if ((MAX_TCPOPTLEN - optlen) < (len + csum_len)) return (optlen); - } + bzero(&infin_opt, sizeof (infin_opt)); infin_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH; infin_opt.mdss_copt.mdss_len = len + csum_len; @@ -352,20 +272,18 @@ mptcp_send_infinite_mapping(struct tcpcb *tp, u_char *opt, unsigned int optlen) ((mp_tp->mpt_local_idsn + 1) == mp_tp->mpt_snduna)) { infin_opt.mdss_subflow_seqn = 1; - mptcplog((LOG_DEBUG, "MPTCP Socket: %s: idsn %llu" - "snduna %llu \n", __func__, mp_tp->mpt_local_idsn, + mptcplog((LOG_DEBUG, "%s: idsn %llu snduna %llu \n", + __func__, mp_tp->mpt_local_idsn, mp_tp->mpt_snduna), (MPTCP_SOCKET_DBG | MPTCP_SENDER_DBG), MPTCP_LOGLVL_LOG); } else { - infin_opt.mdss_subflow_seqn = tp->snd_una - tp->iss; + infin_opt.mdss_subflow_seqn = tp->snd_una - tp->t_mpsub->mpts_iss; } infin_opt.mdss_dsn = (u_int32_t) MPTCP_DATASEQ_LOW32(mp_tp->mpt_snduna); } - MPT_UNLOCK(mp_tp); - if (error != 0) - return (optlen); + if ((infin_opt.mdss_dsn == 0) || (infin_opt.mdss_subflow_seqn == 0)) { return (optlen); } @@ -382,15 +300,13 @@ mptcp_send_infinite_mapping(struct tcpcb *tp, u_char *opt, unsigned int optlen) optlen += csum_len; } - mptcplog((LOG_DEBUG, "MPTCP Socket: %s: dsn = %x, seq = %x len = %x\n", - __func__, + mptcplog((LOG_DEBUG, "%s: dsn = %x, seq = %x len = %x\n", __func__, ntohl(infin_opt.mdss_dsn), ntohl(infin_opt.mdss_subflow_seqn), ntohs(infin_opt.mdss_data_len)), (MPTCP_SOCKET_DBG | MPTCP_SENDER_DBG), MPTCP_LOGLVL_LOG); - /* so->so_flags &= ~SOF_MPTCP_CLIENT; */ tp->t_mpflags |= TMPF_INFIN_SENT; tcpstat.tcps_estab_fallback++; return (optlen); @@ -400,24 +316,21 @@ mptcp_send_infinite_mapping(struct tcpcb *tp, u_char *opt, unsigned int optlen) static int mptcp_ok_to_fin(struct tcpcb *tp, u_int64_t dsn, u_int32_t datalen) { - struct mptcb *mp_tp = NULL; - mp_tp = tptomptp(tp); + struct mptcb *mp_tp = tptomptp(tp); + + mpte_lock_assert_held(mp_tp->mpt_mpte); - MPT_LOCK(mp_tp); dsn = (mp_tp->mpt_sndmax & MPTCP_DATASEQ_LOW32_MASK) | dsn; - if ((dsn + datalen) == mp_tp->mpt_sndmax) { - MPT_UNLOCK(mp_tp); + if ((dsn + datalen) == mp_tp->mpt_sndmax) return (1); - } - MPT_UNLOCK(mp_tp); + return (0); } unsigned int mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, - unsigned int optlen, int flags, int datalen, - unsigned int **dss_lenp, u_int8_t **finp, u_int64_t *dss_valp, - u_int32_t **sseqp, boolean_t *p_mptcp_acknow) + unsigned int optlen, int flags, int len, + boolean_t *p_mptcp_acknow) { struct inpcb *inp = (struct inpcb *)tp->t_inpcb; struct socket *so = inp->inp_socket; @@ -425,17 +338,15 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, boolean_t do_csum = FALSE; boolean_t send_64bit_dsn = FALSE; boolean_t send_64bit_ack = FALSE; - u_int32_t old_mpt_flags = tp->t_mpflags & - (TMPF_SND_MPPRIO | TMPF_SND_REM_ADDR | TMPF_SND_MPFAIL); + u_int32_t old_mpt_flags = tp->t_mpflags & TMPF_MPTCP_SIGNALS; - if ((mptcp_enable == 0) || - (mp_tp == NULL) || - (mp_tp->mpt_flags & MPTCPF_PEEL_OFF) || - (tp->t_state == TCPS_CLOSED)) { + if (mptcp_enable == 0 || mp_tp == NULL || tp->t_state == TCPS_CLOSED) { /* do nothing */ goto ret_optlen; } + mpte_lock_assert_held(mp_tp->mpt_mpte); + if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) { do_csum = TRUE; } @@ -447,11 +358,9 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, if ((MAX_TCPOPTLEN - optlen) < sizeof (struct mptcp_mpcapable_opt_common)) { - mptcplog((LOG_ERR, "MPTCP Socket: " - "%s: no space left %d flags %x " - "tp->t_mpflags %x " - "len %d\n", __func__, optlen, flags, tp->t_mpflags, - datalen), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); + mptcplog((LOG_ERR, "%s: no space left %d flags %x tp->t_mpflags %x len %d\n", + __func__, optlen, flags, tp->t_mpflags, len), + MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); goto ret_optlen; } @@ -463,17 +372,7 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, goto ret_optlen; } - if (((tp->t_mpflags & TMPF_FASTJOINBY2_SEND) || - (tp->t_mpflags & TMPF_FASTJOIN_SEND )) && - (datalen > 0)) { - tp->t_mpflags &= ~TMPF_FASTJOINBY2_SEND; - tp->t_mpflags &= ~TMPF_FASTJOIN_SEND; - goto fastjoin_send; - } - - if (((tp->t_mpflags & TMPF_PREESTABLISHED) && - (!(tp->t_mpflags & TMPF_SENT_KEYS)) && - (!(tp->t_mpflags & TMPF_JOINED_FLOW)))) { + if (tp->t_mpflags & TMPF_SND_KEYS) { struct mptcp_mpcapable_opt_rsp1 mptcp_opt; if ((MAX_TCPOPTLEN - optlen) < sizeof (struct mptcp_mpcapable_opt_rsp1)) @@ -486,17 +385,13 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, mptcp_opt.mmc_common.mmco_version = mp_tp->mpt_version; /* HMAC-SHA1 is the proposal */ mptcp_opt.mmc_common.mmco_flags |= MPCAP_PROPOSAL_SBIT; - MPT_LOCK(mp_tp); if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) mptcp_opt.mmc_common.mmco_flags |= MPCAP_CHECKSUM_CBIT; - mptcp_opt.mmc_localkey = mptcp_get_localkey(mp_tp); - mptcp_opt.mmc_remotekey = mptcp_get_remotekey(mp_tp); - MPT_UNLOCK(mp_tp); + mptcp_opt.mmc_localkey = mp_tp->mpt_localkey; + mptcp_opt.mmc_remotekey = mp_tp->mpt_remotekey; memcpy(opt + optlen, &mptcp_opt, mptcp_opt.mmc_common.mmco_len); optlen += mptcp_opt.mmc_common.mmco_len; - tp->t_mpflags |= TMPF_SENT_KEYS | TMPF_MPTCP_TRUE; - so->so_flags |= SOF_MPTCP_TRUE; - tp->t_mpflags &= ~TMPF_PREESTABLISHED; + tp->t_mpflags &= ~TMPF_SND_KEYS; if (!tp->t_mpuna) { tp->t_mpuna = tp->snd_una; @@ -506,17 +401,7 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, goto ret_optlen; } - if ((tp->t_mpflags & TMPF_JOINED_FLOW) && - (tp->t_mpflags & TMPF_PREESTABLISHED) && - (!(tp->t_mpflags & TMPF_RECVD_JOIN)) && - (tp->t_mpflags & TMPF_SENT_JOIN) && - (!(tp->t_mpflags & TMPF_MPTCP_TRUE))) { - MPT_LOCK(mp_tp); - if (mptcp_get_localkey(mp_tp) == 0) { - MPT_UNLOCK(mp_tp); - goto ret_optlen; - } - MPT_UNLOCK(mp_tp); + if (tp->t_mpflags & TMPF_SND_JACK) { /* Do the ACK part */ optlen = mptcp_setup_join_ack_opts(tp, opt, optlen); if (!tp->t_mpuna) { @@ -525,12 +410,13 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, /* Start a timer to retransmit the ACK */ tp->t_timer[TCPT_JACK_RXMT] = OFFSET_FROM_START(tp, tcp_jack_rxmt); + + tp->t_mpflags &= ~TMPF_SND_JACK; goto ret_optlen; } if (!(tp->t_mpflags & TMPF_MPTCP_TRUE)) goto ret_optlen; -fastjoin_send: /* * From here on, all options are sent only if MPTCP_TRUE * or when data is sent early on as in Fast Join @@ -552,45 +438,39 @@ fastjoin_send: optlen = mptcp_snd_mpprio(tp, opt, optlen); } - MPT_LOCK(mp_tp); - if ((mp_tp->mpt_flags & MPTCPF_SND_64BITDSN) || force_64bit_dsn) { + if (mp_tp->mpt_flags & MPTCPF_SND_64BITDSN) { send_64bit_dsn = TRUE; } if (mp_tp->mpt_flags & MPTCPF_SND_64BITACK) send_64bit_ack = TRUE; - MPT_UNLOCK(mp_tp); - -#define CHECK_OPTLEN { \ - if ((MAX_TCPOPTLEN - optlen) < len) { \ - mptcplog((LOG_ERR, "MPTCP Socket: " \ - "%s: len %d optlen %d \n", __func__, len, optlen), \ - MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); \ - goto ret_optlen; \ - } \ +#define CHECK_OPTLEN { \ + if ((MAX_TCPOPTLEN - optlen) < dssoptlen) { \ + mptcplog((LOG_ERR, "%s: dssoptlen %d optlen %d \n", __func__, \ + dssoptlen, optlen), \ + MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); \ + goto ret_optlen; \ + } \ } #define DO_FIN(dsn_opt) { \ int sndfin = 0; \ - sndfin = mptcp_ok_to_fin(tp, dsn_opt.mdss_dsn, datalen); \ + sndfin = mptcp_ok_to_fin(tp, dsn_opt.mdss_dsn, len); \ if (sndfin) { \ dsn_opt.mdss_copt.mdss_flags |= MDSS_F; \ - *finp = opt + optlen + offsetof(struct mptcp_dss_copt, \ - mdss_flags); \ dsn_opt.mdss_data_len += 1; \ } \ } #define CHECK_DATALEN { \ /* MPTCP socket does not support IP options */ \ - if ((datalen + optlen + len) > tp->t_maxopd) { \ - mptcplog((LOG_ERR, "MPTCP Socket: " \ - "%s: nosp %d len %d opt %d %d %d\n", \ - __func__, datalen, len, optlen, \ + if ((len + optlen + dssoptlen) > tp->t_maxopd) { \ + mptcplog((LOG_ERR, "%s: nosp %d len %d opt %d %d %d\n", \ + __func__, len, dssoptlen, optlen, \ tp->t_maxseg, tp->t_maxopd), \ MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); \ /* remove option length from payload len */ \ - datalen = tp->t_maxopd - optlen - len; \ + len = tp->t_maxopd - optlen - dssoptlen; \ } \ } @@ -606,10 +486,11 @@ fastjoin_send: * XXX If this delay causes issue, remove the 2-byte padding. */ struct mptcp_dss64_ack32_opt dsn_ack_opt; - unsigned int len = sizeof (dsn_ack_opt); + unsigned int dssoptlen = sizeof (dsn_ack_opt); + uint16_t dss_csum; if (do_csum) { - len += 2; + dssoptlen += 2; } CHECK_OPTLEN; @@ -617,18 +498,17 @@ fastjoin_send: bzero(&dsn_ack_opt, sizeof (dsn_ack_opt)); dsn_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH; dsn_ack_opt.mdss_copt.mdss_subtype = MPO_DSS; - dsn_ack_opt.mdss_copt.mdss_len = len; + dsn_ack_opt.mdss_copt.mdss_len = dssoptlen; dsn_ack_opt.mdss_copt.mdss_flags |= MDSS_M | MDSS_m | MDSS_A; CHECK_DATALEN; - mptcp_output_getm_dsnmap64(so, off, (u_int32_t)datalen, - &dsn_ack_opt.mdss_dsn, - &dsn_ack_opt.mdss_subflow_seqn, - &dsn_ack_opt.mdss_data_len); - - *dss_valp = dsn_ack_opt.mdss_dsn; + mptcp_output_getm_dsnmap64(so, off, + &dsn_ack_opt.mdss_dsn, + &dsn_ack_opt.mdss_subflow_seqn, + &dsn_ack_opt.mdss_data_len, + &dss_csum); if ((dsn_ack_opt.mdss_data_len == 0) || (dsn_ack_opt.mdss_dsn == 0)) { @@ -639,30 +519,21 @@ fastjoin_send: DO_FIN(dsn_ack_opt); } - MPT_LOCK(mp_tp); dsn_ack_opt.mdss_ack = htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt)); - MPT_UNLOCK(mp_tp); dsn_ack_opt.mdss_dsn = mptcp_hton64(dsn_ack_opt.mdss_dsn); dsn_ack_opt.mdss_subflow_seqn = htonl( dsn_ack_opt.mdss_subflow_seqn); dsn_ack_opt.mdss_data_len = htons( dsn_ack_opt.mdss_data_len); - *dss_lenp = (unsigned int *)(void *)(opt + optlen + - offsetof(struct mptcp_dss64_ack32_opt, mdss_data_len)); memcpy(opt + optlen, &dsn_ack_opt, sizeof (dsn_ack_opt)); + if (do_csum) + *((uint16_t *)(void *)(opt + optlen + sizeof (dsn_ack_opt))) = dss_csum; - if (do_csum) { - *sseqp = (u_int32_t *)(void *)(opt + optlen + - offsetof(struct mptcp_dss64_ack32_opt, - mdss_subflow_seqn)); - } - optlen += len; - mptcplog((LOG_DEBUG,"MPTCP Socket: " - "%s: long DSS = %llx ACK = %llx \n", - __func__, + optlen += dssoptlen; + mptcplog((LOG_DEBUG,"%s: long DSS = %llx ACK = %llx \n", __func__, mptcp_ntoh64(dsn_ack_opt.mdss_dsn), mptcp_ntoh64(dsn_ack_opt.mdss_ack)), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG); @@ -675,10 +546,11 @@ fastjoin_send: (!send_64bit_dsn) && !(tp->t_mpflags & TMPF_MPTCP_ACKNOW)) { struct mptcp_dsn_opt dsn_opt; - unsigned int len = sizeof (struct mptcp_dsn_opt); + unsigned int dssoptlen = sizeof (struct mptcp_dsn_opt); + uint16_t dss_csum; if (do_csum) { - len += 2; + dssoptlen += 2; } CHECK_OPTLEN; @@ -686,15 +558,15 @@ fastjoin_send: bzero(&dsn_opt, sizeof (dsn_opt)); dsn_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH; dsn_opt.mdss_copt.mdss_subtype = MPO_DSS; - dsn_opt.mdss_copt.mdss_len = len; + dsn_opt.mdss_copt.mdss_len = dssoptlen; dsn_opt.mdss_copt.mdss_flags |= MDSS_M; CHECK_DATALEN; - mptcp_output_getm_dsnmap32(so, off, (u_int32_t)datalen, - &dsn_opt.mdss_dsn, - &dsn_opt.mdss_subflow_seqn, &dsn_opt.mdss_data_len, - dss_valp); + mptcp_output_getm_dsnmap32(so, off, &dsn_opt.mdss_dsn, + &dsn_opt.mdss_subflow_seqn, + &dsn_opt.mdss_data_len, + &dss_csum); if ((dsn_opt.mdss_data_len == 0) || (dsn_opt.mdss_dsn == 0)) { @@ -708,14 +580,11 @@ fastjoin_send: dsn_opt.mdss_dsn = htonl(dsn_opt.mdss_dsn); dsn_opt.mdss_subflow_seqn = htonl(dsn_opt.mdss_subflow_seqn); dsn_opt.mdss_data_len = htons(dsn_opt.mdss_data_len); - *dss_lenp = (unsigned int *)(void *)(opt + optlen + - offsetof(struct mptcp_dsn_opt, mdss_data_len)); memcpy(opt + optlen, &dsn_opt, sizeof (dsn_opt)); - if (do_csum) { - *sseqp = (u_int32_t *)(void *)(opt + optlen + - offsetof(struct mptcp_dsn_opt, mdss_subflow_seqn)); - } - optlen += len; + if (do_csum) + *((uint16_t *)(void *)(opt + optlen + sizeof (dsn_opt))) = dss_csum; + + optlen += dssoptlen; tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW; goto ret_optlen; } @@ -727,23 +596,21 @@ fastjoin_send: !(tp->t_mpflags & TMPF_SEND_DFIN)) { struct mptcp_data_ack_opt dack_opt; - unsigned int len = 0; + unsigned int dssoptlen = 0; do_ack32_only: - len = sizeof (dack_opt); + dssoptlen = sizeof (dack_opt); CHECK_OPTLEN; - bzero(&dack_opt, len); + bzero(&dack_opt, dssoptlen); dack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH; - dack_opt.mdss_copt.mdss_len = len; + dack_opt.mdss_copt.mdss_len = dssoptlen; dack_opt.mdss_copt.mdss_subtype = MPO_DSS; dack_opt.mdss_copt.mdss_flags |= MDSS_A; - MPT_LOCK_SPIN(mp_tp); dack_opt.mdss_ack = htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt)); - MPT_UNLOCK(mp_tp); - memcpy(opt + optlen, &dack_opt, len); - optlen += len; + memcpy(opt + optlen, &dack_opt, dssoptlen); + optlen += dssoptlen; VERIFY(optlen <= MAX_TCPOPTLEN); tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW; goto ret_optlen; @@ -755,27 +622,25 @@ do_ack32_only: !(tp->t_mpflags & TMPF_SEND_DSN) && !(tp->t_mpflags & TMPF_SEND_DFIN)) { struct mptcp_data_ack64_opt dack_opt; - unsigned int len = 0; + unsigned int dssoptlen = 0; do_ack64_only: - len = sizeof (dack_opt); + dssoptlen = sizeof (dack_opt); CHECK_OPTLEN; - bzero(&dack_opt, len); + bzero(&dack_opt, dssoptlen); dack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH; - dack_opt.mdss_copt.mdss_len = len; + dack_opt.mdss_copt.mdss_len = dssoptlen; dack_opt.mdss_copt.mdss_subtype = MPO_DSS; dack_opt.mdss_copt.mdss_flags |= (MDSS_A | MDSS_a); - MPT_LOCK_SPIN(mp_tp); dack_opt.mdss_ack = mptcp_hton64(mp_tp->mpt_rcvnxt); /* * The other end should retransmit 64-bit DSN until it * receives a 64-bit ACK. */ mp_tp->mpt_flags &= ~MPTCPF_SND_64BITACK; - MPT_UNLOCK(mp_tp); - memcpy(opt + optlen, &dack_opt, len); - optlen += len; + memcpy(opt + optlen, &dack_opt, dssoptlen); + optlen += dssoptlen; VERIFY(optlen <= MAX_TCPOPTLEN); tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW; goto ret_optlen; @@ -787,30 +652,28 @@ do_ack64_only: (!send_64bit_ack) && (tp->t_mpflags & TMPF_MPTCP_ACKNOW)) { struct mptcp_dss_ack_opt dss_ack_opt; - unsigned int len = sizeof (dss_ack_opt); + unsigned int dssoptlen = sizeof (dss_ack_opt); + uint16_t dss_csum; if (do_csum) - len += 2; + dssoptlen += 2; CHECK_OPTLEN; bzero(&dss_ack_opt, sizeof (dss_ack_opt)); dss_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH; - dss_ack_opt.mdss_copt.mdss_len = len; + dss_ack_opt.mdss_copt.mdss_len = dssoptlen; dss_ack_opt.mdss_copt.mdss_subtype = MPO_DSS; dss_ack_opt.mdss_copt.mdss_flags |= MDSS_A | MDSS_M; - MPT_LOCK_SPIN(mp_tp); dss_ack_opt.mdss_ack = htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt)); - MPT_UNLOCK(mp_tp); CHECK_DATALEN; - mptcp_output_getm_dsnmap32(so, off, (u_int32_t)datalen, - &dss_ack_opt.mdss_dsn, - &dss_ack_opt.mdss_subflow_seqn, - &dss_ack_opt.mdss_data_len, - dss_valp); + mptcp_output_getm_dsnmap32(so, off, &dss_ack_opt.mdss_dsn, + &dss_ack_opt.mdss_subflow_seqn, + &dss_ack_opt.mdss_data_len, + &dss_csum); if ((dss_ack_opt.mdss_data_len == 0) || (dss_ack_opt.mdss_dsn == 0)) { @@ -825,16 +688,11 @@ do_ack64_only: dss_ack_opt.mdss_subflow_seqn = htonl(dss_ack_opt.mdss_subflow_seqn); dss_ack_opt.mdss_data_len = htons(dss_ack_opt.mdss_data_len); - *dss_lenp = (unsigned int *)(void *)(opt + optlen + - offsetof(struct mptcp_dss_ack_opt, mdss_data_len)); memcpy(opt + optlen, &dss_ack_opt, sizeof (dss_ack_opt)); - if (do_csum) { - *sseqp = (u_int32_t *)(void *)(opt + optlen + - offsetof(struct mptcp_dss_ack_opt, - mdss_subflow_seqn)); - } + if (do_csum) + *((uint16_t *)(void *)(opt + optlen + sizeof (dss_ack_opt))) = dss_csum; - optlen += len; + optlen += dssoptlen; if (optlen > MAX_TCPOPTLEN) panic("optlen too large"); @@ -848,28 +706,28 @@ do_ack64_only: (send_64bit_ack) && (tp->t_mpflags & TMPF_MPTCP_ACKNOW)) { struct mptcp_dss32_ack64_opt dss_ack_opt; - unsigned int len = sizeof (dss_ack_opt); + unsigned int dssoptlen = sizeof (dss_ack_opt); + uint16_t dss_csum; if (do_csum) - len += 2; + dssoptlen += 2; CHECK_OPTLEN; bzero(&dss_ack_opt, sizeof (dss_ack_opt)); dss_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH; - dss_ack_opt.mdss_copt.mdss_len = len; + dss_ack_opt.mdss_copt.mdss_len = dssoptlen; dss_ack_opt.mdss_copt.mdss_subtype = MPO_DSS; dss_ack_opt.mdss_copt.mdss_flags |= MDSS_M | MDSS_A | MDSS_a; - MPT_LOCK_SPIN(mp_tp); dss_ack_opt.mdss_ack = mptcp_hton64(mp_tp->mpt_rcvnxt); - MPT_UNLOCK(mp_tp); CHECK_DATALEN; - mptcp_output_getm_dsnmap32(so, off, (u_int32_t)datalen, - &dss_ack_opt.mdss_dsn, &dss_ack_opt.mdss_subflow_seqn, - &dss_ack_opt.mdss_data_len, dss_valp); + mptcp_output_getm_dsnmap32(so, off, &dss_ack_opt.mdss_dsn, + &dss_ack_opt.mdss_subflow_seqn, + &dss_ack_opt.mdss_data_len, + &dss_csum); if ((dss_ack_opt.mdss_data_len == 0) || (dss_ack_opt.mdss_dsn == 0)) { @@ -884,16 +742,11 @@ do_ack64_only: dss_ack_opt.mdss_subflow_seqn = htonl(dss_ack_opt.mdss_subflow_seqn); dss_ack_opt.mdss_data_len = htons(dss_ack_opt.mdss_data_len); - *dss_lenp = (unsigned int *)(void *)(opt + optlen + - offsetof(struct mptcp_dss32_ack64_opt, mdss_data_len)); memcpy(opt + optlen, &dss_ack_opt, sizeof (dss_ack_opt)); - if (do_csum) { - *sseqp = (u_int32_t *)(void *)(opt + optlen + - offsetof(struct mptcp_dss32_ack64_opt, - mdss_subflow_seqn)); - } + if (do_csum) + *((uint16_t *)(void *)(opt + optlen + sizeof (dss_ack_opt))) = dss_csum; - optlen += len; + optlen += dssoptlen; if (optlen > MAX_TCPOPTLEN) panic("optlen too large"); @@ -903,58 +756,48 @@ do_ack64_only: if (tp->t_mpflags & TMPF_SEND_DFIN) { struct mptcp_dss_ack_opt dss_ack_opt; - unsigned int len = sizeof (struct mptcp_dss_ack_opt); + unsigned int dssoptlen = sizeof (struct mptcp_dss_ack_opt); if (do_csum) - len += 2; + dssoptlen += 2; CHECK_OPTLEN; bzero(&dss_ack_opt, sizeof (dss_ack_opt)); - MPT_LOCK(mp_tp); /* * Data FIN occupies one sequence space. * Don't send it if it has been Acked. */ if (((mp_tp->mpt_sndnxt + 1) != mp_tp->mpt_sndmax) || - (mp_tp->mpt_snduna == mp_tp->mpt_sndmax)) { - MPT_UNLOCK(mp_tp); + (mp_tp->mpt_snduna == mp_tp->mpt_sndmax)) goto ret_optlen; - } dss_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH; - dss_ack_opt.mdss_copt.mdss_len = len; + dss_ack_opt.mdss_copt.mdss_len = dssoptlen; dss_ack_opt.mdss_copt.mdss_subtype = MPO_DSS; dss_ack_opt.mdss_copt.mdss_flags |= MDSS_A | MDSS_M | MDSS_F; dss_ack_opt.mdss_ack = htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt)); dss_ack_opt.mdss_dsn = htonl(MPTCP_DATASEQ_LOW32(mp_tp->mpt_sndnxt)); - MPT_UNLOCK(mp_tp); dss_ack_opt.mdss_subflow_seqn = 0; dss_ack_opt.mdss_data_len = 1; dss_ack_opt.mdss_data_len = htons(dss_ack_opt.mdss_data_len); memcpy(opt + optlen, &dss_ack_opt, sizeof (dss_ack_opt)); - if (do_csum) { - *dss_valp = mp_tp->mpt_sndnxt; - *sseqp = (u_int32_t *)(void *)(opt + optlen + - offsetof(struct mptcp_dss_ack_opt, - mdss_subflow_seqn)); - } - optlen += len; + optlen += dssoptlen; } ret_optlen: if (TRUE == *p_mptcp_acknow ) { VERIFY(old_mpt_flags != 0); - u_int32_t new_mpt_flags = tp->t_mpflags & - (TMPF_SND_MPPRIO | TMPF_SND_REM_ADDR | TMPF_SND_MPFAIL); + u_int32_t new_mpt_flags = tp->t_mpflags & TMPF_MPTCP_SIGNALS; /* * If none of the above mpflags were acted on by * this routine, reset these flags and set p_mptcp_acknow * to false. + * * XXX The reset value of p_mptcp_acknow can be used * to communicate tcp_output to NOT send a pure ack without any * MPTCP options as it will be treated as a dup ack. @@ -965,16 +808,14 @@ ret_optlen: * we haven't modified the logic in tcp_output to avoid * that. */ - if ((old_mpt_flags == new_mpt_flags) || (new_mpt_flags == 0)) { - tp->t_mpflags &= ~(TMPF_SND_MPPRIO - | TMPF_SND_REM_ADDR | TMPF_SND_MPFAIL); + if (old_mpt_flags == new_mpt_flags) { + tp->t_mpflags &= ~TMPF_MPTCP_SIGNALS; *p_mptcp_acknow = FALSE; - mptcplog((LOG_DEBUG, "MPTCP Sender: %s: no action \n", - __func__), MPTCP_SENDER_DBG, MPTCP_LOGLVL_LOG); + mptcplog((LOG_DEBUG, "%s: no action \n", __func__), + MPTCP_SENDER_DBG, MPTCP_LOGLVL_LOG); } else { - mptcplog((LOG_DEBUG, "MPTCP Sender: acknow set, " - "old flags %x new flags %x \n", - old_mpt_flags, new_mpt_flags), + mptcplog((LOG_DEBUG, "%s: acknow set, old flags %x new flags %x \n", + __func__, old_mpt_flags, new_mpt_flags), MPTCP_SENDER_DBG, MPTCP_LOGLVL_LOG); } } @@ -993,8 +834,8 @@ mptcp_sanitize_option(struct tcpcb *tp, int mptcp_subtype) int ret = 1; if (mp_tp == NULL) { - mptcplog((LOG_ERR, "MPTCP Socket: %s: NULL mpsocket \n", - __func__), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); + mptcplog((LOG_ERR, "%s: NULL mpsocket \n", __func__), + MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); return (0); } @@ -1013,8 +854,7 @@ mptcp_sanitize_option(struct tcpcb *tp, int mptcp_subtype) break; default: ret = 0; - mptcplog((LOG_ERR, "MPTCP Socket: " - "%s: type = %d \n", __func__, + mptcplog((LOG_ERR, "%s: type = %d \n", __func__, mptcp_subtype), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); break; @@ -1048,6 +888,8 @@ mptcp_do_mpcapable_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, struct mptcp_mpcapable_opt_rsp *rsp = NULL; struct mptcb *mp_tp = tptomptp(tp); + mpte_lock_assert_held(mp_tp->mpt_mpte); + /* Only valid on SYN/ACK */ if ((th->th_flags & (TH_SYN | TH_ACK)) != (TH_SYN | TH_ACK)) return; @@ -1065,8 +907,7 @@ mptcp_do_mpcapable_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, /* A SYN/ACK contains peer's key and flags */ if (optlen != sizeof (struct mptcp_mpcapable_opt_rsp)) { /* complain */ - mptcplog((LOG_ERR, "MPTCP Socket: " - "%s: SYN_ACK optlen = %d, sizeof mp opt = %lu \n", + mptcplog((LOG_ERR, "%s: SYN_ACK optlen = %d, sizeof mp opt = %lu \n", __func__, optlen, sizeof (struct mptcp_mpcapable_opt_rsp)), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); @@ -1083,7 +924,6 @@ mptcp_do_mpcapable_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, mp_tp->mpt_flags |= MPTCPF_CHECKSUM; rsp = (struct mptcp_mpcapable_opt_rsp *)cp; - MPT_LOCK(mp_tp); mp_tp->mpt_remotekey = rsp->mmc_localkey; /* For now just downgrade to the peer's version */ mp_tp->mpt_peer_version = rsp->mmc_common.mmco_version; @@ -1093,12 +933,11 @@ mptcp_do_mpcapable_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, } if (mptcp_init_remote_parms(mp_tp) != 0) { tcpstat.tcps_invalid_mpcap++; - MPT_UNLOCK(mp_tp); return; } - MPT_UNLOCK(mp_tp); tcp_heuristic_mptcp_success(tp); - tp->t_mpflags |= TMPF_PREESTABLISHED; + tp->t_mpflags |= (TMPF_SND_KEYS | TMPF_MPTCP_TRUE); + tp->t_inpcb->inp_socket->so_flags |= SOF_MPTCP_TRUE; } @@ -1122,9 +961,8 @@ mptcp_do_mpjoin_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, int optlen) return; if (optlen != sizeof (struct mptcp_mpjoin_opt_rsp)) { - mptcplog((LOG_ERR, "MPTCP Socket: " - "SYN_ACK: unexpected optlen = %d mp " - "option = %lu\n", optlen, + mptcplog((LOG_ERR, "%s: SYN_ACK: unexpected optlen = %d mp " + "option = %lu\n", __func__, optlen, sizeof (struct mptcp_mpjoin_opt_rsp)), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); tp->t_mpflags &= ~TMPF_PREESTABLISHED; @@ -1138,77 +976,146 @@ mptcp_do_mpjoin_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, int optlen) error = mptcp_validate_join_hmac(tp, (u_char*)&join_rsp->mmjo_mac, SHA1_TRUNCATED); if (error) { - mptcplog((LOG_ERR, "MPTCP Socket: %s: " - "SYN_ACK error = %d \n", __func__, error), + mptcplog((LOG_ERR, "%s: SYN_ACK error = %d \n", __func__, error), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR); tp->t_mpflags &= ~TMPF_PREESTABLISHED; /* send RST and close */ MPTCP_JOPT_ERROR_PATH(tp); return; } - tp->t_mpflags |= TMPF_SENT_JOIN; + tp->t_mpflags |= (TMPF_SENT_JOIN | TMPF_SND_JACK); } static int mptcp_validate_join_hmac(struct tcpcb *tp, u_char* hmac, int mac_len) { u_char digest[SHA1_RESULTLEN] = {0}; - struct mptcb *mp_tp = NULL; - mptcp_key_t rem_key, loc_key; + struct mptcb *mp_tp = tptomptp(tp); u_int32_t rem_rand, loc_rand; - mp_tp = tp->t_mptcb; + mpte_lock_assert_held(mp_tp->mpt_mpte); rem_rand = loc_rand = 0; - MPT_LOCK(mp_tp); - rem_key = mp_tp->mpt_remotekey; - - /* - * Can happen if the MPTCP-connection is about to be closed and we - * receive an MP_JOIN in-between the events are being handled by the - * worker thread. - */ - if (mp_tp->mpt_localkey == NULL) { - MPT_UNLOCK(mp_tp); - return (-1); - } - - loc_key = *mp_tp->mpt_localkey; - MPT_UNLOCK(mp_tp); - mptcp_get_rands(tp->t_local_aid, mp_tp, &loc_rand, &rem_rand); if ((rem_rand == 0) || (loc_rand == 0)) return (-1); - mptcp_hmac_sha1(rem_key, loc_key, rem_rand, loc_rand, - digest, sizeof (digest)); + mptcp_hmac_sha1(mp_tp->mpt_remotekey, mp_tp->mpt_localkey, rem_rand, loc_rand, + digest); if (bcmp(digest, hmac, mac_len) == 0) return (0); /* matches */ else { printf("%s: remote key %llx local key %llx remote rand %x " - "local rand %x \n", __func__, rem_key, loc_key, + "local rand %x \n", __func__, mp_tp->mpt_remotekey, mp_tp->mpt_localkey, rem_rand, loc_rand); return (-1); } } +/* + * Update the mptcb send state variables, but the actual sbdrop occurs + * in MPTCP layer + */ +void +mptcp_data_ack_rcvd(struct mptcb *mp_tp, struct tcpcb *tp, u_int64_t full_dack) +{ + u_int64_t acked = 0; + + acked = full_dack - mp_tp->mpt_snduna; + + if (acked) { + struct socket *mp_so = mptetoso(mp_tp->mpt_mpte); + + if (acked > mp_so->so_snd.sb_cc) { + if (acked > mp_so->so_snd.sb_cc + 1 || + mp_tp->mpt_state < MPTCPS_FIN_WAIT_1) + mptcplog((LOG_ERR, "%s: acked %u, sb_cc %u full %u suna %u state %u\n", + __func__, (uint32_t)acked, mp_so->so_snd.sb_cc, + (uint32_t)full_dack, (uint32_t)mp_tp->mpt_snduna, + mp_tp->mpt_state), + MPTCP_RECEIVER_DBG, MPTCP_LOGLVL_ERR); + + sbdrop(&mp_so->so_snd, (int)mp_so->so_snd.sb_cc); + } else { + sbdrop(&mp_so->so_snd, acked); + } + + mp_tp->mpt_snduna += acked; + /* In degraded mode, we may get some Data ACKs */ + if ((tp->t_mpflags & TMPF_TCP_FALLBACK) && + !(mp_tp->mpt_flags & MPTCPF_POST_FALLBACK_SYNC) && + MPTCP_SEQ_GT(mp_tp->mpt_sndnxt, mp_tp->mpt_snduna)) { + /* bring back sndnxt to retransmit MPTCP data */ + mp_tp->mpt_sndnxt = mp_tp->mpt_dsn_at_csum_fail; + mp_tp->mpt_flags |= MPTCPF_POST_FALLBACK_SYNC; + tp->t_inpcb->inp_socket->so_flags1 |= + SOF1_POST_FALLBACK_SYNC; + } + + mptcp_clean_reinjectq(mp_tp->mpt_mpte); + + sowwakeup(mp_so); + } + if (full_dack == mp_tp->mpt_sndmax && + mp_tp->mpt_state >= MPTCPS_FIN_WAIT_1) { + mptcp_close_fsm(mp_tp, MPCE_RECV_DATA_ACK); + tp->t_mpflags &= ~TMPF_SEND_DFIN; + } +} + +void +mptcp_update_window_fallback(struct tcpcb *tp) +{ + struct mptcb *mp_tp = tptomptp(tp); + + mpte_lock_assert_held(mp_tp->mpt_mpte); + + if (!(mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP)) + return; + + mptcplog((LOG_DEBUG, "%s: update window to %u\n", __func__, tp->snd_wnd), + MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE); + + mp_tp->mpt_sndwnd = tp->snd_wnd; + mp_tp->mpt_sndwl1 = mp_tp->mpt_rcvnxt; + mp_tp->mpt_sndwl2 = mp_tp->mpt_snduna; + + sowwakeup(tp->t_inpcb->inp_socket); +} + +static void +mptcp_update_window(struct mptcb *mp_tp, u_int64_t ack, u_int64_t seq, + u_int32_t tiwin) +{ + /* Don't look at the window if there is no ACK flag */ + if ((SEQ_LT(mp_tp->mpt_sndwl1, seq) || + (mp_tp->mpt_sndwl1 == seq && (SEQ_LT(mp_tp->mpt_sndwl2, ack) || + (mp_tp->mpt_sndwl2 == ack && tiwin > mp_tp->mpt_sndwnd))))) { + mp_tp->mpt_sndwnd = tiwin; + mp_tp->mpt_sndwl1 = seq; + mp_tp->mpt_sndwl2 = ack; + + mptcplog((LOG_DEBUG, "%s: Updating window to %u\n", __func__, + mp_tp->mpt_sndwnd), MPTCP_RECEIVER_DBG, MPTCP_LOGLVL_VERBOSE); + } +} + static void -mptcp_do_dss_opt_ack_meat(u_int64_t full_dack, struct tcpcb *tp) +mptcp_do_dss_opt_ack_meat(u_int64_t full_dack, u_int64_t full_dsn, + struct tcpcb *tp, u_int32_t tiwin) { struct mptcb *mp_tp = tptomptp(tp); int close_notify = 0; tp->t_mpflags |= TMPF_RCVD_DACK; - MPT_LOCK(mp_tp); if (MPTCP_SEQ_LEQ(full_dack, mp_tp->mpt_sndmax) && MPTCP_SEQ_GEQ(full_dack, mp_tp->mpt_snduna)) { mptcp_data_ack_rcvd(mp_tp, tp, full_dack); if (mp_tp->mpt_state > MPTCPS_FIN_WAIT_2) close_notify = 1; - MPT_UNLOCK(mp_tp); if (mp_tp->mpt_flags & MPTCPF_RCVD_64BITACK) { mp_tp->mpt_flags &= ~MPTCPF_RCVD_64BITACK; mp_tp->mpt_flags &= ~MPTCPF_SND_64BITDSN; @@ -1217,42 +1124,35 @@ mptcp_do_dss_opt_ack_meat(u_int64_t full_dack, struct tcpcb *tp) if (close_notify) mptcp_notify_close(tp->t_inpcb->inp_socket); } else { - MPT_UNLOCK(mp_tp); - mptcplog((LOG_ERR,"MPTCP Socket: " - "%s: unexpected dack %llx snduna %llx " - "sndmax %llx\n", __func__, full_dack, - mp_tp->mpt_snduna, mp_tp->mpt_sndmax), + mptcplog((LOG_ERR,"%s: unexpected dack %u snduna %u sndmax %u\n", __func__, + (u_int32_t)full_dack, (u_int32_t)mp_tp->mpt_snduna, + (u_int32_t)mp_tp->mpt_sndmax), (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), MPTCP_LOGLVL_LOG); } + + mptcp_update_window(mp_tp, full_dack, full_dsn, tiwin); } static void -mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) +mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp, struct tcphdr *th) { struct mptcp_dss_copt *dss_rsp = (struct mptcp_dss_copt *)cp; u_int64_t full_dack = 0; + u_int32_t tiwin = th->th_win << tp->snd_scale; struct mptcb *mp_tp = tptomptp(tp); int csum_len = 0; -#define MPTCP_DSS_OPT_SZ_CHK(len, expected_len) { \ - if (len != expected_len) { \ - mptcplog((LOG_ERR, "MPTCP Socket: " \ - "%s: bad len = %d dss: %x \n", __func__, \ - len, dss_rsp->mdss_flags), \ - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), \ - MPTCP_LOGLVL_LOG); \ - return; \ - } \ +#define MPTCP_DSS_OPT_SZ_CHK(len, expected_len) { \ + if (len != expected_len) { \ + mptcplog((LOG_ERR, "%s: bad len = %d dss: %x \n", __func__, \ + len, dss_rsp->mdss_flags), \ + (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), \ + MPTCP_LOGLVL_LOG); \ + return; \ + } \ } - /* - * mp_tp might become NULL after the call to mptcp_do_fin_opt(). - * Review after rdar://problem/24083886 - */ - if (!mp_tp) - return; - if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) csum_len = 2; @@ -1285,10 +1185,8 @@ mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) u_int32_t dack = dack_opt->mdss_ack; NTOHL(dack); - MPT_LOCK_SPIN(mp_tp); MPTCP_EXTEND_DSN(mp_tp->mpt_snduna, dack, full_dack); - MPT_UNLOCK(mp_tp); - mptcp_do_dss_opt_ack_meat(full_dack, tp); + mptcp_do_dss_opt_ack_meat(full_dack, mp_tp->mpt_sndwl1, tp, tiwin); break; } case (MDSS_M | MDSS_A): @@ -1296,23 +1194,31 @@ mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) /* 32-bit Data ACK + 32-bit DSS */ struct mptcp_dss_ack_opt *dss_ack_rsp; dss_ack_rsp = (struct mptcp_dss_ack_opt *)cp; + u_int64_t full_dsn; + uint16_t csum = 0; MPTCP_DSS_OPT_SZ_CHK(dss_ack_rsp->mdss_copt.mdss_len, sizeof (struct mptcp_dss_ack_opt) + csum_len); u_int32_t dack = dss_ack_rsp->mdss_ack; NTOHL(dack); - MPT_LOCK_SPIN(mp_tp); MPTCP_EXTEND_DSN(mp_tp->mpt_snduna, dack, full_dack); - MPT_UNLOCK(mp_tp); - mptcp_do_dss_opt_ack_meat(full_dack, tp); - if (csum_len == 0) - mptcp_update_rcv_state_f(dss_ack_rsp, tp, 0); - else - mptcp_update_rcv_state_f(dss_ack_rsp, tp, - *(uint16_t *)(void *)(cp + - (dss_ack_rsp->mdss_copt.mdss_len - - csum_len))); + + NTOHL(dss_ack_rsp->mdss_dsn); + NTOHL(dss_ack_rsp->mdss_subflow_seqn); + NTOHS(dss_ack_rsp->mdss_data_len); + MPTCP_EXTEND_DSN(mp_tp->mpt_rcvnxt, dss_ack_rsp->mdss_dsn, full_dsn); + + mptcp_do_dss_opt_ack_meat(full_dack, full_dsn, tp, tiwin); + + if (csum_len != 0) + csum = *(uint16_t *)(void *)(cp + (dss_ack_rsp->mdss_copt.mdss_len - csum_len)); + + mptcp_update_rcv_state_meat(mp_tp, tp, + full_dsn, + dss_ack_rsp->mdss_subflow_seqn, + dss_ack_rsp->mdss_data_len, + csum); break; } case (MDSS_M | MDSS_m): @@ -1321,33 +1227,24 @@ mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) struct mptcp_dsn64_opt *dsn64; dsn64 = (struct mptcp_dsn64_opt *)cp; u_int64_t full_dsn; + uint16_t csum = 0; MPTCP_DSS_OPT_SZ_CHK(dsn64->mdss_copt.mdss_len, sizeof (struct mptcp_dsn64_opt) + csum_len); - mptcplog((LOG_DEBUG,"MPTCP Socket: " - "%s: 64-bit M present.\n", __func__), - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), - MPTCP_LOGLVL_LOG); - - MPT_LOCK_SPIN(mp_tp); mp_tp->mpt_flags |= MPTCPF_SND_64BITACK; - MPT_UNLOCK(mp_tp); full_dsn = mptcp_ntoh64(dsn64->mdss_dsn); NTOHL(dsn64->mdss_subflow_seqn); NTOHS(dsn64->mdss_data_len); - if (csum_len == 0) - mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn, - dsn64->mdss_subflow_seqn, - dsn64->mdss_data_len, - 0); - else - mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn, - dsn64->mdss_subflow_seqn, - dsn64->mdss_data_len, - *(uint16_t *)(void *)(cp + - dsn64->mdss_copt.mdss_len - csum_len)); + + if (csum_len != 0) + csum = *(uint16_t *)(void *)(cp + dsn64->mdss_copt.mdss_len - csum_len); + + mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn, + dsn64->mdss_subflow_seqn, + dsn64->mdss_data_len, + csum); break; } case (MDSS_A | MDSS_a): @@ -1359,17 +1256,10 @@ mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) MPTCP_DSS_OPT_SZ_CHK(dack64->mdss_copt.mdss_len, sizeof (struct mptcp_data_ack64_opt)); - mptcplog((LOG_DEBUG,"MPTCP Socket: " - "%s: 64-bit A present. \n", __func__), - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), - MPTCP_LOGLVL_LOG); - - MPT_LOCK_SPIN(mp_tp); mp_tp->mpt_flags |= MPTCPF_RCVD_64BITACK; - MPT_UNLOCK(mp_tp); full_dack = mptcp_ntoh64(dack64->mdss_ack); - mptcp_do_dss_opt_ack_meat(full_dack, tp); + mptcp_do_dss_opt_ack_meat(full_dack, mp_tp->mpt_sndwl1, tp, tiwin); break; } case (MDSS_M | MDSS_m | MDSS_A): @@ -1377,29 +1267,31 @@ mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) /* 64-bit DSS + 32-bit Data ACK */ struct mptcp_dss64_ack32_opt *dss_ack_rsp; dss_ack_rsp = (struct mptcp_dss64_ack32_opt *)cp; + u_int64_t full_dsn; + uint16_t csum = 0; MPTCP_DSS_OPT_SZ_CHK(dss_ack_rsp->mdss_copt.mdss_len, sizeof (struct mptcp_dss64_ack32_opt) + csum_len); - mptcplog((LOG_DEBUG,"MPTCP Socket: " - "%s: 64-bit M and 32-bit A present.\n", __func__), - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), - MPTCP_LOGLVL_LOG); - u_int32_t dack = dss_ack_rsp->mdss_ack; NTOHL(dack); - MPT_LOCK_SPIN(mp_tp); mp_tp->mpt_flags |= MPTCPF_SND_64BITACK; MPTCP_EXTEND_DSN(mp_tp->mpt_snduna, dack, full_dack); - MPT_UNLOCK(mp_tp); - mptcp_do_dss_opt_ack_meat(full_dack, tp); - if (csum_len == 0) - mptcp_update_rcv_state_g(dss_ack_rsp, tp, 0); - else - mptcp_update_rcv_state_g(dss_ack_rsp, tp, - *(uint16_t *)(void *)(cp + - dss_ack_rsp->mdss_copt.mdss_len - - csum_len)); + + full_dsn = mptcp_ntoh64(dss_ack_rsp->mdss_dsn); + NTOHL(dss_ack_rsp->mdss_subflow_seqn); + NTOHS(dss_ack_rsp->mdss_data_len); + + mptcp_do_dss_opt_ack_meat(full_dack, full_dsn, tp, tiwin); + + if (csum_len != 0) + csum = *(uint16_t *)(void *)(cp + dss_ack_rsp->mdss_copt.mdss_len - csum_len); + + mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn, + dss_ack_rsp->mdss_subflow_seqn, + dss_ack_rsp->mdss_data_len, + csum); + break; } case (MDSS_M | MDSS_A | MDSS_a): @@ -1413,21 +1305,15 @@ mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) dss32_ack64_opt->mdss_copt.mdss_len, sizeof (struct mptcp_dss32_ack64_opt) + csum_len); - mptcplog((LOG_DEBUG,"MPTCP Socket: " - "%s: 32-bit M and 64-bit A present.\n", __func__), - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), - MPTCP_LOGLVL_LOG); - full_dack = mptcp_ntoh64(dss32_ack64_opt->mdss_ack); - mptcp_do_dss_opt_ack_meat(full_dack, tp); NTOHL(dss32_ack64_opt->mdss_dsn); - MPT_LOCK_SPIN(mp_tp); mp_tp->mpt_flags |= MPTCPF_RCVD_64BITACK; MPTCP_EXTEND_DSN(mp_tp->mpt_rcvnxt, dss32_ack64_opt->mdss_dsn, full_dsn); - MPT_UNLOCK(mp_tp); NTOHL(dss32_ack64_opt->mdss_subflow_seqn); NTOHS(dss32_ack64_opt->mdss_data_len); + + mptcp_do_dss_opt_ack_meat(full_dack, full_dsn, tp, tiwin); if (csum_len == 0) mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn, dss32_ack64_opt->mdss_subflow_seqn, @@ -1451,18 +1337,11 @@ mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) MPTCP_DSS_OPT_SZ_CHK(dss64_ack64->mdss_copt.mdss_len, sizeof (struct mptcp_dss64_ack64_opt) + csum_len); - mptcplog((LOG_DEBUG,"MPTCP Socket: " - "%s: 64-bit M and 64-bit A present.\n", __func__), - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), - MPTCP_LOGLVL_LOG); - - MPT_LOCK_SPIN(mp_tp); mp_tp->mpt_flags |= MPTCPF_RCVD_64BITACK; mp_tp->mpt_flags |= MPTCPF_SND_64BITACK; - MPT_UNLOCK(mp_tp); full_dsn = mptcp_ntoh64(dss64_ack64->mdss_dsn); full_dack = mptcp_ntoh64(dss64_ack64->mdss_dsn); - mptcp_do_dss_opt_ack_meat(full_dack, tp); + mptcp_do_dss_opt_ack_meat(full_dack, full_dsn, tp, tiwin); NTOHL(dss64_ack64->mdss_subflow_seqn); NTOHS(dss64_ack64->mdss_data_len); if (csum_len == 0) @@ -1479,30 +1358,22 @@ mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp) break; } default: - mptcplog((LOG_DEBUG,"MPTCP Socket: " - "%s: File bug, DSS flags = %x\n", __func__, - dss_rsp->mdss_flags), + mptcplog((LOG_DEBUG,"%s: File bug, DSS flags = %x\n", + __func__, dss_rsp->mdss_flags), (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), MPTCP_LOGLVL_LOG); break; } } - static void mptcp_do_fin_opt(struct tcpcb *tp) { - struct mptcb *mp_tp = (struct mptcb *)tp->t_mptcb; - - mptcplog((LOG_DEBUG,"MPTCP Socket: %s \n", __func__), - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), - MPTCP_LOGLVL_LOG); + struct mptcb *mp_tp = tptomptp(tp); if (!(tp->t_mpflags & TMPF_RECV_DFIN)) { if (mp_tp != NULL) { - MPT_LOCK(mp_tp); mptcp_close_fsm(mp_tp, MPCE_RECV_DATA_FIN); - MPT_UNLOCK(mp_tp); if (tp->t_inpcb->inp_socket != NULL) { soevent(tp->t_inpcb->inp_socket, @@ -1525,8 +1396,8 @@ mptcp_do_fin_opt(struct tcpcb *tp) static void mptcp_do_dss_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, int optlen) { -#pragma unused(th, optlen) - struct mptcb *mp_tp = (struct mptcb *)tp->t_mptcb; +#pragma unused(optlen) + struct mptcb *mp_tp = tptomptp(tp); if (!mp_tp) return; @@ -1541,7 +1412,7 @@ mptcp_do_dss_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, int optlen) mptcp_do_fin_opt(tp); } - mptcp_do_dss_opt_meat(cp, tp); + mptcp_do_dss_opt_meat(cp, tp, th); } } } @@ -1555,20 +1426,16 @@ mptcp_do_fastclose_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th) if (th->th_flags != TH_ACK) return; - mptcplog((LOG_DEBUG,"MPTCP Socket: %s: \n", __func__), - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), - MPTCP_LOGLVL_LOG); - if (fc_opt->mfast_len != sizeof (struct mptcp_fastclose_opt)) { tcpstat.tcps_invalid_opt++; return; } - mp_tp = (struct mptcb *)tp->t_mptcb; + mp_tp = tptomptp(tp); if (!mp_tp) return; - if (fc_opt->mfast_key != mptcp_get_localkey(mp_tp)) { + if (fc_opt->mfast_key != mp_tp->mpt_localkey) { tcpstat.tcps_invalid_opt++; return; } @@ -1613,18 +1480,14 @@ mptcp_do_mpfail_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th) if ((th->th_flags != TH_ACK) && (th->th_flags != TH_RST)) return; - mptcplog((LOG_DEBUG, "MPTCP Socket: %s: \n", __func__), - (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG), MPTCP_LOGLVL_LOG); - if (fail_opt->mfail_len != sizeof (struct mptcp_mpfail_opt)) return; - mp_tp = (struct mptcb *)tp->t_mptcb; - MPT_LOCK(mp_tp); + mp_tp = tptomptp(tp); + mp_tp->mpt_flags |= MPTCPF_RECVD_MPFAIL; mp_tp->mpt_dsn_at_csum_fail = mptcp_hton64(fail_opt->mfail_dsn); - MPT_UNLOCK(mp_tp); - error = mptcp_get_map_for_dsn(tp->t_inpcb->inp_socket, + error = mptcp_get_map_for_dsn(tp->t_inpcb->inp_socket, mp_tp->mpt_dsn_at_csum_fail, &mdss_subflow_seqn); if (error == 0) { mp_tp->mpt_ssn_at_csum_fail = mdss_subflow_seqn; @@ -1638,6 +1501,12 @@ tcp_do_mptcp_options(struct tcpcb *tp, u_char *cp, struct tcphdr *th, struct tcpopt *to, int optlen) { int mptcp_subtype; + struct mptcb *mp_tp = tptomptp(tp); + + if (mp_tp == NULL) + return; + + mpte_lock_assert_held(mp_tp->mpt_mpte); /* All MPTCP options have atleast 4 bytes */ if (optlen < 4) @@ -1675,49 +1544,11 @@ tcp_do_mptcp_options(struct tcpcb *tp, u_char *cp, struct tcphdr *th, return; } -/* - * MPTCP ADD_ADDR and REMOVE_ADDR options - */ - -/* - * ADD_ADDR is only placeholder code - not sent on wire - * The ADD_ADDR option is not sent on wire because of security issues - * around connection hijacking. - */ -void -mptcp_send_addaddr_opt(struct tcpcb *tp, struct mptcp_addaddr_opt *opt) -{ - - opt->ma_kind = TCPOPT_MULTIPATH; - opt->ma_len = sizeof (struct mptcp_addaddr_opt); - opt->ma_subtype = MPO_ADD_ADDR; - opt->ma_addr_id = tp->t_local_aid; -#ifdef MPTCP_NOTYET - struct inpcb *inp = tp->t_inpcb; - if (inp->inp_vflag == AF_INET) { - opt->ma_ipver = MA_IPVer_V4; - bcopy((char *)&sin->sin_addr.s_addr, (char *)opt + opt->ma_len, - sizeof (in_addr_t)); - opt->ma_len += sizeof (in_addr_t); - } else if (inp->inp_vflag == AF_INET6) { - opt->ma_ipver = MA_IPVer_V6; - bcopy((char *)&sin6->sin6_addr, (char *)opt + opt->ma_len, - sizeof (struct in6_addr)); - opt->ma_len += sizeof (struct in6_addr); - } -#if 0 - if (tp->t_mp_port) { - /* add ports XXX */ - } -#endif -#endif -} - /* REMOVE_ADDR option is sent when a source address goes away */ -void +static void mptcp_send_remaddr_opt(struct tcpcb *tp, struct mptcp_remaddr_opt *opt) { - mptcplog((LOG_DEBUG,"MPTCP Socket: %s: local id %d remove id %d \n", + mptcplog((LOG_DEBUG,"%s: local id %d remove id %d \n", __func__, tp->t_local_aid, tp->t_rem_aid), (MPTCP_SOCKET_DBG|MPTCP_SENDER_DBG), MPTCP_LOGLVL_LOG); @@ -1729,33 +1560,6 @@ mptcp_send_remaddr_opt(struct tcpcb *tp, struct mptcp_remaddr_opt *opt) tp->t_mpflags &= ~TMPF_SND_REM_ADDR; } -/* - * MPTCP MP_PRIO option - */ - -#if 0 -/* - * Current implementation drops incoming MP_PRIO option and this code is - * just a placeholder. The option is dropped because only the mobile client can - * decide which of the subflows is preferred (usually wifi is preferred - * over Cellular). - */ -void -mptcp_do_mpprio_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, - int optlen) -{ - int bkp = 0; - struct mptcp_mpprio_opt *mpprio = (struct mptcp_mpprio_opt *)cp; - - if ((tp == NULL) || !(tp->t_mpflags & TMPF_MPTCP_TRUE)) - return; - - if ((mpprio->mpprio_len != sizeof (struct mptcp_mpprio_addr_opt)) && - (mpprio->mpprio_len != sizeof (struct mptcp_mpprio_opt))) - return; -} -#endif - /* We send MP_PRIO option based on the values set by the SIOCSCONNORDER ioctl */ static int mptcp_snd_mpprio(struct tcpcb *tp, u_char *cp, int optlen) @@ -1767,11 +1571,6 @@ mptcp_snd_mpprio(struct tcpcb *tp, u_char *cp, int optlen) return (optlen); } - if (mptcp_mpprio_enable != 1) { - tp->t_mpflags &= ~TMPF_SND_MPPRIO; - return (optlen); - } - if ((MAX_TCPOPTLEN - optlen) < (int)sizeof (mpprio)) return (optlen); @@ -1786,8 +1585,9 @@ mptcp_snd_mpprio(struct tcpcb *tp, u_char *cp, int optlen) memcpy(cp + optlen, &mpprio, sizeof (mpprio)); optlen += sizeof (mpprio); tp->t_mpflags &= ~TMPF_SND_MPPRIO; - mptcplog((LOG_DEBUG, "MPTCP Socket: %s: aid = %d \n", __func__, + mptcplog((LOG_DEBUG, "%s: aid = %d \n", __func__, tp->t_local_aid), (MPTCP_SOCKET_DBG|MPTCP_SENDER_DBG), MPTCP_LOGLVL_LOG); return (optlen); } +