summaryrefslogtreecommitdiffstats
path: root/src/server/iscsi.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/iscsi.h')
-rw-r--r--src/server/iscsi.h268
1 files changed, 214 insertions, 54 deletions
diff --git a/src/server/iscsi.h b/src/server/iscsi.h
index c167987..56e09f9 100644
--- a/src/server/iscsi.h
+++ b/src/server/iscsi.h
@@ -36,7 +36,7 @@
#if defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define iscsi_get_be16(x) (x)
-#define iscsi_get_be24(x) ((x) & 0xFFFFFFUL)
+#define iscsi_get_be24(x) (iscsi_get_be32((*(uint32_t *) ((uint8_t *) x - 1))) & 0xFFFFFFUL)
#define iscsi_get_be32(x) (x)
#define iscsi_get_be64(x) (x)
@@ -64,18 +64,20 @@ static inline void iscsi_put_be64(uint8_t *data, const uint64_t val)
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
// GCC or CLang
#define iscsi_get_be16(x) (__builtin_bswap16(x))
-#define iscsi_get_be24(x) (iscsi_get_be32(x) & 0xFFFFFFUL)
+#define iscsi_get_be24(x) (iscsi_get_be32((*(uint32_t *) ((uint8_t *) x - 1))) & 0xFFFFFFUL)
#define iscsi_get_be32(x) (__builtin_bswap32(x))
#define iscsi_get_be64(x) (__builtin_bswap64(x))
#elif defined(_MSC_VER)
#include <intrin.h>
// MVSC
#define iscsi_get_be16(x) (_byteswap_ushort(x))
+#define iscsi_get_be24(x) (iscsi_get_be32((*(uint32_t *) ((uint8_t *) x - 1))) & 0xFFFFFFUL)
#define iscsi_get_be32(x) (_byteswap_ulong(x))
#define iscsi_get_be64(x) (_byteswap_uint64(x))
#else
// Other compilers (use slow conversion method with bit rotation, bit shift and logcal AND)
#define iscsi_get_be16(x) ((((uint16_t) (x)) << 8U) | (((uint16_t) (x)) >> 8U))
+#define iscsi_get_be24(x) (iscsi_get_be32((*(uint32_t *) ((uint8_t *) x - 1))) & 0xFFFFFFUL)
#define iscsi_get_be32(x) ((((uint32_t) (x) & 0xFFUL) << 24UL) | (((uint32_t) (x) & 0xFF00UL) << 8UL) | (((uint32_t) (x) & 0xFF0000UL) >> 8UL) | (((uint32_t) (x) >> 24UL)))
#define iscsi_get_be64(x) ((uint64_t)((((x) & 0xFFULL) << 56ULL) | (((x) & 0xFF00ULL) << 40ULL) | (((x) & 0xFF0000ull) << 24ULL) | (((x) & 0xFF000000ULL) << 8ULL) | (((x) & 0xFF00000000ULL) >> 8ULL) | (((x) & 0xFF0000000000ULL) >> 24ULL) | (((x) & 0xFF000000000000ULL) >> 40ULL) | (((x) & 0xFF00000000000000ULL) >> 56ULL)))
#endif
@@ -234,9 +236,9 @@ uint8_t *iscsi_hashmap_key_create(const uint8_t *data, const size_t len); // Cre
void iscsi_hashmap_key_destroy(uint8_t *key); // Deallocates all resources acquired by iscsi_hashmap_create_key
int iscsi_hashmap_key_destroy_value_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // Deallocates all key / value pairs in a hash map by calling free (default destructor)
-int iscsi_hashmap_put(iscsi_hashmap *map, const uint8_t *key, const size_t key_size, uint8_t *value); // Assigns key / value pair to hash map without making copies
-int iscsi_hashmap_get_put(iscsi_hashmap *map, const uint8_t *key, const size_t key_size, uint8_t **out_in_value); // Assigns key / value pair to hash map without making copies
-int iscsi_hashmap_put_free(iscsi_hashmap *map, const uint8_t *key, const size_t key_size, uint8_t *value, iscsi_hashmap_callback callback, uint8_t *user_data); // Assigns key / value pair to hash map without making copies
+int iscsi_hashmap_put(iscsi_hashmap *map, uint8_t *key, const size_t key_size, uint8_t *value); // Assigns key / value pair to hash map without making copies
+int iscsi_hashmap_get_put(iscsi_hashmap *map, uint8_t *key, const size_t key_size, uint8_t **out_in_value); // Assigns key / value pair to hash map without making copies
+int iscsi_hashmap_put_free(iscsi_hashmap *map, uint8_t *key, const size_t key_size, uint8_t *value, iscsi_hashmap_callback callback, uint8_t *user_data); // Assigns key / value pair to hash map without making copies
// with callback function in case the key already exists
int iscsi_hashmap_contains(iscsi_hashmap *map, const uint8_t *key, const size_t key_size); // Checks whether a specified key exists
int iscsi_hashmap_get(iscsi_hashmap *map, const uint8_t *key, const size_t key_size, uint8_t **out_value); // Retrieves the value of a specified key
@@ -244,7 +246,7 @@ int iscsi_hashmap_get(iscsi_hashmap *map, const uint8_t *key, const size_t key_s
void iscsi_hashmap_remove(iscsi_hashmap *map, const uint8_t *key, const size_t key_size); // Marks an element for removal by setting key and value both to NULL
void iscsi_hashmap_remove_free(iscsi_hashmap *map, const uint8_t *key, const size_t key_size, iscsi_hashmap_callback callback, uint8_t *user_data); // Marks an element for removal by setting key and value both to NULL,
// but invokes a callback function before actual marking for removal.
-int iscsi_hashmap_size(iscsi_hashmap *map); // Retrieves the number of elements of the hash map, ignoring elements marked for removal
+uint iscsi_hashmap_size(const iscsi_hashmap *map); // Retrieves the number of elements of the hash map, ignoring elements marked for removal
int iscsi_hashmap_iterate(iscsi_hashmap *map, iscsi_hashmap_callback callback, uint8_t *user_data); // Iterator with callback function invoked on each element which has not been removed
@@ -5607,6 +5609,28 @@ typedef struct __attribute__((packed)) iscsi_nop_in_packet {
} iscsi_nop_in_packet;
+/// iSCSI SCSI transport ID protocol identifier.
+#define ISCSI_TRANSPORT_ID_PROTOCOL_ID_ISCSI 0x05
+
+/// iSCSI SCSI transport ID format.
+#define ISCSI_TRANSPORT_ID_FORMAT 0x01
+
+
+typedef struct __attribute__((packed)) iscsi_transport_id {
+ /// First 4 bits are protocol ID and last 2 bits are format.
+ uint8_t id;
+
+ /// Reserved for future usage (always MUST be 0).
+ uint8_t reserved;
+
+ /// Additional length of name.
+ uint16_t add_len;
+
+ /// Name.
+ uint8_t name[0];
+} iscsi_transport_id;
+
+
/// iSCSI packet validation return code from iscsi_validate_packet function: Validation successful -> iSCSI packet recognized and compliance to protocol specification.
#define ISCSI_VALIDATE_PACKET_RESULT_OK 0L
@@ -5726,30 +5750,20 @@ typedef struct iscsi_key_value_pair_packet {
int iscsi_parse_key_value_pairs(iscsi_hashmap *pairs, const uint8_t *packet_data, uint len, int c_bit, uint8_t **partial_pairs); // Extracts all text key / value pairs out of an iSCSI packet into a hash map
int iscsi_create_key_value_pair_packet_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // Creates a single partial iSCSI packet stream out of a single text key and value pair
-iscsi_key_value_pair_packet *iscsi_create_key_value_pairs_packet(const iscsi_hashmap *pairs); // Creates a properly aligned iSCSI packet DataSegment out of a hash map containing text key and value pairs
+iscsi_key_value_pair_packet *iscsi_create_key_value_pairs_packet(iscsi_hashmap *key_value_pairs); // Creates a properly aligned iSCSI packet DataSegment out of a hash map containing text key and value pairs
-/**
- * @brief iSCSI portal group: Private portal group if set, public otherwise.
- *
- * When redirecting logins, there are two portal group types: public and
- * private.\n
- * Public portal groups return their portals during discovery session.
- * A redirection private portal may also be specified for non-discovery
- * logins.\n
- * Private portal groups instead do not return their portals during
- * the discovery session.
- */
-#define ISCSI_PORTAL_GROUP_PRIVATE (1 << 0)
+/// iSCSI main global data flags: Allow duplicate ISIDs.
+#define ISCSI_GLOBALS_FLAGS_ISID_ALLOW_DUPLICATES (1 << 0L)
-/// iSCSI portal group: CHAP authentication is disabled.
-#define ISCSI_PORTAL_GROUP_CHAP_DISABLE (1 << 1)
+/// iSCSI main global data flags: CHAP authentication is disabled.
+#define ISCSI_GLOBALS_FLAGS_CHAP_DISABLE (1 << 1L)
-/// iSCSI portal group: CHAP authentication is required.
-#define ISCSI_PORTAL_GROUP_CHAP_REQUIRE (1 << 2)
+/// iSCSI main global data flags: CHAP authentication is required.
+#define ISCSI_GLOBALS_FLAGS_CHAP_REQUIRE (1 << 2L)
-/// iSCSI portal group: Mutual.
-#define ISCSI_PORTAL_GROUP_CHAP_MUTUAL (1 << 3)
+/// iSCSI main global data flags: CHAP authentication is mutual.
+#define ISCSI_GLOBALS_FLAGS_CHAP_MUTUAL (1 << 3L)
/**
@@ -5759,6 +5773,9 @@ iscsi_key_value_pair_packet *iscsi_create_key_value_pairs_packet(const iscsi_has
* connections are stored here for global access.
*/
typedef struct iscsi_globals {
+ /// Hash map containing all iSCSI devices.
+ iscsi_hashmap *devices;
+
/// Hash map containing all registered iSCSI portal groups.
iscsi_hashmap *portal_groups;
@@ -5770,9 +5787,45 @@ typedef struct iscsi_globals {
/// Hash map containing connections not associated with an iSCSI sessions.
iscsi_hashmap *connections;
+
+ /// Global flags.
+ int flags;
+
+ /// Maximum number of allowed sessions.
+ uint max_sessions;
+
+ /// CHAP group id.
+ int32_t chap_group;
} iscsi_globals;
+/// iSCSI vector for global access.
+iscsi_globals *iscsi_globvec = NULL;
+
+
+/**
+ * @brief iSCSI portal group: Private portal group if set, public otherwise.
+ *
+ * When redirecting logins, there are two portal group types: public and
+ * private.\n
+ * Public portal groups return their portals during discovery session.
+ * A redirection private portal may also be specified for non-discovery
+ * logins.\n
+ * Private portal groups instead do not return their portals during
+ * the discovery session.
+ */
+#define ISCSI_PORTAL_GROUP_PRIVATE (1 << 0L)
+
+/// iSCSI portal group: CHAP authentication is disabled.
+#define ISCSI_PORTAL_GROUP_CHAP_DISABLE (1 << 1L)
+
+/// iSCSI portal group: CHAP authentication is required.
+#define ISCSI_PORTAL_GROUP_CHAP_REQUIRE (1 << 2L)
+
+/// iSCSI portal group: CHAP authentication is mutual.
+#define ISCSI_PORTAL_GROUP_CHAP_MUTUAL (1 << 3L)
+
+
/**
* @brief iSCSI portal group.
*
@@ -5827,7 +5880,7 @@ void iscsi_portal_destroy(iscsi_portal *portal);
/// ISCSI port flags: In use.
-#define ISCSI_PORT_FLAGS_IN_USE (1 << 0)
+#define ISCSI_PORT_FLAGS_IN_USE (1 << 0L)
/**
@@ -5839,7 +5892,7 @@ void iscsi_portal_destroy(iscsi_portal *portal);
*/
typedef struct iscsi_port {
/// Transport ID.
- uint8_t *transport_id;
+ iscsi_transport_id *transport_id;
/// Name.
uint8_t *name;
@@ -5861,12 +5914,15 @@ typedef struct iscsi_port {
iscsi_port *iscsi_port_create(const uint8_t *name, const uint64_t id, const uint16_t index); // Allocates and initializes an iSCSI port
void iscsi_port_destroy(iscsi_port *port); // Deallocates all resource acquired iscsi_port_create
+uint8_t *iscsi_port_get_name(const iscsi_port *port); // Retrieves the name of an iSCSI port
+
+int iscsi_port_transport_id_set(iscsi_port *port, const uint8_t *name, const uint64_t isid); // Sets the SCSI transport ID of the iSCSI port
/// iSCSI device flags: Allocated.
-#define ISCSI_DEVICE_FLAGS_ALLOCATED (1 << 0)
+#define ISCSI_DEVICE_FLAGS_ALLOCATED (1 << 0L)
/// iSCSI device flags: Removed.
-#define ISCSI_DEVICE_FLAGS_REMOVED (1 << 1)
+#define ISCSI_DEVICE_FLAGS_REMOVED (1 << 1L)
/**
@@ -5901,22 +5957,22 @@ typedef struct iscsi_device {
/// iSCSI target node flags: Header digest.
-#define ISCSI_TARGET_NODE_FLAGS_DIGEST_HEADER (1 << 0)
+#define ISCSI_TARGET_NODE_FLAGS_DIGEST_HEADER (1 << 0L)
/// iSCSI target node flags: Data digest.
-#define ISCSI_TARGET_NODE_FLAGS_DIGEST_DATA (1 << 1)
+#define ISCSI_TARGET_NODE_FLAGS_DIGEST_DATA (1 << 1L)
/// iSCSI target node flags: CHAP authentication disabled.
-#define ISCSI_TARGET_NODE_FLAGS_CHAP_DISABLE (1 << 2)
+#define ISCSI_TARGET_NODE_FLAGS_CHAP_DISABLE (1 << 2L)
/// iSCSI target node flags: CHAP authentication required.
-#define ISCSI_TARGET_NODE_FLAGS_CHAP_REQUIRE (1 << 3)
+#define ISCSI_TARGET_NODE_FLAGS_CHAP_REQUIRE (1 << 3L)
/// iSCSI target node flags: CHAP authentication mutual.
-#define ISCSI_TARGET_NODE_FLAGS_CHAP_MUTUAL (1 << 4)
+#define ISCSI_TARGET_NODE_FLAGS_CHAP_MUTUAL (1 << 4L)
-/// iSCSI target node flags: CHAP authentication mutual.
-#define ISCSI_TARGET_NODE_FLAGS_DESTROYED (1 << 5)
+/// iSCSI target node flags: Destroyed.
+#define ISCSI_TARGET_NODE_FLAGS_DESTROYED (1 << 5L)
/**
@@ -5945,14 +6001,60 @@ typedef struct iscsi_target_node {
/// Flags.
int flags;
+ /// Header digest size (always must be 0 or 4 for now).
+ int header_digest;
+
+ /// Data digest size (always must be 0 or 4 for now).
+ int data_digest;
+
/// CHAP group ID.
- int chap_group;
+ int32_t chap_group;
/// Number of active connections for this target node.
uint32_t active_conns;
} iscsi_target_node;
+/**
+ * @brief iSCSI target node search by name.
+ *
+ * This structure is used by iterating through
+ * all iSCSI target nodes finding by name.
+ */
+typedef struct iscsi_target_node_find_name {
+ /// Found iSCSI target node is stored here, should be initialized to NULL.
+ iscsi_target_node *target;
+
+ /// The name of the target node to search for.
+ uint8_t *name;
+} iscsi_target_node_find_name;
+
+
+/// iSCSI authentication CHAP phase: None.
+#define ISCSI_AUTH_CHAP_PHASE_NONE 0L
+
+/// iSCSI authentication CHAP phase: Wait A.
+#define ISCSI_AUTH_CHAP_PHASE_WAIT_A 1L
+
+/// iSCSI authentication CHAP phase: Wait NR.
+#define ISCSI_AUTH_CHAP_PHASE_WAIT_NR 2L
+
+/// iSCSI authentication CHAP phase: End.
+#define ISCSI_AUTH_CHAP_PHASE_END 3L
+
+
+/**
+ * @brief iSCSI CHAP authentication data structure.
+ *
+ * This structure maintains all data required for
+ * CHAP authentication method.
+ */
+typedef struct iscsi_auth_chap {
+ /// CHAP phase.
+ int phase;
+} iscsi_auth_chap;
+
+
/// iSCSI session: Default maximum number of connections.
#define ISCSI_SESSION_DEFAULT_MAX_CONNECTIONS 2UL
@@ -6027,7 +6129,7 @@ typedef struct iscsi_session {
iscsi_target_node *target;
/// Queue depth.
- int queue_depth;
+ uint queue_depth;
/// iSCSI session type.
int type;
@@ -6104,6 +6206,18 @@ typedef struct iscsi_session {
/// iSCSI connection flags: Full feature.
#define ISCSI_CONNECT_FLAGS_FULL_FEATURE (1 << 3L)
+/// iSCSI connection flags: CHAP authentication is disabled.
+#define ISCSI_CONNECT_FLAGS_CHAP_DISABLE (1 << 4L)
+
+/// iSCSI connection flags: CHAP authentication is required.
+#define ISCSI_CONNECT_FLAGS_CHAP_REQUIRE (1 << 5L)
+
+/// iSCSI connection flags: CHAP authentication is mutual.
+#define ISCSI_CONNECT_FLAGS_CHAP_MUTUAL (1 << 6L)
+
+/// iSCSI connection flags: Authenticated.
+#define ISCSI_CONNECT_FLAGS_AUTH (1 << 7L)
+
/// Ready to wait for PDU.
#define ISCSI_CONNECT_PDU_RECV_STATE_WAIT_PDU_READY 0L
@@ -6149,9 +6263,33 @@ typedef struct iscsi_connection {
/// Temporarily storage for partially received parameter.
uint8_t *partial_pairs;
+ /// iSCSI device.
+ iscsi_device *device;
+
+ /// iSCSI initiator port.
+ iscsi_port *init_port;
+
/// Initiator name.
uint8_t *init_name;
+ //// Initiator IP address.
+ uint8_t *init_adr;
+
+ /// iSCSI target node.
+ iscsi_target_node *target;
+
+ /// iSCSI target port.
+ iscsi_port *target_port;
+
+ /// iSCSI target short name.
+ uint8_t *target_name_short;
+
+ /// iSCSI portal host name.
+ uint8_t *portal_host;
+
+ /// iSCSI portal host port.
+ uint8_t *portal_port;
+
/// iSCSI connection contains a header digest (CRC32), always MUST be 0 or 4 for now.
int header_digest;
@@ -6177,7 +6315,7 @@ typedef struct iscsi_connection {
int state;
/// Maximum receive DataSegment length in bytes.
- int max_recv_ds_len;
+ uint max_recv_ds_len;
/// Portal group tag.
int pg_tag;
@@ -6188,11 +6326,17 @@ typedef struct iscsi_connection {
/// Target Session Identifying Handle (TSIH).
uint16_t tsih;
+ /// Connection ID (CID).
+ uint16_t cid;
+
/// Initiator Task Tag (ITT).
uint32_t init_task_tag;
- /// Connection ID (CID).
- uint16_t cid;
+ /// CHAP authentication.
+ iscsi_auth_chap auth_chap;
+
+ /// CHAP group id.
+ int32_t chap_group;
/// StatSN.
uint32_t stat_sn;
@@ -6201,19 +6345,9 @@ typedef struct iscsi_connection {
uint32_t exp_stat_sn;
} iscsi_connection;
-iscsi_connection *iscsi_connection_create(iscsi_portal *portal, const int sock); // Creates data structure for an iSCSI connection from iSCSI portal and TCP/IP socket
-int iscsi_connection_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // iSCSI connection destructor callback for hash map
-void iscsi_connection_destroy(iscsi_connection *conn); // Deallocates all resources acquired by iscsi_connection_create
-
-void iscsi_connection_schedule(iscsi_connection *conn); // Schedules an iSCSI connection
-
-int iscsi_connection_read(const iscsi_connection *conn, uint8_t *buf, const uint len); // Reads data for the specified iSCSI connection from its TCP socket
-int iscsi_connection_write(const iscsi_connection *conn, uint8_t *buf, const uint len); // Writes data for the specified iSCSI connection to its TCP socket
-
-int iscsi_connection_copy_key_value_pairs(iscsi_connection *conn); // Copies retrieved key and value pairs into SCSI connection and session structures
/// iSCSI PDU flags: Rejected.
-#define ISCSI_PDU_FLAGS_REJECTED (1 << 0)
+#define ISCSI_PDU_FLAGS_REJECTED (1 << 0L)
/**
@@ -6239,6 +6373,9 @@ typedef struct iscsi_pdu {
/// Data digest (CRC32C) packet data for fast access and is straight after BHS, AHS, header digest and DataSegment packet in memory.
iscsi_data_digest *data_digest;
+ /// Key and value pairs to send to client.
+ iscsi_hashmap *key_value_pairs;
+
/// Flags.
int flags;
@@ -6276,13 +6413,36 @@ typedef struct iscsi_pdu {
uint32_t cmd_sn;
} iscsi_pdu;
+iscsi_port *iscsi_device_find_port_by_portal_group_tag(const iscsi_device *device, const uint64_t id); // Gets an iSCSI device being in use by portal group identifier
+int iscsi_target_node_find_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // Finds an iSCSI target node by case insensitive name search
+iscsi_target_node *iscsi_target_node_find(uint8_t *target_name); // Searches an iSCSI target node by name using case insensitive search
+
+uint8_t *iscsi_target_node_get_redirect(iscsi_connection *conn, iscsi_target_node *target); // Retrieves target node redirection address
+int iscsi_target_node_access(iscsi_connection *conn, iscsi_target_node *target, const uint8_t *iqn, const uint8_t *adr); // Checks if target node is accessible
+
+iscsi_session *iscsi_session_create(iscsi_connection *conn, iscsi_target_node *target, const int type); // Creates and initializes an iSCSI session
+void iscsi_session_destroy(iscsi_session *session); // Deallocates all resources acquired by iscsi_session_create
+
+iscsi_connection *iscsi_connection_create(iscsi_portal *portal, const int sock); // Creates data structure for an iSCSI connection from iSCSI portal and TCP/IP socket
+int iscsi_connection_destroy_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // iSCSI connection destructor callback for hash map
+void iscsi_connection_destroy(iscsi_connection *conn); // Deallocates all resources acquired by iscsi_connection_create
+
+int iscsi_connection_drop(iscsi_connection *conn, const uint8_t *conn_match, const int all); // Drops all connections based on matching pattern
+void iscsi_connection_schedule(iscsi_connection *conn); // Schedules an iSCSI connection
+
+int iscsi_connection_read(const iscsi_connection *conn, uint8_t *buf, const uint len); // Reads data for the specified iSCSI connection from its TCP socket
+int iscsi_connection_write(const iscsi_connection *conn, uint8_t *buf, const uint len); // Writes data for the specified iSCSI connection to its TCP socket
+
+int iscsi_connection_copy_key_value_pairs(iscsi_connection *conn); // Copies retrieved key and value pairs into SCSI connection and session structures
+int iscsi_connection_save_incoming_key_value_pairs(iscsi_connection *conn, iscsi_hashmap *key_value_pairs, iscsi_pdu *login_response_pdu, const iscsi_pdu *pdu); // Saves incoming key / value pairs from the client of a login request PDU
+
typedef void (*iscsi_connection_xfer_complete_callback)(uint8_t *user_data); // iSCSI transfer completed callback function.
iscsi_pdu *iscsi_connection_pdu_create(iscsi_connection *conn); // Creates an iSCSI PDU structure used by connections
void iscsi_connection_pdu_destroy(iscsi_pdu *pdu); // Destroys an iSCSI PDU structure used by connections
-int iscsi_connection_read_data(struct spdk_iscsi_conn *conn, int len, void *buf);
-int iscsi_connection_read_iov_data(struct spdk_iscsi_conn *conn, struct iovec *iov, int iov_count);
+int iscsi_connection_read_data(iscsi_connection *conn, int len, void *buf);
+int iscsi_connection_read_iov_data(iscsi_connection *conn, struct iovec *iov, int iov_count);
void iscsi_connection_pdu_write(iscsi_connection *conn, iscsi_pdu *pdu, iscsi_connection_xfer_complete_callback callback, uint8_t *user_data);
#endif /* DNBD3_ISCSI_H_ */