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