Home | History | Annotate | Download | only in isnsd
      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 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include <libxml/xmlreader.h>
     31 #include <libxml/xmlwriter.h>
     32 #include <libxml/tree.h>
     33 #include <sys/types.h>
     34 #include <sys/socket.h>
     35 #include <netinet/in.h>
     36 #include <arpa/inet.h>
     37 #include <pthread.h>
     38 
     39 #include "isns_server.h"
     40 #include "isns_cfg.h"
     41 #include "isns_htab.h"
     42 #include "isns_cache.h"
     43 #include "isns_obj.h"
     44 #include "isns_dd.h"
     45 #include "isns_utils.h"
     46 #include "isns_mgmt.h"
     47 #include "isns_protocol.h"
     48 #include "admintf.h"
     49 
     50 extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
     51 
     52 static isns_type_t
     53 get_lc_type(
     54 	object_type obj
     55 )
     56 {
     57 	isns_type_t type;
     58 
     59 	switch (obj) {
     60 	case Node:
     61 		type = OBJ_ISCSI;
     62 		break;
     63 	case DiscoveryDomain:
     64 	case DiscoveryDomainMember:
     65 		type = OBJ_DD;
     66 		break;
     67 	case DiscoveryDomainSet:
     68 	case DiscoveryDomainSetMember:
     69 		type = OBJ_DDS;
     70 		break;
     71 	default:
     72 		ASSERT(0);
     73 		break;
     74 	}
     75 
     76 	return (type);
     77 }
     78 
     79 static uint32_t
     80 get_lc_id(
     81 	object_type obj
     82 )
     83 {
     84 	uint32_t id;
     85 
     86 	switch (obj) {
     87 	case Node:
     88 		id = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
     89 		break;
     90 	case DiscoveryDomain:
     91 	case DiscoveryDomainMember:
     92 		id = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
     93 		break;
     94 	case DiscoveryDomainSet:
     95 	case DiscoveryDomainSetMember:
     96 		id = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID);
     97 		break;
     98 	default:
     99 		ASSERT(0);
    100 		break;
    101 	}
    102 
    103 	return (id);
    104 }
    105 
    106 /*
    107  * ****************************************************************************
    108  *
    109  * cb_get_node_info: callback for get_node_op
    110  *	The routine process matching node and add a Node object elements
    111  *	to the response doc.
    112  *
    113  * p1	- matching node object
    114  * p2	- lookup control data that was used for node look up
    115  *	    returns parent index(newtork entity) in look up control.
    116  * return - error code
    117  *
    118  * ****************************************************************************
    119  */
    120 static int
    121 cb_get_node_info(
    122 	void *p1,
    123 	void *p2
    124 )
    125 {
    126 	xmlNodePtr	n_obj, n_node, sub_node, root;
    127 	xmlAttrPtr	n_attr;
    128 	isns_attr_t *attr;
    129 
    130 	isns_obj_t *obj = (isns_obj_t *)p1;
    131 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
    132 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
    133 
    134 	root = xmlDocGetRootElement(doc);
    135 	if (root == NULL) {
    136 	    return (ERR_XML_ADDCHILD_FAILED);
    137 	}
    138 
    139 	n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
    140 	if (n_obj) {
    141 	    n_obj = xmlAddChild(root, n_obj);
    142 	    if (n_obj == NULL) {
    143 		return (ERR_XML_ADDCHILD_FAILED);
    144 	    }
    145 	} else {
    146 	    return (ERR_XML_ADDCHILD_FAILED);
    147 	}
    148 
    149 	n_node = xmlNewNode(NULL, (xmlChar *)NODEOBJECT);
    150 	if (n_node) {
    151 	    n_node = xmlAddChild(n_obj, n_node);
    152 	    if (n_node == NULL) {
    153 		return (ERR_XML_ADDCHILD_FAILED);
    154 	    }
    155 	} else {
    156 	    return (ERR_XML_ADDCHILD_FAILED);
    157 	}
    158 
    159 	/* get node name, alias, type and generate xml info */
    160 	attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)];
    161 	n_attr = xmlSetProp(n_node, (xmlChar *)NAMEATTR,
    162 		(xmlChar *)attr->value.ptr);
    163 	if (n_attr == NULL) {
    164 	    return (ERR_XML_SETPROP_FAILED);
    165 	}
    166 
    167 	attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_TYPE_ATTR_ID)];
    168 	switch (attr->value.ui) {
    169 	    case ISNS_CONTROL_NODE_TYPE | ISNS_INITIATOR_NODE_TYPE:
    170 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    171 		    (xmlChar *)CONTROLNODEINITIATORTYPE);
    172 		break;
    173 	    case ISNS_CONTROL_NODE_TYPE | ISNS_TARGET_NODE_TYPE:
    174 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    175 		    (xmlChar *)CONTROLNODETARGETTYPE);
    176 		break;
    177 	    case ISNS_TARGET_NODE_TYPE:
    178 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    179 		    (xmlChar *)TARGETTYPE);
    180 		break;
    181 	    case ISNS_INITIATOR_NODE_TYPE:
    182 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    183 		    (xmlChar *)INITIATORTYPE);
    184 		break;
    185 	    case ISNS_CONTROL_NODE_TYPE:
    186 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    187 		    (xmlChar *)CONTROLNODETYPE);
    188 		break;
    189 	    default:
    190 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    191 		    (xmlChar *)UNKNOWNTYPE);
    192 	}
    193 	if (n_attr == NULL) {
    194 	    return (ERR_XML_SETPROP_FAILED);
    195 	}
    196 
    197 	attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_ALIAS_ATTR_ID)];
    198 	n_attr = xmlSetProp(n_node, (xmlChar *)ALIASATTR,
    199 		(xmlChar *)attr->value.ptr);
    200 	if (n_attr == NULL) {
    201 	    return (ERR_XML_SETPROP_FAILED);
    202 	}
    203 
    204 	/*
    205 	 * A node can have all or no SCN subsribtion.
    206 	 * May avoid redundant code with scsusrciption table.
    207 	 */
    208 	attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_SCN_BITMAP_ATTR_ID)];
    209 	if (IS_SCN_INIT_SELF_INFO_ONLY(attr->value.ui)) {
    210 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)SCNSUBSCRIPTION,
    211 		(xmlChar *)SCNINITSELFONLY);
    212 	    if (sub_node == NULL) {
    213 		return (ERR_XML_NEWCHILD_FAILED);
    214 	    }
    215 	}
    216 	if (IS_SCN_TARGET_SELF_INFO_ONLY(attr->value.ui)) {
    217 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)SCNSUBSCRIPTION,
    218 		(xmlChar *)SCNTARGETSELFONLY);
    219 	    if (sub_node == NULL) {
    220 		return (ERR_XML_NEWCHILD_FAILED);
    221 	    }
    222 	}
    223 	if (IS_SCN_MGMT_REG(attr->value.ui)) {
    224 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)SCNSUBSCRIPTION,
    225 		(xmlChar *)SCNTARGETSELFONLY);
    226 	    if (sub_node == NULL) {
    227 		return (ERR_XML_NEWCHILD_FAILED);
    228 	    }
    229 	}
    230 	if (IS_SCN_OBJ_REMOVED(attr->value.ui)) {
    231 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)SCNSUBSCRIPTION,
    232 		(xmlChar *)SCNOBJECTREMOVED);
    233 	    if (sub_node == NULL) {
    234 		return (ERR_XML_NEWCHILD_FAILED);
    235 	    }
    236 	}
    237 	if (IS_SCN_OBJ_ADDED(attr->value.ui)) {
    238 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)SCNSUBSCRIPTION,
    239 		(xmlChar *)SCNOBJECTADDED);
    240 	    if (sub_node == NULL) {
    241 		return (ERR_XML_NEWCHILD_FAILED);
    242 	    }
    243 	}
    244 	if (IS_SCN_OBJ_UPDATED(attr->value.ui)) {
    245 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)SCNSUBSCRIPTION,
    246 		(xmlChar *)SCNOBJECTUPDATED);
    247 	    if (sub_node == NULL) {
    248 		return (ERR_XML_NEWCHILD_FAILED);
    249 	    }
    250 	}
    251 	if (IS_SCN_MEMBER_REMOVED(attr->value.ui)) {
    252 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)SCNSUBSCRIPTION,
    253 		(xmlChar *)SCNMEMBERREMOVED);
    254 	    if (sub_node == NULL) {
    255 		return (ERR_XML_NEWCHILD_FAILED);
    256 	    }
    257 	}
    258 	if (IS_SCN_MEMBER_ADDED(attr->value.ui)) {
    259 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)SCNSUBSCRIPTION,
    260 		(xmlChar *)SCNMEMBERADDED);
    261 	    if (sub_node == NULL) {
    262 		return (ERR_XML_NEWCHILD_FAILED);
    263 	    }
    264 	}
    265 
    266 	/* set the parent object id, i.e. the network entity object id */
    267 	lcp->id[2] = get_parent_uid(obj);
    268 	/* pass back the node object element to add entity, portal info to it */
    269 	lcp->data[2].ptr =  (uchar_t *)n_node;
    270 
    271 	/* successful */
    272 	return (0);
    273 }
    274 
    275 /*
    276  * ****************************************************************************
    277  *
    278  * cb_get_entity_info: callback for get_node_op
    279  *	The routine process matching network entity and add children elements
    280  *	to a Node object for given entity.
    281  *
    282  * p1	- matching entity object
    283  * p2	- lookup control data that was used for node look up
    284  *	    returns parent index(newtork entity) in look up control.
    285  * return - error code
    286  *
    287  * ****************************************************************************
    288  */
    289 static int
    290 cb_get_entity_info(
    291 	void *p1,
    292 	void *p2
    293 )
    294 {
    295 	isns_obj_t *obj = (isns_obj_t *)p1;
    296 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
    297 	xmlNodePtr n_node = (xmlNodePtr)lcp->data[2].ptr;
    298 	xmlNodePtr sub_node, subchild_node, subgrandchild_node;
    299 	char numbuf[32];
    300 	char buff[INET6_ADDRSTRLEN + 1] = { 0 };
    301 	isns_attr_t *attr;
    302 
    303 	sub_node = xmlNewChild(n_node, NULL, (xmlChar *)NETWORKENTITY, NULL);
    304 
    305 	if (sub_node) {
    306 	    attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)];
    307 	    subchild_node = xmlNewChild(sub_node, NULL,
    308 		(xmlChar *)ENTITYID, (xmlChar *)attr->value.ptr);
    309 	    if (subchild_node == NULL) {
    310 		return (ERR_XML_NEWCHILD_FAILED);
    311 	    }
    312 	    attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_ENTITY_PROTOCOL_ATTR_ID)];
    313 	    (void) sprintf(numbuf, "%u", attr->value.ui);
    314 	    subchild_node = xmlNewChild(sub_node, NULL,
    315 		(xmlChar *)ENTITYPROTOCOL, (xmlChar *)numbuf);
    316 	    if (subchild_node == NULL) {
    317 		return (ERR_XML_NEWCHILD_FAILED);
    318 	    }
    319 	    attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_MGMT_IP_ADDR_ATTR_ID)];
    320 	    if (attr->value.ip) {
    321 		/* convert the ipv6 to ipv4 */
    322 		if (((int *)attr->value.ip)[0] == 0x00 &&
    323 		    ((int *)attr->value.ip)[1] == 0x00 &&
    324 		    ((uchar_t *)attr->value.ip)[8] == 0x00 &&
    325 		    ((uchar_t *)attr->value.ip)[9] == 0x00 &&
    326 		    ((uchar_t *)attr->value.ip)[10] == 0xFF &&
    327 		    ((uchar_t *)attr->value.ip)[11] == 0xFF) {
    328 		    subchild_node = xmlNewChild(sub_node, NULL,
    329 			(xmlChar *)MANAGEMENTIPADDR,
    330 			(xmlChar *)inet_ntop(AF_INET,
    331 			(void *)&(((uint32_t *)attr->value.ip)[3]),
    332 			buff, sizeof (buff)));
    333 		} else {
    334 		    subchild_node = xmlNewChild(sub_node, NULL,
    335 			(xmlChar *)MANAGEMENTIPADDR,
    336 			(xmlChar *)inet_ntop(AF_INET6,
    337 			(void *)attr->value.ip, buff, sizeof (buff)));
    338 		}
    339 		if (subchild_node == NULL) {
    340 		    return (ERR_XML_NEWCHILD_FAILED);
    341 		}
    342 	    }
    343 	    attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_TIMESTAMP_ATTR_ID)];
    344 	    if (attr->value.ui) {
    345 		(void) sprintf(numbuf, "%u", attr->value.ui);
    346 		subchild_node = xmlNewChild(sub_node, NULL,
    347 		(xmlChar *)ENTITYREGTIMESTAMP, (xmlChar *)numbuf);
    348 		if (subchild_node == NULL) {
    349 		    return (ERR_XML_NEWCHILD_FAILED);
    350 		}
    351 	    }
    352 	    attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_VERSION_RANGE_ATTR_ID)];
    353 	    if (attr->value.ui) {
    354 		subchild_node = xmlNewNode(NULL,
    355 		    (xmlChar *)PROTOCOLVERSIONRANGE);
    356 		subchild_node = xmlAddChild(sub_node, subchild_node);
    357 		if (subchild_node == NULL) {
    358 		    return (ERR_XML_NEWCHILD_FAILED);
    359 		}
    360 
    361 		(void) sprintf(numbuf, "%u",
    362 		    (attr->value.ui >> ISNS_VER_SHIFT) & ISNS_VERSION);
    363 		subgrandchild_node = xmlNewChild(subchild_node, NULL,
    364 		    (xmlChar *)PROTOCOLMAXVERSION, (xmlChar *)numbuf);
    365 		if (subgrandchild_node == NULL) {
    366 		    return (ERR_XML_NEWCHILD_FAILED);
    367 		}
    368 		(void) sprintf(numbuf, "%u", attr->value.ui & ISNS_VERSION);
    369 		subgrandchild_node = xmlNewChild(subchild_node, NULL,
    370 		    (xmlChar *)PROTOCOLMINVERSION, (xmlChar *)numbuf);
    371 		if (subgrandchild_node == NULL) {
    372 		    return (ERR_XML_NEWCHILD_FAILED);
    373 		}
    374 	    }
    375 	    attr =
    376 		&obj->attrs[ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID)];
    377 	    if (attr->value.ui) {
    378 		(void) sprintf(numbuf, "%u", attr->value.ui);
    379 		subchild_node = xmlNewChild(sub_node, NULL,
    380 		(xmlChar *)REGISTRATIONPERIOD, (xmlChar *)numbuf);
    381 		if (subchild_node == NULL) {
    382 		    return (ERR_XML_NEWCHILD_FAILED);
    383 		}
    384 	    }
    385 	} else {
    386 	    return (ERR_XML_NEWCHILD_FAILED);
    387 	}
    388 
    389 	/* successful */
    390 	return (0);
    391 }
    392 
    393 /*
    394  * ****************************************************************************
    395  *
    396  * cb_get_pg_info: callback for get_node_op
    397  *	The routine process matching portal group and returns ip address
    398  *	and port number for further portal processing.
    399  *
    400  * p1	- matching portal group object
    401  * p2	- lookup control data that was used for portal group look up
    402  *	    returns portal ip address, port and group tag in look up control.
    403  * return - error code
    404  *
    405  * ****************************************************************************
    406  */
    407 static int
    408 cb_get_pg_info(
    409 	void *p1,
    410 	void *p2
    411 )
    412 {
    413 	isns_obj_t *obj = (isns_obj_t *)p1;
    414 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
    415 
    416 	isns_attr_t *attr;
    417 
    418 	/* get pg portal ip address and port attributes */
    419 	attr = &obj->attrs[ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)];
    420 	(void) memcpy(lcp->data[1].ip, attr->value.ip, sizeof (in6_addr_t));
    421 	attr = &obj->attrs[ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID)];
    422 	lcp->data[2].ui = attr->value.ui;
    423 	attr = &obj->attrs[ATTR_INDEX_PG(ISNS_PG_TAG_ATTR_ID)];
    424 	lcp->id[2] = attr->value.ui;
    425 
    426 	/* successful */
    427 	return (0);
    428 }
    429 
    430 /*
    431  * ****************************************************************************
    432  *
    433  * cb_get_portal_info: callback for get_node_op
    434  *	The routine process matching portal and add portal object info to
    435  *	the node object.
    436  *
    437  * p1	- matching portal object
    438  * p2	- lookup control data that was used for portal look up
    439  * return - error code
    440  *
    441  * ****************************************************************************
    442  */
    443 static int
    444 cb_get_portal_info(
    445 	void *p1,
    446 	void *p2
    447 )
    448 {
    449 	isns_obj_t *obj = (isns_obj_t *)p1;
    450 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
    451 	xmlNodePtr n_node = (xmlNodePtr)lcp->data[2].ptr;
    452 	uint32_t    tag = lcp->id[2];
    453 	xmlNodePtr sub_node, subchild_node, subgrandchild_node;
    454 	char numbuf[32];
    455 	char buff[INET6_ADDRSTRLEN + 1] = { 0 };
    456 	isns_attr_t *attr;
    457 
    458 	sub_node = xmlNewChild(n_node, NULL, (xmlChar *)PORTAL, NULL);
    459 
    460 	/* get portal object attributes. */
    461 	if (sub_node) {
    462 	    attr = &obj->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID)];
    463 	    if (attr->value.ip) {
    464 		/* convert the ipv6 to ipv4 */
    465 		if (((int *)attr->value.ip)[0] == 0x00 &&
    466 		    ((int *)attr->value.ip)[1] == 0x00 &&
    467 		    ((uchar_t *)attr->value.ip)[8] == 0x00 &&
    468 		    ((uchar_t *)attr->value.ip)[9] == 0x00 &&
    469 		    ((uchar_t *)attr->value.ip)[10] == 0xFF &&
    470 		    ((uchar_t *)attr->value.ip)[11] == 0xFF) {
    471 		    subchild_node = xmlNewChild(sub_node, NULL,
    472 			(xmlChar *)IPADDR,
    473 			(xmlChar *)inet_ntop(AF_INET,
    474 			(void *)&(((uint32_t *)attr->value.ip)[3]),
    475 			buff, sizeof (buff)));
    476 		} else {
    477 		    subchild_node = xmlNewChild(sub_node, NULL,
    478 			(xmlChar *)IPADDR,
    479 			(xmlChar *)inet_ntop(AF_INET6,
    480 			(void *)attr->value.ip, buff, sizeof (buff)));
    481 		}
    482 		if (subchild_node == NULL) {
    483 		    return (ERR_XML_NEWCHILD_FAILED);
    484 		}
    485 	    }
    486 	    subchild_node = xmlNewChild(sub_node, NULL, (xmlChar *)UDPTCPPORT,
    487 		NULL);
    488 	    if (subchild_node) {
    489 		attr = &obj->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID)];
    490 		subgrandchild_node = xmlNewChild(subchild_node, NULL,
    491 		    (xmlChar *)PORTTYPE, IS_PORT_UDP(attr->value.ui) ?
    492 		    (xmlChar *)UDPPORT : (xmlChar *)TCPPORT);
    493 		if (subgrandchild_node == NULL) {
    494 		    return (ERR_XML_NEWCHILD_FAILED);
    495 		}
    496 		(void) sprintf(numbuf, "%u", PORT_NUMBER(attr->value.ui));
    497 		subgrandchild_node = xmlNewChild(subchild_node, NULL,
    498 		    (xmlChar *)PORTNUMBER, (xmlChar *)numbuf);
    499 		if (subgrandchild_node == NULL) {
    500 		    return (ERR_XML_NEWCHILD_FAILED);
    501 		}
    502 	    } else {
    503 		return (ERR_XML_NEWCHILD_FAILED);
    504 	    }
    505 	    (void) sprintf(numbuf, "%u", tag);
    506 	    subchild_node = xmlNewChild(sub_node, NULL, (xmlChar *)GROUPTAG,
    507 		(xmlChar *)numbuf);
    508 	    if (subchild_node == NULL) {
    509 		return (ERR_XML_NEWCHILD_FAILED);
    510 	    }
    511 	    attr = &obj->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_NAME_ATTR_ID)];
    512 	    if (attr->value.ptr) {
    513 		subchild_node = xmlNewChild(sub_node, NULL,
    514 		(xmlChar *)SYMBOLICNAME, (xmlChar *)attr->value.ptr);
    515 		if (subchild_node == NULL) {
    516 		    return (ERR_XML_NEWCHILD_FAILED);
    517 		}
    518 	    }
    519 	    attr = &obj->attrs[ATTR_INDEX_PORTAL(ISNS_ESI_INTERVAL_ATTR_ID)];
    520 	    if (attr->value.ui) {
    521 		(void) sprintf(numbuf, "%u", attr->value.ui);
    522 		subchild_node = xmlNewChild(sub_node, NULL,
    523 		(xmlChar *)ESIINTERVAL, (xmlChar *)numbuf);
    524 		if (subchild_node == NULL) {
    525 		    return (ERR_XML_NEWCHILD_FAILED);
    526 		}
    527 	    }
    528 	    attr = &obj->attrs[ATTR_INDEX_PORTAL(ISNS_ESI_PORT_ATTR_ID)];
    529 	    if (attr->value.ui) {
    530 		subchild_node = xmlNewChild(sub_node, NULL,
    531 		    (xmlChar *)ESIPORT, NULL);
    532 		if (subchild_node) {
    533 		    subgrandchild_node = xmlNewChild(subchild_node, NULL,
    534 			(xmlChar *)PORTTYPE, IS_PORT_UDP(attr->value.ui) ?
    535 			(xmlChar *)UDPPORT : (xmlChar *)TCPPORT);
    536 		    if (subgrandchild_node == NULL) {
    537 			return (ERR_XML_NEWCHILD_FAILED);
    538 		    }
    539 		    (void) sprintf(numbuf, "%u", PORT_NUMBER(attr->value.ui));
    540 		    subgrandchild_node = xmlNewChild(subchild_node, NULL,
    541 			(xmlChar *)PORTNUMBER, (xmlChar *)numbuf);
    542 		    if (subgrandchild_node == NULL) {
    543 			return (ERR_XML_NEWCHILD_FAILED);
    544 		    }
    545 		} else {
    546 		    return (ERR_XML_NEWCHILD_FAILED);
    547 		}
    548 	    }
    549 	    attr = &obj->attrs[ATTR_INDEX_PORTAL(ISNS_SCN_PORT_ATTR_ID)];
    550 	    if (attr->value.ui) {
    551 		subchild_node = xmlNewChild(sub_node, NULL,
    552 		    (xmlChar *)SCNPORT, NULL);
    553 		if (subchild_node) {
    554 		    subgrandchild_node = xmlNewChild(subchild_node, NULL,
    555 			(xmlChar *)PORTTYPE, IS_PORT_UDP(attr->value.ui) ?
    556 			(xmlChar *)UDPPORT : (xmlChar *)TCPPORT);
    557 		    (void) sprintf(numbuf, "%u", PORT_NUMBER(attr->value.ui));
    558 		    if (subgrandchild_node == NULL) {
    559 			return (ERR_XML_NEWCHILD_FAILED);
    560 		    }
    561 		    subgrandchild_node = xmlNewChild(subchild_node, NULL,
    562 			(xmlChar *)PORTNUMBER, (xmlChar *)numbuf);
    563 		    if (subgrandchild_node == NULL) {
    564 			return (ERR_XML_NEWCHILD_FAILED);
    565 		    }
    566 		} else {
    567 		    return (ERR_XML_NEWCHILD_FAILED);
    568 		}
    569 	    }
    570 	} else if (sub_node == NULL) {
    571 		return (ERR_XML_NEWCHILD_FAILED);
    572 	}
    573 
    574 	/* successful */
    575 	return (0);
    576 }
    577 
    578 /*
    579  * ****************************************************************************
    580  *
    581  * cb_get_dd_info: callback for get_dd_op
    582  *	The routine process matching dd object
    583  *
    584  * p1	- matching dd object
    585  * p2	- lookup control data that was used for dd look up
    586  * return - error code
    587  *
    588  * ****************************************************************************
    589  */
    590 static int
    591 cb_get_dd_info(
    592 	void *p1,
    593 	void *p2
    594 )
    595 {
    596 	xmlNodePtr	n_obj, n_node, sub_node, root;
    597 	xmlAttrPtr	n_attr;
    598 	isns_attr_t *attr;
    599 	char numbuf[32];
    600 
    601 	isns_obj_t *obj = (isns_obj_t *)p1;
    602 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
    603 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
    604 
    605 	root = xmlDocGetRootElement(doc);
    606 	if (root == NULL) {
    607 	    return (ERR_SYNTAX_MISSING_ROOT);
    608 	}
    609 	n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
    610 	if (n_obj) {
    611 	    n_obj = xmlAddChild(root, n_obj);
    612 	    if (n_obj == NULL) {
    613 		return (ERR_XML_ADDCHILD_FAILED);
    614 	    }
    615 	} else {
    616 	    return (ERR_XML_ADDCHILD_FAILED);
    617 	}
    618 
    619 	n_node = xmlNewNode(NULL, (xmlChar *)DDOBJECT);
    620 	if (n_node) {
    621 	    n_node = xmlAddChild(n_obj, n_node);
    622 	    if (n_node == NULL) {
    623 		return (ERR_XML_ADDCHILD_FAILED);
    624 	    }
    625 	} else {
    626 	    return (ERR_XML_ADDCHILD_FAILED);
    627 	}
    628 
    629 	attr = &obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)];
    630 	n_attr = xmlSetProp(n_node, (xmlChar *)NAMEATTR,
    631 		(xmlChar *)attr->value.ptr);
    632 	if (n_attr == NULL) {
    633 	    return (ERR_XML_SETPROP_FAILED);
    634 	}
    635 	attr = &obj->attrs[ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID)];
    636 	(void) sprintf(numbuf, "%u", attr->value.ui);
    637 	n_attr = xmlSetProp(n_node, (xmlChar *)IDATTR,
    638 		(xmlChar *)numbuf);
    639 	if (n_attr == NULL) {
    640 	    return (ERR_XML_SETPROP_FAILED);
    641 	}
    642 	attr = &obj->attrs[ATTR_INDEX_DD(ISNS_DD_FEATURES_ATTR_ID)];
    643 	if (DD_BOOTLIST_ENABLED(attr->value.ui)) {
    644 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)BOOTLISTENABLEDELEM,
    645 		(xmlChar *)XMLTRUE);
    646 	    if (sub_node == NULL) {
    647 		return (ERR_XML_NEWCHILD_FAILED);
    648 	    }
    649 	} else {
    650 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)BOOTLISTENABLEDELEM,
    651 		(xmlChar *)XMLFALSE);
    652 	    if (sub_node == NULL) {
    653 		return (ERR_XML_NEWCHILD_FAILED);
    654 	    }
    655 	}
    656 
    657 	/* successful */
    658 	return (0);
    659 }
    660 
    661 /*
    662  * ****************************************************************************
    663  *
    664  * cb_get_ddset_info: callback for get_ddset_op
    665  *	The routine process matching dd object
    666  *
    667  * p1	- matching dds object
    668  * p2	- lookup control data that was used for dd set look up
    669  * return - error code
    670  *
    671  * ****************************************************************************
    672  */
    673 static int
    674 cb_get_ddset_info(
    675 	void *p1,
    676 	void *p2
    677 )
    678 {
    679 	xmlNodePtr	n_obj, n_node, sub_node, root;
    680 	xmlAttrPtr	n_attr;
    681 	isns_attr_t *attr;
    682 	char numbuf[32];
    683 
    684 	isns_obj_t *obj = (isns_obj_t *)p1;
    685 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
    686 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
    687 
    688 	root = xmlDocGetRootElement(doc);
    689 	if (root == NULL) {
    690 	    return (ERR_SYNTAX_MISSING_ROOT);
    691 	}
    692 
    693 	n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
    694 	if (n_obj) {
    695 	    n_obj = xmlAddChild(root, n_obj);
    696 	    if (n_obj == NULL) {
    697 		return (ERR_XML_NEWCHILD_FAILED);
    698 	    }
    699 	} else {
    700 	    return (ERR_XML_NEWNODE_FAILED);
    701 	}
    702 
    703 	n_node = xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
    704 	if (n_node) {
    705 	    n_node = xmlAddChild(n_obj, n_node);
    706 	    if (n_node == NULL) {
    707 		return (ERR_XML_ADDCHILD_FAILED);
    708 	    }
    709 	} else {
    710 	    return (ERR_XML_NEWNODE_FAILED);
    711 	}
    712 
    713 	/* get node name, alias, type and generate xml info */
    714 	attr = &obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID)];
    715 	n_attr = xmlSetProp(n_node, (xmlChar *)NAMEATTR,
    716 		(xmlChar *)attr->value.ptr);
    717 	if (n_attr == NULL) {
    718 	    return (ERR_XML_SETPROP_FAILED);
    719 	}
    720 	attr = &obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID)];
    721 	(void) sprintf(numbuf, "%u", attr->value.ui);
    722 	n_attr = xmlSetProp(n_node, (xmlChar *)IDATTR,
    723 		(xmlChar *)numbuf);
    724 	if (n_attr == NULL) {
    725 	    return (ERR_XML_SETPROP_FAILED);
    726 	}
    727 	attr = &obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_STATUS_ATTR_ID)];
    728 	if (DDS_ENABLED(attr->value.ui)) {
    729 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)ENABLEDELEM,
    730 		(xmlChar *)XMLTRUE);
    731 	    if (sub_node == NULL) {
    732 		return (ERR_XML_NEWCHILD_FAILED);
    733 	    }
    734 	} else {
    735 	    sub_node = xmlNewChild(n_node, NULL, (xmlChar *)ENABLEDELEM,
    736 		(xmlChar *)XMLFALSE);
    737 	    if (sub_node == NULL) {
    738 		return (ERR_XML_NEWCHILD_FAILED);
    739 	    }
    740 	}
    741 
    742 	/* successful */
    743 	return (0);
    744 }
    745 
    746 /*
    747  * ****************************************************************************
    748  *
    749  * cb_enumerate_node_info: callback for enumerate_node_op
    750  *	The routine is invoked for each node object.
    751  *
    752  * p1	- node object
    753  * p2	- lookup control data that was used for node look up
    754  * return - error code
    755  *
    756  * ****************************************************************************
    757  */
    758 static int
    759 cb_enumerate_node_info(
    760 	void *p1,
    761 	void *p2
    762 )
    763 {
    764 	xmlNodePtr	n_obj, n_node, root;
    765 	xmlAttrPtr	n_attr;
    766 	isns_attr_t *attr;
    767 
    768 	isns_obj_t *obj = (isns_obj_t *)p1;
    769 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
    770 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
    771 
    772 	root = xmlDocGetRootElement(doc);
    773 	if (root == NULL) {
    774 	    return (ERR_SYNTAX_MISSING_ROOT);
    775 	}
    776 
    777 	n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
    778 	if (n_obj) {
    779 	    n_obj = xmlAddChild(root, n_obj);
    780 	    if (n_obj == NULL) {
    781 		return (ERR_XML_ADDCHILD_FAILED);
    782 	    }
    783 	} else {
    784 	    return (ERR_XML_NEWNODE_FAILED);
    785 	}
    786 
    787 	n_node = xmlNewNode(NULL, (xmlChar *)NODEOBJECT);
    788 	if (n_node) {
    789 	    n_node = xmlAddChild(n_obj, n_node);
    790 	    if (n_node == NULL) {
    791 		return (ERR_XML_ADDCHILD_FAILED);
    792 	    }
    793 	} else {
    794 	    return (ERR_XML_NEWNODE_FAILED);
    795 	}
    796 
    797 	/* get node name, alias, type and generate xml info */
    798 	attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)];
    799 	n_attr = xmlSetProp(n_node, (xmlChar *)NAMEATTR,
    800 		(xmlChar *)attr->value.ptr);
    801 	if (n_attr == NULL) {
    802 	    return (ERR_XML_SETPROP_FAILED);
    803 	}
    804 	attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_TYPE_ATTR_ID)];
    805 	switch (attr->value.ui) {
    806 	    case ISNS_CONTROL_NODE_TYPE | ISNS_INITIATOR_NODE_TYPE:
    807 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    808 		    (xmlChar *)CONTROLNODEINITIATORTYPE);
    809 		break;
    810 	    case ISNS_CONTROL_NODE_TYPE | ISNS_TARGET_NODE_TYPE:
    811 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    812 		    (xmlChar *)CONTROLNODETARGETTYPE);
    813 		break;
    814 	    case ISNS_TARGET_NODE_TYPE:
    815 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    816 		    (xmlChar *)TARGETTYPE);
    817 		break;
    818 	    case ISNS_INITIATOR_NODE_TYPE:
    819 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    820 		    (xmlChar *)INITIATORTYPE);
    821 		break;
    822 	    case ISNS_CONTROL_NODE_TYPE:
    823 		n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    824 		    (xmlChar *)CONTROLNODETYPE);
    825 		break;
    826 	    default:
    827 	    n_attr = xmlSetProp(n_node, (xmlChar *)TYPEATTR,
    828 		    (xmlChar *)UNKNOWNTYPE);
    829 	}
    830 	if (n_attr == NULL) {
    831 	    return (ERR_XML_SETPROP_FAILED);
    832 	}
    833 	attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_ALIAS_ATTR_ID)];
    834 	n_attr = xmlSetProp(n_node, (xmlChar *)ALIASATTR,
    835 		(xmlChar *)attr->value.ptr);
    836 	if (n_attr == NULL) {
    837 	    return (ERR_XML_SETPROP_FAILED);
    838 	}
    839 
    840 	/* successful */
    841 	return (0);
    842 }
    843 
    844 /*
    845  * ****************************************************************************
    846  *
    847  * i_enumerate_dd_dds_info:
    848  *	The routine is implemnetation for enumerate dd and enumerate dds.
    849  *
    850  * p1	- dd or dd set object
    851  * p2	- lookup control data that was used for dd and dd set look up
    852  * return - error code
    853  *
    854  * ****************************************************************************
    855  */
    856 static int
    857 i_enumerate_dd_dds_info(
    858 	void *p1,
    859 	void *p2,
    860 	isns_type_t obj_type
    861 )
    862 {
    863 	xmlNodePtr	n_obj, n_node, sub_node, root;
    864 	xmlAttrPtr	n_attr;
    865 	isns_attr_t *attr;
    866 	char numbuf[32];
    867 
    868 	isns_obj_t *obj = (isns_obj_t *)p1;
    869 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
    870 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
    871 
    872 	root = xmlDocGetRootElement(doc);
    873 	if (root == NULL) {
    874 	    return (ERR_SYNTAX_MISSING_ROOT);
    875 	}
    876 
    877 	n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
    878 	if (n_obj) {
    879 	    n_obj = xmlAddChild(root, n_obj);
    880 	    if (n_obj == NULL) {
    881 		return (ERR_XML_ADDCHILD_FAILED);
    882 	    }
    883 	} else {
    884 	    return (ERR_XML_NEWNODE_FAILED);
    885 	}
    886 
    887 	if (obj_type == OBJ_DD) {
    888 	    n_node = xmlNewNode(NULL, (xmlChar *)DDOBJECT);
    889 	} else {
    890 	    n_node = xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
    891 	}
    892 
    893 	if (n_node) {
    894 	    n_node = xmlAddChild(n_obj, n_node);
    895 	    if (n_node == NULL) {
    896 		return (ERR_XML_ADDCHILD_FAILED);
    897 	    }
    898 	} else {
    899 	    return (ERR_XML_NEWNODE_FAILED);
    900 	}
    901 
    902 	if (obj_type == OBJ_DD) {
    903 	    /* get name, id, feaure and generate xml info */
    904 	    attr = &obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)];
    905 	    n_attr = xmlSetProp(n_node, (xmlChar *)NAMEATTR,
    906 		(xmlChar *)attr->value.ptr);
    907 	    if (n_attr == NULL) {
    908 		return (ERR_XML_SETPROP_FAILED);
    909 	    }
    910 	    attr = &obj->attrs[ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID)];
    911 	    (void) sprintf(numbuf, "%u", attr->value.ui);
    912 	    n_attr = xmlSetProp(n_node, (xmlChar *)IDATTR,
    913 		(xmlChar *)numbuf);
    914 	    if (n_attr == NULL) {
    915 		return (ERR_XML_SETPROP_FAILED);
    916 	    }
    917 	    attr = &obj->attrs[ATTR_INDEX_DD(ISNS_DD_FEATURES_ATTR_ID)];
    918 	    if (DD_BOOTLIST_ENABLED(attr->value.ui)) {
    919 		sub_node = xmlNewChild(n_node, NULL,
    920 		    (xmlChar *)BOOTLISTENABLEDELEM, (xmlChar *)XMLTRUE);
    921 		if (sub_node == NULL) {
    922 		    return (ERR_XML_NEWCHILD_FAILED);
    923 		}
    924 	    } else {
    925 		sub_node = xmlNewChild(n_node, NULL,
    926 		    (xmlChar *)BOOTLISTENABLEDELEM, (xmlChar *)XMLFALSE);
    927 		if (sub_node == NULL) {
    928 		    return (ERR_XML_NEWCHILD_FAILED);
    929 		}
    930 	    }
    931 	} else {
    932 	    /* get name, id, status and generate xml info */
    933 	    attr = &obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID)];
    934 	    n_attr = xmlSetProp(n_node, (xmlChar *)NAMEATTR,
    935 		(xmlChar *)attr->value.ptr);
    936 	    if (n_attr == NULL) {
    937 		return (ERR_XML_SETPROP_FAILED);
    938 	    }
    939 	    attr = &obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID)];
    940 	    (void) sprintf(numbuf, "%u", attr->value.ui);
    941 	    n_attr = xmlSetProp(n_node, (xmlChar *)IDATTR,
    942 		(xmlChar *)numbuf);
    943 	    if (n_attr == NULL) {
    944 		return (ERR_XML_SETPROP_FAILED);
    945 	    }
    946 	    attr = &obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_STATUS_ATTR_ID)];
    947 	    if (DDS_ENABLED(attr->value.ui)) {
    948 		sub_node = xmlNewChild(n_node, NULL,
    949 		    (xmlChar *)ENABLEDELEM, (xmlChar *)XMLTRUE);
    950 		if (sub_node == NULL) {
    951 		    return (ERR_XML_NEWCHILD_FAILED);
    952 		}
    953 	    } else {
    954 		sub_node = xmlNewChild(n_node, NULL,
    955 		    (xmlChar *)ENABLEDELEM, (xmlChar *)XMLFALSE);
    956 		if (sub_node == NULL) {
    957 		    return (ERR_XML_NEWCHILD_FAILED);
    958 		}
    959 	    }
    960 	}
    961 
    962 	/* successful */
    963 	return (0);
    964 }
    965 
    966 /*
    967  * ****************************************************************************
    968  *
    969  * cb_enumerate_dd_info: callback for enumerate_dd_op
    970  *	The routine is invoked for each dd object.
    971  *
    972  * p1	- dd object
    973  * p2	- lookup control data that was used for dd look up
    974  * return - error code
    975  *
    976  * ****************************************************************************
    977  */
    978 static int
    979 cb_enumerate_dd_info(
    980 	void *p1,
    981 	void *p2
    982 )
    983 {
    984 	return (i_enumerate_dd_dds_info(p1, p2, OBJ_DD));
    985 }
    986 
    987 /*
    988  * ****************************************************************************
    989  *
    990  * cb_enumerate_ddset_info: callback for enumerate_dd_op
    991  *	The routine is invoked for each dd object.
    992  *
    993  * p1	- dd object
    994  * p2	- lookup control data that was used for dd set look up
    995  * return - error code
    996  *
    997  * ****************************************************************************
    998  */
    999 static int
   1000 cb_enumerate_ddset_info(
   1001 	void *p1,
   1002 	void *p2
   1003 )
   1004 {
   1005 	return (i_enumerate_dd_dds_info(p1, p2, OBJ_DDS));
   1006 }
   1007 
   1008 /*
   1009  * ****************************************************************************
   1010  *
   1011  * cb_getAssociated_node_info:
   1012  *	The routine is implemnetation for enumerate dd and enumerate dds.
   1013  *
   1014  * p1	- dd or dd set object
   1015  * p2	- lookup control data that was used for dd and dd set look up
   1016  * return - error code
   1017  *
   1018  * ****************************************************************************
   1019  */
   1020 static int
   1021 cb_getAssociated_node_info(
   1022 	void *p1,
   1023 	void *p2
   1024 )
   1025 {
   1026 	xmlNodePtr	n_obj, n_node, root;
   1027 	xmlAttrPtr	n_attr;
   1028 	isns_attr_t *attr;
   1029 
   1030 	isns_obj_t *obj = (isns_obj_t *)p1;
   1031 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
   1032 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
   1033 	uchar_t *ddname = lcp->data[2].ptr;
   1034 
   1035 	root = xmlDocGetRootElement(doc);
   1036 	if (root == NULL) {
   1037 	    return (ERR_SYNTAX_MISSING_ROOT);
   1038 	}
   1039 	n_obj = xmlNewNode(NULL, (xmlChar *)ASSOCIATION);
   1040 	if (n_obj) {
   1041 	    n_obj = xmlAddChild(root, n_obj);
   1042 	    if (n_obj == NULL) {
   1043 		return (ERR_XML_ADDCHILD_FAILED);
   1044 	    }
   1045 	} else {
   1046 	    return (ERR_XML_NEWNODE_FAILED);
   1047 	}
   1048 
   1049 	n_node = xmlNewNode(NULL, (xmlChar *)DDOBJECTMEMBER);
   1050 	if (n_node) {
   1051 	    n_node = xmlAddChild(n_obj, n_node);
   1052 	    if (n_node == NULL) {
   1053 		return (ERR_XML_ADDCHILD_FAILED);
   1054 	    }
   1055 	} else {
   1056 	    return (ERR_XML_NEWNODE_FAILED);
   1057 	}
   1058 
   1059 	/* get node name, alias, type and generate xml info */
   1060 	attr = &obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)];
   1061 	n_attr = xmlSetProp(n_node, (xmlChar *)NODENAMEATTR,
   1062 		(xmlChar *)attr->value.ptr);
   1063 	if (n_attr == NULL) {
   1064 	    return (ERR_XML_SETPROP_FAILED);
   1065 	}
   1066 	n_attr = xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
   1067 		(xmlChar *)ddname);
   1068 	if (n_attr == NULL) {
   1069 	    return (ERR_XML_SETPROP_FAILED);
   1070 	}
   1071 
   1072 	/* successful */
   1073 	return (0);
   1074 }
   1075 
   1076 /*
   1077  * ****************************************************************************
   1078  *
   1079  * cb_getAssociated_node_to_dd_info:
   1080  *	The routine is implemnetation for enumerate dd and enumerate dds.
   1081  *
   1082  * p1	- dd or dd set object
   1083  * p2	- lookup control data that was used for dd and dd set look up
   1084  * return - error code
   1085  *
   1086  * ****************************************************************************
   1087  */
   1088 static int
   1089 cb_getAssociated_node_to_dd_info(
   1090 	void *p1,
   1091 	void *p2
   1092 )
   1093 {
   1094 	xmlNodePtr	n_obj, n_node, root;
   1095 	xmlAttrPtr	n_attr;
   1096 	isns_attr_t *attr;
   1097 
   1098 	isns_obj_t *obj = (isns_obj_t *)p1;
   1099 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
   1100 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
   1101 	uchar_t *nodename = lcp->data[2].ptr;
   1102 
   1103 	root = xmlDocGetRootElement(doc);
   1104 	if (root == NULL) {
   1105 	    return (ERR_SYNTAX_MISSING_ROOT);
   1106 	}
   1107 	n_obj = xmlNewNode(NULL, (xmlChar *)ASSOCIATION);
   1108 	if (n_obj) {
   1109 	    n_obj = xmlAddChild(root, n_obj);
   1110 	    if (n_obj == NULL) {
   1111 		return (ERR_XML_ADDCHILD_FAILED);
   1112 	    }
   1113 	} else {
   1114 	    return (ERR_XML_NEWNODE_FAILED);
   1115 	}
   1116 
   1117 	n_node = xmlNewNode(NULL, (xmlChar *)DDOBJECTMEMBER);
   1118 	if (n_node) {
   1119 	    n_node = xmlAddChild(n_obj, n_node);
   1120 	    if (n_node == NULL) {
   1121 		return (ERR_XML_ADDCHILD_FAILED);
   1122 	    }
   1123 	} else {
   1124 	    return (ERR_XML_NEWNODE_FAILED);
   1125 	}
   1126 
   1127 	/* get node name, alias, type and generate xml info */
   1128 	n_attr = xmlSetProp(n_node, (xmlChar *)NODENAMEATTR,
   1129 		(xmlChar *)nodename);
   1130 	if (n_attr == NULL) {
   1131 	    return (ERR_XML_SETPROP_FAILED);
   1132 	}
   1133 	attr = &obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)];
   1134 	n_attr = xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
   1135 		(xmlChar *)attr->value.ptr);
   1136 	if (n_attr == NULL) {
   1137 	    return (ERR_XML_SETPROP_FAILED);
   1138 	}
   1139 
   1140 	/* successful */
   1141 	return (0);
   1142 }
   1143 
   1144 /*
   1145  * ****************************************************************************
   1146  *
   1147  * cb_getAssociated_dd_info:
   1148  *	The routine is implemnetation for getting dds membership.
   1149  *
   1150  * p1	- dd or dd set object
   1151  * p2	- lookup control data that was used for dd and dd set look up
   1152  * return - error code
   1153  *
   1154  * ****************************************************************************
   1155  */
   1156 static int
   1157 cb_getAssociated_dd_info(
   1158 	void *p1,
   1159 	void *p2
   1160 )
   1161 {
   1162 	xmlNodePtr	n_obj, n_node, root;
   1163 	xmlAttrPtr	n_attr;
   1164 	isns_attr_t *attr;
   1165 
   1166 	isns_obj_t *obj = (isns_obj_t *)p1;
   1167 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
   1168 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
   1169 	uchar_t *ddsetname = lcp->data[2].ptr;
   1170 
   1171 	root = xmlDocGetRootElement(doc);
   1172 	if (root == NULL) {
   1173 	    return (ERR_SYNTAX_MISSING_ROOT);
   1174 	}
   1175 	n_obj = xmlNewNode(NULL, (xmlChar *)ASSOCIATION);
   1176 	if (n_obj) {
   1177 	    n_obj = xmlAddChild(root, n_obj);
   1178 	    if (n_obj == NULL) {
   1179 		return (ERR_XML_ADDCHILD_FAILED);
   1180 	    }
   1181 	} else {
   1182 	    return (ERR_XML_NEWNODE_FAILED);
   1183 	}
   1184 
   1185 	n_node = xmlNewNode(NULL, (xmlChar *)DDSETOBJECTMEMBER);
   1186 	if (n_node) {
   1187 	    n_node = xmlAddChild(n_obj, n_node);
   1188 	    if (n_node == NULL) {
   1189 		return (ERR_XML_ADDCHILD_FAILED);
   1190 	    }
   1191 	} else {
   1192 	    return (ERR_XML_NEWNODE_FAILED);
   1193 	}
   1194 
   1195 	/* get node name, alias, type and generate xml info */
   1196 	attr = &obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)];
   1197 	n_attr = xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
   1198 		(xmlChar *)attr->value.ptr);
   1199 	if (n_attr == NULL) {
   1200 	    return (ERR_XML_SETPROP_FAILED);
   1201 	}
   1202 	n_attr = xmlSetProp(n_node, (xmlChar *)DDSETNAMEATTR,
   1203 		(xmlChar *)ddsetname);
   1204 	if (n_attr == NULL) {
   1205 	    return (ERR_XML_SETPROP_FAILED);
   1206 	}
   1207 
   1208 	/* successful */
   1209 	return (0);
   1210 }
   1211 
   1212 /*
   1213  * ****************************************************************************
   1214  *
   1215  * cb_getAssociated_dd_to_ddset_info:
   1216  *	The routine is implemnetation for enumerate dd and enumerate dds.
   1217  *
   1218  * p1	- dd or dd set object
   1219  * p2	- lookup control data that was used for dd and dd set look up
   1220  * return - error code
   1221  *
   1222  * ****************************************************************************
   1223  */
   1224 static int
   1225 cb_getAssociated_dd_to_ddset_info(
   1226 	void *p1,
   1227 	void *p2
   1228 )
   1229 {
   1230 	xmlNodePtr	n_obj, n_node, root;
   1231 	xmlAttrPtr	n_attr;
   1232 	isns_attr_t *attr;
   1233 
   1234 	isns_obj_t *obj = (isns_obj_t *)p1;
   1235 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
   1236 	xmlDocPtr doc = (xmlDocPtr)lcp->data[1].ptr;
   1237 	uchar_t *ddname = lcp->data[2].ptr;
   1238 
   1239 	root = xmlDocGetRootElement(doc);
   1240 	if (root == NULL) {
   1241 	    return (ERR_SYNTAX_MISSING_ROOT);
   1242 	}
   1243 	n_obj = xmlNewNode(NULL, (xmlChar *)ASSOCIATION);
   1244 	if (n_obj) {
   1245 	    n_obj = xmlAddChild(root, n_obj);
   1246 	    if (n_obj == NULL) {
   1247 		return (ERR_XML_ADDCHILD_FAILED);
   1248 	    }
   1249 	} else {
   1250 	    return (ERR_XML_NEWNODE_FAILED);
   1251 	}
   1252 
   1253 	n_node = xmlNewNode(NULL, (xmlChar *)DDSETOBJECTMEMBER);
   1254 	if (n_node) {
   1255 	    n_node = xmlAddChild(n_obj, n_node);
   1256 	    if (n_node == NULL) {
   1257 		return (ERR_XML_ADDCHILD_FAILED);
   1258 	    }
   1259 	} else {
   1260 	    return (ERR_XML_NEWNODE_FAILED);
   1261 	}
   1262 
   1263 	/* get node name, alias, type and generate xml info */
   1264 	n_attr = xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
   1265 		(xmlChar *)ddname);
   1266 	if (n_attr == NULL) {
   1267 	    return (ERR_XML_SETPROP_FAILED);
   1268 	}
   1269 	attr = &obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID)];
   1270 	n_attr = xmlSetProp(n_node, (xmlChar *)DDSETNAMEATTR,
   1271 		(xmlChar *)attr->value.ptr);
   1272 	if (n_attr == NULL) {
   1273 	    return (ERR_XML_SETPROP_FAILED);
   1274 	}
   1275 
   1276 	/* successful */
   1277 	return (0);
   1278 }
   1279 
   1280 /*
   1281  * ****************************************************************************
   1282  *
   1283  * handle_partial_success:
   1284  *
   1285  * doc	- response doc to fill up
   1286  * ret	- return code from the caller.
   1287  *
   1288  * ****************************************************************************
   1289  */
   1290 static int
   1291 handle_partial_success(
   1292 	xmlDocPtr doc,
   1293 	int ret
   1294 )
   1295 {
   1296 	xmlNodePtr	n_obj, n_node, root;
   1297 	char numbuf[32];
   1298 
   1299 	root = xmlDocGetRootElement(doc);
   1300 	if (root == NULL) {
   1301 	    return (ERR_SYNTAX_MISSING_ROOT);
   1302 	}
   1303 	n_obj = xmlNewNode(NULL, (xmlChar *)RESULTELEMENT);
   1304 	if (n_obj) {
   1305 	    if (root->children) {
   1306 		n_obj = xmlAddPrevSibling(root->children, n_obj);
   1307 		(void) sprintf(numbuf, "%d", (ret != 0) ? PARTIAL_SUCCESS : 0);
   1308 		n_node = xmlNewChild(n_obj, NULL, (xmlChar *)STATUSELEMENT,
   1309 		    (xmlChar *)numbuf);
   1310 		if (n_node == NULL) {
   1311 		    return (ERR_XML_NEWCHILD_FAILED);
   1312 		}
   1313 		n_node = xmlNewChild(n_obj, NULL, (xmlChar *)MESSAGEELEMENT,
   1314 		    (xmlChar *)result_code_to_str((ret != 0) ?
   1315 			PARTIAL_SUCCESS : 0));
   1316 		if (n_node == NULL) {
   1317 		    return (ERR_XML_NEWCHILD_FAILED);
   1318 		}
   1319 	    } else {
   1320 		n_obj = xmlAddChild(root, n_obj);
   1321 		if (n_obj == NULL) {
   1322 		    return (ERR_XML_ADDCHILD_FAILED);
   1323 		}
   1324 		(void) sprintf(numbuf, "%d", ret);
   1325 		n_node = xmlNewChild(n_obj, NULL, (xmlChar *)STATUSELEMENT,
   1326 		    (xmlChar *)numbuf);
   1327 		if (n_node == NULL) {
   1328 		    return (ERR_XML_NEWCHILD_FAILED);
   1329 		}
   1330 		n_node = xmlNewChild(n_obj, NULL, (xmlChar *)MESSAGEELEMENT,
   1331 		    (xmlChar *)result_code_to_str(ret));
   1332 		if (n_node == NULL) {
   1333 		    return (ERR_XML_NEWCHILD_FAILED);
   1334 		}
   1335 	    }
   1336 	} else {
   1337 	    return (ERR_XML_NEWNODE_FAILED);
   1338 	}
   1339 
   1340 	return (0);
   1341 }
   1342 
   1343 /*
   1344  * ****************************************************************************
   1345  *
   1346  * handle_partial_failure:
   1347  *
   1348  * doc	- response doc to fill up
   1349  * ret	- return code from the caller.
   1350  *
   1351  * ****************************************************************************
   1352  */
   1353 static int
   1354 handle_partial_failure(
   1355 	xmlDocPtr doc,
   1356 	int ret,
   1357 	boolean_t all_failed
   1358 )
   1359 {
   1360 	xmlNodePtr	n_obj, n_node, root;
   1361 	char numbuf[32];
   1362 
   1363 	root = xmlDocGetRootElement(doc);
   1364 	if (root == NULL) {
   1365 	    return (ERR_SYNTAX_MISSING_ROOT);
   1366 	}
   1367 	n_obj = xmlNewNode(NULL, (xmlChar *)RESULTELEMENT);
   1368 	if (n_obj) {
   1369 	    if (root->children) {
   1370 		/* some or all associations failed to create */
   1371 		n_obj = xmlAddPrevSibling(root->children, n_obj);
   1372 		/* capture last error. should come up with all failed?? */
   1373 		(void) sprintf(numbuf, "%d",
   1374 		    all_failed ? ret : PARTIAL_FAILURE);
   1375 		n_node = xmlNewChild(n_obj, NULL, (xmlChar *)STATUSELEMENT,
   1376 		    (xmlChar *)numbuf);
   1377 		if (n_node == NULL) {
   1378 			return (ERR_XML_NEWCHILD_FAILED);
   1379 		}
   1380 		n_node = xmlNewChild(n_obj, NULL, (xmlChar *)MESSAGEELEMENT,
   1381 		    (xmlChar *)result_code_to_str(all_failed ? ret :
   1382 			PARTIAL_FAILURE));
   1383 		if (n_node == NULL) {
   1384 		    return (ERR_XML_NEWCHILD_FAILED);
   1385 		}
   1386 	    } else {
   1387 		n_obj = xmlAddChild(root, n_obj);
   1388 		if (n_obj == NULL) {
   1389 		    return (ERR_XML_ADDCHILD_FAILED);
   1390 		}
   1391 		(void) sprintf(numbuf, "%d", (ret != 0) ? ret : 0);
   1392 		n_node = xmlNewChild(n_obj, NULL, (xmlChar *)STATUSELEMENT,
   1393 		    (xmlChar *)numbuf);
   1394 		if (n_node == NULL) {
   1395 		    return (ERR_XML_NEWCHILD_FAILED);
   1396 		}
   1397 		n_node = xmlNewChild(n_obj, NULL, (xmlChar *)MESSAGEELEMENT,
   1398 		    (xmlChar *)result_code_to_str((ret != 0) ? ret : 0));
   1399 		if (n_node == NULL) {
   1400 		    return (ERR_XML_NEWCHILD_FAILED);
   1401 		}
   1402 	    }
   1403 	} else {
   1404 	    return (ERR_XML_NEWNODE_FAILED);
   1405 	}
   1406 
   1407 	return (0);
   1408 }
   1409 
   1410 /*
   1411  * ****************************************************************************
   1412  *
   1413  * get_serverconfig_op:
   1414  *	The routine process server administrative setting.
   1415  *
   1416  * doc	- response doc to fill up.
   1417  *
   1418  * ****************************************************************************
   1419  */
   1420 int
   1421 get_serverconfig_op(
   1422 	xmlDocPtr doc
   1423 )
   1424 {
   1425 	extern uint64_t esi_threshold;
   1426 	extern uint8_t mgmt_scn;
   1427 	extern ctrl_node_t *control_nodes;
   1428 	extern pthread_mutex_t ctrl_node_mtx;
   1429 	extern char data_store[MAXPATHLEN];
   1430 
   1431 	xmlNodePtr	n_obj, root;
   1432 	char numbuf[32];
   1433 	ctrl_node_t *ctrl_node_p;
   1434 	int ret = 0;
   1435 
   1436 	root = xmlDocGetRootElement(doc);
   1437 	if (root == NULL) {
   1438 	    return (ERR_SYNTAX_MISSING_ROOT);
   1439 	}
   1440 	n_obj = xmlNewNode(NULL, (xmlChar *)ISNSSERVER);
   1441 	if (n_obj) {
   1442 	    n_obj = xmlAddChild(root, n_obj);
   1443 	    if (n_obj == NULL) {
   1444 		return (ERR_XML_ADDCHILD_FAILED);
   1445 	    }
   1446 	} else {
   1447 	    return (ERR_XML_ADDCHILD_FAILED);
   1448 	}
   1449 
   1450 	if (xmlNewChild(n_obj, NULL, (xmlChar *)DATASTORELOCATION,
   1451 	    (xmlChar *)data_store) == NULL) {
   1452 	    return (ERR_XML_NEWCHILD_FAILED);
   1453 	}
   1454 
   1455 	(void) sprintf(numbuf, "%llu", esi_threshold);
   1456 	if (xmlNewChild(n_obj, NULL, (xmlChar *)ESIRETRYTHRESHOLD,
   1457 	    (xmlChar *)numbuf) == NULL) {
   1458 	    return (ERR_XML_NEWCHILD_FAILED);
   1459 	}
   1460 	if (xmlNewChild(n_obj, NULL, (xmlChar *)MANAGEMENTSCNENABLED,
   1461 	    (mgmt_scn) ? (uchar_t *)XMLTRUE : (uchar_t *)XMLFALSE) == NULL) {
   1462 	    return (ERR_XML_NEWCHILD_FAILED);
   1463 	}
   1464 
   1465 	(void) pthread_mutex_lock(&ctrl_node_mtx);
   1466 	if (control_nodes == NULL) {
   1467 	    if (xmlNewChild(n_obj, NULL, (xmlChar *)CONTROLNODENAME,
   1468 		    (xmlChar *)NULL) == NULL) {
   1469 		    (void) pthread_mutex_unlock(&ctrl_node_mtx);
   1470 		    return (ERR_XML_NEWCHILD_FAILED);
   1471 	    }
   1472 	} else {
   1473 	    ctrl_node_p = control_nodes;
   1474 	    while (ctrl_node_p != NULL) {
   1475 		if (xmlNewChild(n_obj, NULL, (xmlChar *)CONTROLNODENAME,
   1476 		    (xmlChar *)ctrl_node_p->name) == NULL) {
   1477 		    (void) pthread_mutex_unlock(&ctrl_node_mtx);
   1478 		    return (ERR_XML_NEWCHILD_FAILED);
   1479 		}
   1480 		ctrl_node_p = ctrl_node_p->next;
   1481 	    }
   1482 	}
   1483 	(void) pthread_mutex_unlock(&ctrl_node_mtx);
   1484 
   1485 	return (handle_partial_success(doc, ret));
   1486 }
   1487 
   1488 /*
   1489  * ****************************************************************************
   1490  *
   1491  * get_node_op:
   1492  *	service get operation on a given node.
   1493  *
   1494  * req	- contains all info for a request.
   1495  * doc	- response doc to fill up
   1496  *
   1497  * ****************************************************************************
   1498  */
   1499 int
   1500 get_node_op(
   1501 	request_t *req,
   1502 	xmlDocPtr doc
   1503 	/* any additional arguments go here */
   1504 )
   1505 {
   1506 	int ret = 0, ret_save = 0;
   1507 	int i = 0;
   1508 	lookup_ctrl_t lc, lc2, lc3;
   1509 	uint32_t uid;
   1510 	char buff2[INET6_ADDRSTRLEN];
   1511 
   1512 	/* prepare lookup ctrl data for looking for the node object */
   1513 	lc.curr_uid = 0;
   1514 	lc.type = get_lc_type(req->op_info.obj);
   1515 	lc.id[0] = get_lc_id(req->op_info.obj);
   1516 	lc.op[0] = OP_STRING;
   1517 	lc.op[1] = 0;
   1518 	lc.data[1].ptr = (uchar_t *)doc; /* xml writer descriptor */
   1519 	while (i < req->count) {
   1520 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
   1521 		ret = cache_lookup(&lc, &uid, cb_get_node_info);
   1522 		if (uid == 0) {
   1523 		    ret = ERR_MATCHING_ISCSI_NODE_NOT_FOUND;
   1524 		}
   1525 
   1526 		/* generate network entity object information */
   1527 		if (ret == 0 && lc.id[2] != 0) {
   1528 			/*
   1529 			 * !!! there might be no entity and portal info for
   1530 			 * !!! the node if it is not a registered node
   1531 			 */
   1532 			/* prepare lookup ctrl data for looking for entity */
   1533 			SET_UID_LCP(&lc2, OBJ_ENTITY, lc.id[2]);
   1534 
   1535 			lc2.data[1].ptr = (uchar_t *)doc;
   1536 			/* cb_get_node_info callback returned Node object. */
   1537 			lc2.data[2].ptr = lc.data[2].ptr;
   1538 			ret = cache_lookup(&lc2, &uid, cb_get_entity_info);
   1539 			if (uid == 0) {
   1540 			    ret = ERR_MATCHING_NETWORK_ENTITY_NOT_FOUND;
   1541 			}
   1542 		}
   1543 
   1544 		/* generate portal information */
   1545 		if (ret == 0 && lc.id[2] != 0) {
   1546 			/* prepare lookup ctrl data for looking for pg */
   1547 			lc2.curr_uid = 0;
   1548 			lc2.type = OBJ_PG;
   1549 			lc2.id[0] = ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID);
   1550 			lc2.op[0] = OP_STRING;
   1551 			/* lc.data[0].ptr contains node name */
   1552 			lc2.data[0].ptr = lc.data[0].ptr;
   1553 			lc2.op[1] = 0;
   1554 			lc2.data[1].ip = (in6_addr_t *)buff2;
   1555 
   1556 			/* prepare lookup ctrl data for looking for portal */
   1557 			lc3.curr_uid = 0;
   1558 			lc3.type = OBJ_PORTAL;
   1559 			lc3.id[0] = ATTR_INDEX_PORTAL(
   1560 				ISNS_PORTAL_IP_ADDR_ATTR_ID);
   1561 			lc3.op[0] = OP_MEMORY_IP6;
   1562 			lc3.id[1] = ATTR_INDEX_PORTAL(
   1563 				ISNS_PORTAL_PORT_ATTR_ID);
   1564 			lc3.op[1] = OP_INTEGER;
   1565 			lc3.op[2] = 0;
   1566 			/* cb_get_node_info callback returned Node object. */
   1567 			lc3.data[2].ptr = lc.data[2].ptr;
   1568 			for (;;) {
   1569 				ret = cache_lookup(&lc2, &uid, cb_get_pg_info);
   1570 				if (uid != 0) {
   1571 					/* we found a portal group */
   1572 					lc2.curr_uid = uid;
   1573 					/* it is a null pg if pgt is zero. */
   1574 					if (lc2.id[2] != 0) {
   1575 						/* pass ip addr */
   1576 						lc3.data[0].ip = lc2.data[1].ip;
   1577 						/* pass port num */
   1578 						lc3.data[1].ui = lc2.data[2].ui;
   1579 						/* pass pgt */
   1580 						lc3.id[2] = lc2.id[2];
   1581 						ret = cache_lookup(&lc3, &uid,
   1582 						    cb_get_portal_info);
   1583 					}
   1584 				} else {
   1585 					/*
   1586 					 * no more portal group which is
   1587 					 * tied to this stroage node object.
   1588 					 */
   1589 					break;
   1590 				}
   1591 			}
   1592 		}
   1593 		/* save error for this iteration */
   1594 		if (ret != 0) {
   1595 		    ret_save = ret;
   1596 		}
   1597 		ret = 0;
   1598 		i++;
   1599 	}
   1600 
   1601 	return (handle_partial_success(doc, ret_save));
   1602 }
   1603 
   1604 /*
   1605  * ****************************************************************************
   1606  *
   1607  * i_get_dd_dds_op:
   1608  *	serves get operatrion on dd or dds.
   1609  *
   1610  * req	- contains all info for a request.
   1611  * doc	- response doc to fill up
   1612  * obj_type	- object type(either dd or dd set)
   1613  *
   1614  * ****************************************************************************
   1615  */
   1616 static int
   1617 i_get_dd_dds_op(
   1618 	request_t *req,
   1619 	xmlDocPtr doc,
   1620 	isns_type_t obj_type
   1621 	/* any additional arguments go here */
   1622 )
   1623 {
   1624 	result_code_t ret = 0, ret_save = 0;
   1625 	int i = 0;
   1626 	lookup_ctrl_t lc;
   1627 	uint32_t uid;
   1628 
   1629 	if ((obj_type != OBJ_DD) && (obj_type != OBJ_DDS)) {
   1630 	    return (ERR_INVALID_MGMT_REQUEST);
   1631 	}
   1632 
   1633 	/* prepare lookup ctrl data for looking for the node object */
   1634 	lc.curr_uid = 0;
   1635 	lc.type = obj_type;
   1636 	lc.id[0] = get_lc_id(req->op_info.obj);
   1637 	lc.op[0] = OP_STRING;
   1638 	lc.op[1] = 0;
   1639 	lc.data[1].ptr = (uchar_t *)doc; /* xml writer descriptor */
   1640 	while (i < req->count) {
   1641 		if (obj_type == OBJ_DD) {
   1642 		    lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
   1643 		    ret = cache_lookup(&lc, &uid, cb_get_dd_info);
   1644 		    if (uid == 0) {
   1645 			/* set an error and continue. */
   1646 			ret = ERR_MATCHING_DD_NOT_FOUND;
   1647 		    }
   1648 		} else {
   1649 		    lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
   1650 		    ret = cache_lookup(&lc, &uid, cb_get_ddset_info);
   1651 		    if (uid == 0) {
   1652 			/* set an error and continue. */
   1653 			ret = ERR_MATCHING_DDSET_NOT_FOUND;
   1654 		    }
   1655 		}
   1656 		/* save error for this iteration */
   1657 		if (ret != 0) {
   1658 		    ret_save = ret;
   1659 		}
   1660 		ret = 0;
   1661 		i++;
   1662 	}
   1663 
   1664 	return (handle_partial_success(doc, ret_save));
   1665 }
   1666 
   1667 /*
   1668  * ****************************************************************************
   1669  *
   1670  * i_delete_ddmember_op:
   1671  *	serves delete member operatrion on dd.
   1672  *
   1673  * container	- dd name
   1674  * member	- node name
   1675  *
   1676  * ****************************************************************************
   1677  */
   1678 static int
   1679 i_delete_ddmember_op(
   1680 	uchar_t *container,
   1681 	uchar_t *member
   1682 )
   1683 {
   1684 	int ret = 0;
   1685 
   1686 	isns_assoc_iscsi_t aiscsi;
   1687 	isns_obj_t *assoc;
   1688 	isns_attr_t *attr;
   1689 	int len;
   1690 
   1691 	lookup_ctrl_t lc;
   1692 	uint32_t dd_id;
   1693 
   1694 	/* prepare lookup ctrl data for looking for the dd object */
   1695 	lc.curr_uid = 0;
   1696 	lc.type = OBJ_DD;
   1697 	lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
   1698 	lc.op[0] = OP_STRING;
   1699 	lc.data[0].ptr = container;
   1700 	lc.op[1] = 0;
   1701 
   1702 	if ((dd_id = is_obj_there(&lc)) != 0) {
   1703 	    aiscsi.type = OBJ_ASSOC_ISCSI;
   1704 	    aiscsi.puid = dd_id;
   1705 
   1706 	    len = strlen((char *)member) + 1;
   1707 	    len += 4 - (len % 4);
   1708 
   1709 	    attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
   1710 		ISNS_DD_ISCSI_NAME_ATTR_ID)];
   1711 	    attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
   1712 	    attr->len = len;
   1713 	    attr->value.ptr = (uchar_t *)member;
   1714 	    attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
   1715 		ISNS_DD_ISCSI_INDEX_ATTR_ID)];
   1716 	    attr->tag = 0; /* clear it */
   1717 	    assoc = (isns_obj_t *)&aiscsi;
   1718 	    ret = remove_dd_member(assoc);
   1719 	} else {
   1720 	    ret = ERR_MATCHING_DD_NOT_FOUND;
   1721 	}
   1722 
   1723 	return (ret);
   1724 }
   1725 
   1726 /*
   1727  * ****************************************************************************
   1728  *
   1729  * i_delete_ddsetmember_op:
   1730  *	serves delete member operatrion on dd set.
   1731  *
   1732  * container	- dd set name
   1733  * member	- dd name
   1734  *
   1735  * ****************************************************************************
   1736  */
   1737 static int
   1738 i_delete_ddsetmember_op(
   1739 	uchar_t *container,
   1740 	uchar_t *member
   1741 )
   1742 {
   1743 	int ret = 0;
   1744 
   1745 	lookup_ctrl_t lc, lc2;
   1746 	uint32_t container_id, member_id;
   1747 
   1748 	/* prepare lookup ctrl data for looking for the dd-set object */
   1749 	lc.curr_uid = 0;
   1750 	lc.type = OBJ_DDS;
   1751 	lc.id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID);
   1752 	lc.op[0] = OP_STRING;
   1753 	lc.data[0].ptr = container;
   1754 	lc.op[1] = 0;
   1755 
   1756 	/* prepare lookup ctrl data for looking for the dd object */
   1757 	lc2.curr_uid = 0;
   1758 	lc2.type = OBJ_DD;
   1759 	lc2.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
   1760 	lc2.op[0] = OP_STRING;
   1761 	lc2.data[0].ptr = member;
   1762 	lc2.op[1] = 0;
   1763 
   1764 	if ((container_id = is_obj_there(&lc)) != 0) {
   1765 	    if ((member_id = is_obj_there(&lc2)) != 0) {
   1766 		ret = remove_dds_member(container_id, member_id);
   1767 	    } else {
   1768 		ret = ERR_MATCHING_DD_NOT_FOUND;
   1769 	    }
   1770 	} else {
   1771 	    ret = ERR_MATCHING_DDSET_NOT_FOUND;
   1772 	}
   1773 
   1774 	return (ret);
   1775 }
   1776 
   1777 /*
   1778  * ****************************************************************************
   1779  *
   1780  * get_dd_op:
   1781  *	service get operation on given dd(s).
   1782  *
   1783  * req	- contains all info for a request.
   1784  * doc	- response doc to fill up
   1785  *
   1786  * ****************************************************************************
   1787  */
   1788 int
   1789 get_dd_op(
   1790 	request_t *req,
   1791 	xmlDocPtr doc
   1792 	/* any additional arguments go here */
   1793 )
   1794 {
   1795 	return (i_get_dd_dds_op(req, doc, OBJ_DD));
   1796 }
   1797 
   1798 /*
   1799  * ****************************************************************************
   1800  *
   1801  * get_ddset_op:
   1802  *	service get operation on given dd set(s).
   1803  *
   1804  * req	- contains all info for a request.
   1805  * doc	- response doc to fill up
   1806  *
   1807  * ****************************************************************************
   1808  */
   1809 int
   1810 get_ddset_op(
   1811 	request_t *req,
   1812 	xmlDocPtr doc
   1813 	/* any additional arguments go here */
   1814 )
   1815 {
   1816 	return (i_get_dd_dds_op(req, doc, OBJ_DDS));
   1817 }
   1818 
   1819 /*
   1820  * ****************************************************************************
   1821  *
   1822  * enumerate_node_op:
   1823  *	services enumerate node op.
   1824  *
   1825  * req	- contains enumerate request info.
   1826  * doc	- response doc to fill up
   1827  *
   1828  * ****************************************************************************
   1829  */
   1830 int
   1831 enumerate_node_op(
   1832 	xmlDocPtr   doc
   1833 	/* any additional arguments go here */
   1834 )
   1835 {
   1836 	htab_t *htab = cache_get_htab(OBJ_ISCSI);
   1837 	uint32_t uid = 0;
   1838 	lookup_ctrl_t lc;
   1839 	int	    ret = 0, ret_save = 0;
   1840 
   1841 	SET_UID_LCP(&lc, OBJ_ISCSI, 0);
   1842 
   1843 	lc.data[1].ptr = (uchar_t *)doc;
   1844 	lc.data[2].ui = 0;
   1845 
   1846 	FOR_EACH_ITEM(htab, uid, {
   1847 		lc.data[0].ui = uid;
   1848 		ret = cache_lookup(&lc, NULL, cb_enumerate_node_info);
   1849 		if (ret != 0) {
   1850 		    ret_save = ret;
   1851 		}
   1852 	});
   1853 
   1854 	return (handle_partial_success(doc, ret_save));
   1855 }
   1856 
   1857 /*
   1858  * ****************************************************************************
   1859  *
   1860  * enumerate_dd_op:
   1861  *	services enumerate discovery domain op.
   1862  *
   1863  * req	- contains enumerate request info.
   1864  * doc	- response doc to fill up
   1865  *
   1866  * ****************************************************************************
   1867  */
   1868 int
   1869 enumerate_dd_op(
   1870 	xmlDocPtr   doc
   1871 	/* any additional arguments go here */
   1872 )
   1873 {
   1874 
   1875 	htab_t *htab = cache_get_htab(OBJ_DD);
   1876 	uint32_t uid = 0;
   1877 	lookup_ctrl_t lc;
   1878 	int	    ret = 0, ret_save = 0;
   1879 
   1880 	SET_UID_LCP(&lc, OBJ_DD, 0);
   1881 
   1882 	lc.data[1].ptr = (uchar_t *)doc;
   1883 	lc.data[2].ui = 0;
   1884 
   1885 	FOR_EACH_ITEM(htab, uid, {
   1886 		lc.data[0].ui = uid;
   1887 		ret = cache_lookup(&lc, NULL, cb_enumerate_dd_info);
   1888 		if (ret != 0) {
   1889 		    ret_save = ret;
   1890 		}
   1891 	});
   1892 
   1893 	return (handle_partial_success(doc, ret_save));
   1894 }
   1895 
   1896 /*
   1897  * ****************************************************************************
   1898  *
   1899  * enumerate_ddset_op:
   1900  *	services enumerate discovery domain set op.
   1901  *
   1902  * req	- contains enumerate request info.
   1903  * doc	- response doc to fill up
   1904  *
   1905  * ****************************************************************************
   1906  */
   1907 int
   1908 enumerate_ddset_op(
   1909 	xmlDocPtr   doc
   1910 	/* any additional arguments go here */
   1911 )
   1912 {
   1913 	htab_t *htab = cache_get_htab(OBJ_DDS);
   1914 	uint32_t uid = 0;
   1915 	lookup_ctrl_t lc;
   1916 	int	    ret = 0, ret_save = 0;
   1917 
   1918 	SET_UID_LCP(&lc, OBJ_DDS, 0);
   1919 
   1920 	lc.data[1].ptr = (uchar_t *)doc;
   1921 	lc.data[2].ui = 0;
   1922 
   1923 	FOR_EACH_ITEM(htab, uid, {
   1924 		lc.data[0].ui = uid;
   1925 		ret = cache_lookup(&lc, NULL, cb_enumerate_ddset_info);
   1926 		if (ret != 0) {
   1927 		    ret_save = ret;
   1928 		}
   1929 	});
   1930 
   1931 	return (handle_partial_success(doc, ret_save));
   1932 }
   1933 
   1934 /*
   1935  * ****************************************************************************
   1936  *
   1937  * getassociated_dd_to_node_op:
   1938  *	construct a list of node that is associated with a given Discovery
   1939  *	Domain.
   1940  *
   1941  * req	- contains getAssociated request info.
   1942  * doc	- response doc to fill up
   1943  *
   1944  * ****************************************************************************
   1945  */
   1946 int
   1947 getAssociated_dd_to_node_op(
   1948 	request_t *req,
   1949 	xmlDocPtr   doc
   1950 	/* any additional arguments go here */
   1951 )
   1952 {
   1953 	uint32_t uid = 0, n;
   1954 	lookup_ctrl_t lc, lc2;
   1955 	int	i = 0, ret = 0, ret_save = 0;
   1956 	bmp_t	*p;
   1957 
   1958 	lc.curr_uid = 0;
   1959 	lc.type = OBJ_DD;
   1960 	lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
   1961 	lc.op[0] = OP_STRING;
   1962 	lc.op[1] = 0;
   1963 
   1964 	SET_UID_LCP(&lc2, OBJ_ISCSI, 0);
   1965 
   1966 	lc2.data[1].ptr = (uchar_t *)doc;
   1967 
   1968 	while (i < req->count) {
   1969 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
   1970 		if ((uid = is_obj_there(&lc)) != 0) {
   1971 		    ret = get_dd_matrix(uid, &p, &n);
   1972 		    FOR_EACH_MEMBER(p, n, uid, {
   1973 			lc2.data[0].ui = uid;
   1974 			lc2.data[2].ptr = (uchar_t *)req->req_data.data[i];
   1975 			ret = cache_lookup(&lc2, NULL,
   1976 			    cb_getAssociated_node_info);
   1977 		    });
   1978 		    free(p);
   1979 		} else {
   1980 		    ret = ERR_MATCHING_DD_NOT_FOUND;
   1981 		}
   1982 		/* save error for this iteration */
   1983 		if (ret != 0) {
   1984 		    ret_save = ret;
   1985 		}
   1986 		ret = 0;
   1987 		i++;
   1988 	}
   1989 
   1990 	return (handle_partial_success(doc, ret_save));
   1991 }
   1992 
   1993 /*
   1994  * ****************************************************************************
   1995  *
   1996  * getassociated_node_to_dd_op:
   1997  *	construct a list of Discovery Doamins that is associated with a given
   1998  *	node.
   1999  *
   2000  * req	- contains getAssociated request info.
   2001  * doc	- response doc to fill up
   2002  *
   2003  * ****************************************************************************
   2004  */
   2005 int
   2006 getAssociated_node_to_dd_op(
   2007 	request_t *req,
   2008 	xmlDocPtr   doc
   2009 	/* any additional arguments go here */
   2010 )
   2011 {
   2012 	uint32_t uid = 0, dd_id;
   2013 	lookup_ctrl_t lc, lc2;
   2014 	int	i = 0, ret = 0, ret_save = 0;
   2015 
   2016 	lc.curr_uid = 0;
   2017 	lc.type = OBJ_ISCSI;
   2018 	lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
   2019 	lc.op[0] = OP_STRING;
   2020 	lc.op[1] = 0;
   2021 
   2022 	SET_UID_LCP(&lc2, OBJ_DD, 0);
   2023 
   2024 	lc2.data[1].ptr = (uchar_t *)doc;
   2025 
   2026 	while (i < req->count) {
   2027 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
   2028 		if ((uid = is_obj_there(&lc)) != 0) {
   2029 		    if ((dd_id = get_dd_id(uid, 0)) == 0) {
   2030 			ret = ERR_NO_ASSOCIATED_DD_FOUND;
   2031 			i++;
   2032 			continue;
   2033 		    } else {
   2034 			do {
   2035 			    lc2.data[0].ui = dd_id;
   2036 			    lc2.data[2].ptr = (uchar_t *)req->req_data.data[i];
   2037 			    ret = cache_lookup(&lc2, NULL,
   2038 				cb_getAssociated_node_to_dd_info);
   2039 			    dd_id = get_dd_id(uid, dd_id);
   2040 			} while (dd_id != 0);
   2041 		    };
   2042 		} else {
   2043 		    ret = ERR_MATCHING_NODE_NOT_FOUND;
   2044 		}
   2045 		/* save error for this iteration */
   2046 		if (ret != 0) {
   2047 		    ret_save = ret;
   2048 		}
   2049 		ret = 0;
   2050 		i++;
   2051 	}
   2052 
   2053 	return (handle_partial_success(doc, ret_save));
   2054 }
   2055 
   2056 /*
   2057  * ****************************************************************************
   2058  *
   2059  * getassociated_ddset_to_dd_op:
   2060  *	construct a list of Discovery Doamins that is associated with a given
   2061  *	Discover Domain set.
   2062  *
   2063  * req	- contains getAssociated request info.
   2064  * doc	- response doc to fill up
   2065  *
   2066  * ****************************************************************************
   2067  */
   2068 int
   2069 getAssociated_ddset_to_dd_op(
   2070 	request_t *req,
   2071 	xmlDocPtr   doc
   2072 	/* any additional arguments go here */
   2073 )
   2074 {
   2075 	uint32_t uid = 0, n;
   2076 	lookup_ctrl_t lc, lc2;
   2077 	int	i = 0, ret = 0, ret_save = 0;
   2078 	bmp_t	*p;
   2079 
   2080 	lc.curr_uid = 0;
   2081 	lc.type = OBJ_DDS;
   2082 	lc.id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID);
   2083 	lc.op[0] = OP_STRING;
   2084 	lc.op[1] = 0;
   2085 
   2086 	SET_UID_LCP(&lc2, OBJ_DD, 0);
   2087 
   2088 	lc2.data[1].ptr = (uchar_t *)doc;
   2089 
   2090 	while (i < req->count) {
   2091 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
   2092 		if ((uid = is_obj_there(&lc)) != 0) {
   2093 		    ret = get_dds_matrix(uid, &p, &n);
   2094 		    FOR_EACH_MEMBER(p, n, uid, {
   2095 			lc2.data[0].ui = uid;
   2096 			lc2.data[2].ptr = (uchar_t *)req->req_data.data[i];
   2097 			ret = cache_lookup(&lc2, NULL,
   2098 			    cb_getAssociated_dd_info);
   2099 		    });
   2100 		    free(p);
   2101 		} else {
   2102 		    ret = ERR_MATCHING_DDSET_NOT_FOUND;
   2103 		}
   2104 		/* save error for this iteration */
   2105 		if (ret != 0) {
   2106 		    ret_save = ret;
   2107 		}
   2108 		ret = 0;
   2109 		i++;
   2110 	}
   2111 
   2112 	return (handle_partial_success(doc, ret_save));
   2113 }
   2114 
   2115 /*
   2116  * ****************************************************************************
   2117  *
   2118  * getassociated_dd_to_ddset_op:
   2119  *	construct a list of Discovery Doamin sets that is associated with a
   2120  *	given Discovery Domain.
   2121  *
   2122  * req	- contains getAssociated request info.
   2123  * doc	- response doc to fill up
   2124  *
   2125  * ****************************************************************************
   2126  */
   2127 int
   2128 getAssociated_dd_to_ddset_op(
   2129 	request_t *req,
   2130 	xmlDocPtr   doc
   2131 	/* any additional arguments go here */
   2132 )
   2133 {
   2134 	uint32_t uid = 0, ddset_id;
   2135 	lookup_ctrl_t lc, lc2;
   2136 	int	i = 0, ret = 0, ret_save = 0;
   2137 
   2138 	lc.curr_uid = 0;
   2139 	lc.type = OBJ_DD;
   2140 	lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
   2141 	lc.op[0] = OP_STRING;
   2142 	lc.op[1] = 0;
   2143 
   2144 	SET_UID_LCP(&lc2, OBJ_DDS, 0);
   2145 
   2146 	lc2.data[1].ptr = (uchar_t *)doc;
   2147 
   2148 	while (i < req->count) {
   2149 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
   2150 		if ((uid = is_obj_there(&lc)) != 0) {
   2151 		    lc2.data[2].ui = 0;
   2152 		    if ((ddset_id = get_dds_id(uid, 0)) == 0) {
   2153 			ret = ERR_NO_ASSOCIATED_DDSET_FOUND;
   2154 			i++;
   2155 			continue;
   2156 		    } else {
   2157 			do {
   2158 			    lc2.data[0].ui = ddset_id;
   2159 			    lc2.data[2].ptr = (uchar_t *)req->req_data.data[i];
   2160 			    ret = cache_lookup(&lc2, NULL,
   2161 				cb_getAssociated_dd_to_ddset_info);
   2162 			    ddset_id = get_dds_id(uid, ddset_id);
   2163 			} while (ddset_id != 0);
   2164 		    };
   2165 		} else {
   2166 		    ret = ERR_MATCHING_DD_NOT_FOUND;
   2167 		}
   2168 		if (ret != 0) {
   2169 		    ret_save = ret;
   2170 		}
   2171 		i++;
   2172 	}
   2173 
   2174 	return (handle_partial_success(doc, ret_save));
   2175 }
   2176 
   2177 /*
   2178  * ****************************************************************************
   2179  *
   2180  * delete_dd_ddset_op:
   2181  *	removes a list of dd or dd set.
   2182  *
   2183  * req	- contains delete request info.
   2184  * doc	- response doc to fill up
   2185  * obj_type	- object type(either dd or dd set)
   2186  *
   2187  * ****************************************************************************
   2188  */
   2189 int
   2190 delete_dd_ddset_op(
   2191 	request_t *req,
   2192 	xmlDocPtr doc,
   2193 	object_type type
   2194 	/* any additional arguments go here */
   2195 )
   2196 {
   2197 	result_code_t ret = 0, ret_save = 0;
   2198 	isns_type_t lc_type;
   2199 	int i = 0, err_count = 0;
   2200 	lookup_ctrl_t lc;
   2201 	uint32_t uid;
   2202 	xmlNodePtr	n_obj, n_node, root;
   2203 	xmlAttrPtr	n_attr;
   2204 	int different_err = 0;
   2205 
   2206 	root = xmlDocGetRootElement(doc);
   2207 	if (root == NULL) {
   2208 	    return (ERR_SYNTAX_MISSING_ROOT);
   2209 	}
   2210 	lc_type = get_lc_type(type);
   2211 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
   2212 	    return (ERR_INVALID_MGMT_REQUEST);
   2213 	}
   2214 
   2215 	/* prepare lookup ctrl data for looking for the node object */
   2216 	lc.curr_uid = 0;
   2217 	lc.type = lc_type;
   2218 	lc.id[0] = get_lc_id(req->op_info.obj);
   2219 	lc.op[0] = OP_STRING;
   2220 	lc.op[1] = 0;
   2221 	lc.data[1].ptr = (uchar_t *)doc; /* xml writer descriptor */
   2222 	while (i < req->count) {
   2223 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
   2224 
   2225 		/* lock the cache for writing */
   2226 		(void) cache_lock_write();
   2227 
   2228 		if ((uid = is_obj_there(&lc)) != 0) {
   2229 		    /* remove the dd/ddset */
   2230 		    ret = (lc_type == OBJ_DD) ?
   2231 			remove_dd_object(uid) :
   2232 			remove_dds_object(uid);
   2233 		    /* unlock the cache and sync the data */
   2234 		    ret = cache_unlock_sync(ret);
   2235 		} else {
   2236 		    /* unlock the cache and no need to sync data */
   2237 		    (void) cache_unlock_nosync();
   2238 		    /* set an error and continue. */
   2239 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
   2240 			ERR_MATCHING_DDSET_NOT_FOUND;
   2241 		}
   2242 
   2243 		if (ret != 0) {
   2244 		/* keep track if there are different errors encountered. */
   2245 		    if (ret_save != 0 && ret != ret_save) {
   2246 			different_err++;
   2247 		    }
   2248 		    err_count++;
   2249 		    n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
   2250 		    if (n_obj) {
   2251 			if ((n_obj = xmlAddChild(root, n_obj)) == NULL) {
   2252 			    return (ERR_XML_ADDCHILD_FAILED);
   2253 			}
   2254 		    } else {
   2255 			return (ERR_XML_NEWNODE_FAILED);
   2256 		    }
   2257 
   2258 		    n_node = (lc_type == OBJ_DD) ?
   2259 			xmlNewNode(NULL, (xmlChar *)DDOBJECT) :
   2260 			xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
   2261 		    if (n_node) {
   2262 			if ((n_node = xmlAddChild(n_obj, n_node)) == NULL) {
   2263 			    return (ERR_XML_ADDCHILD_FAILED);
   2264 			}
   2265 			n_attr = xmlSetProp(n_node, (xmlChar *)NAMEATTR,
   2266 				(xmlChar *)req->req_data.data[i]);
   2267 			if (n_attr == NULL) {
   2268 			    return (ERR_XML_SETPROP_FAILED);
   2269 			}
   2270 		    } else {
   2271 			return (ERR_XML_NEWNODE_FAILED);
   2272 		    }
   2273 		    ret_save = ret;
   2274 		}
   2275 		i ++;
   2276 	}
   2277 
   2278 	return (handle_partial_failure(doc, ret_save,
   2279 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
   2280 }
   2281 
   2282 /*
   2283  * ****************************************************************************
   2284  *
   2285  * delete_ddmember_ddsetmember_op:
   2286  *	removes a list of dd memeber or dd seti member.
   2287  *
   2288  * req	- contains delete request info.
   2289  * doc	- response doc to fill up
   2290  * type	- object type(either dd or dd set)
   2291  *
   2292  * ****************************************************************************
   2293  */
   2294 int
   2295 delete_ddmember_ddsetmember_op(
   2296 	request_t *req,
   2297 	xmlDocPtr doc,
   2298 	object_type type
   2299 	/* any additional arguments go here */
   2300 )
   2301 {
   2302 	result_code_t ret = 0, ret_save = 0;
   2303 	isns_type_t lc_type;
   2304 	int i = 0, err_count = 0;
   2305 	lookup_ctrl_t lc, lc2;
   2306 	uint32_t container_id, member_id;
   2307 	xmlNodePtr	n_node, n_obj, root;
   2308 	xmlAttrPtr	n_attr;
   2309 	int different_err = 0;
   2310 	int is_a_member;
   2311 
   2312 	lc_type = get_lc_type(type);
   2313 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
   2314 	    return (ERR_INVALID_MGMT_REQUEST);
   2315 	}
   2316 
   2317 	/* prepare lookup ctrl data for looking for the node object */
   2318 	lc.curr_uid = 0;
   2319 	lc.type = lc_type;
   2320 	lc.id[0] = get_lc_id(req->op_info.obj);
   2321 	lc.op[0] = OP_STRING;
   2322 	lc.op[1] = 0;
   2323 
   2324 	lc2.curr_uid = 0;
   2325 	if (lc_type == OBJ_DD) {
   2326 	    lc2.type = OBJ_ISCSI;
   2327 	    lc2.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
   2328 	} else {
   2329 	    lc2.type = OBJ_DD;
   2330 	    lc2.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
   2331 	}
   2332 	lc2.op[0] = OP_STRING;
   2333 	lc2.op[1] = 0;
   2334 
   2335 	root = xmlDocGetRootElement(doc);
   2336 	if (root == NULL) {
   2337 	    return (ERR_SYNTAX_MISSING_ROOT);
   2338 	}
   2339 
   2340 	while (i < req->count) {
   2341 		lc.data[0].ptr = (uchar_t *)req->req_data.pair[i]->container;
   2342 
   2343 		/* get the dd_id/dds_id */
   2344 		(void) cache_lock_write();
   2345 		container_id = is_obj_there(&lc);
   2346 
   2347 		if (container_id != 0) {
   2348 		    lc2.data[0].ptr = (uchar_t *)req->req_data.pair[i]->member;
   2349 
   2350 		    member_id = is_obj_there(&lc2);
   2351 		    if (member_id != 0) {
   2352 			is_a_member =
   2353 			    (container_id ==
   2354 			    ((lc_type == OBJ_DD) ?
   2355 			    get_dd_id(member_id, container_id - 1) :
   2356 			    get_dds_id(member_id, container_id - 1)));
   2357 		    }
   2358 		    if (member_id != 0 && is_a_member != 0) {
   2359 			/* delete the dd member */
   2360 			ret = (lc_type == OBJ_DD) ?
   2361 			    i_delete_ddmember_op(
   2362 				(uchar_t *)req->req_data.pair[i]->container,
   2363 				(uchar_t *)req->req_data.pair[i]->member) :
   2364 			    i_delete_ddsetmember_op(
   2365 				(uchar_t *)req->req_data.pair[i]->container,
   2366 				(uchar_t *)req->req_data.pair[i]->member);
   2367 			/* unlock the cache and sync the data */
   2368 			ret = cache_unlock_sync(ret);
   2369 		    } else {
   2370 			/* unlock the cache and no need to sync */
   2371 			(void) cache_unlock_nosync();
   2372 			ret = ERR_NO_SUCH_ASSOCIATION;
   2373 		    }
   2374 		} else {
   2375 		    /* unlock the cache and no need to sync */
   2376 		    (void) cache_unlock_nosync();
   2377 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
   2378 			ERR_MATCHING_DDSET_NOT_FOUND;
   2379 		}
   2380 
   2381 		if (ret != 0) {
   2382 		/* keep track if there are different errors encountered. */
   2383 		    if (ret_save != 0 && ret != ret_save) {
   2384 			different_err++;
   2385 		    }
   2386 		    ret_save = ret;
   2387 		    err_count++;
   2388 		    n_obj = xmlNewNode(NULL, (xmlChar *)ASSOCIATION);
   2389 		    if (n_obj) {
   2390 			n_obj = xmlAddChild(root, n_obj);
   2391 			if (n_obj == NULL) {
   2392 			    return (ERR_XML_ADDCHILD_FAILED);
   2393 			}
   2394 		    } else {
   2395 			return (ERR_XML_NEWNODE_FAILED);
   2396 		    }
   2397 		    if (lc_type == OBJ_DD) {
   2398 			n_node =
   2399 			    xmlNewNode(NULL, (xmlChar *)DDOBJECTMEMBER);
   2400 			n_attr = xmlSetProp(n_node, (xmlChar *)NODENAMEATTR,
   2401 			    (xmlChar *)req->req_data.pair[i]->member);
   2402 			if (n_attr == NULL) {
   2403 			    return (ERR_XML_SETPROP_FAILED);
   2404 			}
   2405 			n_attr = xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
   2406 			    (xmlChar *)req->req_data.pair[i]->container);
   2407 			if (n_attr == NULL) {
   2408 			    return (ERR_XML_SETPROP_FAILED);
   2409 			}
   2410 		    } else {
   2411 			n_node =
   2412 			    xmlNewNode(NULL, (xmlChar *)DDSETOBJECTMEMBER);
   2413 			n_attr = xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
   2414 			    (xmlChar *)req->req_data.pair[i]->member);
   2415 			if (n_attr == NULL) {
   2416 			    return (ERR_XML_SETPROP_FAILED);
   2417 			}
   2418 			n_attr = xmlSetProp(n_node, (xmlChar *)DDSETNAMEATTR,
   2419 			    (xmlChar *)req->req_data.pair[i]->container);
   2420 			if (n_attr == NULL) {
   2421 			    return (ERR_XML_SETPROP_FAILED);
   2422 			}
   2423 		    }
   2424 		    if (xmlAddChild(n_obj, n_node) == NULL) {
   2425 			return (ERR_XML_ADDCHILD_FAILED);
   2426 		    }
   2427 		}
   2428 		i++;
   2429 	}
   2430 
   2431 	return (handle_partial_failure(doc, ret_save,
   2432 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
   2433 }
   2434 
   2435 /*
   2436  * ****************************************************************************
   2437  *
   2438  * create_ddmember_ddsetmember_op:
   2439  *	removes a list of dd memeber or dd seti member.
   2440  *
   2441  * req	- contains delete request info.
   2442  * doc	- response doc to fill up
   2443  * type	- object type(either dd or dd set)
   2444  *
   2445  * ****************************************************************************
   2446  */
   2447 int
   2448 create_ddmember_ddsetmember_op(
   2449 	request_t *req,
   2450 	xmlDocPtr doc,
   2451 	object_type type
   2452 	/* any additional arguments go here */
   2453 )
   2454 {
   2455 	result_code_t ret = 0, ret_save = 0;
   2456 	isns_type_t lc_type;
   2457 	int i = 0, err_count = 0;
   2458 	lookup_ctrl_t lc, lc2;
   2459 	uint32_t container_id, member_id;
   2460 	xmlNodePtr	n_node, n_obj, root;
   2461 	isns_assoc_iscsi_t aiscsi = { 0 };
   2462 	isns_assoc_dd_t add = { 0 };
   2463 	isns_obj_t *assoc;
   2464 	isns_attr_t *attr;
   2465 	uint32_t len;
   2466 	int different_err = 0;
   2467 
   2468 	lc_type = get_lc_type(type);
   2469 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
   2470 	    return (ERR_INVALID_MGMT_REQUEST);
   2471 	}
   2472 
   2473 	/* prepare lookup ctrl data for looking for the node object */
   2474 	lc.curr_uid = 0;
   2475 	lc.type = lc_type;
   2476 	lc.id[0] = get_lc_id(req->op_info.obj);
   2477 	lc.op[0] = OP_STRING;
   2478 	lc.op[1] = 0;
   2479 
   2480 	lc2.curr_uid = 0;
   2481 	if (lc_type == OBJ_DD) {
   2482 	    lc2.type = OBJ_ISCSI;
   2483 	    lc2.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
   2484 	} else {
   2485 	    lc2.type = OBJ_DD;
   2486 	    lc2.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
   2487 	}
   2488 	lc2.op[0] = OP_STRING;
   2489 	lc2.op[1] = 0;
   2490 
   2491 	root = xmlDocGetRootElement(doc);
   2492 	if (root == NULL) {
   2493 	    return (ERR_SYNTAX_MISSING_ROOT);
   2494 	}
   2495 
   2496 	while (i < req->count) {
   2497 		lc.data[0].ptr = (uchar_t *)req->req_data.pair[i]->container;
   2498 
   2499 		/* get the dd_id/dds_id */
   2500 		(void) cache_lock_write();
   2501 		container_id = is_obj_there(&lc);
   2502 
   2503 		if (container_id != 0) {
   2504 		    (void) memset(&aiscsi, 0, sizeof (aiscsi));
   2505 		    if (lc_type == OBJ_DD) {
   2506 			aiscsi.puid = container_id;
   2507 			aiscsi.type = OBJ_ASSOC_ISCSI;
   2508 			attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
   2509 			    ISNS_DD_ISCSI_NAME_ATTR_ID)];
   2510 			attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
   2511 			len = xmlStrlen(
   2512 			    (xmlChar *)req->req_data.pair[i]->member) + 1;
   2513 			len += 4 - (len % 4); /* on 4 bytes aligned */
   2514 			attr->len = len;
   2515 			attr->value.ptr =
   2516 			    (uchar_t *)req->req_data.pair[i]->member;
   2517 			assoc = (isns_obj_t *)&aiscsi;
   2518 
   2519 			/* add the dd member */
   2520 			ret = add_dd_member(assoc);
   2521 
   2522 			/* unlock the cache and sync the data */
   2523 			ret = cache_unlock_sync(ret);
   2524 		    } else {
   2525 			lc2.data[0].ptr =
   2526 			    (uchar_t *)req->req_data.pair[i]->member;
   2527 
   2528 			if ((member_id = is_obj_there(&lc2)) != 0) {
   2529 			    add.puid = container_id;
   2530 			    add.type = OBJ_ASSOC_DD;
   2531 			    attr = &add.attrs[ATTR_INDEX_ASSOC_DD(
   2532 				ISNS_DD_ID_ATTR_ID)];
   2533 			    attr->tag = ISNS_DD_ID_ATTR_ID;
   2534 			    attr->len = 4;
   2535 			    attr->value.ui = member_id;
   2536 			    assoc = (isns_obj_t *)&add;
   2537 
   2538 			    /* add the dd-set member */
   2539 			    ret = add_dds_member(assoc);
   2540 
   2541 			    /* unlock the cache and sync the data */
   2542 			    ret = cache_unlock_sync(ret);
   2543 			} else {
   2544 			    /* unlock the cache and no need to sync */
   2545 			    (void) cache_unlock_nosync();
   2546 			    ret = ERR_MATCHING_DD_NOT_FOUND;
   2547 			}
   2548 		    }
   2549 		} else {
   2550 		    /* unlock the cache and no need to sync */
   2551 		    (void) cache_unlock_nosync();
   2552 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
   2553 			ERR_MATCHING_DDSET_NOT_FOUND;
   2554 		}
   2555 		if (ret != 0) {
   2556 		/* keep track if there are different errors encountered. */
   2557 		    if (ret_save != 0 && ret != ret_save) {
   2558 			different_err++;
   2559 		    }
   2560 		    err_count++;
   2561 		    n_obj = xmlNewNode(NULL, (xmlChar *)ASSOCIATION);
   2562 		    if (n_obj) {
   2563 			n_obj = xmlAddChild(root, n_obj);
   2564 			if (n_obj == NULL) {
   2565 			    return (ERR_XML_ADDCHILD_FAILED);
   2566 			}
   2567 		    } else {
   2568 			return (ERR_XML_NEWNODE_FAILED);
   2569 		    }
   2570 		    if (lc_type == OBJ_DD) {
   2571 			n_node =
   2572 			    xmlNewNode(NULL, (xmlChar *)DDOBJECTMEMBER);
   2573 			if (xmlSetProp(n_node, (xmlChar *)NODENAMEATTR,
   2574 			    (xmlChar *)req->req_data.pair[i]->member) == NULL) {
   2575 			    return (ERR_XML_SETPROP_FAILED);
   2576 			}
   2577 			if (xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
   2578 			    (xmlChar *)req->req_data.pair[i]->container) ==
   2579 			    NULL) {
   2580 			    return (ERR_XML_SETPROP_FAILED);
   2581 			}
   2582 		    } else {
   2583 			n_node =
   2584 			    xmlNewNode(NULL, (xmlChar *)DDSETOBJECTMEMBER);
   2585 			if (xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
   2586 			    (xmlChar *)req->req_data.pair[i]->member) == NULL) {
   2587 			    return (ERR_XML_SETPROP_FAILED);
   2588 			}
   2589 			if (xmlSetProp(n_node, (xmlChar *)DDSETNAMEATTR,
   2590 			    (xmlChar *)req->req_data.pair[i]->container) ==
   2591 			    NULL) {
   2592 			    return (ERR_XML_SETPROP_FAILED);
   2593 			}
   2594 		    }
   2595 		    if (xmlAddChild(n_obj, n_node) == NULL) {
   2596 			return (ERR_XML_ADDCHILD_FAILED);
   2597 		    }
   2598 		    ret_save = ret;
   2599 		}
   2600 		i++;
   2601 	}
   2602 
   2603 	return (handle_partial_failure(doc, ret_save,
   2604 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
   2605 }
   2606 
   2607 /*
   2608  * ****************************************************************************
   2609  *
   2610  * rename_dd_ddset_op:
   2611  *	removes a list of dd memeber or dd seti member.
   2612  *
   2613  * req	- contains delete request info.
   2614  * doc	- response doc to fill up
   2615  * type	- object type(either dd or dd set)
   2616  *
   2617  * ****************************************************************************
   2618  */
   2619 static int
   2620 rename_dd_ddset_op(
   2621 	request_t *req,
   2622 	xmlDocPtr doc,
   2623 	object_type type
   2624 	/* any additional arguments go here */
   2625 )
   2626 {
   2627 	result_code_t ret = 0, ret_save = 0;
   2628 	isns_type_t lc_type;
   2629 	int i = 0, err_count = 0;
   2630 	lookup_ctrl_t lc;
   2631 	uint32_t container_id;
   2632 	xmlNodePtr	n_node, n_obj, root;
   2633 	uchar_t *name;
   2634 	uint32_t len;
   2635 	int different_err = 0;
   2636 
   2637 	lc_type = get_lc_type(type);
   2638 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
   2639 	    return (ERR_INVALID_MGMT_REQUEST);
   2640 	}
   2641 
   2642 	/* prepare lookup ctrl data for looking for the node object */
   2643 	SET_UID_LCP(&lc, lc_type, 0);
   2644 
   2645 	root = xmlDocGetRootElement(doc);
   2646 	if (root == NULL) {
   2647 	    return (ERR_SYNTAX_MISSING_ROOT);
   2648 	}
   2649 
   2650 	while (i < req->count) {
   2651 		/* id is checked to be not NULL before calling this routine. */
   2652 		lc.data[0].ui = *(req->req_data.attrlist[i]->id);
   2653 
   2654 		/* get the dd_id/dds_id */
   2655 		(void) cache_lock_write();
   2656 
   2657 		if ((container_id = is_obj_there(&lc)) != 0) {
   2658 		    name = (uchar_t *)req->req_data.attrlist[i]->name;
   2659 		    /* the length of the name need to include the */
   2660 		    /* null terminator and be on 4 bytes aligned */
   2661 		    len = xmlStrlen(name) + 1;
   2662 		    len += 4 - (len % 4);
   2663 
   2664 		    /* rename the dd/dds */
   2665 		    ret = (lc_type == OBJ_DD) ?
   2666 			update_dd_name(container_id, len, name) :
   2667 			update_dds_name(container_id, len, name);
   2668 
   2669 		    /* release the lock and sync the data */
   2670 		    ret = cache_unlock_sync(ret);
   2671 		} else {
   2672 		    /* release the lock and no need to sync */
   2673 		    (void) cache_unlock_nosync();
   2674 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
   2675 			ERR_MATCHING_DDSET_NOT_FOUND;
   2676 		}
   2677 		if (ret != 0) {
   2678 		/* keep track if there are different errors encountered. */
   2679 		    if (ret_save != 0 && ret != ret_save) {
   2680 			different_err++;
   2681 		    }
   2682 		    ret_save = ret;
   2683 		    err_count++;
   2684 		    n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
   2685 		    if (n_obj) {
   2686 			if ((n_obj = xmlAddChild(root, n_obj)) == NULL) {
   2687 			    return (ERR_XML_ADDCHILD_FAILED);
   2688 			}
   2689 		    } else {
   2690 			return (ERR_XML_NEWNODE_FAILED);
   2691 		    }
   2692 
   2693 		    n_node = (lc_type == OBJ_DD) ?
   2694 			xmlNewNode(NULL, (xmlChar *)DDOBJECT) :
   2695 			xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
   2696 		    if (n_node) {
   2697 			if ((n_node = xmlAddChild(n_obj, n_node)) == NULL) {
   2698 			    return (ERR_XML_ADDCHILD_FAILED);
   2699 			} else {
   2700 			    if (xmlSetProp(n_node, (xmlChar *)NAMEATTR,
   2701 				(xmlChar *)req->req_data.attrlist[i]->name) ==
   2702 				NULL) {
   2703 				return (ERR_XML_SETPROP_FAILED);
   2704 			    }
   2705 			}
   2706 		    } else {
   2707 			return (ERR_XML_NEWNODE_FAILED);
   2708 		    }
   2709 
   2710 		}
   2711 		i++;
   2712 	}
   2713 
   2714 	return (handle_partial_failure(doc, ret_save,
   2715 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
   2716 }
   2717 
   2718 /*
   2719  * ****************************************************************************
   2720  *
   2721  * update_dd_ddset_op:
   2722  *	removes a list of dd memeber or dd seti member.
   2723  *
   2724  * req	- contains delete request info.
   2725  * doc	- response doc to fill up
   2726  * type	- object type(either dd or dd set)
   2727  *
   2728  * ****************************************************************************
   2729  */
   2730 static int
   2731 update_dd_ddset_op(
   2732 	request_t *req,
   2733 	xmlDocPtr doc,
   2734 	object_type type
   2735 	/* any additional arguments go here */
   2736 )
   2737 {
   2738 	result_code_t ret = 0, ret_save = 0;
   2739 	isns_type_t lc_type;
   2740 	int i = 0, err_count = 0;
   2741 	lookup_ctrl_t lc;
   2742 	uint32_t container_id;
   2743 	xmlNodePtr	n_node, n_obj, root;
   2744 	int different_err = 0;
   2745 
   2746 	lc_type = get_lc_type(type);
   2747 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
   2748 	    return (ERR_INVALID_MGMT_REQUEST);
   2749 	}
   2750 
   2751 	/* prepare lookup ctrl data for looking for the node object */
   2752 	lc.curr_uid = 0;
   2753 	lc.type = lc_type;
   2754 	lc.id[0] = get_lc_id(req->op_info.obj);
   2755 	lc.op[0] = OP_STRING;
   2756 	lc.op[1] = 0;
   2757 
   2758 	root = xmlDocGetRootElement(doc);
   2759 	if (root == NULL) {
   2760 	    return (ERR_SYNTAX_MISSING_ROOT);
   2761 	}
   2762 
   2763 	while (i < req->count) {
   2764 		lc.data[0].ptr = req->req_data.attrlist[i]->name;
   2765 
   2766 		/* lock the cache for writing */
   2767 		(void) cache_lock_write();
   2768 
   2769 		if ((container_id = is_obj_there(&lc)) != 0) {
   2770 		    ret = (lc_type == OBJ_DD) ?
   2771 			/* enabled is checked to be not NULL before calling. */
   2772 			update_dd_features(container_id,
   2773 			*(req->req_data.attrlist[i]->enabled) ? 1 : 0):
   2774 			update_dds_status(container_id,
   2775 			*(req->req_data.attrlist[i]->enabled) ? 1 : 0);
   2776 		    /* unlock the cache and sync the data */
   2777 		    ret = cache_unlock_sync(ret);
   2778 		} else {
   2779 		    (void) cache_unlock_nosync();
   2780 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
   2781 			ERR_MATCHING_DDSET_NOT_FOUND;
   2782 		}
   2783 		if (ret != 0) {
   2784 		/* keep track if there are different errors encountered. */
   2785 		    if (ret_save != 0 && ret != ret_save) {
   2786 			different_err++;
   2787 		    }
   2788 		    ret_save = ret;
   2789 		    err_count++;
   2790 		    n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
   2791 		    if (n_obj) {
   2792 			if ((n_obj = xmlAddChild(root, n_obj)) == NULL) {
   2793 			    return (ERR_XML_ADDCHILD_FAILED);
   2794 			}
   2795 		    } else {
   2796 			return (ERR_XML_NEWNODE_FAILED);
   2797 		    }
   2798 
   2799 		    n_node = (lc_type == OBJ_DD) ?
   2800 			xmlNewNode(NULL, (xmlChar *)DDOBJECT) :
   2801 			xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
   2802 		    if (n_node) {
   2803 			if ((n_node = xmlAddChild(n_obj, n_node)) == NULL) {
   2804 			    return (ERR_XML_ADDCHILD_FAILED);
   2805 			} else {
   2806 			    if (xmlSetProp(n_node, (xmlChar *)NAMEATTR,
   2807 				(xmlChar *)req->req_data.attrlist[i]->name) ==
   2808 				NULL) {
   2809 				return (ERR_XML_SETPROP_FAILED);
   2810 			    }
   2811 			}
   2812 		    } else {
   2813 			    return (ERR_XML_NEWNODE_FAILED);
   2814 		    }
   2815 		}
   2816 		i++;
   2817 	}
   2818 
   2819 	return (handle_partial_failure(doc, ret_save,
   2820 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
   2821 }
   2822 
   2823 /*
   2824  * ****************************************************************************
   2825  *
   2826  * createModify_dd_ddset_op:
   2827  *	removes a list of dd memeber or dd seti member.
   2828  *
   2829  * req	- contains delete request info.
   2830  * doc	- response doc to fill up
   2831  *
   2832  * ****************************************************************************
   2833  */
   2834 static int
   2835 create_dd_ddset_op(
   2836 	request_t *req,
   2837 	xmlDocPtr doc,
   2838 	object_type type
   2839 	/* any additional arguments go here */
   2840 )
   2841 {
   2842 	isns_obj_t  *obj;
   2843 	result_code_t ret = 0, ret_save = 0;
   2844 	isns_type_t lc_type;
   2845 	lookup_ctrl_t lc;
   2846 	uint32_t uid;
   2847 	int i = 0, err_count = 0;
   2848 	xmlNodePtr	n_obj, n_node, root;
   2849 	int different_err = 0;
   2850 
   2851 	lc_type = get_lc_type(type);
   2852 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
   2853 	    return (ERR_INVALID_MGMT_REQUEST);
   2854 	}
   2855 
   2856 	root = xmlDocGetRootElement(doc);
   2857 	if (root == NULL) {
   2858 	    return (ERR_SYNTAX_MISSING_ROOT);
   2859 	}
   2860 	lc_type = get_lc_type(type);
   2861 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
   2862 	    return (ERR_INVALID_MGMT_REQUEST);
   2863 	}
   2864 
   2865 	/* prepare lookup ctrl data for looking for the node object */
   2866 	lc.curr_uid = 0;
   2867 	lc.type = lc_type;
   2868 	lc.id[0] = get_lc_id(req->op_info.obj);
   2869 	lc.op[0] = OP_STRING;
   2870 	lc.op[1] = 0;
   2871 	lc.data[1].ptr = (uchar_t *)doc; /* xml writer descriptor */
   2872 	while (i < req->count) {
   2873 		lc.data[0].ptr = req->req_data.attrlist[i]->name,
   2874 		/* grab the write lock */
   2875 		(void) cache_lock_write();
   2876 
   2877 		uid = is_obj_there(&lc);
   2878 		if (uid == 0) {
   2879 		    ret = (lc_type == OBJ_DD) ?
   2880 			adm_create_dd(&obj, req->req_data.attrlist[i]->name,
   2881 			0, 0) :
   2882 			adm_create_dds(&obj, req->req_data.attrlist[i]->name,
   2883 			0, 0);
   2884 		    if (ret == 0) {
   2885 			ret = register_object(obj, NULL, NULL);
   2886 			if (ret != 0) {
   2887 			    free_object(obj);
   2888 			}
   2889 			/* release the lock and sync the cache and data store */
   2890 			ret = cache_unlock_sync(ret);
   2891 		    }
   2892 		} else {
   2893 			/* release the lock and no need to sync the data */
   2894 			(void) cache_unlock_nosync();
   2895 			ret = ERR_NAME_IN_USE;
   2896 		}
   2897 
   2898 		if (ret != 0) {
   2899 		/* keep track if there are different errors encountered. */
   2900 		    if (ret_save != 0 && ret != ret_save) {
   2901 			different_err++;
   2902 		    }
   2903 		    ret_save = ret;
   2904 		    err_count++;
   2905 		    n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
   2906 		    if (n_obj) {
   2907 			if ((n_obj = xmlAddChild(root, n_obj)) == NULL) {
   2908 			    return (ERR_XML_ADDCHILD_FAILED);
   2909 			}
   2910 		    } else {
   2911 			return (ERR_XML_ADDCHILD_FAILED);
   2912 		    }
   2913 
   2914 		    n_node = (lc_type == OBJ_DD) ?
   2915 			xmlNewNode(NULL, (xmlChar *)DDOBJECT) :
   2916 			xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
   2917 		    if (n_node) {
   2918 			if ((n_node = xmlAddChild(n_obj, n_node)) == NULL) {
   2919 			    return (ERR_XML_ADDCHILD_FAILED);
   2920 			} else {
   2921 			    if (xmlSetProp(n_node, (xmlChar *)NAMEATTR,
   2922 				(xmlChar *)req->req_data.attrlist[i]->name) ==
   2923 				NULL) {
   2924 				return (ERR_XML_SETPROP_FAILED);
   2925 			    }
   2926 			}
   2927 		    } else {
   2928 			return (ERR_XML_NEWNODE_FAILED);
   2929 		    }
   2930 		}
   2931 		i++;
   2932 	}
   2933 
   2934 	return (handle_partial_failure(doc, ret_save,
   2935 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
   2936 }
   2937 
   2938 /*
   2939  * ****************************************************************************
   2940  *
   2941  * createModify_dd_ddset_op:
   2942  *	removes a list of dd memeber or dd seti member.
   2943  *
   2944  * req	- contains delete request info.
   2945  * doc	- response doc to fill up
   2946  *
   2947  * ****************************************************************************
   2948  */
   2949 int
   2950 createModify_dd_ddset_op(
   2951 	request_t *req,
   2952 	xmlDocPtr doc
   2953 	/* any additional arguments go here */
   2954 )
   2955 {
   2956 	result_code_t ret = 0;
   2957 
   2958 	if (req->req_data.attrlist[0]->id != NULL) {
   2959 	    ret = rename_dd_ddset_op(req, doc, req->op_info.obj);
   2960 	} else if (req->req_data.attrlist[0]->enabled != NULL) {
   2961 	    ret = update_dd_ddset_op(req, doc, req->op_info.obj);
   2962 	} else {
   2963 	    ret = create_dd_ddset_op(req, doc, req->op_info.obj);
   2964 	}
   2965 
   2966 	return (ret);
   2967 }
   2968