Monday, 23 January 2012

What is NETFILTER in linux?

INTRODUCTION
Netfilter is a framework that provides hook handling within the Linux kernel for intercepting and manipulating network packets.
Put more concretely, Netfilter is invoked, for example, by the packet reception and send routines from/to network interfaces.
As the master Netfilter function is called with a packet, Netfilter runs through the list of registered hooks and calls the extensions in succession, which then handle packets as they desire.
 Background
The actual Netfilter implementation is broken into two parts, the kernel portion known as Netfilter and the userland tool that interfaces with Netfilter and creates the rulesets, iptables. Both are required to implement your packet-filtering firewall.
Netfilter includes support for IPv4 and IPv6. 


 Kernel Configuration
 In order to get started using Netfilter, you'll need to have your kernel compiled for Netfilter support.
 Most distributions include this support by default, so a quick test is in order. If you can insert the module ip_tables, then you won't need to worry about this section.
 As root, run the command
omodprobe ip_tables
 Then run
olsmod | grep ip_tables
  
If ip_tables show up, you're in good shape. Then rebuild a kernel. 

Functionality of NET FILTER:
 
 IP packet filter
 A packet filter is a piece of software which looks at the header of packets as they pass through, and decides the fate of the entire packet. It might decide to DROP the packet (i.e., discard the packet as if it had never received it), ACCEPT the packet (i.e., let the packet go through), or something more complicated.
 Why it is required:
oControl : when you are using a Linux box to connect your internal network to another network (say, the Internet) you have an opportunity to allow certain types of traffic, and disallow others.
oSecurity :Simply don't let anyone connect in, by having the packet filter reject incoming packets used to set up connections.
oWatchfulness.

 Packet Mangling:
 Packet mangling is the modification of packets at a packet-based network interface before and/or after routing.
 The process is sometimes used to prioritize network traffic by changing Type of Service (ToS) values in packet headers and to label a packet for a particular user space application.
 NAT
 In computer networking, network address translation (NAT) is the process of modifying IP address information in IP packet headers while in transit across a traffic routing device.
 Firewall
 A firewall is a device or set of devices designed to permit or deny network transmissions based upon a set of rules and is frequently used to protect networks from unauthorized access while permitting legitimate communications to pass
Netfilter has two groups of components, the kernel and user-mode pieces. The user-mode group consists of the iptables and related utilities, libraries, manual pages and scripts.
Netfilter—how it works
  • Defines a set of hooks
  • §Hooks are well defined point in the path of packets when these packets pass through network stack
  • §The protocol code will jump into netfilter framework when it hits the hook point.
  •  Registers Kernel functions to these hooks:
  • §Called when a packet reaches at hook point
  • §Can decide the fate of the packets
  • §After the functions, the packet could continue its journey
  • §Five hooks defined in IPv4: PRE_ROUTING, LOCAL_IN, FORWARD, LOCAL_OUT, POST_ROUTING.
  • §Each hook can alter packets, return NF_DROP, NF_ACCEPT, NF_QUEUE, NF_REPEAT or NF_STOLEN.
 
  
1. Whenever a packet receives to kernel, the first hook which will be called is "PRE_ROUTING" Hook.

  2.  After that there is a router which will decide the fate of the packet, it means based on the destination IP address of the packet, it will decides whether the packet belongs to local(it will be given to Application space, receive these packets through UDP sockets in appl) or Non Local packets(Through Post Hook it will be send out).
  
3. To send the Non Local packets out via post Hook, the Linux machine should become router. It means the Forward hook should be enabled(ipv4.ip_forward =1)
       vim /proc/sys/net/ipv4/ip_forward
   change this ip_forward =0 to 1
   echo 1 > /proc/sys/net/ipv4/ip_forward
  
  4.  The Local generated packet from the application space, will be traversed via LOCAL_OUT and POST_HOOK.
e.g: If you ping to some machine, then the packet will be locally generated and go via LOCAL_OUT and POST_HOOK.

   5.  If the packet is destined to same Machine(Application Space of same Machine),  Then Packet will be traversed via PRE_HOOK and LOCAL_IN. 
Here no need to register a LOCAL_IN hook, in PRE_HOOK just do NF_ACCEPT , then all packets can be received in APPLICATION SPACE using UDP sockets.
Some Interesting Figures:
 
 
 
 
PRE_ROUTING  :  §Incoming packets pass this hook in ip_rcv() before routing
LOCAL_IN : § All incoming packets addressed to the local host pass this hook in ip_local_deliver()
FORWARD : § All incoming packets not addressed to the local host pass this hook in ip_forward()
LOCAL_OUT: §All outgoing packets created by this local computer pass this hook in ip_build_and_send_pkt()
POST_ROUTING: All outgoing packets (forwarded or locally created) will pass this hook in ip_finish_output()


 The netfilter function has five possible return values:  § 
