mp_so = mptetoso(mpte);
mp_tp = mpte->mpte_mptcb;
- mptcplog((LOG_DEBUG, "MPTCP Socket: "
- "%s: mp_so 0x%llx %d\n", __func__,
+ mptcplog((LOG_DEBUG, "%s: mp_so 0x%llx %d\n", __func__,
(u_int64_t)VM_KERNEL_ADDRPERM(mp_so), mp_so->so_error),
MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG);
return (mptcp_usr_disconnect(mp_so));
}
-/*
- * User issued close, and wish to trail thru shutdown states.
- */
-static struct mptses *
-mptcp_usrclosed(struct mptses *mpte)
+void
+mptcp_finish_usrclosed(struct mptses *mpte)
{
- struct socket *mp_so;
- struct mptcb *mp_tp;
- struct mptsub *mpts;
-
- mpte_lock_assert_held(mpte); /* same as MP socket lock */
- mp_so = mptetoso(mpte);
- mp_tp = mpte->mpte_mptcb;
-
- mptcp_close_fsm(mp_tp, MPCE_CLOSE);
+ struct mptcb *mp_tp = mpte->mpte_mptcb;
+ struct socket *mp_so = mptetoso(mpte);
if (mp_tp->mpt_state == MPTCPS_CLOSED) {
mpte = mptcp_close(mpte, mp_tp);
} else if (mp_tp->mpt_state >= MPTCPS_FIN_WAIT_2) {
soisdisconnected(mp_so);
} else {
+ struct mptsub *mpts;
+
TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) {
if ((mp_so->so_state & (SS_CANTRCVMORE|SS_CANTSENDMORE)) ==
(SS_CANTRCVMORE | SS_CANTSENDMORE))
mptcp_subflow_shutdown(mpte, mpts);
}
}
+}
+
+/*
+ * User issued close, and wish to trail thru shutdown states.
+ */
+static struct mptses *
+mptcp_usrclosed(struct mptses *mpte)
+{
+ struct mptcb *mp_tp = mpte->mpte_mptcb;
+
+ mptcp_close_fsm(mp_tp, MPCE_CLOSE);
+
+ /* Not everything has been acknowledged - don't close the subflows! */
+ if (mp_tp->mpt_sndnxt + 1 != mp_tp->mpt_sndmax)
+ return (mpte);
+
+ mptcp_finish_usrclosed(mpte);
return (mpte);
}
mpte->mpte_flags |= MPTE_SVCTYPE_CHECKED;
+ goto out;
+ case MPTCP_ALTERNATE_PORT:
+ /* record at MPTCP level */
+ error = sooptcopyin(sopt, &optval, sizeof(optval),
+ sizeof(optval));
+ if (error)
+ goto out;
+
+ if (optval < 0 || optval > UINT16_MAX) {
+ error = EINVAL;
+ goto out;
+ }
+
+ mpte->mpte_alternate_port = optval;
+
goto out;
default:
/* not eligible */
case TCP_ADAPTIVE_WRITE_TIMEOUT:
case TCP_NOTSENT_LOWAT:
case MPTCP_SERVICE_TYPE:
+ case MPTCP_ALTERNATE_PORT:
/* eligible; get the default value just in case */
error = mptcp_default_tcp_optval(mpte, sopt, &optval);
break;
case MPTCP_SERVICE_TYPE:
optval = mpte->mpte_svctype;
goto out;
+ case MPTCP_ALTERNATE_PORT:
+ optval = mpte->mpte_alternate_port;
+ goto out;
}
/*
case TCP_ADAPTIVE_READ_TIMEOUT:
case TCP_ADAPTIVE_WRITE_TIMEOUT:
case MPTCP_SERVICE_TYPE:
+ case MPTCP_ALTERNATE_PORT:
*optval = 0;
break;
return ("ADAPTIVE_WRITE_TIMEOUT");
case MPTCP_SERVICE_TYPE:
return ("MPTCP_SERVICE_TYPE");
+ case MPTCP_ALTERNATE_PORT:
+ return ("MPTCP_ALTERNATE_PORT");
}
break;