Merge pull request #233 from plieven/for_upstream
fix crc32c header checksums and some bugs
This commit is contained in:
@@ -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_realloc(struct iscsi_context *iscsi, void* ptr, size_t size);
|
||||||
void iscsi_free(struct iscsi_context *iscsi, void* ptr);
|
void iscsi_free(struct iscsi_context *iscsi, void* ptr);
|
||||||
char* iscsi_strdup(struct iscsi_context *iscsi, const char* str);
|
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_szmalloc(struct iscsi_context *iscsi, size_t size);
|
||||||
void iscsi_sfree(struct iscsi_context *iscsi, void* ptr);
|
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);
|
struct scsi_task *iscsi_scsi_get_task_from_pdu(struct iscsi_pdu *pdu);
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
|
|
||||||
static unsigned long crctable[256] = {
|
uint32_t crctable[256] = {
|
||||||
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
|
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
|
||||||
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
|
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
|
||||||
0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
|
0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
|
||||||
@@ -110,9 +110,9 @@ static unsigned long crctable[256] = {
|
|||||||
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
|
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) {
|
while (len-- > 0) {
|
||||||
crc = (crc>>8) ^ crctable[(crc ^ (*buf++)) & 0xFF];
|
crc = (crc>>8) ^ crctable[(crc ^ (*buf++)) & 0xFF];
|
||||||
}
|
}
|
||||||
|
|||||||
13
lib/init.c
13
lib/init.c
@@ -111,15 +111,22 @@ char* iscsi_strdup(struct iscsi_context *iscsi, const char* str) {
|
|||||||
return str2;
|
return str2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size) {
|
void* iscsi_smalloc(struct iscsi_context *iscsi, size_t size) {
|
||||||
void *ptr;
|
void *ptr;
|
||||||
if (size > iscsi->smalloc_size) return NULL;
|
if (size > iscsi->smalloc_size) return NULL;
|
||||||
if (iscsi->smalloc_free > 0) {
|
if (iscsi->smalloc_free > 0) {
|
||||||
ptr = iscsi->smalloc_ptrs[--iscsi->smalloc_free];
|
ptr = iscsi->smalloc_ptrs[--iscsi->smalloc_free];
|
||||||
memset(ptr, 0, iscsi->smalloc_size);
|
|
||||||
iscsi->smallocs++;
|
iscsi->smallocs++;
|
||||||
} else {
|
} 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;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1217,6 +1217,8 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
|||||||
must_have_chap_r = 0;
|
must_have_chap_r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ISCSI_LOG(iscsi, 6, "TargetLoginReply: %s", ptr);
|
||||||
|
|
||||||
ptr += len + 1;
|
ptr += len + 1;
|
||||||
size -= len + 1;
|
size -= len + 1;
|
||||||
}
|
}
|
||||||
|
|||||||
15
lib/pdu.c
15
lib/pdu.c
@@ -36,6 +36,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include "iscsi.h"
|
#include "iscsi.h"
|
||||||
#include "iscsi-private.h"
|
#include "iscsi-private.h"
|
||||||
#include "scsi-lowlevel.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];
|
uint8_t ahslen = in->hdr[4];
|
||||||
struct iscsi_pdu *pdu;
|
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) {
|
if (ahslen != 0) {
|
||||||
iscsi_set_error(iscsi, "cant handle expanded headers yet");
|
iscsi_set_error(iscsi, "cant handle expanded headers yet");
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
47
lib/socket.c
47
lib/socket.c
@@ -366,6 +366,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(ai);
|
freeaddrinfo(ai);
|
||||||
|
strncpy(iscsi->connected_portal, portal, MAX_STRING_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +571,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
|
|
||||||
if (iscsi->incoming == NULL) {
|
if (iscsi->incoming == NULL) {
|
||||||
iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu));
|
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) {
|
if (iscsi->incoming == NULL) {
|
||||||
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
|
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -675,6 +676,25 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
return 0;
|
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
|
static int
|
||||||
iscsi_write_to_socket(struct iscsi_context *iscsi)
|
iscsi_write_to_socket(struct iscsi_context *iscsi)
|
||||||
{
|
{
|
||||||
@@ -725,6 +745,12 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
|
|||||||
/* set exp statsn */
|
/* set exp statsn */
|
||||||
iscsi_pdu_set_expstatsn(iscsi->outqueue_current, iscsi->statsn + 1);
|
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);
|
ISCSI_LIST_REMOVE(&iscsi->outqueue, iscsi->outqueue_current);
|
||||||
if (!(iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT)) {
|
if (!(iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT)) {
|
||||||
/* we have to add the pdu to the waitqueue already here
|
/* 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;
|
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);
|
iscsi_add_to_outqueue(iscsi, pdu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -979,7 +988,7 @@ static int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi,
|
|||||||
void
|
void
|
||||||
iscsi_free_iscsi_in_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
|
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);
|
iscsi_free(iscsi, in->data);
|
||||||
in->data=NULL;
|
in->data=NULL;
|
||||||
iscsi_sfree(iscsi, in);
|
iscsi_sfree(iscsi, in);
|
||||||
|
|||||||
Reference in New Issue
Block a user