NF_ACCEPT : continue callback chain
§NF_DROP     : drop the packet and stop the chain
§NF_STOLEN : stop the chain
§NF_QUEUE  : send the packet to userspace
§NF_REPEAT : call the hook again 

 This program will send packet to loop back interface, In kernel it will go to
APPLICATION CODE -> LOCAL_OUT -> POST_HOOK -> PRE_HOOK ->LOCAL_IN -> APPLICATION CODE

User SPACE Code -> compile  < c++ filename.cpp -lpthread -o test.exe>

#include <stdio.h>
#include <iostream.h>
#include <arpa/inet.h>
#include <string.h>

#define BUFFSIZE 5096

int sendlen, receivelen;
int i,count, sentCnt=0;
unsigned char buffer[BUFFSIZE];
/* client Socket */
struct sockaddr_in receivesocket;
/* Server Socket */
struct sockaddr_in sendsocket;

/* Sock FD */
int sockFd;

/* Number of Times you need */
unsigned int ch;
unsigned int noOfTimes;

/* Send UDP Data */
int sendUDPData();

/* Receive Call Back Function */
void *recvNetfilterData(void *);


int main(int argc, char *argv[]) {
int ret = 0;

   /* Create the UDP socket */
   if ((sockFd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
           perror("socket");
           return -1;
   }

   /* my address or Parameters ( These are required for Binding the Port and
        IP Address )
     Bind to my own port and Address */
   memset(&receivesocket, 0, sizeof(receivesocket));
   receivesocket.sin_family = AF_INET;
   receivesocket.sin_addr.s_addr = htonl(INADDR_ANY);
   receivesocket.sin_port = htons(2905);

   receivelen = sizeof(receivesocket);

   /* Bind the my Socket */
   if (bind(sockFd, (struct sockaddr *) &receivesocket, receivelen) < 0) {
           perror("bind");
           return -1;
   }

   /* Server address or Parameters , Sending System Address and Port Num */
   memset(&sendsocket, 0, sizeof(sendsocket));
   sendsocket.sin_family = AF_INET;
   /* give Proper IP address */
   sendsocket.sin_addr.s_addr = inet_addr("127.0.0.1");
   sendsocket.sin_port = htons(2905);

   /* Create Seperate Thread */
   /* Start the Receiving Thread */

   pthread_t threadId;
   if(pthread_create(&threadId, NULL, recvNetfilterData, NULL))
   {
       cout<<"Error in creating receiver thread";
       return 0;
   }


   /* Do Loop -> Send UDP Data */
   do
    {
       cout<<endl;
       cout<<" Enter your choice:\t"<<endl;
       cout<<" 1. Send UDP Data" <<endl;
       cout<<" 2. exit" <<endl;
       cin>>ch;
       cout<<endl;

       switch(ch)
       {

           case 1:
                   cout<<"Enter the Length of the Payload "<<endl;
                   cin>>sendlen;
                   cout<<"Enter How many times you want to send data "<<endl;
                   cin>>noOfTimes;
                   /* Send UDP Data */
                   sendUDPData();
                   break;

           default:
                  cout<<"Invalid Choice\n";
                  break;
       }
 }while(ch!=2);
return 0;
}
/*
 *  sendUDPData
 */
int sendUDPData()
{
        int count=0;
        memset(buffer, 31, sendlen);

        for(count=0; count< noOfTimes;  count++)
        {
           /* Send the UDP Data */
           if (sendto(sockFd, buffer, sendlen, 0,
     (struct sockaddr*)&sendsocket, sizeof(sendsocket)) != sendlen)                   
           {
                perror("sendto");
                return -1;
           }
           else
           {
                sentCnt++;
           }
         }
    return 0;
}
/*
 * Dump Data
 */
void dumpData(unsigned char *data,  unsigned int len)
{
    unsigned int uIndx;
     if(data)
    {
        for(uIndx=0; uIndx<len; ++uIndx)
        {
           if(uIndx%32 == 0)
           {
              printf("\n%4d:", uIndx);
           }
           if(uIndx%4 == 0)
           {
                 printf(" ");
           }
           printf("%02x", data[uIndx]);
        }
    }
    printf(" Length of Bytes: %d\n", len);
    printf("\n");
}

/*
 * recvNetfilterData()
 */
void *recvNetfilterData(void *args)
{
    unsigned char buf[5096];
    int receivedLen = 0;

    while(true)
    {
        memset(buf, 0, BUFFSIZE);
        /* Recieve the Data from Other system */
        if ((receivedLen = recvfrom(sockFd, buf, BUFFSIZE, 0, NULL, NULL)) < 0)
        {
  perror("recvfrom");
                return 0;
        }
        else if(receivedLen == 0)
        {
             cout<< " The Return Value is 0";
        }
        else
        {
              /* Print The data */
             cout<< " Recvd Byte length" << receivedLen <<endl;
             dumpData(buf, receivedLen);
        }
    }
}
Kernel SPACE Code -> Filename : muniTestNetfilter.c
Makefile
obj-m += netfil.o
netfil-objs :=  muniTestNetfilter.o
all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/version.h>
#include <linux/netlink.h>
#include<linux/udp.h>

/* Optional Headers  not Required, If you don't want Remove*/
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/socket.h>
#include <linux/icmp.h>

/* These are Required for NETFILTER functionality */
#include <net/checksum.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/interrupt.h>


#define DRIVER_AUTHOR_NAME  "MUNI"
#define DRIVER_DESCRIPTION  "NETFILTER"

#define DEST_PORT_NUM      2905

/* NETFILTER*/
static struct nf_hook_ops test_hookPreRouting;
static struct nf_hook_ops test_HookPostRouting;
/*
 * preRoutingHookEntryFunc -> Pre Routing Function
 */

static unsigned int preRoutingHookEntryFunc(
                       unsigned int unHookNum,
                       struct sk_buff **skb,
                       const struct net_device *inDevice,
                       const struct net_device *outDevice,
                       int (*okfn)(struct sk_buff *))
{
    /* Copy the Socket Buffer */
    struct sk_buff *sockBuff = *skb;

    /* Intialise  the UDP Header  */
    struct udphdr *uh = NULL;

    /* If the IP hdr is Zero or SockBuff is Zero Just Accept */
    if(NULL == sockBuff || NULL == sockBuff->nh.iph)
    return NF_ACCEPT;

    /* Point to the UDP Header */
    uh = (struct udphdr*)(sockBuff->data + (sockBuff->nh.iph->ihl * 4));

    /* Filter only UDP Packet */
    if((sockBuff->nh.iph->protocol == IPPROTO_UDP) &&
                       (ntohs(uh->dest) == DEST_PORT_NUM))
    {
        /* Retrieve Udp Header */
        printk(KERN_INFO " Recived Packet [ PRE HOOK ] with  IPDest:%x:PortNum:%d"
                "IPSrc%x:PortNum:%d\n",
               ntohl(sockBuff->nh.iph->daddr),ntohs(uh->dest),
               ntohl(sockBuff->nh.iph->saddr),ntohs(uh->source));
    }
   /*  All  Packets Just NF_ACCEPT
    *  If it is LOCAL packets then it will go to LOCAL_IN 
    *  to Application else for NON LOCAL Packets it will go 
    *  POST HOOK and Out
    */
    return NF_ACCEPT;
}
/*
 * postRoutingHookEntryFunc -> Post Routing Function
 *
 * POST HOOK will be called for NON LOCAL packets from 
 *  PRE_HOOK- POST HOOK via FORWARD
 * else LOCAL_OUT - POST HOOK for Local Generated Packets from the system(PING)

 *
 */
static unsigned int postRoutingHookEntryFunc(

        unsigned int unHookNum,
        struct sk_buff **skb,
        const struct net_device *inDevice,
        const struct net_device *outDevice,
        int (*okfn)(struct sk_buff *))
{
   /* Copy the Socket Buffer */
    struct sk_buff *sockBuff = *skb;

    /* Intialise  the UDP Header  */
    struct udphdr *uh = NULL;

    /* If the IP hdr is Zero or SockBuff is Zero Just Accept */
    if(NULL == sockBuff || NULL == sockBuff->nh.iph)
    return NF_ACCEPT;

    /* Point to the UDP Header */
    uh = (struct udphdr*)(sockBuff->data + (sockBuff->nh.iph->ihl * 4));

    /* Filter only UDP Packet */
   if((sockBuff->nh.iph->protocol == IPPROTO_UDP) &&
                     (ntohs(uh->dest) == DEST_PORT_NUM))
    {
        /* Retrieve Udp Header */
        printk(KERN_INFO " Recived Packet In [ POST HOOK ]  IPDest:%x:PortNum:%d"
                "IPSrc%x:PortNum:%d\n",
               ntohl(sockBuff->nh.iph->daddr),ntohs(uh->dest),
               ntohl(sockBuff->nh.iph->saddr),ntohs(uh->source));
    }

    /*  All  Packets Just do NF_ACCEPT
     *  then packets  will go Out of the Driver
    */
    return NF_ACCEPT;
}
/*
 * Module Init Function
 */
static int __init muni_test_netfilter_init(void)
{
    int unReturn = 0;

    printk(KERN_INFO "Loading MUNI NETFILTER Module\n");

    /* Intialisation of Pre Hook Parameters */

    /* Which Look You need to Call */
    test_hookPreRouting.hooknum  = NF_IP_PRE_ROUTING;
    /* Type of Family */
    test_hookPreRouting.pf       = PF_INET;
    /* Call back function for Prehook */
    test_hookPreRouting.hook     = preRoutingHookEntryFunc;
    /* Priority means, Which module receives the packet first
    * Here Priority = FIRST, means this module receives the packet first.
     */
    test_hookPreRouting.priority = NF_IP_PRI_FIRST;

    /* Register the Pre Routing Hook in Kernel */
    if((unReturn = nf_register_hook(&test_hookPreRouting)) < 0)
    {
        printk(KERN_INFO "Registration of Pre Routing"
                                " Hook is failed and ERROR=%d\n", unReturn);

        /* Un Register the Pre Routing Hook */
        nf_unregister_hook(&test_hookPreRouting);
        return unReturn;
    }

    /* Intialisation of Post Hook Parameters */
    test_HookPostRouting.hooknum = NF_IP_POST_ROUTING;
    test_HookPostRouting.pf      = PF_INET;
    /* Call back function for Post Hook  */
    test_HookPostRouting.hook    = postRoutingHookEntryFunc;

    /* Priority means, Which module receives the packet first
     * Here Priority = FIRST, means this module recives the packet first.
     */
    test_HookPostRouting.priority= NF_IP_PRI_FIRST;

    /* Register the Post Routing Hook in Kernel */
    if((unReturn = nf_register_hook(&test_HookPostRouting)) < 0)
    {
        printk(KERN_INFO "Registration of Post Routing"
                                "Hook is Failed and ERROR=%d\n", unReturn);
        /* Un Register the Post Routing Hook */
        nf_unregister_hook(&test_HookPostRouting);
        return unReturn;
    }

    return 0;
}

/*
 * Module Exit Function
 */
static void __exit muni_test_netfilter_exit(void)
{
    printk(KERN_INFO "UnLoading MUNI NETFILTER Module\n");

    /* Unregister the Pre Routing Hook */
    nf_unregister_hook(&
test_hookPreRouting);

    /* Unregister the Post Routing Hook */
    nf_unregister_hook(&test_HookPostRouting);

}
/* Init Module */
module_init(muni_test_netfilter_init);
/* Exit Module */
module_exit(muni_test_netfilter_exit);

/* Some MODULE PARAMETERS */
MODULE_LICENSE("COPY");
MODULE_AUTHOR(DRIVER_AUTHOR_NAME);
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
MODULE_VERSION("2.6.19.184");

Note:
  • The Same user Space Code can be modified to send as Non Local Packet. This can happen only  by changing the IP address of the server socket and also this code should run in different machine.
  • No need to explicitly declare the LOCAL_IN and LOCAL_OUT hooks, kernel will take care.

Tuesday, 17 January 2012

What are the ways of communication B/W User Space and Kernel Space

What is User Space and Kernel Space:
              Operating system segregates virtual memory into kernel space and user space
Kernel space is strictly reserved for running the kernel, kernel extensions, and most device drivers.
In contrast, user space is the memory area where all user mode applications work and this memory can be swapped out when necessary.


Different ways of Communication b/w User Space and Kernel Space:

There are many ways to Communicate between the User space and Kernel Space, they are:

File system based communication:
  • Procfs 
  • Sysfs 
  • Configfs 
  • Debugfs 
  • Sysctl
  • Character Devices 

Socket Based Communication: 

There are two types of sockets used for communication.

UDP Sockets

Netlink Socket.

In this post, i will be giving more importance for the Netlink socket based communication since this mechanism is extensively used in Linux networking applications.

What is NETLINK Socket:   

  • Netlink socket is a special IPC used for transferring information between kernel and user-space processes.    

  • It provides a full-duplex communication link between the two by way of standard socket APIs for user-space processes and a special kernel API for kernel modules.

  • vNetlink socket uses the address family AF_NETLINK, as compared to AF_INET used by TCP/IP socket.
  • vEach netlink socket feature defines its own protocol type in the kernel header file include/linux/netlink.h 


 Why do the above features use netlink instead of system calls, ioctls or proc filesystems for communication between user and kernel worlds?

  • vIt is a nontrivial task to add system calls, ioctls or proc files for new features; we risk polluting the kernel and damaging the stability of the system.
  • vNetlink socket is simple, though: only a constant, the protocol type, needs to be added to netlink.h.
  • vThen, the kernel module and application can talk using socket-style APIs immediately
  • vNetlink is asynchronous because, as with any other socket API, it provides a socket queue to smooth the burst of messages.
  • vThe system call for sending a netlink message queues the message to the receiver's netlink queue and then invokes the receiver's reception handler.
  • vThe receiver, within the reception handler's context, can decide whether to process the message immediately or leave the message in the queue and process it later in a different context.
  • vUnlike netlink, system calls require synchronous processing. Therefore, if we use a system call to pass a message from user space to the kernel, the kernel scheduling granularity may be affected if the time to process that message is long.

v           NetLink sockets can be used for Multicast.
  
Standard API's

vThe standard socket APIs—socket(), sendmsg() or sendto(), recvmsg() or recvFrom() and close()—can be used by user-space applications to access netlink socket.
int socket(int domain, int type, int protocol)
 The socket domain (address family) is AF_NETLINK, and the type of socket is either SOCK_RAW or SOCK_DGRAM, because netlink is a datagram-oriented service.
 The protocol (protocol type) selects for which netlink feature the socket is used. The following are some predefined netlink protocol types: NETLINK_ROUTE, NETLINK_FIREWALL, NETLINK_ARPD, NETLINK_ROUTE6 and NETLINK_IP6_FW. You also can add your own netlink protocol type easily.

Standard API's for Kernel Space:

How to Create Netlink socket in kernel?

struct sock* 
netlink_kernel_create(struct net *net,int unit,unsigned int groups, 
                  void (*input)(struct sk_buff *skb), 
                  struct mutex *cb_mutex, 
                  struct module *module)
 
 e.g:  No need to pass the net parameter.

/* Create NetLink Socket */
nlSock = netlink_kernel_create 
                                 ( NETLINK_MUNISOCK,    // Unit can be Protocol Type
                                    0,                                            // Groups can be Zero
                                   msgFromNetLinkSock,         // Call Back Function

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
                                   NULL,                                      // Mutex can be zero

#endif
                                   THIS_MODULE);

 
 Important Hint: The value of NETLINK_MUNISOCK should be same in User space and Kernel Space 
                                    This is nothing about protocol Type and it should be same in User space and Kernel Space.
    
                                   cat  /proc/net/netlink  -> To check the netlink Sock ID's in kernel


How to send a unicast message to user Space?
 
int
netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock);
e.g: 
int Error;
Error = netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
if(Error == -1)
{
    printk(KERN_INFO "Unable to send Info Back to User Space\n");
}
 
