<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://k-mathews.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://k-mathews.com/" rel="alternate" type="text/html" /><updated>2023-01-04T17:59:55+00:00</updated><id>https://k-mathews.com/feed.xml</id><title type="html">Dr.-Ing. Kiran Mathews</title><subtitle>Computer scientist, Coder, Hiker, Gooner#COYG</subtitle><entry><title type="html">Program to collect survey details of WiFi interface using Netlink Protocol Library</title><link href="https://k-mathews.com/wireless/Libnl3-WiFi-survey-dump-example-c-program-nl80211.h-Netlink-Protocol-Library-c-program-IEEE802.11/" rel="alternate" type="text/html" title="Program to collect survey details of WiFi interface using Netlink Protocol Library" /><published>2016-11-03T00:00:00+00:00</published><updated>2016-11-03T00:00:00+00:00</updated><id>https://k-mathews.com/wireless/Libnl3-WiFi-survey-dump-example-c-program-nl80211.h-Netlink-Protocol-Library-c-program-IEEE802.11</id><content type="html" xml:base="https://k-mathews.com/wireless/Libnl3-WiFi-survey-dump-example-c-program-nl80211.h-Netlink-Protocol-Library-c-program-IEEE802.11/">&lt;p&gt;In this tutorial, we write a sample &lt;i&gt;c&lt;/i&gt; program to collect the survey details of a WiFi interface. i.e the output of &lt;code style=&quot;border: 1px solid #ffffff&quot;&gt;  iw dev 'inferfaceName' survey dump&lt;/code&gt; &lt;/p&gt;
&lt;p&gt; Depending on the hardware, survey details includes &lt;i&gt;channel active time, channel busy time, transmission time, reception time, noise&lt;/i&gt; and other details. To get the information from the hardware registry, we use Netlink libraries (libnl3). Make sure you have necessary libnl3 headers in your system. The package name is &lt;code style=&quot;border: 1px solid #ffffff&quot;&gt;libnl3-devel(Fedora), libnl3-dev(Debian), &lt;a href=&quot;https://www.rpmfind.net/linux/rpm2html/search.php?query=libnl3-devel&quot;&gt; rpm link.&lt;/a&gt;&lt;/code&gt; The output depends on your hardware and kernel verison. I refered the source code of &lt;a href=&quot;https://www.kernel.org/pub/software/network/iw/&quot;&gt; iw&lt;/a&gt; and &lt;a href=&quot;http://www.infradead.org/~tgr/libnl/doc/core.html&quot;&gt;Netlink protocol library suite dcoumentation &lt;/a&gt; for writing the program. Also, debug the iw commands using &lt;code&gt; NLDBG=4 or NLCB=debug&lt;/code&gt; to understand message values passed to the socket.&lt;/p&gt;

&lt;p&gt; Here, I am listing some of the links of sample programs using libnl3 libraries, which seems to be useful for understanding the working of Netlink protocol suite.
	&lt;ul style=&quot;list-style-type:square&quot;&gt;
		&lt;li&gt; &lt;a href=&quot;https://github.com/Robpol86/libnl
			&quot;&gt;https://github.com/Robpol86/libnl
		&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;http://linux-hacks.blogspot.de/2009/01/sample-code-to-learn-netlink.html&quot;&gt;http://linux-hacks.blogspot.de/2009/01/sample-code-to-learn-netlink.html&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;http://stackoverflow.com/questions/18062268/using-nl80211-h-to-scan-access-points&quot;&gt;http://stackoverflow.com/questions/18062268/using-nl80211-h-to-scan-access-points&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;For compling the program, link with necessary libraries, i.e.&lt;code style=&quot;border: 1px solid #ffffff&quot;&gt; gcc main_survey.c -I /usr/include/libnl3  -lnl-3 -lnl-cli-3 -lnl-genl-3&lt;/code&gt;. In this example, I assumed the interface name as &lt;i&gt;mon0&lt;/i&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
* main_survey.c
*
*  Created on: Nov 3, 2016
*      Author: k_mathews
*/


#include &amp;lt;netlink/netlink.h&amp;gt;
#include &amp;lt;netlink/socket.h&amp;gt;
#include &amp;lt;netlink/genl/genl.h&amp;gt;
#include &amp;lt;netlink/genl/ctrl.h&amp;gt;
#include &amp;lt;netlink/genl/family.h&amp;gt;
#include &amp;lt;net/if.h&amp;gt;
#include &amp;lt;linux/nl80211.h&amp;gt;

static int expectedId;

static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
void *arg)
{
	printf(&quot;Error in callback\n&quot;);
	return 1;

}

