/*************************************************** */
/* Rule Set Based Access Control                     */
/* Implementation of ACI data structures             */
/* Author and (c) 1999-2002: Amon Ott <ao@rsbac.org> */
/* (some smaller parts copied from fs/namei.c        */
/*  and others)                                      */
/*                                                   */
/* Last modified: 30/Apr/2002                        */
/*************************************************** */

#include <linux/types.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/quotaops.h>
#include <linux/proc_fs.h>
#include <linux/msdos_fs.h>
#include <linux/iso_fs.h>
#include <linux/nfs_fs.h>
#include <linux/ext2_fs.h>
#include <linux/coda_psdev.h>
#include <linux/ncp_fs.h>
#include <linux/smb.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,12)
#include <linux/dnotify.h>
#endif
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <asm/uaccess.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#include <asm/atomic.h>
#endif
#include <rsbac/types.h>
#include <rsbac/aci.h>
#include <rsbac/aci_data_structures.h>
#include <rsbac/error.h>
#include <rsbac/helpers.h>
#include <rsbac/fs.h>
#include <rsbac/getname.h>
#include <rsbac/net_getname.h>
#include <rsbac/adf.h>
#include <rsbac/adf_main.h>
#include <rsbac/reg.h>
#include <rsbac/rkmem.h>
#include <rsbac/gen_lists.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
#include <linux/smp_lock.h>

#ifdef CONFIG_RSBAC_PM
#include <rsbac/pm.h>
#endif

#if defined(CONFIG_RSBAC_RC)
#include <rsbac/rc.h>
#endif

#if defined(CONFIG_RSBAC_AUTH)
#include <rsbac/auth.h>
#endif

#if defined(CONFIG_RSBAC_ACL)
#include <rsbac/acl.h>
#endif

#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
#define __KERNEL_SYSCALLS__
#endif
#include <linux/unistd.h>
#include <linux/timer.h>
static u_int auto_interval = CONFIG_RSBAC_AUTO_WRITE * HZ;
#endif /* CONFIG_RSBAC_AUTO_WRITE */

#if  (defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)) \
   || defined(CONFIG_RSBAC_INIT_THREAD)
static DECLARE_WAIT_QUEUE_HEAD(rsbacd_wait);
static struct timer_list rsbac_timer;
#endif

#if defined(CONFIG_RSBAC_NET_OBJ)
#include <rsbac/network.h>
#endif

/************************************************************************** */
/*                          Global Variables                                */
/************************************************************************** */

/* The following global variables are needed for access to ACI data.        */
/* For efficiency reasons there is an array of lists for files and dirs,    */
/* using (inode number) modulo (array size) as a hash function.             */

static boolean rsbac_initialized = FALSE;

static char    compiled_modules[80];

kdev_t rsbac_root_dev;
#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_root_dev);
EXPORT_SYMBOL(rsbac_write_sem);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
struct semaphore rsbac_write_sem = MUTEX;
#else
DECLARE_MUTEX(rsbac_write_sem);
#endif

static struct rsbac_device_list_head_t device_list_head;
static struct rsbac_dev_handles_t      dev_handles;
static struct rsbac_ipc_handles_t      ipc_handles;
static struct rsbac_user_handles_t     user_handles;
static struct rsbac_process_handles_t  process_handles;

#ifdef CONFIG_RSBAC_NET_DEV
static struct rsbac_netdev_handles_t    netdev_handles;
#endif
#ifdef CONFIG_RSBAC_NET_OBJ
static rsbac_list_handle_t              net_temp_handle;
static struct rsbac_nettemp_handles_t   nettemp_handles;
static struct rsbac_lnetobj_handles_t   lnetobj_handles;
static struct rsbac_rnetobj_handles_t   rnetobj_handles;
#endif

/* Default ACIs: implemented as variables, might be changeable some time */

/* rsbac root dir items, end of recursive inherit */
static struct rsbac_gen_fd_aci_t   def_gen_root_dir_aci  = DEFAULT_GEN_ROOT_DIR_ACI;

#if defined(CONFIG_RSBAC_MAC)
static struct rsbac_mac_fd_aci_t   def_mac_root_dir_aci  = DEFAULT_MAC_ROOT_DIR_ACI;
#endif
#if defined(CONFIG_RSBAC_RC)
static struct rsbac_rc_fd_aci_t   def_rc_root_dir_aci  = DEFAULT_RC_ROOT_DIR_ACI;
#endif

#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
#include <rsbac/proc_fs.h>

#ifdef CONFIG_RSBAC_XSTATS
static u_long get_attr_count[T_NONE] = {0,0,0,0,0,0,0};
static u_long set_attr_count[T_NONE] = {0,0,0,0,0,0,0};
static u_long remove_count[T_NONE] = {0,0,0,0,0,0,0};
#endif

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(proc_rsbac_root_p);
#endif
struct proc_dir_entry * proc_rsbac_root_p = NULL;

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(proc_rsbac_backup_p);
#endif
struct proc_dir_entry * proc_rsbac_backup_p = NULL;

#endif /* PROC */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11)
static struct super_block * sockfs_sb_p = NULL;
static struct super_block * pipefs_sb_p = NULL;
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#ifdef CONFIG_DEVFS_MOUNT
#include <linux/devfs_fs_kernel.h>
static struct dentry * devfs_covered_p = NULL;
static struct super_block * devfs_sb_p = NULL;
#endif
#endif

/**************************************************/
/*       Declarations of internal functions       */
/**************************************************/

  static struct rsbac_device_list_item_t * lookup_device(kdev_t);

  static int rsbac_read_open_device_p(char * name,
                                      struct file  *  file_p,
                                      kdev_t kdev,
                                      struct rsbac_device_list_item_t * device_p);

/************************************************* */
/*               Internal Help functions           */
/************************************************* */

static inline int gen_fd_hash(u_long inode)
  {
    return(inode % RSBAC_GEN_NR_FD_LISTS);
  }
#if defined(CONFIG_RSBAC_MAC)
static inline int mac_fd_hash(u_long inode)
  {
    return(inode % RSBAC_MAC_NR_FD_LISTS);
  }
#endif
#if defined(CONFIG_RSBAC_FC)
static inline int fc_fd_hash(u_long inode)
  {
    return(inode % RSBAC_FC_NR_FD_LISTS);
  }
#endif
#if defined(CONFIG_RSBAC_SIM)
static inline int sim_fd_hash(u_long inode)
  {
    return(inode % RSBAC_SIM_NR_FD_LISTS);
  }
#endif
#if defined(CONFIG_RSBAC_PM)
static inline int pm_fd_hash(u_long inode)
  {
    return(inode % RSBAC_PM_NR_FD_LISTS);
  }
#endif
#if defined(CONFIG_RSBAC_MS)
static inline int ms_fd_hash(u_long inode)
  {
    return(inode % RSBAC_MS_NR_FD_LISTS);
  }
static inline int ms_scanned_fd_hash(u_long inode)
  {
    return(inode % RSBAC_MS_SCANNED_NR_FD_LISTS);
  }
#endif
#if defined(CONFIG_RSBAC_FF)
static inline int ff_fd_hash(u_long inode)
  {
    return(inode % RSBAC_FF_NR_FD_LISTS);
  }
#endif
#if defined(CONFIG_RSBAC_RC)
static inline int rc_fd_hash(u_long inode)
  {
    return(inode % RSBAC_RC_NR_FD_LISTS);
  }
#endif
#if defined(CONFIG_RSBAC_AUTH)
static inline int auth_fd_hash(u_long inode)
  {
    return(inode % RSBAC_AUTH_NR_FD_LISTS);
  }
#endif
#if defined(CONFIG_RSBAC_CAP)
static inline int cap_fd_hash(u_long inode)
  {
    return(inode % RSBAC_CAP_NR_FD_LISTS);
  }
#endif

/* These help functions do NOT handle data consistency protection by */
/* rw-spinlocks! This is done exclusively by non-internal functions! */

/************************************************************************** */
/* Read/Write functions                                                     */

/* This help function protects some filesystems from being written to */
/* and disables writing under some conditions, e.g. in an interrupt */ 

boolean writable(struct super_block * sb_p)
 {
#ifdef CONFIG_RSBAC_NO_WRITE
   return(FALSE);
#else
   if (!sb_p || !sb_p->s_dev)
     return(FALSE);
   if (
#ifdef CONFIG_RSBAC_DEBUG
       rsbac_debug_no_write ||
#endif
       (sb_p->s_flags & MS_RDONLY)
       || in_interrupt())
     return(FALSE);
   if (   !MAJOR(sb_p->s_dev)
#ifndef CONFIG_RSBAC_MSDOS_WRITE
       || (sb_p->s_magic == MSDOS_SUPER_MAGIC)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
       || (sb_p->s_magic == SOCKFS_MAGIC)
       || (sb_p->s_magic == PIPEFS_MAGIC)
#endif
       || (sb_p->s_magic == NFS_SUPER_MAGIC)
       || (sb_p->s_magic == CODA_SUPER_MAGIC)
       || (sb_p->s_magic == NCP_SUPER_MAGIC)
       || (sb_p->s_magic == SMB_SUPER_MAGIC)
       || (sb_p->s_magic == ISOFS_SUPER_MAGIC))
     return(FALSE);
   else
     return(TRUE);
#endif
 }

/* This lookup function ensures correct access to the file system.          */
/* It returns a pointer to the dentry of the rsbac directory on the mounted */
/* device specified by kdev. If the directory    */
/* does not exist, it is created, if create_dir == TRUE and writable. */

static int lookup_aci_path_dentry(struct super_block * sb_p,
                            struct dentry ** dir_dentry_pp,
                                 boolean     create_dir,
                                 struct rsbac_device_list_item_t * device_p)
  {
    struct dentry * dir_dentry_p = NULL;
    struct dentry * root_dentry_p = NULL;
    int             err=0;

    if(!sb_p || !dir_dentry_pp)
      return(-RSBAC_EINVALIDPOINTER);

    if(!device_p)
      {
        printk(KERN_WARNING
               "lookup_aci_path_dentry(): No entry for device %02u:%02u\n",
               MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
        return(-RSBAC_EINVALIDDEV);
      }
    /* pipefs must not be read from */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11)
    if(   (sb_p->s_magic == PIPEFS_MAGIC)
       || (sb_p->s_magic == SOCKFS_MAGIC)
      )
      return -RSBAC_ENOTFOUND;
#endif
    /* use for DEBUG only! */
/*    if(create_dir)
      return(-RSBAC_ENOTFOUND); */

    /* already looked up earlier? */
    if(device_p->rsbac_dir_dentry_p)
      {
        *dir_dentry_pp = device_p->rsbac_dir_dentry_p;
#ifdef CONFIG_RSBAC_DEBUG
        if(rsbac_debug_ds)
          {
            printk(KERN_DEBUG
                   "lookup_aci_path_dentry(): device_p->rsbac_dir_dentry_p->d_count for device %02u:%02u is %i!\n",
                   MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev),
               #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                   device_p->rsbac_dir_dentry_p->d_count);
               #else
                   atomic_read(&device_p->rsbac_dir_dentry_p->d_count));
               #endif
          }
#endif
        return(0);
      }

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_ds)
      printk(KERN_DEBUG
             "lookup_aci_path_dentry(): first time lookup for or non-existing %s on device %02u:%02u!\n",
             RSBAC_ACI_PATH,
             MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
#endif
    if (!sb_p->s_root)
      {
        printk(KERN_WARNING
               "lookup_aci_path_dentry(): Super_block for device %02u:%02u has no root dentry!\n",
               MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
        err = -RSBAC_EINVALIDDEV;
        goto out;
      }

    if (!sb_p->s_root->d_inode)
      {
        printk(KERN_WARNING
               "lookup_aci_path_dentry(): Super_block for device %02u:%02u has no root dentry->d_inode!\n",
               MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
        err = -RSBAC_EINVALIDDEV;
        goto out;
      }

    /* lookup dentry of ACI_PATH on this device */
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_ds)
      printk(KERN_DEBUG
             "lookup_aci_path_dentry(): lookup rsbac path %s for device %02u:%02u, sb_p->s_root->d_count is %i!\n",
             RSBAC_ACI_PATH, MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev),
             #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
             sb_p->s_root->d_count);
             #else
             atomic_read(&sb_p->s_root->d_count));
             #endif
#endif
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    dir_dentry_p = rsbac_lookup_dentry(RSBAC_ACI_PATH, dget(sb_p->s_root), 0);
    #else
    dir_dentry_p = rsbac_lookup_one_len(RSBAC_ACI_PATH, sb_p->s_root, strlen(RSBAC_ACI_PATH));
    #endif
    if(IS_ERR(dir_dentry_p))
      switch(PTR_ERR(dir_dentry_p))
        {
          case -ENOENT       :
          case -ENOTDIR      : err = -RSBAC_ENOTFOUND;
                               goto out;
          case -ENOMEM       : printk(KERN_WARNING
                                      "lookup_aci_path_dentry(): memory allocation error!\n");
                               err = -RSBAC_ENOROOTDIR;
                               goto out;
          case -ENAMETOOLONG : printk(KERN_WARNING
                                      "lookup_aci_path_dentry(): ACI_PATH too long on fs!\n");
                               err = -RSBAC_EPATHTOOLONG;
                               goto out;
          case -EACCES       : printk(KERN_WARNING
                                      "lookup_aci_path_dentry(): No access to ACI_PATH!\n");
                               err = -RSBAC_EACCESS;
                               goto out;
          default            : printk(KERN_WARNING
                                      "lookup_aci_path_dentry(): Error on root dir: %li!\n",
                                      PTR_ERR(dir_dentry_p));
                               err = -RSBAC_ENOROOTDIR;
                               goto out;
        }

    if (!dir_dentry_p)
      {
        printk(KERN_WARNING
               "lookup_aci_path_dentry(): rsbac_lookup_(dentry|one) returned null pointer!\n");
        err = -RSBAC_EINVALIDPOINTER;
        goto out;
      }
    if (!dir_dentry_p->d_inode)
      { /* dir could not be found -> try to create it */
        /* but only, if allowed... */
        if (!create_dir)
          {
            err = -RSBAC_ENOTFOUND;
            goto out_dir_dput;
          }
#ifdef CONFIG_RSBAC_DEBUG
        if(rsbac_debug_ds)
          printk(KERN_DEBUG
                 "lookup_aci_path_dentry(): try to create dir, first test writable!\n");
#endif
        /* ... and writable. */
        if (!writable(sb_p))
          { /* mounted read only or special case */
            err = -RSBAC_ENOTWRITABLE;
            goto out_dir_dput;
          }
        root_dentry_p = lock_parent(dir_dentry_p);
        err = PTR_ERR(root_dentry_p);
        if (   IS_ERR(root_dentry_p))
          {
            err = -RSBAC_ECOULDNOTCREATEPATH;
            goto out_dir_dput;
          }
        if (   !root_dentry_p->d_inode
            || !root_dentry_p->d_inode->i_op
            || !root_dentry_p->d_inode->i_op->mkdir)
          {
            unlock_dir(root_dentry_p);
            err = -RSBAC_ECOULDNOTCREATEPATH;
            goto out_dir_dput;
          }
        DQUOT_INIT(root_dentry_p->d_inode);
        err = root_dentry_p->d_inode->i_op->mkdir(root_dentry_p->d_inode,
                                                  dir_dentry_p,
                                                  RSBAC_ACI_DIR_MODE);
        unlock_dir(root_dentry_p);
        if (err)
          {
            err = -RSBAC_ECOULDNOTCREATEPATH;
            goto out_dir_dput;
          }
      }
    else /* was found */
      { /* check, whether this is a dir */
        if(!S_ISDIR(dir_dentry_p->d_inode->i_mode))
          { /* no dir! We have a real prob here! */
            printk(KERN_WARNING
                   "lookup_aci_path_dentry(): supposed /%s dir on dev %02u:%02u is no dir!\n",
                   RSBAC_ACI_PATH,
                   MAJOR(sb_p->s_dev),
                   MINOR(sb_p->s_dev));
            err = -RSBAC_EACCESS;
            goto out_dir_dput;
          }
      }
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_ds)
      printk(KERN_DEBUG
             "lookup_aci_path_dentry(): dir_dentry_p->d_count is %i!\n",
             #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
             dir_dentry_p->d_count);
             #else
             atomic_read(&dir_dentry_p->d_count));
             #endif
    if(rsbac_debug_ds)
      printk(KERN_DEBUG
             "lookup_aci_path_dentry(): sb_p->s_root->d_count is now %i!\n",
             #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
             sb_p->s_root->d_count);
             #else
             atomic_read(&sb_p->s_root->d_count));
             #endif
#endif
    /* we want to keep dir_dentry_p in device_item */
    /* dput must be done in remove_device_item! */
    *dir_dentry_pp = dir_dentry_p;
    device_p->rsbac_dir_dentry_p = dir_dentry_p;
    device_p->rsbac_dir_inode = dir_dentry_p->d_inode->i_ino;

out:
    return (err);

out_dir_dput:
    dput(dir_dentry_p);
    goto out;
  }

/************************************************************************** */
/* The lookup functions return NULL, if the item is not found, and a        */
/* pointer to the item otherwise.                                           */

/* The do_lookup() function is used as an abstraction from the hash         */
/* management.*/

/* First, a lookup for the device list item                                 */

static struct rsbac_device_list_item_t * lookup_device(kdev_t kdev)
    {
      struct rsbac_device_list_item_t  * curr = device_list_head.curr;
      
      /* if there is no current item or it is not the right one, search... */
      if(! (curr && (curr->id == kdev) ) )
        {
          curr = device_list_head.head;
          while (curr && (curr->id != kdev))
            {
              curr = curr->next;
            }
          if (curr)
            device_list_head.curr=curr;
        }
      /* it is the current item -> return it */
        return (curr);
    };

static int dev_compare(void * desc1, void * desc2)
  {
    int result;
    struct rsbac_dev_t * i_desc1 = desc1;
    struct rsbac_dev_t * i_desc2 = desc2;

    result = memcmp(&i_desc1->type,
                    &i_desc2->type,
                    sizeof(i_desc1->type));
    if(result)
      return result;
    else
      return memcmp(&i_desc1->id,
                    &i_desc2->id,
                    sizeof(i_desc1->id));
  }

static int ipc_compare(void * desc1, void * desc2)
  {
    int result;
    struct rsbac_ipc_t * i_desc1 = desc1;
    struct rsbac_ipc_t * i_desc2 = desc2;

    result = memcmp(&i_desc1->type,
                    &i_desc2->type,
                    sizeof(i_desc1->type));
    if(result)
      return result;
    else
      return memcmp(&i_desc1->id.id_nr,
                    &i_desc2->id.id_nr,
                    sizeof(i_desc1->id.id_nr));
  }

#ifdef CONFIG_RSBAC_NET_DEV
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG) || defined(CONFIG_RSBAC_RC)
static int netdev_compare(void * desc1, void * desc2)
  {
    return strncmp(desc1,
                   desc2,
                   RSBAC_IFNAMSIZ);
  }
#endif
#endif

/************************************************************************** */
/* Convert functions                                                        */

static int gen_fd_conv(
	void * old_desc,
	void * old_data,
	void * new_desc,
	void * new_data)
  {
    struct rsbac_gen_fd_aci_t     * new_aci = new_data;
    struct rsbac_gen_fd_old_aci_t * old_aci = old_data;

    memcpy(new_desc, old_desc, sizeof(rsbac_inode_nr_t));
    new_aci->log_array_low = old_aci->log_array_low;
    new_aci->log_array_high = old_aci->log_array_high;
    new_aci->log_program_based = old_aci->log_program_based;
    new_aci->symlink_add_uid = old_aci->symlink_add_uid;
    new_aci->symlink_add_rc_role = FALSE;
    new_aci->linux_dac_disable = LDD_false;
    return 0;
  }

static int gen_fd_old_conv(
	void * old_desc,
	void * old_data,
	void * new_desc,
	void * new_data)
  {
    struct rsbac_gen_fd_aci_t     * new_aci = new_data;
    struct rsbac_gen_fd_old_old_aci_t * old_aci = old_data;

    memcpy(new_desc, old_desc, sizeof(rsbac_inode_nr_t));
    new_aci->log_array_low = old_aci->log_array_low;
    new_aci->log_array_high = old_aci->log_array_high;
    new_aci->log_program_based = old_aci->log_program_based;
    new_aci->symlink_add_uid = FALSE;
    new_aci->symlink_add_rc_role = FALSE;
    new_aci->linux_dac_disable = LDD_false;
    return 0;
  }

rsbac_list_conv_function_t * gen_fd_get_conv(rsbac_version_t old_version)
  {
    switch(old_version)
      {
        case RSBAC_GEN_FD_OLD_ACI_VERSION:
          return gen_fd_conv;
        case RSBAC_GEN_FD_OLD_OLD_ACI_VERSION:
          return gen_fd_old_conv;
        default:
          return NULL;
      }
  }

/************************************************************************** */
/* The add_item() functions add an item to the list, set head.curr to it,   */
/* and return a pointer to the item.                                        */
/* These functions will NOT check, if there is already an item under the    */
/* same ID! If this happens, the lookup functions will return the old item! */
/* All list manipulation must be protected by rw-spinlocks to prevent       */
/* inconsistency and undefined behaviour in other concurrent functions.     */

/* register_fd_lists() */
/* register fd lists for device */

