/*
 *
 * Real-Time and Multimedia Systems Laboratory
 * Copyright (c) 2000 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Real-Time and Multimedia Systems Laboratory
 *  Attn: Prof. Raj Rajkumar
 *  Electrical and Computer Engineering, and Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 *  or via email to raj@ece.cmu.edu
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 */
 
/*
 * $Author: miyos $	 
 * $Id: filtermain.c,v 1.1.1.1 2001/04/19 08:43:54 miyos Exp $
 *
 * TODO
 *     - check if LinuxRK is running (open /prok/rk?) and do not
 *      load unless it is. If I load on a non-rk linux, something
 *      ugly would surely happen :-)
 *
 *     - special treatment uid=0  
 */



#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif        


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/smp_lock.h>


#include <sys/syscall.h>
#include <linux/sched.h>  
#include <asm/uaccess.h>

#include <rk/rk_linux.h>
#include <rk/rk_error.h>
#include <rk/rk.h>

#include "rclmodule.h"

#define SOCK

#ifdef SOCK
#include "socketfilter.h"
#include <net/sock.h>
#endif


/*
 * Can't avoid gcc emitting __udivdi3... 
 *    ugly temporary fix.... miyos
 */ 
void __udivdi3(void){};

int (*set_rcl)(int);
int my_set_rcl(int);


/**************************************************
 * kernel module functions
 **************************************************/

/* Initialize the module - replace the system call */
int init_module(){

  /* Warning - too late for it now, but maybe for next time... */
  printk("Please do a sync before insmod\n and sync before rmmmod.\n");
  printk("eg. sync; sync; sync; insmod rkmodule\n");
  printk("eg. sync; sync; sync; rmmod rmmodule\n");
  
  
  /* TODO
   * should check if /proc/rk exists... 
   *    miyos
   */
  
  /* 
   * intercept/replace system calls 
   */
  /*
   * syscall filter
   */
  sys_fork_call                    = sys_call_table[__NR_fork];
  sys_call_table[__NR_fork]        = sys_fork_trapper;
  sys_vfork_call                   = sys_call_table[__NR_vfork];
  sys_call_table[__NR_vfork]       = sys_vfork_trapper;
  sys_clone_call                   = sys_call_table[__NR_clone];
  sys_call_table[__NR_clone]       = sys_clone_trapper;
  sys_execve_call                  = sys_call_table[__NR_execve];
  sys_call_table[__NR_execve]      = sys_execve_trapper;
  sys_exit_call                    = sys_call_table[__NR_exit];
  sys_call_table[__NR_exit]        = sys_exit_trapper;

  /*
   * socket filter
   */
#ifdef SOCK
  sys_socketcall                   = sys_call_table[__NR_socketcall];
  sys_call_table[__NR_socketcall]  = sys_socketcall_trapper;
#endif

  /*
   * system calls that we need.
   */ 
  sys_resource_set_attach_process  = sys_call_table[__NR_rk_resource_set_attach_process];
  sys_resource_set_detach_process  = sys_call_table[__NR_rk_resource_set_detach_process];
  sys_resource_set_create          = sys_call_table[__NR_rk_resource_set_create];
  /*sys_cpu_reserve_create           = sys_call_table[__NR_rk_cpu_reserve_create];*/
  sys_cpu_reserve_create           = cpu_reserve_create;
  sys_cpu_reserve_ctl              = cpu_reserve_ctl;
  sys_resource_set_destroy         = sys_call_table[__NR_rk_resource_set_destroy];
  getuid_call                      = sys_call_table[__NR_getuid];


  /* misc */
  if(set_rcl == NULL)
    set_rcl = my_set_rcl;
  
  init_manager(0);
  return 0;
}


/* Return the system call back to normal */
void cleanup_module(){

  if (sys_call_table[__NR_fork]   != sys_fork_trapper   ||
      sys_call_table[__NR_vfork]   != sys_vfork_trapper ||
      sys_call_table[__NR_clone]  != sys_clone_trapper  ||
      sys_call_table[__NR_exit]   != sys_exit_trapper   ||
#ifdef SOCK
      sys_call_table[__NR_socketcall]   != sys_socketcall_trapper ||
#endif
      sys_call_table[__NR_execve] != sys_execve_trapper ){
    printk("Warning: The system may be left in an unstable state.\n");
  }

  /*
   * todo: should free rk_uid_stats (and all dyanmically allocated memory)
   */
  
  sys_call_table[__NR_fork]                  = sys_fork_call;
  sys_call_table[__NR_vfork]                 = sys_vfork_call;
  sys_call_table[__NR_clone]                 = sys_clone_call;
  sys_call_table[__NR_exit]                  = sys_exit_call;
  sys_call_table[__NR_execve]                = sys_execve_call;
#ifdef SOCK
  sys_call_table[__NR_socketcall]            = sys_socketcall;
#endif

  /* misc */
  set_rcl = NULL;

  cleanup_socket();
  
  printk("rkmodule unloaded\n");
}  



