/* Authors: Karl MacMillan <kmacmillan@tresys.com>
 *          Frank Mayer <mayerf@tresys.com>
 *          David Caplan <dac@tresys.com>
 *
 * Copyright (C) 2003 - 2005 Tresys Technology, LLC
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <stdlib.h>

#include <sepol/policydb/flask_types.h>
#include <sepol/policydb/conditional.h>

#include "private.h"

/* move all type rules to top of t/f lists to help kernel on evaluation */
static void cond_optimize(cond_av_list_t ** l)
{
	cond_av_list_t *top, *p, *cur;

	top = p = cur = *l;

	while (cur) {
		if ((cur->node->key.specified & AVTAB_TYPE) && (top != cur)) {
			p->next = cur->next;
			cur->next = top;
			top = cur;
			cur = p->next;
		} else {
			p = cur;
			cur = cur->next;
		}
	}
	*l = top;
}

/* reorder t/f lists for kernel */
void cond_optimize_lists(cond_list_t * cl)
{
	cond_list_t *n;

	for (n = cl; n != NULL; n = n->next) {
		cond_optimize(&n->true_list);
		cond_optimize(&n->false_list);
	}
}

static int bool_present(unsigned int target, unsigned int bools[],
			unsigned int num_bools)
{
	unsigned int i = 0;
	int ret = 1;

	if (num_bools > COND_MAX_BOOLS) {
		return 0;
	}
	while (i < num_bools && target != bools[i])
		i++;
	if (i == num_bools)
		ret = 0;	/* got to end w/o match */
	return ret;
}

static int same_bools(cond_node_t * a, cond_node_t * b)
{
	unsigned int i, x;

	x = a->nbools;

	/* same number of bools? */
	if (x != b->nbools)
		return 0;

	/* make sure all the bools in a are also in b */
	for (i = 0; i < x; i++)
		if (!bool_present(a->bool_ids[i], b->bool_ids, x))
			return 0;
	return 1;
}

/*
 * Determine if two conditional expressions are equal. 
 */
int cond_expr_equal(cond_node_t * a, cond_node_t * b)
{
	cond_expr_t *cur_a, *cur_b;

	if (a == NULL || b == NULL)
		return 0;

	if (a->nbools != b->nbools)
		return 0;

	/* if exprs have <= COND_MAX_BOOLS we can check the precompute values
	 * for the expressions.
	 */
	if (a->nbools <= COND_MAX_BOOLS && b->nbools <= COND_MAX_BOOLS) {
		if (!same_bools(a, b))
			return 0;
		return (a->expr_pre_comp == b->expr_pre_comp);
	}

	/* for long expressions we check for exactly the same expression */
	cur_a = a->expr;
	cur_b = b->expr;
	while (1) {
		if (cur_a == NULL && cur_b == NULL)
			return 1;
		else if (cur_a == NULL || cur_b == NULL)
			return 0;
		if (cur_a->expr_type != cur_b->expr_type)
			return 0;
		if (cur_a->expr_type == COND_BOOL) {
			if (cur_a->bool != cur_b->bool)
				return 0;
		}
		cur_a = cur_a->next;
		cur_b = cur_b->next;
	}
	return 1;
}

/* Create a new conditional node, optionally copying
 * the conditional expression from an existing node.
 * If node is NULL then a new node will be created
 * with no conditional expression.
 */
cond_node_t *cond_node_create(policydb_t * p, cond_node_t * node)
{
	cond_node_t *new_node;
	unsigned int i;

	new_node = (cond_node_t *)malloc(sizeof(cond_node_t));
	if (!new_node) {
		return NULL;
	}
	memset(new_node, 0, sizeof(cond_node_t));

	if (node) {
		new_node->expr = cond_copy_expr(node->expr);
		if (!new_node->expr) {
			free(new_node);
			return NULL;
		}
		new_node->cur_state = cond_evaluate_expr(p, new_node->expr);
		new_node->nbools = node->nbools;
		for (i = 0; i < min(node->nbools, COND_MAX_BOOLS); i++)
			new_node->bool_ids[i] = node->bool_ids[i];
		new_node->expr_pre_comp = node->expr_pre_comp;
		new_node->flags = node->flags;
	}

	return new_node;
}

