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