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