Home | History | Annotate | Download | only in isnsd
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include    <libxml/xmlreader.h>
     27 #include    <libxml/xmlwriter.h>
     28 #include    <libxml/tree.h>
     29 #include    <libxml/parser.h>
     30 #include    <libxml/xpath.h>
     31 #include    <stropts.h>
     32 #include    <door.h>
     33 #include    <errno.h>
     34 #include    <sys/types.h>
     35 #include    <unistd.h>
     36 #include    <pwd.h>
     37 #include    <auth_attr.h>
     38 #include    <secdb.h>
     39 #include    <sys/stat.h>
     40 #include    <fcntl.h>
     41 #include    <sys/stat.h>
     42 #include    <sys/mman.h>
     43 #include    <string.h>
     44 #include    <alloca.h>
     45 #include    <pthread.h>
     46 #include    <ucred.h>
     47 #include    "isns_server.h"
     48 #include    "admintf.h"
     49 #include    "isns_mgmt.h"
     50 #include    "isns_utils.h"
     51 #include    "isns_protocol.h"
     52 #include    "isns_log.h"
     53 #include    "isns_provider.h"
     54 
     55 /* door creation flag */
     56 extern boolean_t door_created;
     57 
     58 /* macro for allocating name buffers for the request */
     59 #define	NEW_REQARGV(old, n) (xmlChar **)realloc((xmlChar *)old, \
     60 	(unsigned)(n+2) * sizeof (xmlChar *))
     61 
     62 /* macro for allocating association pair buffers for the request */
     63 #define	NEW_REQPAIRARGV(old, n) (assoc_pair_t **)realloc((assoc_pair_t *)old, \
     64 	(unsigned)(n+2) * sizeof (assoc_pair_t *))
     65 
     66 /* macro for allocating DD/DD set attribute list buffers for the request */
     67 #define	NEW_REQATTRLISTARGV(old, n)\
     68 	(object_attrlist_t **)realloc((object_attrlist_t *)old, \
     69 	(unsigned)(n+2) * sizeof (object_attrlist_t *))
     70 
     71 /* operation table */
     72 static op_table_entry_t op_table[] = {
     73 	{GET, get_op},
     74 	{GETASSOCIATED, getAssociated_op},
     75 	{ENUMERATE, enumerate_op},
     76 	{CREATEMODIFY, createModify_op},
     77 	{DELETE, delete_op},
     78 	{NULL, 0}
     79 };
     80 
     81 /* object table */
     82 static obj_table_entry_t obj_table[] = {
     83 	{NODEOBJECT, Node},
     84 	{DDOBJECT, DiscoveryDomain},
     85 	{DDSETOBJECT, DiscoveryDomainSet},
     86 	{DDOBJECTMEMBER, DiscoveryDomainMember},
     87 	{DDSETOBJECTMEMBER, DiscoveryDomainSetMember},
     88 	{ISNSSERVER, ServerConfig},
     89 	{NULL, 0}
     90 };
     91 
     92 /*
     93  * list to capture thread id and associated door return buffer
     94  * the return buffer from the previous door return is freed
     95  * when the same thread is invoked to take another request.
     96  * While the server is running one buffer is outstanding
     97  * to be freed.
     98  */
     99 static thr_elem_t *thr_list = NULL;
    100 
    101 /*
    102  * get_op_id_from_doc --
    103  *	    extracts an operation id through the given context ptr.
    104  *
    105  * ctext: context ptr for the original doc
    106  *
    107  * Returns an operation id if found or -1 otherwise.
    108  */
    109 static int
    110 get_op_id_from_doc(xmlXPathContextPtr ctext)
    111 {
    112 	xmlChar expr[ISNS_MAX_LABEL_LEN + 13];
    113 	xmlXPathObjectPtr xpath_obj = NULL;
    114 	int i;
    115 
    116 	for (i = 0; op_table[i].op_str != NULL; i++) {
    117 	    (void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    118 		(const unsigned char *)"%s\"%s\"]", "//*[name()=",
    119 		op_table[i].op_str);
    120 	    xpath_obj = xmlXPathEvalExpression(expr, ctext);
    121 	    if ((xpath_obj) && (xpath_obj->nodesetval) &&
    122 		(xpath_obj->nodesetval->nodeNr > 0) &&
    123 		(xpath_obj->nodesetval->nodeTab)) {
    124 		isnslog(LOG_DEBUG, "get_op_id_from_doc ",
    125 		"xpath obj->nodesetval->nodeNr: %d",
    126 		xpath_obj->nodesetval->nodeNr);
    127 		isnslog(LOG_DEBUG, "get_op_id_from_doc", "operation: %s id: %d",
    128 		    op_table[i].op_str, op_table[i].op_id);
    129 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    130 		return (op_table[i].op_id);
    131 	    }
    132 	    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    133 	}
    134 
    135 	if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    136 	return (-1);
    137 }
    138 
    139 /*
    140  * process_get_request_from_doc --
    141  *	    looks for the object through the context ptr and gets the object
    142  *	    name.  Possible object types are Node, DD, DD set and server-config.
    143  *
    144  * ctext: context ptr for the original doc to parse request info.
    145  * req: request to be filled up.
    146  *
    147  * Returns 0 if successful or an error code otherwise.
    148  */
    149 static int
    150 process_get_request_from_doc(xmlXPathContextPtr ctext, request_t *req)
    151 {
    152 	xmlChar expr[ISNS_MAX_LABEL_LEN + 13];
    153 	xmlXPathObjectPtr xpath_obj = NULL;
    154 	xmlNodeSetPtr r_nodes = NULL;
    155 	xmlAttrPtr attr = NULL;
    156 	int i, cnt;
    157 
    158 	int obj = 0;
    159 
    160 	isnslog(LOG_DEBUG, "process_get_request_from_doc", "entered");
    161 	(void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    162 	    (const unsigned char *)"%s\"%s\"]", "//*[name()=", ISNSOBJECT);
    163 	xpath_obj = xmlXPathEvalExpression(expr, ctext);
    164 	if ((xpath_obj) && (xpath_obj->nodesetval) &&
    165 	    (xpath_obj->nodesetval->nodeTab) &&
    166 	    (xpath_obj->nodesetval->nodeNr > 0) &&
    167 	    (xpath_obj->nodesetval->nodeTab[0]->children) &&
    168 	    (xpath_obj->nodesetval->nodeTab[0]->children->name)) {
    169 	    for (i = 0; obj_table[i].obj_str != NULL; i++) {
    170 		/*
    171 		 * To handle DiscoveryDomain and DiscoveryDomainSet
    172 		 * searches isnsobject instead of the object directly.
    173 		 */
    174 		if (xmlStrncmp(
    175 		    xpath_obj->nodesetval->nodeTab[0]->children->name,
    176 		    (xmlChar *)obj_table[i].obj_str, xmlStrlen(
    177 		    xpath_obj->nodesetval->nodeTab[0]->children->name))
    178 		    == 0) {
    179 			obj = obj_table[i].obj_id;
    180 			break;
    181 		}
    182 	    }
    183 	    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    184 	}
    185 
    186 	if (obj == 0) {
    187 	    /* check the server config request. */
    188 	    (void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    189 	    (const unsigned char *)"%s\"%s\"]", "//*[name()=", ISNSSERVER);
    190 	    xpath_obj = xmlXPathEvalExpression(expr, ctext);
    191 	    if ((xpath_obj) && (xpath_obj->nodesetval) &&
    192 		(xpath_obj->nodesetval->nodeNr > 0) &&
    193 		(xpath_obj->nodesetval->nodeTab)) {
    194 		for (i = 0; obj_table[i].obj_str != NULL; i++) {
    195 		    if (strncmp(ISNSSERVER, obj_table[i].obj_str,
    196 			strlen(ISNSSERVER)) == 0) {
    197 			obj = obj_table[i].obj_id;
    198 			break;
    199 		    }
    200 		}
    201 	    }
    202 	    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    203 	}
    204 
    205 	if (obj == 0) {
    206 	    return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    207 	}
    208 
    209 	req->op_info.obj = obj;
    210 
    211 	if (ISNS_MGMT_OBJECT_TYPE_ENABLED()) {
    212 	    ISNS_MGMT_OBJECT_TYPE(obj);
    213 	}
    214 
    215 	(void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 12,
    216 	    (const unsigned char *)"%s\"%s\"]", "//*[name()=",
    217 	    obj_table[i].obj_str);
    218 	xpath_obj = xmlXPathEvalExpression(expr, ctext);
    219 	if (((xpath_obj == NULL) || (xpath_obj->nodesetval == NULL) ||
    220 	    (xpath_obj->nodesetval->nodeNr <= 0) ||
    221 	    (xpath_obj->nodesetval->nodeTab == NULL))) {
    222 	    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    223 	    return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    224 	}
    225 
    226 	switch (obj) {
    227 	    /* using the same algorithm for isns object */
    228 	    case Node:
    229 	    case DiscoveryDomain:
    230 	    case DiscoveryDomainSet:
    231 		r_nodes = xpath_obj->nodesetval;
    232 		cnt = r_nodes->nodeNr;
    233 		req->count = 0;
    234 		req->req_data.data = (xmlChar **) malloc(sizeof (xmlChar *));
    235 		for (i = 0; i < cnt; i++) {
    236 		    attr = r_nodes->nodeTab[i]->properties;
    237 		    for (; attr != NULL; attr = attr->next) {
    238 			if (xmlStrncmp(attr->name, (xmlChar *)NAMEATTR,
    239 			    xmlStrlen((xmlChar *)NAMEATTR)) == 0) {
    240 				req->req_data.data =
    241 				    NEW_REQARGV(req->req_data.data, req->count);
    242 				if (req->req_data.data == (xmlChar **)NULL) {
    243 				    if (xpath_obj)
    244 					xmlXPathFreeObject(xpath_obj);
    245 				    return (ERR_MALLOC_FAILED);
    246 				}
    247 				req->req_data.data[req->count] =
    248 				    xmlNodeGetContent(attr->children);
    249 				req->req_data.data[++req->count] = NULL;
    250 			}
    251 		    }
    252 		}
    253 		break;
    254 	    case ServerConfig:
    255 		/* indication the obj type is sufficient. */
    256 		break;
    257 	    default:
    258 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    259 		return (ERR_XML_OP_FAILED);
    260 	}
    261 
    262 	if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    263 	return (0);
    264 }
    265 
    266 /*
    267  * process_enumerate_request_from_doc --
    268  *	    looks for the object through the context ptr and sets the
    269  *	    request with object type.
    270  *
    271  * ctext: context ptr for the original doc to parse request info.
    272  * req: request to be filled up.
    273  *
    274  * Returns 0 if successful or an error code otherwise.
    275  */
    276 static int
    277 process_enumerate_request_from_doc(xmlXPathContextPtr ctext, request_t *req)
    278 {
    279 	xmlChar expr[ISNS_MAX_LABEL_LEN + 13];
    280 	xmlXPathObjectPtr xpath_obj = NULL;
    281 	int i;
    282 
    283 	int obj = 0;
    284 
    285 	isnslog(LOG_DEBUG, "process_enumerate_request_from_doc", "entered");
    286 	(void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    287 	    (const unsigned char *)"%s\"%s\"]", "//*[name()=", ISNSOBJECTTYPE);
    288 	xpath_obj = xmlXPathEvalExpression(expr, ctext);
    289 	isnslog(LOG_DEBUG, "process_enumerate_request_from_doc",
    290 	"xpath obj->nodesetval->nodeNR: %d", xpath_obj->nodesetval->nodeNr);
    291 	if ((xpath_obj) && (xpath_obj->nodesetval) &&
    292 	    (xpath_obj->nodesetval->nodeNr > 0) &&
    293 	    (xpath_obj->nodesetval->nodeTab)) {
    294 	    for (i = 0; obj_table[i].obj_str != NULL; i++) {
    295 		if (xmlStrncmp(
    296 		    xpath_obj->nodesetval->nodeTab[0]->children->content,
    297 		    (xmlChar *)obj_table[i].obj_str, xmlStrlen((xmlChar *)
    298 		    xpath_obj->nodesetval->nodeTab[0]->children->content))
    299 		    == 0) {
    300 		    obj = obj_table[i].obj_id;
    301 		    break;
    302 		}
    303 	    }
    304 	} else {
    305 	    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    306 	    return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    307 	}
    308 
    309 	if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    310 
    311 	if (obj == 0) {
    312 	    return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    313 	}
    314 
    315 	req->op_info.obj = obj;
    316 
    317 	if (ISNS_MGMT_OBJECT_TYPE_ENABLED()) {
    318 	    ISNS_MGMT_OBJECT_TYPE(obj);
    319 	}
    320 
    321 	return (0);
    322 }
    323 
    324 /*
    325  * process_getAssociated_request_from_doc --
    326  *	    first looks for association type through the contexti and then
    327  *	    find out the given object.  That will indicate the direction of
    328  *	    association, containter to member or vice versa.
    329  *	    Lastly it extract the object name form the doc that assocation
    330  *	    is requested.
    331  *
    332  * ctext: context ptr for the original doc to parse request info.
    333  * req: request to be filled up.
    334  *
    335  * Returns 0 if successful or an error code otherwise.
    336  */
    337 static int
    338 process_getAssociated_request_from_doc(xmlXPathContextPtr ctext, request_t *req)
    339 {
    340 	xmlChar expr[ISNS_MAX_LABEL_LEN + 13];
    341 	xmlXPathObjectPtr xpath_obj = NULL;
    342 	xmlNodeSetPtr r_nodes = NULL;
    343 	xmlAttrPtr attr = NULL;
    344 	int i, cnt, obj = 0;
    345 
    346 	isnslog(LOG_DEBUG, "process_getAssociated_request_from_doc", "entered");
    347 	(void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    348 	    (const unsigned char *)"%s\"%s\"]", "//*[name()=", ASSOCIATIONTYPE);
    349 	xpath_obj = xmlXPathEvalExpression(expr, ctext);
    350 	if ((xpath_obj) && (xpath_obj->nodesetval) &&
    351 		(xpath_obj->nodesetval->nodeNr > 0) &&
    352 		(xpath_obj->nodesetval->nodeTab)) {
    353 	    for (i = 0; obj_table[i].obj_str != NULL; i++) {
    354 		if (xmlStrncmp(
    355 		    xpath_obj->nodesetval->nodeTab[0]->children->content,
    356 		    (xmlChar *)obj_table[i].obj_str, xmlStrlen(
    357 		    xpath_obj->nodesetval->nodeTab[0]->children->content))
    358 		    == 0) {
    359 		    obj = obj_table[i].obj_id;
    360 		    break;
    361 		}
    362 	    }
    363 	}
    364 
    365 	if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    366 
    367 	if (obj == 0) {
    368 	    return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    369 	}
    370 
    371 	req->op_info.obj = obj;
    372 
    373 	if (ISNS_MGMT_OBJECT_TYPE_ENABLED()) {
    374 	    ISNS_MGMT_OBJECT_TYPE(obj);
    375 	}
    376 
    377 	switch (obj) {
    378 	    /* using the same algorithm for isns object */
    379 	    case DiscoveryDomainMember:
    380 		(void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    381 		(const unsigned char *)"%s\"%s\"]", "//*[name()=", NODEOBJECT);
    382 		xpath_obj = xmlXPathEvalExpression(expr, ctext);
    383 		r_nodes = xpath_obj->nodesetval;
    384 		if ((xpath_obj) && (xpath_obj->nodesetval) &&
    385 		    (xpath_obj->nodesetval->nodeNr > 0) &&
    386 		    (xpath_obj->nodesetval->nodeTab)) {
    387 		    req->assoc_req = member_to_container;
    388 		} else {
    389 		    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    390 		    (void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    391 		    (const unsigned char *)"%s\"%s\"]", "//*[name()=",
    392 		    DDOBJECT);
    393 		    xpath_obj = xmlXPathEvalExpression(expr, ctext);
    394 		    r_nodes = xpath_obj->nodesetval;
    395 		    if ((xpath_obj) && (xpath_obj->nodesetval) &&
    396 			(xpath_obj->nodesetval->nodeNr > 0) &&
    397 			(xpath_obj->nodesetval->nodeTab)) {
    398 			req->assoc_req = container_to_member;
    399 		    } else {
    400 			if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    401 			return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    402 		    }
    403 		}
    404 		break;
    405 	    case DiscoveryDomainSetMember:
    406 		(void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    407 		(const unsigned char *)"%s\"%s\"]", "//*[name()=", DDSETOBJECT);
    408 		xpath_obj = xmlXPathEvalExpression(expr, ctext);
    409 		r_nodes = xpath_obj->nodesetval;
    410 		if ((xpath_obj) && (xpath_obj->nodesetval) &&
    411 		    (xpath_obj->nodesetval->nodeNr > 0) &&
    412 		    (xpath_obj->nodesetval->nodeTab)) {
    413 		    req->assoc_req = container_to_member;
    414 		} else {
    415 		    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    416 		    (void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    417 		    (const unsigned char *)"%s\"%s\"]", "//*[name()=",
    418 			DDOBJECT);
    419 		    xpath_obj = xmlXPathEvalExpression(expr, ctext);
    420 		    r_nodes = xpath_obj->nodesetval;
    421 		    if ((xpath_obj) && (xpath_obj->nodesetval) &&
    422 			(xpath_obj->nodesetval->nodeNr > 0) &&
    423 			(xpath_obj->nodesetval->nodeTab)) {
    424 			req->assoc_req = member_to_container;
    425 		    } else {
    426 			if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    427 			return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    428 		    }
    429 		}
    430 		break;
    431 	    default:
    432 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    433 		return (ERR_XML_OP_FAILED);
    434 	}
    435 
    436 	/* now process the name attr */
    437 	cnt = r_nodes->nodeNr;
    438 	req->count = 0;
    439 	req->req_data.data = (xmlChar **) malloc(sizeof (xmlChar *));
    440 	/* for (i = cnt - 1; i >= 0; i--) { */
    441 	for (i = 0; i < cnt; i++) {
    442 	    attr = r_nodes->nodeTab[i]->properties;
    443 	    for (; attr != NULL; attr = attr->next) {
    444 		if (xmlStrncmp(attr->name, (xmlChar *)NAMEATTR,
    445 		    xmlStrlen((xmlChar *)NAMEATTR)) == 0) {
    446 			req->req_data.data =
    447 			    NEW_REQARGV(req->req_data.data, req->count);
    448 			if (req->req_data.data == (xmlChar **)NULL) {
    449 			    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    450 			    return (ERR_MALLOC_FAILED);
    451 			}
    452 			req->req_data.data[req->count++] =
    453 			xmlNodeGetContent(attr->children);
    454 			req->req_data.data[req->count] = NULL;
    455 		}
    456 	    }
    457 	}
    458 
    459 	if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    460 	return (0);
    461 }
    462 
    463 /*
    464  * process_delete_request_from_doc --
    465  *	    first looks for the object through the context ptr and sets the
    466  *	    request with additional data.
    467  *	    For DD and DD set, the name is given.
    468  *	    For DD and DD set membership, container and member pairs are given.
    469  *
    470  * ctext: context ptr for the original doc to parse request info.
    471  * req: request to be filled up.
    472  *
    473  * Returns 0 if successful or an error code otherwise.
    474  */
    475 static int
    476 process_delete_request_from_doc(xmlXPathContextPtr ctext, request_t *req)
    477 {
    478 	xmlChar expr[ISNS_MAX_LABEL_LEN + 13];
    479 	xmlXPathObjectPtr xpath_obj = NULL;
    480 	xmlNodeSetPtr r_nodes = NULL;
    481 	xmlAttrPtr attr = NULL;
    482 	xmlChar *container = NULL, *member = NULL;
    483 	int i, cnt;
    484 
    485 	int obj = 0;
    486 
    487 	isnslog(LOG_DEBUG, "process_delete_request_from_doc", "entered");
    488 	for (i = 0; obj_table[i].obj_str != NULL; i++) {
    489 	    (void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    490 		(const unsigned char *)"%s\"%s\"]", "//*[name()=",
    491 		obj_table[i].obj_str);
    492 	    xpath_obj = xmlXPathEvalExpression(expr, ctext);
    493 	    if ((xpath_obj) && (xpath_obj->nodesetval) &&
    494 		(xpath_obj->nodesetval->nodeNr > 0) &&
    495 		(xpath_obj->nodesetval->nodeTab)) {
    496 		obj = obj_table[i].obj_id;
    497 		break;
    498 	    }
    499 	    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    500 	}
    501 
    502 	if (obj == 0) {
    503 	    return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    504 	}
    505 
    506 	req->op_info.obj = obj;
    507 
    508 	if (ISNS_MGMT_OBJECT_TYPE_ENABLED()) {
    509 	    ISNS_MGMT_OBJECT_TYPE(obj);
    510 	}
    511 
    512 	switch (obj) {
    513 	    case DiscoveryDomainMember:
    514 		/* at least one object exists to get here. */
    515 		r_nodes = xpath_obj->nodesetval;
    516 		cnt = r_nodes->nodeNr;
    517 		req->count = 0;
    518 		req->req_data.pair =
    519 		(assoc_pair_t **)malloc(sizeof (assoc_pair_t *));
    520 		for (i = 0; i < cnt; i++) {
    521 		    attr = r_nodes->nodeTab[i]->properties;
    522 		    for (; attr != NULL; attr = attr->next) {
    523 			if (xmlStrncmp(attr->name, (xmlChar *)DDNAMEATTR,
    524 			    xmlStrlen((xmlChar *)DDNAMEATTR)) == 0) {
    525 				container =
    526 				xmlNodeGetContent(attr->children);
    527 			}
    528 			if (xmlStrncmp(attr->name, (xmlChar *)NODENAMEATTR,
    529 			    xmlStrlen((xmlChar *)NODENAMEATTR)) == 0) {
    530 				member =
    531 				xmlNodeGetContent(attr->children);
    532 			}
    533 		    }
    534 		    if (container != NULL && member != NULL) {
    535 			    req->req_data.pair =
    536 			    NEW_REQPAIRARGV(req->req_data.pair, req->count);
    537 			    if (req->req_data.pair == (assoc_pair_t **)NULL) {
    538 				if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    539 				return (ERR_MALLOC_FAILED);
    540 			    }
    541 			    req->req_data.pair[req->count] = (assoc_pair_t *)
    542 				malloc(sizeof (assoc_pair_t));
    543 			    if (req->req_data.pair[req->count] == NULL) {
    544 				if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    545 				return (ERR_MALLOC_FAILED);
    546 			    }
    547 			    req->req_data.pair[req->count]->container =
    548 				container;
    549 			    req->req_data.pair[req->count]->member =
    550 				member;
    551 			    req->req_data.data[++req->count] = NULL;
    552 		    } else {
    553 			    if (container != NULL) {
    554 				xmlFree(container);
    555 			    }
    556 			    if (member != NULL) {
    557 				xmlFree(member);
    558 			    }
    559 			    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    560 			    return (ERR_XML_OP_FAILED);
    561 		    }
    562 		    container = NULL;
    563 		    member = NULL;
    564 		}
    565 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    566 		break;
    567 	    case DiscoveryDomainSetMember:
    568 		/* at least one object exists to get here. */
    569 		r_nodes = xpath_obj->nodesetval;
    570 		cnt = r_nodes->nodeNr;
    571 		req->count = 0;
    572 		req->req_data.pair =
    573 		(assoc_pair_t **)malloc(sizeof (assoc_pair_t *));
    574 		for (i = 0; i < cnt; i++) {
    575 		    attr = r_nodes->nodeTab[i]->properties;
    576 		    for (; attr != NULL; attr = attr->next) {
    577 			if (xmlStrncmp(attr->name, (xmlChar *)DDSETNAMEATTR,
    578 			    xmlStrlen((xmlChar *)DDNAMEATTR)) == 0) {
    579 				container =
    580 				xmlNodeGetContent(attr->children);
    581 			}
    582 			if (xmlStrncmp(attr->name, (xmlChar *)DDNAMEATTR,
    583 			    xmlStrlen((xmlChar *)NODENAMEATTR)) == 0) {
    584 				member =
    585 				xmlNodeGetContent(attr->children);
    586 			}
    587 		    }
    588 		    if (container != NULL && member != NULL) {
    589 			    req->req_data.pair =
    590 			    NEW_REQPAIRARGV(req->req_data.pair, req->count);
    591 			    if (req->req_data.pair == (assoc_pair_t **)NULL) {
    592 				if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    593 				return (ERR_MALLOC_FAILED);
    594 			    }
    595 			    req->req_data.pair[req->count] = (assoc_pair_t *)
    596 				malloc(sizeof (assoc_pair_t));
    597 			    if (req->req_data.pair[req->count] == NULL) {
    598 				if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    599 				return (ERR_MALLOC_FAILED);
    600 			    }
    601 			    req->req_data.pair[req->count]->container =
    602 				container;
    603 			    req->req_data.pair[req->count++]->member =
    604 				member;
    605 			    req->req_data.data[req->count] = NULL;
    606 		    } else {
    607 			    if (container != NULL) {
    608 				xmlFree(container);
    609 			    }
    610 			    if (member != NULL) {
    611 				xmlFree(member);
    612 			    }
    613 			    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    614 			    return (ERR_XML_OP_FAILED);
    615 		    }
    616 		}
    617 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    618 		break;
    619 	    case DiscoveryDomain:
    620 	    case DiscoveryDomainSet:
    621 		r_nodes = xpath_obj->nodesetval;
    622 		cnt = r_nodes->nodeNr;
    623 		req->count = 0;
    624 		req->req_data.data = (xmlChar **) malloc(sizeof (xmlChar *));
    625 		for (i = 0; i < cnt; i++) {
    626 		    attr = r_nodes->nodeTab[i]->properties;
    627 		    for (; attr != NULL; attr = attr->next) {
    628 			if (xmlStrncmp(attr->name, (xmlChar *)NAMEATTR,
    629 			    xmlStrlen((xmlChar *)NAMEATTR)) == 0) {
    630 				req->req_data.data =
    631 				    NEW_REQARGV(req->req_data.data, req->count);
    632 				if (req->req_data.data == (xmlChar **)NULL) {
    633 				    if (xpath_obj)
    634 					xmlXPathFreeObject(xpath_obj);
    635 				    return (ERR_MALLOC_FAILED);
    636 				}
    637 				req->req_data.data[req->count] =
    638 				xmlNodeGetContent(attr->children);
    639 				req->req_data.data[++req->count] = NULL;
    640 			}
    641 		    }
    642 		}
    643 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    644 		break;
    645 	    default:
    646 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    647 		return (ERR_XML_OP_FAILED);
    648 	}
    649 
    650 	return (0);
    651 }
    652 
    653 /*
    654  * process_createModify_request_from_doc --
    655  *	    first looks for the object through the context ptr and sets the
    656  *	    request with additional data.
    657  *	    For DD and DD set, the name is given.
    658  *	    For DD and DD set membership, container and member pairs are given.
    659  *
    660  * ctext: context ptr for the original doc to parse request info.
    661  * req: request to be filled up.
    662  *
    663  * Returns 0 if successful or an error code otherwise.
    664  */
    665 static int
    666 process_createModify_request_from_doc(xmlXPathContextPtr ctext, request_t *req)
    667 {
    668 	xmlChar expr[ISNS_MAX_LABEL_LEN + 13];
    669 	xmlXPathObjectPtr xpath_obj = NULL;
    670 	xmlNodeSetPtr r_nodes = NULL;
    671 	xmlAttrPtr attr = NULL;
    672 	xmlChar *container = NULL, *member = NULL, *xml_id;
    673 	int i, cnt;
    674 
    675 	int obj = 0;
    676 
    677 	isnslog(LOG_DEBUG, "process_createModify_request_from_doc", "entered");
    678 	for (i = 0; obj_table[i].obj_str != NULL; i++) {
    679 	    (void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
    680 		(const unsigned char *)"%s\"%s\"]", "//*[name()=",
    681 		obj_table[i].obj_str);
    682 	    xpath_obj = xmlXPathEvalExpression(expr, ctext);
    683 	    if ((xpath_obj) && (xpath_obj->nodesetval) &&
    684 		(xpath_obj->nodesetval->nodeNr > 0) &&
    685 		(xpath_obj->nodesetval->nodeTab)) {
    686 		obj = obj_table[i].obj_id;
    687 		break;
    688 	    }
    689 	    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    690 	}
    691 
    692 	if (obj == 0) {
    693 	    return (ERR_XML_VALID_OBJECT_NOT_FOUND);
    694 	}
    695 
    696 	req->op_info.obj = obj;
    697 
    698 	if (ISNS_MGMT_OBJECT_TYPE_ENABLED()) {
    699 	    ISNS_MGMT_OBJECT_TYPE(obj);
    700 	}
    701 
    702 	switch (obj) {
    703 	    case DiscoveryDomainMember:
    704 		/* at least one object exists to get here. */
    705 		r_nodes = xpath_obj->nodesetval;
    706 		cnt = r_nodes->nodeNr;
    707 		req->count = 0;
    708 		req->req_data.pair =
    709 		(assoc_pair_t **)malloc(sizeof (assoc_pair_t *));
    710 		for (i = 0; i < cnt; i++) {
    711 		    attr = r_nodes->nodeTab[i]->properties;
    712 		    for (; attr != NULL; attr = attr->next) {
    713 			if (xmlStrncmp(attr->name, (xmlChar *)DDNAMEATTR,
    714 			    xmlStrlen((xmlChar *)DDNAMEATTR)) == 0) {
    715 				container =
    716 				xmlNodeGetContent(attr->children);
    717 			}
    718 			if (xmlStrncmp(attr->name, (xmlChar *)NODENAMEATTR,
    719 			    xmlStrlen((xmlChar *)NODENAMEATTR)) == 0) {
    720 				member =
    721 				xmlNodeGetContent(attr->children);
    722 			}
    723 		    }
    724 		    if (container != NULL && member != NULL) {
    725 			    req->req_data.pair =
    726 			    NEW_REQPAIRARGV(req->req_data.pair, req->count);
    727 			    if (req->req_data.pair == (assoc_pair_t **)NULL) {
    728 				if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    729 				return (ERR_MALLOC_FAILED);
    730 			    }
    731 			    req->req_data.pair[req->count] = (assoc_pair_t *)
    732 				malloc(sizeof (assoc_pair_t));
    733 			    if (req->req_data.pair[req->count] == NULL) {
    734 				if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    735 				return (ERR_MALLOC_FAILED);
    736 			    }
    737 			    req->req_data.pair[req->count]->container =
    738 				container;
    739 			    req->req_data.pair[req->count]->member =
    740 				member;
    741 			    req->req_data.data[++req->count] = NULL;
    742 		    } else {
    743 			    if (container != NULL) {
    744 				xmlFree(container);
    745 			    }
    746 			    if (member != NULL) {
    747 				xmlFree(member);
    748 			    }
    749 			    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    750 			    return (ERR_XML_OP_FAILED);
    751 		    }
    752 		    container = member = NULL;
    753 		}
    754 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    755 		break;
    756 	    case DiscoveryDomainSetMember:
    757 		/* at least one object exists to get here. */
    758 		r_nodes = xpath_obj->nodesetval;
    759 		cnt = r_nodes->nodeNr;
    760 		req->count = 0;
    761 		req->req_data.pair =
    762 		(assoc_pair_t **)malloc(sizeof (assoc_pair_t *));
    763 		for (i = 0; i < cnt; i++) {
    764 		    attr = r_nodes->nodeTab[i]->properties;
    765 		    for (; attr != NULL; attr = attr->next) {
    766 			if (xmlStrncmp(attr->name, (xmlChar *)DDSETNAMEATTR,
    767 			    xmlStrlen((xmlChar *)DDSETNAMEATTR)) == 0) {
    768 				container =
    769 				xmlNodeGetContent(attr->children);
    770 			}
    771 			if (xmlStrncmp(attr->name, (xmlChar *)DDNAMEATTR,
    772 			    xmlStrlen((xmlChar *)DDNAMEATTR)) == 0) {
    773 				member =
    774 				xmlNodeGetContent(attr->children);
    775 			}
    776 		    }
    777 		    if (container != NULL && member != NULL) {
    778 			    req->req_data.pair =
    779 			    NEW_REQPAIRARGV(req->req_data.pair, req->count);
    780 			    if (req->req_data.pair == (assoc_pair_t **)NULL) {
    781 				if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    782 				return (ERR_MALLOC_FAILED);
    783 			    }
    784 			    req->req_data.pair[req->count] = (assoc_pair_t *)
    785 				malloc(sizeof (assoc_pair_t));
    786 			    if (req->req_data.pair[req->count] == NULL) {
    787 				if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    788 				return (ERR_MALLOC_FAILED);
    789 			    }
    790 			    req->req_data.pair[req->count]->container =
    791 				container;
    792 			    req->req_data.pair[req->count]->member =
    793 				member;
    794 			    req->req_data.data[++req->count] = NULL;
    795 		    } else {
    796 			    if (container != NULL) {
    797 				xmlFree(container);
    798 			    }
    799 			    if (member != NULL) {
    800 				xmlFree(member);
    801 			    }
    802 			    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    803 			    return (ERR_XML_OP_FAILED);
    804 		    }
    805 		    container = member = NULL;
    806 		}
    807 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    808 		break;
    809 	    case DiscoveryDomain:
    810 	    case DiscoveryDomainSet:
    811 		/* at least one object exists to get here. */
    812 		r_nodes = xpath_obj->nodesetval;
    813 		cnt = r_nodes->nodeNr;
    814 		req->count = 0;
    815 		req->req_data.attrlist =
    816 		(object_attrlist_t **)malloc(sizeof (object_attrlist_t *));
    817 		for (i = 0; i < cnt; i++) {
    818 		    req->req_data.attrlist =
    819 			NEW_REQATTRLISTARGV(req->req_data.attrlist, req->count);
    820 		    if (req->req_data.attrlist ==
    821 			(object_attrlist_t **)NULL) {
    822 			if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    823 			return (ERR_MALLOC_FAILED);
    824 		    }
    825 		    req->req_data.attrlist[req->count] = (object_attrlist_t *)
    826 			malloc(sizeof (object_attrlist_t));
    827 		    if (req->req_data.attrlist[req->count] == NULL) {
    828 			if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    829 			return (ERR_MALLOC_FAILED);
    830 		    }
    831 		    req->req_data.attrlist[req->count]->name = NULL;
    832 		    req->req_data.attrlist[req->count]->id = NULL;
    833 		    req->req_data.attrlist[req->count]->enabled = NULL;
    834 		    attr = r_nodes->nodeTab[i]->properties;
    835 		    for (; attr != NULL; attr = attr->next) {
    836 			if ((xmlStrncmp(attr->name, (xmlChar *)NAMEATTR,
    837 			    xmlStrlen((xmlChar *)NAMEATTR))) == 0) {
    838 				req->req_data.attrlist[req->count]->name =
    839 				xmlNodeGetContent(attr->children);
    840 			}
    841 			if ((xmlStrncmp(attr->name, (xmlChar *)IDATTR,
    842 			    xmlStrlen((xmlChar *)IDATTR))) == 0) {
    843 				req->req_data.attrlist[req->count]->id =
    844 				    (uint32_t *)calloc(1, sizeof (uint32_t));
    845 				if (req->req_data.attrlist[req->count]->id ==
    846 				    NULL) {
    847 				    if (xpath_obj)
    848 					xmlXPathFreeObject(xpath_obj);
    849 				    return (ERR_MALLOC_FAILED);
    850 				}
    851 				xml_id = xmlNodeGetContent(attr->children);
    852 				if (xml_id != NULL) {
    853 				    *(req->req_data.attrlist[req->count]->id) =
    854 					atoi((const char *)xml_id);
    855 				    xmlFree(xml_id);
    856 				}
    857 			}
    858 		    }
    859 			/*
    860 			 * check the enabled element.
    861 			 * Only one child element so check the children ptr.
    862 			 */
    863 		    if (r_nodes->nodeTab[i]->children) {
    864 			req->req_data.attrlist[req->count]->enabled =
    865 			    (boolean_t *)malloc(sizeof (boolean_t));
    866 			if (req->req_data.attrlist[req->count]->enabled
    867 			    == NULL) {
    868 			    if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    869 			    return (ERR_MALLOC_FAILED);
    870 			}
    871 			/* value is children of enabled. */
    872 			if (xmlStrncmp(
    873 			    r_nodes->nodeTab[i]->children->children->content,
    874 			    (xmlChar *)XMLTRUE, xmlStrlen((xmlChar *)XMLTRUE))
    875 			    == 0) {
    876 			    *(req->req_data.attrlist[req->count]->enabled)
    877 				= B_TRUE;
    878 			} else {
    879 			    *(req->req_data.attrlist[req->count]->enabled)
    880 				= B_FALSE;
    881 			}
    882 		    }
    883 		    req->req_data.attrlist[++req->count] = NULL;
    884 		}
    885 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    886 		break;
    887 	    default:
    888 		if (xpath_obj) xmlXPathFreeObject(xpath_obj);
    889 		return (ERR_XML_OP_FAILED);
    890 	}
    891 
    892 	return (0);
    893 }
    894 
    895 /*
    896  * build_mgmt_request -- extracts the request info from the given XML doc.
    897  *
    898  * x_doc: ptr to the request XML doc
    899  * req: ptr to the request struct to be filled up.
    900  *
    901  * Return value: ISNS_RSP_SUCCESSFUL if successful or an error code.
    902  */
    903 static int
    904 process_mgmt_request(xmlDocPtr x_doc, request_t *req, ucred_t *uc)
    905 {
    906 	result_code_t   ret;
    907 	int		op;
    908 	xmlXPathContextPtr ctext = NULL;
    909 	uid_t			user;
    910 	struct passwd		pwds, *pwd;
    911 	char			buf_pwd[1024];
    912 
    913 
    914 	isnslog(LOG_DEBUG, "process_mgmt_request", "entered");
    915 	(void) memset(req, 0, sizeof (request_t));
    916 	/* get the operation first. */
    917 	ctext = xmlXPathNewContext(x_doc);
    918 	if (ctext == NULL) {
    919 	    return (ERR_XML_FAILED_TO_SET_XPATH_CONTEXT);
    920 	}
    921 
    922 	isnslog(LOG_DEBUG, "process_mgmt_request", "xpath context succeeded");
    923 	op = get_op_id_from_doc(ctext);
    924 	if (op == -1) {
    925 	    if (ctext) xmlXPathFreeContext(ctext);
    926 	    return (ERR_XML_VALID_OPERATION_NOT_FOUND);
    927 	}
    928 
    929 	user = ucred_getruid(uc);
    930 	ret = getpwuid_r(user, &pwds, buf_pwd, sizeof (buf_pwd), &pwd);
    931 	if (ret != 0) {
    932 	    if (ctext) xmlXPathFreeContext(ctext);
    933 	    return (ERR_DOOR_SERVER_DETECTED_INVALID_USER);
    934 	}
    935 
    936 	/* write operations are restricted. */
    937 	if ((op == delete_op) || (op == createModify_op)) {
    938 	    if (!chkauthattr(ISNS_ADMIN_WRITE_AUTH, pwd->pw_name)) {
    939 		if (ctext) xmlXPathFreeContext(ctext);
    940 		return (ERR_DOOR_SERVER_DETECTED_NOT_AUTHORIZED_USER);
    941 	    }
    942 	}
    943 
    944 	req->op_info.op = op;
    945 
    946 	if (ISNS_MGMT_OPERATION_TYPE_ENABLED()) {
    947 	    ISNS_MGMT_OPERATION_TYPE(op);
    948 	}
    949 
    950 	switch (op) {
    951 	    case (get_op):
    952 		ret = process_get_request_from_doc(ctext, req);
    953 		break;
    954 	    case (getAssociated_op):
    955 		ret = process_getAssociated_request_from_doc(ctext, req);
    956 		break;
    957 	    case (enumerate_op):
    958 		ret = process_enumerate_request_from_doc(ctext, req);
    959 		break;
    960 	    case (delete_op):
    961 		ret = process_delete_request_from_doc(ctext, req);
    962 		break;
    963 	    case (createModify_op):
    964 		ret = process_createModify_request_from_doc(ctext, req);
    965 		break;
    966 	    default:
    967 		ret = ERR_XML_VALID_OPERATION_NOT_FOUND;
    968 	}
    969 
    970 	if (ctext) xmlXPathFreeContext(ctext);
    971 	return (ret);
    972 }
    973 
    974 /*
    975  * build_mgmt_response -- sets an XML doc with a root and calls a porper
    976  *	    routine based on the request.  If the called routine constructed
    977  *	    the response doc with the result element, this routine fills up
    978  *	    response buffer with raw XML doc.
    979  *
    980  * reponse: ptr to response buffer
    981  * req: request to be processed.
    982  * size: ptr to the response doc buffer
    983  */
    984 static int
    985 build_mgmt_response(xmlChar **response, request_t req, int *size)
    986 {
    987 
    988 	int ret;
    989 	xmlDocPtr	doc;
    990 	xmlNodePtr	root;
    991 	xmlXPathContextPtr ctext = NULL;
    992 	xmlChar expr[ISNS_MAX_LABEL_LEN + 13];
    993 	xmlXPathObjectPtr xpath_obj = NULL;
    994 
    995 	isnslog(LOG_DEBUG, "build_mgmt_response", "entered");
    996 
    997 	doc = xmlNewDoc((uchar_t *)"1.0");
    998 	root = xmlNewNode(NULL, (xmlChar *)ISNSRESPONSE);
    999 	(void) xmlDocSetRootElement(doc, root);
   1000 	if (xmlSetProp(root, (xmlChar *)XMLNSATTR, (xmlChar *)XMLNSATTRVAL) ==
   1001 	    NULL) {
   1002 	    return (ERR_XML_SETPROP_FAILED);
   1003 	}
   1004 
   1005 	switch (req.op_info.op) {
   1006 	    case get_op:
   1007 		switch (req.op_info.obj) {
   1008 		    case Node:
   1009 			ret = get_node_op(&req, doc);
   1010 			break;
   1011 		    case DiscoveryDomain:
   1012 			ret = get_dd_op(&req, doc);
   1013 			break;
   1014 		    case DiscoveryDomainSet:
   1015 			ret = get_ddset_op(&req, doc);
   1016 			break;
   1017 		    case ServerConfig:
   1018 			ret = get_serverconfig_op(doc);
   1019 			break;
   1020 		    default:
   1021 			ret = ERR_INVALID_MGMT_REQUEST;
   1022 		}
   1023 		break;
   1024 	    case enumerate_op:
   1025 		isnslog(LOG_DEBUG, "build_mgmt_response", "enumerate_op");
   1026 		switch (req.op_info.obj) {
   1027 		    case Node:
   1028 			ret = enumerate_node_op(doc);
   1029 			break;
   1030 		    case DiscoveryDomain:
   1031 			ret = enumerate_dd_op(doc);
   1032 			break;
   1033 		    case DiscoveryDomainSet:
   1034 			ret = enumerate_ddset_op(doc);
   1035 			break;
   1036 		    default:
   1037 			ret = ERR_INVALID_MGMT_REQUEST;
   1038 		}
   1039 		break;
   1040 	    case getAssociated_op:
   1041 		switch (req.op_info.obj) {
   1042 		    case DiscoveryDomainMember:
   1043 			if (req.assoc_req == container_to_member) {
   1044 			    ret = getAssociated_dd_to_node_op(&req, doc);
   1045 			} else {
   1046 			    ret = getAssociated_node_to_dd_op(&req, doc);
   1047 			}
   1048 			break;
   1049 		    case DiscoveryDomainSetMember:
   1050 			if (req.assoc_req == container_to_member) {
   1051 			    ret = getAssociated_ddset_to_dd_op(&req, doc);
   1052 			} else {
   1053 			    ret = getAssociated_dd_to_ddset_op(&req, doc);
   1054 			}
   1055 			break;
   1056 		    default:
   1057 			ret = ERR_INVALID_MGMT_REQUEST;
   1058 		}
   1059 		break;
   1060 	    case createModify_op:
   1061 		switch (req.op_info.obj) {
   1062 		    case DiscoveryDomain:
   1063 		    case DiscoveryDomainSet:
   1064 			ret = createModify_dd_ddset_op(&req, doc);
   1065 			break;
   1066 		    case DiscoveryDomainMember:
   1067 		    case DiscoveryDomainSetMember:
   1068 			ret = create_ddmember_ddsetmember_op(&req, doc,
   1069 			    req.op_info.obj);
   1070 			break;
   1071 		    default:
   1072 			ret = ERR_INVALID_MGMT_REQUEST;
   1073 		}
   1074 		break;
   1075 	    case delete_op:
   1076 		switch (req.op_info.obj) {
   1077 		    case DiscoveryDomainMember:
   1078 		    case DiscoveryDomainSetMember:
   1079 			ret = delete_ddmember_ddsetmember_op(&req, doc,
   1080 			    req.op_info.obj);
   1081 			break;
   1082 		    case DiscoveryDomain:
   1083 		    case DiscoveryDomainSet:
   1084 			ret = delete_dd_ddset_op(&req, doc, req.op_info.obj);
   1085 			break;
   1086 		    default:
   1087 			ret = ERR_INVALID_MGMT_REQUEST;
   1088 		}
   1089 		break;
   1090 	    default:
   1091 		ret = ERR_INVALID_MGMT_REQUEST;
   1092 	}
   1093 
   1094 	/*
   1095 	 * if failed check to see the doc contains the result element.
   1096 	 * if not, the response is set with only an error code.
   1097 	 */
   1098 	if (ret != ISNS_RSP_SUCCESSFUL) {
   1099 	    ctext = xmlXPathNewContext(doc);
   1100 	    if (ctext != NULL) {
   1101 		(void) xmlStrPrintf(expr, ISNS_MAX_LABEL_LEN + 13,
   1102 		    (const unsigned char *)"%s\"%s\"]", "//*[name()=", RESULT);
   1103 		xpath_obj = xmlXPathEvalExpression(expr, ctext);
   1104 		if ((xpath_obj == NULL) || (xpath_obj->nodesetval == NULL) ||
   1105 		    (xpath_obj->nodesetval->nodeNr <= 0) ||
   1106 		    (xpath_obj->nodesetval->nodeTab == NULL)) {
   1107 		    isnslog(LOG_DEBUG,
   1108 			"build_mgmt_response",
   1109 			"returning repsonse only with error code %d\n", ret);
   1110 			*response = malloc(sizeof (ret));
   1111 			if (*response) **response = ret;
   1112 			*size = sizeof (ret);
   1113 		} else {
   1114 		    xmlDocDumpMemory(doc, response, size);
   1115 		}
   1116 	    } else {
   1117 		/* can't verify the xml doc. dump return the doc anyway. */
   1118 		xmlDocDumpMemory(doc, response, size);
   1119 	    }
   1120 	} else {
   1121 	    xmlDocDumpMemory(doc, response, size);
   1122 	}
   1123 
   1124 	if (xpath_obj) xmlXPathFreeObject(xpath_obj);
   1125 	if (ctext) xmlXPathFreeContext(ctext);
   1126 	if (doc) xmlFreeDoc(doc);
   1127 	return (ret);
   1128 }
   1129 
   1130 /*
   1131  * build_result_message -- construct a response doc with the given result.
   1132  *	    Result contains status code and message.
   1133  *
   1134  * reponse: ptr to response doc
   1135  * code: result code
   1136  * size: ptr to the response doc size
   1137  */
   1138 static int
   1139 build_result_message(xmlChar **response, result_code_t code, int *size)
   1140 {
   1141 	int ret = ISNS_RSP_SUCCESSFUL;
   1142 	xmlDocPtr	doc;
   1143 	xmlNodePtr	root, n_obj;
   1144 	char		numbuf[32];
   1145 
   1146 	isnslog(LOG_DEBUG, "build_result_response", "entered");
   1147 
   1148 	doc = xmlNewDoc((uchar_t *)"1.0");
   1149 	root = xmlNewNode(NULL, (xmlChar *)ISNSRESPONSE);
   1150 	(void) xmlDocSetRootElement(doc, root);
   1151 
   1152 	n_obj = xmlNewChild(root, NULL, (xmlChar *)RESULT, NULL);
   1153 
   1154 	if (code == ISNS_RSP_SUCCESSFUL) {
   1155 	    (void) sprintf(numbuf, "%d", ISNS_RSP_SUCCESSFUL);
   1156 	    if (xmlNewChild(n_obj, NULL, (xmlChar *)STATUSELEMENT,
   1157 		(xmlChar *)numbuf) == NULL) {
   1158 		ret = ERR_XML_NEWCHILD_FAILED;
   1159 	    }
   1160 	} else {
   1161 	    (void) sprintf(numbuf, "%d", code);
   1162 	    if (xmlNewChild(n_obj, NULL, (xmlChar *)STATUSELEMENT,
   1163 		(xmlChar *)numbuf) == NULL) {
   1164 		ret = ERR_XML_NEWCHILD_FAILED;
   1165 	    }
   1166 	    if (xmlNewChild(n_obj, NULL, (xmlChar *)MESSAGEELEMENT,
   1167 		(xmlChar *)result_code_to_str(code)) == NULL) {
   1168 		ret = ERR_XML_NEWCHILD_FAILED;
   1169 	    }
   1170 	}
   1171 
   1172 	xmlDocDumpMemory(doc, response, size);
   1173 
   1174 	if (doc) xmlFreeDoc(doc);
   1175 	return (ret);
   1176 }
   1177 
   1178 /*
   1179  * cleanup_request -- deallocatate memory associated with the given request
   1180  *	    structure.
   1181  */
   1182 static void
   1183 cleanup_request(request_t req)
   1184 {
   1185 	int i;
   1186 
   1187 	isnslog(LOG_DEBUG, "cleanup_request", "entered");
   1188 	switch (req.op_info.op) {
   1189 	    case (get_op):
   1190 		for (i = 0; i < req.count; i++) {
   1191 		    if (req.req_data.data[i])
   1192 			xmlFree(req.req_data.data[i]);
   1193 		}
   1194 		if (req.req_data.data) free(req.req_data.data);
   1195 		break;
   1196 	    case (getAssociated_op):
   1197 		for (i = 0; i < req.count; i++) {
   1198 		    if (req.req_data.data[i])
   1199 			xmlFree(req.req_data.data[i]);
   1200 		}
   1201 		if (req.req_data.data) free(req.req_data.data);
   1202 		break;
   1203 	    case (enumerate_op):
   1204 		break;
   1205 	    case (delete_op):
   1206 		if ((req.op_info.obj == DiscoveryDomainMember) ||
   1207 		    (req.op_info.obj == DiscoveryDomainSetMember)) {
   1208 		    for (i = 0; i < req.count; i++) {
   1209 			if (req.req_data.pair[i]->container)
   1210 			    xmlFree(req.req_data.pair[i]->container);
   1211 			if (req.req_data.pair[i]->member)
   1212 			    xmlFree(req.req_data.pair[i]->member);
   1213 			if (req.req_data.pair[i])
   1214 			    free(req.req_data.pair[i]);
   1215 		    }
   1216 		    if (req.req_data.pair) free(req.req_data.pair);
   1217 		} else {
   1218 		    for (i = 0; i < req.count; i++) {
   1219 			if (req.req_data.data[i])
   1220 			    xmlFree(req.req_data.data[i]);
   1221 		    }
   1222 		    if (req.req_data.data) free(req.req_data.data);
   1223 		}
   1224 		break;
   1225 	    case (createModify_op):
   1226 		if ((req.op_info.obj == DiscoveryDomainMember) ||
   1227 		    (req.op_info.obj == DiscoveryDomainSetMember)) {
   1228 		    for (i = 0; i < req.count; i++) {
   1229 			if (req.req_data.pair[i]->container)
   1230 			    xmlFree(req.req_data.pair[i]->container);
   1231 			if (req.req_data.pair[i]->member)
   1232 			    xmlFree(req.req_data.pair[i]->member);
   1233 			if (req.req_data.pair[i])
   1234 			    free(req.req_data.pair[i]);
   1235 		    }
   1236 		    if (req.req_data.pair) free(req.req_data.pair);
   1237 		} else if ((req.op_info.obj == DiscoveryDomain) ||
   1238 		    (req.op_info.obj == DiscoveryDomainSet)) {
   1239 		    for (i = 0; i < req.count; i++) {
   1240 			if (req.req_data.attrlist[i]->name)
   1241 			    xmlFree(req.req_data.attrlist[i]->name);
   1242 			if (req.req_data.attrlist[i]->id)
   1243 			    free(req.req_data.attrlist[i]->id);
   1244 			if (req.req_data.attrlist[i]->enabled)
   1245 			    free(req.req_data.attrlist[i]->enabled);
   1246 			if (req.req_data.pair[i])
   1247 			    free(req.req_data.pair[i]);
   1248 		    }
   1249 		    if (req.req_data.attrlist) free(req.req_data.attrlist);
   1250 		}
   1251 		break;
   1252 	}
   1253 }
   1254 
   1255 /*
   1256  * Find a matching entry for the given thread id.
   1257  */
   1258 static thr_elem_t *match_entry(pthread_t tid)
   1259 {
   1260 
   1261 	thr_elem_t *thr = thr_list;
   1262 
   1263 	while (thr) {
   1264 	    if (pthread_equal(thr->thr_id, tid)) {
   1265 		return (thr);
   1266 	    }
   1267 	    thr = thr->next;
   1268 	}
   1269 
   1270 	return (NULL);
   1271 }
   1272 
   1273 /*
   1274  * Add an entry to the thr_list for the given thread id.
   1275  */
   1276 static int
   1277 add_entry(pthread_t tid, xmlChar *doc)
   1278 {
   1279 
   1280 	thr_elem_t *new_e;
   1281 	thr_elem_t *thr = thr_list;
   1282 
   1283 	if ((new_e = malloc(sizeof (thr_elem_t))) == NULL) {
   1284 	    return (ERR_MALLOC_FAILED);
   1285 	}
   1286 	new_e->thr_id = tid;
   1287 	new_e->doc = doc;
   1288 	new_e->next = NULL;
   1289 
   1290 	if (thr_list == NULL) {
   1291 	    thr_list = new_e;
   1292 	} else {
   1293 	    while (thr->next) {
   1294 		thr = thr->next;
   1295 	    }
   1296 	    thr->next = new_e;
   1297 	}
   1298 
   1299 	return (ISNS_RSP_SUCCESSFUL);
   1300 }
   1301 
   1302 /*
   1303  * door_server -- proecess the management request and send response back
   1304  *		the client.
   1305  *
   1306  * In order to handle allocation after door_return,
   1307  * a global list, thr_list, is maintained to free the response buffer
   1308  * from the previous invocation of the server function on the same thread.
   1309  * Note:  the door framework creates a thread and the same thread is used
   1310  * while a new thread is created for concurrent door_calls.
   1311  *
   1312  * If a thread is used once the buffer will be left allocated.
   1313  */
   1314 /*ARGSUSED*/
   1315 static void
   1316 door_server(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
   1317     uint_t n_desc)
   1318 {
   1319 	request_t		req;
   1320 	xmlDocPtr		x_doc;
   1321 	xmlChar			*resp_buf = NULL;
   1322 	int			ret, size = 0;
   1323 	pthread_t		tid;
   1324 	thr_elem_t		*thr;
   1325 	ucred_t			*uc = NULL;
   1326 
   1327 	if (ISNS_MGMT_REQUEST_RECEIVED_ENABLED()) {
   1328 	    ISNS_MGMT_REQUEST_RECEIVED();
   1329 	}
   1330 
   1331 	if (door_ucred(&uc) != 0) {
   1332 	    isnslog(LOG_DEBUG, "door_server",
   1333 		"door_ucred failed. errno: %d\n", errno);
   1334 	    ret = build_result_message(&resp_buf,
   1335 		ERR_DOOR_UCRED_FAILED, &size);
   1336 	    if (ret == ISNS_RSP_SUCCESSFUL) {
   1337 		(void) door_return((char *)resp_buf, size + 1,  NULL, 0);
   1338 		/* Not reached */
   1339 	    } else {
   1340 		ret = ERR_DOOR_UCRED_FAILED;
   1341 		(void) door_return((void *)&ret, sizeof (ret),  NULL, 0);
   1342 		/* Not reached */
   1343 	    }
   1344 	}
   1345 
   1346 	isnslog(LOG_DEBUG, "door_server", "entered with request:\n %s\n", argp);
   1347 	if ((x_doc = xmlParseMemory(argp, arg_size)) != NULL) {
   1348 		isnslog(LOG_DEBUG, "door_server", "ParseMemory succeeded");
   1349 		if ((ret = process_mgmt_request(x_doc, &req, uc)) == 0) {
   1350 		    ret = build_mgmt_response(&resp_buf, req, &size);
   1351 		} else {
   1352 		    ret = build_result_message(&resp_buf, ret, &size);
   1353 		}
   1354 		xmlFreeDoc(x_doc);
   1355 		cleanup_request(req);
   1356 	} else {
   1357 		ret = build_result_message(&resp_buf,
   1358 		    ERR_XML_PARSE_MEMORY_FAILED, &size);
   1359 	}
   1360 
   1361 	/* free the ucred */
   1362 	ucred_free(uc);
   1363 
   1364 	if (resp_buf) {
   1365 	    tid = pthread_self();
   1366 	    if ((thr = match_entry(tid)) == NULL) {
   1367 		(void) add_entry(tid, resp_buf);
   1368 	    } else {
   1369 		isnslog(LOG_DEBUG, "door_server",
   1370 		    "free the previouly returned buffer %x on this thread\n",
   1371 		    thr->doc);
   1372 		xmlFree(thr->doc);
   1373 		isnslog(LOG_DEBUG, "door_server",
   1374 		    "store the currently allocated buffer %x on this thread\n",
   1375 		    resp_buf);
   1376 		thr->doc = resp_buf;
   1377 	    }
   1378 	    isnslog(LOG_DEBUG,
   1379 		"door_server", "exiting with response:\n %s\n",
   1380 		    (const char *)resp_buf);
   1381 
   1382 	    if (ISNS_MGMT_REQUEST_RESPONDED_ENABLED()) {
   1383 		ISNS_MGMT_REQUEST_RESPONDED();
   1384 	    }
   1385 
   1386 	    (void) door_return((char *)resp_buf, size + 1,  NULL, 0);
   1387 		/* Not reached */
   1388 	}
   1389 
   1390 	isnslog(LOG_DEBUG,
   1391 	    "door_server", "exiting only with error code %d\n", ret);
   1392 
   1393 	if (ISNS_MGMT_REQUEST_RESPONDED_ENABLED()) {
   1394 	    ISNS_MGMT_REQUEST_RESPONDED();
   1395 	}
   1396 
   1397 	(void) door_return((void *)&ret, sizeof (ret),  NULL, 0);
   1398 
   1399 }
   1400 
   1401 /*
   1402  * setup_mgmt_door -- Create a door portal for management application requests
   1403  *
   1404  * First check to see if another daemon is already running by attempting
   1405  * to send an empty request to the door. If successful it means this
   1406  * daemon should exit.
   1407  */
   1408 int
   1409 setup_mgmt_door(msg_queue_t *sys_q)
   1410 {
   1411 	int fd, door_id;
   1412 	struct stat buf;
   1413 	door_arg_t darg;
   1414 
   1415 	isnslog(LOG_DEBUG, "setup_mgmt_door", "entered");
   1416 	/* check if a door is already running. */
   1417 	if ((fd = open(ISNS_DOOR_NAME, 0)) >= 0) {
   1418 		darg.data_ptr = "<?xml version='1.0' encoding='UTF-8'?>"
   1419 				"<isnsRequest><get><isnsObject>"
   1420 				"<DiscoveryDomain name=\"default\">"
   1421 				"</DiscoveryDomain></isnsObject></get>"
   1422 				"</isnsRequest>";
   1423 		darg.data_size = xmlStrlen((xmlChar *)darg.data_ptr) + 1;
   1424 		darg.desc_ptr = NULL;
   1425 		darg.desc_num = 0;
   1426 		darg.rbuf = NULL;
   1427 		darg.rsize = 0;
   1428 
   1429 		if (door_call(fd, &darg) == 0) {
   1430 			/* door already running. */
   1431 			(void) close(fd);
   1432 			isnslog(LOG_DEBUG, "setup_mgmt_door",
   1433 			    "management door is already runninng.");
   1434 			if (darg.rsize > darg.data_size) {
   1435 			    (void) munmap(darg.rbuf, darg.rsize);
   1436 			}
   1437 			door_created = B_FALSE;
   1438 			return (0);
   1439 		}
   1440 		(void) close(fd);
   1441 	}
   1442 
   1443 	if ((door_id = door_create(door_server, (void *)sys_q, 0)) < 0) {
   1444 		isnslog(LOG_DEBUG, "setup_mgmt_door",
   1445 			"Failed to create managment door");
   1446 		exit(1);
   1447 	}
   1448 
   1449 	if (stat(ISNS_DOOR_NAME, &buf) < 0) {
   1450 	    if ((fd = creat(ISNS_DOOR_NAME, 0666)) < 0) {
   1451 		isnslog(LOG_DEBUG, "setup_mgmt_door",
   1452 		    "open failed on %s errno = %d", ISNS_DOOR_NAME, errno);
   1453 		exit(1);
   1454 	    }
   1455 	    (void) close(fd);
   1456 	}
   1457 
   1458 	/* make sure the file permission set to general access. */
   1459 	(void) chmod(ISNS_DOOR_NAME, 0666);
   1460 	(void) fdetach(ISNS_DOOR_NAME);
   1461 
   1462 	if (fattach(door_id, ISNS_DOOR_NAME) < 0) {
   1463 		syslog(LOG_DEBUG, "setup_mgmt_door",
   1464 		    "fattach failed on %s errno=%d",
   1465 		    ISNS_DOOR_NAME, errno);
   1466 		return (-1);
   1467 	}
   1468 
   1469 	door_created = B_TRUE;
   1470 
   1471 	return (0);
   1472 }
   1473