Having trouble using winpcap to write DLT_USER0 captures - c++

I'm making a C++ program using MINGW that uses the Winpcap library to save BTLE packets into a PCAP file.
I'm trying to open a PCAP file using the DLT_USER0 link layer type.
I can open DLT_USER0 using the call to pcap_open_dead() but pcap_dump_open() is complaining that it doesn't know the corresponding link type.
I get the following message after calling pcap_geterr():
out-dump.pcap: link-layer type -1 isn't supported in savefiles
Here's my code below.
#define OUT_FILENAME "out-dump.pcap"
pcap_t *pcap_dumpfile; // Descriptor of an open capture instance
pcap_dumper_t *dumper; // libpcap savefile descriptor"
// pcap_open_dead() creates a pcap_t structure to use when
// calling other functions in libpacp
pcap_dumpfile = pcap_open_dead(DLT_USER0, 128);
// Check if pcap_dumpfile was created. If it was not it will return a NULL
if (NULL == pcap_dumpfile)
{
cout << "\npcap_open_dead() FAILED!!!" << endl;
}
else
{
// Open a save file to write to!
dumper = pcap_dump_open(pcap_dumpfile, OUT_FILENAME);
pcap_dump_flush(dumper);
// Check if the dumper was created
if (NULL == dumper)
{
// Printout the FAIL status
cout << "\npcap_dump_open() FAILED!!!" << endl;
// Printout the PCAP Error
cout << "\n" << pcap_geterr(pcap_dumpfile) << endl;
// Close the pcap_dumpfile and deallocate it's resources
pcap_close(pcap_dumpfile);
}
}
I'm using the WinPcap 4.1.2 Developer's Pack to build my C++ application.

Sadly, that's a bug in WinPcap 4.1.2.
Hopefully, a future release of WinPcap will be based on a later version of libpcap in which the bug is fixed.

Related

Can't download file using URLDownloadToFile in Visual C++

This question is about the usage of URLDownloadToFile API.
I am using URLDownloadToFile in Visual C++ MFC application. On Windows server 2008, the program is working fine.
Sample code:
// invalidate cache, so file is always downloaded from web site
// (if not called, the file will be retrieved from the cache if
// it's already been downloaded.)
DeleteUrlCacheEntry(aCSVDownloadURL);
CallbackHandler callbackHandler;
IBindStatusCallback* pBindStatusCallback = NULL;
callbackHandler.QueryInterface(IID_IBindStatusCallback,
reinterpret_cast<void**>(&pBindStatusCallback));
HRESULT hr = URLDownloadToFile(
NULL, // A pointer to the controlling IUnknown interface
DownloadURL,
FileName, // Filename to save the downloaded file in local
0, // Reserved. Must be set to 0.
pBindStatusCallback // Callback interface to catch the download response; basically the file name
);
if (hr == S_OK)
{
cout << "Download OK" << endl;
}
else if (hr == E_OUTOFMEMORY)
{
cout << "The buffer length is invalid, or there is insufficient memory to complete the operation." << endl;
} else if (hr == INET_E_DOWNLOAD_FAILURE)
{
cout << "The specified resource or callback interface was invalid." << endl;
}
else {
cout << "Other error" << endl;
}
But when run the app in Windows Server 2012 R2, I get the below error:
Error code: INET_E_DOWNLOAD_FAILURE
Description: The specified resource or callback interface was invalid.
Have done googling for few hours, but still no luck. It would be very much appreciated if there is a solution.
The program is created using Visual Studio 2015

I2C error when using the Windows Monitor Configuration Functions