How to de-queue netlink message from Call back function in Kernel Space?
  
skb = skb_dequeue(&sk->receive_queue))
 
E.g: 
static void msgFromNetLinkSock(struct sock *sk, int nLength)
{
             struct sk_buff *skb;
     struct nlmsghdr *nlh = NULL;
     unsigned char *payload = NULL;

     while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) 
     {
         /* process netlink message pointed by skb->data */
         nlh = (struct nlmsghdr *)skb->data;
         payload = NLMSG_DATA(nlh);
         /* process netlink message with header pointed by
          * nlh and payload pointed by payload
          */
      }
}


Working Code For NETLINK Socket: 

Kernel Space Code:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/version.h>
#include <linux/netlink.h>
#include<linux/udp.h>

/* Optional Headers  not Required, If you don't want Remove*/
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/socket.h>
#include <linux/icmp.h>

/* These Headers are also Optional (Not Required),
   But these are Required for NETFILTER functionality */
#include <net/checksum.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/interrupt.h>

/* NetLink Definitions */
#define NETLINK_HEADER_SIZE     16
#define NETLINK_MUNISOCK        25
#define NL_MSG_TYPE             20

#define MAX_BUFFER_SIZE         1024

/* Driver Definitions */
#define DRIVER_AUTHOR      "AMSEKHAR"
#define DRIVER_DESC        "SAMPLE_NETLINK_SOCKET"

