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