Wednesday, June 26, 2013

GNS3 non superuser setup

GNS3 non superuser setup

What is GNS3 ? Who can use it ?   
    http://www.gns3.net/

The video-tutorial section under site has a tutorial on how to setup GNS3 in linux at /opt/ through sudo (superuser). But I had some issues while I tried to setup VirtualBox along with it to Link guest PCs. So tried installing it as non superuser, here is how I did it

GNS3 non superuser setup


>Download gns3 and dynamips
    gns3(tar.bz2) : http://www.gns3.net/download/
    dynamips(bin) : http://www.gns3.net/dynamips/

>Unzip gns3 to a folder, say GNS3/
  (I did it in a dir in /home/melwin/Downloads)

>Move dynamips to GNS3/

>Make dynamips executable
    chmod +x dynamips-0.2.8-RC3-community-x86.bin

>Run GNS3/gns3.pyw (either from terminal or GUI)

>Enter Project Name. Change Project Dir location if required

>Locate dynamips
    Edit>Preference>Dynamips>Settings>Executable path to Dynamips
    Locate the .bin that we justed moved to GNS3/
    To test click "Test Settings"
        If "Dynamips 0.2.8-RC3 successfully started" message then OK

>Locate IOS dir
    Edit>Preference>General>General Settings[tab]>Paths>OS images
    Locate the Cisco IOS image directory

>Locate project dir [if not during startup]
    Edit>Preference>General>General Settings[tab]>Paths>Project Directory
    Locate the project directory

>Add IOS images
    Edit>IOS images and hypervisiors>IOS Images[tab]>Settings>Image file
    Locate the Cisco IOS image file (.bin)
    If asked for uncompression, allow
    Select Platform and Model based on the IOS image
    Click Save
        There will be a "waring:IDLE PC will have to be configured" we will get there
    Click Close
    (    My Image : c7200-adventerprisek9-mz.124-2.T2.bin
        so platform:c7200 and model:7200
    )

>Drag-drop router
    From the left panel drag and drop the router whose image has been uploaded
    Right click the router (in the middle panel) and click start to start the router

>Select Idle PC value
    Check CPU History, if any of your CPU has high utilization then IDLE PC value has to been configured
    Right the running router and click "IDLE-PC"
    Wait for GNS3 to calculate and show the list of IDLE PC value(s)
    Select the IDLE-PC value that has a * with it.
    If * not present on any value, select the one with minimum value within the []
    Check CPU History, if CPU utilization drops then OK else repeat these steps.

>Save topology
    File>Save or Save As
    Located the topology.net file in the Project Dir if asked

Since we have installed GNS3 as non-superuser, an error("Can't start dynamips at 127.0.0.1 port 7200") might occur. In this case, you will have to locate and test the dynamips everytime you start GNS3.

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

Saturday, January 26, 2013

Simple HTTP Server Programming



Simple HTTP Server

Prerequisites : Socket and thread programming

HTTP is a protocol used for communication between a browser and a web server.

How HTTP works : When you type in  a URL in the browser and click GO the browser extracts the host-name section and uses DNS to obtain the IP address of the web server that host the web site. The browser then uses this IP address to form a TCP connection to the web server. The browser sends HTTP request to retrieve a specific page. If the page exist the server responds by sending the copy of the page in the HTTP response (response code - 400). If the file doesn't exists in the server, the server send  HTTP response containing a response code 404 (Not Found Error Message).


HTTP Request

  The request message syntax:
  • Request line, for eg :  GET /images/logo.png HTTP/1.1
  • Headers
  • An empty line.
  • An optional message body.
  Example of a simple HTTP request:
    GET / HTTP/1.1
    Host: 127.0.0.1:2003

Explanation:
Line 1 : "GET" indicates the request method used . Other methods are PUT, POST etc
     "/" indicates the requested page, here its the root page i.e index.html
     "HTTP/1.1" version of HTTP used
Line 2 : "HOST" host to which request is send
"127.0.0.1" IP address of host
"2003" is the port used

More about HTTP request and headers can be found at
http://en.wikipedia.org/wiki/HTTP_request


HTTP Response
The response message consists of the following:
  • A Status-Line
  • Headers
  • An empty line
  • An optional message body
Example:
HTTP/1.1 200 OK
  Content-type: text/html
