So, I spent the afternoon trying to send an LLDP packet in c# using SharpPcap and Packet.Net.
What I came up with bombs with an NullReferenceException. I know why, but I don't know what to do about it.
This is my code:
namespace LLDPTest {
using System;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
using PacketDotNet;
using SharpPcap.WinPcap;
class Program {
static void Main(string[] args) {
//var timer = new Timer(state => SendLLDPPacketOnAllInterfaces(), null, 0, 1000);
SendLLDPPacketOnAllInterfaces();
Console.ReadLine();
}
private static void SendLLDPPacketOnAllInterfaces() {
var winPcapDeviceList = WinPcapDeviceList.Instance;
foreach (var device in winPcapDeviceList.Where(device => device.Interface.GatewayAddress != null)) {
SendLLDPPacket(device);
}
}
private static void SendLLDPPacket(WinPcapDevice device) {
var packet = LLDPPacket.RandomPacket();
//packet.Header = ???
var ethernetPacket = new EthernetPacket(device.Addresses[1].Addr.hardwareAddress, PhysicalAddress.Parse("01-80-C2-00-00-0E"), EthernetPacketType.LLDP);
ethernetPacket.PayloadPacket = packet;
device.Open();
device.SendPacket(ethernetPacket);
device.Close();
Console.WriteLine("LLDP packet sent!");
}
}
}
The exception is thrown in in line 36 (device.SendPacket(ethernetPacket);
)
The reason for this is that the packet's header property must not be null. The exception is thrown in line 229 of Packet.cs where the following check is performed:
if ((this.header.Bytes != this.payloadPacketOrData.ThePacket.header.Bytes) || ((this.header.Offset + this.header.Length) != this.payloadPacketOrData.ThePacket.header.Offset))
{
return false;
}
Long story short, I simply don't know what I should set the header property to, there are no examples on Google or anywhere else.
EDIT: this.payloadPacketOrData.ThePacket.header
is null. This is the packet that results from the call to LLDPPacket.RandomPacket();
. Unfortunately the header property has no setter.
EDIT2: I'm using the latest versions of both packets from NuGet.
EDIT3: http://wiki.wireshark.org/LinkLayerDiscoveryProtocol says that
It's interesting to note that unlike the LLDP drafts referenced above, the final LLDP standard abandoned the notion of an LLDP Header and instead simply mandated the presence of certain TLVs. In the various draft documents the LLDP Header was supposed to include a Version field. The current LLDP standard does not include any notion of a Version.
Sigh. I have no idea why, but after checking the unit tests (https://github.com/antmicro/Packet.Net/blob/master/Test/PacketType/LldpTest.cs) I stumbled upon the solution (lines 78-79):
I don't know why what the authors call "reparsing" is necessary, but now it works.