Search code examples
c#bacnet

BACnet Virtual Devices - never respond to a direct command


Some background: I'm attempting to create a virtual BACnet router with virtual devices behind it (see related post). My test environment consists of a VM ( 10.2.0.15 ) running on my server with a BACnet explorer and Wireshark running on it. I'm writing the code in VS2013 and also running wireshark on my local machine ( 192.168.56.1 ).

When I start the virtual router and send a who-is broadcast from the VM, I see the command and responses on the wireshark running on the vm. On my local machine, I only see the command in wireshark, but not the responses going out.

All of this works fine. However, the source address of the i-am responses ( according to wireshark on the VM as well as in the BACnet explorer details ) is that of the gateway (10.2.0.2) between the VM and my machine.

The Problem Subsequent who-is commands targeting a specific virtual device never get to my local machine. I can see the command being created using wireshark on the vm, but my code never sees the request nor does wireshark on my local machine see a new packet.

The Question Should the source address of the initial i-am responses be the IP of my local machine or the IP address that I've assigned to the virtual device? As stated above, the source address is currently that of the gateway between the VM and my machine.

Here is the code I'm using to construct the NPDU portion of the response to a who-is command - Hopefully someone can point out what I'm doing incorrectly.

        bytes[pos++] = BACnetEnums.BACNET_PROTOCOL_VERSION;

        //Control byte determines what fields exist in the rest of the NPDU record
        bytes[pos++] = this.AssembleControl();  //in the case, the response is 0x28

        //Destination Network Info
        //65535 - Broadcast
        bytes[pos++] = 0xff;  //DNET
        bytes[pos++] = 0xff;  //DNET

        //Destination 
        bytes[pos++] = 0x00;  //DLEN
                              //DADDR
        //none since len = 0 and this is being broadcasted back

        bytes[pos++] = 0x00;  //SNET
        bytes[pos++] = 0x00;  //SNET

        bytes[pos++] = 0x06;  //SLEN

        //address should be 10.1.0.xxx, where x is the deviceid
        bytes[pos++] = this.SADR[0];  //10
        bytes[pos++] = this.SADR[1];  //1
        bytes[pos++] = this.SADR[2];  //0
        bytes[pos++] = this.SADR[3];  //varies based on the ID of the device - pulled from database
        bytes[pos++] = 0xBA;
        bytes[pos++] = 0xC0;

        //HopCount
        bytes[pos++] = 0xff;

Solution

  • Problem Solved

    In case anyone else has the same problem, check your UDP sockets. In my code, I created a send socket and a receive socket and set one of them to non-exclusive. Unfortunately, in doing so, the sending socket will block any packets coming in on the receive port -- however, it will let UDP broadcasts come through so that it appears to work part of the time.