--
Content-Disposition: inline; filename=09-02-rbce_fs-main

Part 2 of 5 patches to support Rule Based Classification Engine for CKRM.
This patch provides the functionality needed by the rcfs interface for
ce provided in patch 1. No classification functionality yet.

Signed-Off-By: Hubertus Franke <[EMAIL PROTECTED]>
Signed-Off-By: Chandra Seetharaman <[EMAIL PROTECTED]>
Signed-Off-By: Shailabh Nagar <[EMAIL PROTECTED]>
Signed-Off-By: Vivek Kashyap <[EMAIL PROTECTED]>
Signed-Off-By: Gerrit Huizenga <[EMAIL PROTECTED]>

 Makefile        |    2 
 rbce_internal.h |  161 +++++++++
 rbce_main.c     |  993 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 rbce_token.c    |  241 +++++++++++++
 4 files changed, 1383 insertions(+), 14 deletions(-)

Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/Makefile
===================================================================
--- linux-2.6.12-rc3-ckrm5.orig/kernel/ckrm/rbce/Makefile       2005-05-05 
09:38:01.000000000 -0700
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/Makefile    2005-05-05 
09:38:03.000000000 -0700
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_CKRM_RBCE)        += rbce.o
-rbce-objs := rbce_fs.o rbce_main.o
+rbce-objs := rbce_fs.o rbce_main.o rbce_token.o
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_internal.h
===================================================================
--- linux-2.6.12-rc3-ckrm5.orig/kernel/ckrm/rbce/rbce_internal.h        
2005-05-05 09:38:01.000000000 -0700
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_internal.h     2005-05-05 
09:38:03.000000000 -0700
@@ -41,8 +41,165 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-extern int rbce_enabled;
+/*
+ * comman data structure used for identification of class and rules
+ * in the RBCE namespace
+ */
+struct named_obj_hdr {
+       struct list_head link;
+       int referenced;
+       char *name;
+};
+
+#define GET_REF(x) ((x)->obj.referenced)
+#define INC_REF(x) (GET_REF(x)++)
+#define DEC_REF(x) (--GET_REF(x))
+
+struct rbce_class {
+       struct named_obj_hdr obj;
+       int classtype;
+       void *classobj;
+};
+
+typedef int __bitwise rbce_rule_op_t;
+enum rbce_rule_op {
+       RBCE_RULE_CMD_PATH = (__force rbce_rule_op_t) 1,
+       RBCE_RULE_CMD = (__force rbce_rule_op_t) 2,
+       RBCE_RULE_ARGS = (__force rbce_rule_op_t) 3,
+       RBCE_RULE_REAL_UID = (__force rbce_rule_op_t) 4,
+       RBCE_RULE_REAL_GID = (__force rbce_rule_op_t) 5,
+       RBCE_RULE_EFFECTIVE_UID = (__force rbce_rule_op_t) 6,
+       RBCE_RULE_EFFECTIVE_GID = (__force rbce_rule_op_t) 7,
+       RBCE_RULE_APP_TAG = (__force rbce_rule_op_t) 8,
+       RBCE_RULE_IPV4 = (__force rbce_rule_op_t) 9,
+       RBCE_RULE_IPV6 = (__force rbce_rule_op_t) 10,
+       RBCE_RULE_DEP_RULE = (__force rbce_rule_op_t) 11,
+       RBCE_RULE_INVALID = (__force rbce_rule_op_t) 12,
+       RBCE_RULE_INVALID2 = (__force rbce_rule_op_t) 13,
+};
+
+typedef int __bitwise rbce_operator_t;
+enum rbce_operator {
+       RBCE_EQUAL = (__force rbce_operator_t) 1,
+       RBCE_NOT = (__force rbce_operator_t) 2,
+       RBCE_LESS_THAN = (__force rbce_operator_t) 3,
+       RBCE_GREATER_THAN = (__force rbce_operator_t) 4,
+};
+
+struct rbce_rule_term {
+       rbce_rule_op_t op;
+       rbce_operator_t operator;
+       union {
+               char *string;   /* path, cmd, arg, tag, ipv4 and ipv6 */
+               long id;        /* uid, gid, euid, egid */
+               struct rbce_rule *deprule;
+       } u;
+};
+
+struct rbce_rule {
+       struct named_obj_hdr obj;
+       struct rbce_class *target_class;
+       int classtype;
+       int num_terms;
+       int *terms;     /* vector of indices into the global term vector */
+       int index;      /* index of this rule into the global term vector */
+       int termflag;   /* which term ids would require a recalculation */
+       int do_opt;     /* do we have to consider this rule during optimize */
+       char *strtab;   /* string table to store the strings of all terms */
+       int order;      /* order of execution of this rule */
+       int state;      /* RBCE_RULE_ENABLED/RBCE_RULE_DISABLED */
+};
+
+/* rules states */
+#define RBCE_RULE_DISABLED 0
+#define RBCE_RULE_ENABLED  1
+
+/*
+ * Data structures and macros used for optimization
+ */
+#define RBCE_TERM_CMD   (0)
+#define RBCE_TERM_UID   (1)
+#define RBCE_TERM_GID   (2)
+#define RBCE_TERM_TAG   (3)
+#define RBCE_TERM_IPV4  (4)
+#define RBCE_TERM_IPV6  (5)
+
+#define NUM_TERM_MASK_VECTOR  (6)
+
+/* Rule flags. 1 bit for each type of rule term */
+#define RBCE_TERMFLAG_CMD   (1 << RBCE_TERM_CMD)
+#define RBCE_TERMFLAG_UID   (1 << RBCE_TERM_UID)
+#define RBCE_TERMFLAG_GID   (1 << RBCE_TERM_GID)
+#define RBCE_TERMFLAG_TAG   (1 << RBCE_TERM_TAG)
+#define RBCE_TERMFLAG_IPV4  (1 << RBCE_TERM_IPV4)
+#define RBCE_TERMFLAG_IPV6  (1 << RBCE_TERM_IPV6)
+#define RBCE_TERMFLAG_ALL      (RBCE_TERMFLAG_CMD | RBCE_TERMFLAG_UID |        
\
+                               RBCE_TERMFLAG_GID | RBCE_TERMFLAG_TAG | \
+                               RBCE_TERMFLAG_IPV4 | RBCE_TERMFLAG_IPV6)
+
+/* Token operation related data structures, functions etc., */
+typedef int __bitwise rule_token_t;
+enum rule_token {
+       TOKEN_PATH = (__force rule_token_t) 1,
+       TOKEN_CMD = (__force rule_token_t) 2,
+       TOKEN_ARGS = (__force rule_token_t) 3,
+       TOKEN_RUID_EQ = (__force rule_token_t) 4,
+       TOKEN_RUID_LT = (__force rule_token_t) 5,
+       TOKEN_RUID_GT = (__force rule_token_t) 6,
+       TOKEN_RUID_NOT = (__force rule_token_t) 7,
+       TOKEN_RGID_EQ = (__force rule_token_t) 8,
+       TOKEN_RGID_LT = (__force rule_token_t) 9,
+       TOKEN_RGID_GT = (__force rule_token_t) 10,
+       TOKEN_RGID_NOT = (__force rule_token_t) 11,
+       TOKEN_EUID_EQ = (__force rule_token_t) 12,
+       TOKEN_EUID_LT = (__force rule_token_t) 13,
+       TOKEN_EUID_GT = (__force rule_token_t) 14,
+       TOKEN_EUID_NOT = (__force rule_token_t) 15,
+       TOKEN_EGID_EQ = (__force rule_token_t) 16,
+       TOKEN_EGID_LT = (__force rule_token_t) 17,
+       TOKEN_EGID_GT = (__force rule_token_t) 18,
+       TOKEN_EGID_NOT = (__force rule_token_t) 19,
+       TOKEN_TAG = (__force rule_token_t) 20,
+       TOKEN_IPV4 = (__force rule_token_t) 21,
+       TOKEN_IPV6 = (__force rule_token_t) 22,
+       TOKEN_DEP = (__force rule_token_t) 23,
+       TOKEN_DEP_ADD = (__force rule_token_t) 24,
+       TOKEN_DEP_DEL = (__force rule_token_t) 25,
+       TOKEN_ORDER = (__force rule_token_t) 26,
+       TOKEN_CLASS = (__force rule_token_t) 27,
+       TOKEN_STATE = (__force rule_token_t) 28,
+       TOKEN_INVALID = (__force rule_token_t) 29
+};
+
+typedef int __bitwise op_token_t;
+enum op_token {
+       TOKEN_OP_EQUAL = (__force op_token_t) RBCE_EQUAL,
+       TOKEN_OP_NOT = (__force op_token_t) RBCE_NOT,
+       TOKEN_OP_LESS_THAN = (__force op_token_t) RBCE_LESS_THAN,
+       TOKEN_OP_GREATER_THAN = (__force op_token_t) RBCE_GREATER_THAN,
+       TOKEN_OP_DEP = (__force op_token_t) (TOKEN_OP_GREATER_THAN+1),
+       TOKEN_OP_DEP_ADD = (__force op_token_t) (TOKEN_OP_GREATER_THAN+2),
+       TOKEN_OP_DEP_DEL = (__force op_token_t) (TOKEN_OP_GREATER_THAN+3),
+       TOKEN_OP_ORDER = (__force op_token_t) (TOKEN_OP_GREATER_THAN+4),
+       TOKEN_OP_CLASS = (__force op_token_t) (TOKEN_OP_GREATER_THAN+5),
+       TOKEN_OP_STATE = (__force op_token_t) (TOKEN_OP_GREATER_THAN+6),
+};
+
+
+/*
+ * data structure rbce_private_data to hold the app_tag for a task.
+ * Expands later.
+ *
+ */
+struct rbce_private_data {
+       char *app_tag;
+};
+
+#define RBCE_DATA(tsk) ((struct rbce_private_data*)((tsk)->ce_data))
+#define RBCE_DATAP(tsk) ((tsk)->ce_data)
+
 extern struct rbce_eng_callback rbce_rcfs_ecbs;
