/*************************************************** */
/* Rule Set Based Access Control                     */
/* Author and (c) 1999-2002: Amon Ott <ao@rsbac.org> */
/* Generic lists - internal structures               */
/* Last modified: 04/Feb/2002                        */
/*************************************************** */

#ifndef __RSBAC_GEN_LISTS_H
#define __RSBAC_GEN_LISTS_H

#include <linux/init.h>
#include <rsbac/rkmem.h>
#include <rsbac/lists.h>

#define RSBAC_LIST_DISK_VERSION 10002
#define RSBAC_LIST_DISK_OLD_VERSION 10001
#define RSBAC_LIST_NONAME "(no name)"
#define RSBAC_LIST_PROC_NAME "gen_lists"
#define RSBAC_LIST_DEVICENAME "gen_list_device"
#define RSBAC_LIST_FILENAME "genlst"

#define RSBAC_GEN_LIST_DISK_VERSION 10001
#define RSBAC_GEN_LIST_KEY 0x101face

/* Prototypes */

/* Init */
void __init rsbac_list_init(void);

/* mount / umount */
int rsbac_list_mount(kdev_t kdev);
int rsbac_list_umount(kdev_t kdev);

/* Status checking */
int rsbac_check_lists(int correct);

#if defined(CONFIG_RSBAC_AUTO_WRITE)
int rsbac_write_lists(boolean need_lock);
#endif

/* Data Structures */

/* All items will be organized in double linked lists
 * However, we do not know the descriptor or item sizes, so we will access them
   with offsets later and only define the list links here.
 */

struct rsbac_list_item_t
    {
      struct rsbac_list_item_t * prev;
      struct rsbac_list_item_t * next;
             rsbac_time_t        max_age;
    };

/* lists of lists ds */
struct rsbac_list_lol_item_t
    {
      struct rsbac_list_lol_item_t * prev;
      struct rsbac_list_lol_item_t * next;
      struct rsbac_list_item_t     * head;
      struct rsbac_list_item_t     * tail;
      struct rsbac_list_item_t     * curr;
             u_long                  count;
             rsbac_time_t            max_age;
    };

/* Since all registrations will be organized in double linked lists, we must
 * have list items and a list head.
 * The pointer to this item will also be used as list handle. */

typedef __u32 rsbac_list_count_t;

struct rsbac_list_reg_item_t
    {
      struct rsbac_list_info_t             info;
             u_int                         flags;
             rsbac_list_compare_function_t * compare;
             rsbac_list_get_conv_t       * get_conv;
             void                        * def_data;
             char                          name[RSBAC_LIST_MAX_FILENAME+1];
             kdev_t                        device;
      struct rsbac_list_item_t           * head;
      struct rsbac_list_item_t           * tail;
      struct rsbac_list_item_t           * curr;
             rwlock_t                      lock;
             rsbac_list_count_t            count;
             boolean                       dirty;
             boolean                       no_write;
#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
      struct proc_dir_entry              * proc_entry_p;
#endif
      struct rsbac_list_reg_item_t       * prev;
      struct rsbac_list_reg_item_t       * next;
      struct rsbac_list_reg_item_t       * self;
    };

struct rsbac_list_lol_reg_item_t
    {
      struct rsbac_list_lol_info_t         info;
             u_int                         flags;
             rsbac_list_compare_function_t * compare;
             rsbac_list_compare_function_t * subcompare;
             rsbac_list_get_conv_t       * get_conv;
             rsbac_list_get_conv_t       * get_subconv;
             void                        * def_data;
             void                        * def_subdata;
             char                          name[RSBAC_LIST_MAX_FILENAME+1];
             kdev_t                        device;
      struct rsbac_list_lol_item_t       * head;
      struct rsbac_list_lol_item_t       * tail;
      struct rsbac_list_lol_item_t       * curr;
             rwlock_t                      lock;
             rsbac_list_count_t            count;
             boolean                       dirty;
             boolean                       no_write;
#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
      struct proc_dir_entry              * proc_entry_p;
#endif
      struct rsbac_list_lol_reg_item_t   * prev;
      struct rsbac_list_lol_reg_item_t   * next;
      struct rsbac_list_lol_reg_item_t   * self;
    };

/* To provide consistency we use spinlocks for all list accesses. The
   'curr' entry is used to avoid repeated lookups for the same item. */
    
struct rsbac_list_reg_head_t
    {
      struct rsbac_list_reg_item_t * head;
      struct rsbac_list_reg_item_t * tail;
      struct rsbac_list_reg_item_t * curr;
             rwlock_t                lock;
             u_int                   count;
    };

struct rsbac_list_lol_reg_head_t
    {
      struct rsbac_list_lol_reg_item_t * head;
      struct rsbac_list_lol_reg_item_t * tail;
      struct rsbac_list_lol_reg_item_t * curr;
             rwlock_t                    lock;
             u_int                       count;
    };

/* Data structs for file timeout book keeping list filelist */
struct rsbac_list_filelist_desc_t
  {
    char   filename[RSBAC_LIST_MAX_FILENAME+1];
  };

struct rsbac_list_filelist_data_t
  {
    rsbac_time_t timestamp;
    rsbac_time_t max_age;
  };

#endif
