Merge pull request #36 from plieven/master

Merge of my patches as discussed
This commit is contained in:
Ronnie Sahlberg
2012-11-12 16:44:18 -08:00
14 changed files with 272 additions and 89 deletions

View File

@@ -25,7 +25,7 @@ dist_noinst_DATA = lib/libiscsi.syms
lib_LTLIBRARIES = lib/libiscsi.la
lib_libiscsi_la_SOURCES = \
lib/connect.c lib/crc32c.c lib/discovery.c lib/init.c \
lib/login.c lib/md5.c lib/nop.c lib/pdu.c lib/scsi-command.c \
lib/login.c lib/md5.c lib/nop.c lib/pdu.c lib/iscsi-command.c \
lib/scsi-lowlevel.c lib/socket.c lib/sync.c lib/task_mgmt.c \
lib/logging.c

View File

@@ -18,6 +18,7 @@
#define __iscsi_private_h__
#include <stdint.h>
#include <time.h>
#if defined(WIN32)
#include <basetsd.h>
@@ -48,8 +49,8 @@ struct iscsi_in_pdu {
long long data_pos;
unsigned char *data;
};
void iscsi_free_iscsi_in_pdu(struct iscsi_in_pdu *in);
void iscsi_free_iscsi_inqueue(struct iscsi_in_pdu *inqueue);
void iscsi_free_iscsi_in_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in);
void iscsi_free_iscsi_inqueue(struct iscsi_context *iscsi, struct iscsi_in_pdu *inqueue);
enum iscsi_initial_r2t {
ISCSI_INITIAL_R2T_NO = 0,
@@ -68,6 +69,7 @@ struct iscsi_context {
char connected_portal[MAX_STRING_SIZE+1];
char portal[MAX_STRING_SIZE+1];
char alias[MAX_STRING_SIZE+1];
char bind_interfaces[MAX_STRING_SIZE+1];
char user[MAX_STRING_SIZE+1];
char passwd[MAX_STRING_SIZE+1];
@@ -102,6 +104,7 @@ struct iscsi_context {
int login_attempts;
int is_loggedin;
int is_reconnecting;
int bind_interfaces_cnt;
int chap_a;
int chap_i;
@@ -127,9 +130,15 @@ struct iscsi_context {
int lun;
int no_auto_reconnect;
int reconnect_deferred;
int log_level;
iscsi_log_fn log_fn;
int mallocs;
int reallocs;
int frees;
time_t last_reconnect;
};
#define ISCSI_PDU_IMMEDIATE 0x40
@@ -210,16 +219,26 @@ struct iscsi_pdu {
struct iscsi_scsi_cbdata *scsi_cbdata;
};
void iscsi_free_scsi_cbdata(struct iscsi_scsi_cbdata *scsi_cbdata);
void iscsi_free_scsi_cbdata(struct iscsi_context *iscsi, struct iscsi_scsi_cbdata *scsi_cbdata);
struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi,
enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode);
struct iscsi_pdu *iscsi_allocate_pdu_size(struct iscsi_context *iscsi,
enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode,
size_t payload_size);
struct iscsi_pdu *iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi,
enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode,
uint32_t itt,
uint32_t flags);
struct iscsi_pdu *iscsi_allocate_pdu_with_itt_flags_size(struct iscsi_context *iscsi,
enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode,
uint32_t itt,
uint32_t flags,
size_t payload_size);
void iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
void iscsi_pdu_set_pduflags(struct iscsi_pdu *pdu, unsigned char flags);
void iscsi_pdu_set_immediate(struct iscsi_pdu *pdu);
@@ -279,6 +298,11 @@ void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string,
unsigned char *iscsi_get_user_in_buffer(struct iscsi_context *iscsi, struct iscsi_in_pdu *in, uint32_t pos, ssize_t *count);
unsigned char *scsi_task_get_data_in_buffer(struct scsi_task *task, uint32_t pos, ssize_t *count);
inline void* iscsi_malloc(struct iscsi_context *iscsi, size_t size);
inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size);
inline void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size);
inline void iscsi_free(struct iscsi_context *iscsi, void* ptr);
inline char* iscsi_strdup(struct iscsi_context *iscsi, const char* str);
unsigned long crc32c(char *buf, int len);
@@ -286,6 +310,8 @@ struct scsi_task *iscsi_scsi_get_task_from_pdu(struct iscsi_pdu *pdu);
void iscsi_set_noautoreconnect(struct iscsi_context *iscsi, int state);
void iscsi_decrement_iface_rr(void);
#define ISCSI_LOG(iscsi, level, format, args...) \
do { \
if (level <= iscsi->log_level && iscsi->log_fn) { \

View File

@@ -77,6 +77,7 @@ struct iscsi_url {
char user[MAX_STRING_SIZE+1];
char passwd[MAX_STRING_SIZE+1];
int lun;
struct iscsi_context *iscsi;
};
/*
@@ -532,6 +533,7 @@ iscsi_task_mgmt_target_cold_reset_async(struct iscsi_context *iscsi,
struct iscsi_data {
int size;
size_t alloc_size;
unsigned char *data;
};
@@ -1023,6 +1025,13 @@ iscsi_set_tcp_keepintvl(struct iscsi_context *iscsi, int value);
EXTERN void
iscsi_set_tcp_syncnt(struct iscsi_context *iscsi, int value);
/*
* This function is to set the interface that outbound connections for this socket are bound to.
* You max specify more than one interface here separated by comma.
*/
EXTERN void
iscsi_set_bind_interfaces(struct iscsi_context *iscsi, char * interfaces);
#ifdef __cplusplus
}
#endif

View File

@@ -839,4 +839,3 @@ void *scsi_malloc(struct scsi_task *task, size_t size);
#endif
#endif /* __scsi_lowlevel_h__ */

View File

@@ -61,7 +61,7 @@ iscsi_testunitready_cb(struct iscsi_context *iscsi, int status,
"failed.");
ct->cb(iscsi, SCSI_STATUS_ERROR, NULL,
ct->private_data);
free(ct);
iscsi_free(iscsi, ct);
}
scsi_free_scsi_task(task);
return;
@@ -80,7 +80,7 @@ iscsi_testunitready_cb(struct iscsi_context *iscsi, int status,
ct->cb(iscsi, status?SCSI_STATUS_ERROR:SCSI_STATUS_GOOD, NULL,
ct->private_data);
scsi_free_scsi_task(task);
free(ct);
iscsi_free(iscsi, ct);
}
static void
@@ -91,8 +91,9 @@ iscsi_login_cb(struct iscsi_context *iscsi, int status, void *command_data _U_,
if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) {
iscsi_disconnect(iscsi);
if (iscsi->bind_interfaces[0]) iscsi_decrement_iface_rr();
if (iscsi_connect_async(iscsi, iscsi->target_address, iscsi_connect_cb, iscsi->connect_data) != 0) {
free(ct);
iscsi_free(iscsi, ct);
return;
}
return;
@@ -100,7 +101,7 @@ iscsi_login_cb(struct iscsi_context *iscsi, int status, void *command_data _U_,
if (status != 0) {
ct->cb(iscsi, SCSI_STATUS_ERROR, NULL, ct->private_data);
free(ct);
iscsi_free(iscsi, ct);
return;
}
@@ -121,14 +122,14 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data _U_
iscsi_set_error(iscsi, "Failed to connect to iSCSI socket. "
"%s", iscsi_get_error(iscsi));
ct->cb(iscsi, SCSI_STATUS_ERROR, NULL, ct->private_data);
free(ct);
iscsi_free(iscsi, ct);
return;
}
if (iscsi_login_async(iscsi, iscsi_login_cb, ct) != 0) {
iscsi_set_error(iscsi, "iscsi_login_async failed.");
ct->cb(iscsi, SCSI_STATUS_ERROR, NULL, ct->private_data);
free(ct);
iscsi_free(iscsi, ct);
}
}
@@ -140,9 +141,10 @@ iscsi_full_connect_async(struct iscsi_context *iscsi, const char *portal,
struct connect_task *ct;
iscsi->lun = lun;
strncpy(iscsi->portal,portal,MAX_STRING_SIZE);
if (iscsi->portal != portal)
strncpy(iscsi->portal,portal,MAX_STRING_SIZE);
ct = malloc(sizeof(struct connect_task));
ct = iscsi_malloc(iscsi, sizeof(struct connect_task));
if (ct == NULL) {
iscsi_set_error(iscsi, "Out-of-memory. Failed to allocate "
"connect_task structure.");
@@ -218,6 +220,10 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi)
int retry = 0;
if (old_iscsi->last_reconnect) {
while (time(NULL) - old_iscsi->last_reconnect < 5) sleep(1);
}
try_again:
iscsi = iscsi_create_context(old_iscsi->initiator_name);
@@ -235,7 +241,10 @@ try_again:
iscsi->lun = old_iscsi->lun;
strncpy(iscsi->portal,old_iscsi->portal, MAX_STRING_SIZE);
strncpy(iscsi->portal,old_iscsi->portal,MAX_STRING_SIZE);
strncpy(iscsi->bind_interfaces,old_iscsi->bind_interfaces,MAX_STRING_SIZE);
iscsi->bind_interfaces_cnt = old_iscsi->bind_interfaces_cnt;
iscsi->log_level = old_iscsi->log_level;
iscsi->log_fn = old_iscsi->log_fn;
@@ -318,18 +327,23 @@ try_again:
}
if (old_iscsi->incoming != NULL) {
iscsi_free_iscsi_in_pdu(old_iscsi->incoming);
iscsi_free_iscsi_in_pdu(old_iscsi, old_iscsi->incoming);
}
if (old_iscsi->inqueue != NULL) {
iscsi_free_iscsi_inqueue(old_iscsi->inqueue);
iscsi_free_iscsi_inqueue(old_iscsi, old_iscsi->inqueue);
}
close(iscsi->fd);
iscsi->fd = old_iscsi->fd;
iscsi->mallocs+=old_iscsi->mallocs;
iscsi->frees+=old_iscsi->frees;
memcpy(old_iscsi, iscsi, sizeof(struct iscsi_context));
memset(iscsi, 0, sizeof(struct iscsi_context));
free(iscsi);
old_iscsi->is_reconnecting = 0;
old_iscsi->last_reconnect = time(NULL);
return 0;
}

