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