summaryrefslogtreecommitdiffstats
path: root/sys/cam/ctl
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-12-17 15:13:21 +0000
committermav <mav@FreeBSD.org>2014-12-17 15:13:21 +0000
commitfe9781bb787e975c2a1cdb7bd6841ee161c31b2e (patch)
tree663cd0ad837b0a1752ce0820622db742c40e5dd8 /sys/cam/ctl
parentdf55c61fa5caaef1f237ceb37d7870b642661de3 (diff)
downloadFreeBSD-src-fe9781bb787e975c2a1cdb7bd6841ee161c31b2e.zip
FreeBSD-src-fe9781bb787e975c2a1cdb7bd6841ee161c31b2e.tar.gz
Make sequence numbers checks more strict.
While we don't support MCS, hole in received sequence numbers may mean only PDU loss. While we don't support lost PDU recovery, terminate the connection to avoid stuck commands. While there, improve handling of sequence numbers wrap after 2^32 PDUs. MFC after: 2 weeks
Diffstat (limited to 'sys/cam/ctl')
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c48
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.h1
2 files changed, 38 insertions, 11 deletions
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index 8ec5825..0114b57 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -233,19 +233,34 @@ cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request)
}
#endif
- /*
- * The target MUST silently ignore any non-immediate command outside
- * of this range.
- */
- if (cmdsn < cs->cs_cmdsn || cmdsn > cs->cs_cmdsn + maxcmdsn_delta) {
- CFISCSI_SESSION_UNLOCK(cs);
- CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %d, "
- "while expected CmdSN was %d", cmdsn, cs->cs_cmdsn);
- return (true);
- }
+ if ((request->ip_bhs->bhs_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) {
+ /*
+ * The target MUST silently ignore any non-immediate command
+ * outside of this range.
+ */
+ if (ISCSI_SNLT(cmdsn, cs->cs_cmdsn) ||
+ ISCSI_SNGT(cmdsn, cs->cs_cmdsn + maxcmdsn_delta)) {
+ CFISCSI_SESSION_UNLOCK(cs);
+ CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %u, "
+ "while expected %u", cmdsn, cs->cs_cmdsn);
+ return (true);
+ }
- if ((request->ip_bhs->bhs_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0)
+ /*
+ * We don't support multiple connections now, so any
+ * discontinuity in CmdSN means lost PDUs. Since we don't
+ * support PDU retransmission -- terminate the connection.
+ */
+ if (cmdsn != cs->cs_cmdsn) {
+ CFISCSI_SESSION_UNLOCK(cs);
+ CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %u, "
+ "while expected %u; dropping connection",
+ cmdsn, cs->cs_cmdsn);
+ cfiscsi_session_terminate(cs);
+ return (true);
+ }
cs->cs_cmdsn++;
+ }
CFISCSI_SESSION_UNLOCK(cs);
@@ -892,6 +907,16 @@ cfiscsi_pdu_handle_data_out(struct icl_pdu *request)
return;
}
+ if (cdw->cdw_datasn != ntohl(bhsdo->bhsdo_datasn)) {
+ CFISCSI_SESSION_WARN(cs, "received Data-Out PDU with "
+ "DataSN %u, while expected %u; dropping connection",
+ ntohl(bhsdo->bhsdo_datasn), cdw->cdw_datasn);
+ icl_pdu_free(request);
+ cfiscsi_session_terminate(cs);
+ return;
+ }
+ cdw->cdw_datasn++;
+
io = cdw->cdw_ctl_io;
KASSERT((io->io_hdr.flags & CTL_FLAG_DATA_MASK) != CTL_FLAG_DATA_IN,
("CTL_FLAG_DATA_IN"));
@@ -2650,6 +2675,7 @@ cfiscsi_datamove_out(union ctl_io *io)
cdw->cdw_target_transfer_tag = target_transfer_tag;
cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
cdw->cdw_r2t_end = io->scsiio.kern_data_len;
+ cdw->cdw_datasn = 0;
/* Set initial data pointer for the CDW respecting ext_data_filled. */
if (io->scsiio.kern_sg_entries > 0) {
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.h b/sys/cam/ctl/ctl_frontend_iscsi.h
index 336b69d..5000f4c 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.h
+++ b/sys/cam/ctl/ctl_frontend_iscsi.h
@@ -58,6 +58,7 @@ struct cfiscsi_data_wait {
char *cdw_sg_addr;
size_t cdw_sg_len;
uint32_t cdw_r2t_end;
+ uint32_t cdw_datasn;
};
#define CFISCSI_SESSION_STATE_INVALID 0
OpenPOWER on IntegriCloud