View File

@@ -79,19 +79,19 @@ iscsi_discovery_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
}
static void
iscsi_free_discovery_addresses(struct iscsi_discovery_address *addresses)
iscsi_free_discovery_addresses(struct iscsi_context *iscsi, struct iscsi_discovery_address *addresses)
{
while (addresses != NULL) {
struct iscsi_discovery_address *next = addresses->next;
free(discard_const(addresses->target_name));
iscsi_free(iscsi, discard_const(addresses->target_name));
addresses->target_name = NULL;
free(discard_const(addresses->target_address));
iscsi_free(iscsi, discard_const(addresses->target_address));
addresses->target_address = NULL;
addresses->next = NULL;
free(addresses);
iscsi_free(iscsi, addresses);
addresses = next;
}
}
@@ -127,7 +127,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
"discovery data %d>%d", len, size);
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
iscsi_free_discovery_addresses(targets);
iscsi_free_discovery_addresses(iscsi, targets);
return -1;
}
@@ -135,40 +135,39 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
if (!strncmp((char *)ptr, "TargetName=", 11)) {
struct iscsi_discovery_address *target;
target = malloc(sizeof(struct iscsi_discovery_address));
target = iscsi_zmalloc(iscsi, sizeof(struct iscsi_discovery_address));
if (target == NULL) {
iscsi_set_error(iscsi, "Failed to allocate "
"data for new discovered "
"target");
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
iscsi_free_discovery_addresses(targets);
iscsi_free_discovery_addresses(iscsi, targets);
return -1;
}
memset(target, 0, sizeof(struct iscsi_discovery_address));
target->target_name = strdup((char *)ptr+11);
target->target_name = iscsi_strdup(iscsi,(char *)ptr+11);
if (target->target_name == NULL) {
iscsi_set_error(iscsi, "Failed to allocate "
"data for new discovered "
"target name");
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
free(target);
iscsi_free(iscsi, target);
target = NULL;
iscsi_free_discovery_addresses(targets);
iscsi_free_discovery_addresses(iscsi, targets);
return -1;
}
target->next = targets;
targets = target;
} else if (!strncmp((char *)ptr, "TargetAddress=", 14)) {
targets->target_address = strdup((char *)ptr+14);
targets->target_address = iscsi_strdup(iscsi, (char *)ptr+14);
if (targets->target_address == NULL) {
iscsi_set_error(iscsi, "Failed to allocate "
"data for new discovered "
"target address");
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
iscsi_free_discovery_addresses(targets);
iscsi_free_discovery_addresses(iscsi, targets);
return -1;
}
} else {
@@ -176,7 +175,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
"discovery string : %s", ptr);
pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
pdu->private_data);
iscsi_free_discovery_addresses(targets);
iscsi_free_discovery_addresses(iscsi, targets);
return -1;
}
@@ -185,7 +184,7 @@ iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
}
pdu->callback(iscsi, SCSI_STATUS_GOOD, targets, pdu->private_data);
iscsi_free_discovery_addresses(targets);
iscsi_free_discovery_addresses(iscsi, targets);
return 0;
}

