1 /* $OpenBSD: iscsid.h,v 1.9 2011/05/04 21:00:04 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #define ISCSID_DEVICE "/dev/vscsi0" 20 #define ISCSID_CONTROL "/var/run/iscsid.sock" 21 #define ISCSID_CONFIG "/etc/iscsi.conf" 22 #define ISCSID_USER "_iscsid" 23 24 #define ISCSID_BASE_NAME "iqn.1995-11.org.openbsd.iscsid" 25 #define ISCSID_DEF_CONNS 8 26 27 #define PDU_READ_SIZE (256 * 1024) 28 #define CONTROL_READ_SIZE 8192 29 #define PDU_MAXIOV 5 30 #define PDU_WRIOV (PDU_MAXIOV * 8) 31 32 #define PDU_HEADER 0 33 #define PDU_AHS 1 34 #define PDU_HDIGEST 2 35 #define PDU_DATA 3 36 #define PDU_DDIGEST 4 37 38 #define PDU_LEN(x) ((((x) + 3) / 4) * 4) 39 40 /* 41 * Common control message header. 42 * A message can consist of up to 3 parts with specified length. 43 */ 44 struct ctrlmsghdr { 45 u_int16_t type; 46 u_int16_t len[3]; 47 }; 48 49 /* Control message types */ 50 #define CTRL_SUCCESS 1 51 #define CTRL_FAILURE 2 52 #define CTRL_INPROGRESS 3 53 #define CTRL_INITIATOR_CONFIG 4 54 #define CTRL_SESSION_CONFIG 5 55 #define CTRL_LOG_VERBOSE 6 56 57 58 TAILQ_HEAD(session_head, session); 59 TAILQ_HEAD(connection_head, connection); 60 TAILQ_HEAD(pduq, pdu); 61 TAILQ_HEAD(taskq, task); 62 63 /* as in tcp_seq.h */ 64 #define SEQ_LT(a,b) ((int)((a)-(b)) < 0) 65 #define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) 66 #define SEQ_GT(a,b) ((int)((a)-(b)) > 0) 67 #define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0) 68 69 #define SESS_INIT 0x0001 70 #define SESS_FREE 0x0002 71 #define SESS_LOGGED_IN 0x0004 72 #define SESS_FAILED 0x0008 73 #define SESS_DOWN 0x0010 74 #define SESS_ANYSTATE 0xffff 75 #define SESS_RUNNING (SESS_FREE | SESS_LOGGED_IN | SESS_FAILED) 76 77 #define CONN_FREE 0x0001 78 #define CONN_XPT_WAIT 0x0002 79 #define CONN_XPT_UP 0x0004 80 #define CONN_IN_LOGIN 0x0008 81 #define CONN_LOGGED_IN 0x0010 82 #define CONN_IN_LOGOUT 0x0020 83 #define CONN_LOGOUT_REQ 0x0040 84 #define CONN_CLEANUP_WAIT 0x0080 85 #define CONN_IN_CLEANUP 0x0100 86 #define CONN_ANYSTATE 0xffff 87 #define CONN_RUNNING (CONN_LOGGED_IN | CONN_LOGOUT_REQ) 88 #define CONN_FAILED (CONN_CLEANUP_WAIT | CONN_IN_CLEANUP) 89 #define CONN_NEVER_LOGGED_IN (CONN_FREE | CONN_XPT_WAIT | CONN_XPT_UP | \ 90 CONN_IN_LOGIN) 91 92 enum c_event { 93 CONN_EV_FAIL, 94 CONN_EV_FREE, 95 CONN_EV_CONNECT, 96 CONN_EV_CONNECTED, 97 CONN_EV_LOGGED_IN, 98 CONN_EV_LOGOUT, 99 CONN_EV_LOGGED_OUT, 100 CONN_EV_CLOSED 101 }; 102 103 enum s_event { 104 SESS_EV_START, 105 SESS_EV_CONN_LOGGED_IN, 106 SESS_EV_CONN_FAIL, 107 SESS_EV_CONN_CLOSED, 108 SESS_EV_CLOSED, 109 SESS_EV_FAIL 110 }; 111 112 #define SESS_ACT_UP 0 113 #define SESS_ACT_DOWN 1 114 115 struct pdu { 116 TAILQ_ENTRY(pdu) entry; 117 struct iovec iov[PDU_MAXIOV]; 118 size_t resid; 119 }; 120 121 struct pdu_readbuf { 122 char *buf; 123 size_t size; 124 size_t rpos; 125 size_t wpos; 126 struct pdu *wip; 127 }; 128 129 struct connection_config { 130 /* values inherited from session_config */ 131 struct sockaddr_storage TargetAddr; /* IP:port of target */ 132 struct sockaddr_storage LocalAddr; /* IP:port of target */ 133 }; 134 135 struct initiator_config { 136 u_int32_t isid_base; /* only 24 bits */ 137 u_int16_t isid_qual; 138 u_int16_t pad; 139 }; 140 141 struct session_config { 142 /* unique session ID */ 143 char SessionName[32]; 144 /* 145 * I = initialize only, L = leading only 146 * S = session wide, C = connection only 147 */ 148 struct connection_config connection; 149 150 char *TargetName; /* String: IS */ 151 152 char *InitiatorName; /* String: IS */ 153 154 u_int16_t MaxConnections; 155 /* 1, 1-65535 (min()): LS */ 156 u_int8_t HeaderDigest; 157 /* None , (None|CRC32): IC */ 158 u_int8_t DataDigest; 159 /* None , (None|CRC32): IC */ 160 u_int8_t SessionType; 161 /* Normal, (Discovery|Normal): LS */ 162 u_int8_t disabled; 163 }; 164 165 #define SESSION_TYPE_NORMAL 0 166 #define SESSION_TYPE_DISCOVERY 1 167 168 struct session_params { 169 u_int32_t MaxBurstLength; 170 /* 262144, 512-to-(2**24-1) (min()): LS */ 171 u_int32_t FirstBurstLength; 172 /* 65536, 512-to-(2**24-1) (min()): LS */ 173 u_int16_t DefaultTime2Wait; 174 /* 2, 0-to-3600 (max()): LS */ 175 u_int16_t DefaultTime2Retain; 176 /* 20, 0-to-3600 (min()): LS */ 177 u_int16_t MaxOutstandingR2T; 178 /* 1, 1-to-65535 (min()): LS */ 179 u_int16_t TargetPortalGroupTag; 180 /* 1- 65535: IS */ 181 u_int16_t MaxConnections; 182 /* 1, 1-65535 (min()): LS */ 183 u_int8_t InitialR2T; 184 /* yes, bool (||): LS */ 185 u_int8_t ImmediateData; 186 /* yes, bool (&&): LS */ 187 u_int8_t DataPDUInOrder; 188 /* yes, bool (||): LS */ 189 u_int8_t DataSequenceInOrder; 190 /* yes, bool (||): LS */ 191 u_int8_t ErrorRecoveryLevel; 192 /* 0, 0 - 2 (min()): LS */ 193 }; 194 195 struct connection_params { 196 u_int32_t MaxRecvDataSegmentLength; 197 /* 8192, 512-to-(2**24-1): C */ 198 /* inherited from session_config */ 199 u_int8_t HeaderDigest; 200 u_int8_t DataDigest; 201 }; 202 203 struct initiator { 204 struct session_head sessions; 205 struct initiator_config config; 206 u_int target; 207 }; 208 209 struct sessev { 210 SIMPLEQ_ENTRY(sessev) entry; 211 struct connection *conn; 212 enum s_event event; 213 }; 214 215 struct session { 216 TAILQ_ENTRY(session) entry; 217 struct connection_head connections; 218 struct taskq tasks; 219 struct session_config config; 220 struct session_params mine; 221 struct session_params his; 222 struct session_params active; 223 struct initiator *initiator; 224 struct event fsm_ev; 225 SIMPLEQ_HEAD(, sessev) fsmq; 226 u_int32_t cmdseqnum; 227 u_int32_t itt; 228 u_int32_t isid_base; /* only 24 bits */ 229 u_int16_t isid_qual; /* inherited from initiator */ 230 u_int16_t tsih; /* target session id handle */ 231 u_int target; 232 int state; 233 int action; 234 }; 235 236 struct connection { 237 struct event ev; 238 struct event wev; 239 TAILQ_ENTRY(connection) entry; 240 struct connection_params mine; 241 struct connection_params his; 242 struct connection_params active; 243 struct connection_config config; 244 struct pdu_readbuf prbuf; 245 struct pduq pdu_w; 246 struct taskq tasks; 247 struct session *session; 248 u_int32_t expstatsn; 249 int state; 250 int fd; 251 u_int16_t cid; /* conection id */ 252 }; 253 254 struct task { 255 TAILQ_ENTRY(task) entry; 256 struct pduq sendq; 257 struct pduq recvq; 258 void *callarg; 259 void (*callback)(struct connection *, void *, struct pdu *); 260 void (*failback)(void *); 261 u_int32_t cmdseqnum; 262 u_int32_t itt; 263 u_int8_t pending; 264 }; 265 266 struct kvp { 267 char *key; 268 char *value; 269 long flags; 270 }; 271 #define KVP_KEY_ALLOCED 0x01 272 #define KVP_VALUE_ALLOCED 0x02 273 274 extern const struct session_params iscsi_sess_defaults; 275 extern const struct connection_params iscsi_conn_defaults; 276 extern struct session_params initiator_sess_defaults; 277 extern struct connection_params initiator_conn_defaults; 278 279 void iscsid_ctrl_dispatch(void *, struct pdu *); 280 void iscsi_merge_sess_params(struct session_params *, 281 struct session_params *, struct session_params *); 282 void iscsi_merge_conn_params(struct connection_params *, 283 struct connection_params *, struct connection_params *); 284 285 struct initiator *initiator_init(void); 286 void initiator_cleanup(struct initiator *); 287 void initiator_shutdown(struct initiator *); 288 int initiator_isdown(struct initiator *); 289 struct session *initiator_t2s(u_int); 290 void initiator_login(struct connection *); 291 void initiator_discovery(struct session *); 292 void initiator_logout(struct session *, struct connection *, u_int8_t); 293 void initiator_nop_in_imm(struct connection *, struct pdu *); 294 char *default_initiator_name(void); 295 296 int control_init(char *); 297 void control_cleanup(char *); 298 int control_listen(void); 299 int control_queue(void *, struct pdu *); 300 int control_compose(void *, u_int16_t, void *, size_t); 301 302 struct session *session_find(struct initiator *, char *); 303 struct session *session_new(struct initiator *, u_int8_t); 304 void session_cleanup(struct session *); 305 int session_shutdown(struct session *); 306 void session_config(struct session *, struct session_config *); 307 void session_task_issue(struct session *, struct task *); 308 void session_logout_issue(struct session *, struct task *); 309 void session_schedule(struct session *); 310 void session_task_login(struct connection *); 311 void session_fsm(struct session *, enum s_event, struct connection *); 312 313 void conn_new(struct session *, struct connection_config *); 314 void conn_free(struct connection *); 315 int conn_task_ready(struct connection *); 316 void conn_task_issue(struct connection *, struct task *); 317 void conn_task_schedule(struct connection *); 318 void conn_task_cleanup(struct connection *, struct task *); 319 int conn_parse_kvp(struct connection *, struct kvp *); 320 int conn_gen_kvp(struct connection *, struct kvp *, size_t *); 321 void conn_pdu_write(struct connection *, struct pdu *); 322 void conn_fail(struct connection *); 323 void conn_fsm(struct connection *, enum c_event); 324 325 void *pdu_gethdr(struct pdu *); 326 int text_to_pdu(struct kvp *, struct pdu *); 327 struct kvp *pdu_to_text(char *, size_t); 328 u_int64_t text_to_num(const char *, u_int64_t, u_int64_t, const char **); 329 int text_to_bool(const char *, const char **); 330 void pdu_free_queue(struct pduq *); 331 ssize_t pdu_read(struct connection *); 332 ssize_t pdu_write(struct connection *); 333 int pdu_pending(struct connection *); 334 void pdu_parse(struct connection *); 335 int pdu_readbuf_set(struct pdu_readbuf *, size_t); 336 void pdu_readbuf_free(struct pdu_readbuf *); 337 338 struct pdu *pdu_new(void); 339 void *pdu_alloc(size_t); 340 void *pdu_dup(void *, size_t); 341 int pdu_addbuf(struct pdu *, void *, size_t, unsigned int); 342 void *pdu_getbuf(struct pdu *, size_t *, unsigned int); 343 void pdu_free(struct pdu *); 344 int socket_setblockmode(int, int); 345 const char *log_sockaddr(void *); 346 347 void task_init(struct task *, struct session *, int, void *, 348 void (*)(struct connection *, void *, struct pdu *), 349 void (*)(void *)); 350 void taskq_cleanup(struct taskq *); 351 void task_pdu_add(struct task *, struct pdu *); 352 void task_pdu_cb(struct connection *, struct pdu *); 353 354 void vscsi_open(char *); 355 void vscsi_dispatch(int, short, void *); 356 void vscsi_data(unsigned long, int, void *, size_t); 357 void vscsi_status(int, int, void *, size_t); 358 void vscsi_event(unsigned long, u_int, u_int); 359