| 97 | } |
| 98 | |
| 99 | bool SplitTunneling::updateState() |
| 100 | { |
| 101 | spdlog::debug("SplitTunneling::updateState begin"); |
| 102 | AppsIds appsIds; |
| 103 | appsIds.setFromList(apps_); |
| 104 | // adapterIp is types::IpAddress; ipv4NetworkOrder() returns 0 for non-v4/invalid which |
| 105 | // matches the previous Ip4AddressAndMask behaviour for empty/invalid input. |
| 106 | DWORD localIp = connectStatus_.defaultAdapter.adapterIp.ipv4NetworkOrder(); |
| 107 | bool isSplitTunnelActive = connectStatus_.isConnected && isSplitTunnelEnabled_; |
| 108 | |
| 109 | // Allow excluded traffic to bypass firewall even when not connected |
| 110 | if (!connectStatus_.isConnected && isSplitTunnelEnabled_ && isExclude_ |
| 111 | && connectStatus_.defaultAdapter.ifIndex != 0 && FirewallFilter::instance().currentStatus()) |
| 112 | { |
| 113 | hostnamesManager_.enable(connectStatus_.defaultAdapter.gatewayIp, |
| 114 | connectStatus_.defaultAdapter.gatewayIpV6, |
| 115 | connectStatus_.defaultAdapter.ifIndex); |
| 116 | FirewallFilter::instance().setSplitTunnelingAppsIds(appsIds); |
| 117 | FirewallFilter::instance().setSplitTunnelingEnabled(isExclude_); |
| 118 | |
| 119 | calloutFilter_.disable(); |
| 120 | splitTunnelServiceManager_.stop(); |
| 121 | } else if (isSplitTunnelActive) { |
| 122 | if (!splitTunnelServiceManager_.start()) { |
| 123 | return false; |
| 124 | } |
| 125 | |
| 126 | DWORD vpnIp = connectStatus_.vpnAdapter.adapterIp.ipv4NetworkOrder(); |
| 127 | |
| 128 | FirewallFilter::instance().setSplitTunnelingAppsIds(appsIds); |
| 129 | FirewallFilter::instance().setSplitTunnelingEnabled(isExclude_); |
| 130 | |
| 131 | if (isExclude_) { |
| 132 | hostnamesManager_.enable(connectStatus_.defaultAdapter.gatewayIp, |
| 133 | connectStatus_.defaultAdapter.gatewayIpV6, |
| 134 | connectStatus_.defaultAdapter.ifIndex); |
| 135 | } else { |
| 136 | appsIds.addFrom(vpnOtherExecutablesId_); |
| 137 | // WireGuard/IKEv2 are point-to-point: vpn.gatewayIp(V6) is invalid for them. |
| 138 | // Fall back to the adapter address (matches RoutesManager::addDnsRoutes and |
| 139 | // doActionsForInclusiveMode{WireGuard,Ikev2}), which Windows resolves on-link |
| 140 | // via the tunnel interface. |
| 141 | const auto &vpn = connectStatus_.vpnAdapter; |
| 142 | const types::IpAddress &gw = vpn.gatewayIp.isValid() ? vpn.gatewayIp : vpn.adapterIp; |
| 143 | const types::IpAddress &gwV6 = vpn.gatewayIpV6.isValid() ? vpn.gatewayIpV6 : vpn.adapterIpV6; |
| 144 | hostnamesManager_.enable(gw, gwV6, vpn.ifIndex); |
| 145 | } |
| 146 | |
| 147 | // For ctrld utility and the main app executable we need special rules for inclusive mode |
| 148 | AppsIds vpnExecutablesForInclusive; |
| 149 | if (!isExclude_) { |
| 150 | vpnExecutablesForInclusive.addFrom(vpnMainExecutableId_); |
| 151 | vpnExecutablesForInclusive.addFrom(ctrldExecutableId_); |
| 152 | } |
| 153 | calloutFilter_.enable(localIp, vpnIp, |
| 154 | connectStatus_.defaultAdapter.adapterIpV6, |
| 155 | connectStatus_.vpnAdapter.adapterIpV6, |
| 156 | appsIds, vpnExecutablesForInclusive, isExclude_, isAllowLanTraffic_, |
no test coverage detected