/* Find a conditional (the needle) within a list of existing ones (the
 * haystack) that has a matching expression.  If found, return a
 * pointer to the existing node, setting 'was_created' to 0.
 * Otherwise create a new one and return it, setting 'was_created' to
 * 1. */
cond_node_t *cond_node_find(policydb_t * p,
			    cond_node_t * needle, cond_node_t * haystack,
			    int *was_created)
{
	while (haystack) {
		if (cond_expr_equal(needle, haystack)) {
			*was_created = 0;
			return haystack;
		}
		haystack = haystack->next;
	}
	*was_created = 1;

	return cond_node_create(p, needle);
}

/* return either a pre-existing matching node or create a new node */
cond_node_t *cond_node_search(policydb_t * p, cond_node_t * list,
			      cond_node_t * cn)
{
	int was_created;
	cond_node_t *result = cond_node_find(p, cn, list, &was_created);
	if (result != NULL && was_created) {
		/* add conditional node to policy list */
		result->next = p->cond_list;
		p->cond_list = result;
	}
	return result;
}

/*
 * cond_evaluate_expr evaluates a conditional expr
 * in reverse polish notation. It returns true (1), false (0),
 * or undefined (-1). Undefined occurs when the expression
 * exceeds the stack depth of COND_EXPR_MAXDEPTH.
 */
int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr)
{

	cond_expr_t *cur;
	int s[COND_EXPR_MAXDEPTH];
	int sp = -1;

	s[0] = -1;

	for (cur = expr; cur != NULL; cur = cur->next) {
		switch (cur->expr_type) {
		case COND_BOOL:
			if (sp == (COND_EXPR_MAXDEPTH - 1))
				return -1;
			sp++;
			s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
			break;
		case COND_NOT:
			if (sp < 0)
				return -1;
			s[sp] = !s[sp];
			break;
		case COND_OR:
			if (sp < 1)
				return -1;
			sp--;
			s[sp] |= s[sp + 1];
			break;
		case COND_AND:
			if (sp < 1)
				return -1;
			sp--;
			s[sp] &= s[sp + 1];
			break;
		case COND_XOR:
			if (sp < 1)
				return -1;
			sp--;
			s[sp] ^= s[sp + 1];
			break;
		case COND_EQ:
			if (sp < 1)
				return -1;
			sp--;
			s[sp] = (s[sp] == s[sp + 1]);
			break;
		case COND_NEQ:
			if (sp < 1)
				return -1;
			sp--;
			s[sp] = (s[sp] != s[sp + 1]);
			break;
		default:
			return -1;
		}
	}
	return s[0];
}

cond_expr_t *cond_copy_expr(cond_expr_t * expr)
{
	cond_expr_t *cur, *head, *tail, *new_expr;
	tail = head = NULL;
	cur = expr;
	while (cur) {
		new_expr = (cond_expr_t *) malloc(sizeof(cond_expr_t));
		if (!new_expr)
			goto free_head;
		memset(new_expr, 0, sizeof(cond_expr_t));

		new_expr->expr_type = cur->expr_type;
		new_expr->bool = cur->bool;

		if (!head)
			head = new_expr;
		if (tail)
			tail->next = new_expr;
		tail = new_expr;
		cur = cur->next;
	}
	return head;

      free_head:
	while (head) {
		tail = head->next;
		free(head);
		head = tail;
	}
	return NULL;
}

/*
 * evaluate_cond_node evaluates the conditional stored in
 * a cond_node_t and if the result is different than the
 * current state of the node it sets the rules in the true/false
 * list appropriately. If the result of the expression is undefined
 * all of the rules are disabled for safety.
 */
