/************************************************* */
/* Rule Set Based Access Control                   */
/* Implementation of RSBAC general system calls    */
/* Author and (C) 1999-2002: Amon Ott              */
/*                                                 */
/* Last modified: 19/Mar/2002                      */
/************************************************* */

#include <rsbac/types.h>
#include <rsbac/aci.h>
#include <rsbac/pm.h>
#include <rsbac/auth.h>
#include <rsbac/acl.h>
#include <rsbac/reg.h>
#include <rsbac/error.h>
#include <rsbac/debug.h>
#include <rsbac/helpers.h>
#include <rsbac/getname.h>
#include <rsbac/network.h>
#include <asm/segment.h>
#include <asm/semaphore.h>
#include <linux/sched.h>
#include <linux/file.h>
#include <rsbac/rkmem.h>
#include <rsbac/gen_lists.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>

#include <rsbac/adf.h>
#include <rsbac/adf_main.h>
#include <rsbac/adf_syshelpers.h>
#include <rsbac/rc.h>
#include <rsbac/syscalls.h>

#ifdef CONFIG_RSBAC_NET_OBJ
#include <rsbac/network.h>
#endif
/************************************************************************** */
/*                          Global Variables                                */
/************************************************************************** */

extern struct semaphore rsbac_write_sem;

/************************************************* */
/*              Declarations                       */
/************************************************* */

/************************************************* */
/*              General functions                  */
/************************************************* */

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

int sys_rsbac_stats(void)
  {
    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_stats(): 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_DEBUG
    if (rsbac_debug_aef)
      printk(KERN_DEBUG "sys_rsbac_stats(): getting RSBAC status!\n");
#endif
    return(rsbac_stats());
  };

int sys_rsbac_check(int correct, int check_inode)
  {
    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;
    int result;

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_check(): 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_RMSG
    rsbac_printk(KERN_INFO
           "sys_rsbac_check(): triggering RSBAC consistency check, correct = %u, check_inode = %u!\n",
           correct, check_inode);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
    printk(KERN_INFO
           "sys_rsbac_check(): triggering RSBAC consistency check, correct = %u, check_inode = %u!\n",
           correct, check_inode);
#endif
    lock_kernel();
    /* rsbac write blocking */
    if(check_inode)
      down(&rsbac_write_sem);

    result = rsbac_check(correct, check_inode);
    if(!result)
      result=rsbac_check_lists(correct);
    /* call other checks */
    #if defined(CONFIG_RSBAC_AUTH)
    if(!result)
      result=rsbac_check_auth(correct, check_inode);
    #endif
    #if defined(CONFIG_RSBAC_ACL)
    if(!result)
      result=rsbac_check_acl(correct, check_inode);
    #endif
    #if defined(CONFIG_RSBAC_REG)
    if(!result)
      result=rsbac_check_reg(correct, check_inode);
    #endif
    /* release write blocking */
    if(check_inode)
      up(&rsbac_write_sem);

    unlock_kernel();
    return(result);
  };

int sys_rsbac_write(void)
  {
#if defined(CONFIG_RSBAC_AUTO_WRITE)
    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;
    int result;

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

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef)
      printk(KERN_DEBUG "sys_rsbac_write(): saving RSBAC attributes!\n");
#endif
/*    lock_kernel(); -> rsbac_write(need_lock) */
    result = rsbac_write(TRUE);
/*    unlock_kernel(); */
    return result;
#else
    return(0);
#endif /* CONFIG_RSBAC_AUTO_WRITE */
  };

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

int sys_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,
                   int inherit)
    { 
      union rsbac_target_id_t k_tid;
      union rsbac_attribute_value_t k_value;
      int   err = 0;
      boolean i_inherit;

      if(module > SW_NONE)
        return(-RSBAC_EINVALIDMODULE);
      if(!tid || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
      if(!value)
        return(-RSBAC_EINVALIDVALUE);
      if(attr >= A_none)
        return(-RSBAC_EINVALIDATTR);

      if(module == SW_NONE)
        {
          module = get_attr_module(attr);
          if(module == SW_NONE)
            return(-RSBAC_EINVALIDMODULE);
        }

      /* get values from user space */
      rsbac_get_user((u_char *) &k_tid, (u_char *) tid, sizeof(k_tid) );
      rsbac_get_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );

      if(inherit)
        i_inherit = TRUE;
      else
        i_inherit = FALSE;

#ifdef CONFIG_RSBAC_NET_OBJ
      /* sanity check before using pointer */
      if(   (target == T_NETOBJ)
         && (   !k_tid.netobj.sock_p
             || k_tid.netobj.remote_addr
             || !k_tid.netobj.sock_p->inode
             || (&k_tid.netobj.sock_p->inode->u.socket_i != k_tid.netobj.sock_p)
            )
        )
        return -RSBAC_EINVALIDTARGET;
#endif

      /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
      if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_get_attr(): calling ADF\n");
#endif
      if (!rsbac_adf_request(R_READ_ATTRIBUTE,
                             current->pid,
                             target,
                             k_tid,
                             attr,
                             k_value))
        {
          return -EPERM;
        }

      err = rsbac_get_attr(module, target, k_tid, attr, &k_value, i_inherit);
      /* put result value to user space */
      if(!err)
        {
          err = rsbac_put_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );
        }
      return (err);
    };      /* end of sys_rsbac_get_attr() */


int sys_rsbac_get_attr_n(
                   enum rsbac_switch_target_t module,
                   enum rsbac_target_t target,
                   char * t_name,
                   enum rsbac_attribute_t attr,
                   union rsbac_attribute_value_t * value,
                   int inherit)
    { 
      union rsbac_attribute_value_t k_value;
      struct dentry * t_dentry;
      int     err = 0;
      union rsbac_target_id_t  tid;
/*    struct passwd * user_description_p; */
      boolean i_inherit;
      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct nameidata nd;
      #endif

      if(module > SW_NONE)
        return(-RSBAC_EINVALIDMODULE);
      if(!t_name || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
      if(!value)
        return(-RSBAC_EINVALIDVALUE);
      if(attr >= A_none)
        return(-RSBAC_EINVALIDATTR);

      if(module == SW_NONE)
        {
          module = get_attr_module(attr);
          if(module == SW_NONE)
            return(-RSBAC_EINVALIDMODULE);
        }

      if(inherit)
        i_inherit = TRUE;
      else
        i_inherit = FALSE;

      /* get values from user space */
      rsbac_get_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );
      
      switch (target)
        {
          case T_FILE:
            /* lookup filename */
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = PTR_ERR(t_dentry);
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to lookup_dentry() returned %i\n", err);
#endif
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): file not found\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type file, symlink or block/char device? */
            if (   !(S_ISREG(t_dentry->d_inode->i_mode))
                && !(S_ISBLK(t_dentry->d_inode->i_mode))
                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no file\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* fill target id and call internal function */
            tid.file.device = t_dentry->d_inode->i_dev;
            tid.file.inode  = t_dentry->d_inode->i_ino;
            tid.file.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_get_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_READ_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
                goto out_dput;
              }
            err = rsbac_get_attr(module, target, tid, attr, &k_value, i_inherit);
            /* put result value to user space */
            if(!err)
              rsbac_put_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );
            goto out_dput;

          case T_DIR:
            /* lookup filename */
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = PTR_ERR(t_dentry);
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG
                         "sys_rsbac_get_attr(): call to lookup_dentry() returned %i\n",
                          err);
#endif
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): dir not found\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type dir? */
            if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_get_attr(): no dir\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* fill target id and call internal function */
            tid.dir.device = t_dentry->d_inode->i_dev;
            tid.dir.inode  = t_dentry->d_inode->i_ino;
            tid.dir.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_get_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_READ_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
                goto out_dput;
              }
            err = rsbac_get_attr(module, target, tid, attr, &k_value, i_inherit);
            if(!err)
              rsbac_put_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );
            goto out_dput;

          case T_FIFO:
            /* lookup filename */
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = PTR_ERR(t_dentry);
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to lookup_dentry() returned %i\n", err);
#endif
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): file not found\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type fifo? */
            if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no fifo\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* fill target id and call internal function */
            tid.fifo.device = t_dentry->d_inode->i_dev;
            tid.fifo.inode  = t_dentry->d_inode->i_ino;
            tid.fifo.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_get_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_READ_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
                goto out_dput;
              }
            err = rsbac_get_attr(module, target, tid, attr, &k_value, i_inherit);
            /* put result value to user space */
            if(!err)
              rsbac_put_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );
            goto out_dput;

          case T_SYMLINK:
            /* lookup filename */
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = PTR_ERR(t_dentry);
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to lookup_dentry() returned %i\n", err);
#endif
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): file not found\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type fifo? */
            if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no symlink\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* fill target id and call internal function */
            tid.symlink.device = t_dentry->d_inode->i_dev;
            tid.symlink.inode  = t_dentry->d_inode->i_ino;
            tid.symlink.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_get_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_READ_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
                goto out_dput;
              }
            err = rsbac_get_attr(module, target, tid, attr, &k_value, i_inherit);
            /* put result value to user space */
            if(!err)
              rsbac_put_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );
            goto out_dput;

          case T_DEV:
            /* lookup filename */
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = PTR_ERR(t_dentry);
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG
                         "sys_rsbac_get_attr_n(): call to lookup_dentry() returned %i\n",
                         err);
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_get_attr_n(): dev file not found\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type block/char device? */
            if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no dev\n");
#endif
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* fill target id and call internal function */
            if(S_ISBLK(t_dentry->d_inode->i_mode))
              tid.dev.type = D_block;
            else
              tid.dev.type = D_char;
            tid.dev.id  = t_dentry->d_inode->i_rdev;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_get_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_READ_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
                goto out_dput;
              }
            /* get value from DS, but do not inherit */
            err = rsbac_get_attr(module, target, tid, attr, &k_value, FALSE);
            /* put result value to user space */
            if(!err)
              rsbac_put_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );
            goto out_dput;

          default:
            return -RSBAC_EINVALIDTARGET;
        }
out:
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      unlock_kernel();
      #endif
      return(err);

out_dput:
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      dput(t_dentry);
      #else
      path_release(&nd);
      #endif
      goto out;
    };      /* end of sys_rsbac_get_attr_n() */

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

int sys_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)

    { 
      union rsbac_target_id_t k_tid;
      union rsbac_attribute_value_t k_value;
      int   err = 0;
      struct task_struct * task_p;
      
      if(module > SW_NONE)
        return(-RSBAC_EINVALIDMODULE);
      if(!tid || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
      if(!value)
        return(-RSBAC_EINVALIDVALUE);
      if(attr >= A_none)
        return(-RSBAC_EINVALIDATTR);

      if(module == SW_NONE)
        {
          module = get_attr_module(attr);
          if(module == SW_NONE)
            return(-RSBAC_EINVALIDMODULE);
        }
        
      /* get values from user space */
      rsbac_get_user((u_char *) &k_tid, (u_char *) tid, sizeof(k_tid) );
      rsbac_get_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );

      switch(target)
        {
          case T_PROCESS:
            read_lock(&tasklist_lock);
            task_p = find_task_by_pid(k_tid.process);
            read_unlock(&tasklist_lock);
            if(!task_p)
              return(-RSBAC_EINVALIDTARGET);
            break;

#ifdef CONFIG_RSBAC_NET_OBJ
            /* sanity check before using pointer */
          case T_NETOBJ:
            if(   !k_tid.netobj.sock_p
               || k_tid.netobj.remote_addr
               || !k_tid.netobj.sock_p->inode
               || (&k_tid.netobj.sock_p->inode->u.socket_i != k_tid.netobj.sock_p)
              )
              return -RSBAC_EINVALIDTARGET;
#endif


          default:
            break;
        }
      
      /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
      if (rsbac_debug_aef)
        printk(KERN_DEBUG
               "sys_rsbac_set_attr(): calling ADF\n");
#endif
      if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                             current->pid,
                             target,
                             k_tid,
                             attr,
                             k_value))
        {
          return -EPERM;
        }
      err = rsbac_set_attr(module, target, k_tid, attr, k_value);
      return (err);
    };      /* end of sys_rsbac_set_attr() */

