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