static int evaluate_cond_node(policydb_t * p, cond_node_t * node)
{
	int new_state;
	cond_av_list_t *cur;

	new_state = cond_evaluate_expr(p, node->expr);
	if (new_state != node->cur_state) {
		node->cur_state = new_state;
		if (new_state == -1)
			printf
			    ("expression result was undefined - disabling all rules.\n");
		/* turn the rules on or off */
		for (cur = node->true_list; cur != NULL; cur = cur->next) {
			if (new_state <= 0) {
				cur->node->key.specified &= ~AVTAB_ENABLED;
			} else {
				cur->node->key.specified |= AVTAB_ENABLED;
			}
		}

		for (cur = node->false_list; cur != NULL; cur = cur->next) {
			/* -1 or 1 */
			if (new_state) {
				cur->node->key.specified &= ~AVTAB_ENABLED;
			} else {
				cur->node->key.specified |= AVTAB_ENABLED;
			}
		}
	}
	return 0;
}

/* precompute and simplify an expression if possible.  If left with !expression, change 
 * to expression and switch t and f. precompute expression for expressions with limited
 * number of bools.
 */
int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
{
	cond_expr_t *ne, *e;
	cond_av_list_t *tmp;
	unsigned int i, j, orig_value[COND_MAX_BOOLS];
	int k;
	uint32_t test = 0x0;
	avrule_t *tmp2;

	cn->nbools = 0;

	memset(cn->bool_ids, 0, sizeof(cn->bool_ids));
	cn->expr_pre_comp = 0x0;

	/* take care of !expr case */
	ne = NULL;
	e = cn->expr;

	/* becuase it's RPN look at last element */
	while (e->next != NULL) {
		ne = e;
		e = e->next;
	}
	if (e->expr_type == COND_NOT) {
		if (ne) {
			ne->next = NULL;
		} else {	/* ne should never be NULL */
			printf
			    ("Found expr with no bools and only a ! - this should never happen.\n");
			return -1;
		}
		/* swap the true and false lists */
		tmp = cn->true_list;
		cn->true_list = cn->false_list;
		cn->false_list = tmp;
		tmp2 = cn->avtrue_list;
		cn->avtrue_list = cn->avfalse_list;
		cn->avfalse_list = tmp2;

		/* free the "not" node in the list */
		free(e);
	}

	/* find all the bools in the expression */
	for (e = cn->expr; e != NULL; e = e->next) {
		switch (e->expr_type) {
		case COND_BOOL:
			i = 0;
			/* see if we've already seen this bool */
			if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) {
				/* count em all but only record up to COND_MAX_BOOLS */
				if (cn->nbools < COND_MAX_BOOLS)
					cn->bool_ids[cn->nbools++] = e->bool;
				else
					cn->nbools++;
			}
			break;
		default:
			break;
		}
	}

	/* only precompute for exprs with <= COND_AX_BOOLS */
	if (cn->nbools <= COND_MAX_BOOLS) {
		/* save the default values for the bools so we can play with them */
		for (i = 0; i < cn->nbools; i++) {
			orig_value[i] =
			    p->bool_val_to_struct[cn->bool_ids[i] - 1]->state;
		}

		/* loop through all possible combinations of values for bools in expression */
		for (test = 0x0; test < (0x1U << cn->nbools); test++) {
			/* temporarily set the value for all the bools in the
			 * expression using the corr.  bit in test */
			for (j = 0; j < cn->nbools; j++) {
				p->bool_val_to_struct[cn->bool_ids[j] -
						      1]->state =
				    (test & (0x1 << j)) ? 1 : 0;
			}
			k = cond_evaluate_expr(p, cn->expr);
			if (k == -1) {
				printf
				    ("While testing expression, expression result "
				     "was undefined - this should never happen.\n");
				return -1;
			}
			/* set the bit if expression evaluates true */
			if (k)
				cn->expr_pre_comp |= 0x1 << test;
		}

		/* restore bool default values */
		for (i = 0; i < cn->nbools; i++)
			p->bool_val_to_struct[cn->bool_ids[i] - 1]->state =
			    orig_value[i];
	}
	return 0;
}