int sys_rsbac_set_attr_n(
                   enum rsbac_switch_target_t module,
                   enum rsbac_target_t target,
                   char * t_name,
                   enum rsbac_attribute_t attr,
                   union rsbac_attribute_value_t * value)

    {
      struct dentry * t_dentry;
      int     err = 0;
      union rsbac_attribute_value_t k_value;
      union rsbac_target_id_t  tid;
      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct nameidata nd;
      #endif

      if(module > SW_NONE)
        return(-RSBAC_EINVALIDMODULE);
      if(!t_name || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
      if(!value)
        return(-RSBAC_EINVALIDVALUE);
      if(attr >= A_none)
        return(-RSBAC_EINVALIDATTR);
        
      if(module == SW_NONE)
        {
          module = get_attr_module(attr);
          if(module == SW_NONE)
            return(-RSBAC_EINVALIDMODULE);
        }

      /* get values from user space */
      rsbac_get_user((u_char *) &k_value, (u_char *) value, sizeof(k_value) );
      
      switch (target)
        {
          case T_FILE:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err= -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_set_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type file, symlink or block/char device? */
            if (   !(S_ISREG(t_dentry->d_inode->i_mode))
                && !(S_ISBLK(t_dentry->d_inode->i_mode))
                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.file.device = t_dentry->d_inode->i_dev;
            tid.file.inode  = t_dentry->d_inode->i_ino;
            tid.file.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_set_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_set_attr(module, target, tid, attr, k_value);
              }
            goto out_dput;

          case T_DIR:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_set_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
              { /* This is no dir */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.dir.device = t_dentry->d_inode->i_sb->s_dev;
            tid.dir.inode  = t_dentry->d_inode->i_ino;
            tid.dir.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef)
              printk(KERN_DEBUG "sys_rsbac_set_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_set_attr(module, target, tid, attr, k_value);
              }
            goto out_dput;

          case T_FIFO:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err= -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_set_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type fifo? */
            if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.fifo.device = t_dentry->d_inode->i_dev;
            tid.fifo.inode  = t_dentry->d_inode->i_ino;
            tid.fifo.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_set_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_set_attr(module, target, tid, attr, k_value);
              }
            goto out_dput;

          case T_SYMLINK:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err= -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_set_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type fifo? */
            if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.symlink.device = t_dentry->d_inode->i_dev;
            tid.symlink.inode  = t_dentry->d_inode->i_ino;
            tid.symlink.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_set_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_set_attr(module, target, tid, attr, k_value);
              }
            goto out_dput;

          case T_DEV:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_set_attr_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type file, symlink or block/char device? */
            if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* fill target id and call internal function */
            if(S_ISBLK(t_dentry->d_inode->i_mode))
              tid.dev.type = D_block;
            else
              tid.dev.type = D_char;
            tid.dev.id  = t_dentry->d_inode->i_rdev;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_set_attr_n(): calling ADF\n");
#endif
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   attr,
                                   k_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_set_attr(module, target, tid, attr, k_value);
              }
            goto out_dput;

          default:
            return -RSBAC_EINVALIDTARGET;
        }

out:
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      unlock_kernel();
      #endif
      return(err);

out_dput:
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      dput(t_dentry);
      #else
      path_release(&nd);
      #endif
      goto out;
    };      /* end of sys_rsbac_set_attr_n() */

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

int sys_rsbac_remove_target(
        enum rsbac_target_t target,
        union rsbac_target_id_t * tid)
    { 
      union rsbac_target_id_t k_tid;
      int   err = 0;

      /* for adf_request */
      union rsbac_attribute_value_t rsbac_attribute_value;
      
      if(!tid || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
        
      /* get values from user space */
      rsbac_get_user((u_char *) &k_tid, (u_char *) tid, sizeof(k_tid) );

      /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
      if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_remove_target(): calling ADF\n");
#endif
      rsbac_attribute_value.dummy = 0;
      if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                             current->pid,
                             target,
                             k_tid,
                             A_none,
                             rsbac_attribute_value))
        {
          return -EPERM;
        }
      err = rsbac_remove_target(target, k_tid);
      return (err);
    };      /* end of sys_rsbac_remove_target() */

int sys_rsbac_remove_target_n(enum rsbac_target_t target,
                            char * t_name)
    { 
      struct dentry * t_dentry;
      int     err = 0;
      union rsbac_target_id_t  tid;

      /* for adf_request */
      union rsbac_attribute_value_t rsbac_attribute_value;

/*    struct passwd * user_description_p; */
      
      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct nameidata nd;
      #endif

      if(!t_name || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
        
      switch (target)
        {
          case T_FILE:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_remove_target_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type file, symlink or block/char device? */
            if (   !(S_ISREG(t_dentry->d_inode->i_mode))
                && !(S_ISBLK(t_dentry->d_inode->i_mode))
                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.file.device = t_dentry->d_inode->i_sb->s_dev;
            tid.file.inode  = t_dentry->d_inode->i_ino;
            tid.file.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_remove_target_n(): calling ADF\n");
#endif
            rsbac_attribute_value.dummy = 0;
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   A_none,
                                   rsbac_attribute_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_remove_target(target, tid);
              }
            goto out_dput;

          case T_DIR:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_remove_target_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
              { /* This is no file */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.dir.device = t_dentry->d_inode->i_sb->s_dev;
            tid.dir.inode  = t_dentry->d_inode->i_ino;
            tid.dir.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_remove_target_n(): calling ADF\n");
#endif
            rsbac_attribute_value.dummy = 0;
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   A_none,
                                   rsbac_attribute_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_remove_target(target, tid);
              }
            goto out_dput;

          case T_FIFO:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_remove_target_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type fifo? */
            if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.fifo.device = t_dentry->d_inode->i_sb->s_dev;
            tid.fifo.inode  = t_dentry->d_inode->i_ino;
            tid.fifo.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_remove_target_n(): calling ADF\n");
#endif
            rsbac_attribute_value.dummy = 0;
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   A_none,
                                   rsbac_attribute_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_remove_target(target, tid);
              }
            goto out_dput;

          case T_SYMLINK:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_remove_target_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type symlink? */
            if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.symlink.device = t_dentry->d_inode->i_sb->s_dev;
            tid.symlink.inode  = t_dentry->d_inode->i_ino;
            tid.symlink.dentry_p = t_dentry;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_remove_target_n(): calling ADF\n");
#endif
            rsbac_attribute_value.dummy = 0;
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   A_none,
                                   rsbac_attribute_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_remove_target(target, tid);
              }
            goto out_dput;

          case T_DEV:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef)
                  printk(KERN_DEBUG "sys_rsbac_remove_target_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type file, symlink or block/char device? */
            if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
              { /* This is no dev */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* fill target id and call internal function */
            if(S_ISBLK(t_dentry->d_inode->i_mode))
              tid.dev.type = D_block;
            else
              tid.dev.type = D_char;
            tid.dev.id  = t_dentry->d_inode->i_rdev;
            /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
            if (rsbac_debug_aef)
              printk(KERN_DEBUG "sys_rsbac_remove_target_n(): calling ADF\n");
#endif
            rsbac_attribute_value.dummy = 0;
            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                                   current->pid,
                                   target,
                                   tid,
                                   A_none,
                                   rsbac_attribute_value))
              {
                err = -EPERM;
              }
            else
              {
                err = rsbac_remove_target(target, tid);
              }
            goto out_dput;

          default:
            return -RSBAC_EINVALIDTARGET;
        }
out:
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      unlock_kernel();
      #endif
      return(err);

out_dput:
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      dput(t_dentry);
      #else
      path_release(&nd);
      #endif
      goto out;
    };      /* end of sys_rsbac_remove_target_n() */

int sys_rsbac_net_list_all_netdev(rsbac_netdev_id_t * id_p, u_long maxnum)
  {
#ifdef CONFIG_RSBAC_NET_DEV
    int err=0;
    long count;

    if(id_p && maxnum)
      {
        rsbac_netdev_id_t * k_id_p = NULL;

        count = rsbac_net_list_all_netdev(&k_id_p);
        if(count <= 0)
          return count;
        if(count > maxnum)
          count = maxnum;

        err = rsbac_put_user((u_char *) k_id_p, (u_char *) id_p, count * sizeof(*k_id_p) );

        vfree(k_id_p);

        if(err)
          return err;
        else
          return count;
      }
    else
      return rsbac_net_list_all_netdev(NULL);

#else
    return -RSBAC_EINVALIDREQUEST;
#endif /* CONFIG_RSBAC_NET_DEV */
  }

int sys_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)
  {
#ifdef CONFIG_RSBAC_NET_OBJ
    union rsbac_net_temp_syscall_data_t k_data;
    int err = 0;
    /* for adf_request */
#ifndef CONFIG_RSBAC_MAINT
    union rsbac_target_id_t  i_tid;
    union rsbac_attribute_value_t i_attr_val;
#endif

    if(!id)
      return -RSBAC_EINVALIDVALUE;
    if(!data_p)
      return -RSBAC_EINVALIDPOINTER;

    /* get data values from user space */
    switch(call)
      {
        case NTS_set_address:
        case NTS_set_address_family:
        case NTS_set_valid_len:
        case NTS_set_type:
        case NTS_set_protocol:
        case NTS_set_netdev:
        case NTS_set_min_port:
        case NTS_set_max_port:
        case NTS_set_name:
        case NTS_new_template:
        case NTS_copy_template:
          err = rsbac_get_user((u_char *) &k_data, (u_char *) data_p, sizeof(k_data) );
          if(err)
            return err;
          break;
        case NTS_delete_template:
        case NTS_check_id:
        case NTS_get_address:
        case NTS_get_address_family:
        case NTS_get_valid_len:
        case NTS_get_type:
        case NTS_get_protocol:
        case NTS_get_netdev:
        case NTS_get_min_port:
        case NTS_get_max_port:
        case NTS_get_name:
          break;

        default:
          return -RSBAC_EINVALIDREQUEST;
      }

#ifndef CONFIG_RSBAC_MAINT
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef)
      printk(KERN_DEBUG "sys_rsbac_net_temp(): calling ADF\n");
#endif
    i_tid.nettemp = id;
    i_attr_val.dummy = 0;
    switch(call)
      {
        case NTS_new_template:
          if (!rsbac_adf_request(R_CREATE,
                                 current->pid,
                                 T_NETTEMP,
                                 i_tid,
                                 A_none,
                                 i_attr_val))
            #ifdef CONFIG_RSBAC_SOFTMODE
            if(!rsbac_softmode)
            #endif
              return -EPERM;
          break;

        case NTS_copy_template:
          if(!rsbac_net_template_exist(id))
            {
              if(!rsbac_adf_request(R_CREATE,
                                    current->pid,
                                    T_NETTEMP,
                                    i_tid,
                                    A_none,
                                    i_attr_val))
                #ifdef CONFIG_RSBAC_SOFTMODE
                if(!rsbac_softmode)
                #endif
                  return -EPERM;
            }
          else
            {
              if(!rsbac_adf_request(R_WRITE,
                                    current->pid,
                                    T_NETTEMP,
                                    i_tid,
                                    A_none,
                                    i_attr_val))
                #ifdef CONFIG_RSBAC_SOFTMODE
                if(!rsbac_softmode)
                #endif
                  return -EPERM;
            }
          i_tid.nettemp = k_data.id;
          if (!rsbac_adf_request(R_READ,
                                 current->pid,
                                 T_NETTEMP,
                                 i_tid,
                                 A_none,
                                 i_attr_val))
            #ifdef CONFIG_RSBAC_SOFTMODE
            if(!rsbac_softmode)
            #endif
              return -EPERM;
          break;

        case NTS_delete_template:
          if (!rsbac_adf_request(R_DELETE,
                                 current->pid,
                                 T_NETTEMP,
                                 i_tid,
                                 A_none,
                                 i_attr_val))
            #ifdef CONFIG_RSBAC_SOFTMODE
            if(!rsbac_softmode)
            #endif
              return -EPERM;
          break;

        case NTS_get_address:
        case NTS_get_address_family:
        case NTS_get_valid_len:
        case NTS_get_type:
        case NTS_get_protocol:
        case NTS_get_netdev:
        case NTS_get_min_port:
        case NTS_get_max_port:
          if (!rsbac_adf_request(R_READ,
                                 current->pid,
                                 T_NETTEMP,
                                 i_tid,
                                 A_none,
                                 i_attr_val))
            #ifdef CONFIG_RSBAC_SOFTMODE
            if(!rsbac_softmode)
            #endif
              return -EPERM;
          break;

        case NTS_set_address:
        case NTS_set_address_family:
        case NTS_set_valid_len:
        case NTS_set_type:
        case NTS_set_protocol:
        case NTS_set_netdev:
        case NTS_set_min_port:
        case NTS_set_max_port:
        case NTS_set_name:
          if (!rsbac_adf_request(R_WRITE,
                                 current->pid,
                                 T_NETTEMP,
                                 i_tid,
                                 A_none,
                                 i_attr_val))
            #ifdef CONFIG_RSBAC_SOFTMODE
            if(!rsbac_softmode)
            #endif
              return -EPERM;
          break;

        default:
          break;
      }
