Home | History | Annotate | Download | only in iscsitgtd
      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 #include <strings.h>
     29 #include <stdlib.h>
     30 #include <unistd.h>
     31 #include <dirent.h>
     32 #include <assert.h>
     33 #include <sys/types.h>
     34 #include <sys/param.h>
     35 #include <sys/stat.h>
     36 #include <sys/socket.h>
     37 #include <inttypes.h>
     38 #include <netinet/in.h>
     39 #include <arpa/inet.h>
     40 #include <errno.h>
     41 #include <utility.h>
     42 #include <fcntl.h>
     43 #include <syslog.h>
     44 
     45 #include <iscsitgt_impl.h>
     46 #include "target.h"
     47 #include "utility.h"
     48 #include "errcode.h"
     49 #include "isns_client.h"
     50 #include <sys/scsi/generic/commands.h>
     51 #include "mgmt_scf.h"
     52 #include "t10_spc.h"
     53 
     54 #define	CRC32_STR	"CRC32C"
     55 #define	NONE_STR	"None"
     56 
     57 static thick_provo_t	*thick_head,
     58 			*thick_tail;
     59 pthread_mutex_t		thick_mutex;
     60 
     61 static Boolean_t connection_parameters_get(iscsi_conn_t *c, char *targ_name);
     62 static Boolean_t util_create_guid_naa(char **guid);
     63 
     64 void
     65 util_init()
     66 {
     67 	(void) pthread_mutex_init(&thick_mutex, NULL);
     68 }
     69 
     70 /*
     71  * []----
     72  * | check_access -- see if the requesting initiator is in the ACL
     73  * |
     74  * | Optionally will also check to see if this initiator requires
     75  * | authentication.
     76  * []----
     77  */
     78 Boolean_t
     79 check_access(tgt_node_t *targ, char *initiator_name, Boolean_t req_chap)
     80 {
     81 	tgt_node_t	*acl;
     82 	tgt_node_t	*inode		= NULL;
     83 	tgt_node_t	*tgt_initiator	= NULL;
     84 	char		*dummy;
     85 	Boolean_t	valid		= False;
     86 	Boolean_t	found_chap	= False;
     87 	Boolean_t	access		= False;
     88 
     89 	/*
     90 	 * If ISNS is enable check for access privilege from isns server
     91 	 */
     92 	if (isns_enabled() == True) {
     93 		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &dummy)
     94 		    == False) {
     95 			return (False);
     96 		}
     97 		access = isns_qry_initiator(dummy, initiator_name);
     98 		free(dummy);
     99 		if (req_chap == False) {
    100 			return (access);
    101 		}
    102 
    103 		/* Need to check if CHAP is needed for initiator */
    104 		while ((inode = tgt_node_next_child(main_config,
    105 		    XML_ELEMENT_INIT, inode)) != NULL) {
    106 			if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy)
    107 			    == True) {
    108 				if (strcmp(dummy, initiator_name) == 0) {
    109 					free(dummy);
    110 					if (tgt_find_value_str(inode,
    111 					    XML_ELEMENT_CHAPSECRET, &dummy)
    112 					    == True) {
    113 						free(dummy);
    114 						found_chap = True;
    115 						break;
    116 					}
    117 				}
    118 			}
    119 		}
    120 		if (access == True) {
    121 			if ((req_chap == True) && (found_chap == True))
    122 				access = False;
    123 		}
    124 		return (access);
    125 	}
    126 
    127 	/*
    128 	 * If there's no ACL for this target everyone has access.
    129 	 */
    130 	if ((acl = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == NULL)
    131 		return (True);
    132 
    133 	/*
    134 	 * Find the local initiator name and also save the knowledge
    135 	 * if the initiator had a CHAP secret.
    136 	 */
    137 	inode = NULL;
    138 	while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
    139 	    inode)) != NULL) {
    140 		if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy) ==
    141 		    True) {
    142 			if (strcmp(dummy, initiator_name) == 0) {
    143 				free(dummy);
    144 				if (tgt_find_value_str(inode,
    145 				    XML_ELEMENT_CHAPSECRET, &dummy) == True) {
    146 					free(dummy);
    147 					found_chap = True;
    148 				}
    149 				break;
    150 			} else {
    151 				free(dummy);
    152 			}
    153 		}
    154 	}
    155 
    156 	if ((acl != NULL) && (inode == NULL))
    157 		return (False);
    158 
    159 	while ((tgt_initiator = tgt_node_next(acl, XML_ELEMENT_INIT,
    160 	    tgt_initiator)) != NULL) {
    161 
    162 		if (strcmp(inode->x_value, tgt_initiator->x_value) == 0) {
    163 			valid = True;
    164 			break;
    165 		}
    166 	}
    167 
    168 	if (valid == True) {
    169 
    170 		/*
    171 		 * If req_chap is True it means the login code hasn't gone
    172 		 * through the authentication phase and it's trying to
    173 		 * determine if the initiator should have done so. If
    174 		 * we find a CHAP-secret then this routine will fail.
    175 		 * No CHAP-secret for an initiator just means that a
    176 		 * simple ACL list is used. This can be spoofed easily
    177 		 * enough and is mainly used to limit the number of
    178 		 * targets an initiator would see.
    179 		 */
    180 		if ((req_chap == True) && (found_chap == True))
    181 			valid = False;
    182 	}
    183 
    184 	return (valid);
    185 }
    186 
    187 /*
    188  * []----
    189  * | convert_local_tpgt -- Convert a local tpgt name to real addresses
    190  * |
    191  * | To simplify the configuration files targets only have a target portal
    192  * | group tag string(s) associated. In the main configuration file there's
    193  * | a tpgt element which has one or more ip-address elements. So the tag
    194  * | is located and the actual data is inserted into the outgoing stream.
    195  * []----
    196  */
    197 static Boolean_t
    198 convert_local_tpgt(char **text, int *text_length, char *local_tpgt)
    199 {
    200 	tgt_node_t	*tpgt	= NULL;
    201 	tgt_node_t 	*x;
    202 	char		buf[80];
    203 	char		ipaddr[4];
    204 
    205 	while ((tpgt = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
    206 	    tpgt)) != NULL) {
    207 		if (strcmp(tpgt->x_value, local_tpgt) == 0) {
    208 
    209 			/*
    210 			 * The only children of the tpgt element are
    211 			 * ip-address elements. The value of each element is
    212 			 * the string we need to use. So, we don't need to
    213 			 * check the node's name to see if this is correct or
    214 			 * not.
    215 			 */
    216 			if ((tpgt = tgt_node_next(tpgt, XML_ELEMENT_IPADDRLIST,
    217 			    NULL)) == NULL) {
    218 				return (False);
    219 			}
    220 
    221 			x = NULL;
    222 			while ((x = tgt_node_next(tpgt, XML_ELEMENT_IPADDR, x))
    223 			    != NULL) {
    224 				if (inet_pton(AF_INET, x->x_value, &ipaddr)
    225 				    == 1) {
    226 					/*
    227 					 * Valid IPv4 address
    228 					 */
    229 					(void) snprintf(buf, sizeof (buf),
    230 
    231 					    "%s,%s", x->x_value, local_tpgt);
    232 				} else {
    233 					/*
    234 					 * Invalid IPv4 address
    235 					 * try with brackets (RFC2732)
    236 					 */
    237 					(void) snprintf(buf, sizeof (buf),
    238 					    "[%s],%s", x->x_value, local_tpgt);
    239 				}
    240 				(void) add_text(text, text_length,
    241 				    "TargetAddress", buf);
    242 			}
    243 			break;
    244 		}
    245 	}
    246 
    247 	return (True);
    248 }
    249 
    250 /*
    251  * []----
    252  * | add_target_address -- find and add any target address information
    253  * []----
    254  */
    255 static void
    256 add_target_address(iscsi_conn_t *c, char **text, int *text_length,
    257     tgt_node_t *targ)
    258 {
    259 	tgt_node_t	*tpgt_list;
    260 	tgt_node_t	*tpgt = NULL;
    261 	struct sockaddr_in	*sp4;
    262 	struct sockaddr_in6	*sp6;
    263 	/*
    264 	 * 7 is enough room for the largest TPGT of "65536", the ',' and a NULL
    265 	 */
    266 	char	buf[INET6_ADDRSTRLEN + 7];
    267 	char	net_buf[INET6_ADDRSTRLEN];
    268 
    269 	if ((tpgt_list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST,
    270 	    NULL)) == NULL) {
    271 		if_target_address(text, text_length,
    272 		    (struct sockaddr *)&c->c_target_sockaddr);
    273 		return;
    274 	}
    275 
    276 	while ((tpgt = tgt_node_next_child(tpgt_list, XML_ELEMENT_TPGT,
    277 	    tpgt)) != NULL) {
    278 		if (convert_local_tpgt(text, text_length, tpgt->x_value) ==
    279 		    False) {
    280 			if (c->c_target_sockaddr.ss_family == AF_INET) {
    281 				sp4 = (struct sockaddr_in *)
    282 				    &c->c_target_sockaddr;
    283 				(void) snprintf(buf, sizeof (buf), "%s,%s",
    284 				    inet_ntop(sp4->sin_family,
    285 				    (void *)&sp4->sin_addr,
    286 				    net_buf, sizeof (net_buf)),
    287 				    tpgt->x_value);
    288 			} else {
    289 				sp6 = (struct sockaddr_in6 *)
    290 				    &c->c_target_sockaddr;
    291 				(void) snprintf(buf, sizeof (buf), "[%s],%s",
    292 				    inet_ntop(sp6->sin6_family,
    293 				    (void *)&sp6->sin6_addr,
    294 				    net_buf, sizeof (net_buf)),
    295 				    tpgt->x_value);
    296 			}
    297 			(void) add_text(text, text_length, "TargetAddress",
    298 			    buf);
    299 		}
    300 	}
    301 }
    302 
    303 /*
    304  * []----
    305  * | add_targets -- add TargetName and TargetAddress to text argument
    306  * |
    307  * | Add targets which this initiator is allowed to see based on
    308  * | the access_list associated with a target. If a target doesn't
    309  * | have an access list then let everyone see it.
    310  * []----
    311  */
    312 static Boolean_t
    313 add_targets(iscsi_conn_t *c, char **text, int *text_length)
    314 {
    315 	tgt_node_t	*targ		= NULL;
    316 	Boolean_t	rval		= True;
    317 	char		*targ_name	= NULL;
    318 
    319 	while ((rval == True) && ((targ = tgt_node_next_child(targets_config,
    320 	    XML_ELEMENT_TARG, targ)) != NULL)) {
    321 
    322 		if (check_access(targ, c->c_sess->s_i_name, False) == True) {
    323 
    324 			if (tgt_find_value_str(targ, XML_ELEMENT_INAME,
    325 			    &targ_name) == False) {
    326 				rval = False;
    327 				break;
    328 			}
    329 			queue_prt(c->c_mgmtq, Q_CONN_LOGIN,
    330 			    "CON%x    %24s = %s\n", c->c_num, "TargetName",
    331 			    targ_name);
    332 
    333 			(void) add_text(text, text_length, "TargetName",
    334 			    targ_name);
    335 			free(targ_name);
    336 			add_target_address(c, text, text_length, targ);
    337 		}
    338 	}
    339 	return (rval);
    340 }
    341 
    342 /*
    343  * []----
    344  * | add_text -- Add new name/value pair to possibly existing string
    345  * []----
    346  */
    347 Boolean_t
    348 add_text(char **text, int *current_length, char *name, char *val)
    349 {
    350 	int	dlen = *current_length;
    351 	int	plen;
    352 	char	*p;
    353 
    354 	/*
    355 	 * Length is 'name' + separator + 'value' + NULL
    356 	 */
    357 	plen = strlen(name) + 1 + strlen(val) + 1;
    358 
    359 	if (dlen) {
    360 		if ((p = (char *)realloc(*text, dlen + plen)) == NULL)
    361 			return (False);
    362 	} else {
    363 		if ((p = (char *)malloc(plen)) == NULL)
    364 			return (False);
    365 	}
    366 
    367 	*text = p;
    368 	p = *text + dlen;
    369 
    370 	(void) snprintf(p, plen, "%s%c%s", name, ISCSI_TEXT_SEPARATOR, val);
    371 	*current_length = dlen + plen;
    372 
    373 	return (True);
    374 }
    375 
    376 static void
    377 send_named_msg(iscsi_conn_t *c, msg_type_t t, char *name)
    378 {
    379 	target_queue_t	*q = queue_alloc();
    380 	msg_t		*m;
    381 	name_request_t	n;
    382 
    383 	n.nr_q		= q;
    384 	n.nr_name	= name;
    385 
    386 	queue_message_set(c->c_sessq, 0, t, &n);
    387 	m = queue_message_get(q);
    388 	queue_message_free(m);
    389 	queue_free(q, NULL);
    390 }
    391 
    392 static Boolean_t
    393 parse_digest_vals(Boolean_t *bp, char *name, char *val, char **text, int *len)
    394 {
    395 	Boolean_t	rval;
    396 
    397 	/*
    398 	 * It's the initiators data so we'll allow them
    399 	 * to determine if CRC checks should be enabled
    400 	 * or not. So, look at the first token, which
    401 	 * declares their preference, and use that.
    402 	 */
    403 	if (strncmp(val, CRC32_STR, strlen(CRC32_STR)) == 0) {
    404 		*bp = True;
    405 		rval = add_text(text, len, name, CRC32_STR);
    406 	} else if (strncmp(val, NONE_STR, strlen(NONE_STR)) == 0) {
    407 		*bp = False;
    408 		rval = add_text(text, len, name, NONE_STR);
    409 	} else {
    410 		*bp = False;
    411 		rval = add_text(text, len, name, "Reject");
    412 	}
    413 
    414 	return (rval);
    415 }
    416 
    417 /*
    418  * []----
    419  * | parse_text -- receive text information from initiator and parse
    420  * |
    421  * | Read in the current data based on the amount which the login PDU says
    422  * | should be available. Add it to the end of previous data if it exists.
    423  * | Previous data would be from a PDU which had the 'C' bit set and was
    424  * | stored in the connection.
    425  * |
    426  * | Once values for parameter name has been selected store outgoing string
    427  * | in text message for response.
    428  * |
    429  * | If errcode is non-NULL the appropriate login error code will be
    430  * | stored.
    431  * []----
    432  */
    433 Boolean_t
    434 parse_text(iscsi_conn_t *c, int dlen, char **text, int *text_length,
    435     int *errcode)
    436 {
    437 	char		*p		= NULL;
    438 	char		*n;
    439 	char		*cur_pair;
    440 	char		param_rsp[32];
    441 	int		plen;		/* pair length */
    442 	Boolean_t	rval		= True;
    443 	char		*target_name    = NULL;
    444 	char		*initiator_name = NULL;
    445 	char		param_buf[16];
    446 
    447 	if ((p = (char *)malloc(dlen)) == NULL)
    448 		return (False);
    449 
    450 	/*
    451 	 * Read in data to buffer.
    452 	 */
    453 	if (read(c->c_fd, p, dlen) != dlen) {
    454 		free(p);
    455 		return (False);
    456 	}
    457 
    458 	queue_prt(c->c_mgmtq, Q_CONN_NONIO, "CON%x  Available text size %d\n",
    459 	    c->c_num, dlen);
    460 
    461 	/*
    462 	 * Read in and toss any pad data
    463 	 */
    464 	if (dlen % ISCSI_PAD_WORD_LEN) {
    465 		char junk[ISCSI_PAD_WORD_LEN];
    466 		int pad_len = ISCSI_PAD_WORD_LEN - (dlen % ISCSI_PAD_WORD_LEN);
    467 
    468 		if (read(c->c_fd, junk, pad_len) != pad_len) {
    469 			free(p);
    470 			return (False);
    471 		}
    472 	}
    473 
    474 	if (c->c_text_area != NULL) {
    475 		if ((n = (char *)realloc(c->c_text_area,
    476 		    c->c_text_len + dlen)) == NULL) {
    477 			free(p);
    478 			return (False);
    479 		}
    480 		bcopy(p, n + c->c_text_len, dlen);
    481 
    482 		/*
    483 		 * No longer need the space allocated to 'p' since it
    484 		 * will point to the aggregated area of all data.
    485 		 */
    486 		free(p);
    487 
    488 		/*
    489 		 * Point 'p' to this new area for parsing and save the
    490 		 * combined length in dlen.
    491 		 */
    492 		p = n;
    493 		dlen += c->c_text_len;
    494 
    495 		/*
    496 		 * Clear the indication that space has been allocated
    497 		 */
    498 		c->c_text_area = NULL;
    499 		c->c_text_len = 0;
    500 	}
    501 
    502 	/*
    503 	 * At this point 'p' points to the name/value parameters. Need
    504 	 * to cycle through each pair.
    505 	 */
    506 	n = p;
    507 	while (dlen > 0) {
    508 		cur_pair = n;
    509 
    510 		plen = strlen(n);
    511 		if ((n = strchr(cur_pair, ISCSI_TEXT_SEPARATOR)) == NULL) {
    512 			if (errcode != NULL)
    513 				*errcode =
    514 				    (ISCSI_STATUS_CLASS_INITIATOR_ERR << 8) |
    515 				    ISCSI_LOGIN_STATUS_INIT_ERR;
    516 			rval = False;
    517 			break;
    518 		} else
    519 			*n++ = '\0';
    520 
    521 		queue_prt(c->c_mgmtq, Q_CONN_LOGIN, "CON%x    %-24s = %s\n",
    522 		    c->c_num, cur_pair, n);
    523 
    524 		/*
    525 		 * At this point, 'cur_pair' points at the name and 'n'
    526 		 * points at the value.
    527 		 */
    528 
    529 		/*
    530 		 * []--------------------------------------------------[]
    531 		 * | The order of parameters processed matches the	|
    532 		 * | the RFC in section 12.				|
    533 		 * []--------------------------------------------------[]
    534 		 */
    535 		/*
    536 		 * 12.1 -- HeaderDigest
    537 		 * Negotiated
    538 		 */
    539 		if (strcmp("HeaderDigest", cur_pair) == 0) {
    540 
    541 			rval = parse_digest_vals(&c->c_header_digest,
    542 			    cur_pair, n, text, text_length);
    543 
    544 		/*
    545 		 * 12.1 -- DataDigest
    546 		 * Negotiated
    547 		 */
    548 		} else if (strcmp("DataDigest", cur_pair) == 0) {
    549 
    550 			rval = parse_digest_vals(&c->c_data_digest, cur_pair,
    551 			    n, text, text_length);
    552 
    553 		/*
    554 		 * 12.2 -- MaxConnections
    555 		 * Negotiated
    556 		 */
    557 		} else if (strcmp("MaxConnections", cur_pair) == 0) {
    558 
    559 			/* ---- To be fixed ---- */
    560 			c->c_max_connections = 1;
    561 			(void) snprintf(param_rsp, sizeof (param_rsp),
    562 			    "%d", c->c_max_connections);
    563 			rval = add_text(text, text_length,
    564 			    cur_pair, param_rsp);
    565 
    566 		/*
    567 		 * 12.3 -- SendTargets
    568 		 * Declarative
    569 		 */
    570 		} else if (strcmp("SendTargets", cur_pair) == 0) {
    571 
    572 			if ((c->c_sess->s_type != SessionDiscovery) &&
    573 			    (strcmp("All", n) == 0)) {
    574 				rval = add_text(text, text_length, cur_pair,
    575 				    "Irrelevant");
    576 			} else {
    577 				rval = add_targets(c, text, text_length);
    578 			}
    579 
    580 		/*
    581 		 * 12.4 -- TargetName
    582 		 * Declarative
    583 		 */
    584 		} else if (strcmp("TargetName", cur_pair) == 0) {
    585 
    586 			send_named_msg(c, msg_target_name, n);
    587 			target_name = n;
    588 
    589 		/*
    590 		 * 12.5 -- IntiatorName
    591 		 * Declarative
    592 		 */
    593 		} else if (strcmp("InitiatorName", cur_pair) == 0) {
    594 
    595 			send_named_msg(c, msg_initiator_name, n);
    596 			initiator_name = n;
    597 
    598 		/* ---- Section 12.6 is handled within TargetName ---- */
    599 
    600 		/*
    601 		 * 12.7 -- InitiatorAlias
    602 		 * Declarative
    603 		 */
    604 		} else if (strcmp("InitiatorAlias", cur_pair) == 0) {
    605 
    606 			send_named_msg(c, msg_initiator_alias, n);
    607 
    608 		/*
    609 		 * Sections 12.8 (TargetAddress) and 12.9
    610 		 * (TargetPortalGroupTag) are handled during the SendTargets
    611 		 * processing.
    612 		 */
    613 
    614 		/*
    615 		 * 12.10 -- IntialR2T
    616 		 * Negotiated
    617 		 */
    618 		} else if (strcmp("InitialR2T", cur_pair) == 0) {
    619 
    620 			c->c_initialR2T = True;
    621 			rval = add_text(text, text_length, cur_pair, "Yes");
    622 
    623 		/*
    624 		 * 12.11 -- ImmediateData
    625 		 * Negotiated
    626 		 */
    627 		} else if (strcmp("ImmediateData", cur_pair) == 0) {
    628 
    629 			/*
    630 			 * Since we can handle immediate data without
    631 			 * a problem just echo back what the initiator
    632 			 * sends. If the initiator decides to violate
    633 			 * the spec by sending immediate data even though
    634 			 * they've disabled it, it's their problem and
    635 			 * we'll deal with the data.
    636 			 */
    637 			c->c_immediate_data = strcmp(n, "No") ? True : False;
    638 			rval = add_text(text, text_length, cur_pair, n);
    639 
    640 		/*
    641 		 * 12.12 -- MaxRecvDataSegmentLength
    642 		 * Declarative
    643 		 */
    644 		} else if (strcmp("MaxRecvDataSegmentLength", cur_pair) == 0) {
    645 
    646 			c->c_max_recv_data = strtol(n, NULL, 0);
    647 			rval = add_text(text, text_length, cur_pair, n);
    648 
    649 		/*
    650 		 * 12.13 -- MaxBurstLength
    651 		 * Negotiated
    652 		 */
    653 		} else if (strcmp("MaxBurstLength", cur_pair) == 0) {
    654 
    655 			c->c_max_burst_len = strtol(n, NULL, 0);
    656 			rval = add_text(text, text_length, cur_pair, n);
    657 
    658 		/*
    659 		 * 12.14 -- FirstBurstLength
    660 		 * Negotiated
    661 		 */
    662 		} else if (strcmp("FirstBurstLength", cur_pair) == 0) {
    663 
    664 			/*
    665 			 * We can handle anything the initiator wishes
    666 			 * to shove in our direction. So, store the value
    667 			 * in case we ever wish to validate input data,
    668 			 * but there's no real need to do so.
    669 			 */
    670 			c->c_first_burst_len = strtol(n, NULL, 0);
    671 			rval = add_text(text, text_length, cur_pair, n);
    672 
    673 		/*
    674 		 * 12.15 DefaultTime2Wait
    675 		 * Negotiated
    676 		 */
    677 		} else if (strcmp("DefaultTime2Wait", cur_pair) == 0) {
    678 
    679 			c->c_default_time_2_wait = strtol(n, NULL, 0);
    680 			rval = add_text(text, text_length, cur_pair, n);
    681 
    682 		/*
    683 		 * 12.16 -- DefaultTime2Retain
    684 		 * Negotiated
    685 		 */
    686 		} else if (strcmp("DefaultTime2Retain", cur_pair) == 0) {
    687 
    688 			c->c_default_time_2_retain = strtol(n, NULL, 0);
    689 			rval = add_text(text, text_length, cur_pair, n);
    690 
    691 		/*
    692 		 * 12.17 -- MaxOutstandingR2T
    693 		 * Negotiated
    694 		 */
    695 		} else if (strcmp("MaxOutstandingR2T", cur_pair) == 0) {
    696 
    697 			/*
    698 			 * Save the value, but at most we'll toss out
    699 			 * one R2T packet.
    700 			 */
    701 			c->c_max_outstanding_r2t = strtol(n, NULL, 0);
    702 			rval = add_text(text, text_length, cur_pair, n);
    703 
    704 		/*
    705 		 * 12.18 -- DataPDUInOder
    706 		 * Negotiated
    707 		 */
    708 		} else if (strcmp("DataPDUInOrder", cur_pair) == 0) {
    709 
    710 			/*
    711 			 * We can handle DataPDU's out of order and
    712 			 * currently we'll only send them in order. We're
    713 			 * to far removed from the hardware to see data
    714 			 * coming off of the platters out of order so
    715 			 * it's unlikely we'd ever implement this feature.
    716 			 * Store the parameter and echo back the initiators
    717 			 * request.
    718 			 */
    719 			c->c_data_pdu_in_order = strcmp(n, "Yes") == 0 ?
    720 			    True : False;
    721 			rval = add_text(text, text_length, cur_pair, n);
    722 
    723 		/*
    724 		 * 12.19 -- DataSequenceInOrder
    725 		 * Negotiated
    726 		 */
    727 		} else if (strcmp("DataSequenceInOrder", cur_pair) == 0) {
    728 
    729 			/*
    730 			 * Currently we're set up to look at and require
    731 			 * PDU sequence numbers be in order. The check
    732 			 * now is only done as a prelude to supporting
    733 			 * MC/S and guaranteeing the order of incoming
    734 			 * packets on different connections.
    735 			 */
    736 			c->c_data_sequence_in_order = True;
    737 			rval = add_text(text, text_length, cur_pair, "Yes");
    738 
    739 		/*
    740 		 * 12.20 -- ErrorRecoveryLevel
    741 		 * Negotiated
    742 		 */
    743 		} else if (strcmp("ErrorRecoveryLevel", cur_pair) == 0) {
    744 
    745 			c->c_erl = 0;
    746 			(void) snprintf(param_rsp, sizeof (param_rsp),
    747 			    "%d", c->c_erl);
    748 			rval = add_text(text, text_length,
    749 			    cur_pair, param_rsp);
    750 
    751 		/*
    752 		 * 12.21 -- SessionType
    753 		 * Declarative
    754 		 */
    755 		} else if (strcmp("SessionType", cur_pair) == 0) {
    756 
    757 			c->c_sess->s_type = strcmp(n, "Discovery") == 0 ?
    758 			    SessionDiscovery : SessionNormal;
    759 
    760 
    761 		/*
    762 		 * Appendix A 3.1 -- IFMarker
    763 		 * Negotiated
    764 		 */
    765 		} else if (strcmp("IFMarker", cur_pair) == 0) {
    766 
    767 			c->c_ifmarker = False;
    768 			rval = add_text(text, text_length, cur_pair, "No");
    769 
    770 		/*
    771 		 * Appendix A 3.1 -- OFMarker
    772 		 * Negotiated
    773 		 */
    774 		} else if (strcmp("OFMarker", cur_pair) == 0) {
    775 
    776 			c->c_ofmarker = False;
    777 			rval = add_text(text, text_length, cur_pair, "No");
    778 
    779 		} else if ((strcmp("AuthMethod", cur_pair) == 0) ||
    780 		    (strcmp("CHAP_A", cur_pair) == 0) ||
    781 		    (strcmp("CHAP_I", cur_pair) == 0) ||
    782 		    (strcmp("CHAP_C", cur_pair) == 0) ||
    783 		    (strcmp("CHAP_N", cur_pair) == 0) ||
    784 		    (strcmp("CHAP_R", cur_pair) == 0)) {
    785 
    786 			rval = add_text(&(c->auth_text), &c->auth_text_length,
    787 			    cur_pair, n);
    788 
    789 		} else {
    790 
    791 			/*
    792 			 * It's perfectly legitimate for an initiator to
    793 			 * send us a parameter we don't currently understand.
    794 			 * For example, an initiator that supports iSER will
    795 			 * send an RDMA options parameter. If we respond with
    796 			 * a valid return value it knows to switch to iSER
    797 			 * for future processing.
    798 			 */
    799 			rval = add_text(text, text_length,
    800 			    cur_pair, "NotUnderstood");
    801 
    802 			/*
    803 			 * Go ahead a log this information in case we see
    804 			 * something unexpected.
    805 			 */
    806 			queue_prt(c->c_mgmtq, Q_CONN_ERRS,
    807 			    "CON%x  Unknown parameter %s=%s\n",
    808 			    c->c_num, cur_pair, n);
    809 		}
    810 
    811 		/*
    812 		 * If parsed both Initiator and Target names have been parsed,
    813 		 * then it is now time to load the connection parameters.
    814 		 *
    815 		 * This may fail because the target doesn't exist or the
    816 		 * initiator doesn't have permission to access this target.
    817 		 */
    818 		if ((target_name != NULL) && (initiator_name != NULL)) {
    819 			if ((rval = connection_parameters_get(c, target_name))
    820 			    == False) {
    821 				if ((errcode != NULL) && (*errcode == 0))
    822 					*errcode =
    823 					    (ISCSI_STATUS_CLASS_INITIATOR_ERR
    824 					    << 8) |
    825 					    ISCSI_LOGIN_STATUS_TGT_FORBIDDEN;
    826 			} else if ((rval = add_text(text, text_length,
    827 			    "TargetAlias", c->c_targ_alias)) == True) {
    828 
    829 				/*
    830 				 * Add TPGT now
    831 				 */
    832 				(void) snprintf(param_buf, sizeof (param_buf),
    833 				    "%d", c->c_tpgt);
    834 				rval = add_text(text, text_length,
    835 				    "TargetPortalGroupTag", param_buf);
    836 				target_name = initiator_name = NULL;
    837 			}
    838 		}
    839 
    840 		if (rval == False) {
    841 			/*
    842 			 * Make sure the caller wants error status and that it
    843 			 * hasn't already been set.
    844 			 */
    845 			if ((errcode != NULL) && (*errcode == 0))
    846 				*errcode =
    847 				    (ISCSI_STATUS_CLASS_TARGET_ERR << 8) |
    848 				    ISCSI_LOGIN_STATUS_TARGET_ERROR;
    849 			break;
    850 		}
    851 
    852 		/*
    853 		 * next pair of parameters. 1 is added to include the NULL
    854 		 * byte and the end of each string.
    855 		 */
    856 		n = cur_pair + plen + 1;
    857 		dlen -= (plen + 1);
    858 	}
    859 
    860 	if (p != NULL)
    861 		free(p);
    862 
    863 	return (rval);
    864 }
    865 
    866 /*
    867  * Pre-seed connection parameters to default values
    868  * See RFC 3720 Section 12
    869  */
    870 void
    871 connection_parameters_default(iscsi_conn_t *c)
    872 {
    873 	c->c_max_connections = 1;		/* MaxConnections */
    874 	c->c_tpgt = 1;				/* TargetPortalGroupTag */
    875 	c->c_initialR2T = True;			/* InitialR2T */
    876 	c->c_immediate_data = True;		/* ImmediateData */
    877 	c->c_max_recv_data = 8192;		/* MaxRecvDataSegmentLength */
    878 	c->c_max_burst_len = 262144;		/* MaxBurstLength */
    879 	c->c_first_burst_len = 65536;		/* FirstBurstLength */
    880 	c->c_default_time_2_wait = 2;		/* DefaultTime2Wait */
    881 	c->c_default_time_2_retain = 20;	/* DefaultTime2Retain */
    882 	c->c_max_outstanding_r2t = 1;		/* MaxOutStandingR2T */
    883 	c->c_data_pdu_in_order = True;		/* DataPDUInOrder */
    884 	c->c_data_sequence_in_order = True;	/* DataSequenceOrder */
    885 	c->c_erl = 0;				/* ErrorRecoveryLevel */
    886 }
    887 
    888 /*
    889  * []----
    890  * | find_main_tpgt -- Looks up the IP address and finds a match TPGT
    891  * |
    892  * | If no TPGT for this address exists the routine returns 0 which
    893  * | is an illegal TPGT value.
    894  * []----
    895  */
    896 static int
    897 find_main_tpgt(struct sockaddr_storage *pst)
    898 {
    899 	char		ip_addr[16];
    900 	tgt_node_t	*tpgt				= NULL;
    901 	tgt_node_t	*ip_node			= NULL;
    902 	struct in_addr	addr;
    903 	struct in6_addr	addr6;
    904 
    905 	/*
    906 	 * Hardly can you believe that such struct-to-struct
    907 	 * assignment IS valid.
    908 	 */
    909 	addr = ((struct sockaddr_in *)pst)->sin_addr;
    910 	addr6 = ((struct sockaddr_in6 *)pst)->sin6_addr;
    911 
    912 	while ((tpgt = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
    913 	    tpgt)) != NULL) {
    914 
    915 		ip_node = NULL;
    916 		while ((ip_node = tgt_node_next(tpgt, XML_ELEMENT_IPADDR,
    917 		    ip_node)) != NULL) {
    918 
    919 			if (pst->ss_family == AF_INET) {
    920 
    921 				if (inet_pton(AF_INET, ip_node->x_value,
    922 				    ip_addr) != 1) {
    923 					continue;
    924 				}
    925 				if (bcmp(ip_addr, &addr,
    926 					sizeof (struct in_addr)) == 0) {
    927 					return (atoi(tpgt->x_value));
    928 				}
    929 			} else if (pst->ss_family == AF_INET6) {
    930 
    931 				if (inet_pton(AF_INET6, ip_node->x_value,
    932 				    ip_addr) != 1) {
    933 					continue;
    934 				}
    935 				if (bcmp(ip_addr, &addr6,
    936 					sizeof (struct in6_addr)) == 0) {
    937 					return (atoi(tpgt->x_value));
    938 				}
    939 			}
    940 		}
    941 	}
    942 
    943 	return (0);
    944 }
    945 
    946 /*
    947  * convert_to_tpgt -- return a TPGT based on the target address
    948  *
    949  * If a target doesn't have a TPGT list then just return the default
    950  * value of 1. Otherwise determine which TPGT the target address is
    951  * part of and find that TPGT value in the list of TPGTs this target
    952  * is willing to expose. If the TPGT value is not found in the list
    953  * return zero which will break the connection.
    954  */
    955 static int
    956 convert_to_tpgt(iscsi_conn_t *c, tgt_node_t *targ)
    957 {
    958 	tgt_node_t	*list;
    959 	tgt_node_t	*tpgt		= NULL;
    960 	int		addr_tpgt, pos_tpgt;
    961 
    962 	/*
    963 	 * If this target doesn't have a list of target portal group tags
    964 	 * just return the default which is 1.
    965 	 */
    966 	list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL);
    967 	if (list == NULL)
    968 		return (1);
    969 
    970 	/*
    971 	 * If we don't find our IP in the general configuration list
    972 	 * we'll use the default value which is 1 according to RFC3720.
    973 	 */
    974 	addr_tpgt = find_main_tpgt(&(c->c_target_sockaddr));
    975 
    976 	while ((tpgt = tgt_node_next(list, XML_ELEMENT_TPGT, tpgt)) != NULL) {
    977 		(void) tgt_find_value_int(tpgt, XML_ELEMENT_TPGT, &pos_tpgt);
    978 		if (pos_tpgt == addr_tpgt) {
    979 			return (addr_tpgt);
    980 		}
    981 	}
    982 
    983 	return (0);
    984 }
    985 
    986 /*
    987  * []----
    988  * | find_target_node -- given a target IQN name, return the XML node
    989  * []----
    990  */
    991 tgt_node_t *
    992 find_target_node(char *targ_name)
    993 {
    994 	tgt_node_t	*tnode	= NULL;
    995 	char		*iname;
    996 
    997 	while ((tnode = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
    998 	    tnode)) != NULL) {
    999 		if (tgt_find_value_str(tnode, XML_ELEMENT_INAME, &iname) ==
   1000 		    True) {
   1001 			if (strcmp(iname, targ_name) == 0) {
   1002 				free(iname);
   1003 				return (tnode);
   1004 			} else
   1005 				free(iname);
   1006 		}
   1007 	}
   1008 
   1009 	return (NULL);
   1010 }
   1011 
   1012 static Boolean_t
   1013 connection_parameters_get(iscsi_conn_t *c, char *targ_name)
   1014 {
   1015 	tgt_node_t	*targ, *alias;
   1016 	Boolean_t	rval	= False;
   1017 
   1018 	(void) pthread_rwlock_rdlock(&targ_config_mutex);
   1019 	if ((targ = find_target_node(targ_name)) != NULL) {
   1020 
   1021 		if (check_access(targ, c->c_sess->s_i_name, False) == False) {
   1022 			(void) pthread_rwlock_unlock(&targ_config_mutex);
   1023 			return (False);
   1024 		}
   1025 
   1026 		/*
   1027 		 * Have a valid node for our target. Start looking
   1028 		 * for connection oriented parameters.
   1029 		 */
   1030 		if ((c->c_tpgt = convert_to_tpgt(c, targ)) == 0) {
   1031 			(void) pthread_rwlock_unlock(&targ_config_mutex);
   1032 			return (False);
   1033 		}
   1034 		if ((alias = tgt_node_next(targ, XML_ELEMENT_ALIAS, NULL)) ==
   1035 		    NULL) {
   1036 			(void) tgt_find_value_str(targ, XML_ELEMENT_TARG,
   1037 			    &c->c_targ_alias);
   1038 		} else {
   1039 			(void) tgt_find_value_str(alias, XML_ELEMENT_ALIAS,
   1040 			    &c->c_targ_alias);
   1041 		}
   1042 
   1043 		(void) tgt_find_value_int(targ, XML_ELEMENT_MAXCMDS,
   1044 		    &c->c_maxcmdsn);
   1045 		rval = True;
   1046 	}
   1047 
   1048 	(void) pthread_rwlock_unlock(&targ_config_mutex);
   1049 	return (rval);
   1050 }
   1051 
   1052 Boolean_t
   1053 validate_version(tgt_node_t *node, int *maj_p, int *min_p)
   1054 {
   1055 	char	*vers_str	= NULL;
   1056 	char	*minor_part;
   1057 	int	maj, min;
   1058 
   1059 	if ((tgt_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) ||
   1060 	    (vers_str == NULL))
   1061 		return (False);
   1062 
   1063 	maj = strtol(vers_str, &minor_part, 0);
   1064 	if ((maj > *maj_p) || (minor_part == NULL) || (*minor_part != '.')) {
   1065 		free(vers_str);
   1066 		return (False);
   1067 	}
   1068 
   1069 	min	= strtol(&minor_part[1], NULL, 0);
   1070 	*maj_p	= maj;
   1071 	*min_p	= min;
   1072 	free(vers_str);
   1073 
   1074 	return (True);
   1075 }
   1076 
   1077 /*
   1078  * []----
   1079  * | sna_lt -- Serial Number Arithmetic, 32 bits, less than, RFC1982
   1080  * []----
   1081  */
   1082 int
   1083 sna_lt(uint32_t n1, uint32_t n2)
   1084 {
   1085 	return ((n1 != n2) &&
   1086 	    (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) ||
   1087 	    ((n1 > n2) && ((n1 - n2) > SNA32_CHECK))));
   1088 }
   1089 
   1090 /*
   1091  * []----
   1092  * sna_lte -- Serial Number Arithmetic, 32 bits, less than, RFC1982
   1093  * []----
   1094  */
   1095 int
   1096 sna_lte(uint32_t n1, uint32_t n2)
   1097 {
   1098 	return ((n1 == n2) ||
   1099 	    (((n1 < n2) && ((n2 - n1) < SNA32_CHECK)) ||
   1100 	    ((n1 > n2) && ((n1 - n2) > SNA32_CHECK))));
   1101 }
   1102 
   1103 /*
   1104  * util_create_guid -- generate GUID based on the guid type
   1105  * id_type:	SPC_INQUIRY_ID_TYPE_EUI -
   1106  *		EUI-64 based 16-byte designator format;
   1107  *		SPC_INQUIRY_ID_TYPE_NAA -
   1108  *		NAA IEEE Registered Extended designator format.
   1109  *
   1110  * SPC-4 revision 11 section 7.6.3.5.4 and 7.6.3.6.5.
   1111  *
   1112  * Note that now this function is always called with parameter
   1113  * id_type SPC_INQUIRY_ID_TYPE_NAA, therefore the code for creating
   1114  * EUI-64 based 16-byte format GUID is no longer used. But in order
   1115  * to keep backward compatiability and for future extension, all the
   1116  * code that has been used for creating old GUIDs should be kept, to
   1117  * make the format clear for all possible GUIDs targets might have.
   1118  */
   1119 Boolean_t
   1120 util_create_guid(char **guid, uchar_t id_type)
   1121 {
   1122 	eui_16_t	eui;
   1123 	/*
   1124 	 * We only have room for 32bits of data in the GUID. The hiword/loword
   1125 	 * macros will not work on 64bit variables. The work, but produce
   1126 	 * invalid results on Big Endian based machines.
   1127 	 */
   1128 	uint32_t	tval = (uint_t)time((time_t *)0);
   1129 	size_t		guid_size;
   1130 	int		i, fd;
   1131 
   1132 	/*
   1133 	 * Create the NAA (6) GUID.
   1134 	 */
   1135 	if (id_type == SPC_INQUIRY_ID_TYPE_NAA) {
   1136 		return (util_create_guid_naa(guid));
   1137 	}
   1138 
   1139 	if ((mac_len == 0) && (if_find_mac(NULL) == False)) {
   1140 
   1141 		/*
   1142 		 * By default strict GUID generation is enforced. This can
   1143 		 * be disabled by using the correct XML tag in the configuration
   1144 		 * file.
   1145 		 */
   1146 		if (enforce_strict_guid == True)
   1147 			return (False);
   1148 
   1149 		/*
   1150 		 * There's no MAC address available and we've even tried
   1151 		 * a second time to get one. So fallback to using a random
   1152 		 * number for the MAC address.
   1153 		 */
   1154 		if ((fd = open("/dev/random", O_RDONLY)) < 0)
   1155 			return (False);
   1156 		if (read(fd, &eui, sizeof (eui)) != sizeof (eui))
   1157 			return (False);
   1158 		(void) close(fd);
   1159 
   1160 		eui.e_vers		= SUN_EUI_16_VERS;
   1161 		eui.e_company_id[0]	= (SUN_EN >> 16) & 0xff;
   1162 		eui.e_company_id[1]	= (SUN_EN >> 8) & 0xff;
   1163 		eui.e_company_id[2]	= SUN_EN & 0xff;
   1164 
   1165 	} else {
   1166 		bzero(&eui, sizeof (eui));
   1167 
   1168 		eui.e_vers	= SUN_EUI_16_VERS;
   1169 		eui.e_company_id[0]	= (SUN_EN >> 16) & 0xff;
   1170 		eui.e_company_id[1]	= (SUN_EN >> 8) & 0xff;
   1171 		eui.e_company_id[2]	= SUN_EN & 0xff;
   1172 		eui.e_timestamp[0]	= hibyte(hiword(tval));
   1173 		eui.e_timestamp[1]	= lobyte(hiword(tval));
   1174 		eui.e_timestamp[2]	= hibyte(loword(tval));
   1175 		eui.e_timestamp[3]	= lobyte(loword(tval));
   1176 		for (i = 0; i < min(mac_len, sizeof (eui.e_mac)); i++) {
   1177 			eui.e_mac[i] = mac_addr[i];
   1178 		}
   1179 
   1180 		/*
   1181 		 * To prevent duplicate GUIDs we need to sleep for one
   1182 		 * second here since part of the GUID is a time stamp with
   1183 		 * a one second resolution.
   1184 		 */
   1185 		(void) sleep(1);
   1186 	}
   1187 
   1188 	if (tgt_xml_encode((uint8_t *)&eui, sizeof (eui), guid,
   1189 	    &guid_size) == False) {
   1190 		return (False);
   1191 	} else
   1192 		return (True);
   1193 }
   1194 
   1195 Boolean_t
   1196 util_create_guid_naa(char **guid)
   1197 {
   1198 	naa_16_t	naa;
   1199 	/*
   1200 	 * We only have room for 32bits of data in the GUID. The hiword/loword
   1201 	 * macros will not work on 64bit variables. The work, but produce
   1202 	 * invalid results on Big Endian based machines.
   1203 	 */
   1204 	uint32_t	tval = (uint_t)time((time_t *)0);
   1205 	size_t		guid_size;
   1206 	int		i, fd;
   1207 
   1208 	if ((mac_len == 0) && (if_find_mac(NULL) == False)) {
   1209 
   1210 		/*
   1211 		 * By default strict GUID generation is enforced. This can
   1212 		 * be disabled by using the correct XML tag in the configuration
   1213 		 * file.
   1214 		 */
   1215 		if (enforce_strict_guid == True)
   1216 			return (False);
   1217 
   1218 		/*
   1219 		 * There's no MAC address available and we've even tried
   1220 		 * a second time to get one. So fallback to using a random
   1221 		 * number for the MAC address.
   1222 		 */
   1223 		if ((fd = open("/dev/random", O_RDONLY)) < 0)
   1224 			return (False);
   1225 		if (read(fd, &naa, sizeof (naa)) != sizeof (naa))
   1226 			return (False);
   1227 		(void) close(fd);
   1228 
   1229 	} else {
   1230 		bzero(&naa, sizeof (naa));
   1231 
   1232 		/*
   1233 		 * Set vendor specific identifier and extension.
   1234 		 */
   1235 		naa.n_timestamp[0]	= hibyte(hiword(tval));
   1236 		naa.n_timestamp[1]	= lobyte(hiword(tval));
   1237 		naa.n_timestamp[2]	= hibyte(loword(tval));
   1238 		naa.n_timestamp[3]	= lobyte(loword(tval));
   1239 		for (i = 0; i < min(mac_len, sizeof (naa.n_mac)); i++) {
   1240 			naa.n_mac[i] = mac_addr[i];
   1241 		}
   1242 
   1243 		/*
   1244 		 * To prevent duplicate GUIDs we need to sleep for one
   1245 		 * second here since part of the GUID is a time stamp with
   1246 		 * a one second resolution.
   1247 		 */
   1248 		(void) sleep(1);
   1249 	}
   1250 
   1251 	/*
   1252 	 * Set NAA (6) and IEEE Company_ID.
   1253 	 */
   1254 	naa.n_naa		= SUN_NAA_16_TYPE;
   1255 	naa.n_company_id_hi	= (SUN_EN >> 20) & 0x0f;
   1256 	naa.n_company_id_b1	= (SUN_EN >> 12) & 0xff;
   1257 	naa.n_company_id_b2	= (SUN_EN >> 4) & 0xff;
   1258 	naa.n_company_id_lo	= SUN_EN & 0x0f;
   1259 	if (tgt_xml_encode((uint8_t *)&naa, sizeof (naa), guid,
   1260 	    &guid_size) == False) {
   1261 		return (False);
   1262 	} else
   1263 		return (True);
   1264 }
   1265 
   1266 /*
   1267  * []----
   1268  * | create_geom -- based on size, determine best fit for CHS
   1269  * |
   1270  * | Given size in bytes, which will be adjusted to blocks, find
   1271  * | the best fit for making (C * H * S == blocks)
   1272  * |
   1273  * | Note that the following algorithm was derived from the
   1274  * | common disk label implementation, cmlb_convert_geometry().
   1275  * |
   1276  * []----
   1277  */
   1278 void
   1279 create_geom(diskaddr_t size, int *cylinders, int *heads, int *spt)
   1280 {
   1281 	diskaddr_t	blocks = size >> 9;  /* 512 bytes/block */
   1282 
   1283 	/*
   1284 	 * For all devices we calculate cylinders using the heads and sectors
   1285 	 * we assign based on capacity of the device.  The algorithm is
   1286 	 * designed to be compatible with the way other operating systems
   1287 	 * lay out fdisk tables for X86 and to insure that the cylinders never
   1288 	 * exceed 65535 to prevent problems with X86 ioctls that report
   1289 	 * geometry.
   1290 	 * For some smaller disk sizes we report geometry that matches those
   1291 	 * used by X86 BIOS usage. For larger disks, we use SPT that are
   1292 	 * multiples of 63, since other OSes that are not limited to 16-bits
   1293 	 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
   1294 	 *
   1295 	 * The following table (in order) illustrates some end result
   1296 	 * calculations:
   1297 	 *
   1298 	 * Maximum number of blocks	nhead	nsect
   1299 	 *
   1300 	 * 2097152 (1GB)		 64	 32
   1301 	 * 16777216 (8GB)		128	 32
   1302 	 * 1052819775 (502.02GB)	255	 63
   1303 	 * 2105639550 (0.98TB)		255	126
   1304 	 * 3158459325 (1.47TB)		255	189
   1305 	 * 4211279100 (1.96TB)		255	252
   1306 	 * 5264098875 (2.45TB)		255	315
   1307 	 * ...
   1308 	 */
   1309 
   1310 	if (blocks <= 0x200000) {
   1311 		*heads = 64;
   1312 		*spt = 32;
   1313 	} else if (blocks <= 0x01000000) {
   1314 		*heads = 128;
   1315 		*spt = 32;
   1316 	} else {
   1317 		*heads = 255;
   1318 
   1319 		/* make sectors-per-track be smallest multiple of 63 */
   1320 		*spt = ((blocks +
   1321 		    (UINT16_MAX * 255 * 63) - 1) /
   1322 		    (UINT16_MAX * 255 * 63)) * 63;
   1323 
   1324 		if (*spt == 0)
   1325 			*spt = (UINT16_MAX / 63) * 63;
   1326 	}
   1327 
   1328 	/* cyls/dsk = (sectors/dsk) / (sectors/trk * tracks/cyl) */
   1329 	*cylinders = blocks / (*spt * *heads);
   1330 }
   1331 
   1332 /*
   1333  * []----
   1334  * | strtol_multiplier -- common method to deal with human type numbers
   1335  * []----
   1336  */
   1337 Boolean_t
   1338 strtoll_multiplier(char *str, uint64_t *sp)
   1339 {
   1340 	char		*m;
   1341 	uint64_t	size;
   1342 
   1343 	size = strtoll(str, &m, 0);
   1344 	if (m && *m) {
   1345 		switch (*m) {
   1346 		case 't':
   1347 		case 'T':
   1348 			size *= 1024;
   1349 			/*FALLTHRU*/
   1350 		case 'g':
   1351 		case 'G':
   1352 			size *= 1024;
   1353 			/*FALLTHRU*/
   1354 		case 'm':
   1355 		case 'M':
   1356 			size *= 1024;
   1357 			/*FALLTHRU*/
   1358 		case 'k':
   1359 		case 'K':
   1360 			size *= 1024;
   1361 			break;
   1362 
   1363 		default:
   1364 			return (False);
   1365 		}
   1366 	}
   1367 
   1368 	*sp = size;
   1369 	return (True);
   1370 }
   1371 
   1372 /*
   1373  * []----
   1374  * | util_title -- print out start/end title in consistent manner
   1375  * []----
   1376  */
   1377 void
   1378 util_title(target_queue_t *q, int type, int num, char *title)
   1379 {
   1380 	char	*type_str;
   1381 	int	len, pad;
   1382 
   1383 	len	= strlen(title);
   1384 	pad	= len & 1;
   1385 
   1386 	switch (type) {
   1387 	case Q_CONN_LOGIN:
   1388 	case Q_CONN_NONIO:
   1389 		type_str	= "CON";
   1390 		break;
   1391 
   1392 	case Q_SESS_LOGIN:
   1393 	case Q_SESS_NONIO:
   1394 		type_str	= "SES";
   1395 		break;
   1396 
   1397 	case Q_STE_NONIO:
   1398 		type_str	= "SAM";
   1399 		break;
   1400 
   1401 	default:
   1402 		type_str	= "UGH";
   1403 		break;
   1404 	}
   1405 
   1406 	queue_prt(q, type, "%s%x  ---- %*s%s%*s ----\n", type_str, num,
   1407 	    ((60 - len) / 2), "", title, ((60 - len) / 2) + pad, "");
   1408 }
   1409 
   1410 /*
   1411  * []----
   1412  * | task_to_str -- convert task management event to string (DEBUG USE)
   1413  * []----
   1414  */
   1415 char *
   1416 task_to_str(int func)
   1417 {
   1418 	switch (func) {
   1419 	case ISCSI_TM_FUNC_ABORT_TASK:		return ("Abort");
   1420 	case ISCSI_TM_FUNC_ABORT_TASK_SET:	return ("Abort Set");
   1421 	case ISCSI_TM_FUNC_CLEAR_ACA:		return ("Clear ACA");
   1422 	case ISCSI_TM_FUNC_CLEAR_TASK_SET:	return ("Clear Task");
   1423 	case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:	return ("LUN Reset");
   1424 	case ISCSI_TM_FUNC_TARGET_WARM_RESET:	return ("Target Warm Reset");
   1425 	case ISCSI_TM_FUNC_TARGET_COLD_RESET:	return ("Target Cold Reset");
   1426 	case ISCSI_TM_FUNC_TASK_REASSIGN:	return ("Task Reassign");
   1427 	default:				return ("Unknown");
   1428 	}
   1429 }
   1430 
   1431 /*
   1432  * []----
   1433  * | xml_rtn_msg -- create a common format for XML replies to management UI
   1434  * []----
   1435  */
   1436 void
   1437 xml_rtn_msg(char **buf, err_code_t code)
   1438 {
   1439 	char	lbuf[16];
   1440 
   1441 	tgt_buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'");
   1442 	(void) snprintf(lbuf, sizeof (lbuf), "%d", code);
   1443 	tgt_buf_add(buf, XML_ELEMENT_CODE, lbuf);
   1444 	tgt_buf_add(buf, XML_ELEMENT_MESSAGE, errcode_to_str(code));
   1445 	tgt_buf_add_tag(buf, XML_ELEMENT_ERROR, Tag_End);
   1446 }
   1447 
   1448 /*
   1449  * []----
   1450  * | thick_provo_start -- start an initialization thread for targ/lun
   1451  * []----
   1452  */
   1453 void *
   1454 thick_provo_start(void *v)
   1455 {
   1456 	thick_provo_t	*tp	= (thick_provo_t *)v;
   1457 	msg_t		*m;
   1458 	Boolean_t	rval;
   1459 	char		*err	= NULL;
   1460 
   1461 	/*
   1462 	 * Add this threads information to the main queue. This is
   1463 	 * used in case the administrator decides to remove the LU
   1464 	 * before the initialization is complete.
   1465 	 */
   1466 	(void) pthread_mutex_lock(&thick_mutex);
   1467 	if (thick_head == NULL) {
   1468 		thick_head = tp;
   1469 	} else {
   1470 		thick_tail->next = tp;
   1471 		tp->prev = thick_tail;
   1472 	}
   1473 	thick_tail = tp;
   1474 	(void) pthread_mutex_unlock(&thick_mutex);
   1475 
   1476 	/*
   1477 	 * This let's the parent thread know this thread is running.
   1478 	 */
   1479 	queue_message_set(tp->q, 0, msg_mgmt_rply, 0);
   1480 
   1481 	/* ---- Start the initialization of the LU ---- */
   1482 	rval = t10_thick_provision(tp->targ_name, tp->lun, tp->q);
   1483 
   1484 	/* ---- Remove from the linked list ---- */
   1485 	(void) pthread_mutex_lock(&thick_mutex);
   1486 	if (tp->prev == NULL) {
   1487 		assert(tp == thick_head);
   1488 		thick_head = tp->next;
   1489 		if (tp->next == NULL) {
   1490 			assert(tp == thick_tail);
   1491 			thick_tail = NULL;
   1492 		} else
   1493 			tp->next->prev = NULL;
   1494 	} else {
   1495 		tp->prev->next = tp->next;
   1496 		if (tp->next != NULL)
   1497 			tp->next->prev = tp->prev;
   1498 		else
   1499 			thick_tail = tp->prev;
   1500 	}
   1501 	(void) pthread_mutex_unlock(&thick_mutex);
   1502 
   1503 	/*
   1504 	 * There's a race condition where t10_thick_provision() could
   1505 	 * finish and before the thick_mutex lock is grabbed again
   1506 	 * that another thread running the thick_provo_stop() could
   1507 	 * find a match and send a shutdown message. If that happened
   1508 	 * that thread would wait forever in queue_message_get(). So,
   1509 	 * After this target/lun pair has been removed check the message
   1510 	 * queue one last time to see if there's a message available.
   1511 	 * If so, send an ack.
   1512 	 */
   1513 	m = queue_message_try_get(tp->q);
   1514 	if (m != NULL) {
   1515 		assert(m->msg_type == msg_shutdown);
   1516 		queue_message_set((target_queue_t *)m->msg_data, 0,
   1517 		    msg_shutdown_rsp, 0);
   1518 	}
   1519 
   1520 	if (rval == True)
   1521 		iscsi_inventory_change(tp->targ_name);
   1522 	else {
   1523 		queue_prt(mgmtq, Q_GEN_ERRS, "Failed to initialize %s/%d\n",
   1524 		    tp->targ_name, tp->lun);
   1525 		syslog(LOG_ERR, "Failed to initialize %s, LU%d", tp->targ_name,
   1526 		    tp->lun);
   1527 		remove_target_common(tp->targ_name, tp->lun, &err);
   1528 		if (err != NULL) {
   1529 
   1530 			/*
   1531 			 * There's not much we can do here. The most likely
   1532 			 * cause of not being able to remove the target is
   1533 			 * that it's LU 0 and there is currently another
   1534 			 * LU allocated.
   1535 			 */
   1536 			queue_prt(mgmtq, Q_GEN_ERRS,
   1537 			    "Failed to remove target\n");
   1538 			syslog(LOG_ERR, "Failed to remove target/lun after "
   1539 			    "initialization failure");
   1540 		}
   1541 	}
   1542 
   1543 	free(tp->targ_name);
   1544 	queue_free(tp->q, NULL);
   1545 	free(tp);
   1546 
   1547 	queue_message_set(mgmtq, 0, msg_pthread_join,
   1548 	    (void *)(uintptr_t)pthread_self());
   1549 	return (NULL);
   1550 }
   1551 
   1552 /*
   1553  * []----
   1554  * | thick_provo_stop -- stop initialization thread for given targ/lun
   1555  * []----
   1556  */
   1557 void
   1558 thick_provo_stop(char *targ, int lun)
   1559 {
   1560 	thick_provo_t	*tp;
   1561 	target_queue_t	*q	= queue_alloc();
   1562 
   1563 	(void) pthread_mutex_lock(&thick_mutex);
   1564 	tp = thick_head;
   1565 	while (tp) {
   1566 		if ((strcmp(tp->targ_name, targ) == 0) && (tp->lun == lun)) {
   1567 			queue_message_set(tp->q, 0, msg_shutdown, (void *)q);
   1568 			/*
   1569 			 * Drop the global mutex because it's entirely
   1570 			 * possible for a thick_provo_start thread to be
   1571 			 * in the early stages in which it will can call
   1572 			 * thick_provo_chk() from the T10 SAM code.
   1573 			 */
   1574 			(void) pthread_mutex_unlock(&thick_mutex);
   1575 
   1576 			queue_message_free(queue_message_get(q));
   1577 
   1578 			/*
   1579 			 * Pick the lock back up since it'll make the
   1580 			 * finish stage easier to deal with.
   1581 			 */
   1582 			(void) pthread_mutex_lock(&thick_mutex);
   1583 			break;
   1584 		}
   1585 		tp = tp->next;
   1586 	}
   1587 	(void) pthread_mutex_unlock(&thick_mutex);
   1588 	queue_free(q, NULL);
   1589 }
   1590 
   1591 /*
   1592  * []----
   1593  * | thick_provo_chk_thr -- see if there's an initialization thread running
   1594  * []----
   1595  */
   1596 Boolean_t
   1597 thick_provo_chk_thr(char *targ, int lun)
   1598 {
   1599 	thick_provo_t	*tp;
   1600 	Boolean_t	rval = False;
   1601 
   1602 	(void) pthread_mutex_lock(&thick_mutex);
   1603 	tp = thick_head;
   1604 	while (tp) {
   1605 		if ((strcmp(tp->targ_name, targ) == 0) && (tp->lun == lun)) {
   1606 			rval = True;
   1607 			break;
   1608 		}
   1609 		tp = tp->next;
   1610 	}
   1611 	(void) pthread_mutex_unlock(&thick_mutex);
   1612 
   1613 	return (rval);
   1614 }
   1615 
   1616 /*
   1617  * []----
   1618  * | remove_target_common -- remove targ/lun from system.
   1619  * |
   1620  * | This is a common function that's used both by the normal remove
   1621  * | target code and when a write failure occurs during initialization.
   1622  * | It will handle being given either the local target name or the full
   1623  * | IQN name of the target.
   1624  * []----
   1625  */
   1626 void
   1627 remove_target_common(char *name, int lun_num, char **msg)
   1628 {
   1629 	tgt_node_t	*targ			= NULL;
   1630 	tgt_node_t	*list, *lun, *c;
   1631 	char		path[MAXPATHLEN];
   1632 	char		*tname			= NULL;
   1633 	char		*iname			= NULL;
   1634 	int		chk;
   1635 
   1636 	while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
   1637 	    targ)) != NULL) {
   1638 		/* ---- Look for a match on the friendly name ---- */
   1639 		if (strcmp(targ->x_value, name) == 0) {
   1640 			tname = name;
   1641 			break;
   1642 		}
   1643 
   1644 		/* ---- Check to see if they gave the IQN name instead ---- */
   1645 		if ((tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
   1646 		    True) && (strcmp(iname, name) == 0))
   1647 			break;
   1648 		else {
   1649 			free(iname);
   1650 			iname = NULL;
   1651 		}
   1652 	}
   1653 
   1654 	/* ---- Check to see if it's already been removed ---- */
   1655 	if (targ == NULL) {
   1656 		return;
   1657 	}
   1658 
   1659 	/*
   1660 	 * We need both the friendly and IQN names so figure out which wasn't
   1661 	 * given and find it's value.
   1662 	 */
   1663 	if (tname == NULL)
   1664 		tname = targ->x_value;
   1665 	if (iname == NULL) {
   1666 		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) ==
   1667 		    False) {
   1668 			xml_rtn_msg(msg, ERR_INTERNAL_ERROR);
   1669 			return;
   1670 		}
   1671 	}
   1672 
   1673 	if ((list = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL)
   1674 		goto error;
   1675 
   1676 	if (lun_num == 0) {
   1677 
   1678 		/*
   1679 		 * LUN must be the last one removed, so check to
   1680 		 * see if others are still present.
   1681 		 */
   1682 		lun = NULL;
   1683 		while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) !=
   1684 		    NULL) {
   1685 			if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) ==
   1686 			    False)
   1687 				goto error;
   1688 
   1689 			if (chk != lun_num) {
   1690 				xml_rtn_msg(msg, ERR_LUN_ZERO_NOT_LAST);
   1691 				goto error;
   1692 			}
   1693 		}
   1694 	} else {
   1695 
   1696 		/*
   1697 		 * Make sure the LU exists that's being removed
   1698 		 */
   1699 		lun = NULL;
   1700 		while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) !=
   1701 		    NULL) {
   1702 			if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) ==
   1703 			    False)
   1704 				goto error;
   1705 
   1706 			if (chk == lun_num) {
   1707 				lun = tgt_node_alloc(XML_ELEMENT_LUN, Int,
   1708 				    &lun_num);
   1709 				(void) tgt_node_remove(list, lun, MatchBoth);
   1710 				tgt_node_free(lun);
   1711 				break;
   1712 			}
   1713 		}
   1714 		if (lun == NULL) {
   1715 			xml_rtn_msg(msg, ERR_LUN_NOT_FOUND);
   1716 			goto error;
   1717 		}
   1718 	}
   1719 
   1720 	/* ---- Say goodbye to that data ---- */
   1721 	(void) snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir,
   1722 	    iname, LUNBASE, lun_num);
   1723 	(void) unlink(path);
   1724 	(void) snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir,
   1725 	    iname, PARAMBASE, lun_num);
   1726 	(void) unlink(path);
   1727 
   1728 	(void) mgmt_param_remove(tname, lun_num);
   1729 
   1730 	/*
   1731 	 * If the was LUN 0 then do to the previous check
   1732 	 * we know that no other files exist in the target
   1733 	 * directory so the target information can be removed
   1734 	 * along with the directory.
   1735 	 */
   1736 	if (lun_num == 0) {
   1737 		(void) snprintf(path, sizeof (path), "%s/%s", target_basedir,
   1738 		    iname);
   1739 		(void) rmdir(path);
   1740 
   1741 		/*
   1742 		 * Don't forget to remove the symlink to
   1743 		 * the target directory.
   1744 		 */
   1745 		(void) snprintf(path, sizeof (path), "%s/%s", target_basedir,
   1746 		    tname);
   1747 		(void) unlink(path);
   1748 
   1749 		/*
   1750 		 * 'tname' is just a reference to the memory within
   1751 		 * the targets_config structure. So once the tgt_node_remove()
   1752 		 * is called 'tname' is no longer valid.
   1753 		 */
   1754 		c = tgt_node_alloc(XML_ELEMENT_TARG, String, tname);
   1755 		(void) tgt_node_remove(targets_config, c, MatchBoth);
   1756 		tgt_node_free(c);
   1757 	}
   1758 
   1759 	/*
   1760 	 * Not much we can do here if we fail to updated the config.
   1761 	 */
   1762 	if (mgmt_config_save2scf() == False)
   1763 		syslog(LOG_ERR, "Failed to update target configuration!");
   1764 
   1765 error:
   1766 	if (iname != NULL)
   1767 		free(iname);
   1768 }
   1769 
   1770 /*
   1771  * []----
   1772  * | validate_xml
   1773  * |
   1774  * | This function checks if there is predefined entities &<>'" in xml request
   1775  * []----
   1776  */
   1777 Boolean_t
   1778 validate_xml(char *req)
   1779 {
   1780 	in_mark_t in_mark = in_none;
   1781 
   1782 	if (req == NULL)
   1783 		return (False);
   1784 	for (; *req != '\0'; req++) {
   1785 		if (in_mark == in_none) {
   1786 			if (*req == '<') {
   1787 				in_mark = in_lt;
   1788 				continue;
   1789 			} else if (*req == '&') {
   1790 				in_mark = in_amp;
   1791 				continue;
   1792 			} else if (strchr("\"\'>", *req) != NULL) {
   1793 				return (False);
   1794 			}
   1795 		} else if (in_mark == in_lt) {
   1796 			if (*req == '>') {
   1797 				in_mark = in_none;
   1798 				continue;
   1799 			} else if (*req == '<') {
   1800 				return (False);
   1801 			}
   1802 		} else {
   1803 			if (*req == ';') {
   1804 				in_mark = in_none;
   1805 				continue;
   1806 			} else if (*req == '&' || *req == '<') {
   1807 				return (False);
   1808 			}
   1809 		}
   1810 	}
   1811 
   1812 	if (in_mark == in_none)
   1813 		return (True);
   1814 	else
   1815 		return (False);
   1816 }
   1817 
   1818 /*
   1819  * []----
   1820  * | get_local_name
   1821  * |
   1822  * | This function fetches local name from a iscsi-name
   1823  * | Caller is responsible to free the string.
   1824  * []----
   1825  */
   1826 char *
   1827 get_local_name(char *iname)
   1828 {
   1829 	tgt_node_t	*targ = NULL;
   1830 	char		*str;
   1831 	char		*ret = NULL;
   1832 
   1833 	while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
   1834 	    targ)) != NULL) {
   1835 		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &str) == True) {
   1836 			if (strcmp(str, iname) == 0)
   1837 				ret = strdup(targ->x_value);
   1838 			free(str);
   1839 			if (ret != NULL)
   1840 				break;
   1841 		}
   1842 	}
   1843 	return (ret);
   1844 }
   1845