question

BenAtkinson-0174 avatar image
0 Votes"
BenAtkinson-0174 asked BenAtkinson-0174 edited

How to Obtain IP Destination Address from UDP Packet

I am using Azure RTOS (formerly Express Logic) NetX v. 5 on a Reneasas S7G2 platform with Synergy SSP.

In our application, we receive UDP packets - both directed at our IP address and directed at the IP Broadcast address - and I need to differentiate between the two.

The function nx_udp_packet_info_extract() has the ip_address parameter, but this is the source address - not the destination address.

How can I get the destination address from the IP header of a UDP packet? Or - more specifically - is there an API call that will allow me to determine if a received UDP packet was sent to the broadcast address or my device's specific IP address?

Thanks for your help.

Regards,

Ben

azure-rtos
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

BenAtkinson-0174 avatar image
0 Votes"
BenAtkinson-0174 answered BenAtkinson-0174 edited

TiejunZhou:

We are implementing support for the EtherNet/IP industrial protocol in our measurement gauge. The EtherNet/IP spec requires differentiating between received UDP packets sent to the broadcast vs. the "directed" destination address. This is needed thwart DDOS attacks. If the incoming UDP packet has the broadcast address as its destination, the protocol backs off for a random period of time before sending the response. If the incoming UDP packet is "directed," then the protocol sends the response immediately.

......................

I also have an additional question. I found in the NetX documentation and source code that the NX_PACKET structure has a pointer to the IPv4 header of the received UDP packet. I tried using the following code to extract and examine the IP destination address and network mask of the received UDP packet, but I'm getting very inconsistent results in the values found in the "nx_ip_header_destination_ip" field:

 static uint8 IsUdpBroadcastPacket (NX_PACKET *pCmdPacket) {
     ULONG           destinationIpAddr;
     ULONG           inverseNetworkMask;     // Clear out the network portion, keep only the host portion of the address.
     NX_IPV4_HEADER *pIpV4Header;
     uint8           returnValue = false;

     do {
         if (NULL == pCmdPacket) { break; }

         if (NX_IP_VERSION_V4 != pCmdPacket->nx_packet_ip_version) { break; }

         if (NULL == pCmdPacket->nx_packet_address.nx_packet_interface_ptr) { break; }

         pIpV4Header = (NX_IPV4_HEADER*)pCmdPacket->nx_packet_ip_header;
         destinationIpAddr = pIpV4Header->nx_ip_header_destination_ip;
         inverseNetworkMask = ~(pCmdPacket->nx_packet_address.nx_packet_interface_ptr->nx_interface_ip_network_mask);

         msgLog("%s: UDP Packet - Inverse Network mask: 0x%8.8lX, Dest Addr: 0x%8.8lX", __FUNCTION__, inverseNetworkMask, destinationIpAddr);

         // If the host portion of the IPV4 address is all Fs, then
         // this is a broadcast address.
         returnValue = (destinationIpAddr & inverseNetworkMask) == (0xFFFFFFFFUL & inverseNetworkMask);
     } while (false);

     return returnValue;
 }

    
 static NX_UDP_SOCKET udpCIP;

 void eips_usersock_udpCIPReceive () {

 ... %< %< snippet %< %< ...

     NX_PACKET  *cmdPacket;
     uint8       isUdpBroadcastPacket = 0;
     char        packetPayload[32];
     ULONG       pktLen;
     char        recvBuf[USERSOCK_MAX_BUF_SIZ];
     UINT        returnCode;

     returnCode = nx_udp_socket_receive(&udpCIP, &cmdPacket, NX_NO_WAIT);

 ... %< %< snippet %< %< ...

     returnCode = nx_packet_data_retrieve(cmdPacket, recvBuf, &pktLen);

 ... %< %< snippet %< %< ...

     isUdpBroadcastPacket = IsUdpBroadcastPacket(cmdPacket);

     strncpy(&packetPayload[0], &recvBuf[0], sizeof(packetPayload));
     packetPayload[sizeof(packetPayload) - 1] = '\0';
     if (pktLen < sizeof(packetPayload)) { packetPayload[pktLen] = '\0'; }
     msgLog("%s: Received UDP packet at the %s address, PAYLOAD: <%s>",
             __FUNCTION__, isUdpBroadcastPacket ? "BROADCAST" : "DIRECTED", &packetPayload[0]);
 }

