Home › Forums › Discussions › Support › trouble modifying passthru sample
- This topic has 6 replies, 2 voices, and was last updated 15 years, 2 months ago by asmercer2004.
-
AuthorPosts
-
September 18, 2009 at 8:28 pm #5306
Hello,
I installed the winpkfilter api and tried modifying the passthru application in the samples directory. I am trying to append gps data (latitude/longitude/altitude) to every outgoing udp packet. I think that I am modifying the data correctly, but nothing passes beyond the passthru application. I modified the code in the if case for sending, all other code is the same as the sample. The UDP packet consists of a platform header (31 bytes) and a string of data (something along the lines of this: update UAV-123 10 20 30 40 ID 3-0). I know that data is going out before I start the application, but whenever i run it the data stops flowing. As soon as I close it the data resumes.
// if the packet is to be sent
if (PacketBuffer.m_dwDeviceFlags == Ndisapi.PACKET_FLAG_ON_SEND)
{
// get a pointer to the EF header
pPlatformHeader = (PlatformHeader*)((byte*)pUdpHeader + sizeof(UdpHeader));// get a pointer to the data and the length of the data
byte* pData = (byte*)pPlatformHeader + sizeof(PlatformHeader);
long dataLength = PacketBuffer.m_Length – (sizeof(ETHER_HEADER) + sizeof(IPHeader) +
sizeof(UdpHeader) + sizeof(PlatformHeader));// copy the data into a local array
byte[] data = new byte[dataLength];
Marshal.Copy((IntPtr)pData, data, 0, (int)dataLength);// look to see if the message is an update message
String msg = ASCIIEncoding.ASCII.GetString(data);
if (msg.Contains(“update”))
{
// get the platform data from the message
String[] tokens = msg.Split(new char[] { ‘ ‘ });
PlatformLatitude = System.Convert.ToDouble(tokens[2]);
PlatformLongitude = System.Convert.ToDouble(tokens[3]);
PlatformAltitude = System.Convert.ToDouble(tokens[4]);
}PacketBuffer.m_Length += (uint)sizeof(GPSHeader);
// Change the length field of the IP header
ushort IPLen = (ushort)(ntohs(pIpHeader->Len) + (ushort)sizeof(GPSHeader));
pIpHeader->Len = htons(IPLen);// Recalculate IP checksum
pIpHeader->Sum = 0;
byte[] ipHeader = new byte[sizeof(IPHeader)];
Marshal.Copy((IntPtr)pIpHeader, ipHeader, 0, ipHeader.Length);
ushort newChecksum = ComputeHeaderIpChecksum(ipHeader, 0, ipHeader.Length);
pIpHeader->Sum = htons(newChecksum);// adjust udp packet length
ushort udpLength = (ushort)(ntohs(pUdpHeader->length) + (ushort)sizeof(GPSHeader));
pUdpHeader->length = htons(udpLength);// recalc udp checksum
pUdpHeader->th_sum = 0;// build the outgoing packet
byte[] newPacket = new byte[sizeof(ETHER_HEADER) + sizeof(IPHeader) + sizeof(UdpHeader) +
sizeof(PlatformHeader) + dataLength + sizeof(GPSHeader)];Marshal.Copy((IntPtr)pEthHeader, newPacket, 0, sizeof(ETHER_HEADER));
Marshal.Copy((IntPtr)pIpHeader, newPacket, sizeof(ETHER_HEADER), sizeof(IPHeader));
Marshal.Copy((IntPtr)pUdpHeader, newPacket, sizeof(ETHER_HEADER) + sizeof(IPHeader),
sizeof(UdpHeader));
Marshal.Copy((IntPtr)pPlatformHeader, newPacket, sizeof(ETHER_HEADER) + sizeof(IPHeader) +
sizeof(UdpHeader), sizeof(PlatformHeader));
Marshal.Copy((IntPtr)pData, newPacket, sizeof(ETHER_HEADER) + sizeof(IPHeader) +
sizeof(UdpHeader) + sizeof(PlatformHeader), (int)dataLength);
int gpsOffset = sizeof(ETHER_HEADER) + sizeof(IPHeader) + sizeof(UdpHeader) +
sizeof(PlatformHeader) + (int)dataLength;
Array.Copy(System.BitConverter.GetBytes(PlatformLatitude), 0, newPacket, gpsOffset, sizeof(double));
Array.Copy(System.BitConverter.GetBytes(PlatformLongitude), 0, newPacket, gpsOffset+8,
sizeof(double));
Array.Copy(System.BitConverter.GetBytes(PlatformAltitude), 0, newPacket, gpsOffset+16, sizeof(double));IntPtr outgoingPacket = Marshal.AllocHGlobal((IntPtr)(newPacket.Length));
Marshal.Copy(newPacket, 0, outgoingPacket, newPacket.Length);ETH_REQUEST outgoingRequest = new ETH_REQUEST();
outgoingRequest.hAdapterHandle = Request.hAdapterHandle;
outgoingRequest.EthPacket.Buffer = outgoingPacket;// put the modified packet on the network card for sending
Ndisapi.SendPacketToAdapter(hNdisapi, ref outgoingRequest);// free outgoing memory
Marshal.FreeHGlobal(outgoingPacket);
}Also here is the code I used for the IP checksum calculation, in case that is the problem.
ushort ComputeHeaderIpChecksum(byte[] header, int start, int length)
{
ushort word16;
long sum = 0;
for (int i = start; i < (length + start); i += 2)
{
word16 = (ushort)(((header << 8) & 0xFF00) + (header & 0xFF));
sum += (long)word16;
}while ((sum >> 16) != 0)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}sum = ~sum;
return (ushort)sum;
}Any help would be greatly appreciated.
September 20, 2009 at 11:08 am #6838I’m not experienced in C# well enough to inspect your code for possible errors. However, I would recommend you to install network sniffer like Network Monitor or Wireshark and intercept your handcrafted packets from the network. Network sniffer will show if anything is wrong with checksum.
Also, I can’t see in the code fragment where do you check if you are working with UDP packet. Or do you treat every outgoing packet as UDP one?
September 21, 2009 at 3:08 am #6839i have wireshark installed and just can’t see the packets at all. When i modified the receiving section of the passthru code i could see bad ip checksum, but got that part fixed (which makes me think it isn’t a checksum problem). To test all this i have an application in the background that generates an outgoing packet every 5 seconds. When the modified passthru program is run there is NOTHING put on the network (not just a bad packet or header or something, but absolutely nothing). If I shut it down the packets are sent as normal.
In answer to your other question, I am looking exclusively for packets that are udp and on ports 34401-34403. That part of the code wasn’t in what i posted, but I am checking these header fields in the loop before comparing the device flags for a send/receive flag. I am not at my desk right now or i’d post that code if you think it would help.
September 21, 2009 at 2:56 pm #6840SendPacketToAdapter can send any packet on the network even if it is not in correct format. I think you just don’t form the correct INTERMEDIATE_BUFFER. I’m not sure I fully understand what you are doing in your C# code as I’m not really experienced in C#, but to my limited knowledge the code is incorrect.
byte[] newPacket = new byte[sizeof(ETHER_HEADER) + sizeof(IPHeader) + sizeof(UdpHeader) +
sizeof(PlatformHeader) + dataLength + sizeof(GPSHeader)];
...
IntPtr outgoingPacket = Marshal.AllocHGlobal((IntPtr)(newPacket.Length));
Marshal.Copy(newPacket, 0, outgoingPacket, newPacket.Length);
ETH_REQUEST outgoingRequest = new ETH_REQUEST();
outgoingRequest.hAdapterHandle = Request.hAdapterHandle;
outgoingRequest.EthPacket.Buffer = outgoingPacket;In your code above you use newPacket as managed INTERMEDIATE_BUFFER and outgoingPacket as unmanaged INTERMEDIATE_BUFFER. However, the size for allocation for newPacket must be sizeof(INTERMEDIATE_BUFFER), not the size you have used above. As well when you copy managed INTERMEDIATE_BUFFER into unmanaged memory once again you should copy sizeof(INTERMEDIATE_BUFFER).
Note that you have to initialize INTERMEDIATE_BUFFER fields (you can copy values from the original structure and adjust m_Length).
Also note that the resulted packet must fit into MAX_ETHER_FRAME (more exactly it should not exceed network interface MTU value).
September 21, 2009 at 3:11 pm #6841That actually makes sense. I actually wasn’t using the INTERMEDIATE_BUFFER structure at all. I was just builing and IntPtr to a packet that I built. I will correct that to look something like:
INTERMEDIATE_BUFFER outgoingBuffer = new INTERMEDIATE_BUFFER();
outgoingBuffer.m_dwDeviceFlags = PacketBuffer.m_dwDeviceFlags; outgoingBuffer.m_Flags = PacketBuffer.m_Flags;
outgoingBuffer.m_Length = PacketBuffer.m_Length + sizeof(GPSHeader);
outgoingBuffer.m_qLink = PacketBuffer.m_qLink;
outgoingBuffer.m_IBuffer = ???should the m_IBuffer field contain just the udp packet data or the entire packet (ether_header, ipheader, etc.)
September 21, 2009 at 5:10 pm #6842A quick update:
I modified my code based on your last comments (thanks for the response by the way), and ended up with this:
byte[] newPacket = new byte[sizeof(ETHER_HEADER) + sizeof(IPHeader) + sizeof(UdpHeader) + sizeof(PlatformHeader) + dataLength + sizeof(GPSHeader)];
…
INTERMEDIATE_BUFFER outgoingBuffer = new INTERMEDIATE_BUFFER();
outgoingBuffer = PacketBuffer;
outgoingBuffer.m_Length = PacketBuffer.m_Length + (uint)sizeof(GPSHeader);
outgoingBuffer.m_IBuffer = newPacket;IntPtr outgoingPacket = Marshal.AllocHGlobal(Marshal.SizeOf(outgoingBuffer));
Marshal.StructureToPtr(outgoingBuffer, outgoingPacket, false);ETH_REQUEST outgoingRequest = new ETH_REQUEST();
outgoingRequest.hAdapterHandle = Request.hAdapterHandle;
outgoingRequest.EthPacket.Buffer = outgoingPacket;// put the modified packet on the network card for sending
Ndisapi.SendPacketToAdapter(hNdisapi, ref outgoingRequest);When it gets to the line Marshal.StructureToPtr(…) I get the following error:
Type could not be marshaled because the length of an embedded array instance does not match the declared
length in the layout.I assume that this is a problem with the data length or something but I can’t figure it out. Any idea as to why I would be getting this error?
September 21, 2009 at 6:41 pm #6843Another update;
I got it working. It turns out the problem I was having was due to how I was allocating the newPacket array. I changed to allocate a byte array of MAX_ETHER_FRAME size and it works fine now. Thanks for your help. I must say that it is refreshing to be able to post a question and get a reasonable answer instead of the usual “reading off the cue card” response that people seem to put on other forums.
-
AuthorPosts
- You must be logged in to reply to this topic.