@@ -7,7 +7,7 @@ const util = require('util');
77
88class KNXInterface extends EventEmitter {
99
10- constructor ( knxInterface ) {
10+ constructor ( knxInterface , options = { } ) {
1111 super ( ) ;
1212
1313 // Setting object parameters from parameters from the interfacemanager
@@ -16,6 +16,11 @@ class KNXInterface extends EventEmitter {
1616 this . macAddress = knxInterface . interfaceMac ;
1717 this . knxAddress = knxInterface . knxAddress ;
1818
19+ // Resolver (from the interface manager) that maps the gateway IP to the local OS
20+ // interface name sharing its subnet. Re-run on every connect so a reboot that
21+ // reorders interfaces can't leave the tunnel bound to the wrong (V)LAN.
22+ this . getLocalInterfaceName = options . getLocalInterfaceName ;
23+
1924 // KNX interface settings/variabeles
2025 this . isConnected = false ; // Boolean to keep track of the connection status.
2126 this . isTimedOut = false ; // Boolean to keep track of timeout events.
@@ -43,7 +48,13 @@ class KNXInterface extends EventEmitter {
4348 // The KNX tunnel connection itself through the knx library
4449 if ( this . isConnected === true && ! this . isTimedOut ) return ; // Skip re-initializing when already connected and healthy.
4550 try {
46- this . knxConnection = new knx . Connection ( {
51+ // Resolve which local interface routes to this gateway. When it can't be
52+ // determined we omit the option so the knx lib keeps its default behaviour.
53+ const localInterface = typeof this . getLocalInterfaceName === 'function'
54+ ? this . getLocalInterfaceName ( this . ipAddress )
55+ : undefined ;
56+
57+ const connectionOptions = {
4758 ipAddr : this . ipAddress , // IP address obtained through interfacemanager
4859 ipPort : 3671 , // Fixed and part of the KNXnet/IP protocol.
4960 physAddr : this . knxAddress , // KNX address obtained through interfacemanager
@@ -90,7 +101,16 @@ class KNXInterface extends EventEmitter {
90101 this . log ( 'Error from FSM:' , connstatus ) ;
91102 } ,
92103 } ,
93- } ) ;
104+ } ;
105+
106+ // Bind to the interface on the gateway's subnet so the CONNECT_REQUEST HPAI
107+ // carries a routable source address (critical on multi-interface hosts/SHS).
108+ if ( localInterface ) {
109+ this . log ( `Binding tunnel to local interface ${ localInterface } ` ) ;
110+ connectionOptions . interface = localInterface ;
111+ }
112+
113+ this . knxConnection = new knx . Connection ( connectionOptions ) ;
94114 } catch ( error ) {
95115 this . log ( 'KNX lib error' , error ) ; // This should be able to catch the 'no valid ipv4 interfaces' error
96116 }
0 commit comments