I'm attempting to get/set the brightness level of the monitor through the Windows API. I've tried both the Low-Level Monitor Configuration Functions and the High-Level Monitor Configuration Functions, but they both seem to be breaking in the same place. In both cases I have no problem getting the HMONITOR handle and getting the physical monitor handle from the HMONITOR, but once I try to query the DDC/CI capabilities, I get an error saying "An error occurred while transmitting data to the device on the I2C bus."
The particular functions that cause this error are GetMonitorCapabilities for the high-level functions and GetCapabilitiesStringLength for the low-level functions. They both cause the same error.
This leads me to believe that maybe my monitor doesn't support DDC/CI, but I know my laptop's monitor brightness can be changed through the control panel, so it must be controlled through software somehow. Also I can successfully use the WMI classes in a PowerShell script to get/set the brightness as described on this page. Most things I've read suggest that most modern laptop screens do support DDC/CI.
Is there any way to find out what is causing this error or to get more information about it? I'm currently working in C++ in Visual Studio 2013 on Windows 7. I could probably use WMI in my C++ program if I can't get this current method working, but I thought I would ask here first.
Here's the code I currently have:
#include "stdafx.h"
#include <windows.h>
#include <highlevelmonitorconfigurationapi.h>
#include <lowlevelmonitorconfigurationapi.h>
#include <physicalmonitorenumerationapi.h>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
DWORD minBrightness, curBrightness, maxBrightness;
HWND curWin = GetConsoleWindow();
if (curWin == NULL) {
std::cout << "Problem getting a handle to the window." << std::endl;
return 1;
}
// Call MonitorFromWindow to get the HMONITOR handle
HMONITOR curMon = MonitorFromWindow(curWin, MONITOR_DEFAULTTONULL);
if (curMon == NULL) {
std::cout << "Problem getting the display monitor" << std::endl;
return 1;
}
// Call GetNumberOfPhysicalMonitorsFromHMONITOR to get the needed array size
DWORD monitorCount;
if (!GetNumberOfPhysicalMonitorsFromHMONITOR(curMon, &monitorCount)) {
std::cout << "Problem getting the number of physical monitors" << std::endl;
return 1;
}
// Call GetPhysicalMonitorsFromHMONITOR to get a handle to the physical monitor
LPPHYSICAL_MONITOR physicalMonitors = (LPPHYSICAL_MONITOR)malloc(monitorCount*sizeof(PHYSICAL_MONITOR));
if (physicalMonitors == NULL) {
std::cout << "Unable to malloc the physical monitor array." << std::endl;
return 1;
}
if (!GetPhysicalMonitorsFromHMONITOR(curMon, monitorCount, physicalMonitors)) {
std::cout << "Problem getting the physical monitors." << std::endl;
return 1;
}
std::cout << "Num Monitors: " << monitorCount << std::endl; // This prints '1' as expected.
wprintf(L"%s\n", physicalMonitors[0].szPhysicalMonitorDescription); // This prints "Generic PnP Monitor" as expected
// Call GetMonitorCapabilities to find out which functions it supports
DWORD monCaps;
DWORD monColorTemps;
// The following function call fails with the error "An error occurred while transmitting data to the device on the I2C bus."
if (!GetMonitorCapabilities(physicalMonitors[0].hPhysicalMonitor, &monCaps, &monColorTemps)) {
std::cout << "Problem getting the monitor's capabilities." << std::endl;
DWORD errNum = GetLastError();
DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
LPVOID buffer;
FormatMessage(flags, NULL, errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&buffer, 0, NULL);
wprintf(L"%s\n", buffer);
return 1;
}
// Same error when I use GetCapabilitiesStringLength(...) here.
// More code that is currently never reached...
return 0;
}
Edit: Also I should note that physicalMonitors[0].hPhysicalMonitor is 0, even though the monitor count and text description are valid and the GetPhysicalMonitorsFromHMONITOR function returns successfully. Any thoughts on why this might be?
This is a "wonky hardware" problem, the I2C bus it talks about is the logical interconnect between the video adapter and the display monitor. Primarily useful for plug & play. Underlying error code is 0xC01E0582, STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA. It is generated by a the DxgkDdiI2CTransmitDataToDisplay() helper function in the video miniport driver. It is the vendor's video driver job to configure it, providing the functions that tickle the bus and to implement the IOCTL underlying GetMonitorCapabilities().
Clearly you are device driver land here, there isn't anything you can do about this failure in your C++ program. You can randomly spin the wheel of fortune by looking for a driver update from the video adapter manufacturer. But non-zero odds that the monitor is at fault here. Try another one first.
I know its bad time to reply but i thought you should know.
The problem you are facing is because of the DDC/CI disabled on your monitor so you should go to the monitor settings and check if DDC/CI is disabled and if it is, then you have to enable it and run your code again. It would work. If you were not able to find DDC/CI option ( some of the monitor have a separate button for enabling/disabling the DDC/CI like the Benq's T71W monitor has a separate down arrow button to enable/disable DDC/CI ) then you should refer to your monitor's manual or contact the manufacturer.
Hope that helps. and sorry for late reply.
Best of luck. :)
As I read the original question, the poster wanted to control a laptop display using DDC/CI. Laptop displays do not support DDC/CI. They provide a stripped down I2C bus sufficient to read the EDID at slave address x50, but that's it.