int evaluate_conds(policydb_t * p)
{
	int ret;
	cond_node_t *cur;

	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
		ret = evaluate_cond_node(p, cur);
		if (ret)
			return ret;
	}
	return 0;
}

int cond_policydb_init(policydb_t * p)
{
	p->bool_val_to_struct = NULL;
	p->cond_list = NULL;
	if (avtab_init(&p->te_cond_avtab))
		return -1;

	return 0;
}

void cond_av_list_destroy(cond_av_list_t * list)
{
	cond_av_list_t *cur, *next;
	for (cur = list; cur != NULL; cur = next) {
		next = cur->next;
		/* the avtab_ptr_t node is destroy by the avtab */
		free(cur);
	}
}

void cond_expr_destroy(cond_expr_t * expr)
{
	cond_expr_t *cur_expr, *next_expr;

	if (!expr)
		return;

	for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) {
		next_expr = cur_expr->next;
		free(cur_expr);
	}
}

void cond_node_destroy(cond_node_t * node)
{
	if (!node)
		return;

	cond_expr_destroy(node->expr);
	avrule_list_destroy(node->avtrue_list);
	avrule_list_destroy(node->avfalse_list);
	cond_av_list_destroy(node->true_list);
	cond_av_list_destroy(node->false_list);
}

void cond_list_destroy(cond_list_t * list)
{
	cond_node_t *next, *cur;

	if (list == NULL)
		return;

	for (cur = list; cur != NULL; cur = next) {
		next = cur->next;
		cond_node_destroy(cur);
		free(cur);
	}
}

void cond_policydb_destroy(policydb_t * p)
{
	if (p->bool_val_to_struct != NULL)
		free(p->bool_val_to_struct);
	avtab_destroy(&p->te_cond_avtab);
	cond_list_destroy(p->cond_list);
}

int cond_init_bool_indexes(policydb_t * p)
{
	if (p->bool_val_to_struct)
		free(p->bool_val_to_struct);
	p->bool_val_to_struct = (cond_bool_datum_t **)
	    malloc(p->p_bools.nprim * sizeof(cond_bool_datum_t *));
	if (!p->bool_val_to_struct)
		return -1;
	return 0;
}

int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p
		      __attribute__ ((unused)))
{
	if (key)
		free(key);
	free(datum);
	return 0;
}

int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap)
{
	policydb_t *p;
	cond_bool_datum_t *booldatum;

	booldatum = datum;
	p = datap;

	if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim)
		return -EINVAL;

	p->p_bool_val_to_name[booldatum->s.value - 1] = key;
	p->bool_val_to_struct[booldatum->s.value - 1] = booldatum;

	return 0;
}

static int bool_isvalid(cond_bool_datum_t * b)
{
	if (!(b->state == 0 || b->state == 1))
		return 0;
	return 1;
}

int cond_read_bool(policydb_t * p,
		   hashtab_t h,
		   struct policy_file *fp)
{
	char *key = 0;
	cond_bool_datum_t *booldatum;
	uint32_t buf[3], len;
	int rc;

	booldatum = malloc(sizeof(cond_bool_datum_t));
	if (!booldatum)
		return -1;
	memset(booldatum, 0, sizeof(cond_bool_datum_t));

	rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
	if (rc < 0)
		goto err;

	booldatum->s.value = le32_to_cpu(buf[0]);
	booldatum->state = le32_to_cpu(buf[1]);

	if (!bool_isvalid(booldatum))
		goto err;

	len = le32_to_cpu(buf[2]);

	key = malloc(len + 1);
	if (!key)
		goto err;
	rc = next_entry(key, fp, len);
	if (rc < 0)
		goto err;
	key[len] = 0;