static int nlCallback(struct nl_msg* msg, void* arg)
{
	printf(&quot;Callback Received\n&quot;);
	struct nlattr *tb[NL80211_ATTR_MAX + 1];
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
	char dev[20];

	static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
		[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
		[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
	};

	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
	genlmsg_attrlen(gnlh, 0), NULL);

	if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
	printf(&quot;Survey data from %s\n&quot;, dev);

	if (!tb[NL80211_ATTR_SURVEY_INFO]) {
		fprintf(stderr, &quot;survey data missing!\n&quot;);
		return NL_SKIP;
	}

	if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
		tb[NL80211_ATTR_SURVEY_INFO],
		survey_policy)) {
			fprintf(stderr, &quot;failed to parse nested attributes!\n&quot;);
			return NL_SKIP;
		}
	if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
	printf(&quot;\tfrequency:\t\t\t%u MHz%s\n&quot;,
	nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]),
	sinfo[NL80211_SURVEY_INFO_IN_USE] ? &quot; [in use]&quot; : &quot;&quot;);
	if (sinfo[NL80211_SURVEY_INFO_NOISE])
	printf(&quot;\tnoise:\t\t\t\t%d dBm\n&quot;,
	(int8_t)nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]));
	if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME])
	printf(&quot;\tchannel active time:\t\t%llu ms\n&quot;,
	(unsigned long long)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]));
	if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY])
	printf(&quot;\tchannel busy time:\t\t%llu ms\n&quot;,
	(unsigned long long)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]));
	if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY])
	printf(&quot;\textension channel busy time:\t%llu ms\n&quot;,
	(unsigned long long)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY]));
	if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX])
	printf(&quot;\tchannel receive time:\t\t%llu ms\n&quot;,
	(unsigned long long)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]));
	if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX])
	printf(&quot;\tchannel transmit time:\t\t%llu ms\n&quot;,
	(unsigned long long)nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]));
	return NL_SKIP;
}



int main(int argc, char** argv){
	int ret;

	//allocate socket
	struct nl_sock* sk = nl_socket_alloc();
	if (!sk) {
		printf(&quot;Failed to allocate netlink socket.\n&quot;);

	}
	/*
	* connect to generic netlink
	* genl_connect(sk); wiil bind the socket
	*
	*/
	if (genl_connect(sk)) {
		printf(&quot;Failed to connect to generic netlink.\n&quot;);
		goto out_handle_destroy;
	}


	//find the nl80211 driver ID
	expectedId = genl_ctrl_resolve(sk, &quot;nl80211&quot;);

	// callback identifier
	struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);

	//allocate a message
	struct nl_msg* msg = nlmsg_alloc();



	const enum nl80211_commands cmd = NL80211_CMD_GET_SURVEY;


	/*
	* Change the interface name here
	* */
	int ifIndex = if_nametoindex(&quot;mon0&quot;);

	/** setup the message
	* NLM_F_DUMP: Flag to dump the survey details
	***/
	genlmsg_put(msg, 0, 0, expectedId, 0, NLM_F_DUMP, cmd, 0);

	//add message attributes
	nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifIndex);


	//
	/*attach a callback
	*				(another way to attach callback)
	* nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM,
	  nlCallback2, NULL);
	*/
	nl_socket_set_cb(sk,cb);
	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, nlCallback, NULL);
	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, NULL);



	//send the messge (this frees it)
	ret = nl_send_auto_complete(sk, msg);
	//block for message to return
	nl_recvmsgs_default(sk);
	return 0;

	nla_put_failure:
	 nlmsg_free(msg);
	return 1;
	out_handle_destroy:
	 nl_socket_free(sk);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Feel free to ask any questions regarding using libnl3 :-)&lt;/p&gt;</content><author><name></name></author><category term="wireless" /><category term="wireless" /><category term="IEEE802.11" /><category term="Netlink" /><category term="nl80211.h" /><summary type="html">A sample program to get survey details of a WiFi interface using Netlink Library nl80211.h</summary></entry><entry><title type="html">Packet Sniffer for IEEE 802.11</title><link href="https://k-mathews.com/wireless/packet_sniffer_capture_wlan_ieee802.11/" rel="alternate" type="text/html" title="Packet Sniffer for IEEE 802.11" /><published>2016-08-14T00:00:00+00:00</published><updated>2016-08-14T00:00:00+00:00</updated><id>https://k-mathews.com/wireless/packet_sniffer_capture_wlan_ieee802.11</id><content type="html" xml:base="https://k-mathews.com/wireless/packet_sniffer_capture_wlan_ieee802.11/">&lt;p&gt;In this tutorial, we write a sample &lt;i&gt;c&lt;/i&gt; program to sniff the WLAN frames (including corrupted frames). First of all, the interface must be switched into the monitor mode by setting FCS flag.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;iw dev &amp;lt;interfaceName&amp;gt; interface add mon0 type monitor flags fcsfail
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above command will create a monitor interface with name &lt;i&gt;mon0&lt;/i&gt;. Since we passed FCS fail flag, the driver will not drop the corrupted frames too. We use the Pcap library for capturing the frames. Now let us go through the code.&lt;/p&gt;