+extern int rbce_enabled;
 
 extern int rbce_mkdir(struct inode *, struct dentry *, int);
 extern int rbce_rmdir(struct inode *, struct dentry *);
@@ -56,4 +213,6 @@ extern int rbce_delete_rule(const char *
 extern int rbce_set_tasktag(int, char *);
 extern int rbce_rename_rule(const char *, const char *);
 
+extern int rules_parse(char *, struct rbce_rule_term **, int *);
+
 #endif /* _RBCE_INTERNAL_H */
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_main.c
===================================================================
--- linux-2.6.12-rc3-ckrm5.orig/kernel/ckrm/rbce/rbce_main.c    2005-05-05 
09:38:01.000000000 -0700
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_main.c 2005-05-05 
09:38:03.000000000 -0700
@@ -30,32 +30,1001 @@ MODULE_LICENSE("GPL");
 
 static char modname[] = RBCE_MOD_NAME;
 
-/* Stub routines for now */
-void rbce_get_rule(const char *a, char *b)
+/* ==================== global variables etc., ==================== */
+
+int termop_2_vecidx[RBCE_RULE_INVALID] = {
+       [RBCE_RULE_CMD_PATH] = RBCE_TERM_CMD,
+       [RBCE_RULE_CMD] = RBCE_TERM_CMD,
+       [RBCE_RULE_ARGS] = RBCE_TERM_CMD,
+       [RBCE_RULE_REAL_UID] = RBCE_TERM_UID,
+       [RBCE_RULE_REAL_GID] = RBCE_TERM_GID,
+       [RBCE_RULE_EFFECTIVE_UID] = RBCE_TERM_UID,
+       [RBCE_RULE_EFFECTIVE_GID] = RBCE_TERM_GID,
+       [RBCE_RULE_APP_TAG] = RBCE_TERM_TAG,
+       [RBCE_RULE_IPV4] = RBCE_TERM_IPV4,
+       [RBCE_RULE_IPV6] = RBCE_TERM_IPV6,
+       [RBCE_RULE_DEP_RULE] = -1
+};
+
+#define TERMOP_2_TERMFLAG(x)   (1 << termop_2_vecidx[x])
+#define TERM_2_TERMFLAG(x)             (1 << x)
+
+#define POLICY_INC_NUMTERMS    (BITS_PER_LONG) /* No. of terms alloc'd once */
+#define POLICY_ACTION_NEW_VERSION      0x01    /* Force reallocation */
+#define POLICY_ACTION_REDO_ALL         0x02    /* Recompute all rule flags */
+#define POLICY_ACTION_PACK_TERMS       0x04    /* Time to pack the terms */
+
+extern int errno;
+
+int rbce_enabled = 1;
+
+static LIST_HEAD(class_list);
+static struct list_head rules_list[CKRM_MAX_CLASSTYPES];
+static int gl_num_rules;
+static int gl_action, gl_num_terms;
+static int gl_allocated, gl_released;
+static struct rbce_rule_term *gl_terms;
+static int gl_rules_version;
+static rwlock_t rbce_rwlock = RW_LOCK_UNLOCKED;
+       /*
+        * One lock to protect them all !!!
+        * Additions, deletions to rules must
+        * happen with this lock being held in write mode.
+        * Access(read/write) to any of the data structures must happen
+        * with this lock held in read mode.
+        * Since, rule related changes do not happen very often it is ok to
+        * have single rwlock.
+        */
+
+/* ======================= Helper Functions ========================= */
+
+static inline struct rbce_rule *find_rule_name(const char *name)
+{
+       struct named_obj_hdr *pos;
+       int i;
+
+       for (i = 0; i < CKRM_MAX_CLASSTYPES; i++)
+               list_for_each_entry(pos, &rules_list[i], link)
+                       if (!strcmp(pos->name, name))
+                               return ((struct rbce_rule *)pos);
+       return NULL;
+}
+
+struct rbce_class *find_class_name(const char *name)
 {
+       struct named_obj_hdr *pos;
+
+       list_for_each_entry(pos, &class_list, link)
+               if (!strcmp(pos->name, name))
+                       return (struct rbce_class *)pos;
+       return NULL;
 }
-int rbce_rule_exists(const char *a)
+
+/* Type of Rule insertion */
+#define INSERT         0       /* new rule */
+#define REINSERT       1       /* existing rule */
+
+/*
+ * Insert the given rule at the specified order
+ *             order = -1 ==> insert at the tail.
+ *             type == INSERT - insert the rule
+ *             type == REINSERT - remove the rule from its current
+ *                              position and reinsert accoring to order.
+ *
+ * Caller must hold rbce_rwlock in write mode.
+ */
+static int insert_rule(struct rbce_rule *rule, int order, int type)
 {
+#define ORDER_COUNTER_INCR 10
+       static int order_counter;
+       int old_counter;
+       struct list_head *head = &rules_list[rule->classtype];
+       struct list_head *insert = head;
+       struct rbce_rule *tmp;
+
+       if (gl_num_rules == 0)
+               order_counter = 0;
+
+       switch (order) {
+       case -1:
+               rule->order = order_counter;
+               /* FIXME: order_counter overflow/wraparound!! */
+               order_counter += ORDER_COUNTER_INCR;
+               break;
+       default:
+               old_counter = order_counter;
+               if (order_counter < order)
+                       order_counter = order;
+               rule->order = order;
+               order_counter += ORDER_COUNTER_INCR;
+               list_for_each_entry(tmp, head, obj.link) {
+                       if (rule == tmp)
+                               continue;
+                       if (rule->order == tmp->order) {
+                               order_counter = old_counter;
+                               return -EEXIST;
+                       }
+                       if (rule->order < tmp->order) {
+                               insert = &tmp->obj.link;
+                               break;
+                       }
+               }
+       }
+       if (type == REINSERT)
+               list_del(&rule->obj.link);
+       else {
+               /*  protect the module from removed if a rule exists */
+               try_module_get(THIS_MODULE);
+               gl_num_rules++;
+       }
+       gl_rules_version++;
+       list_add_tail(&rule->obj.link, insert);
        return 0;
 }
-int rbce_change_rule(const char *a, char *b)
+
+/*
+ * Get a refernece to the class, create one if it doesn't exist
+ *
+ * Caller need to hold rbce_rwlock in write mode.
+ */
+
+struct rbce_class *create_rbce_class(const char *classname,
+                                           int classtype, void *classobj)
 {
-       return 1;
+       struct rbce_class *cls;
+
+       if (classtype >= CKRM_MAX_CLASSTYPES) {
+               printk(KERN_ERR
+                      "ckrm_classobj returned %d as classtype which cannot "
+                      " be handled by RBCE\n", classtype);
+               return NULL;
+       }
+
+       cls = kmalloc(sizeof(struct rbce_class), GFP_ATOMIC);
+       if (!cls)
+               return NULL;
+       cls->obj.name = kmalloc(strlen(classname) + 1, GFP_ATOMIC);
+       if (cls->obj.name) {
+               GET_REF(cls) = 1;
+               cls->classobj = classobj;
+               strcpy(cls->obj.name, classname);
+               list_add_tail(&cls->obj.link, &class_list);
+               cls->classtype = classtype;
+       } else {
+               kfree(cls);
+               cls = NULL;
+       }
+       return cls;
 }
-int rbce_delete_rule(const char *a)
+
+static struct rbce_class *get_class(char *classname, int *classtype)
 {
-       return 1;
+       struct rbce_class *cls;
+       void *classobj;
+
+       if (!classname)
+               return NULL;
+       cls = find_class_name(classname);
+       if (cls) {
+               if (cls->classobj) {
+                       INC_REF(cls);
+                       *classtype = cls->classtype;
+                       return cls;
+               }
+               return NULL;
+       }
+       classobj = ckrm_classobj(classname, classtype);
+       if (!classobj)
+               return NULL;
+       return create_rbce_class(classname, *classtype, classobj);
 }
-int rbce_set_tasktag(int i, char *a)
+
+/*
+ * Drop a refernece to the class, create one if it doesn't exist
+ *
+ * Caller need to hold rbce_rwlock in write mode.
+ */
+void put_class(struct rbce_class *cls)
 {
-       return 1;
+       if (cls && (DEC_REF(cls) <= 0)) {
+               list_del(&cls->obj.link);
+               kfree(cls->obj.name);
+               kfree(cls);
+       }
+       return;
 }
-int rbce_rename_rule(const char *a, const char *b)
+
+/*
+ * Allocate an index in the global term vector
+ * On success, returns the index. On failure returns -errno.
+ * Caller must hold the rbce_rwlock in write mode as global data is
+ * written onto.
+ */
+static int alloc_term_index(void)
 {
-       return 1;
+       int size = gl_allocated;
+
+       if (gl_num_terms >= size) {
+               int i;
+               struct rbce_rule_term *oldv, *newv;
+               int newsize = size + POLICY_INC_NUMTERMS;
+
+               oldv = gl_terms;
+               newv =
+                   kmalloc(newsize * sizeof(struct rbce_rule_term),
+                           GFP_ATOMIC);
+               if (!newv)
+                       return -ENOMEM;
+               memcpy(newv, oldv, size * sizeof(struct rbce_rule_term));
+               for (i = size; i < newsize; i++)
+                       newv[i].op = -1;
+               gl_terms = newv;
+               gl_allocated = newsize;
+               kfree(oldv);
+
+               gl_action |= POLICY_ACTION_NEW_VERSION;
+       }
+       return gl_num_terms++;
+}
+
+/*
+ * Release an index in the global term vector
+ *
+ * Caller must hold the rbce_rwlock in write mode as the global data
+ * is written onto.
+ */
+static void release_term_index(int idx)
+{
+       if ((idx < 0) || (idx > gl_num_terms))
+               return;
+
+       gl_terms[idx].op = -1;
+       gl_released++;
+       if ((gl_released > POLICY_INC_NUMTERMS) &&
+           (gl_allocated >
+            (gl_num_terms - gl_released + POLICY_INC_NUMTERMS))) {
+               gl_action |= POLICY_ACTION_PACK_TERMS;
+       }
+       return;
+}
+
+/*
+ * Release the indices, string memory, and terms associated with the given
+ * rule.
+ *
+ * Caller should be holding rbce_rwlock
+ */
+static void __release_rule(struct rbce_rule *rule)
+{
+       int i, *terms = rule->terms;
+
+       /* remove memory and references from other rules */
+       for (i = rule->num_terms; --i >= 0;) {
+               struct rbce_rule_term *term = &gl_terms[terms[i]];
+
+               if (term->op == RBCE_RULE_DEP_RULE)
+                       DEC_REF(term->u.deprule);
+               release_term_index(terms[i]);
+       }
+       rule->num_terms = 0;
+       if (rule->strtab) {
+               kfree(rule->strtab);
+               rule->strtab = NULL;
+       }
+       if (rule->terms) {
+               kfree(rule->terms);
+               rule->terms = NULL;
+       }
+       return;
+}
+
+/*
+ * delete the given rule and all memory associated with it.
+ *
+ * Caller is responsible for protecting the global data
+ */
+static inline int __delete_rule(struct rbce_rule *rule)
+{
+       /* make sure we are not referenced by other rules */
+       if (GET_REF(rule))
+               return -EBUSY;
+       __release_rule(rule);
+       put_class(rule->target_class);
+       release_term_index(rule->index);
+       list_del(&rule->obj.link);
+       gl_num_rules--;
+       gl_rules_version++;
+       module_put(THIS_MODULE);
+       kfree(rule->obj.name);
+       kfree(rule);
+       return 0;
+}
+
+/* ======================= Rule related Functions ========================= */
+
+/*
+ * This function takes terms as input and digests the valid rbce terms
+ * and fills the newrule appropriately.
+ *      Valid terms have op != RBCE_RULE_INVALID
+ * This function returns the number of valid terms found.
+ * In case of error it return -errno
+ */
+static inline int
+digest_terms(struct rbce_rule *newrule,
+       struct rbce_rule_term *terms, int nterms)
+{
+       char *strtab = NULL;
+       struct rbce_rule *deprule;
+       int i, j, real_nterms = 0, strtablen = 0;
+
+       for (i = 0; i < nterms; i++) {
+               if (terms[i].op == RBCE_RULE_INVALID)
+                       continue;
+               real_nterms++;
+
+               switch (terms[i].op) {
+               case RBCE_RULE_DEP_RULE:
+                       /* check if the depend rule is valid */
+                       deprule = find_rule_name(terms[i].u.string);
+                       if (!deprule || deprule == newrule) {
+                               real_nterms = -EINVAL;
+                               goto out;
+                       } else {
+                               /* make sure _a_ depend rule */
+                               /* appears in only one term. */
+                               for (j = 0; j < i; j++) {
+                                       if (terms[j].op ==
+                                           RBCE_RULE_DEP_RULE
+                                           && terms[j].u.deprule ==
+                                           deprule) {
+                                               real_nterms = -EINVAL;
+                                               goto out;
+                                       }
+                               }
+                               terms[i].u.deprule = deprule;
+                       }
+
+                       /* +depend is acceptable and -depend is not */
+                       if (terms[i].operator != TOKEN_OP_DEP_DEL)
+                               terms[i].operator = RBCE_EQUAL;
+                       else {
+                               real_nterms = -EINVAL;
+                               goto out;
+                       }
+                       break;
+
+               case RBCE_RULE_CMD_PATH:
+               case RBCE_RULE_CMD:
+               case RBCE_RULE_ARGS:
+               case RBCE_RULE_APP_TAG:
+               case RBCE_RULE_IPV4:
+               case RBCE_RULE_IPV6:
+                       /* sum up the string length */
+                       strtablen += strlen(terms[i].u.string) + 1;
+                       break;
+               default:
+                       break;
+
+               }
+       }
+       if (strtablen) {
+               strtab = kmalloc(strtablen, GFP_ATOMIC);
+               if (!strtab)
+                       real_nterms = -ENOMEM;
+               else {
+                       if (newrule->strtab)
+                               kfree(newrule->strtab);
+                       newrule->strtab = strtab;
+               }
+       }
+out:
+       return real_nterms;
+}
+
+/*
+ * This function takes terms as input and digests the non rbce terms
+ * and fills newrule appropriately.
+ * non rbce teerms are used to get attribute/value that are not part
+ * of the rule terms.
+ *      non rbce terms have op != RBCE_RULE_INVALID
+ * This function returns 0 on success and -errno in case of error
+ */
+static inline int
+digest_nonterms(struct rbce_rule *newrule,
+       struct rbce_rule_term *terms, int nterms)
+{
+       char *class = NULL;
+       int state = -1, order = -1, rc = 0, i;
+
+       for (i = 0; i < nterms; i++) {
+               if (terms[i].op != RBCE_RULE_INVALID)
+                       continue;
+               switch (terms[i].operator) {
+               case TOKEN_OP_ORDER:
+                       order = terms[i].u.id;
+                       if (order < 0) {
+                               rc = -EINVAL;
+                               goto out;
+                       }
+                       break;
+               case TOKEN_OP_STATE:
+                       state = terms[i].u.id != 0;
+                       break;
+               case TOKEN_OP_CLASS:
+                       class = terms[i].u.string;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* Check if class was specified */
+       if (class != NULL) {
+               int classtype;
+               struct rbce_class *targetcls;
+               if ((targetcls = get_class(class, &classtype)) == NULL) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+               if (newrule->target_class)
+                       put_class(newrule->target_class);
+
+               newrule->target_class = targetcls;
+               newrule->classtype = classtype;
+       }
+       if (!newrule->target_class) {
+               rc = -EINVAL;
+               goto out;
+       }
+       if (state != -1)
+               newrule->state = state;
+       if (order != -1)
+               newrule->order = order;
+out:
+       return rc;
+}
+
+/*
+ * Allocate and fill the term vectors of the newrule from the terms array.
+ * Only handle the realy terms and ignore the nonterms.
+ */
+static inline int
+fill_term_vector(struct rbce_rule *newrule,
+       struct rbce_rule_term *terms, int real_nterms)
+{
+       int i, rc = 0, strtablen = 0, j, ii;
+       struct rbce_rule_term *term;
+
+       newrule->terms = kmalloc(real_nterms * sizeof(int), GFP_ATOMIC);
+       if (!newrule->terms) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       for (i = 0, j = 0; j < real_nterms; i++, j++) {
+               if (terms[i].op == RBCE_RULE_INVALID)
+                       continue;
+
+               newrule->terms[j] = alloc_term_index();
+               if (newrule->terms[j] < 0) {
+                       for (ii = 0; ii < j; ii++)
+                               release_term_index(newrule->terms[ii]);
+                       rc = -ENOMEM;
+                       goto out;
+               }
+               term = &gl_terms[newrule->terms[j]];
+               term->op = terms[i].op;
+               term->operator = terms[i].operator;
+               switch (terms[i].op) {
+               case RBCE_RULE_CMD_PATH:
+               case RBCE_RULE_CMD:
+               case RBCE_RULE_ARGS:
+               case RBCE_RULE_APP_TAG:
+               case RBCE_RULE_IPV4:
+               case RBCE_RULE_IPV6:
+                       term->u.string = &newrule->strtab[strtablen];
+                       strcpy(term->u.string, terms[i].u.string);
+                       strtablen = strlen(term->u.string) + 1;
+                       break;
+
+               case RBCE_RULE_REAL_UID:
+               case RBCE_RULE_REAL_GID:
+               case RBCE_RULE_EFFECTIVE_UID:
+               case RBCE_RULE_EFFECTIVE_GID:
+                       term->u.id = terms[i].u.id;
+                       break;
+
+               case RBCE_RULE_DEP_RULE:
+                       term->u.deprule = terms[i].u.deprule;
+                       INC_REF(term->u.deprule);
+                       break;
+               default:
+                       break;
+               }
+       }
+out:
+       if (rc) {
+               kfree(newrule->terms);
+               newrule->terms = NULL;
+       }
+       return rc;
+
+}
+
+/*
+ * Caller need to hold rbce_rwlock in write mode.
+ */
+static int
+fill_rule(struct rbce_rule *newrule, struct rbce_rule_term *terms, int nterms)
+{
+       int real_nterms, index = -1, rc = 0;
+       struct rbce_rule_term *term = NULL;
+
+       if (!newrule)
+               return -EINVAL;
+       newrule->num_terms = 0;
+       newrule->termflag = 0;
+
+       /* Digest filled terms. */
+       real_nterms = digest_terms(newrule, terms, nterms);
+       if (real_nterms < 0)
+               return real_nterms;
+       rc = digest_nonterms(newrule, terms, nterms);
+       if (rc < 0)
+               goto out;
+
+       if (newrule->index == -1) {
+               index = alloc_term_index();
+               if (index < 0) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
+               newrule->index = index;
+               term = &gl_terms[newrule->index];
+               term->op = RBCE_RULE_DEP_RULE;
+               term->u.deprule = newrule;
+       }
+
+       rc = fill_term_vector(newrule, terms, real_nterms);
+out:
+       if (rc) {
+               if (newrule->target_class) {
+                       put_class(newrule->target_class);
+                       newrule->target_class = NULL;
+               }
+               if (index >= 0) {
+                       release_term_index(index);
+                       newrule->index = -1;
+               }
+               kfree(newrule->terms);
+               newrule->terms = NULL;
+               kfree(newrule->strtab);
+               newrule->strtab = NULL;
+               newrule->num_terms = 0;
+       } else
+               newrule->num_terms = real_nterms;
+       return rc;
+}
+
+static inline int
+rbce_create_rule(struct rbce_rule_term *new_terms,
+       int nterms, const char *rname)
+{
+       struct rbce_rule *rule;
+       int rc = -ENOMEM;
+
+       rule = kmalloc (sizeof(struct rbce_rule), GFP_ATOMIC);
+       if (rule) {
+               rule->obj.name = kmalloc(strlen(rname) + 1, GFP_ATOMIC);
+               if (rule->obj.name) {
+                       strcpy(rule->obj.name, rname);
+                       GET_REF(rule) = 0;
+                       rule->order = -1;
+                       rule->index = -1;
+                       rule->num_terms = 0;
+                       rule->state = RBCE_RULE_ENABLED;
+                       rule->target_class = NULL;
+                       rule->strtab = NULL;
+                       rule->classtype = -1;
+                       rule->terms = NULL;
+                       rule->do_opt = 1;
+                       INIT_LIST_HEAD(&rule->obj.link);
+                       rc = fill_rule(rule, new_terms, nterms);
+                       if (rc) {
+                               kfree(rule->obj.name);
+                               kfree(rule);
+                       } else if ((rc = insert_rule(rule,
+                                       rule->order, INSERT)) != 0)
+                               __delete_rule(rule);
+               } else
+                       kfree(rule);
+       }
+       return rc;
+}
+
+static inline struct rbce_rule_term *
+merge_terms(struct rbce_rule *rule, struct rbce_rule_term *new_terms,
+       int nterms, int new_term_mask, int *merged_nterms)
+{
+       struct rbce_rule_term *terms, *term;
+       struct rbce_rule *deprule;
+       int i, j, k, oterms, tot_terms, strlocal_len;
+       char *strlocal;
+
+       oterms = rule->num_terms;
+       tot_terms = nterms + oterms;
+       *merged_nterms = 0;
+
+       terms = kmalloc(tot_terms * sizeof(struct rbce_rule_term), GFP_ATOMIC);
+
+       if (!terms) {
+               return NULL;
+       }
+
+       /* Assume we are going to copy all strings from the original rule. */
+       strlocal_len = 0;
+       for (i = 0; i < oterms; i++) {
+               term = &gl_terms[rule->terms[i]];
+               switch (term->op) {
+               case RBCE_RULE_CMD_PATH:
+               case RBCE_RULE_CMD:
+               case RBCE_RULE_ARGS:
+               case RBCE_RULE_APP_TAG:
+               case RBCE_RULE_IPV4:
+               case RBCE_RULE_IPV6:
+                       strlocal_len += strlen(term->u.string) + 1;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       strlocal = kmalloc(strlocal_len, GFP_ATOMIC);
+       if (!strlocal) {
+               kfree(terms);
+               return NULL;
+       }
+
+       strlocal_len = 0;
+       new_term_mask &= ~(1 << RBCE_RULE_DEP_RULE);
+       /* ignore the new deprule terms for the first iteration. */
+       /* taken care of later. */
+       for (i = 0; i < oterms; i++) {
+               term = &gl_terms[rule->terms[i]];       /* old term */
+
+               if ((1 << term->op) & new_term_mask) {
+                       /* newrule has this attr/value */
+                       for (j = 0; j < nterms; j++)
+                               if (term->op == new_terms[j].op) {
+                                       terms[i].op = new_terms[j].op;
+                                       terms[i].operator = new_terms[j].
+                                           operator;
+                                       terms[i].u.string =
+                                           new_terms[j].u.string;
+                                       new_terms[j].op = RBCE_RULE_INVALID2;
+                                       break;
+                               }
+               } else {
+                       terms[i].op = term->op;
+                       terms[i].operator = term->operator;
+                       switch (term->op) {
+                       case RBCE_RULE_CMD_PATH:
+                       case RBCE_RULE_CMD:
+                       case RBCE_RULE_ARGS:
+                       case RBCE_RULE_APP_TAG:
+                       case RBCE_RULE_IPV4:
+                       case RBCE_RULE_IPV6:
+                               terms[i].u.string = &strlocal[strlocal_len];
+                               strcpy(terms[i].u.string, term->u.string);
+                               strlocal_len = strlen(terms[i].u.string) + 1;
+                               break;
+                       default:
+                               terms[i].u.string = term->u.string;
+                               break;
+                       }
+               }
+       }
+
+       i = oterms;             /* for readability */
+
+       for (j = 0; j < nterms; j++) {
+               /* handled in the previous iteration */
+               if (new_terms[j].op == RBCE_RULE_INVALID2)
+                       continue;
+               if (new_terms[j].op == RBCE_RULE_DEP_RULE) {
+                       if (new_terms[j].operator == TOKEN_OP_DEP) {
+                               /*
+                                * "depend=rule" deletes all depends in the
+                                * original rule so, delete all depend rule
+                                * terms in the original rule
+                                */
+                               for (k = 0; k < oterms; k++)
+                                       if (terms[k].op == RBCE_RULE_DEP_RULE)
+                                               terms[k].op = RBCE_RULE_INVALID;
+                               /* must copy the new deprule term */
+                       } else {
+                               /*
+                                * delete the depend rule term if was defined
+                                * in the original rule for both +depend
+                                * and -depend
+                                */
+                               deprule = find_rule_name(new_terms[j].u.string);
+                               if (deprule)
+                                       for (k = 0; k < oterms; k++) {
+                                               if (terms[k].op ==
+                                                   RBCE_RULE_DEP_RULE
+                                                   && terms[k].u.deprule ==
+                                                   deprule) {
+                                                       terms[k].op =
+                                                           RBCE_RULE_INVALID;
+                                                       break;
+                                               }
+                                       }
+                               if (new_terms[j].operator == TOKEN_OP_DEP_DEL)
+                                       /* No need to copy the new deprule */
+                                       continue;
+                       }
+               }
+               terms[i].op = new_terms[j].op;
+               terms[i].operator = new_terms[j].operator;
+               terms[i].u.string = new_terms[j].u.string;
+               i++;
+               new_terms[j].op = RBCE_RULE_INVALID2;
+       }
+
+       tot_terms = i;
+
+       /* convert old deprule pointers to name pointers. */
+       for (i = 0; i < oterms; i++) {
+               if (terms[i].op != RBCE_RULE_DEP_RULE)
+                       continue;
+               terms[i].u.string = terms[i].u.deprule->obj.name;
+       }
+
+       *merged_nterms = tot_terms;
+       return terms;
+}
+
+int rbce_change_rule(const char *rname, char *rdefn)
+{
+       struct rbce_rule *rule;
+       struct rbce_rule_term *new_terms = NULL, *merged_terms;
+       int nterms, new_term_mask = 0, merged_nterms, rc = -ENOMEM;
+
+       if ((nterms = rules_parse(rdefn, &new_terms, &new_term_mask)) <= 0)
+               return !nterms ? -EINVAL : nterms;
+
+       write_lock(&rbce_rwlock);
+       rule = find_rule_name(rname);
+       if (rule == NULL) {
+               rc = rbce_create_rule(new_terms, nterms, rname);
+               kfree(new_terms);
+               write_unlock(&rbce_rwlock);
+               return rc;
+       }
+
+       merged_terms = merge_terms(rule, new_terms, nterms, new_term_mask,
+                       &merged_nterms);
+
+       if (merged_terms) {
+               /* release the rule */
+               __release_rule(rule);
+
+               rule->do_opt = 1;
+               rc = fill_rule(rule, merged_terms, merged_nterms);
+               if (rc == 0)
+                       rc = insert_rule(rule, rule->order, REINSERT);
+               if (rc != 0)    /* rule creation/insertion failed */
+                       __delete_rule(rule);
+       }
+
+       write_unlock(&rbce_rwlock);
+       kfree(merged_terms);
+       kfree(new_terms);
+       return rc;
+}
+
+/*
+ * Delete the specified rule.
+ *
+ */
+int rbce_delete_rule(const char *rname)
+{
+       int rc = 0;
+       struct rbce_rule *rule;
+
+       write_lock(&rbce_rwlock);
+
+       if ((rule = find_rule_name(rname)) != NULL)
+               rc = __delete_rule(rule);
+       write_unlock(&rbce_rwlock);
+       return rc;
+}
+
+/*
+ * copy the rule specified by rname and to the given result string.
+ *
+ */
+void rbce_get_rule(const char *rname, char *result)
+{
+       int i;
+       struct rbce_rule *rule;
+       struct rbce_rule_term *term;
+       char *cp = result, oper, idtype[3], str[5];
+
+       read_lock(&rbce_rwlock);
+
+       rule = find_rule_name(rname);
+       if (rule != NULL) {
+               for (i = 0; i < rule->num_terms; i++) {
+                       term = gl_terms + rule->terms[i];
+                       switch (term->op) {
+                       case RBCE_RULE_REAL_UID:
+                               strcpy(idtype, "u");
+                               goto handleid;
+                       case RBCE_RULE_REAL_GID:
+                               strcpy(idtype, "g");
+                               goto handleid;
+                       case RBCE_RULE_EFFECTIVE_UID:
+                               strcpy(idtype, "eu");
+                               goto handleid;
+                       case RBCE_RULE_EFFECTIVE_GID:
+                               strcpy(idtype, "eg");
+                       handleid:
+                               switch (term->operator) {
+                               case RBCE_LESS_THAN:
+                                       oper = '<';
+                                       break;
+                               case RBCE_GREATER_THAN:
+                                       oper = '>';
+                                       break;
+                               case RBCE_NOT:
+                                       oper = '!';
+                                       break;
+                               default:
+                                       oper = '=';
+                                       break;
+                               }
+                               cp +=
+                                   sprintf(cp, "%sid%c%ld,", idtype, oper,
+                                           term->u.id);
+                               break;
+                       case RBCE_RULE_CMD_PATH:
+                               strcpy(str, "path");
+                               goto handle_str;
+                       case RBCE_RULE_CMD:
+                               strcpy(str, "cmd");
+                               goto handle_str;
+                       case RBCE_RULE_ARGS:
+                               strcpy(str, "args");
+                               goto handle_str;
+                       case RBCE_RULE_APP_TAG:
+                               strcpy(str, "tag");
+                               goto handle_str;
+                       case RBCE_RULE_IPV4:
+                               strcpy(str, "ipv4");
+                               goto handle_str;
+                       case RBCE_RULE_IPV6:
+                               strcpy(str, "ipv6");
+                             handle_str:
+                               cp +=
+                                   sprintf(cp, "%s=%s,", str, term->u.string);
+                               break;
+                       case RBCE_RULE_DEP_RULE:
+                               cp +=
+                                   sprintf(cp, "depend=%s,",
+                                           term->u.deprule->obj.name);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               cp +=
+                   sprintf(cp, "order=%d,state=%d,", rule->order, rule->state);
+               cp +=
+                   sprintf(cp, "class=%s",
+                           rule->target_class ? rule->target_class->obj.
+                           name : "*****REMOVED*****");
+               *cp = '\0';
+       } else
+               sprintf(result, "***** Rule %s doesn't exist *****", rname);
+
+       read_unlock(&rbce_rwlock);
+       return;
+}
+
+/*
+ * Change the name of the given rule "from_rname" to "to_rname"
+ *
+ */
+int rbce_rename_rule(const char *from_rname, const char *to_rname)
+{
+       struct rbce_rule *rule;
+       int nlen, rc = -EINVAL;
+
+       if (!to_rname || !*to_rname)
+               return rc;
+       write_lock(&rbce_rwlock);
+
+       rule = find_rule_name(from_rname);
+       if (rule != NULL) {
+               if ((nlen = strlen(to_rname)) > strlen(rule->obj.name)) {
+                       char *name = kmalloc(nlen + 1, GFP_ATOMIC);
+                       if (!name)
+                               return -ENOMEM;
+                       kfree(rule->obj.name);
+                       rule->obj.name = name;
+               }
+               strcpy(rule->obj.name, to_rname);
+               rc = 0;
+       }
+       write_unlock(&rbce_rwlock);
+       return rc;
+}
+
+/*
+ * Return TRUE if the given rule exists, FALSE otherwise
+ *
+ */
+int rbce_rule_exists(const char *rname)
+{
+       struct rbce_rule *rule;
+
+       read_lock(&rbce_rwlock);
+       rule = find_rule_name(rname);
+       read_unlock(&rbce_rwlock);
+       return rule != NULL;
+}
+
+/*====================== Magic file handling =======================*/
+struct rbce_private_data *create_private_data(struct rbce_private_data *a,
+                                                    int b)
+{
+       return NULL;
+}
+
+int rbce_set_tasktag(int pid, char *tag)
+{
+       char *tp;
+       int rc = 0;
+       struct task_struct *tsk;
+       struct rbce_private_data *pdata;
+       int len;
+
+       if (!tag)
+               return -EINVAL;
+       len = strlen(tag) + 1;
+       tp = kmalloc(len, GFP_ATOMIC);
+       if (!tp)
+               return -ENOMEM;
+       strncpy(tp,tag,len);
+
+       read_lock(&tasklist_lock);
+       if ((tsk = find_task_by_pid(pid)) == NULL) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+       if (!RBCE_DATA(tsk)) {
+               RBCE_DATAP(tsk) = create_private_data(NULL, 0);
+               if (!RBCE_DATA(tsk)) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
+       }
+       pdata = RBCE_DATA(tsk);
+       if (pdata->app_tag)
+               kfree(pdata->app_tag);
+       pdata->app_tag = tp;
+
+out:
+       read_unlock(&tasklist_lock);
+       if (rc != 0)
+               kfree(tp);
+       return rc;
 }
 
-int rbce_enabled = 1;
 /* ======================= Module definition Functions ====================== 
*/
 
 int init_rbce(void)
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_token.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_token.c        2005-05-05 
09:38:03.000000000 -0700
@@ -0,0 +1,241 @@
+/* Tokens for Rule-based Classification Engine (RBCE) and
+ * Consolidated RBCE module code (combined)
+ *
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003
+ *           (C) Chandra Seetharaman, IBM Corp. 2003
+ *           (C) Vivek Kashyap, IBM Corp. 2004
+ *
+ * Latest version, more details at http://ckrm.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ */
+
+#include <linux/parser.h>
+#include <linux/ctype.h>
+#include "rbce_internal.h"
+
+int token_to_ruleop[TOKEN_INVALID + 1] = {
+       [TOKEN_PATH] = RBCE_RULE_CMD_PATH,
+       [TOKEN_CMD] = RBCE_RULE_CMD,
+       [TOKEN_ARGS] = RBCE_RULE_ARGS,
+       [TOKEN_RUID_EQ] = RBCE_RULE_REAL_UID,
+       [TOKEN_RUID_LT] = RBCE_RULE_REAL_UID,
+       [TOKEN_RUID_GT] = RBCE_RULE_REAL_UID,
+       [TOKEN_RUID_NOT] = RBCE_RULE_REAL_UID,
+       [TOKEN_RGID_EQ] = RBCE_RULE_REAL_GID,
+       [TOKEN_RGID_LT] = RBCE_RULE_REAL_GID,
+       [TOKEN_RGID_GT] = RBCE_RULE_REAL_GID,
+       [TOKEN_RGID_NOT] = RBCE_RULE_REAL_GID,
+       [TOKEN_EUID_EQ] = RBCE_RULE_EFFECTIVE_UID,
+       [TOKEN_EUID_LT] = RBCE_RULE_EFFECTIVE_UID,
+       [TOKEN_EUID_GT] = RBCE_RULE_EFFECTIVE_UID,
+       [TOKEN_EUID_NOT] = RBCE_RULE_EFFECTIVE_UID,
+       [TOKEN_EGID_EQ] = RBCE_RULE_EFFECTIVE_GID,
+       [TOKEN_EGID_LT] = RBCE_RULE_EFFECTIVE_GID,
+       [TOKEN_EGID_GT] = RBCE_RULE_EFFECTIVE_GID,
+       [TOKEN_EGID_NOT] = RBCE_RULE_EFFECTIVE_GID,
+       [TOKEN_TAG] = RBCE_RULE_APP_TAG,
+       [TOKEN_IPV4] = RBCE_RULE_IPV4,
+       [TOKEN_IPV6] = RBCE_RULE_IPV6,
+       [TOKEN_DEP] = RBCE_RULE_DEP_RULE,
+       [TOKEN_DEP_ADD] = RBCE_RULE_DEP_RULE,
+       [TOKEN_DEP_DEL] = RBCE_RULE_DEP_RULE,
+       [TOKEN_ORDER] = RBCE_RULE_INVALID,
+       [TOKEN_CLASS] = RBCE_RULE_INVALID,
+       [TOKEN_STATE] = RBCE_RULE_INVALID,
+};
+
+enum op_token token_to_operator[TOKEN_INVALID + 1] = {
+       [TOKEN_PATH] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_CMD] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_ARGS] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_RUID_EQ] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_RUID_LT] = (__force op_token_t) TOKEN_OP_LESS_THAN,
+       [TOKEN_RUID_GT] = (__force op_token_t) TOKEN_OP_GREATER_THAN,
+       [TOKEN_RUID_NOT] = (__force op_token_t) TOKEN_OP_NOT,
+       [TOKEN_RGID_EQ] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_RGID_LT] = (__force op_token_t) TOKEN_OP_LESS_THAN,
+       [TOKEN_RGID_GT] = (__force op_token_t) TOKEN_OP_GREATER_THAN,
+       [TOKEN_RGID_NOT] = (__force op_token_t) TOKEN_OP_NOT,
+       [TOKEN_EUID_EQ] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_EUID_LT] = (__force op_token_t) TOKEN_OP_LESS_THAN,
+       [TOKEN_EUID_GT] = (__force op_token_t) TOKEN_OP_GREATER_THAN,
+       [TOKEN_EUID_NOT] = (__force op_token_t) TOKEN_OP_NOT,
+       [TOKEN_EGID_EQ] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_EGID_LT] = (__force op_token_t) TOKEN_OP_LESS_THAN,
+       [TOKEN_EGID_GT] = (__force op_token_t) TOKEN_OP_GREATER_THAN,
+       [TOKEN_EGID_NOT] = (__force op_token_t) TOKEN_OP_NOT,
+       [TOKEN_TAG] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_IPV4] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_IPV6] = (__force op_token_t) TOKEN_OP_EQUAL,
+       [TOKEN_DEP] = (__force op_token_t) TOKEN_OP_DEP,
+       [TOKEN_DEP_ADD] = (__force op_token_t) TOKEN_OP_DEP_ADD,
+       [TOKEN_DEP_DEL] = (__force op_token_t) TOKEN_OP_DEP_DEL,
+       [TOKEN_ORDER] = (__force op_token_t) TOKEN_OP_ORDER,
+       [TOKEN_CLASS] = (__force op_token_t) TOKEN_OP_CLASS,
+       [TOKEN_STATE] = (__force op_token_t) TOKEN_OP_STATE
+};
+
+static match_table_t tokens = {
+       {TOKEN_PATH, "path=%s"},
+       {TOKEN_CMD, "cmd=%s"},
+       {TOKEN_ARGS, "args=%s"},
+       {TOKEN_RUID_EQ, "uid=%d"},
+       {TOKEN_RUID_LT, "uid<%d"},
+       {TOKEN_RUID_GT, "uid>%d"},
+       {TOKEN_RUID_NOT, "uid!%d"},
+       {TOKEN_RGID_EQ, "gid=%d"},
+       {TOKEN_RGID_LT, "gid<%d"},
+       {TOKEN_RGID_GT, "gid>%d"},
+       {TOKEN_RGID_NOT, "gid!d"},
+       {TOKEN_EUID_EQ, "euid=%d"},
+       {TOKEN_EUID_LT, "euid<%d"},
+       {TOKEN_EUID_GT, "euid>%d"},
+       {TOKEN_EUID_NOT, "euid!%d"},
+       {TOKEN_EGID_EQ, "egid=%d"},
+       {TOKEN_EGID_LT, "egid<%d"},
+       {TOKEN_EGID_GT, "egid>%d"},
+       {TOKEN_EGID_NOT, "egid!%d"},
+       {TOKEN_TAG, "tag=%s"},
+       {TOKEN_IPV4, "ipv4=%s"},
+       {TOKEN_IPV6, "ipv6=%s"},
+       {TOKEN_DEP, "depend=%s"},
+       {TOKEN_DEP_ADD, "+depend=%s"},
+       {TOKEN_DEP_DEL, "-depend=%s"},
+       {TOKEN_ORDER, "order=%d"},
+       {TOKEN_CLASS, "class=%s"},
+       {TOKEN_STATE, "state=%d"},
+       {TOKEN_INVALID, NULL}
+};
+
+/*
+ * return -EINVAL in case of failures
+ * returns number of terms in terms on success.
+ * never returns 0.
+ */
+
+int
+rules_parse(char *rule_defn, struct rbce_rule_term **rterms, int *term_mask)
+{
+       char *p, *rp = rule_defn;
+       int option, i = 0, nterms;
+       struct rbce_rule_term *terms;
+
+       *rterms = NULL;
+       *term_mask = 0;
+       if (!rule_defn)
+               return -EINVAL;
+
+       nterms = 0;
+       while (*rp++)
+               if (*rp == '>' || *rp == '<' || *rp == '=' || *rp == '!')
+                       nterms++;
+
+       if (!nterms)
+               return -EINVAL;
+
+       terms = kmalloc(nterms * sizeof(struct rbce_rule_term), GFP_KERNEL);
+       if (!terms)
+               return -ENOMEM;
+
+       while ((p = strsep(&rule_defn, ",")) != NULL) {
+
+               substring_t args[MAX_OPT_ARGS];
+               int token;
+
+               while (*p && isspace(*p))
+                       p++;
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+
+               terms[i].op = token_to_ruleop[token];
+               terms[i].operator = token_to_operator[token];
+               switch (token) {
+
+               case TOKEN_PATH:
+               case TOKEN_CMD:
+               case TOKEN_ARGS:
+               case TOKEN_TAG:
+               case TOKEN_IPV4:
+               case TOKEN_IPV6:
+                       /* all these tokens can be specified only once */
+                       if (*term_mask & (1 << terms[i].op)) {
+                               nterms = -EINVAL;
+                               goto out;
+                       }
+               /*FALLTHRU*/
+               case TOKEN_CLASS:
+               case TOKEN_DEP:
+               case TOKEN_DEP_ADD:
+               case TOKEN_DEP_DEL:
+                       terms[i].u.string = args->from;
+                       break;
+
+               case TOKEN_RUID_EQ:
+               case TOKEN_RUID_LT:
+               case TOKEN_RUID_GT:
+               case TOKEN_RUID_NOT:
+               case TOKEN_RGID_EQ:
+               case TOKEN_RGID_LT:
+               case TOKEN_RGID_GT:
+               case TOKEN_RGID_NOT:
+               case TOKEN_EUID_EQ:
+               case TOKEN_EUID_LT:
+               case TOKEN_EUID_GT:
+               case TOKEN_EUID_NOT:
+               case TOKEN_EGID_EQ:
+               case TOKEN_EGID_LT:
+               case TOKEN_EGID_GT:
+               case TOKEN_EGID_NOT:
+                       /* all these tokens can be specified only once */
+                       if (*term_mask & (1 << terms[i].op)) {
+                               nterms = -EINVAL;
+                               goto out;
+                       }
+               /*FALLTHRU*/
+               case TOKEN_ORDER:
+               case TOKEN_STATE:
+                       if (match_int(args, &option)) {
+                               nterms = -EINVAL;
+                               goto out;
+                       }
+                       terms[i].u.id = option;
+                       break;
+               default:
+                       nterms = -EINVAL;
+                       goto out;
+               }
+               /* Check range of term value */
+               switch(token){
+               case TOKEN_STATE:
+                       if ((terms[i].u.id != 0) && (terms[i].u.id != 1)){
+                               nterms = -EINVAL;
+                               goto out;
+                       }
+                       break;
+               default: /* Non-numerical value */
+                       break;
+               }
+               *term_mask |= (1 << terms[i].op);
+               i++;
+       }
+       *rterms = terms;
+
+      out:
+       if (nterms < 0) {
+               kfree(terms);
+               *term_mask = 0;
+       }
+       return nterms;
+}

--



-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games.
Get your fingers limbered up and give it your best shot. 4 great events, 4
opportunities to win big! Highest score wins.NEC IT Guy Games. Play to
win an NEC 61 plasma display. Visit http://www.necitguy.com/?r=20
_______________________________________________
ckrm-tech mailing list
https://lists.sourceforge.net/lists/listinfo/ckrm-tech

Reply via email to