]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/mptcp_opt.c
xnu-4570.1.46.tar.gz
[apple/xnu.git] / bsd / netinet / mptcp_opt.c
index d2aec175082eab5309cb9777695b140c312b183c..8aa8a9a4e38344f2227bdbe094d2935c6aad63f1 100644 (file)
@@ -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@
  *
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
 
 #include <mach/sdt.h>
 
 
 #include <mach/sdt.h>
 
-/*
- * 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 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 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 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.
 
        /*
         * 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);
        }
 
                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
 
        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 inpcb *inp = sotoinpcb(so);
        struct tcpcb *tp = NULL;
+       struct mptsub *mpts;
 
        if (!inp)
                return (optlen);
 
        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)
                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 {
        } 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);
 }
 
        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),
        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;
        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
        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;
 
 {
        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);
 }
 
        return (new_optlen);
 }
 
@@ -284,15 +205,15 @@ mptcp_send_mpfail(struct tcpcb *tp, u_char *opt, unsigned int optlen)
                return (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);
        }
 
        /* 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;
        dsn = mp_tp->mpt_rcvnxt;
-       MPT_UNLOCK(mp_tp);
 
        bzero(&fail_opt, sizeof (fail_opt));
        fail_opt.mfail_kind = TCPOPT_MULTIPATH;
 
        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;
        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);
            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;
        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)
        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);
 
        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 (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);
                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;
        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;
 
                    ((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 {
                            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);
        }
                }
                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);
        }
        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;
        }
 
                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);
 
            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);
        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)
 {
 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;
        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);
                return (1);
-       }
-       MPT_UNLOCK(mp_tp);
+
        return (0);
 }
 
 unsigned int
 mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt,
        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;
 {
        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;
        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;
        }
 
                /* do nothing */
                goto ret_optlen;
        }
 
+       mpte_lock_assert_held(mp_tp->mpt_mpte);
+
        if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) {
                do_csum = TRUE;
        }
        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)) {
 
        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;
        }
 
                goto ret_optlen;
        }
 
@@ -463,17 +372,7 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt,
                goto ret_optlen;
        }
 
                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))
                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;
                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;
                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;
                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;
 
                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;
        }
 
                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) {
                /* 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);
                /* 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;
                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
        /*
         * 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);
        }
 
                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;
 
                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;                                                 \
 }
 
 #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;                 \
        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 */                  \
                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 */             \
                    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;
                 * 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) {
 
                if (do_csum) {
-                       len += 2;
+                       dssoptlen += 2;
                }
 
                CHECK_OPTLEN;
                }
 
                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;
                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;
 
                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)) {
 
                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);
                }
 
                        DO_FIN(dsn_ack_opt);
                }
 
-               MPT_LOCK(mp_tp);
                dsn_ack_opt.mdss_ack =
                    htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt));
                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);
 
                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));
 
                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);
                    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;
            (!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) {
 
                if (do_csum) {
-                       len += 2;
+                       dssoptlen += 2;
                }
 
                CHECK_OPTLEN;
                }
 
                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;
                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;
 
                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)) {
 
                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);
                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));
                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;
        }
                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;
            !(tp->t_mpflags & TMPF_SEND_DFIN)) {
 
                struct mptcp_data_ack_opt dack_opt;
-               unsigned int len = 0;
+               unsigned int dssoptlen = 0;
 do_ack32_only:
 do_ack32_only:
-               len = sizeof (dack_opt);
+               dssoptlen = sizeof (dack_opt);
 
                CHECK_OPTLEN;
 
 
                CHECK_OPTLEN;
 
-               bzero(&dack_opt, len);
+               bzero(&dack_opt, dssoptlen);
                dack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
                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;
                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));
                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;
                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;
            !(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:
 do_ack64_only:
-               len = sizeof (dack_opt);
+               dssoptlen = sizeof (dack_opt);
 
                CHECK_OPTLEN;
 
 
                CHECK_OPTLEN;
 
-               bzero(&dack_opt, len);
+               bzero(&dack_opt, dssoptlen);
                dack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
                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);
                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;
                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;
                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;
            (!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)
 
                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;
 
                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;
                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));
                dss_ack_opt.mdss_ack =
                    htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt));
-               MPT_UNLOCK(mp_tp);
 
                CHECK_DATALEN;
 
 
                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)) {
 
                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_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));
                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");
 
                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;
            (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)
 
                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;
 
                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;
                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);
                dss_ack_opt.mdss_ack =
                    mptcp_hton64(mp_tp->mpt_rcvnxt);