I'm using a separate Linux system to send UDP broadcast packets to my device via netcat:

 me@somewhere:~$ echo 'BROADCAST 1' | nc -b -u 192.168.1.255 44818
 me@somewhere:~$ echo 'BROADCAST 2' | nc -b -u 192.168.1.255 44818
 me@somewhere:~$ echo 'BROADCAST 3' | nc -b -u 192.168.1.255 44818
 me@somewhere:~$ echo 'BROADCAST 4' | nc -b -u 192.168.1.255 44818

With the results of my code and the NetX destination address analysis:

 [ 
 {"Time":     285833, "Msg": "IsUdpBroadcastPacket: UDP Packet - Inverse Network mask: 0x000000FF, Dest Addr: 0xE8181ECA"},
 {"Time":     285833, "Msg": "eips_usersock_udpCIPReceive: Received UDP packet at the DIRECTED address, PAYLOAD: <BROADCAST 1 >"},

 {"Time":     289049, "Msg": "IsUdpBroadcastPacket: UDP Packet - Inverse Network mask: 0x000000FF, Dest Addr: 0x0008CBC0"},
 {"Time":     289049, "Msg": "eips_usersock_udpCIPReceive: Received UDP packet at the DIRECTED address, PAYLOAD: <BROADCAST 2 >"},

 {"Time":     291112, "Msg": "IsUdpBroadcastPacket: UDP Packet - Inverse Network mask: 0x000000FF, Dest Addr: 0xE8181ECA"},
 {"Time":     291112, "Msg": "eips_usersock_udpCIPReceive: Received UDP packet at the DIRECTED address, PAYLOAD: <BROADCAST 3 >"},

 {"Time":     293224, "Msg": "IsUdpBroadcastPacket: UDP Packet - Inverse Network mask: 0x000000FF, Dest Addr: 0xFFFFFFFF"},
 {"Time":     293224, "Msg": "eips_usersock_udpCIPReceive: Received UDP packet at the BROADCAST address, PAYLOAD: <BROADCAST 4 >"}
 ]

Even though the UDP destination address (in reality) is always 192.168.1.255 (0xC0A801FF,) the destination address found in the NetX structure is very inconsistent. The address detection code finds the BROADCAST address only one time out of the four, and this appears to be based on a bogus value of 0xFFFFFFFF rather than the actual broadcast address of 0xC0A801FF.

Do you have any ideas about this?

Thank you,

Ben

· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Ben, thanks for sharing your use case! The workaround you have looks good. The unknown destination IP address could be caused by line 14,

pIpV4Header = (NX_IPV4_HEADER*)pCmdPacket->nx_packet_ip_header;

Try to remove '&' and see if it works for you.

0 Votes 0 ·

TiejunZhou,

Thank you for your suggestion about the "extra" address indirection. You did find the issue - a rookie mistake on my part. :) The workaround now performs as expected every time:

[
{"Time": 176397, "Msg": "IsUdpBroadcastPacket: UDP Packet - Inverse Network mask: 0x000000FF, Dest Addr: 0xC0A801FF"},
{"Time": 176397, "Msg": "eips_usersock_udpCIPReceive: Received UDP packet at the BROADCAST address, PAYLOAD: <BROADCAST 1 >"},
]

Regards,

Ben

0 Votes 0 ·

BTW.... I corrected the posted source code so it can be used by others without the address indirection issue.

2 Votes 2 ·
TiejunZhou-7599 avatar image
1 Vote"
TiejunZhou-7599 answered

Currently, it is not supported to retrieve destination IP address. Could you describe your use case? This would help us to decide if we will add this kind of API or not.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.