#ifndef _NETINET_MPTCP_VAR_H_
#define _NETINET_MPTCP_VAR_H_
#ifdef PRIVATE
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif
#ifdef BSD_KERNEL_PRIVATE
#include <sys/queue.h>
#include <sys/protosw.h>
#include <kern/locks.h>
#include <mach/boolean.h>
#include <netinet/mp_pcb.h>
struct mptses {
struct mppcb *mpte_mppcb;
struct mptcb *mpte_mptcb;
TAILQ_HEAD(, mptopt) mpte_sopts;
TAILQ_HEAD(, mptsub) mpte_subflows;
uint16_t mpte_numflows;
uint16_t mpte_nummpcapflows;
associd_t mpte_associd;
connid_t mpte_connid_last;
decl_lck_mtx_data(, mpte_thread_lock);
struct thread *mpte_thread;
uint32_t mpte_thread_active;
uint32_t mpte_thread_reqs;
struct mptsub *mpte_active_sub;
u_int8_t mpte_flags;
u_int8_t mpte_lost_aid;
};
#define MPTE_SND_REM_ADDR 0x01
#define mptompte(mp) ((struct mptses *)(mp)->mpp_pcbe)
#define MPTE_LOCK_ASSERT_HELD(_mpte) \
lck_mtx_assert(&(_mpte)->mpte_mppcb->mpp_lock, LCK_MTX_ASSERT_OWNED)
#define MPTE_LOCK_ASSERT_NOTHELD(_mpte) \
lck_mtx_assert(&(_mpte)->mpte_mppcb->mpp_lock, LCK_MTX_ASSERT_NOTOWNED)
#define MPTE_LOCK(_mpte) \
lck_mtx_lock(&(_mpte)->mpte_mppcb->mpp_lock)
#define MPTE_LOCK_SPIN(_mpte) \
lck_mtx_lock_spin(&(_mpte)->mpte_mppcb->mpp_lock)
#define MPTE_CONVERT_LOCK(_mpte) do { \
MPTE_LOCK_ASSERT_HELD(_mpte); \
lck_mtx_convert_spin(&(_mpte)->mpte_mppcb->mpp_lock); \
} while (0)
#define MPTE_UNLOCK(_mpte) \
lck_mtx_unlock(&(_mpte)->mpte_mppcb->mpp_lock)
struct mptopt {
TAILQ_ENTRY(mptopt) mpo_entry;
uint32_t mpo_flags;
int mpo_level;
int mpo_name;
int mpo_intval;
};
#define MPOF_ATTACHED 0x1
#define MPOF_SUBFLOW_OK 0x2
#define MPOF_INTERIM 0x4
struct mptsub_connreq {
uint32_t mpcr_type;
uint32_t mpcr_ifscope;
struct proc *mpcr_proc;
};
#define MPTSUB_CONNREQ_MP_ENABLE 1
#define MPTSUB_CONNREQ_MP_ADD 2
struct mptsub {
decl_lck_mtx_data(, mpts_lock);
TAILQ_ENTRY(mptsub) mpts_entry;
uint32_t mpts_refcnt;
uint32_t mpts_flags;
uint32_t mpts_evctl;
uint32_t mpts_family;
connid_t mpts_connid;
int mpts_oldintval;
uint32_t mpts_rank;
int32_t mpts_soerror;
struct mptses *mpts_mpte;
struct socket *mpts_socket;
struct sockaddr_list *mpts_src_sl;
struct sockaddr_list *mpts_dst_sl;
struct ifnet *mpts_outif;
u_int64_t mpts_sndnxt;
u_int32_t mpts_rel_seq;
struct {
u_int64_t mptsl_dsn;
u_int32_t mptsl_sseq;
u_int32_t mptsl_len;
} mpts_lastmap;
struct protosw *mpts_oprotosw;
struct mptsub_connreq mpts_mpcr;
};
#define MPTSF_ATTACHED 0x1
#define MPTSF_CONNECTING 0x2
#define MPTSF_CONNECT_PENDING 0x4
#define MPTSF_CONNECTED 0x8
#define MPTSF_DISCONNECTING 0x10
#define MPTSF_DISCONNECTED 0x20
#define MPTSF_MP_CAPABLE 0x40
#define MPTSF_MP_READY 0x80
#define MPTSF_MP_DEGRADED 0x100
#define MPTSF_SUSPENDED 0x200
#define MPTSF_BOUND_IF 0x400
#define MPTSF_BOUND_IP 0x800
#define MPTSF_BOUND_PORT 0x1000
#define MPTSF_PREFERRED 0x2000
#define MPTSF_SOPT_OLDVAL 0x4000
#define MPTSF_SOPT_INPROG 0x8000
#define MPTSF_DELETEOK 0x10000
#define MPTSF_FAILINGOVER 0x20000
#define MPTSF_ACTIVE 0x40000
#define MPTSF_MPCAP_CTRSET 0x80000
#define MPTSF_BITS \
"\020\1ATTACHED\2CONNECTING\3PENDING\4CONNECTED\5DISCONNECTING" \
"\6DISCONNECTED\7MP_CAPABLE\10MP_READY\11MP_DEGRADED\12SUSPENDED" \
"\13BOUND_IF\14BOUND_IP\15BOUND_PORT\16PREFERRED\17SOPT_OLDVAL" \
"\20SOPT_INPROG\21NOLINGER\22FAILINGOVER\23ACTIVE\24MPCAP_CTRSET"
#define MPTS_LOCK_ASSERT_HELD(_mpts) \
lck_mtx_assert(&(_mpts)->mpts_lock, LCK_MTX_ASSERT_OWNED)
#define MPTS_LOCK_ASSERT_NOTHELD(_mpts) \
lck_mtx_assert(&(_mpts)->mpts_lock, LCK_MTX_ASSERT_NOTOWNED)
#define MPTS_LOCK(_mpts) \
lck_mtx_lock(&(_mpts)->mpts_lock)
#define MPTS_LOCK_SPIN(_mpts) \
lck_mtx_lock_spin(&(_mpts)->mpts_lock)
#define MPTS_CONVERT_LOCK(_mpts) do { \
MPTS_LOCK_ASSERT_HELD(_mpts); \
lck_mtx_convert_spin(&(_mpts)->mpts_lock); \
} while (0)
#define MPTS_UNLOCK(_mpts) \
lck_mtx_unlock(&(_mpts)->mpts_lock)
#define MPTS_ADDREF(_mpts) \
mptcp_subflow_addref(_mpts, 0)
#define MPTS_ADDREF_LOCKED(_mpts) \
mptcp_subflow_addref(_mpts, 1)
#define MPTS_REMREF(_mpts) \
mptcp_subflow_remref(_mpts)
typedef enum mptcp_state {
MPTCPS_CLOSED = 0,
MPTCPS_LISTEN = 1,
MPTCPS_ESTABLISHED = 2,
MPTCPS_CLOSE_WAIT = 3,
MPTCPS_FIN_WAIT_1 = 4,
MPTCPS_CLOSING = 5,
MPTCPS_LAST_ACK = 6,
MPTCPS_FIN_WAIT_2 = 7,
MPTCPS_TIME_WAIT = 8,
MPTCPS_FASTCLOSE_WAIT = 9,
} mptcp_state_t;
typedef u_int64_t mptcp_key_t;
typedef u_int32_t mptcp_token_t;
typedef u_int8_t mptcp_addr_id;
struct mptcp_subf_auth_entry {
LIST_ENTRY(mptcp_subf_auth_entry) msae_next;
u_int32_t msae_laddr_rand;
u_int32_t msae_raddr_rand;
mptcp_addr_id msae_laddr_id;
mptcp_addr_id msae_raddr_id;
};
struct mptcb {
decl_lck_mtx_data(, mpt_lock);
struct mptses *mpt_mpte;
mptcp_state_t mpt_state;
u_int32_t mpt_flags;
u_int32_t mpt_refcnt;
u_int32_t mpt_version;
int mpt_softerror;
mptcp_key_t *mpt_localkey;
mptcp_key_t mpt_remotekey;
mptcp_token_t mpt_localtoken;
mptcp_token_t mpt_remotetoken;
int mpt_rxtshift;
u_int32_t mpt_rxtstart;
u_int64_t mpt_rtseq;
u_int32_t mpt_timer_vals;
u_int32_t mpt_timewait;
u_int64_t mpt_snduna;
u_int64_t mpt_sndnxt;
u_int64_t mpt_sndmax;
u_int64_t mpt_local_idsn;
u_int32_t mpt_sndwnd;
u_int64_t mpt_rcvnxt;
u_int64_t mpt_rcvatmark;
u_int64_t mpt_remote_idsn;
u_int32_t mpt_rcvwnd;
LIST_HEAD(, mptcp_subf_auth_entry) mpt_subauth_list;
u_int64_t mpt_dsn_at_csum_fail;
#define MPT_GC_TICKS (60)
int32_t mpt_gc_ticks;
};
#define MPTCPF_CHECKSUM 0x1
#define MPTCPF_FALLBACK_TO_TCP 0x2
#define MPTCPF_JOIN_READY 0x4
#define MPTCPF_RECVD_MPFAIL 0x8
#define MPTCPF_PEEL_OFF 0x10
#define MPTCPF_SND_64BITDSN 0x20
#define MPTCPF_SND_64BITACK 0x40
#define MPTCPF_RCVD_64BITACK 0x80
#define MPTCPF_BITS \
"\020\1CHECKSUM\2FALLBACK_TO_TCP\3JOIN_READY\4RECVD_MPFAIL\5PEEL_OFF" \
"\6SND_64BITDSN\7SND_64BITACK\10RCVD_64BITACK"
#define MPTT_REXMT 0x01
#define MPTT_TW 0x02
#define MPTT_FASTCLOSE 0x04
#define MPT_LOCK_ASSERT_HELD(_mpt) \
lck_mtx_assert(&(_mpt)->mpt_lock, LCK_MTX_ASSERT_OWNED)
#define MPT_LOCK_ASSERT_NOTHELD(_mpt) \
lck_mtx_assert(&(_mpt)->mpt_lock, LCK_MTX_ASSERT_NOTOWNED)
#define MPT_LOCK(_mpt) \
lck_mtx_lock(&(_mpt)->mpt_lock)
#define MPT_LOCK_SPIN(_mpt) \
lck_mtx_lock_spin(&(_mpt)->mpt_lock)
#define MPT_CONVERT_LOCK(_mpt) do { \
MPT_LOCK_ASSERT_HELD(_mpt); \
lck_mtx_convert_spin(&(_mpt)->mpt_lock); \
} while (0)
#define MPT_UNLOCK(_mpt) \
lck_mtx_unlock(&(_mpt)->mpt_lock)
#define MPCE_CLOSE 0x1
#define MPCE_RECV_DATA_ACK 0x2
#define MPCE_RECV_DATA_FIN 0x4
#define tptomptp(tp) ((struct mptcb *)((tp)->t_mptcb))
struct mpp_mtp {
struct mppcb mpp;
struct mptses mpp_ses;
struct mptcb mtcb;
};
#ifdef SYSCTL_DECL
SYSCTL_DECL(_net_inet_mptcp);
#endif
extern struct mppcbinfo mtcbinfo;
extern struct pr_usrreqs mptcp_usrreqs;
#define MPTCP_SHA1_RESULTLEN 20
#define SHA1_TRUNCATED 8
#define MPTCP_KEY_DIGEST_LEN (MPTCP_SHA1_RESULTLEN)
#define MPTCP_MX_KEY_ALLOCS (256)
#define MPTCP_KEY_PREALLOCS_MX (16)
#define MPTCP_MX_PREALLOC_ZONE_SZ (8192)
struct mptcp_key_entry {
LIST_ENTRY(mptcp_key_entry) mkey_next;
mptcp_key_t mkey_value;
#define MKEYF_FREE 0x0
#define MKEYF_INUSE 0x1
u_int32_t mkey_flags;
char mkey_digest[MPTCP_KEY_DIGEST_LEN];
};
struct mptcp_keys_pool_head {
struct mptcp_key_entry *lh_first;
u_int32_t mkph_count;
vm_size_t mkph_key_elm_sz;
struct zone *mkph_key_entry_zone;
decl_lck_mtx_data(, mkph_lock);
};
#define MPTCP_RWIN_MAX (1<<16)
#define MP_NODEBUG 0x0
#define MP_ERR_DEBUG 0x1
#define MP_VERBOSE_DEBUG_1 0x2
#define MP_VERBOSE_DEBUG_2 0x3
#define MP_VERBOSE_DEBUG_3 0x4
#define MP_VERBOSE_DEBUG_4 0x5
#define MPTCP_DATASEQ_LOW32_MASK (0xffffffff)
#define MPTCP_DATASEQ_LOW32(seq) (seq & MPTCP_DATASEQ_LOW32_MASK)
#define MPTCP_DATASEQ_HIGH32_MASK (0xffffffff00000000)
#define MPTCP_DATASEQ_HIGH32(seq) (seq & MPTCP_DATASEQ_HIGH32_MASK)
#define MPTCP_DATAACK_LOW32_MASK (0xffffffff)
#define MPTCP_DATAACK_LOW32(ack) (ack & MPTCP_DATAACK_LOW32_MASK)
#define MPTCP_DATAACK_HIGH32_MASK (0xffffffff00000000)
#define MPTCP_DATAACK_HIGH32(ack) (ack & MPTCP_DATAACK_HIGH32_MASK)
#define MPTCP_EXTEND_DSN(x, y, z) { \
if ((MPTCP_DATASEQ_LOW32(x) > y) && \
((((u_int32_t)MPTCP_DATASEQ_LOW32(x)) - (u_int32_t)y) >= \
(u_int32_t)(1 << 31))) { \
\
z = MPTCP_DATASEQ_HIGH32(x) + 0x100000000; \
z |= y; \
} else if ((MPTCP_DATASEQ_LOW32(x) < y) && \
(((u_int32_t)y - \
((u_int32_t)MPTCP_DATASEQ_LOW32(x))) >= \
(u_int32_t)(1 << 31))) { \
\
z = MPTCP_DATASEQ_HIGH32(x) - 0x100000000; \
z |= y; \
} else { \
z = MPTCP_DATASEQ_HIGH32(x) | y; \
} \
}
#define mptcplog(x) do { if (mptcp_verbose >= 1) log x; } while (0)
#define mptcplog2(x) do { if (mptcp_verbose >= 2) log x; } while (0)
#define mptcplog3(x) do { if (mptcp_verbose >= 3) log x; } while (0)
extern int mptcp_enable;
extern int mptcp_dbg;
extern int mptcp_mpcap_retries;
extern int mptcp_join_retries;
extern int mptcp_dss_csum;
extern int mptcp_fail_thresh;
extern int mptcp_subflow_keeptime;
extern int mptcp_mpprio_enable;
extern int mptcp_remaddr_enable;
extern uint32_t mptcp_verbose;
#define MPPCB_LIMIT 16
extern uint32_t mptcp_socket_limit;
extern int tcp_jack_rxmt;
__BEGIN_DECLS
extern void mptcp_init(struct protosw *, struct domain *);
extern int mptcp_ctloutput(struct socket *, struct sockopt *);
extern struct mptses *mptcp_sescreate(struct socket *, struct mppcb *);
extern void mptcp_drain(void);
extern struct mptses *mptcp_drop(struct mptses *, struct mptcb *, int);
extern struct mptses *mptcp_close(struct mptses *, struct mptcb *);
extern int mptcp_lock(struct socket *, int, void *);
extern int mptcp_unlock(struct socket *, int, void *);
extern lck_mtx_t *mptcp_getlock(struct socket *, int);
extern void mptcp_thread_signal(struct mptses *);
extern void mptcp_flush_sopts(struct mptses *);
extern int mptcp_setconnorder(struct mptses *, connid_t, uint32_t);
extern int mptcp_getconnorder(struct mptses *, connid_t, uint32_t *);
extern struct mptopt *mptcp_sopt_alloc(int);
extern const char *mptcp_sopt2str(int, int, char *, int);
extern void mptcp_sopt_free(struct mptopt *);
extern void mptcp_sopt_insert(struct mptses *, struct mptopt *);
extern void mptcp_sopt_remove(struct mptses *, struct mptopt *);
extern struct mptopt *mptcp_sopt_find(struct mptses *, struct sockopt *);
extern struct mptsub *mptcp_subflow_alloc(int);
extern void mptcp_subflow_free(struct mptsub *);
extern void mptcp_subflow_addref(struct mptsub *, int);
extern int mptcp_subflow_add(struct mptses *, struct mptsub *,
struct proc *, uint32_t);
extern void mptcp_subflow_del(struct mptses *, struct mptsub *, boolean_t);
extern void mptcp_subflow_remref(struct mptsub *);
extern int mptcp_subflow_output(struct mptses *, struct mptsub *);
extern void mptcp_subflow_disconnect(struct mptses *, struct mptsub *,
boolean_t);
extern void mptcp_subflow_sopeeloff(struct mptses *, struct mptsub *,
struct socket *);
extern int mptcp_subflow_sosetopt(struct mptses *, struct socket *,
struct mptopt *);
extern int mptcp_subflow_sogetopt(struct mptses *, struct socket *,
struct mptopt *);
extern void mptcp_input(struct mptses *, struct mbuf *);
extern int mptcp_output(struct mptses *);
extern void mptcp_close_fsm(struct mptcb *, uint32_t);
extern mptcp_token_t mptcp_get_localtoken(void *);
extern mptcp_token_t mptcp_get_remotetoken(void *);
extern u_int64_t mptcp_get_localkey(void *);
extern u_int64_t mptcp_get_remotekey(void *);
extern void mptcp_free_key(mptcp_key_t *key);
extern void mptcp_hmac_sha1(mptcp_key_t, mptcp_key_t, u_int32_t, u_int32_t,
u_char*, int);
extern void mptcp_get_hmac(mptcp_addr_id, struct mptcb *, u_char *, int);
extern void mptcp_get_rands(mptcp_addr_id, struct mptcb *, u_int32_t *,
u_int32_t *);
extern void mptcp_set_raddr_rand(mptcp_addr_id, struct mptcb *, mptcp_addr_id,
u_int32_t);
extern u_int64_t mptcp_get_trunced_hmac(mptcp_addr_id, struct mptcb *mp_tp);
extern int mptcp_generate_token(char *, int, caddr_t, int);
extern int mptcp_generate_idsn(char *, int, caddr_t, int);
extern boolean_t mptcp_ok_to_keepalive(struct mptcb *);
extern void mptcp_insert_dsn(struct mppcb *, struct mbuf *);
extern void mptcp_output_getm_dsnmap32(struct socket *, int, uint32_t,
u_int32_t *, u_int32_t *, u_int16_t *, u_int64_t *);
extern void mptcp_output_getm_dsnmap64(struct socket *, int, uint32_t,
u_int64_t *, u_int32_t *, u_int16_t *);
extern void mptcp_send_dfin(struct socket *);
extern void mptcp_act_on_txfail(struct socket *);
extern struct mptsub *mptcp_get_subflow(struct mptses *, struct mptsub *);
extern int mptcp_get_map_for_dsn(struct socket *, u_int64_t, u_int32_t *);
extern int32_t mptcp_adj_sendlen(struct socket *so, int32_t off, int32_t len);
extern int32_t mptcp_sbspace(struct mptcb *);
extern void mptcp_notify_mpready(struct socket *);
extern void mptcp_notify_mpfail(struct socket *);
extern void mptcp_notify_close(struct socket *);
__END_DECLS
#endif
#ifdef PRIVATE
typedef struct mptcp_flow {
uint32_t flow_flags;
connid_t flow_cid;
struct sockaddr_storage flow_src;
struct sockaddr_storage flow_dst;
conninfo_tcp_t flow_ci;
} mptcp_flow_t;
typedef struct conninfo_mptcp {
size_t mptcpci_len;
size_t mptcpci_nflows;
uint32_t mptcpci_state;
mptcp_flow_t mptcpci_flows[1];
} conninfo_mptcp_t;
#endif
#endif