#endif /* !MAINT */

    err = rsbac_net_template(call, id, &k_data);
    if(!err)
      {
        /* put data values to user space */
        switch(call)
          {
            case NTS_check_id:
            case NTS_get_address:
            case NTS_get_address_family:
            case NTS_get_valid_len:
            case NTS_get_type:
            case NTS_get_protocol:
            case NTS_get_netdev:
            case NTS_get_min_port:
            case NTS_get_max_port:
            case NTS_get_name:
              err = rsbac_put_user((u_char *) &k_data, (u_char *) data_p, sizeof(k_data) );
              break;

            default:
          }
      }
    return err;

#else
    return -RSBAC_EINVALIDREQUEST;
#endif /* NET_OBJ */
  }

int sys_rsbac_net_list_all_template(rsbac_net_temp_id_t * id_p, u_long maxnum)
  {
#ifdef CONFIG_RSBAC_NET_OBJ
    int err=0;
    int count;
    union rsbac_target_id_t i_tid;
    union rsbac_attribute_value_t i_attr_val;

    i_tid.nettemp = 0;
    i_attr_val.dummy = 0;
    if (!rsbac_adf_request(R_READ,
                           current->pid,
                           T_NETTEMP,
                           i_tid,
                           A_none,
                           i_attr_val))
      return -EPERM;
    if(id_p && maxnum)
      {
        rsbac_net_temp_id_t * k_id_p = NULL;

        count = rsbac_net_list_all_template(&k_id_p);
        if(count <= 0)
          return count;
        if(count > maxnum)
          count = maxnum;

        err = rsbac_put_user((u_char *) k_id_p, (u_char *) id_p, count * sizeof(*k_id_p) );

        vfree(k_id_p);

        if(err)
          return err;
        else
          return count;
      }
    else
      return rsbac_net_list_all_template(NULL);

#else
    return -RSBAC_EINVALIDREQUEST;
#endif /* CONFIG_RSBAC_NET_OBJ */
  }


/************************************************* */
/*                 ADF functions                   */
/************************************************* */

int sys_rsbac_switch(enum rsbac_switch_target_t target, int value)
  {
#ifdef CONFIG_RSBAC_SWITCH
    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;
    char                         * switch_name;
  
    /* call ADF */
    if(target >= SW_NONE)
      return(-RSBAC_EINVALIDTARGET);
    if ((value != 0) && (value != 1))
      return (-RSBAC_EINVALIDVALUE);
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef)
      printk(KERN_DEBUG "sys_rsbac_switch(): calling ADF\n");
#endif
    rsbac_target_id.dummy = 0;
#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
    if(target == DAC_DISABLE)
      {
        rsbac_attribute_value.dummy = 0;
        if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
                               current->pid,
                               T_NONE,
                               rsbac_target_id,
                               A_none,
                               rsbac_attribute_value))
          {
            return -EPERM;
          }
      }
    else
#endif
      {
        rsbac_attribute_value.switch_target = target;
        if (!rsbac_adf_request(R_SWITCH_MODULE,
                               current->pid,
                               T_NONE,
                               rsbac_target_id,
                               A_switch_target,
                               rsbac_attribute_value))
          {
            return -EPERM;
          }
      }
    switch_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
    if(switch_name)
      {
        get_switch_target_name(switch_name,target);
#ifdef CONFIG_RSBAC_RMSG
        rsbac_printk(KERN_WARNING
               "sys_rsbac_switch(): switching RSBAC module %s to %i!\n",
               switch_name, value);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
        printk(KERN_WARNING
               "sys_rsbac_switch(): switching RSBAC module %s to %i!\n",
               switch_name, value);
#endif
        rsbac_kfree(switch_name);
      }

    switch (target)
      {
#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
        case DAC_DISABLE: rsbac_dac_disable = value;
                  break;
#endif
#ifdef CONFIG_RSBAC_SOFTMODE
        case SOFTMODE: rsbac_softmode = value;
                  break;
#endif
#ifdef CONFIG_RSBAC_MAC
        case MAC: rsbac_switch_mac = value;
                  break;
#endif
#ifdef CONFIG_RSBAC_FC
        case FC:  rsbac_switch_fc = value;
                  break;
#endif
#ifdef CONFIG_RSBAC_SIM
        case SIM: rsbac_switch_sim = value;
                  break;
#endif
#ifdef CONFIG_RSBAC_PM
        case PM:  rsbac_switch_pm = value;
                  break;
#endif
#ifdef CONFIG_RSBAC_MS
        case MS:  rsbac_switch_ms = value;
                  break;
#endif
#ifdef CONFIG_RSBAC_FF
        case FF:  rsbac_switch_ff = value;
                  break;
#endif
#if defined(CONFIG_RSBAC_RC)
        case RC:  rsbac_switch_rc = value;
                  break;
#endif
#if defined(CONFIG_RSBAC_AUTH)
        case AUTH: rsbac_switch_auth = value;
                  break;
#endif
#if defined(CONFIG_RSBAC_ACL)
        case ACL: rsbac_switch_acl = value;
                  break;
#endif
#if defined(CONFIG_RSBAC_CAP)
        case CAP: rsbac_switch_cap = value;
                  break;
#endif
        default:
          return (-RSBAC_EINVALIDMODULE);
      }
#endif /* SWITCH */
    return(0); 
  };

/************** MAC ***************/

int sys_rsbac_mac_set_curr_seclevel(rsbac_security_level_t level)
  {
#ifdef CONFIG_RSBAC_MAC
    if(level > SL_max)
      return(-RSBAC_EINVALIDVALUE);
    return (rsbac_mac_set_curr_seclevel(level));
#else
    return (-RSBAC_EINVALIDMODULE);
#endif
  };

rsbac_security_level_t sys_rsbac_mac_get_curr_seclevel(void)
  {
#ifdef CONFIG_RSBAC_MAC
    return (rsbac_mac_get_curr_seclevel());
#else
    return(SL_unclassified); 
#endif
  };

int sys_rsbac_mac_set_max_seclevel(rsbac_security_level_t level)
  {
#ifdef CONFIG_RSBAC_MAC
    if(level > SL_max)
      return(-RSBAC_EINVALIDVALUE);
    return (rsbac_mac_set_max_seclevel(level));
#else
    return (-RSBAC_EINVALIDMODULE);
#endif
  };

rsbac_security_level_t sys_rsbac_mac_get_max_seclevel(void)
  {
#ifdef CONFIG_RSBAC_MAC
    return (rsbac_mac_get_max_seclevel());
#else
    return(SL_unclassified); 
#endif
  };

int sys_rsbac_mac_set_curr_categories(rsbac_mac_category_vector_t * categories_p)
  {
#ifdef CONFIG_RSBAC_MAC
    rsbac_mac_category_vector_t k_categories;
    int err;

    err = rsbac_get_user((u_char *) &k_categories, (u_char *) categories_p, sizeof(k_categories) );
    if(err)
      return err;
    else
      return (rsbac_mac_set_curr_categories(k_categories));
#else
    return (-RSBAC_EINVALIDMODULE);
#endif
  };

int sys_rsbac_mac_get_curr_categories(rsbac_mac_category_vector_t * categories_p)
  {
#ifdef CONFIG_RSBAC_MAC
    int err;
    rsbac_mac_category_vector_t k_categories;

    err = rsbac_mac_get_curr_categories(&k_categories);
    /* put result value to user space */
    if(!err)
      {
        err = rsbac_put_user((u_char *) &k_categories,
                             (u_char *) categories_p,
                             sizeof(k_categories) );
      }
    return (err);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif
  };

int sys_rsbac_mac_set_max_categories(rsbac_mac_category_vector_t * categories_p)
  {
#ifdef CONFIG_RSBAC_MAC
    rsbac_mac_category_vector_t k_categories;
    int err;

    err = rsbac_get_user((u_char *) &k_categories, (u_char *) categories_p, sizeof(k_categories) );
    if(err)
      return err;
    else
      return (rsbac_mac_set_max_categories(k_categories));
#else
    return (-RSBAC_EINVALIDMODULE);
#endif
  };

int sys_rsbac_mac_get_max_categories(rsbac_mac_category_vector_t * categories_p)
  {
#ifdef CONFIG_RSBAC_MAC
    int err;
    rsbac_mac_category_vector_t k_categories;

    err = rsbac_mac_get_max_categories(&k_categories);
    /* put result value to user space */
    if(!err)
      {
        err = rsbac_put_user((u_char *) &k_categories,
                             (u_char *) categories_p,
                             sizeof(k_categories) );
      }
    return (err);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif
  };

/************** PM ***************/

int sys_rsbac_stats_pm(void)
  {
#ifndef CONFIG_RSBAC_PM
    return (0);
#else
    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;

#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_stats_pm(): 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_DEBUG
    if (rsbac_debug_aef_pm)
      printk(KERN_DEBUG "sys_rsbac_stats_pm(): getting RSBAC status!\n");
#endif
    return(rsbac_stats_pm());
#endif
  };

int sys_rsbac_pm(enum  rsbac_pm_function_type_t    function,
                            union rsbac_pm_function_param_t * param_p,
                                  rsbac_pm_tkt_id_t           ticket)
  {
#ifndef CONFIG_RSBAC_PM
    return (-RSBAC_EINVALIDMODULE);
#else
    union  rsbac_pm_function_param_t k_param;
    int result;
    
    if(function >= PF_none)
      return(-RSBAC_EINVALIDREQUEST);
    if(!param_p)
      return(-RSBAC_EINVALIDPOINTER);
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef_pm)
      printk(KERN_DEBUG "sys_rsbac_pm(): called for function %i!\n",
             function);
#endif
    /* get parameters from user space */
    rsbac_get_user((u_char *) &k_param, (u_char *) param_p, sizeof(k_param) );
    /* call pm function and return its result */
    lock_kernel();
    result = rsbac_pm(function, k_param, ticket);
    unlock_kernel();
    return result;
#endif    
  }

int sys_rsbac_pm_change_current_task(rsbac_pm_task_id_t task)
  {
#ifndef CONFIG_RSBAC_PM
    return (0);
#else
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef_pm)
      printk(KERN_DEBUG
             "sys_rsbac_pm_change_current_task(): called for task %i!\n",
             task);
#endif
    /* call pm function and return its result */
    return(rsbac_pm_change_current_task(task));
#endif    
  }

int sys_rsbac_pm_create_file(const char * filename,
                                        int mode,
                                        rsbac_pm_object_class_id_t class)
  {
#ifndef CONFIG_RSBAC_PM
    return (-RSBAC_EINVALIDMODULE);
#else
    if(!filename)
      return(-RSBAC_EINVALIDPOINTER);
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef_pm)
      printk(KERN_DEBUG
             "sys_rsbac_pm_create_file(): called with class %i!\n",
             class);
#endif
    /* call pm function and return its result */
    return(rsbac_pm_create_file(filename, mode, class));
#endif    
  }

/************** MS ***************/

int sys_rsbac_ms_get_copied(int fd)
  {
#ifndef CONFIG_RSBAC_MS
    return (-RSBAC_EINVALIDMODULE);
#else
    union rsbac_target_id_t       i_tid;
    union rsbac_attribute_value_t i_attr_val1;
    struct socket * sock_p;
    struct file * file_p;

    if(   !current->files
       || !((file_p = fcheck(fd)))
       || !file_p->f_dentry
       || !file_p->f_dentry->d_inode
       || !S_ISSOCK(file_p->f_dentry->d_inode->i_mode)
       || !((sock_p = &file_p->f_dentry->d_inode->u.socket_i))
      )
      return(-RSBAC_EINVALIDTARGET);

    /* get ms_scanned for sock */
    i_tid.netobj.sock_p = sock_p;
    i_tid.netobj.remote_addr = NULL;
    i_tid.netobj.remote_len = 0;
    if (rsbac_get_attr(MS,
                       T_NETOBJ,
                       i_tid,
                       A_ms_scanned,
                       &i_attr_val1,
                       FALSE))
      {
        printk(KERN_WARNING
               "sys_rsbac_ms_get_copied(): rsbac_get_attr() returned error!\n");
        return (-RSBAC_EREADFAILED);
      }
    /* only return value, if previously active rejected */
    if(i_attr_val1.ms_scanned != MS_active_rejected)
      return (-RSBAC_EINVALIDTARGET);

    /* OK, process may get copied value -> get it */
    if (rsbac_get_attr(MS,
                       T_IPC,
                       i_tid,
                       A_ms_buflen,
                       &i_attr_val1,
                       FALSE))
      {
        printk(KERN_WARNING
               "sys_rsbac_ms_get_copied(): rsbac_get_attr() returned error!\n");
        return (-RSBAC_EREADFAILED);
      }
    return(i_attr_val1.ms_buflen);
#endif
  };