&lt;p&gt;I wrote this program with the target to check the link quality, i.e. what percentage of frame get corrupted. Replace &lt;code style=&quot;border: 1px solid #ffffff&quot;&gt; char *filter= &quot;wlan src 13:22:33:44:55:66&quot; &lt;/code&gt; in the code with sender address of your device. The program was tested for &lt;b&gt;ATH9k&lt;/b&gt; driver in linux kernel version &lt;b&gt;4.6.4&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;
	In this program, I calculate the percentage of corrupted frames. If there is a high percentage of corrupted frames, it is due to poor link quality. Following is the complete code:
&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*
* Packet_Capture_with_CRC_Check.cc
*
*  Created on: 25.09.2016
*      Author: k.mathews
*/
#include &amp;lt;pcap.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;errno.h&amp;gt;
#include &amp;lt;sys/socket.h&amp;gt;
#include &amp;lt;netinet/in.h&amp;gt;
#include &amp;lt;arpa/inet.h&amp;gt;
#include &amp;lt;netinet/if_ether.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;time.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;inttypes.h&amp;gt;

struct ieee80211_radiotap_header {
        u_int8_t        it_version;     /* set to 0 */
        u_int8_t        it_pad;
        u_int16_t       it_len;         /* entire length */
        u_int32_t       it_present;     /* fields present */
} __attribute__((__packed__));


struct ieee80211_hdr {
  uint16_t frame_control;
  uint16_t  duration_id;
  uint8_t addr1[6];
  uint8_t addr2[6];
  uint8_t addr3[6];
  uint16_t  seq_ctrl;
  uint8_t addr4[6];
} __attribute__ ((packed));

int totalRXFrame,corruptedFrames;

/*
Callback function.
*/

