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