Flush queued GPIB responses

Architecture ->GBIP from external interface is connected to target ( linux) system via gpib bus.
Inside Linux box , there is ethernet cable from GPIB to motherboard.
The PIC_GPIB card on external interface is IEEE 488.2
I am sending a query from external interface to linux box.
Few scenarios
1) If I send a query which does not expect a response back , then next query send will work.
2) If I send a query which expect response back , and when I have received the response and read it and then fire next query it works fine.
3) BUT if I send a query from external interface and got response back and I ignore to read the response , then Next query fails.
I am requesting help for scenario 3.
The coding is done on linux side and its a socket programming , which uses linux inbuilt function from unistd.h for read and write.
My investigation : I have found there is a internal memory on gbib card on external interface which stores the value of previous response until we have the read. Generally I use IEEE string utility software to write commands that goes to linux box and read reposne via read button .
Could someone please direct me how to clean input buffer or memory which stores value so that write from external command contiunues without bothering to read it.
My code on linux side has been developed in C++ and socket programming. I have used in bulit write and read function to write and read to the gpib and to json server.
Sample code is shown below
bool GpibClass::ReadWriteFromGPIB()
{
bool check = true;
int n = 0;
char buffer[BUFFER_SIZE];
fd_set read_set;
struct timeval lTimeOut;
// Reset the read mask for the select
FD_ZERO(&read_set);
FD_SET(mGpibFd, &read_set);
FD_SET(mdiffFd, &read_set);
// Set Timeout to check the status of the connection
// when no data is being received
lTimeOut.tv_sec = CONNECTION_STATUS_CHECK_TIMEOUT_SECONDS;
lTimeOut.tv_usec = 0;
cout << "Entered into this function" << endl;
// Look for sockets with available data
if (-1 == select(FD_SETSIZE, &read_set, NULL, NULL, &lTimeOut))
{
cout << "Select failed" << endl;
// We don't know the cause of select's failure.
// Close everything and start from scratch:
CloseConnection(mGpibFd);
CloseConnection(mdifferntServer); // this is different server
check = false;
}
// Check if data is available from GPIB server,
// and if any read and push it to gpib
if(true == check)
{
cout << "Check data from GPIB after select" << endl;
if (FD_ISSET(mGpibFd, &read_set))
{
n = read(mGpibFd, buffer, BUFFER_SIZE);
cout << "Read from GPIB" << n << " bytes" << endl;
if(0 < n)
{
// write it to different server and check if we get response from it
}
else
{
// Something failed on socket read - most likely
// connection dropped. Close socket and retry later
CloseConnection(mGpibFd);
check = false;
}
}
}
// Check if data is available from different server,
// and if any read and push it to gpib
if(true == check)
{
cout << "Check data from diff server after select" << endl;
if (FD_ISSET(mdiffFd, &read_set))
{
n = read(mdiffFd, buffer, BUFFER_SIZE);
cout << "Read from diff servewr " << n << " bytes" << endl;
if (0 < n)
{
// Append, just in case - makes sure data is sent.
// Extra cr/lf shouldn't cause any problem if the json
// server has already added them
strcpy(buffer + n, "\r\n");
write(mGpibFd, buffer, n + 2);
std::cout <<" the buffer sixze = " << buffer << std::endl;
}
else
{
// Something failed on socket read - most likely
// connection dropped. Close socket and retry later
CloseConnection(mdiffFd);
check = false;
}
}
}
return check;
}
You should ordinarily be reading responses after any operation which could generate them.
If you fail to do that, an easy solution would be to read responses in a loop until you have drained the queue to empty.
You can reset the instrument (probably *RST), but you would probably loose other state as well. You will have to check it's documentation to see if there is a command to reset only the response queue. Checking the documentation is always a good idea, because the number of instruments which precisely comply with the spec is dwarfed by the number which augment or omit parts in unique ways.

pcap_set_rfmon does not work?