#define MAX_DATA_SIZE      50

/* Dump Function */
static void dumpRecvData(unsigned char *data, unsigned int dataLen);

/* Declare Buffer */
unsigned char *ucBuffer = NULL;

/* Netlink Sock ID*/
static struct sock *nl_sock_id = NULL;

/* Process Id */
static pid_t pid = 0;

/*
 * Function Name : dumpRecvData()
 */
void dumpRecvData(unsigned char *data,  unsigned int len)
{
    unsigned int uIndx=0;

    printk("The Data:\n");
    if(data)
    {
           for(uIndx=0; uIndx<len; ++uIndx)
          {
                 if(uIndx%32 == 0)
                {
                     printk("\n%4d:", uIndx);
                 }
                if(uIndx%4 == 0)
               {
                       printk(" ");
               }
               printk("%02x", data[uIndx]);
         }
    }
    printk(" Length of Bytes: %d\n", len);
    printk("\n");
}
/*
 * Function Name : sendDataToUserSpace()
*/
void sendDataToUserSpace(unsigned char  *ucBuffer, int unDataLen)
{
    /* Intialise the Sk buffer */
    struct sk_buff *skb = NULL;

    /* Intialise the Netlink message Hdr */
    struct nlmsghdr *nlhdr = NULL;

    int nRet= 0;

    /* Allocate the Memory Using SKB for sending To Appl Space */
   skb = alloc_skb((unDataLen + sizeof (struct nlmsghdr)), GFP_ATOMIC);

    /* Move the Tail Pointer at end of the Buffer */
    skb_put(skb, (unDataLen + sizeof (struct nlmsghdr)));

    /* Validate the Skb */
    if(NULL != skb)
    {
        nlhdr = (struct nlmsghdr *)skb->data;

        nlhdr->nlmsg_len = NLMSG_SPACE(MAX_BUFFER_SIZE);
        /*pid=0 corresponds to kernel */
        nlhdr->nlmsg_pid = 0;
        nlhdr->nlmsg_flags = 0;
        nlhdr->nlmsg_seq = 1;
        nlhdr->nlmsg_type = NL_MSG_TYPE;

        /* Copy the Payload */
        memmove(NLMSG_DATA(nlhdr), ucBuffer, unDataLen);

        NETLINK_CB(skb).pid = 0;

        /*BSGATM.exe Process ID */
        NETLINK_CB(skb).dst_pid = pid ;
        NETLINK_CB(skb).dst_group = 0;  /* unicast */

        /* send the NetLink Message to Application space */
      nRet = netlink_unicast(nl_sock_id, skb, pid, MSG_DONTWAIT);

        if(nRet == -1)
        {
            printk("Not Send Successfully\n");
            kfree_skb(skb);
        }
        else
        {
            printk(" Successfully sent to Application space\n");
        }
    }
}


 /*
  * Function Name : MsgFromNetLinkSock
  */
