trouble modifying passthru sample

Home Forums Discussions Support trouble modifying passthru sample

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #5306
    asmercer2004
    Participant

      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.

      #6838
      Vadim Smirnov
      Keymaster

        I’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?

        #6839
        asmercer2004
        Participant

          i 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.

          #6840
          Vadim Smirnov
          Keymaster

            SendPacketToAdapter 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).

            #6841
            asmercer2004
            Participant

              That 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.)

              #6842
              asmercer2004
              Participant

                A 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?

                #6843
                asmercer2004
                Participant

                  Another 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.

                Viewing 7 posts - 1 through 7 (of 7 total)
                • You must be logged in to reply to this topic.