Home | History | Annotate | Download | only in src
      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 <stdlib.h>
     31 #include <stdio.h>
     32 #include <string.h>
     33 #include <ctype.h>
     34 
     35 #include <sepol/policydb/conditional.h>
     36 
     37 #include "cil_internal.h"
     38 #include "cil_flavor.h"
     39 #include "cil_log.h"
     40 #include "cil_mem.h"
     41 #include "cil_tree.h"
     42 #include "cil_list.h"
     43 #include "cil_parser.h"
     44 #include "cil_build_ast.h"
     45 #include "cil_copy_ast.h"
     46 #include "cil_verify.h"
     47 #include "cil_strpool.h"
     48 
     49 struct cil_args_build {
     50 	struct cil_tree_node *ast;
     51 	struct cil_db *db;
     52 	struct cil_tree_node *macro;
     53 	struct cil_tree_node *boolif;
     54 	struct cil_tree_node *tunif;
     55 	struct cil_tree_node *in;
     56 };
     57 
     58 int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list)
     59 {
     60 	int rc = SEPOL_ERR;
     61 	struct cil_tree_node *curr;
     62 	enum cil_syntax syntax[] = {
     63 		CIL_SYN_N_STRINGS,
     64 		CIL_SYN_END
     65 	};
     66 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
     67 
     68 	rc = __cil_verify_syntax(current, syntax, syntax_len);
     69 	if (rc != SEPOL_OK) {
     70 		goto exit;
     71  	}
     72 
     73 	cil_list_init(list, flavor);
     74 
     75 	for (curr = current; curr != NULL; curr = curr->next) {
     76 		cil_list_append(*list, CIL_STRING, curr->data);
     77 	}
     78 
     79 	return SEPOL_OK;
     80 
     81 exit:
     82 	return rc;
     83 }
     84 
     85 int cil_gen_node(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor)
     86 {
     87 	int rc = SEPOL_ERR;
     88 	symtab_t *symtab = NULL;
     89 
     90 	rc = __cil_verify_name((const char*)key);
     91 	if (rc != SEPOL_OK) {
     92 		goto exit;
     93 	}
     94 
     95 	rc = cil_get_symtab(ast_node->parent, &symtab, sflavor);
     96 	if (rc != SEPOL_OK) {
     97 		goto exit;
     98 	}
     99 
    100 	ast_node->data = datum;
    101 	ast_node->flavor = nflavor;
    102 
    103 	if (symtab != NULL) {
    104 		rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node);
    105 		if (rc == SEPOL_EEXIST) {
    106 			cil_log(CIL_ERR, "Re-declaration of %s %s\n",
    107 				cil_node_to_string(ast_node), key);
    108 			if (cil_symtab_get_datum(symtab, key, &datum) == SEPOL_OK) {
    109 				if (sflavor == CIL_SYM_BLOCKS) {
    110 					struct cil_tree_node *node = datum->nodes->head->data;
    111 					cil_tree_log(node, CIL_ERR, "Previous declaration");
    112 				}
    113 			}
    114 			goto exit;
    115 		}
    116 	}
    117 
    118 	if (ast_node->flavor >= CIL_MIN_DECLARATIVE && ast_node->parent->flavor == CIL_MACRO) {
    119 		struct cil_list_item *item;
    120 		struct cil_list *param_list = ((struct cil_macro*)ast_node->parent->data)->params;
    121 		if (param_list != NULL) {
    122 			cil_list_for_each(item, param_list) {
    123 				struct cil_param *param = item->data;
    124 				if (param->flavor == ast_node->flavor) {
    125 					if (param->str == key) {
    126 						cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(ast_node), key);
    127 						rc = SEPOL_ERR;
    128 						goto exit;
    129 					}
    130 				}
    131 			}
    132 		}
    133 	}
    134 
    135 	return SEPOL_OK;
    136 
    137 exit:
    138 	cil_log(CIL_ERR, "Failed to create node\n");
    139 	return rc;
    140 }
    141 
    142 void cil_clear_node(struct cil_tree_node *ast_node)
    143 {
    144 	if (ast_node == NULL) {
    145 		return;
    146 	}
    147 
    148 	ast_node->data = NULL;
    149 	ast_node->flavor = CIL_NONE;
    150 }
    151 
    152 int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract)
    153 {
    154 	enum cil_syntax syntax[] = {
    155 		CIL_SYN_STRING,
    156 		CIL_SYN_STRING,
    157 		CIL_SYN_N_LISTS | CIL_SYN_END,
    158 		CIL_SYN_END
    159 	};
    160 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    161 	char *key = NULL;
    162 	struct cil_block *block = NULL;
    163 	int rc = SEPOL_ERR;
    164 
    165 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    166 		goto exit;
    167 	}
    168 
    169 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    170 	if (rc != SEPOL_OK) {
    171 		goto exit;
    172 	}
    173 
    174 	cil_block_init(&block);
    175 
    176 	block->is_abstract = is_abstract;
    177 
    178 	key = parse_current->next->data;
    179 
    180 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)block, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_BLOCK);
    181 	if (rc != SEPOL_OK) {
    182 		goto exit;
    183 	}
    184 
    185 	return SEPOL_OK;
    186 
    187 exit:
    188 	cil_tree_log(parse_current, CIL_ERR, "Bad block declaration");
    189 	cil_destroy_block(block);
    190 	cil_clear_node(ast_node);
    191 	return rc;
    192 }
    193 
    194 void cil_destroy_block(struct cil_block *block)
    195 {
    196 	if (block == NULL) {
    197 		return;
    198 	}
    199 
    200 	cil_symtab_datum_destroy(&block->datum);
    201 	cil_symtab_array_destroy(block->symtab);
    202 	cil_list_destroy(&block->bi_nodes, CIL_FALSE);
    203 
    204 	free(block);
    205 }
    206 
    207 int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    208 {
    209 	enum cil_syntax syntax[] = {
    210 		CIL_SYN_STRING,
    211 		CIL_SYN_STRING,
    212 		CIL_SYN_END
    213 	};
    214 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    215 	struct cil_blockinherit *inherit = NULL;
    216 	int rc = SEPOL_ERR;
    217 
    218 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    219 		goto exit;
    220 	}
    221 
    222 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    223 	if (rc != SEPOL_OK) {
    224 		goto exit;
    225 	}
    226 
    227 	cil_blockinherit_init(&inherit);
    228 
    229 	inherit->block_str = parse_current->next->data;
    230 
    231 	ast_node->data = inherit;
    232 	ast_node->flavor = CIL_BLOCKINHERIT;
    233 
    234 	return SEPOL_OK;
    235 
    236 exit:
    237 	cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration");
    238 	cil_destroy_blockinherit(inherit);
    239 	return rc;
    240 }
    241 
    242 void cil_destroy_blockinherit(struct cil_blockinherit *inherit)
    243 {
    244 	if (inherit == NULL) {
    245 		return;
    246 	}
    247 
    248 	free(inherit);
    249 }
    250 
    251 int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    252 {
    253 	enum cil_syntax syntax[] = {
    254 		CIL_SYN_STRING,
    255 		CIL_SYN_STRING,
    256 		CIL_SYN_END
    257 	};
    258 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    259 	struct cil_blockabstract *abstract = NULL;
    260 	int rc = SEPOL_ERR;
    261 
    262 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    263 		goto exit;
    264 	}
    265 
    266 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    267 	if (rc != SEPOL_OK) {
    268 		goto exit;
    269 	}
    270 
    271 	cil_blockabstract_init(&abstract);
    272 
    273 	abstract->block_str = parse_current->next->data;
    274 
    275 	ast_node->data = abstract;
    276 	ast_node->flavor = CIL_BLOCKABSTRACT;
    277 
    278 	return SEPOL_OK;
    279 
    280 exit:
    281 	cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration");
    282 	cil_destroy_blockabstract(abstract);
    283 	return rc;
    284 }
    285 
    286 void cil_destroy_blockabstract(struct cil_blockabstract *abstract)
    287 {
    288 	if (abstract == NULL) {
    289 		return;
    290 	}
    291 
    292 	free(abstract);
    293 }
    294 
    295 int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    296 {
    297 	enum cil_syntax syntax[] = {
    298 		CIL_SYN_STRING,
    299 		CIL_SYN_STRING,
    300 		CIL_SYN_N_LISTS,
    301 		CIL_SYN_END
    302 	};
    303 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    304 	int rc = SEPOL_ERR;
    305 	struct cil_in *in = NULL;
    306 
    307 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    308 		goto exit;
    309 	}
    310 
    311 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    312 	if (rc != SEPOL_OK) {
    313 		goto exit;
    314 	}
    315 
    316 	cil_in_init(&in);
    317 
    318 	in->block_str = parse_current->next->data;
    319 
    320 	ast_node->data = in;
    321 	ast_node->flavor = CIL_IN;
    322 
    323 	return SEPOL_OK;
    324 exit:
    325 	cil_tree_log(parse_current, CIL_ERR, "Bad in statement");
    326 	cil_destroy_in(in);
    327 	return rc;
    328 }
    329 
    330 void cil_destroy_in(struct cil_in *in)
    331 {
    332 	if (in == NULL) {
    333 		return;
    334 	}
    335 
    336 	cil_symtab_array_destroy(in->symtab);
    337 
    338 	free(in);
    339 }
    340 
    341 int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    342 {
    343 	enum cil_syntax syntax[] = {
    344 		CIL_SYN_STRING,
    345 		CIL_SYN_STRING,
    346 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
    347 		CIL_SYN_END
    348 	};
    349 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    350 	char *key = NULL;
    351 	struct cil_class *class = NULL;
    352 	struct cil_tree_node *perms = NULL;
    353 	int rc = SEPOL_ERR;
    354 
    355 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    356 	if (rc != SEPOL_OK) {
    357 		goto exit;
    358 	}
    359 
    360 	cil_class_init(&class);
    361 
    362 	key = parse_current->next->data;
    363 	if (key == CIL_KEY_UNORDERED) {
    364 		cil_log(CIL_ERR, "'unordered' keyword is reserved and not a valid class name.\n");
    365 		rc = SEPOL_ERR;
    366 		goto exit;
    367 	}
    368 
    369 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)class, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_CLASS);
    370 	if (rc != SEPOL_OK) {
    371 		goto exit;
    372 	}
    373 
    374 	if (parse_current->next->next != NULL) {
    375 		perms = parse_current->next->next->cl_head;
    376 		rc = cil_gen_perm_nodes(db, perms, ast_node, CIL_PERM, &class->num_perms);
    377 		if (rc != SEPOL_OK) {
    378 			goto exit;
    379 		}
    380 		if (class->num_perms > CIL_PERMS_PER_CLASS) {
    381 			cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name);
    382 			goto exit;
    383 		}
    384 
    385 	}
    386 
    387 	return SEPOL_OK;
    388 
    389 exit:
    390 	cil_tree_log(parse_current, CIL_ERR, "Bad class declaration");
    391 	cil_destroy_class(class);
    392 	cil_clear_node(ast_node);
    393 	return rc;
    394 }
    395 
    396 void cil_destroy_class(struct cil_class *class)
    397 {
    398 	if (class == NULL) {
    399 		return;
    400 	}
    401 
    402 	cil_symtab_datum_destroy(&class->datum);
    403 	cil_symtab_destroy(&class->perms);
    404 
    405 	free(class);
    406 }
    407 
    408 int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    409 {
    410 	enum cil_syntax syntax[] = {
    411 		CIL_SYN_STRING,
    412 		CIL_SYN_LIST,
    413 		CIL_SYN_END
    414 	};
    415 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    416 	struct cil_classorder *classorder = NULL;
    417 	struct cil_list_item *curr = NULL;
    418 	struct cil_list_item *head = NULL;
    419 	int rc = SEPOL_ERR;
    420 
    421 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    422 		goto exit;
    423 	}
    424 
    425 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    426 	if (rc !=  SEPOL_OK) {
    427 		goto exit;
    428 	}
    429 
    430 	cil_classorder_init(&classorder);
    431 
    432 	rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASSORDER, &classorder->class_list_str);
    433 	if (rc != SEPOL_OK) {
    434 		goto exit;
    435 	}
    436 
    437 	head = classorder->class_list_str->head;
    438 	cil_list_for_each(curr, classorder->class_list_str) {
    439 		if (curr->data == CIL_KEY_UNORDERED) {
    440 			if (curr == head && curr->next == NULL) {
    441 				cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n");
    442 				rc = SEPOL_ERR;
    443 				goto exit;
    444 			} else if (curr != head) {
    445 				cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n");
    446 				rc = SEPOL_ERR;
    447 				goto exit;
    448 			}
    449 		}
    450 	}
    451 
    452 	ast_node->data = classorder;
    453 	ast_node->flavor = CIL_CLASSORDER;
    454 
    455 	return SEPOL_OK;
    456 
    457 exit:
    458 	cil_tree_log(parse_current, CIL_ERR, "Bad classorder declaration");
    459 	cil_destroy_classorder(classorder);
    460 	return rc;
    461 }
    462 
    463 void cil_destroy_classorder(struct cil_classorder *classorder)
    464 {
    465 	if (classorder == NULL) {
    466 		return;
    467 	}
    468 
    469 	if (classorder->class_list_str != NULL) {
    470 		cil_list_destroy(&classorder->class_list_str, 1);
    471 	}
    472 
    473 	free(classorder);
    474 }
    475 
    476 int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms)
    477 {
    478 	char *key = NULL;
    479 	struct cil_perm *perm = NULL;
    480 	int rc = SEPOL_ERR;
    481 
    482 	cil_perm_init(&perm);
    483 
    484 	key = parse_current->data;
    485 	if (key == NULL) {
    486 		cil_log(CIL_ERR, "Bad permission\n");
    487 		goto exit;
    488 	}
    489 
    490 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)perm, (hashtab_key_t)key, CIL_SYM_PERMS, flavor);
    491 	if (rc != SEPOL_OK) {
    492 		goto exit;
    493 	}
    494 
    495 	perm->value = *num_perms;
    496 	(*num_perms)++;
    497 
    498 	return SEPOL_OK;
    499 
    500 exit:
    501 	cil_destroy_perm(perm);
    502 	cil_clear_node(ast_node);
    503 	return rc;
    504 }
    505 
    506 void cil_destroy_perm(struct cil_perm *perm)
    507 {
    508 	if (perm == NULL) {
    509 		return;
    510 	}
    511 
    512 	cil_symtab_datum_destroy(&perm->datum);
    513 	cil_list_destroy(&perm->classperms, CIL_FALSE);
    514 
    515 	free(perm);
    516 }
    517 
    518 int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms)
    519 {
    520 	int rc = SEPOL_ERR;
    521 	struct cil_tree_node *new_ast = NULL;
    522 
    523 	while(current_perm != NULL) {
    524 		if (current_perm->cl_head != NULL) {
    525 
    526 			rc = SEPOL_ERR;
    527 			goto exit;
    528 		}
    529 		cil_tree_node_init(&new_ast);
    530 		new_ast->parent = ast_node;
    531 		new_ast->line = current_perm->line;
    532 		new_ast->hll_line = current_perm->hll_line;
    533 
    534 		rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms);
    535 		if (rc != SEPOL_OK) {
    536 			cil_tree_node_destroy(&new_ast);
    537 			goto exit;
    538 		}
    539 
    540 		if (ast_node->cl_head == NULL) {
    541 			ast_node->cl_head = new_ast;
    542 		} else {
    543 			ast_node->cl_tail->next = new_ast;
    544 		}
    545 		ast_node->cl_tail = new_ast;
    546 
    547 		current_perm = current_perm->next;
    548 	}
    549 
    550 	return SEPOL_OK;
    551 
    552 exit:
    553 	cil_log(CIL_ERR, "Bad permissions\n");
    554 	cil_tree_children_destroy(ast_node);
    555 	cil_clear_node(ast_node);
    556 	return rc;
    557 }
    558 
    559 int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms)
    560 {
    561 	int rc = SEPOL_ERR;
    562 	enum cil_syntax syntax[] = {
    563 		CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS,
    564 		CIL_SYN_END
    565 	};
    566 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    567 
    568 	rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len);
    569 	if (rc != SEPOL_OK) {
    570 		goto exit;
    571 	}
    572 
    573 	rc = cil_gen_expr(start_perm, CIL_PERM, perms);
    574 	if (rc != SEPOL_OK) {
    575 		goto exit;
    576 	}
    577 
    578 	return SEPOL_OK;
    579 
    580 exit:
    581 	cil_log(CIL_ERR, "Bad permission list or expression\n");
    582 	return rc;
    583 }
    584 
    585 int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classperms **cp)
    586 {
    587 	int rc = SEPOL_ERR;
    588 	enum cil_syntax syntax[] = {
    589 		CIL_SYN_STRING,
    590 		CIL_SYN_LIST,
    591 		CIL_SYN_END
    592 	};
    593 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    594 
    595 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    596 	if (rc != SEPOL_OK) {
    597 		goto exit;
    598 	}
    599 
    600 	cil_classperms_init(cp);
    601 
    602 	(*cp)->class_str = parse_current->data;
    603 
    604 	rc = cil_fill_perms(parse_current->next, &(*cp)->perm_strs);
    605 	if (rc != SEPOL_OK) {
    606 		cil_destroy_classperms(*cp);
    607 		goto exit;
    608 	}
    609 
    610 	return SEPOL_OK;
    611 
    612 exit:
    613 	cil_log(CIL_ERR, "Bad class-permissions\n");
    614 	*cp = NULL;
    615 	return rc;
    616 }
    617 
    618 void cil_destroy_classperms(struct cil_classperms *cp)
    619 {
    620 	if (cp == NULL) {
    621 		return;
    622 	}
    623 
    624 	cil_list_destroy(&cp->perm_strs, CIL_TRUE);
    625 	cil_list_destroy(&cp->perms, CIL_FALSE);
    626 
    627 	free(cp);
    628 }
    629 
    630 void cil_fill_classperms_set(struct cil_tree_node *parse_current, struct cil_classperms_set **cp_set)
    631 {
    632 	cil_classperms_set_init(cp_set);
    633 	(*cp_set)->set_str = parse_current->data;
    634 }
    635 
    636 void cil_destroy_classperms_set(struct cil_classperms_set *cp_set)
    637 {
    638 	if (cp_set == NULL) {
    639 		return;
    640 	}
    641 
    642 	free(cp_set);
    643 }
    644 
    645 int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_list **cp_list)
    646 {
    647 	int rc = SEPOL_ERR;
    648 	struct cil_tree_node *curr;
    649 	enum cil_syntax syntax[] = {
    650 		CIL_SYN_STRING | CIL_SYN_LIST,
    651 	};
    652 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    653 
    654 	if (parse_current == NULL || cp_list == NULL) {
    655 		goto exit;
    656 	}
    657 
    658 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    659 	if (rc != SEPOL_OK) {
    660 		goto exit;
    661 	}
    662 
    663 	cil_list_init(cp_list, CIL_CLASSPERMS);
    664 
    665 	curr = parse_current->cl_head;
    666 
    667 	if (curr == NULL) {
    668 		/* Class-perms form: SET1 */
    669 		struct cil_classperms_set *new_cp_set;
    670 		cil_fill_classperms_set(parse_current, &new_cp_set);
    671 		cil_list_append(*cp_list, CIL_CLASSPERMS_SET, new_cp_set);
    672 	} else if (curr->cl_head == NULL) {
    673 		/* Class-perms form: (CLASS1 (PERM1 ...)) */
    674 		struct cil_classperms *new_cp;
    675 		rc = cil_fill_classperms(curr, &new_cp);
    676 		if (rc != SEPOL_OK) {
    677 			goto exit;
    678 		}
    679 		cil_list_append(*cp_list, CIL_CLASSPERMS, new_cp);
    680 	} else {
    681 		cil_log(CIL_ERR, "Bad class-permissions list syntax\n");
    682 		rc = SEPOL_ERR;
    683 		goto exit;
    684 	}
    685 
    686 	return SEPOL_OK;
    687 
    688 exit:
    689 	cil_log(CIL_ERR, "Problem filling class-permissions list\n");
    690 	cil_list_destroy(cp_list, CIL_TRUE);
    691 	return rc;
    692 }
    693 
    694 void cil_destroy_classperms_list(struct cil_list **cp_list)
    695 {
    696 	struct cil_list_item *curr;
    697 
    698 	if (cp_list == NULL || *cp_list == NULL) {
    699 		return;
    700 	}
    701 
    702 	cil_list_for_each(curr, *cp_list) {
    703 		if (curr->flavor == CIL_CLASSPERMS) {
    704 			cil_destroy_classperms(curr->data);
    705 		} else {
    706 			cil_destroy_classperms_set(curr->data);
    707 		}
    708 	}
    709 
    710 	cil_list_destroy(cp_list, CIL_FALSE);
    711 }
    712 
    713 int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    714 {
    715 	int rc = SEPOL_ERR;
    716 	char *key = NULL;
    717 	struct cil_classpermission *cp = NULL;
    718 	enum cil_syntax syntax[] = {
    719 		CIL_SYN_STRING,
    720 		CIL_SYN_STRING,
    721 		CIL_SYN_END
    722 	};
    723 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    724 
    725 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    726 		goto exit;
    727 	}
    728 
    729 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    730 	if (rc != SEPOL_OK) {
    731 		goto exit;
    732 	}
    733 
    734 	cil_classpermission_init(&cp);
    735 
    736 	key = parse_current->next->data;
    737 
    738 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cp, (hashtab_key_t)key, CIL_SYM_CLASSPERMSETS, CIL_CLASSPERMISSION);
    739 	if (rc != SEPOL_OK) {
    740 		goto exit;
    741 	}
    742 
    743 	return SEPOL_OK;
    744 
    745 exit:
    746 	cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration");
    747 	cil_destroy_classpermission(cp);
    748 	cil_clear_node(ast_node);
    749 	return rc;
    750 }
    751 
    752 void cil_destroy_classpermission(struct cil_classpermission *cp)
    753 {
    754 	if (cp == NULL) {
    755 		return;
    756 	}
    757 
    758 	if (cp->datum.name != NULL) {
    759 		cil_list_destroy(&cp->classperms, CIL_FALSE);
    760 	} else {
    761 		/* anonymous classpermission from call */
    762 		cil_destroy_classperms_list(&cp->classperms);
    763 	}
    764 
    765 	cil_symtab_datum_destroy(&cp->datum);
    766 
    767 
    768 	free(cp);
    769 }
    770 
    771 int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    772 {
    773 	int rc = SEPOL_ERR;
    774 	struct cil_classpermissionset *cps = NULL;
    775 	enum cil_syntax syntax[] = {
    776 		CIL_SYN_STRING,
    777 		CIL_SYN_STRING,
    778 		CIL_SYN_STRING | CIL_SYN_LIST,
    779 		CIL_SYN_END
    780 	};
    781 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    782 
    783 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    784 		goto exit;
    785 	}
    786 
    787 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    788 	if (rc != SEPOL_OK) {
    789 		goto exit;
    790 	}
    791 
    792 	cil_classpermissionset_init(&cps);
    793 
    794 	cps->set_str = parse_current->next->data;
    795 
    796 	rc = cil_fill_classperms_list(parse_current->next->next, &cps->classperms);
    797 	if (rc != SEPOL_OK) {
    798 		goto exit;
    799 	}
    800 
    801 	ast_node->data = cps;
    802 	ast_node->flavor = CIL_CLASSPERMISSIONSET;
    803 
    804 	return SEPOL_OK;
    805 
    806 exit:
    807 	cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset");
    808 	cil_destroy_classpermissionset(cps);
    809 	return rc;
    810 }
    811 
    812 void cil_destroy_classpermissionset(struct cil_classpermissionset *cps)
    813 {
    814 	if (cps == NULL) {
    815 		return;
    816 	}
    817 
    818 	cil_destroy_classperms_list(&cps->classperms);
    819 
    820 	free(cps);
    821 }
    822 
    823 int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    824 {
    825 	enum cil_syntax syntax[] = {
    826 		CIL_SYN_STRING,
    827 		CIL_SYN_STRING,
    828 		CIL_SYN_LIST,
    829 		CIL_SYN_END
    830 	};
    831 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    832 	char *key = NULL;
    833 	struct cil_class *map = NULL;
    834 	int rc = SEPOL_ERR;
    835 
    836 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    837 	if (rc != SEPOL_OK) {
    838 		goto exit;
    839 	}
    840 
    841 	cil_class_init(&map);
    842 
    843 	key = parse_current->next->data;
    844 
    845 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)map, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_MAP_CLASS);
    846 	if (rc != SEPOL_OK) {
    847 		goto exit;
    848 	}
    849 
    850 	rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_MAP_PERM, &map->num_perms);
    851 	if (rc != SEPOL_OK) {
    852 		goto exit;
    853 	}
    854 
    855 	return SEPOL_OK;
    856 
    857 exit:
    858 	cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration");
    859 	cil_destroy_class(map);
    860 	cil_clear_node(ast_node);
    861 	return rc;
    862 }
    863 
    864 int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    865 {
    866 	int rc = SEPOL_ERR;
    867 	struct cil_classmapping *mapping = NULL;
    868 	enum cil_syntax syntax[] = {
    869 		CIL_SYN_STRING,
    870 		CIL_SYN_STRING,
    871 		CIL_SYN_STRING,
    872 		CIL_SYN_STRING | CIL_SYN_LIST,
    873 		CIL_SYN_END
    874 	};
    875 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    876 
    877 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    878 		goto exit;
    879 	}
    880 
    881 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    882 	if (rc != SEPOL_OK) {
    883 		goto exit;
    884 	}
    885 
    886 	cil_classmapping_init(&mapping);
    887 
    888 	mapping->map_class_str = parse_current->next->data;
    889 	mapping->map_perm_str = parse_current->next->next->data;
    890 
    891 	rc = cil_fill_classperms_list(parse_current->next->next->next, &mapping->classperms);
    892 	if (rc != SEPOL_OK) {
    893 		goto exit;
    894 	}
    895 
    896 	ast_node->data = mapping;
    897 	ast_node->flavor = CIL_CLASSMAPPING;
    898 
    899 	return SEPOL_OK;
    900 
    901 exit:
    902 	cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration");
    903 	cil_destroy_classmapping(mapping);
    904 	return rc;
    905 }
    906 
    907 void cil_destroy_classmapping(struct cil_classmapping *mapping)
    908 {
    909 	if (mapping == NULL) {
    910 		return;
    911 	}
    912 
    913 	cil_destroy_classperms_list(&mapping->classperms);
    914 
    915 	free(mapping);
    916 }
    917 
    918 // TODO try to merge some of this with cil_gen_class (helper function for both)
    919 int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    920 {
    921 	enum cil_syntax syntax[] = {
    922 		CIL_SYN_STRING,
    923 		CIL_SYN_STRING,
    924 		CIL_SYN_LIST,
    925 		CIL_SYN_END
    926 	};
    927 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    928 	char *key = NULL;
    929 	struct cil_class *common = NULL;
    930 	int rc = SEPOL_ERR;
    931 
    932 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    933 		goto exit;
    934 	}
    935 
    936 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    937 	if (rc != SEPOL_OK) {
    938 		goto exit;
    939 	}
    940 
    941 	cil_class_init(&common);
    942 
    943 	key = parse_current->next->data;
    944 
    945 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)common, (hashtab_key_t)key, CIL_SYM_COMMONS, CIL_COMMON);
    946 	if (rc != SEPOL_OK) {
    947 		goto exit;
    948 	}
    949 
    950 	rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_PERM, &common->num_perms);
    951 	if (rc != SEPOL_OK) {
    952 		goto exit;
    953 	}
    954 	if (common->num_perms > CIL_PERMS_PER_CLASS) {
    955 		cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name);
    956 		goto exit;
    957 	}
    958 
    959 	return SEPOL_OK;
    960 
    961 exit:
    962 	cil_tree_log(parse_current, CIL_ERR, "Bad common declaration");
    963 	cil_destroy_class(common);
    964 	cil_clear_node(ast_node);
    965 	return rc;
    966 
    967 }
    968 
    969 int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
    970 {
    971 	enum cil_syntax syntax[] = {
    972 		CIL_SYN_STRING,
    973 		CIL_SYN_STRING,
    974 		CIL_SYN_STRING,
    975 		CIL_SYN_END
    976 	};
    977 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
    978 	struct cil_classcommon *clscom = NULL;
    979 	int rc = SEPOL_ERR;
    980 
    981 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
    982 		goto exit;
    983 	}
    984 
    985 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
    986 	if (rc != SEPOL_OK) {
    987 		goto exit;
    988 	}
    989 
    990 	cil_classcommon_init(&clscom);
    991 
    992 	clscom->class_str = parse_current->next->data;
    993 	clscom->common_str = parse_current->next->next->data;
    994 
    995 	ast_node->data = clscom;
    996 	ast_node->flavor = CIL_CLASSCOMMON;
    997 
    998 	return SEPOL_OK;
    999 
   1000 exit:
   1001 	cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration");
   1002 	cil_destroy_classcommon(clscom);
   1003 	return rc;
   1004 
   1005 }
   1006 
   1007 void cil_destroy_classcommon(struct cil_classcommon *clscom)
   1008 {
   1009 	if (clscom == NULL) {
   1010 		return;
   1011 	}
   1012 
   1013 	free(clscom);
   1014 }
   1015 
   1016 int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1017 {
   1018 	enum cil_syntax syntax[] = {
   1019 		CIL_SYN_STRING,
   1020 		CIL_SYN_STRING,
   1021 		CIL_SYN_END
   1022 	};
   1023 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1024 	char *key = NULL;
   1025 	struct cil_sid *sid = NULL;
   1026 	int rc = SEPOL_ERR;
   1027 
   1028 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1029 		goto exit;
   1030 	}
   1031 
   1032 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1033 	if (rc != SEPOL_OK) {
   1034 		goto exit;
   1035 	}
   1036 
   1037 	cil_sid_init(&sid);
   1038 
   1039 	key = parse_current->next->data;
   1040 
   1041 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sid, (hashtab_key_t)key, CIL_SYM_SIDS, CIL_SID);
   1042 	if (rc != SEPOL_OK) {
   1043 		goto exit;
   1044 	}
   1045 
   1046 	return SEPOL_OK;
   1047 
   1048 exit:
   1049 	cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration");
   1050 	cil_destroy_sid(sid);
   1051 	cil_clear_node(ast_node);
   1052 	return rc;
   1053 }
   1054 
   1055 void cil_destroy_sid(struct cil_sid *sid)
   1056 {
   1057 	if (sid == NULL) {
   1058 		return;
   1059 	}
   1060 
   1061 	cil_symtab_datum_destroy(&sid->datum);
   1062 	free(sid);
   1063 }
   1064 
   1065 int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1066 {
   1067 	enum cil_syntax syntax[] = {
   1068 		CIL_SYN_STRING,
   1069 		CIL_SYN_STRING,
   1070 		CIL_SYN_STRING | CIL_SYN_LIST,
   1071 		CIL_SYN_END
   1072 	};
   1073 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1074 	struct cil_sidcontext *sidcon = NULL;
   1075 	int rc = SEPOL_ERR;
   1076 
   1077 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1078 		goto exit;
   1079 	}
   1080 
   1081 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1082 	if (rc != SEPOL_OK) {
   1083 		goto exit;
   1084 	}
   1085 
   1086 	cil_sidcontext_init(&sidcon);
   1087 
   1088 	sidcon->sid_str = parse_current->next->data;
   1089 
   1090 	if (parse_current->next->next->cl_head == NULL) {
   1091 		sidcon->context_str = parse_current->next->next->data;
   1092 	} else {
   1093 		cil_context_init(&sidcon->context);
   1094 
   1095 		rc = cil_fill_context(parse_current->next->next->cl_head, sidcon->context);
   1096 		if (rc != SEPOL_OK) {
   1097 			goto exit;
   1098 		}
   1099 	}
   1100 
   1101 	ast_node->data = sidcon;
   1102 	ast_node->flavor = CIL_SIDCONTEXT;
   1103 
   1104 	return SEPOL_OK;
   1105 
   1106 exit:
   1107 	cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration");
   1108 	cil_destroy_sidcontext(sidcon);
   1109 	return rc;
   1110 }
   1111 
   1112 void cil_destroy_sidcontext(struct cil_sidcontext *sidcon)
   1113 {
   1114 	if (sidcon == NULL) {
   1115 		return;
   1116 	}
   1117 
   1118 	if (sidcon->context_str == NULL && sidcon->context != NULL) {
   1119 		cil_destroy_context(sidcon->context);
   1120 	}
   1121 
   1122 	free(sidcon);
   1123 }
   1124 
   1125 int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1126 {
   1127 	enum cil_syntax syntax[] = {
   1128 		CIL_SYN_STRING,
   1129 		CIL_SYN_LIST,
   1130 		CIL_SYN_END
   1131 	};
   1132 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1133 	struct cil_sidorder *sidorder = NULL;
   1134 	struct cil_list_item *curr = NULL;
   1135 	int rc = SEPOL_ERR;
   1136 
   1137 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1138 		goto exit;
   1139 	}
   1140 
   1141 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1142 	if (rc !=  SEPOL_OK) {
   1143 		goto exit;
   1144 	}
   1145 
   1146 	cil_sidorder_init(&sidorder);
   1147 
   1148 	rc = cil_fill_list(parse_current->next->cl_head, CIL_SIDORDER, &sidorder->sid_list_str);
   1149 	if (rc != SEPOL_OK) {
   1150 		goto exit;
   1151 	}
   1152 
   1153 	cil_list_for_each(curr, sidorder->sid_list_str) {
   1154 		if (curr->data == CIL_KEY_UNORDERED) {
   1155 			cil_log(CIL_ERR, "Sidorder cannot be unordered.\n");
   1156 			rc = SEPOL_ERR;
   1157 			goto exit;
   1158 		}
   1159 	}
   1160 
   1161 	ast_node->data = sidorder;
   1162 	ast_node->flavor = CIL_SIDORDER;
   1163 
   1164 	return SEPOL_OK;
   1165 
   1166 exit:
   1167 	cil_tree_log(parse_current, CIL_ERR, "Bad sidorder declaration");
   1168 	cil_destroy_sidorder(sidorder);
   1169 	return rc;
   1170 }
   1171 
   1172 void cil_destroy_sidorder(struct cil_sidorder *sidorder)
   1173 {
   1174 	if (sidorder == NULL) {
   1175 		return;
   1176 	}
   1177 
   1178 	if (sidorder->sid_list_str != NULL) {
   1179 		cil_list_destroy(&sidorder->sid_list_str, 1);
   1180 	}
   1181 
   1182 	free(sidorder);
   1183 }
   1184 
   1185 int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1186 {
   1187 	enum cil_syntax syntax[] = {
   1188 		CIL_SYN_STRING,
   1189 		CIL_SYN_STRING,
   1190 		CIL_SYN_END
   1191 	};
   1192 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1193 	char *key = NULL;
   1194 	struct cil_user *user = NULL;
   1195 	int rc = SEPOL_ERR;
   1196 
   1197 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1198 		goto exit;
   1199 	}
   1200 
   1201 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1202 	if (rc != SEPOL_OK) {
   1203 		goto exit;
   1204 	}
   1205 
   1206 	cil_user_init(&user);
   1207 
   1208 	key = parse_current->next->data;
   1209 
   1210 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)user, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USER);
   1211 	if (rc != SEPOL_OK) {
   1212 		goto exit;
   1213 	}
   1214 
   1215 	return SEPOL_OK;
   1216 
   1217 exit:
   1218 	cil_tree_log(parse_current, CIL_ERR, "Bad user declaration");
   1219 	cil_destroy_user(user);
   1220 	cil_clear_node(ast_node);
   1221 	return rc;
   1222 }
   1223 
   1224 void cil_destroy_user(struct cil_user *user)
   1225 {
   1226 	if (user == NULL) {
   1227 		return;
   1228 	}
   1229 
   1230 	cil_symtab_datum_destroy(&user->datum);
   1231 	ebitmap_destroy(user->roles);
   1232 	free(user->roles);
   1233 	free(user);
   1234 }
   1235 
   1236 int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1237 {
   1238 	enum cil_syntax syntax[] = {
   1239 		CIL_SYN_STRING,
   1240 		CIL_SYN_STRING,
   1241 		CIL_SYN_END
   1242 	};
   1243 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1244 	char *key = NULL;
   1245 	struct cil_userattribute *attr = NULL;
   1246 	int rc = SEPOL_ERR;
   1247 
   1248 	if (parse_current == NULL || ast_node == NULL) {
   1249 		goto exit;
   1250 	}
   1251 
   1252 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1253 	if (rc != SEPOL_OK) {
   1254 		goto exit;
   1255 	}
   1256 
   1257 	cil_userattribute_init(&attr);
   1258 
   1259 	key = parse_current->next->data;
   1260 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE);
   1261 	if (rc != SEPOL_OK) {
   1262 		goto exit;
   1263 	}
   1264 
   1265 	return SEPOL_OK;
   1266 exit:
   1267 	cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration");
   1268 	cil_destroy_userattribute(attr);
   1269 	cil_clear_node(ast_node);
   1270 	return rc;
   1271 }
   1272 
   1273 void cil_destroy_userattribute(struct cil_userattribute *attr)
   1274 {
   1275 	struct cil_list_item *expr = NULL;
   1276 	struct cil_list_item *next = NULL;
   1277 
   1278 	if (attr == NULL) {
   1279 		return;
   1280 	}
   1281 
   1282 	if (attr->expr_list != NULL) {
   1283 		/* we don't want to destroy the expression stacks (cil_list) inside
   1284 		 * this list cil_list_destroy destroys sublists, so we need to do it
   1285 		 * manually */
   1286 		expr = attr->expr_list->head;
   1287 		while (expr != NULL) {
   1288 			next = expr->next;
   1289 			cil_list_item_destroy(&expr, CIL_FALSE);
   1290 			expr = next;
   1291 		}
   1292 		free(attr->expr_list);
   1293 		attr->expr_list = NULL;
   1294 	}
   1295 
   1296 	cil_symtab_datum_destroy(&attr->datum);
   1297 	ebitmap_destroy(attr->users);
   1298 	free(attr->users);
   1299 	free(attr);
   1300 }
   1301 
   1302 int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1303 {
   1304 	enum cil_syntax syntax[] = {
   1305 		CIL_SYN_STRING,
   1306 		CIL_SYN_STRING,
   1307 		CIL_SYN_STRING | CIL_SYN_LIST,
   1308 		CIL_SYN_END
   1309 	};
   1310 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1311 	struct cil_userattributeset *attrset = NULL;
   1312 	int rc = SEPOL_ERR;
   1313 
   1314 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1315 		goto exit;
   1316 	}
   1317 
   1318 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1319 	if (rc != SEPOL_OK) {
   1320 		goto exit;
   1321 	}
   1322 
   1323 	cil_userattributeset_init(&attrset);
   1324 
   1325 	attrset->attr_str = parse_current->next->data;
   1326 
   1327 	rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr);
   1328 	if (rc != SEPOL_OK) {
   1329 		goto exit;
   1330 	}
   1331 	ast_node->data = attrset;
   1332 	ast_node->flavor = CIL_USERATTRIBUTESET;
   1333 
   1334 	return SEPOL_OK;
   1335 
   1336 exit:
   1337 	cil_tree_log(parse_current, CIL_ERR, "Bad userattributeset declaration");
   1338 	cil_destroy_userattributeset(attrset);
   1339 
   1340 	return rc;
   1341 }
   1342 
   1343 void cil_destroy_userattributeset(struct cil_userattributeset *attrset)
   1344 {
   1345 	if (attrset == NULL) {
   1346 		return;
   1347 	}
   1348 
   1349 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
   1350 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
   1351 
   1352 	free(attrset);
   1353 }
   1354 
   1355 int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1356 {
   1357 	enum cil_syntax syntax[] = {
   1358 		CIL_SYN_STRING,
   1359 		CIL_SYN_STRING,
   1360 		CIL_SYN_STRING | CIL_SYN_LIST,
   1361 		CIL_SYN_END
   1362 	};
   1363 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1364 	struct cil_userlevel *usrlvl = NULL;
   1365 	int rc = SEPOL_ERR;
   1366 
   1367 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1368 		goto exit;
   1369 	}
   1370 
   1371 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1372 	if (rc != SEPOL_OK) {
   1373 		goto exit;
   1374 	}
   1375 
   1376 	cil_userlevel_init(&usrlvl);
   1377 
   1378 	usrlvl->user_str = parse_current->next->data;
   1379 
   1380 	if (parse_current->next->next->cl_head == NULL) {
   1381 		usrlvl->level_str = parse_current->next->next->data;
   1382 	} else {
   1383 		cil_level_init(&usrlvl->level);
   1384 
   1385 		rc = cil_fill_level(parse_current->next->next->cl_head, usrlvl->level);
   1386 		if (rc != SEPOL_OK) {
   1387 			goto exit;
   1388 		}
   1389 	}
   1390 
   1391 	ast_node->data = usrlvl;
   1392 	ast_node->flavor = CIL_USERLEVEL;
   1393 
   1394 	return SEPOL_OK;
   1395 
   1396 exit:
   1397 	cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration");
   1398 	cil_destroy_userlevel(usrlvl);
   1399 	return rc;
   1400 }
   1401 
   1402 void cil_destroy_userlevel(struct cil_userlevel *usrlvl)
   1403 {
   1404 	if (usrlvl == NULL) {
   1405 		return;
   1406 	}
   1407 
   1408 	if (usrlvl->level_str == NULL && usrlvl->level != NULL) {
   1409 		cil_destroy_level(usrlvl->level);
   1410 	}
   1411 
   1412 	free(usrlvl);
   1413 }
   1414 
   1415 int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1416 {
   1417 	enum cil_syntax syntax[] = {
   1418 		CIL_SYN_STRING,
   1419 		CIL_SYN_STRING,
   1420 		CIL_SYN_STRING | CIL_SYN_LIST,
   1421 		CIL_SYN_END
   1422 	};
   1423 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1424 	struct cil_userrange *userrange = NULL;
   1425 	int rc = SEPOL_ERR;
   1426 
   1427 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1428 		goto exit;
   1429 	}
   1430 
   1431 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1432 	if (rc != SEPOL_OK) {
   1433 		goto exit;
   1434 	}
   1435 
   1436 	cil_userrange_init(&userrange);
   1437 
   1438 	userrange->user_str = parse_current->next->data;
   1439 
   1440 	if (parse_current->next->next->cl_head == NULL) {
   1441 		userrange->range_str = parse_current->next->next->data;
   1442 	} else {
   1443 		cil_levelrange_init(&userrange->range);
   1444 
   1445 		rc = cil_fill_levelrange(parse_current->next->next->cl_head, userrange->range);
   1446 		if (rc != SEPOL_OK) {
   1447 			goto exit;
   1448 		}
   1449 	}
   1450 
   1451 	ast_node->data = userrange;
   1452 	ast_node->flavor = CIL_USERRANGE;
   1453 
   1454 	return SEPOL_OK;
   1455 
   1456 exit:
   1457 	cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration");
   1458 	cil_destroy_userrange(userrange);
   1459 	return rc;
   1460 }
   1461 
   1462 void cil_destroy_userrange(struct cil_userrange *userrange)
   1463 {
   1464 	if (userrange == NULL) {
   1465 		return;
   1466 	}
   1467 
   1468 	if (userrange->range_str == NULL && userrange->range != NULL) {
   1469 		cil_destroy_levelrange(userrange->range);
   1470 	}
   1471 
   1472 	free(userrange);
   1473 }
   1474 
   1475 int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1476 {
   1477 	enum cil_syntax syntax[] = {
   1478 		CIL_SYN_STRING,
   1479 		CIL_SYN_STRING,
   1480 		CIL_SYN_STRING,
   1481 		CIL_SYN_END
   1482 	};
   1483 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1484 	struct cil_userprefix *userprefix = NULL;
   1485 	int rc = SEPOL_ERR;
   1486 
   1487 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1488 		goto exit;
   1489 	}
   1490 
   1491 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1492 	if (rc != SEPOL_OK) {
   1493 		goto exit;
   1494 	}
   1495 
   1496 	cil_userprefix_init(&userprefix);
   1497 
   1498 	userprefix->user_str = parse_current->next->data;
   1499 	userprefix->prefix_str = parse_current->next->next->data;
   1500 
   1501 	ast_node->data = userprefix;
   1502 	ast_node->flavor = CIL_USERPREFIX;
   1503 
   1504 	return SEPOL_OK;
   1505 exit:
   1506 	cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration");
   1507 	cil_destroy_userprefix(userprefix);
   1508 	return rc;
   1509 }
   1510 
   1511 void cil_destroy_userprefix(struct cil_userprefix *userprefix)
   1512 {
   1513 	if (userprefix == NULL) {
   1514 		return;
   1515 	}
   1516 
   1517 	free(userprefix);
   1518 }
   1519 
   1520 int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1521 {
   1522 	enum cil_syntax syntax[] = {
   1523 		CIL_SYN_STRING,
   1524 		CIL_SYN_STRING,
   1525 		CIL_SYN_STRING,
   1526 		CIL_SYN_STRING | CIL_SYN_LIST,
   1527 		CIL_SYN_END
   1528 	};
   1529 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1530 	struct cil_selinuxuser *selinuxuser = NULL;
   1531 	int rc = SEPOL_ERR;
   1532 
   1533 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1534 		goto exit;
   1535 	}
   1536 
   1537 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1538 	if (rc != SEPOL_OK) {
   1539 		goto exit;
   1540 	}
   1541 
   1542 	cil_selinuxuser_init(&selinuxuser);
   1543 
   1544 	selinuxuser->name_str = parse_current->next->data;
   1545 	selinuxuser->user_str = parse_current->next->next->data;
   1546 
   1547 	if (parse_current->next->next->next->cl_head == NULL) {
   1548 		selinuxuser->range_str = parse_current->next->next->next->data;
   1549 	} else {
   1550 		cil_levelrange_init(&selinuxuser->range);
   1551 
   1552 		rc = cil_fill_levelrange(parse_current->next->next->next->cl_head, selinuxuser->range);
   1553 		if (rc != SEPOL_OK) {
   1554 			goto exit;
   1555 		}
   1556 	}
   1557 
   1558 	ast_node->data = selinuxuser;
   1559 	ast_node->flavor = CIL_SELINUXUSER;
   1560 
   1561 	return SEPOL_OK;
   1562 exit:
   1563 	cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration");
   1564 	cil_destroy_selinuxuser(selinuxuser);
   1565 	return rc;
   1566 }
   1567 
   1568 int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1569 {
   1570 	enum cil_syntax syntax[] = {
   1571 		CIL_SYN_STRING,
   1572 		CIL_SYN_STRING,
   1573 		CIL_SYN_STRING | CIL_SYN_LIST,
   1574 		CIL_SYN_END
   1575 	};
   1576 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1577 	struct cil_selinuxuser *selinuxuser = NULL;
   1578 	int rc = SEPOL_ERR;
   1579 
   1580 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1581 		goto exit;
   1582 	}
   1583 
   1584 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1585 	if (rc != SEPOL_OK) {
   1586 		goto exit;
   1587 	}
   1588 
   1589 	cil_selinuxuser_init(&selinuxuser);
   1590 
   1591 	selinuxuser->name_str = cil_strpool_add("__default__");
   1592 	selinuxuser->user_str = parse_current->next->data;
   1593 
   1594 	if (parse_current->next->next->cl_head == NULL) {
   1595 		selinuxuser->range_str = parse_current->next->next->data;
   1596 	} else {
   1597 		cil_levelrange_init(&selinuxuser->range);
   1598 
   1599 		rc = cil_fill_levelrange(parse_current->next->next->cl_head, selinuxuser->range);
   1600 		if (rc != SEPOL_OK) {
   1601 			goto exit;
   1602 		}
   1603 	}
   1604 
   1605 	ast_node->data = selinuxuser;
   1606 	ast_node->flavor = CIL_SELINUXUSERDEFAULT;
   1607 
   1608 	return SEPOL_OK;
   1609 exit:
   1610 	cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuserdefault declaration");
   1611 	cil_destroy_selinuxuser(selinuxuser);
   1612 	return rc;
   1613 }
   1614 
   1615 void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser)
   1616 {
   1617 	if (selinuxuser == NULL) {
   1618 		return;
   1619 	}
   1620 
   1621 	if (selinuxuser->range_str == NULL && selinuxuser->range != NULL) {
   1622 		cil_destroy_levelrange(selinuxuser->range);
   1623 	}
   1624 
   1625 	free(selinuxuser);
   1626 }
   1627 
   1628 int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1629 {
   1630 	enum cil_syntax syntax[] = {
   1631 		CIL_SYN_STRING,
   1632 		CIL_SYN_STRING,
   1633 		CIL_SYN_END
   1634 	};
   1635 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1636 	char *key = NULL;
   1637 	struct cil_role *role = NULL;
   1638 	int rc = SEPOL_ERR;
   1639 
   1640 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1641 		goto exit;
   1642 	}
   1643 
   1644 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1645 	if (rc != SEPOL_OK) {
   1646 		goto exit;
   1647 	}
   1648 
   1649 	cil_role_init(&role);
   1650 
   1651 	key = parse_current->next->data;
   1652 
   1653 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)role, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLE);
   1654 	if (rc != SEPOL_OK) {
   1655 		goto exit;
   1656 	}
   1657 
   1658 	return SEPOL_OK;
   1659 
   1660 exit:
   1661 	cil_tree_log(parse_current, CIL_ERR, "Bad role declaration");
   1662 	cil_destroy_role(role);
   1663 	cil_clear_node(ast_node);
   1664 	return rc;
   1665 }
   1666 
   1667 void cil_destroy_role(struct cil_role *role)
   1668 {
   1669 	if (role == NULL) {
   1670 		return;
   1671 	}
   1672 
   1673 	cil_symtab_datum_destroy(&role->datum);
   1674 	ebitmap_destroy(role->types);
   1675 	free(role->types);
   1676 	free(role);
   1677 }
   1678 
   1679 int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1680 {
   1681 	enum cil_syntax syntax[] = {
   1682 		CIL_SYN_STRING,
   1683 		CIL_SYN_STRING,
   1684 		CIL_SYN_STRING,
   1685 		CIL_SYN_END
   1686 	};
   1687 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1688 	struct cil_roletype *roletype = NULL;
   1689 	int rc = SEPOL_ERR;
   1690 
   1691 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1692 		goto exit;
   1693 	}
   1694 
   1695 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1696 	if (rc != SEPOL_OK) {
   1697 		goto exit;
   1698 	}
   1699 
   1700 	cil_roletype_init(&roletype);
   1701 
   1702 	roletype->role_str = parse_current->next->data;
   1703 	roletype->type_str = parse_current->next->next->data;
   1704 
   1705 	ast_node->data = roletype;
   1706 	ast_node->flavor = CIL_ROLETYPE;
   1707 
   1708 	return SEPOL_OK;
   1709 
   1710 exit:
   1711 	cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration");
   1712 	cil_destroy_roletype(roletype);
   1713 	return rc;
   1714 }
   1715 
   1716 void cil_destroy_roletype(struct cil_roletype *roletype)
   1717 {
   1718 	if (roletype == NULL) {
   1719 		return;
   1720 	}
   1721 
   1722 	free(roletype);
   1723 }
   1724 
   1725 int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1726 {
   1727 	enum cil_syntax syntax[] = {
   1728 		CIL_SYN_STRING,
   1729 		CIL_SYN_STRING,
   1730 		CIL_SYN_STRING,
   1731 		CIL_SYN_END
   1732 	};
   1733 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1734 	struct cil_userrole *userrole = NULL;
   1735 	int rc = SEPOL_ERR;
   1736 
   1737 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1738 		goto exit;
   1739 	}
   1740 
   1741 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1742 	if (rc != SEPOL_OK) {
   1743 		goto exit;
   1744 	}
   1745 
   1746 	cil_userrole_init(&userrole);
   1747 
   1748 	userrole->user_str = parse_current->next->data;
   1749 	userrole->role_str = parse_current->next->next->data;
   1750 
   1751 	ast_node->data = userrole;
   1752 	ast_node->flavor = CIL_USERROLE;
   1753 
   1754 	return SEPOL_OK;
   1755 
   1756 exit:
   1757 	cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration");
   1758 	cil_destroy_userrole(userrole);
   1759 	return rc;
   1760 }
   1761 
   1762 void cil_destroy_userrole(struct cil_userrole *userrole)
   1763 {
   1764 	if (userrole == NULL) {
   1765 		return;
   1766 	}
   1767 
   1768 	free(userrole);
   1769 }
   1770 
   1771 int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1772 {
   1773 	enum cil_syntax syntax[] = {
   1774 		CIL_SYN_STRING,
   1775 		CIL_SYN_STRING,
   1776 		CIL_SYN_STRING,
   1777 		CIL_SYN_STRING,
   1778 		CIL_SYN_STRING,
   1779 		CIL_SYN_END
   1780 	};
   1781 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1782 	struct cil_roletransition *roletrans = NULL;
   1783 	int rc = SEPOL_ERR;
   1784 
   1785 	if (parse_current == NULL || ast_node == NULL) {
   1786 		goto exit;
   1787 	}
   1788 
   1789 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1790 	if (rc != SEPOL_OK) {
   1791 		goto exit;
   1792 	}
   1793 
   1794 	cil_roletransition_init(&roletrans);
   1795 
   1796 	roletrans->src_str = parse_current->next->data;
   1797 	roletrans->tgt_str = parse_current->next->next->data;
   1798 	roletrans->obj_str = parse_current->next->next->next->data;
   1799 	roletrans->result_str = parse_current->next->next->next->next->data;
   1800 
   1801 	ast_node->data = roletrans;
   1802 	ast_node->flavor = CIL_ROLETRANSITION;
   1803 
   1804 	return SEPOL_OK;
   1805 
   1806 exit:
   1807 	cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule");
   1808 	cil_destroy_roletransition(roletrans);
   1809 	return rc;
   1810 }
   1811 
   1812 void cil_destroy_roletransition(struct cil_roletransition *roletrans)
   1813 {
   1814 	if (roletrans == NULL) {
   1815 		return;
   1816 	}
   1817 
   1818 	free(roletrans);
   1819 }
   1820 
   1821 int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1822 {
   1823 	enum cil_syntax syntax[] = {
   1824 		CIL_SYN_STRING,
   1825 		CIL_SYN_STRING,
   1826 		CIL_SYN_STRING,
   1827 		CIL_SYN_END
   1828 	};
   1829 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1830 	struct cil_roleallow *roleallow = NULL;
   1831 	int rc = SEPOL_ERR;
   1832 
   1833 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1834 		goto exit;
   1835 	}
   1836 
   1837 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1838 	if (rc != SEPOL_OK) {
   1839 		goto exit;
   1840 	}
   1841 
   1842 	cil_roleallow_init(&roleallow);
   1843 
   1844 	roleallow->src_str = parse_current->next->data;
   1845 	roleallow->tgt_str = parse_current->next->next->data;
   1846 
   1847 	ast_node->data = roleallow;
   1848 	ast_node->flavor = CIL_ROLEALLOW;
   1849 
   1850 	return SEPOL_OK;
   1851 
   1852 exit:
   1853 	cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule");
   1854 	cil_destroy_roleallow(roleallow);
   1855 	return rc;
   1856 }
   1857 
   1858 void cil_destroy_roleallow(struct cil_roleallow *roleallow)
   1859 {
   1860 	if (roleallow == NULL) {
   1861 		return;
   1862 	}
   1863 
   1864 	free(roleallow);
   1865 }
   1866 
   1867 int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1868 {
   1869 	enum cil_syntax syntax[] = {
   1870 		CIL_SYN_STRING,
   1871 		CIL_SYN_STRING,
   1872 		CIL_SYN_END
   1873 	};
   1874 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1875 	char *key = NULL;
   1876 	struct cil_roleattribute *attr = NULL;
   1877 	int rc = SEPOL_ERR;
   1878 
   1879 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1880 		goto exit;
   1881 	}
   1882 
   1883 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1884 	if (rc != SEPOL_OK) {
   1885 		goto exit;
   1886 	}
   1887 
   1888 	if (parse_current->next->data == CIL_KEY_SELF) {
   1889 		cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
   1890 		rc = SEPOL_ERR;
   1891 		goto exit;
   1892 	}
   1893 
   1894 	cil_roleattribute_init(&attr);
   1895 
   1896 	key = parse_current->next->data;
   1897 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLEATTRIBUTE);
   1898 	if (rc != SEPOL_OK) {
   1899 		goto exit;
   1900 	}
   1901 
   1902 	return SEPOL_OK;
   1903 exit:
   1904 	cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration");
   1905 	cil_destroy_roleattribute(attr);
   1906 	cil_clear_node(ast_node);
   1907 	return rc;
   1908 }
   1909 
   1910 void cil_destroy_roleattribute(struct cil_roleattribute *attr)
   1911 {
   1912 	if (attr == NULL) {
   1913 		return;
   1914 	}
   1915 
   1916 	if (attr->expr_list != NULL) {
   1917 		/* we don't want to destroy the expression stacks (cil_list) inside
   1918 		 * this list cil_list_destroy destroys sublists, so we need to do it
   1919 		 * manually */
   1920 		struct cil_list_item *expr = attr->expr_list->head;
   1921 		while (expr != NULL) {
   1922 			struct cil_list_item *next = expr->next;
   1923 			cil_list_item_destroy(&expr, CIL_FALSE);
   1924 			expr = next;
   1925 		}
   1926 		free(attr->expr_list);
   1927 		attr->expr_list = NULL;
   1928 	}
   1929 
   1930 	cil_symtab_datum_destroy(&attr->datum);
   1931 	ebitmap_destroy(attr->roles);
   1932 	free(attr->roles);
   1933 	free(attr);
   1934 }
   1935 
   1936 int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   1937 {
   1938 	enum cil_syntax syntax[] = {
   1939 		CIL_SYN_STRING,
   1940 		CIL_SYN_STRING,
   1941 		CIL_SYN_STRING | CIL_SYN_LIST,
   1942 		CIL_SYN_END
   1943 	};
   1944 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1945 	struct cil_roleattributeset *attrset = NULL;
   1946 	int rc = SEPOL_ERR;
   1947 
   1948 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   1949 		goto exit;
   1950 	}
   1951 
   1952 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   1953 	if (rc != SEPOL_OK) {
   1954 		goto exit;
   1955 	}
   1956 
   1957 	cil_roleattributeset_init(&attrset);
   1958 
   1959 	attrset->attr_str = parse_current->next->data;
   1960 
   1961 	rc = cil_gen_expr(parse_current->next->next, CIL_ROLE, &attrset->str_expr);
   1962 	if (rc != SEPOL_OK) {
   1963 		goto exit;
   1964 	}
   1965 	ast_node->data = attrset;
   1966 	ast_node->flavor = CIL_ROLEATTRIBUTESET;
   1967 
   1968 	return SEPOL_OK;
   1969 
   1970 exit:
   1971 	cil_tree_log(parse_current, CIL_ERR, "Bad roleattributeset declaration");
   1972 	cil_destroy_roleattributeset(attrset);
   1973 
   1974 	return rc;
   1975 }
   1976 
   1977 void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset)
   1978 {
   1979 	if (attrset == NULL) {
   1980 		return;
   1981 	}
   1982 
   1983 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
   1984 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
   1985 
   1986 	free(attrset);
   1987 }
   1988 
   1989 int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
   1990 {
   1991 	enum cil_syntax syntax[] = {
   1992 		CIL_SYN_STRING,
   1993 		CIL_SYN_STRING,
   1994 		CIL_SYN_STRING,
   1995 		CIL_SYN_STRING | CIL_SYN_LIST,
   1996 		CIL_SYN_END
   1997 	};
   1998 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   1999 	struct cil_avrule *rule = NULL;
   2000 	int rc = SEPOL_ERR;
   2001 
   2002 	if (parse_current == NULL || ast_node == NULL) {
   2003 		goto exit;
   2004 	}
   2005 
   2006 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2007 	if (rc != SEPOL_OK) {
   2008 		goto exit;
   2009 	}
   2010 
   2011 	cil_avrule_init(&rule);
   2012 
   2013 	rule->is_extended = 0;
   2014 	rule->rule_kind = rule_kind;
   2015 
   2016 	rule->src_str = parse_current->next->data;
   2017 	rule->tgt_str = parse_current->next->next->data;
   2018 
   2019 	rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->perms.classperms);
   2020 	if (rc != SEPOL_OK) {
   2021 		goto exit;
   2022 	}
   2023 
   2024 	ast_node->data = rule;
   2025 	ast_node->flavor = CIL_AVRULE;
   2026 
   2027 	return SEPOL_OK;
   2028 
   2029 exit:
   2030 	cil_tree_log(parse_current, CIL_ERR, "Bad allow rule");
   2031 	cil_destroy_avrule(rule);
   2032 	return rc;
   2033 }
   2034 
   2035 void cil_destroy_avrule(struct cil_avrule *rule)
   2036 {
   2037 	if (rule == NULL) {
   2038 		return;
   2039 	}
   2040 
   2041 	if (!rule->is_extended) {
   2042 		cil_destroy_classperms_list(&rule->perms.classperms);
   2043 	} else {
   2044 		if (rule->perms.x.permx_str == NULL && rule->perms.x.permx != NULL) {
   2045 			cil_destroy_permissionx(rule->perms.x.permx);
   2046 		}
   2047 	}
   2048 
   2049 	free(rule);
   2050 }
   2051 
   2052 int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permissionx *permx)
   2053 {
   2054 	enum cil_syntax syntax[] = {
   2055 		CIL_SYN_STRING,
   2056 		CIL_SYN_STRING,
   2057 		CIL_SYN_LIST,
   2058 		CIL_SYN_END
   2059 	};
   2060 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2061 	int rc = SEPOL_ERR;
   2062 
   2063 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2064 	if (rc != SEPOL_OK) {
   2065 		goto exit;
   2066 	}
   2067 
   2068 	if (parse_current->data == CIL_KEY_IOCTL) {
   2069 		permx->kind = CIL_PERMX_KIND_IOCTL;
   2070 	} else {
   2071 		cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\"\n", (char *)parse_current->data);
   2072 		rc = SEPOL_ERR;
   2073 		goto exit;
   2074 	}
   2075 
   2076 	permx->obj_str = parse_current->next->data;
   2077 
   2078 	rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str);
   2079 	if (rc != SEPOL_OK) {
   2080 		goto exit;
   2081 	}
   2082 
   2083 	return SEPOL_OK;
   2084 
   2085 exit:
   2086 	cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content");
   2087 	return rc;
   2088 }
   2089 
   2090 int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   2091 {
   2092 	enum cil_syntax syntax[] = {
   2093 		CIL_SYN_STRING,
   2094 		CIL_SYN_STRING,
   2095 		CIL_SYN_LIST,
   2096 		CIL_SYN_END
   2097 	};
   2098 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2099 	char *key = NULL;
   2100 	struct cil_permissionx *permx = NULL;
   2101 	int rc = SEPOL_ERR;
   2102 
   2103 	if (parse_current == NULL || ast_node == NULL) {
   2104 		goto exit;
   2105 	}
   2106 
   2107 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2108 	if (rc != SEPOL_OK) {
   2109 		goto exit;
   2110 	}
   2111 
   2112 	cil_permissionx_init(&permx);
   2113 
   2114 	key = parse_current->next->data;
   2115 
   2116 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX);
   2117 	if (rc != SEPOL_OK) {
   2118 		goto exit;
   2119 	}
   2120 
   2121 	rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx);
   2122 	if (rc != SEPOL_OK) {
   2123 		goto exit;
   2124 	}
   2125 
   2126 	return SEPOL_OK;
   2127 
   2128 exit:
   2129 	cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement");
   2130 	cil_destroy_permissionx(permx);
   2131 	cil_clear_node(ast_node);
   2132 	return rc;
   2133 }
   2134 
   2135 void cil_destroy_permissionx(struct cil_permissionx *permx)
   2136 {
   2137 	if (permx == NULL) {
   2138 		return;
   2139 	}
   2140 
   2141 	cil_symtab_datum_destroy(&permx->datum);
   2142 
   2143 	cil_list_destroy(&permx->expr_str, CIL_TRUE);
   2144 	ebitmap_destroy(permx->perms);
   2145 	free(permx->perms);
   2146 	free(permx);
   2147 }
   2148 
   2149 int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
   2150 {
   2151 	enum cil_syntax syntax[] = {
   2152 		CIL_SYN_STRING,
   2153 		CIL_SYN_STRING,
   2154 		CIL_SYN_STRING,
   2155 		CIL_SYN_STRING | CIL_SYN_LIST,
   2156 		CIL_SYN_END
   2157 	};
   2158 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2159 	struct cil_avrule *rule = NULL;
   2160 	int rc = SEPOL_ERR;
   2161 
   2162 	if (parse_current == NULL || ast_node == NULL) {
   2163 		goto exit;
   2164 	}
   2165 
   2166 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2167 	if (rc != SEPOL_OK) {
   2168 		goto exit;
   2169 	}
   2170 
   2171 	cil_avrule_init(&rule);
   2172 
   2173 	rule->is_extended = 1;
   2174 	rule->rule_kind = rule_kind;
   2175 	rule->src_str = parse_current->next->data;
   2176 	rule->tgt_str = parse_current->next->next->data;
   2177 
   2178 	if (parse_current->next->next->next->cl_head == NULL) {
   2179 		rule->perms.x.permx_str = parse_current->next->next->next->data;
   2180 	} else {
   2181 		cil_permissionx_init(&rule->perms.x.permx);
   2182 
   2183 		rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->perms.x.permx);
   2184 		if (rc != SEPOL_OK) {
   2185 			goto exit;
   2186 		}
   2187 	}
   2188 
   2189 	ast_node->data = rule;
   2190 	ast_node->flavor = CIL_AVRULEX;
   2191 
   2192 	return SEPOL_OK;
   2193 
   2194 exit:
   2195 	cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule");
   2196 	cil_destroy_avrule(rule);
   2197 	return rc;
   2198 }
   2199 
   2200 int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
   2201 {
   2202 	enum cil_syntax syntax[] = {
   2203 		CIL_SYN_STRING,
   2204 		CIL_SYN_STRING,
   2205 		CIL_SYN_STRING,
   2206 		CIL_SYN_STRING,
   2207 		CIL_SYN_STRING,
   2208 		CIL_SYN_END
   2209 	};
   2210 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2211 	struct cil_type_rule *rule = NULL;
   2212 	int rc = SEPOL_ERR;
   2213 
   2214 	if (parse_current == NULL || ast_node == NULL) {
   2215 		goto exit;
   2216 	}
   2217 
   2218 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2219 	if (rc != SEPOL_OK) {
   2220 		goto exit;
   2221 	}
   2222 
   2223 	cil_type_rule_init(&rule);
   2224 
   2225 	rule->rule_kind = rule_kind;
   2226 	rule->src_str = parse_current->next->data;
   2227 	rule->tgt_str = parse_current->next->next->data;
   2228 	rule->obj_str = parse_current->next->next->next->data;
   2229 	rule->result_str = parse_current->next->next->next->next->data;
   2230 
   2231 	ast_node->data = rule;
   2232 	ast_node->flavor = CIL_TYPE_RULE;
   2233 
   2234 	return SEPOL_OK;
   2235 
   2236 exit:
   2237 	cil_tree_log(parse_current, CIL_ERR, "Bad type rule");
   2238 	cil_destroy_type_rule(rule);
   2239 	return rc;
   2240 }
   2241 
   2242 void cil_destroy_type_rule(struct cil_type_rule *rule)
   2243 {
   2244 	if (rule == NULL) {
   2245 		return;
   2246 	}
   2247 
   2248 	free(rule);
   2249 }
   2250 
   2251 int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   2252 {
   2253 	enum cil_syntax syntax[] = {
   2254 		CIL_SYN_STRING,
   2255 		CIL_SYN_STRING,
   2256 		CIL_SYN_END
   2257 	};
   2258 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2259 	char *key = NULL;
   2260 	struct cil_type *type = NULL;
   2261 	int rc = SEPOL_ERR;
   2262 
   2263 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   2264 		goto exit;
   2265 	}
   2266 
   2267 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2268 	if (rc != SEPOL_OK) {
   2269 		goto exit;
   2270 	}
   2271 
   2272 	if (parse_current->next->data == CIL_KEY_SELF) {
   2273 		cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
   2274 		rc = SEPOL_ERR;
   2275 		goto exit;
   2276 	}
   2277 
   2278 	cil_type_init(&type);
   2279 
   2280 	key = parse_current->next->data;
   2281 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE);
   2282 	if (rc != SEPOL_OK) {
   2283 		goto exit;
   2284 	}
   2285 
   2286 	return SEPOL_OK;
   2287 
   2288 exit:
   2289 	cil_tree_log(parse_current, CIL_ERR, "Bad type declaration");
   2290 	cil_destroy_type(type);
   2291 	cil_clear_node(ast_node);
   2292 	return rc;
   2293 }
   2294 
   2295 void cil_destroy_type(struct cil_type *type)
   2296 {
   2297 	if (type == NULL) {
   2298 		return;
   2299 	}
   2300 
   2301 	cil_symtab_datum_destroy(&type->datum);
   2302 	free(type);
   2303 }
   2304 
   2305 int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   2306 {
   2307 	enum cil_syntax syntax[] = {
   2308 		CIL_SYN_STRING,
   2309 		CIL_SYN_STRING,
   2310 		CIL_SYN_END
   2311 	};
   2312 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2313 	char *key = NULL;
   2314 	struct cil_typeattribute *attr = NULL;
   2315 	int rc = SEPOL_ERR;
   2316 
   2317 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   2318 		goto exit;
   2319 	}
   2320 
   2321 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2322 	if (rc != SEPOL_OK) {
   2323 		goto exit;
   2324 	}
   2325 
   2326 	if (parse_current->next->data == CIL_KEY_SELF) {
   2327 		cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
   2328 		rc = SEPOL_ERR;
   2329 		goto exit;
   2330 	}
   2331 
   2332 	cil_typeattribute_init(&attr);
   2333 
   2334 	key = parse_current->next->data;
   2335 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
   2336 	if (rc != SEPOL_OK) {
   2337 		goto exit;
   2338 	}
   2339 
   2340 	return SEPOL_OK;
   2341 
   2342 exit:
   2343 	cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration");
   2344 	cil_destroy_typeattribute(attr);
   2345 	cil_clear_node(ast_node);
   2346 	return rc;
   2347 }
   2348 
   2349 void cil_destroy_typeattribute(struct cil_typeattribute *attr)
   2350 {
   2351 	if (attr == NULL) {
   2352 		return;
   2353 	}
   2354 
   2355 	cil_symtab_datum_destroy(&attr->datum);
   2356 
   2357 	if (attr->expr_list != NULL) {
   2358 		/* we don't want to destroy the expression stacks (cil_list) inside
   2359 		 * this list cil_list_destroy destroys sublists, so we need to do it
   2360 		 * manually */
   2361 		struct cil_list_item *expr = attr->expr_list->head;
   2362 		while (expr != NULL) {
   2363 			struct cil_list_item *next = expr->next;
   2364 			cil_list_item_destroy(&expr, CIL_FALSE);
   2365 			expr = next;
   2366 		}
   2367 		free(attr->expr_list);
   2368 		attr->expr_list = NULL;
   2369 	}
   2370 	ebitmap_destroy(attr->types);
   2371 	free(attr->types);
   2372 	free(attr);
   2373 }
   2374 
   2375 int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
   2376 {
   2377 	enum cil_syntax syntax[] = {
   2378 		CIL_SYN_STRING,
   2379 		CIL_SYN_STRING,
   2380 		CIL_SYN_STRING,
   2381 		CIL_SYN_END
   2382 	};
   2383 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2384 	char *key = NULL;
   2385 	struct cil_bool *boolean = NULL;
   2386 	int rc = SEPOL_ERR;
   2387 
   2388 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   2389 		goto exit;
   2390 	}
   2391 
   2392 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2393 	if (rc != SEPOL_OK) {
   2394 		goto exit;
   2395 	}
   2396 
   2397 	cil_bool_init(&boolean);
   2398 
   2399 	key = parse_current->next->data;
   2400 
   2401 	if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
   2402 		boolean->value = CIL_TRUE;
   2403 	} else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
   2404 		boolean->value = CIL_FALSE;
   2405 	} else {
   2406 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
   2407 		rc = SEPOL_ERR;
   2408 		goto exit;
   2409 	}
   2410 
   2411 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)boolean, (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL);
   2412 	if (rc != SEPOL_OK) {
   2413 		goto exit;
   2414 	}
   2415 
   2416 	return SEPOL_OK;
   2417 
   2418 exit:
   2419 	if (tunableif) {
   2420 		cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration");
   2421 	} else {
   2422 		cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration");
   2423 	}
   2424 	cil_destroy_bool(boolean);
   2425 	cil_clear_node(ast_node);
   2426 	return rc;
   2427 }
   2428 
   2429 void cil_destroy_bool(struct cil_bool *boolean)
   2430 {
   2431 	if (boolean == NULL) {
   2432 		return;
   2433 	}
   2434 
   2435 	cil_symtab_datum_destroy(&boolean->datum);
   2436 	free(boolean);
   2437 }
   2438 
   2439 int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   2440 {
   2441 	enum cil_syntax syntax[] = {
   2442 		CIL_SYN_STRING,
   2443 		CIL_SYN_STRING,
   2444 		CIL_SYN_STRING,
   2445 		CIL_SYN_END
   2446 	};
   2447 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2448 	char *key = NULL;
   2449 	struct cil_tunable *tunable = NULL;
   2450 	int rc = SEPOL_ERR;
   2451 
   2452 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   2453 		goto exit;
   2454 	}
   2455 
   2456 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2457 	if (rc != SEPOL_OK) {
   2458 		goto exit;
   2459 	}
   2460 
   2461 	cil_tunable_init(&tunable);
   2462 
   2463 	key = parse_current->next->data;
   2464 
   2465 	if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
   2466 		tunable->value = CIL_TRUE;
   2467 	} else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
   2468 		tunable->value = CIL_FALSE;
   2469 	} else {
   2470 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
   2471 		rc = SEPOL_ERR;
   2472 		goto exit;
   2473 	}
   2474 
   2475 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)tunable, (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE);
   2476 	if (rc != SEPOL_OK) {
   2477 		goto exit;
   2478 	}
   2479 
   2480 	return SEPOL_OK;
   2481 
   2482 exit:
   2483 	cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration");
   2484 	cil_destroy_tunable(tunable);
   2485 	cil_clear_node(ast_node);
   2486 	return rc;
   2487 }
   2488 
   2489 void cil_destroy_tunable(struct cil_tunable *tunable)
   2490 {
   2491 	if (tunable == NULL) {
   2492 		return;
   2493 	}
   2494 
   2495 	cil_symtab_datum_destroy(&tunable->datum);
   2496 	free(tunable);
   2497 }
   2498 
   2499 static enum cil_flavor __cil_get_expr_operator_flavor(const char *op)
   2500 {
   2501 	if (op == NULL) return CIL_NONE;
   2502 	else if (op == CIL_KEY_AND)   return CIL_AND;
   2503 	else if (op == CIL_KEY_OR)    return CIL_OR;
   2504 	else if (op == CIL_KEY_NOT)   return CIL_NOT;
   2505 	else if (op == CIL_KEY_EQ)    return CIL_EQ;    /* Only conditional */
   2506 	else if (op == CIL_KEY_NEQ)   return CIL_NEQ;   /* Only conditional */
   2507 	else if (op == CIL_KEY_XOR)   return CIL_XOR;
   2508 	else if (op == CIL_KEY_ALL)   return CIL_ALL;   /* Only set and permissionx */
   2509 	else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */
   2510 	else return CIL_NONE;
   2511 }
   2512 
   2513 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth);
   2514 
   2515 static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth)
   2516 {
   2517 	int rc = SEPOL_ERR;
   2518 	enum cil_flavor op;
   2519 
   2520 	if (flavor == CIL_BOOL && *depth > COND_EXPR_MAXDEPTH) {
   2521 		cil_log(CIL_ERR, "Max depth of %d exceeded for boolean expression\n", COND_EXPR_MAXDEPTH);
   2522 		goto exit;
   2523 	}
   2524 
   2525 	op = __cil_get_expr_operator_flavor(current->data);
   2526 
   2527 	rc = cil_verify_expr_syntax(current, op, flavor);
   2528 	if (rc != SEPOL_OK) {
   2529 		goto exit;
   2530 	}
   2531 
   2532 	if (op != CIL_NONE) {
   2533 		cil_list_append(expr, CIL_OP, (void *)op);
   2534 		current = current->next;
   2535 	}
   2536 
   2537 	if (op == CIL_NONE || op == CIL_ALL) {
   2538 		(*depth)++;
   2539 	}
   2540 
   2541 	for (;current != NULL; current = current->next) {
   2542 		rc = __cil_fill_expr(current, flavor, expr, depth);
   2543 		if (rc != SEPOL_OK) {
   2544 			goto exit;
   2545 		}
   2546 	}
   2547 
   2548 	(*depth)--;
   2549 
   2550 	return SEPOL_OK;
   2551 
   2552 exit:
   2553 	return rc;
   2554 }
   2555 
   2556 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth)
   2557 {
   2558 	int rc = SEPOL_ERR;
   2559 
   2560 	if (current->cl_head == NULL) {
   2561 		enum cil_flavor op = __cil_get_expr_operator_flavor(current->data);
   2562 		if (op != CIL_NONE) {
   2563 			cil_log(CIL_ERR, "Operator (%s) not in an expression\n", (char*)current->data);
   2564 			goto exit;
   2565 		}
   2566 		cil_list_append(expr, CIL_STRING, current->data);
   2567 	} else {
   2568 		struct cil_list *sub_expr;
   2569 		cil_list_init(&sub_expr, flavor);
   2570 		rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr, depth);
   2571 		if (rc != SEPOL_OK) {
   2572 			cil_list_destroy(&sub_expr, CIL_TRUE);
   2573 			goto exit;
   2574 		}
   2575 		cil_list_append(expr, CIL_LIST, sub_expr);
   2576 	}
   2577 
   2578 	return SEPOL_OK;
   2579 
   2580 exit:
   2581 	return rc;
   2582 }
   2583 
   2584 
   2585 int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
   2586 {
   2587 	int rc = SEPOL_ERR;
   2588 	int depth = 0;
   2589 
   2590 	cil_list_init(expr, flavor);
   2591 
   2592 	if (current->cl_head == NULL) {
   2593 		rc = __cil_fill_expr(current, flavor, *expr, &depth);
   2594 	} else {
   2595 		rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr, &depth);
   2596 	}
   2597 
   2598 	if (rc != SEPOL_OK) {
   2599 		cil_list_destroy(expr, CIL_TRUE);
   2600 		cil_log(CIL_ERR, "Bad expression\n");
   2601 	}
   2602 
   2603 	return rc;
   2604 }
   2605 
   2606 static enum cil_flavor __cil_get_constraint_operator_flavor(const char *op)
   2607 {
   2608 	if (op == CIL_KEY_AND)         return CIL_AND;
   2609 	else if (op == CIL_KEY_OR)     return CIL_OR;
   2610 	else if (op == CIL_KEY_NOT)    return CIL_NOT;
   2611 	else if (op == CIL_KEY_EQ)     return CIL_EQ;
   2612 	else if (op == CIL_KEY_NEQ)    return CIL_NEQ;
   2613 	else if (op == CIL_KEY_CONS_DOM)    return CIL_CONS_DOM;
   2614 	else if (op == CIL_KEY_CONS_DOMBY)  return CIL_CONS_DOMBY;
   2615 	else if (op == CIL_KEY_CONS_INCOMP) return CIL_CONS_INCOMP;
   2616 	else return CIL_NONE;
   2617 }
   2618 
   2619 static enum cil_flavor __cil_get_constraint_operand_flavor(const char *operand)
   2620 {
   2621 	if (operand == NULL) return CIL_LIST;
   2622 	else if (operand == CIL_KEY_CONS_T1) return CIL_CONS_T1;
   2623 	else if (operand == CIL_KEY_CONS_T2) return CIL_CONS_T2;
   2624 	else if (operand == CIL_KEY_CONS_T3) return CIL_CONS_T3;
   2625 	else if (operand == CIL_KEY_CONS_R1) return CIL_CONS_R1;
   2626 	else if (operand == CIL_KEY_CONS_R2) return CIL_CONS_R2;
   2627 	else if (operand == CIL_KEY_CONS_R3) return CIL_CONS_R3;
   2628 	else if (operand == CIL_KEY_CONS_U1) return CIL_CONS_U1;
   2629 	else if (operand == CIL_KEY_CONS_U2) return CIL_CONS_U2;
   2630 	else if (operand == CIL_KEY_CONS_U3) return CIL_CONS_U3;
   2631 	else if (operand == CIL_KEY_CONS_L1) return CIL_CONS_L1;
   2632 	else if (operand == CIL_KEY_CONS_L2) return CIL_CONS_L2;
   2633 	else if (operand == CIL_KEY_CONS_H1) return CIL_CONS_H1;
   2634 	else if (operand == CIL_KEY_CONS_H2) return CIL_CONS_H2;
   2635 	else return CIL_STRING;
   2636 }
   2637 
   2638 static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current, enum cil_flavor expr_flavor, enum cil_flavor op, struct cil_list **leaf_expr)
   2639 {
   2640 	int rc = SEPOL_ERR;
   2641 	enum cil_flavor leaf_expr_flavor = CIL_NONE;
   2642 	enum cil_flavor l_flavor = CIL_NONE;
   2643 	enum cil_flavor r_flavor = CIL_NONE;
   2644 
   2645 	l_flavor = __cil_get_constraint_operand_flavor(current->next->data);
   2646 	r_flavor = __cil_get_constraint_operand_flavor(current->next->next->data);
   2647 
   2648 	switch (l_flavor) {
   2649 	case CIL_CONS_U1:
   2650 	case CIL_CONS_U2:
   2651 	case CIL_CONS_U3:
   2652 		leaf_expr_flavor = CIL_USER;
   2653 		break;
   2654 	case CIL_CONS_R1:
   2655 	case CIL_CONS_R2:
   2656 	case CIL_CONS_R3:
   2657 		leaf_expr_flavor = CIL_ROLE;
   2658 		break;
   2659 	case CIL_CONS_T1:
   2660 	case CIL_CONS_T2:
   2661 	case CIL_CONS_T3:
   2662 		leaf_expr_flavor = CIL_TYPE;
   2663 		break;
   2664 	case CIL_CONS_L1:
   2665 	case CIL_CONS_L2:
   2666 	case CIL_CONS_H1:
   2667 	case CIL_CONS_H2:
   2668 		leaf_expr_flavor = CIL_LEVEL;
   2669 		break;
   2670 	default:
   2671 		cil_log(CIL_ERR, "Invalid left operand (%s)\n", (char*)current->next->data);
   2672 		goto exit;
   2673 	}
   2674 
   2675 	rc = cil_verify_constraint_leaf_expr_syntax(l_flavor, r_flavor, op, expr_flavor);
   2676 	if (rc != SEPOL_OK) {
   2677 		goto exit;
   2678 	}
   2679 
   2680 	cil_list_init(leaf_expr, leaf_expr_flavor);
   2681 
   2682 	cil_list_append(*leaf_expr, CIL_OP, (void *)op);
   2683 
   2684 	cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)l_flavor);
   2685 
   2686 	if (r_flavor == CIL_STRING) {
   2687 		cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data);
   2688 	} else if (r_flavor == CIL_LIST) {
   2689 		struct cil_list *sub_list;
   2690 		cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
   2691 		cil_list_append(*leaf_expr, CIL_LIST, &sub_list);
   2692 	} else {
   2693 		cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor);
   2694 	}
   2695 
   2696 	return SEPOL_OK;
   2697 
   2698 exit:
   2699 
   2700 	return SEPOL_ERR;
   2701 }
   2702 
   2703 static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr, int *depth)
   2704 {
   2705 	int rc = SEPOL_ERR;
   2706 	enum cil_flavor op;
   2707 	struct cil_list *lexpr;
   2708 	struct cil_list *rexpr;
   2709 
   2710 	if (current->data == NULL || current->cl_head != NULL) {
   2711 		cil_log(CIL_ERR, "Expected a string at the start of the constraint expression\n");
   2712 		goto exit;
   2713 	}
   2714 
   2715 	if (*depth > CEXPR_MAXDEPTH) {
   2716 		cil_log(CIL_ERR, "Max depth of %d exceeded for constraint expression\n", CEXPR_MAXDEPTH);
   2717 		rc = SEPOL_ERR;
   2718 		goto exit;
   2719 	}
   2720 
   2721 	op = __cil_get_constraint_operator_flavor(current->data);
   2722 
   2723 	rc = cil_verify_constraint_expr_syntax(current, op);
   2724 	if (rc != SEPOL_OK) {
   2725 		goto exit;
   2726 	}
   2727 
   2728 	switch (op) {
   2729 	case CIL_EQ:
   2730 	case CIL_NEQ:
   2731 	case CIL_CONS_DOM:
   2732 	case CIL_CONS_DOMBY:
   2733 	case CIL_CONS_INCOMP:
   2734 		(*depth)++;
   2735 		rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr);
   2736 		if (rc != SEPOL_OK) {
   2737 			goto exit;
   2738 		}
   2739 		break;
   2740 	case CIL_NOT:
   2741 		rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth);
   2742 		if (rc != SEPOL_OK) {
   2743 			goto exit;
   2744 		}
   2745 		cil_list_init(expr, flavor);
   2746 		cil_list_append(*expr, CIL_OP, (void *)op);
   2747 		cil_list_append(*expr, CIL_LIST, lexpr);
   2748 		break;
   2749 	default:
   2750 		rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth);
   2751 		if (rc != SEPOL_OK) {
   2752 			goto exit;
   2753 		}
   2754 		rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr, depth);
   2755 		if (rc != SEPOL_OK) {
   2756 			cil_list_destroy(&lexpr, CIL_TRUE);
   2757 			goto exit;
   2758 		}
   2759 		cil_list_init(expr, flavor);
   2760 		cil_list_append(*expr, CIL_OP, (void *)op);
   2761 		cil_list_append(*expr, CIL_LIST, lexpr);
   2762 		cil_list_append(*expr, CIL_LIST, rexpr);
   2763 		break;
   2764 	}
   2765 
   2766 	(*depth)--;
   2767 
   2768 	return SEPOL_OK;
   2769 exit:
   2770 
   2771 	return rc;
   2772 }
   2773 
   2774 int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
   2775 {
   2776 	int rc = SEPOL_ERR;
   2777 	int depth = 0;
   2778 
   2779 	if (current->cl_head == NULL) {
   2780 		goto exit;
   2781 	}
   2782 
   2783 	rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr, &depth);
   2784 	if (rc != SEPOL_OK) {
   2785 		goto exit;
   2786 	}
   2787 
   2788 	return SEPOL_OK;
   2789 
   2790 exit:
   2791 
   2792 	cil_log(CIL_ERR, "Bad expression tree for constraint\n");
   2793 	return rc;
   2794 }
   2795 
   2796 int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
   2797 {
   2798 	enum cil_syntax syntax[] = {
   2799 		CIL_SYN_STRING,
   2800 		CIL_SYN_STRING | CIL_SYN_LIST,
   2801 		CIL_SYN_LIST,
   2802 		CIL_SYN_LIST | CIL_SYN_END,
   2803 		CIL_SYN_END
   2804 	};
   2805 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2806 	struct cil_booleanif *bif = NULL;
   2807 	struct cil_tree_node *next = NULL;
   2808 	struct cil_tree_node *cond = NULL;
   2809 	int rc = SEPOL_ERR;
   2810 
   2811 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   2812 		goto exit;
   2813 	}
   2814 
   2815 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2816 	if (rc != SEPOL_OK) {
   2817 		goto exit;
   2818 	}
   2819 
   2820 	cil_boolif_init(&bif);
   2821 	bif->preserved_tunable = tunableif;
   2822 
   2823 	rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr);
   2824 	if (rc != SEPOL_OK) {
   2825 		goto exit;
   2826 	}
   2827 
   2828 	cond = parse_current->next->next;
   2829 
   2830 	/* Destroying expr tree after stack is created*/
   2831 	if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
   2832 		cond->cl_head->data != CIL_KEY_CONDFALSE) {
   2833 		rc = SEPOL_ERR;
   2834 		cil_log(CIL_ERR, "Conditional neither true nor false\n");
   2835 		goto exit;
   2836 	}
   2837 
   2838 	if (cond->next != NULL) {
   2839 		cond = cond->next;
   2840 		if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
   2841 			cond->cl_head->data != CIL_KEY_CONDFALSE) {
   2842 			rc = SEPOL_ERR;
   2843 			cil_log(CIL_ERR, "Conditional neither true nor false\n");
   2844 			goto exit;
   2845 		}
   2846 	}
   2847 
   2848 
   2849 	next = parse_current->next->next;
   2850 	cil_tree_subtree_destroy(parse_current->next);
   2851 	parse_current->next = next;
   2852 
   2853 	ast_node->flavor = CIL_BOOLEANIF;
   2854 	ast_node->data = bif;
   2855 
   2856 	return SEPOL_OK;
   2857 
   2858 exit:
   2859 	if (tunableif) {
   2860 		cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration");
   2861 	} else {
   2862 		cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration");
   2863 	}
   2864 	cil_destroy_boolif(bif);
   2865 	return rc;
   2866 }
   2867 
   2868 void cil_destroy_boolif(struct cil_booleanif *bif)
   2869 {
   2870 	if (bif == NULL) {
   2871 		return;
   2872 	}
   2873 
   2874 	cil_list_destroy(&bif->str_expr, CIL_TRUE);
   2875 	cil_list_destroy(&bif->datum_expr, CIL_FALSE);
   2876 
   2877 	free(bif);
   2878 }
   2879 
   2880 int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   2881 {
   2882 	enum cil_syntax syntax[] = {
   2883 		CIL_SYN_STRING,
   2884 		CIL_SYN_STRING | CIL_SYN_LIST,
   2885 		CIL_SYN_LIST,
   2886 		CIL_SYN_LIST | CIL_SYN_END,
   2887 		CIL_SYN_END
   2888 	};
   2889 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2890 	struct cil_tunableif *tif = NULL;
   2891 	struct cil_tree_node *next = NULL;
   2892 	struct cil_tree_node *cond = NULL;
   2893 	int rc = SEPOL_ERR;
   2894 
   2895 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   2896 		goto exit;
   2897 	}
   2898 
   2899 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2900 	if (rc != SEPOL_OK) {
   2901 		goto exit;
   2902 	}
   2903 
   2904 	cil_tunif_init(&tif);
   2905 
   2906 	rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr);
   2907 	if (rc != SEPOL_OK) {
   2908 		goto exit;
   2909 	}
   2910 
   2911 	cond = parse_current->next->next;
   2912 
   2913 	if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
   2914 		cond->cl_head->data != CIL_KEY_CONDFALSE) {
   2915 		rc = SEPOL_ERR;
   2916 		cil_log(CIL_ERR, "Conditional neither true nor false\n");
   2917 		goto exit;
   2918 	}
   2919 
   2920 	if (cond->next != NULL) {
   2921 		cond = cond->next;
   2922 
   2923 		if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
   2924 			cond->cl_head->data != CIL_KEY_CONDFALSE) {
   2925 			rc = SEPOL_ERR;
   2926 			cil_log(CIL_ERR, "Conditional neither true nor false\n");
   2927 			goto exit;
   2928 		}
   2929 	}
   2930 
   2931 	/* Destroying expr tree after stack is created*/
   2932 	next = parse_current->next->next;
   2933 	cil_tree_subtree_destroy(parse_current->next);
   2934 	parse_current->next = next;
   2935 
   2936 	ast_node->flavor = CIL_TUNABLEIF;
   2937 	ast_node->data = tif;
   2938 
   2939 	return SEPOL_OK;
   2940 
   2941 exit:
   2942 	cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration");
   2943 	cil_destroy_tunif(tif);
   2944 	return rc;
   2945 }
   2946 
   2947 void cil_destroy_tunif(struct cil_tunableif *tif)
   2948 {
   2949 	if (tif == NULL) {
   2950 		return;
   2951 	}
   2952 
   2953 	cil_list_destroy(&tif->str_expr, CIL_TRUE);
   2954 	cil_list_destroy(&tif->datum_expr, CIL_FALSE);
   2955 
   2956 	free(tif);
   2957 }
   2958 
   2959 int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   2960 {
   2961 	enum cil_syntax syntax[] = {
   2962 		CIL_SYN_STRING,
   2963 		CIL_SYN_N_LISTS,
   2964 		CIL_SYN_END
   2965 	};
   2966 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   2967 	int rc = SEPOL_ERR;
   2968 	struct cil_condblock *cb = NULL;
   2969 
   2970 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   2971 		goto exit;
   2972 	}
   2973 
   2974 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   2975 	if (rc != SEPOL_OK) {
   2976 		goto exit;
   2977 	}
   2978 
   2979 	if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) {
   2980 		rc = SEPOL_ERR;
   2981 		cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n");
   2982 		goto exit;
   2983 	}
   2984 
   2985 	ast_node->flavor = CIL_CONDBLOCK;
   2986 
   2987 	cil_condblock_init(&cb);
   2988 	cb->flavor = flavor;
   2989 
   2990 	ast_node->data = cb;
   2991 
   2992 	return SEPOL_OK;
   2993 
   2994 exit:
   2995 	cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration",
   2996 		(char*)parse_current->data);
   2997 	cil_destroy_condblock(cb);
   2998 	return rc;
   2999 }
   3000 
   3001 void cil_destroy_condblock(struct cil_condblock *cb)
   3002 {
   3003 	if (cb == NULL) {
   3004 		return;
   3005 	}
   3006 
   3007 	cil_symtab_array_destroy(cb->symtab);
   3008 	free(cb);
   3009 }
   3010 
   3011 int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   3012 {
   3013 	enum cil_syntax syntax[] = {
   3014 		CIL_SYN_STRING,
   3015 		CIL_SYN_STRING,
   3016 		CIL_SYN_END
   3017 	};
   3018 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3019 	char *key = NULL;
   3020 	struct cil_alias *alias = NULL;
   3021 	enum cil_sym_index sym_index;
   3022 	int rc = SEPOL_ERR;
   3023 
   3024 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3025 		goto exit;
   3026 	}
   3027 
   3028 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3029 	if (rc != SEPOL_OK) {
   3030 		goto exit;
   3031 	}
   3032 
   3033 	if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) {
   3034 		cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
   3035 		rc = SEPOL_ERR;
   3036 		goto exit;
   3037 	}
   3038 
   3039 	cil_alias_init(&alias);
   3040 
   3041 	key = parse_current->next->data;
   3042 
   3043 	rc = cil_flavor_to_symtab_index(flavor, &sym_index);
   3044 	if (rc != SEPOL_OK) {
   3045 		goto exit;
   3046 	}
   3047 
   3048 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor);
   3049 	if (rc != SEPOL_OK) {
   3050 		goto exit;
   3051 	}
   3052 
   3053 	return SEPOL_OK;
   3054 
   3055 exit:
   3056 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data);
   3057 	cil_destroy_alias(alias);
   3058 	cil_clear_node(ast_node);
   3059 	return rc;
   3060 }
   3061 
   3062 void cil_destroy_alias(struct cil_alias *alias)
   3063 {
   3064 	if (alias == NULL) {
   3065 		return;
   3066 	}
   3067 
   3068 	cil_symtab_datum_destroy(&alias->datum);
   3069 	alias->actual = NULL;
   3070 
   3071 	free(alias);
   3072 }
   3073 
   3074 int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   3075 {
   3076 	int rc = SEPOL_ERR;
   3077 	enum cil_syntax syntax[] = {
   3078 		CIL_SYN_STRING,
   3079 		CIL_SYN_STRING,
   3080 		CIL_SYN_STRING,
   3081 		CIL_SYN_END
   3082 	};
   3083 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3084 	struct cil_aliasactual *aliasactual = NULL;
   3085 
   3086 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3087 		goto exit;
   3088 	}
   3089 
   3090 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3091 	if (rc != SEPOL_OK) {
   3092 		goto exit;
   3093 	}
   3094 
   3095 	if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) {
   3096 		cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
   3097 		rc = SEPOL_ERR;
   3098 		goto exit;
   3099 	}
   3100 
   3101 	cil_aliasactual_init(&aliasactual);
   3102 
   3103 	aliasactual->alias_str = parse_current->next->data;
   3104 
   3105 	aliasactual->actual_str = parse_current->next->next->data;
   3106 
   3107 	ast_node->data = aliasactual;
   3108 	ast_node->flavor = flavor;
   3109 
   3110 	return SEPOL_OK;
   3111 
   3112 exit:
   3113 	cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current));
   3114 	cil_clear_node(ast_node);
   3115 	return rc;
   3116 }
   3117 
   3118 void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual)
   3119 {
   3120 	if (aliasactual == NULL) {
   3121 		return;
   3122 	}
   3123 
   3124 	free(aliasactual);
   3125 }
   3126 
   3127 int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3128 {
   3129 	enum cil_syntax syntax[] = {
   3130 		CIL_SYN_STRING,
   3131 		CIL_SYN_STRING,
   3132 		CIL_SYN_STRING | CIL_SYN_LIST,
   3133 		CIL_SYN_END
   3134 	};
   3135 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3136 	struct cil_typeattributeset *attrset = NULL;
   3137 	int rc = SEPOL_ERR;
   3138 
   3139 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3140 		goto exit;
   3141 	}
   3142 
   3143 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3144 	if (rc != SEPOL_OK) {
   3145 		goto exit;
   3146 	}
   3147 
   3148 	cil_typeattributeset_init(&attrset);
   3149 
   3150 	attrset->attr_str = parse_current->next->data;
   3151 
   3152 	rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr);
   3153 	if (rc != SEPOL_OK) {
   3154 		goto exit;
   3155 	}
   3156 	ast_node->data = attrset;
   3157 	ast_node->flavor = CIL_TYPEATTRIBUTESET;
   3158 
   3159 	return SEPOL_OK;
   3160 
   3161 exit:
   3162 	cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement");
   3163 	cil_destroy_typeattributeset(attrset);
   3164 	return rc;
   3165 }
   3166 
   3167 void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset)
   3168 {
   3169 	if (attrset == NULL) {
   3170 		return;
   3171 	}
   3172 
   3173 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
   3174 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
   3175 
   3176 	free(attrset);
   3177 }
   3178 
   3179 int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3180 {
   3181 	enum cil_syntax syntax[] = {
   3182 		CIL_SYN_STRING,
   3183 		CIL_SYN_STRING | CIL_SYN_LIST,
   3184 		CIL_SYN_STRING,
   3185 		CIL_SYN_END
   3186 	};
   3187 	char *expand_str;
   3188 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3189 	struct cil_expandtypeattribute *expandattr = NULL;
   3190 	int rc = SEPOL_ERR;
   3191 
   3192 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3193 		goto exit;
   3194 	}
   3195 
   3196 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3197 	if (rc != SEPOL_OK) {
   3198 		goto exit;
   3199 	}
   3200 
   3201 	cil_expandtypeattribute_init(&expandattr);
   3202 
   3203 	if (parse_current->next->cl_head == NULL) {
   3204 		cil_list_init(&expandattr->attr_strs, CIL_TYPE);
   3205 		cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data);
   3206 	} else {
   3207 		rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs);
   3208 		if (rc != SEPOL_OK) {
   3209 			goto exit;
   3210 		}
   3211 	}
   3212 
   3213 	expand_str = parse_current->next->next->data;
   3214 
   3215 	if (expand_str == CIL_KEY_CONDTRUE) {
   3216 		expandattr->expand = CIL_TRUE;
   3217 	} else if (expand_str == CIL_KEY_CONDFALSE) {
   3218 		expandattr->expand = CIL_FALSE;
   3219 	} else {
   3220 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
   3221 		goto exit;
   3222 	}
   3223 
   3224 	ast_node->data = expandattr;
   3225 	ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE;
   3226 
   3227 	return SEPOL_OK;
   3228 
   3229 exit:
   3230 	cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement");
   3231 	cil_destroy_expandtypeattribute(expandattr);
   3232 	return rc;
   3233 }
   3234 
   3235 void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
   3236 {
   3237 	if (expandattr == NULL) {
   3238 		return;
   3239 	}
   3240 
   3241 	cil_list_destroy(&expandattr->attr_strs, CIL_TRUE);
   3242 
   3243 	cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
   3244 
   3245 	free(expandattr);
   3246 }
   3247 
   3248 int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3249 {
   3250 	enum cil_syntax syntax[] = {
   3251 		CIL_SYN_STRING,
   3252 		CIL_SYN_STRING,
   3253 		CIL_SYN_END
   3254 	};
   3255 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3256 	struct cil_typepermissive *typeperm = NULL;
   3257 	int rc = SEPOL_ERR;
   3258 
   3259 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3260 		goto exit;
   3261 	}
   3262 
   3263 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3264 	if (rc != SEPOL_OK) {
   3265 		goto exit;
   3266 	}
   3267 
   3268 	cil_typepermissive_init(&typeperm);
   3269 
   3270 	typeperm->type_str = parse_current->next->data;
   3271 
   3272 	ast_node->data = typeperm;
   3273 	ast_node->flavor = CIL_TYPEPERMISSIVE;
   3274 
   3275 	return SEPOL_OK;
   3276 
   3277 exit:
   3278 	cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration");
   3279 	cil_destroy_typepermissive(typeperm);
   3280 	return rc;
   3281 }
   3282 
   3283 void cil_destroy_typepermissive(struct cil_typepermissive *typeperm)
   3284 {
   3285 	if (typeperm == NULL) {
   3286 		return;
   3287 	}
   3288 
   3289 	free(typeperm);
   3290 }
   3291 
   3292 int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3293 {
   3294 	int rc = SEPOL_ERR;
   3295 	enum cil_syntax syntax[] = {
   3296 		CIL_SYN_STRING,
   3297 		CIL_SYN_STRING,
   3298 		CIL_SYN_STRING,
   3299 		CIL_SYN_STRING,
   3300 		CIL_SYN_STRING,
   3301 		CIL_SYN_STRING | CIL_SYN_END,
   3302 		CIL_SYN_END
   3303 	};
   3304 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3305 	char *s1, *s2, *s3, *s4, *s5;
   3306 
   3307 	if (db == NULL || parse_current == NULL || ast_node == NULL ) {
   3308 		goto exit;
   3309 	}
   3310 
   3311 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3312 	if (rc != SEPOL_OK) {
   3313 		goto exit;
   3314 	}
   3315 
   3316 	s1 = parse_current->next->data;
   3317 	s2 = parse_current->next->next->data;
   3318 	s3 = parse_current->next->next->next->data;
   3319 	s4 = parse_current->next->next->next->next->data;
   3320 	s5 = NULL;
   3321 
   3322 	if (parse_current->next->next->next->next->next) {
   3323 		if (s4 == CIL_KEY_STAR) {
   3324 			s4 = parse_current->next->next->next->next->next->data;
   3325 		} else {
   3326 			s5 = parse_current->next->next->next->next->next->data;
   3327 		}
   3328 	}
   3329 
   3330 	if (s5) {
   3331 		struct cil_nametypetransition *nametypetrans = NULL;
   3332 
   3333 		cil_nametypetransition_init(&nametypetrans);
   3334 
   3335 		nametypetrans->src_str = s1;
   3336 		nametypetrans->tgt_str = s2;
   3337 		nametypetrans->obj_str = s3;
   3338 		nametypetrans->result_str = s5;
   3339 		nametypetrans->name_str = s4;
   3340 
   3341 		ast_node->data = nametypetrans;
   3342 		ast_node->flavor = CIL_NAMETYPETRANSITION;
   3343 	} else {
   3344 		struct cil_type_rule *rule = NULL;
   3345 
   3346 		cil_type_rule_init(&rule);
   3347 
   3348 		rule->rule_kind = CIL_TYPE_TRANSITION;
   3349 		rule->src_str = s1;
   3350 		rule->tgt_str = s2;
   3351 		rule->obj_str = s3;
   3352 		rule->result_str = s4;
   3353 
   3354 		ast_node->data = rule;
   3355 		ast_node->flavor = CIL_TYPE_RULE;
   3356 	}
   3357 
   3358 	return SEPOL_OK;
   3359 
   3360 exit:
   3361 	cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration");
   3362 	return rc;
   3363 }
   3364 
   3365 void cil_destroy_name(struct cil_name *name)
   3366 {
   3367 	if (name == NULL) {
   3368 		return;
   3369 	}
   3370 
   3371 	cil_symtab_datum_destroy(&name->datum);
   3372 	free(name);
   3373 }
   3374 
   3375 void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans)
   3376 {
   3377 	if (nametypetrans == NULL) {
   3378 		return;
   3379 	}
   3380 
   3381 	free(nametypetrans);
   3382 }
   3383 
   3384 int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3385 {
   3386 	enum cil_syntax syntax[] = {
   3387 		CIL_SYN_STRING,
   3388 		CIL_SYN_STRING,
   3389 		CIL_SYN_STRING,
   3390 		CIL_SYN_STRING,
   3391 		CIL_SYN_STRING | CIL_SYN_LIST,
   3392 		CIL_SYN_END
   3393 	};
   3394 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3395 	struct cil_rangetransition *rangetrans = NULL;
   3396 	int rc = SEPOL_ERR;
   3397 
   3398 	if (db == NULL || parse_current == NULL || ast_node == NULL ) {
   3399 		goto exit;
   3400 	}
   3401 
   3402 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3403 	if (rc != SEPOL_OK) {
   3404 		goto exit;
   3405 	}
   3406 
   3407 	cil_rangetransition_init(&rangetrans);
   3408 
   3409 	rangetrans->src_str = parse_current->next->data;
   3410 	rangetrans->exec_str = parse_current->next->next->data;
   3411 	rangetrans->obj_str = parse_current->next->next->next->data;
   3412 
   3413 	rangetrans->range_str = NULL;
   3414 
   3415 	if (parse_current->next->next->next->next->cl_head == NULL) {
   3416 		rangetrans->range_str = parse_current->next->next->next->next->data;
   3417 	} else {
   3418 		cil_levelrange_init(&rangetrans->range);
   3419 
   3420 		rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range);
   3421 		if (rc != SEPOL_OK) {
   3422 			goto exit;
   3423 		}
   3424 	}
   3425 
   3426 	ast_node->data = rangetrans;
   3427 	ast_node->flavor = CIL_RANGETRANSITION;
   3428 
   3429 	return SEPOL_OK;
   3430 
   3431 exit:
   3432 	cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration");
   3433 	cil_destroy_rangetransition(rangetrans);
   3434 	return rc;
   3435 }
   3436 
   3437 void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans)
   3438 {
   3439 	if (rangetrans == NULL) {
   3440 		return;
   3441 	}
   3442 
   3443 	if (rangetrans->range_str == NULL && rangetrans->range != NULL) {
   3444 		cil_destroy_levelrange(rangetrans->range);
   3445 	}
   3446 
   3447 	free(rangetrans);
   3448 }
   3449 
   3450 int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3451 {
   3452 	enum cil_syntax syntax[] = {
   3453 		CIL_SYN_STRING,
   3454 		CIL_SYN_STRING,
   3455 		CIL_SYN_END
   3456 	};
   3457 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3458 	char *key = NULL;
   3459 	struct cil_sens *sens = NULL;
   3460 	int rc = SEPOL_ERR;
   3461 
   3462 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3463 		goto exit;
   3464 	}
   3465 
   3466 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3467 	if (rc != SEPOL_OK) {
   3468 		goto exit;
   3469 	}
   3470 
   3471 	cil_sens_init(&sens);
   3472 
   3473 	key = parse_current->next->data;
   3474 
   3475 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS);
   3476 	if (rc != SEPOL_OK) {
   3477 		goto exit;
   3478 	}
   3479 
   3480 	return SEPOL_OK;
   3481 
   3482 exit:
   3483 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration");
   3484 	cil_destroy_sensitivity(sens);
   3485 	cil_clear_node(ast_node);
   3486 	return rc;
   3487 }
   3488 
   3489 void cil_destroy_sensitivity(struct cil_sens *sens)
   3490 {
   3491 	if (sens == NULL) {
   3492 		return;
   3493 	}
   3494 
   3495 	cil_symtab_datum_destroy(&sens->datum);
   3496 
   3497 	cil_list_destroy(&sens->cats_list, CIL_FALSE);
   3498 
   3499 	free(sens);
   3500 }
   3501 
   3502 int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3503 {
   3504 	enum cil_syntax syntax[] = {
   3505 		CIL_SYN_STRING,
   3506 		CIL_SYN_STRING,
   3507 		CIL_SYN_END
   3508 	};
   3509 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3510 	char *key = NULL;
   3511 	struct cil_cat *cat = NULL;
   3512 	int rc = SEPOL_ERR;
   3513 
   3514 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3515 		goto exit;
   3516 	}
   3517 
   3518 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3519 	if (rc != SEPOL_OK) {
   3520 		goto exit;
   3521 	}
   3522 
   3523 	cil_cat_init(&cat);
   3524 
   3525 	key = parse_current->next->data;
   3526 
   3527 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT);
   3528 	if (rc != SEPOL_OK) {
   3529 		goto exit;
   3530 	}
   3531 
   3532 	return SEPOL_OK;
   3533 
   3534 exit:
   3535 	cil_tree_log(parse_current, CIL_ERR, "Bad category declaration");
   3536 	cil_destroy_category(cat);
   3537 	cil_clear_node(ast_node);
   3538 	return rc;
   3539 }
   3540 
   3541 void cil_destroy_category(struct cil_cat *cat)
   3542 {
   3543 	if (cat == NULL) {
   3544 		return;
   3545 	}
   3546 
   3547 	cil_symtab_datum_destroy(&cat->datum);
   3548 	free(cat);
   3549 }
   3550 
   3551 int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3552 {
   3553 	enum cil_syntax syntax[] = {
   3554 		CIL_SYN_STRING,
   3555 		CIL_SYN_STRING,
   3556 		CIL_SYN_LIST,
   3557 		CIL_SYN_END
   3558 	};
   3559 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3560 	char *key = NULL;
   3561 	struct cil_catset *catset = NULL;
   3562 	int rc = SEPOL_ERR;
   3563 
   3564 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3565 		goto exit;
   3566 	}
   3567 
   3568 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3569 	if (rc != SEPOL_OK) {
   3570 		goto exit;
   3571 	}
   3572 
   3573 	cil_catset_init(&catset);
   3574 
   3575 	key = parse_current->next->data;
   3576 
   3577 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET);
   3578 	if (rc != SEPOL_OK) {
   3579 		goto exit;
   3580 	}
   3581 
   3582 	rc = cil_fill_cats(parse_current->next->next, &catset->cats);
   3583 	if (rc != SEPOL_OK) {
   3584 		goto exit;
   3585 	}
   3586 
   3587 	return SEPOL_OK;
   3588 
   3589 exit:
   3590 	cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration");
   3591 	cil_destroy_catset(catset);
   3592 	cil_clear_node(ast_node);
   3593 	return rc;
   3594 }
   3595 
   3596 void cil_destroy_catset(struct cil_catset *catset)
   3597 {
   3598 	if (catset == NULL) {
   3599 		return;
   3600 	}
   3601 
   3602 	cil_symtab_datum_destroy(&catset->datum);
   3603 
   3604 	cil_destroy_cats(catset->cats);
   3605 
   3606 	free(catset);
   3607 }
   3608 
   3609 int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3610 {
   3611 	enum cil_syntax syntax[] = {
   3612 		CIL_SYN_STRING,
   3613 		CIL_SYN_LIST,
   3614 		CIL_SYN_END
   3615 	};
   3616 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3617 	struct cil_catorder *catorder = NULL;
   3618 	struct cil_list_item *curr = NULL;
   3619 	int rc = SEPOL_ERR;
   3620 
   3621 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3622 		goto exit;
   3623 	}
   3624 
   3625 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3626 	if (rc !=  SEPOL_OK) {
   3627 		goto exit;
   3628 	}
   3629 
   3630 	cil_catorder_init(&catorder);
   3631 
   3632 	rc = cil_fill_list(parse_current->next->cl_head, CIL_CATORDER, &catorder->cat_list_str);
   3633 	if (rc != SEPOL_OK) {
   3634 		goto exit;
   3635 	}
   3636 
   3637 	cil_list_for_each(curr, catorder->cat_list_str) {
   3638 		if (curr->data == CIL_KEY_UNORDERED) {
   3639 			cil_log(CIL_ERR, "Category order cannot be unordered.\n");
   3640 			rc = SEPOL_ERR;
   3641 			goto exit;
   3642 		}
   3643 	}
   3644 
   3645 	ast_node->data = catorder;
   3646 	ast_node->flavor = CIL_CATORDER;
   3647 
   3648 	return SEPOL_OK;
   3649 
   3650 exit:
   3651 	cil_tree_log(parse_current, CIL_ERR, "Bad categoryorder declaration");
   3652 	cil_destroy_catorder(catorder);
   3653 	return rc;
   3654 }
   3655 
   3656 void cil_destroy_catorder(struct cil_catorder *catorder)
   3657 {
   3658 	if (catorder == NULL) {
   3659 		return;
   3660 	}
   3661 
   3662 	if (catorder->cat_list_str != NULL) {
   3663 		cil_list_destroy(&catorder->cat_list_str, 1);
   3664 	}
   3665 
   3666 	free(catorder);
   3667 }
   3668 
   3669 int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3670 {
   3671 	enum cil_syntax syntax[] = {
   3672 		CIL_SYN_STRING,
   3673 		CIL_SYN_LIST,
   3674 		CIL_SYN_END
   3675 	};
   3676 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3677 	struct cil_sensorder *sensorder = NULL;
   3678 	struct cil_list_item *curr = NULL;
   3679 	int rc = SEPOL_ERR;
   3680 
   3681 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3682 		goto exit;
   3683 	}
   3684 
   3685 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3686 	if (rc != SEPOL_OK) {
   3687 		goto exit;
   3688 	}
   3689 
   3690 	cil_sensorder_init(&sensorder);
   3691 
   3692 	rc = cil_fill_list(parse_current->next->cl_head, CIL_SENSITIVITYORDER, &sensorder->sens_list_str);
   3693 	if (rc != SEPOL_OK) {
   3694 		goto exit;
   3695 	}
   3696 
   3697 	cil_list_for_each(curr, sensorder->sens_list_str) {
   3698 		if (curr->data == CIL_KEY_UNORDERED) {
   3699 			cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
   3700 			rc = SEPOL_ERR;
   3701 			goto exit;
   3702 		}
   3703 	}
   3704 
   3705 	ast_node->data = sensorder;
   3706 	ast_node->flavor = CIL_SENSITIVITYORDER;
   3707 
   3708 	return SEPOL_OK;
   3709 
   3710 exit:
   3711 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivityorder declaration");
   3712 	cil_destroy_sensitivityorder(sensorder);
   3713 	return rc;
   3714 }
   3715 
   3716 void cil_destroy_sensitivityorder(struct cil_sensorder *sensorder)
   3717 {
   3718 	if (sensorder == NULL) {
   3719 		return;
   3720 	}
   3721 
   3722 	if (sensorder->sens_list_str != NULL) {
   3723 		cil_list_destroy(&sensorder->sens_list_str, CIL_TRUE);
   3724 	}
   3725 
   3726 	free(sensorder);
   3727 }
   3728 
   3729 int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3730 {
   3731 	enum cil_syntax syntax[] = {
   3732 		CIL_SYN_STRING,
   3733 		CIL_SYN_STRING,
   3734 		CIL_SYN_STRING | CIL_SYN_LIST,
   3735 		CIL_SYN_END
   3736 	};
   3737 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3738 	struct cil_senscat *senscat = NULL;
   3739 	int rc = SEPOL_ERR;
   3740 
   3741 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3742 		goto exit;
   3743 	}
   3744 
   3745 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3746 	if (rc != SEPOL_OK) {
   3747 		goto exit;
   3748 	}
   3749 
   3750 	cil_senscat_init(&senscat);
   3751 
   3752 	senscat->sens_str = parse_current->next->data;
   3753 
   3754 	rc = cil_fill_cats(parse_current->next->next, &senscat->cats);
   3755 	if (rc != SEPOL_OK) {
   3756 		goto exit;
   3757 	}
   3758 
   3759 	ast_node->data = senscat;
   3760 	ast_node->flavor = CIL_SENSCAT;
   3761 
   3762 	return SEPOL_OK;
   3763 
   3764 exit:
   3765 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration");
   3766 	cil_destroy_senscat(senscat);
   3767 	return rc;
   3768 }
   3769 
   3770 void cil_destroy_senscat(struct cil_senscat *senscat)
   3771 {
   3772 	if (senscat == NULL) {
   3773 		return;
   3774 	}
   3775 
   3776 	cil_destroy_cats(senscat->cats);
   3777 
   3778 	free(senscat);
   3779 }
   3780 
   3781 int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3782 {
   3783 	enum cil_syntax syntax[] = {
   3784 		CIL_SYN_STRING,
   3785 		CIL_SYN_STRING,
   3786 		CIL_SYN_LIST,
   3787 		CIL_SYN_END
   3788 	};
   3789 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3790 	char *key = NULL;
   3791 	struct cil_level *level = NULL;
   3792 	int rc = SEPOL_ERR;
   3793 
   3794 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3795 		goto exit;
   3796 	}
   3797 
   3798 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3799 	if (rc != SEPOL_OK) {
   3800 		goto exit;
   3801 	}
   3802 
   3803 	cil_level_init(&level);
   3804 
   3805 	key = parse_current->next->data;
   3806 
   3807 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL);
   3808 	if (rc != SEPOL_OK) {
   3809 		goto exit;
   3810 	}
   3811 
   3812 	rc = cil_fill_level(parse_current->next->next->cl_head, level);
   3813 	if (rc != SEPOL_OK) {
   3814 		goto exit;
   3815 	}
   3816 
   3817 	return SEPOL_OK;
   3818 
   3819 exit:
   3820 	cil_tree_log(parse_current, CIL_ERR, "Bad level declaration");
   3821 	cil_destroy_level(level);
   3822 	cil_clear_node(ast_node);
   3823 	return rc;
   3824 }
   3825 
   3826 void cil_destroy_level(struct cil_level *level)
   3827 {
   3828 	if (level == NULL) {
   3829 		return;
   3830 	}
   3831 
   3832 	cil_symtab_datum_destroy(&level->datum);
   3833 
   3834 	cil_destroy_cats(level->cats);
   3835 
   3836 	free(level);
   3837 }
   3838 
   3839 /* low should be pointing to either the name of the low level or to an open paren for an anonymous low level */
   3840 int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange)
   3841 {
   3842 	enum cil_syntax syntax[] = {
   3843 		CIL_SYN_STRING | CIL_SYN_LIST,
   3844 		CIL_SYN_STRING | CIL_SYN_LIST,
   3845 		CIL_SYN_END
   3846 	};
   3847 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3848 	int rc = SEPOL_ERR;
   3849 
   3850 	if (low == NULL || lvlrange == NULL) {
   3851 		goto exit;
   3852 	}
   3853 
   3854 	rc = __cil_verify_syntax(low, syntax, syntax_len);
   3855 	if (rc != SEPOL_OK) {
   3856 
   3857 		goto exit;
   3858 	}
   3859 
   3860 	if (low->cl_head == NULL) {
   3861 		lvlrange->low_str = low->data;
   3862 	} else {
   3863 		cil_level_init(&lvlrange->low);
   3864 		rc = cil_fill_level(low->cl_head, lvlrange->low);
   3865 		if (rc != SEPOL_OK) {
   3866 			goto exit;
   3867 		}
   3868 	}
   3869 
   3870 	if (low->next->cl_head == NULL) {
   3871 		lvlrange->high_str = low->next->data;
   3872 	} else {
   3873 		cil_level_init(&lvlrange->high);
   3874 		rc = cil_fill_level(low->next->cl_head, lvlrange->high);
   3875 		if (rc != SEPOL_OK) {
   3876 			goto exit;
   3877 		}
   3878 	}
   3879 
   3880 	return SEPOL_OK;
   3881 
   3882 exit:
   3883 	cil_log(CIL_ERR, "Bad levelrange\n");
   3884 	return rc;
   3885 }
   3886 
   3887 int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   3888 {
   3889 	enum cil_syntax syntax[] = {
   3890 		CIL_SYN_STRING,
   3891 		CIL_SYN_STRING,
   3892 		CIL_SYN_LIST,
   3893 		CIL_SYN_END
   3894 	};
   3895 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3896 	char *key = NULL;
   3897 	struct cil_levelrange *lvlrange = NULL;
   3898 	int rc = SEPOL_ERR;
   3899 
   3900 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3901 		goto exit;
   3902 	}
   3903 
   3904 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3905 	if (rc != SEPOL_OK) {
   3906 		goto exit;
   3907 	}
   3908 
   3909 	cil_levelrange_init(&lvlrange);
   3910 
   3911 	key = parse_current->next->data;
   3912 
   3913 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE);
   3914 	if (rc != SEPOL_OK) {
   3915 		goto exit;
   3916 	}
   3917 
   3918 	rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange);
   3919 	if (rc != SEPOL_OK) {
   3920 		goto exit;
   3921 	}
   3922 
   3923 	return SEPOL_OK;
   3924 
   3925 exit:
   3926 	cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration");
   3927 	cil_destroy_levelrange(lvlrange);
   3928 	cil_clear_node(ast_node);
   3929 	return rc;
   3930 }
   3931 
   3932 void cil_destroy_levelrange(struct cil_levelrange *lvlrange)
   3933 {
   3934 	if (lvlrange == NULL) {
   3935 		return;
   3936 	}
   3937 
   3938 	cil_symtab_datum_destroy(&lvlrange->datum);
   3939 
   3940 	if (lvlrange->low_str == NULL) {
   3941 		cil_destroy_level(lvlrange->low);
   3942 	}
   3943 
   3944 	if (lvlrange->high_str == NULL) {
   3945 		cil_destroy_level(lvlrange->high);
   3946 	}
   3947 
   3948 	free(lvlrange);
   3949 }
   3950 
   3951 int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   3952 {
   3953 	enum cil_syntax syntax[] = {
   3954 		CIL_SYN_STRING,
   3955 		CIL_SYN_STRING | CIL_SYN_LIST,
   3956 		CIL_SYN_LIST,
   3957 		CIL_SYN_END
   3958 	};
   3959 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   3960 	struct cil_constrain *cons = NULL;
   3961 	int rc = SEPOL_ERR;
   3962 
   3963 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   3964 		goto exit;
   3965 	}
   3966 
   3967 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   3968 	if (rc != SEPOL_OK) {
   3969 		goto exit;
   3970 	}
   3971 
   3972 	cil_constrain_init(&cons);
   3973 
   3974 	rc = cil_fill_classperms_list(parse_current->next, &cons->classperms);
   3975 	if (rc != SEPOL_OK) {
   3976 		goto exit;
   3977 	}
   3978 
   3979 	rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr);
   3980 	if (rc != SEPOL_OK) {
   3981 		goto exit;
   3982 	}
   3983 
   3984 	ast_node->data = cons;
   3985 	ast_node->flavor = flavor;
   3986 
   3987 	return SEPOL_OK;
   3988 
   3989 exit:
   3990 	cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration");
   3991 	cil_destroy_constrain(cons);
   3992 	return rc;
   3993 }
   3994 
   3995 void cil_destroy_constrain(struct cil_constrain *cons)
   3996 {
   3997 	if (cons == NULL) {
   3998 		return;
   3999 	}
   4000 
   4001 	cil_destroy_classperms_list(&cons->classperms);
   4002 	cil_list_destroy(&cons->str_expr, CIL_TRUE);
   4003 	cil_list_destroy(&cons->datum_expr, CIL_FALSE);
   4004 
   4005 	free(cons);
   4006 }
   4007 
   4008 int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   4009 {
   4010 	enum cil_syntax syntax[] = {
   4011 		CIL_SYN_STRING,
   4012 		CIL_SYN_STRING,
   4013 		CIL_SYN_LIST,
   4014 		CIL_SYN_END
   4015 	};
   4016 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4017 	struct cil_validatetrans *validtrans = NULL;
   4018 	int rc = SEPOL_ERR;
   4019 
   4020 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4021 		goto exit;
   4022 	}
   4023 
   4024 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4025 	if (rc != SEPOL_OK) {
   4026 		goto exit;
   4027 	}
   4028 
   4029 	cil_validatetrans_init(&validtrans);
   4030 
   4031 	validtrans->class_str = parse_current->next->data;
   4032 
   4033 	rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr);
   4034 	if (rc != SEPOL_OK) {
   4035 		goto exit;
   4036 	}
   4037 
   4038 	ast_node->data = validtrans;
   4039 	ast_node->flavor = flavor;
   4040 
   4041 	return SEPOL_OK;
   4042 
   4043 exit:
   4044 	cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration");
   4045 	cil_destroy_validatetrans(validtrans);
   4046 	return rc;
   4047 
   4048 
   4049 }
   4050 
   4051 void cil_destroy_validatetrans(struct cil_validatetrans *validtrans)
   4052 {
   4053 	if (validtrans == NULL) {
   4054 		return;
   4055 	}
   4056 
   4057 	cil_list_destroy(&validtrans->str_expr, CIL_TRUE);
   4058 	cil_list_destroy(&validtrans->datum_expr, CIL_FALSE);
   4059 
   4060 	free(validtrans);
   4061 }
   4062 
   4063 /* Fills in context starting from user */
   4064 int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context)
   4065 {
   4066 	enum cil_syntax syntax[] = {
   4067 		CIL_SYN_STRING,
   4068 		CIL_SYN_STRING,
   4069 		CIL_SYN_STRING,
   4070 		CIL_SYN_STRING | CIL_SYN_LIST,
   4071 		CIL_SYN_END
   4072 	};
   4073 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4074 	int rc = SEPOL_ERR;
   4075 
   4076 	if (user_node == NULL || context == NULL) {
   4077 		goto exit;
   4078 	}
   4079 
   4080 	rc = __cil_verify_syntax(user_node, syntax, syntax_len);
   4081 	if (rc != SEPOL_OK) {
   4082 		goto exit;
   4083 	}
   4084 
   4085 	context->user_str = user_node->data;
   4086 	context->role_str = user_node->next->data;
   4087 	context->type_str = user_node->next->next->data;
   4088 
   4089 	context->range_str = NULL;
   4090 
   4091 	if (user_node->next->next->next->cl_head == NULL) {
   4092 		context->range_str = user_node->next->next->next->data;
   4093 	} else {
   4094 		cil_levelrange_init(&context->range);
   4095 
   4096 		rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range);
   4097 		if (rc != SEPOL_OK) {
   4098 			goto exit;
   4099 		}
   4100 	}
   4101 
   4102 	return SEPOL_OK;
   4103 
   4104 exit:
   4105 	cil_log(CIL_ERR, "Bad context\n");
   4106 	return rc;
   4107 }
   4108 
   4109 int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4110 {
   4111 	enum cil_syntax syntax[] = {
   4112 		CIL_SYN_STRING,
   4113 		CIL_SYN_STRING,
   4114 		CIL_SYN_LIST,
   4115 		CIL_SYN_END
   4116 	};
   4117 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4118 	char *key = NULL;
   4119 	struct cil_context *context = NULL;
   4120 	int rc = SEPOL_ERR;
   4121 
   4122 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4123 		goto exit;
   4124 	}
   4125 
   4126 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4127 	if (rc != SEPOL_OK) {
   4128 		goto exit;
   4129 	}
   4130 
   4131 	cil_context_init(&context);
   4132 
   4133 	key = parse_current->next->data;
   4134 
   4135 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT);
   4136 	if (rc != SEPOL_OK) {
   4137 		goto exit;
   4138 	}
   4139 
   4140 	rc = cil_fill_context(parse_current->next->next->cl_head, context);
   4141 	if (rc != SEPOL_OK) {
   4142 		goto exit;
   4143 	}
   4144 
   4145 	return SEPOL_OK;
   4146 
   4147 exit:
   4148 	cil_tree_log(parse_current, CIL_ERR, "Bad context declaration");
   4149 	cil_destroy_context(context);
   4150 	cil_clear_node(ast_node);
   4151 	return SEPOL_ERR;
   4152 }
   4153 
   4154 void cil_destroy_context(struct cil_context *context)
   4155 {
   4156 	if (context == NULL) {
   4157 		return;
   4158 	}
   4159 
   4160 	cil_symtab_datum_destroy(&context->datum);;
   4161 
   4162 	if (context->range_str == NULL && context->range != NULL) {
   4163 		cil_destroy_levelrange(context->range);
   4164 	}
   4165 
   4166 	free(context);
   4167 }
   4168 
   4169 int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4170 {
   4171 	enum cil_syntax syntax[] = {
   4172 		CIL_SYN_STRING,
   4173 		CIL_SYN_STRING,
   4174 		CIL_SYN_STRING,
   4175 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
   4176 		CIL_SYN_END
   4177 	};
   4178 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4179 	int rc = SEPOL_ERR;
   4180 	struct cil_filecon *filecon = NULL;
   4181 	char *type = NULL;
   4182 
   4183 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4184 		goto exit;
   4185 	}
   4186 
   4187 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4188 	if (rc != SEPOL_OK) {
   4189 		goto exit;
   4190 	}
   4191 
   4192 	type = parse_current->next->next->data;
   4193 	cil_filecon_init(&filecon);
   4194 
   4195 	filecon->path_str = parse_current->next->data;
   4196 
   4197 	if (type == CIL_KEY_FILE) {
   4198 		filecon->type = CIL_FILECON_FILE;
   4199 	} else if (type == CIL_KEY_DIR) {
   4200 		filecon->type = CIL_FILECON_DIR;
   4201 	} else if (type == CIL_KEY_CHAR) {
   4202 		filecon->type = CIL_FILECON_CHAR;
   4203 	} else if (type == CIL_KEY_BLOCK) {
   4204 		filecon->type = CIL_FILECON_BLOCK;
   4205 	} else if (type == CIL_KEY_SOCKET) {
   4206 		filecon->type = CIL_FILECON_SOCKET;
   4207 	} else if (type == CIL_KEY_PIPE) {
   4208 		filecon->type = CIL_FILECON_PIPE;
   4209 	} else if (type == CIL_KEY_SYMLINK) {
   4210 		filecon->type = CIL_FILECON_SYMLINK;
   4211 	} else if (type == CIL_KEY_ANY) {
   4212 		filecon->type = CIL_FILECON_ANY;
   4213 	} else {
   4214 		cil_log(CIL_ERR, "Invalid file type\n");
   4215 		rc = SEPOL_ERR;
   4216 		goto exit;
   4217 	}
   4218 
   4219 	if (parse_current->next->next->next->cl_head == NULL) {
   4220 		filecon->context_str = parse_current->next->next->next->data;
   4221 	} else {
   4222 		if (parse_current->next->next->next->cl_head->next == NULL) {
   4223 			filecon->context = NULL;
   4224 		} else {
   4225 			cil_context_init(&filecon->context);
   4226 
   4227 			rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context);
   4228 			if (rc != SEPOL_OK) {
   4229 				goto exit;
   4230 			}
   4231 		}
   4232 	}
   4233 
   4234 	ast_node->data = filecon;
   4235 	ast_node->flavor = CIL_FILECON;
   4236 
   4237 	return SEPOL_OK;
   4238 
   4239 exit:
   4240 	cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration");
   4241 	cil_destroy_filecon(filecon);
   4242 	return rc;
   4243 }
   4244 
   4245 //TODO: Should we be checking if the pointer is NULL when passed in?
   4246 void cil_destroy_filecon(struct cil_filecon *filecon)
   4247 {
   4248 	if (filecon == NULL) {
   4249 		return;
   4250 	}
   4251 
   4252 	if (filecon->context_str == NULL && filecon->context != NULL) {
   4253 		cil_destroy_context(filecon->context);
   4254 	}
   4255 
   4256 	free(filecon);
   4257 }
   4258 
   4259 int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4260 {
   4261 	enum cil_syntax syntax[] = {
   4262 		CIL_SYN_STRING,
   4263 		CIL_SYN_STRING,
   4264 		CIL_SYN_STRING | CIL_SYN_LIST,
   4265 		CIL_SYN_STRING | CIL_SYN_LIST,
   4266 		CIL_SYN_END
   4267 	};
   4268 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4269 	int rc = SEPOL_ERR;
   4270 	struct cil_portcon *portcon = NULL;
   4271 	char *proto;
   4272 
   4273 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4274 		goto exit;
   4275 	}
   4276 
   4277 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4278 	if (rc != SEPOL_OK) {
   4279 		goto exit;
   4280 	}
   4281 
   4282 	cil_portcon_init(&portcon);
   4283 
   4284 	proto = parse_current->next->data;
   4285 	if (proto == CIL_KEY_UDP) {
   4286 		portcon->proto = CIL_PROTOCOL_UDP;
   4287 	} else if (proto == CIL_KEY_TCP) {
   4288 		portcon->proto = CIL_PROTOCOL_TCP;
   4289 	} else if (proto == CIL_KEY_DCCP) {
   4290 		portcon->proto = CIL_PROTOCOL_DCCP;
   4291 	} else {
   4292 		cil_log(CIL_ERR, "Invalid protocol\n");
   4293 		rc = SEPOL_ERR;
   4294 		goto exit;
   4295 	}
   4296 
   4297 	if (parse_current->next->next->cl_head != NULL) {
   4298 		if (parse_current->next->next->cl_head->next != NULL
   4299 		&& parse_current->next->next->cl_head->next->next == NULL) {
   4300 			rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10);
   4301 			if (rc != SEPOL_OK) {
   4302 				cil_log(CIL_ERR, "Improper port specified\n");
   4303 				goto exit;
   4304 			}
   4305 			rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10);
   4306 			if (rc != SEPOL_OK) {
   4307 				cil_log(CIL_ERR, "Improper port specified\n");
   4308 				goto exit;
   4309 			}
   4310 		} else {
   4311 			cil_log(CIL_ERR, "Improper port range specified\n");
   4312 			rc = SEPOL_ERR;
   4313 			goto exit;
   4314 		}
   4315 	} else {
   4316 		rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10);
   4317 		if (rc != SEPOL_OK) {
   4318 			cil_log(CIL_ERR, "Improper port specified\n");
   4319 			goto exit;
   4320 		}
   4321 		portcon->port_high = portcon->port_low;
   4322 	}
   4323 
   4324 	if (parse_current->next->next->next->cl_head == NULL ) {
   4325 		portcon->context_str = parse_current->next->next->next->data;
   4326 	} else {
   4327 		cil_context_init(&portcon->context);
   4328 
   4329 		rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context);
   4330 		if (rc != SEPOL_OK) {
   4331 			goto exit;
   4332 		}
   4333 	}
   4334 
   4335 	ast_node->data = portcon;
   4336 	ast_node->flavor = CIL_PORTCON;
   4337 
   4338 	return SEPOL_OK;
   4339 
   4340 exit:
   4341 	cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration");
   4342 	cil_destroy_portcon(portcon);
   4343 	return rc;
   4344 }
   4345 
   4346 void cil_destroy_portcon(struct cil_portcon *portcon)
   4347 {
   4348 	if (portcon == NULL) {
   4349 		return;
   4350 	}
   4351 
   4352 	if (portcon->context_str == NULL && portcon->context != NULL) {
   4353 		cil_destroy_context(portcon->context);
   4354 	}
   4355 
   4356 	free(portcon);
   4357 }
   4358 
   4359 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4360 {
   4361 	enum cil_syntax syntax[] = {
   4362 		CIL_SYN_STRING,
   4363 		CIL_SYN_STRING | CIL_SYN_LIST,
   4364 		CIL_SYN_STRING | CIL_SYN_LIST,
   4365 		CIL_SYN_STRING | CIL_SYN_LIST,
   4366 		CIL_SYN_END
   4367 	};
   4368 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4369 	int rc = SEPOL_ERR;
   4370 	struct cil_nodecon *nodecon = NULL;
   4371 
   4372 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4373 		goto exit;
   4374 	}
   4375 
   4376 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4377 	if (rc != SEPOL_OK) {
   4378 		goto exit;
   4379 	}
   4380 
   4381 	cil_nodecon_init(&nodecon);
   4382 
   4383 	if (parse_current->next->cl_head == NULL ) {
   4384 		nodecon->addr_str = parse_current->next->data;
   4385 	} else {
   4386 		cil_ipaddr_init(&nodecon->addr);
   4387 
   4388 		rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr);
   4389 		if (rc != SEPOL_OK) {
   4390 			goto exit;
   4391 		}
   4392 	}
   4393 
   4394 	if (parse_current->next->next->cl_head == NULL ) {
   4395 		nodecon->mask_str = parse_current->next->next->data;
   4396 	} else {
   4397 		cil_ipaddr_init(&nodecon->mask);
   4398 
   4399 		rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask);
   4400 		if (rc != SEPOL_OK) {
   4401 			goto exit;
   4402 		}
   4403 	}
   4404 
   4405 	if (parse_current->next->next->next->cl_head == NULL ) {
   4406 		nodecon->context_str = parse_current->next->next->next->data;
   4407 	} else {
   4408 		cil_context_init(&nodecon->context);
   4409 
   4410 		rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context);
   4411 		if (rc != SEPOL_OK) {
   4412 			goto exit;
   4413 		}
   4414 	}
   4415 
   4416 	ast_node->data = nodecon;
   4417 	ast_node->flavor = CIL_NODECON;
   4418 
   4419 	return SEPOL_OK;
   4420 
   4421 exit:
   4422 	cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration");
   4423 	cil_destroy_nodecon(nodecon);
   4424 	return rc;
   4425 }
   4426 
   4427 void cil_destroy_nodecon(struct cil_nodecon *nodecon)
   4428 {
   4429 	if (nodecon == NULL) {
   4430 		return;
   4431 	}
   4432 
   4433 	if (nodecon->addr_str == NULL && nodecon->addr != NULL) {
   4434 		cil_destroy_ipaddr(nodecon->addr);
   4435 	}
   4436 
   4437 	if (nodecon->mask_str == NULL && nodecon->mask != NULL) {
   4438 		cil_destroy_ipaddr(nodecon->mask);
   4439 	}
   4440 
   4441 	if (nodecon->context_str == NULL && nodecon->context != NULL) {
   4442 		cil_destroy_context(nodecon->context);
   4443 	}
   4444 
   4445 	free(nodecon);
   4446 }
   4447 
   4448 int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4449 {
   4450 	enum cil_syntax syntax[] = {
   4451 		CIL_SYN_STRING,
   4452 		CIL_SYN_STRING,
   4453 		CIL_SYN_STRING,
   4454 		CIL_SYN_STRING | CIL_SYN_LIST,
   4455 		CIL_SYN_END
   4456 	};
   4457 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4458 	int rc = SEPOL_ERR;
   4459 	struct cil_genfscon *genfscon = NULL;
   4460 
   4461 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4462 		goto exit;
   4463 	}
   4464 
   4465 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4466 	if (rc != SEPOL_OK) {
   4467 		goto exit;
   4468 	}
   4469 
   4470 	cil_genfscon_init(&genfscon);
   4471 
   4472 	genfscon->fs_str = parse_current->next->data;
   4473 	genfscon->path_str = parse_current->next->next->data;
   4474 
   4475 	if (parse_current->next->next->next->cl_head == NULL ) {
   4476 		genfscon->context_str = parse_current->next->next->next->data;
   4477 	} else {
   4478 		cil_context_init(&genfscon->context);
   4479 
   4480 		rc = cil_fill_context(parse_current->next->next->next->cl_head, genfscon->context);
   4481 		if (rc != SEPOL_OK) {
   4482 			goto exit;
   4483 		}
   4484 	}
   4485 
   4486 	ast_node->data = genfscon;
   4487 	ast_node->flavor = CIL_GENFSCON;
   4488 
   4489 	return SEPOL_OK;
   4490 
   4491 exit:
   4492 	cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
   4493 	cil_destroy_genfscon(genfscon);
   4494 	return SEPOL_ERR;
   4495 }
   4496 
   4497 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
   4498 {
   4499 	if (genfscon == NULL) {
   4500 		return;
   4501 	}
   4502 
   4503 	if (genfscon->context_str == NULL && genfscon->context != NULL) {
   4504 		cil_destroy_context(genfscon->context);
   4505 	}
   4506 
   4507 	free(genfscon);
   4508 }
   4509 
   4510 
   4511 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4512 {
   4513 	enum cil_syntax syntax[] = {
   4514 		CIL_SYN_STRING,
   4515 		CIL_SYN_STRING,
   4516 		CIL_SYN_STRING | CIL_SYN_LIST,
   4517 		CIL_SYN_STRING | CIL_SYN_LIST,
   4518 		CIL_SYN_END
   4519 	};
   4520 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4521 	int rc = SEPOL_ERR;
   4522 	struct cil_netifcon *netifcon = NULL;
   4523 
   4524 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4525 		goto exit;
   4526 	}
   4527 
   4528 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4529 	if (rc != SEPOL_OK) {
   4530 		goto exit;
   4531 	}
   4532 
   4533 	cil_netifcon_init(&netifcon);
   4534 
   4535 	netifcon->interface_str = parse_current->next->data;
   4536 
   4537 	if (parse_current->next->next->cl_head == NULL) {
   4538 		netifcon->if_context_str = parse_current->next->next->data;
   4539 	} else {
   4540 		cil_context_init(&netifcon->if_context);
   4541 
   4542 		rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
   4543 		if (rc != SEPOL_OK) {
   4544 			goto exit;
   4545 		}
   4546 	}
   4547 
   4548 	if (parse_current->next->next->next->cl_head == NULL) {
   4549 		netifcon->packet_context_str = parse_current->next->next->next->data;
   4550 	} else {
   4551 		cil_context_init(&netifcon->packet_context);
   4552 
   4553 		rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
   4554 		if (rc != SEPOL_OK) {
   4555 			goto exit;
   4556 		}
   4557 	}
   4558 
   4559 	ast_node->data = netifcon;
   4560 	ast_node->flavor = CIL_NETIFCON;
   4561 
   4562 	return SEPOL_OK;
   4563 
   4564 exit:
   4565 	cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
   4566 	cil_destroy_netifcon(netifcon);
   4567 	return SEPOL_ERR;
   4568 }
   4569 
   4570 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
   4571 {
   4572 	if (netifcon == NULL) {
   4573 		return;
   4574 	}
   4575 
   4576 	if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
   4577 		cil_destroy_context(netifcon->if_context);
   4578 	}
   4579 
   4580 	if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
   4581 		cil_destroy_context(netifcon->packet_context);
   4582 	}
   4583 
   4584 	free(netifcon);
   4585 }
   4586 
   4587 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4588 {
   4589 	enum cil_syntax syntax[] = {
   4590 		CIL_SYN_STRING,
   4591 		CIL_SYN_STRING,
   4592 		CIL_SYN_STRING | CIL_SYN_LIST,
   4593 		CIL_SYN_END
   4594 	};
   4595 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4596 	int rc = SEPOL_ERR;
   4597 	struct cil_pirqcon *pirqcon = NULL;
   4598 
   4599 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4600 		goto exit;
   4601 	}
   4602 
   4603 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4604 	if (rc != SEPOL_OK) {
   4605 		goto exit;
   4606 	}
   4607 
   4608 	cil_pirqcon_init(&pirqcon);
   4609 
   4610 	rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
   4611 	if (rc != SEPOL_OK) {
   4612 		goto exit;
   4613 	}
   4614 
   4615 	if (parse_current->next->next->cl_head == NULL) {
   4616 		pirqcon->context_str = parse_current->next->next->data;
   4617 	} else {
   4618 		cil_context_init(&pirqcon->context);
   4619 
   4620 		rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
   4621 		if (rc != SEPOL_OK) {
   4622 			goto exit;
   4623 		}
   4624 	}
   4625 
   4626 	ast_node->data = pirqcon;
   4627 	ast_node->flavor = CIL_PIRQCON;
   4628 
   4629 	return SEPOL_OK;
   4630 
   4631 exit:
   4632 	cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
   4633 	cil_destroy_pirqcon(pirqcon);
   4634 	return rc;
   4635 }
   4636 
   4637 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
   4638 {
   4639 	if (pirqcon == NULL) {
   4640 		return;
   4641 	}
   4642 
   4643 	if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
   4644 		cil_destroy_context(pirqcon->context);
   4645 	}
   4646 
   4647 	free(pirqcon);
   4648 }
   4649 
   4650 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4651 {
   4652 	enum cil_syntax syntax[] = {
   4653 		CIL_SYN_STRING,
   4654 		CIL_SYN_STRING | CIL_SYN_LIST,
   4655 		CIL_SYN_STRING | CIL_SYN_LIST,
   4656 		CIL_SYN_END
   4657 	};
   4658 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4659 	int rc = SEPOL_ERR;
   4660 	struct cil_iomemcon *iomemcon = NULL;
   4661 
   4662 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4663 		goto exit;
   4664 	}
   4665 
   4666 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4667 	if (rc != SEPOL_OK) {
   4668 		goto exit;
   4669 	}
   4670 
   4671 	cil_iomemcon_init(&iomemcon);
   4672 
   4673 	if (parse_current->next->cl_head != NULL) {
   4674 		if (parse_current->next->cl_head->next != NULL &&
   4675 		    parse_current->next->cl_head->next->next == NULL) {
   4676 			rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
   4677 			if (rc != SEPOL_OK) {
   4678 				cil_log(CIL_ERR, "Improper iomem specified\n");
   4679 				goto exit;
   4680 			}
   4681 			rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
   4682 			if (rc != SEPOL_OK) {
   4683 				cil_log(CIL_ERR, "Improper iomem specified\n");
   4684 				goto exit;
   4685 			}
   4686 		} else {
   4687 			cil_log(CIL_ERR, "Improper iomem range specified\n");
   4688 			rc = SEPOL_ERR;
   4689 			goto exit;
   4690 		}
   4691 	} else {
   4692 		rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
   4693 		if (rc != SEPOL_OK) {
   4694 			cil_log(CIL_ERR, "Improper iomem specified\n");
   4695 			goto exit;
   4696 		}
   4697 		iomemcon->iomem_high = iomemcon->iomem_low;
   4698 	}
   4699 
   4700 	if (parse_current->next->next->cl_head == NULL ) {
   4701 		iomemcon->context_str = parse_current->next->next->data;
   4702 	} else {
   4703 		cil_context_init(&iomemcon->context);
   4704 
   4705 		rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
   4706 		if (rc != SEPOL_OK) {
   4707 			goto exit;
   4708 		}
   4709 	}
   4710 
   4711 	ast_node->data = iomemcon;
   4712 	ast_node->flavor = CIL_IOMEMCON;
   4713 
   4714 	return SEPOL_OK;
   4715 
   4716 exit:
   4717 	cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
   4718 	cil_destroy_iomemcon(iomemcon);
   4719 	return rc;
   4720 }
   4721 
   4722 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
   4723 {
   4724 	if (iomemcon == NULL) {
   4725 		return;
   4726 	}
   4727 
   4728 	if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
   4729 		cil_destroy_context(iomemcon->context);
   4730 	}
   4731 
   4732 	free(iomemcon);
   4733 }
   4734 
   4735 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4736 {
   4737 	enum cil_syntax syntax[] = {
   4738 		CIL_SYN_STRING,
   4739 		CIL_SYN_STRING | CIL_SYN_LIST,
   4740 		CIL_SYN_STRING | CIL_SYN_LIST,
   4741 		CIL_SYN_END
   4742 	};
   4743 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4744 	int rc = SEPOL_ERR;
   4745 	struct cil_ioportcon *ioportcon = NULL;
   4746 
   4747 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4748 		goto exit;
   4749 	}
   4750 
   4751 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4752 	if (rc != SEPOL_OK) {
   4753 		goto exit;
   4754 	}
   4755 
   4756 	cil_ioportcon_init(&ioportcon);
   4757 
   4758 	if (parse_current->next->cl_head != NULL) {
   4759 		if (parse_current->next->cl_head->next != NULL &&
   4760 		    parse_current->next->cl_head->next->next == NULL) {
   4761 			rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
   4762 			if (rc != SEPOL_OK) {
   4763 				cil_log(CIL_ERR, "Improper ioport specified\n");
   4764 				goto exit;
   4765 			}
   4766 			rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
   4767 			if (rc != SEPOL_OK) {
   4768 				cil_log(CIL_ERR, "Improper ioport specified\n");
   4769 				goto exit;
   4770 			}
   4771 		} else {
   4772 			cil_log(CIL_ERR, "Improper ioport range specified\n");
   4773 			rc = SEPOL_ERR;
   4774 			goto exit;
   4775 		}
   4776 	} else {
   4777 		rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
   4778 		if (rc != SEPOL_OK) {
   4779 			cil_log(CIL_ERR, "Improper ioport specified\n");
   4780 			goto exit;
   4781 		}
   4782 		ioportcon->ioport_high = ioportcon->ioport_low;
   4783 	}
   4784 
   4785 	if (parse_current->next->next->cl_head == NULL ) {
   4786 		ioportcon->context_str = parse_current->next->next->data;
   4787 	} else {
   4788 		cil_context_init(&ioportcon->context);
   4789 
   4790 		rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
   4791 		if (rc != SEPOL_OK) {
   4792 			goto exit;
   4793 		}
   4794 	}
   4795 
   4796 	ast_node->data = ioportcon;
   4797 	ast_node->flavor = CIL_IOPORTCON;
   4798 
   4799 	return SEPOL_OK;
   4800 
   4801 exit:
   4802 	cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
   4803 	cil_destroy_ioportcon(ioportcon);
   4804 	return rc;
   4805 }
   4806 
   4807 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
   4808 {
   4809 	if (ioportcon == NULL) {
   4810 		return;
   4811 	}
   4812 
   4813 	if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
   4814 		cil_destroy_context(ioportcon->context);
   4815 	}
   4816 
   4817 	free(ioportcon);
   4818 }
   4819 
   4820 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4821 {
   4822 	enum cil_syntax syntax[] = {
   4823 		CIL_SYN_STRING,
   4824 		CIL_SYN_STRING,
   4825 		CIL_SYN_STRING | CIL_SYN_LIST,
   4826 		CIL_SYN_END
   4827 	};
   4828 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4829 	int rc = SEPOL_ERR;
   4830 	struct cil_pcidevicecon *pcidevicecon = NULL;
   4831 
   4832 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4833 		goto exit;
   4834 	}
   4835 
   4836 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4837 	if (rc != SEPOL_OK) {
   4838 		goto exit;
   4839 	}
   4840 
   4841 	cil_pcidevicecon_init(&pcidevicecon);
   4842 
   4843 	rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
   4844 	if (rc != SEPOL_OK) {
   4845 		goto exit;
   4846 	}
   4847 
   4848 	if (parse_current->next->next->cl_head == NULL) {
   4849 		pcidevicecon->context_str = parse_current->next->next->data;
   4850 	} else {
   4851 		cil_context_init(&pcidevicecon->context);
   4852 
   4853 		rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
   4854 		if (rc != SEPOL_OK) {
   4855 			goto exit;
   4856 		}
   4857 	}
   4858 
   4859 	ast_node->data = pcidevicecon;
   4860 	ast_node->flavor = CIL_PCIDEVICECON;
   4861 
   4862 	return SEPOL_OK;
   4863 
   4864 exit:
   4865 	cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
   4866 	cil_destroy_pcidevicecon(pcidevicecon);
   4867 	return rc;
   4868 }
   4869 
   4870 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
   4871 {
   4872 	if (pcidevicecon == NULL) {
   4873 		return;
   4874 	}
   4875 
   4876 	if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
   4877 		cil_destroy_context(pcidevicecon->context);
   4878 	}
   4879 
   4880 	free(pcidevicecon);
   4881 }
   4882 
   4883 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4884 {
   4885 	enum cil_syntax syntax[] = {
   4886 		CIL_SYN_STRING,
   4887 		CIL_SYN_STRING,
   4888 		CIL_SYN_STRING | CIL_SYN_LIST,
   4889 		CIL_SYN_END
   4890 	};
   4891 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4892 	int rc = SEPOL_ERR;
   4893 	struct cil_devicetreecon *devicetreecon = NULL;
   4894 
   4895 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4896 		goto exit;
   4897 	}
   4898 
   4899 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4900 	if (rc != SEPOL_OK) {
   4901 		goto exit;
   4902 	}
   4903 
   4904 	cil_devicetreecon_init(&devicetreecon);
   4905 
   4906 	devicetreecon->path = parse_current->next->data;
   4907 
   4908 	if (parse_current->next->next->cl_head == NULL) {
   4909 		devicetreecon->context_str = parse_current->next->next->data;
   4910 	} else {
   4911 		cil_context_init(&devicetreecon->context);
   4912 
   4913 		rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
   4914 		if (rc != SEPOL_OK) {
   4915 			goto exit;
   4916 		}
   4917 	}
   4918 
   4919 	ast_node->data = devicetreecon;
   4920 	ast_node->flavor = CIL_DEVICETREECON;
   4921 
   4922 	return SEPOL_OK;
   4923 
   4924 exit:
   4925 	cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
   4926 	cil_destroy_devicetreecon(devicetreecon);
   4927 	return rc;
   4928 }
   4929 
   4930 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
   4931 {
   4932 	if (devicetreecon == NULL) {
   4933 		return;
   4934 	}
   4935 
   4936 	if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
   4937 		cil_destroy_context(devicetreecon->context);
   4938 	}
   4939 
   4940 	free(devicetreecon);
   4941 }
   4942 
   4943 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4944 {
   4945 	enum cil_syntax syntax[] = {
   4946 		CIL_SYN_STRING,
   4947 		CIL_SYN_STRING,
   4948 		CIL_SYN_STRING,
   4949 		CIL_SYN_STRING | CIL_SYN_LIST,
   4950 		CIL_SYN_END
   4951 	};
   4952 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4953 	char *type = NULL;
   4954 	struct cil_fsuse *fsuse = NULL;
   4955 	int rc = SEPOL_ERR;
   4956 
   4957 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4958 		goto exit;
   4959 	}
   4960 
   4961 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4962 	if (rc != SEPOL_OK) {
   4963 		goto exit;
   4964 	}
   4965 
   4966 	type = parse_current->next->data;
   4967 
   4968 	cil_fsuse_init(&fsuse);
   4969 
   4970 	if (type == CIL_KEY_XATTR) {
   4971 		fsuse->type = CIL_FSUSE_XATTR;
   4972 	} else if (type == CIL_KEY_TASK) {
   4973 		fsuse->type = CIL_FSUSE_TASK;
   4974 	} else if (type == CIL_KEY_TRANS) {
   4975 		fsuse->type = CIL_FSUSE_TRANS;
   4976 	} else {
   4977 		cil_log(CIL_ERR, "Invalid fsuse type\n");
   4978 		goto exit;
   4979 	}
   4980 
   4981 	fsuse->fs_str = parse_current->next->next->data;
   4982 
   4983 	if (parse_current->next->next->next->cl_head == NULL) {
   4984 		fsuse->context_str = parse_current->next->next->next->data;
   4985 	} else {
   4986 		cil_context_init(&fsuse->context);
   4987 
   4988 		rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
   4989 		if (rc != SEPOL_OK) {
   4990 			goto exit;
   4991 		}
   4992 	}
   4993 
   4994 	ast_node->data = fsuse;
   4995 	ast_node->flavor = CIL_FSUSE;
   4996 
   4997 	return SEPOL_OK;
   4998 
   4999 exit:
   5000 	cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
   5001 	cil_destroy_fsuse(fsuse);
   5002 	return SEPOL_ERR;
   5003 }
   5004 
   5005 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
   5006 {
   5007 	if (fsuse == NULL) {
   5008 		return;
   5009 	}
   5010 
   5011 	if (fsuse->context_str == NULL && fsuse->context != NULL) {
   5012 		cil_destroy_context(fsuse->context);
   5013 	}
   5014 
   5015 	free(fsuse);
   5016 }
   5017 
   5018 void cil_destroy_param(struct cil_param *param)
   5019 {
   5020 	if (param == NULL) {
   5021 		return;
   5022 	}
   5023 
   5024 	free(param);
   5025 }
   5026 
   5027 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5028 {
   5029 	int rc = SEPOL_ERR;
   5030 	char *key = NULL;
   5031 	struct cil_macro *macro = NULL;
   5032 	struct cil_tree_node *macro_content = NULL;
   5033 	enum cil_syntax syntax[] = {
   5034 		CIL_SYN_STRING,
   5035 		CIL_SYN_STRING,
   5036 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
   5037 		CIL_SYN_N_LISTS | CIL_SYN_END,
   5038 		CIL_SYN_END
   5039 	};
   5040 	int syntax_len = sizeof(syntax)/ sizeof(*syntax);
   5041 
   5042 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5043 		goto exit;
   5044 	}
   5045 
   5046 	rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
   5047 	if (rc != SEPOL_OK) {
   5048 		goto exit;
   5049 	}
   5050 
   5051 	cil_macro_init(&macro);
   5052 
   5053 	key = parse_current->next->data;
   5054 
   5055 	struct cil_tree_node *current_item = parse_current->next->next->cl_head;
   5056 	while (current_item != NULL) {
   5057 		enum cil_syntax param_syntax[] = {
   5058 			CIL_SYN_STRING,
   5059 			CIL_SYN_STRING,
   5060 			CIL_SYN_END
   5061 		};
   5062 		int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
   5063 		char *kind = NULL;
   5064 		struct cil_param *param = NULL;
   5065 
   5066 		rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
   5067 		if (rc != SEPOL_OK) {
   5068 			goto exit;
   5069 		}
   5070 
   5071 		if (macro->params == NULL) {
   5072 			cil_list_init(&macro->params, CIL_LIST_ITEM);
   5073 		}
   5074 
   5075 		kind = current_item->cl_head->data;
   5076 		cil_param_init(&param);
   5077 
   5078 		if (kind == CIL_KEY_TYPE) {
   5079 			param->flavor = CIL_TYPE;
   5080 		} else if (kind == CIL_KEY_ROLE) {
   5081 			param->flavor = CIL_ROLE;
   5082 		} else if (kind == CIL_KEY_USER) {
   5083 			param->flavor = CIL_USER;
   5084 		} else if (kind == CIL_KEY_SENSITIVITY) {
   5085 			param->flavor = CIL_SENS;
   5086 		} else if (kind == CIL_KEY_CATEGORY) {
   5087 			param->flavor = CIL_CAT;
   5088 		} else if (kind == CIL_KEY_CATSET) {
   5089 			param->flavor = CIL_CATSET;
   5090 		} else if (kind == CIL_KEY_LEVEL) {
   5091 			param->flavor = CIL_LEVEL;
   5092 		} else if (kind == CIL_KEY_LEVELRANGE) {
   5093 			param->flavor = CIL_LEVELRANGE;
   5094 		} else if (kind == CIL_KEY_CLASS) {
   5095 			param->flavor = CIL_CLASS;
   5096 		} else if (kind == CIL_KEY_IPADDR) {
   5097 			param->flavor = CIL_IPADDR;
   5098 		} else if (kind == CIL_KEY_MAP_CLASS) {
   5099 			param->flavor = CIL_MAP_CLASS;
   5100 		} else if (kind == CIL_KEY_CLASSPERMISSION) {
   5101 			param->flavor = CIL_CLASSPERMISSION;
   5102 		} else if (kind == CIL_KEY_BOOL) {
   5103 			param->flavor = CIL_BOOL;
   5104 		} else if (kind == CIL_KEY_STRING) {
   5105 			param->flavor = CIL_NAME;
   5106 		} else if (kind == CIL_KEY_NAME) {
   5107 			param->flavor = CIL_NAME;
   5108 		} else {
   5109 			cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
   5110 			cil_destroy_param(param);
   5111 			goto exit;
   5112 		}
   5113 
   5114 		param->str =  current_item->cl_head->next->data;
   5115 
   5116 		rc = __cil_verify_name(param->str);
   5117 		if (rc != SEPOL_OK) {
   5118 			cil_destroy_param(param);
   5119 			goto exit;
   5120 		}
   5121 
   5122 		//walk current list and check for duplicate parameters
   5123 		struct cil_list_item *curr_param;
   5124 		cil_list_for_each(curr_param, macro->params) {
   5125 			if (param->str == ((struct cil_param*)curr_param->data)->str) {
   5126 				if (param->flavor == ((struct cil_param*)curr_param->data)->flavor) {
   5127 					cil_log(CIL_ERR, "Duplicate parameter\n");
   5128 					cil_destroy_param(param);
   5129 					goto exit;
   5130 				}
   5131 			}
   5132 		}
   5133 
   5134 		cil_list_append(macro->params, CIL_PARAM, param);
   5135 
   5136 		current_item = current_item->next;
   5137 	}
   5138 
   5139 	/* we don't want the tree walker to walk the macro parameters (they were just handled above), so the subtree is deleted, and the next pointer of the
   5140            node containing the macro name is updated to point to the start of the macro content */
   5141 	macro_content = parse_current->next->next->next;
   5142 	cil_tree_subtree_destroy(parse_current->next->next);
   5143 	parse_current->next->next = macro_content;
   5144 	if (macro_content == NULL) {
   5145 		/* No statements in macro and macro parameter list was last node */
   5146 		parse_current->parent->cl_tail = parse_current->next;
   5147 	}
   5148 
   5149 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
   5150 	if (rc != SEPOL_OK) {
   5151 		goto exit;
   5152 	}
   5153 
   5154 	return SEPOL_OK;
   5155 
   5156 exit:
   5157 	cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
   5158 	cil_destroy_macro(macro);
   5159 	cil_clear_node(ast_node);
   5160 	return SEPOL_ERR;
   5161 }
   5162 
   5163 void cil_destroy_macro(struct cil_macro *macro)
   5164 {
   5165 	if (macro == NULL) {
   5166 		return;
   5167 	}
   5168 
   5169 	cil_symtab_datum_destroy(&macro->datum);
   5170 	cil_symtab_array_destroy(macro->symtab);
   5171 
   5172 	if (macro->params != NULL) {
   5173 		cil_list_destroy(&macro->params, 1);
   5174 	}
   5175 
   5176 	free(macro);
   5177 }
   5178 
   5179 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5180 {
   5181 	enum cil_syntax syntax[] = {
   5182 		CIL_SYN_STRING,
   5183 		CIL_SYN_STRING,
   5184 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
   5185 		CIL_SYN_END
   5186 	};
   5187 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5188 	struct cil_call *call = NULL;
   5189 	int rc = SEPOL_ERR;
   5190 
   5191 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5192 		goto exit;
   5193 	}
   5194 
   5195 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5196 	if (rc != SEPOL_OK) {
   5197 		goto exit;
   5198 	}
   5199 
   5200 	cil_call_init(&call);
   5201 
   5202 	call->macro_str = parse_current->next->data;
   5203 
   5204 	if (parse_current->next->next != NULL) {
   5205 		cil_tree_init(&call->args_tree);
   5206 		cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
   5207 	}
   5208 
   5209 	ast_node->data = call;
   5210 	ast_node->flavor = CIL_CALL;
   5211 
   5212 	return SEPOL_OK;
   5213 
   5214 exit:
   5215 	cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
   5216 	cil_destroy_call(call);
   5217 	return rc;
   5218 }
   5219 
   5220 void cil_destroy_call(struct cil_call *call)
   5221 {
   5222 	if (call == NULL) {
   5223 		return;
   5224 	}
   5225 
   5226 	call->macro = NULL;
   5227 
   5228 	if (call->args_tree != NULL) {
   5229 		cil_tree_destroy(&call->args_tree);
   5230 	}
   5231 
   5232 	if (call->args != NULL) {
   5233 		cil_list_destroy(&call->args, 1);
   5234 	}
   5235 
   5236 	free(call);
   5237 }
   5238 
   5239 void cil_destroy_args(struct cil_args *args)
   5240 {
   5241 	if (args == NULL) {
   5242 		return;
   5243 	}
   5244 
   5245 	if (args->arg_str != NULL) {
   5246 		args->arg_str = NULL;
   5247 	} else if (args->arg != NULL) {
   5248 		struct cil_tree_node *node = args->arg->nodes->head->data;
   5249 		switch (args->flavor) {
   5250 		case CIL_NAME:
   5251 			break;
   5252 		case CIL_CATSET:
   5253 			cil_destroy_catset((struct cil_catset *)args->arg);
   5254 			free(node);
   5255 			break;
   5256 		case CIL_LEVEL:
   5257 			cil_destroy_level((struct cil_level *)args->arg);
   5258 			free(node);
   5259 			break;
   5260 		case CIL_LEVELRANGE:
   5261 			cil_destroy_levelrange((struct cil_levelrange *)args->arg);
   5262 			free(node);
   5263 			break;
   5264 		case CIL_IPADDR:
   5265 			cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
   5266 			free(node);
   5267 			break;
   5268 		case CIL_CLASSPERMISSION:
   5269 			cil_destroy_classpermission((struct cil_classpermission *)args->arg);
   5270 			free(node);
   5271 			break;
   5272 		default:
   5273 			cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
   5274 			break;
   5275 		}
   5276 	}
   5277 
   5278 	args->param_str = NULL;
   5279 	args->arg = NULL;
   5280 
   5281 	free(args);
   5282 }
   5283 
   5284 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5285 {
   5286 	enum cil_syntax syntax[] = {
   5287 		CIL_SYN_STRING,
   5288 		CIL_SYN_STRING,
   5289 		CIL_SYN_N_LISTS | CIL_SYN_END,
   5290 		CIL_SYN_END
   5291 	};
   5292 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5293 	char *key = NULL;
   5294 	struct cil_optional *optional = NULL;
   5295 	int rc = SEPOL_ERR;
   5296 
   5297 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5298 		goto exit;
   5299 	}
   5300 
   5301 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5302 	if (rc != SEPOL_OK) {
   5303 		goto exit;
   5304 	}
   5305 
   5306 	cil_optional_init(&optional);
   5307 
   5308 	key = parse_current->next->data;
   5309 
   5310 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
   5311 	if (rc != SEPOL_OK)
   5312 		goto exit;
   5313 
   5314 	return SEPOL_OK;
   5315 
   5316 exit:
   5317 	cil_tree_log(parse_current, CIL_ERR, "Bad optional");
   5318 	cil_destroy_optional(optional);
   5319 	cil_clear_node(ast_node);
   5320 	return rc;
   5321 }
   5322 
   5323 void cil_destroy_optional(struct cil_optional *optional)
   5324 {
   5325 	if (optional == NULL) {
   5326 		return;
   5327 	}
   5328 
   5329 	cil_symtab_datum_destroy(&optional->datum);
   5330 	free(optional);
   5331 }
   5332 
   5333 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5334 {
   5335 	enum cil_syntax syntax[] = {
   5336 		CIL_SYN_STRING,
   5337 		CIL_SYN_STRING,
   5338 		CIL_SYN_END
   5339 	};
   5340 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5341 	char *key = NULL;
   5342 	struct cil_policycap *polcap = NULL;
   5343 	int rc = SEPOL_ERR;
   5344 
   5345 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5346 		goto exit;
   5347 	}
   5348 
   5349 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5350 	if (rc != SEPOL_OK) {
   5351 		goto exit;
   5352 	}
   5353 
   5354 	cil_policycap_init(&polcap);
   5355 
   5356 	key = parse_current->next->data;
   5357 
   5358 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
   5359 	if (rc != SEPOL_OK)
   5360 		goto exit;
   5361 
   5362 	return SEPOL_OK;
   5363 
   5364 exit:
   5365 	cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
   5366 	cil_destroy_policycap(polcap);
   5367 	cil_clear_node(ast_node);
   5368 	return rc;
   5369 }
   5370 
   5371 void cil_destroy_policycap(struct cil_policycap *polcap)
   5372 {
   5373 	if (polcap == NULL) {
   5374 		return;
   5375 	}
   5376 
   5377 	cil_symtab_datum_destroy(&polcap->datum);
   5378 	free(polcap);
   5379 }
   5380 
   5381 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5382 {
   5383 	enum cil_syntax syntax[] = {
   5384 		CIL_SYN_STRING,
   5385 		CIL_SYN_STRING,
   5386 		CIL_SYN_STRING,
   5387 		CIL_SYN_END
   5388 	};
   5389 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5390 	char *key = NULL;
   5391 	struct cil_ipaddr *ipaddr = NULL;
   5392 	int rc = SEPOL_ERR;
   5393 
   5394 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5395 		goto exit;
   5396 	}
   5397 
   5398 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5399 	if (rc != SEPOL_OK) {
   5400 		goto exit;
   5401 	}
   5402 
   5403 	cil_ipaddr_init(&ipaddr);
   5404 
   5405 	key  = parse_current->next->data;
   5406 
   5407 	rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
   5408 	if (rc != SEPOL_OK) {
   5409 		goto exit;
   5410 	}
   5411 
   5412 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
   5413 	if (rc != SEPOL_OK) {
   5414 		goto exit;
   5415 	}
   5416 
   5417 	return SEPOL_OK;
   5418 
   5419 exit:
   5420 	cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
   5421 	cil_destroy_ipaddr(ipaddr);
   5422 	cil_clear_node(ast_node);
   5423 	return rc;
   5424 }
   5425 
   5426 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
   5427 {
   5428 	if (ipaddr == NULL) {
   5429 		return;
   5430 	}
   5431 
   5432 	cil_symtab_datum_destroy(&ipaddr->datum);
   5433 	free(ipaddr);
   5434 }
   5435 
   5436 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
   5437 {
   5438 	int rc = SEPOL_ERR;
   5439 	char *endptr = NULL;
   5440 	int val;
   5441 
   5442 	if (int_node == NULL || integer == NULL) {
   5443 		goto exit;
   5444 	}
   5445 
   5446 	errno = 0;
   5447 	val = strtol(int_node->data, &endptr, base);
   5448 	if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
   5449 		rc = SEPOL_ERR;
   5450 		goto exit;
   5451 	}
   5452 
   5453 	*integer = val;
   5454 
   5455 	return SEPOL_OK;
   5456 
   5457 exit:
   5458 	cil_log(CIL_ERR, "Failed to create integer from string\n");
   5459 	return rc;
   5460 }
   5461 
   5462 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
   5463 {
   5464 	int rc = SEPOL_ERR;
   5465 	char *endptr = NULL;
   5466 	uint64_t val;
   5467 
   5468 	if (int_node == NULL || integer == NULL) {
   5469 		goto exit;
   5470 	}
   5471 
   5472 	errno = 0;
   5473 	val = strtoull(int_node->data, &endptr, base);
   5474 	if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
   5475 		rc = SEPOL_ERR;
   5476 		goto exit;
   5477 	}
   5478 
   5479 	*integer = val;
   5480 
   5481 	return SEPOL_OK;
   5482 
   5483 exit:
   5484 	cil_log(CIL_ERR, "Failed to create integer from string\n");
   5485 	return rc;
   5486 }
   5487 
   5488 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
   5489 {
   5490 	int rc = SEPOL_ERR;
   5491 
   5492 	if (addr_node == NULL || addr == NULL) {
   5493 		goto exit;
   5494 	}
   5495 
   5496 	if (addr_node->cl_head != NULL ||  addr_node->next != NULL) {
   5497 		goto exit;
   5498 	}
   5499 
   5500 	if (strchr(addr_node->data, '.') != NULL) {
   5501 		addr->family = AF_INET;
   5502 	} else {
   5503 		addr->family = AF_INET6;
   5504 	}
   5505 
   5506 	rc = inet_pton(addr->family, addr_node->data, &addr->ip);
   5507 	if (rc != 1) {
   5508 		rc = SEPOL_ERR;
   5509 		goto exit;
   5510 	}
   5511 
   5512 	return SEPOL_OK;
   5513 
   5514 exit:
   5515 	cil_log(CIL_ERR, "Bad ip address or netmask\n");
   5516 	return rc;
   5517 }
   5518 
   5519 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
   5520 {
   5521 	int rc = SEPOL_ERR;
   5522 	enum cil_syntax syntax[] = {
   5523 		CIL_SYN_STRING,
   5524 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
   5525 		CIL_SYN_END
   5526 	};
   5527 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5528 
   5529 	if (curr == NULL) {
   5530 		goto exit;
   5531 	}
   5532 
   5533 	rc = __cil_verify_syntax(curr, syntax, syntax_len);
   5534 	if (rc != SEPOL_OK) {
   5535 		goto exit;
   5536 	}
   5537 
   5538 	level->sens_str = curr->data;
   5539 	if (curr->next != NULL) {
   5540 		rc = cil_fill_cats(curr->next, &level->cats);
   5541 		if (rc != SEPOL_OK) {
   5542 			goto exit;
   5543 		}
   5544 	}
   5545 
   5546 	return SEPOL_OK;
   5547 
   5548 exit:
   5549 	cil_log(CIL_ERR, "Bad level\n");
   5550 	return rc;
   5551 }
   5552 
   5553 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
   5554 {
   5555 	int rc = SEPOL_ERR;
   5556 
   5557 	cil_cats_init(cats);
   5558 
   5559 	rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
   5560 	if (rc != SEPOL_OK) {
   5561 		cil_destroy_cats(*cats);
   5562 		*cats = NULL;
   5563 	}
   5564 
   5565 	return rc;
   5566 }
   5567 
   5568 void cil_destroy_cats(struct cil_cats *cats)
   5569 {
   5570 	if (cats == NULL) {
   5571 		return;
   5572 	}
   5573 
   5574 	cil_list_destroy(&cats->str_expr, CIL_TRUE);
   5575 
   5576 	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
   5577 
   5578 	free(cats);
   5579 }
   5580 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   5581 {
   5582 	enum cil_syntax syntax[] = {
   5583 		CIL_SYN_STRING,
   5584 		CIL_SYN_STRING,
   5585 		CIL_SYN_STRING,
   5586 		CIL_SYN_END
   5587 	};
   5588 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5589 	struct cil_bounds *bounds = NULL;
   5590 	int rc = SEPOL_ERR;
   5591 
   5592 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5593 		goto exit;
   5594 	}
   5595 
   5596 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5597 	if (rc != SEPOL_OK) {
   5598 		goto exit;
   5599 	}
   5600 
   5601 	cil_bounds_init(&bounds);
   5602 
   5603 	bounds->parent_str = parse_current->next->data;
   5604 	bounds->child_str = parse_current->next->next->data;
   5605 
   5606 	ast_node->data = bounds;
   5607 
   5608 	switch (flavor) {
   5609 	case CIL_USER:
   5610 		ast_node->flavor = CIL_USERBOUNDS;
   5611 		break;
   5612 	case CIL_ROLE:
   5613 		ast_node->flavor = CIL_ROLEBOUNDS;
   5614 		break;
   5615 	case CIL_TYPE:
   5616 		ast_node->flavor = CIL_TYPEBOUNDS;
   5617 		break;
   5618 	default:
   5619 		break;
   5620 	}
   5621 
   5622 	return SEPOL_OK;
   5623 
   5624 exit:
   5625 	cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
   5626 	cil_destroy_bounds(bounds);
   5627 	return rc;
   5628 }
   5629 
   5630 void cil_destroy_bounds(struct cil_bounds *bounds)
   5631 {
   5632 	if (bounds == NULL) {
   5633 		return;
   5634 	}
   5635 
   5636 	free(bounds);
   5637 }
   5638 
   5639 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   5640 {
   5641 	int rc = SEPOL_ERR;
   5642 	struct cil_default *def = NULL;
   5643 	char *object;
   5644 	enum cil_syntax syntax[] = {
   5645 		CIL_SYN_STRING,
   5646 		CIL_SYN_STRING | CIL_SYN_LIST,
   5647 		CIL_SYN_STRING,
   5648 		CIL_SYN_END
   5649 	};
   5650 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5651 
   5652 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5653 	if (rc != SEPOL_OK) {
   5654 		goto exit;
   5655 	}
   5656 
   5657 	cil_default_init(&def);
   5658 
   5659 	def->flavor = flavor;
   5660 
   5661 	if (parse_current->next->cl_head == NULL) {
   5662 		cil_list_init(&def->class_strs, CIL_CLASS);
   5663 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
   5664 	} else {
   5665 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
   5666 		if (rc != SEPOL_OK) {
   5667 			goto exit;
   5668 		}
   5669 	}
   5670 
   5671 	object = parse_current->next->next->data;
   5672 	if (object == CIL_KEY_SOURCE) {
   5673 		def->object = CIL_DEFAULT_SOURCE;
   5674 	} else if (object == CIL_KEY_TARGET) {
   5675 		def->object = CIL_DEFAULT_TARGET;
   5676 	} else {
   5677 		cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
   5678 		rc = SEPOL_ERR;
   5679 		goto exit;
   5680 	}
   5681 
   5682 	ast_node->data = def;
   5683 	ast_node->flavor = flavor;
   5684 
   5685 	return SEPOL_OK;
   5686 
   5687 exit:
   5688 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
   5689 	cil_destroy_default(def);
   5690 	return rc;
   5691 }
   5692 
   5693 void cil_destroy_default(struct cil_default *def)
   5694 {
   5695 	if (def == NULL) {
   5696 		return;
   5697 	}
   5698 
   5699 	cil_list_destroy(&def->class_strs, CIL_TRUE);
   5700 
   5701 	cil_list_destroy(&def->class_datums, CIL_FALSE);
   5702 
   5703 	free(def);
   5704 }
   5705 
   5706 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5707 {
   5708 	int rc = SEPOL_ERR;
   5709 	struct cil_defaultrange *def = NULL;
   5710 	char *object;
   5711 	char *range;
   5712 	enum cil_syntax syntax[] = {
   5713 		CIL_SYN_STRING,
   5714 		CIL_SYN_STRING | CIL_SYN_LIST,
   5715 		CIL_SYN_STRING,
   5716 		CIL_SYN_STRING,
   5717 		CIL_SYN_END
   5718 	};
   5719 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5720 
   5721 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5722 	if (rc != SEPOL_OK) {
   5723 		goto exit;
   5724 	}
   5725 
   5726 	cil_defaultrange_init(&def);
   5727 
   5728 	if (parse_current->next->cl_head == NULL) {
   5729 		cil_list_init(&def->class_strs, CIL_CLASS);
   5730 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
   5731 	} else {
   5732 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
   5733 		if (rc != SEPOL_OK) {
   5734 			goto exit;
   5735 		}
   5736 	}
   5737 
   5738 	object = parse_current->next->next->data;
   5739 	range = parse_current->next->next->next->data;
   5740 	if (object == CIL_KEY_SOURCE) {
   5741 		if (range == CIL_KEY_LOW) {
   5742 			def->object_range = CIL_DEFAULT_SOURCE_LOW;
   5743 		} else if (range == CIL_KEY_HIGH) {
   5744 			def->object_range = CIL_DEFAULT_SOURCE_HIGH;
   5745 		} else if (range == CIL_KEY_LOW_HIGH) {
   5746 			def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
   5747 		} else {
   5748 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
   5749 			rc = SEPOL_ERR;
   5750 			goto exit;
   5751 		}
   5752 	} else if (parse_current->next->next->data == CIL_KEY_TARGET) {
   5753 		if (range == CIL_KEY_LOW) {
   5754 			def->object_range = CIL_DEFAULT_TARGET_LOW;
   5755 		} else if (range == CIL_KEY_HIGH) {
   5756 			def->object_range = CIL_DEFAULT_TARGET_HIGH;
   5757 		} else if (range == CIL_KEY_LOW_HIGH) {
   5758 			def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
   5759 		} else {
   5760 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
   5761 			rc = SEPOL_ERR;
   5762 			goto exit;
   5763 		}
   5764 	} else {
   5765 		cil_log(CIL_ERR,"Expected either \'source\' or \'target\'\n");
   5766 		rc = SEPOL_ERR;
   5767 		goto exit;
   5768 	}
   5769 
   5770 	ast_node->data = def;
   5771 	ast_node->flavor = CIL_DEFAULTRANGE;
   5772 
   5773 	return SEPOL_OK;
   5774 
   5775 exit:
   5776 	cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
   5777 	cil_destroy_defaultrange(def);
   5778 	return rc;
   5779 }
   5780 
   5781 void cil_destroy_defaultrange(struct cil_defaultrange *def)
   5782 {
   5783 	if (def == NULL) {
   5784 		return;
   5785 	}
   5786 
   5787 	cil_list_destroy(&def->class_strs, CIL_TRUE);
   5788 
   5789 	cil_list_destroy(&def->class_datums, CIL_FALSE);
   5790 
   5791 	free(def);
   5792 }
   5793 
   5794 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5795 {
   5796 	int rc = SEPOL_ERR;
   5797 	enum cil_syntax syntax[] = {
   5798 		CIL_SYN_STRING,
   5799 		CIL_SYN_STRING,
   5800 		CIL_SYN_END
   5801 	};
   5802 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5803 	struct cil_handleunknown *unknown = NULL;
   5804 	char *unknown_key;
   5805 
   5806 	if (parse_current == NULL || ast_node == NULL) {
   5807 		goto exit;
   5808 	}
   5809 
   5810 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5811 	if (rc != SEPOL_OK) {
   5812 		goto exit;
   5813 	}
   5814 
   5815 	cil_handleunknown_init(&unknown);
   5816 
   5817 	unknown_key = parse_current->next->data;
   5818 	if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
   5819 		unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
   5820 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
   5821 		unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
   5822 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
   5823 		unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
   5824 	} else {
   5825 		cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
   5826 		rc = SEPOL_ERR;
   5827 		goto exit;
   5828 	}
   5829 
   5830 	ast_node->data = unknown;
   5831 	ast_node->flavor = CIL_HANDLEUNKNOWN;
   5832 
   5833 	return SEPOL_OK;
   5834 
   5835 exit:
   5836 	cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
   5837 	cil_destroy_handleunknown(unknown);
   5838 	return rc;
   5839 }
   5840 
   5841 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
   5842 {
   5843 	free(unk);
   5844 }
   5845 
   5846 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5847 {
   5848 	int rc = SEPOL_ERR;
   5849 	enum cil_syntax syntax[] = {
   5850 		CIL_SYN_STRING,
   5851 		CIL_SYN_STRING,
   5852 		CIL_SYN_END
   5853 	};
   5854 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5855 	struct cil_mls *mls = NULL;
   5856 
   5857 	if (parse_current == NULL || ast_node == NULL) {
   5858 		goto exit;
   5859 	}
   5860 
   5861 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5862 	if (rc != SEPOL_OK) {
   5863 		goto exit;
   5864 	}
   5865 
   5866 	cil_mls_init(&mls);
   5867 
   5868 	if (parse_current->next->data == CIL_KEY_CONDTRUE) {
   5869 		mls->value = CIL_TRUE;
   5870 	} else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
   5871 		mls->value = CIL_FALSE;
   5872 	} else {
   5873 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
   5874 		rc = SEPOL_ERR;
   5875 		goto exit;
   5876 	}
   5877 
   5878 	ast_node->data = mls;
   5879 	ast_node->flavor = CIL_MLS;
   5880 
   5881 	return SEPOL_OK;
   5882 
   5883 exit:
   5884 	cil_tree_log(parse_current, CIL_ERR, "Bad mls");
   5885 	cil_destroy_mls(mls);
   5886 	return rc;
   5887 }
   5888 
   5889 void cil_destroy_mls(struct cil_mls *mls)
   5890 {
   5891 	free(mls);
   5892 }
   5893 
   5894 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5895 {
   5896 	/* No need to check syntax, because this is auto generated */
   5897 	struct cil_src_info *info = NULL;
   5898 
   5899 	cil_src_info_init(&info);
   5900 
   5901 	info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE;
   5902 	info->path = parse_current->next->next->data;
   5903 
   5904 	ast_node->data = info;
   5905 	ast_node->flavor = CIL_SRC_INFO;
   5906 
   5907 	return SEPOL_OK;
   5908 }
   5909 
   5910 void cil_destroy_src_info(struct cil_src_info *info)
   5911 {
   5912 	free(info);
   5913 }
   5914 
   5915 int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
   5916 {
   5917 	struct cil_args_build *args = NULL;
   5918 	struct cil_tree_node *ast_current = NULL;
   5919 	struct cil_db *db = NULL;
   5920 	struct cil_tree_node *ast_node = NULL;
   5921 	struct cil_tree_node *macro = NULL;
   5922 	struct cil_tree_node *boolif = NULL;
   5923 	struct cil_tree_node *tunif = NULL;
   5924 	struct cil_tree_node *in = NULL;
   5925 	int rc = SEPOL_ERR;
   5926 
   5927 	if (parse_current == NULL || finished == NULL || extra_args == NULL) {
   5928 		goto exit;
   5929 	}
   5930 
   5931 	args = extra_args;
   5932 	ast_current = args->ast;
   5933 	db = args->db;
   5934 	macro = args->macro;
   5935 	boolif = args->boolif;
   5936 	tunif = args->tunif;
   5937 	in = args->in;
   5938 
   5939 	if (parse_current->parent->cl_head != parse_current) {
   5940 		/* ignore anything that isn't following a parenthesis */
   5941 		rc = SEPOL_OK;
   5942 		goto exit;
   5943 	} else if (parse_current->data == NULL) {
   5944 		/* the only time parenthsis can immediately following parenthesis is if
   5945 		 * the parent is the root node */
   5946 		if (parse_current->parent->parent == NULL) {
   5947 			rc = SEPOL_OK;
   5948 		} else {
   5949 			cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
   5950 		}
   5951 		goto exit;
   5952 	}
   5953 
   5954 	if (macro != NULL) {
   5955 		if (parse_current->data == CIL_KEY_MACRO ||
   5956 			parse_current->data == CIL_KEY_TUNABLE ||
   5957 			parse_current->data == CIL_KEY_IN ||
   5958 			parse_current->data == CIL_KEY_BLOCK ||
   5959 			parse_current->data == CIL_KEY_BLOCKINHERIT ||
   5960 			parse_current->data == CIL_KEY_BLOCKABSTRACT) {
   5961 			rc = SEPOL_ERR;
   5962 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data);
   5963 			goto exit;
   5964 		}
   5965 	}
   5966 
   5967 	if (boolif != NULL) {
   5968 		if (parse_current->data != CIL_KEY_CONDTRUE &&
   5969 			parse_current->data != CIL_KEY_CONDFALSE &&
   5970 			parse_current->data != CIL_KEY_AUDITALLOW &&
   5971 			parse_current->data != CIL_KEY_TUNABLEIF &&
   5972 			parse_current->data != CIL_KEY_ALLOW &&
   5973 			parse_current->data != CIL_KEY_DONTAUDIT &&
   5974 			parse_current->data != CIL_KEY_TYPETRANSITION &&
   5975 			parse_current->data != CIL_KEY_TYPECHANGE &&
   5976 			parse_current->data != CIL_KEY_CALL) {
   5977 			rc = SEPOL_ERR;
   5978 			cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
   5979 			if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
   5980 				cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n",
   5981 						(char*)parse_current->data);
   5982 			} else {
   5983 				cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n",
   5984 						(char*)parse_current->data);
   5985 			}
   5986 			goto exit;
   5987 		}
   5988 	}
   5989 
   5990 	if (tunif != NULL) {
   5991 		if (parse_current->data == CIL_KEY_TUNABLE) {
   5992 			rc = SEPOL_ERR;
   5993 			cil_tree_log(parse_current, CIL_ERR, "Found tunable");
   5994 			cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
   5995 			goto exit;
   5996 		}
   5997 	}
   5998 
   5999 	if (in != NULL) {
   6000 		if (parse_current->data == CIL_KEY_IN) {
   6001 			rc = SEPOL_ERR;
   6002 			cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
   6003 			cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
   6004 			goto exit;
   6005 		}
   6006 	}
   6007 
   6008 	cil_tree_node_init(&ast_node);
   6009 
   6010 	ast_node->parent = ast_current;
   6011 	ast_node->line = parse_current->line;
   6012 	ast_node->hll_line = parse_current->hll_line;
   6013 
   6014 	if (parse_current->data == CIL_KEY_BLOCK) {
   6015 		rc = cil_gen_block(db, parse_current, ast_node, 0);
   6016 	} else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
   6017 		rc = cil_gen_blockinherit(db, parse_current, ast_node);
   6018 	} else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
   6019 		rc = cil_gen_blockabstract(db, parse_current, ast_node);
   6020 	} else if (parse_current->data == CIL_KEY_IN) {
   6021 		rc = cil_gen_in(db, parse_current, ast_node);
   6022 	} else if (parse_current->data == CIL_KEY_CLASS) {
   6023 		rc = cil_gen_class(db, parse_current, ast_node);
   6024 		// To avoid parsing list of perms again
   6025 		*finished = CIL_TREE_SKIP_NEXT;
   6026 	} else if (parse_current->data == CIL_KEY_CLASSORDER) {
   6027 		rc = cil_gen_classorder(db, parse_current, ast_node);
   6028 		*finished = CIL_TREE_SKIP_NEXT;
   6029 	} else if (parse_current->data == CIL_KEY_MAP_CLASS) {
   6030 		rc = cil_gen_map_class(db, parse_current, ast_node);
   6031 		*finished = CIL_TREE_SKIP_NEXT;
   6032 	} else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
   6033 		rc = cil_gen_classmapping(db, parse_current, ast_node);
   6034 		*finished = CIL_TREE_SKIP_NEXT;
   6035 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
   6036 		rc = cil_gen_classpermission(db, parse_current, ast_node);
   6037 		*finished = CIL_TREE_SKIP_NEXT;
   6038 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
   6039 		rc = cil_gen_classpermissionset(db, parse_current, ast_node);
   6040 		*finished = CIL_TREE_SKIP_NEXT;
   6041 	} else if (parse_current->data == CIL_KEY_COMMON) {
   6042 		rc = cil_gen_common(db, parse_current, ast_node);
   6043 		*finished = CIL_TREE_SKIP_NEXT;
   6044 	} else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
   6045 		rc = cil_gen_classcommon(db, parse_current, ast_node);
   6046 	} else if (parse_current->data == CIL_KEY_SID) {
   6047 		rc = cil_gen_sid(db, parse_current, ast_node);
   6048 		*finished = CIL_TREE_SKIP_NEXT;
   6049 	} else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
   6050 		rc = cil_gen_sidcontext(db, parse_current, ast_node);
   6051 		*finished = CIL_TREE_SKIP_NEXT;
   6052 	} else if (parse_current->data == CIL_KEY_SIDORDER) {
   6053 		rc = cil_gen_sidorder(db, parse_current, ast_node);
   6054 		*finished = CIL_TREE_SKIP_NEXT;
   6055 	} else if (parse_current->data == CIL_KEY_USER) {
   6056 		rc = cil_gen_user(db, parse_current, ast_node);
   6057 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
   6058 		rc = cil_gen_userattribute(db, parse_current, ast_node);
   6059 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
   6060 		rc = cil_gen_userattributeset(db, parse_current, ast_node);
   6061 		*finished = CIL_TREE_SKIP_NEXT;
   6062 	} else if (parse_current->data == CIL_KEY_USERLEVEL) {
   6063 		rc = cil_gen_userlevel(db, parse_current, ast_node);
   6064 		*finished = CIL_TREE_SKIP_NEXT;
   6065 	} else if (parse_current->data == CIL_KEY_USERRANGE) {
   6066 		rc = cil_gen_userrange(db, parse_current, ast_node);
   6067 		*finished = CIL_TREE_SKIP_NEXT;
   6068 	} else if (parse_current->data == CIL_KEY_USERBOUNDS) {
   6069 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER);
   6070 	} else if (parse_current->data == CIL_KEY_USERPREFIX) {
   6071 		rc = cil_gen_userprefix(db, parse_current, ast_node);
   6072 	} else if (parse_current->data == CIL_KEY_SELINUXUSER) {
   6073 		rc = cil_gen_selinuxuser(db, parse_current, ast_node);
   6074 		*finished = CIL_TREE_SKIP_NEXT;
   6075 	} else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
   6076 		rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node);
   6077 		*finished = CIL_TREE_SKIP_NEXT;
   6078 	} else if (parse_current->data == CIL_KEY_TYPE) {
   6079 		rc = cil_gen_type(db, parse_current, ast_node);
   6080 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
   6081 		rc = cil_gen_typeattribute(db, parse_current, ast_node);
   6082 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
   6083 		rc = cil_gen_typeattributeset(db, parse_current, ast_node);
   6084 		*finished = CIL_TREE_SKIP_NEXT;
   6085 	} else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
   6086 		rc = cil_gen_expandtypeattribute(db, parse_current, ast_node);
   6087 		*finished = CIL_TREE_SKIP_NEXT;
   6088 	} else if (parse_current->data == CIL_KEY_TYPEALIAS) {
   6089 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS);
   6090 	} else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
   6091 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL);
   6092 	} else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
   6093 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE);
   6094 	} else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
   6095 		rc = cil_gen_typepermissive(db, parse_current, ast_node);
   6096 	} else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
   6097 		rc = cil_gen_rangetransition(db, parse_current, ast_node);
   6098 		*finished = CIL_TREE_SKIP_NEXT;
   6099 	} else if (parse_current->data == CIL_KEY_ROLE) {
   6100 		rc = cil_gen_role(db, parse_current, ast_node);
   6101 	} else if (parse_current->data == CIL_KEY_USERROLE) {
   6102 		rc = cil_gen_userrole(db, parse_current, ast_node);
   6103 	} else if (parse_current->data == CIL_KEY_ROLETYPE) {
   6104 		rc = cil_gen_roletype(db, parse_current, ast_node);
   6105 	} else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
   6106 		rc = cil_gen_roletransition(parse_current, ast_node);
   6107 	} else if (parse_current->data == CIL_KEY_ROLEALLOW) {
   6108 		rc = cil_gen_roleallow(db, parse_current, ast_node);
   6109 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
   6110 		rc = cil_gen_roleattribute(db, parse_current, ast_node);
   6111 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
   6112 		rc = cil_gen_roleattributeset(db, parse_current, ast_node);
   6113 		*finished = CIL_TREE_SKIP_NEXT;
   6114 	} else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
   6115 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE);
   6116 	} else if (parse_current->data == CIL_KEY_BOOL) {
   6117 		rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE);
   6118 	} else if (parse_current->data == CIL_KEY_BOOLEANIF) {
   6119 		rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE);
   6120 	} else if(parse_current->data == CIL_KEY_TUNABLE) {
   6121 		if (db->preserve_tunables) {
   6122 			rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE);
   6123 		} else {
   6124 			rc = cil_gen_tunable(db, parse_current, ast_node);
   6125 		}
   6126 	} else if (parse_current->data == CIL_KEY_TUNABLEIF) {
   6127 		if (db->preserve_tunables) {
   6128 			rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE);
   6129 		} else {
   6130 			rc = cil_gen_tunif(db, parse_current, ast_node);
   6131 		}
   6132 	} else if (parse_current->data == CIL_KEY_CONDTRUE) {
   6133 		rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE);
   6134 	} else if (parse_current->data == CIL_KEY_CONDFALSE) {
   6135 		rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE);
   6136 	} else if (parse_current->data == CIL_KEY_ALLOW) {
   6137 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED);
   6138 		// So that the object and perms lists do not get parsed again
   6139 		*finished = CIL_TREE_SKIP_NEXT;
   6140 	} else if (parse_current->data == CIL_KEY_AUDITALLOW) {
   6141 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
   6142 		*finished = CIL_TREE_SKIP_NEXT;
   6143 	} else if (parse_current->data == CIL_KEY_DONTAUDIT) {
   6144 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
   6145 		*finished = CIL_TREE_SKIP_NEXT;
   6146 	} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
   6147 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
   6148 		*finished = CIL_TREE_SKIP_NEXT;
   6149 	} else if (parse_current->data == CIL_KEY_ALLOWX) {
   6150 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED);
   6151 		*finished = CIL_TREE_SKIP_NEXT;
   6152 	} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
   6153 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
   6154 		*finished = CIL_TREE_SKIP_NEXT;
   6155 	} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
   6156 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
   6157 		*finished = CIL_TREE_SKIP_NEXT;
   6158 	} else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
   6159 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
   6160 		*finished = CIL_TREE_SKIP_NEXT;
   6161 	} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
   6162 		rc = cil_gen_permissionx(db, parse_current, ast_node);
   6163 		*finished = CIL_TREE_SKIP_NEXT;
   6164 	} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
   6165 		rc = cil_gen_typetransition(db, parse_current, ast_node);
   6166 	} else if (parse_current->data == CIL_KEY_TYPECHANGE) {
   6167 		rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE);
   6168 	} else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
   6169 		rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER);
   6170 	} else if (parse_current->data == CIL_KEY_SENSITIVITY) {
   6171 		rc = cil_gen_sensitivity(db, parse_current, ast_node);
   6172 	} else if (parse_current->data == CIL_KEY_SENSALIAS) {
   6173 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS);
   6174 	} else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
   6175 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL);
   6176 	} else if (parse_current->data == CIL_KEY_CATEGORY) {
   6177 		rc = cil_gen_category(db, parse_current, ast_node);
   6178 	} else if (parse_current->data == CIL_KEY_CATALIAS) {
   6179 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS);
   6180 	} else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
   6181 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL);
   6182 	} else if (parse_current->data == CIL_KEY_CATSET) {
   6183 		rc = cil_gen_catset(db, parse_current, ast_node);
   6184 		*finished = CIL_TREE_SKIP_NEXT;
   6185 	} else if (parse_current->data == CIL_KEY_CATORDER) {
   6186 		rc = cil_gen_catorder(db, parse_current, ast_node);
   6187 		*finished = CIL_TREE_SKIP_NEXT;
   6188 	} else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
   6189 		rc = cil_gen_sensitivityorder(db, parse_current, ast_node);
   6190 		*finished = CIL_TREE_SKIP_NEXT;
   6191 	} else if (parse_current->data == CIL_KEY_SENSCAT) {
   6192 		rc = cil_gen_senscat(db, parse_current, ast_node);
   6193 		*finished = CIL_TREE_SKIP_NEXT;
   6194 	} else if (parse_current->data == CIL_KEY_LEVEL) {
   6195 		rc = cil_gen_level(db, parse_current, ast_node);
   6196 		*finished = CIL_TREE_SKIP_NEXT;
   6197 	} else if (parse_current->data == CIL_KEY_LEVELRANGE) {
   6198 		rc = cil_gen_levelrange(db, parse_current, ast_node);
   6199 		*finished = CIL_TREE_SKIP_NEXT;
   6200 	} else if (parse_current->data == CIL_KEY_CONSTRAIN) {
   6201 		rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN);
   6202 		*finished = CIL_TREE_SKIP_NEXT;
   6203 	} else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
   6204 		rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN);
   6205 		*finished = CIL_TREE_SKIP_NEXT;
   6206 	} else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
   6207 		rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS);
   6208 		*finished = CIL_TREE_SKIP_NEXT;
   6209 	} else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
   6210 		rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS);
   6211 		*finished = CIL_TREE_SKIP_NEXT;
   6212 	} else if (parse_current->data == CIL_KEY_CONTEXT) {
   6213 		rc = cil_gen_context(db, parse_current, ast_node);
   6214 		*finished = CIL_TREE_SKIP_NEXT;
   6215 	} else if (parse_current->data == CIL_KEY_FILECON) {
   6216 		rc = cil_gen_filecon(db, parse_current, ast_node);
   6217 		*finished = CIL_TREE_SKIP_NEXT;
   6218 	} else if (parse_current->data == CIL_KEY_PORTCON) {
   6219 		rc = cil_gen_portcon(db, parse_current, ast_node);
   6220 		*finished = CIL_TREE_SKIP_NEXT;
   6221 	} else if (parse_current->data == CIL_KEY_NODECON) {
   6222 		rc = cil_gen_nodecon(db, parse_current, ast_node);
   6223 		*finished = CIL_TREE_SKIP_NEXT;
   6224 	} else if (parse_current->data == CIL_KEY_GENFSCON) {
   6225 		rc = cil_gen_genfscon(db, parse_current, ast_node);
   6226 		*finished = CIL_TREE_SKIP_NEXT;
   6227 	} else if (parse_current->data == CIL_KEY_NETIFCON) {
   6228 		rc = cil_gen_netifcon(db, parse_current, ast_node);
   6229 		*finished = CIL_TREE_SKIP_NEXT;
   6230 	} else if (parse_current->data == CIL_KEY_PIRQCON) {
   6231 		rc = cil_gen_pirqcon(db, parse_current, ast_node);
   6232 		*finished = CIL_TREE_SKIP_NEXT;
   6233 	} else if (parse_current->data == CIL_KEY_IOMEMCON) {
   6234 		rc = cil_gen_iomemcon(db, parse_current, ast_node);
   6235 		*finished = CIL_TREE_SKIP_NEXT;
   6236 	} else if (parse_current->data == CIL_KEY_IOPORTCON) {
   6237 		rc = cil_gen_ioportcon(db, parse_current, ast_node);
   6238 		*finished = CIL_TREE_SKIP_NEXT;
   6239 	} else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
   6240 		rc = cil_gen_pcidevicecon(db, parse_current, ast_node);
   6241 		*finished = CIL_TREE_SKIP_NEXT;
   6242 	} else if (parse_current->data == CIL_KEY_DEVICETREECON) {
   6243 		rc = cil_gen_devicetreecon(db, parse_current, ast_node);
   6244 		*finished = CIL_TREE_SKIP_NEXT;
   6245 	} else if (parse_current->data == CIL_KEY_FSUSE) {
   6246 		rc = cil_gen_fsuse(db, parse_current, ast_node);
   6247 		*finished = CIL_TREE_SKIP_NEXT;
   6248 	} else if (parse_current->data == CIL_KEY_MACRO) {
   6249 		rc = cil_gen_macro(db, parse_current, ast_node);
   6250 	} else if (parse_current->data == CIL_KEY_CALL) {
   6251 		rc = cil_gen_call(db, parse_current, ast_node);
   6252 		*finished = 1;
   6253 	} else if (parse_current->data == CIL_KEY_POLICYCAP) {
   6254 		rc = cil_gen_policycap(db, parse_current, ast_node);
   6255 		*finished = 1;
   6256 	} else if (parse_current->data == CIL_KEY_OPTIONAL) {
   6257 		rc = cil_gen_optional(db, parse_current, ast_node);
   6258 	} else if (parse_current->data == CIL_KEY_IPADDR) {
   6259 		rc = cil_gen_ipaddr(db, parse_current, ast_node);
   6260 	} else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
   6261 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER);
   6262 		*finished = CIL_TREE_SKIP_NEXT;
   6263 	} else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
   6264 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE);
   6265 		*finished = CIL_TREE_SKIP_NEXT;
   6266 	} else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
   6267 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE);
   6268 		*finished = CIL_TREE_SKIP_NEXT;
   6269 	} else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
   6270 		rc = cil_gen_defaultrange(parse_current, ast_node);
   6271 		*finished = CIL_TREE_SKIP_NEXT;
   6272 	} else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
   6273 		rc = cil_gen_handleunknown(parse_current, ast_node);
   6274 		*finished = CIL_TREE_SKIP_NEXT;
   6275 	} else if (parse_current->data == CIL_KEY_MLS) {
   6276 		rc = cil_gen_mls(parse_current, ast_node);
   6277 		*finished = CIL_TREE_SKIP_NEXT;
   6278 	} else if (parse_current->data == CIL_KEY_SRC_INFO) {
   6279 		rc = cil_gen_src_info(parse_current, ast_node);
   6280 	} else {
   6281 		cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
   6282 		rc = SEPOL_ERR;
   6283 	}
   6284 
   6285 	if (rc == SEPOL_OK) {
   6286 		if (ast_current->cl_head == NULL) {
   6287 			if (ast_current->flavor == CIL_MACRO) {
   6288 				args->macro = ast_current;
   6289 			}
   6290 
   6291 			if (ast_current->flavor == CIL_BOOLEANIF) {
   6292 				args->boolif = ast_current;
   6293 			}
   6294 
   6295 			if (ast_current->flavor == CIL_TUNABLEIF) {
   6296 				args->tunif = ast_current;
   6297 			}
   6298 
   6299 			if (ast_current->flavor == CIL_IN) {
   6300 				args->in = ast_current;
   6301 			}
   6302 
   6303 			ast_current->cl_head = ast_node;
   6304 		} else {
   6305 			ast_current->cl_tail->next = ast_node;
   6306 		}
   6307 		ast_current->cl_tail = ast_node;
   6308 		ast_current = ast_node;
   6309 		args->ast = ast_current;
   6310 	} else {
   6311 		cil_tree_node_destroy(&ast_node);
   6312 	}
   6313 
   6314 exit:
   6315 	return rc;
   6316 }
   6317 
   6318 int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
   6319 {
   6320 	int rc = SEPOL_ERR;
   6321 	struct cil_tree_node *ast = NULL;
   6322 	struct cil_args_build *args = NULL;
   6323 
   6324 	if (extra_args == NULL) {
   6325 		goto exit;
   6326 	}
   6327 
   6328 	args = extra_args;
   6329 	ast = args->ast;
   6330 
   6331 	if (ast->flavor == CIL_ROOT) {
   6332 		rc = SEPOL_OK;
   6333 		goto exit;
   6334 	}
   6335 
   6336 	args->ast = ast->parent;
   6337 
   6338 	if (ast->flavor == CIL_MACRO) {
   6339 		args->macro = NULL;
   6340 	}
   6341 
   6342 	if (ast->flavor == CIL_BOOLEANIF) {
   6343 		args->boolif = NULL;
   6344 	}
   6345 
   6346 	if (ast->flavor == CIL_TUNABLEIF) {
   6347 		args->tunif = NULL;
   6348 	}
   6349 
   6350 	if (ast->flavor == CIL_IN) {
   6351 		args->in = NULL;
   6352 	}
   6353 
   6354 	// At this point we no longer have any need for parse_current or any of its
   6355 	// siblings; they have all been converted to the appropriate AST node. The
   6356 	// full parse tree will get deleted elsewhere, but in an attempt to
   6357 	// minimize memory useage (of which the parse tree uses alot), start
   6358 	// deleting the parts we don't need now.
   6359 	cil_tree_children_destroy(parse_current->parent);
   6360 
   6361 	return SEPOL_OK;
   6362 
   6363 exit:
   6364 	return rc;
   6365 }
   6366 
   6367 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
   6368 {
   6369 	int rc = SEPOL_ERR;
   6370 	struct cil_args_build extra_args;
   6371 
   6372 	if (db == NULL || parse_tree == NULL || ast == NULL) {
   6373 		goto exit;
   6374 	}
   6375 
   6376 	extra_args.ast = ast;
   6377 	extra_args.db = db;
   6378 	extra_args.macro = NULL;
   6379 	extra_args.boolif = NULL;
   6380 	extra_args.tunif = NULL;
   6381 	extra_args.in = NULL;
   6382 
   6383 	rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args);
   6384 	if (rc != SEPOL_OK) {
   6385 		goto exit;
   6386 	}
   6387 
   6388 	return SEPOL_OK;
   6389 
   6390 exit:
   6391 	return rc;
   6392 }
   6393