1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * This file contains methods to handle the iSCSI Full Feature Phase aspects 29 * of the protocol. 30 */ 31 32 #include <unistd.h> 33 #include <poll.h> 34 #include <strings.h> 35 #include <stdlib.h> 36 #include <sys/types.h> 37 #include <assert.h> 38 #include <stdio.h> 39 #include <errno.h> 40 #include <utility.h> 41 #include <netinet/in.h> 42 #include <inttypes.h> 43 #include <sys/socket.h> 44 #include <sys/iscsi_protocol.h> 45 46 #include <arpa/inet.h> 47 48 #include "iscsi_ffp.h" 49 #include "iscsi_cmd.h" 50 #include "t10_spc.h" 51 #include "utility.h" 52 #include "iscsi_provider_impl.h" 53 54 static Boolean_t handle_text_msg(iscsi_conn_t *, iscsi_hdr_t *, char *, int); 55 static Boolean_t handle_logout_msg(iscsi_conn_t *, iscsi_hdr_t *, char *, int); 56 static Boolean_t handle_scsi_cmd(iscsi_conn_t *, iscsi_hdr_t *, char *, int); 57 static Boolean_t handle_noop_cmd(iscsi_conn_t *, iscsi_hdr_t *, char *, int); 58 static Boolean_t handle_scsi_data(iscsi_conn_t *, iscsi_hdr_t *, char *, int); 59 static Boolean_t handle_task_mgt(iscsi_conn_t *, iscsi_hdr_t *, char *, int); 60 static Boolean_t dataout_delayed(iscsi_cmd_t *cmd, msg_type_t type); 61 void dataout_callback(t10_cmd_t *t, char *data, size_t *xfer); 62 63 Boolean_t 64 iscsi_full_feature(iscsi_conn_t *c) 65 { 66 iscsi_hdr_t h; 67 Boolean_t rval = False; 68 char debug[128]; 69 char *ahs = NULL; 70 int cc; 71 int ahslen; 72 73 if ((cc = recv(c->c_fd, &h, sizeof (h), MSG_WAITALL)) != sizeof (h)) { 74 if (errno == ECONNRESET) { 75 (void) snprintf(debug, sizeof (debug), 76 "CON%x full_feature -- initiator reset socket\n", 77 c->c_num); 78 } else { 79 (void) snprintf(debug, sizeof (debug), 80 "CON%x full_feature(got-%d, expect-%d), errno=%d\n", 81 c->c_num, cc, sizeof (h), errno); 82 } 83 queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug); 84 conn_state(c, T8); 85 return (False); 86 } 87 88 /* 89 * Look to see if there's an Additional Header Segment available. 90 * If so, read it in. 91 */ 92 if ((ahslen = (h.hlength * sizeof (uint32_t))) != 0) { 93 if ((ahs = malloc(ahslen)) == NULL) 94 return (False); 95 if (recv(c->c_fd, ahs, ahslen, MSG_WAITALL) != ahslen) { 96 (void) snprintf(debug, sizeof (debug), 97 "CON%x Failed to read in AHS", c->c_num); 98 queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug); 99 free(ahs); 100 return (False); 101 } 102 } 103 104 (void) pthread_mutex_lock(&c->c_state_mutex); 105 if (c->c_state != S5_LOGGED_IN && c->c_state != S7_LOGOUT_REQUESTED) { 106 (void) snprintf(debug, sizeof (debug), 107 "CON%x full_feature -- not in S5_LOGGED_IN state\n", 108 c->c_num); 109 queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug); 110 if (ahs != NULL) 111 free(ahs); 112 (void) pthread_mutex_unlock(&c->c_state_mutex); 113 return (False); 114 } 115 (void) pthread_mutex_unlock(&c->c_state_mutex); 116 117 if (c->c_header_digest == True) { 118 uint32_t crc_actual; 119 uint32_t crc_calculated; 120 121 (void) recv(c->c_fd, (char *)&crc_actual, 122 sizeof (crc_actual), MSG_WAITALL); 123 crc_calculated = iscsi_crc32c((void *)&h, sizeof (h)); 124 if (ahslen) 125 crc_calculated = iscsi_crc32c_continued(ahs, 126 ahslen, crc_calculated); 127 if (crc_actual != crc_calculated) { 128 (void) snprintf(debug, sizeof (debug), 129 "CON%x CRC error: actual 0x%x v. calc 0x%x", 130 c->c_num, crc_actual, crc_calculated); 131 queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug); 132 if (ahs != NULL) 133 free(ahs); 134 return (False); 135 } 136 } 137 138 if (c->c_sess->s_type == SessionDiscovery) { 139 switch (h.opcode & ISCSI_OPCODE_MASK) { 140 default: 141 /* 142 * Need to handle the error case here. 143 */ 144 (void) snprintf(debug, sizeof (debug), 145 "CON%x Wrong opcode for Discovery, %d", 146 c->c_num, h.opcode & ISCSI_OPCODE_MASK); 147 queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug); 148 rval = False; 149 break; 150 151 case ISCSI_OP_LOGOUT_CMD: 152 /* 153 * This will transition from S5_LOGGED_IN 154 * to S6_IN_LOGOUT to S1_FREE; 155 */ 156 rval = handle_logout_msg(c, &h, ahs, ahslen); 157 break; 158 159 case ISCSI_OP_TEXT_CMD: 160 rval = handle_text_msg(c, &h, ahs, ahslen); 161 break; 162 } 163 } else { 164 iscsi_cmd_remove(c, ntohl(h.expstatsn)); 165 switch (h.opcode & ISCSI_OPCODE_MASK) { 166 case ISCSI_OP_NOOP_OUT: 167 rval = handle_noop_cmd(c, &h, ahs, ahslen); 168 break; 169 170 case ISCSI_OP_SCSI_CMD: 171 rval = handle_scsi_cmd(c, &h, ahs, ahslen); 172 break; 173 174 case ISCSI_OP_SCSI_TASK_MGT_MSG: 175 rval = handle_task_mgt(c, &h, ahs, ahslen); 176 break; 177 178 case ISCSI_OP_LOGIN_CMD: 179 /* 180 * This is an illegal state transition. Should 181 * we drop the connection? 182 */ 183 break; 184 185 case ISCSI_OP_TEXT_CMD: 186 rval = handle_text_msg(c, &h, ahs, ahslen); 187 break; 188 189 case ISCSI_OP_SCSI_DATA: 190 rval = handle_scsi_data(c, &h, ahs, ahslen); 191 break; 192 193 case ISCSI_OP_LOGOUT_CMD: 194 /* 195 * This will transition from S5_LOGGED_IN 196 * to S6_IN_LOGOUT. 197 */ 198 rval = handle_logout_msg(c, &h, ahs, ahslen); 199 break; 200 201 case ISCSI_OP_SNACK_CMD: 202 default: 203 (void) snprintf(debug, sizeof (debug), 204 "CON%x Opcode: %d not handled", 205 c->c_num, h.opcode & ISCSI_OPCODE_MASK); 206 queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, debug); 207 conn_state(c, T8); 208 rval = True; 209 break; 210 } 211 } 212 213 if (ahs != NULL) 214 free(ahs); 215 return (rval); 216 } 217 218 /*ARGSUSED*/ 219 static Boolean_t 220 handle_task_mgt(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen) 221 { 222 iscsi_scsi_task_mgt_hdr_t *hp = (iscsi_scsi_task_mgt_hdr_t *)p; 223 iscsi_scsi_task_mgt_rsp_hdr_t *rsp; 224 iscsi_cmd_t *cmd; 225 uint32_t lun; 226 Boolean_t lu_reset = False; 227 228 if (spc_decode_lu_addr(&hp->lun[0], 8, &lun) == False) 229 return (False); 230 231 if (ISCSI_TASK_COMMAND_ENABLED()) { 232 uiscsiproto_t info; 233 234 info.uip_target_addr = &c->c_target_sockaddr; 235 info.uip_initiator_addr = &c->c_initiator_sockaddr; 236 237 info.uip_target = c->c_sess->s_t_name; 238 info.uip_initiator = c->c_sess->s_i_name; 239 info.uip_lun = lun; 240 241 info.uip_itt = hp->itt; 242 info.uip_ttt = hp->itt; 243 244 info.uip_cmdsn = ntohl(hp->cmdsn); 245 info.uip_statsn = ntohl(hp->expstatsn); 246 info.uip_datasn = ntohl(hp->expdatasn); 247 248 info.uip_datalen = ntoh24(hp->dlength); 249 info.uip_flags = 0; 250 251 ISCSI_TASK_COMMAND(&info); 252 } 253 254 if ((rsp = calloc(1, sizeof (*rsp))) == NULL) 255 return (False); 256 257 rsp->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP; 258 rsp->flags = ISCSI_FLAG_FINAL; 259 rsp->itt = hp->itt; 260 261 (void) pthread_mutex_lock(&c->c_mutex); 262 rsp->statsn = htonl(c->c_statsn++); 263 (void) pthread_mutex_unlock(&c->c_mutex); 264 265 (void) pthread_mutex_lock(&c->c_sess->s_mutex); 266 if (ntohl(hp->cmdsn) > c->c_sess->s_seencmdsn) 267 c->c_sess->s_seencmdsn = ntohl(hp->cmdsn); 268 (void) pthread_mutex_unlock(&c->c_sess->s_mutex); 269 270 queue_prt(c->c_mgmtq, Q_CONN_NONIO, 271 "CON%x PDU(Task Mgt): %s, cmdsn 0x%x\n", 272 c->c_num, 273 task_to_str(hp->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK), 274 ntohl(hp->cmdsn)); 275 276 switch (hp->function & ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK) { 277 case ISCSI_TM_FUNC_ABORT_TASK: 278 queue_prt(c->c_mgmtq, Q_CONN_NONIO, 279 "CON%x Abort ITT 0x%x\n", c->c_num, hp->rtt); 280 if ((cmd = iscsi_cmd_find(c, hp->rtt, FindITT)) == NULL) { 281 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 282 "CON%x Invalid AbortTask rtt 0x%x\n", 283 c->c_num, hp->rtt); 284 rsp->response = SCSI_TCP_TM_RESP_NO_TASK; 285 } else { 286 (void) pthread_mutex_lock(&c->c_mutex); 287 iscsi_cmd_cancel(c, cmd); 288 (void) pthread_mutex_unlock(&c->c_mutex); 289 rsp->response = SCSI_TCP_TM_RESP_COMPLETE; 290 } 291 break; 292 293 case ISCSI_TM_FUNC_ABORT_TASK_SET: 294 /* ---- This is actually "Function not support" ---- */ 295 rsp->response = SCSI_TCP_TM_RESP_IN_PRGRESS; 296 break; 297 298 case ISCSI_TM_FUNC_CLEAR_ACA: 299 /* ---- This is actually "Function not support" ---- */ 300 rsp->response = SCSI_TCP_TM_RESP_IN_PRGRESS; 301 break; 302 303 case ISCSI_TM_FUNC_CLEAR_TASK_SET: 304 /* ---- This is actually "Function not support" ---- */ 305 rsp->response = SCSI_TCP_TM_RESP_IN_PRGRESS; 306 break; 307 308 case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET: 309 lu_reset = True; 310 /*FALLTHRU*/ 311 case ISCSI_TM_FUNC_TARGET_WARM_RESET: 312 (void) pthread_mutex_lock(&c->c_mutex); 313 for (cmd = c->c_cmd_head; cmd; cmd = cmd->c_next) { 314 if (((hp->function & 315 ISCSI_FLAG_TASK_MGMT_FUNCTION_MASK) == 316 ISCSI_TM_FUNC_TARGET_WARM_RESET) || 317 (lun == cmd->c_lun)) { 318 iscsi_cmd_cancel(c, cmd); 319 320 } 321 } 322 (void) pthread_mutex_unlock(&c->c_mutex); 323 324 if (lu_reset == True) 325 queue_message_set(c->c_sessq, 0, msg_reset_lu, 326 (void *)(uintptr_t)lun); 327 else 328 queue_message_set(c->c_sessq, 0, msg_reset_targ, 0); 329 rsp->response = SCSI_TCP_TM_RESP_COMPLETE; 330 break; 331 332 case ISCSI_TM_FUNC_TARGET_COLD_RESET: 333 /* 334 * According to the specification a cold reset should 335 * close *all* connections on the target, not just those 336 * for this current session. 337 */ 338 queue_message_set(c->c_sessq, 0, msg_reset_targ, (void *)1); 339 conn_state(c, T8); 340 break; 341 342 case ISCSI_TM_FUNC_TASK_REASSIGN: 343 default: 344 /* ---- This is actually "Function not support" ---- */ 345 rsp->response = SCSI_TCP_TM_RESP_IN_PRGRESS; 346 break; 347 } 348 349 (void) pthread_mutex_lock(&c->c_state_mutex); 350 if (c->c_state == S5_LOGGED_IN) 351 queue_message_set(c->c_dataq, 352 hp->opcode & ISCSI_OP_IMMEDIATE ? Q_HIGH : 0, 353 msg_send_pkt, rsp); 354 (void) pthread_mutex_unlock(&c->c_state_mutex); 355 return (True); 356 } 357 358 /*ARGSUSED*/ 359 static Boolean_t 360 handle_noop_cmd(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen) 361 { 362 iscsi_nop_out_hdr_t *hp = (iscsi_nop_out_hdr_t *)p; 363 iscsi_nop_in_hdr_t *in; 364 365 if (ISCSI_NOP_RECEIVE_ENABLED()) { 366 uiscsiproto_t info; 367 368 info.uip_target_addr = &c->c_target_sockaddr; 369 info.uip_initiator_addr = &c->c_initiator_sockaddr; 370 371 info.uip_target = c->c_sess->s_t_name; 372 info.uip_initiator = c->c_sess->s_i_name; 373 info.uip_lun = 0; 374 375 info.uip_itt = hp->itt; 376 info.uip_ttt = hp->ttt; 377 378 info.uip_cmdsn = ntohl(hp->cmdsn); 379 info.uip_statsn = ntohl(hp->expstatsn); 380 info.uip_datasn = 0; 381 382 info.uip_datalen = ntoh24(hp->dlength); 383 info.uip_flags = hp->flags; 384 385 ISCSI_NOP_RECEIVE(&info); 386 } 387 388 /* 389 * Just an answer to our ping 390 */ 391 if (hp->ttt != ISCSI_RSVD_TASK_TAG) 392 return (True); 393 394 if ((in = calloc(1, sizeof (*in))) == NULL) { 395 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 396 "CON%x NopIn -- failed to malloc space for header", 397 c->c_num); 398 return (False); 399 } 400 401 in->opcode = ISCSI_OP_NOOP_IN; 402 in->flags = ISCSI_FLAG_FINAL; 403 /* 404 * Need to handle possible data associated with NOP-Out 405 */ 406 bcopy(hp->lun, in->lun, 8); 407 in->itt = hp->itt; 408 in->ttt = ISCSI_RSVD_TASK_TAG; 409 (void) pthread_mutex_lock(&c->c_sess->s_mutex); 410 if (ntohl(hp->cmdsn) > c->c_sess->s_seencmdsn) 411 c->c_sess->s_seencmdsn = ntohl(hp->cmdsn); 412 (void) pthread_mutex_unlock(&c->c_sess->s_mutex); 413 414 (void) pthread_mutex_lock(&c->c_state_mutex); 415 if (c->c_state == S5_LOGGED_IN) 416 queue_message_set(c->c_dataq, 417 hp->opcode & ISCSI_OP_IMMEDIATE ? Q_HIGH : 0, 418 msg_send_pkt, in); 419 (void) pthread_mutex_unlock(&c->c_state_mutex); 420 return (True); 421 } 422 423 /*ARGSUSED*/ 424 static Boolean_t 425 handle_scsi_data(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen) 426 { 427 iscsi_data_hdr_t *hp = (iscsi_data_hdr_t *)p; 428 int dlen = ntoh24(hp->dlength); 429 iscsi_cmd_t *cmd; 430 431 if (ISCSI_DATA_RECEIVE_ENABLED()) { 432 uiscsiproto_t info; 433 434 info.uip_target_addr = &c->c_target_sockaddr; 435 info.uip_initiator_addr = &c->c_initiator_sockaddr; 436 437 info.uip_target = c->c_sess->s_t_name; 438 info.uip_initiator = c->c_sess->s_i_name; 439 info.uip_lun = 0; 440 441 info.uip_itt = hp->itt; 442 info.uip_ttt = hp->itt; 443 444 info.uip_cmdsn = 0; 445 info.uip_statsn = ntohl(hp->expstatsn); 446 info.uip_datasn = ntohl(hp->datasn); 447 448 info.uip_datalen = dlen; 449 info.uip_flags = hp->flags; 450 451 ISCSI_DATA_RECEIVE(&info); 452 } 453 454 if ((cmd = iscsi_cmd_find(c, hp->ttt, FindTTT)) == NULL) { 455 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 456 "CON%x failed to find ttt 0x%x\n", c->c_num, hp->ttt); 457 /* 458 * Need to handle error case. 459 */ 460 return (False); 461 } 462 cmd->c_opcode = hp->opcode & ISCSI_OPCODE_MASK; 463 464 /* 465 * assert(cmd->c_lun == hp->lun[1]); 466 * Previously this check was done, but is caused a problem with 467 * the RedHat initiator. There was a discussion on the IPS alias 468 * around this very topic. Even though section 10.7.4 states: 469 * "If the Target Transfer Tag is provided, then the LUN field 470 * MUST hold a valid value and be consistent with whatever was 471 * specified with the command; otherwise, the LUN field is 472 * reserved." 473 * Everyone agreed though that for a DataOut command the LUN field 474 * wasn't required to be valid because the TTT gives the Target 475 * enough information to complete the command. 476 */ 477 assert(cmd->c_allegiance == c); 478 assert(cmd->c_itt == hp->itt); 479 480 cmd->c_offset_out = ntohl(hp->offset); 481 cmd->c_data_len = dlen; 482 (void) pthread_mutex_lock(&c->c_mutex); 483 (void) pthread_mutex_lock(&c->c_state_mutex); 484 if (c->c_state == S5_LOGGED_IN) { 485 if (cmd->c_state != CmdCanceled) { 486 t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T4); 487 } 488 } 489 (void) pthread_mutex_unlock(&c->c_state_mutex); 490 (void) pthread_mutex_unlock(&c->c_mutex); 491 492 #ifdef FULL_DEBUG 493 queue_prt(c->c_mgmtq, Q_CONN_IO, 494 "CON%x PDU(DataOut) TTT 0x%x, offset=0x%x, len=0x%x\n", 495 c->c_num, cmd->c_ttt, cmd->c_t10_cmd->c_offset, dlen); 496 #endif 497 498 return (dataout_delayed(cmd, msg_cmd_data_out)); 499 } 500 501 static Boolean_t 502 handle_scsi_cmd(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen) 503 { 504 iscsi_scsi_cmd_hdr_t *hp = (iscsi_scsi_cmd_hdr_t *)p; 505 int dlen = ntoh24(hp->dlength); 506 iscsi_cmd_t *cmd; 507 508 (void) pthread_mutex_lock(&c->c_sess->s_mutex); 509 if (ntohl(hp->cmdsn) > c->c_sess->s_seencmdsn) 510 c->c_sess->s_seencmdsn = ntohl(hp->cmdsn); 511 (void) pthread_mutex_unlock(&c->c_sess->s_mutex); 512 513 if ((cmd = iscsi_cmd_alloc(c, hp->opcode & ISCSI_OPCODE_MASK)) == NULL) 514 return (False); 515 516 bcopy(hp->scb, cmd->c_scb_default, sizeof (cmd->c_scb_default)); 517 cmd->c_scb = cmd->c_scb_default; 518 cmd->c_scb_len = sizeof (cmd->c_scb_default); 519 cmd->c_data_len = dlen; 520 521 if (ahslen) { 522 523 /* 524 * Additional Header Section ---- 525 * 526 * For Object Storage Devices the SCB is quite large. On 527 * the order of 140 bytes which means the data must be 528 * found in the AHS. 529 */ 530 uint16_t hslen; 531 uint16_t next_seg; 532 uint8_t hstyp; 533 534 do { 535 /* 536 * Find this header segment's length and type 537 */ 538 bcopy(ahs, &hslen, sizeof (hslen)); 539 hslen = ntohs(hslen); 540 hstyp = ahs[2]; 541 542 switch (hstyp) { 543 /* ---- Extended CDB ---- */ 544 case 1: 545 /* 546 * The hslen accounts for the reserved 547 * data byte in the segment. So the first 548 * sixteen bytes are in hp->scb with the 549 * remainder here. By only adding 15 bytes 550 * we allocate the correct amount of space 551 */ 552 cmd->c_scb_extended = malloc(hslen + 15); 553 cmd->c_scb_len = hslen + 15; 554 if (cmd->c_scb_extended == NULL) 555 return (False); 556 557 /* 558 * First 16 bytes of extended SCB are 559 * found in the normal location. 560 */ 561 bcopy(hp->scb, cmd->c_scb_extended, 16); 562 bcopy(&ahs[4], &cmd->c_scb_extended[16], 563 hslen - 16); 564 cmd->c_scb = cmd->c_scb_extended; 565 break; 566 567 /* ---- Expected bidirectional read data len ---- */ 568 case 2: 569 /* 570 * We shouldn't need this since we're 571 * not prealloc'ing resources. If that should 572 * change or the need for error checking 573 * here's the spot to locate the data. 574 */ 575 break; 576 } 577 578 /* 579 * hslen contains the effective length in bytes of 580 * segment, excluding type and length (not including 581 * padding). Each segment is padded to a 4 byte 582 * boundary. 583 */ 584 next_seg = ((hslen + sizeof (hslen) + 585 sizeof (hstyp) + 3) & ~3); 586 ahs += next_seg; 587 ahslen -= next_seg; 588 589 } while (ahslen); 590 } 591 592 /* 593 * XXX Need to handle error case better. 594 */ 595 if (spc_decode_lu_addr(&hp->lun[0], sizeof (hp->lun), &cmd->c_lun) == 596 False) { 597 return (False); 598 } 599 600 if (ISCSI_SCSI_COMMAND_ENABLED()) { 601 uiscsiproto_t info; 602 uiscsicmd_t uc; 603 604 info.uip_target_addr = &c->c_target_sockaddr; 605 info.uip_initiator_addr = &c->c_initiator_sockaddr; 606 607 info.uip_target = c->c_sess->s_t_name; 608 info.uip_initiator = c->c_sess->s_i_name; 609 info.uip_lun = cmd->c_lun; 610 611 info.uip_itt = hp->itt; 612 info.uip_ttt = ISCSI_RSVD_TASK_TAG; 613 614 info.uip_cmdsn = ntohl(hp->cmdsn); 615 info.uip_statsn = ntohl(hp->expstatsn); 616 info.uip_datasn = 0; 617 618 info.uip_datalen = dlen; 619 info.uip_flags = hp->flags; 620 621 uc.uic_len = cmd->c_scb_len; 622 uc.uic_cdb = cmd->c_scb; 623 624 ISCSI_SCSI_COMMAND(&info, &uc); 625 } 626 627 cmd->c_itt = hp->itt; 628 cmd->c_cmdsn = ntohl(hp->cmdsn); 629 cmd->c_dlen_expected = ntohl(hp->data_length); 630 cmd->c_writeop = hp->flags & ISCSI_FLAG_CMD_WRITE ? 631 True : False; 632 633 #ifdef FULL_DEBUG 634 queue_prt(c->c_mgmtq, Q_CONN_IO, 635 "CON%x PDU(SCSI Cmd, TA=%d) CmdSN 0x%x ITT 0x%x TTT 0x%x " 636 "LUN[%02x] id=%p\n", c->c_num, 637 hp->flags & ISCSI_FLAG_CMD_ATTR_MASK, cmd->c_cmdsn, cmd->c_itt, 638 cmd->c_ttt, cmd->c_lun, cmd); 639 #endif 640 641 if (dlen && (hp->flags & ISCSI_FLAG_CMD_WRITE)) { 642 /* 643 * NOTE: This should only occur if ImmediateData==Yes. 644 * We can handle this even if the initiator violates 645 * the specification so no need to worry. Use the rule 646 * of "Be strict in what is sent, but lenient in what 647 * is accepted." 648 */ 649 return (dataout_delayed(cmd, msg_cmd_send)); 650 } else { 651 (void) pthread_mutex_lock(&c->c_state_mutex); 652 if (c->c_state == S5_LOGGED_IN) 653 queue_message_set(c->c_sessq, 0, 654 msg_cmd_send, (void *)cmd); 655 (void) pthread_mutex_unlock(&c->c_state_mutex); 656 return (True); 657 } 658 } 659 660 /* 661 * []---- 662 * | handle_text_msg -- process incoming test parameters 663 * | 664 * | NOTE: Need to handle continuation packets sent by the initiator. 665 * []---- 666 */ 667 /*ARGSUSED*/ 668 static Boolean_t 669 handle_text_msg(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen) 670 { 671 iscsi_text_rsp_hdr_t rsp; 672 iscsi_text_hdr_t *hp = (iscsi_text_hdr_t *)p; 673 char *text = NULL; 674 int text_length = 0; 675 Boolean_t release_at_end = False; 676 int dlen = ntoh24(hp->dlength); 677 678 if (ISCSI_TEXT_COMMAND_ENABLED()) { 679 uiscsiproto_t info; 680 char nil = '\0'; 681 682 info.uip_initiator = c->c_sess->s_i_name; 683 info.uip_target_addr = &c->c_target_sockaddr; 684 info.uip_initiator_addr = &c->c_initiator_sockaddr; 685 686 info.uip_target = c->c_sess->s_t_name; 687 info.uip_initiator = c->c_sess->s_i_name; 688 info.uip_target = &nil; 689 info.uip_lun = 0; 690 691 info.uip_itt = hp->itt; 692 info.uip_ttt = hp->ttt; 693 694 info.uip_cmdsn = ntohl(hp->cmdsn); 695 info.uip_statsn = ntohl(hp->expstatsn); 696 info.uip_datasn = 0; 697 698 info.uip_datalen = dlen; 699 info.uip_flags = hp->flags; 700 701 ISCSI_TEXT_COMMAND(&info); 702 } 703 704 bzero(&rsp, sizeof (rsp)); 705 rsp.opcode = ISCSI_OP_TEXT_RSP; 706 rsp.itt = hp->itt; 707 708 queue_prt(c->c_mgmtq, Q_CONN_NONIO, "CON%x PDU(Text Message)\n", 709 c->c_num); 710 711 /* 712 * Need to determine if this incoming text PDU is an initial message 713 * or a continuation. 714 */ 715 if (hp->ttt == ISCSI_RSVD_TASK_TAG) { 716 717 /* ---- Initial text PDU, so parse the incoming data ---- */ 718 if (parse_text(c, dlen, &text, &text_length, NULL) == False) { 719 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 720 "Failed to parse Text\n"); 721 if (text) { 722 /* 723 * It's possible that we started to create 724 * a response, but yet an error occurred. 725 * Release the partial text response if that 726 * occurred. 727 */ 728 free(text); 729 } 730 return (False); 731 } 732 733 /* 734 * 10.11.4 -- 735 * When the target receives a Text Request with the Target 736 * Transfer Tag set to the reserved value of 0xffffffff, it 737 * resets its internal information (resets state) associated 738 * with the given Initiator Task Tag (restarts the negotiation). 739 */ 740 if (c->c_text_area != NULL) 741 free(c->c_text_area); 742 743 c->c_text_area = text; 744 if (text_length > c->c_max_recv_data) { 745 746 /* 747 * Too much data to send at once, break it up into 748 * multiple transfers. 749 */ 750 rsp.flags = ISCSI_FLAG_TEXT_CONTINUE; 751 rsp.ttt = 1; 752 c->c_text_len = text_length; 753 text_length = c->c_max_recv_data; 754 c->c_text_sent = text_length; 755 } else { 756 rsp.flags = ISCSI_FLAG_FINAL; 757 rsp.ttt = ISCSI_RSVD_TASK_TAG; 758 release_at_end = True; 759 } 760 } else { 761 762 /* ---- Continuation of previous text request ---- */ 763 text_length = c->c_text_len - c->c_text_sent; 764 text = c->c_text_area + c->c_text_sent; 765 if (text_length > c->c_max_recv_data) { 766 rsp.flags = ISCSI_FLAG_TEXT_CONTINUE; 767 rsp.ttt = 1; 768 text_length = c->c_max_recv_data; 769 c->c_text_sent += text_length; 770 } else { 771 rsp.flags = ISCSI_FLAG_FINAL; 772 rsp.ttt = ISCSI_RSVD_TASK_TAG; 773 release_at_end = True; 774 } 775 } 776 777 queue_prt(c->c_mgmtq, Q_CONN_NONIO, 778 "CON%x Text PDU: flags=0x%02x, ttt=0x%08x, len=%d\n", 779 c->c_num, rsp.flags, rsp.ttt, text_length); 780 781 hton24(rsp.dlength, text_length); 782 (void) pthread_mutex_lock(&c->c_mutex); 783 rsp.statsn = htonl(c->c_statsn++); 784 (void) pthread_mutex_lock(&c->c_sess->s_mutex); 785 if (ntohl(hp->cmdsn) > c->c_sess->s_seencmdsn) 786 c->c_sess->s_seencmdsn = ntohl(hp->cmdsn); 787 rsp.maxcmdsn = htonl(iscsi_cmd_window(c) + c->c_sess->s_seencmdsn); 788 rsp.expcmdsn = htonl(c->c_sess->s_seencmdsn + 1); 789 (void) pthread_mutex_unlock(&c->c_sess->s_mutex); 790 (void) pthread_mutex_unlock(&c->c_mutex); 791 792 if (ISCSI_TEXT_RESPONSE_ENABLED()) { 793 uiscsiproto_t info; 794 char nil = '\0'; 795 796 info.uip_target_addr = &c->c_target_sockaddr; 797 info.uip_initiator_addr = &c->c_initiator_sockaddr; 798 799 info.uip_target = c->c_sess->s_t_name; 800 info.uip_initiator = c->c_sess->s_i_name; 801 info.uip_initiator = c->c_sess->s_i_name; 802 info.uip_target = &nil; 803 info.uip_lun = 0; 804 805 info.uip_itt = rsp.itt; 806 info.uip_ttt = rsp.ttt; 807 808 info.uip_cmdsn = ntohl(rsp.expcmdsn); 809 info.uip_statsn = ntohl(rsp.statsn); 810 info.uip_datasn = 0; 811 812 info.uip_datalen = text_length; 813 info.uip_flags = rsp.flags; 814 815 ISCSI_TEXT_RESPONSE(&info); 816 } 817 818 send_iscsi_pkt(c, (iscsi_hdr_t *)&rsp, text); 819 820 if (release_at_end == True) { 821 free(c->c_text_area); 822 c->c_text_area = NULL; 823 } 824 return (True); 825 } 826 827 /*ARGSUSED*/ 828 static Boolean_t 829 handle_logout_msg(iscsi_conn_t *c, iscsi_hdr_t *p, char *ahs, int ahslen) 830 { 831 iscsi_logout_rsp_hdr_t *rsp; 832 iscsi_logout_hdr_t *hp = (iscsi_logout_hdr_t *)p; 833 char debug[80]; 834 835 if (ISCSI_LOGOUT_COMMAND_ENABLED()) { 836 uiscsiproto_t info; 837 char nil = '\0'; 838 839 info.uip_target_addr = &c->c_target_sockaddr; 840 info.uip_initiator_addr = &c->c_initiator_sockaddr; 841 842 info.uip_target = c->c_sess->s_t_name; 843 info.uip_initiator = c->c_sess->s_i_name; 844 info.uip_initiator = c->c_sess->s_i_name; 845 info.uip_target = &nil; 846 info.uip_lun = 0; 847 848 info.uip_itt = hp->itt; 849 info.uip_ttt = ISCSI_RSVD_TASK_TAG; 850 851 info.uip_cmdsn = ntohl(hp->cmdsn); 852 info.uip_statsn = ntohl(hp->expstatsn); 853 info.uip_datasn = 0; 854 855 info.uip_datalen = ntoh24(hp->dlength); 856 info.uip_flags = hp->flags; 857 858 ISCSI_LOGOUT_COMMAND(&info); 859 } 860 861 if ((rsp = calloc(1, sizeof (*rsp))) == NULL) 862 return (False); 863 864 (void) snprintf(debug, sizeof (debug), 865 "CON%x PDU(Logout Request)", c->c_num); 866 queue_str(c->c_mgmtq, Q_CONN_NONIO, msg_log, debug); 867 868 (void) pthread_mutex_lock(&c->c_mutex); 869 (void) pthread_mutex_lock(&c->c_sess->s_mutex); 870 if (hp->cmdsn > c->c_sess->s_seencmdsn) 871 c->c_sess->s_seencmdsn = htonl(hp->cmdsn); 872 rsp->expcmdsn = htonl(c->c_sess->s_seencmdsn + 1); 873 rsp->maxcmdsn = htonl(iscsi_cmd_window(c) + 874 c->c_sess->s_seencmdsn); 875 (void) pthread_mutex_unlock(&c->c_sess->s_mutex); 876 (void) pthread_mutex_unlock(&c->c_mutex); 877 878 rsp->opcode = ISCSI_OP_LOGOUT_RSP; 879 rsp->flags = ISCSI_FLAG_FINAL; 880 rsp->itt = hp->itt; 881 (void) pthread_mutex_lock(&c->c_mutex); 882 rsp->statsn = htonl(c->c_statsn++); 883 (void) pthread_mutex_unlock(&c->c_mutex); 884 885 c->c_last_pkg = (iscsi_hdr_t *)rsp; 886 887 /* 888 * Call the state transition last. This will send out 889 * an asynchronous message to shutdown the session and STE. 890 * Once that's complete a shutdown reply will be sent to 891 * the transmit connection thread. That will cause another 892 * transition to T13 which expects to send out this logout 893 * response. 894 */ 895 if (c->c_state == S7_LOGOUT_REQUESTED) 896 conn_state(c, T10); 897 else 898 conn_state(c, T9); 899 900 return (True); 901 } 902 903 /* 904 * dataout_delayed -- possibly copy data from initiator 905 * 906 * If DataDigests are enabled copy the data from the socket into a buffer 907 * and perform the CRC check now. 908 * 909 * If MaxConnections==1 don't copy the data now and wait until the STE is 910 * ready to copy the data directly from the socket to it's final location. 911 * This is extremely beneficial when using mmap'd data. 912 * NOTE: 913 * (1) For this to work we must not use the queues and instead 914 * call the STE functions directly. If the queues are used 915 * this routine must pause until STE processes the data to 916 * prevent this thread from attempting to read data from 917 * the socket as if it's the next PDU header. 918 * (2) Currently we don't call STE directly. To prevent a performance 919 * issue we'll have the code in place to support calling 920 * STE directly, but any time MaxConnections is greater than 0 921 * we'll copy the buffer. This will be removed at some future 922 * point. 923 */ 924 static Boolean_t 925 dataout_delayed(iscsi_cmd_t *cmd, msg_type_t type) 926 { 927 iscsi_conn_t *c = cmd->c_allegiance; 928 int dlen = cmd->c_data_len; 929 int cc; 930 uint32_t crc_calc; 931 uint32_t crc_actual; 932 char pad_buf[ISCSI_PAD_WORD_LEN - 1]; 933 char pad_len; 934 char debug[80]; 935 936 cmd->c_dataout_cb = dataout_callback; 937 938 if (cmd->c_data == NULL) { 939 if ((cmd->c_data = (char *)malloc(dlen)) == NULL) { 940 (void) pthread_mutex_lock(&c->c_mutex); 941 t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5); 942 iscsi_cmd_free(c, cmd); 943 (void) pthread_mutex_unlock(&c->c_mutex); 944 return (False); 945 } 946 cmd->c_data_alloc = True; 947 } 948 949 if ((cc = recv(c->c_fd, cmd->c_data, dlen, MSG_WAITALL)) != dlen) { 950 if (errno == ECONNRESET) { 951 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 952 "CON%x dataout_delayed -- " 953 "initiator reset socket\n", c->c_num); 954 } else { 955 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 956 "CON%x recv(got-%d, expect-%d), errno=%d\n", 957 c->c_num, cc, dlen, errno); 958 } 959 960 (void) pthread_mutex_lock(&c->c_mutex); 961 t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5); 962 iscsi_cmd_free(c, cmd); 963 (void) pthread_mutex_unlock(&c->c_mutex); 964 conn_state(c, T8); 965 return (True); 966 } 967 968 pad_len = ((ISCSI_PAD_WORD_LEN - 969 (dlen & (ISCSI_PAD_WORD_LEN - 1))) & (ISCSI_PAD_WORD_LEN - 1)); 970 971 if (pad_len) { 972 if (recv(c->c_fd, pad_buf, pad_len, MSG_WAITALL) != pad_len) { 973 if (errno == ECONNRESET) { 974 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 975 "CON%x dataout_delayed -- " 976 "initiator reset socket\n", c->c_num); 977 } else { 978 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 979 "CON%x Pad Word read errno=%d\n", c->c_num, 980 errno); 981 } 982 983 (void) pthread_mutex_lock(&c->c_mutex); 984 t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5); 985 iscsi_cmd_free(c, cmd); 986 (void) pthread_mutex_unlock(&c->c_mutex); 987 conn_state(c, T8); 988 return (True); 989 } 990 } 991 992 if (c->c_data_digest == True) { 993 if (recv(c->c_fd, (char *)&crc_actual, sizeof (crc_actual), 994 MSG_WAITALL) != sizeof (crc_actual)) { 995 if (errno == ECONNRESET) { 996 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 997 "CON%x dataout_delayed -- " 998 "initiator reset socket\n", c->c_num); 999 } else { 1000 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 1001 "CON%x CRC32 read errno=%d\n", c->c_num, 1002 errno); 1003 } 1004 1005 (void) pthread_mutex_lock(&c->c_mutex); 1006 t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5); 1007 iscsi_cmd_free(c, cmd); 1008 (void) pthread_mutex_unlock(&c->c_mutex); 1009 conn_state(c, T8); 1010 return (True); 1011 } 1012 crc_calc = iscsi_crc32c((void *)cmd->c_data, dlen); 1013 if (crc_calc != crc_actual) { 1014 1015 (void) snprintf(debug, sizeof (debug), 1016 "CON%x CRC Error: actual %x vs. calc 0x%x", 1017 c->c_num, crc_actual, crc_calc); 1018 1019 /* 1020 * NOTE: Need to think about this one some more. 1021 * Just because we get a data error doesn't mean 1022 * we should drop the connection. Look at the 1023 * spec and determine what's the appropriate 1024 * error recovery for this issue. 1025 */ 1026 (void) pthread_mutex_lock(&c->c_mutex); 1027 t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5); 1028 iscsi_cmd_free(c, cmd); 1029 (void) pthread_mutex_unlock(&c->c_mutex); 1030 conn_state(c, T8); 1031 return (True); 1032 } 1033 } 1034 1035 /* 1036 * We'll update the offset with the amount of data that 1037 * has been received. During a SCSI response PDU this value 1038 * will be used to determine if there's an overrun condition. 1039 */ 1040 cmd->c_offset_out += dlen; 1041 1042 (void) pthread_mutex_lock(&c->c_mutex); 1043 (void) pthread_mutex_lock(&c->c_state_mutex); 1044 if (c->c_state == S5_LOGGED_IN) { 1045 if ((cmd->c_state == CmdCanceled) && 1046 (type == msg_cmd_data_out)) 1047 t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5); 1048 else 1049 queue_message_set(c->c_sessq, 0, type, (void *)cmd); 1050 } else if (cmd->c_state == CmdCanceled) { 1051 t10_cmd_shoot_event(cmd->c_t10_cmd, T10_Cmd_T5); 1052 } 1053 (void) pthread_mutex_unlock(&c->c_state_mutex); 1054 (void) pthread_mutex_unlock(&c->c_mutex); 1055 1056 /* 1057 * The else case here is if we're calling STE directly and the data 1058 * will be read from the socket when STE is ready for it. 1059 */ 1060 1061 return (True); 1062 } 1063 1064 /* 1065 * []---- 1066 * | dataout_callback -- copy data from socket to emulation buffer 1067 * []---- 1068 */ 1069 void 1070 dataout_callback(t10_cmd_t *t, char *data, size_t *xfer) 1071 { 1072 iscsi_cmd_t *cmd = (iscsi_cmd_t *)T10_TRANS_ID(t); 1073 iscsi_conn_t *c = cmd->c_allegiance; 1074 int dlen = cmd->c_data_len; 1075 int cc; 1076 char pad_buf[ISCSI_PAD_WORD_LEN - 1]; 1077 char pad_len = 0; 1078 1079 pad_len = ((ISCSI_PAD_WORD_LEN - 1080 (dlen & (ISCSI_PAD_WORD_LEN - 1))) & 1081 (ISCSI_PAD_WORD_LEN - 1)); 1082 1083 1084 if (T10_DATA(t) != NULL) { 1085 assert(T10_DATA(t) == cmd->c_data); 1086 assert(cmd->c_data_alloc == True); 1087 free(T10_DATA(t)); 1088 T10_DATA(t) = NULL; 1089 cmd->c_data = NULL; 1090 cmd->c_data_alloc = False; 1091 return; 1092 } 1093 1094 if ((cc = recv(c->c_fd, data, dlen, MSG_WAITALL)) != dlen) { 1095 if (errno == ECONNRESET) { 1096 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 1097 "CON%x data_callback -- initiator reset socket\n", 1098 c->c_num); 1099 } else { 1100 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 1101 "CON%x recv(got-%d, expect-%d) errno=%d", 1102 c->c_num, cc, dlen, errno); 1103 } 1104 1105 conn_state(c, T8); 1106 goto finish; 1107 } 1108 1109 if (pad_len) { 1110 if (recv(c->c_fd, pad_buf, pad_len, MSG_WAITALL) != pad_len) { 1111 if (errno == ECONNRESET) { 1112 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 1113 "CON%x data_callback -- " 1114 "initiator reset socket\n", c->c_num); 1115 } else { 1116 queue_prt(c->c_mgmtq, Q_CONN_ERRS, 1117 "CON%x data_callback -- " 1118 "pad read errno=%d\n", c->c_num, errno); 1119 } 1120 conn_state(c, T8); 1121 goto finish; 1122 } 1123 } 1124 1125 finish: 1126 *xfer = cc; 1127 /* ---- Send msg that receive side of the connection can go ---- */ 1128 (void) sema_post(&c->c_datain); 1129 } 1130