-               MPT_UNLOCK(mp_tp);
 
                CHECK_DATALEN;
 
 
                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)) {
 
                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_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));
                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");
 
                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;
 
        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)
 
                if (do_csum)
-                       len += 2;
+                       dssoptlen += 2;
 
                CHECK_OPTLEN;
 
                bzero(&dss_ack_opt, sizeof (dss_ack_opt));
 
 
                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) ||
                /*
                 * 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;
                        goto ret_optlen;
-               }
 
                dss_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
 
                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));
                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));
                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);
        }
 
 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.
 
                /*
                 * 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.
                 * 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.
                 */
                 * 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;
                        *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 {
                } 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);
                }
        }
                            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) {
        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);
        }
 
                return (0);
        }
 
@@ -1013,8 +854,7 @@ mptcp_sanitize_option(struct tcpcb *tp, int mptcp_subtype)
                        break;
                default:
                        ret = 0;
                        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;
                            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);
 
        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;
        /* 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 */
        /* 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);
                    __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;
                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;
        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++;
        }
        if (mptcp_init_remote_parms(mp_tp) != 0) {
                tcpstat.tcps_invalid_mpcap++;
-               MPT_UNLOCK(mp_tp);
                return;
        }
                return;
        }
-       MPT_UNLOCK(mp_tp);
        tcp_heuristic_mptcp_success(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)) {
                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;
                    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) {
        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;
        }
                    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};
 }
 
 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;
 
        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;
 
 
        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_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 "
 
        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);
        }
 }
 
                    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
 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;
 
 {
        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;
        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;
                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 {
                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_SOCKET_DBG|MPTCP_RECEIVER_DBG),
                    MPTCP_LOGLVL_LOG);
        }
+
+       mptcp_update_window(mp_tp, full_dack, full_dsn, tiwin);
 }
 
 static void
 }
 
 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;
 {
        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;
 
        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;
 
        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);
 
                        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);
                        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):
                        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;
                        /* 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);
 
                        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);
                        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):
                        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;
                        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);
 
 
                        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;
                        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);
 
                        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):
                        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));
 
                        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;
                        mp_tp->mpt_flags |= MPTCPF_RCVD_64BITACK;
-                       MPT_UNLOCK(mp_tp);
 
                        full_dack = mptcp_ntoh64(dack64->mdss_ack);
 
                        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):
                        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;
                        /* 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);
 
 
                        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);
                        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);
                        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):
                        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);
 
                            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);
                        full_dack = mptcp_ntoh64(dss32_ack64_opt->mdss_ack);
-                       mptcp_do_dss_opt_ack_meat(full_dack, tp);
                        NTOHL(dss32_ack64_opt->mdss_dsn);
                        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);
                        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);
                        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,
                        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);
 
                        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;
                        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);
                        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)
                        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:
                        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;
        }
 }
 
                            (MPTCP_SOCKET_DBG|MPTCP_RECEIVER_DBG),
                            MPTCP_LOGLVL_LOG);
                        break;
        }
 }
 
-
 static void
 mptcp_do_fin_opt(struct tcpcb *tp)
 {
 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) {
 
        if (!(tp->t_mpflags & TMPF_RECV_DFIN)) {
                if (mp_tp != NULL) {
-                       MPT_LOCK(mp_tp);
                        mptcp_close_fsm(mp_tp, MPCE_RECV_DATA_FIN);
                        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,
 
                        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)
 {
 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;
 
        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_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;
 
        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;
        }
 
        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 (!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;
        }
                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;
 
        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;
 
        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);
        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;
            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 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)
 
        /* 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;
 }
 
        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 */
 /* 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)
 {
 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);
 
            __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;
 }
 
        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)
 /* 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);
        }
 
                return (optlen);
        }
 
-       if (mptcp_mpprio_enable != 1) {
-               tp->t_mpflags &= ~TMPF_SND_MPPRIO;
-               return (optlen);
-       }
-
        if ((MAX_TCPOPTLEN - optlen) <
            (int)sizeof (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;
        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);
 }
            tp->t_local_aid), 
            (MPTCP_SOCKET_DBG|MPTCP_SENDER_DBG), MPTCP_LOGLVL_LOG);
        return (optlen);
 }
+