diff --git a/include/iscsi-private.h b/include/iscsi-private.h index b91af60..b9f38f7 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -351,10 +351,11 @@ void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size); void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size); void iscsi_free(struct iscsi_context *iscsi, void* ptr); char* iscsi_strdup(struct iscsi_context *iscsi, const char* str); +void* iscsi_smalloc(struct iscsi_context *iscsi, size_t size); void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size); void iscsi_sfree(struct iscsi_context *iscsi, void* ptr); -unsigned long crc32c(char *buf, int len); +uint32_t crc32c(uint8_t *buf, int len); struct scsi_task *iscsi_scsi_get_task_from_pdu(struct iscsi_pdu *pdu); diff --git a/lib/crc32c.c b/lib/crc32c.c index 0ae2cda..4455171 100644 --- a/lib/crc32c.c +++ b/lib/crc32c.c @@ -43,7 +43,7 @@ /* */ /*****************************************************************/ -static unsigned long crctable[256] = { +uint32_t crctable[256] = { 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, @@ -110,9 +110,9 @@ static unsigned long crctable[256] = { 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L }; -unsigned long crc32c(char *buf, int len) +uint32_t crc32c(uint8_t *buf, int len) { - unsigned long crc = 0xffffffff; + uint32_t crc = 0xffffffff; while (len-- > 0) { crc = (crc>>8) ^ crctable[(crc ^ (*buf++)) & 0xFF]; } diff --git a/lib/init.c b/lib/init.c index 9941ceb..1b063cd 100644 --- a/lib/init.c +++ b/lib/init.c @@ -111,15 +111,22 @@ char* iscsi_strdup(struct iscsi_context *iscsi, const char* str) { return str2; } -void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size) { +void* iscsi_smalloc(struct iscsi_context *iscsi, size_t size) { void *ptr; if (size > iscsi->smalloc_size) return NULL; if (iscsi->smalloc_free > 0) { ptr = iscsi->smalloc_ptrs[--iscsi->smalloc_free]; - memset(ptr, 0, iscsi->smalloc_size); iscsi->smallocs++; } else { - ptr = iscsi_zmalloc(iscsi, iscsi->smalloc_size); + ptr = iscsi_malloc(iscsi, iscsi->smalloc_size); + } + return ptr; +} + +void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size) { + void *ptr = iscsi_smalloc(iscsi, size); + if (ptr) { + memset(ptr, 0, size); } return ptr; } diff --git a/lib/login.c b/lib/login.c index dd0e7ab..36de085 100644 --- a/lib/login.c +++ b/lib/login.c @@ -1217,6 +1217,8 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, must_have_chap_r = 0; } + ISCSI_LOG(iscsi, 6, "TargetLoginReply: %s", ptr); + ptr += len + 1; size -= len + 1; } diff --git a/lib/pdu.c b/lib/pdu.c index 1275b33..63adcc6 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "iscsi.h" #include "iscsi-private.h" #include "scsi-lowlevel.h" @@ -429,6 +430,20 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in) uint8_t ahslen = in->hdr[4]; struct iscsi_pdu *pdu; + /* verify header checksum */ + if (iscsi->header_digest != ISCSI_HEADER_DIGEST_NONE) { + uint32_t crc, crc_rcvd = 0; + crc = crc32c(in->hdr, ISCSI_RAW_HEADER_SIZE); + crc_rcvd |= in->hdr[ISCSI_RAW_HEADER_SIZE+0]; + crc_rcvd |= in->hdr[ISCSI_RAW_HEADER_SIZE+1] << 8; + crc_rcvd |= in->hdr[ISCSI_RAW_HEADER_SIZE+2] << 16; + crc_rcvd |= in->hdr[ISCSI_RAW_HEADER_SIZE+3] << 24; + if (crc != crc_rcvd) { + iscsi_set_error(iscsi, "header checksum verification failed: calculated 0x%" PRIx32 " received 0x%" PRIx32, crc, crc_rcvd); + return -1; + } + } + if (ahslen != 0) { iscsi_set_error(iscsi, "cant handle expanded headers yet"); return -1; diff --git a/lib/socket.c b/lib/socket.c index 036b4f4..8eee56d 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -366,6 +366,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal, } freeaddrinfo(ai); + strncpy(iscsi->connected_portal, portal, MAX_STRING_SIZE); return 0; } @@ -570,7 +571,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi) if (iscsi->incoming == NULL) { iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu)); - iscsi->incoming->hdr = iscsi_szmalloc(iscsi, ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE); + iscsi->incoming->hdr = iscsi_smalloc(iscsi, ISCSI_HEADER_SIZE); if (iscsi->incoming == NULL) { iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu"); return -1; @@ -675,6 +676,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) +{ + uint32_t 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(pdu->outdata.data, ISCSI_RAW_HEADER_SIZE); + + pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+3] = (crc >> 24); + pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+2] = (crc >> 16); + pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+1] = (crc >> 8); + pdu->outdata.data[ISCSI_RAW_HEADER_SIZE+0] = (crc); + return 0; +} + static int iscsi_write_to_socket(struct iscsi_context *iscsi) { @@ -724,7 +744,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 +980,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; @@ -979,7 +988,7 @@ static int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, void iscsi_free_iscsi_in_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in) { - iscsi_free(iscsi, in->hdr); + iscsi_sfree(iscsi, in->hdr); iscsi_free(iscsi, in->data); in->data=NULL; iscsi_sfree(iscsi, in);