<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Binary Tides &#187; Linux</title>
	<atom:link href="http://www.binarytides.com/blog/category/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.binarytides.com/blog</link>
	<description>Socket Programming , Game Programming , PHP , Mysql , Ubuntu etc.</description>
	<lastBuildDate>Thu, 02 Feb 2012 09:31:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Compile wxwebconnect on Ubuntu 11.04 64 bit</title>
		<link>http://www.binarytides.com/blog/compile-wxwebconnect-on-ubuntu-11-04-64-bit/</link>
		<comments>http://www.binarytides.com/blog/compile-wxwebconnect-on-ubuntu-11-04-64-bit/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 09:31:28 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[wxwidgets]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1346</guid>
		<description><![CDATA[wxwebconnect is a control for wxwidgets that allows to embed a gecko browser in a wxwidgets application. So lets try to install it on Ubuntu 11.04 wxWidgets can be installed from synaptic. Look for packages called libwxgtk2.8-* 1. Download wxwebconnect source from http://www.kirix.com/labs/wxwebconnect/downloads.html Extract them in home directory. Inside the webconnect directory you would see directories like webconnect , xr and testapp. 2. Over here create a directory called wxWidgets. Download wxwidgets 2.8.12 from here [...]]]></description>
			<content:encoded><![CDATA[<p>wxwebconnect is a control for wxwidgets that allows to embed a gecko browser in a wxwidgets application.</p>
<p>So lets try to install it on Ubuntu 11.04</p>
<p>wxWidgets can be installed from synaptic. Look for packages called libwxgtk2.8-*</p>
<p>1. Download wxwebconnect source from http://www.kirix.com/labs/wxwebconnect/downloads.html<br />
Extract them in home directory. Inside the webconnect directory you would see directories like webconnect , xr and testapp.</p>
<p>2. Over here create a directory called wxWidgets. Download wxwidgets 2.8.12 from here http://www.wxwidgets.org/downloads/<br />
wxGTK for Ubuntu.</p>
<p>3. Extract wxwidgets inside  /home/user/webconnect-1.1/wxWidgets</p>
<p>4. You would also need libgtk2.0-dev first, so installed it from synaptic. Now do a ./configure and make for wxwidgets<br />
Once this process is over wxwidgets should be build.</p>
<p>5. Now do a make inside /home/user/webconnect-1.1/webconnect</p>
<p>6. Now do a make inside /home/user/webconnect-1.1/testapp.</p>
<p>7. Now everything is compiled. But one this still remains is xulrunner. You need xulrunner 1.9.x . The one available on Mozilla website will not work. So lets do a trick. Install the xulrunner-1.9.2 package from synaptic.</p>
<p>It will install all xulrunner files in /usr/lib/xulrunner-1.9.2.17/ or a similar location. Go there and copy everything. First empty the /home/user/webconnect-1.1/xr directory and then paste everything here.</p>
<p>8. Now go inside testapp and execute the testapp binary which we created a while back. It should run and open webpages fine.</p>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1346&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/compile-wxwebconnect-on-ubuntu-11-04-64-bit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Whois client code in C with Linux sockets</title>
		<link>http://www.binarytides.com/blog/whois-client-code-in-c-with-linux-sockets/</link>
		<comments>http://www.binarytides.com/blog/whois-client-code-in-c-with-linux-sockets/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 06:47:17 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Sockets]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1266</guid>
		<description><![CDATA[A whois client is a program that will simply fetch the whois information for a domain/ip address from the whois servers. The code over here works according to the algorithm discussed here. Code hostname_to_ip &#8211; This is a simple function to get an IP of a domain. str_replace &#8211; This is a generic string processing function that is used to search for a string in another big string and replace it with another string. Output]]></description>
			<content:encoded><![CDATA[<p>A whois client is a program that will simply fetch the whois information for a domain/ip address from the whois servers. The code over here works according to the algorithm discussed here.</p>
<p><strong>Code</strong></p>
<pre class="brush: cpp; title: Code; notranslate">
/*
 * @brief
 * Whois client program
 *
 * @details
 * This program shall perform whois for a domain and get you the whois data of that domain
 *
 * @author Silver Moon ( m00n.silv3r@gmail.com )
 * */

#include&lt;stdio.h&gt;	//scanf , printf
#include&lt;string.h&gt;	//strtok
#include&lt;stdlib.h&gt;	//realloc
#include&lt;sys/socket.h&gt;	//socket
#include&lt;netinet/in.h&gt; //sockaddr_in
#include&lt;arpa/inet.h&gt;	//getsockname
#include&lt;netdb.h&gt;	//hostent
#include&lt;unistd.h&gt;	//close

int get_whois_data(char * , char **);
int hostname_to_ip(char * , char *);
int whois_query(char * , char * , char **);
char *str_replace(char *search , char *replace , char *subject );

int main(int argc , char *argv[])
{
	char domain[100] , *data = NULL;

	printf(&quot;Enter domain name to whois : &quot;);
	scanf(&quot;%s&quot; , domain);

	get_whois_data(domain , &amp;data);

	//puts(data);
	return 0;
}

/*
 * Get the whois data of a domain
 * */
int get_whois_data(char *domain , char **data)
{
	char ext[1024] , *pch , *response = NULL , *response_2 = NULL , *wch , *dt;

	//remove &quot;http://&quot; and &quot;www.&quot;
	domain = str_replace(&quot;http://&quot; , &quot;&quot; , domain);
	domain = str_replace(&quot;www.&quot; , &quot;&quot; , domain);

	//get the extension , com , org , edu
	dt = strdup(domain);
	if(dt == NULL)
	{
		printf(&quot;strdup failed&quot;);
	}
	pch = (char*)strtok(dt , &quot;.&quot;);
	while(pch != NULL)
	{
		strcpy(ext , pch);
		pch = strtok(NULL , &quot;.&quot;);
	}

	//This will tell the whois server for the particular TLD like com , org
	if(whois_query(&quot;whois.iana.org&quot; , ext , &amp;response))
	{
		printf(&quot;Whois query failed&quot;);
	}

	//Now analysze the response :)
	pch = strtok(response , &quot;\n&quot;);
	while(pch != NULL)
	{
		//Check if whois line
		wch = strstr(pch , &quot;whois.&quot;);
		if(wch != NULL)
		{
			break;
		}

		//Next line please
		pch = strtok(NULL , &quot;\n&quot;);
	}

	//Now we have the TLD whois server in wch , query again
	//This will provide minimal whois information along with the parent whois server of the specific domain :)
	free(response);
	//This should not be necessary , but segmentation fault without this , why ?
	response = NULL;
	if(wch != NULL)
	{
		printf(&quot;\nTLD Whois server is : %s&quot; , wch);
		if(whois_query(wch , domain , &amp;response))
		{
			printf(&quot;Whois query failed&quot;);
		}
	}
	else
	{
		printf(&quot;\nTLD whois server for %s not found&quot; , ext);
		return 1;
	}

	response_2 = strdup(response);

	//Again search for a whois server in this response. :)
	pch = strtok(response , &quot;\n&quot;);
	while(pch != NULL)
	{
		//Check if whois line
		wch = strstr(pch , &quot;whois.&quot;);
		if(wch != NULL)
		{
			break;
		}

		//Next line please
		pch = strtok(NULL , &quot;\n&quot;);
	}

	/*
	 * If a registrar whois server is found then query it
	 * */
	if(wch)
	{
		//Now we have the registrar whois server , this has the direct full information of the particular domain
		//so lets query again

		printf(&quot;\nRegistrar Whois server is : %s&quot; , wch);

		if(whois_query(wch , domain , &amp;response))
		{
			printf(&quot;Whois query failed&quot;);
		}

		printf(&quot;\n%s&quot; , response);
	}

	/*
	 * otherwise echo the output from the previous whois result
	 * */
	else
	{
		printf(&quot;%s&quot; , response_2);
	}
	return 0;
}

/*
 * Perform a whois query to a server and record the response
 * */
int whois_query(char *server , char *query , char **response)
{
	char ip[32] , message[100] , buffer[1500];
	int sock , read_size , total_size = 0;
	struct sockaddr_in dest;

	sock = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);

    //Prepare connection structures :)
    memset( &amp;dest , 0 , sizeof(dest) );
    dest.sin_family = AF_INET;

	printf(&quot;\nResolving %s...&quot; , server);
	if(hostname_to_ip(server , ip))
	{
		printf(&quot;Failed&quot;);
		return 1;
	}
	printf(&quot;%s&quot; , ip);
	dest.sin_addr.s_addr = inet_addr( ip );
	dest.sin_port = htons( 43 );

	//Now connect to remote server
	if(connect( sock , (const struct sockaddr*) &amp;dest , sizeof(dest) ) &lt; 0)
	{
		perror(&quot;connect failed&quot;);
	}

	//Now send some data or message
	printf(&quot;\nQuerying for ... %s ...&quot; , query);
	sprintf(message , &quot;%s\r\n&quot; , query);
	if( send(sock , message , strlen(message) , 0) &lt; 0)
	{
		perror(&quot;send failed&quot;);
	}

	//Now receive the response
	while( (read_size = recv(sock , buffer , sizeof(buffer) , 0) ) )
	{
		*response = realloc(*response , read_size + total_size);
		if(*response == NULL)
		{
			printf(&quot;realloc failed&quot;);
		}
		memcpy(*response + total_size , buffer , read_size);
		total_size += read_size;
	}
	printf(&quot;Done&quot;);
	fflush(stdout);

	*response = realloc(*response , total_size + 1);
	*(*response + total_size) = '&#92;&#48;';

	close(sock);
	return 0;
}

/*
 * @brief
 * Get the ip address of a given hostname
 *
 * */
int hostname_to_ip(char * hostname , char* ip)
{
	struct hostent *he;
	struct in_addr **addr_list;
	int i;

	if ( (he = gethostbyname( hostname ) ) == NULL)
	{
		// get the host info
		herror(&quot;gethostbyname&quot;);
		return 1;
	}

	addr_list = (struct in_addr **) he-&gt;h_addr_list;

	for(i = 0; addr_list[i] != NULL; i++)
	{
		//Return the first one;
		strcpy(ip , inet_ntoa(*addr_list[i]) );
		return 0;
	}

	return 0;
}

/*
 * Search and replace a string with another string , in a string
 * */
char *str_replace(char *search , char *replace , char *subject)
{
	char  *p = NULL , *old = NULL , *new_subject = NULL ;
	int c = 0 , search_size;

	search_size = strlen(search);

	//Count how many occurences
	for(p = strstr(subject , search) ; p != NULL ; p = strstr(p + search_size , search))
	{
		c++;
	}

	//Final size
	c = ( strlen(replace) - search_size )*c + strlen(subject);

	//New subject with new size
	new_subject = malloc( c );

	//Set it to blank
	strcpy(new_subject , &quot;&quot;);

	//The start position
	old = subject;

	for(p = strstr(subject , search) ; p != NULL ; p = strstr(p + search_size , search))
	{
		//move ahead and copy some text from original subject , from a certain position
		strncpy(new_subject + strlen(new_subject) , old , p - old);

		//move ahead and copy the replacement text
		strcpy(new_subject + strlen(new_subject) , replace);

		//The new start position after this search match
		old = p + search_size;
	}

	//Copy the part after the last search match
	strcpy(new_subject + strlen(new_subject) , old);

	return new_subject;
}
</pre>
<p>hostname_to_ip &#8211; This is a simple function to get an IP of a domain.<br />
str_replace &#8211; This is a generic string processing function that is used to search for a string in another big string and replace it with another string.</p>
<p><strong>Output</strong></p>
<pre class="brush: bash; title: Code; notranslate">
Enter domain name to whois : www.wikipedia.org

Resolving whois.iana.org...192.0.47.59
Querying for ... org ...Done
TLD Whois server is : whois.pir.org
Resolving whois.pir.org...149.17.192.7
Querying for ... wikipedia.org ...DoneAccess to .ORG WHOIS information is provided to assist persons in
determining the contents of a domain name registration record in the
Public Interest Registry registry database. The data in this record is provided by
Public Interest Registry for informational purposes only, and Public Interest Registry does not
guarantee its accuracy.  This service is intended only for query-based
access. You agree that you will use this data only for lawful purposes
and that, under no circumstances will you use this data to: (a) allow,
enable, or otherwise support the transmission by e-mail, telephone, or
facsimile of mass unsolicited, commercial advertising or solicitations
to entities other than the data recipient's own existing customers; or
(b) enable high volume, automated, electronic processes that send
queries or data to the systems of Registry Operator, a Registrar, or
Afilias except as reasonably necessary to register domain names or
modify existing registrations. All rights reserved. Public Interest Registry reserves
the right to modify these terms at any time. By submitting this query,
you agree to abide by this policy. 

Domain ID:D51687756-LROR
Domain Name:WIKIPEDIA.ORG
Created On:13-Jan-2001 00:12:14 UTC
Last Updated On:02-Dec-2009 20:57:17 UTC
Expiration Date:13-Jan-2015 00:12:14 UTC
Sponsoring Registrar:GoDaddy.com, Inc. (R91-LROR)
Status:CLIENT DELETE PROHIBITED
Status:CLIENT RENEW PROHIBITED
Status:CLIENT TRANSFER PROHIBITED
Status:CLIENT UPDATE PROHIBITED
Registrant ID:CR31094073
Registrant Name:DNS Admin
Registrant Organization:Wikimedia Foundation, Inc.
Registrant Street1:149 New Montgomery Street
Registrant Street2:Third Floor
Registrant Street3:
Registrant City:San Francisco
Registrant State/Province:California
Registrant Postal Code:94105
Registrant Country:US
Registrant Phone:+1.4158396885
Registrant Phone Ext.:
Registrant FAX:+1.4158820495
Registrant FAX Ext.:
Registrant Email:dns-admin@wikimedia.org
Admin ID:CR31094075
Admin Name:DNS Admin
Admin Organization:Wikimedia Foundation, Inc.
Admin Street1:149 New Montgomery Street
Admin Street2:Third Floor
Admin Street3:
Admin City:San Francisco
Admin State/Province:California
Admin Postal Code:94105
Admin Country:US
Admin Phone:+1.4158396885
Admin Phone Ext.:
Admin FAX:+1.4158820495
Admin FAX Ext.:
Admin Email:dns-admin@wikimedia.org
Tech ID:CR31094074
Tech Name:DNS Admin
Tech Organization:Wikimedia Foundation, Inc.
Tech Street1:149 New Montgomery Street
Tech Street2:Third Floor
Tech Street3:
Tech City:San Francisco
Tech State/Province:California
Tech Postal Code:94105
Tech Country:US
Tech Phone:+1.4158396885
Tech Phone Ext.:
Tech FAX:+1.4158820495
Tech FAX Ext.:
Tech Email:dns-admin@wikimedia.org
Name Server:NS0.WIKIMEDIA.ORG
Name Server:NS1.WIKIMEDIA.ORG
Name Server:NS2.WIKIMEDIA.ORG
Name Server:
Name Server:
Name Server:
Name Server:
Name Server:
Name Server:
Name Server:
Name Server:
Name Server:
Name Server:
DNSSEC:Unsigned
</pre>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1266&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/whois-client-code-in-c-with-linux-sockets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Get local ip in C on linux</title>
		<link>http://www.binarytides.com/blog/get-local-ip-in-c-on-linux/</link>
		<comments>http://www.binarytides.com/blog/get-local-ip-in-c-on-linux/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 06:41:04 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Sockets]]></category>
		<category><![CDATA[c]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1248</guid>
		<description><![CDATA[The local ip is the source ip in IP packets send out from a system. The kernal maintains routing tables which it uses to decide the default gateway , its interface and the local ip configured for that interface. The /proc/net/route file (not really a file but appears like one) has more information about it. A typical /proc/net/route output would look like : The above lists the interface , destination , gateway etc. The interface [...]]]></description>
			<content:encoded><![CDATA[<p>The local ip is the source ip in IP packets send out from a system. The kernal maintains routing tables which it uses to decide the default gateway , its interface and the local ip configured for that interface. The <em>/proc/net/route</em> file (not really a file but appears like one) has more information about it.</p>
<p>A typical <em>/proc/net/route</em> output would look like :</p>
<pre class="brush: bash; title: Code; notranslate">
$ cat /proc/net/route
Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask            MTU     Window  IRTT
eth0    0000A8C0        00000000        0001    0       0       1       00FFFFFF        0       0       0
eth0    0000FEA9        00000000        0001    0       0       1000    0000FFFF        0       0       0
eth0    00000000        0100A8C0        0003    0       0       0       00000000        0       0       0
</pre>
<p>The above lists the interface , destination , gateway etc. The interface (Iface) whose destination is 00000000 is the interface of the default gateway.</p>
<p>Now have a look at the route command output</p>
<pre class="brush: bash; title: Code; notranslate">
$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.0     0.0.0.0         255.255.255.0   U     1      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0
0.0.0.0         192.168.0.1     0.0.0.0         UG    0      0        0 eth0
</pre>
<p>Now the gateway for the destination 0.0.0.0 is the default gateway. So from the /proc/net/route output this line is of interest :</p>
<pre class="brush: bash; title: Code; notranslate">
eth0    00000000        0100A8C0        0003    0       0       0       00000000        0       0       0
</pre>
<p>Its destination is 00000000 and gateway is 0100A8C0. The gateway is actually the IP address of the gateway in hex format in reverse order (little endian). Its 01.00.A8.C0 or 1.0.168.192</p>
<p>So by reading that line in a C program we can find out the default gateway and its interface. The IP address of this interface shall be the source ip in IP packets send out from this system.</p>
<p>The code for this is pretty simple as we can see :</p>
<pre class="brush: cpp; title: Code; notranslate">

FILE *f;
char line[100] , *p , *c;

f = fopen(&quot;/proc/net/route&quot; , &quot;r&quot;);

while(fgets(line , 100 , f))
{
	p = strtok(line , &quot; \t&quot;);
	c = strtok(NULL , &quot; \t&quot;);

	if(p!=NULL &amp;&amp; c!=NULL)
	{
		if(strcmp(c , &quot;00000000&quot;) == 0)
		{
			printf(&quot;Default interface is : %s \n&quot; , p);
			break;
		}
	}
}
</pre>
<p>The above code prints : &#8220;Default interface is : eth0&#8243;</p>
<p>Now we need to get the ip address of the default interface eth0. The getnameinfo function can be used for this.<br />
Sample code is found <a target="_blank" href="http://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html" >here</a>.</p>
<p>Combining that with our previous code we get :</p>
<pre class="brush: cpp; title: Code; notranslate">
/*
 * Find local ip used as source ip in ip packets.
 * Read the /proc/net/route file
 */

#include&lt;stdio.h&gt;	//printf
#include&lt;string.h&gt;	//memset
#include&lt;errno.h&gt;	//errno
#include&lt;sys/socket.h&gt;
#include&lt;netdb.h&gt;
#include&lt;ifaddrs.h&gt;
#include&lt;stdlib.h&gt;
#include&lt;unistd.h&gt;

int main ( int argc , char *argv[] )
{
    FILE *f;
    char line[100] , *p , *c;

    f = fopen(&quot;/proc/net/route&quot; , &quot;r&quot;);

    while(fgets(line , 100 , f))
    {
		p = strtok(line , &quot; \t&quot;);
		c = strtok(NULL , &quot; \t&quot;);

		if(p!=NULL &amp;&amp; c!=NULL)
		{
			if(strcmp(c , &quot;00000000&quot;) == 0)
			{
				printf(&quot;Default interface is : %s \n&quot; , p);
				break;
			}
		}
	}

    //which family do we require , AF_INET or AF_INET6
    int fm = AF_INET;
    struct ifaddrs *ifaddr, *ifa;
	int family , s;
	char host[NI_MAXHOST];

	if (getifaddrs(&amp;ifaddr) == -1)
	{
		perror(&quot;getifaddrs&quot;);
		exit(EXIT_FAILURE);
	}

	//Walk through linked list, maintaining head pointer so we can free list later
	for (ifa = ifaddr; ifa != NULL; ifa = ifa-&gt;ifa_next)
	{
		if (ifa-&gt;ifa_addr == NULL)
		{
			continue;
		}

		family = ifa-&gt;ifa_addr-&gt;sa_family;

		if(strcmp( ifa-&gt;ifa_name , p) == 0)
		{
			if (family == fm)
			{
				s = getnameinfo( ifa-&gt;ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6) , host , NI_MAXHOST , NULL , 0 , NI_NUMERICHOST);

				if (s != 0)
				{
					printf(&quot;getnameinfo() failed: %s\n&quot;, gai_strerror(s));
					exit(EXIT_FAILURE);
				}

				printf(&quot;address: %s&quot;, host);
			}
			printf(&quot;\n&quot;);
		}
	}

	freeifaddrs(ifaddr);

	return 0;
}
</pre>
<p><strong>Output</strong></p>
<pre class="brush: bash; title: Code; notranslate">
Default interface is : eth0 

address: 192.168.0.6
</pre>
<p>Another method is to open a connection to a remote server and call getsockname</p>
<p><strong>Code</strong></p>
<pre class="brush: cpp; title: Code; notranslate">
/*
 * Find local ip used as source ip in ip packets.
 * Use getsockname and a udp connection
 */

#include&lt;stdio.h&gt;	//printf
#include&lt;string.h&gt;	//memset
#include&lt;errno.h&gt;	//errno
#include&lt;sys/socket.h&gt;	//socket
#include&lt;netinet/in.h&gt; //sockaddr_in
#include&lt;arpa/inet.h&gt;	//getsockname
#include&lt;unistd.h&gt;	//close

int main ( int argc , char *argv[] )
{
    const char* google_dns_server = &quot;8.8.8.8&quot;;
    int dns_port = 53;

	struct sockaddr_in serv;

    int sock = socket ( AF_INET, SOCK_DGRAM, 0);

    //Socket could not be created
    if(sock &lt; 0)
    {
		perror(&quot;Socket error&quot;);
	}

	memset( &amp;serv, 0, sizeof(serv) );
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = inet_addr( google_dns_server );
    serv.sin_port = htons( dns_port );

    int err = connect( sock , (const struct sockaddr*) &amp;serv , sizeof(serv) );

    struct sockaddr_in name;
    socklen_t namelen = sizeof(name);
    err = getsockname(sock, (struct sockaddr*) &amp;name, &amp;namelen);

	char buffer[100];
    const char* p = inet_ntop(AF_INET, &amp;name.sin_addr, buffer, 100);

	if(p != NULL)
	{
		printf(&quot;Local ip is : %s \n&quot; , buffer);
	}
	else
	{
		//Some error
		printf (&quot;Error number : %d . Error message : %s \n&quot; , errno , strerror(errno));
	}

    close(sock);

    return 0;
}
</pre>
<p><strong>Output</strong></p>
<pre class="brush: bash; title: Code; notranslate">
Local ip is : 192.168.0.6
</pre>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1248&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/get-local-ip-in-c-on-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Get ip address from hostname in C using Linux sockets</title>
		<link>http://www.binarytides.com/blog/get-ip-address-from-hostname-in-c-using-linux-sockets/</link>
		<comments>http://www.binarytides.com/blog/get-ip-address-from-hostname-in-c-using-linux-sockets/#comments</comments>
		<pubDate>Sat, 10 Dec 2011 15:17:55 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Sockets]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1194</guid>
		<description><![CDATA[Here are 2 methods to get the ip address of a hostname : The first method uses the traditional gethostbyname function to retrieve information about a hostname/domain name. Code Compile and Run The second method uses the getaddrinfo function to retrieve information about a hostname/domain name. Code Compile and Run]]></description>
			<content:encoded><![CDATA[<p>Here are 2 methods to get the ip address of a hostname :</p>
<p>The first method uses the traditional gethostbyname function to retrieve information about a hostname/domain name.<br />
<strong>Code</strong></p>
<pre class="brush: cpp; title: Code; notranslate">
#include&lt;stdio.h&gt; //printf
#include&lt;string.h&gt; //memset
#include&lt;stdlib.h&gt; //for exit(0);
#include&lt;sys/socket.h&gt;
#include&lt;errno.h&gt; //For errno - the error number
#include&lt;netdb.h&gt;	//hostent
#include&lt;arpa/inet.h&gt;

int hostname_to_ip(char *  , char *);

int main(int argc , char *argv[])
{
	if(argc &lt;2)
	{
		printf(&quot;Please provide a hostname to resolve&quot;);
		exit(1);
	}

	char *hostname = argv[1];
	char ip[100];

	hostname_to_ip(hostname , ip);
	printf(&quot;%s resolved to %s&quot; , hostname , ip);

	printf(&quot;\n&quot;);

}
/*
	Get ip from domain name
 */

int hostname_to_ip(char * hostname , char* ip)
{
	struct hostent *he;
	struct in_addr **addr_list;
	int i;

	if ( (he = gethostbyname( hostname ) ) == NULL)
	{
		// get the host info
		herror(&quot;gethostbyname&quot;);
		return 1;
	}

	addr_list = (struct in_addr **) he-&gt;h_addr_list;

	for(i = 0; addr_list[i] != NULL; i++)
	{
		//Return the first one;
		strcpy(ip , inet_ntoa(*addr_list[i]) );
		return 0;
	}

	return 1;
}
</pre>
<p><strong>Compile and Run</strong></p>
<pre class="brush: bash; title: Code; notranslate">

$ gcc hostname_to_ip.c &amp;&amp; ./a.out www.google.com
www.google.com resolved to 74.125.235.16

$ gcc hostname_to_ip.c &amp;&amp; ./a.out www.msn.com
www.msn.com resolved to 207.46.140.34

$ gcc hostname_to_ip.c &amp;&amp; ./a.out www.yahoo.com
www.yahoo.com resolved to 98.137.149.56
</pre>
<p>The second method uses the getaddrinfo function to retrieve information about a hostname/domain name.<br />
<strong>Code</strong></p>
<pre class="brush: cpp; title: Code; notranslate">
#include&lt;stdio.h&gt; //printf
#include&lt;string.h&gt; //memset
#include&lt;stdlib.h&gt; //for exit(0);
#include&lt;sys/socket.h&gt;
#include&lt;errno.h&gt; //For errno - the error number
#include&lt;netdb.h&gt;	//hostent
#include&lt;arpa/inet.h&gt;

int hostname_to_ip(char *  , char *);

int main(int argc , char *argv[])
{
	if(argc &lt;2)
	{
		printf(&quot;Please provide a hostname to resolve&quot;);
		exit(1);
	}

	char *hostname = argv[1];
	char ip[100];

	hostname_to_ip(hostname , ip);
	printf(&quot;%s resolved to %s&quot; , hostname , ip);

	printf(&quot;\n&quot;);

}
/*
	Get ip from domain name
 */

int hostname_to_ip(char *hostname , char *ip)
{
	int sockfd;
	struct addrinfo hints, *servinfo, *p;
	struct sockaddr_in *h;
	int rv;

	memset(&amp;hints, 0, sizeof hints);
	hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
	hints.ai_socktype = SOCK_STREAM;

	if ( (rv = getaddrinfo( hostname , &quot;http&quot; , &amp;hints , &amp;servinfo)) != 0)
	{
		fprintf(stderr, &quot;getaddrinfo: %s\n&quot;, gai_strerror(rv));
		return 1;
	}

	// loop through all the results and connect to the first we can
	for(p = servinfo; p != NULL; p = p-&gt;ai_next)
	{
		h = (struct sockaddr_in *) p-&gt;ai_addr;
		strcpy(ip , inet_ntoa( h-&gt;sin_addr ) );
	}

	freeaddrinfo(servinfo); // all done with this structure
	return 0;
}
</pre>
<p><strong>Compile and Run</strong></p>
<pre class="brush: bash; title: Code; notranslate">
$ gcc hostname_to_ip.c &amp;&amp; ./a.out www.google.com
www.google.com resolved to 74.125.235.19

$ gcc hostname_to_ip.c &amp;&amp; ./a.out www.yahoo.com
www.yahoo.com resolved to 72.30.2.43

$ gcc hostname_to_ip.c &amp;&amp; ./a.out www.msn.com
www.msn.com resolved to 207.46.140.34
</pre>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1194&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/get-ip-address-from-hostname-in-c-using-linux-sockets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Check which mpm (multi processing module) apache is running</title>
		<link>http://www.binarytides.com/blog/check-which-mpm-multi-processing-module-apache-is-running/</link>
		<comments>http://www.binarytides.com/blog/check-which-mpm-multi-processing-module-apache-is-running/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 14:39:56 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[apache]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1178</guid>
		<description><![CDATA[There are different mpm like : 1. worker 2. prefork 3. itk 4. peruser Apache might be running one of them. mpms are not modules that are loaded by apache. Instead they are compiled into apache. To check which mpm apache is using run the following command : Ubuntu On Ubuntu Apache is called apache2 Tha above command is used to find the apache binary Now run the apache binary with the l option : [...]]]></description>
			<content:encoded><![CDATA[<p>There are different mpm like :<br />
1. worker<br />
2. prefork<br />
3. itk<br />
4. peruser</p>
<p>Apache might be running one of them. mpms are not modules that are loaded by apache. Instead they are compiled into apache.</p>
<p>To check which mpm apache is using run the following command :</p>
<p><strong>Ubuntu</strong></p>
<p>On Ubuntu Apache is called apache2</p>
<pre class="brush: bash; title: Code; notranslate">
$ whereis apache2
apache2: /usr/sbin/apache2 /etc/apache2 /usr/lib/apache2 /usr/lib64/apache2 /usr/share/apache2 /usr/share/man/man8/apache2.8.gz
</pre>
<p>Tha above command is used to find the apache binary</p>
<p>Now run the apache binary with the l option :</p>
<pre class="brush: bash; title: Code; notranslate">
$ /usr/sbin/apache2 -l
Compiled in modules:
  core.c
  mod_log_config.c
  mod_logio.c
  worker.c
  http_core.c
  mod_so.c
</pre>
<p>The above commands provide a list of modules that are compiled into apache. Over there it can be seen that worker.c is in the list. So mpm worker is being used.</p>
<p>Another method is to execute the apache binary with the V option :</p>
<pre class="brush: bash; title: Code; notranslate">
$ /usr/sbin/apache2 -V
Server version: Apache/2.2.17 (Ubuntu)
Server built:   Nov  3 2011 02:15:48
Server's Module Magic Number: 20051115:25
Server loaded:  APR 1.4.2, APR-Util 1.3.9
Compiled using: APR 1.4.2, APR-Util 1.3.9
Architecture:   64-bit
Server MPM:     Worker
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR=&quot;server/mpm/worker&quot;
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT=&quot;/etc/apache2&quot;
 -D SUEXEC_BIN=&quot;/usr/lib/apache2/suexec&quot;
 -D DEFAULT_PIDLOG=&quot;/var/run/apache2.pid&quot;
 -D DEFAULT_SCOREBOARD=&quot;logs/apache_runtime_status&quot;
 -D DEFAULT_ERRORLOG=&quot;logs/error_log&quot;
 -D AP_TYPES_CONFIG_FILE=&quot;mime.types&quot;
 -D SERVER_CONFIG_FILE=&quot;apache2.conf&quot;
</pre>
<p>It provides various information about the MPM (name , threaded , forked) :<br />
<code><br />
Server MPM:     Worker<br />
  threaded:     yes (fixed thread count)<br />
    forked:     yes (variable process count)<br />
</code></p>
<p>A shorter command can be :</p>
<pre class="brush: bash; title: Code; notranslate">
$ /usr/sbin/apache2 -V | grep MPM
Server MPM:     Worker
 -D APACHE_MPM_DIR=&quot;server/mpm/worker&quot;
</pre>
<p><strong>CentOS</strong></p>
<p>On CentOS Apache is called httpd</p>
<pre class="brush: bash; title: Code; notranslate">
# whereis httpd
httpd: /usr/sbin/httpd /etc/httpd.old /etc/httpd
</pre>
<pre class="brush: bash; title: Code; notranslate">
# /usr/sbin/httpd -l
/usr/sbin/httpd: line 63: ulimit: open files: cannot modify limit: Operation not permitted
/usr/sbin/httpd: line 64: ulimit: open files: cannot modify limit: Operation not permitted
/usr/sbin/httpd: line 65: ulimit: open files: cannot modify limit: Operation not permitted
Compiled in modules:
  core.c
  mod_authn_file.c
  mod_authn_default.c
  mod_authz_host.c
  mod_authz_groupfile.c
  mod_authz_user.c
  mod_authz_default.c
  mod_auth_basic.c
  mod_cache.c
  mod_include.c
  mod_filter.c
  mod_deflate.c
  mod_log_config.c
  mod_logio.c
  mod_env.c
  mod_expires.c
  mod_headers.c
  mod_unique_id.c
  mod_setenvif.c
  mod_version.c
  mod_proxy.c
  mod_proxy_connect.c
  mod_proxy_ftp.c
  mod_proxy_http.c
  mod_proxy_scgi.c
  mod_proxy_ajp.c
  mod_proxy_balancer.c
  mod_ssl.c
  prefork.c
  http_core.c
  mod_mime.c
  mod_status.c
  mod_autoindex.c
  mod_asis.c
  mod_info.c
  mod_suexec.c
  mod_cgi.c
  mod_negotiation.c
  mod_dir.c
  mod_actions.c
  mod_userdir.c
  mod_alias.c
  mod_rewrite.c
  mod_so.c
</pre>
<p>It shows the prefork mpm.</p>
<pre class="brush: bash; title: Code; notranslate">
# /usr/sbin/httpd -V
/usr/sbin/httpd: line 63: ulimit: open files: cannot modify limit: Operation not permitted
/usr/sbin/httpd: line 64: ulimit: open files: cannot modify limit: Operation not permitted
/usr/sbin/httpd: line 65: ulimit: open files: cannot modify limit: Operation not permitted
Server version: Apache/2.2.17 (Unix)
Server built:   Feb 12 2011 11:30:46
Cpanel::Easy::Apache v3.2.0 rev5291
Server's Module Magic Number: 20051115:25
Server loaded:  APR 1.4.2, APR-Util 1.3.10
Compiled using: APR 1.4.2, APR-Util 1.3.10
Architecture:   32-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR=&quot;server/mpm/prefork&quot;
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT=&quot;/usr/local/apache&quot;
 -D SUEXEC_BIN=&quot;/usr/local/apache/bin/suexec&quot;
 -D DEFAULT_PIDLOG=&quot;logs/httpd.pid&quot;
 -D DEFAULT_SCOREBOARD=&quot;logs/apache_runtime_status&quot;
 -D DEFAULT_LOCKFILE=&quot;logs/accept.lock&quot;
 -D DEFAULT_ERRORLOG=&quot;logs/error_log&quot;
 -D AP_TYPES_CONFIG_FILE=&quot;conf/mime.types&quot;
 -D SERVER_CONFIG_FILE=&quot;conf/httpd.conf&quot;
</pre>
<p>The mpm information is :<br />
<code><br />
Server MPM:     Prefork<br />
  threaded:     no<br />
    forked:     yes (variable process count)<br />
</code></p>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1178&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/check-which-mpm-multi-processing-module-apache-is-running/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux command to check distro</title>
		<link>http://www.binarytides.com/blog/linux-command-to-check-distro/</link>
		<comments>http://www.binarytides.com/blog/linux-command-to-check-distro/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 12:36:49 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1174</guid>
		<description><![CDATA[Here are a few commands which can be used to find out which distribution a particular Linux system is. lsb_release command cat /etc/*-release cat /proc/version cat /etc/issue uname -a]]></description>
			<content:encoded><![CDATA[<p>Here are a few commands which can be used to find out which distribution a particular Linux system is.</p>
<p><strong>lsb_release command</strong></p>
<pre class="brush: bash; title: Code; notranslate">
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 11.04
Release:        11.04
Codename:       natty
</pre>
<p><strong>cat /etc/*-release</strong></p>
<pre class="brush: bash; title: Code; notranslate">
$ cat /etc/*-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=11.04
DISTRIB_CODENAME=natty
DISTRIB_DESCRIPTION=&quot;Ubuntu 11.04&quot;
</pre>
<pre class="brush: bash; title: Code; notranslate">
# cat /etc/*release
CentOS release 5.7 (Final)
</pre>
<p><strong>cat /proc/version</strong></p>
<pre class="brush: bash; title: Code; notranslate">
$ cat /proc/version
Linux version 2.6.38-13-generic (buildd@allspice) (gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) ) #52-Ubuntu SMP Tue Nov 8 16:53:51 UTC 2011
</pre>
<pre class="brush: bash; title: Code; notranslate">
#  cat /proc/version
Linux version 2.6.18-028stab070.14 (root@rhel5-build-x64) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)) #1 SMP Thu Nov 18 16:04:02 MSK 2010
</pre>
<p><strong>cat /etc/issue</strong></p>
<pre class="brush: bash; title: Code; notranslate">
$ cat /etc/issue
Ubuntu 11.04 \n \l
</pre>
<p><strong>uname -a</strong></p>
<pre class="brush: bash; title: Code; notranslate">
$ uname -a
Linux enlightened-desktop 2.6.38-13-generic #52-Ubuntu SMP Tue Nov 8 16:53:51 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
</pre>
<pre class="brush: bash; title: Code; notranslate">
$ cat /etc/[A-Za-z]*[_-][rv]e[lr]*
squeeze/sid
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=11.04
DISTRIB_CODENAME=natty
DISTRIB_DESCRIPTION=&quot;Ubuntu 11.04&quot;
</pre>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1174&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/linux-command-to-check-distro/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Run php as cgi with apache on Ubuntu Linux</title>
		<link>http://www.binarytides.com/blog/run-php-as-cgi-with-apache-on-ubuntu-linux/</link>
		<comments>http://www.binarytides.com/blog/run-php-as-cgi-with-apache-on-ubuntu-linux/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 10:39:01 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1171</guid>
		<description><![CDATA[Install PHP CGI Install the php5-cgi package from synaptic. Configure Enable mod actions in apache. Disable mod php Edit the /etc/apache2/sites-enabled/000-default file and add this to the end of the file before the ending VirtualHost tag : Save the file. Restart apache. Check phpinfo. The server api should be CGI/FastCGI.]]></description>
			<content:encoded><![CDATA[<p><strong>Install PHP CGI</strong></p>
<p>Install the php5-cgi package from synaptic.</p>
<pre class="brush: bash; title: Code; notranslate">
$ sudo apt-get install php5-cgi
</pre>
<p><strong>Configure</strong></p>
<p>Enable mod actions in apache.</p>
<pre class="brush: bash; title: Code; notranslate">
$ sudo a2enmod actions
</pre>
<p>Disable mod php</p>
<pre class="brush: bash; title: Code; notranslate">
$ sudo a2dismod php5
</pre>
<p>Edit the /etc/apache2/sites-enabled/000-default file and add this to the end of the file before the ending VirtualHost tag :</p>
<pre class="brush: xml; title: Code; notranslate">
#Settings for CGI
ScriptAlias /local-bin /usr/bin
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-cgi

&lt;/VirtualHost&gt;
</pre>
<p>Save the file. Restart apache. Check phpinfo. The server api should be CGI/FastCGI.</p>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1171&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/run-php-as-cgi-with-apache-on-ubuntu-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Run Apache as a specific user with mpm itk on Ubuntu Linux</title>
		<link>http://www.binarytides.com/blog/run-apache-as-a-specific-user-with-mpm-itk-on-ubuntu-linux/</link>
		<comments>http://www.binarytides.com/blog/run-apache-as-a-specific-user-with-mpm-itk-on-ubuntu-linux/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 05:33:37 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[apache]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=861</guid>
		<description><![CDATA[Install mpm itk On ubuntu mpm itk can be installed from synaptic. Look for the package called apache2-mpm-itk Configure Configuration for mpm itk can be done in the file sites-enabled/000-default In the VirtualHost *:80 section add this just before the end of the VirtualHost tag Restart apache. Now apache should be running as that username specified in &#8220;your_username&#8221;. Now this means that even PHP scripts will also run with the same username (unless something like [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Install mpm itk</strong></p>
<p>On ubuntu mpm itk can be installed from synaptic. Look for the package called apache2-mpm-itk</p>
<pre class="brush: bash; title: Code; notranslate">
sudo apt-get install apache2-mpm-itk
</pre>
<p><strong>Configure</strong></p>
<p>Configuration for mpm itk can be done in the file sites-enabled/000-default</p>
<pre class="brush: bash; title: Code; notranslate">
$ gksudo gedit /etc/apache2/sites-enabled/000-default
</pre>
<p>In the VirtualHost *:80 section add this just before the end of the VirtualHost tag</p>
<pre class="brush: xml; title: Code; notranslate">
&lt;IfModule mpm_itk_module&gt;
AssignUserId your_username your_username
&lt;/IfModule&gt;

&lt;/VirtualHost&gt;
</pre>
<p>Restart apache. Now apache should be running as that username specified in &#8220;your_username&#8221;.<br />
Now this means that even PHP scripts will also run with the same username (unless something like suexec/suphp is changing their user).</p>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=861&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/run-apache-as-a-specific-user-with-mpm-itk-on-ubuntu-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Packet Sniffer Code in C using Linux Sockets (BSD) &#8211; Part 2</title>
		<link>http://www.binarytides.com/blog/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/</link>
		<comments>http://www.binarytides.com/blog/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 12:27:46 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Sockets]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1045</guid>
		<description><![CDATA[In the previous part we made a simple sniffer which created a raw socket and started receiving on it. But it had few drawbacks : 1. Could sniff only incoming data. 2. Could sniff only TCP or UDP or ICMP or any one protocol packets at a time. 3. Provided IP frames , so ethernet headers were not available. In this article we are going to modify the same code to fix the above 3 [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://www.binarytides.com/blog/packet-sniffer-code-in-c-using-linux-sockets-bsd/" >previous part</a> we made a simple sniffer which created a raw socket and started receiving on it. But it had few drawbacks :</p>
<p>1. Could sniff only incoming data.<br />
2. Could sniff only TCP or UDP or ICMP or any one protocol packets at a time.<br />
3. Provided IP frames , so ethernet headers were not available.</p>
<p>In this article we are going to modify the same code to fix the above 3 drawbacks. However we shall not be using libpcap.<br />
This will be done using pure linux sockets.</p>
<p>The difference is very small and is 2 lines :<br />
Instead of :</p>
<pre class="brush: cpp; title: Code; notranslate">
sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
</pre>
<p>We do :</p>
<pre class="brush: cpp; title: Code; notranslate">
sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
//Optional
//setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , &quot;eth0&quot; , strlen(&quot;eth0&quot;)+ 1 );
</pre>
<p>and we are done. Now it will :<br />
1. Sniff both incoming and outgoing traffic.<br />
2. Sniff ALL ETHERNET FRAMES , which includes all kinds of IP packets and even more if there are any.<br />
3. Provides the Ethernet headers too , which contain the mac addresses.</p>
<p>The setsockopt line is optional.<br />
Its important to provide the correct interface name to setsockopt , eth0 in this case and in most cases.<br />
So may be you would like to present the user with a list of interfaces available and allow him to choose the one to be sniffed.</p>
<p>Here is the full source code :</p>
<pre class="brush: cpp; title: Code; notranslate">

#include&lt;netinet/in.h&gt;
#include&lt;errno.h&gt;
#include&lt;netdb.h&gt;
#include&lt;stdio.h&gt;	//For standard things
#include&lt;stdlib.h&gt;	//malloc
#include&lt;string.h&gt;	//strlen

#include&lt;netinet/ip_icmp.h&gt;	//Provides declarations for icmp header
#include&lt;netinet/udp.h&gt;	//Provides declarations for udp header
#include&lt;netinet/tcp.h&gt;	//Provides declarations for tcp header
#include&lt;netinet/ip.h&gt;	//Provides declarations for ip header
#include&lt;netinet/if_ether.h&gt;	//For ETH_P_ALL
#include&lt;net/ethernet.h&gt;	//For ether_header
#include&lt;sys/socket.h&gt;
#include&lt;arpa/inet.h&gt;
#include&lt;sys/ioctl.h&gt;
#include&lt;sys/time.h&gt;
#include&lt;sys/types.h&gt;
#include&lt;unistd.h&gt;

void ProcessPacket(unsigned char* , int);
void print_ip_header(unsigned char* , int);
void print_tcp_packet(unsigned char * , int );
void print_udp_packet(unsigned char * , int );
void print_icmp_packet(unsigned char* , int );
void PrintData (unsigned char* , int);

FILE *logfile;
struct sockaddr_in source,dest;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j;	

int main()
{
	int saddr_size , data_size;
	struct sockaddr saddr;

	unsigned char *buffer = (unsigned char *) malloc(65536); //Its Big!

	logfile=fopen(&quot;log.txt&quot;,&quot;w&quot;);
	if(logfile==NULL)
	{
		printf(&quot;Unable to create log.txt file.&quot;);
	}
	printf(&quot;Starting...\n&quot;);

	int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
	//setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , &quot;eth0&quot; , strlen(&quot;eth0&quot;)+ 1 );

	if(sock_raw &lt; 0)
	{
		//Print the error with proper message
		perror(&quot;Socket Error&quot;);
		return 1;
	}
	while(1)
	{
		saddr_size = sizeof saddr;
		//Receive a packet
		data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &amp;saddr , (socklen_t*)&amp;saddr_size);
		if(data_size &lt;0 )
		{
			printf(&quot;Recvfrom error , failed to get packets\n&quot;);
			return 1;
		}
		//Now process the packet
		ProcessPacket(buffer , data_size);
	}
	close(sock_raw);
	printf(&quot;Finished&quot;);
	return 0;
}

void ProcessPacket(unsigned char* buffer, int size)
{
	//Get the IP Header part of this packet , excluding the ethernet header
	struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
	++total;
	switch (iph-&gt;protocol) //Check the Protocol and do accordingly...
	{
		case 1:  //ICMP Protocol
			++icmp;
			print_icmp_packet( buffer , size);
			break;

		case 2:  //IGMP Protocol
			++igmp;
			break;

		case 6:  //TCP Protocol
			++tcp;
			print_tcp_packet(buffer , size);
			break;

		case 17: //UDP Protocol
			++udp;
			print_udp_packet(buffer , size);
			break;

		default: //Some Other Protocol like ARP etc.
			++others;
			break;
	}
	printf(&quot;TCP : %d   UDP : %d   ICMP : %d   IGMP : %d   Others : %d   Total : %d\r&quot;, tcp , udp , icmp , igmp , others , total);
}

void print_ethernet_header(unsigned char* Buffer, int Size)
{
	struct ethhdr *eth = (struct ethhdr *)Buffer;

	fprintf(logfile , &quot;\n&quot;);
	fprintf(logfile , &quot;Ethernet Header\n&quot;);
	fprintf(logfile , &quot;   |-Destination Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n&quot;, eth-&gt;h_dest[0] , eth-&gt;h_dest[1] , eth-&gt;h_dest[2] , eth-&gt;h_dest[3] , eth-&gt;h_dest[4] , eth-&gt;h_dest[5] );
	fprintf(logfile , &quot;   |-Source Address      : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n&quot;, eth-&gt;h_source[0] , eth-&gt;h_source[1] , eth-&gt;h_source[2] , eth-&gt;h_source[3] , eth-&gt;h_source[4] , eth-&gt;h_source[5] );
	fprintf(logfile , &quot;   |-Protocol            : %u \n&quot;,(unsigned short)eth-&gt;h_proto);
}

void print_ip_header(unsigned char* Buffer, int Size)
{
	print_ethernet_header(Buffer , Size);

	unsigned short iphdrlen;

	struct iphdr *iph = (struct iphdr *)(Buffer  + sizeof(struct ethhdr) );
	iphdrlen =iph-&gt;ihl*4;

	memset(&amp;source, 0, sizeof(source));
	source.sin_addr.s_addr = iph-&gt;saddr;

	memset(&amp;dest, 0, sizeof(dest));
	dest.sin_addr.s_addr = iph-&gt;daddr;

	fprintf(logfile , &quot;\n&quot;);
	fprintf(logfile , &quot;IP Header\n&quot;);
	fprintf(logfile , &quot;   |-IP Version        : %d\n&quot;,(unsigned int)iph-&gt;version);
	fprintf(logfile , &quot;   |-IP Header Length  : %d DWORDS or %d Bytes\n&quot;,(unsigned int)iph-&gt;ihl,((unsigned int)(iph-&gt;ihl))*4);
	fprintf(logfile , &quot;   |-Type Of Service   : %d\n&quot;,(unsigned int)iph-&gt;tos);
	fprintf(logfile , &quot;   |-IP Total Length   : %d  Bytes(Size of Packet)\n&quot;,ntohs(iph-&gt;tot_len));
	fprintf(logfile , &quot;   |-Identification    : %d\n&quot;,ntohs(iph-&gt;id));
	//fprintf(logfile , &quot;   |-Reserved ZERO Field   : %d\n&quot;,(unsigned int)iphdr-&gt;ip_reserved_zero);
	//fprintf(logfile , &quot;   |-Dont Fragment Field   : %d\n&quot;,(unsigned int)iphdr-&gt;ip_dont_fragment);
	//fprintf(logfile , &quot;   |-More Fragment Field   : %d\n&quot;,(unsigned int)iphdr-&gt;ip_more_fragment);
	fprintf(logfile , &quot;   |-TTL      : %d\n&quot;,(unsigned int)iph-&gt;ttl);
	fprintf(logfile , &quot;   |-Protocol : %d\n&quot;,(unsigned int)iph-&gt;protocol);
	fprintf(logfile , &quot;   |-Checksum : %d\n&quot;,ntohs(iph-&gt;check));
	fprintf(logfile , &quot;   |-Source IP        : %s\n&quot;,inet_ntoa(source.sin_addr));
	fprintf(logfile , &quot;   |-Destination IP   : %s\n&quot;,inet_ntoa(dest.sin_addr));
}

void print_tcp_packet(unsigned char* Buffer, int Size)
{
	unsigned short iphdrlen;

	struct iphdr *iph = (struct iphdr *)( Buffer  + sizeof(struct ethhdr) );
	iphdrlen = iph-&gt;ihl*4;

	struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen + sizeof(struct ethhdr));

	int header_size =  sizeof(struct ethhdr) + iphdrlen + tcph-&gt;doff*4;

	fprintf(logfile , &quot;\n\n***********************TCP Packet*************************\n&quot;);	

	print_ip_header(Buffer,Size);

	fprintf(logfile , &quot;\n&quot;);
	fprintf(logfile , &quot;TCP Header\n&quot;);
	fprintf(logfile , &quot;   |-Source Port      : %u\n&quot;,ntohs(tcph-&gt;source));
	fprintf(logfile , &quot;   |-Destination Port : %u\n&quot;,ntohs(tcph-&gt;dest));
	fprintf(logfile , &quot;   |-Sequence Number    : %u\n&quot;,ntohl(tcph-&gt;seq));
	fprintf(logfile , &quot;   |-Acknowledge Number : %u\n&quot;,ntohl(tcph-&gt;ack_seq));
	fprintf(logfile , &quot;   |-Header Length      : %d DWORDS or %d BYTES\n&quot; ,(unsigned int)tcph-&gt;doff,(unsigned int)tcph-&gt;doff*4);
	//fprintf(logfile , &quot;   |-CWR Flag : %d\n&quot;,(unsigned int)tcph-&gt;cwr);
	//fprintf(logfile , &quot;   |-ECN Flag : %d\n&quot;,(unsigned int)tcph-&gt;ece);
	fprintf(logfile , &quot;   |-Urgent Flag          : %d\n&quot;,(unsigned int)tcph-&gt;urg);
	fprintf(logfile , &quot;   |-Acknowledgement Flag : %d\n&quot;,(unsigned int)tcph-&gt;ack);
	fprintf(logfile , &quot;   |-Push Flag            : %d\n&quot;,(unsigned int)tcph-&gt;psh);
	fprintf(logfile , &quot;   |-Reset Flag           : %d\n&quot;,(unsigned int)tcph-&gt;rst);
	fprintf(logfile , &quot;   |-Synchronise Flag     : %d\n&quot;,(unsigned int)tcph-&gt;syn);
	fprintf(logfile , &quot;   |-Finish Flag          : %d\n&quot;,(unsigned int)tcph-&gt;fin);
	fprintf(logfile , &quot;   |-Window         : %d\n&quot;,ntohs(tcph-&gt;window));
	fprintf(logfile , &quot;   |-Checksum       : %d\n&quot;,ntohs(tcph-&gt;check));
	fprintf(logfile , &quot;   |-Urgent Pointer : %d\n&quot;,tcph-&gt;urg_ptr);
	fprintf(logfile , &quot;\n&quot;);
	fprintf(logfile , &quot;                        DATA Dump                         &quot;);
	fprintf(logfile , &quot;\n&quot;);

	fprintf(logfile , &quot;IP Header\n&quot;);
	PrintData(Buffer,iphdrlen);

	fprintf(logfile , &quot;TCP Header\n&quot;);
	PrintData(Buffer+iphdrlen,tcph-&gt;doff*4);

	fprintf(logfile , &quot;Data Payload\n&quot;);
	PrintData(Buffer + header_size , Size - header_size );

	fprintf(logfile , &quot;\n###########################################################&quot;);
}

void print_udp_packet(unsigned char *Buffer , int Size)
{

	unsigned short iphdrlen;

	struct iphdr *iph = (struct iphdr *)(Buffer +  sizeof(struct ethhdr));
	iphdrlen = iph-&gt;ihl*4;

	struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen  + sizeof(struct ethhdr));

	int header_size =  sizeof(struct ethhdr) + iphdrlen + sizeof udph;

	fprintf(logfile , &quot;\n\n***********************UDP Packet*************************\n&quot;);

	print_ip_header(Buffer,Size);			

	fprintf(logfile , &quot;\nUDP Header\n&quot;);
	fprintf(logfile , &quot;   |-Source Port      : %d\n&quot; , ntohs(udph-&gt;source));
	fprintf(logfile , &quot;   |-Destination Port : %d\n&quot; , ntohs(udph-&gt;dest));
	fprintf(logfile , &quot;   |-UDP Length       : %d\n&quot; , ntohs(udph-&gt;len));
	fprintf(logfile , &quot;   |-UDP Checksum     : %d\n&quot; , ntohs(udph-&gt;check));

	fprintf(logfile , &quot;\n&quot;);
	fprintf(logfile , &quot;IP Header\n&quot;);
	PrintData(Buffer , iphdrlen);

	fprintf(logfile , &quot;UDP Header\n&quot;);
	PrintData(Buffer+iphdrlen , sizeof udph);

	fprintf(logfile , &quot;Data Payload\n&quot;);	

	//Move the pointer ahead and reduce the size of string
	PrintData(Buffer + header_size , Size - header_size);

	fprintf(logfile , &quot;\n###########################################################&quot;);
}

void print_icmp_packet(unsigned char* Buffer , int Size)
{
	unsigned short iphdrlen;

	struct iphdr *iph = (struct iphdr *)(Buffer  + sizeof(struct ethhdr));
	iphdrlen = iph-&gt;ihl * 4;

	struct icmphdr *icmph = (struct icmphdr *)(Buffer + iphdrlen  + sizeof(struct ethhdr));

	int header_size =  sizeof(struct ethhdr) + iphdrlen + sizeof icmph;

	fprintf(logfile , &quot;\n\n***********************ICMP Packet*************************\n&quot;);	

	print_ip_header(Buffer , Size);

	fprintf(logfile , &quot;\n&quot;);

	fprintf(logfile , &quot;ICMP Header\n&quot;);
	fprintf(logfile , &quot;   |-Type : %d&quot;,(unsigned int)(icmph-&gt;type));

	if((unsigned int)(icmph-&gt;type) == 11)
	{
		fprintf(logfile , &quot;  (TTL Expired)\n&quot;);
	}
	else if((unsigned int)(icmph-&gt;type) == ICMP_ECHOREPLY)
	{
		fprintf(logfile , &quot;  (ICMP Echo Reply)\n&quot;);
	}

	fprintf(logfile , &quot;   |-Code : %d\n&quot;,(unsigned int)(icmph-&gt;code));
	fprintf(logfile , &quot;   |-Checksum : %d\n&quot;,ntohs(icmph-&gt;checksum));
	//fprintf(logfile , &quot;   |-ID       : %d\n&quot;,ntohs(icmph-&gt;id));
	//fprintf(logfile , &quot;   |-Sequence : %d\n&quot;,ntohs(icmph-&gt;sequence));
	fprintf(logfile , &quot;\n&quot;);

	fprintf(logfile , &quot;IP Header\n&quot;);
	PrintData(Buffer,iphdrlen);

	fprintf(logfile , &quot;UDP Header\n&quot;);
	PrintData(Buffer + iphdrlen , sizeof icmph);

	fprintf(logfile , &quot;Data Payload\n&quot;);	

	//Move the pointer ahead and reduce the size of string
	PrintData(Buffer + header_size , (Size - header_size) );

	fprintf(logfile , &quot;\n###########################################################&quot;);
}

void PrintData (unsigned char* data , int Size)
{
	int i , j;
	for(i=0 ; i &lt; Size ; i++)
	{
		if( i!=0 &amp;&amp; i%16==0)   //if one line of hex printing is complete...
		{
			fprintf(logfile , &quot;         &quot;);
			for(j=i-16 ; j&lt;i ; j++)
			{
				if(data[j]&gt;=32 &amp;&amp; data[j]&lt;=128)
					fprintf(logfile , &quot;%c&quot;,(unsigned char)data[j]); //if its a number or alphabet

				else fprintf(logfile , &quot;.&quot;); //otherwise print a dot
			}
			fprintf(logfile , &quot;\n&quot;);
		} 

		if(i%16==0) fprintf(logfile , &quot;   &quot;);
			fprintf(logfile , &quot; %02X&quot;,(unsigned int)data[i]);

		if( i==Size-1)  //print the last spaces
		{
			for(j=0;j&lt;15-i%16;j++)
			{
			  fprintf(logfile , &quot;   &quot;); //extra spaces
			}

			fprintf(logfile , &quot;         &quot;);

			for(j=i-i%16 ; j&lt;=i ; j++)
			{
				if(data[j]&gt;=32 &amp;&amp; data[j]&lt;=128)
				{
				  fprintf(logfile , &quot;%c&quot;,(unsigned char)data[j]);
				}
				else
				{
				  fprintf(logfile , &quot;.&quot;);
				}
			}

			fprintf(logfile ,  &quot;\n&quot; );
		}
	}
}
</pre>
<p>The log file will looks somewhat like this :</p>
<pre class="brush: cpp; title: Code; notranslate">

***********************TCP Packet*************************

Ethernet Header
   |-Destination Address : 00-25-5E-1A-3D-F1
   |-Source Address      : 00-1C-C0-F8-79-EE
   |-Protocol            : 8 

IP Header
   |-IP Version        : 4
   |-IP Header Length  : 5 DWORDS or 20 Bytes
   |-Type Of Service   : 0
   |-IP Total Length   : 141  Bytes(Size of Packet)
   |-Identification    : 13122
   |-TTL      : 64
   |-Protocol : 6
   |-Checksum : 45952
   |-Source IP        : 192.168.1.6
   |-Destination IP   : 74.125.71.125

TCP Header
   |-Source Port      : 33655
   |-Destination Port : 5222
   |-Sequence Number    : 78458457
   |-Acknowledge Number : 2427066746
   |-Header Length      : 5 DWORDS or 20 BYTES
   |-Urgent Flag          : 0
   |-Acknowledgement Flag : 1
   |-Push Flag            : 1
   |-Reset Flag           : 0
   |-Synchronise Flag     : 0
   |-Finish Flag          : 0
   |-Window         : 62920
   |-Checksum       : 21544
   |-Urgent Pointer : 0

                        DATA Dump
IP Header
    00 25 5E 1A 3D F1 00 1C C0 F8 79 EE 08 00 45 00         .%^.=.....y...E.
    00 8D 33 42                                             ..3B
TCP Header
    40 00 40 06 B3 80 C0 A8 01 06 4A 7D 47 7D 83 77         @.@..?....J}G}.w
    14 66 04 AD                                             .f..
Data Payload
    17 03 01 00 60 A0 9C 5D 14 A1 25 AB CE 8B 7C EB         ....`..]..%...|.
    1A A4 43 A6 60 DD E8 6B 6E 43 C1 94 6A D2 25 23         ..C.`..knC..j.%#
    03 98 59 67 1A 2C 07 D3 7E B2 B8 9F 83 38 4C 69         ..Yg.,..~....8Li
    D3 3A 8E 0D 9E F0 6B CE 9E 6B F4 E1 BD 9E 50 53         .:....k..k....PS
    6D F6 AB 11 05 D6 41 82 F0 03 0C A6 E2 48 2B 71         m.....A......H+q
    16 81 FF 5B DF 50 D4 5B AD 90 04 5E 4C 94 E7 9B         ...[.P.[...^L...
    0B 72 7E 32 88                                          .r~2.

###########################################################

***********************TCP Packet*************************

Ethernet Header
   |-Destination Address : 00-1C-C0-F8-79-EE
   |-Source Address      : 00-25-5E-1A-3D-F1
   |-Protocol            : 8 

IP Header
   |-IP Version        : 4
   |-IP Header Length  : 5 DWORDS or 20 Bytes
   |-Type Of Service   : 32
   |-IP Total Length   : 141  Bytes(Size of Packet)
   |-Identification    : 30410
   |-TTL      : 48
   |-Protocol : 6
   |-Checksum : 49112
   |-Source IP        : 74.125.71.125
   |-Destination IP   : 192.168.1.6

TCP Header
   |-Source Port      : 5222
   |-Destination Port : 33655
   |-Sequence Number    : 2427066746
   |-Acknowledge Number : 78458558
   |-Header Length      : 5 DWORDS or 20 BYTES
   |-Urgent Flag          : 0
   |-Acknowledgement Flag : 1
   |-Push Flag            : 1
   |-Reset Flag           : 0
   |-Synchronise Flag     : 0
   |-Finish Flag          : 0
   |-Window         : 63784
   |-Checksum       : 63942
   |-Urgent Pointer : 0

                        DATA Dump
IP Header
    00 1C C0 F8 79 EE 00 25 5E 1A 3D F1 08 00 45 20         ....y..%^.=...E
    00 8D 76 CA                                             ..v.
TCP Header
    00 00 30 06 BF D8 4A 7D 47 7D C0 A8 01 06 14 66         ..0...J}G}.....f
    83 77 90 AA                                             .w..
Data Payload
    17 03 01 00 60 01 B9 00 4E C7 79 0D 89 09 15 BF         ....`...N.y.....
    9C BB 53 8D 50 DB 97 4E 25 AC FA E2 55 20 94 8B         ..S.P..N%...U ..
    AF 6E 84 E2 95 8B D9 26 A3 63 7D E4 F0 CA 6F 72         .n.....&amp;.c}...or
    F6 29 95 79 98 BC 12 BF F1 C5 34 42 83 A3 F8 B6         .).y......4B....
    9E B2 7B 1C FC F7 3E BA 4E B1 FB 36 89 93 E3 58         ..{...&gt;.N..6...X
    A7 FC 5B C3 68 9E 35 CC 25 00 7D 82 3D DB 86 EA         ..[.h.5.%.}.=...
    66 89 99 B3 65                                          f...e

###########################################################
</pre>
<p>In the above log we can see the ethernet headers being printed. They show the source and destination mac address along with the packet protocol. 8 means IP protocol</p>
<p>Note :</p>
<p>1. If you want to sniff only IP and ARP packets for example then you can try this :<br />
sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_IP|ETH_P_ARP)) ;</p>
<p>The complete list of protocols is found in /usr/include/linux/if_ether.h</p>
<pre class="brush: cpp; title: Code; notranslate">
/*
 *	These are the defined Ethernet Protocol ID's.
 */

#define ETH_P_LOOP	0x0060		/* Ethernet Loopback packet	*/
#define ETH_P_PUP	0x0200		/* Xerox PUP packet		*/
#define ETH_P_PUPAT	0x0201		/* Xerox PUP Addr Trans packet	*/
#define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
#define ETH_P_X25	0x0805		/* CCITT X.25			*/
#define ETH_P_ARP	0x0806		/* Address Resolution packet	*/
#define	ETH_P_BPQ	0x08FF		/* G8BPQ AX.25 Ethernet Packet	[ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_IEEEPUP	0x0a00		/* Xerox IEEE802.3 PUP packet */
#define ETH_P_IEEEPUPAT	0x0a01		/* Xerox IEEE802.3 PUP Addr Trans packet */
#define ETH_P_DEC       0x6000          /* DEC Assigned proto           */
#define ETH_P_DNA_DL    0x6001          /* DEC DNA Dump/Load            */
#define ETH_P_DNA_RC    0x6002          /* DEC DNA Remote Console       */
#define ETH_P_DNA_RT    0x6003          /* DEC DNA Routing              */
#define ETH_P_LAT       0x6004          /* DEC LAT                      */
#define ETH_P_DIAG      0x6005          /* DEC Diagnostics              */
#define ETH_P_CUST      0x6006          /* DEC Customer use             */
#define ETH_P_SCA       0x6007          /* DEC Systems Comms Arch       */
#define ETH_P_TEB	0x6558		/* Trans Ether Bridging		*/
#define ETH_P_RARP      0x8035		/* Reverse Addr Res packet	*/
#define ETH_P_ATALK	0x809B		/* Appletalk DDP		*/
#define ETH_P_AARP	0x80F3		/* Appletalk AARP		*/
#define ETH_P_8021Q	0x8100          /* 802.1Q VLAN Extended Header  */
#define ETH_P_IPX	0x8137		/* IPX over DIX			*/
#define ETH_P_IPV6	0x86DD		/* IPv6 over bluebook		*/
#define ETH_P_PAUSE	0x8808		/* IEEE Pause frames. See 802.3 31B */
#define ETH_P_SLOW	0x8809		/* Slow Protocol. See 802.3ad 43B */
#define ETH_P_WCCP	0x883E		/* Web-cache coordination protocol
					 * defined in draft-wilson-wrec-wccp-v2-00.txt */
#define ETH_P_PPP_DISC	0x8863		/* PPPoE discovery messages     */
#define ETH_P_PPP_SES	0x8864		/* PPPoE session messages	*/
#define ETH_P_MPLS_UC	0x8847		/* MPLS Unicast traffic		*/
#define ETH_P_MPLS_MC	0x8848		/* MPLS Multicast traffic	*/
#define ETH_P_ATMMPOA	0x884c		/* MultiProtocol Over ATM	*/
#define ETH_P_LINK_CTL	0x886c		/* HPNA, wlan link local tunnel */
#define ETH_P_ATMFATE	0x8884		/* Frame-based ATM Transport
					 * over Ethernet
					 */
#define ETH_P_PAE	0x888E		/* Port Access Entity (IEEE 802.1X) */
#define ETH_P_AOE	0x88A2		/* ATA over Ethernet		*/
#define ETH_P_TIPC	0x88CA		/* TIPC 			*/
#define ETH_P_1588	0x88F7		/* IEEE 1588 Timesync */
#define ETH_P_FCOE	0x8906		/* Fibre Channel over Ethernet  */
#define ETH_P_FIP	0x8914		/* FCoE Initialization Protocol */
#define ETH_P_EDSA	0xDADA		/* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */

/*
 *	Non DIX types. Won't clash for 1500 types.
 */

#define ETH_P_802_3	0x0001		/* Dummy type for 802.3 frames  */
#define ETH_P_AX25	0x0002		/* Dummy protocol id for AX.25  */
#define ETH_P_ALL	0x0003		/* Every packet (be careful!!!) */
#define ETH_P_802_2	0x0004		/* 802.2 frames 		*/
#define ETH_P_SNAP	0x0005		/* Internal only		*/
#define ETH_P_DDCMP     0x0006          /* DEC DDCMP: Internal only     */
#define ETH_P_WAN_PPP   0x0007          /* Dummy type for WAN PPP frames*/
#define ETH_P_PPP_MP    0x0008          /* Dummy type for PPP MP frames */
#define ETH_P_LOCALTALK 0x0009		/* Localtalk pseudo type 	*/
#define ETH_P_CAN	0x000C		/* Controller Area Network      */
#define ETH_P_PPPTALK	0x0010		/* Dummy type for Atalk over PPP*/
#define ETH_P_TR_802_2	0x0011		/* 802.2 frames 		*/
#define ETH_P_MOBITEX	0x0015		/* Mobitex (kaz@cafe.net)	*/
#define ETH_P_CONTROL	0x0016		/* Card specific control frames */
#define ETH_P_IRDA	0x0017		/* Linux-IrDA			*/
#define ETH_P_ECONET	0x0018		/* Acorn Econet			*/
#define ETH_P_HDLC	0x0019		/* HDLC frames			*/
#define ETH_P_ARCNET	0x001A		/* 1A for ArcNet :-)            */
#define ETH_P_DSA	0x001B		/* Distributed Switch Arch.	*/
#define ETH_P_TRAILER	0x001C		/* Trailer switch tagging	*/
#define ETH_P_PHONET	0x00F5		/* Nokia Phonet frames          */
#define ETH_P_IEEE802154 0x00F6		/* IEEE802.15.4 frame		*/
#define ETH_P_CAIF	0x00F7		/* ST-Ericsson CAIF protocol	*/
</pre>
<p>Enjoy!!</p>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1045&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Code a network packet sniffer in python for Linux</title>
		<link>http://www.binarytides.com/blog/code-a-network-packet-sniffer-in-python-for-linux/</link>
		<comments>http://www.binarytides.com/blog/code-a-network-packet-sniffer-in-python-for-linux/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 07:06:40 +0000</pubDate>
		<dc:creator>Binary Tides</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Sockets]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.binarytides.com/blog/?p=1018</guid>
		<description><![CDATA[The most basic form of a sniffer would be : Run this with root privileges or sudo on ubuntu : sudo python sniffer.py The above sniffer works on the principle that a raw socket is capable of receiving all (of its type , like AF_INET) incoming traffic in Linux. The output could look like this : The above is a dump of the network packets in hex. They can be parsed using the unpack function. [...]]]></description>
			<content:encoded><![CDATA[<p>The most basic form of a sniffer would be :</p>
<pre class="brush: python; title: Code; notranslate">
#Packet sniffer in python
#For Linux

import socket

#create an INET, raw socket
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

# receive a packet
while True:
  print s.recvfrom(65565)
</pre>
<p>Run this with root privileges or sudo on ubuntu :<br />
<code>sudo python sniffer.py</code></p>
<p>The above sniffer works on the principle that a raw socket is capable of receiving all (of its type , like AF_INET) incoming traffic in Linux.</p>
<p>The output could look like this :</p>
<pre class="brush: bash; title: Code; notranslate">
$ sudo python raw_socket.py
(&quot;E \x00x\xcc\xfc\x00\x000\x06j%J}G\x13\xc0\xa8\x01\x06\x01\xbb\xa3\xdc\x0b\xbeI\xbf\x1aF[\x83P\x18\xff\xff\x88\xf6\x00\x00\x17\x03\x01\x00\x1c\xbbT\xb3\x07}\xb0\xedqE\x1e\xe7;-\x03\x9bU\xb7\xb1r\xd2\x9e]\xa1\xb8\xac\xa4V\x9a\x17\x03\x01\x00*\xed\x1f\xda\xa4##Qe\x9a\xe9\xd6\xadN\xf4\x9b\xc4\xf0C'\x01\xc4\x82\xdb\xb2\x8d(\xa5\xd0\x06\x95\x13WO\x0f\x8e\x1c\xa6f\x1d\xdf\xe1x&quot;, ('74.125.71.19', 0))
('E \x00I\xcc\xfd\x00\x000\x06jSJ}G\x13\xc0\xa8\x01\x06\x01\xbb\xa3\xdc\x0b\xbeJ\x0f\x1aF[\x83P\x18\xff\xff:\x11\x00\x00\x17\x03\x01\x00\x1c\xaa];\t\x81yi\xbbC\xb5\x11\x14(Ct\x13\x10wt\xe0\xbam\xa9\x88/\xf8O{', ('74.125.71.19', 0))
('E \x00(\xcc\xfe\x00\x000\x06jsJ}G\x13\xc0\xa8\x01\x06\x01\xbb\xa3\xdc\x0b\xbeJ0\x1aFa\x19P\x10\xff\xff\xe5\xb0\x00\x00', ('74.125.71.19', 0))
('E \x00(\xcc\xff\x00\x000\x06jrJ}G\x13\xc0\xa8\x01\x06\x01\xbb\xa3\xdc\x0b\xbeJ0\x1aFbtP\x10\xff\xff\xe4U\x00\x00', ('74.125.71.19', 0))
</pre>
<p>The above is a dump of the network packets in hex. They can be parsed using the unpack function.</p>
<p>Here is the code to parse a TCP packet</p>
<pre class="brush: python; title: Code; notranslate">

#Packet sniffer in python
#For Linux

import socket
from struct import *

#create an INET, STREAMing socket
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

# receive a packet
while True:
  packet = s.recvfrom(65565)

  #packet string from tuple
  packet = packet[0]

  #take first 20 characters for the ip header
  ip_header = packet[0:20]

  #now unpack them :)
  iph = unpack('!BBHHHBBH4s4s' , ip_header)

  version_ihl = iph[0]
  version = version_ihl &gt;&gt; 4
  ihl = version_ihl &amp; 0xF

  ttl = iph[5]
  protocol = iph[6]
  s_addr = socket.inet_ntoa(iph[8]);
  d_addr = socket.inet_ntoa(iph[9]);

  print 'Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + ' TTL : ' + str(ttl) + ' Protocol : ' + str(protocol) + ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr)

  tcp_header = packet[20:40]

  #now unpack them :)
  tcph = unpack('!HHLLBBHHH' , tcp_header)

  source_port = tcph[0]
  dest_port = tcph[1]
  sequence = tcph[2]
  acknowledgement = tcph[3]
  doff_reserved = tcph[4]
  tcph_length = doff_reserved &gt;&gt; 4

  print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Sequence Number : ' + str(sequence) + ' Acknowledgement : ' + str(acknowledgement) + ' TCP header length : ' + str(tcph_length)

  h_size = ihl * 4 + tcph_length * 4
  data_size = len(packet) - h_size

  #get data from the packet
  data = packet[data_size:]

  print 'Data : ' + data
  print
</pre>
<p>The above code breaks down the packet into IP Header + TCP Header + Data.<br />
The unpack function is used to break down the packet. <a target="_blank" href="http://docs.python.org/library/struct.html#format-characters" >Documentation</a></p>
<p>The output of the code should look like this :</p>
<pre class="brush: bash; title: Code; notranslate">
$ sudo python raw_socket.py
Version : 4 IP Header Length : 5 TTL : 48 Protocol : 6 Source Address : 74.125.71.104 Destination Address : 192.168.1.6
Source Port : 80 Dest Port : 36454 Sequence Number : 3689394456 Acknowledgement : 2825932501 TCP header length : 5
Data : E (%?0=J}Gh?P?f?????pN?P,??

Version : 4 IP Header Length : 5 TTL : 48 Protocol : 6 Source Address : 74.125.71.132 Destination Address : 192.168.1.6
Source Port : 80 Dest Port : 46534 Sequence Number : 2071060663 Acknowledgement : 2858668979 TCP header length : 5
Data : E (?H0;?J}G??P??{q?c?P

Version : 4 IP Header Length : 5 TTL : 48 Protocol : 6 Source Address : 74.125.71.132 Destination Address : 192.168.1.6
Source Port : 80 Dest Port : 46533 Sequence Number : 377985304 Acknowledgement : 2869878012 TCP header length : 5
Data : E (??0JqJ}G??P????????PR?

Version : 4 IP Header Length : 5 TTL : 48 Protocol : 6 Source Address : 74.125.71.17 Destination Address : 192.168.1.6
Source Port : 443 Dest Port : 59643 Sequence Number : 183723837 Acknowledgement : 3530935779 TCP header length : 5
Data : 2=?D?? ???????
</pre>
<p>According to RFC 791 an IP header looks like this :</p>
<pre class="brush: cpp; title: Code; notranslate">

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|  IHL  |Type of Service|          Total Length         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Identification        |Flags|      Fragment Offset    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Time to Live |    Protocol   |         Header Checksum       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Source Address                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Destination Address                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</pre>
<p>If the IHL is 5 then total size is 20 bytes hence options+padding is absent.<br />
For TCP packets the protocol is 6. Source address is the source IPv4 address in long format.</p>
<p>Next comes the TCP header :</p>
<pre class="brush: cpp; title: Code; notranslate">
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data |           |U|A|P|R|S|F|                               |
| Offset| Reserved  |R|C|S|S|Y|I|            Window             |
|       |           |G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Urgent Pointer        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</pre>
<p>and the balance after the TCP header is the data portion.</p>
<p>The C version of the code is <a href="http://www.binarytides.com/blog/packet-sniffer-code-in-c-using-linux-sockets-bsd/" >here</a>.<br />
The Php version of the code is <a href="http://www.binarytides.com/blog/code-a-packet-sniffer-in-php/" >here</a>.</p>
<h3>Note : </h3>
<p>1. The above sniffer picks up only TCP packets, because of the declaration :</p>
<p>s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)</p>
<p>For UDP and ICMP the declaration has to be :</p>
<p>s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)<br />
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)</p>
<p>You might be tempted to think of doing :<br />
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)</p>
<p>but this will not work , since IPPROTO_IP is a dummy protocol not a real one.</p>
<p>2. This sniffer picks up only incoming packets.</p>
<p>3. This sniffer delivers only IP frames , which means ethernet headers are not available.</p>
<h3>Better Sniffer</h3>
<p>Now let us see how we can overcome the above mentioned drawbacks. The solutions is quite simple.</p>
<p>This line :<br />
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)</p>
<p>needs to be changed to :<br />
s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0&#215;0003))</p>
<p>Now the same socket will receive :<br />
1. All incoming and outgoing traffic.</p>
<p>2. All Ethernet frames , which means all kinds of IP packets(TCP , UDP , ICMP) and even other kinds of packets(like ARP) if there are any.</p>
<p>3. It will also provide the ethernet header as a part of the received packet.</p>
<p>Here is the source code :</p>
<pre class="brush: python; title: Code; notranslate">
#Packet sniffer in python
#For Linux - Sniffs all incoming and outgoing packets :)

import socket
from struct import *

#Convert a string of 6 characters of ethernet address into a dash separated hex string
def eth_addr (a) :
  b = &quot;%.2x-%.2x-%.2x-%.2x-%.2x-%.2x&quot; % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]), ord(a[4]) , ord(a[5]))
  return b

#create an PACKET , RAW SOCKET
#define ETH_P_ALL    0x0003          /* Every packet (be careful!!!) */
s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0x0003))

# receive a packet
while True:
  packet = s.recvfrom(65565)

  #packet string from tuple
  packet = packet[0]

  #parse ethernet header
  eth_length = 14

  eth_header = packet[:eth_length]
  eth = unpack('!6s6sH' , eth_header)
  eth_protocol = socket.ntohs(eth[2])
  print 'Destination MAC : ' + eth_addr(packet[0:6]) + ' Source MAC : ' + eth_addr(packet[6:12]) + ' Protocol : ' + str(eth_protocol)

  #Parse IP packets
  if eth_protocol == 8 :
    #Parse IP header
    #take first 20 characters for the ip header
    ip_header = packet[eth_length:20+eth_length]

    #now unpack them :)
    iph = unpack('!BBHHHBBH4s4s' , ip_header)

    version_ihl = iph[0]
    version = version_ihl &gt;&gt; 4
    ihl = version_ihl &amp; 0xF

    iph_length = ihl * 4

    ttl = iph[5]
    protocol = iph[6]
    s_addr = socket.inet_ntoa(iph[8]);
    d_addr = socket.inet_ntoa(iph[9]);

    print 'Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + ' TTL : ' + str(ttl) + ' Protocol : ' + str(protocol) + ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr)

    #TCP protocol
    if protocol == 6 :
      t = iph_length + eth_length
      tcp_header = packet[t:t+20]

      #now unpack them :)
      tcph = unpack('!HHLLBBHHH' , tcp_header)

      source_port = tcph[0]
      dest_port = tcph[1]
      sequence = tcph[2]
      acknowledgement = tcph[3]
      doff_reserved = tcph[4]
      tcph_length = doff_reserved &gt;&gt; 4

      print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Sequence Number : ' + str(sequence) + ' Acknowledgement : ' + str(acknowledgement) + ' TCP header length : ' + str(tcph_length)

      h_size = eth_length + iph_length + tcph_length * 4
      data_size = len(packet) - h_size

      #get data from the packet
      data = packet[data_size:]

      print 'Data : ' + data

    #ICMP Packets
    elif protocol == 1 :
      u = iph_length + eth_length
      icmph_length = 4
      icmp_header = packet[u:u+4]

      #now unpack them :)
      icmph = unpack('!BBH' , icmp_header)

      icmp_type = icmph[0]
      code = icmph[1]
      checksum = icmph[2]

      print 'Type : ' + str(icmp_type) + ' Code : ' + str(code) + ' Checksum : ' + str(checksum)

      h_size = eth_length + iph_length + icmph_length
      data_size = len(packet) - h_size

      #get data from the packet
      data = packet[data_size:]

      print 'Data : ' + data

    #UDP packets
    elif protocol == 17 :
      u = iph_length + eth_length
      udph_length = 8
      udp_header = packet[u:u+8]

      #now unpack them :)
      udph = unpack('!HHHH' , udp_header)

      source_port = udph[0]
      dest_port = udph[1]
      length = udph[2]
      checksum = udph[3]

      print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Length : ' + str(length) + ' Checksum : ' + str(checksum)

      h_size = eth_length + iph_length + udph_length
      data_size = len(packet) - h_size

      #get data from the packet
      data = packet[data_size:]

      print 'Data : ' + data

    #some other IP packet like IGMP
    else :
      print 'Protocol other than TCP/UDP/ICMP'

    print
</pre>
<p>Run with root privileges.</p>
<p>The output should be something like this :</p>
<pre class="brush: cpp; title: Code; notranslate">
Destination MAC : 00-1c-c0-f8-79-ee Source MAC : 00-25-5e-1a-3d-f1 Protocol : 8
Version : 4 IP Header Length : 5 TTL : 57 Protocol : 6 Source Address : 64.131.72.23 Destination Address : 192.168.1.6
Source Port : 80 Dest Port : 58928 Sequence Number : 1392138007 Acknowledgement : 2935013912 TCP header length : 6
Data : ??y?%^?=E ,@9?c@?H?P?0R?W????`?5t?

Destination MAC : 00-25-5e-1a-3d-f1 Source MAC : 00-1c-c0-f8-79-ee Protocol : 8
Version : 4 IP Header Length : 5 TTL : 64 Protocol : 6 Source Address : 192.168.1.6 Destination Address : 64.131.72.23
Source Port : 58928 Dest Port : 80 Sequence Number : 2935013912 Acknowledgement : 1392138008 TCP header length : 5
Data : %^?=???yE(mU@@?2?@?H?0P????R?W?PJc

Destination MAC : 00-1c-c0-f8-79-ee Source MAC : 00-25-5e-1a-3d-f1 Protocol : 8
Version : 4 IP Header Length : 5 TTL : 55 Protocol : 17 Source Address : 78.141.179.8 Destination Address : 192.168.1.6
Source Port : 34049 Dest Port : 56295 Length : 28 Checksum : 25749
Data : @7?YN?????d??????r'?y@?f?h`??

Destination MAC : 00-1c-c0-f8-79-ee Source MAC : 00-25-5e-1a-3d-f1 Protocol : 8
Version : 4 IP Header Length : 5 TTL : 118 Protocol : 17 Source Address : 173.181.21.51 Destination Address : 192.168.1.6
Source Port : 5999 Dest Port : 56295 Length : 26 Checksum : 22170
Data : s)vL??3?o???V?Z???cw?k??pIQ
</pre>
<p>It parses the Ethernet header and also the UDP and ICMP headers.</p>
<p>Ethernet header looks like this :</p>
<pre class="brush: cpp; title: Code; notranslate">

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       Ethernet destination address (first 32 bits)            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Ethernet dest (last 16 bits)  |Ethernet source (first 16 bits)|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       Ethernet source address (last 32 bits)                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|        Type code              |                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</pre>
<p>UDP Header according to RFC 768 :</p>
<pre class="brush: cpp; title: Code; notranslate">
 0      7 8     15 16    23 24    31
 +--------+--------+--------+--------+
 |     Source      |   Destination   |
 |      Port       |      Port       |
 +--------+--------+--------+--------+
 |                 |                 |
 |     Length      |    Checksum     |
 +--------+--------+--------+--------+
 |
 |          data octets ...
 +---------------- ...
</pre>
<p>ICMP Header according to RFC 792 :</p>
<pre class="brush: cpp; title: Code; notranslate">
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |     Code      |          Checksum             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             unused                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Internet Header + 64 bits of Original Data Datagram      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</pre>
<p>This kind of a sniffer does not depend on any external libraries like libpcap.</p>
<p>The C version of this code is <a href="http://www.binarytides.com/blog/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/" >here</a>.</p>
<p>References :</p>
<p>1. Python Socket <a target="_blank" href="http://docs.python.org/library/socket.html" >documentation</a>.</p>
<img src="http://www.binarytides.com/blog/?ak_action=api_record_view&id=1018&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.binarytides.com/blog/code-a-network-packet-sniffer-in-python-for-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