void my_callback_general(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*
packet){
	printf(&quot;\n********************************** CRC CHECKING ************************************\n&quot;);
	int i,j,len;
	const struct ieee80211_radiotap_header *rt;
	const struct ieee80211_hdr  *ethernet;
	unsigned int rxCRC;

	/* Variables for CRC calculation */

	unsigned int byte, crcCalculated, c;
	const unsigned int g0 = 0xEDB88320, g1 = g0 &amp;gt;&amp;gt; 1,
	                      g2 = g0 &amp;gt;&amp;gt; 2,    g3 = g0 &amp;gt;&amp;gt; 3;

	rt = (struct ieee80211_radiotap_header*)(packet);
	ethernet = (struct ieee80211_hdr*)(packet+rt-&amp;gt;it_len);

	printf(&quot;Payload:\n&quot;); /* And now the data */
	printf(&quot;Packet Lenght:%i \t length of portion %i size of radiotap header %i\n&quot;,
			(pkthdr-&amp;gt;len),(pkthdr-&amp;gt;caplen),rt-&amp;gt;it_len);

	len = (pkthdr-&amp;gt;len) - rt-&amp;gt;it_len - 4 ;
	uint8_t *data[(len-1)];

	/* Trimming data for calculating CRC (exculding RadiotapHeader and last 4 byte(CRC))*/
	for(i=rt-&amp;gt;it_len,j=0;i&amp;lt;(pkthdr-&amp;gt;len)-4;i++,j++) {
			data[j]=packet[i];
		}
 	printf(&quot;Trimmed data :\n&quot;);
	for(i=0;i&amp;lt;len;i++) {
		 printf(&quot;%x&quot;,data[i]);
	}
	printf(&quot;\n&quot;);

	/* Received CRC in rxCRC*/
	rxCRC = 0x00000000;
	rxCRC=(packet[(pkthdr-&amp;gt;len)-4]&amp;lt;&amp;lt;24)|
		 (packet[(pkthdr-&amp;gt;len)-3]&amp;lt;&amp;lt;16)|
		 (packet[(pkthdr-&amp;gt;len)-2]&amp;lt;&amp;lt;8)|
		 (packet[(pkthdr-&amp;gt;len)-1]&amp;lt;&amp;lt;0);

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

	/*Calculating CRC*/
		crcCalculated = 0xFFFFFFFF;
	   for(i=0;i&amp;lt;len;i++){   // Get next byte.
		  byte= data[i];
		  crcCalculated = crcCalculated ^ byte;
	      for (j = 1; j &amp;gt;= 0; j--) {        // Do two times.
	         switch(crcCalculated &amp;amp; 0xF) {
	         case  0: c = 0;                  break;
	         case  1: c =                g3;  break;
	         case  2: c =           g2;       break;
	         case  3: c =           g2 ^ g3;  break;
	         case  4: c =      g1;            break;
	         case  5: c =      g1 ^      g3;  break;
	         case  6: c =      g1 ^ g2;       break;
	         case  7: c =      g1 ^ g2 ^ g3;  break;
	         case  8: c = g0;                 break;
	         case  9: c = g0 ^           g3;  break;
	         case 10: c = g0 ^      g2;       break;
	         case 11: c = g0 ^      g2 ^ g3;  break;
	         case 12: c = g0 ^ g1;            break;
	         case 13: c = g0 ^ g1 ^      g3;  break;
	         case 14: c = g0 ^ g1 ^ g2;       break;
	         case 15: c = g0 ^ g1 ^ g2 ^ g3;  break;
	         }
	         crcCalculated = (crcCalculated &amp;gt;&amp;gt; 4) ^ c;

	      }

	   }
	   crcCalculated=~crcCalculated;
	 /* Byte reverse. */
	   crcCalculated = ((unsigned char)(crcCalculated&amp;gt;&amp;gt;0)&amp;lt;&amp;lt;24) |
	    ((unsigned char)(crcCalculated&amp;gt;&amp;gt;8)&amp;lt;&amp;lt;16) |
	    ((unsigned char)(crcCalculated&amp;gt;&amp;gt;16)&amp;lt;&amp;lt;8) |
	    ((unsigned char)(crcCalculated&amp;gt;&amp;gt;24)&amp;lt;&amp;lt;0);
		printf(&quot;calculate CRC:%x\n&quot;,crcCalculated);
		printf(&quot;recevied CRC:%x\n&quot;,rxCRC);
		printf(&quot;\n&quot;);

		/* Verfiying the checksum*/
		if((int)crcCalculated != (int)rxCRC){
			printf(&quot;Corrupt Frame\n&quot;);
			totalRXFrame++;
			corruptedFrames++;
		}
		else if ((int)crcCalculated == (int)rxCRC){
			printf(&quot;Uncorrupted Frame\n&quot;);
			totalRXFrame++;
		}
	printf(&quot;\n Percentage of corrupted frame:%f&quot;,(totalRXFrame/corruptedFrames)*100);
}

int main(int argc, char *argv[])
{
	char *dev ;
	char errbuf[PCAP_ERRBUF_SIZE] ;
	const u_char *packet ;
	struct pcap_pkthdr hdr;
	bpf_u_int32 netp; /* ip */
	struct ether_header *eptr; /* net/ethernet.h */
	struct bpf_program fp; /* hold compiled program */
	char *filter= &quot;wlan src 13:22:33:44:55:66&quot; ;
	dev = argv[1];
	totalRXFrame = 0;
	corruptedFrames = 0;
	if (dev == NULL){
	fprintf(stderr,&quot;couldn't find default device :%s\n&quot;, errbuf);
	exit(1);
	return(2);
	}
	else
		printf(&quot;Device : %s\n&quot;,dev);
/* sniffing */
	pcap_t *handle_capture;

	handle_capture = pcap_open_live(dev,2048,1,1000,errbuf);
	if(handle_capture == NULL){
		printf(&quot;pcap_open_live(): %s\n&quot;,errbuf);
		exit(1);
	}

// filtering

/* Now we'll compile the filter expression*/

	if(pcap_compile(handle_capture, &amp;amp;fp, filter, 0, netp) == -1) {
		fprintf(stderr, &quot;Error calling pcap_compile\n&quot;);
		exit(1);
	}

/* set the filter */
	if(pcap_setfilter(handle_capture, &amp;amp;fp) == -1) {
		fprintf(stderr, &quot;Error setting filter\n&quot;);
		exit(1);
	}
	pcap_loop(handle_capture,atoi(argv[1]),my_callback_general,NULL);
	return(0);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Feel free to ask your questions :-)&lt;/p&gt;</content><author><name></name></author><category term="wireless" /><category term="wireless" /><category term="IEEE802.11" /><summary type="html">Packet sniffer for IEEE 802.11 (WLAN) with CRC check</summary></entry></feed>