diff options
Diffstat (limited to 'src/server/iscsi.h')
| -rw-r--r-- | src/server/iscsi.h | 268 |
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_ */ |