static void msgFromNetLinkSock(struct sock *sk, int len)
{
    struct sk_buff *skb = NULL;
    struct nlmsghdr *nlhdr = NULL;
    int type, unDataLen;
    /* skb_dequeue takes the  buffer from a queue.
     * Nothing(No Buffer) is there then it return  NULL pointer.*/
    while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
    {

        /* Extract the NetLink Header fields for Processing */
        nlhdr = (struct nlmsghdr *)skb->data;

        if(nlhdr->nlmsg_pid != 0)
        {
            pid = nlhdr->nlmsg_pid; /*pid of sending process */
        }
        /* Copy the Type of message */
        type = nlhdr->nlmsg_type;

        if (type != NL_MSG_TYPE)
        {
            printk(KERN_INFO "Recieved Message Type :%d", type);
            kfree_skb(skb);
            continue;
        }
        /* Point the data to Buffer */
        ucBuffer = NLMSG_DATA(nlhdr);
        
        /* Compute Actual Length */
        /* skb->len and nlhdr->nlmsg_len are same.*/
        //or unDataLen = nlhdr->nlmsg_len - NETLINK_HDR_SIZE;
        unDataLen = skb->len - NETLINK_HEADER_SIZE;

        /* dump Recieved Data*/
        dumpRecvData(ucBuffer, unDataLen);

        
        /* Send the Data to User SPace from Kernel */
        sendDataToUserSpace(ucBuffer, unDataLen);

   
      /* If this is not there, then it will throw an atomic error */
        kfree_skb(skb);

    }
}

/*
 * Function Name : netlinkProcess_init()
*/

static int __init init_netlinkAppl(void)
{

    printk(KERN_INFO "NFNL Loading netlinkProcess  Module\n");

    // Create NetLink Socket
    nl_sock_id = netlink_kernel_create(NETLINK_MUNISOCK,
                                    0,
                                    msgFromNetLinkSock,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
                                    NULL,
#endif
                                    THIS_MODULE);
    if(!nl_sock_id)
    {
        printk(KERN_ERR "NFNL %s: receive handler registration failed\n", __func__);
        return -ENOMEM;
    }

    return 0;
}
 /*
 * Function Name : cleanup Module()
 */

static void __exit exit_netlinkAppl(void)
{
    printk(KERN_INFO "NFNL UnLoading netlinkProcess  Module\n");
    if(nl_sock_id)
    {
        //netlink_kernel_release(nl_sock_id);
        sock_release(nl_sock_id->sk_socket);
    }
}

/* Module Init and exit */
module_init(init_netlinkAppl);
module_exit(exit_netlinkAppl);

/* Module properties */
MODULE_LICENSE("Proprietary");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION("2.6.18.194");


How to compile the Kernel Space Code

1. Create Makefile
2. Copy the below contents in to Makefile.


obj-m += netlinksock.o
netlinksock-objs := netlinkProcess.o
all:
  make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
  make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean




