1 /* $OpenBSD: iscsid.h,v 1.24 2025/01/28 20:41:44 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 #define ISCSID_HOLD_TIME_MAX 128 27 28 #define PDU_READ_SIZE (256 * 1024) 29 #define CONTROL_READ_SIZE 8192 30 #define PDU_MAXIOV 5 31 #define PDU_WRIOV (PDU_MAXIOV * 8) 32 33 #define PDU_HEADER 0 34 #define PDU_AHS 1 35 #define PDU_HDIGEST 2 36 #define PDU_DATA 3 37 #define PDU_DDIGEST 4 38 39 #define PDU_LEN(x) ((((x) + 3) / 4) * 4) 40 41 #ifndef nitems 42 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 43 #endif 44 45 /* 46 * Common control message header. 47 * A message can consist of up to 3 parts with specified length. 48 */ 49 struct ctrlmsghdr { 50 u_int16_t type; 51 u_int16_t len[3]; 52 }; 53 54 struct ctrldata { 55 void *buf; 56 size_t len; 57 }; 58 59 #define CTRLARGV(x...) ((struct ctrldata []){ x }) 60 61 /* Control message types */ 62 #define CTRL_SUCCESS 1 63 #define CTRL_FAILURE 2 64 #define CTRL_INPROGRESS 3 65 #define CTRL_INITIATOR_CONFIG 4 66 #define CTRL_SESSION_CONFIG 5 67 #define CTRL_LOG_VERBOSE 6 68 #define CTRL_VSCSI_STATS 7 69 #define CTRL_SHOW_SUM 8 70 #define CTRL_SESS_POLL 9 71 72 TAILQ_HEAD(session_head, session); 73 TAILQ_HEAD(connection_head, connection); 74 TAILQ_HEAD(pduq, pdu); 75 TAILQ_HEAD(taskq, task); 76 77 /* as in tcp_seq.h */ 78 #define SEQ_LT(a,b) ((int)((a)-(b)) < 0) 79 #define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) 80 #define SEQ_GT(a,b) ((int)((a)-(b)) > 0) 81 #define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0) 82 83 #define SESS_INIT 0x0001 84 #define SESS_FREE 0x0002 85 #define SESS_LOGGED_IN 0x0004 86 #define SESS_FAILED 0x0008 87 #define SESS_ANYSTATE 0xffff 88 #define SESS_RUNNING (SESS_FREE | SESS_LOGGED_IN | SESS_FAILED) 89 90 #define CONN_FREE 0x0001 /* S1 = R3 */ 91 #define CONN_XPT_WAIT 0x0002 /* S2 */ 92 #define CONN_XPT_UP 0x0004 /* S3 */ 93 #define CONN_IN_LOGIN 0x0008 /* S4 */ 94 #define CONN_LOGGED_IN 0x0010 /* S5 */ 95 #define CONN_IN_LOGOUT 0x0020 /* S6 */ 96 #define CONN_LOGOUT_REQ 0x0040 /* S7 */ 97 #define CONN_CLEANUP_WAIT 0x0080 /* S8 = R1 */ 98 #define CONN_IN_CLEANUP 0x0100 /* R2 */ 99 #define CONN_ANYSTATE 0xffff 100 #define CONN_RUNNING (CONN_LOGGED_IN | CONN_LOGOUT_REQ) 101 #define CONN_FAILED (CONN_CLEANUP_WAIT | CONN_IN_CLEANUP) 102 #define CONN_NEVER_LOGGED_IN (CONN_FREE | CONN_XPT_WAIT | CONN_XPT_UP | \ 103 CONN_IN_LOGIN) 104 105 enum c_event { 106 CONN_EV_FAIL, 107 CONN_EV_FREE, 108 CONN_EV_CONNECT, 109 CONN_EV_CONNECTED, 110 CONN_EV_LOGGED_IN, 111 CONN_EV_REQ_LOGOUT, 112 CONN_EV_LOGOUT, 113 CONN_EV_LOGGED_OUT, 114 CONN_EV_CLOSED, 115 CONN_EV_CLEANING_UP 116 }; 117 118 enum s_event { 119 SESS_EV_START, 120 SESS_EV_STOP, 121 SESS_EV_CONN_LOGGED_IN, 122 SESS_EV_CONN_FAIL, 123 SESS_EV_CONN_CLOSED, 124 SESS_EV_REINSTATEMENT, 125 SESS_EV_TIMEOUT, 126 SESS_EV_CLOSED, 127 SESS_EV_FAIL, 128 SESS_EV_FREE 129 }; 130 131 #define SESS_ACT_UP 0 132 #define SESS_ACT_DOWN 1 133 134 struct pdu { 135 TAILQ_ENTRY(pdu) entry; 136 struct iovec iov[PDU_MAXIOV]; 137 size_t resid; 138 }; 139 140 struct pdu_readbuf { 141 char *buf; 142 size_t size; 143 size_t rpos; 144 size_t wpos; 145 struct pdu *wip; 146 }; 147 148 struct connection_config { 149 /* values inherited from session_config */ 150 struct sockaddr_storage TargetAddr; /* IP:port of target */ 151 struct sockaddr_storage LocalAddr; /* IP:port of target */ 152 }; 153 154 struct initiator_config { 155 u_int32_t isid_base; /* only 24 bits */ 156 u_int16_t isid_qual; 157 u_int16_t pad; 158 }; 159 160 struct session_config { 161 /* unique session ID */ 162 char SessionName[32]; 163 /* 164 * I = initialize only, L = leading only 165 * S = session wide, C = connection only 166 */ 167 struct connection_config connection; 168 169 char *TargetName; /* String: IS */ 170 171 char *InitiatorName; /* String: IS */ 172 173 u_int16_t MaxConnections; 174 /* 1, 1-65535 (min()): LS */ 175 u_int8_t HeaderDigest; 176 /* None , (None|CRC32): IC */ 177 u_int8_t DataDigest; 178 /* None , (None|CRC32): IC */ 179 u_int8_t SessionType; 180 /* Normal, (Discovery|Normal): LS */ 181 u_int8_t disabled; 182 }; 183 184 #define DIGEST_NONE 0x1 185 #define DIGEST_CRC32C 0x2 186 187 #define SESSION_TYPE_NORMAL 0 188 #define SESSION_TYPE_DISCOVERY 1 189 190 struct session_params { 191 u_int32_t MaxBurstLength; 192 /* 262144, 512-to-(2**24-1) (min()): LS */ 193 u_int32_t FirstBurstLength; 194 /* 65536, 512-to-(2**24-1) (min()): LS */ 195 u_int16_t DefaultTime2Wait; 196 /* 2, 0-to-3600 (max()): LS */ 197 u_int16_t DefaultTime2Retain; 198 /* 20, 0-to-3600 (min()): LS */ 199 u_int16_t MaxOutstandingR2T; 200 /* 1, 1-to-65535 (min()): LS */ 201 u_int16_t TargetPortalGroupTag; 202 /* 1- 65535: IS */ 203 u_int16_t MaxConnections; 204 /* 1, 1-65535 (min()): LS */ 205 u_int8_t InitialR2T; 206 /* yes, bool (||): LS */ 207 u_int8_t ImmediateData; 208 /* yes, bool (&&): LS */ 209 u_int8_t DataPDUInOrder; 210 /* yes, bool (||): LS */ 211 u_int8_t DataSequenceInOrder; 212 /* yes, bool (||): LS */ 213 u_int8_t ErrorRecoveryLevel; 214 /* 0, 0 - 2 (min()): LS */ 215 }; 216 217 struct connection_params { 218 u_int32_t MaxRecvDataSegmentLength; 219 /* 8192, 512-to-(2**24-1): C */ 220 /* inherited from session_config */ 221 u_int8_t HeaderDigest; 222 u_int8_t DataDigest; 223 }; 224 225 struct initiator { 226 struct session_head sessions; 227 struct initiator_config config; 228 u_int target; 229 }; 230 231 struct sessev { 232 struct event ev; 233 struct session *sess; 234 struct connection *conn; 235 enum s_event event; 236 }; 237 238 struct session { 239 TAILQ_ENTRY(session) entry; 240 struct sessev sev; 241 struct connection_head connections; 242 struct taskq tasks; 243 struct session_config config; 244 struct session_params mine; 245 struct session_params his; 246 struct session_params active; 247 u_int32_t cmdseqnum; 248 u_int32_t itt; 249 u_int32_t isid_base; /* only 24 bits */ 250 u_int16_t isid_qual; /* inherited from initiator */ 251 u_int16_t tsih; /* target session id handle */ 252 u_int target; 253 int holdTimer; /* internal hold timer */ 254 int state; 255 int action; 256 }; 257 258 struct session_poll { 259 int session_count; 260 int session_init_count; 261 int session_running_count; 262 int conn_logged_in_count; 263 int conn_failed_count; 264 int conn_waiting_count; 265 int sess_conn_status; 266 }; 267 268 struct connection { 269 struct event ev; 270 struct event wev; 271 struct sessev sev; 272 TAILQ_ENTRY(connection) entry; 273 struct connection_params mine; 274 struct connection_params his; 275 struct connection_params active; 276 struct connection_config config; 277 struct pdu_readbuf prbuf; 278 struct pduq pdu_w; 279 struct taskq tasks; 280 struct session *session; 281 u_int32_t expstatsn; 282 int state; 283 int fd; 284 u_int16_t cid; /* connection id */ 285 }; 286 287 struct task { 288 TAILQ_ENTRY(task) entry; 289 struct pduq sendq; 290 struct pduq recvq; 291 void *callarg; 292 void (*callback)(struct connection *, void *, struct pdu *); 293 void (*failback)(void *); 294 u_int32_t cmdseqnum; 295 u_int32_t itt; 296 u_int8_t pending; 297 }; 298 299 struct kvp { 300 char *key; 301 char *value; 302 long flags; 303 }; 304 #define KVP_KEY_ALLOCED 0x01 305 #define KVP_VALUE_ALLOCED 0x02 306 307 struct vscsi_stats { 308 u_int64_t bytes_rd; 309 u_int64_t bytes_wr; 310 u_int64_t cnt_read; 311 u_int64_t cnt_write; 312 u_int64_t cnt_i2t; 313 u_int64_t cnt_i2t_dir[3]; 314 u_int64_t cnt_t2i; 315 u_int64_t cnt_t2i_status[3]; 316 u_int32_t cnt_probe; 317 u_int32_t cnt_detach; 318 }; 319 320 extern const struct session_params iscsi_sess_defaults; 321 extern const struct connection_params iscsi_conn_defaults; 322 extern struct session_params initiator_sess_defaults; 323 extern struct connection_params initiator_conn_defaults; 324 325 void iscsid_ctrl_dispatch(void *, struct pdu *); 326 void iscsi_merge_sess_params(struct session_params *, 327 struct session_params *, struct session_params *); 328 void iscsi_merge_conn_params(struct connection_params *, 329 struct connection_params *, struct connection_params *); 330 331 void initiator_init(void); 332 void initiator_cleanup(void); 333 void initiator_set_config(struct initiator_config *); 334 struct initiator_config *initiator_get_config(void); 335 void initiator_shutdown(void); 336 int initiator_isdown(void); 337 struct session *initiator_new_session(u_int8_t); 338 struct session *initiator_find_session(char *); 339 struct session *initiator_t2s(u_int); 340 struct session_head *initiator_get_sessions(void); 341 void initiator_login(struct connection *); 342 void initiator_discovery(struct session *); 343 void initiator_logout(struct session *, struct connection *, u_int8_t); 344 void initiator_nop_in_imm(struct connection *, struct pdu *); 345 char *default_initiator_name(void); 346 347 int control_init(char *); 348 void control_cleanup(char *); 349 void control_event_init(void); 350 void control_queue(void *, struct pdu *); 351 int control_compose(void *, u_int16_t, void *, size_t); 352 int control_build(void *, u_int16_t, int, struct ctrldata *); 353 354 void session_cleanup(struct session *); 355 int session_shutdown(struct session *); 356 void session_config(struct session *, struct session_config *); 357 void session_task_issue(struct session *, struct task *); 358 void session_logout_issue(struct session *, struct task *); 359 void session_schedule(struct session *); 360 void session_fsm(struct sessev *, enum s_event, unsigned int); 361 void session_fsm_callback(int, short, void *); 362 363 void conn_new(struct session *, struct connection_config *); 364 void conn_free(struct connection *); 365 int conn_task_ready(struct connection *); 366 void conn_task_issue(struct connection *, struct task *); 367 void conn_task_schedule(struct connection *); 368 void conn_task_cleanup(struct connection *, struct task *); 369 int conn_parse_kvp(struct connection *, struct kvp *); 370 int kvp_set_from_mine(struct kvp *, const char *, struct connection *); 371 void conn_pdu_write(struct connection *, struct pdu *); 372 void conn_fail(struct connection *); 373 void conn_fsm(struct connection *, enum c_event); 374 375 void *pdu_gethdr(struct pdu *); 376 int text_to_pdu(struct kvp *, struct pdu *); 377 struct kvp *pdu_to_text(char *, size_t); 378 u_int64_t text_to_num(const char *, u_int64_t, u_int64_t, const char **); 379 int text_to_bool(const char *, const char **); 380 int text_to_digest(const char *, const char **); 381 void pdu_free_queue(struct pduq *); 382 ssize_t pdu_read(struct connection *); 383 ssize_t pdu_write(struct connection *); 384 int pdu_pending(struct connection *); 385 void pdu_parse(struct connection *); 386 int pdu_readbuf_set(struct pdu_readbuf *, size_t); 387 void pdu_readbuf_free(struct pdu_readbuf *); 388 389 struct pdu *pdu_new(void); 390 void *pdu_alloc(size_t); 391 void *pdu_dup(void *, size_t); 392 int pdu_addbuf(struct pdu *, void *, size_t, unsigned int); 393 void *pdu_getbuf(struct pdu *, size_t *, unsigned int); 394 void pdu_free(struct pdu *); 395 int socket_setblockmode(int, int); 396 const char *log_sockaddr(void *); 397 void kvp_free(struct kvp *); 398 399 void task_init(struct task *, struct session *, int, void *, 400 void (*)(struct connection *, void *, struct pdu *), 401 void (*)(void *)); 402 void taskq_cleanup(struct taskq *); 403 void task_pdu_add(struct task *, struct pdu *); 404 void task_pdu_cb(struct connection *, struct pdu *); 405 406 void vscsi_open(char *); 407 void vscsi_dispatch(int, short, void *); 408 void vscsi_data(unsigned long, int, void *, size_t); 409 void vscsi_status(int, int, void *, size_t); 410 void vscsi_event(unsigned long, u_int, u_int); 411 struct vscsi_stats *vscsi_stats(void); 412 413 /* Session polling */ 414 void poll_session(struct session_poll *, struct session *); 415 void poll_finalize(struct session_poll *); 416 417 /* logmsg.c */ 418 void log_hexdump(void *, size_t); 419 void log_pdu(struct pdu *, int); 420