/************** RC ***************/

int sys_rsbac_rc_copy_role (rsbac_rc_role_id_t from_role,
                                       rsbac_rc_role_id_t to_role)
  {
#if defined(CONFIG_RSBAC_RC)
    if(   (from_role > RC_role_max_value)
       || (from_role > RC_role_max_value))
      return(-RSBAC_EINVALIDVALUE);
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef_rc)
      printk(KERN_DEBUG
             "sys_rsbac_rc_copy_role(): from %i, to %i!\n",
             from_role, to_role);
#endif
    /* call rc function and return its result */
    return(rsbac_rc_sys_copy_role(from_role, to_role));
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

/* Getting values */
int sys_rsbac_rc_get_item (enum  rsbac_rc_target_t       target,
                                      union rsbac_rc_target_id_t  * tid_p,
                                      union rsbac_rc_target_id_t  * subtid_p,
                                      enum  rsbac_rc_item_t         item,
                                      union rsbac_rc_item_value_t * value_p,
                                            rsbac_time_t          * ttl_p)
  {
#if defined(CONFIG_RSBAC_RC)
    union rsbac_rc_target_id_t  k_tid;
    union rsbac_rc_target_id_t  k_subtid;
    union rsbac_rc_item_value_t k_value;
          rsbac_time_t          k_ttl;
    int err = 0;

    if(   (target >= RT_NONE)
       || (item >= RI_none))
      return(-RSBAC_EINVALIDVALUE);
    /* get values from user space */
    rsbac_get_user((u_char *) &k_tid, (u_char *) tid_p, sizeof(k_tid) );
    rsbac_get_user((u_char *) &k_subtid, (u_char *) subtid_p, sizeof(k_subtid) );
    rsbac_get_user((u_char *) &k_value, (u_char *) value_p, sizeof(k_value) );
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef_rc)
      printk(KERN_DEBUG
             "sys_rsbac_rc_get_item(): target %i, item %i!\n",
             target, item);
#endif
    /* call rc function and return its result */
    err = rsbac_rc_sys_get_item(target, k_tid, k_subtid, item, &k_value, &k_ttl);
    /* put result value to user space */
    if(!err)
      {
        err = rsbac_put_user((u_char *) &k_value, (u_char *) value_p, sizeof(k_value) );
        if(!err && ttl_p)
          err = rsbac_put_user((u_char *) &k_ttl, (u_char *) ttl_p, sizeof(k_ttl) );
      }
    return (err);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

/* Setting values */
int sys_rsbac_rc_set_item (enum  rsbac_rc_target_t       target,
                                      union rsbac_rc_target_id_t  * tid_p,
                                      union rsbac_rc_target_id_t  * subtid_p,
                                      enum  rsbac_rc_item_t         item,
                                      union rsbac_rc_item_value_t * value_p,
                                            rsbac_time_t            ttl)
  {
#if defined(CONFIG_RSBAC_RC)
    union rsbac_rc_target_id_t  k_tid;
    union rsbac_rc_target_id_t  k_subtid;
    union rsbac_rc_item_value_t k_value;

    if(   (target >= RT_NONE)
       || (item >= RI_none))
      return(-RSBAC_EINVALIDVALUE);
    /* get values from user space */
    rsbac_get_user((u_char *) &k_tid, (u_char *) tid_p, sizeof(k_tid) );
    rsbac_get_user((u_char *) &k_subtid, (u_char *) subtid_p, sizeof(k_subtid) );
    rsbac_get_user((u_char *) &k_value, (u_char *) value_p, sizeof(k_value) );
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef_rc)
      printk(KERN_DEBUG
             "sys_rsbac_rc_set_item(): target %i, item %i!\n",
             target, item);
#endif
    /* call rc function and return its result */
    return rsbac_rc_sys_set_item(target, k_tid, k_subtid, item, k_value, ttl);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

