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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #define FD_SETSIZE 65536 29 #include <sys/types.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <strings.h> 33 #include <time.h> 34 #include <unistd.h> 35 #include <pthread.h> 36 #include <sys/conf.h> 37 #include <sys/socket.h> 38 #include <netinet/in.h> 39 #include <arpa/inet.h> 40 #include <stdint.h> 41 #include <dirent.h> 42 #include <sys/stat.h> 43 #include <fcntl.h> 44 #include <assert.h> 45 #include <errno.h> 46 #include <door.h> 47 #include <signal.h> 48 #include <siginfo.h> 49 #include <sys/ethernet.h> 50 #include <libscf.h> 51 #include <syslog.h> 52 #include <synch.h> 53 #include <libxml/xmlreader.h> 54 #include <sys/resource.h> 55 #include <syslog.h> 56 #include <sys/select.h> 57 #include <iscsitgt_impl.h> 58 #include <umem.h> 59 60 #include "queue.h" 61 #include "port.h" 62 #include "iscsi_conn.h" 63 #include "target.h" 64 #include "utility.h" 65 #include "iscsi_ffp.h" 66 #include "errcode.h" 67 #include "t10.h" 68 #include "mgmt_scf.h" 69 70 #include "isns_client.h" 71 72 #define EMPTY_CONFIG "<config version='1.0'>\n</config>\n" 73 74 /* ---- Forward declarations ---- */ 75 static void variable_handler(tgt_node_t *, target_queue_t *, target_queue_t *, 76 ucred_t *); 77 78 79 /* ---- Global configuration data. ---- */ 80 char *target_basedir = NULL; 81 char *target_log = DEFAULT_TARGET_LOG; 82 char *config_file = DEFAULT_CONFIG_LOCATION; 83 char *pgr_basedir = NULL; 84 int iscsi_port = 3260, /* defined by the spec */ 85 dbg_lvl = 0, 86 door_min_space; 87 tgt_node_t *main_config, 88 *targets_config; 89 Boolean_t enforce_strict_guid = True, 90 thin_provisioning = False, 91 disable_tpgs = False, 92 dbg_timestamps = False, 93 pgr_persist = True; 94 int targets_vers_maj, 95 targets_vers_min, 96 main_vers_maj, 97 main_vers_min; 98 pthread_rwlock_t targ_config_mutex; 99 umem_cache_t *iscsi_cmd_cache, 100 *t10_cmd_cache, 101 *queue_cache; 102 103 typedef struct var_table { 104 char *v_name; 105 int *v_value; 106 } var_table_t; 107 108 typedef struct cmd_table { 109 char *c_name; 110 void (*c_func)(tgt_node_t *, target_queue_t *, target_queue_t *, 111 ucred_t *); 112 } cmd_table_t; 113 114 admin_table_t admin_prop_list[] = { 115 {XML_ELEMENT_BASEDIR, update_basedir, NULL}, 116 {XML_ELEMENT_CHAPSECRET, 0, NULL}, 117 {XML_ELEMENT_CHAPNAME, 0, NULL}, 118 {XML_ELEMENT_RAD_ACCESS, 0, NULL}, 119 {XML_ELEMENT_RAD_SERV, valid_radius_srv, NULL}, 120 {XML_ELEMENT_RAD_SECRET, 0, NULL}, 121 {XML_ELEMENT_ISNS_ACCESS, 0, NULL}, 122 {XML_ELEMENT_ISNS_SERV, valid_isns_srv, NULL}, 123 {XML_ELEMENT_FAST, 0, NULL}, 124 {XML_ELEMENT_DELETE_CHAPSECRET, 0, XML_ELEMENT_CHAPSECRET}, 125 {XML_ELEMENT_DELETE_CHAPNAME, 0, XML_ELEMENT_CHAPNAME}, 126 {XML_ELEMENT_DELETE_RAD_SECRET, 0, XML_ELEMENT_RAD_SECRET}, 127 {XML_ELEMENT_DELETE_RAD_SERV, 0, XML_ELEMENT_RAD_SERV}, 128 {0, 0} 129 }; 130 131 /* 132 * Global variables which can be set via the management XML interface 133 * with the syntax of "<variable><dbg_lvl>0x033</dbg_lvl></variable>" 134 */ 135 var_table_t var_table[] = { 136 { "dbg_lvl", &dbg_lvl }, 137 { "qlog_lvl", &qlog_lvl }, 138 /* ---- End of Table marker ---- */ 139 { NULL, 0 } 140 }; 141 142 /* 143 * Commands which are run via the management XML interface 144 */ 145 cmd_table_t cmd_table[] = { 146 { "variable", variable_handler }, 147 { "create", create_func }, 148 { "modify", modify_func }, 149 { "delete", remove_func }, 150 { "list", list_func }, 151 /* ---- End of Table marker ---- */ 152 { NULL, NULL } 153 }; 154 155 /* 156 * []---- 157 * | process_config -- parse the main configuration file 158 * | 159 * | Everything in the configuratin file is optional. That's because 160 * | the management CLI can set the value to everything and update 161 * | the configuration. 162 * []---- 163 */ 164 static Boolean_t 165 process_config() 166 { 167 tgt_node_t *node = NULL; 168 169 #ifndef lint 170 LIBXML_TEST_VERSION; 171 #endif 172 173 if (mgmt_get_main_config(&node) == False) { 174 return (False); 175 } 176 177 main_vers_maj = XML_VERS_MAIN_MAJ; 178 main_vers_min = XML_VERS_MAIN_MIN; 179 if (validate_version(node, &main_vers_maj, &main_vers_min) == 180 False) { 181 syslog(LOG_ERR, "Target main config invalid"); 182 return (False); 183 } 184 185 /* 186 * The base directory is optional in the sense that the daemon 187 * can start without it, but the daemon can't really do 188 * anything until the administrator sets the value. 189 */ 190 (void) tgt_find_value_str(node, XML_ELEMENT_BASEDIR, 191 &target_basedir); 192 193 /* 194 * These are optional settings for the target. Each of 195 * these has a default value which can be overwritten in 196 * the configuration. 197 */ 198 (void) tgt_find_value_str(node, XML_ELEMENT_TARGLOG, 199 &target_log); 200 (void) tgt_find_value_int(node, XML_ELEMENT_ISCSIPORT, 201 &iscsi_port); 202 (void) tgt_find_value_intchk(node, XML_ELEMENT_DBGLVL, &dbg_lvl); 203 (void) tgt_find_value_boolean(node, XML_ELEMENT_ENFORCE, 204 &enforce_strict_guid); 205 (void) tgt_find_value_boolean(node, XML_ELEMENT_THIN_PROVO, 206 &thin_provisioning); 207 (void) tgt_find_value_boolean(node, XML_ELEMENT_DISABLE_TPGS, 208 &disable_tpgs); 209 (void) tgt_find_value_boolean(node, XML_ELEMENT_TIMESTAMPS, 210 &dbg_timestamps); 211 (void) tgt_find_value_boolean(node, XML_ELEMENT_PGR_PERSIST, 212 &pgr_persist); 213 (void) tgt_find_value_str(node, XML_ELEMENT_PGR_BASEDIR, 214 &pgr_basedir); 215 if (tgt_find_value_intchk(node, XML_ELEMENT_LOGLVL, 216 &qlog_lvl) == True) 217 queue_log(True); 218 219 main_config = node; 220 targets_config = node; 221 222 return (True); 223 } 224 225 /* 226 * []---- 227 * | logout_cleanup -- see if the initiator did what was requested 228 * | 229 * | When a target issues an asynchrouns event with the code set to 230 * | "logout requested" the initiator is supposed to respond with 231 * | a LogoutRequested PDU within a certain amount of time. If it 232 * | fails to do so, it's the targets responsibility to clean up. 233 * | We will check logout status in a 1 second interval, if the 234 * | initiators responded to the logout request then logout is 235 * | conpleted, if ASYNC_LOGOUT_TIMEOUT seconds (currently 10) 236 * | is reached then we will reissue the management request to 237 * | to logout which will cause the connections to close. 238 * []---- 239 */ 240 static void * 241 logout_cleanup(void *v) 242 { 243 int msg_sent, i; 244 char *targ = (char *)v; 245 mgmt_request_t m; 246 iscsi_conn_t *conn; 247 extern pthread_mutex_t port_mutex; 248 Boolean_t logout = False; 249 250 bzero(&m, sizeof (m)); 251 m.m_request = mgmt_logout; 252 m.m_q = queue_alloc(); 253 msg_sent = 0; 254 255 /* 256 * The for loop is to manage the wait time for the 257 * logout request to complete, if logout completed 258 * before ASYNC_LOGOUT_TIMEOUT then done 259 */ 260 for (i = 0; i < ASYNC_LOGOUT_TIMEOUT; i++) { 261 logout = True; 262 (void) pthread_mutex_lock(&port_mutex); 263 for (conn = conn_head; conn; conn = conn->c_next) { 264 if ((conn->c_state == S7_LOGOUT_REQUESTED) && 265 (strcmp(conn->c_sess->s_t_name, targ) == 0)) { 266 logout = False; 267 break; 268 } 269 } 270 (void) pthread_mutex_unlock(&port_mutex); 271 if (logout) 272 break; 273 else 274 (void) sleep(1); 275 } 276 277 /* 278 * Logout did not complete, queue message to shutdown 279 * connection. 280 */ 281 if (logout == False) { 282 (void) pthread_mutex_lock(&port_mutex); 283 for (conn = conn_head; conn; conn = conn->c_next) { 284 if ((conn->c_state == S7_LOGOUT_REQUESTED) && 285 (strcmp(conn->c_sess->s_t_name, targ) == 0)) { 286 queue_message_set(conn->c_dataq, 0, 287 msg_mgmt_rqst, &m); 288 msg_sent++; 289 } 290 } 291 (void) pthread_mutex_unlock(&port_mutex); 292 } 293 294 /* 295 * Wait to see if they received the message. 296 */ 297 for (i = 0; i < msg_sent; i++) 298 queue_message_free(queue_message_get(m.m_q)); 299 queue_free(m.m_q, NULL); 300 free(targ); 301 302 queue_message_set(mgmtq, 0, msg_pthread_join, 303 (void *)(uintptr_t)pthread_self()); 304 return ((void *)0); 305 } 306 307 void 308 logout_targ(char *targ) 309 { 310 mgmt_request_t m; 311 iscsi_conn_t *conn; 312 int i, msg_sent; 313 pthread_t junk; 314 extern pthread_mutex_t port_mutex; 315 316 /* 317 * Now we look for connections to this target and issue 318 * a request to asynchronously logout. 319 */ 320 bzero(&m, sizeof (m)); 321 m.m_request = mgmt_logout; 322 m.m_q = queue_alloc(); 323 msg_sent = 0; 324 325 (void) pthread_mutex_lock(&port_mutex); 326 for (conn = conn_head; conn; conn = conn->c_next) { 327 if (conn->c_state != S5_LOGGED_IN) 328 continue; 329 if (conn->c_sess->s_type == SessionDiscovery) 330 continue; 331 332 if (strcmp(conn->c_sess->s_t_name, targ) == 0) { 333 queue_message_set(conn->c_dataq, 0, msg_mgmt_rqst, &m); 334 msg_sent++; 335 } 336 } 337 (void) pthread_mutex_unlock(&port_mutex); 338 339 /* ---- Wait to see if they received the message. ---- */ 340 for (i = 0; i < msg_sent; i++) 341 queue_message_free(queue_message_get(m.m_q)); 342 343 queue_free(m.m_q, NULL); 344 345 /* ---- Start housecleaning thread ---- */ 346 (void) pthread_create(&junk, NULL, logout_cleanup, 347 (void *)strdup(targ)); 348 } 349 350 /* 351 * [] ---- XML Management Handlers ---- [] 352 */ 353 354 /* 355 * []---- 356 * | variable_handler -- used to set a couple of internal global variables 357 * []---- 358 */ 359 /*ARGSUSED*/ 360 void 361 variable_handler(tgt_node_t *x, target_queue_t *reply, target_queue_t *mgmt, 362 ucred_t *cred) 363 { 364 char *reply_buf = NULL; 365 var_table_t *v; 366 tgt_node_t *c; 367 368 if (check_auth_modify(cred) != True) { 369 xml_rtn_msg(&reply_buf, ERR_NO_PERMISSION); 370 queue_str(reply, 0, msg_mgmt_rply, reply_buf); 371 return; 372 } 373 for (c = x->x_child; c; c = c->x_sibling) { 374 375 for (v = var_table; v->v_name; v++) { 376 if (strcmp(c->x_name, v->v_name) == 0) { 377 *v->v_value = strtol(c->x_value, NULL, 0); 378 if (strcmp(v->v_name, "qlog_lvl") == 0) 379 queue_log(True); 380 xml_rtn_msg(&reply_buf, ERR_SUCCESS); 381 break; 382 } 383 } 384 if (v->v_name == NULL) 385 xml_rtn_msg(&reply_buf, ERR_NO_MATCH); 386 387 queue_str(reply, 0, msg_mgmt_rply, reply_buf); 388 } 389 } 390 391 /* 392 * []---- 393 * | parse_xml -- incoming management requests are sent here for processing 394 * []---- 395 */ 396 static void 397 parse_xml(tgt_node_t *x, target_queue_t *reply, target_queue_t *mgmt, 398 ucred_t *cred) 399 { 400 char *reply_msg = NULL; 401 cmd_table_t *c; 402 403 if ((x->x_name == NULL) || (x->x_state == NodeFree)) { 404 xml_rtn_msg(&reply_msg, ERR_SYNTAX_EMPTY); 405 queue_message_set(reply, 0, msg_mgmt_rply, reply_msg); 406 return; 407 } 408 409 for (c = cmd_table; c->c_name != NULL; c++) 410 if (strcmp(c->c_name, x->x_name) == 0) 411 break; 412 if (c->c_name == NULL) { 413 xml_rtn_msg(&reply_msg, ERR_INVALID_COMMAND); 414 queue_message_set(reply, 0, msg_mgmt_rply, reply_msg); 415 } else { 416 (c->c_func)(x, reply, mgmt, cred); 417 } 418 } 419 420 /* 421 * space_message -- create a message indicating the amount of space needed. 422 * 423 * This code could have been inline in the server_for_door function, but 424 * at system startup we'll determine the minimum amount of space needed for 425 * a door call return pointer. This minimum amount of space will be either 426 * a "need more space" or a "success" message. So, have this code as a function 427 * reduces any duplication. 428 */ 429 static void 430 space_message(char **buf, int size) 431 { 432 char lbuf[16]; 433 tgt_buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'"); 434 (void) snprintf(lbuf, sizeof (lbuf), "%d", size); 435 tgt_buf_add(buf, XML_ELEMENT_MORESPACE, lbuf); 436 tgt_buf_add_tag(buf, XML_ELEMENT_ERROR, Tag_End); 437 } 438 439 /*ARGSUSED*/ 440 static void 441 server_for_door(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, 442 uint_t n_desc) 443 { 444 target_queue_t *mgmtq = (target_queue_t *)cookie; 445 mgmt_request_t m; 446 msg_t *msg = NULL; 447 tgt_node_t *node = NULL; 448 xmlTextReaderPtr r; 449 char *err_rply = NULL; 450 ucred_t *uc = NULL; 451 size_t cur_space; 452 453 /* 454 * A well written application will always give us enough space 455 * to send either a "success" message or a "more space needed". 456 * If the minimum amount of space isn't given then just return 457 * with a NULL pointer. 458 */ 459 if (arg_size < door_min_space) { 460 (void) door_return(NULL, 0, NULL, 0); 461 return; 462 } 463 464 /* 465 * Pick up the user credentials of the client application. Used to 466 * validate that the effective user ID is either root or the process 467 * has the privilege to complete the operation. 468 */ 469 if (door_ucred(&uc) != 0) { 470 xml_rtn_msg(&err_rply, ERR_BAD_CREDS); 471 (void) strlcpy(argp, err_rply, arg_size); 472 free(err_rply); 473 (void) door_return(argp, strlen(argp) + 1, NULL, 0); 474 return; 475 } 476 477 if (validate_xml(argp) != True) { 478 xml_rtn_msg(&err_rply, ERR_INVALID_XML_REQUEST); 479 (void) strlcpy(argp, err_rply, arg_size); 480 free(err_rply); 481 (void) door_return(argp, strlen(argp) + 1, NULL, 0); 482 return; 483 } 484 485 bzero(&m, sizeof (m)); 486 487 if ((r = (xmlTextReaderPtr)xmlReaderForMemory(argp, strlen(argp), 488 NULL, NULL, 0)) != NULL) { 489 while (xmlTextReaderRead(r)) { 490 if (tgt_node_process(r, &node) == False) 491 break; 492 } 493 if (node != NULL) { 494 m.m_q = queue_alloc(); 495 m.m_request = mgmt_parse_xml; 496 m.m_time = time(NULL); 497 m.m_targ_name = NULL; 498 m.m_u.m_node = node; 499 m.m_cred = uc; 500 501 queue_message_set(mgmtq, 0, msg_mgmt_rqst, &m); 502 if ((msg = queue_message_get(m.m_q)) == NULL) { 503 (void) xmlFreeTextReader(r); 504 (void) xmlCleanupParser(); 505 (void) ucred_free(uc); 506 tgt_node_free(node); 507 if (m.m_q != NULL) 508 queue_free(m.m_q, NULL); 509 (void) door_return("", 1, NULL, 0); 510 return; 511 } 512 513 /* 514 * Check to see if the response can fit into the 515 * incoming argument buffer. If so, copy the response 516 * to that buffer so that we can free the data. 517 * If it's not big enough we'll request an updated 518 * space message, then delete the current data, allowing 519 * the request to be requeued again. 520 */ 521 if ((cur_space = strlen(msg->msg_data)) < arg_size) { 522 (void) strlcpy(argp, msg->msg_data, arg_size); 523 } else { 524 /* 525 * err_rply will be copied to argp at the end 526 */ 527 space_message(&err_rply, cur_space + 1); 528 } 529 free(msg->msg_data); 530 queue_message_free(msg); 531 } else { 532 xml_rtn_msg(&err_rply, ERR_NULL_XML_MESSAGE); 533 } 534 535 xmlFreeTextReader(r); 536 xmlCleanupParser(); 537 538 } else { 539 xml_rtn_msg(&err_rply, ERR_INIT_XML_READER_FAILED); 540 } 541 542 if (node != NULL) 543 tgt_node_free(node); 544 if (err_rply != NULL) { 545 (void) strlcpy(argp, err_rply, arg_size); 546 free(err_rply); 547 } 548 if (m.m_q != NULL) 549 queue_free(m.m_q, NULL); 550 551 ucred_free(uc); 552 (void) door_return(argp, strlen(argp) + 1, NULL, 0); 553 } 554 555 /* 556 * []---- 557 * | setup_door -- Create a door portal for management requests 558 * | 559 * | First check to see if another daemon is already running by attempting 560 * | to send an empty request to the door. If successful it means this 561 * | daemon should exit. 562 * []---- 563 */ 564 static void 565 setup_door(target_queue_t *q, char *door_name) 566 { 567 int did, fd; 568 struct stat s; 569 door_arg_t d; 570 char *msg = NULL; 571 572 /* 573 * Figure out what the minimum amount of space required to send back 574 * either a success message or a need more space one. 575 * 576 * Commands fall into one of three categories. 577 * (1) Idempotent commands, like list operations, which can 578 * return large ammounts of data. If there's not enough room 579 * the client is informed and the command is run again with a 580 * larger buffer. 581 * (2) Create, modify, or delete operations that fail. These 582 * commands may return an error message which is larger than 583 * the incoming request buffer. If so, the client is informed 584 * that a larger buffer is needed and the command is rerun. This 585 * time it'll recieve the full error message. So, these commands 586 * are idempotent because no state changes occur on failure. 587 * (3) Create, modify, or delete operations which are successful. 588 * Since successful completion means state has change the daemon 589 * must always be able to report success, other wise a second 590 * attempt with a larger buffer would then fail, where the first 591 * one actually succeeded. 592 */ 593 xml_rtn_msg(&msg, ERR_SUCCESS); 594 door_min_space = strlen(msg); 595 free(msg); 596 msg = NULL; 597 /* 598 * Use an impossibly big number which will create the longest string 599 */ 600 space_message(&msg, 0x80000000); 601 door_min_space = MAX(door_min_space, strlen(msg)); 602 free(msg); 603 604 door_min_space++; /* add 1 for the NULL byte */ 605 606 /* 607 * DOOR_MIN_SPACE will be the amount used by the library as the default. 608 * Currently this will be set to 128 (check iscsitgt_impl.h for value). 609 * Since this will be a compiled value and the "success" or "more space" 610 * messages could grown we need to detect if there will be a problem. 611 * By failing here consistently, SMF will put the daemon in maintenance 612 * state and this will be caught during testing. Otherwise the library 613 * would receive a NULL back, but not know how much space is really 614 * required. 615 */ 616 if (door_min_space > DOOR_MIN_SPACE) { 617 syslog(LOG_ERR, 618 "Calculated min space (%d) is larger than default (%d)", 619 door_min_space, DOOR_MIN_SPACE); 620 assert(0); 621 } 622 623 if ((fd = open(door_name, 0)) >= 0) { 624 625 /* 626 * There's at least a file with the same name as our 627 * door. Let's see if someone is currently answering 628 * by sending an empty XML request. 629 */ 630 d.data_ptr = "<config></config>"; 631 d.data_size = strlen(d.data_ptr) + 1; 632 d.desc_ptr = NULL; 633 d.desc_num = 0; 634 d.rbuf = NULL; 635 d.rsize = 0; 636 637 if (door_call(fd, &d) == 0) { 638 639 /* 640 * If the door_call succeeds that means another 641 * daemon is already running so let's just exit. 642 */ 643 exit(0); 644 } 645 (void) close(fd); 646 } 647 648 if ((did = door_create(server_for_door, (void *)q, 0)) < 0) { 649 syslog(LOG_ERR, "door_create"); 650 exit(1); 651 } 652 653 if (stat(door_name, &s) < 0) { 654 int newfd; 655 if ((newfd = creat(door_name, 0666)) < 0) { 656 syslog(LOG_ERR, "creat failed"); 657 exit(1); 658 } 659 (void) close(newfd); 660 } 661 (void) fdetach(door_name); 662 663 /* 664 * Open the door for general access. As the calls come in we'll 665 * get the credentials and validate within each operation as to the 666 * required privileges. 667 */ 668 (void) chmod(door_name, 0666); 669 670 if (fattach(did, door_name) < 0) { 671 syslog(LOG_ERR, "fattach failed errno=%d", errno); 672 exit(2); 673 } 674 } 675 676 /*ARGSUSED*/ 677 void 678 exit_after_door_setup(int sig, siginfo_t *sip, void *v) 679 { 680 exit(SMF_EXIT_OK); 681 } 682 683 int 684 main(int argc, char **argv) 685 { 686 char c, *p, *door_name; 687 msg_t *msg; 688 target_queue_t *q; 689 port_args_t port1, port2; 690 Boolean_t mgmt_up = False; 691 Boolean_t daemonize = True; 692 Boolean_t console_output = True; 693 pthread_t junk; 694 mgmt_request_t *mgmt; 695 struct sigaction act; 696 struct rlimit rl; 697 void *thr_status; 698 699 door_name = ISCSI_TARGET_MGMT_DOOR; 700 701 while ((c = getopt(argc, argv, "c:d:")) != EOF) { 702 switch (c) { 703 case 'c': 704 config_file = optarg; 705 break; 706 case 'd': 707 door_name = optarg; 708 break; 709 } 710 } 711 712 /* 713 * If the initiator closes the socket because of a protocol error 714 * or bad digest on the header packet we'll receive a SIGPIPE if we're 715 * in the middle of a write operation. There's no need to receive 716 * a signal when a -1 from the write will handle things correctly. 717 * So, ignore SIGPIPE's. 718 */ 719 (void) sigignore(SIGPIPE); 720 721 /* 722 * Setup memory caches 723 */ 724 if ((iscsi_cmd_cache = umem_cache_create("iSCSI conn cmds", 725 sizeof (iscsi_cmd_t), 8, NULL, NULL, NULL, NULL, NULL, 0)) == 726 NULL) { 727 perror("cache create"); 728 exit(SMF_EXIT_ERR_CONFIG); 729 } 730 if ((t10_cmd_cache = umem_cache_create("T10 cmds", 731 sizeof (t10_cmd_t), 8, NULL, NULL, NULL, NULL, NULL, 0)) == NULL) { 732 perror("cache create"); 733 exit(SMF_EXIT_ERR_CONFIG); 734 } 735 if ((queue_cache = umem_cache_create("Queue messages", 736 sizeof (msg_t), 8, NULL, NULL, NULL, NULL, NULL, 0)) == NULL) { 737 perror("cache create"); 738 exit(SMF_EXIT_ERR_CONFIG); 739 } 740 741 /* 742 * Look at the function lu_buserr_handler() in t10_sam.c to see the 743 * details of why we need to handle segmentation violations. 744 */ 745 bzero(&act, sizeof (act)); 746 act.sa_sigaction = lu_buserr_handler; 747 act.sa_flags = SA_SIGINFO; 748 749 if (sigaction(SIGBUS, &act, NULL) == -1) { 750 perror("sigaction"); 751 exit(SMF_EXIT_ERR_CONFIG); 752 } 753 754 755 if (mgmt_convert_conf() == CONVERT_FAIL) 756 exit(SMF_EXIT_ERR_CONFIG); 757 758 if (process_config() == False) 759 exit(SMF_EXIT_ERR_CONFIG); 760 761 /* 762 * During the normal corse of events 'target_basedir' will be 763 * free when the administrator changes the base directory. Instead 764 * of trying to check for the initial case of this value being set 765 * to some static string, always allocate that string. 766 * NOTE: This must be done *after* process_config() is called since 767 * it's possible and very likely that this value will be set at that 768 * time. 769 */ 770 if (target_basedir == NULL) 771 target_basedir = strdup(DEFAULT_TARGET_BASEDIR); 772 773 (void) tgt_find_value_boolean(main_config, XML_ELEMENT_DBGDAEMON, 774 &daemonize); 775 776 q = queue_alloc(); 777 if (daemonize == True) { 778 closefrom(0); 779 780 /* 781 * Set up a signal handler to catch SIGUSR2. Once the child 782 * has setup the door, it will signal the parent that it's 783 * safe to exit. Without doing this it's possible that the 784 * daemon will start and the parent exit before the child has 785 * setup the door. If that happens 'zfs share -a iscsi' which 786 * is run from svc-iscsitgt will fail to open the door and try 787 * to wait for the iscsitgt service to come online. Since 788 * the zfs command is part of the service start, the service 789 * will not come online and we'll fail to share any ZVOLs. 790 */ 791 bzero(&act, sizeof (act)); 792 act.sa_sigaction = exit_after_door_setup; 793 act.sa_flags = SA_SIGINFO; 794 if (sigaction(SIGUSR2, &act, NULL) == -1) { 795 perror("sigaction"); 796 exit(SMF_EXIT_ERR_CONFIG); 797 } 798 799 switch (fork()) { 800 case 0: 801 /* 802 * As the child process, setup the door and then 803 * signal the parent that it can exit since the child 804 * is now ready to start accepting requests on the 805 * door. 806 */ 807 setup_door(q, door_name); 808 (void) kill(getppid(), SIGUSR2); 809 break; 810 811 case -1: 812 /* ---- Failed to fork!. Trouble ---- */ 813 exit(SMF_EXIT_ERR_CONFIG); 814 815 default: 816 /* 817 * If pause() returns with an error something 818 * interrupted the process which was not a SIGUSR2. 819 * Exit with an error code such that SMF can flag 820 * this problem. 821 */ 822 if (pause() == -1) 823 exit(SMF_EXIT_ERR_CONFIG); 824 } 825 } else { 826 827 /* 828 * The daemon is working in debug mode, so go ahead and 829 * setup the door now. 830 */ 831 setup_door(q, door_name); 832 } 833 834 /* 835 * Initialize the various subsystems. In most cases these are 836 * just initializing mutexs. 837 */ 838 (void) pthread_rwlock_init(&targ_config_mutex, NULL); 839 iscsi_cmd_init(); 840 session_init(); 841 t10_init(q); 842 port_init(); 843 queue_init(); 844 util_init(); 845 (void) isns_init(q); 846 847 /* 848 * If there's no MAC address currently available don't worry about 849 * it. The first time an initiator connects the SAM-3 layer will 850 * attempt to create a GUID and force another look for a MAC address. 851 */ 852 if (if_find_mac(q) == False) 853 queue_prt(q, Q_GEN_DETAILS, "MAIN: No MAC address available"); 854 855 /* 856 * At a minimum we need two file descriptors for each target, one for 857 * the socket and one for the backing store. If there's more than one 858 * initiator attached to a given target than that number goes up by 1. 859 * Once we have multiple sessions per connection that to will cause 860 * an increase. 861 */ 862 if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) && 863 (rl.rlim_cur < TARGET_NOFILE)) { 864 rl.rlim_cur = TARGET_NOFILE; 865 if (setrlimit(RLIMIT_NOFILE, &rl) != 0) 866 syslog(LOG_NOTICE, 867 "Can't set new limit for open files"); 868 } 869 870 port1.port_mgmtq = q; 871 port1.port_num = iscsi_port; 872 (void) pthread_create(&junk, NULL, port_watcher, &port1); 873 874 if ((tgt_find_value_int(main_config, XML_ELEMENT_MGMTPORT, 875 &port2.port_num) == True) && (port2.port_num != -1)) { 876 port2.port_mgmtq = q; 877 port2.port_dataq = queue_alloc(); 878 (void) pthread_create(&junk, NULL, port_management, &port2); 879 } 880 881 do { 882 msg = queue_message_get(q); 883 884 switch (msg->msg_type) { 885 case msg_pthread_join: 886 (void) pthread_join((pthread_t)(uintptr_t)msg->msg_data, 887 &thr_status); 888 if (thr_status != 0) 889 queue_prt(q, Q_GEN_ERRS, 890 "Thread %d exit with %d", 891 msg->msg_data, thr_status); 892 msg->msg_data = NULL; 893 break; 894 895 case msg_log: 896 if ((p = strchr(msg->msg_data, '\n')) != NULL) 897 *p = '\0'; 898 p = (char *)msg->msg_data; 899 if ((msg->msg_pri_level & dbg_lvl) == 0) 900 break; 901 902 if (mgmt_up == True) 903 queue_str(port2.port_dataq, Q_GEN_DETAILS, 904 msg_log, p); 905 if (console_output == True) 906 (void) printf("%s\n", p); 907 break; 908 909 case msg_mgmt_rqst: 910 mgmt = (mgmt_request_t *)msg->msg_data; 911 if (mgmt->m_request == mgmt_parse_xml) 912 parse_xml(mgmt->m_u.m_node, mgmt->m_q, q, 913 mgmt->m_cred); 914 msg->msg_data = NULL; 915 break; 916 917 case msg_status: 918 p = (char *)msg->msg_data; 919 /* 920 * NOTE: 921 * These are real error conditons being sent from 922 * the other threads and should be logged in 923 * some manner, either syslog() or using a FMA 924 * interface. 925 */ 926 (void) printf("STATUS: %s\n", p); 927 break; 928 929 default: 930 break; 931 } 932 933 if (msg->msg_data != NULL) 934 free(msg->msg_data); 935 queue_message_free(msg); 936 /*CONSTANTCONDITION*/ 937 } while (1); 938 939 return (0); 940 } 941