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