As I stated in my last post, I am currently geeking out on packet capture software. The WireShark network analysis tool is pretty awesome and is built using the WinPCap library which is itself a port of libpcap to the Win32 environment. The unfortunate part, or at least for us .NET developers, is that there is no (IMHO of course) good .NET binding to WinPCap. Well, I’ve gone ahead and spent some time getting an initial wrapper done using P/Invoke.
I’ve taken a different initial strategy from the other project I found and I think it makes more sense in the long run. The other project attempts to provide a more elegant binding by wrapping the native functions of WinPCap in a couple of simple objects. This isn’t necessarily bad, however the author decided to hide the actual P/Invoke calls, which means if you (like me) don’t like his class structure, you can’t simply use the P/Invokes directly to build your own. So, I went ahead and I wrote my own set of P/Invoke calls to bind to WinPCap.
tried to stick to the following rules:
- All P/Invoke method name exactly match the native function names
- All managed type names used in marshalling exactly match the native struct names
- All method parameters in the P/Invokes have the same name as in their native functions
- Marshal parameters as closely as possible (i.e. don’t just use IntPtr for everything)
Of course, I couldn’t stick to the rules 100% due to some technical limitations, but in most cases it is obvious where I deviated.
We should see the following advantages from this:
- All documentation already in existence for WinPCap is still 100% relevant.
- All C/C++ code samples using the native WinPCap can be ported (more or less) directly into C# code.
- Developers now have the freedom to build their own tools using WinPCap in .NET using whatever class structure they’d like
Aside from the supporting structs that are used to marshal the unmanaged types, there are only two classes you need to be concerned with in the library.
WinPCapConstants – Holds the constants translated from the #defines of the pcap.h header file
WinPCapDriver – Static class that holds all P/Invoke declarations used to bind to WinPCap. All functions except those that are listed in the WinPCap docs as Windows specific or dealing with packet filtering are currently available. The Windows specific functions and packet filtering functions will be added as the project progresses.
There is also one handy extension method that I added to help with marshalling the various data structures used by WinPCap. It is defined as follows:
public static class IntPtrExtensions
public static TStruct AsStruct<TStruct>(this IntPtr ptr)
return (TStruct)Marshal.PtrToStructure(ptr, typeof(TStruct));
Normally, we’d have to write something like the following to marshal a pcap_if structure from unmanaged to managed code:
pcap_if nic = (pcap_if)Marshal.PtrToStructure(nicPointer, typeof(pcap_if));
This is pretty heinous…In C we would have been able to just cast or dereference the pointer. With the extension method above, the code becomes more readable:
pcap_if nic = nicPointer.AsStruct<pcap_if>();
It isn’t all that much shorter in terms of length, but it reads much more like English.
My next step is to continue porting the original WinPCap examples from C to C#. This will help me test the P/Invoke calls and learn more about WinPCap and how it is supposed to operate. After that I will create my own higher-level wrapper using C# to abstract the details. Again, the best part of all this is that if you don’t like my high level code then you should still at least be able to access WinPCap via .NET, albeit in a more raw form.
The following code should work, but you first need to install WinPCap. I also recommend you download the developer pack so you can compare the native C examples with the couple of .NET ones I’ve done so far. The differences are relatively minor, but important since they mostly have to do with features/limitations of mixing C and .NET. Also, the HTML based documentation for WinPCap is still valid, and I have yet to put much in the way of comments in my code.
Consider the following downloads as Alpha quality at best:
Download Solution – Nomad.Net.PacketCapture.zip
Download Solution – Nomad.Net.PacketCapture.Examples.zip