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