xref: /titanic_51/usr/src/cmd/isns/isnsd/admintf.c (revision fc3af78a71855c71878866a294572d00e6720533)
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 2008 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 					/* pass ip addr from cb_get_pg_info. */
1574 					lc3.data[0].ip = lc2.data[1].ip;
1575 					/* pass port num from cb_get_pg_info. */
1576 					lc3.data[1].ui = lc2.data[2].ui;
1577 					/* pass pgt from cb_get_pg_info. */
1578 					lc3.id[2] = lc2.id[2];
1579 					ret = cache_lookup(&lc3, &uid,
1580 					    cb_get_portal_info);
1581 				} else {
1582 					/*
1583 					 * no more portal group which is
1584 					 * tied to this stroage node object.
1585 					 */
1586 					break;
1587 				}
1588 			}
1589 		}
1590 		/* save error for this iteration */
1591 		if (ret != 0) {
1592 		    ret_save = ret;
1593 		}
1594 		ret = 0;
1595 		i++;
1596 	}
1597 
1598 	return (handle_partial_success(doc, ret_save));
1599 }
1600 
1601 /*
1602  * ****************************************************************************
1603  *
1604  * i_get_dd_dds_op:
1605  *	serves get operatrion on dd or dds.
1606  *
1607  * req	- contains all info for a request.
1608  * doc	- response doc to fill up
1609  * obj_type	- object type(either dd or dd set)
1610  *
1611  * ****************************************************************************
1612  */
1613 static int
1614 i_get_dd_dds_op(
1615 	request_t *req,
1616 	xmlDocPtr doc,
1617 	isns_type_t obj_type
1618 	/* any additional arguments go here */
1619 )
1620 {
1621 	result_code_t ret = 0, ret_save = 0;
1622 	int i = 0;
1623 	lookup_ctrl_t lc;
1624 	uint32_t uid;
1625 
1626 	if ((obj_type != OBJ_DD) && (obj_type != OBJ_DDS)) {
1627 	    return (ERR_INVALID_MGMT_REQUEST);
1628 	}
1629 
1630 	/* prepare lookup ctrl data for looking for the node object */
1631 	lc.curr_uid = 0;
1632 	lc.type = obj_type;
1633 	lc.id[0] = get_lc_id(req->op_info.obj);
1634 	lc.op[0] = OP_STRING;
1635 	lc.op[1] = 0;
1636 	lc.data[1].ptr = (uchar_t *)doc; /* xml writer descriptor */
1637 	while (i < req->count) {
1638 		if (obj_type == OBJ_DD) {
1639 		    lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
1640 		    ret = cache_lookup(&lc, &uid, cb_get_dd_info);
1641 		    if (uid == 0) {
1642 			/* set an error and continue. */
1643 			ret = ERR_MATCHING_DD_NOT_FOUND;
1644 		    }
1645 		} else {
1646 		    lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
1647 		    ret = cache_lookup(&lc, &uid, cb_get_ddset_info);
1648 		    if (uid == 0) {
1649 			/* set an error and continue. */
1650 			ret = ERR_MATCHING_DDSET_NOT_FOUND;
1651 		    }
1652 		}
1653 		/* save error for this iteration */
1654 		if (ret != 0) {
1655 		    ret_save = ret;
1656 		}
1657 		ret = 0;
1658 		i++;
1659 	}
1660 
1661 	return (handle_partial_success(doc, ret_save));
1662 }
1663 
1664 /*
1665  * ****************************************************************************
1666  *
1667  * i_delete_ddmember_op:
1668  *	serves delete member operatrion on dd.
1669  *
1670  * container	- dd name
1671  * member	- node name
1672  *
1673  * ****************************************************************************
1674  */
1675 static int
1676 i_delete_ddmember_op(
1677 	uchar_t *container,
1678 	uchar_t *member
1679 )
1680 {
1681 	int ret = 0;
1682 
1683 	isns_assoc_iscsi_t aiscsi;
1684 	isns_obj_t *assoc;
1685 	isns_attr_t *attr;
1686 	int len;
1687 
1688 	lookup_ctrl_t lc;
1689 	uint32_t dd_id;
1690 
1691 	/* prepare lookup ctrl data for looking for the dd object */
1692 	lc.curr_uid = 0;
1693 	lc.type = OBJ_DD;
1694 	lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
1695 	lc.op[0] = OP_STRING;
1696 	lc.data[0].ptr = container;
1697 	lc.op[1] = 0;
1698 
1699 	if ((dd_id = is_obj_there(&lc)) != 0) {
1700 	    aiscsi.type = OBJ_ASSOC_ISCSI;
1701 	    aiscsi.puid = dd_id;
1702 
1703 	    len = strlen((char *)member) + 1;
1704 	    len += 4 - (len % 4);
1705 
1706 	    attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1707 		ISNS_DD_ISCSI_NAME_ATTR_ID)];
1708 	    attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
1709 	    attr->len = len;
1710 	    attr->value.ptr = (uchar_t *)member;
1711 	    attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1712 		ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1713 	    attr->tag = 0; /* clear it */
1714 	    assoc = (isns_obj_t *)&aiscsi;
1715 	    ret = remove_dd_member(assoc);
1716 	} else {
1717 	    ret = ERR_MATCHING_DD_NOT_FOUND;
1718 	}
1719 
1720 	return (ret);
1721 }
1722 
1723 /*
1724  * ****************************************************************************
1725  *
1726  * i_delete_ddsetmember_op:
1727  *	serves delete member operatrion on dd set.
1728  *
1729  * container	- dd set name
1730  * member	- dd name
1731  *
1732  * ****************************************************************************
1733  */
1734 static int
1735 i_delete_ddsetmember_op(
1736 	uchar_t *container,
1737 	uchar_t *member
1738 )
1739 {
1740 	int ret = 0;
1741 
1742 	lookup_ctrl_t lc, lc2;
1743 	uint32_t container_id, member_id;
1744 
1745 	/* prepare lookup ctrl data for looking for the dd-set object */
1746 	lc.curr_uid = 0;
1747 	lc.type = OBJ_DDS;
1748 	lc.id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID);
1749 	lc.op[0] = OP_STRING;
1750 	lc.data[0].ptr = container;
1751 	lc.op[1] = 0;
1752 
1753 	/* prepare lookup ctrl data for looking for the dd object */
1754 	lc2.curr_uid = 0;
1755 	lc2.type = OBJ_DD;
1756 	lc2.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
1757 	lc2.op[0] = OP_STRING;
1758 	lc2.data[0].ptr = member;
1759 	lc2.op[1] = 0;
1760 
1761 	if ((container_id = is_obj_there(&lc)) != 0) {
1762 	    if ((member_id = is_obj_there(&lc2)) != 0) {
1763 		ret = remove_dds_member(container_id, member_id);
1764 	    } else {
1765 		ret = ERR_MATCHING_DD_NOT_FOUND;
1766 	    }
1767 	} else {
1768 	    ret = ERR_MATCHING_DDSET_NOT_FOUND;
1769 	}
1770 
1771 	return (ret);
1772 }
1773 
1774 /*
1775  * ****************************************************************************
1776  *
1777  * get_dd_op:
1778  *	service get operation on given dd(s).
1779  *
1780  * req	- contains all info for a request.
1781  * doc	- response doc to fill up
1782  *
1783  * ****************************************************************************
1784  */
1785 int
1786 get_dd_op(
1787 	request_t *req,
1788 	xmlDocPtr doc
1789 	/* any additional arguments go here */
1790 )
1791 {
1792 	return (i_get_dd_dds_op(req, doc, OBJ_DD));
1793 }
1794 
1795 /*
1796  * ****************************************************************************
1797  *
1798  * get_ddset_op:
1799  *	service get operation on given dd set(s).
1800  *
1801  * req	- contains all info for a request.
1802  * doc	- response doc to fill up
1803  *
1804  * ****************************************************************************
1805  */
1806 int
1807 get_ddset_op(
1808 	request_t *req,
1809 	xmlDocPtr doc
1810 	/* any additional arguments go here */
1811 )
1812 {
1813 	return (i_get_dd_dds_op(req, doc, OBJ_DDS));
1814 }
1815 
1816 /*
1817  * ****************************************************************************
1818  *
1819  * enumerate_node_op:
1820  *	services enumerate node op.
1821  *
1822  * req	- contains enumerate request info.
1823  * doc	- response doc to fill up
1824  *
1825  * ****************************************************************************
1826  */
1827 int
1828 enumerate_node_op(
1829 	xmlDocPtr   doc
1830 	/* any additional arguments go here */
1831 )
1832 {
1833 	htab_t *htab = cache_get_htab(OBJ_ISCSI);
1834 	uint32_t uid = 0;
1835 	lookup_ctrl_t lc;
1836 	int	    ret = 0, ret_save = 0;
1837 
1838 	SET_UID_LCP(&lc, OBJ_ISCSI, 0);
1839 
1840 	lc.data[1].ptr = (uchar_t *)doc;
1841 	lc.data[2].ui = 0;
1842 
1843 	FOR_EACH_ITEM(htab, uid, {
1844 		lc.data[0].ui = uid;
1845 		ret = cache_lookup(&lc, NULL, cb_enumerate_node_info);
1846 		if (ret != 0) {
1847 		    ret_save = ret;
1848 		}
1849 	});
1850 
1851 	return (handle_partial_success(doc, ret_save));
1852 }
1853 
1854 /*
1855  * ****************************************************************************
1856  *
1857  * enumerate_dd_op:
1858  *	services enumerate discovery domain op.
1859  *
1860  * req	- contains enumerate request info.
1861  * doc	- response doc to fill up
1862  *
1863  * ****************************************************************************
1864  */
1865 int
1866 enumerate_dd_op(
1867 	xmlDocPtr   doc
1868 	/* any additional arguments go here */
1869 )
1870 {
1871 
1872 	htab_t *htab = cache_get_htab(OBJ_DD);
1873 	uint32_t uid = 0;
1874 	lookup_ctrl_t lc;
1875 	int	    ret = 0, ret_save = 0;
1876 
1877 	SET_UID_LCP(&lc, OBJ_DD, 0);
1878 
1879 	lc.data[1].ptr = (uchar_t *)doc;
1880 	lc.data[2].ui = 0;
1881 
1882 	FOR_EACH_ITEM(htab, uid, {
1883 		lc.data[0].ui = uid;
1884 		ret = cache_lookup(&lc, NULL, cb_enumerate_dd_info);
1885 		if (ret != 0) {
1886 		    ret_save = ret;
1887 		}
1888 	});
1889 
1890 	return (handle_partial_success(doc, ret_save));
1891 }
1892 
1893 /*
1894  * ****************************************************************************
1895  *
1896  * enumerate_ddset_op:
1897  *	services enumerate discovery domain set op.
1898  *
1899  * req	- contains enumerate request info.
1900  * doc	- response doc to fill up
1901  *
1902  * ****************************************************************************
1903  */
1904 int
1905 enumerate_ddset_op(
1906 	xmlDocPtr   doc
1907 	/* any additional arguments go here */
1908 )
1909 {
1910 	htab_t *htab = cache_get_htab(OBJ_DDS);
1911 	uint32_t uid = 0;
1912 	lookup_ctrl_t lc;
1913 	int	    ret = 0, ret_save = 0;
1914 
1915 	SET_UID_LCP(&lc, OBJ_DDS, 0);
1916 
1917 	lc.data[1].ptr = (uchar_t *)doc;
1918 	lc.data[2].ui = 0;
1919 
1920 	FOR_EACH_ITEM(htab, uid, {
1921 		lc.data[0].ui = uid;
1922 		ret = cache_lookup(&lc, NULL, cb_enumerate_ddset_info);
1923 		if (ret != 0) {
1924 		    ret_save = ret;
1925 		}
1926 	});
1927 
1928 	return (handle_partial_success(doc, ret_save));
1929 }
1930 
1931 /*
1932  * ****************************************************************************
1933  *
1934  * getassociated_dd_to_node_op:
1935  *	construct a list of node that is associated with a given Discovery
1936  *	Domain.
1937  *
1938  * req	- contains getAssociated request info.
1939  * doc	- response doc to fill up
1940  *
1941  * ****************************************************************************
1942  */
1943 int
1944 getAssociated_dd_to_node_op(
1945 	request_t *req,
1946 	xmlDocPtr   doc
1947 	/* any additional arguments go here */
1948 )
1949 {
1950 	uint32_t uid = 0, n;
1951 	lookup_ctrl_t lc, lc2;
1952 	int	i = 0, ret = 0, ret_save = 0;
1953 	bmp_t	*p;
1954 
1955 	lc.curr_uid = 0;
1956 	lc.type = OBJ_DD;
1957 	lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
1958 	lc.op[0] = OP_STRING;
1959 	lc.op[1] = 0;
1960 
1961 	SET_UID_LCP(&lc2, OBJ_ISCSI, 0);
1962 
1963 	lc2.data[1].ptr = (uchar_t *)doc;
1964 
1965 	while (i < req->count) {
1966 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
1967 		if ((uid = is_obj_there(&lc)) != 0) {
1968 		    ret = get_dd_matrix(uid, &p, &n);
1969 		    FOR_EACH_MEMBER(p, n, uid, {
1970 			lc2.data[0].ui = uid;
1971 			lc2.data[2].ptr = (uchar_t *)req->req_data.data[i];
1972 			ret = cache_lookup(&lc2, NULL,
1973 			    cb_getAssociated_node_info);
1974 		    });
1975 		    free(p);
1976 		} else {
1977 		    ret = ERR_MATCHING_DD_NOT_FOUND;
1978 		}
1979 		/* save error for this iteration */
1980 		if (ret != 0) {
1981 		    ret_save = ret;
1982 		}
1983 		ret = 0;
1984 		i++;
1985 	}
1986 
1987 	return (handle_partial_success(doc, ret_save));
1988 }
1989 
1990 /*
1991  * ****************************************************************************
1992  *
1993  * getassociated_node_to_dd_op:
1994  *	construct a list of Discovery Doamins that is associated with a given
1995  *	node.
1996  *
1997  * req	- contains getAssociated request info.
1998  * doc	- response doc to fill up
1999  *
2000  * ****************************************************************************
2001  */
2002 int
2003 getAssociated_node_to_dd_op(
2004 	request_t *req,
2005 	xmlDocPtr   doc
2006 	/* any additional arguments go here */
2007 )
2008 {
2009 	uint32_t uid = 0, dd_id;
2010 	lookup_ctrl_t lc, lc2;
2011 	int	i = 0, ret = 0, ret_save = 0;
2012 
2013 	lc.curr_uid = 0;
2014 	lc.type = OBJ_ISCSI;
2015 	lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
2016 	lc.op[0] = OP_STRING;
2017 	lc.op[1] = 0;
2018 
2019 	SET_UID_LCP(&lc2, OBJ_DD, 0);
2020 
2021 	lc2.data[1].ptr = (uchar_t *)doc;
2022 
2023 	while (i < req->count) {
2024 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
2025 		if ((uid = is_obj_there(&lc)) != 0) {
2026 		    if ((dd_id = get_dd_id(uid, 0)) == 0) {
2027 			ret = ERR_NO_ASSOCIATED_DD_FOUND;
2028 			i++;
2029 			continue;
2030 		    } else {
2031 			do {
2032 			    lc2.data[0].ui = dd_id;
2033 			    lc2.data[2].ptr = (uchar_t *)req->req_data.data[i];
2034 			    ret = cache_lookup(&lc2, NULL,
2035 				cb_getAssociated_node_to_dd_info);
2036 			    dd_id = get_dd_id(uid, dd_id);
2037 			} while (dd_id != 0);
2038 		    };
2039 		} else {
2040 		    ret = ERR_MATCHING_NODE_NOT_FOUND;
2041 		}
2042 		/* save error for this iteration */
2043 		if (ret != 0) {
2044 		    ret_save = ret;
2045 		}
2046 		ret = 0;
2047 		i++;
2048 	}
2049 
2050 	return (handle_partial_success(doc, ret_save));
2051 }
2052 
2053 /*
2054  * ****************************************************************************
2055  *
2056  * getassociated_ddset_to_dd_op:
2057  *	construct a list of Discovery Doamins that is associated with a given
2058  *	Discover Domain set.
2059  *
2060  * req	- contains getAssociated request info.
2061  * doc	- response doc to fill up
2062  *
2063  * ****************************************************************************
2064  */
2065 int
2066 getAssociated_ddset_to_dd_op(
2067 	request_t *req,
2068 	xmlDocPtr   doc
2069 	/* any additional arguments go here */
2070 )
2071 {
2072 	uint32_t uid = 0, n;
2073 	lookup_ctrl_t lc, lc2;
2074 	int	i = 0, ret = 0, ret_save = 0;
2075 	bmp_t	*p;
2076 
2077 	lc.curr_uid = 0;
2078 	lc.type = OBJ_DDS;
2079 	lc.id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID);
2080 	lc.op[0] = OP_STRING;
2081 	lc.op[1] = 0;
2082 
2083 	SET_UID_LCP(&lc2, OBJ_DD, 0);
2084 
2085 	lc2.data[1].ptr = (uchar_t *)doc;
2086 
2087 	while (i < req->count) {
2088 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
2089 		if ((uid = is_obj_there(&lc)) != 0) {
2090 		    ret = get_dds_matrix(uid, &p, &n);
2091 		    FOR_EACH_MEMBER(p, n, uid, {
2092 			lc2.data[0].ui = uid;
2093 			lc2.data[2].ptr = (uchar_t *)req->req_data.data[i];
2094 			ret = cache_lookup(&lc2, NULL,
2095 			    cb_getAssociated_dd_info);
2096 		    });
2097 		    free(p);
2098 		} else {
2099 		    ret = ERR_MATCHING_DDSET_NOT_FOUND;
2100 		}
2101 		/* save error for this iteration */
2102 		if (ret != 0) {
2103 		    ret_save = ret;
2104 		}
2105 		ret = 0;
2106 		i++;
2107 	}
2108 
2109 	return (handle_partial_success(doc, ret_save));
2110 }
2111 
2112 /*
2113  * ****************************************************************************
2114  *
2115  * getassociated_dd_to_ddset_op:
2116  *	construct a list of Discovery Doamin sets that is associated with a
2117  *	given Discovery Domain.
2118  *
2119  * req	- contains getAssociated request info.
2120  * doc	- response doc to fill up
2121  *
2122  * ****************************************************************************
2123  */
2124 int
2125 getAssociated_dd_to_ddset_op(
2126 	request_t *req,
2127 	xmlDocPtr   doc
2128 	/* any additional arguments go here */
2129 )
2130 {
2131 	uint32_t uid = 0, ddset_id;
2132 	lookup_ctrl_t lc, lc2;
2133 	int	i = 0, ret = 0, ret_save = 0;
2134 
2135 	lc.curr_uid = 0;
2136 	lc.type = OBJ_DD;
2137 	lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
2138 	lc.op[0] = OP_STRING;
2139 	lc.op[1] = 0;
2140 
2141 	SET_UID_LCP(&lc2, OBJ_DDS, 0);
2142 
2143 	lc2.data[1].ptr = (uchar_t *)doc;
2144 
2145 	while (i < req->count) {
2146 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
2147 		if ((uid = is_obj_there(&lc)) != 0) {
2148 		    lc2.data[2].ui = 0;
2149 		    if ((ddset_id = get_dds_id(uid, 0)) == 0) {
2150 			ret = ERR_NO_ASSOCIATED_DDSET_FOUND;
2151 			i++;
2152 			continue;
2153 		    } else {
2154 			do {
2155 			    lc2.data[0].ui = ddset_id;
2156 			    lc2.data[2].ptr = (uchar_t *)req->req_data.data[i];
2157 			    ret = cache_lookup(&lc2, NULL,
2158 				cb_getAssociated_dd_to_ddset_info);
2159 			    ddset_id = get_dds_id(uid, ddset_id);
2160 			} while (ddset_id != 0);
2161 		    };
2162 		} else {
2163 		    ret = ERR_MATCHING_DD_NOT_FOUND;
2164 		}
2165 		if (ret != 0) {
2166 		    ret_save = ret;
2167 		}
2168 		i++;
2169 	}
2170 
2171 	return (handle_partial_success(doc, ret_save));
2172 }
2173 
2174 /*
2175  * ****************************************************************************
2176  *
2177  * delete_dd_ddset_op:
2178  *	removes a list of dd or dd set.
2179  *
2180  * req	- contains delete request info.
2181  * doc	- response doc to fill up
2182  * obj_type	- object type(either dd or dd set)
2183  *
2184  * ****************************************************************************
2185  */
2186 int
2187 delete_dd_ddset_op(
2188 	request_t *req,
2189 	xmlDocPtr doc,
2190 	object_type type
2191 	/* any additional arguments go here */
2192 )
2193 {
2194 	result_code_t ret = 0, ret_save = 0;
2195 	isns_type_t lc_type;
2196 	int i = 0, err_count = 0;
2197 	lookup_ctrl_t lc;
2198 	uint32_t uid;
2199 	xmlNodePtr	n_obj, n_node, root;
2200 	xmlAttrPtr	n_attr;
2201 	int different_err = 0;
2202 
2203 	root = xmlDocGetRootElement(doc);
2204 	if (root == NULL) {
2205 	    return (ERR_SYNTAX_MISSING_ROOT);
2206 	}
2207 	lc_type = get_lc_type(type);
2208 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
2209 	    return (ERR_INVALID_MGMT_REQUEST);
2210 	}
2211 
2212 	/* prepare lookup ctrl data for looking for the node object */
2213 	lc.curr_uid = 0;
2214 	lc.type = lc_type;
2215 	lc.id[0] = get_lc_id(req->op_info.obj);
2216 	lc.op[0] = OP_STRING;
2217 	lc.op[1] = 0;
2218 	lc.data[1].ptr = (uchar_t *)doc; /* xml writer descriptor */
2219 	while (i < req->count) {
2220 		lc.data[0].ptr = (uchar_t *)req->req_data.data[i];
2221 
2222 		/* lock the cache for writing */
2223 		(void) cache_lock_write();
2224 
2225 		if ((uid = is_obj_there(&lc)) != 0) {
2226 		    /* remove the dd/ddset */
2227 		    ret = (lc_type == OBJ_DD) ?
2228 			remove_dd_object(uid) :
2229 			remove_dds_object(uid);
2230 		    /* unlock the cache and sync the data */
2231 		    ret = cache_unlock_sync(ret);
2232 		} else {
2233 		    /* unlock the cache and no need to sync data */
2234 		    (void) cache_unlock_nosync();
2235 		    /* set an error and continue. */
2236 		    ret = ERR_MATCHING_DD_NOT_FOUND;
2237 		}
2238 
2239 		if (ret != 0) {
2240 		/* keep track if there are different errors encountered. */
2241 		    if (ret_save != 0 && ret != ret_save) {
2242 			different_err++;
2243 		    }
2244 		    err_count++;
2245 		    n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
2246 		    if (n_obj) {
2247 			if ((n_obj = xmlAddChild(root, n_obj)) == NULL) {
2248 			    return (ERR_XML_ADDCHILD_FAILED);
2249 			}
2250 		    } else {
2251 			return (ERR_XML_NEWNODE_FAILED);
2252 		    }
2253 
2254 		    n_node = (lc_type == OBJ_DD) ?
2255 			xmlNewNode(NULL, (xmlChar *)DDOBJECT) :
2256 			xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
2257 		    if (n_node) {
2258 			if ((n_node = xmlAddChild(n_obj, n_node)) == NULL) {
2259 			    return (ERR_XML_ADDCHILD_FAILED);
2260 			}
2261 			n_attr = xmlSetProp(n_node, (xmlChar *)NAMEATTR,
2262 				(xmlChar *)req->req_data.data[i]);
2263 			if (n_attr == NULL) {
2264 			    return (ERR_XML_SETPROP_FAILED);
2265 			}
2266 		    } else {
2267 			return (ERR_XML_NEWNODE_FAILED);
2268 		    }
2269 		    ret_save = ret;
2270 		}
2271 		i ++;
2272 	}
2273 
2274 	return (handle_partial_failure(doc, ret_save,
2275 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
2276 }
2277 
2278 /*
2279  * ****************************************************************************
2280  *
2281  * delete_ddmember_ddsetmember_op:
2282  *	removes a list of dd memeber or dd seti member.
2283  *
2284  * req	- contains delete request info.
2285  * doc	- response doc to fill up
2286  * type	- object type(either dd or dd set)
2287  *
2288  * ****************************************************************************
2289  */
2290 int
2291 delete_ddmember_ddsetmember_op(
2292 	request_t *req,
2293 	xmlDocPtr doc,
2294 	object_type type
2295 	/* any additional arguments go here */
2296 )
2297 {
2298 	result_code_t ret = 0, ret_save = 0;
2299 	isns_type_t lc_type;
2300 	int i = 0, err_count = 0;
2301 	lookup_ctrl_t lc, lc2;
2302 	uint32_t container_id, member_id;
2303 	xmlNodePtr	n_node, n_obj, root;
2304 	xmlAttrPtr	n_attr;
2305 	int different_err = 0;
2306 	int is_a_member;
2307 
2308 	lc_type = get_lc_type(type);
2309 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
2310 	    return (ERR_INVALID_MGMT_REQUEST);
2311 	}
2312 
2313 	/* prepare lookup ctrl data for looking for the node object */
2314 	lc.curr_uid = 0;
2315 	lc.type = lc_type;
2316 	lc.id[0] = get_lc_id(req->op_info.obj);
2317 	lc.op[0] = OP_STRING;
2318 	lc.op[1] = 0;
2319 
2320 	lc2.curr_uid = 0;
2321 	if (lc_type == OBJ_DD) {
2322 	    lc2.type = OBJ_ISCSI;
2323 	    lc2.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
2324 	} else {
2325 	    lc2.type = OBJ_DD;
2326 	    lc2.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
2327 	}
2328 	lc2.op[0] = OP_STRING;
2329 	lc2.op[1] = 0;
2330 
2331 	root = xmlDocGetRootElement(doc);
2332 	if (root == NULL) {
2333 	    return (ERR_SYNTAX_MISSING_ROOT);
2334 	}
2335 
2336 	while (i < req->count) {
2337 		lc.data[0].ptr = (uchar_t *)req->req_data.pair[i]->container;
2338 
2339 		/* get the dd_id/dds_id */
2340 		(void) cache_lock_write();
2341 		container_id = is_obj_there(&lc);
2342 
2343 		if (container_id != 0) {
2344 		    lc2.data[0].ptr = (uchar_t *)req->req_data.pair[i]->member;
2345 
2346 		    member_id = is_obj_there(&lc2);
2347 		    if (member_id != 0) {
2348 			is_a_member =
2349 			    (container_id ==
2350 			    ((lc_type == OBJ_DD) ?
2351 			    get_dd_id(member_id, container_id - 1) :
2352 			    get_dds_id(member_id, container_id - 1)));
2353 		    }
2354 		    if (member_id != 0 && is_a_member != 0) {
2355 			/* delete the dd member */
2356 			ret = (lc_type == OBJ_DD) ?
2357 			    i_delete_ddmember_op(
2358 				(uchar_t *)req->req_data.pair[i]->container,
2359 				(uchar_t *)req->req_data.pair[i]->member) :
2360 			    i_delete_ddsetmember_op(
2361 				(uchar_t *)req->req_data.pair[i]->container,
2362 				(uchar_t *)req->req_data.pair[i]->member);
2363 			/* unlock the cache and sync the data */
2364 			ret = cache_unlock_sync(ret);
2365 		    } else {
2366 			/* unlock the cache and no need to sync */
2367 			(void) cache_unlock_nosync();
2368 			ret = ERR_NO_SUCH_ASSOCIATION;
2369 		    }
2370 		} else {
2371 		    /* unlock the cache and no need to sync */
2372 		    (void) cache_unlock_nosync();
2373 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
2374 			ERR_MATCHING_DDSET_NOT_FOUND;
2375 		}
2376 
2377 		if (ret != 0) {
2378 		/* keep track if there are different errors encountered. */
2379 		    if (ret_save != 0 && ret != ret_save) {
2380 			different_err++;
2381 		    }
2382 		    ret_save = ret;
2383 		    err_count++;
2384 		    n_obj = xmlNewNode(NULL, (xmlChar *)ASSOCIATION);
2385 		    if (n_obj) {
2386 			n_obj = xmlAddChild(root, n_obj);
2387 			if (n_obj == NULL) {
2388 			    return (ERR_XML_ADDCHILD_FAILED);
2389 			}
2390 		    } else {
2391 			return (ERR_XML_NEWNODE_FAILED);
2392 		    }
2393 		    if (lc_type == OBJ_DD) {
2394 			n_node =
2395 			    xmlNewNode(NULL, (xmlChar *)DDOBJECTMEMBER);
2396 			n_attr = xmlSetProp(n_node, (xmlChar *)NODENAMEATTR,
2397 			    (xmlChar *)req->req_data.pair[i]->member);
2398 			if (n_attr == NULL) {
2399 			    return (ERR_XML_SETPROP_FAILED);
2400 			}
2401 			n_attr = xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
2402 			    (xmlChar *)req->req_data.pair[i]->container);
2403 			if (n_attr == NULL) {
2404 			    return (ERR_XML_SETPROP_FAILED);
2405 			}
2406 		    } else {
2407 			n_node =
2408 			    xmlNewNode(NULL, (xmlChar *)DDSETOBJECTMEMBER);
2409 			n_attr = xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
2410 			    (xmlChar *)req->req_data.pair[i]->member);
2411 			if (n_attr == NULL) {
2412 			    return (ERR_XML_SETPROP_FAILED);
2413 			}
2414 			n_attr = xmlSetProp(n_node, (xmlChar *)DDSETNAMEATTR,
2415 			    (xmlChar *)req->req_data.pair[i]->container);
2416 			if (n_attr == NULL) {
2417 			    return (ERR_XML_SETPROP_FAILED);
2418 			}
2419 		    }
2420 		    if (xmlAddChild(n_obj, n_node) == NULL) {
2421 			return (ERR_XML_ADDCHILD_FAILED);
2422 		    }
2423 		}
2424 		i++;
2425 	}
2426 
2427 	return (handle_partial_failure(doc, ret_save,
2428 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
2429 }
2430 
2431 /*
2432  * ****************************************************************************
2433  *
2434  * create_ddmember_ddsetmember_op:
2435  *	removes a list of dd memeber or dd seti member.
2436  *
2437  * req	- contains delete request info.
2438  * doc	- response doc to fill up
2439  * type	- object type(either dd or dd set)
2440  *
2441  * ****************************************************************************
2442  */
2443 int
2444 create_ddmember_ddsetmember_op(
2445 	request_t *req,
2446 	xmlDocPtr doc,
2447 	object_type type
2448 	/* any additional arguments go here */
2449 )
2450 {
2451 	result_code_t ret = 0, ret_save = 0;
2452 	isns_type_t lc_type;
2453 	int i = 0, err_count = 0;
2454 	lookup_ctrl_t lc, lc2;
2455 	uint32_t container_id, member_id;
2456 	xmlNodePtr	n_node, n_obj, root;
2457 	isns_assoc_iscsi_t aiscsi = { 0 };
2458 	isns_assoc_dd_t add = { 0 };
2459 	isns_obj_t *assoc;
2460 	isns_attr_t *attr;
2461 	uint32_t len;
2462 	int different_err = 0;
2463 
2464 	lc_type = get_lc_type(type);
2465 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
2466 	    return (ERR_INVALID_MGMT_REQUEST);
2467 	}
2468 
2469 	/* prepare lookup ctrl data for looking for the node object */
2470 	lc.curr_uid = 0;
2471 	lc.type = lc_type;
2472 	lc.id[0] = get_lc_id(req->op_info.obj);
2473 	lc.op[0] = OP_STRING;
2474 	lc.op[1] = 0;
2475 
2476 	lc2.curr_uid = 0;
2477 	if (lc_type == OBJ_DD) {
2478 	    lc2.type = OBJ_ISCSI;
2479 	    lc2.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
2480 	} else {
2481 	    lc2.type = OBJ_DD;
2482 	    lc2.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
2483 	}
2484 	lc2.op[0] = OP_STRING;
2485 	lc2.op[1] = 0;
2486 
2487 	root = xmlDocGetRootElement(doc);
2488 	if (root == NULL) {
2489 	    return (ERR_SYNTAX_MISSING_ROOT);
2490 	}
2491 
2492 	while (i < req->count) {
2493 		lc.data[0].ptr = (uchar_t *)req->req_data.pair[i]->container;
2494 
2495 		/* get the dd_id/dds_id */
2496 		(void) cache_lock_write();
2497 		container_id = is_obj_there(&lc);
2498 
2499 		if (container_id != 0) {
2500 		    (void) memset(&aiscsi, 0, sizeof (aiscsi));
2501 		    if (lc_type == OBJ_DD) {
2502 			aiscsi.puid = container_id;
2503 			aiscsi.type = OBJ_ASSOC_ISCSI;
2504 			attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
2505 			    ISNS_DD_ISCSI_NAME_ATTR_ID)];
2506 			attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
2507 			len = xmlStrlen(
2508 			    (xmlChar *)req->req_data.pair[i]->member) + 1;
2509 			len += 4 - (len % 4); /* on 4 bytes aligned */
2510 			attr->len = len;
2511 			attr->value.ptr =
2512 			    (uchar_t *)req->req_data.pair[i]->member;
2513 			assoc = (isns_obj_t *)&aiscsi;
2514 
2515 			/* add the dd member */
2516 			ret = add_dd_member(assoc);
2517 
2518 			/* unlock the cache and sync the data */
2519 			ret = cache_unlock_sync(ret);
2520 		    } else {
2521 			lc2.data[0].ptr =
2522 			    (uchar_t *)req->req_data.pair[i]->member;
2523 
2524 			if ((member_id = is_obj_there(&lc2)) != 0) {
2525 			    add.puid = container_id;
2526 			    add.type = OBJ_ASSOC_DD;
2527 			    attr = &add.attrs[ATTR_INDEX_ASSOC_DD(
2528 				ISNS_DD_ID_ATTR_ID)];
2529 			    attr->tag = ISNS_DD_ID_ATTR_ID;
2530 			    attr->len = 4;
2531 			    attr->value.ui = member_id;
2532 			    assoc = (isns_obj_t *)&add;
2533 
2534 			    /* add the dd-set member */
2535 			    ret = add_dds_member(assoc);
2536 
2537 			    /* unlock the cache and sync the data */
2538 			    ret = cache_unlock_sync(ret);
2539 			} else {
2540 			    /* unlock the cache and no need to sync */
2541 			    (void) cache_unlock_nosync();
2542 			    ret = ERR_MATCHING_DD_NOT_FOUND;
2543 			}
2544 		    }
2545 		} else {
2546 		    /* unlock the cache and no need to sync */
2547 		    (void) cache_unlock_nosync();
2548 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
2549 			ERR_MATCHING_DDSET_NOT_FOUND;
2550 		}
2551 		if (ret != 0) {
2552 		/* keep track if there are different errors encountered. */
2553 		    if (ret_save != 0 && ret != ret_save) {
2554 			different_err++;
2555 		    }
2556 		    err_count++;
2557 		    n_obj = xmlNewNode(NULL, (xmlChar *)ASSOCIATION);
2558 		    if (n_obj) {
2559 			n_obj = xmlAddChild(root, n_obj);
2560 			if (n_obj == NULL) {
2561 			    return (ERR_XML_ADDCHILD_FAILED);
2562 			}
2563 		    } else {
2564 			return (ERR_XML_NEWNODE_FAILED);
2565 		    }
2566 		    if (lc_type == OBJ_DD) {
2567 			n_node =
2568 			    xmlNewNode(NULL, (xmlChar *)DDOBJECTMEMBER);
2569 			if (xmlSetProp(n_node, (xmlChar *)NODENAMEATTR,
2570 			    (xmlChar *)req->req_data.pair[i]->member) == NULL) {
2571 			    return (ERR_XML_SETPROP_FAILED);
2572 			}
2573 			if (xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
2574 			    (xmlChar *)req->req_data.pair[i]->container) ==
2575 			    NULL) {
2576 			    return (ERR_XML_SETPROP_FAILED);
2577 			}
2578 		    } else {
2579 			n_node =
2580 			    xmlNewNode(NULL, (xmlChar *)DDSETOBJECTMEMBER);
2581 			if (xmlSetProp(n_node, (xmlChar *)DDNAMEATTR,
2582 			    (xmlChar *)req->req_data.pair[i]->member) == NULL) {
2583 			    return (ERR_XML_SETPROP_FAILED);
2584 			}
2585 			if (xmlSetProp(n_node, (xmlChar *)DDSETNAMEATTR,
2586 			    (xmlChar *)req->req_data.pair[i]->container) ==
2587 			    NULL) {
2588 			    return (ERR_XML_SETPROP_FAILED);
2589 			}
2590 		    }
2591 		    if (xmlAddChild(n_obj, n_node) == NULL) {
2592 			return (ERR_XML_ADDCHILD_FAILED);
2593 		    }
2594 		    ret_save = ret;
2595 		}
2596 		i++;
2597 	}
2598 
2599 	return (handle_partial_failure(doc, ret_save,
2600 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
2601 }
2602 
2603 /*
2604  * ****************************************************************************
2605  *
2606  * rename_dd_ddset_op:
2607  *	removes a list of dd memeber or dd seti member.
2608  *
2609  * req	- contains delete request info.
2610  * doc	- response doc to fill up
2611  * type	- object type(either dd or dd set)
2612  *
2613  * ****************************************************************************
2614  */
2615 static int
2616 rename_dd_ddset_op(
2617 	request_t *req,
2618 	xmlDocPtr doc,
2619 	object_type type
2620 	/* any additional arguments go here */
2621 )
2622 {
2623 	result_code_t ret = 0, ret_save = 0;
2624 	isns_type_t lc_type;
2625 	int i = 0, err_count = 0;
2626 	lookup_ctrl_t lc;
2627 	uint32_t container_id;
2628 	xmlNodePtr	n_node, n_obj, root;
2629 	uchar_t *name;
2630 	uint32_t len;
2631 	int different_err = 0;
2632 
2633 	lc_type = get_lc_type(type);
2634 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
2635 	    return (ERR_INVALID_MGMT_REQUEST);
2636 	}
2637 
2638 	/* prepare lookup ctrl data for looking for the node object */
2639 	SET_UID_LCP(&lc, lc_type, 0);
2640 
2641 	root = xmlDocGetRootElement(doc);
2642 	if (root == NULL) {
2643 	    return (ERR_SYNTAX_MISSING_ROOT);
2644 	}
2645 
2646 	while (i < req->count) {
2647 		/* id is checked to be not NULL before calling this routine. */
2648 		lc.data[0].ui = *(req->req_data.attrlist[i]->id);
2649 
2650 		/* get the dd_id/dds_id */
2651 		(void) cache_lock_write();
2652 
2653 		if ((container_id = is_obj_there(&lc)) != 0) {
2654 		    name = (uchar_t *)req->req_data.attrlist[i]->name;
2655 		    /* the length of the name need to include the */
2656 		    /* null terminator and be on 4 bytes aligned */
2657 		    len = xmlStrlen(name) + 1;
2658 		    len += 4 - (len % 4);
2659 
2660 		    /* rename the dd/dds */
2661 		    ret = (lc_type == OBJ_DD) ?
2662 			update_dd_name(container_id, len, name) :
2663 			update_dds_name(container_id, len, name);
2664 
2665 		    /* release the lock and sync the data */
2666 		    ret = cache_unlock_sync(ret);
2667 		} else {
2668 		    /* release the lock and no need to sync */
2669 		    (void) cache_unlock_nosync();
2670 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
2671 			ERR_MATCHING_DDSET_NOT_FOUND;
2672 		}
2673 		if (ret != 0) {
2674 		/* keep track if there are different errors encountered. */
2675 		    if (ret_save != 0 && ret != ret_save) {
2676 			different_err++;
2677 		    }
2678 		    ret_save = ret;
2679 		    err_count++;
2680 		    n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
2681 		    if (n_obj) {
2682 			if ((n_obj = xmlAddChild(root, n_obj)) == NULL) {
2683 			    return (ERR_XML_ADDCHILD_FAILED);
2684 			}
2685 		    } else {
2686 			return (ERR_XML_NEWNODE_FAILED);
2687 		    }
2688 
2689 		    n_node = (lc_type == OBJ_DD) ?
2690 			xmlNewNode(NULL, (xmlChar *)DDOBJECT) :
2691 			xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
2692 		    if (n_node) {
2693 			if ((n_node = xmlAddChild(n_obj, n_node)) == NULL) {
2694 			    return (ERR_XML_ADDCHILD_FAILED);
2695 			} else {
2696 			    if (xmlSetProp(n_node, (xmlChar *)NAMEATTR,
2697 				(xmlChar *)req->req_data.attrlist[i]->name) ==
2698 				NULL) {
2699 				return (ERR_XML_SETPROP_FAILED);
2700 			    }
2701 			}
2702 		    } else {
2703 			return (ERR_XML_NEWNODE_FAILED);
2704 		    }
2705 
2706 		}
2707 		i++;
2708 	}
2709 
2710 	return (handle_partial_failure(doc, ret_save,
2711 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
2712 }
2713 
2714 /*
2715  * ****************************************************************************
2716  *
2717  * update_dd_ddset_op:
2718  *	removes a list of dd memeber or dd seti member.
2719  *
2720  * req	- contains delete request info.
2721  * doc	- response doc to fill up
2722  * type	- object type(either dd or dd set)
2723  *
2724  * ****************************************************************************
2725  */
2726 static int
2727 update_dd_ddset_op(
2728 	request_t *req,
2729 	xmlDocPtr doc,
2730 	object_type type
2731 	/* any additional arguments go here */
2732 )
2733 {
2734 	result_code_t ret = 0, ret_save = 0;
2735 	isns_type_t lc_type;
2736 	int i = 0, err_count = 0;
2737 	lookup_ctrl_t lc;
2738 	uint32_t container_id;
2739 	xmlNodePtr	n_node, n_obj, root;
2740 	int different_err = 0;
2741 
2742 	lc_type = get_lc_type(type);
2743 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
2744 	    return (ERR_INVALID_MGMT_REQUEST);
2745 	}
2746 
2747 	/* prepare lookup ctrl data for looking for the node object */
2748 	lc.curr_uid = 0;
2749 	lc.type = lc_type;
2750 	lc.id[0] = get_lc_id(req->op_info.obj);
2751 	lc.op[0] = OP_STRING;
2752 	lc.op[1] = 0;
2753 
2754 	root = xmlDocGetRootElement(doc);
2755 	if (root == NULL) {
2756 	    return (ERR_SYNTAX_MISSING_ROOT);
2757 	}
2758 
2759 	while (i < req->count) {
2760 		lc.data[0].ptr = req->req_data.attrlist[i]->name;
2761 
2762 		/* lock the cache for writing */
2763 		(void) cache_lock_write();
2764 
2765 		if ((container_id = is_obj_there(&lc)) != 0) {
2766 		    ret = (lc_type == OBJ_DD) ?
2767 			/* enabled is checked to be not NULL before calling. */
2768 			update_dd_features(container_id,
2769 			*(req->req_data.attrlist[i]->enabled) ? 1 : 0):
2770 			update_dds_status(container_id,
2771 			*(req->req_data.attrlist[i]->enabled) ? 1 : 0);
2772 		    /* unlock the cache and sync the data */
2773 		    ret = cache_unlock_sync(ret);
2774 		} else {
2775 		    (void) cache_unlock_nosync();
2776 		    ret = (lc_type == OBJ_DD) ?  ERR_MATCHING_DD_NOT_FOUND :
2777 			ERR_MATCHING_DDSET_NOT_FOUND;
2778 		}
2779 		if (ret != 0) {
2780 		/* keep track if there are different errors encountered. */
2781 		    if (ret_save != 0 && ret != ret_save) {
2782 			different_err++;
2783 		    }
2784 		    ret_save = ret;
2785 		    err_count++;
2786 		    n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
2787 		    if (n_obj) {
2788 			if ((n_obj = xmlAddChild(root, n_obj)) == NULL) {
2789 			    return (ERR_XML_ADDCHILD_FAILED);
2790 			}
2791 		    } else {
2792 			return (ERR_XML_NEWNODE_FAILED);
2793 		    }
2794 
2795 		    n_node = (lc_type == OBJ_DD) ?
2796 			xmlNewNode(NULL, (xmlChar *)DDOBJECT) :
2797 			xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
2798 		    if (n_node) {
2799 			if ((n_node = xmlAddChild(n_obj, n_node)) == NULL) {
2800 			    return (ERR_XML_ADDCHILD_FAILED);
2801 			} else {
2802 			    if (xmlSetProp(n_node, (xmlChar *)NAMEATTR,
2803 				(xmlChar *)req->req_data.attrlist[i]->name) ==
2804 				NULL) {
2805 				return (ERR_XML_SETPROP_FAILED);
2806 			    }
2807 			}
2808 		    } else {
2809 			    return (ERR_XML_NEWNODE_FAILED);
2810 		    }
2811 		}
2812 		i++;
2813 	}
2814 
2815 	return (handle_partial_failure(doc, ret_save,
2816 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
2817 }
2818 
2819 /*
2820  * ****************************************************************************
2821  *
2822  * createModify_dd_ddset_op:
2823  *	removes a list of dd memeber or dd seti member.
2824  *
2825  * req	- contains delete request info.
2826  * doc	- response doc to fill up
2827  *
2828  * ****************************************************************************
2829  */
2830 static int
2831 create_dd_ddset_op(
2832 	request_t *req,
2833 	xmlDocPtr doc,
2834 	object_type type
2835 	/* any additional arguments go here */
2836 )
2837 {
2838 	isns_obj_t  *obj;
2839 	result_code_t ret = 0, ret_save = 0;
2840 	isns_type_t lc_type;
2841 	lookup_ctrl_t lc;
2842 	uint32_t uid;
2843 	int i = 0, err_count = 0;
2844 	xmlNodePtr	n_obj, n_node, root;
2845 	int different_err = 0;
2846 
2847 	lc_type = get_lc_type(type);
2848 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
2849 	    return (ERR_INVALID_MGMT_REQUEST);
2850 	}
2851 
2852 	root = xmlDocGetRootElement(doc);
2853 	if (root == NULL) {
2854 	    return (ERR_SYNTAX_MISSING_ROOT);
2855 	}
2856 	lc_type = get_lc_type(type);
2857 	if ((lc_type != OBJ_DD) && (lc_type != OBJ_DDS)) {
2858 	    return (ERR_INVALID_MGMT_REQUEST);
2859 	}
2860 
2861 	/* prepare lookup ctrl data for looking for the node object */
2862 	lc.curr_uid = 0;
2863 	lc.type = lc_type;
2864 	lc.id[0] = get_lc_id(req->op_info.obj);
2865 	lc.op[0] = OP_STRING;
2866 	lc.op[1] = 0;
2867 	lc.data[1].ptr = (uchar_t *)doc; /* xml writer descriptor */
2868 	while (i < req->count) {
2869 		lc.data[0].ptr = req->req_data.attrlist[i]->name,
2870 		/* grab the write lock */
2871 		(void) cache_lock_write();
2872 
2873 		uid = is_obj_there(&lc);
2874 		if (uid == 0) {
2875 		    ret = (lc_type == OBJ_DD) ?
2876 			adm_create_dd(&obj, req->req_data.attrlist[i]->name,
2877 			0, 0) :
2878 			adm_create_dds(&obj, req->req_data.attrlist[i]->name,
2879 			0, 0);
2880 		    if (ret == 0) {
2881 			ret = register_object(obj, NULL, NULL);
2882 			if (ret != 0) {
2883 			    free_object(obj);
2884 			}
2885 			/* release the lock and sync the cache and data store */
2886 			ret = cache_unlock_sync(ret);
2887 		    }
2888 		} else {
2889 			/* release the lock and no need to sync the data */
2890 			(void) cache_unlock_nosync();
2891 			ret = ERR_NAME_IN_USE;
2892 		}
2893 
2894 		if (ret != 0) {
2895 		/* keep track if there are different errors encountered. */
2896 		    if (ret_save != 0 && ret != ret_save) {
2897 			different_err++;
2898 		    }
2899 		    ret_save = ret;
2900 		    err_count++;
2901 		    n_obj = xmlNewNode(NULL, (xmlChar *)ISNSOBJECT);
2902 		    if (n_obj) {
2903 			if ((n_obj = xmlAddChild(root, n_obj)) == NULL) {
2904 			    return (ERR_XML_ADDCHILD_FAILED);
2905 			}
2906 		    } else {
2907 			return (ERR_XML_ADDCHILD_FAILED);
2908 		    }
2909 
2910 		    n_node = (lc_type == OBJ_DD) ?
2911 			xmlNewNode(NULL, (xmlChar *)DDOBJECT) :
2912 			xmlNewNode(NULL, (xmlChar *)DDSETOBJECT);
2913 		    if (n_node) {
2914 			if ((n_node = xmlAddChild(n_obj, n_node)) == NULL) {
2915 			    return (ERR_XML_ADDCHILD_FAILED);
2916 			} else {
2917 			    if (xmlSetProp(n_node, (xmlChar *)NAMEATTR,
2918 				(xmlChar *)req->req_data.attrlist[i]->name) ==
2919 				NULL) {
2920 				return (ERR_XML_SETPROP_FAILED);
2921 			    }
2922 			}
2923 		    } else {
2924 			return (ERR_XML_NEWNODE_FAILED);
2925 		    }
2926 		}
2927 		i++;
2928 	}
2929 
2930 	return (handle_partial_failure(doc, ret_save,
2931 	    (req->count == err_count && !different_err) ? B_TRUE : B_FALSE));
2932 }
2933 
2934 /*
2935  * ****************************************************************************
2936  *
2937  * createModify_dd_ddset_op:
2938  *	removes a list of dd memeber or dd seti member.
2939  *
2940  * req	- contains delete request info.
2941  * doc	- response doc to fill up
2942  *
2943  * ****************************************************************************
2944  */
2945 int
2946 createModify_dd_ddset_op(
2947 	request_t *req,
2948 	xmlDocPtr doc
2949 	/* any additional arguments go here */
2950 )
2951 {
2952 	result_code_t ret = 0;
2953 
2954 	if (req->req_data.attrlist[0]->id != NULL) {
2955 	    ret = rename_dd_ddset_op(req, doc, req->op_info.obj);
2956 	} else if (req->req_data.attrlist[0]->enabled != NULL) {
2957 	    ret = update_dd_ddset_op(req, doc, req->op_info.obj);
2958 	} else {
2959 	    ret = create_dd_ddset_op(req, doc, req->op_info.obj);
2960 	}
2961 
2962 	return (ret);
2963 }
2964