Tuesday, April 30, 2013

Network Programming in the Kernel


Prerequisites : Socket and Module programming

Advantage of implementing application within the kernel : 
  • The overhead associated with user-space/kernel-space transition can be avoided by implementing the application completely in the Kernel Space .
  • In specific research and high-performance computing environments, there is a need for achieving data transfers at great speeds. Kernel applications find use in such situations.
Disadvantages:
  • Security is a primary concern within the kernel, since kernel process run with unlimited privileges.Consequently, special care needs to be taken while designing in-kernel applications.
  • Large applications cannot be implemented in the kernel due to memory constraints.
  • Every kernel needs a specific implementation route.
  • Failure in the web server may cause the OS to crash.



/*  
 * Called when a process writes to dev file
 * Stores the string written to the device in
 * local buffer and sends the string using
 * SOCK_STREAM to 127.0.0.1:2001
 */
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
int ret; //return value
int k,leng;
struct sockaddr_in server;
struct socket *soc=NULL;
struct iovec iov;
struct msghdr msgh;
mm_segment_t oldmm;
printk(KERN_INFO "[device_write]File opened for writing\n");

ret=copy_from_user(msg,buff,80);
//buff : buffer that accepts the string from 
// the program that issued a write.
// Points to user area memory
//msg  : kernel/module space that hold the 
// value written.
msgh.msg_name     = 0;
msgh.msg_namelen  = 0;
// Socket address members msg_name and msg_namelen.
// Required only when your socket is a datagram socket.
// msg_name member points to the socket address that 
// you are sending to or receiving from.

    msgh.msg_iov      = &iov;
    msgh.msg_iovlen   = 1;
// I/O vector references msg_iov and msg_iovlen.
// msg_iov member points to the struct iovec array.
// msg_iovlen indicates how many elements are in your 
// I/O vector array 

    msgh.msg_control  = NULL;
    msgh.msg_controllen = 0;
// Ancillary data buffer members msg_control    
// and msg_controllen. Used to pass protocol-specific 
// control messages. No control messages for TCP.

    msgh.msg_flags    = MSG_DONTWAIT;
// Received message flag bits msg_flags.
// MSG_DONTWAIT prevents the system call from blocking if, 
// for example, there are no data to be received.

    oldmm = get_fs();
    set_fs(KERNEL_DS);
// get_fs returns the current segment descriptor stored in FS.
// set_fs stores a descriptor into FS, so it will be used for 
//  data transfer instructions.

    msgh.msg_iov->iov_len = 80;
    msgh.msg_iov->iov_base = (char *) msg;

    printk(KERN_INFO "[chardev:device_write] msg : %s\n",msg);

    k=sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&soc);
    memset(&server,0,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=2001;
    server.sin_addr.s_addr=inet_addr("127.0.0.1");
    k=soc->ops->connect(soc,(struct sockaddr *)&server,sizeof(server),O_RDWR);
    if(k!=-1) printk(KERN_INFO"[device_write] connect() OK. Next sock_sendmsg().\n");
    else printk(KERN_INFO"[device_write] connect() FAILED. Next sock_sendmsg().\n");
    leng = sock_sendmsg(soc, &msgh, 80);
//msg length 80
    if(leng) printk(KERN_INFO"[device_write] sock_sendmsg() OK. Next close().\n");
    else printk(KERN_INFO"[device_write] sock_sendmsg() FAILED. Next close().\n");
    sock_release(soc);

return ret;
}

Further Reading :
 In-Kernel Web Sever

 kHTTPd