Merge pull request #36 from plieven/master
Merge of my patches as discussed
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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) { \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -839,4 +839,3 @@ void *scsi_malloc(struct scsi_task *task, size_t size);
|
||||
#endif
|
||||
|
||||
#endif /* __scsi_lowlevel_h__ */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
78
lib/init.c
78
lib/init.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.");
|
||||
|
||||
73
lib/pdu.c
73
lib/pdu.c
@@ -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;
|
||||
|
||||
77
lib/socket.c
77
lib/socket.c
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user