int sys_rsbac_rc_get_list(enum  rsbac_rc_target_t       target,
                                     union rsbac_rc_target_id_t  * tid_p,
                                     enum  rsbac_rc_item_t         item,
                                     u_int maxnum,
                                     __u32  * array_p,
                                     rsbac_time_t * ttl_array_p)

  {
#if defined(CONFIG_RSBAC_RC)
    union rsbac_rc_target_id_t  k_tid;
    int err;

    rsbac_get_user((u_char *) &k_tid, (u_char *) tid_p, sizeof(k_tid) );
    if(array_p)
      {
        __u32 * k_array_p;
        rsbac_time_t * k_ttl_array_p;

        if(!maxnum)
          return -RSBAC_EINVALIDVALUE;
        /* call rc function and return its result */
        err = rsbac_rc_get_list(target, k_tid, item, &k_array_p, &k_ttl_array_p);
        /* put result value to user space */
        if(err > 0)
          {
            int tmperr;

            if(err > maxnum)
              err = maxnum;
            tmperr = rsbac_put_user((u_char *) k_array_p, (u_char *) array_p, err * sizeof(*k_array_p) );
            if(tmperr)
              err=tmperr;
            vfree(k_array_p);
            if(k_ttl_array_p && ttl_array_p)
              {
                tmperr = rsbac_put_user((u_char *) k_ttl_array_p, (u_char *) ttl_array_p, err * sizeof(*k_ttl_array_p) );
                if(tmperr)
                  err=tmperr;
              }
            vfree(k_ttl_array_p);
          }
        return (err);
      }
    else
      return rsbac_rc_get_list(target, k_tid, item, NULL, NULL);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

/* Set own role */
int sys_rsbac_rc_change_role (rsbac_rc_role_id_t role)
  {
#if defined(CONFIG_RSBAC_RC)
    if(role > RC_role_max_value)
      return(-RSBAC_EINVALIDVALUE);
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef_rc)
      printk(KERN_DEBUG
             "sys_rsbac_rc_change_role(): role %i!\n",
             role);
#endif
    /* call rc function and return its result */
    return rsbac_rc_sys_change_role(role);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

/* Getting own effective rights */
int sys_rsbac_rc_get_eff_rights_n(enum  rsbac_target_t   target,
                                                   char           * t_name,
                                                   rsbac_rc_request_vector_t * request_vector_p,
                                                   rsbac_time_t          * ttl_p)
  {
#if defined(CONFIG_RSBAC_RC)
      struct dentry * t_dentry;
      int     err = 0;
      rsbac_rc_request_vector_t k_req_vec;
      rsbac_time_t          k_ttl;
      union rsbac_target_id_t  tid;

      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct nameidata nd;
      #endif

      if(!t_name || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
        
      switch (target)
        {
          case T_FILE:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef_rc)
                  printk(KERN_DEBUG "sys_rsbac_rc_get_eff_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type file, symlink or block/char device? */
            if (   !(S_ISREG(t_dentry->d_inode->i_mode))
                && !(S_ISBLK(t_dentry->d_inode->i_mode))
                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.file.device = t_dentry->d_inode->i_sb->s_dev;
            tid.file.inode  = t_dentry->d_inode->i_ino;
            tid.file.dentry_p = t_dentry;
            err = rsbac_rc_sys_get_eff_rights(T_FILE, tid, &k_req_vec, &k_ttl);
            /* put result value to user space */
            if(!err)
              {
                err = rsbac_put_user((u_char *) &k_req_vec, (u_char *) request_vector_p, sizeof(k_req_vec) );
                if(!err && ttl_p)
                  err = rsbac_put_user((u_char *) &k_ttl, (u_char *) ttl_p, sizeof(k_ttl) );
              }
            goto out_dput;

          case T_DIR:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef_rc)
                  printk(KERN_DEBUG "sys_rsbac_rc_get_eff_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
              { /* This is no file */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.dir.device = t_dentry->d_inode->i_sb->s_dev;
            tid.dir.inode  = t_dentry->d_inode->i_ino;
            tid.dir.dentry_p = t_dentry;
            err = rsbac_rc_sys_get_eff_rights(T_DIR, tid, &k_req_vec, &k_ttl);
            /* put result value to user space */
            if(!err)
              {
                err = rsbac_put_user((u_char *) &k_req_vec, (u_char *) request_vector_p, sizeof(k_req_vec) );
                if(!err && ttl_p)
                  err = rsbac_put_user((u_char *) &k_ttl, (u_char *) ttl_p, sizeof(k_ttl) );
              }
            goto out_dput;

          case T_FIFO:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef_rc)
                  printk(KERN_DEBUG "sys_rsbac_rc_get_eff_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type fifo? */
            if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.fifo.device = t_dentry->d_inode->i_sb->s_dev;
            tid.fifo.inode  = t_dentry->d_inode->i_ino;
            tid.fifo.dentry_p = t_dentry;
            err = rsbac_rc_sys_get_eff_rights(T_FILE, tid, &k_req_vec, &k_ttl);
            /* put result value to user space */
            if(!err)
              {
                err = rsbac_put_user((u_char *) &k_req_vec, (u_char *) request_vector_p, sizeof(k_req_vec) );
                if(!err && ttl_p)
                  err = rsbac_put_user((u_char *) &k_ttl, (u_char *) ttl_p, sizeof(k_ttl) );
              }
            goto out_dput;

          case T_SYMLINK:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef_rc)
                  printk(KERN_DEBUG "sys_rsbac_rc_get_eff_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type fifo? */
            if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
              { /* This is no file or device */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            tid.symlink.device = t_dentry->d_inode->i_sb->s_dev;
            tid.symlink.inode  = t_dentry->d_inode->i_ino;
            tid.symlink.dentry_p = t_dentry;
            err = rsbac_rc_sys_get_eff_rights(T_FILE, tid, &k_req_vec, &k_ttl);
            /* put result value to user space */
            if(!err)
              {
                err = rsbac_put_user((u_char *) &k_req_vec, (u_char *) request_vector_p, sizeof(k_req_vec) );
                if(!err && ttl_p)
                  err = rsbac_put_user((u_char *) &k_ttl, (u_char *) ttl_p, sizeof(k_ttl) );
              }
            goto out_dput;

          case T_DEV:
            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
            lock_kernel();
            t_dentry = lookup_dentry(t_name,NULL,0);
            if (IS_ERR(t_dentry))
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out;
              }
            #else
            if ((err = user_path_walk_link(t_name, &nd)))
              {
#ifdef CONFIG_RSBAC_DEBUG
                if (rsbac_debug_aef_rc)
                  printk(KERN_DEBUG "sys_rsbac_rc_get_eff_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                goto out;
              }
            t_dentry = nd.dentry;
            #endif
            if (!t_dentry->d_inode)
              {
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* is inode of type file, symlink or block/char device? */
            if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
              { /* This is no dev */
                err = -RSBAC_EINVALIDTARGET;
                goto out_dput;
              }
            /* fill target id and call internal function */
            if(S_ISBLK(t_dentry->d_inode->i_mode))
              tid.dev.type = D_block;
            else
              tid.dev.type = D_char;
            tid.dev.id  = t_dentry->d_inode->i_rdev;
            err = rsbac_rc_sys_get_eff_rights(T_DEV, tid, &k_req_vec, &k_ttl);
            /* put result value to user space */
            if(!err)
              {
                err = rsbac_put_user((u_char *) &k_req_vec, (u_char *) request_vector_p, sizeof(k_req_vec) );
                if(!err && ttl_p)
                  err = rsbac_put_user((u_char *) &k_ttl, (u_char *) ttl_p, sizeof(k_ttl) );
              }
            goto out_dput;

          default:
            return -RSBAC_EINVALIDTARGET;
        }
  out:
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      unlock_kernel();
      #endif
      return(err);

  out_dput:
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
      dput(t_dentry);
      #else
      path_release(&nd);
      #endif
      goto out;
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

/************** AUTH ***************/

/* Provide means for adding and removing of capabilities */
int sys_rsbac_auth_add_p_cap(rsbac_pid_t pid,
                                        rsbac_uid_t first_uid,
                                        rsbac_uid_t last_uid)
  {
#if defined(CONFIG_RSBAC_AUTH)
    struct task_struct * task_p;

    read_lock(&tasklist_lock);
    task_p = find_task_by_pid(pid);
    read_unlock(&tasklist_lock);
    if(!task_p)
      return(-RSBAC_EINVALIDTARGET);
    if(first_uid > last_uid)
      return(-RSBAC_EINVALIDVALUE);

    /* call auth function and return its result */
    /* permission checking is done there */
    return(rsbac_auth_add_p_cap(pid, first_uid, last_uid));
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

int sys_rsbac_auth_remove_p_cap(rsbac_pid_t pid,
                                           rsbac_uid_t first_uid,
                                           rsbac_uid_t last_uid)
  {
#if defined(CONFIG_RSBAC_AUTH)
    struct task_struct * task_p;

    if(first_uid > last_uid)
      return(-RSBAC_EINVALIDVALUE);

    read_lock(&tasklist_lock);
    task_p = find_task_by_pid(pid);
    read_unlock(&tasklist_lock);
    if(!task_p)
      return(-RSBAC_EINVALIDTARGET);
    /* call auth function and return its result */
    /* permission checking is done there */
    return(rsbac_auth_remove_p_cap(pid, first_uid, last_uid));
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

int sys_rsbac_auth_add_f_cap(char * filename,
                                        rsbac_uid_t first_uid,
                                        rsbac_uid_t last_uid)
  {
#if defined(CONFIG_RSBAC_AUTH)
    struct dentry * t_dentry;
    int     err = 0;
    union rsbac_target_id_t  tid;

    /* for adf_request */
#if defined(CONFIG_RSBAC_AUTH) && !defined(CONFIG_RSBAC_MAINT)
    union rsbac_attribute_value_t rsbac_attribute_value;
#endif

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
    struct nameidata nd;
    #endif

    if(!filename)
      return(-RSBAC_EINVALIDTARGET);
    if(first_uid > last_uid)
      return(-RSBAC_EINVALIDVALUE);

    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    lock_kernel();
    t_dentry = lookup_dentry(filename,NULL,0);
    if (IS_ERR(t_dentry))
      {
        err = -RSBAC_EINVALIDTARGET;
        goto out;
      }
    #else
    if ((err = user_path_walk_link(filename, &nd)))
      {
#ifdef CONFIG_RSBAC_DEBUG
        if (rsbac_debug_aef_auth)
          printk(KERN_DEBUG "sys_rsbac_auth_add_f_cap(): call to user_path_walk_link() returned %i\n", err);
#endif
        goto out;
      }
    t_dentry = nd.dentry;
    #endif
    if (!t_dentry->d_inode)
      {
        err = -RSBAC_EINVALIDTARGET;
        goto out_dput;
      }
    /* is inode of type file? */
    if (!S_ISREG(t_dentry->d_inode->i_mode))
      { /* This is no file */
        err = -RSBAC_EINVALIDTARGET;
        goto out_dput;
      }
    tid.file.device = t_dentry->d_inode->i_sb->s_dev;
    tid.file.inode  = t_dentry->d_inode->i_ino;
    tid.file.dentry_p = t_dentry;
#if defined(CONFIG_RSBAC_AUTH) && !defined(CONFIG_RSBAC_MAINT)
    /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_auth_add_f_cap(): calling ADF\n");
#endif
    rsbac_attribute_value.auth_cap = first_uid;
    if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                           current->pid,
                           T_FILE,
                           tid,
                           A_auth_add_f_cap,
                           rsbac_attribute_value))
      {
        err = -EPERM;
      }
    else
#endif
      err = rsbac_auth_add_f_cap(tid.file, first_uid, last_uid);

out_dput:
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    dput(t_dentry);
    #else
    path_release(&nd);
    #endif
out:
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    unlock_kernel();
    #endif
    return(err);

#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

int sys_rsbac_auth_remove_f_cap(char * filename,
                                           rsbac_uid_t first_uid,
                                           rsbac_uid_t last_uid)
  {
#if defined(CONFIG_RSBAC_AUTH)
    struct dentry * t_dentry;
    int     err = 0;
    union rsbac_target_id_t  tid;

    /* for adf_request */
#if defined(CONFIG_RSBAC_AUTH) && !defined(CONFIG_RSBAC_MAINT)
    union rsbac_attribute_value_t rsbac_attribute_value;
#endif

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
    struct nameidata nd;
    #endif

    if(!filename)
      return(-RSBAC_EINVALIDTARGET);
    if(first_uid > last_uid)
      return(-RSBAC_EINVALIDVALUE);

    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    lock_kernel();
    t_dentry = lookup_dentry(filename,NULL,0);
    if (IS_ERR(t_dentry))
      {
        err = -RSBAC_EINVALIDTARGET;
        goto out;
      }
    #else
    if ((err = user_path_walk_link(filename, &nd)))
      {
#ifdef CONFIG_RSBAC_DEBUG
        if (rsbac_debug_aef_auth)
          printk(KERN_DEBUG "sys_rsbac_auth_remove_f_cap(): call to user_path_walk_link() returned %i\n", err);
#endif
        goto out;
      }
    t_dentry = nd.dentry;
    #endif
    if (!t_dentry->d_inode)
      {
        err = -RSBAC_EINVALIDTARGET;
        goto out_dput;
      }
    /* is inode of type file? */
    if (!S_ISREG(t_dentry->d_inode->i_mode))
      { /* This is no file */
        err = -RSBAC_EINVALIDTARGET;
        goto out_dput;
      }
    tid.file.device = t_dentry->d_inode->i_sb->s_dev;
    tid.file.inode  = t_dentry->d_inode->i_ino;
    tid.file.dentry_p = t_dentry;
#if defined(CONFIG_RSBAC_AUTH) && !defined(CONFIG_RSBAC_MAINT)
    /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_auth_add_f_cap(): calling ADF\n");
#endif
    rsbac_attribute_value.auth_cap = first_uid;
    if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
                           current->pid,
                           T_FILE,
                           tid,
                           A_auth_remove_f_cap,
                           rsbac_attribute_value))
      {
        err = -EPERM;
      }
    else
#endif
      err = rsbac_auth_remove_f_cap(tid.file, first_uid, last_uid);

out_dput:
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    dput(t_dentry);
    #else
    path_release(&nd);
    #endif
out:
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    unlock_kernel();
    #endif
    return(err);

#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

/* caplist must have space for 2 * maxnum uid entries - first and last each! */
int sys_rsbac_auth_get_f_caplist(char * filename,
                                            rsbac_uid_t caplist[],
                                            int maxnum)
  {
#if defined(CONFIG_RSBAC_AUTH)
    struct dentry * t_dentry;
    int     err = 0, tmperr = 0;
    union rsbac_target_id_t  tid;
    rsbac_uid_t * k_caplist;
    boolean vmalloc_used;

    /* for adf_request */
#if defined(CONFIG_RSBAC_AUTH) && !defined(CONFIG_RSBAC_MAINT)
    union rsbac_attribute_value_t rsbac_attribute_value;
#endif

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
    struct nameidata nd;
    #endif

    if(!filename)
      return(-RSBAC_EINVALIDTARGET);
    if(!caplist)
      return(-RSBAC_EINVALIDPOINTER);
    if(maxnum <= 0)
      return(-RSBAC_EINVALIDVALUE);

    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    lock_kernel();
    t_dentry = lookup_dentry(filename,NULL,0);
    if (IS_ERR(t_dentry))
      {
        err = -RSBAC_EINVALIDTARGET;
        goto out;
      }
    #else
    if ((err = user_path_walk_link(filename, &nd)))
      {
#ifdef CONFIG_RSBAC_DEBUG
        if (rsbac_debug_aef_auth)
          printk(KERN_DEBUG "sys_rsbac_auth_get_f_caplist(): call to user_path_walk_link() returned %i\n", err);
#endif
        goto out;
      }
    t_dentry = nd.dentry;
    #endif
    if (!t_dentry->d_inode)
      {
        err = -RSBAC_EINVALIDTARGET;
        goto out_dput;
      }
    /* is inode of type file? */
    if (!S_ISREG(t_dentry->d_inode->i_mode))
      { /* This is no file */
        err = -RSBAC_EINVALIDTARGET;
        goto out_dput;
      }
    tid.file.device = t_dentry->d_inode->i_sb->s_dev;
    tid.file.inode  = t_dentry->d_inode->i_ino;
    tid.file.dentry_p = t_dentry;
#if defined(CONFIG_RSBAC_AUTH) && !defined(CONFIG_RSBAC_MAINT)
    /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef) printk(KERN_DEBUG "sys_rsbac_auth_get_f_caplist(): calling ADF\n");
#endif
    rsbac_attribute_value.dummy = 0;
    if (!rsbac_adf_request(R_READ_ATTRIBUTE,
                           current->pid,
                           T_FILE,
                           tid,
                           A_auth_get_caplist,
                           rsbac_attribute_value))
      {
        err = -EPERM;
        goto out_dput;
      }
#endif
    k_caplist = rsbac_vkmalloc(2 * maxnum * sizeof(rsbac_uid_t), &vmalloc_used);
    if(!k_caplist)
      return -RSBAC_ENOMEM;
    err = rsbac_auth_get_f_caplist(tid.file, k_caplist, maxnum);
    if(err>0)
      {
        tmperr = rsbac_put_user((u_char *) k_caplist, (u_char *) caplist,
                                sizeof(rsbac_uid_t) * 2 * err);
        if(tmperr < 0)
          err = tmperr;
      }
    rsbac_vkfree(k_caplist, vmalloc_used);

out_dput:
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    dput(t_dentry);
    #else
    path_release(&nd);
    #endif
out:
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    unlock_kernel();
    #endif
    return(err);

#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
  };

/**********************************/
/************** REG ***************/

int sys_rsbac_reg(rsbac_reg_handle_t handle,
                             void * arg)
  {
#if defined(CONFIG_RSBAC_REG)
    return rsbac_reg_syscall(handle, arg);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif
  }


/**********************************/
/************** ACL ***************/

int sys_rsbac_acl(enum   rsbac_acl_syscall_type_t call,
                             struct rsbac_acl_syscall_arg_t * arg)
    { 
#if defined(CONFIG_RSBAC_ACL)
      struct rsbac_acl_syscall_arg_t k_arg;
/*      union rsbac_target_id_t i_tid; */
      int   err = 0;
      
      if(call >= ACLC_none)
        return(-RSBAC_EINVALIDREQUEST);
      if(!arg)
        return(-RSBAC_EINVALIDPOINTER);

      /* get values from user space */
      err = rsbac_get_user((u_char *) &k_arg, (u_char *) arg, sizeof(k_arg) );
      if(err < 0)
        return err;

      if(k_arg.target >= T_NONE)
        return(-RSBAC_EINVALIDTARGET);
/*      printk(KERN_DEBUG "sys_rsbac_acl(): target = %u, call = %u, subj_type = %u, subj_id = %u!\n",
             k_arg.target, call, k_arg.subj_type, k_arg.subj_id); */
      if(call != ACLC_set_mask)
        {
          switch(k_arg.subj_type)
            {
              case ACLS_USER:
                break;
              case ACLS_GROUP:
                if(k_arg.subj_id != RSBAC_ACL_GROUP_EVERYONE)
                  {
                    struct rsbac_acl_group_entry_t entry;
                           rsbac_uid_t caller;

                    if(   rsbac_acl_get_group_entry(k_arg.subj_id, &entry)
                       || rsbac_get_owner(&caller)
                       || (   (entry.owner != caller)
                           && (entry.type != ACLG_GLOBAL)
                          )
                      )
                      return(-RSBAC_EINVALIDVALUE);
                  }
                break;
              #if defined(CONFIG_RSBAC_RC)
              case ACLS_ROLE:
                if(k_arg.subj_id > RC_role_max_value)
                  {
                    printk(KERN_DEBUG "sys_rsbac_acl(): Invalid role %u!\n", k_arg.subj_id);
                    return(-RSBAC_EINVALIDVALUE);
                  }
                break;
              #endif
              default:
                printk(KERN_DEBUG "sys_rsbac_acl(): Invalid subject type %u!\n", k_arg.subj_type);
                return(-RSBAC_EINVALIDVALUE);
            }
          if(   (call == ACLC_remove_user)
             && (k_arg.target != T_USER)
            )
            return -RSBAC_EINVALIDTARGET;
          
        }
        
      /* call acl function */
      switch(call)
        {
          case ACLC_set_acl_entry:
            err = rsbac_acl_sys_set_acl_entry(k_arg.target,
                                              k_arg.tid,
                                              k_arg.subj_type,
                                              k_arg.subj_id,
                                              k_arg.rights,
                                              k_arg.ttl);
            break;
          case ACLC_remove_acl_entry:
            err = rsbac_acl_sys_remove_acl_entry(k_arg.target,
                                                 k_arg.tid,
                                                 k_arg.subj_type,
                                                 k_arg.subj_id);
            break;
          case ACLC_remove_acl:
            err = rsbac_acl_sys_remove_acl(k_arg.target,
                                           k_arg.tid);
            break;
          case ACLC_add_to_acl_entry:
            err = rsbac_acl_sys_add_to_acl_entry(k_arg.target,
                                                 k_arg.tid,
                                                 k_arg.subj_type,
                                                 k_arg.subj_id,
                                                 k_arg.rights,
                                                 k_arg.ttl);
            break;
          case ACLC_remove_from_acl_entry:
            err = rsbac_acl_sys_remove_from_acl_entry(k_arg.target,
                                                      k_arg.tid,
                                                      k_arg.subj_type,
                                                      k_arg.subj_id,
                                                      k_arg.rights);
            break;
          case ACLC_set_mask:
            err = rsbac_acl_sys_set_mask(k_arg.target,
                                         k_arg.tid,
                                         k_arg.rights);
            break;
          case ACLC_remove_user:
            err = rsbac_acl_sys_remove_user(k_arg.tid.user);
            break;

          default:
            err=-RSBAC_EINVALIDREQUEST;
        }
      return (err);
#else
      return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl() */


int sys_rsbac_acl_n(enum   rsbac_acl_syscall_type_t call,
                               struct rsbac_acl_syscall_n_arg_t * arg)
    {
#if defined(CONFIG_RSBAC_ACL)
      struct dentry * t_dentry = NULL;
      int     err = 0;
      boolean need_put = FALSE;
      union rsbac_target_id_t  tid;
      struct rsbac_acl_syscall_n_arg_t k_arg;

      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct nameidata nd;
      #endif

      if(call >= ACLC_none)
        return(-RSBAC_EINVALIDREQUEST);
      if(!arg)
        return(-RSBAC_EINVALIDPOINTER);

      /* get values from user space */
      err = rsbac_get_user((u_char *) &k_arg, (u_char *) arg, sizeof(k_arg) );
      if(err < 0)
        return err;

      if(k_arg.target >= T_NONE)
        return(-RSBAC_EINVALIDTARGET);
      if(call != ACLC_set_mask)
        {
          switch(k_arg.subj_type)
            {
              case ACLS_USER:
                break;
              case ACLS_GROUP:
                if(k_arg.subj_id != RSBAC_ACL_GROUP_EVERYONE)
                  {
                    struct rsbac_acl_group_entry_t entry;
                           rsbac_uid_t caller;

                    if(   rsbac_acl_get_group_entry(k_arg.subj_id, &entry)
                       || rsbac_get_owner(&caller)
                       || (   (entry.owner != caller)
                           && (entry.type != ACLG_GLOBAL)
                          )
                      )
                      return(-RSBAC_EINVALIDVALUE);
                  }
                break;
              #if defined(CONFIG_RSBAC_RC)
              case ACLS_ROLE:
                if(k_arg.subj_id > RC_role_max_value)
                  return(-RSBAC_EINVALIDVALUE);
                break;
              #endif
              default:
                return(-RSBAC_EINVALIDVALUE);
            }
        }
        
      switch (k_arg.target)
        {
          case T_FILE:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type file, symlink or block/char device? */
                if (   !(S_ISREG(t_dentry->d_inode->i_mode))
                    && !(S_ISBLK(t_dentry->d_inode->i_mode))
                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.file.device = t_dentry->d_inode->i_dev;
                tid.file.inode  = t_dentry->d_inode->i_ino;
                tid.file.dentry_p = t_dentry;
              }
            else
              {
                tid.file.device = 0;
                tid.file.inode  = 0;
                tid.file.dentry_p = NULL;
              }
            break;

          case T_DIR:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
                  { /* This is no dir */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.dir.device = t_dentry->d_inode->i_sb->s_dev;
                tid.dir.inode  = t_dentry->d_inode->i_ino;
                tid.dir.dentry_p = t_dentry;
              }
            else
              {
                tid.dir.device = 0;
                tid.dir.inode  = 0;
                tid.dir.dentry_p = NULL;
              }
            break;

          case T_FIFO:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type fifo? */
                if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.fifo.device = t_dentry->d_inode->i_dev;
                tid.fifo.inode  = t_dentry->d_inode->i_ino;
                tid.fifo.dentry_p = t_dentry;
              }
            else
              {
                tid.fifo.device = 0;
                tid.fifo.inode  = 0;
                tid.fifo.dentry_p = NULL;
              }
            break;

          case T_SYMLINK:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type symlink? */
                if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.symlink.device = t_dentry->d_inode->i_dev;
                tid.symlink.inode  = t_dentry->d_inode->i_ino;
                tid.symlink.dentry_p = t_dentry;
              }
            else
              {
                tid.symlink.device = 0;
                tid.symlink.inode  = 0;
                tid.symlink.dentry_p = NULL;
              }
            break;

          case T_DEV:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type file, symlink or block/char device? */
                if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* fill target id and call internal function */
                if(S_ISBLK(t_dentry->d_inode->i_mode))
                  tid.dev.type = D_block;
                else
                  tid.dev.type = D_char;
                tid.dev.id  = t_dentry->d_inode->i_rdev;
              }
            else
              {
                tid.dev.type = D_none;
                tid.dev.id = 0;
              }
            break;

          default:
            return -RSBAC_EINVALIDTARGET;
        }
      /* call acl function */
      switch(call)
        {
          case ACLC_set_acl_entry:
            err = rsbac_acl_sys_set_acl_entry(k_arg.target,
                                              tid,
                                              k_arg.subj_type,
                                              k_arg.subj_id,
                                              k_arg.rights,
                                              k_arg.ttl);
            break;
          case ACLC_remove_acl_entry:
            err = rsbac_acl_sys_remove_acl_entry(k_arg.target,
                                                 tid,
                                                 k_arg.subj_type,
                                                 k_arg.subj_id);
            break;
          case ACLC_remove_acl:
            err = rsbac_acl_sys_remove_acl(k_arg.target,
                                           tid);
            break;
          case ACLC_add_to_acl_entry:
            err = rsbac_acl_sys_add_to_acl_entry(k_arg.target,
                                                 tid,
                                                 k_arg.subj_type,
                                                 k_arg.subj_id,
                                                 k_arg.rights,
                                                 k_arg.ttl);
            break;
          case ACLC_remove_from_acl_entry:
            err = rsbac_acl_sys_remove_from_acl_entry(k_arg.target,
                                                      tid,
                                                      k_arg.subj_type,
                                                      k_arg.subj_id,
                                                      k_arg.rights);
            break;
          case ACLC_set_mask:
            err = rsbac_acl_sys_set_mask(k_arg.target,
                                         tid,
                                         k_arg.rights);
            break;

          default:
            err=-RSBAC_EINVALIDREQUEST;
        }

out_dput:
      if(need_put)
        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        {
          dput(t_dentry);
          unlock_kernel();
        }
        #else
        path_release(&nd);
        #endif
out:
      return(err);
#else
      return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl_n() */

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

int sys_rsbac_acl_get_rights (struct rsbac_acl_syscall_arg_t   * arg,
                                                rsbac_acl_rights_vector_t * rights_p,
                                                u_int                     effective)
    { 
#if defined(CONFIG_RSBAC_ACL)
      struct rsbac_acl_syscall_arg_t k_arg;
      rsbac_acl_rights_vector_t k_rights = 0;
      int   err = 0;
      
      if(!arg || !rights_p)
        return(-RSBAC_EINVALIDPOINTER);
      /* get values from user space */
      rsbac_get_user((u_char *) &k_arg, (u_char *) arg, sizeof(k_arg) );

      if(k_arg.target >= T_NONE)
        return(-RSBAC_EINVALIDTARGET);
/*      printk(KERN_DEBUG "sys_rsbac_acl_get_rights(): target = %u, subj_type = %u, subj_id = %u!\n",
             k_arg.target, k_arg.subj_type, k_arg.subj_id); */
      switch(k_arg.subj_type)
        {
          case ACLS_USER:
            break;
          case ACLS_GROUP:
            if(k_arg.subj_id != RSBAC_ACL_GROUP_EVERYONE)
              {
                struct rsbac_acl_group_entry_t entry;
                       rsbac_uid_t caller;

                if(   rsbac_acl_get_group_entry(k_arg.subj_id, &entry)
                   || rsbac_get_owner(&caller)
                   || (   (entry.owner != caller)
                       && (entry.type != ACLG_GLOBAL)
                      )
                  )
                  return(-RSBAC_EINVALIDVALUE);
              }
            break;
          case ACLS_ROLE:
          #if defined(CONFIG_RSBAC_RC)
            if(k_arg.subj_id > RC_role_max_value)
              return(-RSBAC_EINVALIDVALUE);
          #endif
            break;
          default:
            printk(KERN_DEBUG "sys_rsbac_acl_get_rights(): Invalid subject type %u!\n", k_arg.subj_type);
            return(-RSBAC_EINVALIDVALUE);
        }

      /* call acl function */
      err = rsbac_acl_sys_get_rights(k_arg.target,
                                     k_arg.tid,
                                     k_arg.subj_type,
                                     k_arg.subj_id,
                                     &k_rights,
                                     effective);
      if(!err)
        {
          err = rsbac_put_user((u_char *) &k_rights, (u_char *) rights_p, sizeof(k_rights) );
        }
      return (err);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl_get_rights() */


int sys_rsbac_acl_get_rights_n(struct rsbac_acl_syscall_n_arg_t * arg,
                                                 rsbac_acl_rights_vector_t * rights_p,
                                                 u_int                     effective)
    {
#if defined(CONFIG_RSBAC_ACL)
      struct dentry * t_dentry = NULL;
      boolean need_put = FALSE;
      int     err = 0;
      union rsbac_target_id_t  tid;
      struct rsbac_acl_syscall_n_arg_t k_arg;
      rsbac_acl_rights_vector_t k_rights = 0;
      
      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct nameidata nd;
      #endif

      if(!arg || !rights_p)
        return(-RSBAC_EINVALIDPOINTER);
      /* get values from user space */
      rsbac_get_user((u_char *) &k_arg, (u_char *) arg, sizeof(k_arg) );

      if(k_arg.target >= T_NONE)
        return(-RSBAC_EINVALIDTARGET);
      switch(k_arg.subj_type)
        {
          case ACLS_USER:
            break;
          case ACLS_GROUP:
            if(k_arg.subj_id != RSBAC_ACL_GROUP_EVERYONE)
              {
                struct rsbac_acl_group_entry_t entry;
                       rsbac_uid_t caller;

                if(   rsbac_acl_get_group_entry(k_arg.subj_id, &entry)
                   || rsbac_get_owner(&caller)
                   || (   (entry.owner != caller)
                       && (entry.type != ACLG_GLOBAL)
                      )
                  )
                  return(-RSBAC_EINVALIDVALUE);
              }
            break;
          case ACLS_ROLE:
          #if defined(CONFIG_RSBAC_RC)
            if(k_arg.subj_id > RC_role_max_value)
              return(-RSBAC_EINVALIDVALUE);
          #endif
            break;
          default:
            return(-RSBAC_EINVALIDVALUE);
        }
        
      switch (k_arg.target)
        {
          case T_FILE:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type file, symlink or block/char device? */
                if (   !(S_ISREG(t_dentry->d_inode->i_mode))
                    && !(S_ISBLK(t_dentry->d_inode->i_mode))
                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.file.device = t_dentry->d_inode->i_dev;
                tid.file.inode  = t_dentry->d_inode->i_ino;
                tid.file.dentry_p = t_dentry;
              }
            else
              {
                tid.file.device = 0;
                tid.file.inode  = 0;
                tid.file.dentry_p = NULL;
              }
            break;

          case T_DIR:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
                  { /* This is no dir */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.dir.device = t_dentry->d_inode->i_sb->s_dev;
                tid.dir.inode  = t_dentry->d_inode->i_ino;
                tid.dir.dentry_p = t_dentry;
              }
            else
              {
                tid.dir.device = 0;
                tid.dir.inode  = 0;
                tid.dir.dentry_p = NULL;
              }
            break;

          case T_FIFO:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type fifo? */
                if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
                  { /* This is no fifo */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.fifo.device = t_dentry->d_inode->i_dev;
                tid.fifo.inode  = t_dentry->d_inode->i_ino;
                tid.fifo.dentry_p = t_dentry;
              }
            else
              {
                tid.fifo.device = 0;
                tid.fifo.inode  = 0;
                tid.fifo.dentry_p = NULL;
              }
            break;

          case T_SYMLINK:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type symlink? */
                if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
                  { /* This is no symlink */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.symlink.device = t_dentry->d_inode->i_dev;
                tid.symlink.inode  = t_dentry->d_inode->i_ino;
                tid.symlink.dentry_p = t_dentry;
              }
            else
              {
                tid.symlink.device = 0;
                tid.symlink.inode  = 0;
                tid.symlink.dentry_p = NULL;
              }
            break;

          case T_DEV:
            if(k_arg.name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(k_arg.name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(k_arg.name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_rights_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type file, symlink or block/char device? */
                if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* fill target id and call internal function */
                if(S_ISBLK(t_dentry->d_inode->i_mode))
                  tid.dev.type = D_block;
                else
                  tid.dev.type = D_char;
                tid.dev.id  = t_dentry->d_inode->i_rdev;
              }
            else
              {
                tid.dev.type = D_none;
                tid.dev.id = 0;
              }
            break;

          default:
            return -RSBAC_EINVALIDTARGET;
        }

      /* call acl function */
      err = rsbac_acl_sys_get_rights(k_arg.target,
                                     tid,
                                     k_arg.subj_type,
                                     k_arg.subj_id,
                                     &k_rights,
                                     effective);

out_dput:
      if(need_put)
        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        {
          dput(t_dentry);
          unlock_kernel();
        }
        #else
        path_release(&nd);
        #endif
out:
      if(!err)
        {
          rsbac_put_user((u_char *) &k_rights, (u_char *) rights_p, sizeof(k_rights) );
        }
      return(err);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl_get_rights_n() */

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

int sys_rsbac_acl_get_tlist (enum   rsbac_target_t              target,
                                        union  rsbac_target_id_t         * tid,
                                        struct rsbac_acl_entry_t           entry_array[],
                                               rsbac_time_t                ttl_array[],
                                               u_int                       maxnum)
    { 
#if defined(CONFIG_RSBAC_ACL)
      union  rsbac_target_id_t   k_tid;
      struct rsbac_acl_entry_t * k_entry_p;
             rsbac_time_t      * k_ttl_p;
             int   err = 0;

      if(!tid || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
      if(!entry_array)
        return(-RSBAC_EINVALIDPOINTER);
      if(!maxnum)
        return(-RSBAC_EINVALIDVALUE);
        
      /* get values from user space */
      rsbac_get_user((u_char *) &k_tid, (u_char *) tid, sizeof(k_tid) );

      /* call acl function */
      err = rsbac_acl_sys_get_tlist(target, k_tid, &k_entry_p, &k_ttl_p);
      if(err>0)
        {
          if(err > maxnum)
            err = maxnum;
          rsbac_put_user((u_char *) k_entry_p,
                         (u_char *) entry_array,
                         err * sizeof(*k_entry_p) );
          if(ttl_array)
            {
              rsbac_put_user((u_char *) k_ttl_p,
                             (u_char *) ttl_array,
                             err * sizeof(*k_ttl_p) );
            }
          vfree(k_entry_p);
          vfree(k_ttl_p);
        }
      return (err);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl_get_tlist() */

int sys_rsbac_acl_get_tlist_n(enum   rsbac_target_t      target,
                                         char                     * t_name,
                                         struct rsbac_acl_entry_t   entry_array[],
                                         rsbac_time_t               ttl_array[],
                                                u_int               maxnum)
    {
#if defined(CONFIG_RSBAC_ACL)
      struct dentry * t_dentry = NULL;
      struct rsbac_acl_entry_t * k_entry_p;
      rsbac_time_t * k_ttl_p;
      boolean need_put = FALSE;
      int     err = 0;
      union rsbac_target_id_t  tid;
      
      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct nameidata nd;
      #endif
        
      if(target >= T_NONE)
        return(-RSBAC_EINVALIDTARGET);
      if(!entry_array)
        return(-RSBAC_EINVALIDPOINTER);

      switch (target)
        {
          case T_FILE:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_tlist_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type file, symlink or block/char device? */
                if (   !(S_ISREG(t_dentry->d_inode->i_mode))
                    && !(S_ISBLK(t_dentry->d_inode->i_mode))
                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.file.device = t_dentry->d_inode->i_dev;
                tid.file.inode  = t_dentry->d_inode->i_ino;
                tid.file.dentry_p = t_dentry;
              }
            else
              {
                tid.file.device = 0;
                tid.file.inode  = 0;
                tid.file.dentry_p = NULL;
              }
            break;

          case T_DIR:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_tlist_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
                  { /* This is no dir */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.dir.device = t_dentry->d_inode->i_sb->s_dev;
                tid.dir.inode  = t_dentry->d_inode->i_ino;
                tid.dir.dentry_p = t_dentry;
              }
            else
              {
                tid.dir.device = 0;
                tid.dir.inode  = 0;
                tid.dir.dentry_p = NULL;
              }
            break;

          case T_FIFO:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_tlist_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type fifo? */
                if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
                  { /* This is no fifo */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.fifo.device = t_dentry->d_inode->i_dev;
                tid.fifo.inode  = t_dentry->d_inode->i_ino;
                tid.fifo.dentry_p = t_dentry;
              }
            else
              {
                tid.fifo.device = 0;
                tid.fifo.inode  = 0;
                tid.fifo.dentry_p = NULL;
              }
            break;

          case T_SYMLINK:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_tlist_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type symlink? */
                if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
                  { /* This is no symlink */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.symlink.device = t_dentry->d_inode->i_dev;
                tid.symlink.inode  = t_dentry->d_inode->i_ino;
                tid.symlink.dentry_p = t_dentry;
              }
            else
              {
                tid.symlink.device = 0;
                tid.symlink.inode  = 0;
                tid.symlink.dentry_p = NULL;
              }
            break;

          case T_DEV:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_tlist_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type file, symlink or block/char device? */
                if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* fill target id and call internal function */
                if(S_ISBLK(t_dentry->d_inode->i_mode))
                  tid.dev.type = D_block;
                else
                  tid.dev.type = D_char;
                tid.dev.id  = t_dentry->d_inode->i_rdev;
              }
            else
              {
                tid.dev.type = D_none;
                tid.dev.id = 0;
              }
            break;

          default:
            return -RSBAC_EINVALIDTARGET;
        }
      /* call ACL function */
      err = rsbac_acl_sys_get_tlist(target, tid, &k_entry_p, &k_ttl_p);

out_dput:
      if(need_put)
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        {
          dput(t_dentry);
          unlock_kernel();
        }
      #else
        path_release(&nd);
      #endif
out:
      if(err>0)
        {
          if(err > maxnum)
            err = maxnum;
          rsbac_put_user((u_char *) k_entry_p,
                         (u_char *) entry_array,
                         err * sizeof(*k_entry_p) );
          if(ttl_array)
            {
              rsbac_put_user((u_char *) k_ttl_p,
                             (u_char *) ttl_array,
                             err * sizeof(*k_ttl_p) );
            }
          vfree(k_entry_p);
          vfree(k_ttl_p);
        }
      return(err);

#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl_get_tlist_n() */

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

int sys_rsbac_acl_get_mask (enum   rsbac_target_t              target,
                                       union  rsbac_target_id_t         * tid,
                                              rsbac_acl_rights_vector_t * mask_p)
    { 
#if defined(CONFIG_RSBAC_ACL)
      union  rsbac_target_id_t k_tid;
             rsbac_acl_rights_vector_t k_mask;
             int   err = 0;
      
      if(!tid || (target >= T_NONE))
        return(-RSBAC_EINVALIDTARGET);
      if(!mask_p)
        return(-RSBAC_EINVALIDPOINTER);

      /* get values from user space */
      rsbac_get_user((u_char *) &k_tid, (u_char *) tid, sizeof(k_tid) );

      /* call acl function */
      err = rsbac_acl_sys_get_mask(target, k_tid, &k_mask);
      if(!err)
        {
          rsbac_put_user((u_char *) &k_mask,
                         (u_char *) mask_p,
                         sizeof(k_mask) );
        }
      return (err);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl_get_mask() */

int sys_rsbac_acl_get_mask_n(enum rsbac_target_t              target,
                                             char                      * t_name,
                                             rsbac_acl_rights_vector_t * mask_p)
    {
#if defined(CONFIG_RSBAC_ACL)
      struct dentry * t_dentry = NULL;
      rsbac_acl_rights_vector_t k_mask;
      boolean need_put = FALSE;
      int     err = 0;
      union rsbac_target_id_t  tid;

      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct nameidata nd;
      #endif
      
      if(target >= T_NONE)
        return(-RSBAC_EINVALIDTARGET);
      if(!mask_p)
        return(-RSBAC_EINVALIDPOINTER);
        

      switch (target)
        {
          case T_FILE:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_mask_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type file, symlink or block/char device? */
                if (   !(S_ISREG(t_dentry->d_inode->i_mode))
                    && !(S_ISBLK(t_dentry->d_inode->i_mode))
                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.file.device = t_dentry->d_inode->i_dev;
                tid.file.inode  = t_dentry->d_inode->i_ino;
                tid.file.dentry_p = t_dentry;
              }
            else
              {
                tid.file.device = 0;
                tid.file.inode  = 0;
                tid.file.dentry_p = NULL;
              }
            break;

          case T_DIR:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_mask_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
                  { /* This is no dir */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.dir.device = t_dentry->d_inode->i_sb->s_dev;
                tid.dir.inode  = t_dentry->d_inode->i_ino;
                tid.dir.dentry_p = t_dentry;
              }
            else
              {
                tid.dir.device = 0;
                tid.dir.inode  = 0;
                tid.dir.dentry_p = NULL;
              }
            break;

          case T_FIFO:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_mask_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type fifo? */
                if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
                  { /* This is no fifo */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.fifo.device = t_dentry->d_inode->i_dev;
                tid.fifo.inode  = t_dentry->d_inode->i_ino;
                tid.fifo.dentry_p = t_dentry;
              }
            else
              {
                tid.fifo.device = 0;
                tid.fifo.inode  = 0;
                tid.fifo.dentry_p = NULL;
              }
            break;

          case T_SYMLINK:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err= -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_mask_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type symlink? */
                if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
                  { /* This is no symlink */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                tid.symlink.device = t_dentry->d_inode->i_dev;
                tid.symlink.inode  = t_dentry->d_inode->i_ino;
                tid.symlink.dentry_p = t_dentry;
              }
            else
              {
                tid.symlink.device = 0;
                tid.symlink.inode  = 0;
                tid.symlink.dentry_p = NULL;
              }
            break;

          case T_DEV:
            if(t_name)
              {
                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
                lock_kernel();
                t_dentry = lookup_dentry(t_name,NULL,0);
                if (IS_ERR(t_dentry))
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    unlock_kernel();
                    goto out;
                  }
                #else
                if ((err = user_path_walk_link(t_name, &nd)))
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if (rsbac_debug_aef_acl)
                      printk(KERN_DEBUG "sys_rsbac_acl_get_mask_n(): call to user_path_walk_link() returned %i\n", err);
#endif
                    goto out;
                   }
                t_dentry = nd.dentry;
                #endif
                need_put = TRUE;
                if (!t_dentry->d_inode)
                  {
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* is inode of type block/char device? */
                if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
                  { /* This is no file or device */
                    err = -RSBAC_EINVALIDTARGET;
                    goto out_dput;
                  }
                /* fill target id and call internal function */
                if(S_ISBLK(t_dentry->d_inode->i_mode))
                  tid.dev.type = D_block;
                else
                  tid.dev.type = D_char;
                tid.dev.id  = t_dentry->d_inode->i_rdev;
              }
            else
              {
                tid.dev.type = D_none;
                tid.dev.id = 0;
              }
            break;

          default:
            return -RSBAC_EINVALIDTARGET;
        }
      /* call ACL function */
      err = rsbac_acl_sys_get_mask(target, tid, &k_mask);

out_dput:
      if(need_put)
        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
        {
          dput(t_dentry);
          unlock_kernel();
        }
        #else
        path_release(&nd);
        #endif
out:
      if(!err)
        {
          rsbac_put_user((u_char *) &k_mask,
                         (u_char *) mask_p,
                         sizeof(k_mask) );
        }
      return(err);

#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl_get_mask_n() */

/********  ACL groups *********/

int sys_rsbac_acl_group(enum  rsbac_acl_group_syscall_type_t call,
                                   union rsbac_acl_group_syscall_arg_t * arg_p)
    { 
#if defined(CONFIG_RSBAC_ACL)
      union rsbac_acl_group_syscall_arg_t k_arg;
      int   err = 0;

      if(call >= ACLGS_none)
        return(-RSBAC_EINVALIDREQUEST);
      if(!arg_p)
        return(-RSBAC_EINVALIDPOINTER);

      /* get values from user space */
      err = rsbac_get_user((u_char *) &k_arg, (u_char *) arg_p, sizeof(k_arg) );

      /* call acl function */
      if(err >= 0)
        err = rsbac_acl_sys_group(call, k_arg);
      return (err);
#else
    return (-RSBAC_EINVALIDMODULE);
#endif    
    };      /* end of sys_rsbac_acl() */


/************************************************* */
/*             DEBUG/LOG functions                 */
/************************************************* */

int sys_rsbac_adf_log_switch(enum rsbac_adf_request_t target,
                                        enum rsbac_log_level_t   value)
  {
    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;

    if ((value != LL_none) && (value != LL_denied) && (value != LL_full))
      return (-RSBAC_EINVALIDVALUE);
    if(target >= R_NONE)
      return(-RSBAC_EINVALIDTARGET);
    /* call ADF */
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef)
      printk(KERN_DEBUG "sys_rsbac_adf_log_switch(): calling ADF\n");
#endif
    rsbac_target_id.dummy = 0;
    rsbac_attribute_value.request = target;
    if (!rsbac_adf_request(R_SWITCH_LOG,
                           current->pid,
                           T_NONE,
                           rsbac_target_id,
                           A_request,
                           rsbac_attribute_value))
             {
               return -EPERM;
             }
#ifdef CONFIG_RSBAC_DEBUG
    if (rsbac_debug_aef)
      {
        char * request_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
        if(request_name)
          {
            get_request_name(request_name,target);
            printk(KERN_DEBUG "sys_rsbac_adf_log_switch(): switching RSBAC module logging for request %s (No. %i) to %i!\n",
                   request_name, target, value);
            rsbac_kfree(request_name);
          }
      }
#endif
    rsbac_adf_log_switch(target,value);
    return(0);
  };

/*
 * Commands to sys_rsbac_log:
 *
 * 	0 -- Close the log.  Currently a NOP.
 * 	1 -- Open the log. Currently a NOP.
 * 	2 -- Read from the log.
 * 	3 -- Read up to the last 4k of messages in the ring buffer.
 * 	4 -- Read and clear last 4k of messages in the ring buffer
 * 	5 -- Clear ring buffer.
 */
int sys_rsbac_log(int type,
                             char * buf,
                             int len)
  {
#if defined(CONFIG_RSBAC_RMSG)
    /* lock_kernel is done in rsbac_log */
    return(rsbac_log(type,buf,len));
#else
    return(0);
#endif /* RMSG */
  };


/* Big dispatcher for all syscalls */
asmlinkage int sys_rsbac(enum  rsbac_syscall_t call,
                         union rsbac_syscall_arg_t * arg_p)
  {
    union rsbac_syscall_arg_t k_arg;
    int err;

    if(call >= RSYS_none)
      return -RSBAC_EINVALIDREQUEST;

    /* get values from user space */
    if(arg_p)
      {
        err = rsbac_get_user((u_char *) &k_arg, (u_char *) arg_p, sizeof(k_arg) );
        if(err)
          return err;
      }
    else
      {
        memset(&k_arg, 0, sizeof(k_arg));
      }

    switch(call)
      {
        case RSYS_stats:
          return sys_rsbac_stats();
        case RSYS_check:
          return sys_rsbac_check(k_arg.check.correct, k_arg.check.check_inode);
        case RSYS_get_attr:
          return sys_rsbac_get_attr(k_arg.get_attr.module,
                                    k_arg.get_attr.target,
                                    k_arg.get_attr.tid,
                                    k_arg.get_attr.attr,
                                    k_arg.get_attr.value,
                                    k_arg.get_attr.inherit);
        case RSYS_get_attr_n:
          return sys_rsbac_get_attr_n(k_arg.get_attr_n.module,
                                      k_arg.get_attr_n.target,
                                      k_arg.get_attr_n.t_name,
                                      k_arg.get_attr_n.attr,
                                      k_arg.get_attr_n.value,
                                      k_arg.get_attr_n.inherit);
        case RSYS_set_attr:
          return sys_rsbac_set_attr(k_arg.set_attr.module,
                                    k_arg.set_attr.target,
                                    k_arg.set_attr.tid,
                                    k_arg.set_attr.attr,
                                    k_arg.set_attr.value);
        case RSYS_set_attr_n:
          return sys_rsbac_set_attr_n(k_arg.set_attr_n.module,
                                      k_arg.set_attr_n.target,
                                      k_arg.set_attr_n.t_name,
                                      k_arg.set_attr_n.attr,
                                      k_arg.set_attr_n.value);
        case RSYS_remove_target:
          return sys_rsbac_remove_target(k_arg.remove_target.target,
                                         k_arg.remove_target.tid);
        case RSYS_remove_target_n:
          return sys_rsbac_remove_target_n(k_arg.remove_target_n.target,
                                           k_arg.remove_target_n.t_name);
        case RSYS_net_list_all_netdev:
          return sys_rsbac_net_list_all_netdev(k_arg.net_list_all_netdev.id_p,
                                               k_arg.net_list_all_netdev.maxnum);
        case RSYS_net_template:
          return sys_rsbac_net_template(k_arg.net_template.call,
                                        k_arg.net_template.id,
                                        k_arg.net_template.data_p);
        case RSYS_net_list_all_template:
          return sys_rsbac_net_list_all_template(k_arg.net_list_all_template.id_p,
                                                 k_arg.net_list_all_template.maxnum);
        case RSYS_switch:
          return sys_rsbac_switch(k_arg.switch_module.target,
                                  k_arg.switch_module.value);
        case RSYS_adf_log_switch:
          return sys_rsbac_adf_log_switch(k_arg.adf_log_switch.target,
                                          k_arg.adf_log_switch.value);
        case RSYS_write:
          return sys_rsbac_write();
        case RSYS_log:
          return sys_rsbac_log(k_arg.log.type,
                               k_arg.log.buf,
                               k_arg.log.len);
        case RSYS_mac_set_curr_seclevel:
          return sys_rsbac_mac_set_curr_seclevel(k_arg.mac_set_curr_seclevel.level);
        case RSYS_mac_get_curr_seclevel:
          return sys_rsbac_mac_get_curr_seclevel();
        case RSYS_mac_set_max_seclevel:
          return sys_rsbac_mac_set_max_seclevel(k_arg.mac_set_max_seclevel.level);
        case RSYS_mac_get_max_seclevel:
          return sys_rsbac_mac_get_max_seclevel();
        case RSYS_mac_set_curr_categories:
          return sys_rsbac_mac_set_curr_categories(k_arg.mac_set_curr_categories.categories_p);
        case RSYS_mac_get_curr_categories:
          return sys_rsbac_mac_get_curr_categories(k_arg.mac_get_curr_categories.categories_p);
        case RSYS_mac_set_max_categories:
          return sys_rsbac_mac_set_max_categories(k_arg.mac_set_max_categories.categories_p);
        case RSYS_mac_get_max_categories:
          return sys_rsbac_mac_get_max_categories(k_arg.mac_get_max_categories.categories_p);
        case RSYS_stats_pm:
          return sys_rsbac_stats_pm();
        case RSYS_pm:
          return sys_rsbac_pm(k_arg.pm.function,
                              k_arg.pm.param_p,
                              k_arg.pm.ticket);
        case RSYS_pm_change_current_task:
          return sys_rsbac_pm_change_current_task(k_arg.pm_change_current_task.task);
        case RSYS_pm_create_file:
          return sys_rsbac_pm_create_file(k_arg.pm_create_file.filename,
                                          k_arg.pm_create_file.mode,
                                          k_arg.pm_create_file.object_class);
        case RSYS_ms_get_copied:
          return sys_rsbac_ms_get_copied(k_arg.ms_get_copied.fd);
        case RSYS_rc_copy_role:
          return sys_rsbac_rc_copy_role(k_arg.rc_copy_role.from_role,
                                        k_arg.rc_copy_role.to_role);
        case RSYS_rc_get_item:
          return sys_rsbac_rc_get_item(k_arg.rc_get_item.target,
                                       k_arg.rc_get_item.tid_p,
                                       k_arg.rc_get_item.subtid_p,
                                       k_arg.rc_get_item.item,
                                       k_arg.rc_get_item.value_p,
                                       k_arg.rc_get_item.ttl_p);
        case RSYS_rc_set_item:
          return sys_rsbac_rc_set_item(k_arg.rc_set_item.target,
                                       k_arg.rc_set_item.tid_p,
                                       k_arg.rc_set_item.subtid_p,
                                       k_arg.rc_set_item.item,
                                       k_arg.rc_set_item.value_p,
                                       k_arg.rc_set_item.ttl);
        case RSYS_rc_change_role:
          return sys_rsbac_rc_change_role(k_arg.rc_change_role.role);
        case RSYS_rc_get_eff_rights_n:
          return sys_rsbac_rc_get_eff_rights_n(k_arg.rc_get_eff_rights_n.target,
                                               k_arg.rc_get_eff_rights_n.t_name,
                                               k_arg.rc_get_eff_rights_n.request_vector_p,
                                               k_arg.rc_get_eff_rights_n.ttl_p);
        case RSYS_rc_get_list:
          return sys_rsbac_rc_get_list(k_arg.rc_get_list.target,
                                       k_arg.rc_get_list.tid_p,
                                       k_arg.rc_get_list.item,
                                       k_arg.rc_get_list.maxnum,
                                       k_arg.rc_get_list.array_p,
                                       k_arg.rc_get_list.ttl_array_p);
        case RSYS_auth_add_p_cap:
          return sys_rsbac_auth_add_p_cap(k_arg.auth_add_p_cap.pid,
                                          k_arg.auth_add_p_cap.first_uid,
                                          k_arg.auth_add_p_cap.last_uid);
        case RSYS_auth_remove_p_cap:
          return sys_rsbac_auth_remove_p_cap(k_arg.auth_remove_p_cap.pid,
                                             k_arg.auth_remove_p_cap.first_uid,
                                             k_arg.auth_remove_p_cap.last_uid);
        case RSYS_auth_add_f_cap:
          return sys_rsbac_auth_add_f_cap(k_arg.auth_add_f_cap.filename,
                                          k_arg.auth_add_f_cap.first_uid,
                                          k_arg.auth_add_f_cap.last_uid);
        case RSYS_auth_remove_f_cap:
          return sys_rsbac_auth_remove_f_cap(k_arg.auth_remove_f_cap.filename,
                                             k_arg.auth_remove_f_cap.first_uid,
                                             k_arg.auth_remove_f_cap.last_uid);
        case RSYS_auth_get_f_caplist:
          return sys_rsbac_auth_get_f_caplist(k_arg.auth_get_f_caplist.filename,
                                              k_arg.auth_get_f_caplist.caplist,
                                              k_arg.auth_get_f_caplist.maxnum);
        case RSYS_acl:
          return sys_rsbac_acl(k_arg.acl.call,
                               k_arg.acl.arg);
        case RSYS_acl_n:
          return sys_rsbac_acl_n(k_arg.acl_n.call,
                                 k_arg.acl_n.arg);
        case RSYS_acl_get_rights:
          return sys_rsbac_acl_get_rights(k_arg.acl_get_rights.arg,
                                          k_arg.acl_get_rights.rights_p,
                                          k_arg.acl_get_rights.effective);
        case RSYS_acl_get_rights_n:
          return sys_rsbac_acl_get_rights_n(k_arg.acl_get_rights_n.arg,
                                            k_arg.acl_get_rights_n.rights_p,
                                            k_arg.acl_get_rights_n.effective);
        case RSYS_acl_get_tlist:
          return sys_rsbac_acl_get_tlist(k_arg.acl_get_tlist.target,
                                         k_arg.acl_get_tlist.tid,
                                         k_arg.acl_get_tlist.entry_array,
                                         k_arg.acl_get_tlist.ttl_array,
                                         k_arg.acl_get_tlist.maxnum);
        case RSYS_acl_get_tlist_n:
          return sys_rsbac_acl_get_tlist_n(k_arg.acl_get_tlist_n.target,
                                           k_arg.acl_get_tlist_n.t_name,
                                           k_arg.acl_get_tlist_n.entry_array,
                                           k_arg.acl_get_tlist_n.ttl_array,
                                           k_arg.acl_get_tlist_n.maxnum);
        case RSYS_acl_get_mask:
          return sys_rsbac_acl_get_mask(k_arg.acl_get_mask.target,
                                        k_arg.acl_get_mask.tid,
                                        k_arg.acl_get_mask.mask_p);
        case RSYS_acl_get_mask_n:
          return sys_rsbac_acl_get_mask_n(k_arg.acl_get_mask_n.target,
                                          k_arg.acl_get_mask_n.t_name,
                                          k_arg.acl_get_mask_n.mask_p);
        case RSYS_acl_group:
          return sys_rsbac_acl_group(k_arg.acl_group.call,
                                     k_arg.acl_group.arg_p);
        case RSYS_reg:
          return sys_rsbac_reg(k_arg.reg.handle,
                               k_arg.reg.arg);

        default:
          return -RSBAC_EINVALIDREQUEST;
      }
  };


/* end of syscalls.c */
