[Winpcap-users] Packet random access using file seek
Pat Marion
pat.marion at kitware.com
Tue Apr 23 04:11:48 PDT 2013
Thanks for the suggestions Gisle and Guy!
On Tue, Apr 23, 2013 at 6:46 PM, Gisle Vanem <gvanem at broadpark.no> wrote:
> Unless as Guy hints, the layout of 'FILE' is different in your program
> and what it is in winpcap.lib.
>
That's what I'm thinking now.
It could be that your Windows problem has something to do with I/O
> buffering. I.e. '_ftell()' is lying (giving you a wrong file-position)
> since your 'FILE*' is buffered. You could try to set the 'FILE* ' to
> unbuffered with:
>
> your_file = fopen ("bla-bla.pcpa", "rb");
> ...
> setvbuf (your_file, NULL, _IONBF, 0);
>
I gave this a shot, but it didn't have an effect. It does seem to be
related to buffering though, because the file position reported by ftell is
always greater than what I expect it to be, but never greater by more than
4096.
I wrote a test program that demonstrates the problem. You can run the
program by passing a pcap save filename as the only argument. It prints
the file position after pcap_fopen_offline(), which is expected to be 24,
and then it reads one packet with pcap_next_ex() and prints the file
position again, which should be 24 + 16 + packet data length. 24 is the
number of bytes in the pcap global header, 16 is the number of bytes in a
packet header.
Perhaps, as Guy suggests, I am making dangerous assumptions on the pcap
file layout, and my general strategy of using file seeking is one that I
will have to ultimately abandon.
Anyway, the output values depend on the pcap file used for testing. An
example output on macosx:
File position after pcap_fopen_offline: 24
File position after pcap_next_ex: 1288
Expected file position: 1288
While on Windows it prints:
File position after pcap_fopen_offline: 4096
File position after pcap_next_ex: 4096
Expected file position: 1288
My speculation is that file buffering is used by stdio, and ftell called
within the winpcap dll would report the correct file read position, but
ftell called by my program returns the location at the end of the read
buffer.
// test.cpp
#include <pcap.h>
#include <cstdio>
#include <iostream>
int main(int argc, char* argv[])
{
char errbuff[PCAP_ERRBUF_SIZE];
FILE* myFile = fopen(argv[1], "rb");
//setvbuf(this->MyFile, NULL, _IONBF, 0);
pcap_t *pcapFile = pcap_fopen_offline(myFile, errbuff);
if (!pcapFile)
{
std::cout << "pcap error: " << errbuff << std::endl;
return 1;
}
std::cout << "File position after pcap_fopen_offline: " << ftell(myFile)
<< std::endl;
const unsigned char* data;
struct pcap_pkthdr *header;
pcap_next_ex(pcapFile, &header, &data);
std::cout << "File position after pcap_next_ex: " << ftell(myFile) <<
std::endl;
std::cout << "Expected file position: " << 24 + 16 + header->len <<
std::endl;
pcap_close(pcapFile);
fclose(myFile);
return 0;
}
On Tue, Apr 23, 2013 at 6:46 PM, Gisle Vanem <gvanem at broadpark.no> wrote:
> "Pat Marion" <pat.marion at kitware.com> wrote:
>
> I took a look at the implementation of pcap_hopen_offline(). I see that
>> it
>> takes the input FILE* and creates a new FILE* using a series of function
>> calls:
>>
>
> Not excactly. It takes an OS low level handle and gives you a 'FILE*'
> suitable for the CRT you're using in your program. '_get_osfhandle()' is
> documented here:
> http://msdn.microsoft.com/en-**us/library/ks2530z6(v=vs.71).**aspx<http://msdn.microsoft.com/en-us/library/ks2530z6(v=vs.71).aspx>
>
>
> _fileno()
>> _get_osfhandle()
>> _open_osfhandle()
>> _fdopen()
>>
>> So, if I understand correctly, it is creating a new FILE* that is relative
>> to its own CRT.
>>
>
> Yes.
>
>
> I think that means I can no longer use any information I
>> query about the original input FILE*, because winpcap has created its own
>> FILE* stream to read from.
>>
>
> But check 'pcap_hopen_offline()' and see that it's calling '_fdopen()'.
> The ret-val of that is a 'FILE*' suitable for the CRT winpcap.lib was built
> for. I fail to see why that shouldn't work. Unless as Guy hints, the
> layout of 'FILE' is different in your program and what it is in
> winpcap.lib.
>
>> So that leads me to think that my plan to use ftell() to record file
>> positions of packets, and fseek() to jump to the begining of packets, is
>> not going to work on Windows. What do you think?
>>
>
> It could be that your Windows problem has something to do with I/O
> buffering. I.e. '_ftell()' is lying (giving you a wrong file-position)
> since your 'FILE*' is buffered. You could try to set the 'FILE* ' to
> unbuffered with:
>
> your_file = fopen ("bla-bla.pcpa", "rb");
> ...
> setvbuf (your_file, NULL, _IONBF, 0);
> Ref.
> http://msdn.microsoft.com/en-**us/library/86cebhfs(v=vs.71).**aspx<http://msdn.microsoft.com/en-us/library/86cebhfs(v=vs.71).aspx>
>
>
> --gv
> ______________________________**_________________
> Winpcap-users mailing list
> Winpcap-users at winpcap.org
> https://www.winpcap.org/**mailman/listinfo/winpcap-users<https://www.winpcap.org/mailman/listinfo/winpcap-users>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winpcap.org/pipermail/winpcap-users/attachments/20130423/83cba48e/attachment-0001.html>
More information about the Winpcap-users
mailing list