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 #include <stdio.h> 28 #include <assert.h> 29 #include <sys/types.h> 30 #include <stdlib.h> 31 #include <strings.h> 32 #include <syslog.h> 33 34 #include <iscsitgt_impl.h> 35 #include "iscsi_conn.h" 36 #include "iscsi_sess.h" 37 #include "t10.h" 38 #include "utility.h" 39 #include "target.h" 40 41 pthread_mutex_t sess_mutex; 42 /* 43 * This value is used as the TSIH which must be non-zero. 44 */ 45 int sess_num = 1; 46 iscsi_sess_t *sess_head; 47 48 static void session_free(struct iscsi_sess *s); 49 static void sess_set_auth(iscsi_sess_t *isp); 50 static void *sess_from_t10(void *v); 51 static void *sess_process(void *v); 52 53 /* 54 * []---- 55 * | session_init -- initialize global variables and mutexs 56 * []---- 57 */ 58 void 59 session_init() 60 { 61 (void) pthread_mutex_init(&sess_mutex, NULL); 62 } 63 64 /* 65 * []---- 66 * | session_alloc -- create a new session attached to the lead connection 67 * []---- 68 */ 69 Boolean_t 70 session_alloc(iscsi_conn_t *c, uint8_t *isid) 71 { 72 iscsi_sess_t *s, *n; 73 74 if (c->c_sess != NULL) 75 return (True); 76 77 s = (iscsi_sess_t *)calloc(sizeof (iscsi_sess_t), 1); 78 if (s == NULL) 79 return (False); 80 81 bcopy(isid, s->s_isid, 6); 82 83 (void) pthread_mutex_init(&s->s_mutex, NULL); 84 c->c_sess = s; 85 s->s_conn_head = c; 86 s->s_sessq = queue_alloc(); 87 s->s_t10q = queue_alloc(); 88 c->c_sessq = s->s_sessq; 89 s->s_mgmtq = c->c_mgmtq; 90 s->s_type = SessionNormal; 91 92 sess_set_auth(s); 93 94 (void) pthread_mutex_lock(&sess_mutex); 95 s->s_num = sess_num++; 96 s->s_tsid = s->s_num; 97 s->s_state = SS_STARTED; 98 99 if (sess_head == NULL) 100 sess_head = s; 101 else { 102 for (n = sess_head; n->s_next; n = n->s_next) 103 ; 104 n->s_next = s; 105 } 106 (void) pthread_mutex_unlock(&sess_mutex); 107 108 (void) pthread_create(&s->s_thr_id_t10, NULL, sess_from_t10, s); 109 (void) pthread_create(&s->s_thr_id_conn, NULL, sess_process, s); 110 111 util_title(s->s_mgmtq, Q_SESS_LOGIN, s->s_num, "Start Session"); 112 113 return (True); 114 } 115 116 /* 117 * []---- 118 * | session_free -- remove connection from session 119 * []---- 120 */ 121 static void 122 session_free(iscsi_sess_t *s) 123 { 124 iscsi_sess_t *n; 125 126 /* 127 * Early errors in connection setup can still call this routine 128 * which means the session hasn't been called. 129 */ 130 if (s == NULL) 131 return; 132 133 (void) pthread_mutex_lock(&sess_mutex); 134 if (s->s_i_name) 135 free(s->s_i_name); 136 if (s->s_t_name) 137 free(s->s_t_name); 138 if (s->s_i_alias) 139 free(s->s_i_alias); 140 141 if (sess_head == s) 142 sess_head = s->s_next; 143 else { 144 for (n = sess_head; n; n = n->s_next) { 145 if (n->s_next == s) { 146 n->s_next = s->s_next; 147 break; 148 } 149 } 150 if (n == NULL) { 151 queue_prt(s->s_mgmtq, Q_SESS_ERRS, 152 "SES%x NOT IN SESSION LIST!\n", s->s_num); 153 } 154 } 155 (void) pthread_mutex_unlock(&sess_mutex); 156 } 157 158 /* 159 * []---- 160 * | session_remove_connection -- removes conn from sess list 161 * | 162 * | Returns True if this was the last connection which is always the case 163 * | for now. In the future with multiple connections per session it'll be 164 * | different. 165 * []---- 166 */ 167 /*ARGSUSED*/ 168 static Boolean_t 169 session_remove_connection(iscsi_sess_t *s, iscsi_conn_t *c) 170 { 171 bzero(s->s_isid, 6); 172 return (True); 173 } 174 175 /* 176 * []---- 177 * | convert_i_local -- Return a local name for the initiator if avilable. 178 * | 179 * | NOTE: If this routine returns true, it's the callers responsibility 180 * | to free the memory. 181 * []---- 182 */ 183 Boolean_t 184 convert_i_local(char *ip, char **rtn) 185 { 186 tgt_node_t *inode = NULL; 187 char *iname, *name; 188 189 while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT, 190 inode)) != NULL) { 191 if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &iname) == 192 False) { 193 continue; 194 } 195 if (strcmp(iname, ip) == 0) { 196 if (tgt_find_value_str(inode, XML_ELEMENT_INIT, 197 &name) == False) { 198 free(iname); 199 return (False); 200 } else 201 free(iname); 202 *rtn = name; 203 return (True); 204 } else 205 free(iname); 206 } 207 return (False); 208 } 209 210 /* 211 * []---- 212 * | sess_from_t10 -- handle messages from the T10 layer 213 * []---- 214 */ 215 void * 216 sess_from_t10(void *v) 217 { 218 iscsi_sess_t *s = (iscsi_sess_t *)v; 219 msg_t *m; 220 Boolean_t process = True; 221 t10_conn_shutdown_t t_c_s; 222 Boolean_t sent_wait_for_destroy = False; 223 224 t_c_s.t10_to_conn_q = NULL; 225 t_c_s.conn_to_t10_q = NULL; 226 227 while (process == True) { 228 m = queue_message_get(s->s_t10q); 229 switch (m->msg_type) { 230 case msg_cmd_data_rqst: 231 queue_message_set(s->s_conn_head->c_dataq, 0, 232 msg_cmd_data_rqst, m->msg_data); 233 break; 234 235 case msg_cmd_data_in: 236 queue_message_set(s->s_conn_head->c_dataq, 0, 237 msg_cmd_data_in, m->msg_data); 238 break; 239 240 case msg_cmd_cmplt: 241 queue_message_set(s->s_conn_head->c_dataq, 0, 242 msg_cmd_cmplt, m->msg_data); 243 break; 244 245 case msg_shutdown_rsp: 246 247 if (s->s_t10) { 248 if (!sent_wait_for_destroy) { 249 if (t_c_s.t10_to_conn_q == NULL) { 250 t_c_s.t10_to_conn_q = 251 queue_alloc(); 252 if (t_c_s.t10_to_conn_q 253 == NULL) { 254 queue_message_set( 255 s->s_t10q, 0, 256 msg_shutdown_rsp, 257 m->msg_data); 258 break; 259 } 260 } 261 if (t_c_s.conn_to_t10_q == NULL) { 262 t_c_s.conn_to_t10_q = 263 queue_alloc(); 264 if (t_c_s.conn_to_t10_q == 265 NULL) { 266 queue_message_set( 267 s->s_t10q, 0, 268 msg_shutdown_rsp, 269 m->msg_data); 270 break; 271 } 272 } 273 queue_message_set( 274 s->s_conn_head->c_dataq, 0, 275 msg_wait_for_destroy, 276 (void *)&t_c_s); 277 queue_message_free(queue_message_get( 278 t_c_s.conn_to_t10_q)); 279 sent_wait_for_destroy = True; 280 } 281 282 if (t10_handle_destroy(s->s_t10, False) != 0) { 283 /* 284 * Destroy couldn't complete, 285 * put the message back on our 286 * own queue to be picked up 287 * later and tried again. 288 */ 289 queue_message_set(s->s_t10q, 0, 290 msg_shutdown_rsp, 291 m->msg_data); 292 break; 293 } 294 s->s_t10 = NULL; 295 queue_message_set(t_c_s.t10_to_conn_q, 296 0, 1, (void *)NULL); 297 queue_message_free(queue_message_get( 298 t_c_s.conn_to_t10_q)); 299 queue_free(t_c_s.t10_to_conn_q, NULL); 300 queue_free(t_c_s.conn_to_t10_q, NULL); 301 sent_wait_for_destroy = False; 302 } 303 304 (void) pthread_mutex_lock(&s->s_mutex); 305 s->s_state = SS_SHUTDOWN_CMPLT; 306 (void) pthread_mutex_unlock(&s->s_mutex); 307 308 session_free(s); 309 310 /* 311 * Let the connection, which is the last, know 312 * about our completion of the shutdown. 313 */ 314 queue_message_set(s->s_conn_head->c_dataq, 0, 315 msg_shutdown_rsp, (void *)True); 316 process = False; 317 s->s_state = SS_FREE; 318 break; 319 320 default: 321 queue_prt(s->s_mgmtq, Q_SESS_ERRS, 322 "SES%x Unknown msg type (%d) from T10\n", 323 s->s_num, m->msg_type); 324 queue_message_set(s->s_conn_head->c_dataq, 0, 325 m->msg_type, m->msg_data); 326 break; 327 } 328 queue_message_free(m); 329 } 330 queue_message_set(s->s_mgmtq, 0, msg_pthread_join, 331 (void *)(uintptr_t)pthread_self()); 332 queue_free(s->s_t10q, NULL); 333 util_title(s->s_mgmtq, Q_SESS_LOGIN, s->s_num, "End Session"); 334 free(s); 335 return (NULL); 336 } 337 338 /* 339 * []---- 340 * | sess_process -- handle messages from the connection(s) 341 * []---- 342 */ 343 static void * 344 sess_process(void *v) 345 { 346 iscsi_sess_t *s = (iscsi_sess_t *)v; 347 iscsi_conn_t *c; 348 iscsi_cmd_t *cmd; 349 msg_t *m; 350 Boolean_t process = True; 351 mgmt_request_t *mgmt; 352 name_request_t *nr; 353 t10_cmd_t *t10_cmd; 354 char **buf, local_buf[16]; 355 int lun; 356 extern void dataout_callback(t10_cmd_t *t, char *data, size_t *xfer); 357 358 (void) pthread_mutex_lock(&s->s_mutex); 359 s->s_state = SS_RUNNING; 360 (void) pthread_mutex_unlock(&s->s_mutex); 361 do { 362 m = queue_message_get(s->s_sessq); 363 switch (m->msg_type) { 364 case msg_cmd_send: 365 cmd = (iscsi_cmd_t *)m->msg_data; 366 if (s->s_t10 == NULL) { 367 368 /* 369 * The value of 0x960 comes from T10. 370 * See SPC-4, revision 1a, section 6.4.2, 371 * table 87 372 * 373 * XXX Need to rethink how I should do 374 * the callback. 375 */ 376 s->s_t10 = t10_handle_create( 377 s->s_t_name, s->s_i_name, T10_TRANS_ISCSI, 378 s->s_conn_head->c_tpgt, 379 s->s_conn_head->c_max_burst_len, 380 s->s_t10q, dataout_callback); 381 } 382 if (t10_cmd_create(s->s_t10, cmd->c_lun, cmd->c_scb, 383 cmd->c_scb_len, (transport_t)cmd, 384 &t10_cmd) == False) { 385 386 /* 387 * If the command create failed, the T10 layer 388 * will attempt to create a sense buffer 389 * telling the initiator what went wrong. If 390 * that layer was unable to accomplish that 391 * things are really bad and we need to just 392 * close the connection. 393 */ 394 if (t10_cmd != NULL) { 395 queue_message_set( 396 cmd->c_allegiance->c_dataq, 397 0, msg_cmd_cmplt, t10_cmd); 398 } else { 399 queue_prt(s->s_mgmtq, Q_SESS_ERRS, 400 "SES%x FAILED to create cmd\n", 401 s->s_num); 402 conn_state(cmd->c_allegiance, T11); 403 } 404 } else { 405 (void) pthread_mutex_lock( 406 &cmd->c_allegiance->c_mutex); 407 if (cmd->c_state != CmdCanceled) { 408 cmd->c_t10_cmd = t10_cmd; 409 (void) t10_cmd_send(s->s_t10, 410 cmd->c_t10_cmd, cmd->c_data, 411 cmd->c_data_len); 412 } else { 413 t10_cmd_shoot_event(t10_cmd, 414 T10_Cmd_T6); 415 } 416 (void) pthread_mutex_unlock( 417 &cmd->c_allegiance->c_mutex); 418 } 419 break; 420 421 case msg_cmd_data_out: 422 cmd = (iscsi_cmd_t *)m->msg_data; 423 if (s->s_t10 != NULL) 424 (void) t10_cmd_data(s->s_t10, cmd->c_t10_cmd, 425 cmd->c_offset_out, cmd->c_data, 426 cmd->c_data_len); 427 break; 428 429 case msg_targ_inventory_change: 430 if (s->s_t10 != NULL) 431 (void) t10_task_mgmt(s->s_t10, InventoryChange, 432 0, 0); 433 break; 434 435 case msg_lu_capacity_change: 436 lun = (int)(uintptr_t)m->msg_data; 437 if (s->s_t10 != NULL) 438 (void) t10_task_mgmt(s->s_t10, CapacityChange, 439 lun, 0); 440 break; 441 442 case msg_reset_targ: 443 if (s->s_t10 != NULL) 444 (void) t10_task_mgmt(s->s_t10, ResetTarget, 445 0, 0); 446 break; 447 448 case msg_reset_lu: 449 if (s->s_t10 != NULL) 450 (void) t10_task_mgmt(s->s_t10, ResetLun, 451 (int)(uintptr_t)m->msg_data, 0); 452 break; 453 454 case msg_shutdown: 455 (void) pthread_mutex_lock(&s->s_mutex); 456 s->s_state = SS_SHUTDOWN_START; 457 (void) pthread_mutex_unlock(&s->s_mutex); 458 459 /* 460 * Shutdown rquest comming from a connection. Only 461 * shutdown the STE if this is the last connection 462 * for this session. 463 */ 464 c = (iscsi_conn_t *)m->msg_data; 465 if (session_remove_connection(s, c) == True) { 466 queue_prt(s->s_mgmtq, Q_SESS_NONIO, 467 "SES%x Starting shutdown\n", s->s_num); 468 469 /* 470 * If this is the last connection for this 471 * session send a message to the SAM-3 layer to 472 * shutdown. 473 */ 474 if (s->s_t10 != NULL) { 475 t10_handle_disable(s->s_t10); 476 } 477 /* 478 * Do all work using the session pointer before 479 * sending the shutdown response msg. The 480 * session struct can get freed by the thread 481 * that picks up and handles the shutdown 482 * response. 483 */ 484 queue_message_set(s->s_mgmtq, 0, 485 msg_pthread_join, 486 (void *)(uintptr_t)pthread_self()); 487 queue_message_set(s->s_t10q, 0, 488 msg_shutdown_rsp, 0); 489 process = False; 490 } else { 491 492 /* 493 * Since this isn't the last connection for 494 * the session, acknowledge the connection 495 * request now since it's references from 496 * this session have been removed. 497 */ 498 queue_message_set(c->c_dataq, 0, 499 msg_shutdown_rsp, (void *)False); 500 } 501 break; 502 503 case msg_initiator_name: 504 nr = (name_request_t *)m->msg_data; 505 s->s_i_name = strdup(nr->nr_name); 506 507 /* 508 * Acknowledge the request by sending back an empty 509 * message. 510 */ 511 queue_message_set(nr->nr_q, 0, msg_initiator_name, 0); 512 break; 513 514 case msg_initiator_alias: 515 nr = (name_request_t *)m->msg_data; 516 s->s_i_alias = strdup(nr->nr_name); 517 518 /* 519 * Acknowledge the request by sending back an empty 520 * message. 521 */ 522 queue_message_set(nr->nr_q, 0, msg_initiator_alias, 0); 523 break; 524 525 case msg_target_name: 526 nr = (name_request_t *)m->msg_data; 527 s->s_t_name = strdup(nr->nr_name); 528 529 /* 530 * Acknowledge the request by sending back an empty 531 * message. 532 */ 533 queue_message_set(nr->nr_q, 0, msg_target_name, 0); 534 break; 535 536 case msg_mgmt_rqst: 537 mgmt = (mgmt_request_t *)m->msg_data; 538 m->msg_data = NULL; 539 540 (void) pthread_mutex_lock(&mgmt->m_resp_mutex); 541 buf = mgmt->m_u.m_resp; 542 543 if ((s->s_type == SessionNormal) && 544 (mgmt->m_request == mgmt_full_phase_statistics) && 545 (strcmp(s->s_t_name, mgmt->m_targ_name) == 0)) { 546 547 tgt_buf_add_tag(buf, XML_ELEMENT_CONN, 548 Tag_Start); 549 tgt_buf_add_tag(buf, s->s_i_name, Tag_String); 550 if (s->s_i_alias != NULL) { 551 tgt_buf_add(buf, XML_ELEMENT_ALIAS, 552 s->s_i_alias); 553 } 554 555 /* 556 * Need to loop through the connections 557 * and create one time_connected tag for 558 * each. This will be needed once MC/S support 559 * is added. 560 */ 561 (void) snprintf(local_buf, sizeof (local_buf), 562 "%d", 563 mgmt->m_time - s->s_conn_head->c_up_at); 564 tgt_buf_add(buf, XML_ELEMENT_TIMECON, 565 local_buf); 566 567 tgt_buf_add_tag(buf, XML_ELEMENT_STATS, 568 Tag_Start); 569 570 t10_targ_stat(s->s_t10, buf); 571 572 tgt_buf_add_tag(buf, XML_ELEMENT_STATS, 573 Tag_End); 574 tgt_buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End); 575 } 576 577 (void) pthread_mutex_unlock(&mgmt->m_resp_mutex); 578 579 queue_message_set(mgmt->m_q, 0, msg_mgmt_rply, 0); 580 581 break; 582 583 default: 584 queue_prt(s->s_mgmtq, Q_SESS_ERRS, 585 "SES%x Unknown msg type (%d) from Connection\n", 586 s->s_num, m->msg_type); 587 break; 588 } 589 queue_message_free(m); 590 } while (process == True); 591 592 queue_message_set(mgmtq, 0, msg_pthread_join, 593 (void *)(uintptr_t)pthread_self()); 594 return (NULL); 595 } 596 597 /* 598 * []---- 599 * | session_validate -- do what the name says 600 * | 601 * | At this point the connection has processed the login command so that 602 * | we have InitiatorName and ISID at a minimum. Check to see if there 603 * | are other sessions which match. If so, log that one out and proceed with 604 * | this session. If nothing matches, then link this into a global list. 605 * | 606 * | Once we support multiple connections per session need to scan list 607 * | to see if other connection have the same CID. If so, log out that 608 * | connection. 609 * []---- 610 */ 611 Boolean_t 612 session_validate(iscsi_sess_t *s) 613 { 614 iscsi_sess_t *check; 615 616 queue_prt(s->s_mgmtq, Q_SESS_NONIO, 617 "SES%x %s ISID[%02x%02x%02x%02x%02x%02x]\n", 618 s->s_num, s->s_i_alias == NULL ? s->s_i_name : s->s_i_alias, 619 s->s_isid[0], s->s_isid[1], s->s_isid[2], 620 s->s_isid[3], s->s_isid[4], s->s_isid[5]); 621 622 623 /* 624 * SessionType=Discovery which means no target name and therefore 625 * this is okay. 626 */ 627 if (s->s_t_name == NULL) 628 return (True); 629 630 (void) pthread_mutex_lock(&sess_mutex); 631 for (check = sess_head; check; check = check->s_next) { 632 /* 633 * Ignore ourselves in this check. 634 */ 635 if (check == s) 636 continue; 637 if ((check->s_t_name == NULL) || 638 (strcmp(check->s_t_name, s->s_t_name) != 0)) 639 continue; 640 if (strcmp(check->s_i_name, s->s_i_name) != 0) 641 continue; 642 if (check->s_conn_head->c_tpgt != s->s_conn_head->c_tpgt) 643 continue; 644 /* 645 * Section 5.3.5 646 * Session reinstatement is the process of the initiator 647 * logging in with an ISID that is possible active from 648 * the target's perspective. Thus implicitly logging out 649 * the session that corresponds to the ISID and 650 * reinstating a new iSCSI session in its place (with the 651 * same ISID). 652 */ 653 if (bcmp(check->s_isid, s->s_isid, 6) == 0) { 654 queue_prt(s->s_mgmtq, Q_SESS_NONIO, 655 "SES%x Implicit shutdown\n", check->s_num); 656 if (check->s_conn_head->c_state == S5_LOGGED_IN) 657 conn_state(check->s_conn_head, T8); 658 else 659 conn_state(check->s_conn_head, T7); 660 break; 661 } 662 } 663 (void) pthread_mutex_unlock(&sess_mutex); 664 665 return (True); 666 } 667 668 /* 669 * []---- 670 * | static iscsi_sess_set_auth - 671 * []---- 672 */ 673 static void 674 sess_set_auth(iscsi_sess_t *isp) 675 { 676 IscsiAuthClient *auth_client = NULL; 677 tgt_node_t *node = NULL; 678 679 if (isp == (iscsi_sess_t *)NULL) 680 return; 681 682 /* Zero out the session authentication structure */ 683 bzero(&isp->sess_auth, sizeof (iscsi_auth_t)); 684 isp->sess_auth.auth_enabled = B_TRUE; 685 686 /* Load CHAP name */ 687 node = tgt_node_next_child(main_config, XML_ELEMENT_CHAPNAME, NULL); 688 if (node != NULL && node->x_value != NULL) { 689 (void) strcpy(isp->sess_auth.username, node->x_value); 690 } 691 692 /* Load CHAP secret */ 693 node = tgt_node_next_child(main_config, XML_ELEMENT_CHAPSECRET, NULL); 694 if (node != NULL && node->x_value != NULL) { 695 (void) strcpy((char *)isp->sess_auth.password, node->x_value); 696 isp->sess_auth.password_length = strlen(node->x_value); 697 } 698 699 /* 700 * Set up authentication buffers always. We don't know if 701 * initiator will request CHAP until later. 702 */ 703 isp->sess_auth.num_auth_buffers = 5; 704 isp->sess_auth.auth_buffers[0].address = 705 &(isp->sess_auth.auth_client_block); 706 isp->sess_auth.auth_buffers[0].length = 707 sizeof (isp->sess_auth.auth_client_block); 708 isp->sess_auth.auth_buffers[1].address = 709 &(isp->sess_auth.auth_recv_string_block); 710 isp->sess_auth.auth_buffers[1].length = 711 sizeof (isp->sess_auth.auth_recv_string_block); 712 isp->sess_auth.auth_buffers[2].address = 713 &(isp->sess_auth.auth_send_string_block); 714 isp->sess_auth.auth_buffers[2].length = 715 sizeof (isp->sess_auth.auth_send_string_block); 716 isp->sess_auth.auth_buffers[3].address = 717 &(isp->sess_auth.auth_recv_binary_block); 718 isp->sess_auth.auth_buffers[3].length = 719 sizeof (isp->sess_auth.auth_recv_binary_block); 720 isp->sess_auth.auth_buffers[4].address = 721 &(isp->sess_auth.auth_send_binary_block); 722 isp->sess_auth.auth_buffers[4].length = 723 sizeof (isp->sess_auth.auth_send_binary_block); 724 725 if (isp->sess_auth.auth_buffers && 726 isp->sess_auth.num_auth_buffers) { 727 728 auth_client = (IscsiAuthClient *)isp-> 729 sess_auth.auth_buffers[0].address; 730 731 /* 732 * prepare for authentication 733 */ 734 if (iscsiAuthClientInit(iscsiAuthNodeTypeTarget, 735 isp->sess_auth.num_auth_buffers, 736 isp->sess_auth.auth_buffers) != 737 iscsiAuthStatusNoError) { 738 syslog(LOG_ERR, "iscsi connection login failed - " 739 "unable to initialize authentication\n"); 740 return; 741 } 742 743 if (iscsiAuthClientSetVersion(auth_client, 744 iscsiAuthVersionRfc) != iscsiAuthStatusNoError) { 745 syslog(LOG_ERR, "iscsi connection login failed - " 746 "unable to set version\n"); 747 return; 748 } 749 750 if (isp->sess_auth.username && 751 (iscsiAuthClientSetUsername(auth_client, 752 isp->sess_auth.username) != 753 iscsiAuthStatusNoError)) { 754 syslog(LOG_ERR, "iscsi connection login failed - " 755 "unable to set username\n"); 756 return; 757 } 758 759 if (isp->sess_auth.password && 760 (iscsiAuthClientSetPassword(auth_client, 761 isp->sess_auth.password, isp->sess_auth.password_length) != 762 iscsiAuthStatusNoError)) { 763 syslog(LOG_ERR, "iscsi connection login failed - " 764 "unable to set password\n"); 765 return; 766 } 767 768 /* 769 * FIXME: we disable the minimum size check for now 770 */ 771 if (iscsiAuthClientSetIpSec(auth_client, 1) != 772 iscsiAuthStatusNoError) { 773 syslog(LOG_ERR, "iscsi connection login failed - " 774 "unable to set ipsec\n"); 775 return; 776 } 777 778 if (iscsiAuthClientSetAuthRemote(auth_client, 779 isp->sess_auth.auth_enabled) != iscsiAuthStatusNoError) { 780 syslog(LOG_ERR, "iscsi connection login failed - " 781 "unable to set remote authentication\n"); 782 return; 783 } 784 } 785 } 786