1 /* $OpenBSD: iscsid.h,v 1.19 2024/05/21 05:00:48 jsg 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 SESSION_TYPE_NORMAL 0 185 #define SESSION_TYPE_DISCOVERY 1 186 187 struct session_params { 188 u_int32_t MaxBurstLength; 189 /* 262144, 512-to-(2**24-1) (min()): LS */ 190 u_int32_t FirstBurstLength; 191 /* 65536, 512-to-(2**24-1) (min()): LS */ 192 u_int16_t DefaultTime2Wait; 193 /* 2, 0-to-3600 (max()): LS */ 194 u_int16_t DefaultTime2Retain; 195 /* 20, 0-to-3600 (min()): LS */ 196 u_int16_t MaxOutstandingR2T; 197 /* 1, 1-to-65535 (min()): LS */ 198 u_int16_t TargetPortalGroupTag; 199 /* 1- 65535: IS */ 200 u_int16_t MaxConnections; 201 /* 1, 1-65535 (min()): LS */ 202 u_int8_t InitialR2T; 203 /* yes, bool (||): LS */ 204 u_int8_t ImmediateData; 205 /* yes, bool (&&): LS */ 206 u_int8_t DataPDUInOrder; 207 /* yes, bool (||): LS */ 208 u_int8_t DataSequenceInOrder; 209 /* yes, bool (||): LS */ 210 u_int8_t ErrorRecoveryLevel; 211 /* 0, 0 - 2 (min()): LS */ 212 }; 213 214 struct connection_params { 215 u_int32_t MaxRecvDataSegmentLength; 216 /* 8192, 512-to-(2**24-1): C */ 217 /* inherited from session_config */ 218 u_int8_t HeaderDigest; 219 u_int8_t DataDigest; 220 }; 221 222 struct initiator { 223 struct session_head sessions; 224 struct initiator_config config; 225 u_int target; 226 }; 227 228 struct sessev { 229 struct session *sess; 230 struct connection *conn; 231 enum s_event event; 232 }; 233 234 struct session { 235 TAILQ_ENTRY(session) entry; 236 struct connection_head connections; 237 struct taskq tasks; 238 struct session_config config; 239 struct session_params mine; 240 struct session_params his; 241 struct session_params active; 242 struct initiator *initiator; 243 u_int32_t cmdseqnum; 244 u_int32_t itt; 245 u_int32_t isid_base; /* only 24 bits */ 246 u_int16_t isid_qual; /* inherited from initiator */ 247 u_int16_t tsih; /* target session id handle */ 248 u_int target; 249 int holdTimer; /* internal hold timer */ 250 int state; 251 int action; 252 }; 253 254 struct session_poll { 255 int session_count; 256 int session_init_count; 257 int session_running_count; 258 int conn_logged_in_count; 259 int conn_failed_count; 260 int conn_waiting_count; 261 int sess_conn_status; 262 }; 263 264 struct connection { 265 struct event ev; 266 struct event wev; 267 TAILQ_ENTRY(connection) entry; 268 struct connection_params mine; 269 struct connection_params his; 270 struct connection_params active; 271 struct connection_config config; 272 struct pdu_readbuf prbuf; 273 struct pduq pdu_w; 274 struct taskq tasks; 275 struct session *session; 276 u_int32_t expstatsn; 277 int state; 278 int fd; 279 u_int16_t cid; /* connection id */ 280 }; 281 282 struct task { 283 TAILQ_ENTRY(task) entry; 284 struct pduq sendq; 285 struct pduq recvq; 286 void *callarg; 287 void (*callback)(struct connection *, void *, struct pdu *); 288 void (*failback)(void *); 289 u_int32_t cmdseqnum; 290 u_int32_t itt; 291 u_int8_t pending; 292 }; 293 294 struct kvp { 295 char *key; 296 char *value; 297 long flags; 298 }; 299 #define KVP_KEY_ALLOCED 0x01 300 #define KVP_VALUE_ALLOCED 0x02 301 302 struct vscsi_stats { 303 u_int64_t bytes_rd; 304 u_int64_t bytes_wr; 305 u_int64_t cnt_read; 306 u_int64_t cnt_write; 307 u_int64_t cnt_i2t; 308 u_int64_t cnt_i2t_dir[3]; 309 u_int64_t cnt_t2i; 310 u_int64_t cnt_t2i_status[3]; 311 u_int32_t cnt_probe; 312 u_int32_t cnt_detach; 313 }; 314 315 extern const struct session_params iscsi_sess_defaults; 316 extern const struct connection_params iscsi_conn_defaults; 317 extern struct session_params initiator_sess_defaults; 318 extern struct connection_params initiator_conn_defaults; 319 320 void iscsid_ctrl_dispatch(void *, struct pdu *); 321 void iscsi_merge_sess_params(struct session_params *, 322 struct session_params *, struct session_params *); 323 void iscsi_merge_conn_params(struct connection_params *, 324 struct connection_params *, struct connection_params *); 325 326 struct initiator *initiator_init(void); 327 void initiator_cleanup(struct initiator *); 328 void initiator_shutdown(struct initiator *); 329 int initiator_isdown(struct initiator *); 330 struct session *initiator_t2s(u_int); 331 void initiator_login(struct connection *); 332 void initiator_discovery(struct session *); 333 void initiator_logout(struct session *, struct connection *, u_int8_t); 334 void initiator_nop_in_imm(struct connection *, struct pdu *); 335 char *default_initiator_name(void); 336 337 int control_init(char *); 338 void control_cleanup(char *); 339 void control_event_init(void); 340 void control_queue(void *, struct pdu *); 341 int control_compose(void *, u_int16_t, void *, size_t); 342 int control_build(void *, u_int16_t, int, struct ctrldata *); 343 344 struct session *session_find(struct initiator *, char *); 345 struct session *session_new(struct initiator *, u_int8_t); 346 void session_cleanup(struct session *); 347 int session_shutdown(struct session *); 348 void session_config(struct session *, struct session_config *); 349 void session_task_issue(struct session *, struct task *); 350 void session_logout_issue(struct session *, struct task *); 351 void session_schedule(struct session *); 352 void session_fsm(struct session *, enum s_event, struct connection *, 353 unsigned int); 354 355 void conn_new(struct session *, struct connection_config *); 356 void conn_free(struct connection *); 357 int conn_task_ready(struct connection *); 358 void conn_task_issue(struct connection *, struct task *); 359 void conn_task_schedule(struct connection *); 360 void conn_task_cleanup(struct connection *, struct task *); 361 int conn_parse_kvp(struct connection *, struct kvp *); 362 int conn_gen_kvp(struct connection *, struct kvp *, size_t *); 363 void conn_pdu_write(struct connection *, struct pdu *); 364 void conn_fail(struct connection *); 365 void conn_fsm(struct connection *, enum c_event); 366 367 void *pdu_gethdr(struct pdu *); 368 int text_to_pdu(struct kvp *, struct pdu *); 369 struct kvp *pdu_to_text(char *, size_t); 370 u_int64_t text_to_num(const char *, u_int64_t, u_int64_t, const char **); 371 int text_to_bool(const char *, const char **); 372 void pdu_free_queue(struct pduq *); 373 ssize_t pdu_read(struct connection *); 374 ssize_t pdu_write(struct connection *); 375 int pdu_pending(struct connection *); 376 void pdu_parse(struct connection *); 377 int pdu_readbuf_set(struct pdu_readbuf *, size_t); 378 void pdu_readbuf_free(struct pdu_readbuf *); 379 380 struct pdu *pdu_new(void); 381 void *pdu_alloc(size_t); 382 void *pdu_dup(void *, size_t); 383 int pdu_addbuf(struct pdu *, void *, size_t, unsigned int); 384 void *pdu_getbuf(struct pdu *, size_t *, unsigned int); 385 void pdu_free(struct pdu *); 386 int socket_setblockmode(int, int); 387 const char *log_sockaddr(void *); 388 389 void task_init(struct task *, struct session *, int, void *, 390 void (*)(struct connection *, void *, struct pdu *), 391 void (*)(void *)); 392 void taskq_cleanup(struct taskq *); 393 void task_pdu_add(struct task *, struct pdu *); 394 void task_pdu_cb(struct connection *, struct pdu *); 395 396 void vscsi_open(char *); 397 void vscsi_dispatch(int, short, void *); 398 void vscsi_data(unsigned long, int, void *, size_t); 399 void vscsi_status(int, int, void *, size_t); 400 void vscsi_event(unsigned long, u_int, u_int); 401 struct vscsi_stats *vscsi_stats(void); 402 403 /* Session polling */ 404 void poll_session(struct session_poll *, struct session *); 405 void poll_finalize(struct session_poll *); 406 407 /* logmsg.c */ 408 void log_hexdump(void *, size_t); 409 void log_pdu(struct pdu *, int); 410