#define MODULE // this is a LKM
#include <linux/module.h> // for Module access
//#include <linux/kernel.h> // For kernel access
#include <sys/syscall.h> // for the SYS_socketcall value

#include <linux/net.h> // For the various sys_socketcall parameters
//#include <asm/unistd.h>
#include <asm/errno.h> // For the error return values
#include <asm/uaccess.h> // for copy_from_user



// Define a debug print statement
#define BBPRINT(a) printk("%s(%i): %s\n", __FILE__, __LINE__, a)
 
// Type define a byte -> unsigned char
typedef unsigned char byte;

// Our friendly neighborhood system call table
extern void* sys_call_table[];

// Taken from socket.c
// Argument list sizes for sys_socketcall
#define AL(x) ((x) * sizeof(unsigned long))
static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
				AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
				AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};


// Create our orginal function pointer
int (*original_socketcall)(int call, unsigned long *args);

// Our function's advance declaration
int my_socketcall(int call, unsigned long *args);

int init_module(void)
{
	BBPRINT("Loading Socket LKM");

	// Save the original location	
	original_socketcall = sys_call_table[SYS_socketcall];

	// Replace the table entry with our socketcall
	sys_call_table[SYS_socketcall] = my_socketcall; 

	return 0;
}

// This is run when the module is unloaded
void cleanup_module(void)
{
	//Go back to the orignal socketcall
	sys_call_table[SYS_socketcall] = original_socketcall;

	BBPRINT("Unloading Socket LKM");
}


int my_socketcall(int call, unsigned long *args)
{
	unsigned long a[6];
	unsigned long a0,a1;

	int err;

	if(call < 1 || call > SYS_RECVMSG)
		return -EINVAL;

	// copy_from_user should be SMP safe.
	if (copy_from_user(a, args, nargs[call]))
		return -EFAULT;
		
	a0=a[0];
	a1=a[1];


	// Call the original function
	return(original_socketcall(call, args));
}