	if (p->policy_type != POLICY_KERN &&
	    p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
		rc = next_entry(buf, fp, sizeof(uint32_t));
		if (rc < 0)
			goto err;
		booldatum->flags = le32_to_cpu(buf[0]);
	}

	if (hashtab_insert(h, key, booldatum))
		goto err;

	return 0;
      err:
	cond_destroy_bool(key, booldatum, 0);
	return -1;
}

struct cond_insertf_data {
	struct policydb *p;
	cond_av_list_t *other;
	cond_av_list_t *head;
	cond_av_list_t *tail;
};

static int cond_insertf(avtab_t * a
			__attribute__ ((unused)), avtab_key_t * k,
			avtab_datum_t * d, void *ptr)
{
	struct cond_insertf_data *data = ptr;
	struct policydb *p = data->p;
	cond_av_list_t *other = data->other, *list, *cur;
	avtab_ptr_t node_ptr;
	uint8_t found;

	/*
	 * For type rules we have to make certain there aren't any
	 * conflicting rules by searching the te_avtab and the
	 * cond_te_avtab.
	 */
	if (k->specified & AVTAB_TYPE) {
		if (avtab_search(&p->te_avtab, k)) {
			printf
			    ("security: type rule already exists outside of a conditional.");
			goto err;
		}
		/*
		 * If we are reading the false list other will be a pointer to
		 * the true list. We can have duplicate entries if there is only
		 * 1 other entry and it is in our true list.
		 *
		 * If we are reading the true list (other == NULL) there shouldn't
		 * be any other entries.
		 */
		if (other) {
			node_ptr = avtab_search_node(&p->te_cond_avtab, k);
			if (node_ptr) {
				if (avtab_search_node_next
				    (node_ptr, k->specified)) {
					printf
					    ("security: too many conflicting type rules.");
					goto err;
				}
				found = 0;
				for (cur = other; cur != NULL; cur = cur->next) {
					if (cur->node == node_ptr) {
						found = 1;
						break;
					}
				}
				if (!found) {
					printf
					    ("security: conflicting type rules.\n");
					goto err;
				}
			}
		} else {
			if (avtab_search(&p->te_cond_avtab, k)) {
				printf
				    ("security: conflicting type rules when adding type rule for true.\n");
				goto err;
			}
		}
	}

	node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
	if (!node_ptr) {
		printf("security: could not insert rule.");
		goto err;
	}
	node_ptr->parse_context = (void *)1;

	list = malloc(sizeof(cond_av_list_t));
	if (!list)
		goto err;
	memset(list, 0, sizeof(cond_av_list_t));

	list->node = node_ptr;
	if (!data->head)
		data->head = list;
	else
		data->tail->next = list;
	data->tail = list;
	return 0;

      err:
	cond_av_list_destroy(data->head);
	data->head = NULL;
	return -1;
}

static int cond_read_av_list(policydb_t * p, void *fp,
			     cond_av_list_t ** ret_list, cond_av_list_t * other)
{
	unsigned int i;
	int rc;
	uint32_t buf[1], len;
	struct cond_insertf_data data;

	*ret_list = NULL;

	len = 0;
	rc = next_entry(buf, fp, sizeof(uint32_t));
	if (rc < 0)
		return -1;

	len = le32_to_cpu(buf[0]);
	if (len == 0) {
		return 0;
	}

	data.p = p;
	data.other = other;
	data.head = NULL;
	data.tail = NULL;
	for (i = 0; i < len; i++) {
		rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab,
				     cond_insertf, &data);
		if (rc)
			return rc;

	}

	*ret_list = data.head;
	return 0;
}

static int expr_isvalid(policydb_t * p, cond_expr_t * expr)
{
	if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
		printf
		    ("security: conditional expressions uses unknown operator.\n");
		return 0;
	}

	if (expr->bool > p->p_bools.nprim) {
		printf
		    ("security: conditional expressions uses unknown bool.\n");
		return 0;
	}
	return 1;
}