View File

@@ -33,25 +33,62 @@
#include "iscsi-private.h"
#include "slist.h"
inline void* iscsi_malloc(struct iscsi_context *iscsi, size_t size) {
void * ptr = malloc(size);
if (ptr != NULL) iscsi->mallocs++;
return ptr;
}
inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size) {
void * ptr = malloc(size);
if (ptr != NULL) {
memset(ptr,0x00,size);
iscsi->mallocs++;
}
return ptr;
}
inline void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size) {
void * _ptr = realloc(ptr, size);
if (_ptr != NULL) {
iscsi->reallocs++;
}
return _ptr;
}
inline void iscsi_free(struct iscsi_context *iscsi, void* ptr) {
if (ptr == NULL) return;
free(ptr);
iscsi->frees++;
}
inline char* iscsi_strdup(struct iscsi_context *iscsi, const char* str) {
char *str2 = strdup(str);
if (str2 != NULL) iscsi->mallocs++;
return str2;
}
struct iscsi_context *
iscsi_create_context(const char *initiator_name)
{
struct iscsi_context *iscsi;
if (!initiator_name[0]) {
return NULL;
}
iscsi = malloc(sizeof(struct iscsi_context));
if (iscsi == NULL) {
return NULL;
}
memset(iscsi, 0, sizeof(struct iscsi_context));
strncpy(iscsi->initiator_name,initiator_name,MAX_STRING_SIZE);
if (!iscsi->initiator_name[0]) {
free(iscsi);
return NULL;
}
iscsi->fd = -1;
srand(time(NULL) ^ getpid() ^ (u_int32_t) ((uintptr_t) iscsi));
/* initialize to a "random" isid */
iscsi_set_isid_random(iscsi, rand(), 0);
@@ -100,6 +137,10 @@ iscsi_create_context(const char *initiator_name)
iscsi_set_tcp_syncnt(iscsi,atoi(getenv("LIBISCSI_TCP_SYNCNT")));
}
if (getenv("LIBISCSI_BIND_INTERFACES") != NULL) {
iscsi_set_bind_interfaces(iscsi,getenv("LIBISCSI_BIND_INTERFACES"));
}
return iscsi;
}
@@ -227,14 +268,21 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
}
if (iscsi->incoming != NULL) {
iscsi_free_iscsi_in_pdu(iscsi->incoming);
iscsi_free_iscsi_in_pdu(iscsi, iscsi->incoming);
}
if (iscsi->inqueue != NULL) {
iscsi_free_iscsi_inqueue(iscsi->inqueue);
iscsi_free_iscsi_inqueue(iscsi, iscsi->inqueue);
}
iscsi->connect_data = NULL;
if (iscsi->mallocs != iscsi->frees) {
ISCSI_LOG(iscsi,1,"%d memory blocks lost at iscsi_destroy_context() after %d malloc(s), %d realloc(s) and %d free(s)",iscsi->mallocs-iscsi->frees,iscsi->mallocs,iscsi->reallocs,iscsi->frees);
} else {
ISCSI_LOG(iscsi,5,"memory is clean at iscsi_destroy_context() after %d mallocs, %d realloc(s) and %d frees",iscsi->mallocs,iscsi->reallocs,iscsi->frees);
}
memset(iscsi, 0, sizeof(struct iscsi_context));
free(iscsi);
return 0;
@@ -393,13 +441,18 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
tmp=strchr(portal,'/');
if (tmp) *tmp=0;
}
iscsi_url = malloc(sizeof(struct iscsi_url));
if (iscsi != NULL)
iscsi_url = iscsi_malloc(iscsi, sizeof(struct iscsi_url));
else
iscsi_url = malloc(sizeof(struct iscsi_url));
if (iscsi_url == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate iscsi_url structure");
return NULL;
}
memset(iscsi_url, 0, sizeof(struct iscsi_url));
iscsi_url->iscsi= iscsi;
strncpy(iscsi_url->portal,portal,MAX_STRING_SIZE);
@@ -431,7 +484,12 @@ iscsi_parse_portal_url(struct iscsi_context *iscsi, const char *url)
void
iscsi_destroy_url(struct iscsi_url *iscsi_url)
{
free(iscsi_url);
struct iscsi_context *iscsi = iscsi_url->iscsi;
memset(iscsi_url, 0, sizeof(struct iscsi_url));
if (iscsi != NULL)
iscsi_free(iscsi, iscsi_url);
else
free(iscsi_url);
}

