summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2016-01-16 14:41:44 +0000
committertuexen <tuexen@FreeBSD.org>2016-01-16 14:41:44 +0000
commit9b0e77811d60c22821172c855fb8186925eb6af4 (patch)
treee5d85483051dc50656e3439d2b1dbb927eb841fe /sys/netinet
parent65380e690e927bda1081b63c1ac0aaafe11f376d (diff)
downloadFreeBSD-src-9b0e77811d60c22821172c855fb8186925eb6af4.zip
FreeBSD-src-9b0e77811d60c22821172c855fb8186925eb6af4.tar.gz
MFC r287282:
Fix the exporting of SCTP association states to userland. Without this, associations in SHUTDOWN-PENDING were never reported correctly.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/sctp_constants.h2
-rw-r--r--sys/netinet/sctp_sysctl.c2
-rw-r--r--sys/netinet/sctp_usrreq.c7
-rw-r--r--sys/netinet/sctputil.c43
-rw-r--r--sys/netinet/sctputil.h3
5 files changed, 49 insertions, 8 deletions
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index d90bd25..135d46c 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -458,7 +458,7 @@ __FBSDID("$FreeBSD$");
/*
- * SCTP states for internal state machine XXX (should match "user" values)
+ * SCTP states for internal state machine
*/
#define SCTP_STATE_EMPTY 0x0000
#define SCTP_STATE_INUSE 0x0001
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index 6eef6b9..1b35af7 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -453,7 +453,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
if (stcb->asoc.primary_destination != NULL)
xstcb.primary_addr = stcb->asoc.primary_destination->ro._l_addr;
xstcb.heartbeat_interval = stcb->asoc.heart_beat_delay;
- xstcb.state = SCTP_GET_STATE(&stcb->asoc); /* FIXME */
+ xstcb.state = (uint32_t) sctp_map_assoc_state(stcb->asoc.state);
/* 7.0 does not support these */
xstcb.assoc_id = sctp_get_associd(stcb);
xstcb.peers_rwnd = stcb->asoc.peers_rwnd;
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 76a2857..78f4508 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -2668,12 +2668,7 @@ flags_out:
error = EINVAL;
break;
}
- /*
- * I think passing the state is fine since
- * sctp_constants.h will be available to the user
- * land.
- */
- sstat->sstat_state = stcb->asoc.state;
+ sstat->sstat_state = sctp_map_assoc_state(stcb->asoc.state);
sstat->sstat_assoc_id = sctp_get_associd(stcb);
sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 069ed34..3030994 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -893,6 +893,49 @@ sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int ch
return (x);
}
+int32_t
+sctp_map_assoc_state(int kernel_state)
+{
+ int32_t user_state;
+
+ if (kernel_state & SCTP_STATE_WAS_ABORTED) {
+ user_state = SCTP_CLOSED;
+ } else if (kernel_state & SCTP_STATE_SHUTDOWN_PENDING) {
+ user_state = SCTP_SHUTDOWN_PENDING;
+ } else {
+ switch (kernel_state & SCTP_STATE_MASK) {
+ case SCTP_STATE_EMPTY:
+ user_state = SCTP_CLOSED;
+ break;
+ case SCTP_STATE_INUSE:
+ user_state = SCTP_CLOSED;
+ break;
+ case SCTP_STATE_COOKIE_WAIT:
+ user_state = SCTP_COOKIE_WAIT;
+ break;
+ case SCTP_STATE_COOKIE_ECHOED:
+ user_state = SCTP_COOKIE_ECHOED;
+ break;
+ case SCTP_STATE_OPEN:
+ user_state = SCTP_ESTABLISHED;
+ break;
+ case SCTP_STATE_SHUTDOWN_SENT:
+ user_state = SCTP_SHUTDOWN_SENT;
+ break;
+ case SCTP_STATE_SHUTDOWN_RECEIVED:
+ user_state = SCTP_SHUTDOWN_RECEIVED;
+ break;
+ case SCTP_STATE_SHUTDOWN_ACK_SENT:
+ user_state = SCTP_SHUTDOWN_ACK_SENT;
+ break;
+ default:
+ user_state = SCTP_CLOSED;
+ break;
+ }
+ }
+ return (user_state);
+}
+
int
sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
uint32_t override_tag, uint32_t vrf_id)
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index 7df0a6c..82de736 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -67,6 +67,9 @@ void
/*
* Function prototypes
*/
+int32_t
+sctp_map_assoc_state(int);
+
uint32_t
sctp_get_ifa_hash_val(struct sockaddr *addr);
OpenPOWER on IntegriCloud