Upcoming Posts

Upcoming Posts....

Make your own partition magic software.
How to make an assembler.
What is booting?
Write a simple OS!

‎"I have no special talents. I am only passionately curious." - Albert Einstein

Tuesday, April 24, 2012

Write your own Socket library in C/C++ for Linux

We have read so many things about invoking System Calls on Linux. Theories are useless unless we implement them :) (at least I believe). Thus Let's play with sockets by calling System/Kernel services directly. i.e. we will not use methods provided by C runtime libs. We will implement methods of POSIX Socket API like socket, bind etc.

Linux provides single system call called "sys_socketcall" for socket related operations. Its System call number is 102 (defined as macro __NR_socketcall in /usr/include/asm/unistd.h). Its protype defined in kernel is as follows:

long sys_socketcall(int call, unsigned long *args)

The fist parameter 'call' is an integer that identifies the specific operation to be performed. The possible values for call are defined in /usr/include/linux/net.h. Some of them are listem below:

#define SYS_SOCKET      1               /* sys_socket(2)                */
#define SYS_BIND        2               /* sys_bind(2)                  */
#define SYS_CONNECT     3               /* sys_connect(2)               */
#define SYS_LISTEN      4               /* sys_listen(2)                */
#define SYS_ACCEPT      5               /* sys_accept(2)                */

The second parameter 'args' is a pointer to an array of 'long' containing arguments for the operation.

Let's implement POSIX socket creation method "int socket(int domain, int type, int protocol)":

int my_socket(int domain, int type, int protocol)
{
long arg[3], sock = 0;

/*
   Copy 'domain', 'type' and 'protocol' in 'arg' array. This array will be passed to system call as parameter to kernel.
 */

arg[0] = domain;
arg[1] = type;
arg[2] = protocol;

/* 
long sys_socketcall(int call, unsigned long *args) ;

To call above system call, we would need to copy "__NR_socketcall" System call no. into eax register,  "SYS_SOCKET" socket operation 'call' code into ebx, and an array of 'long' containing 'domain', 'type', 'protocol' into ecx register.

The following code does the same thing. For more informaiton, find on google 'assembly using gcc' :).
*/

asm(
"int $0x80\n\t"  /* int 0x80 invokes Linux system call */
:"=a"(sock)   /* system call returns output in eax register, copy eax
                                     registers value into sock  */
:"a"(__NR_socketcall), "b"(SYS_SOCKET), "c"(arg)

/*
Above line passes "__NR_socketcall" System call no into eax register,
"SYS_SOCKET" socket operation 'call' code into ebx,
and an array of 'long' containing 'domain', 'type', 'protocol' into ecx register.
*/
); /* asm statement ends here*/

return sock; /* return socket FD*/
}

For the sake of simplicity, I haven't perfomed sanity check. While writing your own implementation, please do perform sanity check before invoking System call.

Similarly, you can define all the socket methods like bind, listen,accept, send etc and can make your own Socket library. Is not it simple? May be I have picked the simple one ;) to System Call simple.


Please leave your comments!!!

1 comment: