We discovered this bug trying to register an endpoint (ip 62.22.27.131) to a gatekeeper (ip 62.22.20.229), using H323Plus v1.26.5 w ptlib 2.12.8.
As you can see in the trace log:
------------------------
0:00.010 Yate H323G...f3d7464700 transports.cxx(2363) RAS Gatekeeper discovery on interface: 62.22.27.131:59483 0:00.021 Yate H323G...f3d7464700 h323pdu.cxx(79) Trans Sending PDU [ip$62.22.27.131:59483/ip$62.22.20.229:1719] : gatekeeperRequest { requestSeqNum = 36153 protocolIdentifier = 0.0.8.2250.0.7 rasAddress = ipAddress { ip = 4 octets { 3e 16 1b 83 >... } port = 59483 }
^^^--- We see our RAS Address is set correctly (3e 16 1b 83 = 62.22.27.131) and port 59483 ... rest of the PDU trace has been trimmed ... }
0:00.076 Yate H323G...f3d7464700 h323pdu.cxx(79) H225RAS Receiving PDU [ip$62.22.20.229:54287/ip$62.22.20.229:1719] : gatekeeperConfirm { requestSeqNum = 36153 protocolIdentifier = 0.0.8.2250.0.7 gatekeeperIdentifier = 9 characters { 0047 004b 0040 0070 0070 0063 0069 0067 GK@ppcig 006b k } rasAddress = ipAddress { ip = 4 octets { 3e 16 14 e5 >... } port = 1719 } } Raw PDU: size=25 pos=25.0 { 000 04 80 8d 38 06 00 08 91 4a 00 07 10 00 47 00 4b 8 J G K 00 40 00 70 00 70 00 63 00 69 00 67 00 6b 00 3e @ p p c i g k > 16 14 e5 06 b7 } 0:00.076 Yate H323G...f3d7464700 gkclient.cxx(288) RAS Gatekeeper discovery found ip$62.22.20.229:1719 0:00.076 Yate H323G...f3d7464700 transports.cxx(2461) RAS Gatekeeper discovered at: 62.22.20.229:1719 (if=62.22.27.131:59483)
^^^^---- this transport still has the correct interface / local ip
0:00.076 Yate H323G...f3d7464700 osutil.cxx(189) PTLib File handle high water mark set: 26 Thread unblock pipe 0:00.077 Yate H323G...f3d7464700 tlibthrd.cxx(305) PTLib Created thread 0x7ff3b4008420 Transactor:%x 0:00.077 PTLib Hous...f3d7568700 osutils.cxx(2158) PTLib Cleaning 1 AutoDelete threads 0:00.077 Transactor:d31ab700 tlibthrd.cxx(354) PTLib Started thread 0x7ff3b4008420 (5287) "Transactor:d31ab700" 0:00.077 Transactor:d31ab700 h323trans.cxx(266) Trans Starting listener thread on Transport[remote=ip$62.22.20.229:1719 if=ip$62.22.20.229:54287]
^^^--- See that this new transport has a wrong "if=" (with remote GK address not our local address)
0:00.077 Yate H323G...f3d7464700 transports.cxx(749) TCP Appending H.225 transport ip$62.22.27.131:2720 using associated transport Transport[remote=ip$62.22.20.229:1719 if=ip$62.22.20.229:54287] 0:00.077 Transactor:d31ab700 h323trans.cxx(274) Trans Reading PDU 0:00.077 Transactor:d31ab700 tlibthrd.cxx(1012) PTLib PThread::PXBlockOnIO(22,0) 0:00.077 Yate H323G...f3d7464700 h323trans.cxx(435) Trans Making request: registrationRequest 0:00.077 Yate H323G...f3d7464700 h323pdu.cxx(79) Trans Sending PDU [ip$62.22.20.229:54287/ip$62.22.20.229:1719] : registrationRequest { requestSeqNum = 36154 protocolIdentifier = 0.0.8.2250.0.7 discoveryComplete = true callSignalAddress = 1 entries { [0]=ipAddress { ip = 4 octets { 3e 16 1b 83 >... } port = 2720 }
^^^---- callSignalAddress is our endpoint IP address (62.22.27.131). Ok
} rasAddress = 1 entries { [0]=ipAddress { ip = 4 octets { 3e 16 14 e5 >... } port = 59483 } } ^^^--- rasAddress has been set incorrectly to the remote gatekeeper address (62.22.20.229) although the port is OK (it's the same used in the previous GRQ pdu) }
-------------------
By looking at the source code:
In transports.cxx, function H323TransportUDP::ReadPDU:
PBoolean H323TransportUDP::ReadPDU(PBYTEArray & pdu)
#if PTLIB_VER >= 2110 if (canGetInterface) { WORD notused; // TODO: verify that this actually does the same as the pre 2.11.x version socket->GetLastReceiveAddress(lastReceivedInterface, notused); } #else if (canGetInterface) lastReceivedInterface = socket->GetLastReceiveToAddress(); #endif
Since the PTLIB's version we are using is 2.12.8, the compiled code is as follows:
WORD notused; // TODO: verify that this actually does the same as the pre 2.11.x version socket->GetLastReceiveAddress(lastReceivedInterface, notused);
Be noticed the comment and that the name of the called function is not the same as the pre 2.11.x code: GetLastReceiveAddress() vs GetLastReceiveToAddress()
GetLastReceiveToAddress() returned local ip address but this function has been removed from PTLib and the existing function (the one is used) GetLastReceiveAddress returns the address of the *sender* in the last connection.
Due to use GetLastReceiveAddress, now lastReceivedInterface has the remote ip (62.22.20.229). And lastReceivedInterface is used in the function H323TransportUDP::GetLocalAddress():
H323TransportAddress H323TransportUDP::GetLocalAddress() const { if (canGetInterface && !lastReceivedInterface.IsLoopback()) return H323TransportAddress(lastReceivedInterface, interfacePort);
.....
returning lastReceivedInterface (62.22.20.229) as our local address incorrectly.
The GetLocalAddress function is used in many places so this can cause many problems as the one we have spotted here.