• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_get_next_path(struct cil_tree_node * node,char ** path,int * is_cil)62 struct 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 
cil_tree_get_cil_path(struct cil_tree_node * node)101 char *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 
cil_tree_log(struct cil_tree_node * node,enum cil_log_level lvl,const char * msg,...)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 
cil_tree_init(struct cil_tree ** tree)148 int 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 
cil_tree_destroy(struct cil_tree ** tree)159 void 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 
cil_tree_subtree_destroy(struct cil_tree_node * node)170 void cil_tree_subtree_destroy(struct cil_tree_node *node)
171 {
172 	cil_tree_children_destroy(node);
173 	cil_tree_node_destroy(&node);
174 }
175 
cil_tree_children_destroy(struct cil_tree_node * node)176 void 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 
cil_tree_node_init(struct cil_tree_node ** node)208 void 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 
cil_tree_node_destroy(struct cil_tree_node ** node)223 void 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 
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)260 int 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 
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)296 int 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 */
cil_expr_to_string(struct cil_list * expr,char ** out)334 static 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 
499 exit:
500 	return rc;
501 }
502 
cil_tree_print_expr(struct cil_list * datum_expr,struct cil_list * str_expr)503 void cil_tree_print_expr(struct cil_list *datum_expr, struct cil_list *str_expr)
504 {
505 	char *expr_str;
506 	int rc;
507 
508 	cil_log(CIL_INFO, "(");
509 
510 	if (datum_expr != NULL) {
511 		rc = cil_expr_to_string(datum_expr, &expr_str);
512 	} else {
513 		rc = cil_expr_to_string(str_expr, &expr_str);
514 	}
515 	if (rc != SEPOL_OK) {
516 		cil_log(CIL_INFO, "ERROR)");
517 		return;
518 	}
519 	cil_log(CIL_INFO, "%s)", expr_str);
520 	free(expr_str);
521 }
522 
cil_tree_print_perms_list(struct cil_tree_node * current_perm)523 void cil_tree_print_perms_list(struct cil_tree_node *current_perm)
524 {
525 	while (current_perm != NULL) {
526 		if (current_perm->flavor == CIL_PERM) {
527 			cil_log(CIL_INFO, " %s", ((struct cil_perm *)current_perm->data)->datum.name);
528 		} else if (current_perm->flavor == CIL_MAP_PERM) {
529 			cil_log(CIL_INFO, " %s", ((struct cil_perm*)current_perm->data)->datum.name);
530 		} else {
531 			cil_log(CIL_INFO, "\n\n perms list contained unexpected data type: %d\n", current_perm->flavor);
532 			break;
533 		}
534 		current_perm = current_perm->next;
535 	}
536 }
537 
cil_tree_print_cats(struct cil_cats * cats)538 void cil_tree_print_cats(struct cil_cats *cats)
539 {
540 	cil_tree_print_expr(cats->datum_expr, cats->str_expr);
541 }
542 
cil_tree_print_perm_strs(struct cil_list * perm_strs)543 void cil_tree_print_perm_strs(struct cil_list *perm_strs)
544 {
545 	struct cil_list_item *curr;
546 
547 	if (perm_strs == NULL) {
548 		return;
549 	}
550 
551 	cil_log(CIL_INFO, " (");
552 
553 	cil_list_for_each(curr, perm_strs) {
554 		cil_log(CIL_INFO, " %s", (char*)curr->data);
555 	}
556 
557 	cil_log(CIL_INFO, " )");
558 }
559 
560 
cil_tree_print_classperms(struct cil_classperms * cp)561 void cil_tree_print_classperms(struct cil_classperms *cp)
562 {
563 	if (cp == NULL) {
564 		return;
565 	}
566 
567 	cil_log(CIL_INFO, " class: %s", cp->class_str);
568 	cil_log(CIL_INFO, ", perm_strs:");
569 	cil_tree_print_perm_strs(cp->perm_strs);
570 }
571 
cil_tree_print_classperms_set(struct cil_classperms_set * cp_set)572 void cil_tree_print_classperms_set(struct cil_classperms_set *cp_set)
573 {
574 	if (cp_set == NULL) {
575 		return;
576 	}
577 
578 	cil_log(CIL_INFO, " %s", cp_set->set_str);
579 }
580 
cil_tree_print_classperms_list(struct cil_list * cp_list)581 void cil_tree_print_classperms_list(struct cil_list *cp_list)
582 {
583 	struct cil_list_item *i;
584 
585 	if (cp_list == NULL) {
586 		return;
587 	}
588 
589 	cil_list_for_each(i, cp_list) {
590 		if (i->flavor == CIL_CLASSPERMS) {
591 			cil_tree_print_classperms(i->data);
592 		} else {
593 			cil_tree_print_classperms_set(i->data);
594 		}
595 	}
596 }
597 
cil_tree_print_level(struct cil_level * level)598 void cil_tree_print_level(struct cil_level *level)
599 {
600 	if (level->sens != NULL) {
601 		cil_log(CIL_INFO, " %s", level->sens->datum.name);
602 	} else if (level->sens_str != NULL) {
603 		cil_log(CIL_INFO, " %s", level->sens_str);
604 	}
605 
606 	cil_tree_print_cats(level->cats);
607 
608 	return;
609 }
610 
cil_tree_print_levelrange(struct cil_levelrange * lvlrange)611 void cil_tree_print_levelrange(struct cil_levelrange *lvlrange)
612 {
613 	cil_log(CIL_INFO, " (");
614 	if (lvlrange->low != NULL) {
615 		cil_log(CIL_INFO, " (");
616 		cil_tree_print_level(lvlrange->low);
617 		cil_log(CIL_INFO, " )");
618 	} else if (lvlrange->low_str != NULL) {
619 		cil_log(CIL_INFO, " %s", lvlrange->low_str);
620 	}
621 
622 	if (lvlrange->high != NULL) {
623 		cil_log(CIL_INFO, " (");
624 		cil_tree_print_level(lvlrange->high);
625 		cil_log(CIL_INFO, " )");
626 	} else if (lvlrange->high_str != NULL) {
627 		cil_log(CIL_INFO, " %s", lvlrange->high_str);
628 	}
629 	cil_log(CIL_INFO, " )");
630 }
631 
cil_tree_print_context(struct cil_context * context)632 void cil_tree_print_context(struct cil_context *context)
633 {
634 	cil_log(CIL_INFO, " (");
635 	if (context->user != NULL) {
636 		cil_log(CIL_INFO, " %s", context->user->datum.name);
637 	} else if (context->user_str != NULL) {
638 		cil_log(CIL_INFO, " %s", context->user_str);
639 	}
640 
641 	if (context->role != NULL) {
642 		cil_log(CIL_INFO, " %s", context->role->datum.name);
643 	} else if (context->role_str != NULL) {
644 		cil_log(CIL_INFO, " %s", context->role_str);
645 	}
646 
647 	if (context->type != NULL) {
648 		cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)context->type)->name);
649 	} else if (context->type_str != NULL) {
650 		cil_log(CIL_INFO, " %s", context->type_str);
651 	}
652 
653 	if (context->range != NULL) {
654 		cil_tree_print_levelrange(context->range);
655 	} else if (context->range_str != NULL) {
656 		cil_log(CIL_INFO, " %s", context->range_str);
657 	}
658 
659 	cil_log(CIL_INFO, " )");
660 
661 	return;
662 }
663 
cil_tree_print_constrain(struct cil_constrain * cons)664 void cil_tree_print_constrain(struct cil_constrain *cons)
665 {
666 	cil_tree_print_classperms_list(cons->classperms);
667 
668 	cil_tree_print_expr(cons->datum_expr, cons->str_expr);
669 
670 	cil_log(CIL_INFO, "\n");
671 }
672 
cil_tree_print_node(struct cil_tree_node * node)673 void cil_tree_print_node(struct cil_tree_node *node)
674 {
675 	if (node->data == NULL) {
676 		cil_log(CIL_INFO, "FLAVOR: %d", node->flavor);
677 		return;
678 	} else {
679 		switch( node->flavor ) {
680 		case CIL_BLOCK: {
681 			struct cil_block *block = node->data;
682 			cil_log(CIL_INFO, "BLOCK: %s\n", block->datum.name);
683 			return;
684 		}
685 		case CIL_BLOCKINHERIT: {
686 			struct cil_blockinherit *inherit = node->data;
687 			cil_log(CIL_INFO, "BLOCKINHERIT: %s\n", inherit->block_str);
688 			return;
689 		}
690 		case CIL_BLOCKABSTRACT: {
691 			struct cil_blockabstract *abstract = node->data;
692 			cil_log(CIL_INFO, "BLOCKABSTRACT: %s\n", abstract->block_str);
693 			return;
694 		}
695 		case CIL_IN: {
696 			struct cil_in *in = node->data;
697 			cil_log(CIL_INFO, "IN: %s\n", in->block_str);
698 			return;
699 		}
700 		case CIL_USER: {
701 			struct cil_user *user = node->data;
702 			cil_log(CIL_INFO, "USER: %s\n", user->datum.name);
703 			return;
704 		}
705 		case CIL_TYPE: {
706 			struct cil_type *type = node->data;
707 			cil_log(CIL_INFO, "TYPE: %s\n", type->datum.name);
708 			return;
709 		}
710 		case CIL_EXPANDTYPEATTRIBUTE: {
711 			struct cil_expandtypeattribute *attr = node->data;
712 
713 			fprintf(stderr, "%s %u\n", __func__, __LINE__);
714 			cil_log(CIL_INFO, "(EXPANDTYPEATTRIBUTE ");
715 			cil_tree_print_expr(attr->attr_datums, attr->attr_strs);
716 			cil_log(CIL_INFO, "%s)\n",attr->expand ?
717 					CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE);
718 
719 			return;
720 		}
721 		case CIL_TYPEATTRIBUTESET: {
722 			struct cil_typeattributeset *attr = node->data;
723 
724 			cil_log(CIL_INFO, "(TYPEATTRIBUTESET %s ", attr->attr_str);
725 
726 			cil_tree_print_expr(attr->datum_expr, attr->str_expr);
727 
728 			cil_log(CIL_INFO, "\n");
729 			return;
730 		}
731 		case CIL_TYPEATTRIBUTE: {
732 			struct cil_typeattribute *attr = node->data;
733 			cil_log(CIL_INFO, "TYPEATTRIBUTE: %s\n", attr->datum.name);
734 			return;
735 		}
736 		case CIL_ROLE: {
737 			struct cil_role *role = node->data;
738 			cil_log(CIL_INFO, "ROLE: %s\n", role->datum.name);
739 			return;
740 		}
741 		case CIL_USERROLE: {
742 			struct cil_userrole *userrole = node->data;
743 			cil_log(CIL_INFO, "USERROLE:");
744 			struct cil_symtab_datum *datum = NULL;
745 
746 			if (userrole->user != NULL) {
747 				datum = userrole->user;
748 				cil_log(CIL_INFO, " %s", datum->name);
749 			} else if (userrole->user_str != NULL) {
750 				cil_log(CIL_INFO, " %s", userrole->user_str);
751 			}
752 
753 			if (userrole->role != NULL) {
754 				datum = userrole->role;
755 				cil_log(CIL_INFO, " %s", datum->name);
756 			} else if (userrole->role_str != NULL) {
757 				cil_log(CIL_INFO, " %s", userrole->role_str);
758 			}
759 
760 			cil_log(CIL_INFO, "\n");
761 			return;
762 		}
763 		case CIL_USERLEVEL: {
764 			struct cil_userlevel *usrlvl = node->data;
765 			cil_log(CIL_INFO, "USERLEVEL:");
766 
767 			if (usrlvl->user_str != NULL) {
768 				cil_log(CIL_INFO, " %s", usrlvl->user_str);
769 			}
770 
771 			if (usrlvl->level != NULL) {
772 				cil_log(CIL_INFO, " (");
773 				cil_tree_print_level(usrlvl->level);
774 				cil_log(CIL_INFO, " )");
775 			} else if (usrlvl->level_str != NULL) {
776 				cil_log(CIL_INFO, " %s", usrlvl->level_str);
777 			}
778 
779 			cil_log(CIL_INFO, "\n");
780 			return;
781 		}
782 		case CIL_USERRANGE: {
783 			struct cil_userrange *userrange = node->data;
784 			cil_log(CIL_INFO, "USERRANGE:");
785 
786 			if (userrange->user_str != NULL) {
787 				cil_log(CIL_INFO, " %s", userrange->user_str);
788 			}
789 
790 			if (userrange->range != NULL) {
791 				cil_log(CIL_INFO, " (");
792 				cil_tree_print_levelrange(userrange->range);
793 				cil_log(CIL_INFO, " )");
794 			} else if (userrange->range_str != NULL) {
795 				cil_log(CIL_INFO, " %s", userrange->range_str);
796 			}
797 
798 			cil_log(CIL_INFO, "\n");
799 			return;
800 		}
801 		case CIL_USERBOUNDS: {
802 			struct cil_bounds *bnds = node->data;
803 			cil_log(CIL_INFO, "USERBOUNDS: user: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
804 			return;
805 		}
806 		case CIL_ROLETYPE: {
807 			struct cil_roletype *roletype = node->data;
808 			struct cil_symtab_datum *datum = NULL;
809 			cil_log(CIL_INFO, "ROLETYPE:");
810 
811 			if (roletype->role != NULL) {
812 				datum = roletype->role;
813 				cil_log(CIL_INFO, " %s", datum->name);
814 			} else if (roletype->role_str != NULL) {
815 				cil_log(CIL_INFO, " %s", roletype->role_str);
816 			}
817 
818 			if (roletype->type != NULL) {
819 				datum = roletype->type;
820 				cil_log(CIL_INFO, " %s", datum->name);
821 			} else if (roletype->type_str != NULL) {
822 				cil_log(CIL_INFO, " %s", roletype->type_str);
823 			}
824 
825 			cil_log(CIL_INFO, "\n");
826 			return;
827 		}
828 		case CIL_ROLETRANSITION: {
829 			struct cil_roletransition *roletrans = node->data;
830 			cil_log(CIL_INFO, "ROLETRANSITION:");
831 
832 			if (roletrans->src != NULL) {
833 				cil_log(CIL_INFO, " %s", roletrans->src->datum.name);
834 			} else {
835 				cil_log(CIL_INFO, " %s", roletrans->src_str);
836 			}
837 
838 			if (roletrans->tgt != NULL) {
839 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)roletrans->tgt)->name);
840 			} else {
841 				cil_log(CIL_INFO, " %s", roletrans->tgt_str);
842 			}
843 
844 			if (roletrans->obj != NULL) {
845 				cil_log(CIL_INFO, " %s", roletrans->obj->datum.name);
846 			} else {
847 				cil_log(CIL_INFO, " %s", roletrans->obj_str);
848 			}
849 
850 			if (roletrans->result != NULL) {
851 				cil_log(CIL_INFO, " %s\n", roletrans->result->datum.name);
852 			} else {
853 				cil_log(CIL_INFO, " %s\n", roletrans->result_str);
854 			}
855 
856 			return;
857 		}
858 		case CIL_ROLEALLOW: {
859 			struct cil_roleallow *roleallow = node->data;
860 			cil_log(CIL_INFO, "ROLEALLOW:");
861 
862 			if (roleallow->src != NULL) {
863 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->src)->name);
864 			} else {
865 				cil_log(CIL_INFO, " %s", roleallow->src_str);
866 			}
867 
868 			if (roleallow->tgt != NULL) {
869 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->tgt)->name);
870 			} else {
871 				cil_log(CIL_INFO, " %s", roleallow->tgt_str);
872 			}
873 
874 			cil_log(CIL_INFO, "\n");
875 			return;
876 		}
877 		case CIL_ROLEATTRIBUTESET: {
878 			struct cil_roleattributeset *attr = node->data;
879 
880 			cil_log(CIL_INFO, "(ROLEATTRIBUTESET %s ", attr->attr_str);
881 
882 			cil_tree_print_expr(attr->datum_expr, attr->str_expr);
883 
884 			cil_log(CIL_INFO, "\n");
885 			return;
886 		}
887 		case CIL_ROLEATTRIBUTE: {
888 			struct cil_roleattribute *attr = node->data;
889 			cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name);
890 			return;
891 		}
892 		case CIL_USERATTRIBUTESET: {
893 			struct cil_userattributeset *attr = node->data;
894 
895 			cil_log(CIL_INFO, "(USERATTRIBUTESET %s ", attr->attr_str);
896 
897 			cil_tree_print_expr(attr->datum_expr, attr->str_expr);
898 
899 			cil_log(CIL_INFO, "\n");
900 			return;
901 		}
902 		case CIL_USERATTRIBUTE: {
903 			struct cil_userattribute *attr = node->data;
904 			cil_log(CIL_INFO, "USERATTRIBUTE: %s\n", attr->datum.name);
905 			return;
906 		}
907 		case CIL_ROLEBOUNDS: {
908 			struct cil_bounds *bnds = node->data;
909 			cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
910 			return;
911 		}
912 		case CIL_CLASS: {
913 			struct cil_class *cls = node->data;
914 			cil_log(CIL_INFO, "CLASS: %s ", cls->datum.name);
915 
916 			if (cls->common != NULL) {
917 				cil_log(CIL_INFO, "inherits: %s ", cls->common->datum.name);
918 			}
919 			cil_log(CIL_INFO, "(");
920 
921 			cil_tree_print_perms_list(node->cl_head);
922 
923 			cil_log(CIL_INFO, " )");
924 			return;
925 		}
926 		case CIL_CLASSORDER: {
927 			struct cil_classorder *classorder = node->data;
928 			struct cil_list_item *class;
929 
930 			if (classorder->class_list_str == NULL) {
931 				cil_log(CIL_INFO, "CLASSORDER: ()\n");
932 				return;
933 			}
934 
935 			cil_log(CIL_INFO, "CLASSORDER: (");
936 			cil_list_for_each(class, classorder->class_list_str) {
937 				cil_log(CIL_INFO, " %s", (char*)class->data);
938 			}
939 			cil_log(CIL_INFO, " )\n");
940 			return;
941 		}
942 		case CIL_COMMON: {
943 			struct cil_class *common = node->data;
944 			cil_log(CIL_INFO, "COMMON: %s (", common->datum.name);
945 
946 			cil_tree_print_perms_list(node->cl_head);
947 
948 			cil_log(CIL_INFO, " )");
949 			return;
950 		}
951 		case CIL_CLASSCOMMON: {
952 			struct cil_classcommon *clscom = node->data;
953 
954 			cil_log(CIL_INFO, "CLASSCOMMON: class: %s, common: %s\n", clscom->class_str, clscom->common_str);
955 
956 			return;
957 		}
958 		case CIL_CLASSPERMISSION: {
959 			struct cil_classpermission *cp = node->data;
960 
961 			cil_log(CIL_INFO, "CLASSPERMISSION: %s", cp->datum.name);
962 
963 			cil_log(CIL_INFO, "\n");
964 
965 			return;
966 		}
967 		case CIL_CLASSPERMISSIONSET: {
968 			struct cil_classpermissionset *cps = node->data;
969 
970 			cil_log(CIL_INFO, "CLASSPERMISSIONSET: %s", cps->set_str);
971 
972 			cil_tree_print_classperms_list(cps->classperms);
973 
974 			cil_log(CIL_INFO, "\n");
975 
976 			return;
977 		}
978 		case CIL_MAP_CLASS: {
979 			struct cil_class *cm = node->data;
980 			cil_log(CIL_INFO, "MAP_CLASS: %s", cm->datum.name);
981 
982 			cil_log(CIL_INFO, " (");
983 			cil_tree_print_perms_list(node->cl_head);
984 			cil_log(CIL_INFO, " )\n");
985 
986 			return;
987 		}
988 		case CIL_MAP_PERM: {
989 			struct cil_perm *cmp = node->data;
990 
991 			cil_log(CIL_INFO, "MAP_PERM: %s", cmp->datum.name);
992 
993 			if (cmp->classperms == NULL) {
994 				cil_log(CIL_INFO, " perms: ()");
995 				return;
996 			}
997 
998 			cil_log(CIL_INFO, " kernel class perms: (");
999 
1000 			cil_tree_print_classperms_list(cmp->classperms);
1001 
1002 			cil_log(CIL_INFO, " )\n");
1003 
1004 			return;
1005 		}
1006 		case CIL_CLASSMAPPING: {
1007 			struct cil_classmapping *mapping = node->data;
1008 
1009 			cil_log(CIL_INFO, "CLASSMAPPING: map class: %s, map perm: %s,", mapping->map_class_str, mapping->map_perm_str);
1010 
1011 			cil_log(CIL_INFO, " (");
1012 
1013 			cil_tree_print_classperms_list(mapping->classperms);
1014 
1015 			cil_log(CIL_INFO, " )\n");
1016 			return;
1017 		}
1018 		case CIL_BOOL: {
1019 			struct cil_bool *boolean = node->data;
1020 			cil_log(CIL_INFO, "BOOL: %s, value: %d\n", boolean->datum.name, boolean->value);
1021 			return;
1022 		}
1023 		case CIL_TUNABLE: {
1024 			struct cil_tunable *tunable = node->data;
1025 			cil_log(CIL_INFO, "TUNABLE: %s, value: %d\n", tunable->datum.name, tunable->value);
1026 			return;
1027 		}
1028 		case CIL_BOOLEANIF: {
1029 			struct cil_booleanif *bif = node->data;
1030 
1031 			cil_log(CIL_INFO, "(BOOLEANIF ");
1032 
1033 			cil_tree_print_expr(bif->datum_expr, bif->str_expr);
1034 
1035 			cil_log(CIL_INFO, " )\n");
1036 			return;
1037 		}
1038 		case CIL_TUNABLEIF: {
1039 			struct cil_tunableif *tif = node->data;
1040 
1041 			cil_log(CIL_INFO, "(TUNABLEIF ");
1042 
1043 			cil_tree_print_expr(tif->datum_expr, tif->str_expr);
1044 
1045 			cil_log(CIL_INFO, " )\n");
1046 			return;
1047 		}
1048 		case CIL_CONDBLOCK: {
1049 			struct cil_condblock *cb = node->data;
1050 			if (cb->flavor == CIL_CONDTRUE) {
1051 				cil_log(CIL_INFO, "true\n");
1052 			} else if (cb->flavor == CIL_CONDFALSE) {
1053 				cil_log(CIL_INFO, "false\n");
1054 			}
1055 			return;
1056 		}
1057 		case CIL_ALL:
1058 			cil_log(CIL_INFO, "all");
1059 			return;
1060 		case CIL_AND:
1061 			cil_log(CIL_INFO, "&&");
1062 			return;
1063 		case CIL_OR:
1064 			cil_log(CIL_INFO, "|| ");
1065 			return;
1066 		case CIL_NOT:
1067 			cil_log(CIL_INFO, "!");
1068 			return;
1069 		case CIL_EQ:
1070 			cil_log(CIL_INFO, "==");
1071 			return;
1072 		case CIL_NEQ:
1073 			cil_log(CIL_INFO, "!=");
1074 			return;
1075 		case CIL_TYPEALIAS: {
1076 			struct cil_alias *alias = node->data;
1077 			cil_log(CIL_INFO, "TYPEALIAS: %s\n", alias->datum.name);
1078 			return;
1079 		}
1080 		case CIL_TYPEALIASACTUAL: {
1081 			struct cil_aliasactual *aliasactual = node->data;
1082 			cil_log(CIL_INFO, "TYPEALIASACTUAL: type: %s, alias: %s\n", aliasactual->alias_str, aliasactual->actual_str);
1083 			return;
1084 		}
1085 		case CIL_TYPEBOUNDS: {
1086 			struct cil_bounds *bnds = node->data;
1087 			cil_log(CIL_INFO, "TYPEBOUNDS: type: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
1088 			return;
1089 		}
1090 		case CIL_TYPEPERMISSIVE: {
1091 			struct cil_typepermissive *typeperm = node->data;
1092 
1093 			if (typeperm->type != NULL) {
1094 				cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", ((struct cil_symtab_datum *)typeperm->type)->name);
1095 			} else {
1096 				cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", typeperm->type_str);
1097 			}
1098 
1099 			return;
1100 		}
1101 		case CIL_NAMETYPETRANSITION: {
1102 			struct cil_nametypetransition *nametypetrans = node->data;
1103 			cil_log(CIL_INFO, "TYPETRANSITION:");
1104 
1105 			if (nametypetrans->src != NULL) {
1106 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->src)->name);
1107 			} else {
1108 				cil_log(CIL_INFO, " %s", nametypetrans->src_str);
1109 			}
1110 
1111 			if (nametypetrans->tgt != NULL) {
1112 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->tgt)->name);
1113 			} else {
1114 				cil_log(CIL_INFO, " %s", nametypetrans->tgt_str);
1115 			}
1116 
1117 			if (nametypetrans->obj != NULL) {
1118 				cil_log(CIL_INFO, " %s", nametypetrans->obj->datum.name);
1119 			} else {
1120 				cil_log(CIL_INFO, " %s", nametypetrans->obj_str);
1121 			}
1122 
1123 			cil_log(CIL_INFO, " %s\n", nametypetrans->name_str);
1124 
1125 			if (nametypetrans->result != NULL) {
1126 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->result)->name);
1127 			} else {
1128 				cil_log(CIL_INFO, " %s", nametypetrans->result_str);
1129 			}
1130 
1131 			return;
1132 		}
1133 		case CIL_RANGETRANSITION: {
1134 			struct cil_rangetransition *rangetrans = node->data;
1135 			cil_log(CIL_INFO, "RANGETRANSITION:");
1136 
1137 			if (rangetrans->src != NULL) {
1138 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->src)->name);
1139 			} else {
1140 				cil_log(CIL_INFO, " %s", rangetrans->src_str);
1141 			}
1142 
1143 			if (rangetrans->exec != NULL) {
1144 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->exec)->name);
1145 			} else {
1146 				cil_log(CIL_INFO, " %s", rangetrans->exec_str);
1147 			}
1148 
1149 			if (rangetrans->obj != NULL) {
1150 				cil_log(CIL_INFO, " %s", rangetrans->obj->datum.name);
1151 			} else {
1152 				cil_log(CIL_INFO, " %s", rangetrans->obj_str);
1153 			}
1154 
1155 			if (rangetrans->range != NULL) {
1156 				cil_log(CIL_INFO, " (");
1157 				cil_tree_print_levelrange(rangetrans->range);
1158 				cil_log(CIL_INFO, " )");
1159 			} else {
1160 				cil_log(CIL_INFO, " %s", rangetrans->range_str);
1161 			}
1162 
1163 			cil_log(CIL_INFO, "\n");
1164 			return;
1165 		}
1166 		case CIL_AVRULE: {
1167 			struct cil_avrule *rule = node->data;
1168 			switch (rule->rule_kind) {
1169 			case CIL_AVRULE_ALLOWED:
1170 				cil_log(CIL_INFO, "ALLOW:");
1171 				break;
1172 			case CIL_AVRULE_AUDITALLOW:
1173 				cil_log(CIL_INFO, "AUDITALLOW:");
1174 				break;
1175 			case CIL_AVRULE_DONTAUDIT:
1176 				cil_log(CIL_INFO, "DONTAUDIT:");
1177 				break;
1178 			case CIL_AVRULE_NEVERALLOW:
1179 				cil_log(CIL_INFO, "NEVERALLOW:");
1180 				break;
1181 			}
1182 
1183 			if (rule->src != NULL) {
1184 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->src)->name);
1185 			} else {
1186 				cil_log(CIL_INFO, " %s", rule->src_str);
1187 			}
1188 
1189 			if (rule->tgt != NULL) {
1190 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->tgt)->name);
1191 			} else {
1192 				cil_log(CIL_INFO, " %s", rule->tgt_str);
1193 			}
1194 
1195 			cil_tree_print_classperms_list(rule->perms.classperms);
1196 
1197 			cil_log(CIL_INFO, "\n");
1198 
1199 			return;
1200 		}
1201 		case CIL_TYPE_RULE: {
1202 			struct cil_type_rule *rule = node->data;
1203 			switch (rule->rule_kind) {
1204 			case CIL_TYPE_TRANSITION:
1205 				cil_log(CIL_INFO, "TYPETRANSITION:");
1206 				break;
1207 			case CIL_TYPE_MEMBER:
1208 				cil_log(CIL_INFO, "TYPEMEMBER:");
1209 				break;
1210 			case CIL_TYPE_CHANGE:
1211 				cil_log(CIL_INFO, "TYPECHANGE:");
1212 				break;
1213 			}
1214 
1215 			if (rule->src != NULL) {
1216 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->src)->name);
1217 			} else {
1218 				cil_log(CIL_INFO, " %s", rule->src_str);
1219 			}
1220 
1221 			if (rule->tgt != NULL) {
1222 				cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->tgt)->name);
1223 			} else {
1224 				cil_log(CIL_INFO, " %s", rule->tgt_str);
1225 			}
1226 
1227 			if (rule->obj != NULL) {
1228 				cil_log(CIL_INFO, " %s", rule->obj->datum.name);
1229 			} else {
1230 				cil_log(CIL_INFO, " %s", rule->obj_str);
1231 			}
1232 
1233 			if (rule->result != NULL) {
1234 				cil_log(CIL_INFO, " %s\n", ((struct cil_symtab_datum *)rule->result)->name);
1235 			} else {
1236 				cil_log(CIL_INFO, " %s\n", rule->result_str);
1237 			}
1238 
1239 			return;
1240 		}
1241 		case CIL_SENS: {
1242 			struct cil_sens *sens = node->data;
1243 			cil_log(CIL_INFO, "SENSITIVITY: %s\n", sens->datum.name);
1244 			return;
1245 		}
1246 		case CIL_SENSALIAS: {
1247 			struct cil_alias *alias = node->data;
1248 			cil_log(CIL_INFO, "SENSITIVITYALIAS: %s\n", alias->datum.name);
1249 			return;
1250 		}
1251 		case CIL_SENSALIASACTUAL: {
1252 			struct cil_aliasactual *aliasactual = node->data;
1253 			cil_log(CIL_INFO, "SENSITIVITYALIAS: alias: %s, sensitivity: %s\n", aliasactual->alias_str, aliasactual->actual_str);
1254 
1255 			return;
1256 		}
1257 		case CIL_CAT: {
1258 			struct cil_cat *cat = node->data;
1259 			cil_log(CIL_INFO, "CATEGORY: %s\n", cat->datum.name);
1260 			return;
1261 		}
1262 		case CIL_CATALIAS: {
1263 			struct cil_alias *alias = node->data;
1264 			cil_log(CIL_INFO, "CATEGORYALIAS: %s\n", alias->datum.name);
1265 			return;
1266 		}
1267 		case CIL_CATALIASACTUAL: {
1268 			struct cil_aliasactual *aliasactual = node->data;
1269 			cil_log(CIL_INFO, "CATEGORYALIAS: alias %s, category: %s\n", aliasactual->alias_str, aliasactual->actual_str);
1270 			return;
1271 		}
1272 		case CIL_CATSET: {
1273 			struct cil_catset *catset = node->data;
1274 
1275 			cil_log(CIL_INFO, "CATSET: %s ",catset->datum.name);
1276 
1277 			cil_tree_print_cats(catset->cats);
1278 
1279 			return;
1280 		}
1281 		case CIL_CATORDER: {
1282 			struct cil_catorder *catorder = node->data;
1283 			struct cil_list_item *cat;
1284 
1285 			if (catorder->cat_list_str == NULL) {
1286 				cil_log(CIL_INFO, "CATORDER: ()\n");
1287 				return;
1288 			}
1289 
1290 			cil_log(CIL_INFO, "CATORDER: (");
1291 			cil_list_for_each(cat, catorder->cat_list_str) {
1292 				cil_log(CIL_INFO, " %s", (char*)cat->data);
1293 			}
1294 			cil_log(CIL_INFO, " )\n");
1295 			return;
1296 		}
1297 		case CIL_SENSCAT: {
1298 			struct cil_senscat *senscat = node->data;
1299 
1300 			cil_log(CIL_INFO, "SENSCAT: sens:");
1301 
1302 			if (senscat->sens_str != NULL) {
1303 				cil_log(CIL_INFO, " %s ", senscat->sens_str);
1304 			} else {
1305 				cil_log(CIL_INFO, " [processed]");
1306 			}
1307 
1308 			cil_tree_print_cats(senscat->cats);
1309 
1310 			return;
1311 		}
1312 		case CIL_SENSITIVITYORDER: {
1313 			struct cil_sensorder *sensorder = node->data;
1314 			struct cil_list_item *sens;
1315 
1316 			cil_log(CIL_INFO, "SENSITIVITYORDER: (");
1317 
1318 			if (sensorder->sens_list_str != NULL) {
1319 				cil_list_for_each(sens, sensorder->sens_list_str) {
1320 					if (sens->flavor == CIL_LIST) {
1321 						struct cil_list_item *sub;
1322 						cil_log(CIL_INFO, " (");
1323 						cil_list_for_each(sub, (struct cil_list*)sens->data) {
1324 							cil_log(CIL_INFO, " %s", (char*)sub->data);
1325 						}
1326 						cil_log(CIL_INFO, " )");
1327 					} else {
1328 						cil_log(CIL_INFO, " %s", (char*)sens->data);
1329 					}
1330 				}
1331 			}
1332 
1333 			cil_log(CIL_INFO, " )\n");
1334 			return;
1335 		}
1336 		case CIL_LEVEL: {
1337 			struct cil_level *level = node->data;
1338 			cil_log(CIL_INFO, "LEVEL %s:", level->datum.name);
1339 			cil_tree_print_level(level);
1340 			cil_log(CIL_INFO, "\n");
1341 			return;
1342 		}
1343 		case CIL_LEVELRANGE: {
1344 			struct cil_levelrange *lvlrange = node->data;
1345 			cil_log(CIL_INFO, "LEVELRANGE %s:", lvlrange->datum.name);
1346 			cil_tree_print_levelrange(lvlrange);
1347 			cil_log(CIL_INFO, "\n");
1348 			return;
1349 		}
1350 		case CIL_CONSTRAIN: {
1351 			struct cil_constrain *cons = node->data;
1352 			cil_log(CIL_INFO, "CONSTRAIN: (");
1353 			cil_tree_print_constrain(cons);
1354 			return;
1355 		}
1356 		case CIL_MLSCONSTRAIN: {
1357 			struct cil_constrain *cons = node->data;
1358 			cil_log(CIL_INFO, "MLSCONSTRAIN: (");
1359 			cil_tree_print_constrain(cons);
1360 			return;
1361 		}
1362 		case CIL_VALIDATETRANS: {
1363 			struct cil_validatetrans *vt = node->data;
1364 
1365 			cil_log(CIL_INFO, "(VALIDATETRANS ");
1366 
1367 			if (vt->class != NULL) {
1368 				cil_log(CIL_INFO, "%s ", vt->class->datum.name);
1369 			} else if (vt->class_str != NULL) {
1370 				cil_log(CIL_INFO, "%s ", vt->class_str);
1371 			}
1372 
1373 			cil_tree_print_expr(vt->datum_expr, vt->str_expr);
1374 
1375 			cil_log(CIL_INFO, ")\n");
1376 			return;
1377 		}
1378 		case CIL_MLSVALIDATETRANS: {
1379 			struct cil_validatetrans *vt = node->data;
1380 
1381 			cil_log(CIL_INFO, "(MLSVALIDATETRANS ");
1382 
1383 			if (vt->class != NULL) {
1384 				cil_log(CIL_INFO, "%s ", vt->class->datum.name);
1385 			} else if (vt->class_str != NULL) {
1386 				cil_log(CIL_INFO, "%s ", vt->class_str);
1387 			}
1388 
1389 			cil_tree_print_expr(vt->datum_expr, vt->str_expr);
1390 
1391 			cil_log(CIL_INFO, ")\n");
1392 			return;
1393 		}
1394 		case CIL_CONTEXT: {
1395 			struct cil_context *context = node->data;
1396 			cil_log(CIL_INFO, "CONTEXT %s:", context->datum.name);
1397 			cil_tree_print_context(context);
1398 			cil_log(CIL_INFO, "\n");
1399 			return;
1400 		}
1401 		case CIL_FILECON: {
1402 			struct cil_filecon *filecon = node->data;
1403 			cil_log(CIL_INFO, "FILECON:");
1404 			cil_log(CIL_INFO, " %s %d", filecon->path_str, filecon->type);
1405 
1406 			if (filecon->context != NULL) {
1407 				cil_tree_print_context(filecon->context);
1408 			} else if (filecon->context_str != NULL) {
1409 				cil_log(CIL_INFO, " %s", filecon->context_str);
1410 			}
1411 
1412 			cil_log(CIL_INFO, "\n");
1413 			return;
1414 
1415 		}
1416 		case CIL_IBPKEYCON: {
1417 			struct cil_ibpkeycon *ibpkeycon = node->data;
1418 
1419 			cil_log(CIL_INFO, "IBPKEYCON: %s", ibpkeycon->subnet_prefix_str);
1420 			cil_log(CIL_INFO, " (%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high);
1421 
1422 			if (ibpkeycon->context)
1423 				cil_tree_print_context(ibpkeycon->context);
1424 			else if (ibpkeycon->context_str)
1425 				cil_log(CIL_INFO, " %s", ibpkeycon->context_str);
1426 
1427 			cil_log(CIL_INFO, "\n");
1428 			return;
1429 		}
1430 		case CIL_PORTCON: {
1431 			struct cil_portcon *portcon = node->data;
1432 			cil_log(CIL_INFO, "PORTCON:");
1433 			if (portcon->proto == CIL_PROTOCOL_UDP) {
1434 				cil_log(CIL_INFO, " udp");
1435 			} else if (portcon->proto == CIL_PROTOCOL_TCP) {
1436 				cil_log(CIL_INFO, " tcp");
1437 			} else if (portcon->proto == CIL_PROTOCOL_DCCP) {
1438 				cil_log(CIL_INFO, " dccp");
1439 			} else if (portcon->proto == CIL_PROTOCOL_SCTP) {
1440 				cil_log(CIL_INFO, " sctp");
1441 			}
1442 			cil_log(CIL_INFO, " (%d %d)", portcon->port_low, portcon->port_high);
1443 
1444 			if (portcon->context != NULL) {
1445 				cil_tree_print_context(portcon->context);
1446 			} else if (portcon->context_str != NULL) {
1447 				cil_log(CIL_INFO, " %s", portcon->context_str);
1448 			}
1449 
1450 			cil_log(CIL_INFO, "\n");
1451 			return;
1452 		}
1453 		case CIL_NODECON: {
1454 			struct cil_nodecon *nodecon = node->data;
1455 			char buf[256];
1456 
1457 			cil_log(CIL_INFO, "NODECON:");
1458 
1459 			if (nodecon->addr) {
1460 				inet_ntop(nodecon->addr->family, &nodecon->addr->ip, buf, 256);
1461 				cil_log(CIL_INFO, " %s", buf);
1462 			}  else {
1463 				cil_log(CIL_INFO, " %s", nodecon->addr_str);
1464 			}
1465 
1466 			if (nodecon->mask) {
1467 				inet_ntop(nodecon->mask->family, &nodecon->mask->ip, buf, 256);
1468 				cil_log(CIL_INFO, " %s", buf);
1469 			} else {
1470 				cil_log(CIL_INFO, " %s", nodecon->mask_str);
1471 			}
1472 
1473 			if (nodecon->context != NULL) {
1474 				cil_tree_print_context(nodecon->context);
1475 			} else if (nodecon->context_str != NULL) {
1476 				cil_log(CIL_INFO, " %s", nodecon->context_str);
1477 			}
1478 
1479 			cil_log(CIL_INFO, "\n");
1480 			return;
1481 		}
1482 		case CIL_GENFSCON: {
1483 			struct cil_genfscon *genfscon = node->data;
1484 			cil_log(CIL_INFO, "GENFSCON:");
1485 			cil_log(CIL_INFO, " %s %s", genfscon->fs_str, genfscon->path_str);
1486 
1487 			if (genfscon->context != NULL) {
1488 				cil_tree_print_context(genfscon->context);
1489 			} else if (genfscon->context_str != NULL) {
1490 				cil_log(CIL_INFO, " %s", genfscon->context_str);
1491 			}
1492 
1493 			cil_log(CIL_INFO, "\n");
1494 			return;
1495 		}
1496 		case CIL_NETIFCON: {
1497 			struct cil_netifcon *netifcon = node->data;
1498 			cil_log(CIL_INFO, "NETIFCON %s", netifcon->interface_str);
1499 
1500 			if (netifcon->if_context != NULL) {
1501 				cil_tree_print_context(netifcon->if_context);
1502 			} else if (netifcon->if_context_str != NULL) {
1503 				cil_log(CIL_INFO, " %s", netifcon->if_context_str);
1504 			}
1505 
1506 			if (netifcon->packet_context != NULL) {
1507 				cil_tree_print_context(netifcon->packet_context);
1508 			} else if (netifcon->packet_context_str != NULL) {
1509 				cil_log(CIL_INFO, " %s", netifcon->packet_context_str);
1510 			}
1511 
1512 			cil_log(CIL_INFO, "\n");
1513 			return;
1514 		}
1515 		case CIL_IBENDPORTCON: {
1516 			struct cil_ibendportcon *ibendportcon = node->data;
1517 
1518 			cil_log(CIL_INFO, "IBENDPORTCON: %s %u ", ibendportcon->dev_name_str, ibendportcon->port);
1519 
1520 			if (ibendportcon->context)
1521 				cil_tree_print_context(ibendportcon->context);
1522 			else if (ibendportcon->context_str)
1523 				cil_log(CIL_INFO, " %s", ibendportcon->context_str);
1524 
1525 			cil_log(CIL_INFO, "\n");
1526 			return;
1527 		}
1528 		case CIL_PIRQCON: {
1529 			struct cil_pirqcon *pirqcon = node->data;
1530 
1531 			cil_log(CIL_INFO, "PIRQCON %d", pirqcon->pirq);
1532 			if (pirqcon->context != NULL) {
1533 				cil_tree_print_context(pirqcon->context);
1534 			} else {
1535 				cil_log(CIL_INFO, " %s", pirqcon->context_str);
1536 			}
1537 
1538 			cil_log(CIL_INFO, "\n");
1539 			return;
1540 		}
1541 		case CIL_IOMEMCON: {
1542 			struct cil_iomemcon *iomemcon = node->data;
1543 
1544 			cil_log(CIL_INFO, "IOMEMCON ( %"PRId64" %"PRId64" )", iomemcon->iomem_low, iomemcon->iomem_high);
1545 			if (iomemcon->context != NULL) {
1546 				cil_tree_print_context(iomemcon->context);
1547 			} else {
1548 				cil_log(CIL_INFO, " %s", iomemcon->context_str);
1549 			}
1550 
1551 			cil_log(CIL_INFO, "\n");
1552 			return;
1553 		}
1554 		case CIL_IOPORTCON: {
1555 			struct cil_ioportcon *ioportcon = node->data;
1556 
1557 			cil_log(CIL_INFO, "IOPORTCON ( %d %d )", ioportcon->ioport_low, ioportcon->ioport_high);
1558 			if (ioportcon->context != NULL) {
1559 				cil_tree_print_context(ioportcon->context);
1560 			} else {
1561 				cil_log(CIL_INFO, " %s", ioportcon->context_str);
1562 			}
1563 
1564 			cil_log(CIL_INFO, "\n");
1565 			return;
1566 		}
1567 		case CIL_PCIDEVICECON: {
1568 			struct cil_pcidevicecon *pcidevicecon = node->data;
1569 
1570 			cil_log(CIL_INFO, "PCIDEVICECON %d", pcidevicecon->dev);
1571 			if (pcidevicecon->context != NULL) {
1572 				cil_tree_print_context(pcidevicecon->context);
1573 			} else {
1574 				cil_log(CIL_INFO, " %s", pcidevicecon->context_str);
1575 			}
1576 
1577 			cil_log(CIL_INFO, "\n");
1578 			return;
1579 		}
1580 		case CIL_DEVICETREECON: {
1581 			struct cil_devicetreecon *devicetreecon = node->data;
1582 
1583 			cil_log(CIL_INFO, "DEVICETREECON %s", devicetreecon->path);
1584 			if (devicetreecon->context != NULL) {
1585 				cil_tree_print_context(devicetreecon->context);
1586 			} else {
1587 				cil_log(CIL_INFO, " %s", devicetreecon->context_str);
1588 			}
1589 
1590 			cil_log(CIL_INFO, "\n");
1591 			return;
1592 		}
1593 		case CIL_FSUSE: {
1594 			struct cil_fsuse *fsuse = node->data;
1595 			cil_log(CIL_INFO, "FSUSE: ");
1596 
1597 			if (fsuse->type == CIL_FSUSE_XATTR) {
1598 				cil_log(CIL_INFO, "xattr ");
1599 			} else if (fsuse->type == CIL_FSUSE_TASK) {
1600 				cil_log(CIL_INFO, "task ");
1601 			} else if (fsuse->type == CIL_FSUSE_TRANS) {
1602 				cil_log(CIL_INFO, "trans ");
1603 			} else {
1604 				cil_log(CIL_INFO, "unknown ");
1605 			}
1606 
1607 			cil_log(CIL_INFO, "%s ", fsuse->fs_str);
1608 
1609 			if (fsuse->context != NULL) {
1610 				cil_tree_print_context(fsuse->context);
1611 			} else {
1612 				cil_log(CIL_INFO, " %s", fsuse->context_str);
1613 			}
1614 
1615 			cil_log(CIL_INFO, "\n");
1616 			return;
1617 		}
1618 		case CIL_SID: {
1619 			struct cil_sid *sid = node->data;
1620 			cil_log(CIL_INFO, "SID: %s\n", sid->datum.name);
1621 			return;
1622 		}
1623 		case CIL_SIDCONTEXT: {
1624 			struct cil_sidcontext *sidcon = node->data;
1625 			cil_log(CIL_INFO, "SIDCONTEXT: %s", sidcon->sid_str);
1626 
1627 			if (sidcon->context != NULL) {
1628 				cil_tree_print_context(sidcon->context);
1629 			} else {
1630 				cil_log(CIL_INFO, " %s", sidcon->context_str);
1631 			}
1632 
1633 			cil_log(CIL_INFO, "\n");
1634 			return;
1635 		}
1636 		case CIL_SIDORDER: {
1637 			struct cil_sidorder *sidorder = node->data;
1638 			struct cil_list_item *sid;
1639 
1640 			if (sidorder->sid_list_str == NULL) {
1641 				cil_log(CIL_INFO, "SIDORDER: ()\n");
1642 				return;
1643 			}
1644 
1645 			cil_log(CIL_INFO, "SIDORDER: (");
1646 			cil_list_for_each(sid, sidorder->sid_list_str) {
1647 				cil_log(CIL_INFO, " %s", (char*)sid->data);
1648 			}
1649 			cil_log(CIL_INFO, " )\n");
1650 			return;
1651 		}
1652 		case CIL_POLICYCAP: {
1653 			struct cil_policycap *polcap = node->data;
1654 			cil_log(CIL_INFO, "POLICYCAP: %s\n", polcap->datum.name);
1655 			return;
1656 		}
1657 		case CIL_MACRO: {
1658 			struct cil_macro *macro = node->data;
1659 			cil_log(CIL_INFO, "MACRO %s:", macro->datum.name);
1660 
1661 			if (macro->params != NULL && macro->params->head != NULL) {
1662 				struct cil_list_item *curr_param;
1663 				cil_log(CIL_INFO, " parameters: (");
1664 				cil_list_for_each(curr_param, macro->params) {
1665 					cil_log(CIL_INFO, " flavor: %d, string: %s;", ((struct cil_param*)curr_param->data)->flavor, ((struct cil_param*)curr_param->data)->str);
1666 
1667 				}
1668 				cil_log(CIL_INFO, " )");
1669 			}
1670 			cil_log(CIL_INFO, "\n");
1671 
1672 			return;
1673 		}
1674 		case CIL_CALL: {
1675 			struct cil_call *call = node->data;
1676 			cil_log(CIL_INFO, "CALL: macro name:");
1677 
1678 			if (call->macro != NULL) {
1679 				cil_log(CIL_INFO, " %s", call->macro->datum.name);
1680 			} else {
1681 				cil_log(CIL_INFO, " %s", call->macro_str);
1682 			}
1683 
1684 			if (call->args != NULL) {
1685 				cil_log(CIL_INFO, ", args: ( ");
1686 				struct cil_list_item *item;
1687 				cil_list_for_each(item, call->args) {
1688 					struct cil_symtab_datum *datum = ((struct cil_args*)item->data)->arg;
1689 					if (datum != NULL) {
1690 						if (datum->nodes != NULL && datum->nodes->head != NULL) {
1691 							cil_tree_print_node((struct cil_tree_node*)datum->nodes->head->data);
1692 						}
1693 					} else if (((struct cil_args*)item->data)->arg_str != NULL) {
1694 						switch (item->flavor) {
1695 						case CIL_TYPE: cil_log(CIL_INFO, "type:"); break;
1696 						case CIL_USER: cil_log(CIL_INFO, "user:"); break;
1697 						case CIL_ROLE: cil_log(CIL_INFO, "role:"); break;
1698 						case CIL_SENS: cil_log(CIL_INFO, "sensitivity:"); break;
1699 						case CIL_CAT: cil_log(CIL_INFO, "category:"); break;
1700 						case CIL_CATSET: cil_log(CIL_INFO, "categoryset:"); break;
1701 						case CIL_LEVEL: cil_log(CIL_INFO, "level:"); break;
1702 						case CIL_CLASS: cil_log(CIL_INFO, "class:"); break;
1703 						default: break;
1704 						}
1705 						cil_log(CIL_INFO, "%s ", ((struct cil_args*)item->data)->arg_str);
1706 					}
1707 				}
1708 				cil_log(CIL_INFO, ")");
1709 			}
1710 
1711 			cil_log(CIL_INFO, "\n");
1712 			return;
1713 		}
1714 		case CIL_OPTIONAL: {
1715 			struct cil_optional *optional = node->data;
1716 			cil_log(CIL_INFO, "OPTIONAL: %s\n", optional->datum.name);
1717 			return;
1718 		}
1719 		case CIL_IPADDR: {
1720 			struct cil_ipaddr *ipaddr = node->data;
1721 			char buf[256];
1722 
1723 			inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256);
1724 			cil_log(CIL_INFO, "IPADDR %s: %s\n", ipaddr->datum.name, buf);
1725 
1726 			break;
1727 		}
1728 		default : {
1729 			cil_log(CIL_INFO, "CIL FLAVOR: %d\n", node->flavor);
1730 			return;
1731 		}
1732 		}
1733 	}
1734 }
1735 
cil_tree_print(struct cil_tree_node * tree,uint32_t depth)1736 void cil_tree_print(struct cil_tree_node *tree, uint32_t depth)
1737 {
1738 	struct cil_tree_node *current = NULL;
1739 	current = tree;
1740 	uint32_t x = 0;
1741 
1742 	if (current != NULL) {
1743 		if (current->cl_head == NULL) {
1744 			if (current->flavor == CIL_NODE) {
1745 				if (current->parent->cl_head == current) {
1746 					cil_log(CIL_INFO, "%s", (char*)current->data);
1747 				} else {
1748 					cil_log(CIL_INFO, " %s", (char*)current->data);
1749 				}
1750 			} else if (current->flavor != CIL_PERM) {
1751 				for (x = 0; x<depth; x++) {
1752 					cil_log(CIL_INFO, "\t");
1753 				}
1754 				cil_tree_print_node(current);
1755 			}
1756 		} else {
1757 			if (current->parent != NULL) {
1758 				cil_log(CIL_INFO, "\n");
1759 				for (x = 0; x<depth; x++) {
1760 					cil_log(CIL_INFO, "\t");
1761 				}
1762 				cil_log(CIL_INFO, "(");
1763 
1764 				if (current->flavor != CIL_NODE) {
1765 					cil_tree_print_node(current);
1766 				}
1767 			}
1768 			cil_tree_print(current->cl_head, depth + 1);
1769 		}
1770 
1771 		if (current->next == NULL) {
1772 			if ((current->parent != NULL) && (current->parent->cl_tail == current) && (current->parent->parent != NULL)) {
1773 				if (current->flavor == CIL_PERM) {
1774 					cil_log(CIL_INFO, ")\n");
1775 				} else if (current->flavor != CIL_NODE) {
1776 					for (x = 0; x<depth-1; x++) {
1777 						cil_log(CIL_INFO, "\t");
1778 					}
1779 					cil_log(CIL_INFO, ")\n");
1780 				} else {
1781 					cil_log(CIL_INFO, ")");
1782 				}
1783 			}
1784 
1785 			if ((current->parent != NULL) && (current->parent->parent == NULL))
1786 				cil_log(CIL_INFO, "\n\n");
1787 		} else {
1788 			cil_tree_print(current->next, depth);
1789 		}
1790 	} else {
1791 		cil_log(CIL_INFO, "Tree is NULL\n");
1792 	}
1793 }
1794