From 23738bf1c3ecab68d59e1666911e9a5b9ca35c73 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Thu, 5 Jan 2017 12:28:37 +0100 Subject: [PATCH] socket: calculate header checksum at the right place we mangled the PDU header after calculating the checksum which effectively broke CRC32C header digests completely. Signed-off-by: Peter Lieven --- lib/socket.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/socket.c b/lib/socket.c index aa25059..caf51a5 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -675,6 +675,25 @@ iscsi_read_from_socket(struct iscsi_context *iscsi) return 0; } +static int iscsi_pdu_update_headerdigest(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) +{ + unsigned long crc; + + if (pdu->outdata.size < ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE) { + iscsi_set_error(iscsi, "PDU too small (%u) to contain header digest", + (unsigned int) pdu->outdata.size); + return -1; + } + + crc = crc32c((char *)pdu->outdata.data, ISCSI_RAW_HEADER_SIZE); + + pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+3] = (crc >> 24)&0xff; + pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+2] = (crc >> 16)&0xff; + pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+1] = (crc >> 8)&0xff; + pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+0] = (crc) &0xff; + return 0; +} + static int iscsi_write_to_socket(struct iscsi_context *iscsi) { @@ -724,7 +743,13 @@ iscsi_write_to_socket(struct iscsi_context *iscsi) /* set exp statsn */ iscsi_pdu_set_expstatsn(iscsi->outqueue_current, iscsi->statsn + 1); - + + /* calculate header checksum */ + if (iscsi->header_digest != ISCSI_HEADER_DIGEST_NONE && + iscsi_pdu_update_headerdigest(iscsi, iscsi->outqueue_current) != 0) { + return -1; + } + ISCSI_LIST_REMOVE(&iscsi->outqueue, iscsi->outqueue_current); if (!(iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT)) { /* we have to add the pdu to the waitqueue already here @@ -954,23 +979,6 @@ static int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, return -1; } - if (iscsi->header_digest != ISCSI_HEADER_DIGEST_NONE) { - unsigned long crc; - - if (pdu->outdata.size < ISCSI_RAW_HEADER_SIZE + 4) { - iscsi_set_error(iscsi, "PDU too small (%u) to contain header digest", - (unsigned int) pdu->outdata.size); - return -1; - } - - crc = crc32c((char *)pdu->outdata.data, ISCSI_RAW_HEADER_SIZE); - - pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+3] = (crc >> 24)&0xff; - pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+2] = (crc >> 16)&0xff; - pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+1] = (crc >> 8)&0xff; - pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+0] = (crc) &0xff; - } - iscsi_add_to_outqueue(iscsi, pdu); return 0;