I am trying to set my device to monitor mode, and i know its capable of being in monitor mode doing a "iwconfig wlan0 mode monitor" works, i run my code and i can capture packets from anywhere.
The problem is that in libpcap it fails to set my device to monitor mode at all(without entering the above-mentioned command line).I can't capture any packets until i manually connect to a access point.
pcap_t *handler = pcap_create("wlan0",errbuff);
if(pcap_set_rfmon(handler,1)==0 )
{
std::cout << "monitor mode enabled" << std::endl;
}
handler=pcap_open_live ("wlan0", 2048,0,512,errbuff);
int status = pcap_activate(handler); //it returns 0 here.
so is this a code problem, or the pcap library problem?Anybody successfully set their device to monitor mode without using command lines?I am using a Realtek2500 btw.
You're not supposed to use pcap_open_live and pcap_create/pcap_activate in the same code. Try doing
pcap_t *handler = pcap_create("wlan0",errbuff);
if (handler == NULL)
{
std::cerr << "pcap_create failed: " << errbuf << std::endl;
return; // or exit or return an error code or something
}
if(pcap_set_rfmon(handler,1)==0 )
{
std::cout << "monitor mode enabled" << std::endl;
}
pcap_set_snaplen(handler, 2048); // Set the snapshot length to 2048
pcap_set_promisc(handler, 0); // Turn promiscuous mode off
pcap_set_timeout(handler, 512); // Set the timeout to 512 milliseconds
int status = pcap_activate(handler);
and, of course, check the value of status.
in addtion to Guy Harris's answer.
using pcap_open_live to open your device will make it been activated. you will get PCAP_ERROR_ACTIVATED -4, , when you continue to call pcap_set_rfmon.
/* the operation can't be performed on already activated captures */
#define PCAP_ERROR_ACTIVATED -4
so use pcap_create to open the handle, and set rfmon, and call pcap_activate to activate it.
caution: pcap_set_rfmon() returns 0 on success...
so this code is correct:
pcap_t *handler = pcap_create("wlan0",errbuff);
**if(pcap_set_rfmon(handler,1) )**
{
std::cout << "monitor mode enabled" << std::endl;
}

C++ Serial Port Question

