1/*
2 * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 *    1. Redistributions of source code must retain the above copyright notice,
8 *       this list of conditions and the following disclaimer.
9 *
10 *    2. Redistributions in binary form must reproduce the above copyright notice,
11 *       this list of conditions and the following disclaimer in the documentation
12 *       and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * The views and conclusions contained in the software and documentation are those
26 * of the authors and should not be interpreted as representing official policies,
27 * either expressed or implied, of Tresys Technology, LLC.
28 */
29
30#include <stdio.h>
31#include <stdarg.h>
32#include <inttypes.h>
33
34#include <sepol/policydb/conditional.h>
35
36#include "cil_internal.h"
37#include "cil_flavor.h"
38#include "cil_log.h"
39#include "cil_tree.h"
40#include "cil_list.h"
41#include "cil_parser.h"
42#include "cil_strpool.h"
43
44void cil_tree_print_perms_list(struct cil_tree_node *current_perm);
45void cil_tree_print_classperms(struct cil_classperms *cp);
46void cil_tree_print_level(struct cil_level *level);
47void cil_tree_print_levelrange(struct cil_levelrange *lvlrange);
48void cil_tree_print_context(struct cil_context *context);
49void cil_tree_print_expr_tree(struct cil_tree_node *expr_root);
50void cil_tree_print_constrain(struct cil_constrain *cons);
51void cil_tree_print_node(struct cil_tree_node *node);
52
53__attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_error(const char* msg, ...)
54{
55	va_list ap;
56	va_start(ap, msg);
57	cil_vlog(CIL_ERR, msg, ap);
58	va_end(ap);
59	exit(1);
60}
61
62struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil)
63{
64	if (!node) {
65		return NULL;
66	}
67
68	node = node->parent;
69
70	while (node) {
71		if (node->flavor == CIL_NODE && node->data == NULL) {
72			if (node->cl_head->data == CIL_KEY_SRC_INFO) {
73				/* Parse Tree */
74				*path = node->cl_head->next->next->data;
75				*is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL);
76				return node;
77			}
78			node = node->parent;
79		} else if (node->flavor == CIL_SRC_INFO) {
80				/* AST */
81				struct cil_src_info *info = node->data;
82				*path = info->path;
83				*is_cil = info->is_cil;
84				return node;
85		} else {
86			if (node->flavor == CIL_CALL) {
87				struct cil_call *call = node->data;
88				node = NODE(call->macro);
89			} else if (node->flavor == CIL_BLOCKINHERIT) {
90				struct cil_blockinherit *inherit = node->data;
91				node = NODE(inherit->block);
92			} else {
93				node = node->parent;
94			}
95		}
96	}
97
98	return NULL;
99}
100
101char *cil_tree_get_cil_path(struct cil_tree_node *node)
102{
103	char *path = NULL;
104	int is_cil;
105
106	while (node) {
107		node = cil_tree_get_next_path(node, &path, &is_cil);
108		if (node && is_cil) {
109			return path;
110		}
111	}
112
113	return NULL;
114}
115
116__attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...)
117{
118	va_list ap;
119
120	va_start(ap, msg);
121	cil_vlog(lvl, msg, ap);
122	va_end(ap);
123
124	if (node) {
125		char *path = NULL;
126		int is_cil;
127		unsigned hll_line = node->hll_line;
128
129		path = cil_tree_get_cil_path(node);
130
131		if (path != NULL) {
132			cil_log(lvl, " at %s:%d", path, node->line);
133		}
134
135		while (node) {
136			node = cil_tree_get_next_path(node, &path, &is_cil);
137			if (node && !is_cil) {
138				cil_log(lvl," from %s:%d", path, hll_line);
139				path = NULL;
140				hll_line = node->hll_line;
141			}
142		}
143	}
144
145	cil_log(lvl,"\n");
146}
147
148int cil_tree_init(struct cil_tree **tree)
149{
150	struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree));
151
152	cil_tree_node_init(&new_tree->root);
153
154	*tree = new_tree;
155
156	return SEPOL_OK;
157}
158
159void cil_tree_destroy(struct cil_tree **tree)
160{
161	if (tree == NULL || *tree == NULL) {
162		return;
163	}
164
165	cil_tree_subtree_destroy((*tree)->root);
166	free(*tree);
167	*tree = NULL;
168}
169
170void cil_tree_subtree_destroy(struct cil_tree_node *node)
171{
172	cil_tree_children_destroy(node);
173	cil_tree_node_destroy(&node);
174}
175
176void cil_tree_children_destroy(struct cil_tree_node *node)
177{
178	struct cil_tree_node *start_node = node;
179	struct cil_tree_node *next = NULL;
180
181	if (node == NULL) {
182		return;
183	}
184
185	if (node->cl_head != NULL) {
186		node = node->cl_head;
187	}
188
189	while (node != start_node) {
190		if (node->cl_head != NULL){
191			next = node->cl_head;
192		} else {
193			if (node->next == NULL) {
194				next = node->parent;
195				if (node->parent != NULL) {
196					node->parent->cl_head = NULL;
197				}
198				cil_tree_node_destroy(&node);
199			} else {
200				next = node->next;
201				cil_tree_node_destroy(&node);
202			}
203		}
204		node = next;
205	}
206}
207
208void cil_tree_node_init(struct cil_tree_node **node)
209{
210	struct cil_tree_node *new_node = cil_malloc(sizeof(*new_node));
211	new_node->cl_head = NULL;
212	new_node->cl_tail = NULL;
213	new_node->parent = NULL;
214	new_node->data = NULL;
215	new_node->next = NULL;
216	new_node->flavor = CIL_ROOT;
217	new_node->line = 0;
218	new_node->hll_line = 0;
219
220	*node = new_node;
221}
222
223void cil_tree_node_destroy(struct cil_tree_node **node)
224{
225	struct cil_symtab_datum *datum;
226
227	if (node == NULL || *node == NULL) {
228		return;
229	}
230
231	if ((*node)->flavor >= CIL_MIN_DECLARATIVE) {
232		datum = (*node)->data;
233		cil_symtab_datum_remove_node(datum, *node);
234		if (datum->nodes == NULL) {
235			cil_destroy_data(&(*node)->data, (*node)->flavor);
236		}
237	} else {
238		cil_destroy_data(&(*node)->data, (*node)->flavor);
239	}
240	free(*node);
241	*node = NULL;
242}
243
244/* Perform depth-first walk of the tree
245   Parameters:
246   start_node:          root node to start walking from
247   process_node:        function to call when visiting a node
248                        Takes parameters:
249                            node:     node being visited
250                            finished: boolean indicating to the tree walker that it should move on from this branch
251                            extra_args:    additional data
252   first_child:		Function to call before entering list of children
253                        Takes parameters:
254                            node:     node of first child
255                            extra args:     additional data
256   last_child:		Function to call when finished with the last child of a node's children
257   extra_args:               any additional data to be passed to the helper functions
258*/
259
260int cil_tree_walk_core(struct cil_tree_node *node,
261					   int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args),
262					   int (*first_child)(struct cil_tree_node *node, void *extra_args),
263					   int (*last_child)(struct cil_tree_node *node, void *extra_args),
264					   void *extra_args)
265{
266	int rc = SEPOL_ERR;
267
268	while (node) {
269		uint32_t finished = CIL_TREE_SKIP_NOTHING;
270
271		if (process_node != NULL) {
272			rc = (*process_node)(node, &finished, extra_args);
273			if (rc != SEPOL_OK) {
274				cil_tree_log(node, CIL_INFO, "Problem");
275				return rc;
276			}
277		}
278
279		if (finished & CIL_TREE_SKIP_NEXT) {
280			return SEPOL_OK;
281		}
282
283		if (node->cl_head != NULL && !(finished & CIL_TREE_SKIP_HEAD)) {
284			rc = cil_tree_walk(node, process_node, first_child, last_child, extra_args);
285			if (rc != SEPOL_OK) {
286				return rc;
287			}
288		}
289
290		node = node->next;
291	}
292
293	return SEPOL_OK;
294}
295
296int cil_tree_walk(struct cil_tree_node *node,
297				  int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args),
298				  int (*first_child)(struct cil_tree_node *node, void *extra_args),
299				  int (*last_child)(struct cil_tree_node *node, void *extra_args),
300				  void *extra_args)
301{
302	int rc = SEPOL_ERR;
303
304	if (!node || !node->cl_head) {
305		return SEPOL_OK;
306	}
307
308	if (first_child != NULL) {
309		rc = (*first_child)(node->cl_head, extra_args);
310		if (rc != SEPOL_OK) {
311			cil_tree_log(node, CIL_INFO, "Problem");
312			return rc;
313		}
314	}
315
316	rc = cil_tree_walk_core(node->cl_head, process_node, first_child, last_child, extra_args);
317	if (rc != SEPOL_OK) {
318		return rc;
319	}
320
321	if (last_child != NULL) {
322		rc = (*last_child)(node->cl_tail, extra_args);
323		if (rc != SEPOL_OK) {
324			cil_tree_log(node, CIL_INFO, "Problem");
325			return rc;
326		}
327	}
328
329	return SEPOL_OK;
330}
331
332
333/* Copied from cil_policy.c, but changed to prefix -- Need to refactor */
334static int cil_expr_to_string(struct cil_list *expr, char **out)
335{
336	int rc = SEPOL_ERR;
337	struct cil_list_item *curr;
338	char *stack[COND_EXPR_MAXDEPTH] = {};
339	int pos = 0;
340
341	cil_list_for_each(curr, expr) {
342		if (pos > COND_EXPR_MAXDEPTH) {
343			rc = SEPOL_ERR;
344			goto exit;
345		}
346		switch (curr->flavor) {
347		case CIL_LIST:
348			rc = cil_expr_to_string(curr->data, &stack[pos]);
349			if (rc != SEPOL_OK) {
350				goto exit;
351			}
352			pos++;
353			break;
354		case CIL_STRING:
355			stack[pos] = curr->data;
356			pos++;
357			break;
358		case CIL_DATUM:
359			stack[pos] = ((struct cil_symtab_datum *)curr->data)->name;
360			pos++;
361			break;
362		case CIL_OP: {
363			int len;
364			char *expr_str;
365			enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data);
366			char *op_str = NULL;
367
368			if (pos == 0) {
369				rc = SEPOL_ERR;
370				goto exit;
371			}
372			switch (op_flavor) {
373			case CIL_AND:
374				op_str = CIL_KEY_AND;
375				break;
376			case CIL_OR:
377				op_str = CIL_KEY_OR;
378				break;
379			case CIL_NOT:
380				op_str = CIL_KEY_NOT;
381				break;
382			case CIL_ALL:
383				op_str = CIL_KEY_ALL;
384				break;
385			case CIL_EQ:
386				op_str = CIL_KEY_EQ;
387				break;
388			case CIL_NEQ:
389				op_str = CIL_KEY_NEQ;
390				break;
391			case CIL_XOR:
392				op_str = CIL_KEY_XOR;
393				break;
394			case CIL_RANGE:
395				op_str = CIL_KEY_RANGE;
396				break;
397			case CIL_CONS_DOM:
398				op_str = CIL_KEY_CONS_DOM;
399				break;
400			case CIL_CONS_DOMBY:
401				op_str = CIL_KEY_CONS_DOMBY;
402				break;
403			case CIL_CONS_INCOMP:
404				op_str = CIL_KEY_CONS_INCOMP;
405				break;
406			default:
407				cil_log(CIL_ERR, "Unknown operator in expression\n");
408				goto exit;
409				break;
410			}
411			if (op_flavor == CIL_NOT) {
412				len = strlen(stack[pos-1]) + strlen(op_str) + 4;
413				expr_str = cil_malloc(len);
414				snprintf(expr_str, len, "(%s %s)", op_str, stack[pos-1]);
415				free(stack[pos-1]);
416				stack[pos-1] = NULL;
417				pos--;
418			} else {
419				if (pos < 2) {
420					rc = SEPOL_ERR;
421					goto exit;
422				}
423				len = strlen(stack[pos-1]) + strlen(stack[pos-2]) + strlen(op_str) + 5;
424				expr_str = cil_malloc(len);
425				snprintf(expr_str, len, "(%s %s %s)", op_str, stack[pos-1], stack[pos-2]);
426				free(stack[pos-2]);
427				free(stack[pos-1]);
428				stack[pos-2] = NULL;
429				stack[pos-1] = NULL;
430				pos -= 2;
431			}
432			stack[pos] = expr_str;
433			pos++;
434			break;
435		}
436		case CIL_CONS_OPERAND: {
437			enum cil_flavor operand_flavor = *((enum cil_flavor *)curr->data);
438			char *operand_str = NULL;
439			switch (operand_flavor) {
440			case CIL_CONS_U1:
441				operand_str = CIL_KEY_CONS_U1;
442				break;
443			case CIL_CONS_U2:
444				operand_str = CIL_KEY_CONS_U2;
445				break;
446			case CIL_CONS_U3:
447				operand_str = CIL_KEY_CONS_U3;
448				break;
449			case CIL_CONS_T1:
450				operand_str = CIL_KEY_CONS_T1;
451				break;
452			case CIL_CONS_T2:
453				operand_str = CIL_KEY_CONS_T2;
454				break;
455			case CIL_CONS_T3:
456				operand_str = CIL_KEY_CONS_T3;
457				break;
458			case CIL_CONS_R1:
459				operand_str = CIL_KEY_CONS_R1;
460				break;
461			case CIL_CONS_R2:
462				operand_str = CIL_KEY_CONS_R2;
463				break;
464			case CIL_CONS_R3:
465				operand_str = CIL_KEY_CONS_R3;
466				break;
467			case CIL_CONS_L1:
468				operand_str = CIL_KEY_CONS_L1;
469				break;
470			case CIL_CONS_L2:
471				operand_str = CIL_KEY_CONS_L2;
472				break;
473			case CIL_CONS_H1:
474				operand_str = CIL_KEY_CONS_H1;
475				break;
476			case CIL_CONS_H2:
477				operand_str = CIL_KEY_CONS_H2;
478				break;
479			default:
480				cil_log(CIL_ERR, "Unknown operand in expression\n");
481				goto exit;
482				break;
483			}
484			stack[pos] = operand_str;
485			pos++;
486			break;
487		}
488		default:
489			cil_log(CIL_ERR, "Unknown flavor in expression\n");
490			goto exit;
491			break;
492		}
493	}
494
495	*out = stack[0];
496
497	return SEPOL_OK;
498
499exit:
500	return rc;
501}
502
503void cil_tree_print_expr(struct cil_list *datum_expr, struct cil_list *str_expr)
504{
505	char *expr_str;
506
507	cil_log(CIL_INFO, "(");
508
509	if (datum_expr != NULL) {
510		cil_expr_to_string(datum_expr, &expr_str);
511	} else {
512		cil_expr_to_string(str_expr, &expr_str);
513	}
514
515	cil_log(CIL_INFO, "%s)", expr_str);
516	free(expr_str);
517}
518
519void cil_tree_print_perms_list(struct cil_tree_node *current_perm)
520{
521	while (current_perm != NULL) {
522		if (current_perm->flavor == CIL_PERM) {
523			cil_log(CIL_INFO, " %s", ((struct cil_perm *)current_perm->data)->datum.name);
524		} else if (current_perm->flavor == CIL_MAP_PERM) {
525			cil_log(CIL_INFO, " %s", ((struct cil_perm*)current_perm->data)->datum.name);
526		} else {
527			cil_log(CIL_INFO, "\n\n perms list contained unexpected data type: %d\n", current_perm->flavor);
528			break;
529		}
530		current_perm = current_perm->next;
531	}
532}
533
534void cil_tree_print_cats(struct cil_cats *cats)
535{
536	cil_tree_print_expr(cats->datum_expr, cats->str_expr);
537}
538
539void cil_tree_print_perm_strs(struct cil_list *perm_strs)
540{
541	struct cil_list_item *curr;
542
543	if (perm_strs == NULL) {
544		return;
545	}
546
547	cil_log(CIL_INFO, " (");
548
549	cil_list_for_each(curr, perm_strs) {
550		cil_log(CIL_INFO, " %s", (char*)curr->data);
551	}
552
553	cil_log(CIL_INFO, " )");
554}
555
556
557void cil_tree_print_classperms(struct cil_classperms *cp)
558{
559	if (cp == NULL) {
560		return;
561	}
562
563	cil_log(CIL_INFO, " class: %s", cp->class_str);
564	cil_log(CIL_INFO, ", perm_strs:");
565	cil_tree_print_perm_strs(cp->perm_strs);
566}
567
568void cil_tree_print_classperms_set(struct cil_classperms_set *cp_set)
569{
570	if (cp_set == NULL) {
571		return;
572	}
573
574	cil_log(CIL_INFO, " %s", cp_set->set_str);
575}
576
577void cil_tree_print_classperms_list(struct cil_list *cp_list)
578{
579	struct cil_list_item *i;
580
581	if (cp_list == NULL) {
582		return;
583	}
584
585	cil_list_for_each(i, cp_list) {
586		if (i->flavor == CIL_CLASSPERMS) {
587			cil_tree_print_classperms(i->data);
588		} else {
589			cil_tree_print_classperms_set(i->data);
590		}
591	}
592}
593
594void cil_tree_print_level(struct cil_level *level)
595{
596	if (level->sens != NULL) {
597		cil_log(CIL_INFO, " %s", level->sens->datum.name);
598	} else if (level->sens_str != NULL) {
599		cil_log(CIL_INFO, " %s", level->sens_str);
600	}
601
602	cil_tree_print_cats(level->cats);
603
604	return;
605}
606
607void cil_tree_print_levelrange(struct cil_levelrange *lvlrange)
608{
609	cil_log(CIL_INFO, " (");
610	if (lvlrange->low != NULL) {
611		cil_log(CIL_INFO, " (");
612		cil_tree_print_level(lvlrange->low);
613		cil_log(CIL_INFO, " )");
614	} else if (lvlrange->low_str != NULL) {
615		cil_log(CIL_INFO, " %s", lvlrange->low_str);
616	}
617
618	if (lvlrange->high != NULL) {
619		cil_log(CIL_INFO, " (");
620		cil_tree_print_level(lvlrange->high);
621		cil_log(CIL_INFO, " )");
622	} else if (lvlrange->high_str != NULL) {
623		cil_log(CIL_INFO, " %s", lvlrange->high_str);
624	}
625	cil_log(CIL_INFO, " )");
626}
627
628void cil_tree_print_context(struct cil_context *context)
629{
630	cil_log(CIL_INFO, " (");
631	if (context->user != NULL) {
632		cil_log(CIL_INFO, " %s", context->user->datum.name);
633	} else if (context->user_str != NULL) {
634		cil_log(CIL_INFO, " %s", context->user_str);
635	}
636
637	if (context->role != NULL) {
638		cil_log(CIL_INFO, " %s", context->role->datum.name);
639	} else if (context->role_str != NULL) {
640		cil_log(CIL_INFO, " %s", context->role_str);
641	}
642
643	if (context->type != NULL) {
644		cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)context->type)->name);
645	} else if (context->type_str != NULL) {
646		cil_log(CIL_INFO, " %s", context->type_str);
647	}
648
649	if (context->range != NULL) {
650		cil_tree_print_levelrange(context->range);
651	} else if (context->range_str != NULL) {
652		cil_log(CIL_INFO, " %s", context->range_str);
653	}
654
655	cil_log(CIL_INFO, " )");
656
657	return;
658}
659
660void cil_tree_print_constrain(struct cil_constrain *cons)
661{
662	cil_tree_print_classperms_list(cons->classperms);
663
664	cil_tree_print_expr(cons->datum_expr, cons->str_expr);
665
666	cil_log(CIL_INFO, "\n");
667}
668
669void cil_tree_print_node(struct cil_tree_node *node)
670{
671	if (node->data == NULL) {
672		cil_log(CIL_INFO, "FLAVOR: %d", node->flavor);
673		return;
674	} else {
675		switch( node->flavor ) {
676		case CIL_BLOCK: {
677			struct cil_block *block = node->data;
678			cil_log(CIL_INFO, "BLOCK: %s\n", block->datum.name);
679			return;
680		}
681		case CIL_BLOCKINHERIT: {
682			struct cil_blockinherit *inherit = node->data;
683			cil_log(CIL_INFO, "BLOCKINHERIT: %s\n", inherit->block_str);
684			return;
685		}
686		case CIL_BLOCKABSTRACT: {
687			struct cil_blockabstract *abstract = node->data;
688			cil_log(CIL_INFO, "BLOCKABSTRACT: %s\n", abstract->block_str);
689			return;
690		}
691		case CIL_IN: {
692			struct cil_in *in = node->data;
693			cil_log(CIL_INFO, "IN: %s\n", in->block_str);
694			return;
695		}
696		case CIL_USER: {
697			struct cil_user *user = node->data;
698			cil_log(CIL_INFO, "USER: %s\n", user->datum.name);
699			return;
700		}
701		case CIL_TYPE: {
702			struct cil_type *type = node->data;
703			cil_log(CIL_INFO, "TYPE: %s\n", type->datum.name);
704			return;
705		}
706		case CIL_EXPANDTYPEATTRIBUTE: {
707			struct cil_expandtypeattribute *attr = node->data;
708
709			fprintf(stderr, "%s %u\n", __func__, __LINE__);
710			cil_log(CIL_INFO, "(EXPANDTYPEATTRIBUTE ");
711			cil_tree_print_expr(attr->attr_datums, attr->attr_strs);
712			cil_log(CIL_INFO, "%s)\n",attr->expand ?
713					CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE);
714
715			return;
716		}
717		case CIL_TYPEATTRIBUTESET: {
718			struct cil_typeattributeset *attr = node->data;
719
720			cil_log(CIL_INFO, "(TYPEATTRIBUTESET %s ", attr->attr_str);
721
722			cil_tree_print_expr(attr->datum_expr, attr->str_expr);
723
724			cil_log(CIL_INFO, "\n");
725			return;
726		}
727		case CIL_TYPEATTRIBUTE: {
728			struct cil_typeattribute *attr = node->data;
729			cil_log(CIL_INFO, "TYPEATTRIBUTE: %s\n", attr->datum.name);
730			return;
731		}
732		case CIL_ROLE: {
733			struct cil_role *role = node->data;
734			cil_log(CIL_INFO, "ROLE: %s\n", role->datum.name);
735			return;
736		}
737		case CIL_USERROLE: {
738			struct cil_userrole *userrole = node->data;
739			cil_log(CIL_INFO, "USERROLE:");
740			struct cil_symtab_datum *datum = NULL;
741
742			if (userrole->user != NULL) {
743				datum = userrole->user;
744				cil_log(CIL_INFO, " %s", datum->name);
745			} else if (userrole->user_str != NULL) {
746				cil_log(CIL_INFO, " %s", userrole->user_str);
747			}
748
749			if (userrole->role != NULL) {
750				datum = userrole->role;
751				cil_log(CIL_INFO, " %s", datum->name);
752			} else if (userrole->role_str != NULL) {
753				cil_log(CIL_INFO, " %s", userrole->role_str);
754			}
755
756			cil_log(CIL_INFO, "\n");
757			return;
758		}
759		case CIL_USERLEVEL: {
760			struct cil_userlevel *usrlvl = node->data;
761			cil_log(CIL_INFO, "USERLEVEL:");
762
763			if (usrlvl->user_str != NULL) {
764				cil_log(CIL_INFO, " %s", usrlvl->user_str);
765			}
766
767			if (usrlvl->level != NULL) {
768				cil_log(CIL_INFO, " (");
769				cil_tree_print_level(usrlvl->level);
770				cil_log(CIL_INFO, " )");
771			} else if (usrlvl->level_str != NULL) {
772				cil_log(CIL_INFO, " %s", usrlvl->level_str);
773			}
774
775			cil_log(CIL_INFO, "\n");
776			return;
777		}
778		case CIL_USERRANGE: {
779			struct cil_userrange *userrange = node->data;
780			cil_log(CIL_INFO, "USERRANGE:");
781
782			if (userrange->user_str != NULL) {
783				cil_log(CIL_INFO, " %s", userrange->user_str);
784			}
785
786			if (userrange->range != NULL) {
787				cil_log(CIL_INFO, " (");
788				cil_tree_print_levelrange(userrange->range);
789				cil_log(CIL_INFO, " )");
790			} else if (userrange->range_str != NULL) {
791				cil_log(CIL_INFO, " %s", userrange->range_str);
792			}
793
794			cil_log(CIL_INFO, "\n");
795			return;
796		}
797		case CIL_USERBOUNDS: {
798			struct cil_bounds *bnds = node->data;
799			cil_log(CIL_INFO, "USERBOUNDS: user: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
800			return;
801		}
802		case CIL_ROLETYPE: {
803			struct cil_roletype *roletype = node->data;
804			struct cil_symtab_datum *datum = NULL;
805			cil_log(CIL_INFO, "ROLETYPE:");
806
807			if (roletype->role != NULL) {
808				datum = roletype->role;
809				cil_log(CIL_INFO, " %s", datum->name);
810			} else if (roletype->role_str != NULL) {
811				cil_log(CIL_INFO, " %s", roletype->role_str);
812			}
813
814			if (roletype->type != NULL) {
815				datum = roletype->type;
816				cil_log(CIL_INFO, " %s", datum->name);
817			} else if (roletype->type_str != NULL) {
818				cil_log(CIL_INFO, " %s", roletype->type_str);
819			}
820
821			cil_log(CIL_INFO, "\n");
822			return;
823		}
824		case CIL_ROLETRANSITION: {
825			struct cil_roletransition *roletrans = node->data;
826			cil_log(CIL_INFO, "ROLETRANSITION:");
827
828			if (roletrans->src != NULL) {
829				cil_log(CIL_INFO, " %s", roletrans->src->datum.name);
830			} else {
831				cil_log(CIL_INFO, " %s", roletrans->src_str);
832			}
833
834			if (roletrans->tgt != NULL) {
835				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)roletrans->tgt)->name);
836			} else {
837				cil_log(CIL_INFO, " %s", roletrans->tgt_str);
838			}
839
840			if (roletrans->obj != NULL) {
841				cil_log(CIL_INFO, " %s", roletrans->obj->datum.name);
842			} else {
843				cil_log(CIL_INFO, " %s", roletrans->obj_str);
844			}
845
846			if (roletrans->result != NULL) {
847				cil_log(CIL_INFO, " %s\n", roletrans->result->datum.name);
848			} else {
849				cil_log(CIL_INFO, " %s\n", roletrans->result_str);
850			}
851
852			return;
853		}
854		case CIL_ROLEALLOW: {
855			struct cil_roleallow *roleallow = node->data;
856			cil_log(CIL_INFO, "ROLEALLOW:");
857
858			if (roleallow->src != NULL) {
859				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->src)->name);
860			} else {
861				cil_log(CIL_INFO, " %s", roleallow->src_str);
862			}
863
864			if (roleallow->tgt != NULL) {
865				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->tgt)->name);
866			} else {
867				cil_log(CIL_INFO, " %s", roleallow->tgt_str);
868			}
869
870			cil_log(CIL_INFO, "\n");
871			return;
872		}
873		case CIL_ROLEATTRIBUTESET: {
874			struct cil_roleattributeset *attr = node->data;
875
876			cil_log(CIL_INFO, "(ROLEATTRIBUTESET %s ", attr->attr_str);
877
878			cil_tree_print_expr(attr->datum_expr, attr->str_expr);
879
880			cil_log(CIL_INFO, "\n");
881			return;
882		}
883		case CIL_ROLEATTRIBUTE: {
884			struct cil_roleattribute *attr = node->data;
885			cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name);
886			return;
887		}
888		case CIL_USERATTRIBUTESET: {
889			struct cil_userattributeset *attr = node->data;
890
891			cil_log(CIL_INFO, "(USERATTRIBUTESET %s ", attr->attr_str);
892
893			cil_tree_print_expr(attr->datum_expr, attr->str_expr);
894
895			cil_log(CIL_INFO, "\n");
896			return;
897		}
898		case CIL_USERATTRIBUTE: {
899			struct cil_userattribute *attr = node->data;
900			cil_log(CIL_INFO, "USERATTRIBUTE: %s\n", attr->datum.name);
901			return;
902		}
903		case CIL_ROLEBOUNDS: {
904			struct cil_bounds *bnds = node->data;
905			cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
906			return;
907		}
908		case CIL_CLASS: {
909			struct cil_class *cls = node->data;
910			cil_log(CIL_INFO, "CLASS: %s ", cls->datum.name);
911
912			if (cls->common != NULL) {
913				cil_log(CIL_INFO, "inherits: %s ", cls->common->datum.name);
914			}
915			cil_log(CIL_INFO, "(");
916
917			cil_tree_print_perms_list(node->cl_head);
918
919			cil_log(CIL_INFO, " )");
920			return;
921		}
922		case CIL_CLASSORDER: {
923			struct cil_classorder *classorder = node->data;
924			struct cil_list_item *class;
925
926			if (classorder->class_list_str == NULL) {
927				cil_log(CIL_INFO, "CLASSORDER: ()\n");
928				return;
929			}
930
931			cil_log(CIL_INFO, "CLASSORDER: (");
932			cil_list_for_each(class, classorder->class_list_str) {
933				cil_log(CIL_INFO, " %s", (char*)class->data);
934			}
935			cil_log(CIL_INFO, " )\n");
936			return;
937		}
938		case CIL_COMMON: {
939			struct cil_class *common = node->data;
940			cil_log(CIL_INFO, "COMMON: %s (", common->datum.name);
941
942			cil_tree_print_perms_list(node->cl_head);
943
944			cil_log(CIL_INFO, " )");
945			return;
946		}
947		case CIL_CLASSCOMMON: {
948			struct cil_classcommon *clscom = node->data;
949
950			cil_log(CIL_INFO, "CLASSCOMMON: class: %s, common: %s\n", clscom->class_str, clscom->common_str);
951
952			return;
953		}
954		case CIL_CLASSPERMISSION: {
955			struct cil_classpermission *cp = node->data;
956
957			cil_log(CIL_INFO, "CLASSPERMISSION: %s", cp->datum.name);
958
959			cil_log(CIL_INFO, "\n");
960
961			return;
962		}
963		case CIL_CLASSPERMISSIONSET: {
964			struct cil_classpermissionset *cps = node->data;
965
966			cil_log(CIL_INFO, "CLASSPERMISSIONSET: %s", cps->set_str);
967
968			cil_tree_print_classperms_list(cps->classperms);
969
970			cil_log(CIL_INFO, "\n");
971
972			return;
973		}
974		case CIL_MAP_CLASS: {
975			struct cil_class *cm = node->data;
976			cil_log(CIL_INFO, "MAP_CLASS: %s", cm->datum.name);
977
978			cil_log(CIL_INFO, " (");
979			cil_tree_print_perms_list(node->cl_head);
980			cil_log(CIL_INFO, " )\n");
981
982			return;
983		}
984		case CIL_MAP_PERM: {
985			struct cil_perm *cmp = node->data;
986
987			cil_log(CIL_INFO, "MAP_PERM: %s", cmp->datum.name);
988
989			if (cmp->classperms == NULL) {
990				cil_log(CIL_INFO, " perms: ()");
991				return;
992			}
993
994			cil_log(CIL_INFO, " kernel class perms: (");
995
996			cil_tree_print_classperms_list(cmp->classperms);
997
998			cil_log(CIL_INFO, " )\n");
999
1000			return;
1001		}
1002		case CIL_CLASSMAPPING: {
1003			struct cil_classmapping *mapping = node->data;
1004
1005			cil_log(CIL_INFO, "CLASSMAPPING: map class: %s, map perm: %s,", mapping->map_class_str, mapping->map_perm_str);
1006
1007			cil_log(CIL_INFO, " (");
1008
1009			cil_tree_print_classperms_list(mapping->classperms);
1010
1011			cil_log(CIL_INFO, " )\n");
1012			return;
1013		}
1014		case CIL_BOOL: {
1015			struct cil_bool *boolean = node->data;
1016			cil_log(CIL_INFO, "BOOL: %s, value: %d\n", boolean->datum.name, boolean->value);
1017			return;
1018		}
1019		case CIL_TUNABLE: {
1020			struct cil_tunable *tunable = node->data;
1021			cil_log(CIL_INFO, "TUNABLE: %s, value: %d\n", tunable->datum.name, tunable->value);
1022			return;
1023		}
1024		case CIL_BOOLEANIF: {
1025			struct cil_booleanif *bif = node->data;
1026
1027			cil_log(CIL_INFO, "(BOOLEANIF ");
1028
1029			cil_tree_print_expr(bif->datum_expr, bif->str_expr);
1030
1031			cil_log(CIL_INFO, " )\n");
1032			return;
1033		}
1034		case CIL_TUNABLEIF: {
1035			struct cil_tunableif *tif = node->data;
1036
1037			cil_log(CIL_INFO, "(TUNABLEIF ");
1038
1039			cil_tree_print_expr(tif->datum_expr, tif->str_expr);
1040
1041			cil_log(CIL_INFO, " )\n");
1042			return;
1043		}
1044		case CIL_CONDBLOCK: {
1045			struct cil_condblock *cb = node->data;
1046			if (cb->flavor == CIL_CONDTRUE) {
1047				cil_log(CIL_INFO, "true\n");
1048			} else if (cb->flavor == CIL_CONDFALSE) {
1049				cil_log(CIL_INFO, "false\n");
1050			}
1051			return;
1052		}
1053		case CIL_ALL:
1054			cil_log(CIL_INFO, "all");
1055			return;
1056		case CIL_AND:
1057			cil_log(CIL_INFO, "&&");
1058			return;
1059		case CIL_OR:
1060			cil_log(CIL_INFO, "|| ");
1061			return;
1062		case CIL_NOT:
1063			cil_log(CIL_INFO, "!");
1064			return;
1065		case CIL_EQ:
1066			cil_log(CIL_INFO, "==");
1067			return;
1068		case CIL_NEQ:
1069			cil_log(CIL_INFO, "!=");
1070			return;
1071		case CIL_TYPEALIAS: {
1072			struct cil_alias *alias = node->data;
1073			cil_log(CIL_INFO, "TYPEALIAS: %s\n", alias->datum.name);
1074			return;
1075		}
1076		case CIL_TYPEALIASACTUAL: {
1077			struct cil_aliasactual *aliasactual = node->data;
1078			cil_log(CIL_INFO, "TYPEALIASACTUAL: type: %s, alias: %s\n", aliasactual->alias_str, aliasactual->actual_str);
1079			return;
1080		}
1081		case CIL_TYPEBOUNDS: {
1082			struct cil_bounds *bnds = node->data;
1083			cil_log(CIL_INFO, "TYPEBOUNDS: type: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
1084			return;
1085		}
1086		case CIL_TYPEPERMISSIVE: {
1087			struct cil_typepermissive *typeperm = node->data;
1088
1089			if (typeperm->type != NULL) {
1090				cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", ((struct cil_symtab_datum *)typeperm->type)->name);
1091			} else {
1092				cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", typeperm->type_str);
1093			}
1094
1095			return;
1096		}
1097		case CIL_NAMETYPETRANSITION: {
1098			struct cil_nametypetransition *nametypetrans = node->data;
1099			cil_log(CIL_INFO, "TYPETRANSITION:");
1100
1101			if (nametypetrans->src != NULL) {
1102				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->src)->name);
1103			} else {
1104				cil_log(CIL_INFO, " %s", nametypetrans->src_str);
1105			}
1106
1107			if (nametypetrans->tgt != NULL) {
1108				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->tgt)->name);
1109			} else {
1110				cil_log(CIL_INFO, " %s", nametypetrans->tgt_str);
1111			}
1112
1113			if (nametypetrans->obj != NULL) {
1114				cil_log(CIL_INFO, " %s", nametypetrans->obj->datum.name);
1115			} else {
1116				cil_log(CIL_INFO, " %s", nametypetrans->obj_str);
1117			}
1118
1119			cil_log(CIL_INFO, " %s\n", nametypetrans->name_str);
1120
1121			if (nametypetrans->result != NULL) {
1122				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->result)->name);
1123			} else {
1124				cil_log(CIL_INFO, " %s", nametypetrans->result_str);
1125			}
1126
1127			return;
1128		}
1129		case CIL_RANGETRANSITION: {
1130			struct cil_rangetransition *rangetrans = node->data;
1131			cil_log(CIL_INFO, "RANGETRANSITION:");
1132
1133			if (rangetrans->src != NULL) {
1134				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->src)->name);
1135			} else {
1136				cil_log(CIL_INFO, " %s", rangetrans->src_str);
1137			}
1138
1139			if (rangetrans->exec != NULL) {
1140				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->exec)->name);
1141			} else {
1142				cil_log(CIL_INFO, " %s", rangetrans->exec_str);
1143			}
1144
1145			if (rangetrans->obj != NULL) {
1146				cil_log(CIL_INFO, " %s", rangetrans->obj->datum.name);
1147			} else {
1148				cil_log(CIL_INFO, " %s", rangetrans->obj_str);
1149			}
1150
1151			if (rangetrans->range != NULL) {
1152				cil_log(CIL_INFO, " (");
1153				cil_tree_print_levelrange(rangetrans->range);
1154				cil_log(CIL_INFO, " )");
1155			} else {
1156				cil_log(CIL_INFO, " %s", rangetrans->range_str);
1157			}
1158
1159			cil_log(CIL_INFO, "\n");
1160			return;
1161		}
1162		case CIL_AVRULE: {
1163			struct cil_avrule *rule = node->data;
1164			switch (rule->rule_kind) {
1165			case CIL_AVRULE_ALLOWED:
1166				cil_log(CIL_INFO, "ALLOW:");
1167				break;
1168			case CIL_AVRULE_AUDITALLOW:
1169				cil_log(CIL_INFO, "AUDITALLOW:");
1170				break;
1171			case CIL_AVRULE_DONTAUDIT:
1172				cil_log(CIL_INFO, "DONTAUDIT:");
1173				break;
1174			case CIL_AVRULE_NEVERALLOW:
1175				cil_log(CIL_INFO, "NEVERALLOW:");
1176				break;
1177			}
1178
1179			if (rule->src != NULL) {
1180				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->src)->name);
1181			} else {
1182				cil_log(CIL_INFO, " %s", rule->src_str);
1183			}
1184
1185			if (rule->tgt != NULL) {
1186				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->tgt)->name);
1187			} else {
1188				cil_log(CIL_INFO, " %s", rule->tgt_str);
1189			}
1190
1191			cil_tree_print_classperms_list(rule->perms.classperms);
1192
1193			cil_log(CIL_INFO, "\n");
1194
1195			return;
1196		}
1197		case CIL_TYPE_RULE: {
1198			struct cil_type_rule *rule = node->data;
1199			switch (rule->rule_kind) {
1200			case CIL_TYPE_TRANSITION:
1201				cil_log(CIL_INFO, "TYPETRANSITION:");
1202				break;
1203			case CIL_TYPE_MEMBER:
1204				cil_log(CIL_INFO, "TYPEMEMBER:");
1205				break;
1206			case CIL_TYPE_CHANGE:
1207				cil_log(CIL_INFO, "TYPECHANGE:");
1208				break;
1209			}
1210
1211			if (rule->src != NULL) {
1212				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->src)->name);
1213			} else {
1214				cil_log(CIL_INFO, " %s", rule->src_str);
1215			}
1216
1217			if (rule->tgt != NULL) {
1218				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->tgt)->name);
1219			} else {
1220				cil_log(CIL_INFO, " %s", rule->tgt_str);
1221			}
1222
1223			if (rule->obj != NULL) {
1224				cil_log(CIL_INFO, " %s", rule->obj->datum.name);
1225			} else {
1226				cil_log(CIL_INFO, " %s", rule->obj_str);
1227			}
1228
1229			if (rule->result != NULL) {
1230				cil_log(CIL_INFO, " %s\n", ((struct cil_symtab_datum *)rule->result)->name);
1231			} else {
1232				cil_log(CIL_INFO, " %s\n", rule->result_str);
1233			}
1234
1235			return;
1236		}
1237		case CIL_SENS: {
1238			struct cil_sens *sens = node->data;
1239			cil_log(CIL_INFO, "SENSITIVITY: %s\n", sens->datum.name);
1240			return;
1241		}
1242		case CIL_SENSALIAS: {
1243			struct cil_alias *alias = node->data;
1244			cil_log(CIL_INFO, "SENSITIVITYALIAS: %s\n", alias->datum.name);
1245			return;
1246		}
1247		case CIL_SENSALIASACTUAL: {
1248			struct cil_aliasactual *aliasactual = node->data;
1249			cil_log(CIL_INFO, "SENSITIVITYALIAS: alias: %s, sensitivity: %s\n", aliasactual->alias_str, aliasactual->actual_str);
1250
1251			return;
1252		}
1253		case CIL_CAT: {
1254			struct cil_cat *cat = node->data;
1255			cil_log(CIL_INFO, "CATEGORY: %s\n", cat->datum.name);
1256			return;
1257		}
1258		case CIL_CATALIAS: {
1259			struct cil_alias *alias = node->data;
1260			cil_log(CIL_INFO, "CATEGORYALIAS: %s\n", alias->datum.name);
1261			return;
1262		}
1263		case CIL_CATALIASACTUAL: {
1264			struct cil_aliasactual *aliasactual = node->data;
1265			cil_log(CIL_INFO, "CATEGORYALIAS: alias %s, category: %s\n", aliasactual->alias_str, aliasactual->actual_str);
1266			return;
1267		}
1268		case CIL_CATSET: {
1269			struct cil_catset *catset = node->data;
1270
1271			cil_log(CIL_INFO, "CATSET: %s ",catset->datum.name);
1272
1273			cil_tree_print_cats(catset->cats);
1274
1275			return;
1276		}
1277		case CIL_CATORDER: {
1278			struct cil_catorder *catorder = node->data;
1279			struct cil_list_item *cat;
1280
1281			if (catorder->cat_list_str == NULL) {
1282				cil_log(CIL_INFO, "CATORDER: ()\n");
1283				return;
1284			}
1285
1286			cil_log(CIL_INFO, "CATORDER: (");
1287			cil_list_for_each(cat, catorder->cat_list_str) {
1288				cil_log(CIL_INFO, " %s", (char*)cat->data);
1289			}
1290			cil_log(CIL_INFO, " )\n");
1291			return;
1292		}
1293		case CIL_SENSCAT: {
1294			struct cil_senscat *senscat = node->data;
1295
1296			cil_log(CIL_INFO, "SENSCAT: sens:");
1297
1298			if (senscat->sens_str != NULL) {
1299				cil_log(CIL_INFO, " %s ", senscat->sens_str);
1300			} else {
1301				cil_log(CIL_INFO, " [processed]");
1302			}
1303
1304			cil_tree_print_cats(senscat->cats);
1305
1306			return;
1307		}
1308		case CIL_SENSITIVITYORDER: {
1309			struct cil_sensorder *sensorder = node->data;
1310			struct cil_list_item *sens;
1311
1312			cil_log(CIL_INFO, "SENSITIVITYORDER: (");
1313
1314			if (sensorder->sens_list_str != NULL) {
1315				cil_list_for_each(sens, sensorder->sens_list_str) {
1316					if (sens->flavor == CIL_LIST) {
1317						struct cil_list_item *sub;
1318						cil_log(CIL_INFO, " (");
1319						cil_list_for_each(sub, (struct cil_list*)sens->data) {
1320							cil_log(CIL_INFO, " %s", (char*)sub->data);
1321						}
1322						cil_log(CIL_INFO, " )");
1323					} else {
1324						cil_log(CIL_INFO, " %s", (char*)sens->data);
1325					}
1326				}
1327			}
1328
1329			cil_log(CIL_INFO, " )\n");
1330			return;
1331		}
1332		case CIL_LEVEL: {
1333			struct cil_level *level = node->data;
1334			cil_log(CIL_INFO, "LEVEL %s:", level->datum.name);
1335			cil_tree_print_level(level);
1336			cil_log(CIL_INFO, "\n");
1337			return;
1338		}
1339		case CIL_LEVELRANGE: {
1340			struct cil_levelrange *lvlrange = node->data;
1341			cil_log(CIL_INFO, "LEVELRANGE %s:", lvlrange->datum.name);
1342			cil_tree_print_levelrange(lvlrange);
1343			cil_log(CIL_INFO, "\n");
1344			return;
1345		}
1346		case CIL_CONSTRAIN: {
1347			struct cil_constrain *cons = node->data;
1348			cil_log(CIL_INFO, "CONSTRAIN: (");
1349			cil_tree_print_constrain(cons);
1350			return;
1351		}
1352		case CIL_MLSCONSTRAIN: {
1353			struct cil_constrain *cons = node->data;
1354			cil_log(CIL_INFO, "MLSCONSTRAIN: (");
1355			cil_tree_print_constrain(cons);
1356			return;
1357		}
1358		case CIL_VALIDATETRANS: {
1359			struct cil_validatetrans *vt = node->data;
1360
1361			cil_log(CIL_INFO, "(VALIDATETRANS ");
1362
1363			if (vt->class != NULL) {
1364				cil_log(CIL_INFO, "%s ", vt->class->datum.name);
1365			} else if (vt->class_str != NULL) {
1366				cil_log(CIL_INFO, "%s ", vt->class_str);
1367			}
1368
1369			cil_tree_print_expr(vt->datum_expr, vt->str_expr);
1370
1371			cil_log(CIL_INFO, ")\n");
1372			return;
1373		}
1374		case CIL_MLSVALIDATETRANS: {
1375			struct cil_validatetrans *vt = node->data;
1376
1377			cil_log(CIL_INFO, "(MLSVALIDATETRANS ");
1378
1379			if (vt->class != NULL) {
1380				cil_log(CIL_INFO, "%s ", vt->class->datum.name);
1381			} else if (vt->class_str != NULL) {
1382				cil_log(CIL_INFO, "%s ", vt->class_str);
1383			}
1384
1385			cil_tree_print_expr(vt->datum_expr, vt->str_expr);
1386
1387			cil_log(CIL_INFO, ")\n");
1388			return;
1389		}
1390		case CIL_CONTEXT: {
1391			struct cil_context *context = node->data;
1392			cil_log(CIL_INFO, "CONTEXT %s:", context->datum.name);
1393			cil_tree_print_context(context);
1394			cil_log(CIL_INFO, "\n");
1395			return;
1396		}
1397		case CIL_FILECON: {
1398			struct cil_filecon *filecon = node->data;
1399			cil_log(CIL_INFO, "FILECON:");
1400			cil_log(CIL_INFO, " %s %d", filecon->path_str, filecon->type);
1401
1402			if (filecon->context != NULL) {
1403				cil_tree_print_context(filecon->context);
1404			} else if (filecon->context_str != NULL) {
1405				cil_log(CIL_INFO, " %s", filecon->context_str);
1406			}
1407
1408			cil_log(CIL_INFO, "\n");
1409			return;
1410
1411		}
1412		case CIL_PORTCON: {
1413			struct cil_portcon *portcon = node->data;
1414			cil_log(CIL_INFO, "PORTCON:");
1415			if (portcon->proto == CIL_PROTOCOL_UDP) {
1416				cil_log(CIL_INFO, " udp");
1417			} else if (portcon->proto == CIL_PROTOCOL_TCP) {
1418				cil_log(CIL_INFO, " tcp");
1419			} else if (portcon->proto == CIL_PROTOCOL_DCCP) {
1420				cil_log(CIL_INFO, " dccp");
1421			}
1422			cil_log(CIL_INFO, " (%d %d)", portcon->port_low, portcon->port_high);
1423
1424			if (portcon->context != NULL) {
1425				cil_tree_print_context(portcon->context);
1426			} else if (portcon->context_str != NULL) {
1427				cil_log(CIL_INFO, " %s", portcon->context_str);
1428			}
1429
1430			cil_log(CIL_INFO, "\n");
1431			return;
1432		}
1433		case CIL_NODECON: {
1434			struct cil_nodecon *nodecon = node->data;
1435			char buf[256];
1436
1437			cil_log(CIL_INFO, "NODECON:");
1438
1439			if (nodecon->addr) {
1440				inet_ntop(nodecon->addr->family, &nodecon->addr->ip, buf, 256);
1441				cil_log(CIL_INFO, " %s", buf);
1442			}  else {
1443				cil_log(CIL_INFO, " %s", nodecon->addr_str);
1444			}
1445
1446			if (nodecon->mask) {
1447				inet_ntop(nodecon->mask->family, &nodecon->mask->ip, buf, 256);
1448				cil_log(CIL_INFO, " %s", buf);
1449			} else {
1450				cil_log(CIL_INFO, " %s", nodecon->mask_str);
1451			}
1452
1453			if (nodecon->context != NULL) {
1454				cil_tree_print_context(nodecon->context);
1455			} else if (nodecon->context_str != NULL) {
1456				cil_log(CIL_INFO, " %s", nodecon->context_str);
1457			}
1458
1459			cil_log(CIL_INFO, "\n");
1460			return;
1461		}
1462		case CIL_GENFSCON: {
1463			struct cil_genfscon *genfscon = node->data;
1464			cil_log(CIL_INFO, "GENFSCON:");
1465			cil_log(CIL_INFO, " %s %s", genfscon->fs_str, genfscon->path_str);
1466
1467			if (genfscon->context != NULL) {
1468				cil_tree_print_context(genfscon->context);
1469			} else if (genfscon->context_str != NULL) {
1470				cil_log(CIL_INFO, " %s", genfscon->context_str);
1471			}
1472
1473			cil_log(CIL_INFO, "\n");
1474			return;
1475		}
1476		case CIL_NETIFCON: {
1477			struct cil_netifcon *netifcon = node->data;
1478			cil_log(CIL_INFO, "NETIFCON %s", netifcon->interface_str);
1479
1480			if (netifcon->if_context != NULL) {
1481				cil_tree_print_context(netifcon->if_context);
1482			} else if (netifcon->if_context_str != NULL) {
1483				cil_log(CIL_INFO, " %s", netifcon->if_context_str);
1484			}
1485
1486			if (netifcon->packet_context != NULL) {
1487				cil_tree_print_context(netifcon->packet_context);
1488			} else if (netifcon->packet_context_str != NULL) {
1489				cil_log(CIL_INFO, " %s", netifcon->packet_context_str);
1490			}
1491
1492			cil_log(CIL_INFO, "\n");
1493			return;
1494		}
1495		case CIL_PIRQCON: {
1496			struct cil_pirqcon *pirqcon = node->data;
1497
1498			cil_log(CIL_INFO, "PIRQCON %d", pirqcon->pirq);
1499			if (pirqcon->context != NULL) {
1500				cil_tree_print_context(pirqcon->context);
1501			} else {
1502				cil_log(CIL_INFO, " %s", pirqcon->context_str);
1503			}
1504
1505			cil_log(CIL_INFO, "\n");
1506			return;
1507		}
1508		case CIL_IOMEMCON: {
1509			struct cil_iomemcon *iomemcon = node->data;
1510
1511			cil_log(CIL_INFO, "IOMEMCON ( %"PRId64" %"PRId64" )", iomemcon->iomem_low, iomemcon->iomem_high);
1512			if (iomemcon->context != NULL) {
1513				cil_tree_print_context(iomemcon->context);
1514			} else {
1515				cil_log(CIL_INFO, " %s", iomemcon->context_str);
1516			}
1517
1518			cil_log(CIL_INFO, "\n");
1519			return;
1520		}
1521		case CIL_IOPORTCON: {
1522			struct cil_ioportcon *ioportcon = node->data;
1523
1524			cil_log(CIL_INFO, "IOPORTCON ( %d %d )", ioportcon->ioport_low, ioportcon->ioport_high);
1525			if (ioportcon->context != NULL) {
1526				cil_tree_print_context(ioportcon->context);
1527			} else {
1528				cil_log(CIL_INFO, " %s", ioportcon->context_str);
1529			}
1530
1531			cil_log(CIL_INFO, "\n");
1532			return;
1533		}
1534		case CIL_PCIDEVICECON: {
1535			struct cil_pcidevicecon *pcidevicecon = node->data;
1536
1537			cil_log(CIL_INFO, "PCIDEVICECON %d", pcidevicecon->dev);
1538			if (pcidevicecon->context != NULL) {
1539				cil_tree_print_context(pcidevicecon->context);
1540			} else {
1541				cil_log(CIL_INFO, " %s", pcidevicecon->context_str);
1542			}
1543
1544			cil_log(CIL_INFO, "\n");
1545			return;
1546		}
1547		case CIL_DEVICETREECON: {
1548			struct cil_devicetreecon *devicetreecon = node->data;
1549
1550			cil_log(CIL_INFO, "DEVICETREECON %s", devicetreecon->path);
1551			if (devicetreecon->context != NULL) {
1552				cil_tree_print_context(devicetreecon->context);
1553			} else {
1554				cil_log(CIL_INFO, " %s", devicetreecon->context_str);
1555			}
1556
1557			cil_log(CIL_INFO, "\n");
1558			return;
1559		}
1560		case CIL_FSUSE: {
1561			struct cil_fsuse *fsuse = node->data;
1562			cil_log(CIL_INFO, "FSUSE: ");
1563
1564			if (fsuse->type == CIL_FSUSE_XATTR) {
1565				cil_log(CIL_INFO, "xattr ");
1566			} else if (fsuse->type == CIL_FSUSE_TASK) {
1567				cil_log(CIL_INFO, "task ");
1568			} else if (fsuse->type == CIL_FSUSE_TRANS) {
1569				cil_log(CIL_INFO, "trans ");
1570			} else {
1571				cil_log(CIL_INFO, "unknown ");
1572			}
1573
1574			cil_log(CIL_INFO, "%s ", fsuse->fs_str);
1575
1576			if (fsuse->context != NULL) {
1577				cil_tree_print_context(fsuse->context);
1578			} else {
1579				cil_log(CIL_INFO, " %s", fsuse->context_str);
1580			}
1581
1582			cil_log(CIL_INFO, "\n");
1583			return;
1584		}
1585		case CIL_SID: {
1586			struct cil_sid *sid = node->data;
1587			cil_log(CIL_INFO, "SID: %s\n", sid->datum.name);
1588			return;
1589		}
1590		case CIL_SIDCONTEXT: {
1591			struct cil_sidcontext *sidcon = node->data;
1592			cil_log(CIL_INFO, "SIDCONTEXT: %s", sidcon->sid_str);
1593
1594			if (sidcon->context != NULL) {
1595				cil_tree_print_context(sidcon->context);
1596			} else {
1597				cil_log(CIL_INFO, " %s", sidcon->context_str);
1598			}
1599
1600			cil_log(CIL_INFO, "\n");
1601			return;
1602		}
1603		case CIL_SIDORDER: {
1604			struct cil_sidorder *sidorder = node->data;
1605			struct cil_list_item *sid;
1606
1607			if (sidorder->sid_list_str == NULL) {
1608				cil_log(CIL_INFO, "SIDORDER: ()\n");
1609				return;
1610			}
1611
1612			cil_log(CIL_INFO, "SIDORDER: (");
1613			cil_list_for_each(sid, sidorder->sid_list_str) {
1614				cil_log(CIL_INFO, " %s", (char*)sid->data);
1615			}
1616			cil_log(CIL_INFO, " )\n");
1617			return;
1618		}
1619		case CIL_POLICYCAP: {
1620			struct cil_policycap *polcap = node->data;
1621			cil_log(CIL_INFO, "POLICYCAP: %s\n", polcap->datum.name);
1622			return;
1623		}
1624		case CIL_MACRO: {
1625			struct cil_macro *macro = node->data;
1626			cil_log(CIL_INFO, "MACRO %s:", macro->datum.name);
1627
1628			if (macro->params != NULL && macro->params->head != NULL) {
1629				struct cil_list_item *curr_param;
1630				cil_log(CIL_INFO, " parameters: (");
1631				cil_list_for_each(curr_param, macro->params) {
1632					cil_log(CIL_INFO, " flavor: %d, string: %s;", ((struct cil_param*)curr_param->data)->flavor, ((struct cil_param*)curr_param->data)->str);
1633
1634				}
1635				cil_log(CIL_INFO, " )");
1636			}
1637			cil_log(CIL_INFO, "\n");
1638
1639			return;
1640		}
1641		case CIL_CALL: {
1642			struct cil_call *call = node->data;
1643			cil_log(CIL_INFO, "CALL: macro name:");
1644
1645			if (call->macro != NULL) {
1646				cil_log(CIL_INFO, " %s", call->macro->datum.name);
1647			} else {
1648				cil_log(CIL_INFO, " %s", call->macro_str);
1649			}
1650
1651			if (call->args != NULL) {
1652				cil_log(CIL_INFO, ", args: ( ");
1653				struct cil_list_item *item;
1654				cil_list_for_each(item, call->args) {
1655					struct cil_symtab_datum *datum = ((struct cil_args*)item->data)->arg;
1656					if (datum != NULL) {
1657						if (datum->nodes != NULL && datum->nodes->head != NULL) {
1658							cil_tree_print_node((struct cil_tree_node*)datum->nodes->head->data);
1659						}
1660					} else if (((struct cil_args*)item->data)->arg_str != NULL) {
1661						switch (item->flavor) {
1662						case CIL_TYPE: cil_log(CIL_INFO, "type:"); break;
1663						case CIL_USER: cil_log(CIL_INFO, "user:"); break;
1664						case CIL_ROLE: cil_log(CIL_INFO, "role:"); break;
1665						case CIL_SENS: cil_log(CIL_INFO, "sensitivity:"); break;
1666						case CIL_CAT: cil_log(CIL_INFO, "category:"); break;
1667						case CIL_CATSET: cil_log(CIL_INFO, "categoryset:"); break;
1668						case CIL_LEVEL: cil_log(CIL_INFO, "level:"); break;
1669						case CIL_CLASS: cil_log(CIL_INFO, "class:"); break;
1670						default: break;
1671						}
1672						cil_log(CIL_INFO, "%s ", ((struct cil_args*)item->data)->arg_str);
1673					}
1674				}
1675				cil_log(CIL_INFO, ")");
1676			}
1677
1678			cil_log(CIL_INFO, "\n");
1679			return;
1680		}
1681		case CIL_OPTIONAL: {
1682			struct cil_optional *optional = node->data;
1683			cil_log(CIL_INFO, "OPTIONAL: %s\n", optional->datum.name);
1684			return;
1685		}
1686		case CIL_IPADDR: {
1687			struct cil_ipaddr *ipaddr = node->data;
1688			char buf[256];
1689
1690			inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256);
1691			cil_log(CIL_INFO, "IPADDR %s: %s\n", ipaddr->datum.name, buf);
1692
1693			break;
1694		}
1695		default : {
1696			cil_log(CIL_INFO, "CIL FLAVOR: %d\n", node->flavor);
1697			return;
1698		}
1699		}
1700	}
1701}
1702
1703void cil_tree_print(struct cil_tree_node *tree, uint32_t depth)
1704{
1705	struct cil_tree_node *current = NULL;
1706	current = tree;
1707	uint32_t x = 0;
1708
1709	if (current != NULL) {
1710		if (current->cl_head == NULL) {
1711			if (current->flavor == CIL_NODE) {
1712				if (current->parent->cl_head == current) {
1713					cil_log(CIL_INFO, "%s", (char*)current->data);
1714				} else {
1715					cil_log(CIL_INFO, " %s", (char*)current->data);
1716				}
1717			} else if (current->flavor != CIL_PERM) {
1718				for (x = 0; x<depth; x++) {
1719					cil_log(CIL_INFO, "\t");
1720				}
1721				cil_tree_print_node(current);
1722			}
1723		} else {
1724			if (current->parent != NULL) {
1725				cil_log(CIL_INFO, "\n");
1726				for (x = 0; x<depth; x++) {
1727					cil_log(CIL_INFO, "\t");
1728				}
1729				cil_log(CIL_INFO, "(");
1730
1731				if (current->flavor != CIL_NODE) {
1732					cil_tree_print_node(current);
1733				}
1734			}
1735			cil_tree_print(current->cl_head, depth + 1);
1736		}
1737
1738		if (current->next == NULL) {
1739			if ((current->parent != NULL) && (current->parent->cl_tail == current) && (current->parent->parent != NULL)) {
1740				if (current->flavor == CIL_PERM) {
1741					cil_log(CIL_INFO, ")\n");
1742				} else if (current->flavor != CIL_NODE) {
1743					for (x = 0; x<depth-1; x++) {
1744						cil_log(CIL_INFO, "\t");
1745					}
1746					cil_log(CIL_INFO, ")\n");
1747				} else {
1748					cil_log(CIL_INFO, ")");
1749				}
1750			}
1751
1752			if ((current->parent != NULL) && (current->parent->parent == NULL))
1753				cil_log(CIL_INFO, "\n\n");
1754		} else {
1755			cil_tree_print(current->next, depth);
1756		}
1757	} else {
1758		cil_log(CIL_INFO, "Tree is NULL\n");
1759	}
1760}
1761