/* * Copyright (C) 2002 - 2003 Ardis Technologies * Copyright (C) 2007 - 2018 Vladislav Bolkhovitin * Copyright (C) 2007 - 2018 Western Digital Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, version 2 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef ISCSID_H #define ISCSID_H #include #include #include #include #include #include #include "types.h" #ifdef INSIDE_KERNEL_TREE #include #include #else #include "iscsi_scst.h" #include "isert_scst.h" #endif #include "iscsi_hdr.h" #include "param.h" #include "misc.h" #ifndef bool typedef enum {false = 0, true} bool; #endif #define sBUG() assert(0) #define sBUG_ON(p) assert(!(p)) struct iscsi_init_params { int max_data_seg_len; int max_queued_cmds; }; struct buf_segment { struct __qelem entry; unsigned int len; char data[]; }; struct PDU { struct iscsi_hdr bhs; void *ahs; unsigned int ahssize; void *data; unsigned int datasize; }; #define KEY_STATE_START 0 #define KEY_STATE_REQUEST 1 #define KEY_STATE_DONE_ADDED 2 #define KEY_STATE_DONE 3 struct session { struct __qelem slist; char *initiator; struct target *target; union iscsi_sid sid; struct __qelem conn_list; }; struct connection { int state; int iostate; int fd; unsigned int passed_to_kern:1; unsigned int sessions_count_incremented:1; struct target *target; struct session *sess; u32 tid; /* Put here, because negotiations is done before session created */ struct iscsi_param session_params[session_key_last]; char *initiator; char *target_portal; char *user; union iscsi_sid sid; u16 cid; int session_type; int auth_method; u32 stat_sn; u32 exp_stat_sn; u32 cmd_sn; u32 exp_cmd_sn; u32 ttt; struct PDU req; void *req_buffer; struct PDU rsp; struct __qelem rsp_buf_list; unsigned char *buffer; int rwsize; int auth_state; union { struct { int digest_alg; int id; int challenge_size; unsigned char *challenge; } chap; } auth; struct __qelem clist; bool is_iser; int (*cork_transmit)(int fd); int (*uncork_transmit)(int fd); int (*getsockname)(int fd, struct sockaddr *name, socklen_t *namelen); int (*is_discovery)(int fd); }; #define IOSTATE_FREE 0 #define IOSTATE_READ_BHS 1 #define IOSTATE_READ_AHS_DATA 2 #define IOSTATE_WRITE_BHS 3 #define IOSTATE_WRITE_AHS 4 #define IOSTATE_WRITE_DATA 5 #define STATE_FREE 0 #define STATE_SECURITY 1 #define STATE_SECURITY_AUTH 2 #define STATE_SECURITY_DONE 3 #define STATE_SECURITY_LOGIN 4 #define STATE_SECURITY_FULL 5 #define STATE_LOGIN 6 #define STATE_LOGIN_FULL 7 #define STATE_FULL 8 #define STATE_KERNEL 9 #define STATE_CLOSE 10 #define STATE_EXIT 11 #define STATE_DROP 12 #define AUTH_STATE_START 0 #define AUTH_STATE_CHALLENGE 1 #define SESSION_NORMAL 0 #define SESSION_DISCOVERY 1 #define AUTH_UNKNOWN -1 #define AUTH_NONE 0 #define AUTH_CHAP 1 #define DIGEST_UNKNOWN -1 #define BHS_SIZE 48 /* * Must be 8192, since it used as MaxRecvDataSegmentLength during Login phase, * because iSCSI RFC requires: "The default MaxRecvDataSegmentLength is used * during Login". */ #define INCOMING_BUFSIZE 8192 #define ISCSI_USER_DIR_INCOMING 0 #define ISCSI_USER_DIR_OUTGOING 1 #define ISCSI_USER_NAME(attr) ((attr)->attr_key) #define ISCSI_USER_PASS(attr) ((attr)->attr_value) struct iscsi_attr { struct __qelem ulist; const char *attr_key; const char *attr_value; u32 sysfs_mode; char sysfs_name[64]; }; struct target { struct __qelem tlist; struct __qelem sessions_list; unsigned int tgt_enabled:1; unsigned int per_portal_acl:1; unsigned int target_params[target_key_last]; unsigned int session_params[session_key_last]; u32 tid; char name[ISCSI_NAME_LEN]; char *alias; unsigned int sessions_count; struct redirect_addr { char addr[NI_MAXHOST + 1]; int port; u8 type; /* one of ISCSI_STATUS_TGT_MOVED_* constants */ } redirect; struct __qelem target_in_accounts; struct __qelem target_out_accounts; struct __qelem allowed_portals; struct __qelem isns_head; }; extern int ctrl_fd; extern int conn_blocked; #define ADDR_MAX 32 #define LISTEN_MAX 32 #define INCOMING_MAX 256 enum { POLL_LISTEN, POLL_IPC = POLL_LISTEN + LISTEN_MAX, POLL_ISER_LISTEN, POLL_NL, POLL_ISNS, POLL_SCN_LISTEN, POLL_SCN, POLL_INCOMING, POLL_MAX = POLL_INCOMING + INCOMING_MAX, }; extern struct pollfd poll_array[POLL_MAX]; extern int nl_fd; /* chap.c */ extern int cmnd_exec_auth_chap(struct connection *conn); /* conn.c */ extern struct connection *conn_alloc(void); extern void conn_free(struct connection *conn); extern void conn_pass_to_kern(struct connection *conn, int fd); extern void conn_read_pdu(struct connection *conn); extern void conn_write_pdu(struct connection *conn); extern void conn_free_pdu(struct connection *conn); extern void conn_free_rsp_buf_list(struct connection *conn); /* iscsi_scstd.c */ extern uint16_t server_port; extern struct iscsi_init_params iscsi_init_params; extern void isns_set_fd(int isns, int scn_listen, int scn); extern const char *get_error_str(int error); /* iscsid.c */ extern int iscsi_enabled; extern int cmnd_execute(struct connection *conn); extern void cmnd_finish(struct connection *conn); extern char *text_key_find(struct connection *conn, const char *searchKey); extern void text_key_add(struct connection *conn, const char *key, const char *value); /* log.c */ extern int log_daemon; extern int log_level; extern void log_init(void); extern void __log(const char *func, int line, int prio, int level, const char *fmt, ...) __attribute__ ((format (printf, 5, 6))); extern void __log_pdu(const char *func, int line, int level, struct PDU *pdu); #define log_info(args...) __log(__func__, __LINE__, LOG_INFO, 0, ## args) #define log_warning(args...) __log(__func__, __LINE__, LOG_WARNING, 0, ## args) #define log_error(args...) __log(__func__, __LINE__, LOG_ERR, 0, ## args) #define log_debug(level, args...) __log(__func__, __LINE__, LOG_DEBUG, level, ## args) #define log_pdu(level, args...) __log_pdu(__func__, __LINE__, level, ## args) /* Conditional versions of log_* functions. Useful when log priority depends * on some parameter, say recurrence of some event. In these cases the first * occurrence could be logged as log_info while the latter ones may be logged * with log_debug. So, if level != 0 then log_debug is called. */ #define log_info_cond(level, args...) \ __log(__func__, __LINE__, LOG_INFO, level, ## args) #define log_warning_cond(level, args...) \ __log(__func__, __LINE__, LOG_WARNING, level, ## args) #define log_error_cond(level, args...) \ __log(__func__, __LINE__, LOG_ERR, level, ## args) /* session.c */ extern struct session *session_find_name(u32 tid, const char *iname, union iscsi_sid sid); extern struct session *session_find_id(u32 tid, u64 sid); extern int session_create(struct connection *conn); extern void session_free(struct session *session); extern struct connection *conn_find(struct session *session, u16 cid); /* target.c */ extern struct __qelem targets_list; extern int target_create(const char *name, struct target **out_target); extern void target_free(struct target *target); extern int target_add(struct target *target, u32 *tid, u32 cookie); extern int target_del(u32 tid, u32 cookie); extern u32 target_find_id_by_name(const char *name); extern struct target *target_find_by_name(const char *name); extern struct target *target_find_by_id(u32); extern void target_list_build(struct connection *, char *); extern int target_portal_allowed(struct target *target, const char *target_portal, const char *initiator_name); extern const char *iscsi_make_full_initiator_name(int per_portal_acl, const char *initiator_name, const char *target_portal, char *buf, int size); extern bool target_redirected(struct target *target, struct connection *conn); /* message.c */ extern int iscsi_adm_request_listen(void); extern int iscsi_adm_request_handle(int accept_fd); /* ctldev.c */ extern int kernel_open(void); extern int kernel_params_get(u32 tid, u64 sid, int type, struct iscsi_param *params); extern int kernel_params_set(u32 tid, u64 sid, int type, u32 partial, const struct iscsi_param *params); extern int kernel_target_create(struct target *target, u32 *tid, u32 cookie); extern int kernel_target_destroy(u32 tid, u32 cookie); extern int kernel_user_add(struct target *target, struct iscsi_attr *attr, u32 cookie); extern int kernel_user_del(struct target *target, struct iscsi_attr *attr, u32 cookie); extern int kernel_attr_add(struct target *target, const char *name, u32 mode, u32 cookie); extern int kernel_attr_del(struct target *target, const char *name, u32 cookie); extern int kernel_initiator_allowed(u32 tid, const char *initiator_name); extern int kernel_session_create(struct connection *conn); extern int kernel_session_destroy(u32 tid, u64 sid); extern int kernel_conn_create(u32 tid, u64 sid, u32 cid, u32 stat_sn, u32 exp_stat_sn, int fd); extern int kernel_conn_destroy(u32 tid, u64 sid, u32 cid); /* event.c */ extern int handle_iscsi_events(int fd, bool wait); extern int nl_open(void); /* config.c */ extern char *config_sep_string(char **pp); extern int config_parse_main(const char *data, u32 cookie); extern int config_load(const char *config_name); extern int config_target_create(u32 *tid, char *name); extern int config_target_destroy(u32 tid); extern int config_account_add(u32 tid, int dir, char *name, char *pass, const char *sysfs_name, u32 cookie); extern int __config_account_add(struct target *target, int dir, char *name, char *pass, const char *sysfs_name, int send_to_kern, u32 cookie); extern int config_account_query(u32 tid, int dir, const char *name, char *pass); extern int config_account_list(u32 tid, int dir, u32 *cnt, u32 *overflow, char *buf, size_t buf_sz); extern int config_account_del(u32 tid, int dir, char *name, u32 cookie); extern int config_params_get(u32 tid, u64 sid, int type, struct iscsi_param *params); extern int config_params_set(u32 tid, u64 sid, int type, u32 partial, struct iscsi_param *params); extern int config_initiator_access_allowed(u32 tid, int fd); extern int accounts_empty(u32 tid, int dir); extern struct iscsi_attr *account_get_first(u32 tid, int dir); extern struct iscsi_attr *account_lookup_by_sysfs_name(struct target *target, int dir, const char *sysfs_name); extern int account_replace(struct target *target, int direction, const char *sysfs_name, char *value); extern void accounts_free(struct __qelem *accounts_list); extern struct iscsi_attr *iscsi_attr_lookup_by_sysfs_name( struct __qelem *attrs_list, const char *sysfs_name); extern struct iscsi_attr *iscsi_attr_lookup_by_key( struct __qelem *attrs_list, const char *key); extern void iscsi_attrs_free(struct __qelem *attrs_list); extern int iscsi_attr_create(int attr_size, struct __qelem *attrs_list, const char *sysfs_name_tmpl, const char *key, const char *val, u32 mode, struct iscsi_attr **res_attr); extern void iscsi_attr_destroy(struct iscsi_attr *attr); extern int iscsi_attr_replace(struct __qelem *attrs_list, const char *sysfs_name, char *raw_value); /* isns.c */ extern char *isns_server; extern int isns_access_control; extern char isns_entity_target_name[ISCSI_NAME_LEN]; extern int isns_timeout; extern int isns_init(void); extern int isns_handle(int is_timeout); extern int isns_scn_handle(int accept); extern int isns_scn_access_allowed(u32 tid, char *name); extern int isns_target_register(char *name); extern int isns_target_deregister(char *name); extern void isns_exit(void); #endif /* ISCSID_H */