int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
{
	int rc = SEPOL_OK;
	struct cil_args_resolve *args = extra_args;
	enum cil_pass pass = 0;
	struct cil_list *ins;

	if (node == NULL || args == NULL) {
		goto exit;
	}
	ins = args->in_list;

	pass = args->pass;
	switch (pass) {
	case CIL_PASS_TIF:
		if (node->flavor == CIL_TUNABLEIF) {
			rc = cil_resolve_tunif(node, args);
		}
		break;
	case CIL_PASS_IN:
		if (node->flavor == CIL_IN) {
			// due to ordering issues, in statements are just gathered here and
			// resolved together in cil_resolve_in_list once all are found
			cil_list_prepend(ins, CIL_NODE, node);
		}
		break;
	case CIL_PASS_BLKIN_LINK:
		if (node->flavor == CIL_BLOCKINHERIT) {
			rc = cil_resolve_blockinherit_link(node, args);
		}
		break;
	case CIL_PASS_BLKIN_COPY:
		if (node->flavor == CIL_BLOCK) {
			rc = cil_resolve_blockinherit_copy(node, args);
		}
		break;
	case CIL_PASS_BLKABS:
		if (node->flavor == CIL_BLOCKABSTRACT) {
			rc = cil_resolve_blockabstract(node, args);
		}
		break;
	case CIL_PASS_MACRO:
		if (node->flavor == CIL_CALL && args->macro != NULL) {
			rc = cil_resolve_call1(node, args);
		}
		break;
	case CIL_PASS_CALL1:
		if (node->flavor == CIL_CALL) {
			rc = cil_resolve_call1(node, args);
		}
		break;
	case CIL_PASS_CALL2:
		if (node->flavor == CIL_CALL) {
			rc = cil_resolve_call2(node, args);
		}
		break;
	case CIL_PASS_ALIAS1:
		switch (node->flavor) {
		case CIL_TYPEALIASACTUAL:
			rc = cil_resolve_aliasactual(node, args, CIL_TYPE, CIL_TYPEALIAS);
			break;
		case CIL_SENSALIASACTUAL:
			rc = cil_resolve_aliasactual(node, args, CIL_SENS, CIL_SENSALIAS);
			break;
		case CIL_CATALIASACTUAL:
			rc = cil_resolve_aliasactual(node, args, CIL_CAT, CIL_CATALIAS);
			break;
		default: 
			break;
		}
		break;
	case CIL_PASS_ALIAS2:
		switch (node->flavor) {
		case CIL_TYPEALIAS:
			rc = cil_resolve_alias_to_actual(node, CIL_TYPE);
			break;
		case CIL_SENSALIAS:
			rc = cil_resolve_alias_to_actual(node, CIL_SENS);
			break;
		case CIL_CATALIAS:
			rc = cil_resolve_alias_to_actual(node, CIL_CAT);
			break;
		default:
			break;
		}
		break;
	case CIL_PASS_MISC1:
		switch (node->flavor) {
		case CIL_SIDORDER:
			rc = cil_resolve_sidorder(node, args);
			break;
		case CIL_CLASSORDER:
			rc = cil_resolve_classorder(node, args);
			break;
		case CIL_CATORDER:
			rc = cil_resolve_catorder(node, args);
			break;
		case CIL_SENSITIVITYORDER:
			rc = cil_resolve_sensitivityorder(node, args);
			break;
		case CIL_BOOLEANIF:
			rc = cil_resolve_boolif(node, args);
			break;
		default:
			break;
		}
		break;
	case CIL_PASS_MLS:
		switch (node->flavor) {
		case CIL_CATSET:
			rc = cil_resolve_catset(node, (struct cil_catset*)node->data, args);
			break;
		default:
			break;
		}
		break;
	case CIL_PASS_MISC2:
		switch (node->flavor) {
		case CIL_SENSCAT:
			rc = cil_resolve_senscat(node, args);
			break;
		case CIL_CLASSCOMMON:
			rc = cil_resolve_classcommon(node, args);
			break;
		default:
			break;
		}
		break;
	case CIL_PASS_MISC3:
		switch (node->flavor) {
		case CIL_TYPEATTRIBUTESET:
			rc = cil_resolve_typeattributeset(node, args);
			break;
		case CIL_EXPANDTYPEATTRIBUTE:
			rc = cil_resolve_expandtypeattribute(node, args);
			break;
		case CIL_TYPEBOUNDS:
			rc = cil_resolve_bounds(node, args, CIL_TYPE, CIL_TYPEATTRIBUTE);
			break;
		case CIL_TYPEPERMISSIVE:
			rc = cil_resolve_typepermissive(node, args);
			break;
		case CIL_NAMETYPETRANSITION:
			rc = cil_resolve_nametypetransition(node, args);
			break;
		case CIL_RANGETRANSITION:
			rc = cil_resolve_rangetransition(node, args);
			break;
		case CIL_CLASSPERMISSIONSET:
			rc = cil_resolve_classpermissionset(node, (struct cil_classpermissionset*)node->data, args);
			break;
		case CIL_CLASSMAPPING:
			rc = cil_resolve_classmapping(node, args);
			break;
		case CIL_AVRULE:
		case CIL_AVRULEX:
			rc = cil_resolve_avrule(node, args);
			break;
		case CIL_PERMISSIONX:
			rc = cil_resolve_permissionx(node, (struct cil_permissionx*)node->data, args);
			break;
		case CIL_TYPE_RULE:
			rc = cil_resolve_type_rule(node, args);
			break;
		case CIL_USERROLE:
			rc = cil_resolve_userrole(node, args);
			break;
		case CIL_USERLEVEL:
			rc = cil_resolve_userlevel(node, args);
			break;
		case CIL_USERRANGE:
			rc = cil_resolve_userrange(node, args);
			break;
		case CIL_USERBOUNDS:
			rc = cil_resolve_bounds(node, args, CIL_USER, CIL_USERATTRIBUTE);
			break;
		case CIL_USERPREFIX:
			rc = cil_resolve_userprefix(node, args);
			break;
		case CIL_SELINUXUSER:
		case CIL_SELINUXUSERDEFAULT:
			rc = cil_resolve_selinuxuser(node, args);
			break;
		case CIL_ROLEATTRIBUTESET:
			rc = cil_resolve_roleattributeset(node, args);
			break;
		case CIL_ROLETYPE:
			rc = cil_resolve_roletype(node, args);
			break;
		case CIL_ROLETRANSITION:
			rc = cil_resolve_roletransition(node, args);
			break;
		case CIL_ROLEALLOW:
			rc = cil_resolve_roleallow(node, args);
			break;
		case CIL_ROLEBOUNDS:
			rc = cil_resolve_bounds(node, args, CIL_ROLE, CIL_ROLEATTRIBUTE);
			break;
		case CIL_LEVEL:
			rc = cil_resolve_level(node, (struct cil_level*)node->data, args);
			break;
		case CIL_LEVELRANGE:
			rc = cil_resolve_levelrange(node, (struct cil_levelrange*)node->data, args);
			break;
		case CIL_CONSTRAIN:
			rc = cil_resolve_constrain(node, args);
			break;
		case CIL_MLSCONSTRAIN:
			rc = cil_resolve_constrain(node, args);
			break;
		case CIL_VALIDATETRANS:
		case CIL_MLSVALIDATETRANS:
			rc = cil_resolve_validatetrans(node, args);
			break;
		case CIL_CONTEXT:
			rc = cil_resolve_context(node, (struct cil_context*)node->data, args);
			break;
		case CIL_FILECON:
			rc = cil_resolve_filecon(node, args);
			break;
		case CIL_IBPKEYCON:
			rc = cil_resolve_ibpkeycon(node, args);
			break;
		case CIL_PORTCON:
			rc = cil_resolve_portcon(node, args);
			break;
		case CIL_NODECON:
			rc = cil_resolve_nodecon(node, args);
			break;
		case CIL_GENFSCON:
			rc = cil_resolve_genfscon(node, args);
			break;
		case CIL_NETIFCON:
			rc = cil_resolve_netifcon(node, args);
			break;
		case CIL_IBENDPORTCON:
			rc = cil_resolve_ibendportcon(node, args);
			break;
		case CIL_PIRQCON:
			rc = cil_resolve_pirqcon(node, args);
			break;
		case CIL_IOMEMCON:
			rc = cil_resolve_iomemcon(node, args);
			break;
		case CIL_IOPORTCON:
			rc = cil_resolve_ioportcon(node, args);
			break;
		case CIL_PCIDEVICECON:
			rc = cil_resolve_pcidevicecon(node, args);
			break;
		case CIL_DEVICETREECON:
			rc = cil_resolve_devicetreecon(node, args);
			break;
		case CIL_FSUSE:
			rc = cil_resolve_fsuse(node, args);
			break;
		case CIL_SIDCONTEXT:
			rc = cil_resolve_sidcontext(node, args);
			break;
		case CIL_DEFAULTUSER:
		case CIL_DEFAULTROLE:
		case CIL_DEFAULTTYPE:
			rc = cil_resolve_default(node, args);
			break;
		case CIL_DEFAULTRANGE:
			rc = cil_resolve_defaultrange(node, args);
			break;
		case CIL_USERATTRIBUTESET:
			rc = cil_resolve_userattributeset(node, args);
			break;
		default:
			break;
		}
		break;
	default:
		break;
	}

	return rc;

exit:
	return rc;
}