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