xref: /titanic_52/usr/src/cmd/isns/isnsd/admintf.c (revision e0724c534a46ca4754330bc022bf1e2a68f5bb93)
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