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