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
get_op_id_from_doc(xmlXPathContextPtr ctext)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
process_get_request_from_doc(xmlXPathContextPtr ctext,request_t * req)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
process_enumerate_request_from_doc(xmlXPathContextPtr ctext,request_t * req)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
process_getAssociated_request_from_doc(xmlXPathContextPtr ctext,request_t * req)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
process_delete_request_from_doc(xmlXPathContextPtr ctext,request_t * req)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
process_createModify_request_from_doc(xmlXPathContextPtr ctext,request_t * req)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
process_mgmt_request(xmlDocPtr x_doc,request_t * req,ucred_t * uc)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
build_mgmt_response(xmlChar ** response,request_t req,int * size)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
build_result_message(xmlChar ** response,result_code_t code,int * size)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
cleanup_request(request_t req)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 */
match_entry(pthread_t tid)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
add_entry(pthread_t tid,xmlChar * doc)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
door_server(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_desc)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
setup_mgmt_door(msg_queue_t * sys_q)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