<html>
<head></head>
<body>
 <h1>Header</h1>
 <p>Congrats !! your HTTP server is working.</p>
</body>
</html>

Explanation :
Line 1 : "HTTP/1.1" HTTP version used
"200" status code
"OK" description of status code
Line 2 : "Content-type: text/html" indicates type of the file.
Line 3 : HTML code of the page

More about HTTP response and headers
http://en.wikipedia.org/wiki/HTTP_response

HTTP status code
                http://en.wikipedia.org/wiki/List_of_HTTP_status_codes




/*------------------------------Simple HTTP Server----------------------------*/


#include<sys/socket.h>
#include<sys/stat.h>  
#include<sys/types.h>  
#include<netinet/in.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include <netdb.h>

#define BUFF_LEN 1028

pthread_t c;

/* HTTP response and header for a successful request.  */
static char* ok_response =
  "HTTP/1.1 200 OK\n"
  "Content-type: text/html\n"
  "\n"
  "<html>\n"
  "<head></head>\n"
  " <body>\n"
  "  <h1>Header</h1>\n"
  "  <p>Congrats !! your HTTP server is working.</p>\n"
  " </body>\n"
  "</html>\n";

void * serve_client(int tsd)
{
int k;
char buff[BUFF_LEN]; //used to store the HTTP request
printf("[Server : %d].\n",tsd);
k=recv(tsd,buff,BUFF_LEN,0);
if(k==-1)
printf("[Server : %d] recv() failed.\n",tsd);
else printf("[Server : %d] recv() OK .\n",tsd);

// Printing the HTTP request recieved
printf("[Server : %d] Recieved : %s\n",tsd,buff);

/* Actual HTTP server does some processing and responds accordingly.
* Here I have just send a HTTP response.
*/

//Sending the HTTP response
write (tsd, ok_response, strlen (ok_response));

close(tsd);
printf("[Server : %d] going to pthread_exit().\n\n",tsd);
pthread_exit(NULL);
}


int main(int argc,char *argv[])
{ char buff[100];
int k;
socklen_t len;
int sock_desc,temp_sock_desc;
short port;
struct sockaddr_in server,client;

printf("[Server] Start . Next memset()\n");
memset(&server,0,sizeof(server));
memset(&client,0,sizeof(client));

printf("[Server] memset() OK . Next socket()\n");
sock_desc=socket(AF_INET,SOCK_STREAM,0);
printf("[Server] socket() OK . Next bind()\n");
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
port = (argc > 1) ? atoi(argv[1]) : 3001; //default port : 3001
server.sin_port=htons(port);

k=bind(sock_desc,(struct sockaddr*)&server,sizeof(server));
if(k==-1)
printf("[Server] bind() failed.\n");
else printf("[Server] bind() OK . Next listen()\n");

k=listen(sock_desc,10);
if(k==-1)
printf("[Server] listen() failed.\n");
else printf("[Server] listen() OK . Next accept()\n");

len=sizeof(client);

while(1)
{
temp_sock_desc=accept(sock_desc,(struct sockaddr*)&client,&len);
printf("\n[Server] accept() OK .\n");

printf("[Server] Client IP : %s.\n",(char*)inet_ntoa(client.sin_addr));
printf("[Server] sock_desc : %d.\n",sock_desc);
printf("[Server] temp_sock_desc : %d.\n",temp_sock_desc);

/*
* Start a thread to server each client.
*/
pthread_create( &c,NULL,(void *)serve_client, (int *) temp_sock_desc);

}

close(temp_sock_desc);
close(sock_desc);
exit(0);
return 0;
}

/*------------------------------End Of Program----------------------------*/



Working :

This programs waits for a client to connect and then starts a thread to serve the client.
This thread recieves a message(HTTP request) from the client and sends a HTTP response
to the client.

A real HTTP server does more than this. It includes

  • checking if the requested file exist and send response accordingly.
  • Integration of Server side scripting languages like PHP,ASP,JSP.etc
  • status code based actions
  • caching
  • and so on


By parsing through the HTTP request the requirements of the client can be understood and
required output can be generated.


Compiling and running :

  1. Copy the code and paste it in a file,say "server.c"
  2. compile : gcc server.c -lpthread
  3. run : ./a.out 2001
  4. In browser : http://127.0.0.1:2001/