Problem:
I have a hand held device that scans those graphic color barcodes on all packaging. There is a track device that I can use that will slide the device automatically. This track device functions by taking ascii code through a serial port. I need to get this thing to work in FileMaker on a Mac. So no terminal programs, etc...
What I've got so far:
I bought a Keyspan USB/Serial adapter. Using a program called ZTerm I was successful in sending commands to the device.
Example:
"C,7^M^J"
I was also able to do the same thing in Terminal using this command: screen /dev/tty.KeySerial1 57600
and then type in the same command above(but when I typed in I just hit Control-M and Control-J for the carriage return and line feed)
Now I'm writing a plug-in for FileMaker(in C++ of course). I want to get what I did above happen in C++ so when I install that plug-in in FileMaker I can just call one of those functions and have the whole process take place right there.
I'm able to connect to the device, but I can't talk to it. It is not responding to anything.
I've tried connecting to the device(successfully) using these:
FILE *comport;
if ((comport = fopen("/dev/tty.KeySerial1", "w")) == NULL){...}
and
int fd;
fd = open("/dev/tty.KeySerial1", O_RDWR | O_NOCTTY | O_NDELAY);
This is what I've tried so far in way of talking to the device:
fputs ("C,7^M^J",comport);
or
fprintf(comport,"C,7^M^J");
or
char buffer[] = { 'C' , ',' , '7' , '^' , 'M' , '^' , 'J' };
fwrite (buffer , 1 , sizeof(buffer) , comport );
or
fwrite('C,7^M^J', 1, 1, comport);
Questions:
When I connected to the device from Terminal and using ZTerm, I was able to set my baud rate of 57600. I think that may be why it isn't responding here. But I don't know how to do it here.... Does any one know how to do that? I tried this, but it didn't work:
comport->BaudRate = 57600;
There are a lot of class solutions out there but they all call these include files like termios.h and stdio.h. I don't have these and, for whatever reason, I can't find them to download. I've downloaded a few examples but there are like 20 files in them and they're all calling other files I can't find(like the ones listed above). Do I need to find these and if so where? I just don't know enough about C++ Is there a website where I can download libraries??
Another solution might be to put those terminal commands in C++. Is there a way to do that?
So this has been driving me crazy. I'm not a C++ guy, I only know basic programming concepts. Is anyone out there a C++ expert? I ideally I'd like this to just work using functions I already have, like those fwrite, fputs stuff.
Thanks!
Sending a ^ and then a M doesn't send control-M, thats just the way you write it,
to send a control character the easiest way is to just use the ascii control code.
ps. ^M is carriage return ie "\r" and ^J is linefeed "\n"
edit: Probably more than you will (hopefully) ever need to know - but read The Serial Port Howto before going any further.
This isn't a C++ question. You're asking how to interact with the TTY driver to set teh baud rate. The fact that you're opening the file under /dev tells me that you're on a unix derivative, so the relevant man page to read on a linux system is "man 3 termios".
Basically, you use the open() variant above, and pass the file descriptor to tcsetattr/tcgetattr.
Are you sure you've installed all the compiler tools properly? On my OS X 10.5.8 Mac,
termios.h and stdio.h are right there under /usr/include, just as I'd expect. The
code you've already found for serial port programming on other Unix variants should
only require minor changes (if any) to work on a Mac. Can you tell us a bit more about
what you've tried, and what went wrong?
mgb also has a good point about how the control characters need to be represented.
You can set the baud rate with ioctl. Here's a link to an example.
You don't specify which Unix you are using, so below I'm posting some Linux production code I use.
Pleae note below code is a class method so ignore any external (ie undeclared) references.
Steps are as follows -
Configure your termio structure, this is where you set any needed flags etc (ie the step you accomplished using zterm. The termio settings below configure the port to 8 databits, 1 stopbit and no parity (8-n-1). Also the port will be in "raw" (as opposed to cooked) mode so its a character stream, text isn't framed into lines etc The baud constants match the actual value, ie for 56700 baud you use "57600".
The timing parameters mean that characters are returned from the device as soon as they are available.
Once you have your termainal parameters set, you open the device (using POSIX open()), and then can use tcgetattr/tcsetattr to configure the device via the fd.
At this point you can read/write to the device using the read()/write() system calls.
Note that in the below example read() will block if no data is available so you may want to use select()/poll() if blocking is undesirable.
Hope that helps.
termios termio
tcflag_t baud_specifier;
//reset device state...
memset (&termio, 0, sizeof (termios));
read_buffer.clear();
//get our boad rate...
if (!(baud_specifier = baud_constant (baud))) {
ostringstream txt;
txt << "invalid baud - " << baud;
device_status_msg = txt.str();
status = false;
return (true);
}
//configure device state...
termio.c_cflag = baud_specifier | CS8 | CLOCAL | CREAD;
//do we want handshaking?
if (rtscts) {
termio.c_cflag |= CRTSCTS;
}
termio.c_iflag = IGNPAR;
termio.c_oflag = 0;
termio.c_lflag = 0;
//com port timing, no wait between characters and read unblocks as soon as there is a character
termio.c_cc[VTIME] = 0;
termio.c_cc[VMIN] = 0;
//open device...
if ((fd = open (device.c_str(), O_RDWR | O_NOCTTY)) == -1) {
ostringstream txt;
txt << "open(\"" << device << "\") failed with " << errno << " - "
<< std_error_msg (errno);
device_status_msg = txt.str();
status = false;
return (true);
}
//keep a copy of curret device state...
if (tcgetattr (fd, &old_termio) == -1) {
ostringstream txt;
txt << "tcgetattr() failed with " << errno << " - " << std_error_msg (errno);
device_status_msg = txt.str();
status = false;
return (true);
}
//flush any unwanted bytes
if (tcflush (fd, TCIOFLUSH) == -1) {
ostringstream txt;
txt << "tcflush() failed with " << errno << " - " << std_error_msg (errno);
device_status_msg = txt.str();
status = false;
return (true);
}
//apply our device config...
if (tcsetattr (fd, TCSANOW, &termio) == -1) {
ostringstream txt;
txt << "tcsetattr() failed with " << errno << " - " << std_error_msg (errno);
device_status_msg = txt.str();
status = false;
return (true);
}
node_log_f ("successfully initialised device %s at %i baud", "open_device()",
device.c_str(), baud);
status = true;
return (true);
}