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