View File

@@ -37,7 +37,7 @@ struct iscsi_scsi_cbdata {
};
void
iscsi_free_scsi_cbdata(struct iscsi_scsi_cbdata *scsi_cbdata)
iscsi_free_scsi_cbdata(struct iscsi_context *iscsi, struct iscsi_scsi_cbdata *scsi_cbdata)
{
if (scsi_cbdata == NULL) {
return;
@@ -45,7 +45,7 @@ iscsi_free_scsi_cbdata(struct iscsi_scsi_cbdata *scsi_cbdata)
if (scsi_cbdata->task != NULL) {
scsi_cbdata->task = NULL;
}
free(scsi_cbdata);
iscsi_free(iscsi, scsi_cbdata);
}
static void
@@ -186,13 +186,13 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
return -1;
}
scsi_cbdata = malloc(sizeof(struct iscsi_scsi_cbdata));
scsi_cbdata = iscsi_zmalloc(iscsi, sizeof(struct iscsi_scsi_cbdata));
if (scsi_cbdata == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: failed to allocate "
"scsi cbdata.");
return -1;
}
memset(scsi_cbdata, 0, sizeof(struct iscsi_scsi_cbdata));
scsi_cbdata->task = task;
scsi_cbdata->callback = cb;
scsi_cbdata->private_data = private_data;
@@ -204,7 +204,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
if (pdu == NULL) {
iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate "
"scsi pdu.");
iscsi_free_scsi_cbdata(scsi_cbdata);
iscsi_free_scsi_cbdata(iscsi, scsi_cbdata);
return -1;
}
pdu->scsi_cbdata = scsi_cbdata;

