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