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
50extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
51
52static isns_type_t
53get_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
79static uint32_t
80get_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 */
120static int
121cb_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 */
289static int
290cb_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 */
407static int
408cb_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 */
443static int
444cb_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 */
590static int
591cb_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 */
673static int
674cb_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 */
758static int
759cb_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 */
856static int
857i_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 */
978static int
979cb_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 */
999static int
1000cb_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 */
1020static int
1021cb_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 */
1088static int
1089cb_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 */
1156static int
1157cb_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 */
1224static int
1225cb_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 */
1290static int
1291handle_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 */
1353static int
1354handle_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 */
1420int
1421get_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 */
1499int
1500get_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 */
1616static int
1617i_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 */
1678static int
1679i_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 */
1737static int
1738i_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 */
1788int
1789get_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 */
1809int
1810get_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 */
1830int
1831enumerate_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 */
1868int
1869enumerate_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 */
1907int
1908enumerate_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 */
1946int
1947getAssociated_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 */
2005int
2006getAssociated_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 */
2068int
2069getAssociated_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 */
2127int
2128getAssociated_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 */
2189int
2190delete_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 */
2294int
2295delete_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 */
2447int
2448create_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 */
2619static int
2620rename_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 */
2730static int
2731update_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 */
2834static int
2835create_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 */
2949int
2950createModify_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