summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2010-02-20 20:30:40 +0000
committertuexen <tuexen@FreeBSD.org>2010-02-20 20:30:40 +0000
commitf9cc41e4ee80a4c28e6617322ecf1fea377c070e (patch)
tree0240a38567ab0eb9dcacc4a7ba50cc425104f0f8 /sys/netinet
parent29381991cf960220b44aa20487b64388a3fa5947 (diff)
downloadFreeBSD-src-f9cc41e4ee80a4c28e6617322ecf1fea377c070e.zip
FreeBSD-src-f9cc41e4ee80a4c28e6617322ecf1fea377c070e.tar.gz
Fix handling of SHUTDOWN-ACK chunk in COOKIE_WAIT and COOKIE_ECHOED.
MFC after: 1 week
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/sctp_input.c12
-rw-r--r--sys/netinet/sctp_output.c16
-rw-r--r--sys/netinet/sctp_output.h2
3 files changed, 24 insertions, 6 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index d211e9a..ef18737 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -918,7 +918,8 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
static void
sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
- struct sctp_tcb *stcb, struct sctp_nets *net)
+ struct sctp_tcb *stcb,
+ struct sctp_nets *net)
{
struct sctp_association *asoc;
@@ -934,6 +935,13 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
asoc = &stcb->asoc;
/* process according to association state */
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ /* unexpected SHUTDOWN-ACK... do OOTB handling... */
+ sctp_send_shutdown_complete(stcb, net, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ return;
+ }
if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/* unexpected SHUTDOWN-ACK... so ignore... */
@@ -975,7 +983,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
/* stop the timer */
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9);
/* send SHUTDOWN-COMPLETE */
- sctp_send_shutdown_complete(stcb, net);
+ sctp_send_shutdown_complete(stcb, net, 0);
/* notify upper layer protocol */
if (stcb->sctp_socket) {
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 4afe009..be4c3a8 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -10622,27 +10622,37 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
void
sctp_send_shutdown_complete(struct sctp_tcb *stcb,
- struct sctp_nets *net)
+ struct sctp_nets *net,
+ int reflect_vtag)
{
/* formulate and SEND a SHUTDOWN-COMPLETE */
struct mbuf *m_shutdown_comp;
struct sctp_shutdown_complete_chunk *shutdown_complete;
+ uint32_t vtag;
+ uint8_t flags;
m_shutdown_comp = sctp_get_mbuf_for_msg(sizeof(struct sctp_chunkhdr), 0, M_DONTWAIT, 1, MT_HEADER);
if (m_shutdown_comp == NULL) {
/* no mbuf's */
return;
}
+ if (reflect_vtag) {
+ flags = SCTP_HAD_NO_TCB;
+ vtag = stcb->asoc.my_vtag;
+ } else {
+ flags = 0;
+ vtag = stcb->asoc.peer_vtag;
+ }
shutdown_complete = mtod(m_shutdown_comp, struct sctp_shutdown_complete_chunk *);
shutdown_complete->ch.chunk_type = SCTP_SHUTDOWN_COMPLETE;
- shutdown_complete->ch.chunk_flags = 0;
+ shutdown_complete->ch.chunk_flags = flags;
shutdown_complete->ch.chunk_length = htons(sizeof(struct sctp_shutdown_complete_chunk));
SCTP_BUF_LEN(m_shutdown_comp) = sizeof(struct sctp_shutdown_complete_chunk);
(void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
m_shutdown_comp, 0, NULL, 0, 1, 0, NULL, 0,
stcb->sctp_ep->sctp_lport, stcb->rport,
- htonl(stcb->asoc.peer_vtag),
+ htonl(vtag),
net->port, SCTP_SO_NOT_LOCKED, NULL);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
return;
diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h
index ce76feb..bd40a0b 100644
--- a/sys/netinet/sctp_output.h
+++ b/sys/netinet/sctp_output.h
@@ -111,7 +111,7 @@ void sctp_send_shutdown(struct sctp_tcb *, struct sctp_nets *);
void sctp_send_shutdown_ack(struct sctp_tcb *, struct sctp_nets *);
-void sctp_send_shutdown_complete(struct sctp_tcb *, struct sctp_nets *);
+void sctp_send_shutdown_complete(struct sctp_tcb *, struct sctp_nets *, int);
void
sctp_send_shutdown_complete2(struct mbuf *, int, struct sctphdr *,
OpenPOWER on IntegriCloud