#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include <linux/kthread.h>
#define NETLINK_TEST 17

MODULE_DESCRIPTION("Establish connection between user and kernel space");
MODULE_AUTHOR("root (root@localhost.localdomain)");
MODULE_LICENSE("$LICENSE$");

void wait_for_pid(struct sock *sk, int len);
static int waiting(void *);
void send(void );

struct sock *nl_sk = NULL;
struct sk_buff *skb;
struct nlmsghdr *nlh = NULL;
struct task_struct * wait_for_signal;
static u32 usrPID;
static int strat_signal;
EXPORT_SYMBOL(strat_signal);


static int connection_init_module(void)
{

	printk( KERN_DEBUG "Module connection init\n" );
	nl_sk = netlink_kernel_create(NETLINK_TEST, wait_for_pid);
	wait_for_signal=kthread_create(waiting,NULL,"wait");
	return 0;
}

static void connection_exit_module(void)
{
	printk( KERN_DEBUG "Module connection exit\n" );
	sock_release(nl_sk->sk_socket);
}

void wait_for_pid(struct sock *sk,int len)
{
	u32 pid=-1;
 	u8 *payload = NULL;
	int err;
	skb = skb_recv_datagram(nl_sk, 0, 0, &err);
	nlh = (struct nlmsghdr *)skb->data;
	printk("Received netlink message:%s\n",NLMSG_DATA(nlh));
	pid = nlh->nlmsg_pid;
	if(usrPID==0)
		usrPID=pid;
	printk("I've got your PID that is :%d\n",usrPID);
	if(usrPID)
		wake_up_process(wait_for_signal);
	
}

static int waiting(void *data)
{
	while(1)
	{
	
		while(!strat_signal)
		{
			msleep(1*1000);
		}
		printk("I've got stop signal\n");
		send();
		strat_signal=0;
		msleep(1*1000);
	}
	return 0;
}

inline void send(void)
{
	
	printk("<<<<<<<<inside send>>>>>>>>\n");
	NETLINK_CB(skb).groups = 0; /* not in mcast group */
 	NETLINK_CB(skb).pid = 0;      /* from kernel */
 	NETLINK_CB(skb).dst_pid = usrPID;
 	NETLINK_CB(skb).dst_groups = 0;  /* unicast */
 	netlink_unicast(nl_sk, skb, usrPID, MSG_DONTWAIT);
// 	sock_release(nl_sk->sk_socket);
}

module_init(connection_init_module);
module_exit(connection_exit_module);