static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp)
{
	uint32_t buf[2];
	int len, i, rc;
	cond_expr_t *expr = NULL, *last = NULL;

	rc = next_entry(buf, fp, sizeof(uint32_t));
	if (rc < 0)
		goto err;

	node->cur_state = le32_to_cpu(buf[0]);

	len = 0;
	rc = next_entry(buf, fp, sizeof(uint32_t));
	if (rc < 0)
		goto err;

	/* expr */
	len = le32_to_cpu(buf[0]);

	for (i = 0; i < len; i++) {
		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
		if (rc < 0)
			goto err;

		expr = malloc(sizeof(cond_expr_t));
		if (!expr) {
			goto err;
		}
		memset(expr, 0, sizeof(cond_expr_t));

		expr->expr_type = le32_to_cpu(buf[0]);
		expr->bool = le32_to_cpu(buf[1]);

		if (!expr_isvalid(p, expr)) {
			free(expr);
			goto err;
		}

		if (i == 0) {
			node->expr = expr;
		} else {
			last->next = expr;
		}
		last = expr;
	}

	if (p->policy_type == POLICY_KERN) {
		if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
			goto err;
		if (cond_read_av_list(p, fp, &node->false_list, node->true_list)
		    != 0)
			goto err;
	} else {
		if (avrule_read_list(p, &node->avtrue_list, fp))
			goto err;
		if (avrule_read_list(p, &node->avfalse_list, fp))
			goto err;
	}

	if (p->policy_type != POLICY_KERN &&
	    p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
		rc = next_entry(buf, fp, sizeof(uint32_t));
		if (rc < 0)
			goto err;
		node->flags = le32_to_cpu(buf[0]);
	}

	return 0;
      err:
	cond_node_destroy(node);
	free(node);
	return -1;
}

int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp)
{
	cond_node_t *node, *last = NULL;
	uint32_t buf[1];
	int i, len, rc;

	rc = next_entry(buf, fp, sizeof(uint32_t));
	if (rc < 0)
		return -1;

	len = le32_to_cpu(buf[0]);

	rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel);
	if (rc)
		goto err;

	for (i = 0; i < len; i++) {
		node = malloc(sizeof(cond_node_t));
		if (!node)
			goto err;
		memset(node, 0, sizeof(cond_node_t));

		if (cond_read_node(p, node, fp) != 0)
			goto err;

		if (i == 0) {
			*list = node;
		} else {
			last->next = node;
		}
		last = node;
	}
	return 0;
      err:
	return -1;
}

/* Determine whether additional permissions are granted by the conditional
 * av table, and if so, add them to the result 
 */
void cond_compute_av(avtab_t * ctab, avtab_key_t * key,
		     struct sepol_av_decision *avd)
{
	avtab_ptr_t node;

	if (!ctab || !key || !avd)
		return;

	for (node = avtab_search_node(ctab, key); node != NULL;
	     node = avtab_search_node_next(node, key->specified)) {
		if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) ==
		    (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED)))
			avd->allowed |= node->datum.data;
		if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) ==
		    (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED)))
			/* Since a '0' in an auditdeny mask represents a 
			 * permission we do NOT want to audit (dontaudit), we use
			 * the '&' operand to ensure that all '0's in the mask
			 * are retained (much unlike the allow and auditallow cases).
			 */
			avd->auditdeny &= node->datum.data;
		if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) ==
		    (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED)))
			avd->auditallow |= node->datum.data;
	}
	return;
}

avtab_datum_t *cond_av_list_search(avtab_key_t * key,
				   cond_av_list_t * cond_list)
{

	cond_av_list_t *cur_av;

	for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) {

		if (cur_av->node->key.source_type == key->source_type &&
		    cur_av->node->key.target_type == key->target_type &&
		    cur_av->node->key.target_class == key->target_class)

			return &cur_av->node->datum;

	}
	return NULL;

}
