1c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
2c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth/* Copyright (c) 2008-2009 Nall Design Works
3c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth   Copyright 2006 Trusted Computer Solutions, Inc. */
4c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
5c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth/*
6c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth Exported Interface
7c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
8c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth int init_translations(void);
9c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth void finish_context_translations(void);
10c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth int trans_context(const security_context_t, security_context_t *);
11c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth int untrans_context(const security_context_t, security_context_t *);
12c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
13c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth*/
14c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
15c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <math.h>
16c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <glob.h>
17c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <values.h>
18c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <unistd.h>
19c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <fcntl.h>
20c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <stdlib.h>
21c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <string.h>
22c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <stdio.h>
23c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <stdio_ext.h>
24c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <ctype.h>
25c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <selinux/selinux.h>
26c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <selinux/context.h>
27c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <syslog.h>
28c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <errno.h>
29c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <pcre.h>
30c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <ctype.h>
31c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <time.h>
32c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include <sys/time.h>
33c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
34c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
35c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include "mls_level.h"
36c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#include "mcstrans.h"
37c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
38c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#define N_BUCKETS 1453
39c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#define OVECCOUNT (512*3)
40c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
41c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#define log_error(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
42c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
43c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
44c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#define log_debug(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
45c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#else
46c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#define log_debug(fmt, ...) ;
47c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
48c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
49c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic unsigned int maxbit=0;
50c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
51c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth/* Define data structures */
52c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct context_map {
53c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *raw;
54c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *trans;
55c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} context_map_t;
56c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
57c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct context_map_node {
58c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *key;
59c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_map_t *map;
60c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct context_map_node *next;
61c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} context_map_node_t;
62c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
63c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct affix {
64c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *text;
65c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct affix *next;
66c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} affix_t;
67c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
68c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct word {
69c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *text;
70c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t cat;
71c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t normal;
72c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t inverse;
73c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct word *next;
74c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} word_t;
75c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
76c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct word_group {
77c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *name;
78c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *whitespace;
79c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *join;
80c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
81c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	affix_t *prefixes;
82c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	affix_t *suffixes;
83c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	word_t *words;
84c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
85c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	pcre *prefix_regexp;
86c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	pcre *word_regexp;
87c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	pcre *suffix_regexp;
88c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
89c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t def;
90c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
91c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	word_t **sword;
9207ba7c6853b76ffb6db952542a3f04f72807dc7bStephen Smalley	unsigned int sword_len;
93c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
94c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct word_group *next;
95c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} word_group_t;
96c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
97c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct base_classification {
98c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *trans;
99c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	mls_level_t *level;
100c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct base_classification *next;
101c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} base_classification_t;
102c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
103c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct domain {
104c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *name;
105c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
106c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_map_node_t *raw_to_trans[N_BUCKETS];
107c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_map_node_t *trans_to_raw[N_BUCKETS];
108c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
109c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	base_classification_t *base_classifications;
110c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	word_group_t *groups;
111c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
112c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	pcre *base_classification_regexp;
113c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct domain *next;
114c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} domain_t;
115c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
116c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic domain_t *domains;
117c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
118c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct sens_constraint {
119c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char op;
120c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *text;
121c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	unsigned int sens;
122c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t cat;
123c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct sens_constraint *next;
124c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} sens_constraint_t;
125c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
126c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic sens_constraint_t *sens_constraints;
127c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
128c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtypedef struct cat_constraint {
129c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char op;
130c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *text;
131c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int nbits;
132c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t mask;
133c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t cat;
134c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct cat_constraint *next;
135c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth} cat_constraint_t;
136c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
137c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic cat_constraint_t *cat_constraints;
138c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
139c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothunsigned int
140c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothhash(const char *str) {
141c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	unsigned int hash = 5381;
142c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int c;
143c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
144c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while ((c = *(unsigned const char *)str++))
145c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		hash = ((hash << 5) + hash) + c;
146c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
147c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return hash;
148c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
149c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1507e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencestatic int
151c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothadd_to_hashtable(context_map_node_t **table, char *key, context_map_t *map) {
152c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	unsigned int bucket = hash(key) % N_BUCKETS;
153c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_map_node_t **n;
154c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (n = &table[bucket]; *n; n = &(*n)->next)
155c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		;
156c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	*n = malloc(sizeof(context_map_node_t));
157c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (! *n)
158c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		goto err;
159c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	(*n)->key = key;
160c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	(*n)->map = map;
161c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	(*n)->next = NULL;
1627e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return 0;
163c89625db93f63f29a57451e692ae33ab24d49291Xavier Totherr:
164c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	syslog(LOG_ERR, "add_to_hashtable: allocation error");
1657e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return -1;
166c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
167c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1687e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencestatic int
1697e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencenumdigits(unsigned int n)
1707e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence{
1717e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	int count = 1;
1727e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	while ((n = n / 10))
1737e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		count++;
1747e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return count;
1757e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence}
1767e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
1777e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencestatic int
1787e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceparse_category(ebitmap_t *e, const char *raw, int allowinverse)
1797e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence{
180c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int inverse = 0;
1817e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	unsigned int low, high;
182c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while (*raw) {
1837e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (allowinverse && *raw == '~') {
1847e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			inverse = !inverse;
185c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			raw++;
186c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			continue;
187c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
188c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (sscanf(raw,"c%u", &low) != 1)
189c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			return -1;
1907e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		raw += numdigits(low) + 1;
191c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (*raw == '.') {
192c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			raw++;
193c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (sscanf(raw,"c%u", &high) != 1)
194c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				return -1;
1957e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			raw += numdigits(high) + 1;
1967e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		} else {
1977e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			high = low;
1987e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
199c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		while (low <= high) {
2007e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			if (low >= maxbit)
2017e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				maxbit = low + 1;
2027e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			if (ebitmap_set_bit(e, low, inverse ? 0 : 1) < 0)
2037e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				return -1;
204c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			low++;
205c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
2067e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (*raw == ',') {
2077e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			raw++;
2087e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			inverse = 0;
2097e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		} else if (*raw != '\0') {
2107e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
2117e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
212c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
213c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return 0;
214c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
215c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
2167e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceint
2177e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceparse_ebitmap(ebitmap_t *e, ebitmap_t *def, const char *raw) {
2187e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	int rc = ebitmap_cpy(e, def);
2197e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (rc < 0)
2207e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return rc;
2217e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	rc = parse_category(e, raw, 1);
2227e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (rc < 0)
2237e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return rc;
2247e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return 0;
2257e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence}
2267e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
2277e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencemls_level_t *
2287e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceparse_raw(const char *raw) {
2297e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	mls_level_t *mls = calloc(1, sizeof(mls_level_t));
2307e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!mls)
2317e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
2327e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (sscanf(raw,"s%u", &mls->sens) != 1)
2337e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
2347e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	raw += numdigits(mls->sens) + 1;
2357e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (*raw == ':') {
2367e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		raw++;
2377e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (parse_category(&mls->cat, raw, 0) < 0)
2387e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			goto err;
2397e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	} else if (*raw != '\0') {
2407e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
241c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
242c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
2437e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return mls;
2447e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
2457e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceerr:
2467e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_destroy(&mls->cat);
2477e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	free(mls);
2487e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return NULL;
249c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
250c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
251c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothvoid
252c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothdestroy_word(word_t **list, word_t *word) {
2537e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!word) {
2547e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return;
2557e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
256c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (; list && *list; list = &(*list)->next) {
257c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (*list == word) {
258c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*list = word->next;
259c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			break;
260c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
261c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
262c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(word->text);
263c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_destroy(&word->cat);
264c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_destroy(&word->normal);
265c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_destroy(&word->inverse);
266c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	memset(word, 0, sizeof(word_t));
267c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(word);
268c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
269c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
2707e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceword_t *
2717e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencecreate_word(word_t **list, const char *text) {
2727e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	word_t *w = calloc(1, sizeof(word_t));
2737e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!w) {
2747e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
2757e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
2767e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	w->text = strdup(text);
2777e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!w->text) {
2787e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
2797e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
280c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (list) {
281c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (; *list; list = &(*list)->next)
282c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			;
2837e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		*list = w;
284c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
285c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
2867e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return w;
2877e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
2887e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceerr:
2897e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	log_error("create_word: allocation error %s", strerror(errno));
2907e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	destroy_word(NULL, w);
2917e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return NULL;
292c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
293c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
294c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothvoid
295c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothdestroy_group(word_group_t **list, word_group_t *group) {
296c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (; list && *list; list = &(*list)->next) {
297c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (*list == group) {
298c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*list = group->next;
299c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			break;
300c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
301c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
302c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while(group->prefixes) {
303c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		affix_t *next = group->prefixes->next;
304c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(group->prefixes->text);
305c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(group->prefixes);
306c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		group->prefixes=next;
307c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
308c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while(group->suffixes) {
309c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		affix_t *next = group->suffixes->next;
310c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(group->suffixes->text);
311c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(group->suffixes);
312c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		group->suffixes=next;
313c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
314c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while(group->words)
315c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		destroy_word(&group->words, group->words);
316c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(group->whitespace);
317c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(group->name);
318c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(group->sword);
319c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(group->join);
320c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	pcre_free(group->prefix_regexp);
321c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	pcre_free(group->word_regexp);
322c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	pcre_free(group->suffix_regexp);
323c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_destroy(&group->def);
324c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(group);
325c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
326c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
3277e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceword_group_t *
3287e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencecreate_group(word_group_t **list, const char *name) {
3297e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	word_group_t *group = calloc(1, sizeof(word_group_t));
3307e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!group)
3317e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return NULL;
3327e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	group->name = strdup(name);
3337e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!group->name) {
3347e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
3357e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
3367e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	group->join = strdup(" ");
3377e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!group->join) {
3387e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
3397e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
3407e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	group->whitespace = strdup(" ");
3417e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!group->whitespace) {
3427e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
3437e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
3447e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	group->sword = NULL;
345c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
3467e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (list) {
3477e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		for (; *list; list = &(*list)->next)
3487e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			;
3497e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		*list = group;
3507e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
351c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
3527e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return group;
3537e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
3547e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceerr:
3557e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	log_error("allocation error %s", strerror(errno));
3567e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	destroy_group(NULL, group);
3577e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return NULL;
358c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
359c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
360c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothvoid
361c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothdestroy_domain(domain_t *domain) {
362c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int i;
363c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth        unsigned int rt = 0, tr = 0;
364c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (i=0; i < N_BUCKETS; i++) {
365c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		context_map_node_t *ptr;
366c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (ptr = domain->trans_to_raw[i]; ptr;)  {
367c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			context_map_node_t *t = ptr->next;
368c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(ptr);
369c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			ptr = t;
370c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			tr++;
371c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
372c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		domain->trans_to_raw[i] = NULL;
373c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
374c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (i=0; i < N_BUCKETS; i++) {
375c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		context_map_node_t *ptr;
376c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (ptr = domain->raw_to_trans[i]; ptr;)  {
377c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			context_map_node_t *t = ptr->next;
378c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(ptr->map->raw);
379c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(ptr->map->trans);
380c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(ptr->map);
381c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(ptr);
382c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			ptr = t;
383c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			rt++;
384c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
385c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		domain->raw_to_trans[i] = NULL;
386c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
387c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while (domain->base_classifications)  {
388c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		base_classification_t *next = domain->base_classifications->next;
389c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(domain->base_classifications->trans);
390c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ebitmap_destroy(&domain->base_classifications->level->cat);
391c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(domain->base_classifications->level);
392c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(domain->base_classifications);
393c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		domain->base_classifications = next;
394c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
395c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	pcre_free(domain->base_classification_regexp);
396c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while (domain->groups)
397c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		destroy_group(&domain->groups, domain->groups);
398c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(domain->name);
399c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(domain);
400c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
401c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	syslog(LOG_INFO, "cache sizes: tr = %u, rt = %u", tr, rt);
402c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
403c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
4047e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencedomain_t *
4057e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencecreate_domain(const char *name) {
4067e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	domain_t *domain = calloc(1, sizeof(domain_t));
4077e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!domain) {
4087e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
4097e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
4107e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	domain->name = strdup(name);
4117e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!domain->name) {
4127e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
4137e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
4147e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
4157e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	domain_t **d = &domains;
4167e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	for (; *d; d = &(*d)->next)
4177e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		;
4187e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	*d = domain;
4197e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
4207e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return domain;
4217e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
4227e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceerr:
4237e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	log_error("allocation error %s", strerror(errno));
4247e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	destroy_domain(domain);
4257e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return NULL;
4267e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence}
4277e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
428c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothint
429c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothadd_word(word_group_t *group, char *raw, char *trans) {
430c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (strchr(trans,'-')) {
431c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		log_error("'%s'is invalid because '-' is illegal in modifiers.\n", trans);
4327e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return -1;
433c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
434c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	word_t *word = create_word(&group->words, trans);
435c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int rc = parse_ebitmap(&word->cat, &group->def, raw);
436c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (rc < 0) {
437c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		log_error(" syntax error in %s\n", raw);
438c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		destroy_word(&group->words, word);
439c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
440c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
4412f68def6338d072ae13328cf6357a4468408ce1bSteve Lawrence	if (ebitmap_andnot(&word->normal, &word->cat, &group->def, maxbit) < 0)
4427e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return -1;
443c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
444c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t temp;
4457e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (ebitmap_xor(&temp, &word->cat, &group->def) < 0)
4467e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return -1;
4477e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (ebitmap_and(&word->inverse, &temp, &group->def) < 0)
4487e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return -1;
449c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_destroy(&temp);
450c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
451c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return 0;
452c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
453c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
454c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothint
455c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothadd_constraint(char op, char *raw, char *tok) {
456c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug("%s\n", "add_constraint");
457c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_t empty;
458c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_init(&empty);
459c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!raw || !*raw) {
460c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "unable to parse line");
461c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
462c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
463c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (*raw == 's') {
464c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		sens_constraint_t *constraint = calloc(1, sizeof(sens_constraint_t));
4657e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (!constraint) {
4667e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			log_error("allocation error %s", strerror(errno));
4677e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
4687e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
469c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (sscanf(raw,"s%u", &constraint->sens) != 1) {
470c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			syslog(LOG_ERR, "unable to parse level");
471c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(constraint);
472c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			return -1;
473c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
474c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (parse_ebitmap(&constraint->cat, &empty, tok) < 0) {
475c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			syslog(LOG_ERR, "unable to parse cat");
476c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(constraint);
477c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			return -1;
478c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
479c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (asprintf(&constraint->text, "%s%c%s", raw, op, tok) < 0) {
480c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			log_error("asprintf failed %s", strerror(errno));
4817e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
482c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
483c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		constraint->op = op;
484c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		sens_constraint_t **p;
485c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (p= &sens_constraints; *p; p = &(*p)->next)
486c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth                        ;
487c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth                *p = constraint;
488c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return 0;
489c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (*raw == 'c' ) {
490c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		cat_constraint_t *constraint = calloc(1, sizeof(cat_constraint_t));
4917e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (!constraint) {
4927e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			log_error("allocation error %s", strerror(errno));
4937e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
4947e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
495c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (parse_ebitmap(&constraint->mask, &empty, raw) < 0) {
496c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			syslog(LOG_ERR, "unable to parse mask");
497c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(constraint);
498c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			return -1;
499c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
500c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (parse_ebitmap(&constraint->cat, &empty, tok) < 0) {
501c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			syslog(LOG_ERR, "unable to parse cat");
502c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			ebitmap_destroy(&constraint->mask);
503c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(constraint);
504c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			return -1;
505c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
506c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (asprintf(&constraint->text, "%s%c%s", raw, op, tok) < 0) {
507c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			log_error("asprintf failed %s", strerror(errno));
5087e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
509c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
510c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		constraint->nbits = ebitmap_cardinality(&constraint->cat);
511c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		constraint->op = op;
512c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		cat_constraint_t **p;
513c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (p= &cat_constraints; *p; p = &(*p)->next)
514c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth                        ;
515c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth                *p = constraint;
516c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return 0;
517c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else {
518c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
519c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
520c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
521c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return 0;
522c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
523c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
524c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothint
525c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothviolates_constraints(mls_level_t *l) {
526c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int nbits;
527c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	sens_constraint_t *s;
52830cbe52c5b824a6a6924fec50b633ba1a3224991Jason Zaman	ebitmap_t common;
529c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (s=sens_constraints; s; s=s->next) {
530c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (s->sens == l->sens) {
5317e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			if (ebitmap_and(&common, &s->cat, &l->cat) < 0)
5327e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				return 1;
533c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			nbits = ebitmap_cardinality(&common);
534c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			ebitmap_destroy(&common);
535c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (nbits) {
536c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				char *text = mls_level_to_string(l);
537c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				syslog(LOG_WARNING, "%s violates %s", text, s->text);
538c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				free(text);
539c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				return 1;
540c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
541c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
542c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
543c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	cat_constraint_t *c;
544c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (c=cat_constraints; c; c=c->next) {
5457e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (ebitmap_and(&common, &c->mask, &l->cat) < 0)
5467e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return 1;
547c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		nbits = ebitmap_cardinality(&common);
548c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ebitmap_destroy(&common);
549c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (nbits > 0) {
5507e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			if (ebitmap_and(&common, &c->cat, &l->cat) < 0)
5517e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				return 1;
552c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			nbits = ebitmap_cardinality(&common);
553c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			ebitmap_destroy(&common);
554c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if ((c->op == '!' && nbits) ||
555c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			    (c->op == '>' && nbits != c->nbits)) {
556c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				char *text = mls_level_to_string(l);
557c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				syslog(LOG_WARNING, "%s violates %s (%d,%d)", text, c->text, nbits, c->nbits);
558c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				free(text);
559c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				return 1;
560c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
561c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
562c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
563c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return 0;
564c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
565c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
566c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothvoid
567c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothdestroy_sens_constraint(sens_constraint_t **list, sens_constraint_t *constraint) {
5687e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!constraint) {
5697e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return;
5707e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
571c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (; list && *list; list = &(*list)->next) {
572c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (*list == constraint) {
573c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*list = constraint->next;
574c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			break;
575c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
576c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
577c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_destroy(&constraint->cat);
578c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(constraint->text);
579c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	memset(constraint, 0, sizeof(sens_constraint_t));
580c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(constraint);
581c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
582c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
583c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothvoid
584c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothdestroy_cat_constraint(cat_constraint_t **list, cat_constraint_t *constraint) {
5857e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!constraint) {
5867e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return;
5877e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
588c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (; list && *list; list = &(*list)->next) {
589c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (*list == constraint) {
590c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*list = constraint->next;
591c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			break;
592c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
593c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
594c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_destroy(&constraint->mask);
595c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	ebitmap_destroy(&constraint->cat);
596c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(constraint->text);
597c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	memset(constraint, 0, sizeof(cat_constraint_t));
598c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(constraint);
599c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
600c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
601c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
602c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic int
603c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothadd_base_classification(domain_t *domain, char *raw, char *trans) {
604c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	mls_level_t *level = parse_raw(raw);
605c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (level) {
606c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		base_classification_t **i;
607c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		base_classification_t *base_classification = calloc(1, sizeof(base_classification_t));
6087e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (!base_classification) {
6097e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			log_error("allocation error %s", strerror(errno));
6107e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
6117e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
612c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		base_classification->trans=strdup(trans);
6137e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (!base_classification->trans) {
6147e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			log_error("allocation error %s", strerror(errno));
6157e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			free(base_classification);
6167e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
6177e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
618c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		base_classification->level=level;
619c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
620c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (i=&domain->base_classifications; *i; i=&(*i)->next)
621c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		;
622c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		*i = base_classification;
623c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			return 0;
624c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
625c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_error(" add_base_classification error %s %s\n", raw, trans);
626c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return -1;
627c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
628c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
6297e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrencestatic int
630c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothadd_cache(domain_t *domain, char *raw, char *trans) {
6317e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	context_map_t *map = calloc(1, sizeof(context_map_t));
632c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!map) goto err;
633c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
634c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	map->raw = strdup(raw);
6357e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!map->raw) {
6367e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
6377e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
638c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	map->trans = strdup(trans);
6397e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!map->trans) {
6407e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
6417e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
642c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
643c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" add_cache (%s,%s)\n", raw, trans);
6447e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (add_to_hashtable(domain->raw_to_trans, map->raw, map) < 0)
6457e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
6467e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
6477e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (add_to_hashtable(domain->trans_to_raw, map->trans, map) < 0)
6487e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
6497e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
6507e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return 0;
651c89625db93f63f29a57451e692ae33ab24d49291Xavier Totherr:
652c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_error("%s: allocation error", "add_cache");
6537e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return -1;
654c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
655c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
656c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic context_map_t *
657c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothfind_in_table(context_map_node_t **table, const char *key) {
658c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	unsigned int bucket = hash(key) % N_BUCKETS;
659c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_map_node_t **n;
660c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (n = &table[bucket]; *n; n = &(*n)->next)
661c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (!strcmp((*n)->key, key))
662c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			return (*n)->map;
663c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return NULL;
664c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
665c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
666c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothchar *
667c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtrim(char *str, const char *whitespace) {
668c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *p = str + strlen(str);
669c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
670c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while (p > str && strchr(whitespace, *(p-1)) != NULL)
671c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		*--p = 0;
672c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return str;
673c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
674c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
675c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothchar *
676c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtriml(char *str, const char *whitespace) {
677c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *p = str;
678c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
679c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while (*p && (strchr(whitespace, *p) != NULL))
680c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		p++;
681c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return p;
682c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
683c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
6847e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceint
6857e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceupdate(char **p, char *const val) {
686c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free (*p);
687c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	*p = strdup(val);
6887e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!*p) {
6897e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		log_error("allocation error %s", strerror(errno));
6907e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return -1;
6917e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
6927e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return 0;
693c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
694c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
6957e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceint
6967e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceappend(affix_t **affixes, const char *val) {
697c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	affix_t *affix = calloc(1, sizeof(affix_t));
6987e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!affix) {
6997e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
7007e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
701c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	affix->text = strdup(val);
7027e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!affix->text)
7037e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
704c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (;*affixes; affixes = &(*affixes)->next)
705c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		;
706c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	*affixes = affix;
7077e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return 0;
7087e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
7097e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceerr:
7107e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	log_error("allocation error %s", strerror(errno));
7117e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return -1;
712c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
713c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
714c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic int read_translations(const char *filename);
715c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
716c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth/* Process line from translation file.
717c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth   Remove white space and set raw do data before the "=" and tok to data after it
718c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth   Modifies the data pointed to by the buffer parameter
719c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth */
720c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic int
721c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothprocess_trans(char *buffer) {
722c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	static domain_t *domain;
723c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	static word_group_t *group;
724c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	static int base_classification;
725c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	static int lineno = 0;
726c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char op='\0';
727c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
728c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	lineno++;
729c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug("%d: %s", lineno, buffer);
730c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
731c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	/* zap leading whitespace */
732c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	buffer = triml(buffer, "\t ");
733c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
734c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	/* Ignore comments */
735c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (*buffer == '#') return 0;
736c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *comment = strpbrk (buffer, "#");
737c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (comment) {
738c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		*comment = '\0';
739c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
740c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
741c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	/* zap trailing whitespace */
742c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	buffer = trim(buffer, "\t \r\n");
743c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
744c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (*buffer == 0) return 0;
745c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
746c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *delim = strpbrk (buffer, "=!>");
747c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (! delim) {
748c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "invalid line (no !, = or >) %d", lineno);
749c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
750c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
751c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
752c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	op = *delim;
753c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	*delim = '\0';
754c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *raw = buffer;
755c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *tok = delim+1;
756c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
7577e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	/* remove trailing/leading whitespace from the split tokens */
7587e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	trim(raw, "\t ");
7597e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	tok = triml(tok, "\t ");
7607e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
761c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (! *raw) {
762c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "invalid line %d", lineno);
763c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
764c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
765c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
766c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (! *tok) {
767c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "invalid line %d", lineno);
768c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
769c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
770c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
771c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	/* constraints have different syntax */
772c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (op == '!' || op == '>') {
773c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return add_constraint(op, raw, tok);
774c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
775c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
776c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!strcmp(raw, "Domain")) {
777c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		domain = create_domain(tok);
778c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		group = NULL;
779c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return 0;
780c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
781c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
782c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!domain) {
783c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		domain = create_domain("Default");
7847e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (!domain)
7857e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
786c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		group = NULL;
787c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
788c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
789c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!group &&
790c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	    (!strcmp(raw, "Whitespace") || !strcmp(raw, "Join") ||
7917e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	     !strcmp(raw, "Prefix") || !strcmp(raw, "Suffix") ||
7927e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		 !strcmp(raw, "Default"))) {
793c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "expected  ModifierGroup declaration on line %d", lineno);
794c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
795c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
796c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
797c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!strcmp(raw, "Include")) {
798c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		unsigned int n;
799c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		glob_t g;
800c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		g.gl_offs = 0;
801c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (glob(tok, GLOB_ERR, NULL, &g) < 0) {
802c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			globfree(&g);
8037e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
804c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
805c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (n=0; n < g.gl_pathc; n++) {
806c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (read_translations(g.gl_pathv[n]) < 0) {
807c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				globfree(&g);
808c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				return -1;
809c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
810c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
811c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		globfree(&g);
812c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (!strcmp(raw, "Base")) {
813c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		base_classification = 1;
814c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (!strcmp(raw, "ModifierGroup")) {
815c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		group = create_group(&domain->groups, tok);
8167e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (!group)
8177e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
818c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		base_classification = 0;
819c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (!strcmp(raw, "Whitespace")) {
8207e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (update (&group->whitespace, tok) < 0)
8217e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
822c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (!strcmp(raw, "Join")) {
8237e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (update (&group->join, tok) < 0)
8247e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
825c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (!strcmp(raw, "Prefix")) {
8267e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (append (&group->prefixes, tok) < 0)
8277e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
828c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (!strcmp(raw, "Suffix")) {
8297e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (append (&group->suffixes, tok) < 0)
8307e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
831c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (!strcmp(raw, "Default")) {
832c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ebitmap_t empty;
833c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ebitmap_init(&empty);
834c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (parse_ebitmap(&group->def, &empty, tok) < 0) {
835c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			syslog(LOG_ERR, "unable to parse Default %d", lineno);
836c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			return -1;
837c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
838c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else if (group) {
8397e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (add_word(group, raw, tok) < 0) {
8407e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			syslog(LOG_ERR, "unable to add base_classification on line %d", lineno);
8417e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
8427e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
843c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else {
844c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (base_classification) {
845c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (add_base_classification(domain, raw, tok) < 0) {
846c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				syslog(LOG_ERR, "unable to add base_classification on line %d", lineno);
847c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				return -1;
848c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
849c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
8507e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (add_cache(domain, raw, tok) < 0)
8517e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
852c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
853c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return 0;
854c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
855c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
856c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothint
857c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothread_translations(const char *filename) {
858c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	size_t size = 0;
859c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *buffer = NULL;
860c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int rval = 0;
861c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
862c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	FILE *cfg = fopen(filename,"r");
863c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!cfg) {
864c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "%s file open failed", filename);
865c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
866c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
867c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
868c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	__fsetlocking(cfg, FSETLOCKING_BYCALLER);
869c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while (getline(&buffer, &size, cfg) > 0) {
870c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if( process_trans(buffer) < 0 ) {
871c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			syslog(LOG_ERR, "%s file read failed", filename);
872c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			rval = -1;
873c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			break;
874c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
875c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
876c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(buffer);
877c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	fclose(cfg);
878c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return rval;
879c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
880c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
881c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothint
882c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothinit_translations(void) {
883c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (is_selinux_mls_enabled() <= 0)
884c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return -1;
885c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
886c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return(read_translations(selinux_translations_path()));
887c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
888c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
889c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothchar *
890c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothextract_range(const security_context_t incon) {
891c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_t con = context_new(incon);
892c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!con) {
893c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "extract_range context_new(%s) failed: %s", incon, strerror(errno));
894c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return NULL;
895c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
896c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
897c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	const char *range = context_range_get(con);
898c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!range) {
899c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "extract_range: context_range_get(%s) failed: %m", incon);
900c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		context_free(con);
901c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return NULL;
902c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
903c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *r = strdup(range);
9047e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!r) {
9057e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		log_error("extract_range: allocation error %s", strerror(errno));
9067e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return NULL;
9077e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
908c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_free(con);
909c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return r;
910c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
911c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
912c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothchar *
913c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothnew_context_str(const security_context_t incon, const char *range) {
9147e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	char *rcon = NULL;
915c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_t con = context_new(incon);
916c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!con) {
9177e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto exit;
918c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
919c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_range_set(con, range);
920c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	rcon = strdup(context_str(con));
9217e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!rcon) {
9227e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto exit;
9237e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
9247e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
925c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return rcon;
9267e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
9277e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceexit:
9287e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	log_error("new_context_str: %s %s", incon, strerror(errno));
9297e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return NULL;
930c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
931c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
932c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothchar *
933c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothfind_in_hashtable(const char *range, domain_t *domain, context_map_node_t **table) {
934c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *trans = NULL;
935c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	context_map_t *map = find_in_table(table, range);
936c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (map) {
937c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		trans = strdup((table == domain->raw_to_trans) ? map->trans: map->raw);
9387e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (!trans) {
9397e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			log_error("find_in_hashtable: allocation error %s", strerror(errno));
9407e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return NULL;
9417e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
942c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		log_debug(" found %s in hashtable returning %s\n", range, trans);
943c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
944c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return trans;
945c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
946c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
947c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothvoid
948c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothemit_whitespace(char*buffer, char *whitespace) {
949c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	strcat(buffer, "[");
950c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	strcat(buffer, whitespace);
951c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	strcat(buffer, "]");
952c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
953c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
954c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic int
955c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstring_size(const void *p1, const void *p2) {
956c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return strlen(*(char **)p2) - strlen(*(char **)p1);
957c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
958c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
959c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothstatic int
960c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothword_size(const void *p1, const void *p2) {
961c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	word_t *w1 = *(word_t **)p1;
962c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	word_t *w2 = *(word_t **)p2;
963c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int w1_len=strlen(w1->text);
964c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int w2_len=strlen(w2->text);
965c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (w1_len == w2_len)
966c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		return strcmp(w1->text, w2->text);
967c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return (w2_len - w1_len);
968c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
969c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
970c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothvoid
971c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothbuild_regexp(pcre **r, char *buffer) {
972c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	const char *error;
973c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int error_offset;
974c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (*r)
975c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		pcre_free(*r);
976c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	*r = pcre_compile(buffer, PCRE_CASELESS, &error, &error_offset, NULL);
977c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (error) {
978c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		log_error("pcre=%s, error=%s\n", buffer, error ? error: "none");
979c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
980c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	buffer[0] = '\0';
981c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
982c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
9837e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceint
984c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothbuild_regexps(domain_t *domain) {
985c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char buffer[1024 * 128];
986c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	buffer[0] = '\0';
987c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	base_classification_t *bc;
988c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	word_group_t *g;
989c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	affix_t *a;
990c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	word_t *w;
991c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	size_t n_el, i;
992c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
993c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (n_el = 0, bc = domain->base_classifications; bc; bc = bc->next) {
994c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		n_el++;
995c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
996c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
997c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char **sortable = calloc(n_el, sizeof(char *));
9987e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!sortable) {
9997e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		log_error("allocation error %s", strerror(errno));
10007e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		return -1;
10017e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
1002c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1003c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (i=0, bc = domain->base_classifications; bc; bc = bc->next) {
1004c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		sortable[i++] = bc->trans;
1005c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1006c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1007c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	qsort(sortable, n_el, sizeof(char *), string_size);
1008c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1009c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (i = 0; i < n_el; i++) {
1010c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		strcat(buffer, sortable[i]);
1011c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (i < n_el) strcat(buffer,"|");
1012c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1013c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1014c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(sortable);
1015c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1016c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(">>> %s classification regexp=%s\n", domain->name, buffer);
1017c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	build_regexp(&domain->base_classification_regexp, buffer);
1018c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1019c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (g = domain->groups; g; g = g->next) {
1020c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (g->prefixes) {
1021c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer,"(?:");
1022c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			for (a = g->prefixes; a; a = a->next) {
1023c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				strcat(buffer, a->text);
1024c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (a->next) strcat(buffer,"|");
1025c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1026c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer,")");
1027c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer,"[ 	]+");
1028c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			log_debug(">>> %s %s prefix regexp=%s\n", domain->name, g->name, buffer);
1029c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			build_regexp(&g->prefix_regexp, buffer);
1030c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1031c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1032c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (g->prefixes)
1033c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer, "^");
1034c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		strcat(buffer, "(?:");
1035c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1036c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		g->sword_len=0;
1037c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (w = g->words; w; w = w->next)
1038c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			g->sword_len++;
1039c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1040c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		g->sword = calloc(g->sword_len, sizeof(word_t *));
10417e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (!g->sword) {
10427e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			log_error("allocation error %s", strerror(errno));
10437e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			return -1;
10447e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
1045c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
104630cbe52c5b824a6a6924fec50b633ba1a3224991Jason Zaman		i=0;
1047c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (w = g->words; w; w = w->next)
1048c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			g->sword[i++]=w;
1049c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1050c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		qsort(g->sword, g->sword_len, sizeof(word_t *), word_size);
1051c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1052c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (i=0; i < g->sword_len; i++) {
1053c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (i) strcat(buffer,"|");
1054c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer,"\\b");
1055c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer, g->sword[i]->text);
1056c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer,"\\b");
1057c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1058c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
10597e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (g->whitespace) {
10607e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			strcat(buffer,"|[");
10617e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			strcat(buffer, g->whitespace);
10627e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			strcat(buffer, "]+");
10637e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		}
1064c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1065c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		strcat(buffer, ")+");
1066c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (g->suffixes)
1067c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer, "$");
1068c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1069c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		log_debug(">>> %s %s modifier regexp=%s\n", domain->name, g->name, buffer);
1070c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		build_regexp(&g->word_regexp, buffer);
1071c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (g->suffixes) {
1072c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer,"[ 	]+");
1073c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer,"(?:");
1074c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			for (a = g->suffixes; a; a = a->next) {
1075c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				strcat(buffer, a->text);
1076c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (a->next) strcat(buffer,"|");
1077c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1078c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			strcat(buffer,")");
1079c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			log_debug(">>> %s %s suffix regexp=%s\n", domain->name, g->name, buffer);
1080c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			build_regexp(&g->suffix_regexp, buffer);
1081c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1082c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
10837e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
10847e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return 0;
1085c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
1086c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1087c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothchar *
1088c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothcompute_raw_from_trans(const char *level, domain_t *domain) {
1089c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1090c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
1091c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct timeval startTime;
1092c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	gettimeofday(&startTime, 0);
1093c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
1094c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
109530cbe52c5b824a6a6924fec50b633ba1a3224991Jason Zaman	int rc = 0;
1096c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int ovector[OVECCOUNT];
10977e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	word_group_t *g = NULL;
10987e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	char *work = NULL;
1099c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *r = NULL;
11007e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	const char * match = NULL;
11017e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	int work_len;
1102c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	mls_level_t *mraw = NULL;
11037e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_t set, clear, tmp;
11047e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
11057e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&set);
11067e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&clear);
11077e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&tmp);
11087e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
11097e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	work = strdup(level);
11107e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	if (!work) {
11117e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		log_error("compute_raw_from_trans: allocation error %s", strerror(errno));
11127e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
11137e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	}
11147e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	work_len = strlen(work);
1115c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1116c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!domain->base_classification_regexp)
11177e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		if (build_regexps(domain) < 0)
11187e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			goto err;
1119c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!domain->base_classification_regexp)
11207e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
1121c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" compute_raw_from_trans work = %s\n", work);
112230cbe52c5b824a6a6924fec50b633ba1a3224991Jason Zaman	rc = pcre_exec(domain->base_classification_regexp, 0, work, work_len, 0, PCRE_ANCHORED, ovector, OVECCOUNT);
1123c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (rc > 0) {
11247e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		match = NULL;
1125c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		pcre_get_substring(work, ovector, rc, 0, &match);
11267e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		log_debug(" compute_raw_from_trans match = %s len = %u\n", match, strlen(match));
1127c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		base_classification_t *bc;
1128c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (bc = domain->base_classifications; bc; bc = bc->next) {
1129c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (!strcmp(bc->trans, match)) {
1130c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				log_debug(" compute_raw_from_trans base classification %s matched %s\n", level, bc->trans);
1131c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				mraw = malloc(sizeof(mls_level_t));
11327e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				if (!mraw) {
11337e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					log_error("allocation error %s", strerror(errno));
11347e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					goto err;
11357e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				}
11367e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				if (mls_level_cpy(mraw, bc->level) < 0)
11377e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					goto err;
1138c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				break;
1139c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1140c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1141c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1142c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		memset(work + ovector[0], '#', ovector[1] - ovector[0]);
1143c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		char *p=work + ovector[0] + ovector[1];
1144c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		while (*p && (strchr(" 	", *p) != NULL))
1145c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*p++ = '#';
1146c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		pcre_free((char *)match);
11477e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		match = NULL;
1148c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else {
1149c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		log_debug(" compute_raw_from_trans no base classification matched %s\n", level);
1150c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1151c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1152c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (mraw == NULL) {
11537e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
1154c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1155c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1156c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int complete = 0;
1157c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int change = 1;
1158c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while(change && !complete) {
1159c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		change = 0;
1160c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		for (g = domain->groups; g && !change && !complete; g = g->next) {
1161c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			int prefix = 0, suffix = 0;
1162c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			int prefix_offset = 0, prefix_len = 0;
1163c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			int suffix_offset = 0, suffix_len = 0;
1164c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (g->prefix_regexp) {
116530cbe52c5b824a6a6924fec50b633ba1a3224991Jason Zaman				rc = pcre_exec(g->prefix_regexp, 0, work, work_len, 0, 0, ovector, OVECCOUNT);
1166c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (rc > 0) {
1167c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					prefix = 1;
1168c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					prefix_offset = ovector[0];
1169c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					prefix_len = ovector[1] - ovector[0];
1170c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1171c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1172c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (g->suffix_regexp) {
117330cbe52c5b824a6a6924fec50b633ba1a3224991Jason Zaman				rc = pcre_exec(g->suffix_regexp, 0, work, work_len, 0, 0, ovector, OVECCOUNT);
1174c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (rc > 0) {
1175c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					suffix = 1;
1176c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					suffix_offset = ovector[0];
1177c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					suffix_len = ovector[1] - ovector[0];
1178c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1179c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1180c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1181c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth/* anchors prefix ^, suffix $ */
1182c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (((!g->prefixes && !g->suffixes) ||
1183c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			     (g->prefixes && prefix) ||
1184c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			     (g->suffixes && suffix)) &&
1185c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			     g->word_regexp) {
1186c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				char *s = work + prefix_offset + prefix_len;
1187c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				int l = (suffix_len ? suffix_offset : work_len) - prefix_len - prefix_offset;
118830cbe52c5b824a6a6924fec50b633ba1a3224991Jason Zaman				rc = pcre_exec(g->word_regexp, 0, s, l, 0, 0, ovector, OVECCOUNT);
1189c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (rc > 0) {
11907e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					match = NULL;
1191c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					pcre_get_substring(s, ovector, rc, 0, &match);
1192c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					trim((char *)match, g->whitespace);
1193c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (*match) {
1194c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						char *p = triml((char *)match, g->whitespace);
1195c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						while (p && *p) {
1196c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							int plen = strlen(p);
119707ba7c6853b76ffb6db952542a3f04f72807dc7bStephen Smalley							unsigned int i;
1198c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							for (i = 0; i < g->sword_len; i++) {
1199c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								word_t *w = g->sword[i];
1200c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								int wlen = strlen(w->text);
1201c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								if (plen >= wlen && !strncmp(w->text, p, strlen(w->text))){
12022f68def6338d072ae13328cf6357a4468408ce1bSteve Lawrence									if (ebitmap_andnot(&set, &w->cat, &g->def, maxbit) < 0) goto err;
1203c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
12047e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence									if (ebitmap_xor(&tmp, &w->cat, &g->def) < 0) goto err;
12057e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence									if (ebitmap_and(&clear, &tmp, &g->def) < 0) goto err;
12067e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence									if (ebitmap_union(&mraw->cat, &set) < 0) goto err;
1207c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1208c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth									ebitmap_destroy(&tmp);
12097e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence									if (ebitmap_cpy(&tmp, &mraw->cat) < 0) goto err;
1210c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth									ebitmap_destroy(&mraw->cat);
12112f68def6338d072ae13328cf6357a4468408ce1bSteve Lawrence									if (ebitmap_andnot(&mraw->cat, &tmp, &clear, maxbit) < 0) goto err;
1212c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1213c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth									ebitmap_destroy(&tmp);
1214c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth									ebitmap_destroy(&set);
1215c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth									ebitmap_destroy(&clear);
1216c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth									p += strlen(w->text);
1217c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth									change++;
1218c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth									break;
1219c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								}
1220c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							}
1221c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							if (i == g->sword_len) {
1222c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								syslog(LOG_ERR, "conversion error");
1223c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								break;
1224c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							}
1225c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							p = triml(p, g->whitespace);
1226c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						}
1227c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						memset(work + prefix_offset, '#', prefix_len);
1228c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						memset(work + suffix_offset, '#', suffix_len);
1229c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						memset(s + ovector[0], '#', ovector[1] - ovector[0]);
1230c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1231c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					pcre_free((void *)match);
12327e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					match = NULL;
1233c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1234c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1235c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth/* YYY */
1236c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			complete=1;
1237c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			char *p = work;
1238c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			while(*p) {
1239c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (isalnum(*p++)) {
1240c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					complete=0;
1241c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					break;
1242c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1243c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1244c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1245c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1246c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(work);
1247c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (violates_constraints(mraw)) {
1248c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		complete = 0;
1249c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1250c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (complete)
1251c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		r = mls_level_to_string(mraw);
1252c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	mls_level_destroy(mraw);
1253c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(mraw);
1254c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1255c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
1256c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct timeval stopTime;
1257c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	gettimeofday(&stopTime, 0);
1258c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	long int ms;
1259c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (startTime.tv_usec > stopTime.tv_usec)
1260c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000);
1261c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	else
1262c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ms = (stopTime.tv_sec - startTime.tv_sec    ) * 1000 + (stopTime.tv_usec/1000        - startTime.tv_usec/1000);
1263c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" compute_raw_from_trans in %ld ms'\n", ms);
1264c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
1265c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1266c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return r;
12677e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
12687e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceerr:
12697e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	mls_level_destroy(mraw);
12707e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	free(mraw);
12717e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	free(work);
12727e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	pcre_free((void *)match);
12737e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_destroy(&tmp);
12747e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_destroy(&set);
12757e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_destroy(&clear);
12767e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return NULL;
1277c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
1278c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1279c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothchar *
1280c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothcompute_trans_from_raw(const char *level, domain_t *domain) {
1281c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1282c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
1283c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct timeval startTime;
1284c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	gettimeofday(&startTime, 0);
1285c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
1286c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
128730cbe52c5b824a6a6924fec50b633ba1a3224991Jason Zaman	word_group_t *g;
12887e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	mls_level_t *l = NULL;
1289c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *rval = NULL;
12906e4bb702af6a77dba2c646a9563899243ad5ebd5Stephen Smalley	word_group_t *groups = NULL;
12917e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_t bit_diff, temp, handled, nothandled, unhandled, orig_unhandled;
12927e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
12937e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&bit_diff);
12947e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&temp);
12957e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&handled);
12967e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&nothandled);
12977e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&unhandled);
12987e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	ebitmap_init(&orig_unhandled);
12997e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
1300c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!level)
13017e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
13027e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
13037e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	l = parse_raw(level);
1304c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!l)
13057e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
1306c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" compute_trans_from_raw raw = %s\n", level);
1307c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1308c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth/* YYY */
1309c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	/* check constraints */
1310c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (violates_constraints(l)) {
1311c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		syslog(LOG_ERR, "%s violates constraints", level);
13127e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		goto err;
1313c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1314c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1315c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int doInverse = l->sens > 0;
1316c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1317c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	base_classification_t *bc, *last = NULL;
1318c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	int done = 0;
1319c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (bc = domain->base_classifications; bc && !done; bc = bc->next) {
1320c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (l->sens == bc->level->sens) {
1321c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			/* skip if alias of last bc */
1322c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (last &&
1323c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			    last->level->sens == bc->level->sens &&
1324c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			    ebitmap_cmp(&last->level->cat, &bc->level->cat) == 0)
1325c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				continue;
1326c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1327c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			/* compute bits not consumed by base classification */
13287e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			if (ebitmap_xor(&unhandled, &l->cat, &bc->level->cat) < 0)
13297e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				goto err;
13307e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence			if (ebitmap_cpy(&orig_unhandled, &unhandled) < 0)
13317e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				goto err;
1332c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1333c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			/* prebuild groups */
1334c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			for (g = domain->groups; g; g = g->next) {
1335c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				word_group_t **t;
1336c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				for (t = &groups; *t; t = &(*t)->next)
1337c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (!strcmp(g->name, (*t)->name))
1338c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						break;
1339c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1340c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (! *t) {
1341c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					word_group_t *wg = create_group(&groups, g->name);
1342c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (g->prefixes)
13437e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						if (append(&wg->prefixes, g->prefixes->text) < 0)
13447e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							goto err;
1345c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (g->suffixes)
13467e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						if (append(&wg->suffixes, g->suffixes->text) < 0)
13477e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							goto err;
1348c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (g->join)
13497e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						if (update(&wg->join, g->join) < 0)
13507e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							goto err;
1351c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1352c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1353c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1354c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			int loops, hamming, change=1;
1355c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			for (loops = 50; ebitmap_cardinality(&unhandled) && loops > 0 && change; loops--) {
1356c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				change = 0;
1357c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				hamming = 10000;
13587e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				if (ebitmap_xor(&handled, &unhandled, &orig_unhandled) < 0)
13597e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					goto err;
13602f68def6338d072ae13328cf6357a4468408ce1bSteve Lawrence				if (ebitmap_not(&nothandled, &handled, maxbit) < 0)
13617e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					goto err;
1362c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				word_group_t *currentGroup = NULL;
1363c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				word_t *currentWord = NULL;
1364c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				for (g = domain->groups; g && hamming; g = g->next) {
1365c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					word_t *w;
1366c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					for (w = g->words; w && hamming; w = w->next) {
1367c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						int cardinality = ebitmap_cardinality(&w->normal);
1368c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						/* If the word is all inverse bits and the level does not have inverse bits - skip */
1369c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						if (cardinality && !doInverse) {
1370c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							continue;
1371c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						}
1372c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1373c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						/* if only unhandled bits are different */
13747e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						if (ebitmap_or(&temp, &w->normal, &w->inverse) < 0)
13757e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							goto err;
13767e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						if (ebitmap_and(&bit_diff, &temp, &nothandled) < 0)
13777e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							goto err;
1378c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						ebitmap_destroy(&temp);
1379c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth// xor bit_diff handled?
13807e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						if (ebitmap_and(&temp, &bit_diff, &unhandled) < 0)
13817e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							goto err;
1382c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						if (ebitmap_cmp(&bit_diff, &temp)) {
13832f68def6338d072ae13328cf6357a4468408ce1bSteve Lawrence							int h = ebitmap_hamming_distance(&bit_diff, &unhandled);
1384c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							if (h < hamming) {
1385c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								hamming = h;
1386c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								currentGroup = g;
1387c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth								currentWord = w;
1388c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							}
1389c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						}
1390c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						ebitmap_destroy(&bit_diff);
1391c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						ebitmap_destroy(&temp);
1392c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1393c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1394c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				ebitmap_destroy(&handled);
1395c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				ebitmap_destroy(&nothandled);
1396c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1397c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (currentWord) {
13987e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					if (ebitmap_xor(&bit_diff, &currentWord->cat, &bc->level->cat) < 0)
13997e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						goto err;
1400c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
14017e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					if (ebitmap_cpy(&temp, &unhandled) < 0)
14027e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						goto err;
1403c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					ebitmap_destroy(&unhandled);
14042f68def6338d072ae13328cf6357a4468408ce1bSteve Lawrence					if (ebitmap_andnot(&unhandled, &temp, &bit_diff, maxbit) < 0)
14057e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						goto err;
1406c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1407c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					ebitmap_destroy(&bit_diff);
1408c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					ebitmap_destroy(&temp);
1409c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1410c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					word_group_t **t;
1411c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					for (t = &groups; *t; t = &(*t)->next)
1412c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						if (!strcmp(currentGroup->name, (*t)->name))
1413c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							break;
1414c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					create_word(&(*t)->words, currentWord->text);
1415c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					change++;
1416c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1417c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1418c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1419c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			done = (ebitmap_cardinality(&unhandled) == 0);
1420c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			ebitmap_destroy(&unhandled);
1421c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			ebitmap_destroy(&orig_unhandled);
1422c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (done) {
1423c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				char buffer[9999];
1424c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				buffer[0] = 0;
1425c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				strcat(buffer, bc->trans);
1426c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				strcat(buffer, " ");
1427c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				for (g=groups; g; g = g->next) {
1428c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (g->words && g->prefixes) {
1429c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						strcat(buffer, g->prefixes->text);
1430c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						strcat(buffer, " ");
1431c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1432c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					word_t *w;
1433c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					for (w=g->words; w; w = w->next) {
1434c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						strcat(buffer, w->text);
1435c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						if (w->next)
1436c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							strcat(buffer, g->join);
1437c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1438c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (g->words && g->suffixes) {
1439c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						strcat(buffer, " ");
1440c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						strcat(buffer, g->suffixes->text);
1441c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1442c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					word_group_t *n = g->next;
1443c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					while(g->words && n) {
1444c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						if (n->words) {
1445c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							strcat(buffer, " ");
1446c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth							break;
1447c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						}
1448c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						n = n->next;
1449c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1450c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1451c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				rval = strdup(buffer);
14527e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				if (!rval) {
14537e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					log_error("compute_trans_from_raw: allocation error %s", strerror(errno));
14547e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					goto err;
14557e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				}
1456c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1457c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			/* clean up */
1458c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			while (groups)
1459c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				destroy_group(&groups, groups);
1460c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1461c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		last = bc;
1462c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1463c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (l) {
1464c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		mls_level_destroy(l);
1465c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(l);
1466c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1467c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1468c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
1469c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct timeval stopTime;
1470c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	gettimeofday(&stopTime, 0);
1471c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	long int ms;
1472c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (startTime.tv_usec > stopTime.tv_usec)
1473c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000);
1474c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	else
1475c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ms = (stopTime.tv_sec - startTime.tv_sec    ) * 1000 + (stopTime.tv_usec/1000        - startTime.tv_usec/1000);
1476c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1477c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" compute_trans_from_raw in %ld ms'\n", ms);
1478c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
1479c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1480c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return rval;
14817e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence
14827e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrenceerr:
14837e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	while (groups)
14847e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence		destroy_group(&groups, groups);
14857e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	mls_level_destroy(l);
14867e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	free(l);
14877e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence	return NULL;
1488c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
1489c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1490c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothint
1491c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothtrans_context(const security_context_t incon, security_context_t *rcon) {
1492c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *trans = NULL;
1493c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	*rcon = NULL;
1494c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1495c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
1496c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct timeval startTime;
1497c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	gettimeofday(&startTime, 0);
1498c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
1499c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1500c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" trans_context input = %s\n", incon);
1501c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *range = extract_range(incon);
1502c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!range) return -1;
1503c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1504c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	domain_t *domain = domains;
1505c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (;domain; domain = domain->next) {
1506c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		trans = find_in_hashtable(range, domain, domain->raw_to_trans);
1507c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (trans) break;
1508c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1509c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		/* try split and translate */
1510c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		char *lrange = NULL, *urange = NULL;
1511c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		char *ltrans = NULL, *utrans = NULL;
1512c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		char *dashp = strchr(range,'-');
1513c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (dashp) {
1514c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*dashp = 0;
1515c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			lrange = range;
1516c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			urange = dashp+1;
1517c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		} else {
1518c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			trans = compute_trans_from_raw(range, domain);
1519c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (trans)
15207e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				if (add_cache(domain, range, trans) < 0)
15217e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					return -1;
1522c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1523c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1524c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (lrange && urange) {
1525c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			ltrans = find_in_hashtable(lrange, domain, domain->raw_to_trans);
1526c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (! ltrans) {
1527c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				ltrans = compute_trans_from_raw(lrange, domain);
15287e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				if (ltrans) {
15297e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					if (add_cache(domain, lrange, ltrans) < 0)
15307e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						return -1;
15317e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				} else {
1532c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					ltrans = strdup(lrange);
1533c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (! ltrans) {
1534c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						log_error("strdup failed %s", strerror(errno));
15357e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						return -1;
1536c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1537c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1538c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1539c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1540c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			utrans = find_in_hashtable(urange, domain, domain->raw_to_trans);
1541c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (! utrans) {
1542c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				utrans = compute_trans_from_raw(urange, domain);
15437e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				if (utrans) {
15447e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					if (add_cache(domain, urange, utrans) < 0)
15457e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						return -1;
15467e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				} else {
1547c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					utrans = strdup(urange);
1548c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (! utrans) {
1549c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						log_error("strdup failed %s", strerror(errno));
15507e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence 						return -1;
1551c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth 					}
1552c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth 				}
1553c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1554c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1555c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (strcmp(ltrans, utrans) == 0) {
1556c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (asprintf(&trans, "%s", ltrans) < 0) {
1557c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					log_error("asprintf failed %s", strerror(errno));
15587e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					return -1;
1559c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1560c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			} else {
1561c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (asprintf(&trans, "%s-%s", ltrans, utrans) < 0) {
1562c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					log_error("asprintf failed %s", strerror(errno));
15637e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					return -1;
1564c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1565c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1566c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(ltrans);
1567c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(utrans);
1568c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*dashp = '-';
1569c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			break;
1570c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1571c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (dashp)
1572c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*dashp = '-';
1573c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1574c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1575c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (trans) {
1576c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		*rcon = new_context_str(incon, trans);
1577c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(trans);
1578c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else {
1579c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		*rcon = new_context_str(incon, range);
1580c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1581c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(range);
1582c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1583c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
1584c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct timeval stopTime;
1585c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	gettimeofday(&stopTime, 0);
1586c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	long int ms;
1587c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (startTime.tv_usec > stopTime.tv_usec)
1588c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000);
1589c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	else
1590c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ms = (stopTime.tv_sec - startTime.tv_sec    ) * 1000 + (stopTime.tv_usec/1000        - startTime.tv_usec/1000);
1591c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1592c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" trans_context input='%s' output='%s in %ld ms'\n", incon, *rcon, ms);
1593c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
1594c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return 0;
1595c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
1596c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1597c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothint
1598c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothuntrans_context(const security_context_t incon, security_context_t *rcon) {
1599c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *raw = NULL;
1600c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	*rcon = NULL;
1601c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1602c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
1603c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct timeval startTime;
1604c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	gettimeofday(&startTime, 0);
1605c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
1606c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1607c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" untrans_context incon = %s\n", incon);
1608c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	char *range = extract_range(incon);
1609c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (!range) return -1;
1610c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" untrans_context range = %s\n", range);
1611c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1612c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	domain_t *domain = domains;
1613c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	for (;domain; domain = domain->next) {
1614c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		raw = find_in_hashtable(range, domain, domain->trans_to_raw);
1615c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (raw) break;
1616c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1617c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		/* try split and translate */
1618c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		char *lrange = NULL, *urange = NULL;
1619c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		char *lraw = NULL, *uraw = NULL;
1620c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		char *dashp = strchr(range,'-');
1621c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (dashp) {
1622c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*dashp = 0;
1623c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			lrange = range;
1624c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			urange = dashp+1;
1625c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		} else {
1626c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			raw = compute_raw_from_trans(range, domain);
1627c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (raw) {
1628c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				char *canonical = find_in_hashtable(raw, domain, domain->raw_to_trans);
1629c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (!canonical) {
1630c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					canonical = compute_trans_from_raw(raw, domain);
1631c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (canonical && strcmp(canonical, range))
16327e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						if (add_cache(domain, raw, canonical) < 0)
16337e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							return -1;
1634c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1635c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (canonical)
1636c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					free(canonical);
16377e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence				if (add_cache(domain, raw, range) < 0)
16387e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					return -1;
1639c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			} else {
1640c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				log_debug("untrans_context unable to compute raw context %s\n", range);
1641c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1642c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1643c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1644c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (lrange && urange) {
1645c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			lraw = find_in_hashtable(lrange, domain, domain->trans_to_raw);
1646c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (! lraw) {
1647c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				lraw = compute_raw_from_trans(lrange, domain);
1648c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (lraw) {
1649c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					char *canonical = find_in_hashtable(lraw, domain, domain->raw_to_trans);
1650c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (!canonical) {
1651c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						canonical = compute_trans_from_raw(lraw, domain);
1652c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						if (canonical)
16537e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							if (add_cache(domain, lraw, canonical) < 0)
16547e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence								return -1;
1655c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1656c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (canonical)
1657c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						free(canonical);
16587e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					if (add_cache(domain, lraw, lrange) < 0)
16597e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						return -1;
1660c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				} else {
1661c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					lraw = strdup(lrange);
1662c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (! lraw) {
1663c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						log_error("strdup failed %s", strerror(errno));
16647e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						return -1;
1665c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1666c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1667c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1668c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1669c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			uraw = find_in_hashtable(urange, domain, domain->trans_to_raw);
1670c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (! uraw) {
1671c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				uraw = compute_raw_from_trans(urange, domain);
1672c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (uraw) {
1673c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					char *canonical = find_in_hashtable(uraw, domain, domain->raw_to_trans);
1674c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (!canonical) {
1675c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						canonical = compute_trans_from_raw(uraw, domain);
1676c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						if (canonical)
16777e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							if (add_cache(domain, uraw, canonical) < 0)
16787e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence								return -1;
16797e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence							}
1680c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (canonical)
1681c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						free(canonical);
16827e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					if (add_cache(domain, uraw, urange) < 0)
16837e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						return -1;
1684c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				} else {
1685c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					uraw = strdup(urange);
1686c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					if (! uraw) {
1687c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth						log_error("strdup failed %s", strerror(errno));
16887e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence						return -1;
1689c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					}
1690c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1691c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1692c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1693c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1694c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			if (strcmp(lraw, uraw) == 0) {
1695c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (asprintf(&raw, "%s", lraw) < 0) {
1696c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					log_error("asprintf failed %s", strerror(errno));
16977e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					return -1;
1698c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1699c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			} else {
1700c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				if (asprintf(&raw, "%s-%s", lraw, uraw) < 0) {
1701c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth					log_error("asprintf failed %s", strerror(errno));
17027e0f0124743d241354afa888f3bfe23355679bc9Steve Lawrence					return -1;
1703c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth				}
1704c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			}
1705c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(lraw);
1706c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			free(uraw);
1707c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*dashp = '-';
1708c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			break;
1709c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		}
1710c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		if (dashp)
1711c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth			*dashp = '-';
1712c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1713c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1714c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (raw) {
1715c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		*rcon = new_context_str(incon, raw);
1716c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		free(raw);
1717c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	} else {
1718c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		*rcon = new_context_str(incon, range);
1719c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1720c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	free(range);
1721c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1722c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#ifdef DEBUG
1723c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	struct timeval stopTime;
1724c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	gettimeofday(&stopTime, 0);
1725c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	long int ms;
1726c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	if (startTime.tv_usec > stopTime.tv_usec)
1727c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000);
1728c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	else
1729c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		ms = (stopTime.tv_sec - startTime.tv_sec    ) * 1000 + (stopTime.tv_usec/1000        - startTime.tv_usec/1000);
1730c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1731c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	log_debug(" untrans_context input='%s' output='%s' n %ld ms\n", incon, *rcon, ms);
1732c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth#endif
1733c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	return 0;
1734c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
1735c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1736c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothvoid
1737c89625db93f63f29a57451e692ae33ab24d49291Xavier Tothfinish_context_translations(void) {
1738c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while(domains) {
1739c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		domain_t *next = domains->next;
1740c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		destroy_domain(domains);
1741c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		domains = next;
1742c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1743c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while(sens_constraints) {
1744c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		sens_constraint_t *next = sens_constraints->next;
1745c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		destroy_sens_constraint(&sens_constraints, sens_constraints);
1746c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		sens_constraints = next;
1747c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1748c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	while(cat_constraints) {
1749c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		cat_constraint_t *next = cat_constraints->next;
1750c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		destroy_cat_constraint(&cat_constraints, cat_constraints);
1751c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth		cat_constraints = next;
1752c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth	}
1753c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth}
1754c89625db93f63f29a57451e692ae33ab24d49291Xavier Toth
1755