I am learning to write pcap code in c. Below i have written a simple c code to automatically detect a device for snifiing, getting ip and subnet mask, getting link layer headers and filtering traffic and then printing packet size.
Code complies successfully but gets stuck at
Network device found: wlo1
when run. Removing the filter part does print the packet size. And removing the priting packet part; the program complies and runs successfully.
I think i am lacking understanding of filtering part.
I compile using(on linux): gcc program_name -lpcap
Output of the code is:
Network device found: wlo1
wlo1 is wlan device
#include <stdio.h>
#include <pcap.h>
int main(int argc, char *argv[]){
char *dev; //device automatically detected for sniffing
char errbuf[PCAP_ERRBUF_SIZE]; //error string
pcap_t *handle; //session hnadle
struct bpf_program fp; //The compiled filter expression
char filter_exp[] = "port 23"; //The filter expression
bpf_u_int32 mask; //The netmask of our sniffing device
bpf_u_int32 net; //The IP of our sniffing device
struct pcap_pkthdr header;
const unsigned char *packet;
//device detection block
dev = pcap_lookupdev(errbuf);
if (dev == NULL){
printf("Error finding device: %s\n", errbuf);
return 1;
}
printf("Network device found: %s\n", dev);
//opening device for sniffing
handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if(handle == NULL){
fprintf(stderr,"Couldn't open device %s : %s\n",dev,errbuf);
return 1;
}
// //check for link-layer header of the device
if(pcap_datalink(handle) != DLT_EN10MB){ //for ethernet data link layer
if(pcap_datalink(handle) != DLT_IEEE802_11){ //for wlan data link layer
fprintf(stderr, "Device %s doesn't provide WLAN headers - not supported\n", dev);
return 1;
}
else{
fprintf(stderr, "Device %s doesn't provide Ethernet headers - not supported\n", dev);
return 1;
}
}
//block to get device ip and subnet mask
if(pcap_lookupnet(dev, &net, &mask, errbuf) == -1){
fprintf(stderr, "Can't get netmask for device %s\n", dev);
net = 0;
mask = 0;
}
//block for filtering traffic we want to sniff
if(pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
return 1;
}
if(pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
return 1;
}
/* Grab a packet */
packet = pcap_next(handle, &header);
/* Print its length */
printf("Jacked a packet with length of [%d]\n", header.len);
/* And close the session */
pcap_close(handle);
return 0;
}
If wlo1 is capturing in monitor mode on a "protected" network (a network with traffic encrypted at the link layer, using WEP or WPA/WPA2/WPA3), then any filter that works above the link layer - such as a TCP/UDP-layer filter, which "port 80" is - will not work, because the packets, as delivered to the filtering code, will have the 802.11 payload encrypted, so filters won't work on them.
Therefore, no packets will pass the filter.
Related
I have a NXP FRDM-K64F board and I want to set the ethernet example but I cannot get it working. This is how my code looks like after setting the static IP address.
#include "mbed.h"
#include "main-hw.h"
#include "EthernetInterface.h"
// Network interface
EthernetInterface net;
int main(void)
{
// Bring up the ethernet interface
printf("Ethernet socket example\r\n");
int ret;
ret = net.set_network("192.168.15.177","255.255.255.0","192.168.15.1");
printf("Set Net: %d\r\n",ret);
char macadd[6];
mbed_mac_address(macadd);
printf("%02x:%02x:%02x:%02x:%02x:%02x \r\n", macadd[0], macadd[1], macadd[2], macadd[3], macadd[4], macadd[5]);
const char *mac = net.get_mac_address();
printf("MAC address is: %s\r\n", mac ? mac : "No MAC");
const char *ip = net.get_ip_address();
printf("IP address is: %s\r\n", ip ? ip : "No IP");
ret = net.connect();
printf("Connect: %d\n",ret);
// Show the network address
// const char *ip = net.get_ip_address();
// printf("IP address is: %s\n", ip ? ip : "No IP");
// Open a socket on the network interface, and create a TCP connection to mbed.org
TCPSocket socket;
socket.open(&net);
socket.connect("developer.mbed.org", 80);
// Send a simple http request
char sbuffer[] = "GET / HTTP/1.1\r\nHost: developer.mbed.org\r\n\r\n";
int scount = socket.send(sbuffer, sizeof sbuffer);
printf("sent %d [%.*s]\n", scount, strstr(sbuffer, "\r\n")-sbuffer, sbuffer);
// Recieve a simple http response and print out the response line
char rbuffer[64];
int rcount = socket.recv(rbuffer, sizeof rbuffer);
printf("recv %d [%.*s]\n", rcount, strstr(rbuffer, "\r\n")-rbuffer, rbuffer);
// Close the socket to return its memory and bring down the network interface
socket.close();
// Bring down the ethernet interface
net.disconnect();
printf("Done\n");
return 0;
}
What I see is that I only get the macAddress with the mbed_mac_address command. With net.get_mac_address and net.get_ip_address I only get NULL values.
The process get to the net.connect and I see no more results.
What am I doing wrong?
With mbed OS 5.3.4 this works fine for me on a K64F:
#include "mbed.h"
#include "EthernetInterface.h"
// Network interface
EthernetInterface net;
// Socket demo
int main() {
// Set static IP
net.set_network("192.168.1.99", "255.255.255.0", "192.168.1.1");
// Bring up the ethernet interface
printf("Ethernet socket example\n");
net.connect();
// Show the network address
const char *ip = net.get_ip_address();
printf("IP address is: %s\n", ip ? ip : "No IP");
printf("MAC address is: %s\n", net.get_mac_address());
// Open a socket on the network interface, and create a TCP connection to mbed.org
TCPSocket socket;
socket.open(&net);
socket.connect("developer.mbed.org", 80);
// Send a simple http request
char sbuffer[] = "GET / HTTP/1.1\r\nHost: developer.mbed.org\r\n\r\n";
int scount = socket.send(sbuffer, sizeof sbuffer);
printf("sent %d [%.*s]\n", scount, strstr(sbuffer, "\r\n")-sbuffer, sbuffer);
// Recieve a simple http response and print out the response line
char rbuffer[64];
int rcount = socket.recv(rbuffer, sizeof rbuffer);
printf("recv %d [%.*s]\n", rcount, strstr(rbuffer, "\r\n")-rbuffer, rbuffer);
// Close the socket to return its memory and bring down the network interface
socket.close();
// Bring down the ethernet interface
net.disconnect();
printf("Done\n");
}
Updating mbed OS
If you still have the mbed library (not mbed-os) in the online compiler, right click on 'mbed', and click 'Remove'. Then click on 'Add library' > 'From URL' and enter https://github.com/armmbed/mbed-os.
If you have mbed-os, right click on the library and select 'Upgrade'.
From mbed CLI:
$ mbed remove mbed
$ mbed add mbed-os
Or when you already have mbed-os:
$ cd mbed-os
$ git pull
$ git checkout latest
i have made a packet sniffer using libpcap on C++.
I am using pcap_loop and calling a loopback function , which at the moment i havent put much thought of.
Here is my code.
int PacketSniff(int *count)
{
int ifnum;
int NumOfDevs=0;
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 ip;
bpf_u_int32 netmask;
struct in_addr ip_addr , netmask_addr;
pcap_if_t *devs , *d;
pcap_t *handler;
char packet_filter[] = "ip";
struct bpf_program fcode;
/* Find all interface devices */
pcap_findalldevs(&devs, errbuf);
for(d=devs; d; d=d->next)
{
printf("%d. %s", ++NumOfDevs, d->name);
if (d->description)
{
printf(" (%s)\n", d->description);
}
else
{
printf(" (No description available)\n");
}
}
if(NumOfDevs==0)
{
printf("\nNo interfaces found!\n");
return (-1);
}
/* Prompt User to select interface */
printf("Enter the interface number (1-%d):\n",NumOfDevs);
scanf("%d",&ifnum);
if(ifnum < 1 || ifnum > NumOfDevs)
{
printf("\nInterface number out of range.\n");
/* Free the device list */
pcap_freealldevs(devs);
return (-1);
}
/* Jump to the selected adapter/interface */
for(d=devs; ifnum>1 ;d=d->next, ifnum--);
/* Open the selected adapter/interface */
handler = pcap_open_live(d->name, 65535, 0, 2000, errbuf);
if ((handler = pcap_open_live(d->name, 65535, 0, 2000, errbuf)) == NULL)
{
fprintf(stderr, "Couldn't open device %s: %s\n", d->name, errbuf);
return(-1);
}
if (pcap_datalink(handler) != DLT_EN10MB )
{
fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
pcap_freealldevs(devs);
return -1;
}
/* This means that we set the datalink layer header size at 14 */
int linkhdrlen = 14;
if (pcap_lookupnet(d->name, &ip, &netmask, errbuf) <0 )
{
fprintf(stderr, "Can't get netmask for device %s\n", d->name);
netmask = 0;
ip = 0;
}
/* Compile the filter */
if (pcap_compile(handler, &fcode, packet_filter, 1, netmask) <0 )
{
fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax. Error: %s\n", errbuf);
pcap_freealldevs(devs);
return -1;
}
/* Set the filter */
if (pcap_setfilter(handler, &fcode)<0)
{
fprintf(stderr,"\nError setting the filter. Error: %s\n", errbuf);
pcap_freealldevs(devs);
return -1;
}
printf("\nListening for packets on interface <%s>...\n", d->name);
/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs(devs);
pcap_loop(handler, 0, my_callback, NULL);}
And my_callback is like this:
void my_callback(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_ptr){
struct tm ltime;
char timestr[16];
struct ip_header *iphdr;
struct tcp_header *tcphdr;
time_t local_tv_sec;
/* Convert the timestamp to readable format */
local_tv_sec = header->ts.tv_sec;
localtime_r(&local_tv_sec , <ime);
strftime( timestr, sizeof timestr, "%H:%M:%S", <ime);
/* Print timestamp and length of the packet */
printf("Time >> %s.%.6d \nPacket Length:%d \n\n", timestr, header->ts.tv_usec, header->len);
/* Retireve the position of the ip header http://www.tcpdump.org/pcap.html */
iphdr = (ip_header *) (pkt_ptr +14);
// Advance to the transport layer header then parse and display
// the fields based on the type of hearder: tcp, udp or icmp.
pkt_ptr += 4*iphdr->ver_ihl ;
tcphdr = (tcp_header *)(pkt_ptr + 14);
/* print ip addresses and tcp ports */
printf("%d.%d.%d.%d : %d ---> %d.%d.%d.%d : %d\n\n",
iphdr->saddr.byte1,
iphdr->saddr.byte2,
iphdr->saddr.byte3,
iphdr->saddr.byte4,
tcphdr->src_port,
iphdr->daddr.byte1,
iphdr->daddr.byte2,
iphdr->daddr.byte3,
iphdr->daddr.byte4,
tcphdr->dst_port);}
Now i can sniff packets and print various things .
But my goal is to Extract Stats from the packets (like numOfpackets , numOfTCPpackets , numOfIncomingPAcket , numOfOutgoingPackets , Packet Size Variance , Time Interval Variance ) while they are being sniffed .
But i want this to be done in 1000ms Time-Windows.
For example: Every 1000ms i want an output file of..
numOfTCPPackets = ....
numof = ....
.
.
.
My questions are :
How can i incorporate those Time-Windows?
How to extract the needed stats without interfering too muchwith the sniffing speed.?
Thank you a lot!
Use pcap_next() instead of pcap_loop() to get the packet and set the timeout with pcap_set_timeout() to a small value such as 10 milliseconds to prevent pcap_next() blocking forever so that your code to write the statistics to the file gets a chance to run. You need to call pcap_next() in a loop and have code like the following after the pcap_next() call:
if (cur_time64() - last_time64 >= stat_time64)
{
last_time64 += stat_time64;
print_statistics_to_file();
}
...where cur_time64() returns the current time as a 64-bit integer in microseconds since the epoch (you can use gettimeofday() to implement cur_time64() if you use a Unix-like operating system). stat_time64 would be 1 second, i.e. 1000*1000, in your example.
Then, proceed to process the packet. Check the return value of pcap_next() to see if it returned a packet: if no, continue the loop; if yes, process the packet.
To do the checks without interfering too much with the sniffing speed, your only option is to write the code as efficiently as possible. Handle only those header fields you absolutely need to handle, i.e. you can avoid checking the checksums of IP and TCP headers.
I have connected 3 laptops in same LAN.
lap-1: 192.168.1.2
lap-2: 192.168.1.3
lap-3: 192.168.1.4
I made lap-1 as server and listen on 9333 port. lap-2 acts as client. Using netcat I sent data from lap2 to lap1. I'm able to capture packets using pcap in lap1. I have turned on promiscuous mode using sudo ifconfig eth0 promisc. Also in pcap_live_open method I have set promiscuous mode flag.
Then I turned off promiscuous mode and also in pcap_live_open function. Still I'm able to capture packets.
I googled about promiscuous mode and what I could infer was if device opens an interface in promiscuous mode it would able to capture all packets attached to that network.
so considering this, I made acting lap-3 as server and lap-2 remains as client. I followed the same procedure as above. I run the pcap executable in lap-1 hoping that I would able to capture packets transferred between lap-3 and lap-2 but pcap running in lap-1 is not able to do so with promiscuous mode on. All 3 laps are connected to same network.
Can anyone enlighten me the use of promiscuous mode with simple scenario?
This is my pcap code:
29988 is reverse(swap) of 9333, I'm just looking for that.
#include <pcap/pcap.h>
#include <stdint.h>
const u_char *packet;
int main()
{
char *dev = "eth0";
pcap_t *handle;
int j=0;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
bpf_u_int32 mask;
bpf_u_int32 net;
struct pcap_pkthdr header;
uint8_t *ip_header_len;
uint16_t ip_header_len_val;
uint16_t *port;
/* Find the properties for the device */
while (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
printf("Couldn't get netmask for device %s: %s\n", dev, errbuf);
net = 0;
mask = 0;
}
printf("lookedup pcap device: %s\n", dev);
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ,1,0, errbuf);
if (handle == NULL) {
printf("Couldn't open device %s: %s\n", dev, errbuf);
}
/* Compile and apply the filter */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
printf("Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
pcap_close(handle);
}
/* if (pcap_setfilter(handle, &fp) == -1) {
printf("Couldn't install filter %s: %s", filter_exp, pcap_geterr(handle));
return(-1);
}
*/
/* Grab a packet */
while ((packet = pcap_next(handle, &header)) != NULL)
{
uint16_t *data_size;
uint16_t size,total_len_val,tcp_header_len_val;
char tdata[128];
uint8_t *data,*tcp_header_len;
uint16_t *total_len;
//ip_proto = (uint8_t *)&packet[9];
ip_header_len = (uint8_t *)&packet[14];
ip_header_len_val = (*ip_header_len) & 0x0F;
ip_header_len_val = ip_header_len_val*4;
// printf("IP header len val:%d\n",ip_header_len_val);
port = (uint16_t *)&packet[14+ip_header_len_val+2];
//printf("port:%d\n",*port);
total_len = (uint16_t *)&packet[14+2];
total_len_val = ((*total_len) >> 8) & 0x00FF;
total_len_val = total_len_val + (((*total_len) << 8) & 0xFF00);
//total_len_val=*total_len;
// printf("tot len val:%d\n",total_len_val);
tcp_header_len = (uint8_t *)&packet[14+ip_header_len_val+12];
tcp_header_len_val = (*tcp_header_len) & 0xF0;
tcp_header_len_val = tcp_header_len_val>>4;
tcp_header_len_val = tcp_header_len_val * 4;
// printf("tcp header len val:%d\n",tcp_header_len_val);
size = (total_len_val- ip_header_len_val) - tcp_header_len_val;
data = (uint8_t *)&packet[14+ip_header_len_val+tcp_header_len_val];
memset(tdata,0,128);
mempcpy(tdata,data,size);
tdata[size]='\0';
if((*port)==29988)
{
printf("Data Packet:%s\n",tdata);
}
}
}
I expect that when you say that they are all on the same network, that what you mean is that they are connected to the same Ethernet switch. That switch will only send data to laptop1 that is destined for laptop1. In the old days when it was common to use an Ethernet hub, then all traffic went to all connected devices, but now a switch is very cheap and hubs are no longer common. If you can find a hub, then you can try this out, but otherwise you will only ever be able to see traffic destined for your device.
As Brad mentioned, the router knows at which port the destined device is connected, so it only send the packets there. If you want to try this out, you can use VirtualBox or VMware, and connect the machines in a virtual network.
I am trying to work with pcap but I have some troubles reading a sequence number.
I use the code below to listen for an incomming packet, but when I try to read the sequence number the program halts without an error. Just stops the execution silently.
This code largely comes from the pcap tutorial from the tcpdump site.
bpf_u_int32 net=0, mask=0;
pcap_t *descr = NULL;
struct bpf_program filter;
struct ip *iphdr = NULL;
struct tcphdr *tcphdr = NULL;
struct pcap_pkthdr pkthdr;
const unsigned char *packet = NULL;
char pcap_errbuf[PCAP_ERRBUF_SIZE];
char filter_exp[] = "tcp port 111 dst host 10.0.0.10";
char * dev;
// Define the device
dev = pcap_lookupdev(pcap_errbuf);
if (dev == NULL) {
printf( "Couldn't find default device: %s\n", pcap_errbuf); fflush(stdout);
exit(1);
}
// Find the properties for the device
if( pcap_lookupnet(dev, &net, &mask, pcap_errbuf) == -1 ){
printf("Couldn't get netmask for device %s: %s\n", dev, pcap_errbuf); fflush(stdout);
net = 0;
mask = 0;
}
// Open the session in non-promiscuous mode
descr = pcap_open_live(dev, BUFSIZ, 0, 1000, pcap_errbuf);
if (descr == NULL) {
printf("Couldn't open device %s: %s\n", dev, pcap_errbuf); fflush(stdout);
exit(1);
}
// Compile and apply the filter
if( pcap_compile(descr, &filter, filter_exp, 0, net) == -1) {
printf("Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(descr)); fflush(stdout);
exit(1);
}
if (pcap_setfilter(descr, &filter) == -1) {
printf( "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(descr)); fflush(stdout);
exit(1);
}
packet = pcap_next(descr, &pkthdr );
iphdr = (struct ip *)(packet+14);
tcphdr = (struct tcphdr *)(packet+14+20);
printf("test1\n"); fflush( stdout );
printf("SEQ: %d\n", ntohl(tcphdr->th_seq) ); fflush( stdout );
printf("test2\n");
pcap_close(descr);
The "test1" is printed, but the "test2" and the "SEQ: %d" isn't. Its hard to debug if there's no error at all.
Anyone seen this before?
Thanks
Nikolai Fetissov is correct - you must check whether pcap_next() returns NULL or not. It might return NULL if, for example, the timeout expires and no packets have arrived. In that case, you should keep looping until it returns a non-null value.
However, it could also return NULL if there's an error, and that error might mean that you won't get any more packets. A better routine to use is pcap_next_ex(), which returns returns 1 if the packet was read without problems, 0 if packets are being read from a live capture and the timeout expired, -1 if an error occurred while reading the packet, and -2 if packets are being read from a savefile and there are no more packets to read from the savefile.
In your case, you're doing a live capture, so you should use pcap_next_ex(), and loop until it returns either 1, in which case you print the packet information, or -1, in which case you report an error and exit:
int status;
while ((status = pcap_next_ex(descr, &pkthdr, &packet)) == 0)
;
if (status == -1) {
fprintf(stderr, "pcap_next_ex failed: %s\n", pcap_geterr(descr));
exit(1);
}
iphdr = (struct ip *)(packet+14);
tcphdr = (struct tcphdr *)(packet+14+20);
printf("test1\n"); fflush( stdout );
printf("SEQ: %d\n", ntohl(tcphdr->th_seq) ); fflush( stdout );
printf("test2\n");
pcap_close(descr);
Note also that there's no guarantee that the IPv4 header is 20 bytes long - it could be longer, so you need to extract the header length from the first byte of the IPv4 header (the header length/version field), multiply it by 4 (as it's in units of 4-byte words), and use that when calculating the address of the TCP header, rather than using a hard-coded 20.
In addition, you should also make sure that the link-layer header type of the device, as returned by pcap_datalink(descr), is DLT_EN10MB, to make sure the packets have Ethernet headers rather than some other type of header.
In addition, I just copied your printf code, as I was concentrating on the capture problem. Somebody else added an ntohl() call, which is necessary when printing the sequence number - multi-byte numerical fields in IP and TCP headers are in "network byte order", i.e. big-endian, but you might be running on a little-endian machine, so the sequence number has to be converted to the host byte order before printing it.
Since posting my original question about enumerating multiple devices, I have discovered the reason multiple enumerations were not occuring; The devices all have the same deviceID. With this discovery, I would like to pose a new question, hopfully leading to a work around...
[EDIT]
The new question:
Is there a method, other than unique enumeration, available to get dedicated sockets for each of many devices, when all devices use the same deviceID?
Scenario and rules:
I am developing an application on Windows 7, using Microsoft SDK and an ANSI C compiler. The application design requires it to detect any IrDA device in range, connect using sockets, and communicate. Communication will be to multiple devices through multiple IrDA dongles (one dongle per device), each dongle is connected to the PC via USB. Note: Using virtual COM ports is to be avoided.
The objective: connect each device to its own socket providing an exclusive communication channel between it and the application software.
illustrations and source code (for enumeration of IrDA devices) are below.
[EDIT]
Illustration 1: Overall scenario:
Illustration 2: From Device Manager:
Illustration 3: Properties of each 'found' IrDA device:
Here is the code to enumerate two or more unique IrDA devices: (tested and working well)
//Adapted from: http://msdn.microsoft.com/en-us/library/windows/desktop/ms738544(v=vs.85).aspx
#include <winsock2.h>
#include <ws2tcpip.h>
#include <af_irda.h>
#include <stdio.h>
#include <windows.h>
// link with Ws2_32.lib
char* iGetLastErrorText(DWORD nErrorCode);
int __cdecl main(void)
{
//-----------------------------------------
// Declare and initialize variables
WSADATA wsaData;
int iResult;
int i, tries = 0;
DWORD dwError;
SOCKET Sock = INVALID_SOCKET;
#define DEVICE_LIST_LEN 10
SOCKADDR_IRDA DestSockAddr = { AF_IRDA, 0, 0, 0, 0, "SampleIrDAService" };
unsigned char DevListBuff[sizeof (DEVICELIST) -
sizeof (IRDA_DEVICE_INFO) +
(sizeof (IRDA_DEVICE_INFO) * DEVICE_LIST_LEN)];
int DevListLen = sizeof (DevListBuff);
PDEVICELIST pDevList;
pDevList = (PDEVICELIST) & DevListBuff;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
Sock = socket(AF_IRDA, SOCK_STREAM, 0);
if (Sock == INVALID_SOCKET) {
dwError = WSAGetLastError();
printf
("socket failed trying to create an AF_IRDA socket with error %d\n",
dwError);
if (dwError == WSAEAFNOSUPPORT) {
printf("Check that the local computer has an infrared device\n");
printf
("and a device driver is installed for the infrared device\n");
}
WSACleanup();
return 1;
}
pDevList->numDevice = 0;
while((pDevList->numDevice < 2)&&( tries++ < 3 ))
{
// Sock is not in connected state
iResult = getsockopt(Sock, SOL_IRLMP, IRLMP_ENUMDEVICES,
(char *) pDevList, &DevListLen);
if (iResult == SOCKET_ERROR) {
printf("getsockopt failed with error %d - %s\n", WSAGetLastError(), iGetLastErrorText(WSAGetLastError()));
iResult = closesocket(Sock);
if(iResult == SOCKET_ERROR)
{
printf("closesocket failed with error %d - %s\n", WSAGetLastError(), iGetLastErrorText(WSAGetLastError()));
WSACleanup();
getchar();
return 1;
}
WSACleanup();
getchar();
return 1;
}
if (pDevList->numDevice == 0) {
// no devices discovered or cached
// not a bad idea to run a couple of times
printf("No IRDA devices were discovered or cached\n");
} else {
// one per discovered device
printf("pDevList->numDevice = %d\n", pDevList->numDevice);
for (i = 0; i < (int) pDevList->numDevice; i++) {
printf( "irdaCharSet: %d\nHints1: %d\nHints2: %d\nDeviceID: %x\nDeviceName: %s\n\n",
pDevList->Device[i].irdaCharSet,
pDevList->Device[i].irdaDeviceHints1,
pDevList->Device[i].irdaDeviceHints2,
pDevList->Device[i].irdaDeviceID,
pDevList->Device[i].irdaDeviceName);
// typedef struct _IRDA_DEVICE_INFO
// {
// u_char irdaDeviceID[4];
// char irdaDeviceName[22];
// u_char irdaDeviceHints1;
// u_char irdaDeviceHints2;
// u_char irdaCharSet;
// } _IRDA_DEVICE_INFO;
// pDevList->Device[i]. see _IRDA_DEVICE_INFO for fields
// display the device names and let the user select one
}
}
}
// assume the user selected the first device [0]
memcpy(&DestSockAddr.irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0],4);
iResult = connect(Sock, (const struct sockaddr *) &DestSockAddr, sizeof (SOCKADDR_IRDA));
if (iResult == SOCKET_ERROR)
{
if (iResult == SOCKET_ERROR) {
printf("connect failed with error %d - %s\n", WSAGetLastError(), iGetLastErrorText(WSAGetLastError()));
iResult = closesocket(Sock);
if(iResult == SOCKET_ERROR)
{
printf("closesocket failed with error %d - %s\n", WSAGetLastError(), iGetLastErrorText(WSAGetLastError()));
WSACleanup();
getchar();
return 1;
}
WSACleanup();
getchar();
return 1;
}
}
else
{
printf("connect to first IRDA device was successful\n");
}
getchar();
WSACleanup();
return 0;
}
char* iGetLastErrorText(DWORD nErrorCode)
{
char* msg;
// Ask Windows to prepare a standard message for a GetLastError() code:
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, nErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
// Return the message
if (!msg)
return("Unknown error");
else
return(msg);
}
Closing the loop on this old question: The short answer is no, There is not another method.
IrDA sockets are created and in my case, in Windows 7, enumerated based on a Windows interrogation of any and all IrDA signals active and in range. The enumeration process stores data for each unique Device ID (specifically, IrDA Dev id) it finds. If it sees 3 unique Device IDs, then data for each can be stored, and made available for a connection to be completed. Subsequently, for each connection made, separate conversations can be held with each of those devices. However, if the same three devices are active, and in range, but have identical Device IDs, Windows will only store data corresponding to that one ID, and only one connection can be made.