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 if (proto == CIL_KEY_SCTP) {
   4409 		portcon->proto = CIL_PROTOCOL_SCTP;
   4410 	} else {
   4411 		cil_log(CIL_ERR, "Invalid protocol\n");
   4412 		rc = SEPOL_ERR;
   4413 		goto exit;
   4414 	}
   4415 
   4416 	if (parse_current->next->next->cl_head != NULL) {
   4417 		if (parse_current->next->next->cl_head->next != NULL
   4418 		&& parse_current->next->next->cl_head->next->next == NULL) {
   4419 			rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10);
   4420 			if (rc != SEPOL_OK) {
   4421 				cil_log(CIL_ERR, "Improper port specified\n");
   4422 				goto exit;
   4423 			}
   4424 			rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10);
   4425 			if (rc != SEPOL_OK) {
   4426 				cil_log(CIL_ERR, "Improper port specified\n");
   4427 				goto exit;
   4428 			}
   4429 		} else {
   4430 			cil_log(CIL_ERR, "Improper port range specified\n");
   4431 			rc = SEPOL_ERR;
   4432 			goto exit;
   4433 		}
   4434 	} else {
   4435 		rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10);
   4436 		if (rc != SEPOL_OK) {
   4437 			cil_log(CIL_ERR, "Improper port specified\n");
   4438 			goto exit;
   4439 		}
   4440 		portcon->port_high = portcon->port_low;
   4441 	}
   4442 
   4443 	if (parse_current->next->next->next->cl_head == NULL ) {
   4444 		portcon->context_str = parse_current->next->next->next->data;
   4445 	} else {
   4446 		cil_context_init(&portcon->context);
   4447 
   4448 		rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context);
   4449 		if (rc != SEPOL_OK) {
   4450 			goto exit;
   4451 		}
   4452 	}
   4453 
   4454 	ast_node->data = portcon;
   4455 	ast_node->flavor = CIL_PORTCON;
   4456 
   4457 	return SEPOL_OK;
   4458 
   4459 exit:
   4460 	cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration");
   4461 	cil_destroy_portcon(portcon);
   4462 	return rc;
   4463 }
   4464 
   4465 void cil_destroy_portcon(struct cil_portcon *portcon)
   4466 {
   4467 	if (portcon == NULL) {
   4468 		return;
   4469 	}
   4470 
   4471 	if (portcon->context_str == NULL && portcon->context != NULL) {
   4472 		cil_destroy_context(portcon->context);
   4473 	}
   4474 
   4475 	free(portcon);
   4476 }
   4477 
   4478 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4479 {
   4480 	enum cil_syntax syntax[] = {
   4481 		CIL_SYN_STRING,
   4482 		CIL_SYN_STRING | CIL_SYN_LIST,
   4483 		CIL_SYN_STRING | CIL_SYN_LIST,
   4484 		CIL_SYN_STRING | CIL_SYN_LIST,
   4485 		CIL_SYN_END
   4486 	};
   4487 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4488 	int rc = SEPOL_ERR;
   4489 	struct cil_nodecon *nodecon = NULL;
   4490 
   4491 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4492 		goto exit;
   4493 	}
   4494 
   4495 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4496 	if (rc != SEPOL_OK) {
   4497 		goto exit;
   4498 	}
   4499 
   4500 	cil_nodecon_init(&nodecon);
   4501 
   4502 	if (parse_current->next->cl_head == NULL ) {
   4503 		nodecon->addr_str = parse_current->next->data;
   4504 	} else {
   4505 		cil_ipaddr_init(&nodecon->addr);
   4506 
   4507 		rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr);
   4508 		if (rc != SEPOL_OK) {
   4509 			goto exit;
   4510 		}
   4511 	}
   4512 
   4513 	if (parse_current->next->next->cl_head == NULL ) {
   4514 		nodecon->mask_str = parse_current->next->next->data;
   4515 	} else {
   4516 		cil_ipaddr_init(&nodecon->mask);
   4517 
   4518 		rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask);
   4519 		if (rc != SEPOL_OK) {
   4520 			goto exit;
   4521 		}
   4522 	}
   4523 
   4524 	if (parse_current->next->next->next->cl_head == NULL ) {
   4525 		nodecon->context_str = parse_current->next->next->next->data;
   4526 	} else {
   4527 		cil_context_init(&nodecon->context);
   4528 
   4529 		rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context);
   4530 		if (rc != SEPOL_OK) {
   4531 			goto exit;
   4532 		}
   4533 	}
   4534 
   4535 	ast_node->data = nodecon;
   4536 	ast_node->flavor = CIL_NODECON;
   4537 
   4538 	return SEPOL_OK;
   4539 
   4540 exit:
   4541 	cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration");
   4542 	cil_destroy_nodecon(nodecon);
   4543 	return rc;
   4544 }
   4545 
   4546 void cil_destroy_nodecon(struct cil_nodecon *nodecon)
   4547 {
   4548 	if (nodecon == NULL) {
   4549 		return;
   4550 	}
   4551 
   4552 	if (nodecon->addr_str == NULL && nodecon->addr != NULL) {
   4553 		cil_destroy_ipaddr(nodecon->addr);
   4554 	}
   4555 
   4556 	if (nodecon->mask_str == NULL && nodecon->mask != NULL) {
   4557 		cil_destroy_ipaddr(nodecon->mask);
   4558 	}
   4559 
   4560 	if (nodecon->context_str == NULL && nodecon->context != NULL) {
   4561 		cil_destroy_context(nodecon->context);
   4562 	}
   4563 
   4564 	free(nodecon);
   4565 }
   4566 
   4567 int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4568 {
   4569 	enum cil_syntax syntax[] = {
   4570 		CIL_SYN_STRING,
   4571 		CIL_SYN_STRING,
   4572 		CIL_SYN_STRING,
   4573 		CIL_SYN_STRING | CIL_SYN_LIST,
   4574 		CIL_SYN_END
   4575 	};
   4576 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4577 	int rc = SEPOL_ERR;
   4578 	struct cil_genfscon *genfscon = NULL;
   4579 
   4580 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4581 		goto exit;
   4582 	}
   4583 
   4584 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4585 	if (rc != SEPOL_OK) {
   4586 		goto exit;
   4587 	}
   4588 
   4589 	cil_genfscon_init(&genfscon);
   4590 
   4591 	genfscon->fs_str = parse_current->next->data;
   4592 	genfscon->path_str = parse_current->next->next->data;
   4593 
   4594 	if (parse_current->next->next->next->cl_head == NULL ) {
   4595 		genfscon->context_str = parse_current->next->next->next->data;
   4596 	} else {
   4597 		cil_context_init(&genfscon->context);
   4598 
   4599 		rc = cil_fill_context(parse_current->next->next->next->cl_head, genfscon->context);
   4600 		if (rc != SEPOL_OK) {
   4601 			goto exit;
   4602 		}
   4603 	}
   4604 
   4605 	ast_node->data = genfscon;
   4606 	ast_node->flavor = CIL_GENFSCON;
   4607 
   4608 	return SEPOL_OK;
   4609 
   4610 exit:
   4611 	cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
   4612 	cil_destroy_genfscon(genfscon);
   4613 	return SEPOL_ERR;
   4614 }
   4615 
   4616 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
   4617 {
   4618 	if (genfscon == NULL) {
   4619 		return;
   4620 	}
   4621 
   4622 	if (genfscon->context_str == NULL && genfscon->context != NULL) {
   4623 		cil_destroy_context(genfscon->context);
   4624 	}
   4625 
   4626 	free(genfscon);
   4627 }
   4628 
   4629 
   4630 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4631 {
   4632 	enum cil_syntax syntax[] = {
   4633 		CIL_SYN_STRING,
   4634 		CIL_SYN_STRING,
   4635 		CIL_SYN_STRING | CIL_SYN_LIST,
   4636 		CIL_SYN_STRING | CIL_SYN_LIST,
   4637 		CIL_SYN_END
   4638 	};
   4639 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4640 	int rc = SEPOL_ERR;
   4641 	struct cil_netifcon *netifcon = NULL;
   4642 
   4643 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4644 		goto exit;
   4645 	}
   4646 
   4647 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4648 	if (rc != SEPOL_OK) {
   4649 		goto exit;
   4650 	}
   4651 
   4652 	cil_netifcon_init(&netifcon);
   4653 
   4654 	netifcon->interface_str = parse_current->next->data;
   4655 
   4656 	if (parse_current->next->next->cl_head == NULL) {
   4657 		netifcon->if_context_str = parse_current->next->next->data;
   4658 	} else {
   4659 		cil_context_init(&netifcon->if_context);
   4660 
   4661 		rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
   4662 		if (rc != SEPOL_OK) {
   4663 			goto exit;
   4664 		}
   4665 	}
   4666 
   4667 	if (parse_current->next->next->next->cl_head == NULL) {
   4668 		netifcon->packet_context_str = parse_current->next->next->next->data;
   4669 	} else {
   4670 		cil_context_init(&netifcon->packet_context);
   4671 
   4672 		rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
   4673 		if (rc != SEPOL_OK) {
   4674 			goto exit;
   4675 		}
   4676 	}
   4677 
   4678 	ast_node->data = netifcon;
   4679 	ast_node->flavor = CIL_NETIFCON;
   4680 
   4681 	return SEPOL_OK;
   4682 
   4683 exit:
   4684 	cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
   4685 	cil_destroy_netifcon(netifcon);
   4686 	return SEPOL_ERR;
   4687 }
   4688 
   4689 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
   4690 {
   4691 	if (netifcon == NULL) {
   4692 		return;
   4693 	}
   4694 
   4695 	if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
   4696 		cil_destroy_context(netifcon->if_context);
   4697 	}
   4698 
   4699 	if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
   4700 		cil_destroy_context(netifcon->packet_context);
   4701 	}
   4702 
   4703 	free(netifcon);
   4704 }
   4705 
   4706 int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4707 {
   4708 	enum cil_syntax syntax[] = {
   4709 		CIL_SYN_STRING,
   4710 		CIL_SYN_STRING,
   4711 		CIL_SYN_STRING,
   4712 		CIL_SYN_STRING | CIL_SYN_LIST,
   4713 		CIL_SYN_END
   4714 	};
   4715 	int syntax_len = sizeof(syntax) / sizeof(*syntax);
   4716 	int rc = SEPOL_ERR;
   4717 	struct cil_ibendportcon *ibendportcon = NULL;
   4718 
   4719 	if (!parse_current || !ast_node)
   4720 		goto exit;
   4721 
   4722 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4723 	if (rc != SEPOL_OK)
   4724 		goto exit;
   4725 
   4726 	cil_ibendportcon_init(&ibendportcon);
   4727 
   4728 	ibendportcon->dev_name_str = parse_current->next->data;
   4729 
   4730 	rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10);
   4731 	if (rc != SEPOL_OK) {
   4732 		cil_log(CIL_ERR, "Improper ibendport port specified\n");
   4733 		goto exit;
   4734 	}
   4735 
   4736 	if (!parse_current->next->next->next->cl_head) {
   4737 		ibendportcon->context_str = parse_current->next->next->next->data;
   4738 	} else {
   4739 		cil_context_init(&ibendportcon->context);
   4740 
   4741 		rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context);
   4742 		if (rc != SEPOL_OK)
   4743 			goto exit;
   4744 	}
   4745 
   4746 	ast_node->data = ibendportcon;
   4747 	ast_node->flavor = CIL_IBENDPORTCON;
   4748 
   4749 	return SEPOL_OK;
   4750 
   4751 exit:
   4752 	cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
   4753 	cil_destroy_ibendportcon(ibendportcon);
   4754 	return SEPOL_ERR;
   4755 }
   4756 
   4757 void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
   4758 {
   4759 	if (!ibendportcon)
   4760 		return;
   4761 
   4762 	if (!ibendportcon->context_str && ibendportcon->context)
   4763 		cil_destroy_context(ibendportcon->context);
   4764 
   4765 	free(ibendportcon);
   4766 }
   4767 
   4768 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4769 {
   4770 	enum cil_syntax syntax[] = {
   4771 		CIL_SYN_STRING,
   4772 		CIL_SYN_STRING,
   4773 		CIL_SYN_STRING | CIL_SYN_LIST,
   4774 		CIL_SYN_END
   4775 	};
   4776 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4777 	int rc = SEPOL_ERR;
   4778 	struct cil_pirqcon *pirqcon = NULL;
   4779 
   4780 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4781 		goto exit;
   4782 	}
   4783 
   4784 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4785 	if (rc != SEPOL_OK) {
   4786 		goto exit;
   4787 	}
   4788 
   4789 	cil_pirqcon_init(&pirqcon);
   4790 
   4791 	rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
   4792 	if (rc != SEPOL_OK) {
   4793 		goto exit;
   4794 	}
   4795 
   4796 	if (parse_current->next->next->cl_head == NULL) {
   4797 		pirqcon->context_str = parse_current->next->next->data;
   4798 	} else {
   4799 		cil_context_init(&pirqcon->context);
   4800 
   4801 		rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
   4802 		if (rc != SEPOL_OK) {
   4803 			goto exit;
   4804 		}
   4805 	}
   4806 
   4807 	ast_node->data = pirqcon;
   4808 	ast_node->flavor = CIL_PIRQCON;
   4809 
   4810 	return SEPOL_OK;
   4811 
   4812 exit:
   4813 	cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
   4814 	cil_destroy_pirqcon(pirqcon);
   4815 	return rc;
   4816 }
   4817 
   4818 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
   4819 {
   4820 	if (pirqcon == NULL) {
   4821 		return;
   4822 	}
   4823 
   4824 	if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
   4825 		cil_destroy_context(pirqcon->context);
   4826 	}
   4827 
   4828 	free(pirqcon);
   4829 }
   4830 
   4831 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4832 {
   4833 	enum cil_syntax syntax[] = {
   4834 		CIL_SYN_STRING,
   4835 		CIL_SYN_STRING | CIL_SYN_LIST,
   4836 		CIL_SYN_STRING | CIL_SYN_LIST,
   4837 		CIL_SYN_END
   4838 	};
   4839 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4840 	int rc = SEPOL_ERR;
   4841 	struct cil_iomemcon *iomemcon = NULL;
   4842 
   4843 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4844 		goto exit;
   4845 	}
   4846 
   4847 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4848 	if (rc != SEPOL_OK) {
   4849 		goto exit;
   4850 	}
   4851 
   4852 	cil_iomemcon_init(&iomemcon);
   4853 
   4854 	if (parse_current->next->cl_head != NULL) {
   4855 		if (parse_current->next->cl_head->next != NULL &&
   4856 		    parse_current->next->cl_head->next->next == NULL) {
   4857 			rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
   4858 			if (rc != SEPOL_OK) {
   4859 				cil_log(CIL_ERR, "Improper iomem specified\n");
   4860 				goto exit;
   4861 			}
   4862 			rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
   4863 			if (rc != SEPOL_OK) {
   4864 				cil_log(CIL_ERR, "Improper iomem specified\n");
   4865 				goto exit;
   4866 			}
   4867 		} else {
   4868 			cil_log(CIL_ERR, "Improper iomem range specified\n");
   4869 			rc = SEPOL_ERR;
   4870 			goto exit;
   4871 		}
   4872 	} else {
   4873 		rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
   4874 		if (rc != SEPOL_OK) {
   4875 			cil_log(CIL_ERR, "Improper iomem specified\n");
   4876 			goto exit;
   4877 		}
   4878 		iomemcon->iomem_high = iomemcon->iomem_low;
   4879 	}
   4880 
   4881 	if (parse_current->next->next->cl_head == NULL ) {
   4882 		iomemcon->context_str = parse_current->next->next->data;
   4883 	} else {
   4884 		cil_context_init(&iomemcon->context);
   4885 
   4886 		rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
   4887 		if (rc != SEPOL_OK) {
   4888 			goto exit;
   4889 		}
   4890 	}
   4891 
   4892 	ast_node->data = iomemcon;
   4893 	ast_node->flavor = CIL_IOMEMCON;
   4894 
   4895 	return SEPOL_OK;
   4896 
   4897 exit:
   4898 	cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
   4899 	cil_destroy_iomemcon(iomemcon);
   4900 	return rc;
   4901 }
   4902 
   4903 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
   4904 {
   4905 	if (iomemcon == NULL) {
   4906 		return;
   4907 	}
   4908 
   4909 	if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
   4910 		cil_destroy_context(iomemcon->context);
   4911 	}
   4912 
   4913 	free(iomemcon);
   4914 }
   4915 
   4916 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   4917 {
   4918 	enum cil_syntax syntax[] = {
   4919 		CIL_SYN_STRING,
   4920 		CIL_SYN_STRING | CIL_SYN_LIST,
   4921 		CIL_SYN_STRING | CIL_SYN_LIST,
   4922 		CIL_SYN_END
   4923 	};
   4924 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   4925 	int rc = SEPOL_ERR;
   4926 	struct cil_ioportcon *ioportcon = NULL;
   4927 
   4928 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   4929 		goto exit;
   4930 	}
   4931 
   4932 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   4933 	if (rc != SEPOL_OK) {
   4934 		goto exit;
   4935 	}
   4936 
   4937 	cil_ioportcon_init(&ioportcon);
   4938 
   4939 	if (parse_current->next->cl_head != NULL) {
   4940 		if (parse_current->next->cl_head->next != NULL &&
   4941 		    parse_current->next->cl_head->next->next == NULL) {
   4942 			rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
   4943 			if (rc != SEPOL_OK) {
   4944 				cil_log(CIL_ERR, "Improper ioport specified\n");
   4945 				goto exit;
   4946 			}
   4947 			rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
   4948 			if (rc != SEPOL_OK) {
   4949 				cil_log(CIL_ERR, "Improper ioport specified\n");
   4950 				goto exit;
   4951 			}
   4952 		} else {
   4953 			cil_log(CIL_ERR, "Improper ioport range specified\n");
   4954 			rc = SEPOL_ERR;
   4955 			goto exit;
   4956 		}
   4957 	} else {
   4958 		rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
   4959 		if (rc != SEPOL_OK) {
   4960 			cil_log(CIL_ERR, "Improper ioport specified\n");
   4961 			goto exit;
   4962 		}
   4963 		ioportcon->ioport_high = ioportcon->ioport_low;
   4964 	}
   4965 
   4966 	if (parse_current->next->next->cl_head == NULL ) {
   4967 		ioportcon->context_str = parse_current->next->next->data;
   4968 	} else {
   4969 		cil_context_init(&ioportcon->context);
   4970 
   4971 		rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
   4972 		if (rc != SEPOL_OK) {
   4973 			goto exit;
   4974 		}
   4975 	}
   4976 
   4977 	ast_node->data = ioportcon;
   4978 	ast_node->flavor = CIL_IOPORTCON;
   4979 
   4980 	return SEPOL_OK;
   4981 
   4982 exit:
   4983 	cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
   4984 	cil_destroy_ioportcon(ioportcon);
   4985 	return rc;
   4986 }
   4987 
   4988 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
   4989 {
   4990 	if (ioportcon == NULL) {
   4991 		return;
   4992 	}
   4993 
   4994 	if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
   4995 		cil_destroy_context(ioportcon->context);
   4996 	}
   4997 
   4998 	free(ioportcon);
   4999 }
   5000 
   5001 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5002 {
   5003 	enum cil_syntax syntax[] = {
   5004 		CIL_SYN_STRING,
   5005 		CIL_SYN_STRING,
   5006 		CIL_SYN_STRING | CIL_SYN_LIST,
   5007 		CIL_SYN_END
   5008 	};
   5009 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5010 	int rc = SEPOL_ERR;
   5011 	struct cil_pcidevicecon *pcidevicecon = NULL;
   5012 
   5013 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5014 		goto exit;
   5015 	}
   5016 
   5017 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5018 	if (rc != SEPOL_OK) {
   5019 		goto exit;
   5020 	}
   5021 
   5022 	cil_pcidevicecon_init(&pcidevicecon);
   5023 
   5024 	rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
   5025 	if (rc != SEPOL_OK) {
   5026 		goto exit;
   5027 	}
   5028 
   5029 	if (parse_current->next->next->cl_head == NULL) {
   5030 		pcidevicecon->context_str = parse_current->next->next->data;
   5031 	} else {
   5032 		cil_context_init(&pcidevicecon->context);
   5033 
   5034 		rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
   5035 		if (rc != SEPOL_OK) {
   5036 			goto exit;
   5037 		}
   5038 	}
   5039 
   5040 	ast_node->data = pcidevicecon;
   5041 	ast_node->flavor = CIL_PCIDEVICECON;
   5042 
   5043 	return SEPOL_OK;
   5044 
   5045 exit:
   5046 	cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
   5047 	cil_destroy_pcidevicecon(pcidevicecon);
   5048 	return rc;
   5049 }
   5050 
   5051 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
   5052 {
   5053 	if (pcidevicecon == NULL) {
   5054 		return;
   5055 	}
   5056 
   5057 	if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
   5058 		cil_destroy_context(pcidevicecon->context);
   5059 	}
   5060 
   5061 	free(pcidevicecon);
   5062 }
   5063 
   5064 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5065 {
   5066 	enum cil_syntax syntax[] = {
   5067 		CIL_SYN_STRING,
   5068 		CIL_SYN_STRING,
   5069 		CIL_SYN_STRING | CIL_SYN_LIST,
   5070 		CIL_SYN_END
   5071 	};
   5072 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5073 	int rc = SEPOL_ERR;
   5074 	struct cil_devicetreecon *devicetreecon = NULL;
   5075 
   5076 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5077 		goto exit;
   5078 	}
   5079 
   5080 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5081 	if (rc != SEPOL_OK) {
   5082 		goto exit;
   5083 	}
   5084 
   5085 	cil_devicetreecon_init(&devicetreecon);
   5086 
   5087 	devicetreecon->path = parse_current->next->data;
   5088 
   5089 	if (parse_current->next->next->cl_head == NULL) {
   5090 		devicetreecon->context_str = parse_current->next->next->data;
   5091 	} else {
   5092 		cil_context_init(&devicetreecon->context);
   5093 
   5094 		rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
   5095 		if (rc != SEPOL_OK) {
   5096 			goto exit;
   5097 		}
   5098 	}
   5099 
   5100 	ast_node->data = devicetreecon;
   5101 	ast_node->flavor = CIL_DEVICETREECON;
   5102 
   5103 	return SEPOL_OK;
   5104 
   5105 exit:
   5106 	cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
   5107 	cil_destroy_devicetreecon(devicetreecon);
   5108 	return rc;
   5109 }
   5110 
   5111 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
   5112 {
   5113 	if (devicetreecon == NULL) {
   5114 		return;
   5115 	}
   5116 
   5117 	if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
   5118 		cil_destroy_context(devicetreecon->context);
   5119 	}
   5120 
   5121 	free(devicetreecon);
   5122 }
   5123 
   5124 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5125 {
   5126 	enum cil_syntax syntax[] = {
   5127 		CIL_SYN_STRING,
   5128 		CIL_SYN_STRING,
   5129 		CIL_SYN_STRING,
   5130 		CIL_SYN_STRING | CIL_SYN_LIST,
   5131 		CIL_SYN_END
   5132 	};
   5133 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5134 	char *type = NULL;
   5135 	struct cil_fsuse *fsuse = NULL;
   5136 	int rc = SEPOL_ERR;
   5137 
   5138 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5139 		goto exit;
   5140 	}
   5141 
   5142 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5143 	if (rc != SEPOL_OK) {
   5144 		goto exit;
   5145 	}
   5146 
   5147 	type = parse_current->next->data;
   5148 
   5149 	cil_fsuse_init(&fsuse);
   5150 
   5151 	if (type == CIL_KEY_XATTR) {
   5152 		fsuse->type = CIL_FSUSE_XATTR;
   5153 	} else if (type == CIL_KEY_TASK) {
   5154 		fsuse->type = CIL_FSUSE_TASK;
   5155 	} else if (type == CIL_KEY_TRANS) {
   5156 		fsuse->type = CIL_FSUSE_TRANS;
   5157 	} else {
   5158 		cil_log(CIL_ERR, "Invalid fsuse type\n");
   5159 		goto exit;
   5160 	}
   5161 
   5162 	fsuse->fs_str = parse_current->next->next->data;
   5163 
   5164 	if (parse_current->next->next->next->cl_head == NULL) {
   5165 		fsuse->context_str = parse_current->next->next->next->data;
   5166 	} else {
   5167 		cil_context_init(&fsuse->context);
   5168 
   5169 		rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
   5170 		if (rc != SEPOL_OK) {
   5171 			goto exit;
   5172 		}
   5173 	}
   5174 
   5175 	ast_node->data = fsuse;
   5176 	ast_node->flavor = CIL_FSUSE;
   5177 
   5178 	return SEPOL_OK;
   5179 
   5180 exit:
   5181 	cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
   5182 	cil_destroy_fsuse(fsuse);
   5183 	return SEPOL_ERR;
   5184 }
   5185 
   5186 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
   5187 {
   5188 	if (fsuse == NULL) {
   5189 		return;
   5190 	}
   5191 
   5192 	if (fsuse->context_str == NULL && fsuse->context != NULL) {
   5193 		cil_destroy_context(fsuse->context);
   5194 	}
   5195 
   5196 	free(fsuse);
   5197 }
   5198 
   5199 void cil_destroy_param(struct cil_param *param)
   5200 {
   5201 	if (param == NULL) {
   5202 		return;
   5203 	}
   5204 
   5205 	free(param);
   5206 }
   5207 
   5208 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5209 {
   5210 	int rc = SEPOL_ERR;
   5211 	char *key = NULL;
   5212 	struct cil_macro *macro = NULL;
   5213 	struct cil_tree_node *macro_content = NULL;
   5214 	enum cil_syntax syntax[] = {
   5215 		CIL_SYN_STRING,
   5216 		CIL_SYN_STRING,
   5217 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
   5218 		CIL_SYN_N_LISTS | CIL_SYN_END,
   5219 		CIL_SYN_END
   5220 	};
   5221 	int syntax_len = sizeof(syntax)/ sizeof(*syntax);
   5222 
   5223 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5224 		goto exit;
   5225 	}
   5226 
   5227 	rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
   5228 	if (rc != SEPOL_OK) {
   5229 		goto exit;
   5230 	}
   5231 
   5232 	cil_macro_init(&macro);
   5233 
   5234 	key = parse_current->next->data;
   5235 
   5236 	struct cil_tree_node *current_item = parse_current->next->next->cl_head;
   5237 	while (current_item != NULL) {
   5238 		enum cil_syntax param_syntax[] = {
   5239 			CIL_SYN_STRING,
   5240 			CIL_SYN_STRING,
   5241 			CIL_SYN_END
   5242 		};
   5243 		int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
   5244 		char *kind = NULL;
   5245 		struct cil_param *param = NULL;
   5246 
   5247 		rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
   5248 		if (rc != SEPOL_OK) {
   5249 			goto exit;
   5250 		}
   5251 
   5252 		if (macro->params == NULL) {
   5253 			cil_list_init(&macro->params, CIL_LIST_ITEM);
   5254 		}
   5255 
   5256 		kind = current_item->cl_head->data;
   5257 		cil_param_init(&param);
   5258 
   5259 		if (kind == CIL_KEY_TYPE) {
   5260 			param->flavor = CIL_TYPE;
   5261 		} else if (kind == CIL_KEY_ROLE) {
   5262 			param->flavor = CIL_ROLE;
   5263 		} else if (kind == CIL_KEY_USER) {
   5264 			param->flavor = CIL_USER;
   5265 		} else if (kind == CIL_KEY_SENSITIVITY) {
   5266 			param->flavor = CIL_SENS;
   5267 		} else if (kind == CIL_KEY_CATEGORY) {
   5268 			param->flavor = CIL_CAT;
   5269 		} else if (kind == CIL_KEY_CATSET) {
   5270 			param->flavor = CIL_CATSET;
   5271 		} else if (kind == CIL_KEY_LEVEL) {
   5272 			param->flavor = CIL_LEVEL;
   5273 		} else if (kind == CIL_KEY_LEVELRANGE) {
   5274 			param->flavor = CIL_LEVELRANGE;
   5275 		} else if (kind == CIL_KEY_CLASS) {
   5276 			param->flavor = CIL_CLASS;
   5277 		} else if (kind == CIL_KEY_IPADDR) {
   5278 			param->flavor = CIL_IPADDR;
   5279 		} else if (kind == CIL_KEY_MAP_CLASS) {
   5280 			param->flavor = CIL_MAP_CLASS;
   5281 		} else if (kind == CIL_KEY_CLASSPERMISSION) {
   5282 			param->flavor = CIL_CLASSPERMISSION;
   5283 		} else if (kind == CIL_KEY_BOOL) {
   5284 			param->flavor = CIL_BOOL;
   5285 		} else if (kind == CIL_KEY_STRING) {
   5286 			param->flavor = CIL_NAME;
   5287 		} else if (kind == CIL_KEY_NAME) {
   5288 			param->flavor = CIL_NAME;
   5289 		} else {
   5290 			cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
   5291 			cil_destroy_param(param);
   5292 			goto exit;
   5293 		}
   5294 
   5295 		param->str =  current_item->cl_head->next->data;
   5296 
   5297 		rc = __cil_verify_name(param->str);
   5298 		if (rc != SEPOL_OK) {
   5299 			cil_destroy_param(param);
   5300 			goto exit;
   5301 		}
   5302 
   5303 		//walk current list and check for duplicate parameters
   5304 		struct cil_list_item *curr_param;
   5305 		cil_list_for_each(curr_param, macro->params) {
   5306 			if (param->str == ((struct cil_param*)curr_param->data)->str) {
   5307 				if (param->flavor == ((struct cil_param*)curr_param->data)->flavor) {
   5308 					cil_log(CIL_ERR, "Duplicate parameter\n");
   5309 					cil_destroy_param(param);
   5310 					goto exit;
   5311 				}
   5312 			}
   5313 		}
   5314 
   5315 		cil_list_append(macro->params, CIL_PARAM, param);
   5316 
   5317 		current_item = current_item->next;
   5318 	}
   5319 
   5320 	/* 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
   5321            node containing the macro name is updated to point to the start of the macro content */
   5322 	macro_content = parse_current->next->next->next;
   5323 	cil_tree_subtree_destroy(parse_current->next->next);
   5324 	parse_current->next->next = macro_content;
   5325 	if (macro_content == NULL) {
   5326 		/* No statements in macro and macro parameter list was last node */
   5327 		parse_current->parent->cl_tail = parse_current->next;
   5328 	}
   5329 
   5330 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
   5331 	if (rc != SEPOL_OK) {
   5332 		goto exit;
   5333 	}
   5334 
   5335 	return SEPOL_OK;
   5336 
   5337 exit:
   5338 	cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
   5339 	cil_destroy_macro(macro);
   5340 	cil_clear_node(ast_node);
   5341 	return SEPOL_ERR;
   5342 }
   5343 
   5344 void cil_destroy_macro(struct cil_macro *macro)
   5345 {
   5346 	if (macro == NULL) {
   5347 		return;
   5348 	}
   5349 
   5350 	cil_symtab_datum_destroy(&macro->datum);
   5351 	cil_symtab_array_destroy(macro->symtab);
   5352 
   5353 	if (macro->params != NULL) {
   5354 		cil_list_destroy(&macro->params, 1);
   5355 	}
   5356 
   5357 	free(macro);
   5358 }
   5359 
   5360 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5361 {
   5362 	enum cil_syntax syntax[] = {
   5363 		CIL_SYN_STRING,
   5364 		CIL_SYN_STRING,
   5365 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
   5366 		CIL_SYN_END
   5367 	};
   5368 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5369 	struct cil_call *call = NULL;
   5370 	int rc = SEPOL_ERR;
   5371 
   5372 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5373 		goto exit;
   5374 	}
   5375 
   5376 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5377 	if (rc != SEPOL_OK) {
   5378 		goto exit;
   5379 	}
   5380 
   5381 	cil_call_init(&call);
   5382 
   5383 	call->macro_str = parse_current->next->data;
   5384 
   5385 	if (parse_current->next->next != NULL) {
   5386 		cil_tree_init(&call->args_tree);
   5387 		cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
   5388 	}
   5389 
   5390 	ast_node->data = call;
   5391 	ast_node->flavor = CIL_CALL;
   5392 
   5393 	return SEPOL_OK;
   5394 
   5395 exit:
   5396 	cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
   5397 	cil_destroy_call(call);
   5398 	return rc;
   5399 }
   5400 
   5401 void cil_destroy_call(struct cil_call *call)
   5402 {
   5403 	if (call == NULL) {
   5404 		return;
   5405 	}
   5406 
   5407 	call->macro = NULL;
   5408 
   5409 	if (call->args_tree != NULL) {
   5410 		cil_tree_destroy(&call->args_tree);
   5411 	}
   5412 
   5413 	if (call->args != NULL) {
   5414 		cil_list_destroy(&call->args, 1);
   5415 	}
   5416 
   5417 	free(call);
   5418 }
   5419 
   5420 void cil_destroy_args(struct cil_args *args)
   5421 {
   5422 	if (args == NULL) {
   5423 		return;
   5424 	}
   5425 
   5426 	if (args->arg_str != NULL) {
   5427 		args->arg_str = NULL;
   5428 	} else if (args->arg != NULL) {
   5429 		struct cil_tree_node *node = args->arg->nodes->head->data;
   5430 		switch (args->flavor) {
   5431 		case CIL_NAME:
   5432 			break;
   5433 		case CIL_CATSET:
   5434 			cil_destroy_catset((struct cil_catset *)args->arg);
   5435 			free(node);
   5436 			break;
   5437 		case CIL_LEVEL:
   5438 			cil_destroy_level((struct cil_level *)args->arg);
   5439 			free(node);
   5440 			break;
   5441 		case CIL_LEVELRANGE:
   5442 			cil_destroy_levelrange((struct cil_levelrange *)args->arg);
   5443 			free(node);
   5444 			break;
   5445 		case CIL_IPADDR:
   5446 			cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
   5447 			free(node);
   5448 			break;
   5449 		case CIL_CLASSPERMISSION:
   5450 			cil_destroy_classpermission((struct cil_classpermission *)args->arg);
   5451 			free(node);
   5452 			break;
   5453 		default:
   5454 			cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
   5455 			break;
   5456 		}
   5457 	}
   5458 
   5459 	args->param_str = NULL;
   5460 	args->arg = NULL;
   5461 
   5462 	free(args);
   5463 }
   5464 
   5465 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5466 {
   5467 	enum cil_syntax syntax[] = {
   5468 		CIL_SYN_STRING,
   5469 		CIL_SYN_STRING,
   5470 		CIL_SYN_N_LISTS | CIL_SYN_END,
   5471 		CIL_SYN_END
   5472 	};
   5473 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5474 	char *key = NULL;
   5475 	struct cil_optional *optional = NULL;
   5476 	int rc = SEPOL_ERR;
   5477 
   5478 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5479 		goto exit;
   5480 	}
   5481 
   5482 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5483 	if (rc != SEPOL_OK) {
   5484 		goto exit;
   5485 	}
   5486 
   5487 	cil_optional_init(&optional);
   5488 
   5489 	key = parse_current->next->data;
   5490 
   5491 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
   5492 	if (rc != SEPOL_OK)
   5493 		goto exit;
   5494 
   5495 	return SEPOL_OK;
   5496 
   5497 exit:
   5498 	cil_tree_log(parse_current, CIL_ERR, "Bad optional");
   5499 	cil_destroy_optional(optional);
   5500 	cil_clear_node(ast_node);
   5501 	return rc;
   5502 }
   5503 
   5504 void cil_destroy_optional(struct cil_optional *optional)
   5505 {
   5506 	if (optional == NULL) {
   5507 		return;
   5508 	}
   5509 
   5510 	cil_symtab_datum_destroy(&optional->datum);
   5511 	free(optional);
   5512 }
   5513 
   5514 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5515 {
   5516 	enum cil_syntax syntax[] = {
   5517 		CIL_SYN_STRING,
   5518 		CIL_SYN_STRING,
   5519 		CIL_SYN_END
   5520 	};
   5521 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5522 	char *key = NULL;
   5523 	struct cil_policycap *polcap = NULL;
   5524 	int rc = SEPOL_ERR;
   5525 
   5526 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5527 		goto exit;
   5528 	}
   5529 
   5530 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5531 	if (rc != SEPOL_OK) {
   5532 		goto exit;
   5533 	}
   5534 
   5535 	cil_policycap_init(&polcap);
   5536 
   5537 	key = parse_current->next->data;
   5538 
   5539 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
   5540 	if (rc != SEPOL_OK)
   5541 		goto exit;
   5542 
   5543 	return SEPOL_OK;
   5544 
   5545 exit:
   5546 	cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
   5547 	cil_destroy_policycap(polcap);
   5548 	cil_clear_node(ast_node);
   5549 	return rc;
   5550 }
   5551 
   5552 void cil_destroy_policycap(struct cil_policycap *polcap)
   5553 {
   5554 	if (polcap == NULL) {
   5555 		return;
   5556 	}
   5557 
   5558 	cil_symtab_datum_destroy(&polcap->datum);
   5559 	free(polcap);
   5560 }
   5561 
   5562 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5563 {
   5564 	enum cil_syntax syntax[] = {
   5565 		CIL_SYN_STRING,
   5566 		CIL_SYN_STRING,
   5567 		CIL_SYN_STRING,
   5568 		CIL_SYN_END
   5569 	};
   5570 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5571 	char *key = NULL;
   5572 	struct cil_ipaddr *ipaddr = NULL;
   5573 	int rc = SEPOL_ERR;
   5574 
   5575 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5576 		goto exit;
   5577 	}
   5578 
   5579 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5580 	if (rc != SEPOL_OK) {
   5581 		goto exit;
   5582 	}
   5583 
   5584 	cil_ipaddr_init(&ipaddr);
   5585 
   5586 	key  = parse_current->next->data;
   5587 
   5588 	rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
   5589 	if (rc != SEPOL_OK) {
   5590 		goto exit;
   5591 	}
   5592 
   5593 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
   5594 	if (rc != SEPOL_OK) {
   5595 		goto exit;
   5596 	}
   5597 
   5598 	return SEPOL_OK;
   5599 
   5600 exit:
   5601 	cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
   5602 	cil_destroy_ipaddr(ipaddr);
   5603 	cil_clear_node(ast_node);
   5604 	return rc;
   5605 }
   5606 
   5607 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
   5608 {
   5609 	if (ipaddr == NULL) {
   5610 		return;
   5611 	}
   5612 
   5613 	cil_symtab_datum_destroy(&ipaddr->datum);
   5614 	free(ipaddr);
   5615 }
   5616 
   5617 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
   5618 {
   5619 	int rc = SEPOL_ERR;
   5620 	char *endptr = NULL;
   5621 	int val;
   5622 
   5623 	if (int_node == NULL || integer == NULL) {
   5624 		goto exit;
   5625 	}
   5626 
   5627 	errno = 0;
   5628 	val = strtol(int_node->data, &endptr, base);
   5629 	if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
   5630 		rc = SEPOL_ERR;
   5631 		goto exit;
   5632 	}
   5633 
   5634 	*integer = val;
   5635 
   5636 	return SEPOL_OK;
   5637 
   5638 exit:
   5639 	cil_log(CIL_ERR, "Failed to create integer from string\n");
   5640 	return rc;
   5641 }
   5642 
   5643 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
   5644 {
   5645 	int rc = SEPOL_ERR;
   5646 	char *endptr = NULL;
   5647 	uint64_t val;
   5648 
   5649 	if (int_node == NULL || integer == NULL) {
   5650 		goto exit;
   5651 	}
   5652 
   5653 	errno = 0;
   5654 	val = strtoull(int_node->data, &endptr, base);
   5655 	if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
   5656 		rc = SEPOL_ERR;
   5657 		goto exit;
   5658 	}
   5659 
   5660 	*integer = val;
   5661 
   5662 	return SEPOL_OK;
   5663 
   5664 exit:
   5665 	cil_log(CIL_ERR, "Failed to create integer from string\n");
   5666 	return rc;
   5667 }
   5668 
   5669 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
   5670 {
   5671 	int rc = SEPOL_ERR;
   5672 
   5673 	if (addr_node == NULL || addr == NULL) {
   5674 		goto exit;
   5675 	}
   5676 
   5677 	if (addr_node->cl_head != NULL ||  addr_node->next != NULL) {
   5678 		goto exit;
   5679 	}
   5680 
   5681 	if (strchr(addr_node->data, '.') != NULL) {
   5682 		addr->family = AF_INET;
   5683 	} else {
   5684 		addr->family = AF_INET6;
   5685 	}
   5686 
   5687 	rc = inet_pton(addr->family, addr_node->data, &addr->ip);
   5688 	if (rc != 1) {
   5689 		rc = SEPOL_ERR;
   5690 		goto exit;
   5691 	}
   5692 
   5693 	return SEPOL_OK;
   5694 
   5695 exit:
   5696 	cil_log(CIL_ERR, "Bad ip address or netmask\n");
   5697 	return rc;
   5698 }
   5699 
   5700 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
   5701 {
   5702 	int rc = SEPOL_ERR;
   5703 	enum cil_syntax syntax[] = {
   5704 		CIL_SYN_STRING,
   5705 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
   5706 		CIL_SYN_END
   5707 	};
   5708 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5709 
   5710 	if (curr == NULL) {
   5711 		goto exit;
   5712 	}
   5713 
   5714 	rc = __cil_verify_syntax(curr, syntax, syntax_len);
   5715 	if (rc != SEPOL_OK) {
   5716 		goto exit;
   5717 	}
   5718 
   5719 	level->sens_str = curr->data;
   5720 	if (curr->next != NULL) {
   5721 		rc = cil_fill_cats(curr->next, &level->cats);
   5722 		if (rc != SEPOL_OK) {
   5723 			goto exit;
   5724 		}
   5725 	}
   5726 
   5727 	return SEPOL_OK;
   5728 
   5729 exit:
   5730 	cil_log(CIL_ERR, "Bad level\n");
   5731 	return rc;
   5732 }
   5733 
   5734 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
   5735 {
   5736 	int rc = SEPOL_ERR;
   5737 
   5738 	cil_cats_init(cats);
   5739 
   5740 	rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
   5741 	if (rc != SEPOL_OK) {
   5742 		cil_destroy_cats(*cats);
   5743 		*cats = NULL;
   5744 	}
   5745 
   5746 	return rc;
   5747 }
   5748 
   5749 void cil_destroy_cats(struct cil_cats *cats)
   5750 {
   5751 	if (cats == NULL) {
   5752 		return;
   5753 	}
   5754 
   5755 	cil_list_destroy(&cats->str_expr, CIL_TRUE);
   5756 
   5757 	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
   5758 
   5759 	free(cats);
   5760 }
   5761 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   5762 {
   5763 	enum cil_syntax syntax[] = {
   5764 		CIL_SYN_STRING,
   5765 		CIL_SYN_STRING,
   5766 		CIL_SYN_STRING,
   5767 		CIL_SYN_END
   5768 	};
   5769 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5770 	struct cil_bounds *bounds = NULL;
   5771 	int rc = SEPOL_ERR;
   5772 
   5773 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
   5774 		goto exit;
   5775 	}
   5776 
   5777 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5778 	if (rc != SEPOL_OK) {
   5779 		goto exit;
   5780 	}
   5781 
   5782 	cil_bounds_init(&bounds);
   5783 
   5784 	bounds->parent_str = parse_current->next->data;
   5785 	bounds->child_str = parse_current->next->next->data;
   5786 
   5787 	ast_node->data = bounds;
   5788 
   5789 	switch (flavor) {
   5790 	case CIL_USER:
   5791 		ast_node->flavor = CIL_USERBOUNDS;
   5792 		break;
   5793 	case CIL_ROLE:
   5794 		ast_node->flavor = CIL_ROLEBOUNDS;
   5795 		break;
   5796 	case CIL_TYPE:
   5797 		ast_node->flavor = CIL_TYPEBOUNDS;
   5798 		break;
   5799 	default:
   5800 		break;
   5801 	}
   5802 
   5803 	return SEPOL_OK;
   5804 
   5805 exit:
   5806 	cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
   5807 	cil_destroy_bounds(bounds);
   5808 	return rc;
   5809 }
   5810 
   5811 void cil_destroy_bounds(struct cil_bounds *bounds)
   5812 {
   5813 	if (bounds == NULL) {
   5814 		return;
   5815 	}
   5816 
   5817 	free(bounds);
   5818 }
   5819 
   5820 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
   5821 {
   5822 	int rc = SEPOL_ERR;
   5823 	struct cil_default *def = NULL;
   5824 	char *object;
   5825 	enum cil_syntax syntax[] = {
   5826 		CIL_SYN_STRING,
   5827 		CIL_SYN_STRING | CIL_SYN_LIST,
   5828 		CIL_SYN_STRING,
   5829 		CIL_SYN_END
   5830 	};
   5831 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5832 
   5833 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5834 	if (rc != SEPOL_OK) {
   5835 		goto exit;
   5836 	}
   5837 
   5838 	cil_default_init(&def);
   5839 
   5840 	def->flavor = flavor;
   5841 
   5842 	if (parse_current->next->cl_head == NULL) {
   5843 		cil_list_init(&def->class_strs, CIL_CLASS);
   5844 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
   5845 	} else {
   5846 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
   5847 		if (rc != SEPOL_OK) {
   5848 			goto exit;
   5849 		}
   5850 	}
   5851 
   5852 	object = parse_current->next->next->data;
   5853 	if (object == CIL_KEY_SOURCE) {
   5854 		def->object = CIL_DEFAULT_SOURCE;
   5855 	} else if (object == CIL_KEY_TARGET) {
   5856 		def->object = CIL_DEFAULT_TARGET;
   5857 	} else {
   5858 		cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
   5859 		rc = SEPOL_ERR;
   5860 		goto exit;
   5861 	}
   5862 
   5863 	ast_node->data = def;
   5864 	ast_node->flavor = flavor;
   5865 
   5866 	return SEPOL_OK;
   5867 
   5868 exit:
   5869 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
   5870 	cil_destroy_default(def);
   5871 	return rc;
   5872 }
   5873 
   5874 void cil_destroy_default(struct cil_default *def)
   5875 {
   5876 	if (def == NULL) {
   5877 		return;
   5878 	}
   5879 
   5880 	cil_list_destroy(&def->class_strs, CIL_TRUE);
   5881 
   5882 	cil_list_destroy(&def->class_datums, CIL_FALSE);
   5883 
   5884 	free(def);
   5885 }
   5886 
   5887 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5888 {
   5889 	int rc = SEPOL_ERR;
   5890 	struct cil_defaultrange *def = NULL;
   5891 	char *object;
   5892 	char *range;
   5893 	enum cil_syntax syntax[] = {
   5894 		CIL_SYN_STRING,
   5895 		CIL_SYN_STRING | CIL_SYN_LIST,
   5896 		CIL_SYN_STRING,
   5897 		CIL_SYN_STRING,
   5898 		CIL_SYN_END
   5899 	};
   5900 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5901 
   5902 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5903 	if (rc != SEPOL_OK) {
   5904 		goto exit;
   5905 	}
   5906 
   5907 	cil_defaultrange_init(&def);
   5908 
   5909 	if (parse_current->next->cl_head == NULL) {
   5910 		cil_list_init(&def->class_strs, CIL_CLASS);
   5911 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
   5912 	} else {
   5913 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
   5914 		if (rc != SEPOL_OK) {
   5915 			goto exit;
   5916 		}
   5917 	}
   5918 
   5919 	object = parse_current->next->next->data;
   5920 	range = parse_current->next->next->next->data;
   5921 	if (object == CIL_KEY_SOURCE) {
   5922 		if (range == CIL_KEY_LOW) {
   5923 			def->object_range = CIL_DEFAULT_SOURCE_LOW;
   5924 		} else if (range == CIL_KEY_HIGH) {
   5925 			def->object_range = CIL_DEFAULT_SOURCE_HIGH;
   5926 		} else if (range == CIL_KEY_LOW_HIGH) {
   5927 			def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
   5928 		} else {
   5929 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
   5930 			rc = SEPOL_ERR;
   5931 			goto exit;
   5932 		}
   5933 	} else if (parse_current->next->next->data == CIL_KEY_TARGET) {
   5934 		if (range == CIL_KEY_LOW) {
   5935 			def->object_range = CIL_DEFAULT_TARGET_LOW;
   5936 		} else if (range == CIL_KEY_HIGH) {
   5937 			def->object_range = CIL_DEFAULT_TARGET_HIGH;
   5938 		} else if (range == CIL_KEY_LOW_HIGH) {
   5939 			def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
   5940 		} else {
   5941 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
   5942 			rc = SEPOL_ERR;
   5943 			goto exit;
   5944 		}
   5945 	} else {
   5946 		cil_log(CIL_ERR,"Expected either \'source\' or \'target\'\n");
   5947 		rc = SEPOL_ERR;
   5948 		goto exit;
   5949 	}
   5950 
   5951 	ast_node->data = def;
   5952 	ast_node->flavor = CIL_DEFAULTRANGE;
   5953 
   5954 	return SEPOL_OK;
   5955 
   5956 exit:
   5957 	cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
   5958 	cil_destroy_defaultrange(def);
   5959 	return rc;
   5960 }
   5961 
   5962 void cil_destroy_defaultrange(struct cil_defaultrange *def)
   5963 {
   5964 	if (def == NULL) {
   5965 		return;
   5966 	}
   5967 
   5968 	cil_list_destroy(&def->class_strs, CIL_TRUE);
   5969 
   5970 	cil_list_destroy(&def->class_datums, CIL_FALSE);
   5971 
   5972 	free(def);
   5973 }
   5974 
   5975 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   5976 {
   5977 	int rc = SEPOL_ERR;
   5978 	enum cil_syntax syntax[] = {
   5979 		CIL_SYN_STRING,
   5980 		CIL_SYN_STRING,
   5981 		CIL_SYN_END
   5982 	};
   5983 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   5984 	struct cil_handleunknown *unknown = NULL;
   5985 	char *unknown_key;
   5986 
   5987 	if (parse_current == NULL || ast_node == NULL) {
   5988 		goto exit;
   5989 	}
   5990 
   5991 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   5992 	if (rc != SEPOL_OK) {
   5993 		goto exit;
   5994 	}
   5995 
   5996 	cil_handleunknown_init(&unknown);
   5997 
   5998 	unknown_key = parse_current->next->data;
   5999 	if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
   6000 		unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
   6001 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
   6002 		unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
   6003 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
   6004 		unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
   6005 	} else {
   6006 		cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
   6007 		rc = SEPOL_ERR;
   6008 		goto exit;
   6009 	}
   6010 
   6011 	ast_node->data = unknown;
   6012 	ast_node->flavor = CIL_HANDLEUNKNOWN;
   6013 
   6014 	return SEPOL_OK;
   6015 
   6016 exit:
   6017 	cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
   6018 	cil_destroy_handleunknown(unknown);
   6019 	return rc;
   6020 }
   6021 
   6022 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
   6023 {
   6024 	free(unk);
   6025 }
   6026 
   6027 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   6028 {
   6029 	int rc = SEPOL_ERR;
   6030 	enum cil_syntax syntax[] = {
   6031 		CIL_SYN_STRING,
   6032 		CIL_SYN_STRING,
   6033 		CIL_SYN_END
   6034 	};
   6035 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
   6036 	struct cil_mls *mls = NULL;
   6037 
   6038 	if (parse_current == NULL || ast_node == NULL) {
   6039 		goto exit;
   6040 	}
   6041 
   6042 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
   6043 	if (rc != SEPOL_OK) {
   6044 		goto exit;
   6045 	}
   6046 
   6047 	cil_mls_init(&mls);
   6048 
   6049 	if (parse_current->next->data == CIL_KEY_CONDTRUE) {
   6050 		mls->value = CIL_TRUE;
   6051 	} else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
   6052 		mls->value = CIL_FALSE;
   6053 	} else {
   6054 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
   6055 		rc = SEPOL_ERR;
   6056 		goto exit;
   6057 	}
   6058 
   6059 	ast_node->data = mls;
   6060 	ast_node->flavor = CIL_MLS;
   6061 
   6062 	return SEPOL_OK;
   6063 
   6064 exit:
   6065 	cil_tree_log(parse_current, CIL_ERR, "Bad mls");
   6066 	cil_destroy_mls(mls);
   6067 	return rc;
   6068 }
   6069 
   6070 void cil_destroy_mls(struct cil_mls *mls)
   6071 {
   6072 	free(mls);
   6073 }
   6074 
   6075 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
   6076 {
   6077 	/* No need to check syntax, because this is auto generated */
   6078 	struct cil_src_info *info = NULL;
   6079 
   6080 	cil_src_info_init(&info);
   6081 
   6082 	info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE;
   6083 	info->path = parse_current->next->next->data;
   6084 
   6085 	ast_node->data = info;
   6086 	ast_node->flavor = CIL_SRC_INFO;
   6087 
   6088 	return SEPOL_OK;
   6089 }
   6090 
   6091 void cil_destroy_src_info(struct cil_src_info *info)
   6092 {
   6093 	free(info);
   6094 }
   6095 
   6096 int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
   6097 {
   6098 	struct cil_args_build *args = NULL;
   6099 	struct cil_tree_node *ast_current = NULL;
   6100 	struct cil_db *db = NULL;
   6101 	struct cil_tree_node *ast_node = NULL;
   6102 	struct cil_tree_node *macro = NULL;
   6103 	struct cil_tree_node *boolif = NULL;
   6104 	struct cil_tree_node *tunif = NULL;
   6105 	struct cil_tree_node *in = NULL;
   6106 	int rc = SEPOL_ERR;
   6107 
   6108 	if (parse_current == NULL || finished == NULL || extra_args == NULL) {
   6109 		goto exit;
   6110 	}
   6111 
   6112 	args = extra_args;
   6113 	ast_current = args->ast;
   6114 	db = args->db;
   6115 	macro = args->macro;
   6116 	boolif = args->boolif;
   6117 	tunif = args->tunif;
   6118 	in = args->in;
   6119 
   6120 	if (parse_current->parent->cl_head != parse_current) {
   6121 		/* ignore anything that isn't following a parenthesis */
   6122 		rc = SEPOL_OK;
   6123 		goto exit;
   6124 	} else if (parse_current->data == NULL) {
   6125 		/* the only time parenthsis can immediately following parenthesis is if
   6126 		 * the parent is the root node */
   6127 		if (parse_current->parent->parent == NULL) {
   6128 			rc = SEPOL_OK;
   6129 		} else {
   6130 			cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
   6131 		}
   6132 		goto exit;
   6133 	}
   6134 
   6135 	if (macro != NULL) {
   6136 		if (parse_current->data == CIL_KEY_MACRO ||
   6137 			parse_current->data == CIL_KEY_TUNABLE ||
   6138 			parse_current->data == CIL_KEY_IN ||
   6139 			parse_current->data == CIL_KEY_BLOCK ||
   6140 			parse_current->data == CIL_KEY_BLOCKINHERIT ||
   6141 			parse_current->data == CIL_KEY_BLOCKABSTRACT) {
   6142 			rc = SEPOL_ERR;
   6143 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data);
   6144 			goto exit;
   6145 		}
   6146 	}
   6147 
   6148 	if (boolif != NULL) {
   6149 		if (parse_current->data != CIL_KEY_CONDTRUE &&
   6150 			parse_current->data != CIL_KEY_CONDFALSE &&
   6151 			parse_current->data != CIL_KEY_AUDITALLOW &&
   6152 			parse_current->data != CIL_KEY_TUNABLEIF &&
   6153 			parse_current->data != CIL_KEY_ALLOW &&
   6154 			parse_current->data != CIL_KEY_DONTAUDIT &&
   6155 			parse_current->data != CIL_KEY_TYPETRANSITION &&
   6156 			parse_current->data != CIL_KEY_TYPECHANGE &&
   6157 			parse_current->data != CIL_KEY_CALL) {
   6158 			rc = SEPOL_ERR;
   6159 			cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
   6160 			if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
   6161 				cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n",
   6162 						(char*)parse_current->data);
   6163 			} else {
   6164 				cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n",
   6165 						(char*)parse_current->data);
   6166 			}
   6167 			goto exit;
   6168 		}
   6169 	}
   6170 
   6171 	if (tunif != NULL) {
   6172 		if (parse_current->data == CIL_KEY_TUNABLE) {
   6173 			rc = SEPOL_ERR;
   6174 			cil_tree_log(parse_current, CIL_ERR, "Found tunable");
   6175 			cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
   6176 			goto exit;
   6177 		}
   6178 	}
   6179 
   6180 	if (in != NULL) {
   6181 		if (parse_current->data == CIL_KEY_IN) {
   6182 			rc = SEPOL_ERR;
   6183 			cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
   6184 			cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
   6185 			goto exit;
   6186 		}
   6187 	}
   6188 
   6189 	cil_tree_node_init(&ast_node);
   6190 
   6191 	ast_node->parent = ast_current;
   6192 	ast_node->line = parse_current->line;
   6193 	ast_node->hll_line = parse_current->hll_line;
   6194 
   6195 	if (parse_current->data == CIL_KEY_BLOCK) {
   6196 		rc = cil_gen_block(db, parse_current, ast_node, 0);
   6197 	} else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
   6198 		rc = cil_gen_blockinherit(db, parse_current, ast_node);
   6199 	} else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
   6200 		rc = cil_gen_blockabstract(db, parse_current, ast_node);
   6201 	} else if (parse_current->data == CIL_KEY_IN) {
   6202 		rc = cil_gen_in(db, parse_current, ast_node);
   6203 	} else if (parse_current->data == CIL_KEY_CLASS) {
   6204 		rc = cil_gen_class(db, parse_current, ast_node);
   6205 		// To avoid parsing list of perms again
   6206 		*finished = CIL_TREE_SKIP_NEXT;
   6207 	} else if (parse_current->data == CIL_KEY_CLASSORDER) {
   6208 		rc = cil_gen_classorder(db, parse_current, ast_node);
   6209 		*finished = CIL_TREE_SKIP_NEXT;
   6210 	} else if (parse_current->data == CIL_KEY_MAP_CLASS) {
   6211 		rc = cil_gen_map_class(db, parse_current, ast_node);
   6212 		*finished = CIL_TREE_SKIP_NEXT;
   6213 	} else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
   6214 		rc = cil_gen_classmapping(db, parse_current, ast_node);
   6215 		*finished = CIL_TREE_SKIP_NEXT;
   6216 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
   6217 		rc = cil_gen_classpermission(db, parse_current, ast_node);
   6218 		*finished = CIL_TREE_SKIP_NEXT;
   6219 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
   6220 		rc = cil_gen_classpermissionset(db, parse_current, ast_node);
   6221 		*finished = CIL_TREE_SKIP_NEXT;
   6222 	} else if (parse_current->data == CIL_KEY_COMMON) {
   6223 		rc = cil_gen_common(db, parse_current, ast_node);
   6224 		*finished = CIL_TREE_SKIP_NEXT;
   6225 	} else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
   6226 		rc = cil_gen_classcommon(db, parse_current, ast_node);
   6227 	} else if (parse_current->data == CIL_KEY_SID) {
   6228 		rc = cil_gen_sid(db, parse_current, ast_node);
   6229 		*finished = CIL_TREE_SKIP_NEXT;
   6230 	} else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
   6231 		rc = cil_gen_sidcontext(db, parse_current, ast_node);
   6232 		*finished = CIL_TREE_SKIP_NEXT;
   6233 	} else if (parse_current->data == CIL_KEY_SIDORDER) {
   6234 		rc = cil_gen_sidorder(db, parse_current, ast_node);
   6235 		*finished = CIL_TREE_SKIP_NEXT;
   6236 	} else if (parse_current->data == CIL_KEY_USER) {
   6237 		rc = cil_gen_user(db, parse_current, ast_node);
   6238 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
   6239 		rc = cil_gen_userattribute(db, parse_current, ast_node);
   6240 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
   6241 		rc = cil_gen_userattributeset(db, parse_current, ast_node);
   6242 		*finished = CIL_TREE_SKIP_NEXT;
   6243 	} else if (parse_current->data == CIL_KEY_USERLEVEL) {
   6244 		rc = cil_gen_userlevel(db, parse_current, ast_node);
   6245 		*finished = CIL_TREE_SKIP_NEXT;
   6246 	} else if (parse_current->data == CIL_KEY_USERRANGE) {
   6247 		rc = cil_gen_userrange(db, parse_current, ast_node);
   6248 		*finished = CIL_TREE_SKIP_NEXT;
   6249 	} else if (parse_current->data == CIL_KEY_USERBOUNDS) {
   6250 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER);
   6251 	} else if (parse_current->data == CIL_KEY_USERPREFIX) {
   6252 		rc = cil_gen_userprefix(db, parse_current, ast_node);
   6253 	} else if (parse_current->data == CIL_KEY_SELINUXUSER) {
   6254 		rc = cil_gen_selinuxuser(db, parse_current, ast_node);
   6255 		*finished = CIL_TREE_SKIP_NEXT;
   6256 	} else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
   6257 		rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node);
   6258 		*finished = CIL_TREE_SKIP_NEXT;
   6259 	} else if (parse_current->data == CIL_KEY_TYPE) {
   6260 		rc = cil_gen_type(db, parse_current, ast_node);
   6261 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
   6262 		rc = cil_gen_typeattribute(db, parse_current, ast_node);
   6263 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
   6264 		rc = cil_gen_typeattributeset(db, parse_current, ast_node);
   6265 		*finished = CIL_TREE_SKIP_NEXT;
   6266 	} else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
   6267 		rc = cil_gen_expandtypeattribute(db, parse_current, ast_node);
   6268 		*finished = CIL_TREE_SKIP_NEXT;
   6269 	} else if (parse_current->data == CIL_KEY_TYPEALIAS) {
   6270 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS);
   6271 	} else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
   6272 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL);
   6273 	} else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
   6274 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE);
   6275 	} else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
   6276 		rc = cil_gen_typepermissive(db, parse_current, ast_node);
   6277 	} else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
   6278 		rc = cil_gen_rangetransition(db, parse_current, ast_node);
   6279 		*finished = CIL_TREE_SKIP_NEXT;
   6280 	} else if (parse_current->data == CIL_KEY_ROLE) {
   6281 		rc = cil_gen_role(db, parse_current, ast_node);
   6282 	} else if (parse_current->data == CIL_KEY_USERROLE) {
   6283 		rc = cil_gen_userrole(db, parse_current, ast_node);
   6284 	} else if (parse_current->data == CIL_KEY_ROLETYPE) {
   6285 		rc = cil_gen_roletype(db, parse_current, ast_node);
   6286 	} else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
   6287 		rc = cil_gen_roletransition(parse_current, ast_node);
   6288 	} else if (parse_current->data == CIL_KEY_ROLEALLOW) {
   6289 		rc = cil_gen_roleallow(db, parse_current, ast_node);
   6290 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
   6291 		rc = cil_gen_roleattribute(db, parse_current, ast_node);
   6292 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
   6293 		rc = cil_gen_roleattributeset(db, parse_current, ast_node);
   6294 		*finished = CIL_TREE_SKIP_NEXT;
   6295 	} else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
   6296 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE);
   6297 	} else if (parse_current->data == CIL_KEY_BOOL) {
   6298 		rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE);
   6299 	} else if (parse_current->data == CIL_KEY_BOOLEANIF) {
   6300 		rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE);
   6301 	} else if(parse_current->data == CIL_KEY_TUNABLE) {
   6302 		if (db->preserve_tunables) {
   6303 			rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE);
   6304 		} else {
   6305 			rc = cil_gen_tunable(db, parse_current, ast_node);
   6306 		}
   6307 	} else if (parse_current->data == CIL_KEY_TUNABLEIF) {
   6308 		if (db->preserve_tunables) {
   6309 			rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE);
   6310 		} else {
   6311 			rc = cil_gen_tunif(db, parse_current, ast_node);
   6312 		}
   6313 	} else if (parse_current->data == CIL_KEY_CONDTRUE) {
   6314 		rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE);
   6315 	} else if (parse_current->data == CIL_KEY_CONDFALSE) {
   6316 		rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE);
   6317 	} else if (parse_current->data == CIL_KEY_ALLOW) {
   6318 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED);
   6319 		// So that the object and perms lists do not get parsed again
   6320 		*finished = CIL_TREE_SKIP_NEXT;
   6321 	} else if (parse_current->data == CIL_KEY_AUDITALLOW) {
   6322 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
   6323 		*finished = CIL_TREE_SKIP_NEXT;
   6324 	} else if (parse_current->data == CIL_KEY_DONTAUDIT) {
   6325 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
   6326 		*finished = CIL_TREE_SKIP_NEXT;
   6327 	} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
   6328 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
   6329 		*finished = CIL_TREE_SKIP_NEXT;
   6330 	} else if (parse_current->data == CIL_KEY_ALLOWX) {
   6331 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED);
   6332 		*finished = CIL_TREE_SKIP_NEXT;
   6333 	} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
   6334 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
   6335 		*finished = CIL_TREE_SKIP_NEXT;
   6336 	} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
   6337 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
   6338 		*finished = CIL_TREE_SKIP_NEXT;
   6339 	} else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
   6340 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
   6341 		*finished = CIL_TREE_SKIP_NEXT;
   6342 	} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
   6343 		rc = cil_gen_permissionx(db, parse_current, ast_node);
   6344 		*finished = CIL_TREE_SKIP_NEXT;
   6345 	} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
   6346 		rc = cil_gen_typetransition(db, parse_current, ast_node);
   6347 	} else if (parse_current->data == CIL_KEY_TYPECHANGE) {
   6348 		rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE);
   6349 	} else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
   6350 		rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER);
   6351 	} else if (parse_current->data == CIL_KEY_SENSITIVITY) {
   6352 		rc = cil_gen_sensitivity(db, parse_current, ast_node);
   6353 	} else if (parse_current->data == CIL_KEY_SENSALIAS) {
   6354 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS);
   6355 	} else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
   6356 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL);
   6357 	} else if (parse_current->data == CIL_KEY_CATEGORY) {
   6358 		rc = cil_gen_category(db, parse_current, ast_node);
   6359 	} else if (parse_current->data == CIL_KEY_CATALIAS) {
   6360 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS);
   6361 	} else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
   6362 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL);
   6363 	} else if (parse_current->data == CIL_KEY_CATSET) {
   6364 		rc = cil_gen_catset(db, parse_current, ast_node);
   6365 		*finished = CIL_TREE_SKIP_NEXT;
   6366 	} else if (parse_current->data == CIL_KEY_CATORDER) {
   6367 		rc = cil_gen_catorder(db, parse_current, ast_node);
   6368 		*finished = CIL_TREE_SKIP_NEXT;
   6369 	} else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
   6370 		rc = cil_gen_sensitivityorder(db, parse_current, ast_node);
   6371 		*finished = CIL_TREE_SKIP_NEXT;
   6372 	} else if (parse_current->data == CIL_KEY_SENSCAT) {
   6373 		rc = cil_gen_senscat(db, parse_current, ast_node);
   6374 		*finished = CIL_TREE_SKIP_NEXT;
   6375 	} else if (parse_current->data == CIL_KEY_LEVEL) {
   6376 		rc = cil_gen_level(db, parse_current, ast_node);
   6377 		*finished = CIL_TREE_SKIP_NEXT;
   6378 	} else if (parse_current->data == CIL_KEY_LEVELRANGE) {
   6379 		rc = cil_gen_levelrange(db, parse_current, ast_node);
   6380 		*finished = CIL_TREE_SKIP_NEXT;
   6381 	} else if (parse_current->data == CIL_KEY_CONSTRAIN) {
   6382 		rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN);
   6383 		*finished = CIL_TREE_SKIP_NEXT;
   6384 	} else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
   6385 		rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN);
   6386 		*finished = CIL_TREE_SKIP_NEXT;
   6387 	} else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
   6388 		rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS);
   6389 		*finished = CIL_TREE_SKIP_NEXT;
   6390 	} else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
   6391 		rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS);
   6392 		*finished = CIL_TREE_SKIP_NEXT;
   6393 	} else if (parse_current->data == CIL_KEY_CONTEXT) {
   6394 		rc = cil_gen_context(db, parse_current, ast_node);
   6395 		*finished = CIL_TREE_SKIP_NEXT;
   6396 	} else if (parse_current->data == CIL_KEY_FILECON) {
   6397 		rc = cil_gen_filecon(db, parse_current, ast_node);
   6398 		*finished = CIL_TREE_SKIP_NEXT;
   6399 	} else if (parse_current->data == CIL_KEY_IBPKEYCON) {
   6400 		rc = cil_gen_ibpkeycon(db, parse_current, ast_node);
   6401 		*finished = CIL_TREE_SKIP_NEXT;
   6402 	} else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
   6403 		rc = cil_gen_ibendportcon(db, parse_current, ast_node);
   6404 		*finished = CIL_TREE_SKIP_NEXT;
   6405 	} else if (parse_current->data == CIL_KEY_PORTCON) {
   6406 		rc = cil_gen_portcon(db, parse_current, ast_node);
   6407 		*finished = CIL_TREE_SKIP_NEXT;
   6408 	} else if (parse_current->data == CIL_KEY_NODECON) {
   6409 		rc = cil_gen_nodecon(db, parse_current, ast_node);
   6410 		*finished = CIL_TREE_SKIP_NEXT;
   6411 	} else if (parse_current->data == CIL_KEY_GENFSCON) {
   6412 		rc = cil_gen_genfscon(db, parse_current, ast_node);
   6413 		*finished = CIL_TREE_SKIP_NEXT;
   6414 	} else if (parse_current->data == CIL_KEY_NETIFCON) {
   6415 		rc = cil_gen_netifcon(db, parse_current, ast_node);
   6416 		*finished = CIL_TREE_SKIP_NEXT;
   6417 	} else if (parse_current->data == CIL_KEY_PIRQCON) {
   6418 		rc = cil_gen_pirqcon(db, parse_current, ast_node);
   6419 		*finished = CIL_TREE_SKIP_NEXT;
   6420 	} else if (parse_current->data == CIL_KEY_IOMEMCON) {
   6421 		rc = cil_gen_iomemcon(db, parse_current, ast_node);
   6422 		*finished = CIL_TREE_SKIP_NEXT;
   6423 	} else if (parse_current->data == CIL_KEY_IOPORTCON) {
   6424 		rc = cil_gen_ioportcon(db, parse_current, ast_node);
   6425 		*finished = CIL_TREE_SKIP_NEXT;
   6426 	} else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
   6427 		rc = cil_gen_pcidevicecon(db, parse_current, ast_node);
   6428 		*finished = CIL_TREE_SKIP_NEXT;
   6429 	} else if (parse_current->data == CIL_KEY_DEVICETREECON) {
   6430 		rc = cil_gen_devicetreecon(db, parse_current, ast_node);
   6431 		*finished = CIL_TREE_SKIP_NEXT;
   6432 	} else if (parse_current->data == CIL_KEY_FSUSE) {
   6433 		rc = cil_gen_fsuse(db, parse_current, ast_node);
   6434 		*finished = CIL_TREE_SKIP_NEXT;
   6435 	} else if (parse_current->data == CIL_KEY_MACRO) {
   6436 		rc = cil_gen_macro(db, parse_current, ast_node);
   6437 	} else if (parse_current->data == CIL_KEY_CALL) {
   6438 		rc = cil_gen_call(db, parse_current, ast_node);
   6439 		*finished = 1;
   6440 	} else if (parse_current->data == CIL_KEY_POLICYCAP) {
   6441 		rc = cil_gen_policycap(db, parse_current, ast_node);
   6442 		*finished = 1;
   6443 	} else if (parse_current->data == CIL_KEY_OPTIONAL) {
   6444 		rc = cil_gen_optional(db, parse_current, ast_node);
   6445 	} else if (parse_current->data == CIL_KEY_IPADDR) {
   6446 		rc = cil_gen_ipaddr(db, parse_current, ast_node);
   6447 	} else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
   6448 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER);
   6449 		*finished = CIL_TREE_SKIP_NEXT;
   6450 	} else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
   6451 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE);
   6452 		*finished = CIL_TREE_SKIP_NEXT;
   6453 	} else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
   6454 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE);
   6455 		*finished = CIL_TREE_SKIP_NEXT;
   6456 	} else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
   6457 		rc = cil_gen_defaultrange(parse_current, ast_node);
   6458 		*finished = CIL_TREE_SKIP_NEXT;
   6459 	} else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
   6460 		rc = cil_gen_handleunknown(parse_current, ast_node);
   6461 		*finished = CIL_TREE_SKIP_NEXT;
   6462 	} else if (parse_current->data == CIL_KEY_MLS) {
   6463 		rc = cil_gen_mls(parse_current, ast_node);
   6464 		*finished = CIL_TREE_SKIP_NEXT;
   6465 	} else if (parse_current->data == CIL_KEY_SRC_INFO) {
   6466 		rc = cil_gen_src_info(parse_current, ast_node);
   6467 	} else {
   6468 		cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
   6469 		rc = SEPOL_ERR;
   6470 	}
   6471 
   6472 	if (rc == SEPOL_OK) {
   6473 		if (ast_current->cl_head == NULL) {
   6474 			if (ast_current->flavor == CIL_MACRO) {
   6475 				args->macro = ast_current;
   6476 			}
   6477 
   6478 			if (ast_current->flavor == CIL_BOOLEANIF) {
   6479 				args->boolif = ast_current;
   6480 			}
   6481 
   6482 			if (ast_current->flavor == CIL_TUNABLEIF) {
   6483 				args->tunif = ast_current;
   6484 			}
   6485 
   6486 			if (ast_current->flavor == CIL_IN) {
   6487 				args->in = ast_current;
   6488 			}
   6489 
   6490 			ast_current->cl_head = ast_node;
   6491 		} else {
   6492 			ast_current->cl_tail->next = ast_node;
   6493 		}
   6494 		ast_current->cl_tail = ast_node;
   6495 		ast_current = ast_node;
   6496 		args->ast = ast_current;
   6497 	} else {
   6498 		cil_tree_node_destroy(&ast_node);
   6499 	}
   6500 
   6501 exit:
   6502 	return rc;
   6503 }
   6504 
   6505 int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
   6506 {
   6507 	int rc = SEPOL_ERR;
   6508 	struct cil_tree_node *ast = NULL;
   6509 	struct cil_args_build *args = NULL;
   6510 
   6511 	if (extra_args == NULL) {
   6512 		goto exit;
   6513 	}
   6514 
   6515 	args = extra_args;
   6516 	ast = args->ast;
   6517 
   6518 	if (ast->flavor == CIL_ROOT) {
   6519 		rc = SEPOL_OK;
   6520 		goto exit;
   6521 	}
   6522 
   6523 	args->ast = ast->parent;
   6524 
   6525 	if (ast->flavor == CIL_MACRO) {
   6526 		args->macro = NULL;
   6527 	}
   6528 
   6529 	if (ast->flavor == CIL_BOOLEANIF) {
   6530 		args->boolif = NULL;
   6531 	}
   6532 
   6533 	if (ast->flavor == CIL_TUNABLEIF) {
   6534 		args->tunif = NULL;
   6535 	}
   6536 
   6537 	if (ast->flavor == CIL_IN) {
   6538 		args->in = NULL;
   6539 	}
   6540 
   6541 	// At this point we no longer have any need for parse_current or any of its
   6542 	// siblings; they have all been converted to the appropriate AST node. The
   6543 	// full parse tree will get deleted elsewhere, but in an attempt to
   6544 	// minimize memory useage (of which the parse tree uses alot), start
   6545 	// deleting the parts we don't need now.
   6546 	cil_tree_children_destroy(parse_current->parent);
   6547 
   6548 	return SEPOL_OK;
   6549 
   6550 exit:
   6551 	return rc;
   6552 }
   6553 
   6554 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
   6555 {
   6556 	int rc = SEPOL_ERR;
   6557 	struct cil_args_build extra_args;
   6558 
   6559 	if (db == NULL || parse_tree == NULL || ast == NULL) {
   6560 		goto exit;
   6561 	}
   6562 
   6563 	extra_args.ast = ast;
   6564 	extra_args.db = db;
   6565 	extra_args.macro = NULL;
   6566 	extra_args.boolif = NULL;
   6567 	extra_args.tunif = NULL;
   6568 	extra_args.in = NULL;
   6569 
   6570 	rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args);
   6571 	if (rc != SEPOL_OK) {
   6572 		goto exit;
   6573 	}
   6574 
   6575 	return SEPOL_OK;
   6576 
   6577 exit:
   6578 	return rc;
   6579 }
   6580