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