View File

@@ -81,6 +81,7 @@ iscsi_set_tcp_keepidle
iscsi_set_tcp_keepcnt
iscsi_set_tcp_keepintvl
iscsi_set_tcp_syncnt
iscsi_set_bind_interface
iscsi_startstopunit_sync
iscsi_startstopunit_task
iscsi_synchronizecache10_sync

View File

@@ -79,6 +79,7 @@ iscsi_set_tcp_keepidle
iscsi_set_tcp_keepcnt
iscsi_set_tcp_keepintvl
iscsi_set_tcp_syncnt
iscsi_set_bind_interface
iscsi_startstopunit_sync
iscsi_startstopunit_task
iscsi_synchronizecache10_sync

View File

@@ -705,10 +705,10 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
return -1;
}
pdu = iscsi_allocate_pdu_with_itt_flags(iscsi,
pdu = iscsi_allocate_pdu_with_itt_flags_size(iscsi,
ISCSI_PDU_LOGIN_REQUEST,
ISCSI_PDU_LOGIN_RESPONSE,
iscsi->itt, 0);
iscsi->itt, 0, 1024);
if (pdu == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
"login pdu.");

View File

@@ -31,27 +31,28 @@
#include "slist.h"
struct iscsi_pdu *
iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags)
iscsi_allocate_pdu_with_itt_flags_size(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags, size_t payload_size)
{
struct iscsi_pdu *pdu;
pdu = malloc(sizeof(struct iscsi_pdu));
pdu = iscsi_zmalloc(iscsi, sizeof(struct iscsi_pdu));
if (pdu == NULL) {
iscsi_set_error(iscsi, "failed to allocate pdu");
return NULL;
}
memset(pdu, 0, sizeof(struct iscsi_pdu));
pdu->outdata.size = ISCSI_HEADER_SIZE;
pdu->outdata.data = malloc(pdu->outdata.size);
pdu->outdata.alloc_size = 64;
while (pdu->outdata.alloc_size < ISCSI_HEADER_SIZE+payload_size) pdu->outdata.alloc_size<<=1;
pdu->outdata.data = iscsi_malloc(iscsi, pdu->outdata.alloc_size);
memset(pdu->outdata.data, 0, ISCSI_HEADER_SIZE);
if (pdu->outdata.data == NULL) {
iscsi_set_error(iscsi, "failed to allocate pdu header");
free(pdu);
iscsi_free(iscsi, pdu);
return NULL;
}
memset(pdu->outdata.data, 0, pdu->outdata.size);
/* opcode */
pdu->outdata.data[0] = opcode;
@@ -72,6 +73,13 @@ iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode
return pdu;
}
struct iscsi_pdu *
iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags)
{
return iscsi_allocate_pdu_with_itt_flags_size(iscsi, opcode, response_opcode, itt, flags, 0);
}
struct iscsi_pdu *
iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode)
@@ -79,6 +87,13 @@ iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
return iscsi_allocate_pdu_with_itt_flags(iscsi, opcode, response_opcode, iscsi->itt++, 0);
}
struct iscsi_pdu *
iscsi_allocate_pdu_size(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode, size_t payload_size)
{
return iscsi_allocate_pdu_with_itt_flags_size(iscsi, opcode, response_opcode, iscsi->itt++, 0, payload_size);
}
void
@@ -89,18 +104,18 @@ iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
return;
}
free(pdu->outdata.data);
iscsi_free(iscsi, pdu->outdata.data);
pdu->outdata.data = NULL;
free(pdu->indata.data);
iscsi_free(iscsi, pdu->indata.data);
pdu->indata.data = NULL;
if (pdu->scsi_cbdata) {
iscsi_free_scsi_cbdata(pdu->scsi_cbdata);
iscsi_free_scsi_cbdata(iscsi, pdu->scsi_cbdata);
pdu->scsi_cbdata = NULL;
}
free(pdu);
iscsi_free(iscsi, pdu);
}
@@ -108,8 +123,7 @@ int
iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
unsigned char *dptr, int dsize, int pdualignment)
{
int len, aligned;
unsigned char *buf;
size_t len, aligned;
if (dsize == 0) {
iscsi_set_error(iscsi, "Trying to append zero size data to "
@@ -122,25 +136,36 @@ iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
if (pdualignment) {
aligned = (aligned+3)&0xfffffffc;
}
buf = malloc(aligned);
if (buf == NULL) {
size_t new_alloc_size = data->alloc_size;
if (new_alloc_size < 64) new_alloc_size=64;
while (aligned > new_alloc_size) new_alloc_size<<=1;
if (data->data != NULL && data->alloc_size == 0) data->alloc_size=data->size;
if (data->alloc_size == 0) {
data->data = iscsi_malloc(iscsi, new_alloc_size);
}
else
if (data->alloc_size != new_alloc_size) {
data->data = iscsi_realloc(iscsi, data->data, new_alloc_size);
}
if (data->data == NULL) {
iscsi_set_error(iscsi, "failed to allocate buffer for %d "
"bytes", len);
"bytes", (int) len);
return -1;
}
data->alloc_size = new_alloc_size;
memcpy(data->data + data->size, dptr, dsize);
if (data->size > 0) {
memcpy(buf, data->data, data->size);
}
memcpy(buf + data->size, dptr, dsize);
if (len != aligned) {
/* zero out any padding at the end */
memset(buf+len, 0, aligned-len);
memset(data->data+len, 0, aligned-len);
}
free(data->data);
data->data = buf;
data->size = len;
return 0;

View File

@@ -46,6 +46,12 @@
#include "iscsi-private.h"
#include "slist.h"
static uint32_t iface_rr = 0;
void iscsi_decrement_iface_rr() {
iface_rr--;
}
static void set_nonblocking(int fd)
{
#if defined(WIN32)
@@ -122,7 +128,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
return -1;
}
addr = strdup(portal);
addr = iscsi_strdup(iscsi, portal);
if (addr == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: "
"Failed to strdup portal address.");
@@ -151,7 +157,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
host ++;
str = strchr(host, ']');
if (str == NULL) {
free(addr);
iscsi_free(iscsi, addr);
iscsi_set_error(iscsi, "Invalid target:%s "
"Missing ']' in IPv6 address", portal);
return -1;
@@ -161,12 +167,12 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
/* is it a hostname ? */
if (getaddrinfo(host, NULL, NULL, &ai) != 0) {
free(addr);
iscsi_free(iscsi, addr);
iscsi_set_error(iscsi, "Invalid target:%s "
"Can not resolv into IPv4/v6.", portal);
return -1;
}
free(addr);
iscsi_free(iscsi, addr);
switch (ai->ai_family) {
case AF_INET:
@@ -216,6 +222,31 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
set_tcp_syncnt(iscsi);
}
#if __linux
if (iscsi->bind_interfaces[0]) {
char *pchr = iscsi->bind_interfaces, *pchr2;
int iface_n = iface_rr++%iscsi->bind_interfaces_cnt;
int iface_c = 0;
do {
pchr2 = strchr(pchr,',');
if (iface_c == iface_n) {
if (pchr2) pchr2[0]=0x00;
break;
}
if (pchr2) {pchr=pchr2+1;}
iface_c++;
} while (pchr2);
int res = setsockopt(iscsi->fd, SOL_SOCKET, SO_BINDTODEVICE, pchr, strlen(pchr));
if (res < 0) {
ISCSI_LOG(iscsi,1,"failed to bind to interface '%s': %s",pchr,strerror(errno));
} else {
ISCSI_LOG(iscsi,3,"successfully bound to interface '%s'",pchr);
}
if (pchr2) pchr2[0]=',';
}
#endif
if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
&& errno != EINPROGRESS) {
iscsi_set_error(iscsi, "Connect failed with errno : "
@@ -297,12 +328,11 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
ssize_t data_size, count;
if (iscsi->incoming == NULL) {
iscsi->incoming = malloc(sizeof(struct iscsi_in_pdu));
iscsi->incoming = iscsi_zmalloc(iscsi, sizeof(struct iscsi_in_pdu));
if (iscsi->incoming == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
return -1;
}
memset(iscsi->incoming, 0, sizeof(struct iscsi_in_pdu));
}
in = iscsi->incoming;
@@ -347,7 +377,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
/* if not, allocate one */
if (buf == NULL) {
if (in->data == NULL) {
in->data = malloc(data_size);
in->data = iscsi_malloc(iscsi, data_size);
if (in->data == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size);
return -1;
@@ -386,7 +416,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
return -1;
}
SLIST_REMOVE(&iscsi->inqueue, current);
iscsi_free_iscsi_in_pdu(current);
iscsi_free_iscsi_in_pdu(iscsi, current);
}
@@ -567,18 +597,20 @@ iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
}
void
iscsi_free_iscsi_in_pdu(struct iscsi_in_pdu *in)
iscsi_free_iscsi_in_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
{
free(in->data);
free(in);
iscsi_free(iscsi, in->data);
in->data=NULL;
iscsi_free(iscsi, in);
in=NULL;
}
void
iscsi_free_iscsi_inqueue(struct iscsi_in_pdu *inqueue)
iscsi_free_iscsi_inqueue(struct iscsi_context *iscsi, struct iscsi_in_pdu *inqueue)
{
while (inqueue != NULL) {
struct iscsi_in_pdu *next = inqueue->next;
iscsi_free_iscsi_in_pdu(inqueue);
iscsi_free_iscsi_in_pdu(iscsi, inqueue);
inqueue = next;
}
}
@@ -647,3 +679,22 @@ int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, in
return 0;
}
void iscsi_set_bind_interfaces(struct iscsi_context *iscsi, char * interfaces)
{
#if __linux
strncpy(iscsi->bind_interfaces,interfaces,MAX_STRING_SIZE);
iscsi->bind_interfaces_cnt=0;
char * pchr = interfaces;
char * pchr2 = NULL;
do {
pchr2 = strchr(pchr,',');
if (pchr2) {pchr=pchr2+1;}
iscsi->bind_interfaces_cnt++;
} while (pchr2);
ISCSI_LOG(iscsi,2,"will bind to one of the following %d interface(s) on next socket creation: %s",iscsi->bind_interfaces_cnt,interfaces);
if (!iface_rr) iface_rr=rand()%iscsi->bind_interfaces_cnt+1;
#else
ISCSI_LOG(iscsi,1,"binding to an interface is not supported on your OS");
#endif
}

View File

@@ -14,7 +14,7 @@ cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\logi
cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\md5.c -Folib\md5.obj
cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\nop.c -Folib\nop.obj
cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\pdu.c -Folib\pdu.obj
cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\scsi-command.c -Folib\scsi-command.obj
cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\iscsi-command.c -Folib\iscsi-command.obj
cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\scsi-lowlevel.c -Folib\scsi-lowlevel.obj
cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\socket.c -Folib\socket.obj
cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd lib\sync.c -Folib\sync.obj
@@ -27,9 +27,9 @@ cl /I. /Iinclude -Zi -Od -c -D_U_="" -DWIN32 -D_WIN32_WINNT=0x0600 -MDd win32\wi
rem
rem create a linklibrary/dll
rem
lib /out:lib\libiscsi.lib /def:lib\libiscsi.def lib\connect.obj lib\crc32c.obj lib\discovery.obj lib\init.obj lib\login.obj lib\md5.obj lib\nop.obj lib\pdu.obj lib\scsi-command.obj lib\scsi-lowlevel.obj lib\socket.obj lib\sync.obj lib\task_mgmt.obj lib\win32_compat.obj
lib /out:lib\libiscsi.lib /def:lib\libiscsi.def lib\connect.obj lib\crc32c.obj lib\discovery.obj lib\init.obj lib\login.obj lib\md5.obj lib\nop.obj lib\pdu.obj lib\iscsi-command.obj lib\scsi-lowlevel.obj lib\socket.obj lib\sync.obj lib\task_mgmt.obj lib\win32_compat.obj
link /DLL /out:lib\libiscsi.dll /DEBUG /DEBUGTYPE:cv lib\libiscsi.exp lib\connect.obj lib\crc32c.obj lib\discovery.obj lib\init.obj lib\login.obj lib\md5.obj lib\nop.obj lib\pdu.obj lib\scsi-command.obj lib\scsi-lowlevel.obj lib\socket.obj lib\sync.obj lib\task_mgmt.obj lib\win32_compat.obj ws2_32.lib kernel32.lib
link /DLL /out:lib\libiscsi.dll /DEBUG /DEBUGTYPE:cv lib\libiscsi.exp lib\connect.obj lib\crc32c.obj lib\discovery.obj lib\init.obj lib\login.obj lib\md5.obj lib\nop.obj lib\pdu.obj lib\iscsi-command.obj lib\scsi-lowlevel.obj lib\socket.obj lib\sync.obj lib\task_mgmt.obj lib\win32_compat.obj ws2_32.lib kernel32.lib