static int register_fd_lists(struct rsbac_device_list_item_t * device_p,
                             kdev_t kdev)
  {
    char                          * name;
    int                             err = 0;
    int                             tmperr;
    char                            number[16];
    u_int                           file_no;
    struct rsbac_list_info_t        info;
    struct rsbac_gen_fd_aci_t       def_gen_fd_aci  = DEFAULT_GEN_FD_ACI;
#if defined(CONFIG_RSBAC_MAC)
    struct rsbac_mac_fd_aci_t       def_mac_fd_aci  = DEFAULT_MAC_FD_ACI;
#endif
#if defined(CONFIG_RSBAC_FC)
           rsbac_fc_oc_t            def_fc_fd_aci = RSBAC_FC_OC_DEF;
#endif
#if defined(CONFIG_RSBAC_SIM)
           rsbac_sim_dt_t           def_sim_fd_aci = RSBAC_SIM_DT_DEF;
#endif
#if defined(CONFIG_RSBAC_PM)
    struct rsbac_pm_fd_aci_t        def_pm_fd_aci  = DEFAULT_PM_FD_ACI;
#endif
#if defined(CONFIG_RSBAC_MS)
    struct rsbac_ms_fd_aci_t        def_ms_fd_aci  = DEFAULT_MS_FD_ACI;
           rsbac_ms_scanned_t       def_ms_scanned_fd_aci = DEFAULT_MS_FD_SCANNED;
#endif
#if defined(CONFIG_RSBAC_FF)
           rsbac_ff_flags_t         def_ff_fd_aci  = RSBAC_FF_DEF;
#endif
#if defined(CONFIG_RSBAC_RC)
    struct rsbac_rc_fd_aci_t        def_rc_fd_aci  = DEFAULT_RC_FD_ACI;
#endif
#if defined(CONFIG_RSBAC_AUTH)
    struct rsbac_auth_fd_aci_t      def_auth_fd_aci  = DEFAULT_AUTH_FD_ACI;
#endif
#if defined(CONFIG_RSBAC_CAP)
    struct rsbac_cap_fd_aci_t       def_cap_fd_aci  = DEFAULT_CAP_FD_ACI;
#endif
    if(!device_p)
      return(-RSBAC_EINVALIDPOINTER);
    name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
    if(!name)
      return -RSBAC_ENOMEM;

    /* register general lists */
    for (file_no = 0; file_no < RSBAC_GEN_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_GEN_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_GEN_FD_ACI_VERSION;
        info.key = RSBAC_GEN_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(struct rsbac_gen_fd_aci_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.gen[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     gen_fd_get_conv,
                                     &def_gen_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering general list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }

#if defined(CONFIG_RSBAC_MAC)
    /* register MAC lists */
    for (file_no = 0; file_no < RSBAC_MAC_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_MAC_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_MAC_FD_ACI_VERSION;
        info.key = RSBAC_MAC_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(struct rsbac_mac_fd_aci_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.mac[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_mac_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering MAC list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_FC)
    /* register FC lists */
    for (file_no = 0; file_no < RSBAC_FC_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_FC_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_FC_FD_ACI_VERSION;
        info.key = RSBAC_FC_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(rsbac_fc_oc_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.fc[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_fc_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering FC list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_SIM)
    /* register SIM lists */
    for (file_no = 0; file_no < RSBAC_SIM_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_SIM_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_SIM_FD_ACI_VERSION;
        info.key = RSBAC_SIM_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(rsbac_sim_dt_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.sim[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_sim_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering SIM list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_PM)
    /* register PM lists */
    for (file_no = 0; file_no < RSBAC_PM_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_PM_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_PM_FD_ACI_VERSION;
        info.key = RSBAC_PM_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(struct rsbac_pm_fd_aci_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.pm[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_pm_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering PM list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_MS)
    /* register MS lists */
    for (file_no = 0; file_no < RSBAC_MS_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_MS_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_MS_FD_ACI_VERSION;
        info.key = RSBAC_MS_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(struct rsbac_ms_fd_aci_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.ms[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST |
                                     RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_ms_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering MS list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
    /* register MS scanned lists */
    for (file_no = 0; file_no < RSBAC_MS_SCANNED_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_MS_SCANNED_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_MS_SCANNED_FD_ACI_VERSION;
        info.key = RSBAC_MS_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(rsbac_ms_scanned_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.mss[file_no]),
                                     info,
                                     #ifdef CONFIG_RSBAC_MS_PERSIST
                                     RSBAC_LIST_PERSIST |
                                     #endif
                                     RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_ms_scanned_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering MS scanned list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_FF)
    /* register FF lists */
    for (file_no = 0; file_no < RSBAC_FF_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_FF_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_FF_FD_ACI_VERSION;
        info.key = RSBAC_FF_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(rsbac_ff_flags_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.ff[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_ff_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering FF list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_RC)
    /* register RC lists */
    for (file_no = 0; file_no < RSBAC_RC_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_RC_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_RC_FD_ACI_VERSION;
        info.key = RSBAC_RC_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(struct rsbac_rc_fd_aci_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.rc[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_rc_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering RC list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_AUTH)
    /* register AUTH lists */
    for (file_no = 0; file_no < RSBAC_AUTH_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_AUTH_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_AUTH_FD_ACI_VERSION;
        info.key = RSBAC_AUTH_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(struct rsbac_auth_fd_aci_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.auth[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_auth_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering AUTH list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_CAP)
    /* register CAP lists */
    for (file_no = 0; file_no < RSBAC_CAP_NR_FD_LISTS; file_no++)
      {
        /* construct name from base name + number */
        strcpy(name, RSBAC_CAP_FD_NAME);
        strcat(name, inttostr(number,file_no) );

        info.version = RSBAC_CAP_FD_ACI_VERSION;
        info.key = RSBAC_CAP_FD_ACI_KEY;
        info.desc_size = sizeof(rsbac_inode_nr_t);
        info.data_size = sizeof(struct rsbac_cap_fd_aci_t);
        info.max_age = 0;
        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
                                     &(device_p->handles.cap[file_no]),
                                     info,
                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                     rsbac_list_compare_u32,
                                     NULL,
                                     &def_cap_fd_aci,
                                     name,
                                     kdev);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "register_fd_lists(): registering CAP list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(kdev),
                       MINOR(kdev),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

    return err;
  }

/* aci_detach_fd_lists() */
/* detach from fd lists for device */

static int aci_detach_fd_lists(struct rsbac_device_list_item_t * device_p)
  {
    int                             err = 0;
    int                             tmperr;
    u_int                           file_no;

    if(!device_p)
      return(-RSBAC_EINVALIDPOINTER);

    /* detach all general lists */
    for (file_no = 0; file_no < RSBAC_GEN_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.gen[file_no],
                                   RSBAC_GEN_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from general list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }

#if defined(CONFIG_RSBAC_MAC)
    /* detach all MAC lists */
    for (file_no = 0; file_no < RSBAC_MAC_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.mac[file_no],
                                   RSBAC_MAC_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from MAC list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_FC)
    /* detach all FC lists */
    for (file_no = 0; file_no < RSBAC_FC_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.fc[file_no],
                                   RSBAC_FC_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from FC list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_SIM)
    /* detach all SIM lists */
    for (file_no = 0; file_no < RSBAC_SIM_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.sim[file_no],
                                   RSBAC_SIM_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from SIM list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_PM)
    /* detach all PM lists */
    for (file_no = 0; file_no < RSBAC_PM_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.pm[file_no],
                                   RSBAC_PM_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from PM list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_MS)
    /* detach all MS lists */
    for (file_no = 0; file_no < RSBAC_MS_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.ms[file_no],
                                   RSBAC_MS_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from MS list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
    /* detach all MS scanned lists */
    for (file_no = 0; file_no < RSBAC_MS_SCANNED_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.mss[file_no],
                                   RSBAC_MS_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from MS scanned list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_FF)
    /* detach all FF lists */
    for (file_no = 0; file_no < RSBAC_FF_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.ff[file_no],
                                   RSBAC_FF_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from FF list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_RC)
    /* detach all RC lists */
    for (file_no = 0; file_no < RSBAC_RC_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.rc[file_no],
                                   RSBAC_RC_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from RC list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_AUTH)
    /* detach all AUTH lists */
    for (file_no = 0; file_no < RSBAC_AUTH_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.auth[file_no],
                                   RSBAC_AUTH_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from AUTH list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

#if defined(CONFIG_RSBAC_CAP)
    /* detach all CAP lists */
    for (file_no = 0; file_no < RSBAC_CAP_NR_FD_LISTS; file_no++)
      {
        tmperr = rsbac_list_detach(&device_p->handles.cap[file_no],
                                   RSBAC_CAP_FD_ACI_KEY);
        if(tmperr)
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "detach_fd_lists(): detaching from CAP list %u for device %02u:%02u failed with error %s!\n",
                       file_no,
                       MAJOR(device_p->id),
                       MINOR(device_p->id),
                       get_error_name(tmp, tmperr));
                rsbac_kfree(tmp);
              }
            err = tmperr;
          }
      }
#endif

    return err;
  }


/* Create a device item without adding to list. No locking needed. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
static struct rsbac_device_list_item_t 
          * create_device_item(struct super_block * sb_p)
#else
static struct rsbac_device_list_item_t 
          * create_device_item(struct super_block * sb_p, struct dentry * d_covers)
#endif
    {
      struct rsbac_device_list_item_t * new_item_p;

      if(!sb_p)
        return NULL;
      /* allocate memory for new device, return NULL, if failed */
      if ( !(new_item_p = (struct rsbac_device_list_item_t *)
                    rsbac_kmalloc(sizeof(*new_item_p)) ) )
         return(NULL);

      memset(new_item_p, 0, sizeof(*new_item_p));
      new_item_p->id = sb_p->s_dev;
      new_item_p->sb_p = sb_p;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      new_item_p->d_covers = d_covers;
      new_item_p->mount_count = 1;
#endif
      /* everything else is 0 by memset -> return */
      return(new_item_p);
    };

/* Add an existing device item to list. Locking needed. */
static struct rsbac_device_list_item_t 
          * add_device_item(struct rsbac_device_list_item_t * device_p)
    {
      if (!device_p)
         return(NULL);
         
      /* add new device to device list */
      if (!device_list_head.head)
        { /* first device */
          device_list_head.head=device_p;
          device_list_head.tail=device_p;
          device_list_head.curr=device_p;
          device_list_head.count=1;
          device_p->prev=NULL;
          device_p->next=NULL;
        }  
      else
        { /* there is another device -> hang to tail */
          device_p->prev=device_list_head.tail;
          device_p->next=NULL;
          device_list_head.tail->next=device_p;
          device_list_head.tail=device_p;
          device_list_head.curr=device_p;
          device_list_head.count++;
        };
      return(device_p);
    };

/************************************************************************** */
/* The remove_item() functions remove an item from the list. If this item   */
/* is head, tail or curr, these pointers are set accordingly.               */
/* To speed up removing several subsequent items, curr is set to the next   */
/* item, if possible.                                                       */
/* If the item is not found, nothing is done.                               */

static void clear_device_item(struct rsbac_device_list_item_t * item_p)
  {
    if(!item_p)
      return;

    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    /* dput() rsbac_dir_dentry_p, if set */
    if(item_p->rsbac_dir_dentry_p)
      dput(item_p->rsbac_dir_dentry_p);
    #endif
    /* OK, lets remove the device item itself */
    rsbac_kfree(item_p);
  }; /* end of clear_device_item() */

static void remove_device_item(kdev_t kdev)
    {
      struct rsbac_device_list_item_t   * item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_device(kdev)) )
        { /* ok, item was found */
          if (device_list_head.head == item_p)  
             { /* item is head */
               if (device_list_head.tail == item_p)
                 { /* item is head and tail = only item -> list will be empty*/
                   device_list_head.head = NULL;
                   device_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   device_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if (device_list_head.tail == item_p)
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   device_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset.                              */
          device_list_head.curr=NULL;
          /* adjust counter */
          device_list_head.count--;

          /* clean up */
          aci_detach_fd_lists(item_p);

          /* clear item */
          clear_device_item(item_p);
        };  /* end of if: item was found */

    }; /* end of remove_device_item() */

/**************************************************/
/*       Externally visible help functions        */
/**************************************************/

/* helper, copied from open.d/do_truncate() */
static int rsbac_clear_file(struct dentry *dentry)
{
	struct inode *inode = dentry->d_inode;
	int error;
	struct iattr newattrs;

	down(&inode->i_sem);
	newattrs.ia_size = 0;
	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
	error = notify_change(dentry, &newattrs);
	up(&inode->i_sem);
	return error;
}

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_get_super_block);
#endif
struct super_block * rsbac_get_super_block(kdev_t kdev)
  {
    struct rsbac_device_list_item_t * device_p;
    u_long dflags;
    struct super_block * sb_p;

    if(!kdev)
      return NULL;

    /* get super_block-pointer */
    rsbac_read_lock(&device_list_head.lock, &dflags);
    device_p = lookup_device(kdev);
    if (!device_p)
      {
        printk(KERN_WARNING
               "rsbac_get_super_block(): unknown device %02u:%02u\n",
               MAJOR(kdev), MINOR(kdev));
        rsbac_read_unlock(&device_list_head.lock, &dflags);
        return NULL;
      }
    sb_p = device_p->sb_p;
    rsbac_read_unlock(&device_list_head.lock, &dflags);
    return sb_p;
  }

static int rsbac_read_open_device_p(char * name,
                                    struct file  *  file_p,
                                    kdev_t kdev,
                                    struct rsbac_device_list_item_t * device_p)
  {
    struct dentry                 * dir_dentry_p;
    struct dentry                 * file_dentry_p;
    struct file                     file;
    int                             tmperr, err;

    if(!name || !file_p)
      {
#ifdef CONFIG_RSBAC_DEBUG
        if (rsbac_debug_ds)
          printk(KERN_WARNING "rsbac_read_open(): called with NULL pointer!");
#endif
        return(-RSBAC_EINVALIDPOINTER);
      }

    if(!device_p)
      {
        u_long dflags;

        rsbac_read_lock(&device_list_head.lock, &dflags);
        device_p = lookup_device(kdev);
        if(!device_p)
          {
            rsbac_read_unlock(&device_list_head.lock, &dflags);
            return -RSBAC_EINVALIDDEV;
          }
        /* lookup dentry of ACI_PATH on root device, returns errorcode, if   */
        if ((err=lookup_aci_path_dentry(device_p->sb_p, &dir_dentry_p, FALSE, device_p)))
          {
            rsbac_read_unlock(&device_list_head.lock, &dflags);
            return(err);
          }
        rsbac_read_unlock(&device_list_head.lock, &dflags);
      }
    else
      {
        /* lookup dentry of ACI_PATH on root device, returns errorcode, if   */
        if ((err=lookup_aci_path_dentry(device_p->sb_p, &dir_dentry_p, FALSE, device_p)))
          return(err);
      }

    /* open file for reading - this must be done 'by hand', because     */
    /* standard system calls are now extended by rsbac decision calls.  */
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    file_dentry_p = rsbac_lookup_dentry(name, dget(dir_dentry_p), 0);
    #else
    file_dentry_p = rsbac_lookup_one_len(name, dir_dentry_p, strlen(name));
    #endif
    if (!file_dentry_p || IS_ERR (file_dentry_p))
      { /* error in lookup */
        return(-RSBAC_EREADFAILED);
      }
    if (!file_dentry_p->d_inode)
      { /* file not found: trying backup */
        char * bname;
        int  name_len = strlen(name);

        dput(file_dentry_p);
        bname = rsbac_kmalloc(RSBAC_MAXNAMELEN);
        if(!bname)
          {
            return -RSBAC_ENOMEM;
          }

        strcpy(bname,name);
        bname[name_len] = 'b';
        name_len++;
        bname[name_len] = (char) 0;
#ifdef CONFIG_RSBAC_DEBUG
        if (rsbac_debug_ds)
          printk(KERN_DEBUG "rsbac_read_open(): could not lookup file %s, trying backup %s\n",
                 name,bname);
#endif
        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        file_dentry_p = rsbac_lookup_dentry(bname, dget(dir_dentry_p), 0);
        #else
        file_dentry_p = rsbac_lookup_one_len(bname, dir_dentry_p, strlen(bname));
        #endif
        rsbac_kfree(bname);
        if (!file_dentry_p || IS_ERR (file_dentry_p))
          { /* error in lookup */
            return(-RSBAC_EREADFAILED);
          }
        if (!file_dentry_p->d_inode)
          { /* backup file also not found: return error */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG "rsbac_read_open(): could not lookup backup file %sb\n",
                     name);
#endif
            dput(file_dentry_p);
            return(-RSBAC_ENOTFOUND);
          }
      }
    if ( !(S_ISREG(file_dentry_p->d_inode->i_mode)) )
      { /* this is not a file! -> error! */
        printk(KERN_WARNING "rsbac_read_open(): expected file is not a file!\n");
        dput(file_dentry_p);
        return(-RSBAC_EREADFAILED);
      }

    /* Now we fill the file structure and */
    /* if there is an open func for this file, use it, otherwise ignore */
    if ((tmperr = init_private_file(&file, file_dentry_p,O_RDONLY)))
      {
        dput(file_dentry_p);
        printk(KERN_WARNING "rsbac_read_open(): could not open file '%s'!\n", name);
        return -RSBAC_EREADFAILED;
      }

    /* if there is no read func, we get a problem -> error */
    if ((!file.f_op) || (!file.f_op->read))
      {
        if (!file.f_op)
          printk(KERN_WARNING "rsbac_read_open(): no f_op for file '%s'!\n", name);
        else
          {
            printk(KERN_WARNING "rsbac_read_open(): no file read func for file '%s'!\n", name);
            if (file.f_op->release)
              file.f_op->release(file_dentry_p->d_inode,&file);
          }
        dput(file_dentry_p);
        return -RSBAC_EREADFAILED;
      }
    *file_p = file;
    return 0;
  } /* end of rsbac_read_open_device_p */

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_read_open);
#endif
int  rsbac_read_open(char * name,
                     struct file  *  file_p,
                     kdev_t kdev)
  {
    return rsbac_read_open_device_p(name, file_p, kdev, NULL);
  }

#ifndef check_parent
#define check_parent(dir, dentry) \
	((dir) == (dentry)->d_parent && !list_empty(&dentry->d_hash))
#endif

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_write_open);
#endif
int  rsbac_write_open(char * name,
                      struct file  *  file_p,
                      kdev_t kdev)
  {
    struct dentry                   * dir_dentry_p = NULL;
    struct dentry                   * ldir_dentry_p = NULL;
    struct dentry                   * file_dentry_p = NULL;
    struct file                       file;
    int                               err = 0;
    int                               tmperr = 0;
    struct super_block              * sb_p;
    
        if(!file_p || !name)
          {
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_write)
              printk(KERN_DEBUG "rsbac_write_open(): called with NULL pointer!\n");
#endif
            return(-RSBAC_EINVALIDPOINTER);
          }

        /* get super_block-pointer */
        sb_p = rsbac_get_super_block(kdev);
        if (!sb_p)
          {
            printk(KERN_WARNING
                   "rsbac_write_open(): invalid device %02u:%02u\n",
                   MAJOR(kdev), MINOR(kdev));
            return (-RSBAC_EINVALIDDEV);
          }
        if(!writable(sb_p))
          {
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_write)
              printk(KERN_DEBUG
                     "rsbac_write_open(): called for non-writable device\n");
#endif
            err = -RSBAC_ENOTWRITABLE;
            goto out;
          }
          
        /* lookup dentry of ACI_PATH on this device (create, if needed and possible),
         * returns errorcode, if failed */
        if ((tmperr = lookup_aci_path_dentry(sb_p, &dir_dentry_p, TRUE,
                                             lookup_device(kdev))))
          {
            err = tmperr;
            goto out;
          }

        /* open file for reading - this must be done 'by hand', because     */
        /* standard system calls are now extended by rsbac decision calls.  */
        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        file_dentry_p = rsbac_lookup_dentry(name, dget(dir_dentry_p), 0);
        #else
        file_dentry_p = rsbac_lookup_one_len(name, dir_dentry_p, strlen(name));
        #endif
        if (!file_dentry_p || IS_ERR(file_dentry_p))
          {
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_write)
              printk(KERN_DEBUG
                     "rsbac_write_open(): lookup of %s returned error %li\n",
                     name, PTR_ERR(file_dentry_p));
#endif
            err = -RSBAC_EWRITEFAILED;
            goto out;
          }

#if 1
        if (file_dentry_p->d_inode)
          { /* file was found: try to rename it as backup file */
            if (   !dir_dentry_p->d_inode->i_op
                || !dir_dentry_p->d_inode->i_op->rename)
              {
                printk(KERN_WARNING
                       "rsbac_write_open(): File system supports no rename - no backup of %s made!",
                       name);
              }
            else
              {
                char * bname;
                int  name_len = strlen(name);
                struct dentry * new_file_dentry_p = NULL;
                struct dentry * old_dir_p, * new_dir_p;

                bname = rsbac_kmalloc(RSBAC_MAXNAMELEN);
                if(!bname)
                  {
                    err = -RSBAC_ENOMEM;
                    goto out_dput;
                  }
                strcpy(bname,name);
                bname[name_len] = 'b';
                bname[name_len+1] = (char) 0;
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                new_file_dentry_p = rsbac_lookup_dentry(bname,
                                                        dget(dir_dentry_p),
                                                        0);
                #else
                new_file_dentry_p = rsbac_lookup_one_len(bname, dir_dentry_p, strlen(bname));
                #endif
                if(new_file_dentry_p && !IS_ERR(new_file_dentry_p))
                  {
                    /* lock parent == rsbac-dir for rest of rename */
                    old_dir_p = dget(file_dentry_p->d_parent);
                    new_dir_p = dget(new_file_dentry_p->d_parent);
                    double_lock(new_dir_p, old_dir_p);

                    DQUOT_INIT(old_dir_p->d_inode);
                    DQUOT_INIT(new_dir_p->d_inode);
                    /* try to rename file in rsbac dir */
                    /* if (rsbac_debug_write)
                     * printk(KERN_DEBUG "rsbac_write_open(): calling rename function\n");
                     */
                    err = dir_dentry_p->d_inode->i_op->rename(old_dir_p->d_inode,
                                                              file_dentry_p,
                                                              new_dir_p->d_inode,
                                                              new_file_dentry_p);
                    /* unlock dir (dputs both dentries) */
                    double_unlock(new_dir_p, old_dir_p);
                    if(err)
                      {
                        printk(KERN_WARNING
                               "rsbac_write_open(): could not rename %s to %s on dev %02u:%02u, error %i - no backup!\n",
                               name,bname, MAJOR(kdev),MINOR(kdev), err);
                      }
                    else
                      {
                        /* The following d_move() should become unconditional */
             #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                        if (!(sb_p->s_flags & MS_ODD_RENAME))
                          d_move(file_dentry_p, new_file_dentry_p);
             #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,12)
                        if (!(sb_p->s_type->fs_flags & FS_ODD_RENAME))
                          d_move(file_dentry_p, new_file_dentry_p);
                        inode_dir_notify(old_dir_p->d_inode, DN_RENAME);
             #else
                        if (!(sb_p->s_flags & FS_ODD_RENAME))
                          d_move(file_dentry_p, new_file_dentry_p);
             #endif
                      }
                    dput(new_file_dentry_p);
                    dput(file_dentry_p);
                    /* re-init dentry structure */
                    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                    file_dentry_p = rsbac_lookup_dentry(name,
                                                        dget(dir_dentry_p),
                                                        0);
                    #else
                    file_dentry_p = rsbac_lookup_one_len(name, dir_dentry_p, strlen(name));
                    #endif
                    if (!file_dentry_p || IS_ERR (file_dentry_p))
                      {
#ifdef CONFIG_RSBAC_DEBUG
                        if (rsbac_debug_write)
                          printk(KERN_DEBUG
                                 "rsbac_write_open(): relookup of %s returned error %li\n",
                                 name, PTR_ERR(file_dentry_p));
#endif
                        err = -RSBAC_EWRITEFAILED;
                        goto out;
                      }
                    if (file_dentry_p->d_inode)
                      {
                        printk(KERN_WARNING
                               "rsbac_write_open(): relookup of %s returned dentry with existing inode %li, trying unlink\n",
                               name, file_dentry_p->d_inode->i_ino);
                        /* file was found: try to delete it */
                        if (   !dir_dentry_p->d_inode->i_op
                            || !dir_dentry_p->d_inode->i_op->unlink)
                          {
                            printk(KERN_WARNING
                                   "rsbac_write_open(): File system supports no unlink - %s not deleted!",
                                   name);
                            rsbac_kfree(bname);
                            err = -RSBAC_EWRITEFAILED;
                            goto out_dput;
                          }
                        else
                          {
                            old_dir_p = lock_parent(file_dentry_p);

                            DQUOT_INIT(old_dir_p->d_inode);
                            err = -ENOENT;
                            if (check_parent(old_dir_p, file_dentry_p))
                              {
                                err = dir_dentry_p->d_inode->i_op->unlink(old_dir_p->d_inode,
                                                                          file_dentry_p);
                              }
                            else
                              {
                                printk(KERN_WARNING
                                       "rsbac_write_open(): could not unlink %s on dev %02u:%02u, parent check failed!\n",
                                       name, MAJOR(kdev),MINOR(kdev));
                              }
                            /* unlock parent dir */
                            unlock_dir(old_dir_p);
                            /* free file dentry */
                            dput(file_dentry_p);
                            if(err)
                              {
                                printk(KERN_WARNING
                                       "rsbac_write_open(): could not unlink %s on dev %02u:%02u, error %i!\n",
                                       name, MAJOR(kdev),MINOR(kdev), err);
                              }
                            /* re-init dentry structure */
                            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                            file_dentry_p = rsbac_lookup_dentry(name,
                                                                dget(dir_dentry_p),
                                                                0);
                            #else
                            file_dentry_p = rsbac_lookup_one_len(name, dir_dentry_p, strlen(name));
                            #endif
                            if (!file_dentry_p || IS_ERR (file_dentry_p))
                              {
#ifdef CONFIG_RSBAC_DEBUG
                                if (rsbac_debug_write)
                                  printk(KERN_DEBUG
                                         "rsbac_write_open(): relookup of %s returned error %li\n",
                                         name, PTR_ERR(file_dentry_p));
#endif
                                rsbac_kfree(bname);
                                err = -RSBAC_EWRITEFAILED;
                                goto out;
                              }
                            if (new_file_dentry_p->d_inode)
                              {
                                printk(KERN_WARNING
                                       "rsbac_write_open(): relookup of %s returned dentry with existing inode %li\n",
                                       name, file_dentry_p->d_inode->i_ino);
                                rsbac_kfree(bname);
                                err = -RSBAC_EWRITEFAILED;
                                goto out_dput;
                              }
                          }
                      }
                  }
                else
                  {
                    printk(KERN_WARNING
                           "rsbac_write_open(): rsbac_lookup_(dentry|one) for backup file %s on dev %02u:%02u failed with error %li - no backup!\n",
                           bname, MAJOR(kdev),MINOR(kdev), PTR_ERR(new_file_dentry_p));
                  }
                rsbac_kfree(bname);
              }
          }
#endif /* backup part */

        if(!file_dentry_p->d_inode)
          {
            /* file not found or renamed away: try to create a new one */
            if (   !dir_dentry_p->d_inode->i_op
                || !dir_dentry_p->d_inode->i_op->create)
              {
                printk(KERN_WARNING "%s\n",
                       "rsbac_write_open(): File system supports no create!");
                       err = -RSBAC_EWRITEFAILED;
                       goto out_dput;
              }

            /* lock parent == rsbac-dir for create */
            ldir_dentry_p = lock_parent(file_dentry_p);
            if(IS_ERR(ldir_dentry_p))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_write)
                  printk(KERN_DEBUG
                         "rsbac_write_open(): lock_parent of %s returned error %li\n",
                         name, PTR_ERR(ldir_dentry_p));
#endif
                err = -RSBAC_EWRITEFAILED;
                goto out_dput;
              }
            if (!check_parent(ldir_dentry_p, file_dentry_p))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_write)
                  printk(KERN_DEBUG
                         "rsbac_write_open(): check_parent of %s returned error\n",
                         name);
#endif
                unlock_dir(ldir_dentry_p);
                dput(file_dentry_p);
                err = -RSBAC_EWRITEFAILED;
              }
            /* try to create file in rsbac dir */
            /* if (rsbac_debug_write)
             *   printk(KERN_DEBUG "%s\n",
             *          "rsbac_write_open(): calling create function");
             */
            DQUOT_INIT(ldir_dentry_p->d_inode);
            err = dir_dentry_p->d_inode->i_op->create(ldir_dentry_p->d_inode,
                                                      file_dentry_p,
                                                      RSBAC_ACI_FILE_MODE);
            unlock_dir(ldir_dentry_p);

            if (err)
              {
                goto out_dput;
              }
            /* create was successful */
          }

        if ( !(S_ISREG(file_dentry_p->d_inode->i_mode)) )
          { /* this is not a file! -> error! */
            printk(KERN_WARNING
                   "rsbac_write_open(): expected file is not a file, mode is %o!\n",
                   file_dentry_p->d_inode->i_mode);
            err = -RSBAC_EWRITEFAILED;
            goto out_dput;
          }
        /* Now we fill the file structure and */
        /* if there is an open func for this file, use it, otherwise ignore */
        if ((tmperr = init_private_file(&file, file_dentry_p,O_RDONLY)))
          {
            printk(KERN_WARNING "rsbac_write_open(): could not init file!\n");
            err = -RSBAC_EWRITEFAILED;
            goto out_dput;
          }

        /* Without a write function we get into troubles -> error */
	if ((!file.f_op) || (!file.f_op->write))
	  {
            printk(KERN_WARNING
                   "rsbac_write_open(): file write function missing!\n");
            if(file.f_op && file.f_op->release)
              {
                  file.f_op->release(file_dentry_p->d_inode,&file);
              }
            err = -RSBAC_EWRITEFAILED;
            goto out_dput;
	  }

        /* trying to get write access                                   */
        /* if (rsbac_debug_write)
         *   printk(KERN_DEBUG "rsbac_write_open(): trying to get write access!\n");
         */
        if (get_write_access(file_dentry_p->d_inode))
	  {
            printk(KERN_WARNING
                   "rsbac_write_open(): could not get write access!\n");
            if (file.f_op->release)
              file.f_op->release(file_dentry_p->d_inode,&file);
            err = -RSBAC_EWRITEFAILED;
            goto out_dput;
	  }
	/* truncating */
	if(rsbac_clear_file(file_dentry_p))
	  {
            if (file.f_op->release)
              file.f_op->release(file_dentry_p->d_inode,&file);
	    put_write_access(file_dentry_p->d_inode);
            printk(KERN_WARNING
                   "rsbac_write_open(): could not truncate!\n");
            err = -RSBAC_EWRITEFAILED;
            goto out_dput;
          }
    /* set synchronous mode for this file */
    file.f_flags |= O_SYNC;

    *file_p = file;

out:
    return err;

out_dput:
    dput(file_dentry_p);
    goto out;
  }


#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_read_close);
#endif
void rsbac_read_close(struct file * file_p)
  {
        /* cleanup copied from __fput */
	struct dentry * dentry = file_p->f_dentry;
	struct inode * inode = dentry->d_inode;

	if (file_p->f_op && file_p->f_op->release)
		file_p->f_op->release(inode, file_p);
	file_p->f_dentry = NULL;
	if (file_p->f_mode & FMODE_WRITE)
		put_write_access(inode);
	dput(dentry);
  }

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_write_close);
#endif
void rsbac_write_close(struct file * file_p)
  {
    rsbac_read_close(file_p);
  }

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_get_full_path);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
int rsbac_get_full_path(struct dentry * dentry_p, char path[], int maxlen)
  {
    int len=0;
    char * i_path;
    int   tmplen=0;

    if(!dentry_p || !path)
      return -RSBAC_EINVALIDPOINTER;
    if(maxlen <= 0)
      return -RSBAC_EINVALIDVALUE;
    i_path = rsbac_kmalloc(maxlen + RSBAC_MAXNAMELEN);
    if(!i_path)
      return -RSBAC_ENOMEM;
    
    path[0] = 0;

    while(dentry_p && (len<maxlen) && dentry_p->d_name.len && dentry_p->d_name.name)
      {
        tmplen = dentry_p->d_covers->d_name.len;
        if((tmplen+1) > (maxlen-len))
          {
            rsbac_kfree(i_path);
            return(len);
          }
        strncpy(i_path, dentry_p->d_covers->d_name.name, tmplen);
        if(len && (i_path[tmplen-1] != '/'))
          {
            i_path[tmplen] = '/';
            tmplen++;
          }
        i_path[tmplen]=0;
        strcat(i_path, path);
        strcpy(path, i_path);
        len += tmplen;
        if(   dentry_p->d_covers
           && dentry_p->d_covers->d_parent
           && (dentry_p->d_covers->d_parent != dentry_p)
          )
          dentry_p = dentry_p->d_covers->d_parent;
        else
          break;
      }
    rsbac_kfree(i_path);
    return(len);
  };
#else
int rsbac_get_full_path(struct dentry * dentry_p, char path[], int maxlen)
  {
    int len=0;
    char * i_path;
    int   tmplen=0;

    if(!dentry_p || !path)
      return -RSBAC_EINVALIDPOINTER;
    if(maxlen <= 0)
      return -RSBAC_EINVALIDVALUE;
    i_path = rsbac_kmalloc(maxlen + RSBAC_MAXNAMELEN);
    if(!i_path)
      return -RSBAC_ENOMEM;

    path[0] = 0;

    while(dentry_p && (len<maxlen) && dentry_p->d_name.len && dentry_p->d_name.name)
      {
        tmplen = dentry_p->d_name.len;
        if((tmplen+1) > (maxlen-len))
          {
            rsbac_kfree(i_path);
            return(len);
          }
        strncpy(i_path, dentry_p->d_name.name, tmplen);
        if(len && (i_path[tmplen-1] != '/'))
          {
            i_path[tmplen] = '/';
            tmplen++;
          }
        i_path[tmplen]=0;
        strcat(i_path, path);
        strcpy(path, i_path);
        len += tmplen;
        if(   dentry_p->d_parent
           && (dentry_p->d_parent != dentry_p)
           && (dentry_p->d_sb->s_root != dentry_p)
          )
          dentry_p = dentry_p->d_parent;
        else
          {
            struct rsbac_device_list_item_t * device_p;

            device_p = lookup_device(dentry_p->d_inode->i_dev);
            if(   device_p
               && device_p->d_covers
              )
              dentry_p = device_p->d_covers;
            else
              break;
          }
      }
    rsbac_kfree(i_path);
    return(len);
  };
#endif

/************************************************* */
/*               proc fs functions                 */
/************************************************* */

#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
static int
devices_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
#else
static int
devices_proc_info(char *buffer, char **start, off_t offset, int length)
#endif
{
  int len = 0;
  off_t pos   = 0;
  off_t begin = 0;
  struct rsbac_device_list_item_t   * device_p;
  u_long dflags;

  if (!rsbac_initialized) return (-ENOSYS);

  len += sprintf(buffer, "%u RSBAC Devices\n---------------\n",
                 device_list_head.count);

  /* wait for read access to device_list_head */
  rsbac_read_lock(&device_list_head.lock, &dflags);
  /* OK, go on */
  for (device_p = device_list_head.head; device_p; device_p = device_p->next)
    {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      if(device_p->sb_p && device_p->sb_p->s_type && device_p->sb_p->s_type->name)
        len += sprintf(buffer + len, "%02u:%02u with fs_type = %s\n",
                       MAJOR(device_p->id), MINOR(device_p->id),
                       device_p->sb_p->s_type->name);
      else
        len += sprintf(buffer + len, "%02u:%02u\n",
                       MAJOR(device_p->id), MINOR(device_p->id));
#else
      if(device_p->sb_p && device_p->sb_p->s_type && device_p->sb_p->s_type->name)
        len += sprintf(buffer + len, "%02u:%02u with mount_count = %u, d_covers = %p, fs_type = %s\n",
                       MAJOR(device_p->id), MINOR(device_p->id),
                       device_p->mount_count,
                       device_p->d_covers,
                       device_p->sb_p->s_type->name);
      else
        len += sprintf(buffer + len, "%02u:%02u with mount_count = %u, d_covers = %p\n",
                       MAJOR(device_p->id), MINOR(device_p->id),
                       device_p->mount_count,
                       device_p->d_covers);
#endif
      pos = begin + len;
      if (pos < offset)
        {
          len = 0;
          begin = pos;
        }
      if (pos > offset+length) break;
    }
  
  /* free access to device_list_head */
  rsbac_read_unlock(&device_list_head.lock, &dflags);

  *start = buffer + (offset - begin);
  len -= (offset - begin);
  
  if (len > length)
    len = length;
  return len;
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
static int
stats_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
#else
static int
stats_proc_info(char *buffer, char **start, off_t offset, int length)
#endif
{
    u_int len = 0;
    off_t pos   = 0;
    off_t begin = 0;
    struct rsbac_device_list_item_t   * device_p;
    int                                 i;
    u_long                              fd_count, fd_dev_count, fd_sum = 0;
    u_long                              sum = 0;
    u_long                              total_sum = 0;
    long                                tmp_count;
    u_long                              dflags;

    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;

    if (!rsbac_initialized) return (-ENOSYS);

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "stats_proc_info(): calling ADF\n");
#endif
    rsbac_target_id.scd = ST_rsbac;
    rsbac_attribute_value.dummy = 0;
    if (!rsbac_adf_request(R_GET_STATUS_DATA,
                           current->pid,
                           T_SCD,
                           rsbac_target_id,
                           A_none,
                           rsbac_attribute_value))
      {
        return -EPERM;
      }

#ifdef CONFIG_RSBAC_MAINT
    len = sprintf(buffer, "RSBAC Status\n------------\nRSBAC Version: %s (Maintenance Mode)\nSupported Modules:%s\n",
                   RSBAC_VERSION, compiled_modules);
#else
    len = sprintf(buffer, "RSBAC Status\n------------\nRSBAC Version: %s\nCompiled Modules:%s\n",
                   RSBAC_VERSION, compiled_modules);
#endif
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    #ifdef CONFIG_RSBAC_SWITCH
    {
      char * active_modules;

      active_modules = rsbac_kmalloc(RSBAC_MAXNAMELEN);
      if(active_modules)
        {
          active_modules[0] = (char) 0;
          #ifdef CONFIG_RSBAC_REG
          strcat(active_modules, " REG");
          #endif
          #ifdef CONFIG_RSBAC_MAC
          if(rsbac_switch_mac)
            #ifdef CONFIG_RSBAC_MAC_LIGHT
            strcat(active_modules, " MAC-L");
            #else
            strcat(active_modules, " MAC");
            #endif
          #endif
          #ifdef CONFIG_RSBAC_FC
          if(rsbac_switch_fc)
            strcat(active_modules, " FC");
          #endif
          #ifdef CONFIG_RSBAC_SIM
          if(rsbac_switch_sim)
            strcat(active_modules, " SIM");
          #endif
          #ifdef CONFIG_RSBAC_PM
          if(rsbac_switch_pm)
            strcat(active_modules, " PM");
          #endif
          #ifdef CONFIG_RSBAC_MS
          if(rsbac_switch_ms)
            strcat(active_modules, " MS");
          #endif
          #ifdef CONFIG_RSBAC_FF
          if(rsbac_switch_ff)
            strcat(active_modules, " FF");
          #endif
          #ifdef CONFIG_RSBAC_RC
          if(rsbac_switch_rc)
            strcat(active_modules, " RC");
          #endif
          #ifdef CONFIG_RSBAC_AUTH
          if(rsbac_switch_auth)
            strcat(active_modules, " AUTH");
          #endif
          #ifdef CONFIG_RSBAC_ACL
          if(rsbac_switch_acl)
            strcat(active_modules, " ACL");
          #endif
          #ifdef CONFIG_RSBAC_CAP
          if(rsbac_switch_cap)
            strcat(active_modules, " CAP");
          #endif
          len += sprintf(buffer+len, "Active Modules:  %s\n",
                         active_modules);
          rsbac_kfree(active_modules);
          pos = begin + len;
          if (pos < offset)
            {
              len = 0;
              begin = pos;
            }
          if (pos > offset+length)
            goto out;
        }
    }
    #else
      len += sprintf(buffer+len, "All modules active (no switching)\n");
      pos = begin + len;
      if (pos < offset)
        {
          len = 0;
          begin = pos;
        }
      if (pos > offset+length)
        goto out;
    #endif

    #ifdef CONFIG_RSBAC_SOFTMODE
    if(rsbac_softmode)
      {
        len += sprintf(buffer+len, "Softmode is enabled\n");
        pos = begin + len;
        if (pos < offset)
          {
            len = 0;
            begin = pos;
          }
        if (pos > offset+length)
          goto out;
      }
    else
      {
        len += sprintf(buffer+len, "Softmode is disabled\n");
        pos = begin + len;
        if (pos < offset)
          {
            len = 0;
            begin = pos;
          }
        if (pos > offset+length)
          goto out;
      }
    #endif

    len += sprintf(buffer+len, "\n");

    /* wait for read access to device_list_head */
    rsbac_read_lock(&device_list_head.lock, &dflags);
    /* OK, go on */
    device_p = device_list_head.head;
    if(device_p)
      len += sprintf(buffer + len, "FD items:\n");
    while (device_p)
      {
        fd_dev_count = 0;
        /* for all sublists */
        fd_count = 0;
        for (i=0; i < RSBAC_GEN_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.gen[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, "Dev %02u:%02u: %lu GEN",
                       MAJOR(device_p->id), MINOR(device_p->id), fd_count);
        fd_dev_count += fd_count;

#if defined(CONFIG_RSBAC_MAC)
        fd_count = 0;
        for (i=0; i < RSBAC_MAC_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.mac[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu MAC",
                       fd_count);
        fd_dev_count += fd_count;
#endif

#if defined(CONFIG_RSBAC_FC)
        fd_count = 0;
        for (i=0; i < RSBAC_FC_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.fc[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu FC",
                       fd_count);
        fd_dev_count += fd_count;
#endif

#if defined(CONFIG_RSBAC_SIM)
        fd_count = 0;
        for (i=0; i < RSBAC_SIM_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.sim[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu SIM",
                       fd_count);
        fd_dev_count += fd_count;
#endif

#if defined(CONFIG_RSBAC_PM)
        fd_count = 0;
        for (i=0; i < RSBAC_PM_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.pm[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu PM",
                       fd_count);
        fd_dev_count += fd_count;
#endif

#if defined(CONFIG_RSBAC_MS)
        fd_count = 0;
        for (i=0; i < RSBAC_MS_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.ms[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu MS",
                       fd_count);
        fd_dev_count += fd_count;
        fd_count = 0;
        for (i=0; i < RSBAC_MS_SCANNED_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.mss[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu MS_SCANNED",
                       fd_count);
        fd_dev_count += fd_count;
#endif

#if defined(CONFIG_RSBAC_FF)
        fd_count = 0;
        for (i=0; i < RSBAC_FF_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.ff[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu FF",
                       fd_count);
        fd_dev_count += fd_count;
#endif

#if defined(CONFIG_RSBAC_RC)
        fd_count = 0;
        for (i=0; i < RSBAC_RC_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.rc[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu RC",
                       fd_count);
        fd_dev_count += fd_count;
#endif

#if defined(CONFIG_RSBAC_AUTH)
        fd_count = 0;
        for (i=0; i < RSBAC_AUTH_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.auth[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu AUTH",
                       fd_count);
        fd_dev_count += fd_count;
#endif

#if defined(CONFIG_RSBAC_CAP)
        fd_count = 0;
        for (i=0; i < RSBAC_CAP_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.cap[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        len += sprintf(buffer + len, ", %lu CAP",
                       fd_count);
        fd_dev_count += fd_count;
#endif

        len += sprintf(buffer + len, ", %lu total\n",
                       fd_dev_count);
        pos = begin + len;
        if (pos < offset)
          {
            len = 0;
            begin = pos;
          }
        if (pos > offset+length)
          {
            /* free access to device_list_head */
            rsbac_read_unlock(&device_list_head.lock, &dflags);
            goto out;
          }
        fd_sum += fd_dev_count;
        device_p = device_p->next;
      };
    len += sprintf(buffer + len, "Sum of %u Devices with %lu fd-items\n\n",
                   device_list_head.count, fd_sum);
    total_sum += fd_sum;
    /* free access to device_list_head */
    rsbac_read_unlock(&device_list_head.lock, &dflags);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    
    /* dev lists */
    sum = 0;
    tmp_count = rsbac_list_count(dev_handles.gen);
    len += sprintf(buffer + len, "DEV: %lu GEN",
                   tmp_count);
    sum += tmp_count;
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(dev_handles.mac);
    len += sprintf(buffer + len, ", %lu MAC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(dev_handles.fc);
    len += sprintf(buffer + len, ", %lu FC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(dev_handles.sim);
    len += sprintf(buffer + len, ", %lu SIM",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(dev_handles.pm);
    len += sprintf(buffer + len, ", %lu PM",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(dev_handles.rc);
    len += sprintf(buffer + len, ", %lu RC",
                   tmp_count);
    sum += tmp_count;
#endif
    len += sprintf(buffer + len, ", %lu total\n",
                   sum);
    total_sum += sum;
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    /* ipc lists */
    sum = 0;
    len += sprintf(buffer + len, "IPC: 0 GEN");
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(ipc_handles.mac);
    len += sprintf(buffer + len, ", %lu MAC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(ipc_handles.fc);
    len += sprintf(buffer + len, ", %lu FC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(ipc_handles.sim);
    len += sprintf(buffer + len, ", %lu SIM",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(ipc_handles.pm);
    len += sprintf(buffer + len, ", %lu PM",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(ipc_handles.rc);
    len += sprintf(buffer + len, ", %lu RC",
                   tmp_count);
    sum += tmp_count;
#endif
    len += sprintf(buffer + len, ", %lu total\n",
                   sum);
    total_sum += sum;
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    /* user lists */
    sum = 0;
    tmp_count = rsbac_list_count(user_handles.gen);
    len += sprintf(buffer + len, "USER: %lu GEN",
                   tmp_count);
    sum += tmp_count;
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(user_handles.mac);
    len += sprintf(buffer + len, ", %lu MAC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(user_handles.fc);
    len += sprintf(buffer + len, ", %lu FC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(user_handles.sim);
    len += sprintf(buffer + len, ", %lu SIM",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(user_handles.pm);
    len += sprintf(buffer + len, ", %lu PM",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_MS)
    tmp_count = rsbac_list_count(user_handles.ms);
    len += sprintf(buffer + len, ", %lu MS",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FF)
    tmp_count = rsbac_list_count(user_handles.ff);
    len += sprintf(buffer + len, ", %lu FF",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(user_handles.rc);
    len += sprintf(buffer + len, ", %lu RC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_AUTH)
    tmp_count = rsbac_list_count(user_handles.auth);
    len += sprintf(buffer + len, ", %lu AUTH",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_CAP)
    tmp_count = rsbac_list_count(user_handles.cap);
    len += sprintf(buffer + len, ", %lu CAP",
                   tmp_count);
    sum += tmp_count;
#endif
    len += sprintf(buffer + len, ", %lu total\n",
                   sum);
    total_sum += sum;
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    /* process lists */
    sum = 0;
    tmp_count = rsbac_list_count(process_handles.gen);
    len += sprintf(buffer + len, "PROCESS: %lu GEN",
                   tmp_count);
    sum += tmp_count;
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(process_handles.mac);
    len += sprintf(buffer + len, ", %lu MAC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(process_handles.pm);
    len += sprintf(buffer + len, ", %lu PM",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_MS)
    tmp_count = rsbac_list_count(process_handles.ms);
    len += sprintf(buffer + len, ", %lu MS",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(process_handles.rc);
    len += sprintf(buffer + len, ", %lu RC",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_AUTH)
    tmp_count = rsbac_list_count(process_handles.auth);
    len += sprintf(buffer + len, ", %lu AUTH",
                   tmp_count);
    sum += tmp_count;
#endif
    len += sprintf(buffer + len, ", %lu total\n",
                   sum);
    total_sum += sum;
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

#if defined(CONFIG_RSBAC_NET_DEV)
    /* netdev lists */
    sum = 0;
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
    tmp_count = rsbac_list_count(netdev_handles.gen);
    len += sprintf(buffer + len, "NETDEV: %lu GEN, ",
                   tmp_count);
    sum += tmp_count;
#else
    len += sprintf(buffer + len, "NETDEV: ");
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(netdev_handles.rc);
    len += sprintf(buffer + len, "%lu RC, ",
                   tmp_count);
    sum += tmp_count;
#endif
    len += sprintf(buffer + len, "%lu total\n",
                   sum);
    total_sum += sum;
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

#endif

#if defined(CONFIG_RSBAC_NET_OBJ)
    /* net template list */
    tmp_count = rsbac_list_count(net_temp_handle);
    len += sprintf(buffer + len, "%lu Network Templates\n",
                   tmp_count);

    /* nettemp lists */
    sum = 0;
#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
    tmp_count = rsbac_list_count(nettemp_handles.gen);
    len += sprintf(buffer + len, "NETTEMP: %lu GEN, ",
                   tmp_count);
    sum += tmp_count;
#else
    len += sprintf(buffer + len, "NETTEMP: ");
#endif
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(nettemp_handles.mac);
    len += sprintf(buffer + len, "%lu MAC, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(nettemp_handles.fc);
    len += sprintf(buffer + len, "%lu FC, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(nettemp_handles.sim);
    len += sprintf(buffer + len, "%lu SIM, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(nettemp_handles.pm);
    len += sprintf(buffer + len, "%lu PM, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(nettemp_handles.rc);
    len += sprintf(buffer + len, "%lu RC, ",
                   tmp_count);
    sum += tmp_count;
#endif
    len += sprintf(buffer + len, "%lu total\n",
                   sum);
    total_sum += sum;
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    /* local netobj lists */
    sum = 0;
    len += sprintf(buffer + len, "LNETOBJ: ");
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(lnetobj_handles.mac);
    len += sprintf(buffer + len, "%lu MAC, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(lnetobj_handles.fc);
    len += sprintf(buffer + len, "%lu FC, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(lnetobj_handles.sim);
    len += sprintf(buffer + len, "%lu SIM, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(lnetobj_handles.pm);
    len += sprintf(buffer + len, "%lu PM, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_MS)
    tmp_count = rsbac_list_count(lnetobj_handles.ms);
    len += sprintf(buffer + len, "%lu MS, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(lnetobj_handles.rc);
    len += sprintf(buffer + len, "%lu RC, ",
                   tmp_count);
    sum += tmp_count;
#endif
    len += sprintf(buffer + len, "%lu total\n",
                   sum);
    total_sum += sum;
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    /* remote netobj lists */
    sum = 0;
    len += sprintf(buffer + len, "RNETOBJ: ");
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(rnetobj_handles.mac);
    len += sprintf(buffer + len, "%lu MAC, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(rnetobj_handles.fc);
    len += sprintf(buffer + len, "%lu FC, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(rnetobj_handles.sim);
    len += sprintf(buffer + len, "%lu SIM, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(rnetobj_handles.pm);
    len += sprintf(buffer + len, "%lu PM, ",
                   tmp_count);
    sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(rnetobj_handles.rc);
    len += sprintf(buffer + len, "%lu RC, ",
                   tmp_count);
    sum += tmp_count;
#endif
    len += sprintf(buffer + len, "%lu total\n",
                   sum);
    total_sum += sum;
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

#endif /* NET_OBJ */

    len += sprintf(buffer + len,
                   "Total sum of %lu registered rsbac-items\n",
                   total_sum);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    
    len += sprintf(buffer + len,
                   "\nadf_request calls:\nfile: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
                   rsbac_adf_request_count[T_FILE],
                   rsbac_adf_request_count[T_DIR],
                   rsbac_adf_request_count[T_FIFO],
                   rsbac_adf_request_count[T_SYMLINK],
                   rsbac_adf_request_count[T_DEV],
                   rsbac_adf_request_count[T_IPC],
                   rsbac_adf_request_count[T_SCD],
                   rsbac_adf_request_count[T_USER],
                   rsbac_adf_request_count[T_PROCESS],
                   rsbac_adf_request_count[T_NETDEV],
                   rsbac_adf_request_count[T_NETTEMP],
                   rsbac_adf_request_count[T_NETOBJ]);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    
    len += sprintf(buffer + len,
                   "adf_set_attr calls:\nfile: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
                   rsbac_adf_set_attr_count[T_FILE],
                   rsbac_adf_set_attr_count[T_DIR],
                   rsbac_adf_set_attr_count[T_FIFO],
                   rsbac_adf_set_attr_count[T_SYMLINK],
                   rsbac_adf_set_attr_count[T_DEV],
                   rsbac_adf_set_attr_count[T_IPC],
                   rsbac_adf_set_attr_count[T_SCD],
                   rsbac_adf_set_attr_count[T_USER],
                   rsbac_adf_set_attr_count[T_PROCESS],
                   rsbac_adf_set_attr_count[T_NETDEV],
                   rsbac_adf_set_attr_count[T_NETTEMP],
                   rsbac_adf_set_attr_count[T_NETOBJ]);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }

out:
  *start = buffer + (offset - begin);
  len -= (offset - begin);
  
  if (len > length)
    len = length;
  return len;
}

#ifdef CONFIG_RSBAC_XSTATS
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
static int
xstats_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
#else
static int
xstats_proc_info(char *buffer, char **start, off_t offset, int length)
#endif
{
    u_int len = 0;
    off_t pos   = 0;
    off_t begin = 0;
    int                                 i,j;
    char                                name[80];
    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;

    if (!rsbac_initialized) return (-ENOSYS);

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "xstats_proc_info(): calling ADF\n");
#endif
    rsbac_target_id.scd = ST_rsbac;
    rsbac_attribute_value.dummy = 0;
    if (!rsbac_adf_request(R_GET_STATUS_DATA,
                           current->pid,
                           T_SCD,
                           rsbac_target_id,
                           A_none,
                           rsbac_attribute_value))
      {
        return -EPERM;
      }

    len += sprintf(buffer,
                   "RSBAC ADF call Statistics\n-------------------------\nadf_request table:\n");
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    len += sprintf(buffer + len, "Request /\tFILE\tDIR\tFIFO\tSYMLINK\tDEV\tIPC\tSCD\tUSER\tPROCESS\tNETDEV\tNETTEMP\tNETOBJ\tNONE");
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    for(i=0;i<R_NONE;i++)
      {
        get_request_name(name, i);
        name[15]=0;
        len += sprintf(buffer + len, "\n%-14s\t",name);
        pos = begin + len;
        if (pos < offset)
          {
            len = 0;
            begin = pos;
          }
        if (pos > offset+length)
          goto out;
        for(j=0;j<=T_NONE;j++)
          {
            if(j == T_NETTEMP_NT)
              continue;
            len += sprintf(buffer + len, "%lu\t",
                           rsbac_adf_request_xcount[j][i]);
            pos = begin + len;
            if (pos < offset)
              {
                len = 0;
                begin = pos;
              }
            if (pos > offset+length)
              goto out;
          }
      }
    
    len += sprintf(buffer + len,
                   "\n\nadf_request calls:\nfile: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu, none: %lu\n",
                   rsbac_adf_request_count[T_FILE],
                   rsbac_adf_request_count[T_DIR],
                   rsbac_adf_request_count[T_FIFO],
                   rsbac_adf_request_count[T_SYMLINK],
                   rsbac_adf_request_count[T_DEV],
                   rsbac_adf_request_count[T_IPC],
                   rsbac_adf_request_count[T_SCD],
                   rsbac_adf_request_count[T_USER],
                   rsbac_adf_request_count[T_PROCESS],
                   rsbac_adf_request_count[T_NETDEV],
                   rsbac_adf_request_count[T_NETTEMP],
                   rsbac_adf_request_count[T_NETOBJ],
                   rsbac_adf_request_count[T_NONE]);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    len += sprintf(buffer+len,
                   "\n\nadf_set_attr table:\nRequest /\tFILE\tDIR\tFIFO\tSYMLINK\tDEV\tIPC\tSCD\tUSER\tPROCESS\tNETDEV\tNETTEMP\tNETOBJ\tNONE");
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    for(i=0;i<R_NONE;i++)
      {
        get_request_name(name, i);
        name[15]=0;
        len += sprintf(buffer + len, "\n%-14s\t",name);
        pos = begin + len;
        if (pos < offset)
          {
            len = 0;
            begin = pos;
          }
        if (pos > offset+length)
          goto out;
        for(j=0;j<=T_NONE;j++)
          {
            if(j == T_NETTEMP_NT)
              continue;
            len += sprintf(buffer + len, "%lu\t",
                           rsbac_adf_set_attr_xcount[j][i]);
            pos = begin + len;
            if (pos < offset)
              {
                len = 0;
                begin = pos;
              }
            if (pos > offset+length)
              goto out;
          }
      }
    
    len += sprintf(buffer + len,
                   "\n\nadf_set_attr calls:\nfile: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu, none: %lu\n",
                   rsbac_adf_set_attr_count[T_FILE],
                   rsbac_adf_set_attr_count[T_DIR],
                   rsbac_adf_set_attr_count[T_FIFO],
                   rsbac_adf_set_attr_count[T_SYMLINK],
                   rsbac_adf_set_attr_count[T_DEV],
                   rsbac_adf_set_attr_count[T_IPC],
                   rsbac_adf_set_attr_count[T_SCD],
                   rsbac_adf_set_attr_count[T_USER],
                   rsbac_adf_set_attr_count[T_PROCESS],
                   rsbac_adf_set_attr_count[T_NETDEV],
                   rsbac_adf_set_attr_count[T_NETTEMP],
                   rsbac_adf_set_attr_count[T_NETOBJ],
                   rsbac_adf_set_attr_count[T_NONE]);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    len += sprintf(buffer + len,
                   "\n\nData Structures:\nrsbac_get_attr calls:\nfile: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
                   get_attr_count[T_FILE],
                   get_attr_count[T_DIR],
                   get_attr_count[T_FIFO],
                   get_attr_count[T_SYMLINK],
                   get_attr_count[T_DEV],
                   get_attr_count[T_IPC],
                   get_attr_count[T_SCD],
                   get_attr_count[T_USER],
                   get_attr_count[T_PROCESS],
                   get_attr_count[T_NETDEV],
                   get_attr_count[T_NETTEMP],
                   get_attr_count[T_NETOBJ]);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    len += sprintf(buffer + len,
                   "\nrsbac_set_attr calls:\nfile: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
                   set_attr_count[T_FILE],
                   set_attr_count[T_DIR],
                   set_attr_count[T_FIFO],
                   set_attr_count[T_SYMLINK],
                   set_attr_count[T_DEV],
                   set_attr_count[T_IPC],
                   set_attr_count[T_SCD],
                   set_attr_count[T_USER],
                   set_attr_count[T_PROCESS],
                   set_attr_count[T_NETDEV],
                   set_attr_count[T_NETTEMP],
                   set_attr_count[T_NETOBJ]);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;

    len += sprintf(buffer + len,
                   "\nrsbac_remove_target calls:\nfile: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
                   remove_count[T_FILE],
                   remove_count[T_DIR],
                   remove_count[T_FIFO],
                   remove_count[T_SYMLINK],
                   remove_count[T_DEV],
                   remove_count[T_IPC],
                   remove_count[T_SCD],
                   remove_count[T_USER],
                   remove_count[T_PROCESS],
                   remove_count[T_NETDEV],
                   remove_count[T_NETTEMP],
                   remove_count[T_NETOBJ]);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }

out:
  *start = buffer + (offset - begin);
  len -= (offset - begin);
  
  if (len > length)
    len = length;
  return len;
}
#endif

#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
static int
auto_write_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
#else
static int
auto_write_proc_info(char *buffer, char **start, off_t offset, int length)
#endif
{
  int len = 0;
  off_t pos   = 0;
  off_t begin = 0;

  union rsbac_target_id_t       rsbac_target_id;
  union rsbac_attribute_value_t rsbac_attribute_value;

  if (!rsbac_initialized) return (-ENOSYS);

#ifdef CONFIG_RSBAC_DEBUG
  if (rsbac_debug_aef) printk(KERN_DEBUG "auto_write_proc_info(): calling ADF\n");
#endif
  rsbac_target_id.scd = ST_rsbac;
  rsbac_attribute_value.dummy = 0;
  if (!rsbac_adf_request(R_GET_STATUS_DATA,
                         current->pid,
                         T_SCD,
                         rsbac_target_id,
                         A_none,
                         rsbac_attribute_value))
    {
      return -EPERM;
    }

  len = sprintf(buffer, "RSBAC auto write settings\n-------------------------\n");
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;

  len += sprintf(buffer + len, "auto interval %u jiffies (%i jiffies = 1 second)\n",
                 auto_interval, HZ);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;

#ifdef CONFIG_RSBAC_DEBUG
  len += sprintf(buffer + len, "debug level is %i\n",
                 rsbac_debug_auto);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
#endif

out:
  *start = buffer + (offset - begin);
  len -= (offset - begin);
  
  if (len > length)
    len = length;
  return len;
}

static ssize_t auto_write_proc_write(struct file * file, const char * buf,
                                       u_long count, void *ppos)
{
    ssize_t err = -EINVAL;
    char * k_buf;
    char * p;

    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;

    if(count > PROC_BLOCK_SIZE) {
	return(-EOVERFLOW);
    }

    if (!(k_buf = (char *) __get_free_page(GFP_KERNEL)))
      return(-ENOMEM);
    copy_from_user(k_buf, buf, count);

  if(count < 13 || strncmp("auto", k_buf, 4))
    {
      goto out;
    }
  if (!rsbac_initialized)
    {
      err=-ENOSYS;
      goto out;
    }

#ifdef CONFIG_RSBAC_DEBUG
  if (rsbac_debug_aef) printk(KERN_DEBUG "auto_write_proc_write(): calling ADF\n");
#endif
  rsbac_target_id.scd = ST_rsbac;
  rsbac_attribute_value.dummy = 0;
  if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
                         current->pid,
                         T_SCD,
                         rsbac_target_id,
                         A_none,
                         rsbac_attribute_value))
    {
      err = -EPERM;
      goto out;
    }

    /*
     * Usage: echo "auto interval #N" > /proc/rsbac_info/auto_write
     *   to set auto_interval to given value
     */
    if(!strncmp("interval", k_buf + 5, 8)) 
    {
        unsigned int interval;

	p = k_buf + 5 + 9;

        if( *p == '\0' )
           goto out;

        interval = simple_strtoul(p, NULL, 0);
        /* only accept minimum of 1 second */
        if(interval >= HZ)
          {
            printk(KERN_INFO
                   "auto_write_proc_write(): setting auto write interval to %u\n",
                   interval);
            auto_interval = interval;
            err = count;
            goto out;
          }
        else
          {
            printk(KERN_INFO
                   "auto_write_proc_write(): rejecting too short auto write interval %u (min. %i)\n",
                   interval, HZ);
            goto out;
          }
    }

#ifdef CONFIG_RSBAC_DEBUG
    /*
     * Usage: echo "auto debug #N" > /proc/rsbac_info/auto_write
     *   to set rsbac_debug_auto to given value
     */
    if(!strncmp("debug", k_buf + 5, 5)) 
    {
        unsigned int debug_level;

	p = k_buf + 5 + 6;

        if( *p == '\0' )
          goto out;

        debug_level = simple_strtoul(p, NULL, 0);
        /* only accept 0 or 1 */
        if(!debug_level || (debug_level == 1))
          {
            printk(KERN_INFO
                   "auto_write_proc_write(): setting rsbac_debug_auto to %u\n",
                   debug_level);
            rsbac_debug_auto = debug_level;
            err = count;
          }
        else
          {
            printk(KERN_INFO
                   "auto_write_proc_write(): rejecting invalid debug level (should be 0 or 1)\n");
          }
    }
#endif

out:
  free_page((ulong) k_buf);
  return(err);
}
#endif /* CONFIG_RSBAC_AUTO_WRITE > 0 */

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
static int
versions_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
#else
static int
versions_proc_info(char *buffer, char **start, off_t offset, int length)
#endif
{
  int len = 0;
  off_t pos   = 0;
  off_t begin = 0;

  union rsbac_target_id_t       rsbac_target_id;
  union rsbac_attribute_value_t rsbac_attribute_value;

  if (!rsbac_initialized) return (-ENOSYS);

#ifdef CONFIG_RSBAC_DEBUG
  if (rsbac_debug_aef) printk(KERN_DEBUG "versions_proc_info(): calling ADF\n");
#endif
  rsbac_target_id.scd = ST_rsbac;
  rsbac_attribute_value.dummy = 0;
  if (!rsbac_adf_request(R_GET_STATUS_DATA,
                         current->pid,
                         T_SCD,
                         rsbac_target_id,
                         A_none,
                         rsbac_attribute_value))
    {
      return -EPERM;
    }

  len = sprintf(buffer,
                "RSBAC version settings (%s)\n----------------------\n",
                RSBAC_VERSION);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;

  len += sprintf(buffer + len, "FD lists:\nGEN  aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_GEN_FD_ACI_VERSION, sizeof(struct rsbac_gen_fd_aci_t), RSBAC_GEN_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#if defined(CONFIG_RSBAC_MAC)
  len += sprintf(buffer + len, "MAC  aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_MAC_FD_ACI_VERSION, sizeof(struct rsbac_mac_fd_aci_t), RSBAC_MAC_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_FC)
  len += sprintf(buffer + len, "FC   aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_FC_FD_ACI_VERSION, sizeof(rsbac_fc_oc_t), RSBAC_FC_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_SIM)
  len += sprintf(buffer + len, "SIM  aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_SIM_FD_ACI_VERSION, sizeof(rsbac_sim_dt_t), RSBAC_SIM_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_PM)
  len += sprintf(buffer + len, "PM   aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_PM_FD_ACI_VERSION, sizeof(struct rsbac_pm_fd_aci_t), RSBAC_PM_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_MS)
  len += sprintf(buffer + len, "MS   aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_MS_FD_ACI_VERSION, sizeof(struct rsbac_ms_fd_aci_t), RSBAC_MS_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
  len += sprintf(buffer + len, "MS_S aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_MS_SCANNED_FD_ACI_VERSION,
                 sizeof(rsbac_ms_scanned_t),
                 RSBAC_MS_SCANNED_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_FF)
  len += sprintf(buffer + len, "FF   aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_FF_FD_ACI_VERSION, sizeof(rsbac_ff_flags_t), RSBAC_FF_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_RC)
  len += sprintf(buffer + len, "RC   aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_RC_FD_ACI_VERSION, sizeof(struct rsbac_rc_fd_aci_t), RSBAC_RC_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_AUTH)
  len += sprintf(buffer + len, "AUTH aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_AUTH_FD_ACI_VERSION, sizeof(struct rsbac_auth_fd_aci_t), RSBAC_AUTH_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_CAP)
  len += sprintf(buffer + len, "CAP  aci version is %i, aci entry size is %i, %i lists per device\n",
                 RSBAC_CAP_FD_ACI_VERSION, sizeof(struct rsbac_cap_fd_aci_t), RSBAC_CAP_NR_FD_LISTS);
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif


  len += sprintf(buffer + len, "\nDEV lists:\nGEN  aci version is %i, aci entry size is %i\n",
                 RSBAC_GEN_DEV_ACI_VERSION, sizeof(struct rsbac_gen_dev_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#if defined(CONFIG_RSBAC_MAC)
  len += sprintf(buffer + len, "MAC  aci version is %i, aci entry size is %i\n",
                 RSBAC_MAC_DEV_ACI_VERSION, sizeof(struct rsbac_mac_dev_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_FC)
  len += sprintf(buffer + len, "FC   aci version is %i, aci entry size is %i\n",
                 RSBAC_FC_DEV_ACI_VERSION, sizeof(rsbac_fc_oc_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_SIM)
  len += sprintf(buffer + len, "SIM  aci version is %i, aci entry size is %i\n",
                 RSBAC_SIM_DEV_ACI_VERSION, sizeof(rsbac_sim_dt_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_PM)
  len += sprintf(buffer + len, "PM   aci version is %i, aci entry size is %i\n",
                 RSBAC_PM_DEV_ACI_VERSION, sizeof(struct rsbac_pm_dev_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_RC)
  len += sprintf(buffer + len, "RC   aci version is %i, aci entry size is %i\n",
                 RSBAC_RC_DEV_ACI_VERSION, sizeof(rsbac_rc_type_id_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif


  len += sprintf(buffer + len, "\nIPC lists:\n");
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#if defined(CONFIG_RSBAC_MAC)
  len += sprintf(buffer + len, "MAC  aci version is %i, aci entry size is %i\n",
                 RSBAC_MAC_IPC_ACI_VERSION, sizeof(struct rsbac_mac_ipc_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_FC)
  len += sprintf(buffer + len, "FC   aci version is %i, aci entry size is %i\n",
                 RSBAC_FC_IPC_ACI_VERSION, sizeof(rsbac_fc_oc_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_SIM)
  len += sprintf(buffer + len, "SIM  aci version is %i, aci entry size is %i\n",
                 RSBAC_SIM_IPC_ACI_VERSION, sizeof(rsbac_sim_dt_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_PM)
  len += sprintf(buffer + len, "PM   aci version is %i, aci entry size is %i\n",
                 RSBAC_PM_IPC_ACI_VERSION, sizeof(struct rsbac_pm_ipc_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_RC)
  len += sprintf(buffer + len, "RC   aci version is %i, aci entry size is %i\n",
                 RSBAC_RC_DEV_ACI_VERSION, sizeof(rsbac_rc_type_id_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif


  len += sprintf(buffer + len, "\nUSER lists:\nGEN  aci version is %i, aci entry size is %i\n",
                 RSBAC_GEN_USER_ACI_VERSION, sizeof(struct rsbac_gen_user_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#if defined(CONFIG_RSBAC_MAC)
  len += sprintf(buffer + len, "MAC  aci version is %i, aci entry size is %i\n",
                 RSBAC_MAC_USER_ACI_VERSION, sizeof(struct rsbac_mac_user_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_FC)
  len += sprintf(buffer + len, "FC   aci version is %i, aci entry size is %i\n",
                 RSBAC_FC_USER_ACI_VERSION, sizeof(rsbac_system_role_int_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_SIM)
  len += sprintf(buffer + len, "SIM  aci version is %i, aci entry size is %i\n",
                 RSBAC_SIM_USER_ACI_VERSION, sizeof(rsbac_system_role_int_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_PM)
  len += sprintf(buffer + len, "PM   aci version is %i, aci entry size is %i\n",
                 RSBAC_PM_USER_ACI_VERSION, sizeof(struct rsbac_pm_user_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_MS)
  len += sprintf(buffer + len, "MS   aci version is %i, aci entry size is %i\n",
                 RSBAC_MS_USER_ACI_VERSION, sizeof(rsbac_system_role_int_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_RC)
  len += sprintf(buffer + len, "RC   aci version is %i, aci entry size is %i\n",
                 RSBAC_RC_USER_ACI_VERSION, sizeof(rsbac_rc_role_id_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_AUTH)
  len += sprintf(buffer + len, "AUTH aci version is %i, aci entry size is %i\n",
                 RSBAC_AUTH_USER_ACI_VERSION, sizeof(rsbac_system_role_int_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_CAP)
  len += sprintf(buffer + len, "CAP aci version is %i, aci entry size is %i\n",
                 RSBAC_CAP_USER_ACI_VERSION, sizeof(struct rsbac_cap_user_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif


  len += sprintf(buffer + len, "\nPROCESS lists:\nGEN  aci version is %i, aci entry size is %i\n",
                 RSBAC_GEN_PROCESS_ACI_VERSION, sizeof(rsbac_request_vector_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#if defined(CONFIG_RSBAC_MAC)
  len += sprintf(buffer + len, "MAC  aci version is %i, aci entry size is %i\n",
                 RSBAC_MAC_PROCESS_ACI_VERSION, sizeof(struct rsbac_mac_process_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_PM)
  len += sprintf(buffer + len, "PM   aci version is %i, aci entry size is %i\n",
                 RSBAC_PM_PROCESS_ACI_VERSION, sizeof(struct rsbac_pm_process_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_MS)
  len += sprintf(buffer + len, "MS   aci version is %i, aci entry size is %i\n",
                 RSBAC_MS_PROCESS_ACI_VERSION, sizeof(struct rsbac_ms_process_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_RC)
  len += sprintf(buffer + len, "RC   aci version is %i, aci entry size is %i\n",
                 RSBAC_RC_PROCESS_ACI_VERSION, sizeof(struct rsbac_rc_process_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_AUTH)
  len += sprintf(buffer + len, "AUTH aci version is %i, aci entry size is %i\n",
                 RSBAC_AUTH_PROCESS_ACI_VERSION, sizeof(struct rsbac_auth_process_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif

#if defined(CONFIG_RSBAC_NET_DEV)
  len += sprintf(buffer + len, "\nNETDEV lists:\n");
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
  len += sprintf(buffer + len, "GEN  aci version is %i, aci entry size is %i\n",
                 RSBAC_GEN_NETDEV_ACI_VERSION, sizeof(struct rsbac_gen_netdev_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_RC)
  len += sprintf(buffer + len, "RC   aci version is %i, aci entry size is %i\n",
                 RSBAC_RC_NETDEV_ACI_VERSION, sizeof(rsbac_rc_type_id_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#endif

#if defined(CONFIG_RSBAC_NET_OBJ)
  len += sprintf(buffer + len, "\nNetwork Template list: version is %i, data size is %i\n",
                 RSBAC_NET_TEMP_VERSION, sizeof(struct rsbac_net_temp_data_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
  len += sprintf(buffer + len, "\nNETOBJ lists:\nGEN  aci version is %i, aci entry size is %i\n",
                 RSBAC_GEN_NETOBJ_ACI_VERSION, sizeof(struct rsbac_gen_netobj_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#if defined(CONFIG_RSBAC_MAC)
  len += sprintf(buffer + len, "MAC  aci version is %i, aci entry size is %i\n",
                 RSBAC_MAC_NETOBJ_ACI_VERSION, sizeof(struct rsbac_mac_netobj_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_FC)
  len += sprintf(buffer + len, "FC   aci version is %i, aci entry size is %i\n",
                 RSBAC_FC_NETOBJ_ACI_VERSION, sizeof(rsbac_fc_oc_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_SIM)
  len += sprintf(buffer + len, "SIM  aci version is %i, aci entry size is %i\n",
                 RSBAC_SIM_NETOBJ_ACI_VERSION, sizeof(rsbac_sim_dt_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_PM)
  len += sprintf(buffer + len, "PM   aci version is %i, aci entry size is %i\n",
                 RSBAC_PM_NETOBJ_ACI_VERSION, sizeof(struct rsbac_pm_netobj_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_MS)
  len += sprintf(buffer + len, "MS   aci version is %i, aci entry size is %i\n",
                 RSBAC_MS_NETOBJ_ACI_VERSION, sizeof(struct rsbac_ms_netobj_aci_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#if defined(CONFIG_RSBAC_RC)
  len += sprintf(buffer + len, "RC   aci version is %i, aci entry size is %i\n",
                 RSBAC_RC_NETOBJ_ACI_VERSION, sizeof(rsbac_rc_type_id_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }
    if (pos > offset+length)
      goto out;
#endif
#endif

  len += sprintf(buffer + len, "\nlog_level array: adf request version is %i, no_write is %i, array size is %i\n",
                 RSBAC_ADF_REQUEST_ARRAY_VERSION, log_levels_no_write, R_NONE * sizeof(enum rsbac_adf_request_t));
  pos = begin + len;
  if (pos < offset)
    {
      len = 0;
      begin = pos;
    }

out:
  *start = buffer + (offset - begin);
  len -= (offset - begin);
  
  if (len > length)
    len = length;
  return len;
}

#ifdef CONFIG_RSBAC_NET_OBJ
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
static int
net_temp_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
#else
static int
net_temp_proc_info(char *buffer, char **start, off_t offset, int length)
#endif
{
    u_int len = 0;
    off_t pos   = 0;
    off_t begin = 0;
    rsbac_net_temp_id_t * temp_array;
    long                                count;

    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;

    if (!rsbac_initialized) return (-ENOSYS);

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "net_temp_proc_info(): calling ADF\n");
#endif
    rsbac_target_id.scd = ST_rsbac;
    rsbac_attribute_value.dummy = 0;
    if (!rsbac_adf_request(R_GET_STATUS_DATA,
                           current->pid,
                           T_SCD,
                           rsbac_target_id,
                           A_none,
                           rsbac_attribute_value))
      {
        return -EPERM;
      }

    len = sprintf(buffer, "Network Templates\n-----------------\n");
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    
    count = rsbac_list_get_all_desc(net_temp_handle, (void **) &temp_array);
    if(count > 0)
      {
        __u32 i;
        struct rsbac_net_temp_data_t data;

        for(i=0; i < count; i++)
          {
            if(!rsbac_list_get_data(net_temp_handle, &temp_array[i], &data))
              {
                len += sprintf(buffer + len, "%10u  %s\n",
                               temp_array[i], data.name);
                pos = begin + len;
                if (pos < offset)
                  {
                    len = 0;
                    begin = pos;
                  }
                if (pos > offset+length)
                  {
                    vfree(temp_array);
                    goto out;
                  }
              }
          }
        vfree(temp_array);
      }
    len += sprintf(buffer + len, "%lu templates\n",
                   count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }

out:
  *start = buffer + (offset - begin);
  len -= (offset - begin);
  
  if (len > length)
    len = length;
  return len;
}
#endif /* NET_OBJ */

static int register_all_rsbac_proc(void)
  {
    struct proc_dir_entry * tmp_entry_p;

    proc_rsbac_root_p = create_proc_entry("rsbac-info",
                                          S_IFDIR | S_IRUGO | S_IXUGO,
                                          &proc_root);
    if(!proc_rsbac_root_p)
      return -RSBAC_ECOULDNOTADDITEM;

    proc_rsbac_backup_p = create_proc_entry("backup",
                                          S_IFDIR | S_IRUGO | S_IXUGO,
                                          proc_rsbac_root_p);
    if(!proc_rsbac_root_p)
      return -RSBAC_ECOULDNOTADDITEM;

    tmp_entry_p = create_proc_entry("devices",
                                    S_IFREG | S_IRUGO,
                                    proc_rsbac_root_p);
    if(!tmp_entry_p)
      return -RSBAC_ECOULDNOTADDITEM;
    tmp_entry_p->get_info = devices_proc_info;

    tmp_entry_p = create_proc_entry("stats",
                                    S_IFREG | S_IRUGO,
                                    proc_rsbac_root_p);
    if(!tmp_entry_p)
      return -RSBAC_ECOULDNOTADDITEM;
    tmp_entry_p->get_info = stats_proc_info;

    #ifdef CONFIG_RSBAC_XSTATS
    tmp_entry_p = create_proc_entry("xstats",
                                    S_IFREG | S_IRUGO,
                                    proc_rsbac_root_p);
    if(!tmp_entry_p)
      return -RSBAC_ECOULDNOTADDITEM;
    tmp_entry_p->get_info = xstats_proc_info;
    #endif
    #if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
    tmp_entry_p = create_proc_entry("auto_write",
                                    S_IFREG | S_IRUGO | S_IWUGO,
                                    proc_rsbac_root_p);
    if(!tmp_entry_p)
      return -RSBAC_ECOULDNOTADDITEM;
    tmp_entry_p->get_info = auto_write_proc_info;
    tmp_entry_p->write_proc = auto_write_proc_write;
    #endif
    tmp_entry_p = create_proc_entry("versions",
                                    S_IFREG | S_IRUGO,
                                    proc_rsbac_root_p);
    if(!tmp_entry_p)
      return -RSBAC_ECOULDNOTADDITEM;
    tmp_entry_p->get_info = versions_proc_info;

#ifdef CONFIG_RSBAC_NET_OBJ
    tmp_entry_p = create_proc_entry("net_temp",
                                    S_IFREG | S_IRUGO,
                                    proc_rsbac_root_p);
    if(!tmp_entry_p)
      return -RSBAC_ECOULDNOTADDITEM;
    tmp_entry_p->get_info = net_temp_proc_info;
#endif

    return(0);
  }

/*
static int unregister_all_rsbac_proc(void)
  {
#ifdef CONFIG_RSBAC_NET_OBJ
    remove_proc_entry("net_temp", proc_rsbac_root_p);
#endif
    remove_proc_entry("versions", proc_rsbac_root_p);
    remove_proc_entry("devices", proc_rsbac_root_p);
    remove_proc_entry("stats", proc_rsbac_root_p);
    remove_proc_entry("auto-write", proc_rsbac_root_p);
    remove_proc_entry("backup", proc_rsbac_root_p);
    remove_proc_entry("rsbac-info", &proc_root);
    return(0);
  }
*/
#endif /* CONFIG_PROC_FS && CONFIG_RSBAC_PROC */


/************************************************* */
/*               RSBAC daemon                      */
/************************************************* */

/************************************************************************** */
/* Initialization, including ACI restoration for root device from disk.     */
/* After this call, all ACI is kept in memory for performance reasons,      */
/* but user and file/dir object ACI are written to disk on every change.    */

/* Since there can be no access to aci data structures before init,         */
/* rsbac_do_init() will initialize all rw-spinlocks to unlocked.               */

/* MS init prototype */
#if defined(CONFIG_RSBAC_MS) && !defined(CONFIG_RSBAC_MAINT)
int __init rsbac_init_ms(void);
#endif

static void __init registration_error(int err, char * listname)
  {
    if(err < 0)
      {
        char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_do_init(): Registering %s list failed with error %s\n",
                   listname,
                   get_error_name(tmp, err));
            rsbac_kfree(tmp);
          }
      }
  }

static int __init rsbac_do_init(void)
  {
    int err = 0;
    struct rsbac_device_list_item_t * device_p;
    struct rsbac_device_list_item_t * new_device_p;
    u_long flags;
    struct rsbac_list_info_t     list_info;
    struct super_block * sb_p;

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    compiled_modules[0] = (char) 0;
    #ifdef CONFIG_RSBAC_REG
    strcat(compiled_modules, " REG");
    #endif
    #ifdef CONFIG_RSBAC_MAC
      #ifdef CONFIG_RSBAC_MAC_LIGHT
      strcat(compiled_modules, " MAC-L");
      #else
      strcat(compiled_modules, " MAC");
      #endif
    #endif
    #ifdef CONFIG_RSBAC_FC
    strcat(compiled_modules, " FC");
    #endif
    #ifdef CONFIG_RSBAC_SIM
    strcat(compiled_modules, " SIM");
    #endif
    #ifdef CONFIG_RSBAC_PM
    strcat(compiled_modules, " PM");
    #endif
    #ifdef CONFIG_RSBAC_MS
    strcat(compiled_modules, " MS");
    #endif
    #ifdef CONFIG_RSBAC_FF
    strcat(compiled_modules, " FF");
    #endif
    #ifdef CONFIG_RSBAC_RC
    strcat(compiled_modules, " RC");
    #endif
    #ifdef CONFIG_RSBAC_AUTH
    strcat(compiled_modules, " AUTH");
    #endif
    #ifdef CONFIG_RSBAC_ACL
    strcat(compiled_modules, " ACL");
    #endif
    #ifdef CONFIG_RSBAC_CAP
    strcat(compiled_modules, " CAP");
    #endif
#ifdef CONFIG_RSBAC_MAINT
    printk(KERN_INFO
           "rsbac_do_init(): Initializing RSBAC %s (Maintenance Mode)\n",
           RSBAC_VERSION);
    printk(KERN_INFO
           "rsbac_do_init(): Supported module data structures:%s\n",
           compiled_modules);
#else
    printk(KERN_INFO
           "rsbac_do_init(): Initializing RSBAC %s\n",
           RSBAC_VERSION);
    printk(KERN_INFO
           "rsbac_do_init(): compiled modules:%s\n",
           compiled_modules);
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
    /* init memory */
    printk(KERN_INFO
           "rsbac_do_init(): Initializing memory slabs\n");
    rsbac_kmem_cache_sizes_init();
#endif

    /* set rw-spinlocks to unlocked status and init data structures */
    device_list_head.lock = RW_LOCK_UNLOCKED;
    device_list_head.head = NULL;
    device_list_head.tail = NULL;
    device_list_head.curr = NULL;
    device_list_head.count = 0;

#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before registering proc dir: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    printk(KERN_INFO "rsbac_do_init(): Registering RSBAC proc dir\n");
    register_all_rsbac_proc();
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before get_super: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    sb_p = get_super(rsbac_root_dev);
    if(!sb_p)
      return -RSBAC_ENOROOTDEV;
    /* read fd aci from root device */
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG
             "rsbac_do_init(): reading aci from device number %02u:%02u\n",
             MAJOR(rsbac_root_dev),
             MINOR(rsbac_root_dev));
#endif
    /* create a private device item */
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    new_device_p = create_device_item(sb_p);
    #else
    new_device_p = create_device_item(sb_p, NULL);
    #endif
    if (!new_device_p)
      {
        printk(KERN_CRIT "rsbac_do_init(): Could not alloc device item!\n");
        err = -RSBAC_ECOULDNOTADDDEVICE;
        goto out_free;
      }
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before register_fd_lists: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    /* Add new_device_p to device list */
    /* wait for write access to device_list_head */
    rsbac_write_lock(&device_list_head.lock, &flags);
    /* OK, go on */
    device_p = add_device_item(new_device_p);
    /* device was added, allow access */
    rsbac_write_unlock(&device_list_head.lock, &flags);
    if (!device_p)
      {
        printk(KERN_CRIT "rsbac_do_init(): Could not add device!\n");
        clear_device_item(new_device_p);
        err = -RSBAC_ECOULDNOTADDDEVICE;
        goto out_free;
      }

    /* init lists - we need the root device_p to be initialized, but no generic list registered */
    printk(KERN_INFO
           "rsbac_do_init(): Initializing generic lists\n");
    rsbac_list_init();

    /* no locking needed, device_p is known and there can be no parallel init! */
    if((err = register_fd_lists(device_p,rsbac_root_dev)))
      {
        char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_do_init(): File/Dir lists registration failed for dev %02u:%02u, err %s!\n",
                   MAJOR(rsbac_root_dev), MINOR(rsbac_root_dev), get_error_name(tmp,err));
            rsbac_kfree(tmp);
          }
      }

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before DEV lists registration: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering DEV lists\n");
#endif
    {
      struct rsbac_gen_dev_aci_t def_aci = DEFAULT_GEN_DEV_ACI;

      list_info.version = RSBAC_GEN_DEV_ACI_VERSION;
      list_info.key = RSBAC_GEN_DEV_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_dev_t);
      list_info.data_size = sizeof(struct rsbac_gen_dev_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &dev_handles.gen,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                dev_compare,
                                NULL,
                                &def_aci,
                                RSBAC_GEN_ACI_DEV_NAME,
                                0);
      if(err)
        {
          registration_error(err, "DEV General");
        }
    }
#if defined(CONFIG_RSBAC_MAC)
    {
      struct rsbac_mac_dev_aci_t def_aci = DEFAULT_MAC_DEV_ACI;

      list_info.version = RSBAC_MAC_DEV_ACI_VERSION;
      list_info.key = RSBAC_MAC_DEV_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_dev_t);
      list_info.data_size = sizeof(struct rsbac_mac_dev_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &dev_handles.mac,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                dev_compare,
                                NULL,
                                &def_aci,
                                RSBAC_MAC_ACI_DEV_NAME,
                                0);
      if(err)
        {
          registration_error(err, "DEV MAC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_FC)
    {
      rsbac_fc_oc_t def_aci = RSBAC_FC_OC_ROOT_DEF;

      list_info.version = RSBAC_FC_DEV_ACI_VERSION;
      list_info.key = RSBAC_FC_DEV_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_dev_t);
      list_info.data_size = sizeof(rsbac_fc_oc_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &dev_handles.fc,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                dev_compare,
                                NULL,
                                &def_aci,
                                RSBAC_FC_ACI_DEV_NAME,
                                0);
      if(err)
        {
          registration_error(err, "DEV FC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_SIM)
    {
      rsbac_sim_dt_t def_aci = RSBAC_SIM_DT_ROOT_DEF;

      list_info.version = RSBAC_SIM_DEV_ACI_VERSION;
      list_info.key = RSBAC_SIM_DEV_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_dev_t);
      list_info.data_size = sizeof(rsbac_sim_dt_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &dev_handles.sim,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                dev_compare,
                                NULL,
                                &def_aci,
                                RSBAC_SIM_ACI_DEV_NAME,
                                0);
      if(err)
        {
          registration_error(err, "DEV SIM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_PM)
    {
      struct rsbac_pm_dev_aci_t def_aci = DEFAULT_PM_DEV_ACI;

      list_info.version = RSBAC_PM_DEV_ACI_VERSION;
      list_info.key = RSBAC_PM_DEV_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_dev_t);
      list_info.data_size = sizeof(struct rsbac_pm_dev_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &dev_handles.pm,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                dev_compare,
                                NULL,
                                &def_aci,
                                RSBAC_PM_ACI_DEV_NAME,
                                0);
      if(err)
        {
          registration_error(err, "DEV PM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_RC)
    {
      rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;

      list_info.version = RSBAC_RC_DEV_ACI_VERSION;
      list_info.key = RSBAC_RC_DEV_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_dev_t);
      list_info.data_size = sizeof(rsbac_rc_type_id_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &dev_handles.rc,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                dev_compare,
                                NULL,
                                &def_aci,
                                RSBAC_RC_ACI_DEV_NAME,
                                0);
      if(err)
        {
          registration_error(err, "DEV RC");
        }
    }
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before registering IPC lists: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering IPC lists\n");
#endif
#if defined(CONFIG_RSBAC_MAC)
    {
      struct rsbac_mac_ipc_aci_t def_aci = DEFAULT_MAC_IPC_ACI;

      list_info.version = RSBAC_MAC_IPC_ACI_VERSION;
      list_info.key = RSBAC_MAC_IPC_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_ipc_t);
      list_info.data_size = sizeof(struct rsbac_mac_ipc_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &ipc_handles.mac,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                ipc_compare,
                                NULL,
                                &def_aci,
                                RSBAC_MAC_ACI_IPC_NAME,
                                0);
      if(err)
        {
          registration_error(err, "IPC MAC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_FC)
    {
      rsbac_fc_oc_t def_aci = RSBAC_FC_OC_ROOT_DEF;

      list_info.version = RSBAC_FC_IPC_ACI_VERSION;
      list_info.key = RSBAC_FC_IPC_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_ipc_t);
      list_info.data_size = sizeof(rsbac_fc_oc_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &ipc_handles.fc,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                ipc_compare,
                                NULL,
                                &def_aci,
                                RSBAC_FC_ACI_IPC_NAME,
                                0);
      if(err)
        {
          registration_error(err, "IPC FC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_SIM)
    {
      rsbac_sim_dt_t def_aci = RSBAC_SIM_DT_ROOT_DEF;

      list_info.version = RSBAC_SIM_IPC_ACI_VERSION;
      list_info.key = RSBAC_SIM_IPC_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_ipc_t);
      list_info.data_size = sizeof(rsbac_sim_dt_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &ipc_handles.sim,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                ipc_compare,
                                NULL,
                                &def_aci,
                                RSBAC_SIM_ACI_IPC_NAME,
                                0);
      if(err)
        {
          registration_error(err, "IPC SIM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_PM)
    {
      struct rsbac_pm_ipc_aci_t def_aci = DEFAULT_PM_IPC_ACI;

      list_info.version = RSBAC_PM_IPC_ACI_VERSION;
      list_info.key = RSBAC_PM_IPC_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_ipc_t);
      list_info.data_size = sizeof(struct rsbac_pm_ipc_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &ipc_handles.pm,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                ipc_compare,
                                NULL,
                                &def_aci,
                                RSBAC_PM_ACI_IPC_NAME,
                                0);
      if(err)
        {
          registration_error(err, "IPC PM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_RC)
    {
      rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;

      list_info.version = RSBAC_RC_IPC_ACI_VERSION;
      list_info.key = RSBAC_RC_IPC_ACI_KEY;
      list_info.desc_size = sizeof(struct rsbac_ipc_t);
      list_info.data_size = sizeof(rsbac_rc_type_id_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &ipc_handles.rc,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                ipc_compare,
                                NULL,
                                &def_aci,
                                RSBAC_RC_ACI_IPC_NAME,
                                0);
      if(err)
        {
          registration_error(err, "IPC RC");
        }
    }
#endif


#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before registering USER lists: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering USER lists\n");
#endif

    {
      struct rsbac_gen_user_aci_t def_aci = DEFAULT_GEN_U_ACI;

      list_info.version = RSBAC_GEN_USER_ACI_VERSION;
      list_info.key = RSBAC_GEN_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(struct rsbac_gen_user_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.gen,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_GEN_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER General");
        }
    }
#if defined(CONFIG_RSBAC_MAC)
    {
      struct rsbac_mac_user_aci_t def_aci = DEFAULT_MAC_U_ACI;

      list_info.version = RSBAC_MAC_USER_ACI_VERSION;
      list_info.key = RSBAC_MAC_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(struct rsbac_mac_user_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.mac,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_MAC_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER MAC");
        }
      else
      if(!rsbac_list_count(user_handles.mac))
        {
          struct rsbac_mac_user_aci_t sysadm_aci = DEFAULT_MAC_U_SYSADM_ACI;
          struct rsbac_mac_user_aci_t secoff_aci = DEFAULT_MAC_U_SECOFF_ACI;
          rsbac_uid_t                 user;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER MAC ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          if(rsbac_list_add(user_handles.mac, &user, &sysadm_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER MAC entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          if(rsbac_list_add(user_handles.mac, &user, &secoff_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER MAC entry could not be added!\n");
        }
    }
#endif
#if defined(CONFIG_RSBAC_FC)
    {
      rsbac_system_role_int_t def_aci = SR_user;

      list_info.version = RSBAC_FC_USER_ACI_VERSION;
      list_info.key = RSBAC_FC_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(rsbac_system_role_int_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.fc,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_FC_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER FC");
        }
      else
      if(!rsbac_list_count(user_handles.fc))
        {
          rsbac_uid_t                 user;
          rsbac_system_role_int_t     role;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER FC ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          role = SR_administrator;
          if(rsbac_list_add(user_handles.fc, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER FC entry could not be added!\n");
          user = RSBAC_BIN_UID;
          role = SR_administrator;
          if(rsbac_list_add(user_handles.fc, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): BIN USER FC entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          role = SR_security_officer;
          if(rsbac_list_add(user_handles.fc, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER FC entry could not be added!\n");
        }
    }
#endif
#if defined(CONFIG_RSBAC_SIM)
    {
      rsbac_system_role_int_t def_aci = SR_user;

      list_info.version = RSBAC_SIM_USER_ACI_VERSION;
      list_info.key = RSBAC_SIM_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(rsbac_system_role_int_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.sim,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_SIM_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER SIM");
        }
      else
      if(!rsbac_list_count(user_handles.sim))
        {
          rsbac_uid_t                 user;
          rsbac_system_role_int_t     role;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER SIM ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          role = SR_administrator;
          if(rsbac_list_add(user_handles.sim, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER SIM entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          role = SR_security_officer;
          if(rsbac_list_add(user_handles.sim, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER SIM entry could not be added!\n");
        }
    }
#endif
#if defined(CONFIG_RSBAC_PM)
    {
      struct rsbac_pm_user_aci_t def_aci = DEFAULT_PM_U_ACI;

      list_info.version = RSBAC_PM_USER_ACI_VERSION;
      list_info.key = RSBAC_PM_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(struct rsbac_pm_user_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.pm,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_PM_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER PM");
        }
      else
      if(!rsbac_list_count(user_handles.pm))
        {
          struct rsbac_pm_user_aci_t sysadm_aci   = DEFAULT_PM_U_SYSADM_ACI;
          struct rsbac_pm_user_aci_t secoff_aci   = DEFAULT_PM_U_SECOFF_ACI;
          struct rsbac_pm_user_aci_t dataprot_aci = DEFAULT_PM_U_DATAPROT_ACI;
          struct rsbac_pm_user_aci_t tpman_aci    = DEFAULT_PM_U_TPMAN_ACI;
          rsbac_uid_t                user;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER PM ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          if(rsbac_list_add(user_handles.pm, &user, &sysadm_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER PM entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          if(rsbac_list_add(user_handles.pm, &user, &secoff_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER PM entry could not be added!\n");
          user = RSBAC_DATAPROT_UID;
          if(rsbac_list_add(user_handles.pm, &user, &dataprot_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): DATAPROT USER PM entry could not be added!\n");
          user = RSBAC_TPMAN_UID;
          if(rsbac_list_add(user_handles.pm, &user, &tpman_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): TPMAN USER PM entry could not be added!\n");
         }
    }
#endif
#if defined(CONFIG_RSBAC_MS)
    {
      rsbac_system_role_int_t def_aci = SR_user;

      list_info.version = RSBAC_MS_USER_ACI_VERSION;
      list_info.key = RSBAC_MS_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(rsbac_system_role_int_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.ms,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_MS_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER MS");
        }
      else
      if(!rsbac_list_count(user_handles.ms))
        {
          rsbac_uid_t                 user;
          rsbac_system_role_int_t     role;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER MS ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          role = SR_administrator;
          if(rsbac_list_add(user_handles.ms, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER MS entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          role = SR_security_officer;
          if(rsbac_list_add(user_handles.ms, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER MS entry could not be added!\n");
        }
    }
#endif
#if defined(CONFIG_RSBAC_FF)
    {
      rsbac_system_role_int_t def_aci = SR_user;

      list_info.version = RSBAC_FF_USER_ACI_VERSION;
      list_info.key = RSBAC_FF_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(rsbac_system_role_int_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.ff,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_FF_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER FF");
        }
      else
      if(!rsbac_list_count(user_handles.ff))
        {
          rsbac_uid_t                 user;
          rsbac_system_role_int_t     role;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER FF ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          role = SR_administrator;
          if(rsbac_list_add(user_handles.ff, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER FF entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          role = SR_security_officer;
          if(rsbac_list_add(user_handles.ff, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER FF entry could not be added!\n");
        }
    }
#endif
#if defined(CONFIG_RSBAC_RC)
    {
      rsbac_rc_role_id_t def_aci = RSBAC_RC_GENERAL_ROLE;

      list_info.version = RSBAC_RC_USER_ACI_VERSION;
      list_info.key = RSBAC_RC_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(rsbac_rc_role_id_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.rc,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_RC_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER RC");
        }
      else
      if(!rsbac_list_count(user_handles.rc))
        {
          rsbac_uid_t                 user;
          rsbac_rc_role_id_t          role;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER RC ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          role = RSBAC_RC_SYSTEM_ADMIN_ROLE;
          if(rsbac_list_add(user_handles.rc, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER RC entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          role = RSBAC_RC_ROLE_ADMIN_ROLE;
          if(rsbac_list_add(user_handles.rc, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER RC entry could not be added!\n");
        }
    }
#endif
#if defined(CONFIG_RSBAC_AUTH)
    {
      rsbac_system_role_int_t def_aci = SR_user;

      list_info.version = RSBAC_AUTH_USER_ACI_VERSION;
      list_info.key = RSBAC_AUTH_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(rsbac_system_role_int_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.auth,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_AUTH_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER AUTH");
        }
      else
      if(!rsbac_list_count(user_handles.auth))
        {
          rsbac_uid_t                 user;
          rsbac_system_role_int_t     role;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER AUTH ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          role = SR_administrator;
          if(rsbac_list_add(user_handles.auth, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER AUTH entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          role = SR_security_officer;
          if(rsbac_list_add(user_handles.auth, &user, &role))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER AUTH entry could not be added!\n");
        }
    }
#endif
#if defined(CONFIG_RSBAC_CAP)
    {
      struct rsbac_cap_user_aci_t def_aci = DEFAULT_CAP_U_ACI;

      list_info.version = RSBAC_CAP_USER_ACI_VERSION;
      list_info.key = RSBAC_CAP_USER_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_uid_t);
      list_info.data_size = sizeof(struct rsbac_cap_user_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &user_handles.cap,
                                list_info,
                                #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
                                RSBAC_LIST_BACKUP |
                                #endif
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_CAP_ACI_USER_NAME,
                                0);
      if(err)
        {
          registration_error(err, "USER CAP");
        }
      else
      if(!rsbac_list_count(user_handles.cap))
        {
          struct rsbac_cap_user_aci_t sysadm_aci   = DEFAULT_CAP_U_SYSADM_ACI;
          struct rsbac_cap_user_aci_t secoff_aci   = DEFAULT_CAP_U_SECOFF_ACI;
          rsbac_uid_t                 user;

          printk(KERN_WARNING
                 "rsbac_do_init(): USER CAP ACI could not be read - generating standard entries!\n");
          user = RSBAC_SYSADM_UID;
          if(rsbac_list_add(user_handles.cap, &user, &sysadm_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): SYSADM USER CAP entry could not be added!\n");
          user = RSBAC_SECOFF_UID;
          if(rsbac_list_add(user_handles.cap, &user, &secoff_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): SECOFF USER CAP entry could not be added!\n");
        }
    }
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before registering PROCESS aci: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering PROCESS lists\n");
#endif
    {
      rsbac_request_vector_t def_aci = 0;

      list_info.version = RSBAC_GEN_PROCESS_ACI_VERSION;
      list_info.key = RSBAC_GEN_PROCESS_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_pid_t);
      list_info.data_size = sizeof(rsbac_request_vector_t); /* ind. process log */
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &process_handles.gen,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_GEN_ACI_PROCESS_NAME,
                                0);
      if(err)
        {
          registration_error(err, "PROCESS General");
        }
    }
#if defined(CONFIG_RSBAC_MAC)
    {
      struct rsbac_mac_process_aci_t def_aci = DEFAULT_MAC_P_ACI;

      list_info.version = RSBAC_MAC_PROCESS_ACI_VERSION;
      list_info.key = RSBAC_MAC_PROCESS_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_pid_t);
      list_info.data_size = sizeof(struct rsbac_mac_process_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &process_handles.mac,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_MAC_ACI_PROCESS_NAME,
                                0);
      if(err)
        {
          registration_error(err, "PROCESS MAC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_PM)
    {
      struct rsbac_pm_process_aci_t def_aci = DEFAULT_PM_P_ACI;

      list_info.version = RSBAC_PM_PROCESS_ACI_VERSION;
      list_info.key = RSBAC_PM_PROCESS_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_pid_t);
      list_info.data_size = sizeof(struct rsbac_pm_process_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &process_handles.pm,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_PM_ACI_PROCESS_NAME,
                                0);
      if(err)
        {
          registration_error(err, "PROCESS PM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_MS)
    {
      struct rsbac_ms_process_aci_t def_aci = DEFAULT_MS_P_ACI;

      list_info.version = RSBAC_MS_PROCESS_ACI_VERSION;
      list_info.key = RSBAC_MS_PROCESS_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_pid_t);
      list_info.data_size = sizeof(struct rsbac_ms_process_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &process_handles.ms,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_MS_ACI_PROCESS_NAME,
                                0);
      if(err)
        {
          registration_error(err, "PROCESS MS");
        }
    }
#endif
#if defined(CONFIG_RSBAC_RC)
    {
      struct rsbac_rc_process_aci_t def_aci = DEFAULT_RC_P_ACI;

      list_info.version = RSBAC_RC_PROCESS_ACI_VERSION;
      list_info.key = RSBAC_RC_PROCESS_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_pid_t);
      list_info.data_size = sizeof(struct rsbac_rc_process_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &process_handles.rc,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_RC_ACI_PROCESS_NAME,
                                0);
      if(err)
        {
          registration_error(err, "PROCESS RC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_AUTH)
    {
      struct rsbac_auth_process_aci_t def_aci = DEFAULT_AUTH_P_ACI;

      list_info.version = RSBAC_AUTH_PROCESS_ACI_VERSION;
      list_info.key = RSBAC_AUTH_PROCESS_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_pid_t);
      list_info.data_size = sizeof(struct rsbac_auth_process_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &process_handles.auth,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_AUTH_ACI_PROCESS_NAME,
                                0);
      if(err)
        {
          registration_error(err, "PROCESS AUTH");
        }
    }
#endif


/* Add all processes to list of processes as init processes */
#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_RC)
    {
      #ifdef CONFIG_RSBAC_MAC
      struct rsbac_mac_user_aci_t mac_u_aci;
      struct rsbac_mac_process_aci_t mac_p_aci = DEFAULT_MAC_P_INIT_ACI;
      #endif
      #ifdef CONFIG_RSBAC_RC
      rsbac_rc_role_id_t rc_u_role;
      struct rsbac_rc_process_aci_t rc_p_aci = DEFAULT_RC_P_INIT_ACI;
      #endif
      rsbac_uid_t user = RSBAC_SYSADM_UID;
      rsbac_pid_t pid = 1;
      struct task_struct * p;

/* Prepare entries: change standard values to root's values */
      #ifdef CONFIG_RSBAC_MAC
      if(!rsbac_list_get_data(user_handles.mac, &user, &mac_u_aci))
        {
          mac_p_aci.owner_sec_level = mac_u_aci.access_appr;
          mac_p_aci.current_sec_level = mac_u_aci.access_appr;
          mac_p_aci.min_write_open = mac_u_aci.access_appr;
          mac_p_aci.mac_owner_categories = mac_u_aci.mac_categories;
          mac_p_aci.mac_curr_categories = mac_u_aci.mac_categories;
          mac_p_aci.min_write_categories = mac_u_aci.mac_categories;
        }
      #endif
      #ifdef CONFIG_RSBAC_RC
      if(!rsbac_list_get_data(user_handles.rc, &user, &rc_u_role))
        {
          rc_p_aci.rc_role = rc_u_role;
        }
      #endif

/* Set process aci - first init */
      #ifdef CONFIG_RSBAC_MAC
      if(rsbac_list_add(process_handles.mac, &pid, &mac_p_aci))
        printk(KERN_WARNING
               "rsbac_do_init(): MAC ACI for Init process 1 could not be added!");
      #endif
      #ifdef CONFIG_RSBAC_RC
      if(rsbac_list_add(process_handles.rc, &pid, &rc_p_aci))
        printk(KERN_WARNING
               "rsbac_do_init(): RC ACI for Init process 1 could not be added!");
      #endif
      read_lock(&tasklist_lock);
      for_each_task(p)
        {
          /* not for kernel though... */
          if(!p->pid || (p->pid == 1))
            continue;
#ifdef CONFIG_RSBAC_DEBUG
          if (rsbac_debug_ds)
            printk(KERN_DEBUG "rsbac_do_init(): setting aci for process %u\n",
                   p->pid);
#endif
          #ifdef CONFIG_RSBAC_MAC
          if(rsbac_list_add(process_handles.mac, &p->pid, &mac_p_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): MAC ACI for Init process %u could not be added!",
                   p->pid);
          #endif
          #ifdef CONFIG_RSBAC_RC
          if(rsbac_list_add(process_handles.rc, &p->pid, &rc_p_aci))
            printk(KERN_WARNING
                   "rsbac_do_init(): RC ACI for Init process %u could not be added!",
                   p->pid);
          #endif
        }
      read_unlock(&tasklist_lock);
    }
#endif /* MAC or RC */

#ifdef CONFIG_RSBAC_NET_DEV
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering NETDEV lists\n");
#endif
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
    {
      struct rsbac_gen_netdev_aci_t def_aci = DEFAULT_GEN_NETDEV_ACI;

      list_info.version = RSBAC_GEN_NETDEV_ACI_VERSION;
      list_info.key = RSBAC_GEN_NETDEV_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_netdev_id_t);
      list_info.data_size = sizeof(struct rsbac_gen_netdev_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &netdev_handles.gen,
                                list_info,
                                RSBAC_LIST_BACKUP |
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                netdev_compare,
                                NULL,
                                &def_aci,
                                RSBAC_GEN_ACI_NETDEV_NAME,
                                0);
      if(err)
        {
          registration_error(err, "NETDEV General");
        }
    }
#endif
#if defined(CONFIG_RSBAC_RC)
    {
      rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;

      list_info.version = RSBAC_RC_NETDEV_ACI_VERSION;
      list_info.key = RSBAC_RC_NETDEV_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_netdev_id_t);
      list_info.data_size = sizeof(rsbac_rc_type_id_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &netdev_handles.rc,
                                list_info,
                                RSBAC_LIST_BACKUP |
                                RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                netdev_compare,
                                NULL,
                                &def_aci,
                                RSBAC_RC_ACI_NETDEV_NAME,
                                0);
      if(err)
        {
          registration_error(err, "NETDEV RC");
        }
    }
#endif
#endif

#ifdef CONFIG_RSBAC_NET_OBJ
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering network template list\n");
#endif
    list_info.version = RSBAC_NET_TEMP_VERSION;
    list_info.key = RSBAC_NET_TEMP_KEY;
    list_info.desc_size = sizeof(rsbac_net_temp_id_t);
    list_info.data_size = sizeof(struct rsbac_net_temp_data_t);
    list_info.max_age = 0;
    err = rsbac_list_register(RSBAC_LIST_VERSION,
                              &net_temp_handle,
                              list_info,
                              RSBAC_LIST_BACKUP |
                              RSBAC_LIST_PERSIST,
                              rsbac_list_compare_u32,
                              NULL,
                              NULL,
                              RSBAC_NET_TEMP_NAME,
                              0);
    if(err)
      {
        registration_error(err, "Network Template");
      }
    else
    if(!rsbac_list_count(net_temp_handle))
      {
        rsbac_net_temp_id_t id;
        struct rsbac_net_temp_data_t unix_data = RSBAC_NET_TEMP_UNIX_DATA;
        struct rsbac_net_temp_data_t lnet_data = RSBAC_NET_TEMP_LNET_DATA;
        struct rsbac_net_temp_data_t lan_data = RSBAC_NET_TEMP_LAN_DATA;
        struct rsbac_net_temp_data_t auto_data = RSBAC_NET_TEMP_AUTO_DATA;
        struct rsbac_net_temp_data_t inet_data = RSBAC_NET_TEMP_INET_DATA;
        struct rsbac_net_temp_data_t all_data = RSBAC_NET_TEMP_ALL_DATA;

        printk(KERN_WARNING
               "rsbac_do_init(): Network Templates could not be read - generating standard entries!\n");
        id = RSBAC_NET_TEMP_UNIX_ID;
        rsbac_list_add(net_temp_handle, &id, &unix_data);
        id = RSBAC_NET_TEMP_LNET_ID;
        rsbac_net_str_to_inet(RSBAC_NET_TEMP_LNET_ADDRESS, (__u32 *) lnet_data.address);
        rsbac_list_add(net_temp_handle, &id, &lnet_data);
        id = RSBAC_NET_TEMP_LAN_ID;
        rsbac_net_str_to_inet(RSBAC_NET_TEMP_LAN_ADDRESS, (__u32 *) lan_data.address);
        rsbac_list_add(net_temp_handle, &id, &lan_data);
        id = RSBAC_NET_TEMP_AUTO_ID;
        rsbac_net_str_to_inet(RSBAC_NET_TEMP_AUTO_ADDRESS, (__u32 *) auto_data.address);
        rsbac_list_add(net_temp_handle, &id, &auto_data);
        id = RSBAC_NET_TEMP_INET_ID;
        rsbac_list_add(net_temp_handle, &id, &inet_data);
        id = RSBAC_NET_TEMP_ALL_ID;
        rsbac_list_add(net_temp_handle, &id, &all_data);
      }

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering NETTEMP lists\n");
#endif

#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
    {
      struct rsbac_gen_netobj_aci_t def_aci = DEFAULT_GEN_NETOBJ_ACI;

      list_info.version = RSBAC_GEN_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_GEN_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_temp_id_t);
      list_info.data_size = sizeof(struct rsbac_gen_netobj_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &nettemp_handles.gen,
                                list_info,
                                RSBAC_LIST_BACKUP | RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_GEN_ACI_NETTEMP_NAME,
                                0);
      if(err)
        {
          registration_error(err, "NETTEMP GEN");
        }
    }
#endif
#if defined(CONFIG_RSBAC_MAC)
    {
      struct rsbac_mac_netobj_aci_t def_aci = DEFAULT_MAC_NETOBJ_ACI;

      list_info.version = RSBAC_MAC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_MAC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_temp_id_t);
      list_info.data_size = sizeof(struct rsbac_mac_netobj_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &nettemp_handles.mac,
                                list_info,
                                RSBAC_LIST_BACKUP | RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_MAC_ACI_NETTEMP_NAME,
                                0);
      if(err)
        {
          registration_error(err, "NETTEMP MAC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_FC)
    {
      rsbac_fc_oc_t def_aci = RSBAC_FC_OC_ROOT_DEF;

      list_info.version = RSBAC_FC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_FC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_temp_id_t);
      list_info.data_size = sizeof(rsbac_fc_oc_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &nettemp_handles.fc,
                                list_info,
                                RSBAC_LIST_BACKUP | RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_FC_ACI_NETTEMP_NAME,
                                0);
      if(err)
        {
          registration_error(err, "NETTEMP FC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_SIM)
    {
      rsbac_sim_dt_t def_aci = RSBAC_SIM_DT_ROOT_DEF;

      list_info.version = RSBAC_SIM_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_SIM_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_temp_id_t);
      list_info.data_size = sizeof(rsbac_sim_dt_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &nettemp_handles.sim,
                                list_info,
                                RSBAC_LIST_BACKUP | RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_SIM_ACI_NETTEMP_NAME,
                                0);
      if(err)
        {
          registration_error(err, "NETTEMP SIM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_PM)
    {
      struct rsbac_pm_netobj_aci_t def_aci = DEFAULT_PM_NETOBJ_ACI;

      list_info.version = RSBAC_PM_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_PM_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_temp_id_t);
      list_info.data_size = sizeof(struct rsbac_pm_netobj_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &nettemp_handles.pm,
                                list_info,
                                RSBAC_LIST_BACKUP | RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_PM_ACI_NETTEMP_NAME,
                                0);
      if(err)
        {
          registration_error(err, "NETTEMP PM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_RC)
    {
      struct rsbac_rc_nettemp_aci_t def_aci = DEFAULT_RC_NETTEMP_ACI;

      list_info.version = RSBAC_RC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_RC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_temp_id_t);
      list_info.data_size = sizeof(struct rsbac_rc_nettemp_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &nettemp_handles.rc,
                                list_info,
                                RSBAC_LIST_BACKUP | RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_RC_ACI_NETTEMP_NAME,
                                0);
      if(err)
        {
          registration_error(err, "NETTEMP RC");
        }
    }
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering local NETOBJ lists\n");
#endif
#if defined(CONFIG_RSBAC_MAC)
    {
      struct rsbac_mac_netobj_aci_t def_aci = DEFAULT_MAC_NETOBJ_ACI;

      list_info.version = RSBAC_MAC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_MAC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(struct rsbac_mac_netobj_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &lnetobj_handles.mac,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_MAC_ACI_LNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "LNETOBJ MAC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_FC)
    {
      rsbac_fc_oc_t def_aci = RSBAC_FC_OC_ROOT_DEF;

      list_info.version = RSBAC_FC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_FC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(rsbac_fc_oc_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &lnetobj_handles.fc,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_FC_ACI_LNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "LNETOBJ FC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_SIM)
    {
      rsbac_sim_dt_t def_aci = RSBAC_SIM_DT_ROOT_DEF;

      list_info.version = RSBAC_SIM_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_SIM_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(rsbac_sim_dt_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &lnetobj_handles.sim,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_SIM_ACI_LNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "LNETOBJ SIM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_PM)
    {
      struct rsbac_pm_netobj_aci_t def_aci = DEFAULT_PM_NETOBJ_ACI;

      list_info.version = RSBAC_PM_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_PM_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(struct rsbac_pm_netobj_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &lnetobj_handles.pm,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_PM_ACI_LNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "LNETOBJ PM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_MS)
    {
      struct rsbac_ms_netobj_aci_t def_aci = DEFAULT_MS_NETOBJ_ACI;

      list_info.version = RSBAC_MS_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_MS_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(struct rsbac_ms_netobj_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &lnetobj_handles.ms,
                                list_info,
                                RSBAC_LIST_DEF_DATA,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_MS_ACI_LNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "LNETOBJ MS");
        }
    }
#endif
#if defined(CONFIG_RSBAC_RC)
    {
      rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;

      list_info.version = RSBAC_RC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_RC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(rsbac_rc_type_id_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &lnetobj_handles.rc,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_RC_ACI_LNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "LNETOBJ RC");
        }
    }
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_do_init(): registering remote NETOBJ lists\n");
#endif
#if defined(CONFIG_RSBAC_MAC)
    {
      struct rsbac_mac_netobj_aci_t def_aci = DEFAULT_MAC_NETOBJ_ACI;

      list_info.version = RSBAC_MAC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_MAC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(struct rsbac_mac_netobj_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &rnetobj_handles.mac,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_MAC_ACI_RNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "RNETOBJ MAC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_FC)
    {
      rsbac_fc_oc_t def_aci = RSBAC_FC_OC_ROOT_DEF;

      list_info.version = RSBAC_FC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_FC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(rsbac_fc_oc_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &rnetobj_handles.fc,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_FC_ACI_RNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "RNETOBJ FC");
        }
    }
#endif
#if defined(CONFIG_RSBAC_SIM)
    {
      rsbac_sim_dt_t def_aci = RSBAC_SIM_DT_ROOT_DEF;

      list_info.version = RSBAC_SIM_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_SIM_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(rsbac_sim_dt_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &rnetobj_handles.sim,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_SIM_ACI_RNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "RNETOBJ SIM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_PM)
    {
      struct rsbac_pm_netobj_aci_t def_aci = DEFAULT_PM_NETOBJ_ACI;

      list_info.version = RSBAC_PM_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_PM_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(struct rsbac_pm_netobj_aci_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &rnetobj_handles.pm,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_PM_ACI_RNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "RNETOBJ PM");
        }
    }
#endif
#if defined(CONFIG_RSBAC_RC)
    {
      rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;

      list_info.version = RSBAC_RC_NETOBJ_ACI_VERSION;
      list_info.key = RSBAC_RC_NETOBJ_ACI_KEY;
      list_info.desc_size = sizeof(rsbac_net_obj_id_t);
      list_info.data_size = sizeof(rsbac_rc_type_id_t);
      list_info.max_age = 0;
      err = rsbac_list_register(RSBAC_LIST_VERSION,
                                &rnetobj_handles.rc,
                                list_info,
                                0,
                                rsbac_list_compare_u32,
                                NULL,
                                &def_aci,
                                RSBAC_RC_ACI_RNETOBJ_NAME,
                                0);
      if(err)
        {
          registration_error(err, "RNETOBJ RC");
        }
    }
#endif
#endif /* NET_OBJ */

/* Call other init functions */
    #ifdef CONFIG_RSBAC_PM
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before init_pm: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    rsbac_init_pm();
    #endif

    #if defined(CONFIG_RSBAC_MS) && !defined(CONFIG_RSBAC_MAINT)
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before init_ms: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    rsbac_init_ms();
    #endif

    #if defined(CONFIG_RSBAC_RC)
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before init_rc: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    rsbac_init_rc();
    #endif

    #if defined(CONFIG_RSBAC_AUTH)
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before init_auth: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    rsbac_init_auth();
    if (rsbac_auth_enable_login)
      {
        struct dentry * t_dentry;
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
        struct dentry * dir_dentry = NULL;
        #endif
        struct rsbac_auth_fd_aci_t auth_fd_aci = DEFAULT_AUTH_FD_ACI;
        int list_no;

        printk(KERN_WARNING
               "rsbac_do_init(): auth_enable_login is set: setting auth_may_setuid for %s\n",
               RSBAC_AUTH_LOGIN_PATH);

        /* lookup filename */
        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        t_dentry = rsbac_lookup_dentry(RSBAC_AUTH_LOGIN_PATH,NULL,0);
        if (IS_ERR(t_dentry))
          {
            err = PTR_ERR(t_dentry);
            printk(KERN_WARNING "rsbac_do_init(): call to lookup_dentry() returned %i\n", err);
            goto auth_out;
          }
        #else
        if(sb_p)
          {
            dir_dentry = rsbac_lookup_one_len(RSBAC_AUTH_LOGIN_PATH_DIR,
                                              sb_p->s_root,
                                              strlen(RSBAC_AUTH_LOGIN_PATH_DIR));
          }
        if (!dir_dentry)
          {
            err = -RSBAC_ENOTFOUND;
            printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s failed\n",
                   RSBAC_AUTH_LOGIN_PATH_DIR);
            goto auth_out;
          }
        if (IS_ERR(dir_dentry))
          {
            err = PTR_ERR(dir_dentry);
            printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s returned %i\n",
                   RSBAC_AUTH_LOGIN_PATH_DIR,
                   err);
            goto auth_out;
          }
        if (!dir_dentry->d_inode)
          {
            err = -RSBAC_ENOTFOUND;
            printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s failed\n",
                   RSBAC_AUTH_LOGIN_PATH_DIR);
            dput(dir_dentry);
            goto auth_out;
          }
        t_dentry = rsbac_lookup_one_len(RSBAC_AUTH_LOGIN_PATH_FILE,
                                        dir_dentry,
                                        strlen(RSBAC_AUTH_LOGIN_PATH_FILE));
        if (!t_dentry)
          {
            err = -RSBAC_ENOTFOUND;
            printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s/%s failed\n",
                   RSBAC_AUTH_LOGIN_PATH_DIR,
                   RSBAC_AUTH_LOGIN_PATH_FILE);
            goto auth_out;
          }
        if (IS_ERR(t_dentry))
          {
            err = PTR_ERR(t_dentry);
            printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s/%s returned %i\n",
                   RSBAC_AUTH_LOGIN_PATH_DIR,
                   RSBAC_AUTH_LOGIN_PATH_FILE,
                   err);
            goto auth_out;
          }
        if (!t_dentry->d_inode)
          {
            err = -RSBAC_ENOTFOUND;
            printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s/%s failed\n",
                   RSBAC_AUTH_LOGIN_PATH_DIR,
                   RSBAC_AUTH_LOGIN_PATH_FILE);
            dput(t_dentry);
            goto auth_out;
          }
        #endif

        if (!t_dentry->d_inode)
          {
            printk(KERN_WARNING "rsbac_do_init(): file %s not found\n",
                   RSBAC_AUTH_LOGIN_PATH);
            err = -RSBAC_EINVALIDTARGET;
            goto auth_out_dput;
          }
        /* is inode of type file? */
        if (!S_ISREG(t_dentry->d_inode->i_mode))
          {
            printk(KERN_WARNING "rsbac_do_init(): %s is no file\n", RSBAC_AUTH_LOGIN_PATH);
            err = -RSBAC_EINVALIDTARGET;
            goto auth_out_dput;
          }
        list_no = auth_fd_hash(t_dentry->d_inode->i_ino);
        rsbac_list_get_data(device_p->handles.auth[list_no],
                            &t_dentry->d_inode->i_ino,
                            &auth_fd_aci);
        auth_fd_aci.auth_may_setuid = TRUE;
        if(rsbac_list_add(device_p->handles.auth[list_no],
                          &t_dentry->d_inode->i_ino,
                          &auth_fd_aci))
          { /* Adding failed! */
            printk(KERN_WARNING
                   "rsbac_do_init(): Could not add AUTH file/dir item!\n");
            err = -RSBAC_ECOULDNOTADDITEM;
          }

      auth_out_dput:
        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        dput(t_dentry);
        #endif
      auth_out:
      }
    #endif

    #if defined(CONFIG_RSBAC_ACL)
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before init_acl: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    rsbac_init_acl();
    #endif

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before init_debug: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    rsbac_init_debug();
    rsbac_init_adf();

    /* free super_block pointer */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,8)
    drop_super(sb_p);
#endif

/* Tell that rsbac is initialized                                       */    
    rsbac_initialized = TRUE;

/* Add devfs mount */
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
    #ifdef CONFIG_DEVFS_MOUNT
    if(   devfs_covered_p
       && devfs_sb_p
      )
      {
        printk(KERN_WARNING "rsbac_do_init(): automounting devfs device %02u:%02u\n",
               MAJOR(devfs_sb_p->s_dev), MINOR(devfs_sb_p->s_dev));
        rsbac_mount(devfs_sb_p, devfs_covered_p);
      }
    #endif
    #endif

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11)
    if(sockfs_sb_p)
      {
        printk(KERN_WARNING "rsbac_do_init(): automounting sockfs device %02u:%02u\n",
               MAJOR(sockfs_sb_p->s_dev), MINOR(sockfs_sb_p->s_dev));
        rsbac_mount(sockfs_sb_p, NULL);
      }
    if(pipefs_sb_p)
      {
        printk(KERN_WARNING "rsbac_do_init(): automounting pipefs device %02u:%02u\n",
               MAJOR(pipefs_sb_p->s_dev), MINOR(pipefs_sb_p->s_dev));
        rsbac_mount(pipefs_sb_p, NULL);
      }
    #endif

/* Force a check, if configured */
#ifdef CONFIG_RSBAC_INIT_CHECK
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_do_init: free stack before rsbac_check: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    printk(KERN_INFO "rsbac_do_init(): Forcing consistency check.\n");
    rsbac_check_lists(1);
    rsbac_check(1,0);
    /* call other checks */
    #if defined(CONFIG_RSBAC_AUTH)
    rsbac_check_auth(1,0);
    #endif
    #if defined(CONFIG_RSBAC_ACL)
    rsbac_check_acl(1,0);
    #endif
#endif

    if (!current->fs)
      {
        printk(KERN_WARNING "rsbac_do_init(): current->fs is invalid!\n");
        err = -RSBAC_EINVALIDPOINTER;
      }
out:
/* Ready. */
    printk(KERN_INFO "rsbac_do_init(): Ready.\n");
    return(err);

out_free:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,8)
    /* free super_block pointer */
    drop_super(sb_p);
#endif
    goto out;
  };


#if  (defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)) \
   || defined(CONFIG_RSBAC_INIT_THREAD)
/* rsbac kernel timer for auto-write */
void wakeup_rsbacd(u_long dummy)
  {
    wake_up(&rsbacd_wait);
  }
#endif

#ifdef CONFIG_RSBAC_INIT_THREAD
/* rsbac kernel daemon for init */
static int rsbac_initd(void * dummy)
  {
    printk(KERN_INFO "rsbac_initd(): Initializing.\n");
    current->session = 1;
    current->pgrp = 1;
    strcpy(current->comm, "rsbac_initd");

/* Dead loop for timeout testing */
/*    while(1) { } */

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_initd: free stack before rsbac_do_init(): %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    /* init RSBAC */
    rsbac_do_init();

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_initd: free stack after rsbac_do_init(): %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    /* wake up init process */
    wake_up(&rsbacd_wait);
    /* ready */
    printk(KERN_INFO "rsbac_initd(): Exiting.\n");
    do_exit(0);
    return 0;
  }
#endif

#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
/* rsbac kernel daemon for auto-write */
static int rsbacd(void * dummy)
  {
    struct task_struct *tsk = current;
    char * name = rsbac_kmalloc(RSBAC_MAXNAMELEN);

    printk(KERN_INFO "rsbacd(): Initializing.\n");
    tsk->session = 1;
    tsk->pgrp = 1;
    strcpy(tsk->comm, "rsbacd");

/*    lock_kernel(); */

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_auto)
      printk(KERN_DEBUG "rsbacd(): Setting auto timer.\n");
#endif
/* This might already have been done for rsbac_initd thread */
#ifndef CONFIG_RSBAC_INIT_THREAD
    init_timer(&rsbac_timer);
    rsbac_timer.function = wakeup_rsbacd;
    rsbac_timer.data = 0;
    rsbac_timer.expires = jiffies + auto_interval;
    add_timer(&rsbac_timer);
#endif

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbacd: free stack: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    for(;;)
      {
        /* wait */
        spin_lock_irq(&tsk->sigmask_lock);
        flush_signals(tsk);
        sigfillset(&tsk->blocked);
        recalc_sigpending(tsk);
        spin_unlock_irq(&tsk->sigmask_lock);
        /* set new timer */
        mod_timer(&rsbac_timer, jiffies + auto_interval);
        interruptible_sleep_on(&rsbacd_wait);
        /* sleep */
/*        schedule_timeout(auto_interval); */
        if(rsbac_initialized)
          {
            int err;
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_auto)
              printk(KERN_DEBUG
                     "rsbacd(): calling rsbac_write()\n");
#endif
*/
            /* call rsbac_write with lock_kernel() */
            err = rsbac_write(TRUE);
            if(err < 0)
              {
                if(name)
                  printk(KERN_WARNING
                         "rsbacd(): rsbac_write returned error %s!\n",
                         get_error_name(name,err));
                else
                  printk(KERN_WARNING
                         "rsbacd(): rsbac_write returned error %i!\n",
                         err);
              }
#ifdef CONFIG_RSBAC_DEBUG
            else
              if (rsbac_debug_auto && (err > 0))
                printk(KERN_DEBUG
                       "rsbacd(): rsbac_write() wrote %i lists\n", err);
#endif
          }
      }
  }
#endif /* CONFIG_RSBAC_AUTO_WRITE > 0 */

/************************************************* */
/*               Init function                     */
/************************************************* */

/* All functions return 0, if no error occurred, and a negative error code  */
/* otherwise. The error codes are defined in rsbac_error.h.                 */

/* declare sys_kill */
extern long sys_kill(int pid, int sig);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);
#endif


int __init rsbac_init(kdev_t root_dev)
  {
    int err = 0;
#if  (defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)) \
   || defined(CONFIG_RSBAC_INIT_THREAD)
    rsbac_pid_t rsbacd_pid;
#endif

    if (rsbac_initialized)
      {
        printk(KERN_WARNING "rsbac_init(): RSBAC already initialized\n");
        return(-RSBAC_EREINIT);
      }
    if (!current->fs)
      {
        printk(KERN_WARNING "rsbac_init(): current->fs is invalid!\n");
        return(-RSBAC_EINVALIDPOINTER);
      }

    rsbac_root_dev = root_dev;

#if  (defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)) \
   || defined(CONFIG_RSBAC_INIT_THREAD)
    /* init the rsbacd wait queue head */
    init_waitqueue_head(&rsbacd_wait);
#endif

#ifdef CONFIG_RSBAC_INIT_THREAD
/* trigger dependency */
#ifdef CONFIG_RSBAC_MAX_INIT_TIME
#endif
    printk(KERN_INFO "rsbac_init(): Setting init timeout to %u seconds (%u jiffies).\n",
           RSBAC_MAX_INIT_TIME, RSBAC_MAX_INIT_TIME * HZ);
    init_timer(&rsbac_timer);
    rsbac_timer.function = wakeup_rsbacd;
    rsbac_timer.data = 0;
    rsbac_timer.expires = jiffies + (RSBAC_MAX_INIT_TIME * HZ);
    add_timer(&rsbac_timer);

/* Start rsbac thread for init */
    rsbacd_pid = kernel_thread(rsbac_initd, NULL, SIGCHLD);
    printk(KERN_INFO "rsbac_init(): Started rsbac_initd thread with pid %u\n",
           rsbacd_pid);

    if(!rsbac_initialized)
      interruptible_sleep_on(&rsbacd_wait);
    if(!rsbac_initialized)
      {
        printk(KERN_ERR
               "rsbac_init(): *** RSBAC init timed out - RSBAC not correctly initialized! ***\n");
        printk(KERN_ERR
               "rsbac_init(): *** Killing rsbac_initd! ***\n");
        sys_kill(rsbacd_pid, SIGKILL);
        rsbac_initialized = FALSE;
      }
#else
    rsbac_do_init();
#endif

#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
    if(rsbac_initialized)
      {
        /* Start rsbac thread for auto write */
        rsbacd_pid = kernel_thread(rsbacd, NULL, 0);
        printk(KERN_INFO "rsbac_init(): Started rsbacd thread with pid %u\n",
               rsbacd_pid);
      }
#endif

/* Ready. */
/*    schedule(); */
#ifdef CONFIG_RSBAC_INIT_THREAD
    sys_wait4(-1, NULL, WNOHANG, NULL);
#endif
    printk(KERN_INFO "rsbac_init(): Ready.\n");
    return(err);
  };

/* To check, whether RSBAC is already initialized: */

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_is_initialized);
#endif
inline boolean rsbac_is_initialized(void)
  {
    return rsbac_initialized;
  };

/* When mounting a device, its ACI must be read and added to the ACI lists. */

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
int rsbac_mount(struct super_block * sb_p)
#else
int rsbac_mount(struct super_block * sb_p, struct dentry * d_covers)
#endif
  {
    int err = 0;
    struct rsbac_device_list_item_t * device_p;
    struct rsbac_device_list_item_t * new_device_p;
    u_long flags;

    if(!sb_p)
      {
        printk(KERN_WARNING
               "rsbac_mount(): called with NULL pointer\n");
        return -RSBAC_EINVALIDPOINTER;
      }
    if (!rsbac_initialized)
      {
        printk(KERN_WARNING
               "rsbac_mount(): RSBAC not initialized while mounting DEV %02u:%02u, delaying\n",
               MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11)
        if(sb_p->s_magic == SOCKFS_MAGIC)
          {
            printk(KERN_WARNING
                   "rsbac_mount(): sockfs mount detected, keeping values for later use\n");
            sockfs_sb_p = sb_p;
          }
        if(sb_p->s_magic == PIPEFS_MAGIC)
          {
            printk(KERN_WARNING
                   "rsbac_mount(): pipefs mount detected, keeping values for later use\n");
            pipefs_sb_p = sb_p;
          }
        #endif
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
        #ifdef CONFIG_DEVFS_MOUNT
        if(sb_p->s_magic == DEVFS_SUPER_MAGIC)
          {
            printk(KERN_WARNING
                   "rsbac_mount(): devfs mount detected, keeping values for later use\n");
            devfs_sb_p = sb_p;
            devfs_covered_p = d_covers;
          }
        #endif
        #endif

        return(-RSBAC_ENOTINITIALIZED);
      }
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_mount(): mounting device %02u:%02u\n",
             MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
	printk(KERN_DEBUG "rsbac_mount: free stack: %lu\n",
	       (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    /* wait for read access to device_list_head */
    rsbac_read_lock(&device_list_head.lock, &flags);
    device_p = lookup_device(sb_p->s_dev);
    /* repeated mount? */
    if(device_p)
      {
        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        printk(KERN_WARNING "rsbac_mount: repeated mount of device %02u:%02u\n",
               MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
	#else
        printk(KERN_INFO "rsbac_mount: repeated mount %u of device %02u:%02u\n",
               device_p->mount_count, MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
	device_p->mount_count++;
	if(   d_covers
	   && !device_p->d_covers
	   && (sb_p->s_dev != rsbac_root_dev)
	  )
	  {
            printk(KERN_WARNING "rsbac_mount: replacing NULL d_covers with new value %p as inheritance parent\n",
                   d_covers);
	    device_p->d_covers = d_covers;
	  }
	#endif
        rsbac_read_unlock(&device_list_head.lock, &flags);
        /* Generic lists */
        rsbac_list_mount(sb_p->s_dev);
      }
    else
      {
        rsbac_read_unlock(&device_list_head.lock, &flags);
        /* OK, go on */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        new_device_p = create_device_item(sb_p); 
#else
        new_device_p = create_device_item(sb_p, d_covers); 
#endif
#ifdef CONFIG_RSBAC_DEBUG
        if(rsbac_debug_stack)
          {
            unsigned long * n = (unsigned long *) (current+1);

            while (!*n)
              n++;
	    printk(KERN_DEBUG "rsbac_mount: after creating device item: free stack: %lu\n",
	           (unsigned long) n - (unsigned long)(current+1));
          }
#endif
        if(!new_device_p)
          {
            return -RSBAC_ECOULDNOTADDDEVICE;
          }
        rsbac_read_lock(&device_list_head.lock, &flags);
        /* make sure to only add, if this device item has not been added in the meantime */
        device_p = lookup_device(sb_p->s_dev);
        if(device_p)
          {
            printk(KERN_WARNING
                   "rsbac_mount(): mount race for device %02u:%02u detected!\n",
                   MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
            #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
            device_p->mount_count++;
            #endif
            rsbac_read_unlock(&device_list_head.lock, &flags);
            clear_device_item(new_device_p);
          }
        else
          {
/* changed to read-locked adding of device - lookups always find a correct chain,
 * and there cannot be two mounts at the same time due to mount semaphore
 */
            device_p = add_device_item(new_device_p);
            rsbac_read_unlock(&device_list_head.lock, &flags);
            if(!device_p)
              {
                printk(KERN_WARNING "rsbac_mount: adding device %02u:%02u failed!\n",
                       MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
                clear_device_item(new_device_p);
                return -RSBAC_ECOULDNOTADDDEVICE;
              }
          }

        /* Generic lists */
        rsbac_list_mount(sb_p->s_dev);
        /* we do not lock device head - we know the device_p and hope for the best... */
        /* also, we are within kernel mount sem */
        if((err = register_fd_lists(new_device_p, sb_p->s_dev)))
          {
            char * tmp;

            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
            if(tmp)
              {
                printk(KERN_WARNING
                       "rsbac_mount(): File/Dir ACI registration failed for dev %02u:%02u, err %s!\n",
                       MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev), get_error_name(tmp,err));
                rsbac_kfree(tmp);
              }
          }
#ifdef CONFIG_RSBAC_DEBUG
        if(rsbac_debug_stack)
          {
            unsigned long * n = (unsigned long *) (current+1);

            while (!*n)
              n++;
            printk(KERN_DEBUG "rsbac_mount: after registering fd lists: free stack: %lu\n",
                   (unsigned long) n - (unsigned long)(current+1));
          }
#endif
      }

    /* call other mount functions */
    /****** AUTH *******/
    #if defined(CONFIG_RSBAC_AUTH)
    rsbac_mount_auth(sb_p->s_dev);
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
        printk(KERN_DEBUG "rsbac_mount: after mount_auth: free stack: %lu\n",
               (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    #endif
    /****** ACL *******/
    #if defined(CONFIG_RSBAC_ACL)
    rsbac_mount_acl(sb_p->s_dev);
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
        printk(KERN_DEBUG "rsbac_mount: after mount_acl: free stack: %lu\n",
               (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    #endif
    /****** REG *******/
    #if defined(CONFIG_RSBAC_REG)
    rsbac_mount_reg(sb_p->s_dev);
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_stack)
      {
        unsigned long * n = (unsigned long *) (current+1);

        while (!*n)
          n++;
        printk(KERN_DEBUG "rsbac_mount: after mount_reg: free stack: %lu\n",
               (unsigned long) n - (unsigned long)(current+1));
      }
#endif
    #endif  /* REG */

    return(err);
  };
  
/* When umounting a device, its ACI must be removed from the ACI lists.     */
/* Removing the device ACI should be no problem.                            */

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
int rsbac_umount(struct super_block * sb_p)
#else
int rsbac_umount(struct super_block * sb_p, struct dentry * d_covers)
#endif
  {
    u_long flags;
    struct rsbac_device_list_item_t * device_p;

    if(!sb_p)
      {
        printk(KERN_WARNING
               "rsbac_umount(): called with NULL pointer\n");
        return -RSBAC_EINVALIDPOINTER;
      }
    if (!rsbac_initialized)
      {
        printk(KERN_WARNING "rsbac_umount(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG "rsbac_umount(): umounting device %02u:%02u\n",
             MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
#endif
    /* sync attribute lists */
#if defined(CONFIG_RSBAC_AUTO_WRITE)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
    rsbac_write(TRUE);
#else
    rsbac_write(FALSE);
#endif
#endif /* CONFIG_RSBAC_AUTO_WRITE */
    /* call other umount functions */
    #if defined(CONFIG_RSBAC_AUTH)
    rsbac_umount_auth(sb_p->s_dev);
    #endif
    /****** ACL *******/
    #if defined(CONFIG_RSBAC_ACL)
    rsbac_umount_acl(sb_p->s_dev);
    #endif
    /****** REG *******/
    #if defined(CONFIG_RSBAC_REG)
    rsbac_umount_reg(sb_p->s_dev);
    #endif  /* REG */
    /* Generic lists */
    rsbac_list_umount(sb_p->s_dev);
    /* wait for write access to device_list_head */
    rsbac_write_lock(&device_list_head.lock, &flags);
    /* OK, nobody else is working on it... */
    device_p = lookup_device(sb_p->s_dev);
    if(device_p)
      {
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
        if(device_p->mount_count == 1)
        #endif
          remove_device_item(sb_p->s_dev);
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
        else
          {
            if(device_p->mount_count > 1)
              {
                device_p->mount_count--;
                if(device_p->d_covers == d_covers)
                  {
                    printk(KERN_WARNING "rsbac_mount: removed primary mount for device %02u:%02u, inheritance broken!\n",
                           MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
                    device_p->d_covers = NULL;
                  }
              }
            else
              {
                printk(KERN_WARNING "rsbac_mount: device %02u:%02u has mount_count < 1!\n",
                       MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
              }
          }
        #endif
      }
    /* allow access */
    rsbac_write_unlock(&device_list_head.lock, &flags);
    return(0);
  };

/***************************************************/
/* We also need some status information...         */

int rsbac_stats(void)
  {
    struct rsbac_device_list_item_t   * device_p;
    int                                 i;
    u_long                              fd_count = 0, fd_sum = 0;
    u_long                              dev_sum = 0;
    u_long                              ipc_sum = 0;
    u_long                              user_sum = 0;
    u_long                              process_sum = 0;
#if defined(CONFIG_RSBAC_NET_OBJ)
    u_long                              nettemp_sum = 0;
    u_long                              lnetobj_sum = 0;
    u_long                              rnetobj_sum = 0;
#endif
    u_long                              total_sum = 0;
    long                                tmp_count;
    u_long                              dflags;

    if (!rsbac_initialized)
      {
        printk(KERN_WARNING "rsbac_stats(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    /* wait for read access to device_list_head */
    rsbac_read_lock(&device_list_head.lock, &dflags);
    /* OK, go on */
/*    printk(KERN_INFO "rsbac_stats(): currently %u processes working on file/dir aci\n",
                     device_list_head.lock.lock); */
    device_p = device_list_head.head;
    while (device_p)
      { /* for all sublists */
        fd_count = 0;
        for (i=0; i < RSBAC_GEN_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.gen[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(KERN_INFO "Device %02u:%02u fd_items: %lu GEN",
               MAJOR(device_p->id), MINOR(device_p->id), fd_count);
        fd_sum += fd_count;

#if defined(CONFIG_RSBAC_MAC)
        fd_count = 0;
        for (i=0; i < RSBAC_MAC_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.mac[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu MAC",
               fd_count);
        fd_sum += fd_count;
#endif

#if defined(CONFIG_RSBAC_FC)
        fd_count = 0;
        for (i=0; i < RSBAC_FC_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.fc[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu FC",
               fd_count);
        fd_sum += fd_count;
#endif

#if defined(CONFIG_RSBAC_SIM)
        fd_count = 0;
        for (i=0; i < RSBAC_SIM_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.sim[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu SIM",
               fd_count);
        fd_sum += fd_count;
#endif

#if defined(CONFIG_RSBAC_PM)
        fd_count = 0;
        for (i=0; i < RSBAC_PM_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.pm[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu PM",
               fd_count);
        fd_sum += fd_count;
#endif

#if defined(CONFIG_RSBAC_MS)
        fd_count = 0;
        for (i=0; i < RSBAC_MS_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.ms[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu MS",
               fd_count);
        fd_sum += fd_count;
        fd_count = 0;
        for (i=0; i < RSBAC_MS_SCANNED_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.mss[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu MS_SCANNED",
               fd_count);
        fd_sum += fd_count;
#endif

#if defined(CONFIG_RSBAC_FF)
        fd_count = 0;
        for (i=0; i < RSBAC_FF_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.ff[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu FF",
               fd_count);
        fd_sum += fd_count;
#endif

#if defined(CONFIG_RSBAC_RC)
        fd_count = 0;
        for (i=0; i < RSBAC_RC_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.rc[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu RC",
               fd_count);
        fd_sum += fd_count;
#endif

#if defined(CONFIG_RSBAC_AUTH)
        fd_count = 0;
        for (i=0; i < RSBAC_AUTH_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.auth[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu AUTH",
               fd_count);
        fd_sum += fd_count;
#endif

#if defined(CONFIG_RSBAC_CAP)
        fd_count = 0;
        for (i=0; i < RSBAC_CAP_NR_FD_LISTS; i++)
          {
            tmp_count = rsbac_list_count(device_p->handles.cap[i]);
            if(tmp_count > 0)
              fd_count+=tmp_count;
          };
        printk(", %lu CAP",
               fd_count);
        fd_sum += fd_count;
#endif

        printk("\n");
        device_p = device_p->next;
      };
    printk(KERN_INFO "rsbac_stats(): Sum of %u Devices with %lu fd-items\n",
                 device_list_head.count, fd_sum);
    /* free access to device_list_head */
    rsbac_read_unlock(&device_list_head.lock, &dflags);
    total_sum += fd_sum;
    
    /* dev lists */
    tmp_count = rsbac_list_count(dev_handles.gen);
    printk(KERN_INFO "DEV items: %lu GEN",
                   tmp_count);
    dev_sum += tmp_count;
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(dev_handles.mac);
    printk(", %lu MAC",
                   tmp_count);
    dev_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(dev_handles.fc);
    printk(", %lu FC",
                   tmp_count);
    dev_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(dev_handles.sim);
    printk(", %lu SIM",
                   tmp_count);
    dev_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(dev_handles.pm);
    printk(", %lu PM",
                   tmp_count);
    dev_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(dev_handles.rc);
    printk(", %lu RC",
                   tmp_count);
    dev_sum += tmp_count;
#endif
    printk("\n");
    printk(KERN_INFO "Sum of %lu DEV items\n",
                   dev_sum);
    total_sum += dev_sum;

    /* ipc lists */
    printk(KERN_INFO "IPC items:\nno GEN");
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(ipc_handles.mac);
    printk(", %lu MAC",
                   tmp_count);
    ipc_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(ipc_handles.fc);
    printk(", %lu FC",
                   tmp_count);
    ipc_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(ipc_handles.sim);
    printk(", %lu SIM",
                   tmp_count);
    ipc_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(ipc_handles.pm);
    printk(", %lu PM",
                   tmp_count);
    ipc_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(ipc_handles.rc);
    printk(", %lu RC",
                   tmp_count);
    ipc_sum += tmp_count;
#endif
    printk("\n");
    printk(KERN_INFO "Sum of %lu IPC items\n",
                   ipc_sum);
    total_sum += ipc_sum;

    /* user lists */
    tmp_count = rsbac_list_count(user_handles.gen);
    printk(KERN_INFO "USER items:\n%lu GEN",
                   tmp_count);
    user_sum += tmp_count;
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(user_handles.mac);
    printk(", %lu MAC",
                   tmp_count);
    user_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(user_handles.fc);
    printk(", %lu FC",
                   tmp_count);
    user_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(user_handles.sim);
    printk(", %lu SIM",
                   tmp_count);
    user_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(user_handles.pm);
    printk(", %lu PM",
                   tmp_count);
    user_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_MS)
    tmp_count = rsbac_list_count(user_handles.ms);
    printk(", %lu MS",
                   tmp_count);
    user_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(user_handles.rc);
    printk(", %lu RC",
                   tmp_count);
    user_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_AUTH)
    tmp_count = rsbac_list_count(user_handles.auth);
    printk(", %lu AUTH",
                   tmp_count);
    user_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_CAP)
    tmp_count = rsbac_list_count(user_handles.cap);
    printk(", %lu CAP",
                   tmp_count);
    user_sum += tmp_count;
#endif
    printk("\n");
    printk(KERN_INFO "Sum of %lu USER items\n",
                   user_sum);
    total_sum += user_sum;

    /* process lists */
    tmp_count = rsbac_list_count(process_handles.gen);
    printk(KERN_INFO "PROCESS items:\n%lu GEN",
                   tmp_count);
    process_sum += tmp_count;
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(process_handles.mac);
    printk(", %lu MAC",
                   tmp_count);
    process_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(process_handles.pm);
    printk(", %lu PM",
                   tmp_count);
    process_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_MS)
    tmp_count = rsbac_list_count(process_handles.ms);
    printk(", %lu MS",
                   tmp_count);
    process_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(process_handles.rc);
    printk(", %lu RC",
                   tmp_count);
    process_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_AUTH)
    tmp_count = rsbac_list_count(process_handles.auth);
    printk(", %lu AUTH",
                   tmp_count);
    process_sum += tmp_count;
#endif
    printk("\n");
    printk(KERN_INFO "Sum of %lu PROCESS items\n",
                   process_sum);
    total_sum += process_sum;

#if defined(CONFIG_RSBAC_NET_OBJ)
    /* nettemp lists */
    printk(KERN_INFO "NETTEMP items:\n");
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(nettemp_handles.mac);
    printk(", %lu MAC",
                   tmp_count);
    nettemp_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(nettemp_handles.fc);
    printk(", %lu FC",
                   tmp_count);
    nettemp_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(nettemp_handles.sim);
    printk(", %lu SIM",
                   tmp_count);
    nettemp_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(nettemp_handles.pm);
    printk(", %lu PM",
                   tmp_count);
    nettemp_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(nettemp_handles.rc);
    printk(", %lu RC",
                   tmp_count);
    nettemp_sum += tmp_count;
#endif
    printk("\n");
    printk(KERN_INFO "Sum of %lu NETTEMP items\n",
                   nettemp_sum);
    total_sum += nettemp_sum;

    /* local netobj lists */
    printk(KERN_INFO "Local NETOBJ items:\n");
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(lnetobj_handles.mac);
    printk(", %lu MAC",
                   tmp_count);
    lnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(lnetobj_handles.fc);
    printk(", %lu FC",
                   tmp_count);
    lnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(lnetobj_handles.sim);
    printk(", %lu SIM",
                   tmp_count);
    lnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(lnetobj_handles.pm);
    printk(", %lu PM",
                   tmp_count);
    lnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_MS)
    tmp_count = rsbac_list_count(lnetobj_handles.ms);
    printk(", %lu MS",
                   tmp_count);
    lnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(lnetobj_handles.rc);
    printk(", %lu RC",
                   tmp_count);
    lnetobj_sum += tmp_count;
#endif
    printk("\n");
    printk(KERN_INFO "Sum of %lu Local NETOBJ items\n",
                   lnetobj_sum);
    total_sum += lnetobj_sum;

    /* remote netobj lists */
    printk(KERN_INFO "Remote NETOBJ items:\n");
#if defined(CONFIG_RSBAC_MAC)
    tmp_count = rsbac_list_count(rnetobj_handles.mac);
    printk(", %lu MAC",
                   tmp_count);
    rnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_FC)
    tmp_count = rsbac_list_count(rnetobj_handles.fc);
    printk(", %lu FC",
                   tmp_count);
    rnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_SIM)
    tmp_count = rsbac_list_count(rnetobj_handles.sim);
    printk(", %lu SIM",
                   tmp_count);
    rnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_PM)
    tmp_count = rsbac_list_count(rnetobj_handles.pm);
    printk(", %lu PM",
                   tmp_count);
    rnetobj_sum += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
    tmp_count = rsbac_list_count(rnetobj_handles.rc);
    printk(", %lu RC",
                   tmp_count);
    rnetobj_sum += tmp_count;
#endif
    printk("\n");
    printk(KERN_INFO "Sum of %lu Remote NETOBJ items\n",
                   rnetobj_sum);
    total_sum += rnetobj_sum;
#endif /* NET_OBJ */

    printk(KERN_INFO
           "Total of %lu registered rsbac-items\n",
           total_sum);
    
    printk(KERN_INFO
           "adf_request calls: file: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
           rsbac_adf_request_count[T_FILE],
           rsbac_adf_request_count[T_DIR],
           rsbac_adf_request_count[T_FIFO],
           rsbac_adf_request_count[T_SYMLINK],
           rsbac_adf_request_count[T_DEV],
           rsbac_adf_request_count[T_IPC],
           rsbac_adf_request_count[T_SCD],
           rsbac_adf_request_count[T_USER],
           rsbac_adf_request_count[T_PROCESS],
           rsbac_adf_request_count[T_NETDEV],
           rsbac_adf_request_count[T_NETTEMP],
           rsbac_adf_request_count[T_NETOBJ]);
    printk(KERN_INFO
           "adf_set_attr calls: file: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
           rsbac_adf_set_attr_count[T_FILE],
           rsbac_adf_set_attr_count[T_DIR],
           rsbac_adf_set_attr_count[T_FIFO],
           rsbac_adf_set_attr_count[T_SYMLINK],
           rsbac_adf_set_attr_count[T_DEV],
           rsbac_adf_set_attr_count[T_IPC],
           rsbac_adf_set_attr_count[T_SCD],
           rsbac_adf_set_attr_count[T_USER],
           rsbac_adf_set_attr_count[T_PROCESS],
           rsbac_adf_set_attr_count[T_NETDEV],
           rsbac_adf_set_attr_count[T_NETTEMP],
           rsbac_adf_set_attr_count[T_NETOBJ]);

    #if defined(CONFIG_RSBAC_PM)
    rsbac_stats_pm();
    #endif
    #if defined(CONFIG_RSBAC_RC)
    rsbac_stats_rc();
    #endif
    #if defined(CONFIG_RSBAC_AUTH)
    rsbac_stats_auth();
    #endif
    #if defined(CONFIG_RSBAC_ACL)
    rsbac_stats_acl();
    #endif
    return(0);
  };

/* check for inode on disk (but not for reiserfs, because of broken 64bit inode numbers,
 * or for non-devices) */
int rsbac_check_inode(struct super_block * sb_p, rsbac_inode_nr_t inode)
  {
    struct inode * inode_p;
    int err = 0;

    if(!sb_p)
      return -RSBAC_EINVALIDPOINTER;
    if(!inode)
      return -RSBAC_EINVALIDVALUE;
    if(!MAJOR(sb_p->s_dev))
      return 0;

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
    if(sb_p->s_op && sb_p->s_op->read_inode2)
      return 0;
    #endif
    inode_p = iget(sb_p, inode);
    if(is_bad_inode(inode_p))
      {
        return -RSBAC_ENOTFOUND;
      }
    /* currently only deletion checking of ext2 inodes is possible */
    if(sb_p->s_magic == EXT2_SUPER_MAGIC)
      {
        if(inode_p->u.ext2_i.i_dtime)
          { /* inode has been deleted */
            err = -RSBAC_ENOTFOUND;
          }
        else
          {
            if(inode_p->i_nlink <= 0)
              { /* inode has been unlinked, but no dtime is set -> warn */
                printk(KERN_WARNING
                       "rsbac_check_inode(): inode %u with nlink <= 0 on device %02u:%02u detected!\n",
                       inode, MAJOR(sb_p->s_dev), MINOR(sb_p->s_dev));
                err = -RSBAC_ENOTFOUND;
              }
          }
      }
    iput(inode_p);
    return err;
  }


/***************************************************/
/* consistency checking (as far as possible)       */

int rsbac_check(int correct, int check_inode)
  {
    struct rsbac_device_list_item_t   * device_p;
    int                                 i;
    char                              * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
    int                                 list_no;
    long                                desc_count;
    u_long                              fd_count = 0, fd_sum = 0, tmp_count,
                                        b_count, def_count;
    u_long                              dflags;
    rsbac_inode_nr_t                  * fd_desc_p;

    if (!rsbac_initialized)
      {
        printk(KERN_WARNING "rsbac_check(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (!tmp)
      {
        return(-RSBAC_ENOMEM);
      }
    {
      /* wait for read access to device_list_head */
      rsbac_read_lock(&device_list_head.lock, &dflags);
      /* OK, go on */
      device_p = device_list_head.head;
      while (device_p)
        {
          fd_count = 0;
          b_count = 0;
          def_count = 0;
          if(check_inode)
            {
              if(!device_p->sb_p)
                {
                  printk(KERN_WARNING "rsbac_check(): no super block for device %02u:%02u!\n",
                         MAJOR(device_p->id), MINOR(device_p->id));
                }
              else
                {
                  /* is last write finished? (only, if writable) */
                  if(writable(device_p->sb_p))
                    {
                      /* sync to be sure */
                      printk(KERN_INFO "rsbac_check(): syncing device %02u:%02u\n",
                             MAJOR(device_p->id), MINOR(device_p->id));
                      fsync_dev(device_p->id);
                    }
                }
            }
  
          /* General lists */
          for(list_no = 0; list_no < RSBAC_GEN_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.gen[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.gen[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
  
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  
  #if defined(CONFIG_RSBAC_MAC)
          /* MAC lists */
          for(list_no = 0; list_no < RSBAC_MAC_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): MAC list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.mac[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.mac[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* MAC */

  #if defined(CONFIG_RSBAC_FC)
          /* FC lists */
          for(list_no = 0; list_no < RSBAC_FC_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): FC list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.fc[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.fc[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* FC */

  #if defined(CONFIG_RSBAC_SIM)
          /* SIM lists */
          for(list_no = 0; list_no < RSBAC_SIM_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): SIM list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.sim[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.sim[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* SIM */

  #if defined(CONFIG_RSBAC_PM)
          /* PM lists */
          for(list_no = 0; list_no < RSBAC_PM_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): PM list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.pm[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.pm[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* PM */

  #if defined(CONFIG_RSBAC_MS)
          /* MS lists */
          for(list_no = 0; list_no < RSBAC_MS_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): MS list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.ms[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.ms[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
          /* MS scanned lists */
          for(list_no = 0; list_no < RSBAC_MS_SCANNED_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): MS_SCANNED list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.mss[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.ms[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* MS */

  #if defined(CONFIG_RSBAC_FF)
          /* FF lists */
          for(list_no = 0; list_no < RSBAC_FF_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): FF list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.ff[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.ff[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* FF */

  #if defined(CONFIG_RSBAC_RC)
          /* RC lists */
          for(list_no = 0; list_no < RSBAC_RC_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): RC list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.rc[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.rc[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* RC */

  #if defined(CONFIG_RSBAC_AUTH)
          /* AUTH lists */
          for(list_no = 0; list_no < RSBAC_AUTH_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): AUTH list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.auth[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.auth[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* AUTH */

  #if defined(CONFIG_RSBAC_CAP)
          /* CAP lists */
          for(list_no = 0; list_no < RSBAC_CAP_NR_FD_LISTS; list_no++)
            {
  /*            printk(KERN_INFO "rsbac_check(): CAP list %u\n",
                     list_no); */
              tmp_count = 0;
              desc_count = rsbac_list_get_all_desc(device_p->handles.cap[list_no], (void **) &fd_desc_p);
              if(desc_count > 0)
                {
                  for(i=0; i<desc_count; i++)
                    {
                      /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
                      if(check_inode && device_p->sb_p)
                        {
                          if(rsbac_check_inode(device_p->sb_p, fd_desc_p[i]))
                            { /* inode is bad -> remove */
                              b_count++;
                              if(correct)
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
                                          fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                  rsbac_list_remove(device_p->handles.cap[list_no], &fd_desc_p[i]);
                                  continue;
                                }
                              else
                                {
                                  printk(KERN_INFO
                                         "rsbac_check(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
                                         fd_desc_p[i], MAJOR(device_p->id), MINOR(device_p->id), list_no);
                                }
                            } /* end of bad_inode */
                        }
                    }
                  tmp_count++;
                  vfree(fd_desc_p);
                  fd_count += desc_count;
                }
            } /* end of for-fd-list-array */
  #endif /* CAP */

          switch(correct)
            {
              case 2:  printk(KERN_INFO
                              "rsbac_check(): Device %02u:%02u has %lu file/dir items (%lu removed due to bad inodes)\n",
                              MAJOR(device_p->id), MINOR(device_p->id), fd_count,
                              b_count);
                              break;
              case 1:  printk(KERN_INFO
                              "rsbac_check(): Device %02u:%02u has %lu file/dir items (%lu removed due to bad inodes)\n",
                              MAJOR(device_p->id), MINOR(device_p->id), fd_count,
                              b_count);
                              break;
              default: printk(KERN_INFO
                              "rsbac_check(): Device %02u:%02u has %lu file/dir items (%lu with bad inodes)\n",
                              MAJOR(device_p->id), MINOR(device_p->id), fd_count,
                              b_count);
            }
          fd_sum += fd_count;
          /* go on */
          device_p = device_p->next;
        };
      printk(KERN_INFO "rsbac_check(): Sum of %u Devices with %lu fd-items\n",
                   device_list_head.count, fd_sum);
      /* free access to device_list_head */
      rsbac_read_unlock(&device_list_head.lock, &dflags);
    }
    rsbac_kfree(tmp);
    return(0);
  };


/***************************************************/
/* rsbac_write() to write all dirty lists to disk  */
/*               returns no. of lists written      */

#if defined(CONFIG_RSBAC_AUTO_WRITE)
int rsbac_write(boolean need_lock)
  {
    int                                 err=0;
    u_int                               count = 0;
    int                                 subcount;
  
    if (!rsbac_initialized)
      {
        printk(KERN_WARNING "rsbac_write(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_no_write)
      return 0;
#endif
    
    subcount = rsbac_write_debug(need_lock);
    if(subcount > 0)
      {
        count += subcount;
      }
    else
    if(subcount < 0)
      {
        err = subcount;
        if(err != -RSBAC_ENOTWRITABLE)
          printk(KERN_WARNING
                 "rsbac_write(): rsbac_write_debug() returned error %i\n",
                 err);
      }

    subcount = rsbac_write_lists(need_lock);
    if(subcount > 0)
      {
        count += subcount;
      }
    else
    if(subcount < 0)
      {
        err = subcount;
        if(err != -RSBAC_ENOTWRITABLE)
          printk(KERN_WARNING
                 "rsbac_write(): rsbac_write_lists() returned error %i\n",
                 err);
      }

#if defined(CONFIG_RSBAC_AUTH)
    subcount = rsbac_write_auth(need_lock);
    if(subcount > 0)
      {
        count += subcount;
      }
    else
    if(subcount < 0)
      {
        err = subcount;
        if(err != -RSBAC_ENOTWRITABLE)
          printk(KERN_WARNING
                 "rsbac_write(): rsbac_write_auth() returned error %i\n",
                 err);
      }
#endif

/****** REG *******/
#if defined(CONFIG_RSBAC_REG)
    subcount = rsbac_write_reg(need_lock);
    if(subcount > 0)
      {
        count += subcount;
      }
    else
    if(subcount < 0)
      {
        err = subcount;
        if(err != -RSBAC_ENOTWRITABLE)
          printk(KERN_WARNING
                 "rsbac_write(): rsbac_write_reg() returned error %i\n",
                 err);
      }
#endif  /* REG */

#ifdef CONFIG_RSBAC_DEBUG
    if(rsbac_debug_write)
      printk(KERN_DEBUG "rsbac_write(): total of %u lists written\n",
             count);
#endif
    return(count);
  };
#endif /* CONFIG_RSBAC_AUTO_WRITE */

/************************************************* */
/*               Attribute functions               */
/************************************************* */

/* A rsbac_set_attr() call for a non-existing object, user                  */
/* or process entry will first add the target and then set the attribute.   */
/* Invalid combinations and trying to set security_level to or from         */
/* SL_rsbac_internal return an error.                                       */
/* A rsbac_get_attr() call for a non-existing target will return the        */
/* default value stored in def_aci, which should be the first enum item.*/

/* All these procedures handle the rw-spinlocks to protect the targets during */
/* access.                                                                  */

/* get the parent of a target
 * returns -RSBAC_EINVALIDTARGET for non-fs targets
 * and -RSBAC_ENOTFOUND, if no parent available
 * In kernels >= 2.4.0, device_p->d_covers is used and the item is properly
 * locked for reading, so never call with a write lock held on device_p!
 */
#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_get_parent);
#endif
int rsbac_get_parent(enum rsbac_target_t target,
                     union rsbac_target_id_t tid,
                     enum rsbac_target_t * parent_target_p,
                     union rsbac_target_id_t * parent_tid_p)
  {
    if(!parent_target_p || !parent_tid_p)
      return -RSBAC_EINVALIDPOINTER;
/*
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_ds)
      printk(KERN_DEBUG
             "rsbac_get_parent(): Getting file/dir/fifo/symlink parent for device %02u:%02u, inode %lu, dentry_p %p\n",
             MAJOR(tid.file.device),MINOR(tid.file.device), (u_long) tid.file.inode, tid.file.dentry_p);
#endif
*/
    switch(target)
      {
        case T_FILE:
        case T_DIR:
        case T_FIFO:
        case T_SYMLINK:
          break;
        default:
          return -RSBAC_EINVALIDTARGET;
      }

    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    if(   (tid.file.dentry_p)
       /* stop recursing on rsbac_root_dev's root dentry */
       && (   (tid.file.device != rsbac_root_dev)
           || (tid.file.dentry_p->d_sb->s_root != tid.file.dentry_p))
       && (tid.file.dentry_p->d_covers)
       && (tid.file.dentry_p->d_covers->d_parent)
       /* inode there? (d_covers is used do step over mount points) */
       && (tid.file.dentry_p->d_covers->d_parent->d_inode)
      )
      { /* OK, parent is there */
        *parent_target_p = T_DIR;
        parent_tid_p->dir.device
          = tid.file.dentry_p->d_covers->d_parent->d_inode->i_dev;
        parent_tid_p->dir.inode
          = tid.file.dentry_p->d_covers->d_parent->d_inode->i_ino;
        parent_tid_p->dir.dentry_p = tid.file.dentry_p->d_covers->d_parent;
        return 0;
      }
    else
      {
        return -RSBAC_ENOTFOUND;
      }

    #else /* VERSION >= 2.4.0 */

    if(!tid.file.dentry_p)
      return -RSBAC_ENOTFOUND;

    *parent_target_p = T_DIR;
    /* Is this dentry root of a mounted device? */
    if(tid.file.dentry_p->d_sb->s_root == tid.file.dentry_p)
      {
        struct rsbac_device_list_item_t * device_p;
        u_long dflags;

        /* wait for read access to device_list_head */
        rsbac_read_lock(&device_list_head.lock, &dflags);

        device_p = lookup_device(tid.file.device);
        if(   !device_p
           || !device_p->d_covers
           || !device_p->d_covers->d_parent
           || !device_p->d_covers->d_parent->d_inode
          )
          {
            /* free access to device_list_head */
            rsbac_read_unlock(&device_list_head.lock, &dflags);
            return -RSBAC_ENOTFOUND;
          }
        parent_tid_p->dir.device = device_p->d_covers->d_parent->d_inode->i_dev;
        parent_tid_p->dir.inode = device_p->d_covers->d_parent->d_inode->i_ino;
        parent_tid_p->dir.dentry_p = device_p->d_covers->d_parent;
        /* free access to device_list_head */
        rsbac_read_unlock(&device_list_head.lock, &dflags);
      }
    else
      { /* no root of filesystem -> simply use d_parent, dev keeps unchanged */
        if(tid.file.dentry_p == tid.file.dentry_p->d_parent)
          {
            printk(KERN_WARNING
                   "rsbac_get_parent(): oops - d_parent == dentry_p!\n");
            return -RSBAC_ENOTFOUND;
          }
        parent_tid_p->dir.device = tid.file.device;
        parent_tid_p->dir.inode = tid.file.dentry_p->d_parent->d_inode->i_ino;
        parent_tid_p->dir.dentry_p = tid.file.dentry_p->d_parent;
      }
    return 0;
    #endif /* #else of Version < 2.4.0 */
  }

/* The value parameter to rsbac_get_attr() and rsbac_set_attr() is a pointer */
/* to the appropiate data structure holding the attribute value.            */                         

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_get_attr);
#endif
int rsbac_get_attr(enum rsbac_switch_target_t module,
                   enum rsbac_target_t target,
                   union rsbac_target_id_t tid,
                   enum rsbac_attribute_t attr,
                   union rsbac_attribute_value_t * value,
                   boolean inherit)
  { 
    int err = 0;
    struct rsbac_device_list_item_t   * device_p;
    u_long                              dflags;
#if defined(CONFIG_RSBAC_FF)
    rsbac_ff_flags_t                    ff_flags = 0;
    rsbac_ff_flags_t                    ff_tmp_flags;
    rsbac_ff_flags_t                    ff_mask = -1;
#endif

    if (!rsbac_initialized)
      {
        printk(KERN_WARNING "rsbac_get_attr(): RSBAC not initialized\n");
         return(-RSBAC_ENOTINITIALIZED);
      }
    if (!value)
      return(-RSBAC_EINVALIDPOINTER);
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_get_attr(): called from interrupt!\n");
      }
    #ifdef CONFIG_RSBAC_XSTATS
    get_attr_count[target]++;
    #endif
    switch (target)
      {
        case T_FILE:
        case T_DIR:
        case T_FIFO:
        case T_SYMLINK:
          /* use loop for inheritance - used to be recursive calls */
          for(;;)
          {
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
                printk(KERN_DEBUG "rsbac_get_attr(): Getting file/dir/fifo/symlink attribute %u for device %02u:%02u, inode %lu, dentry_p %p\n",
                       attr, MAJOR(tid.file.device),MINOR(tid.file.device), (u_long) tid.file.inode, tid.file.dentry_p);
#endif
*/
            /* wait for read access to device_list_head */
            rsbac_read_lock(&device_list_head.lock, &dflags);
            /* OK, go on */
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
                printk(KERN_DEBUG
                       "rsbac_get_attr(): passed device read lock\n");
#endif
*/

            /* lookup device */
            device_p = lookup_device(tid.file.device);
            if (!device_p)
              {
                printk(KERN_WARNING
                       "rsbac_get_attr(): Could not lookup device %02u:%02u!\n",
                       MAJOR(tid.file.device), MINOR(tid.file.device));
                /* free read lock */
                rsbac_read_unlock(&device_list_head.lock, &dflags);
                return(-RSBAC_EINVALIDDEV);
              }
            switch(module)
              {
                case GEN:
                  {
                    struct rsbac_gen_fd_aci_t aci = DEFAULT_GEN_FD_ACI;

                    if(attr == A_internal)
                      {
                        if(device_p->rsbac_dir_inode == tid.file.inode)
                          value->internal = TRUE;
                        else
                          if(inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                { /* yes: inherit this single level */
                                  if(device_p->rsbac_dir_inode == parent_tid.file.inode)
                                    value->internal = TRUE;
                                  else
                                    value->internal = FALSE;
                                }
                              else
                                {
                                  value->internal = FALSE;
                                }
                            }
                          else
                            {
                              value->internal = FALSE;
                            }

                        /* free access to device_list_head */
                        rsbac_read_unlock(&device_list_head.lock, &dflags);
                        return 0;
                      }
                    rsbac_list_get_data(device_p->handles.gen[gen_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_log_array_low:
                          value->log_array_low = aci.log_array_low;
                          break;
                        case A_log_array_high:
                          value->log_array_high = aci.log_array_high;
                          break;
                        case A_log_program_based:
                          value->log_program_based = aci.log_program_based;
                          break;
                        case A_symlink_add_uid:
                          value->symlink_add_uid = aci.symlink_add_uid;
                          break;
                        case A_symlink_add_rc_role:
                          value->symlink_add_rc_role = aci.symlink_add_rc_role;
                          break;
                        case A_linux_dac_disable:
                          value->linux_dac_disable = aci.linux_dac_disable;
                          if((value->linux_dac_disable == LDD_inherit) && inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* free access to device_list_head - see above */
                              rsbac_read_unlock(&device_list_head.lock, &dflags);

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                {
                                  value->linux_dac_disable
                                    = def_gen_root_dir_aci.linux_dac_disable;
                                  return 0;
                                }
                            }
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;

#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_fd_aci_t aci = DEFAULT_MAC_FD_ACI;

                    rsbac_list_get_data(device_p->handles.mac[mac_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          value->security_level = aci.sec_level;
                          if((value->security_level == SL_inherit) && inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* free access to device_list_head - see above */
                              rsbac_read_unlock(&device_list_head.lock, &dflags);

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                {
                                  value->security_level
                                    = def_mac_root_dir_aci.sec_level;
                                  return 0;
                                }
                            }
                          break;
                        case A_mac_categories:
                          value->mac_categories = aci.mac_categories;
                          if(   (value->mac_categories == RSBAC_MAC_INHERIT_CAT_VECTOR)
                             && inherit
                            )
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* free access to device_list_head - see above */
                              rsbac_read_unlock(&device_list_head.lock, &dflags);

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                {
                                  value->mac_categories
                                    = def_mac_root_dir_aci.mac_categories;
                                  return 0;
                                }
                            }
                          break;
                        case A_mac_trusted_for_user:
                          value->mac_trusted_for_user = aci.mac_trusted_for_user;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    switch (attr)
                      {
                        case A_object_category:
                          value->object_category = RSBAC_FC_OC_DEF;
                          rsbac_list_get_data(device_p->handles.fc[fc_fd_hash(tid.file.inode)],
                                              &tid.file.inode,
                                              &value->object_category);
                          if((value->object_category == OC_inherit) && inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* free access to device_list_head - see above */
                              rsbac_read_unlock(&device_list_head.lock, &dflags);

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                {
                                  value->object_category
                                    = RSBAC_FC_OC_ROOT_DEF;
                                  return 0;
                                }
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    switch (attr)
                      {
                        case A_data_type:
                          value->data_type = RSBAC_SIM_DT_DEF;
                          rsbac_list_get_data(device_p->handles.sim[sim_fd_hash(tid.file.inode)],
                                              &tid.file.inode,
                                              &value->data_type);
                          if(value->data_type == DT_inherit && inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* free access to device_list_head - see above */
                              rsbac_read_unlock(&device_list_head.lock, &dflags);

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                {
                                  value->data_type
                                    = RSBAC_SIM_DT_ROOT_DEF;
                                  return 0;
                                }
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_fd_aci_t aci = DEFAULT_PM_FD_ACI;

                    rsbac_list_get_data(device_p->handles.pm[pm_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_object_class:
                          value->pm_object_class = aci.pm_object_class;
                          break;
                        case A_pm_tp:
                          value->pm_tp = aci.pm_tp;
                          break;
                        case A_pm_object_type:
                          value->pm_object_type = aci.pm_object_type;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_MS)
                case MS:
                  {
                    if(attr == A_ms_scanned)
                      {
                        err = rsbac_list_get_data(device_p->handles.mss[ms_scanned_fd_hash(tid.file.inode)],
                                                  &tid.file.inode,
                                                  &value->ms_scanned);
                      }
                    else
                      {
                        struct rsbac_ms_fd_aci_t aci = DEFAULT_MS_FD_ACI;

                        rsbac_list_get_data(device_p->handles.ms[ms_fd_hash(tid.file.inode)],
                                            &tid.file.inode,
                                            &aci);
                        switch (attr)
                          {
                            case A_ms_trusted:
                              value->ms_trusted = aci.ms_trusted;
                              break;
                            case A_ms_sock_trusted_tcp:
                              value->ms_sock_trusted_tcp = aci.ms_sock_trusted_tcp;
                              break;
                            case A_ms_sock_trusted_udp:
                              value->ms_sock_trusted_udp = aci.ms_sock_trusted_udp;
                              break;
                            default:
                              err = -RSBAC_EINVALIDATTR;
                          }
                      }
                  }
                  break;
#endif /* MS */

#if defined(CONFIG_RSBAC_FF)
                case FF:
                  {
                    switch (attr)
                      {
                        case A_ff_flags:
                          ff_tmp_flags = RSBAC_FF_DEF;
                          rsbac_list_get_data(device_p->handles.ff[ff_fd_hash(tid.file.inode)],
                                              &tid.file.inode,
                                              &ff_tmp_flags);
                          ff_flags |= ff_tmp_flags & ff_mask;
                          value->ff_flags = ff_flags;
                          if((ff_tmp_flags & FF_add_inherited) && inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  /* free access to device_list_head - see above */
                                  rsbac_read_unlock(&device_list_head.lock, &dflags);

                                  ff_mask &= ~(FF_no_delete_or_rename | FF_add_inherited);
                                  ff_flags &= ~(FF_add_inherited);
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                value->ff_flags &= ~(FF_add_inherited);
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FF */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    struct rsbac_rc_fd_aci_t aci = DEFAULT_RC_FD_ACI;

                    rsbac_list_get_data(device_p->handles.rc[rc_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_rc_type_fd:
                          value->rc_type_fd = aci.rc_type_fd;
                          if(value->rc_type_fd == RC_type_inherit_parent && inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* free access to device_list_head - see above */
                              rsbac_read_unlock(&device_list_head.lock, &dflags);

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                {
                                  value->rc_type_fd
                                    = def_rc_root_dir_aci.rc_type_fd;
                                  return 0;
                                }
                            }
                          break;
                        case A_rc_force_role:
                          value->rc_force_role = aci.rc_force_role;
                          if(value->rc_force_role == RC_role_inherit_parent && inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* free access to device_list_head - see above */
                              rsbac_read_unlock(&device_list_head.lock, &dflags);

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                {
                                  value->rc_force_role
                                    = def_rc_root_dir_aci.rc_force_role;
                                  return 0;
                                }
                            }
                          break;
                        case A_rc_initial_role:
                          value->rc_initial_role = aci.rc_initial_role;
                          if(value->rc_initial_role == RC_role_inherit_parent && inherit)
                            {
                              enum rsbac_target_t       parent_target;
                              union rsbac_target_id_t   parent_tid;

                              /* free access to device_list_head - see above */
                              rsbac_read_unlock(&device_list_head.lock, &dflags);

                              /* inheritance possible? */
                              if(!rsbac_get_parent(target, tid, &parent_target, &parent_tid))
                                {
                                  target = parent_target;
                                  tid = parent_tid;
                                  continue;
                                }
                              else
                                {
                                  value->rc_initial_role
                                    = def_rc_root_dir_aci.rc_initial_role;
                                  return 0;
                                }
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* RC */

#if defined(CONFIG_RSBAC_AUTH)
                case AUTH:
                  {
                    struct rsbac_auth_fd_aci_t aci = DEFAULT_AUTH_FD_ACI;

                    rsbac_list_get_data(device_p->handles.auth[auth_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_auth_may_setuid:
                          value->auth_may_setuid = aci.auth_may_setuid;
                          break;
                        case A_auth_may_set_cap:
                          value->auth_may_set_cap = aci.auth_may_set_cap;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* AUTH */

#if defined(CONFIG_RSBAC_CAP)
                case CAP:
                  {
                    struct rsbac_cap_fd_aci_t aci = DEFAULT_CAP_FD_ACI;

                    rsbac_list_get_data(device_p->handles.cap[cap_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_min_caps:
                          value->min_caps = aci.min_caps;
                          break;
                        case A_max_caps:
                          value->max_caps = aci.max_caps;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* CAP */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* free access to device_list_head */
            rsbac_read_unlock(&device_list_head.lock, &dflags);
            /* and return */
            return err;
            } /* end of for(;;) loop for inheritance */

        case T_DEV:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
                printk(KERN_DEBUG
                       "rsbac_get_attr(): Getting dev attribute\n");
#endif
*/
            switch(module)
              {
                case GEN:
                  {
                    struct rsbac_gen_dev_aci_t aci = DEFAULT_GEN_DEV_ACI;

                    rsbac_list_get_data(dev_handles.gen,
                                        &tid.dev,
                                        &aci);
                    switch (attr)
                      {
                        case A_log_array_low:
                          value->log_array_low = aci.log_array_low;
                          break;
                        case A_log_array_high:
                          value->log_array_high = aci.log_array_high;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;

#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_dev_aci_t aci = DEFAULT_MAC_DEV_ACI;

                    rsbac_list_get_data(dev_handles.mac,
                                        &tid.dev,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          value->security_level = aci.sec_level;
                          break;
                        case A_mac_categories:
                          value->mac_categories = aci.mac_categories;
                          break;
                        case A_mac_check:
                          value->mac_check = aci.mac_check;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_fc_oc_t fc_oc = RSBAC_FC_OC_ROOT_DEF;

                    rsbac_list_get_data(dev_handles.fc,
                                        &tid.dev,
                                        &fc_oc);
                    switch (attr)
                      {
                        case A_object_category:
                          value->object_category = fc_oc;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_sim_dt_t sim_dt = RSBAC_SIM_DT_ROOT_DEF;

                    rsbac_list_get_data(dev_handles.sim,
                                        &tid.dev,
                                        &sim_dt);
                    switch (attr)
                      {
                        case A_data_type:
                          value->data_type = sim_dt;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_dev_aci_t aci = DEFAULT_PM_DEV_ACI;

                    rsbac_list_get_data(dev_handles.pm,
                                        &tid.dev,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_object_class:
                          value->pm_object_class = aci.pm_object_class;
                          break;
                        case A_pm_object_type:
                          value->pm_object_type = aci.pm_object_type;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;

                    rsbac_list_get_data(dev_handles.rc,
                                        &tid.dev,
                                        &type);
                    switch (attr)
                      {
                        case A_rc_type:
                          value->rc_type = type;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* RC */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            return err;

        case T_IPC:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG
                        "rsbac_get_attr(): Getting ipc attribute\n");
#endif
*/
            /* lookup only, if not sock or (sock-id != NULL), OK with NULL fifo */
            switch(module)
              {
#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_ipc_aci_t aci = DEFAULT_MAC_IPC_ACI;

                    rsbac_list_get_data(ipc_handles.mac,
                                        &tid.ipc,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          value->security_level = aci.sec_level;
                          break;
                        case A_mac_categories:
                          value->mac_categories = aci.mac_categories;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_fc_oc_t fc_oc = RSBAC_FC_OC_ROOT_DEF;

                    rsbac_list_get_data(ipc_handles.fc,
                                        &tid.ipc,
                                        &fc_oc);
                    switch (attr)
                      {
                        case A_object_category:
                          value->object_category = fc_oc;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_sim_dt_t sim_dt = RSBAC_SIM_DT_ROOT_DEF;

                    rsbac_list_get_data(ipc_handles.sim,
                                        &tid.ipc,
                                        &sim_dt);
                    switch (attr)
                      {
                        case A_data_type:
                          value->data_type = sim_dt;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_ipc_aci_t aci = DEFAULT_PM_IPC_ACI;

                    rsbac_list_get_data(ipc_handles.pm,
                                        &tid.ipc,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_object_class:
                          value->pm_object_class = aci.pm_object_class;
                          break;
                        case A_pm_ipc_purpose:
                          value->pm_ipc_purpose = aci.pm_ipc_purpose;
                          break;
                        case A_pm_object_type:
                          value->pm_object_type = aci.pm_object_type;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;

                    rsbac_list_get_data(ipc_handles.rc,
                                        &tid.ipc,
                                        &type);
                    switch (attr)
                      {
                        case A_rc_type:
                          value->rc_type = type;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* RC */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            return err;
             
        case T_USER:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG
                           "rsbac_get_attr(): Getting user attribute\n");
#endif
*/
            switch(module)
              {
                case GEN:
                  {
                    struct rsbac_gen_user_aci_t aci = DEFAULT_GEN_U_ACI;

                    rsbac_list_get_data(user_handles.gen,
                                        &tid.user,
                                        &aci);
                    switch (attr)
                      {
                        case A_pseudo:
                          value->pseudo = aci.pseudo;
                          break;
                        case A_log_user_based:
                          value->log_user_based = aci.log_user_based;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;

#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_user_aci_t aci = DEFAULT_MAC_U_ACI;

                    rsbac_list_get_data(user_handles.mac,
                                        &tid.user,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          value->security_level = aci.access_appr;
                          break;
                        case A_mac_categories:
                          value->mac_categories = aci.mac_categories;
                          break;
                        case A_system_role:
                        case A_mac_role:
                          value->system_role = aci.system_role;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_system_role_int_t role = SR_user;

                    rsbac_list_get_data(user_handles.fc,
                                        &tid.user,
                                        &role);
                    switch (attr)
                      {
                        case A_system_role:
                        case A_fc_role:
                          value->system_role = role;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_system_role_int_t role = SR_user;

                    rsbac_list_get_data(user_handles.sim,
                                        &tid.user,
                                        &role);
                    switch (attr)
                      {
                        case A_system_role:
                        case A_sim_role:
                          value->system_role = role;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_user_aci_t aci = DEFAULT_PM_U_ACI;

                    rsbac_list_get_data(user_handles.pm,
                                        &tid.user,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_task_set:
                          value->pm_task_set = aci.pm_task_set;
                          break;
                        case A_pm_role:
                          value->pm_role = aci.pm_role;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_MS)
                case MS:
                  {
                    rsbac_system_role_int_t role = SR_user;

                    rsbac_list_get_data(user_handles.ms,
                                        &tid.user,
                                        &role);
                    switch (attr)
                      {
                        case A_system_role:
                        case A_ms_role:
                          value->system_role = role;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MS */

#if defined(CONFIG_RSBAC_FF)
                case FF:
                  {
                    rsbac_system_role_int_t role = SR_user;

                    rsbac_list_get_data(user_handles.ff,
                                        &tid.user,
                                        &role);
                    switch (attr)
                      {
                        case A_system_role:
                        case A_ff_role:
                          value->system_role = role;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MS */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_role_id_t role = RSBAC_RC_GENERAL_ROLE;

                    rsbac_list_get_data(user_handles.rc,
                                        &tid.user,
                                        &role);
                    switch (attr)
                      {
                        case A_rc_def_role:
                          value->rc_def_role = role;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* RC */

#if defined(CONFIG_RSBAC_AUTH)
                case AUTH:
                  {
                    rsbac_system_role_int_t role = SR_user;

                    rsbac_list_get_data(user_handles.auth,
                                        &tid.user,
                                        &role);
                    switch (attr)
                      {
                        case A_system_role:
                        case A_auth_role:
                          value->system_role = role;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* AUTH */

#if defined(CONFIG_RSBAC_CAP)
                case CAP:
                  {
                    struct rsbac_cap_user_aci_t aci = DEFAULT_CAP_U_ACI;

                    rsbac_list_get_data(user_handles.cap,
                                        &tid.user,
                                        &aci);
                    switch (attr)
                      {
                        case A_system_role:
                        case A_cap_role:
                          value->system_role = aci.cap_role;
                          break;
                        case A_min_caps:
                          value->min_caps = aci.min_caps;
                          break;
                        case A_max_caps:
                          value->max_caps = aci.max_caps;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* CAP */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            return err;
            
        case T_PROCESS:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_get_attr(): Getting process attribute");
#endif
*/
            switch(module)
              {
                case GEN:
                  {
                    rsbac_request_vector_t rv = 0;

                    rsbac_list_get_data(process_handles.gen,
                                        &tid.process,
                                        &rv);
                    switch (attr)
                      {
                        case A_log_program_based:
                          value->log_program_based = rv;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;

#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_process_aci_t aci = DEFAULT_MAC_P_ACI;

                    rsbac_list_get_data(process_handles.mac,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          value->security_level = aci.owner_sec_level;
                          break;
                        case A_mac_categories:
                          value->mac_categories = aci.mac_owner_categories;
                          break;
                        case A_current_sec_level:
                          value->current_sec_level = aci.current_sec_level;
                          break;
                        case A_mac_curr_categories:
                          value->mac_categories = aci.mac_curr_categories;
                          break;
                        case A_min_write_open:
                          value->min_write_open = aci.min_write_open;
                          break;
                        case A_min_write_categories:
                          value->mac_categories = aci.min_write_categories;
                          break;
                        case A_max_read_open:
                          value->max_read_open = aci.max_read_open;
                          break;
                        case A_max_read_categories:
                          value->mac_categories = aci.max_read_categories;
                          break;
                        case A_mac_auto:
                          value->mac_auto = aci.mac_auto;
                          break;
                        case A_mac_trusted:
                          value->mac_trusted = aci.mac_trusted;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_process_aci_t aci = DEFAULT_PM_P_ACI;

                    rsbac_list_get_data(process_handles.pm,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_tp:
                          value->pm_tp = aci.pm_tp;
                          break;
                        case A_pm_current_task:
                          value->pm_current_task = aci.pm_current_task;
                          break;
                        case A_pm_process_type:
                          value->pm_process_type = aci.pm_process_type;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_MS)
                case MS:
                  {
                    struct rsbac_ms_process_aci_t aci = DEFAULT_MS_P_ACI;

                    rsbac_list_get_data(process_handles.ms,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_ms_trusted:
                          value->ms_trusted = aci.ms_trusted;
                          break;
                        case A_ms_sock_trusted_tcp:
                          value->ms_sock_trusted_tcp = aci.ms_sock_trusted_tcp;
                          break;
                        case A_ms_sock_trusted_udp:
                          value->ms_sock_trusted_udp = aci.ms_sock_trusted_udp;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MS */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    struct rsbac_rc_process_aci_t aci = DEFAULT_RC_P_ACI;

                    rsbac_list_get_data(process_handles.rc,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_rc_role:
                          value->rc_role = aci.rc_role;
                          break;
                        case A_rc_type:
                          value->rc_type = aci.rc_type;
                          break;
                        case A_rc_force_role:
                          value->rc_force_role = aci.rc_force_role;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* RC */

#if defined(CONFIG_RSBAC_AUTH)
                case AUTH:
                  {
                    struct rsbac_auth_process_aci_t aci = DEFAULT_AUTH_P_ACI;

                    rsbac_list_get_data(process_handles.auth,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_auth_may_setuid:
                          value->auth_may_setuid = aci.auth_may_setuid;
                          break;
                        case A_auth_may_set_cap:
                          value->auth_may_set_cap = aci.auth_may_set_cap;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* AUTH */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            return err;

#ifdef CONFIG_RSBAC_NET_DEV
        case T_NETDEV:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
                printk(KERN_DEBUG
                       "rsbac_get_attr(): Getting netdev attribute\n");
#endif
*/
            switch(module)
              {
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
                case GEN:
                  {
                    struct rsbac_gen_netdev_aci_t aci = DEFAULT_GEN_NETDEV_ACI;

                    rsbac_list_get_data(netdev_handles.gen,
                                        &tid.netdev,
                                        &aci);
                    switch (attr)
                      {
                        case A_log_array_low:
                          value->log_array_low = aci.log_array_low;
                          break;
                        case A_log_array_high:
                          value->log_array_high = aci.log_array_high;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif
#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;

                    rsbac_list_get_data(netdev_handles.rc,
                                        &tid.netdev,
                                        &type);
                    switch (attr)
                      {
                        case A_rc_type:
                          value->rc_type = type;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* RC */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            return err;
#endif

#ifdef CONFIG_RSBAC_NET_OBJ
        case T_NETTEMP:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_get_attr(): Getting nettemp attribute");
#endif
*/
            if(   tid.nettemp
               && !rsbac_list_exist(net_temp_handle, &tid.nettemp)
              )
              return -RSBAC_EINVALIDTARGET;
            switch(module)
              {
#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
                case GEN:
                  {
                    struct rsbac_gen_fd_aci_t aci = DEFAULT_GEN_NETOBJ_ACI;

                    if(tid.nettemp)
                      rsbac_list_get_data(nettemp_handles.gen,
                                          &tid.nettemp,
                                          &aci);
                    switch (attr)
                      {
                        case A_log_array_low:
                          value->log_array_low = aci.log_array_low;
                          break;
                        case A_log_array_high:
                          value->log_array_high = aci.log_array_high;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif
#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_netobj_aci_t aci = DEFAULT_MAC_NETOBJ_ACI;

                    rsbac_list_get_data(nettemp_handles.mac,
                                        &tid.nettemp,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          value->security_level = aci.sec_level;
                          break;
                        case A_mac_categories:
                          value->mac_categories = aci.mac_categories;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_fc_oc_t fc_oc = RSBAC_FC_OC_ROOT_DEF;

                    rsbac_list_get_data(nettemp_handles.fc,
                                        &tid.nettemp,
                                        &fc_oc);
                    switch (attr)
                      {
                        case A_object_category:
                          value->object_category = fc_oc;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_sim_dt_t sim_dt = RSBAC_SIM_DT_ROOT_DEF;

                    rsbac_list_get_data(nettemp_handles.sim,
                                        &tid.nettemp,
                                        &sim_dt);
                    switch (attr)
                      {
                        case A_data_type:
                          value->data_type = sim_dt;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_netobj_aci_t aci = DEFAULT_PM_NETOBJ_ACI;

                    rsbac_list_get_data(nettemp_handles.pm,
                                        &tid.nettemp,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_object_class:
                          value->pm_object_class = aci.pm_object_class;
                          break;
                        case A_pm_ipc_purpose:
                          value->pm_ipc_purpose = aci.pm_ipc_purpose;
                          break;
                        case A_pm_object_type:
                          value->pm_object_type = aci.pm_object_type;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    struct rsbac_rc_nettemp_aci_t aci = DEFAULT_RC_NETTEMP_ACI;

                    rsbac_list_get_data(nettemp_handles.rc,
                                        &tid.nettemp,
                                        &aci);
                    switch (attr)
                      {
                        case A_rc_type:
                          value->rc_type = aci.netobj_type;
                          break;

                        case A_rc_type_nt:
                          value->rc_type = aci.nettemp_type;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* RC */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            return err;

        case T_NETOBJ:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_get_attr(): Getting netobj attribute");
#endif
*/
            switch(module)
              {
#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
                case GEN:
                  {
                    struct rsbac_gen_netobj_aci_t aci = DEFAULT_GEN_NETOBJ_ACI;
                    rsbac_net_temp_id_t temp = 0;

                    switch (attr)
                      {
                        case A_local_log_array_low:
                        case A_local_log_array_high:
                          rsbac_net_lookup_templates(tid.netobj,
                                                     &temp,
                                                     NULL);
                          break;
                        case A_remote_log_array_low:
                        case A_remote_log_array_high:
                          rsbac_net_lookup_templates(tid.netobj,
                                                     NULL,
                                                     &temp);
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(temp)
                      rsbac_list_get_data(nettemp_handles.gen,
                                          &temp,
                                          &aci);
                    switch (attr)
                      {
                        case A_local_log_array_low:
                        case A_remote_log_array_low:
                          value->log_array_low = aci.log_array_low;
                          break;
                        case A_local_log_array_high:
                        case A_remote_log_array_high:
                          value->log_array_high = aci.log_array_high;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif
#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_netobj_aci_t aci = DEFAULT_MAC_NETOBJ_ACI;

                    switch(attr)
                      {
                        case A_local_sec_level:
                        case A_local_mac_categories:
                          if(rsbac_list_get_data(lnetobj_handles.mac,
                                                 &tid.netobj.sock_p,
                                                 &aci))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      &temp,
                                                      NULL);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.mac,
                                                    &temp,
                                                    &aci);
                            }
                          break;

                        case A_remote_sec_level:
                        case A_remote_mac_categories:
                          if(rsbac_list_get_data(rnetobj_handles.mac,
                                                 &tid.netobj.sock_p,
                                                 &aci))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      NULL,
                                                      &temp);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.mac,
                                                    &temp,
                                                    &aci);
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(err)
                      break;
                    switch (attr)
                      {
                        case A_local_sec_level:
                        case A_remote_sec_level:
                          value->security_level = aci.sec_level;
                          break;
                        case A_local_mac_categories:
                        case A_remote_mac_categories:
                          value->mac_categories = aci.mac_categories;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_fc_oc_t fc_oc = RSBAC_FC_OC_ROOT_DEF;

                    switch(attr)
                      {
                        case A_local_object_category:
                          if(rsbac_list_get_data(lnetobj_handles.fc,
                                                 &tid.netobj.sock_p,
                                                 &fc_oc))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      &temp,
                                                      NULL);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.fc,
                                                    &temp,
                                                    &fc_oc);
                            }
                          break;

                        case A_remote_object_category:
                          if(rsbac_list_get_data(rnetobj_handles.fc,
                                                 &tid.netobj.sock_p,
                                                 &fc_oc))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      NULL,
                                                      &temp);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.fc,
                                                    &temp,
                                                    &fc_oc);
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      value->object_category = fc_oc;
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_sim_dt_t sim_dt = RSBAC_SIM_DT_ROOT_DEF;

                    switch(attr)
                      {
                        case A_local_data_type:
                          if(rsbac_list_get_data(lnetobj_handles.sim,
                                                 &tid.netobj.sock_p,
                                                 &sim_dt))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      &temp,
                                                      NULL);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.sim,
                                                    &temp,
                                                    &sim_dt);
                            }
                          break;

                        case A_remote_data_type:
                          if(rsbac_list_get_data(rnetobj_handles.sim,
                                                 &tid.netobj.sock_p,
                                                 &sim_dt))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      NULL,
                                                      &temp);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.sim,
                                                    &temp,
                                                    &sim_dt);
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      value->data_type = sim_dt;
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_netobj_aci_t aci = DEFAULT_PM_NETOBJ_ACI;

                    switch(attr)
                      {
                        case A_local_pm_object_class:
                        case A_local_pm_ipc_purpose:
                        case A_local_pm_object_type:
                          if(rsbac_list_get_data(lnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      &temp,
                                                      NULL);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.pm,
                                                    &temp,
                                                    &aci);
                            }
                          break;

                        case A_remote_pm_object_class:
                        case A_remote_pm_ipc_purpose:
                        case A_remote_pm_object_type:
                          if(rsbac_list_get_data(rnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      NULL,
                                                      &temp);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.pm,
                                                    &temp,
                                                    &aci);
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(err)
                      break;
                    switch (attr)
                      {
                        case A_local_pm_object_class:
                        case A_remote_pm_object_class:
                          value->pm_object_class = aci.pm_object_class;
                          break;
                        case A_local_pm_ipc_purpose:
                        case A_remote_pm_ipc_purpose:
                          value->pm_ipc_purpose = aci.pm_ipc_purpose;
                          break;
                        case A_local_pm_object_type:
                        case A_remote_pm_object_type:
                          value->pm_object_type = aci.pm_object_type;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_MS)
                case MS:
                  {
                    struct rsbac_ms_netobj_aci_t aci = DEFAULT_MS_NETOBJ_ACI;
                    int i;

                    rsbac_list_get_data(lnetobj_handles.ms,
                                        &tid.netobj.sock_p,
                                        &aci);
                    switch (attr)
                      {
                        case A_ms_backbuf:
                          value->ms_backbuf = aci.ms_backbuf;
                          break;
                        case A_ms_buflen:
                          value->ms_buflen = aci.ms_buflen;
                          break;
                        case A_ms_str_nr:
                          for(i=0; i<RSBAC_MS_NR_MALWARE; i++)
                            value->ms_str_nr[i] = aci.ms_str_nr[i];
                          break;
                        case A_ms_str_offset:
                          for(i=0; i<RSBAC_MS_NR_MALWARE; i++)
                            value->ms_str_offset[i] = aci.ms_str_offset[i];
                          break;
                        case A_ms_scanned:
                          value->ms_scanned = aci.ms_scanned;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* MS */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;

                    switch(attr)
                      {
                        case A_local_rc_type:
                          if(rsbac_list_get_data(lnetobj_handles.rc,
                                                 &tid.netobj.sock_p,
                                                 &type))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;
                              struct rsbac_rc_nettemp_aci_t aci;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      &temp,
                                                      NULL);
                              if(temp)
                                {
                                  if(!rsbac_list_get_data(nettemp_handles.rc,
                                                          &temp,
                                                          &aci))
                                    type = aci.netobj_type;
                                }
                            }
                          break;

                        case A_remote_rc_type:
                          if(rsbac_list_get_data(rnetobj_handles.rc,
                                                 &tid.netobj.sock_p,
                                                 &type))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;
                              struct rsbac_rc_nettemp_aci_t aci;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      NULL,
                                                      &temp);
                              if(temp)
                                {
                                  if(!rsbac_list_get_data(nettemp_handles.rc,
                                                          &temp,
                                                          &aci))
                                    type = aci.netobj_type;
                                }
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      value->rc_type = type;
                  }
                  break;
#endif /* RC */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            return err;

#endif /* NET_OBJ */

        /* switch target: no valid target */
        default:  
          return(-RSBAC_EINVALIDTARGET);          
      }

    return(err);
  };      /* end of rsbac_get_attr() */

/************************************************************************** */

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_set_attr);
#endif
int rsbac_set_attr(enum rsbac_switch_target_t module,
                   enum rsbac_target_t target,
                   union rsbac_target_id_t tid,
                   enum rsbac_attribute_t attr,
                   union rsbac_attribute_value_t value)

    { 
      int err = 0;
      struct rsbac_device_list_item_t   * device_p;
      u_long                              dflags;
      char tmp[RSBAC_MAXNAMELEN];
    
      if (!rsbac_initialized)
        {
          printk(KERN_WARNING "rsbac_set_attr(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_set_attr(): called from interrupt!\n");
        }
      switch (target)
        {
          case T_FILE:
          case T_DIR:
          case T_FIFO:
          case T_SYMLINK:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
                printk(KERN_DEBUG "rsbac_set_attr(): Setting file/dir/fifo/symlink attribute %u for device %02u:%02u, inode %lu, dentry_p %p\n",
                       attr, MAJOR(tid.file.device),MINOR(tid.file.device), (u_long) tid.file.inode, tid.file.dentry_p);
#endif
*/
            /* wait for read access to device_list_head */
            rsbac_read_lock(&device_list_head.lock, &dflags);
            /* OK, go on */
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
                printk(KERN_DEBUG
                       "rsbac_set_attr(): passed device read lock\n");
#endif
*/

            /* lookup device */
            device_p = lookup_device(tid.file.device);
            if (!device_p)
              {
                printk(KERN_WARNING
                       "rsbac_set_attr(): Could not lookup device!\n");
                /* free read lock */
                rsbac_read_unlock(&device_list_head.lock, &dflags);
                return(-RSBAC_EINVALIDDEV);
              }
            switch(module)
              {
                case GEN:
                  {
                    struct rsbac_gen_fd_aci_t aci = DEFAULT_GEN_FD_ACI;

                    rsbac_list_get_data(device_p->handles.gen[gen_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_log_array_low:
                          aci.log_array_low = value.log_array_low;
                          break;
                        case A_log_array_high:
                          aci.log_array_high = value.log_array_high;
                          break;
                        case A_log_program_based:
                          aci.log_program_based = value.log_program_based;
                          break;
                        case A_symlink_add_uid:
                          aci.symlink_add_uid = value.symlink_add_uid;
                          break;
                        case A_symlink_add_rc_role:
                          aci.symlink_add_rc_role = value.symlink_add_rc_role;
                          break;
                        case A_linux_dac_disable:
                          aci.linux_dac_disable = value.linux_dac_disable;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(device_p->handles.gen[gen_fd_hash(tid.file.inode)],
                                             &tid.file.inode,
                                             &aci);
                      }
                  }
                  break;

#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_fd_aci_t aci = DEFAULT_MAC_FD_ACI;

                    rsbac_list_get_data(device_p->handles.mac[mac_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          aci.sec_level = value.security_level;
                          break;
                        case A_mac_categories:
                          aci.mac_categories = value.mac_categories;
                          break;
                        case A_mac_trusted_for_user:
                          aci.mac_trusted_for_user = value.mac_trusted_for_user;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(device_p->handles.mac[mac_fd_hash(tid.file.inode)],
                                             &tid.file.inode,
                                             &aci);
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    switch (attr)
                      {
                        case A_object_category:
                          err = rsbac_list_add(device_p->handles.fc[fc_fd_hash(tid.file.inode)],
                                               &tid.file.inode,
                                               &value.object_category);
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    switch (attr)
                      {
                        case A_data_type:
                          err = rsbac_list_add(device_p->handles.sim[sim_fd_hash(tid.file.inode)],
                                               &tid.file.inode,
                                               &value.data_type);
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_fd_aci_t aci = DEFAULT_PM_FD_ACI;

                    rsbac_list_get_data(device_p->handles.pm[pm_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_object_class:
                          aci.pm_object_class = value.pm_object_class;
                          break;
                        case A_pm_tp:
                          aci.pm_tp = value.pm_tp;
                          break;
                        case A_pm_object_type:
                          aci.pm_object_type = value.pm_object_type;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(device_p->handles.pm[pm_fd_hash(tid.file.inode)],
                                             &tid.file.inode,
                                             &aci);
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_MS)
                case MS:
                  {
                    if(attr == A_ms_scanned)
                      {
                        err = rsbac_list_add_ttl(device_p->handles.mss[ms_scanned_fd_hash(tid.file.inode)],
                                                 CONFIG_RSBAC_MS_TTL,
                                                 &tid.file.inode,
                                                 &value.ms_scanned);
                      }
                    else
                      {
                        struct rsbac_ms_fd_aci_t aci = DEFAULT_MS_FD_ACI;

                        rsbac_list_get_data(device_p->handles.ms[ms_fd_hash(tid.file.inode)],
                                            &tid.file.inode,
                                            &aci);
                        switch (attr)
                          {
                            case A_ms_trusted:
                              aci.ms_trusted = value.ms_trusted;
                              break;
                            case A_ms_sock_trusted_tcp:
                              aci.ms_sock_trusted_tcp = value.ms_sock_trusted_tcp;
                              break;
                            case A_ms_sock_trusted_udp:
                              aci.ms_sock_trusted_udp = value.ms_sock_trusted_udp;
                              break;
                            default:
                              err = -RSBAC_EINVALIDATTR;
                          }
                        if(!err)
                          {
                            err = rsbac_list_add(device_p->handles.ms[ms_fd_hash(tid.file.inode)],
                                                 &tid.file.inode,
                                                 &aci);
                          }
                      }
                  }
                  break;
#endif /* MS */

#if defined(CONFIG_RSBAC_FF)
                case FF:
                  {
                    switch (attr)
                      {
                        case A_ff_flags:
                          err = rsbac_list_add(device_p->handles.ff[ff_fd_hash(tid.file.inode)],
                                               &tid.file.inode,
                                               &value.ff_flags);
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FF */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    struct rsbac_rc_fd_aci_t aci = DEFAULT_RC_FD_ACI;

                    rsbac_list_get_data(device_p->handles.rc[rc_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_rc_type_fd:
                          aci.rc_type_fd = value.rc_type_fd;
                          break;
                        case A_rc_force_role:
                          aci.rc_force_role = value.rc_force_role;
                          break;
                        case A_rc_initial_role:
                          aci.rc_initial_role = value.rc_initial_role;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(device_p->handles.rc[rc_fd_hash(tid.file.inode)],
                                             &tid.file.inode,
                                             &aci);
                      }
                  }
                  break;
#endif /* RC */

#if defined(CONFIG_RSBAC_AUTH)
                case AUTH:
                  {
                    struct rsbac_auth_fd_aci_t aci = DEFAULT_AUTH_FD_ACI;

                    rsbac_list_get_data(device_p->handles.auth[auth_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_auth_may_setuid:
                          aci.auth_may_setuid = value.auth_may_setuid;
                          break;
                        case A_auth_may_set_cap:
                          aci.auth_may_set_cap = value.auth_may_set_cap;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(device_p->handles.auth[auth_fd_hash(tid.file.inode)],
                                             &tid.file.inode,
                                             &aci);
                      }
                  }
                  break;
#endif /* AUTH */

#if defined(CONFIG_RSBAC_CAP)
                case CAP:
                  {
                    struct rsbac_cap_fd_aci_t aci = DEFAULT_CAP_FD_ACI;

                    rsbac_list_get_data(device_p->handles.cap[cap_fd_hash(tid.file.inode)],
                                        &tid.file.inode,
                                        &aci);
                    switch (attr)
                      {
                        case A_min_caps:
                          aci.min_caps = value.min_caps;
                          break;
                        case A_max_caps:
                          aci.max_caps = value.max_caps;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(device_p->handles.cap[cap_fd_hash(tid.file.inode)],
                                             &tid.file.inode,
                                             &aci);
                      }
                  }
                  break;
#endif

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* free access to device_list_head */
            rsbac_read_unlock(&device_list_head.lock, &dflags);
            /* and return */
            break;
           
          case T_DEV:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG
                     "rsbac_set_attr(): Setting dev attribute\n");
#endif
*/
            switch(module)
              {
                case GEN:
                  {
                    struct rsbac_gen_dev_aci_t aci = DEFAULT_GEN_DEV_ACI;

                    rsbac_list_get_data(dev_handles.gen,
                                        &tid.dev,
                                        &aci);
                    switch (attr)
                      {
                        case A_log_array_low:
                          aci.log_array_low = value.log_array_low;
                          break;
                        case A_log_array_high:
                          aci.log_array_high = value.log_array_high;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(dev_handles.gen,
                                             &tid.dev,
                                             &aci);
                      }
                  }
                  break;

#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_dev_aci_t aci = DEFAULT_MAC_DEV_ACI;

                    rsbac_list_get_data(dev_handles.mac,
                                        &tid.dev,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          aci.sec_level = value.security_level;
                          break;
                        case A_mac_categories:
                          aci.mac_categories = value.mac_categories;
                          break;
                        case A_mac_check:
                          aci.mac_check = value.mac_check;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(dev_handles.mac,
                                             &tid.dev,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_fc_oc_t fc_oc = value.object_category;

                    switch (attr)
                      {
                        case A_object_category:
                          err = rsbac_list_add(dev_handles.fc,
                                               &tid.dev,
                                               &fc_oc);
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_sim_dt_t sim_dt = value.data_type;

                    switch (attr)
                      {
                        case A_data_type:
                          err = rsbac_list_add(dev_handles.sim,
                                               &tid.dev,
                                               &sim_dt);
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_dev_aci_t aci = DEFAULT_PM_DEV_ACI;

                    rsbac_list_get_data(dev_handles.pm,
                                        &tid.dev,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_object_type:
                          aci.pm_object_type = value.pm_object_type;
                          break;
                        case A_pm_object_class:
                          aci.pm_object_class = value.pm_object_class;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(dev_handles.pm,
                                             &tid.dev,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_type_id_t type = value.rc_type;

                    switch (attr)
                      {
                        case A_rc_type:
                          err = rsbac_list_add(dev_handles.rc,
                                               &tid.dev,
                                               &type);
                          break; 
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            break;
            
          case T_IPC:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_set_attr(): Setting ipc attribute");
#endif
*/
            switch(module)
              {
#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_ipc_aci_t aci = DEFAULT_MAC_IPC_ACI;

                    rsbac_list_get_data(ipc_handles.mac,
                                        &tid.ipc,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          aci.sec_level = value.security_level;
                          break;
                        case A_mac_categories:
                          aci.mac_categories = value.mac_categories;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(ipc_handles.mac,
                                             &tid.ipc,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_fc_oc_t fc_oc = value.object_category;

                    switch (attr)
                      {
                        case A_object_category:
                          err = rsbac_list_add(ipc_handles.fc,
                                               &tid.ipc,
                                               &fc_oc);
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_sim_dt_t sim_dt = value.data_type;

                    switch (attr)
                      {
                        case A_data_type:
                          err = rsbac_list_add(ipc_handles.sim,
                                               &tid.ipc,
                                               &sim_dt);
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_ipc_aci_t aci = DEFAULT_PM_IPC_ACI;

                    rsbac_list_get_data(ipc_handles.pm,
                                        &tid.ipc,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_object_type:
                          aci.pm_object_type = value.pm_object_type;
                          break;
                        case A_pm_ipc_purpose:
                          aci.pm_ipc_purpose = value.pm_ipc_purpose;
                          break;
                        case A_pm_object_class:
                          aci.pm_object_class = value.pm_object_class;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(ipc_handles.pm,
                                             &tid.ipc,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_type_id_t type = value.rc_type;

                    switch (attr)
                      {
                        case A_rc_type:
                          err = rsbac_list_add(ipc_handles.rc,
                                               &tid.ipc,
                                               &type);
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            break;
            
          case T_USER:
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG
                     "rsbac_set_attr(): Setting %s user attribute %i for %u to %i\n",
                     get_switch_target_name(tmp, module), attr, tid.user, value.dummy);
#endif
            switch(module)
              {
                case GEN:
                  {
                    struct rsbac_gen_user_aci_t aci = DEFAULT_GEN_U_ACI;

                    rsbac_list_get_data(user_handles.gen,
                                        &tid.user,
                                        &aci);
                    switch (attr)
                      {
                        case A_pseudo:
                          aci.pseudo = value.pseudo;
                          break;
                        case A_log_user_based:
                          aci.log_user_based = value.log_user_based;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(user_handles.gen,
                                             &tid.user,
                                             &aci);
                      }
                  }
                  break;

#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_user_aci_t aci = DEFAULT_MAC_U_ACI;

                    rsbac_list_get_data(user_handles.mac,
                                        &tid.user,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          aci.access_appr = value.security_level;
                          break;
                        case A_mac_categories:
                          aci.mac_categories = value.mac_categories;
                          break;
                        case A_system_role:
                        case A_mac_role:
                          aci.system_role = value.system_role;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(user_handles.mac,
                                             &tid.user,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_system_role_int_t role = value.system_role;

                    switch (attr)
                      {
                        case A_system_role:
                        case A_fc_role:
                          err = rsbac_list_add(user_handles.fc,
                                               &tid.user,
                                               &role);
                          break; 
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_system_role_int_t role = value.system_role;

                    switch (attr)
                      {
                        case A_system_role:
                        case A_sim_role:
                          err = rsbac_list_add(user_handles.sim,
                                               &tid.user,
                                               &role);
                          break; 
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_user_aci_t aci = DEFAULT_PM_U_ACI;

                    rsbac_list_get_data(user_handles.pm,
                                        &tid.user,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_task_set:
                          aci.pm_task_set = value.pm_task_set;
                          break;
                        case A_pm_role:
                          aci.pm_role = value.pm_role;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(user_handles.pm,
                                             &tid.user,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_MS)
                case MS:
                  {
                    rsbac_system_role_int_t role = value.system_role;

                    switch (attr)
                      {
                        case A_system_role:
                        case A_ms_role:
                          err = rsbac_list_add(user_handles.ms,
                                               &tid.user,
                                               &role);
                          break; 
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_FF)
                case FF:
                  {
                    rsbac_system_role_int_t role = value.system_role;

                    switch (attr)
                      {
                        case A_system_role:
                        case A_ff_role:
                          err = rsbac_list_add(user_handles.ff,
                                               &tid.user,
                                               &role);
                          break; 
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_role_id_t role = value.rc_role;

                    switch (attr)
                      {
                        case A_rc_def_role:
                          err = rsbac_list_add(user_handles.rc,
                                               &tid.user,
                                               &role);
                          break; 
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_AUTH)
                case AUTH:
                  {
                    rsbac_system_role_int_t role = value.system_role;

                    switch (attr)
                      {
                        case A_system_role:
                        case A_auth_role:
                          err = rsbac_list_add(user_handles.auth,
                                               &tid.user,
                                               &role);
                          break; 
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_CAP)
                case CAP:
                  {
                    struct rsbac_cap_user_aci_t aci = DEFAULT_CAP_U_ACI;

                    rsbac_list_get_data(user_handles.cap,
                                        &tid.user,
                                        &aci);
                    switch (attr)
                      {
                        case A_system_role:
                        case A_auth_role:
                          aci.cap_role = value.system_role;
                          break;
                        case A_min_caps:
                          aci.min_caps = value.min_caps;
                          break;
                        case A_max_caps:
                          aci.max_caps = value.max_caps;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(user_handles.cap,
                                             &tid.user,
                                             &aci);
                      }
                  }
                  break;
#endif

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            break;
            
          case T_PROCESS:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG
                     "rsbac_set_attr(): Setting process attribute\n");
#endif
*/
            if (!tid.process)
              {
                printk(KERN_WARNING
                       "rsbac_set_attr(): Trying to set attribute for process 0!\n");
                return -RSBAC_EINVALIDTARGET;
              }
            switch(module)
              {
                case GEN:
                  {
                    rsbac_request_vector_t rv = value.log_program_based;

                    switch (attr)
                      {
                        case A_log_program_based:
                          err = rsbac_list_add(process_handles.gen,
                                               &tid.process,
                                               &rv);
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;

#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_process_aci_t aci = DEFAULT_MAC_P_ACI;

                    rsbac_list_get_data(process_handles.mac,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          aci.owner_sec_level = value.security_level;
                          break;
                        case A_mac_categories:
                          aci.mac_owner_categories = value.mac_categories;
                          break;
                        case A_current_sec_level:
                          aci.current_sec_level = value.current_sec_level;
                          break;
                        case A_mac_curr_categories:
                          aci.mac_curr_categories = value.mac_categories;
                          break;
                        case A_min_write_open:
                          aci.min_write_open = value.min_write_open;
                          break;
                        case A_min_write_categories:
                          aci.min_write_categories = value.mac_categories;
                          break;
                        case A_max_read_open:
                          aci.max_read_open = value.max_read_open;
                          break;
                        case A_max_read_categories:
                          aci.max_read_categories = value.mac_categories;
                          break;
                        case A_mac_auto:
                          aci.mac_auto = value.mac_auto;
                          break;
                        case A_mac_trusted:
                          aci.mac_trusted = value.mac_trusted;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(process_handles.mac,
                                             &tid.process,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_process_aci_t aci = DEFAULT_PM_P_ACI;

                    rsbac_list_get_data(process_handles.pm,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_tp:
                          aci.pm_tp = value.pm_tp;
                          break;
                        case A_pm_current_task:
                          aci.pm_current_task = value.pm_current_task;
                          break;
                        case A_pm_process_type:
                          aci.pm_process_type = value.pm_process_type;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(process_handles.pm,
                                             &tid.process,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_MS)
                case MS:
                  {
                    struct rsbac_ms_process_aci_t aci = DEFAULT_MS_P_ACI;

                    rsbac_list_get_data(process_handles.ms,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_ms_trusted:
                          aci.ms_trusted = value.ms_trusted;
                          break;
                        case A_ms_sock_trusted_tcp:
                          aci.ms_sock_trusted_tcp = value.ms_sock_trusted_tcp;
                          break;
                        case A_ms_sock_trusted_udp:
                          aci.ms_sock_trusted_udp = value.ms_sock_trusted_udp;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(process_handles.ms,
                                             &tid.process,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    struct rsbac_rc_process_aci_t aci = DEFAULT_RC_P_ACI;

                    rsbac_list_get_data(process_handles.rc,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_rc_role:
                          aci.rc_role = value.rc_role;
                          break;
                        case A_rc_type:
                          aci.rc_type = value.rc_type;
                          break;
                        case A_rc_force_role:
                          aci.rc_force_role = value.rc_force_role;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(process_handles.rc,
                                             &tid.process,
                                             &aci);
                      }
                  }
                  break;
#endif

#if defined(CONFIG_RSBAC_AUTH)
                case AUTH:
                  {
                    struct rsbac_auth_process_aci_t aci = DEFAULT_AUTH_P_ACI;

                    rsbac_list_get_data(process_handles.auth,
                                        &tid.process,
                                        &aci);
                    switch (attr)
                      {
                        case A_auth_may_setuid:
                          aci.auth_may_setuid = value.auth_may_setuid;
                          break;
                        case A_auth_may_set_cap:
                          aci.auth_may_set_cap = value.auth_may_set_cap;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(process_handles.auth,
                                             &tid.process,
                                             &aci);
                      }
                  }
                  break;
#endif

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            break;

#ifdef CONFIG_RSBAC_NET_DEV
          case T_NETDEV:
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG
                     "rsbac_set_attr(): Setting netdev attribute\n");
#endif
            switch(module)
              {
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
                case GEN:
                  {
                    struct rsbac_gen_netdev_aci_t aci = DEFAULT_GEN_NETDEV_ACI;

                    rsbac_list_get_data(netdev_handles.gen,
                                        &tid.netdev,
                                        &aci);
                    switch (attr)
                      {
                        case A_log_array_low:
                          aci.log_array_low = value.log_array_low;
                          break;
                        case A_log_array_high:
                          aci.log_array_high = value.log_array_high;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(netdev_handles.gen,
                                             &tid.netdev,
                                             &aci);
                      }
                  }
                  break;
#endif
#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_type_id_t type = value.rc_type;

                    switch (attr)
                      {
                        case A_rc_type:
                          err = rsbac_list_add(netdev_handles.rc,
                                               &tid.netdev,
                                               &type);
                          break; 
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            /* and return */
            break;
#endif

#ifdef CONFIG_RSBAC_NET_OBJ
          case T_NETTEMP:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_set_attr(): Setting nettemp attribute");
#endif
*/
            if(!rsbac_list_exist(net_temp_handle, &tid.nettemp))
              return -RSBAC_EINVALIDTARGET;
            switch(module)
              {
#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
                case GEN:
                  {
                    struct rsbac_gen_netobj_aci_t aci = DEFAULT_GEN_NETOBJ_ACI;

                    rsbac_list_get_data(nettemp_handles.gen,
                                        &tid.nettemp,
                                        &aci);
                    switch (attr)
                      {
                        case A_log_array_low:
                          aci.log_array_low = value.log_array_low;
                          break;
                        case A_log_array_high:
                          aci.log_array_high = value.log_array_high;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(nettemp_handles.gen,
                                             &tid.nettemp,
                                             &aci);
                      }
                  }
                  break;
#endif /* IND_NETOBJ_LOG */
#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_netobj_aci_t aci = DEFAULT_MAC_NETOBJ_ACI;

                    rsbac_list_get_data(nettemp_handles.mac,
                                        &tid.nettemp,
                                        &aci);
                    switch (attr)
                      {
                        case A_security_level:
                          aci.sec_level = value.security_level;
                          break;
                        case A_mac_categories:
                          aci.mac_categories = value.mac_categories;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(nettemp_handles.mac,
                                             &tid.nettemp,
                                             &aci);
                      }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_fc_oc_t fc_oc = value.object_category;

                    err = rsbac_list_add(nettemp_handles.fc,
                                         &tid.nettemp,
                                         &fc_oc);
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_sim_dt_t sim_dt = value.data_type;

                    err = rsbac_list_add(nettemp_handles.sim,
                                         &tid.nettemp,
                                         &sim_dt);
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_netobj_aci_t aci = DEFAULT_PM_NETOBJ_ACI;

                    rsbac_list_get_data(nettemp_handles.pm,
                                        &tid.nettemp,
                                        &aci);
                    switch (attr)
                      {
                        case A_pm_object_class:
                          aci.pm_object_class = value.pm_object_class;
                          break;
                        case A_pm_ipc_purpose:
                          aci.pm_ipc_purpose = value.pm_ipc_purpose;
                          break;
                        case A_pm_object_type:
                          aci.pm_object_type = value.pm_object_type;
                          break;
                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(nettemp_handles.pm,
                                             &tid.nettemp,
                                             &aci);
                      }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    struct rsbac_rc_nettemp_aci_t aci = DEFAULT_RC_NETTEMP_ACI;

                    rsbac_list_get_data(nettemp_handles.rc,
                                        &tid.nettemp,
                                        &aci);
                    switch (attr)
                      {
                        case A_rc_type:
                          aci.netobj_type = value.rc_type;
                          break;
                        case A_rc_type_nt:
                          aci.nettemp_type = value.rc_type;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      {
                        err = rsbac_list_add(nettemp_handles.rc,
                                             &tid.nettemp,
                                             &aci);
                      }
                  }
                  break;
#endif /* RC */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            break;

          case T_NETOBJ:
/*
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_set_attr(): Setting netobj attribute");
#endif
*/
            switch(module)
              {
#if defined(CONFIG_RSBAC_MAC)
                case MAC:
                  {
                    struct rsbac_mac_netobj_aci_t aci = DEFAULT_MAC_NETOBJ_ACI;

                    switch(attr)
                      {
                        case A_local_sec_level:
                        case A_local_mac_categories:
                          if(rsbac_list_get_data(lnetobj_handles.mac,
                                                 &tid.netobj.sock_p,
                                                 &aci))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      &temp,
                                                      NULL);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.mac,
                                                    &temp,
                                                    &aci);
                            }
                          break;

                        case A_remote_sec_level:
                        case A_remote_mac_categories:
                          if(rsbac_list_get_data(rnetobj_handles.mac,
                                                 &tid.netobj.sock_p,
                                                 &aci))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      NULL,
                                                      &temp);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.mac,
                                                    &temp,
                                                    &aci);
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(err)
                      break;
                    {
                      switch (attr)
                        {
                          case A_local_sec_level:
                            aci.sec_level = value.security_level;
                            err = rsbac_list_add(lnetobj_handles.mac,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;
                          case A_remote_sec_level:
                            aci.sec_level = value.security_level;
                            err = rsbac_list_add(rnetobj_handles.mac,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;
                          case A_local_mac_categories:
                            aci.mac_categories = value.mac_categories;
                            err = rsbac_list_add(lnetobj_handles.mac,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;
                          case A_remote_mac_categories:
                            aci.mac_categories = value.mac_categories;
                            err = rsbac_list_add(rnetobj_handles.mac,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;

                          default:
                            err = -RSBAC_EINVALIDATTR;
                        }
                    }
                  }
                  break;
#endif /* MAC */

#if defined(CONFIG_RSBAC_FC)
                case FC:
                  {
                    rsbac_fc_oc_t fc_oc = value.object_category;

                    switch(attr)
                      {
                        case A_local_object_category:
                          err = rsbac_list_add(lnetobj_handles.fc,
                                               &tid.netobj.sock_p,
                                               &fc_oc);
                          break;

                        case A_remote_object_category:
                          err = rsbac_list_add(rnetobj_handles.fc,
                                               &tid.netobj.sock_p,
                                               &fc_oc);
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* FC */

#if defined(CONFIG_RSBAC_SIM)
                case SIM:
                  {
                    rsbac_sim_dt_t sim_dt = value.data_type;

                    switch(attr)
                      {
                        case A_local_data_type:
                          err = rsbac_list_add(lnetobj_handles.sim,
                                               &tid.netobj.sock_p,
                                               &sim_dt);
                          break;

                        case A_remote_data_type:
                          err = rsbac_list_add(rnetobj_handles.sim,
                                               &tid.netobj.sock_p,
                                               &sim_dt);
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* SIM */

#if defined(CONFIG_RSBAC_PM)
                case PM:
                  {
                    struct rsbac_pm_netobj_aci_t aci = DEFAULT_PM_NETOBJ_ACI;

                    switch(attr)
                      {
                        case A_local_pm_object_class:
                        case A_local_pm_ipc_purpose:
                        case A_local_pm_object_type:
                          if(rsbac_list_get_data(lnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      &temp,
                                                      NULL);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.pm,
                                                    &temp,
                                                    &aci);
                            }
                          break;

                        case A_remote_pm_object_class:
                        case A_remote_pm_ipc_purpose:
                        case A_remote_pm_object_type:
                          if(rsbac_list_get_data(rnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci))
                            { /* not found -> fallback to template */
                              rsbac_net_temp_id_t temp = 0;

                              rsbac_net_lookup_templates(tid.netobj,
                                                      NULL,
                                                      &temp);
                              if(temp)
                                rsbac_list_get_data(nettemp_handles.pm,
                                                    &temp,
                                                    &aci);
                            }
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(err)
                      break;
                    {
                      switch (attr)
                        {
                          case A_local_pm_object_class:
                            aci.pm_object_class = value.pm_object_class;
                            err = rsbac_list_add(lnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;
                          case A_remote_pm_object_class:
                            aci.pm_object_class = value.pm_object_class;
                            err = rsbac_list_add(rnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;
                          case A_local_pm_ipc_purpose:
                            aci.pm_ipc_purpose = value.pm_ipc_purpose;
                            err = rsbac_list_add(lnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;
                          case A_remote_pm_ipc_purpose:
                            aci.pm_ipc_purpose = value.pm_ipc_purpose;
                            err = rsbac_list_add(rnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;
                          case A_local_pm_object_type:
                            aci.pm_object_type = value.pm_object_type;
                            err = rsbac_list_add(lnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;
                          case A_remote_pm_object_type:
                            aci.pm_object_type = value.pm_object_type;
                            err = rsbac_list_add(rnetobj_handles.pm,
                                                 &tid.netobj.sock_p,
                                                 &aci);
                            break;

                          default:
                            err = -RSBAC_EINVALIDATTR;
                        }
                    }
                  }
                  break;
#endif /* PM */

#if defined(CONFIG_RSBAC_MS)
                case MS:
                  {
                    struct rsbac_ms_netobj_aci_t aci = DEFAULT_MS_NETOBJ_ACI;
                    int i;

                    rsbac_list_get_data(lnetobj_handles.ms,
                                        &tid.netobj.sock_p,
                                        &aci);
                    switch (attr)
                      {
                        case A_ms_backbuf:
                          memcpy(aci.ms_backbuf,
                                 value.ms_backbuf,
                                 RSBAC_MS_MAX_STR_LEN);
                          break;
                        case A_ms_buflen:
                          aci.ms_buflen = value.ms_buflen;
                          break;
                        case A_ms_str_nr:
                          for(i=0; i<RSBAC_MS_NR_MALWARE; i++)
                            aci.ms_str_nr[i] = value.ms_str_nr[i];
                          break;
                        case A_ms_str_offset:
                          for(i=0; i<RSBAC_MS_NR_MALWARE; i++)
                            aci.ms_str_offset[i] = value.ms_str_offset[i];
                          break;
                        case A_ms_scanned:
                          aci.ms_scanned = value.ms_scanned;
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                    if(!err)
                      err = rsbac_list_add_ttl(lnetobj_handles.ms,
                                               CONFIG_RSBAC_MS_TTL,
                                               &tid.netobj.sock_p,
                                               &aci);
                      break;
                  }
                  break;
#endif /* MS */

#if defined(CONFIG_RSBAC_RC)
                case RC:
                  {
                    rsbac_rc_type_id_t type = value.rc_type;

                    switch(attr)
                      {
                        case A_local_rc_type:
                          err = rsbac_list_add(lnetobj_handles.rc,
                                               &tid.netobj.sock_p,
                                               &type);
                          break;

                        case A_remote_rc_type:
                          err = rsbac_list_add(rnetobj_handles.rc,
                                               &tid.netobj.sock_p,
                                               &type);
                          break;

                        default:
                          err = -RSBAC_EINVALIDATTR;
                      }
                  }
                  break;
#endif /* RC */

                default:
                  err = -RSBAC_EINVALIDMODULE;
              }
            break;
#endif /* NET_OBJ */

          /* switch(target): no valid target */
          default:  
            return(-RSBAC_EINVALIDTARGET);          
        }
      #ifdef CONFIG_RSBAC_XSTATS
      if(!err)
        set_attr_count[target]++;
      #endif
      return(err);
    };      /* end of rsbac_set_attr() */

/************************************************************************** */

#if defined(CONFIG_RSBAC_REG)
EXPORT_SYMBOL(rsbac_remove_target);
#endif
int rsbac_remove_target(enum rsbac_target_t target,
                        union rsbac_target_id_t tid)
    { 
      int error=0;
      struct rsbac_device_list_item_t   * device_p;
      u_long                              dflags;
    
      if (!rsbac_initialized)
        {
          printk(KERN_WARNING "rsbac_remove_target(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_remove_target(): called from interrupt!\n");
        }
      switch (target)
        {
          case T_FILE:
          case T_DIR:
          case T_FIFO:
          case T_SYMLINK:
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_remove_target(): Removing file/dir/fifo/symlink ACI");
#endif
#if defined(CONFIG_RSBAC_AUTH)
            /* file items can also have an auth_f_capset -> remove first */
            if(target == T_FILE)
              error = rsbac_auth_remove_f_capset(tid.file);
#endif
#if defined(CONFIG_RSBAC_ACL)
            /* items can also have an acl_fd_item -> remove first */
            error = rsbac_acl_remove_acl(target, tid);
#endif
            /* wait for read access to device_list_head */
            rsbac_read_lock(&device_list_head.lock, &dflags);
            /* OK, go on */

            /* lookup device */
            device_p = lookup_device(tid.file.device);
            if (device_p)
              {
                rsbac_list_remove(device_p->handles.gen[gen_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#if defined(CONFIG_RSBAC_MAC)
                rsbac_list_remove(device_p->handles.mac[mac_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
#if defined(CONFIG_RSBAC_FC)
                rsbac_list_remove(device_p->handles.fc[fc_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
#if defined(CONFIG_RSBAC_SIM)
                rsbac_list_remove(device_p->handles.sim[sim_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
#if defined(CONFIG_RSBAC_PM)
                rsbac_list_remove(device_p->handles.pm[pm_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
#if defined(CONFIG_RSBAC_MS)
                rsbac_list_remove(device_p->handles.ms[ms_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
                rsbac_list_remove(device_p->handles.mss[ms_scanned_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
#if defined(CONFIG_RSBAC_FF)
                rsbac_list_remove(device_p->handles.ff[ff_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
#if defined(CONFIG_RSBAC_RC)
                rsbac_list_remove(device_p->handles.rc[rc_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
#if defined(CONFIG_RSBAC_AUTH)
                rsbac_list_remove(device_p->handles.auth[auth_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
#if defined(CONFIG_RSBAC_CAP)
                rsbac_list_remove(device_p->handles.cap[cap_fd_hash(tid.file.inode)],
                                  &tid.file.inode);
#endif
              }
            else
              error = -RSBAC_EINVALIDDEV;

            /* free access to device_list_head */
            rsbac_read_unlock(&device_list_head.lock, &dflags);
            break;

          case T_DEV:
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_remove_target(): Removing dev ACI");
#endif
            rsbac_list_remove(dev_handles.gen,
                              &tid.dev);
#if defined(CONFIG_RSBAC_MAC)
            rsbac_list_remove(dev_handles.mac,
                              &tid.dev);
#endif
#if defined(CONFIG_RSBAC_FC)
            rsbac_list_remove(dev_handles.fc,
                              &tid.dev);
#endif
#if defined(CONFIG_RSBAC_SIM)
            rsbac_list_remove(dev_handles.sim,
                              &tid.dev);
#endif
#if defined(CONFIG_RSBAC_PM)
            rsbac_list_remove(dev_handles.pm,
                              &tid.dev);
#endif
#if defined(CONFIG_RSBAC_RC)
            rsbac_list_remove(dev_handles.rc,
                              &tid.dev);
#endif
            break;

          case T_IPC:
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG
                     "rsbac_remove_target(): Removing ipc ACI\n");
#endif
#if defined(CONFIG_RSBAC_MAC)
            rsbac_list_remove(ipc_handles.mac,
                              &tid.dev);
#endif
#if defined(CONFIG_RSBAC_FC)
            rsbac_list_remove(ipc_handles.fc,
                              &tid.dev);
#endif
#if defined(CONFIG_RSBAC_SIM)
            rsbac_list_remove(ipc_handles.sim,
                              &tid.dev);
#endif
#if defined(CONFIG_RSBAC_PM)
            rsbac_list_remove(ipc_handles.pm,
                              &tid.dev);
#endif
#if defined(CONFIG_RSBAC_RC)
            rsbac_list_remove(ipc_handles.rc,
                              &tid.dev);
#endif
            break;

          case T_USER:
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds) printk(KERN_DEBUG "%s\n",
                        "rsbac_remove_target(): Removing user ACI");
#endif
            rsbac_list_remove(user_handles.gen,
                              &tid.user);
#if defined(CONFIG_RSBAC_MAC)
            rsbac_list_remove(user_handles.mac,
                              &tid.user);
#endif
#if defined(CONFIG_RSBAC_FC)
            rsbac_list_remove(user_handles.fc,
                              &tid.user);
#endif
#if defined(CONFIG_RSBAC_SIM)
            rsbac_list_remove(user_handles.sim,
                              &tid.user);
#endif
#if defined(CONFIG_RSBAC_PM)
            rsbac_list_remove(user_handles.pm,
                              &tid.user);
#endif
#if defined(CONFIG_RSBAC_MS)
            rsbac_list_remove(user_handles.ms,
                              &tid.user);
#endif
#if defined(CONFIG_RSBAC_FF)
            rsbac_list_remove(user_handles.ff,
                              &tid.user);
#endif
#if defined(CONFIG_RSBAC_RC)
            rsbac_list_remove(user_handles.rc,
                              &tid.user);
#endif
#if defined(CONFIG_RSBAC_AUTH)
            rsbac_list_remove(user_handles.auth,
                              &tid.user);
#endif
#if defined(CONFIG_RSBAC_CAP)
            rsbac_list_remove(user_handles.cap,
                              &tid.user);
#endif
            break;

          case T_PROCESS:
/* too noisy... kicked out.
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG
                     "rsbac_remove_target(): Removing process ACI\n");
#endif
*/
#if defined(CONFIG_RSBAC_ACL)
            /* process items can also have an acl_p_item -> remove first */
            error = rsbac_acl_remove_acl(target, tid);
#endif
            rsbac_list_remove(process_handles.gen,
                              &tid.process);
#if defined(CONFIG_RSBAC_MAC)
            rsbac_list_remove(process_handles.mac,
                              &tid.process);
#endif
#if defined(CONFIG_RSBAC_PM)
            rsbac_list_remove(process_handles.pm,
                              &tid.process);
#endif
#if defined(CONFIG_RSBAC_MS)
            rsbac_list_remove(process_handles.ms,
                              &tid.process);
#endif
#if defined(CONFIG_RSBAC_RC)
            rsbac_list_remove(process_handles.rc,
                              &tid.process);
#endif
#if defined(CONFIG_RSBAC_AUTH)
            /* process items can also have an auth_p_capset -> remove first */
            error = rsbac_auth_remove_p_capset(tid.process);
            rsbac_list_remove(process_handles.auth,
                              &tid.process);
#endif
            break;

#ifdef CONFIG_RSBAC_NET_DEV
          case T_NETDEV:
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
            rsbac_list_remove(netdev_handles.gen,
                              &tid.netdev);
#endif
#if defined(CONFIG_RSBAC_RC)
            rsbac_list_remove(netdev_handles.rc,
                              &tid.netdev);
#endif
            break;
#endif

#ifdef CONFIG_RSBAC_NET_OBJ
          case T_NETTEMP:
/* too noisy... kicked out.
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG
                     "rsbac_remove_target(): Removing nettemp ACI\n");
#endif
*/
#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
            rsbac_list_remove(nettemp_handles.gen,
                              &tid.nettemp);
#endif
#if defined(CONFIG_RSBAC_MAC)
            rsbac_list_remove(nettemp_handles.mac,
                              &tid.nettemp);
#endif
#if defined(CONFIG_RSBAC_FC)
            rsbac_list_remove(nettemp_handles.fc,
                              &tid.nettemp);
#endif
#if defined(CONFIG_RSBAC_SIM)
            rsbac_list_remove(nettemp_handles.sim,
                              &tid.nettemp);
#endif
#if defined(CONFIG_RSBAC_PM)
            rsbac_list_remove(nettemp_handles.pm,
                              &tid.nettemp);
#endif
#if defined(CONFIG_RSBAC_RC)
            rsbac_list_remove(nettemp_handles.rc,
                              &tid.nettemp);
#endif
#if defined(CONFIG_RSBAC_ACL_NET_OBJ_PROT)
            rsbac_acl_remove_acl(T_NETTEMP_NT,
                                 tid);
            rsbac_acl_remove_acl(T_NETTEMP,
                                 tid);
#endif
            break;

          case T_NETOBJ:
/* too noisy... kicked out.
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_ds)
              printk(KERN_DEBUG
                     "rsbac_remove_target(): Removing netobj ACI\n");
#endif
*/
#if defined(CONFIG_RSBAC_MAC)
            rsbac_list_remove(lnetobj_handles.mac,
                              &tid.netobj.sock_p);
            rsbac_list_remove(rnetobj_handles.mac,
                              &tid.netobj.sock_p);
#endif
#if defined(CONFIG_RSBAC_FC)
            rsbac_list_remove(lnetobj_handles.fc,
                              &tid.netobj.sock_p);
            rsbac_list_remove(rnetobj_handles.fc,
                              &tid.netobj.sock_p);
#endif
#if defined(CONFIG_RSBAC_SIM)
            rsbac_list_remove(lnetobj_handles.sim,
                              &tid.netobj.sock_p);
            rsbac_list_remove(rnetobj_handles.sim,
                              &tid.netobj.sock_p);
#endif
#if defined(CONFIG_RSBAC_PM)
            rsbac_list_remove(lnetobj_handles.pm,
                              &tid.netobj.sock_p);
            rsbac_list_remove(rnetobj_handles.pm,
                              &tid.netobj.sock_p);
#endif
#if defined(CONFIG_RSBAC_MS)
            rsbac_list_remove(lnetobj_handles.ms,
                              &tid.netobj.sock_p);
#endif
#if defined(CONFIG_RSBAC_RC)
            rsbac_list_remove(lnetobj_handles.rc,
                              &tid.netobj.sock_p);
            rsbac_list_remove(rnetobj_handles.rc,
                              &tid.netobj.sock_p);
#endif
            break;

#endif /* NET_OBJ */

          default:
            return(-RSBAC_EINVALIDTARGET);          
        }
      #ifdef CONFIG_RSBAC_XSTATS
      remove_count[target]++;
      #endif
      return(error);
    };      /* end of rsbac_remove_target() */


#ifdef CONFIG_RSBAC_NET_DEV
int rsbac_net_list_all_netdev(rsbac_netdev_id_t ** id_pp)
  {
    int count=0;
    int tmp_count;

    if(id_pp)
      {
        rsbac_netdev_id_t * i_id_p = NULL;
        char * pos = NULL;
        int i_count = 0;
#if defined(CONFIG_RSBAC_RC)
        u_int i;
#endif

#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
        tmp_count = rsbac_list_count(netdev_handles.gen);
        if(tmp_count > 0)
          i_count += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
        tmp_count = rsbac_list_count(netdev_handles.rc);
        if(tmp_count > 0)
          i_count += tmp_count;
#endif
        if(i_count > 0)
          {
            i_count += 20; /* max value to expect */
            *id_pp = vmalloc(i_count * sizeof(**id_pp));
            if(!*id_pp)
              return -RSBAC_ENOMEM;
            pos = (char *) *id_pp;
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
            tmp_count = rsbac_list_get_all_desc(netdev_handles.gen, (void **) &i_id_p);
            if(tmp_count > 0)
              {
                if(tmp_count > i_count)
                  tmp_count = i_count;
                memcpy(pos, i_id_p, tmp_count * sizeof(*i_id_p));
                vfree(i_id_p);
                count = tmp_count;
                i_count -= tmp_count;
                pos += tmp_count * sizeof(*i_id_p);
              }
#endif
#if defined(CONFIG_RSBAC_RC)
            if(i_count)
              {
                tmp_count = rsbac_list_get_all_desc(netdev_handles.rc, (void **) &i_id_p);
                if(tmp_count > 0)
                  {
                    if(tmp_count > i_count)
                      tmp_count = i_count;
                    for(i=0; i< tmp_count; i++)
                      {
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
                        if(!rsbac_list_exist(netdev_handles.gen, &i_id_p[i]))
#endif
                          {
                            memcpy(pos, &i_id_p[i], sizeof(*i_id_p));
                            pos += sizeof(*i_id_p);
                            count++;
                          }
                      }
                    vfree(i_id_p);
                  }
              }
#endif
            if(!count)
              vfree(*id_pp);
          }
      }
    else
      {
#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
        tmp_count = rsbac_list_count(netdev_handles.gen);
        if(tmp_count > 0)
          count += tmp_count;
#endif
#if defined(CONFIG_RSBAC_RC)
        tmp_count = rsbac_list_count(netdev_handles.rc);
        if(tmp_count > 0)
          count += tmp_count;
#endif
      }
    return count;
  }
#endif

#ifdef CONFIG_RSBAC_NET_OBJ
/* Get a template id from a net description */
int rsbac_net_get_id (struct rsbac_net_description_t desc,
                      rsbac_net_temp_id_t * id_p)
  {
    if(!rsbac_initialized)
      return -RSBAC_ENOTINITIALIZED;
    if(!id_p)
      return -RSBAC_EINVALIDPOINTER;
    if(rsbac_list_get_desc(net_temp_handle,
                           id_p,
                           &desc,
                           rsbac_net_compare_data)
      )
      *id_p = RSBAC_NET_UNKNOWN;
    return 0;
  }

/* get the template ids for a netobj */
/* set *_temp_p to NULL, if you do not need it */
int rsbac_net_lookup_templates(struct rsbac_net_obj_desc_t netobj,
                               rsbac_net_temp_id_t * local_temp_p,
                               rsbac_net_temp_id_t * remote_temp_p)
  {
    struct rsbac_net_description_t rsbac_net_desc;
    int err=0;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
    struct net_device *dev;
#else
    struct device *dev;
#endif

    if(!netobj.sock_p || !netobj.sock_p->sk || !netobj.sock_p->ops)
      return -RSBAC_EINVALIDPOINTER;
    if(!local_temp_p && !remote_temp_p)
      return -RSBAC_EINVALIDVALUE;

    rsbac_net_desc.address_family = netobj.sock_p->ops->family;
    rsbac_net_desc.type = netobj.sock_p->type;
    rsbac_net_desc.protocol = netobj.sock_p->sk->protocol;
    if(netobj.sock_p->sk->bound_dev_if)
      {
        dev = dev_get_by_index(netobj.sock_p->sk->bound_dev_if);
        if(dev)
          {
            strcpy(rsbac_net_desc.netdev, dev->name);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
            dev_put(dev);
#endif
          }
        else
          rsbac_net_desc.netdev[0] = RSBAC_NET_UNKNOWN;
      }
    else
      rsbac_net_desc.netdev[0] = RSBAC_NET_UNKNOWN;
    if(local_temp_p)
      {
        switch(rsbac_net_desc.address_family)
          {
            case AF_INET:
              if(netobj.local_addr)
                {
                  struct sockaddr_in * addr = netobj.local_addr;

                  rsbac_net_desc.address = &addr->sin_addr.s_addr;
                  rsbac_net_desc.address_len = sizeof(__u32);
                  rsbac_net_desc.port = ntohs(addr->sin_port);
                }
              else
                {
                  rsbac_net_desc.address = &netobj.sock_p->sk->rcv_saddr;
                  rsbac_net_desc.address_len = sizeof(__u32);
                  rsbac_net_desc.port = netobj.sock_p->sk->num;
                }
              dev = ip_dev_find(*(__u32 *)rsbac_net_desc.address);
              if(dev)
                {
                  strcpy(rsbac_net_desc.netdev, dev->name);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
                  dev_put(dev);
#endif
                }
              break;
            case AF_UNIX:
              if(netobj.sock_p->sk->protinfo.af_unix.addr)
                {
                  rsbac_net_desc.address = netobj.sock_p->sk->protinfo.af_unix.addr->name[0].sun_path;
                  rsbac_net_desc.address_len = netobj.sock_p->sk->protinfo.af_unix.addr->len;
                }
              else
              if(netobj.local_addr)
                {
                  struct sockaddr_un * addr = netobj.local_addr;

                  if(addr->sun_path)
                    {
                      rsbac_net_desc.address = addr->sun_path;
                      rsbac_net_desc.address_len = strlen(addr->sun_path);
                    }
                  else
                    {
                      rsbac_net_desc.address = NULL;
                      rsbac_net_desc.address_len = 0;
                    }
                }
              else
                {
                  rsbac_net_desc.address = NULL;
                  rsbac_net_desc.address_len = 0;
                }
              break;

            default:
              rsbac_net_desc.address = NULL;
              rsbac_net_desc.port = RSBAC_NET_UNKNOWN;
          }
        if((err = rsbac_net_get_id(rsbac_net_desc, local_temp_p)))
          {
            *local_temp_p = 0;
            printk(KERN_WARNING
                   "rsbac_net_lookup_templates(): rsbac_net_get_id for local returned error %u\n",
                   err);
          }
#ifdef CONFIG_RSBAC_DEBUG
        if(   rsbac_debug_ds_net
           && (rsbac_net_desc.address_family == AF_INET)
          )
          printk(KERN_DEBUG
                 "rsbac_net_lookup_templates(): user %u temp id for local is %u\n",
                 current->uid, *local_temp_p);
#endif
      }
    if(remote_temp_p)
      {
        switch(rsbac_net_desc.address_family)
          {
            case AF_INET:
              if(netobj.remote_addr)
                {
                  struct sockaddr_in * addr = netobj.remote_addr;

                  rsbac_net_desc.address = &addr->sin_addr.s_addr;
                  rsbac_net_desc.address_len = sizeof(__u32);
                  rsbac_net_desc.port = ntohs(addr->sin_port);
                }
              else
                {
                  rsbac_net_desc.address = &netobj.sock_p->sk->daddr;
                  rsbac_net_desc.address_len = sizeof(__u32);
                  rsbac_net_desc.port = netobj.sock_p->sk->dport;
                }
              dev = ip_dev_find(*(__u32 *)rsbac_net_desc.address);
              if(dev)
                {
                  strcpy(rsbac_net_desc.netdev, dev->name);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
                  dev_put(dev);
#endif
                }
              break;
            case AF_UNIX:
              rsbac_net_desc.port = RSBAC_NET_UNKNOWN;
              if(   (netobj.sock_p->sk->protinfo.af_unix.other)
                 && (netobj.sock_p->sk->protinfo.af_unix.other->protinfo.af_unix.addr)
                )
                {
                  rsbac_net_desc.address
                   = netobj.sock_p->sk->protinfo.af_unix.other->protinfo.af_unix.addr->name;
                  rsbac_net_desc.address_len
                   = netobj.sock_p->sk->protinfo.af_unix.other->protinfo.af_unix.addr->len;
                }
              else
              if(netobj.remote_addr)
                {
                  struct sockaddr_un * addr = netobj.remote_addr;

                  if(addr->sun_path)
                    {
                      rsbac_net_desc.address = addr->sun_path;
                      rsbac_net_desc.address_len = strlen(addr->sun_path);
                    }
                  else
                    {
                      rsbac_net_desc.address = NULL;
                      rsbac_net_desc.address_len = 0;
                    }
                }
              else
                {
                  rsbac_net_desc.address = NULL;
                  rsbac_net_desc.address_len = 0;
                }
              break;

            default:
              rsbac_net_desc.address = NULL;
              rsbac_net_desc.address_len = 0;
              rsbac_net_desc.port = RSBAC_NET_UNKNOWN;
          }
        if((err = rsbac_net_get_id(rsbac_net_desc, remote_temp_p)))
          {
            *remote_temp_p = 0;
            printk(KERN_WARNING
                   "rsbac_net_lookup_templates(): rsbac_net_get_id for remote returned error %u\n",
                   err);
          }
#ifdef CONFIG_RSBAC_DEBUG
        if(   rsbac_debug_ds_net
           && (rsbac_net_desc.address_family == AF_INET)
          )
          printk(KERN_DEBUG
                 "rsbac_net_lookup_templates(): user %u temp id for remote is %u\n",
                 current->uid, *remote_temp_p);
#endif
      }
    return 0;
  }

void rsbac_net_obj_cleanup(rsbac_net_obj_id_t netobj)
  {
    union rsbac_target_id_t tid;

    tid.netobj.sock_p = netobj;
    rsbac_remove_target(T_NETOBJ, tid);
  }

int rsbac_net_template(enum rsbac_net_temp_syscall_t call,
                       rsbac_net_temp_id_t id,
                       union rsbac_net_temp_syscall_data_t * data_p)
  {
    struct rsbac_net_temp_data_t int_data = RSBAC_NET_TEMP_DEFAULT_DATA;
    int err;

    switch(call)
      {
        case NTS_new_template:
        case NTS_check_id:
          break;
        case NTS_copy_template:
          err = rsbac_list_get_data(net_temp_handle, &data_p->id, &int_data);
          if(err)
            return err;
          break;
        default:
          err = rsbac_list_get_data(net_temp_handle, &id, &int_data);
          if(err)
            return err;
      }
    /* get data values from user space */
    switch(call)
      {
        case NTS_set_address:
          memcpy(&int_data.address, &data_p->address, sizeof(int_data.address));
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_set_address_family:
          int_data.address_family = data_p->address_family;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_set_valid_len:
          int_data.valid_len = data_p->valid_len;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_set_type:
          int_data.type = data_p->type;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_set_protocol:
          int_data.protocol = data_p->protocol;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_set_netdev:
          strncpy(int_data.netdev, data_p->netdev, RSBAC_IFNAMSIZ);
          int_data.netdev[RSBAC_IFNAMSIZ] = 0;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_set_min_port:
          int_data.min_port = data_p->min_port;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_set_max_port:
          int_data.max_port = data_p->max_port;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_set_name:
          strncpy(int_data.name, data_p->name, RSBAC_NET_TEMP_NAMELEN - 1);
          int_data.name[RSBAC_NET_TEMP_NAMELEN - 1] = 0;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_new_template:
          if(rsbac_list_exist(net_temp_handle, &id))
            return -RSBAC_EEXISTS;
          strncpy(int_data.name, data_p->name, RSBAC_NET_TEMP_NAMELEN - 1);
          int_data.name[RSBAC_NET_TEMP_NAMELEN - 1] = 0;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_copy_template:
          if(rsbac_list_exist(net_temp_handle, &id))
            return -RSBAC_EEXISTS;
          return rsbac_list_add(net_temp_handle, &id, &int_data);
        case NTS_delete_template:
          return rsbac_list_remove(net_temp_handle, &id);
        case NTS_check_id:
          if(rsbac_list_exist(net_temp_handle, &id))
            {
              data_p->id = id;
              return 0;
            }
          else
            return -RSBAC_ENOTFOUND;
        case NTS_get_address:
          memcpy(&data_p->address, &int_data.address, sizeof(int_data.address));
          return 0;
        case NTS_get_address_family:
          data_p->address_family = int_data.address_family;
          return 0;
        case NTS_get_valid_len:
          data_p->valid_len = int_data.valid_len;
          return 0;
        case NTS_get_type:
          data_p->type = int_data.type;
          return 0;
        case NTS_get_protocol:
          data_p->protocol = int_data.protocol;
          return 0;
        case NTS_get_netdev:
          strncpy(data_p->netdev, int_data.netdev, RSBAC_IFNAMSIZ);
          return 0;
        case NTS_get_min_port:
          data_p->min_port = int_data.min_port;
          return 0;
        case NTS_get_max_port:
          data_p->max_port = int_data.max_port;
          return 0;
        case NTS_get_name:
          strcpy(data_p->name, int_data.name);
          return 0;

        default:
          return -RSBAC_EINVALIDREQUEST;
      }
  }

int rsbac_net_list_all_template(rsbac_net_temp_id_t ** id_pp)
  {
    if(id_pp)
      return rsbac_list_get_all_desc(net_temp_handle, (void **) id_pp);
    else
      return rsbac_list_count(net_temp_handle);
  }

int rsbac_net_template_exist(rsbac_net_temp_id_t temp)
  {
    return rsbac_list_exist(net_temp_handle, &temp);
  }

int rsbac_net_remote_request(enum rsbac_adf_request_t request)
  {
    switch(request)
      {
        case R_ACCEPT:
        case R_CONNECT:
        case R_SEND:
        case R_RECEIVE:
        case R_READ:
        case R_WRITE:
          return TRUE;

        default:
          return FALSE;
      }
  }

#endif /* NET_OBJ */

/* end of rsbac_aci_data_structures.c */
