This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / kernel / ckrm / rbce / token.c
1 /* Tokens for Rule-based Classification Engine (RBCE) and
2  * Consolidated RBCE module code (combined)
3  *
4  * Copyright (C) Hubertus Franke, IBM Corp. 2003
5  *           (C) Chandra Seetharaman, IBM Corp. 2003
6  *           (C) Vivek Kashyap, IBM Corp. 2004 
7  * 
8  * Latest version, more details at http://ckrm.sf.net
9  * 
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it would be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  * 
19  *
20  */
21
22 #include <linux/parser.h>
23 #include <linux/ctype.h>
24
25 enum rule_token_t {
26         TOKEN_PATH,
27         TOKEN_CMD,
28         TOKEN_ARGS,
29         TOKEN_RUID_EQ,
30         TOKEN_RUID_LT,
31         TOKEN_RUID_GT,
32         TOKEN_RUID_NOT,
33         TOKEN_RGID_EQ,
34         TOKEN_RGID_LT,
35         TOKEN_RGID_GT,
36         TOKEN_RGID_NOT,
37         TOKEN_EUID_EQ,
38         TOKEN_EUID_LT,
39         TOKEN_EUID_GT,
40         TOKEN_EUID_NOT,
41         TOKEN_EGID_EQ,
42         TOKEN_EGID_LT,
43         TOKEN_EGID_GT,
44         TOKEN_EGID_NOT,
45         TOKEN_XID_EQ,
46         TOKEN_XID_LT,
47         TOKEN_XID_GT,
48         TOKEN_XID_NOT,
49         TOKEN_TAG,
50         TOKEN_IPV4,
51         TOKEN_IPV6,
52         TOKEN_DEP,
53         TOKEN_DEP_ADD,
54         TOKEN_DEP_DEL,
55         TOKEN_ORDER,
56         TOKEN_CLASS,
57         TOKEN_STATE,
58         TOKEN_INVALID
59 };
60
61 int token_to_ruleop[TOKEN_INVALID + 1] = {
62         [TOKEN_PATH] = RBCE_RULE_CMD_PATH,
63         [TOKEN_CMD] = RBCE_RULE_CMD,
64         [TOKEN_ARGS] = RBCE_RULE_ARGS,
65         [TOKEN_RUID_EQ] = RBCE_RULE_REAL_UID,
66         [TOKEN_RUID_LT] = RBCE_RULE_REAL_UID,
67         [TOKEN_RUID_GT] = RBCE_RULE_REAL_UID,
68         [TOKEN_RUID_NOT] = RBCE_RULE_REAL_UID,
69         [TOKEN_RGID_EQ] = RBCE_RULE_REAL_GID,
70         [TOKEN_RGID_LT] = RBCE_RULE_REAL_GID,
71         [TOKEN_RGID_GT] = RBCE_RULE_REAL_GID,
72         [TOKEN_RGID_NOT] = RBCE_RULE_REAL_GID,
73         [TOKEN_EUID_EQ] = RBCE_RULE_EFFECTIVE_UID,
74         [TOKEN_EUID_LT] = RBCE_RULE_EFFECTIVE_UID,
75         [TOKEN_EUID_GT] = RBCE_RULE_EFFECTIVE_UID,
76         [TOKEN_EUID_NOT] = RBCE_RULE_EFFECTIVE_UID,
77         [TOKEN_EGID_EQ] = RBCE_RULE_EFFECTIVE_GID,
78         [TOKEN_EGID_LT] = RBCE_RULE_EFFECTIVE_GID,
79         [TOKEN_EGID_GT] = RBCE_RULE_EFFECTIVE_GID,
80         [TOKEN_EGID_NOT] = RBCE_RULE_EFFECTIVE_GID,
81         [TOKEN_XID_EQ]  = RBCE_RULE_XID,
82         [TOKEN_XID_LT]  = RBCE_RULE_XID,
83         [TOKEN_XID_GT]  = RBCE_RULE_XID,
84         [TOKEN_XID_NOT] = RBCE_RULE_XID,
85         [TOKEN_TAG] = RBCE_RULE_APP_TAG,
86         [TOKEN_IPV4] = RBCE_RULE_IPV4,
87         [TOKEN_IPV6] = RBCE_RULE_IPV6,
88         [TOKEN_DEP] = RBCE_RULE_DEP_RULE,
89         [TOKEN_DEP_ADD] = RBCE_RULE_DEP_RULE,
90         [TOKEN_DEP_DEL] = RBCE_RULE_DEP_RULE,
91         [TOKEN_ORDER] = RBCE_RULE_INVALID,
92         [TOKEN_CLASS] = RBCE_RULE_INVALID,
93         [TOKEN_STATE] = RBCE_RULE_INVALID,
94 };
95
96 enum op_token {
97         TOKEN_OP_EQUAL = RBCE_EQUAL,
98         TOKEN_OP_NOT = RBCE_NOT,
99         TOKEN_OP_LESS_THAN = RBCE_LESS_THAN,
100         TOKEN_OP_GREATER_THAN = RBCE_GREATER_THAN,
101         TOKEN_OP_DEP,
102         TOKEN_OP_DEP_ADD,
103         TOKEN_OP_DEP_DEL,
104         TOKEN_OP_ORDER,
105         TOKEN_OP_CLASS,
106         TOKEN_OP_STATE,
107 };
108
109 enum op_token token_to_operator[TOKEN_INVALID + 1] = {
110         [TOKEN_PATH] = TOKEN_OP_EQUAL,
111         [TOKEN_CMD] = TOKEN_OP_EQUAL,
112         [TOKEN_ARGS] = TOKEN_OP_EQUAL,
113         [TOKEN_RUID_EQ] = TOKEN_OP_EQUAL,
114         [TOKEN_RUID_LT] = TOKEN_OP_LESS_THAN,
115         [TOKEN_RUID_GT] = TOKEN_OP_GREATER_THAN,
116         [TOKEN_RUID_NOT] = TOKEN_OP_NOT,
117         [TOKEN_RGID_EQ] = TOKEN_OP_EQUAL,
118         [TOKEN_RGID_LT] = TOKEN_OP_LESS_THAN,
119         [TOKEN_RGID_GT] = TOKEN_OP_GREATER_THAN,
120         [TOKEN_RGID_NOT] = TOKEN_OP_NOT,
121         [TOKEN_EUID_EQ] = TOKEN_OP_EQUAL,
122         [TOKEN_EUID_LT] = TOKEN_OP_LESS_THAN,
123         [TOKEN_EUID_GT] = TOKEN_OP_GREATER_THAN,
124         [TOKEN_EUID_NOT] = TOKEN_OP_NOT,
125         [TOKEN_EGID_EQ] = TOKEN_OP_EQUAL,
126         [TOKEN_EGID_LT] = TOKEN_OP_LESS_THAN,
127         [TOKEN_EGID_GT] = TOKEN_OP_GREATER_THAN,
128         [TOKEN_EGID_NOT] = TOKEN_OP_NOT,
129         [TOKEN_XID_EQ]  = TOKEN_OP_EQUAL,
130         [TOKEN_XID_LT]  = TOKEN_OP_LESS_THAN,
131         [TOKEN_XID_GT]  = TOKEN_OP_GREATER_THAN,
132         [TOKEN_XID_NOT] = TOKEN_OP_NOT,
133         [TOKEN_TAG] = TOKEN_OP_EQUAL,
134         [TOKEN_IPV4] = TOKEN_OP_EQUAL,
135         [TOKEN_IPV6] = TOKEN_OP_EQUAL,
136         [TOKEN_DEP] = TOKEN_OP_DEP,
137         [TOKEN_DEP_ADD] = TOKEN_OP_DEP_ADD,
138         [TOKEN_DEP_DEL] = TOKEN_OP_DEP_DEL,
139         [TOKEN_ORDER] = TOKEN_OP_ORDER,
140         [TOKEN_CLASS] = TOKEN_OP_CLASS,
141         [TOKEN_STATE] = TOKEN_OP_STATE
142 };
143
144 static match_table_t tokens = {
145         {TOKEN_PATH, "path=%s"},
146         {TOKEN_CMD, "cmd=%s"},
147         {TOKEN_ARGS, "args=%s"},
148         {TOKEN_RUID_EQ, "uid=%d"},
149         {TOKEN_RUID_LT, "uid<%d"},
150         {TOKEN_RUID_GT, "uid>%d"},
151         {TOKEN_RUID_NOT, "uid!%d"},
152         {TOKEN_RGID_EQ, "gid=%d"},
153         {TOKEN_RGID_LT, "gid<%d"},
154         {TOKEN_RGID_GT, "gid>%d"},
155         {TOKEN_RGID_NOT, "gid!d"},
156         {TOKEN_EUID_EQ, "euid=%d"},
157         {TOKEN_EUID_LT, "euid<%d"},
158         {TOKEN_EUID_GT, "euid>%d"},
159         {TOKEN_EUID_NOT, "euid!%d"},
160         {TOKEN_EGID_EQ, "egid=%d"},
161         {TOKEN_EGID_LT, "egid<%d"},
162         {TOKEN_EGID_GT, "egid>%d"},
163         {TOKEN_EGID_NOT, "egid!%d"},
164         {TOKEN_XID_EQ,  "xid=%d"},
165         {TOKEN_XID_LT,  "xid<%d"},
166         {TOKEN_XID_GT,  "xid>%d"},
167         {TOKEN_XID_NOT, "xid!%d"},
168         {TOKEN_TAG, "tag=%s"},
169         {TOKEN_IPV4, "ipv4=%s"},
170         {TOKEN_IPV6, "ipv6=%s"},
171         {TOKEN_DEP, "depend=%s"},
172         {TOKEN_DEP_ADD, "+depend=%s"},
173         {TOKEN_DEP_DEL, "-depend=%s"},
174         {TOKEN_ORDER, "order=%d"},
175         {TOKEN_CLASS, "class=%s"},
176         {TOKEN_STATE, "state=%d"},
177         {TOKEN_INVALID, NULL}
178 };
179
180 /*
181  * return -EINVAL in case of failures
182  * returns number of terms in terms on success.
183  * never returns 0.
184  */
185
186 static int
187 rules_parse(char *rule_defn, struct rbce_rule_term **rterms, int *term_mask)
188 {
189         char *p, *rp = rule_defn;
190         int option, i = 0, nterms;
191         struct rbce_rule_term *terms;
192
193         *rterms = NULL;
194         *term_mask = 0;
195         if (!rule_defn)
196                 return -EINVAL;
197
198         nterms = 0;
199         while (*rp++) {
200                 if (*rp == '>' || *rp == '<' || *rp == '=' || *rp == '!') {
201                         nterms++;
202                 }
203         }
204
205         if (!nterms) {
206                 return -EINVAL;
207         }
208
209         terms = kmalloc(nterms * sizeof(struct rbce_rule_term), GFP_KERNEL);
210         if (!terms) {
211                 return -ENOMEM;
212         }
213
214         while ((p = strsep(&rule_defn, ",")) != NULL) {
215
216                 substring_t args[MAX_OPT_ARGS];
217                 int token;
218
219                 while (*p && isspace(*p))
220                         p++;
221                 if (!*p)
222                         continue;
223
224                 token = match_token(p, tokens, args);
225
226                 terms[i].op = token_to_ruleop[token];
227                 terms[i].operator = token_to_operator[token];
228                 switch (token) {
229
230                 case TOKEN_PATH:
231                 case TOKEN_CMD:
232                 case TOKEN_ARGS:
233                 case TOKEN_TAG:
234                 case TOKEN_IPV4:
235                 case TOKEN_IPV6:
236                         // all these tokens can be specified only once
237                         if (*term_mask & (1 << terms[i].op)) {
238                                 nterms = -EINVAL;
239                                 goto out;
240                         }
241                 /*FALLTHRU*/ case TOKEN_CLASS:
242                 case TOKEN_DEP:
243                 case TOKEN_DEP_ADD:
244                 case TOKEN_DEP_DEL:
245                         terms[i].u.string = args->from;
246                         break;
247
248                 case TOKEN_RUID_EQ:
249                 case TOKEN_RUID_LT:
250                 case TOKEN_RUID_GT:
251                 case TOKEN_RUID_NOT:
252                 case TOKEN_RGID_EQ:
253                 case TOKEN_RGID_LT:
254                 case TOKEN_RGID_GT:
255                 case TOKEN_RGID_NOT:
256                 case TOKEN_EUID_EQ:
257                 case TOKEN_EUID_LT:
258                 case TOKEN_EUID_GT:
259                 case TOKEN_EUID_NOT:
260                 case TOKEN_EGID_EQ:
261                 case TOKEN_EGID_LT:
262                 case TOKEN_EGID_GT:
263                 case TOKEN_EGID_NOT:
264                 case TOKEN_XID_EQ:
265                 case TOKEN_XID_LT:
266                 case TOKEN_XID_GT:
267                 case TOKEN_XID_NOT:
268                         // all these tokens can be specified only once
269                         if (*term_mask & (1 << terms[i].op)) {
270                                 nterms = -EINVAL;
271                                 goto out;
272                         }
273                 /*FALLTHRU*/ case TOKEN_ORDER:
274                 case TOKEN_STATE:
275                         if (match_int(args, &option)) {
276                                 nterms = -EINVAL;
277                                 goto out;
278                         }
279                         terms[i].u.id = option;
280                         break;
281                 default:
282                         nterms = -EINVAL;
283                         goto out;
284                 }
285                 *term_mask |= (1 << terms[i].op);
286                 i++;
287         }
288         *rterms = terms;
289
290       out:
291         if (nterms < 0) {
292                 kfree(terms);
293                 *term_mask = 0;
294         }                       /* else {
295                                    for (i = 0; i < nterms; i++) {
296                                    printk("token: i %d; op %d, operator %d, str %ld\n",
297                                    i, terms[i].op, terms[i].operator, terms[i].u.id);
298                                    }
299                                    } */
300         return nterms;
301 }