User Space Code:

#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/netlink.h>

/* Netlink Defines */
#define NL_MSG_TYPE         20
#define NETLINK_MUNISOCK    25
#define NETLINK_HEADER_SIZE 16
#define MAX_DATA_SIZE       30

/* Socket FD */
int netlinkSockFD;
struct sockaddr_nl SrcAddr;
struct sockaddr_nl DestAddr;

/* Sequence No */
int SeqNo;
/* process Id */
pid_t PID;

/* Configure The Structure */
unsigned char ucBuffer[MAX_DATA_SIZE];

/*
 * Name            : SendMessage()
 */
bool sendDataToKernel(int len)
{
    unsigned char buf[1024]={0};
    bool ret = false;
    int errno;
    unsigned int uIndx;

    /* Intialise the buffer */
    for(uIndx=0; uIndx<len; uIndx++)
    {
       ucBuffer[uIndx] = 0x31;
    }

    struct nlmsghdr *nlh = (struct nlmsghdr*)buf;

    nlh->nlmsg_len = (len + NETLINK_HEADER_SIZE );
    nlh->nlmsg_pid = PID;  /* self pid */

    nlh->nlmsg_seq = SeqNo++;
    nlh->nlmsg_flags = 0;
    nlh->nlmsg_type = NL_MSG_TYPE;

    /* Copy the Buffer */
    memcpy(NLMSG_DATA(nlh), &ucBuffer, len);

    /* Send the Data */
    int res = sendto(netlinkSockFD, nlh, nlh->nlmsg_len, 0,
                   (const struct sockaddr*) &DestAddr, sizeof(struct sockaddr_nl));
    if(-1 == res)
    {
        cout<<"Unable to Transmit Netlink Message: "<<strerror(errno);
        return ret;
    }
    return (ret=true);
}


/*
 * Function Name : dumpData()
 */
void dumpData(unsigned char *data,  unsigned int len)
{
    unsigned int uIndx;

    if(data)
    {
        for(uIndx=0; uIndx<len; ++uIndx)
        {
           if(uIndx%32 == 0)
           {
              printf("\n%4d:", uIndx);
           }
           if(uIndx%4 == 0)
           {
                 printf(" ");
           }
           //printf("%02x", data[uIndx]);
           printf("%02x", *(data + uIndx));
        }
    }
    printf("\n Length of Bytes: %d\n", len);
    printf("\n");
}

/*
 * Func: recvMsgFromKernel()
 */

