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