void *recvMsgFromKernel(void *args)
{
    unsigned char ucBuffer[1024];
    struct sockaddr_nl client_addr;
    socklen_t size = sizeof(struct sockaddr_nl);
    int length =0;

    while(true)
    {
        memset(ucBuffer, 0,1024);

        // Recieve Data from Kernel
        length = recvfrom(netlinkSockFD, ucBuffer, 1024 , MSG_NOSIGNAL, (struct sockaddr*)&client_addr, &size);
        if (length > 0 )
        {
             struct nlmsghdr *nlh = (struct nlmsghdr*) ucBuffer;
             if(0 != nlh->nlmsg_pid)
             {
                 printf("\nReceived Message from Unknown Source\n");
                 continue;
             }
             else
             {
                 unsigned char ucBuf[1024];
                 unsigned int unActualLen = length - sizeof (struct nlmsghdr);
                 memmove(&ucBuf, NLMSG_DATA(nlh), length - sizeof(struct nlmsghdr));
                 /* dump Recieved Data */
                dumpData(ucBuf, unActualLen);
             }
         }
    }
}

 
/*
 * Name            : main()
 */
int main()
{
    bool ret;
    int ch, len, errno;


    /* Intialise Socket Paramters */
    netlinkSockFD = -1;
    PID = getpid();
    SeqNo = 0;
    memset(&DestAddr, 0, sizeof(struct sockaddr_nl));
    memset(&SrcAddr, 0, sizeof(struct sockaddr_nl));
          

          //create receive thread
    pthread_t threadId;

    if(pthread_create(&threadId, NULL, recvMsgFromKernel, NULL))
    {
        perror("Error in creating receiver thread");
        return -1;
    }

    /* Create NetLink Socket */
    netlinkSockFD = socket(PF_NETLINK, SOCK_RAW, NETLINK_MUNISOCK);
    if(netlinkSockFD == -1)
    {
        cout<< "Unable to open socket - " << strerror(errno);
        return 0;
    }
   else
    {
       cout<< "Netlink Socket created Successfully\n";
    }

    memset(&DestAddr, 0, sizeof(struct sockaddr_nl));
    DestAddr.nl_family = AF_NETLINK;
    DestAddr.nl_pid = 0; /* For Linux Kernel */
    DestAddr.nl_groups = 0; /* unicast */

    do
    {
       cout<<endl;
       cout<<" Enter your choice:\t"<<endl;
       cout<<" 1. Send Data to Kernel" <<endl;
       cout<<" 2. exit" <<endl;
       cin>>ch;
       cout<<endl;

       switch(ch)
       {
           case 1:
              {
                   cout<<"Enter the Length of the Payload "<<endl;
                   cin>>len;

                   ret = sendDataToKernel(len);
                   if(ret)
                   {
                        cout<<"\n Netlink Socket Sent successfully \n";
                   }
                   else
                   {
                        cout<<"\n Netlink Socket Failed in Sending Message \n";
                   }
                   break;
               }
           default:
                  cout<<"Invalid Choice\n";
                  break;
       }
    }while(ch!=2);
}


How to compile the user space code:

> First save this file as userNetLinkSock.cpp then compile using below command

> c++ userNetLinkSock.cpp -lpthread -o user


 



 TIPS For NetLink Socket:

> While allocating memory for SKB,   once allocate memory , after that "skb_put" to be there to move the tail pointer appropriately.

    e.g:
    skb = alloc_skb((unDataLen + sizeof (struct nlmsghdr)) , GFP_ATOMIC);

    /* Move the Tail Pointer at end of the Buffer */
    skb_put(skb, (unDataLen + sizeof (struct nlmsghdr)));

> Set the destination PID value(while sending data to user space) appropriately depending on the receiving application.

> To avoid this kind of error :assertion (!atomic_read(&sk->sk_rmem_alloc)) failed, ensure that the skb is freed after being dequeued and processed.  ( SKB Should be freed in De-queue Function)       e.g: static void msgFromNetLinkSock(struct sock *sk, int len)                                                                  {
     /* skb_dequeue takes the  buffer from a queue.
      * Nothing(No Buffer) is there then it return  NULL pointer.*/
    while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
    {

        /* Send the Data to User SPace from Kernel */
        xxfunction(ucBuffer, unDataLen);

        kfree_skb(skb);   // free the SKB
    }
}                          

> While sending the data from user space, the net link message length should be                           actual data len+  NETLINK Header size 

e.g:  nlh->nlmsg_len = (len+NETLINK_HEADER_SIZE(16)

> The payload of any buffer should be stored in NLMSG_DATA(nlhdr).

e.g: while receiving data from user space , then point the   ucBuffer = NLMSG_DATA(nlhdr);           

e.g:   While sending data from kernel,                                                                                                                /* Copy the Payload */
        memmove(NLMSG_DATA(nlhdr), ucBuffer, unDataLen);
                                                                       

For Further reading:   http://people.ee.ethz.ch/~arkeller/linux/kernel_user_space_howto.html