Skip to content

Commit 0347ee5

Browse files
committed
ap: make the gateway configurable in container mode + fix blank default
Backend: - container mode now provisions the LAN with the configured gateway (IP_GW/IP_NET) instead of a hardcoded 192.168.40.1, so a custom -g applies in both routed and managed modes - empty -g falls back to 192.168.42.1 instead of erroring App: - fix: clearing the gateway field kept the last value (e.g. 67.67.69.69); blank now resets and starts on the default 192.168.42.1 - show 192.168.42.1 as a placeholder hint instead of prefilling the field - show the gateway field in container mode too (only DNS stays hidden) Signed-off-by: ravindu644 <droidcasts@protonmail.com>
1 parent 49ce1ba commit 0347ee5

5 files changed

Lines changed: 34 additions & 22 deletions

File tree

Android/app/src/main/java/com/virtualap/app/ui/screen/MainScreen.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -578,17 +578,19 @@ fun MainScreen(
578578
)
579579
Spacer(Modifier.height(12.dp))
580580

581-
// Gateway IP + DNS are VirtualAP's own L3 — irrelevant when
582-
// a container owns the LAN, so hide them in managed mode.
583-
if (!vm.config.containerMode) {
584-
// Gateway IP
581+
// Gateway IP - the AP subnet gateway in routed mode and the
582+
// LAN gateway provisioned inside the container in managed
583+
// mode, so it's shown in both. Blank uses the default.
585584
var gatewayText by remember(vm.config.gateway) { mutableStateOf(vm.config.gateway) }
586585
val gatewayError = gatewayText.isNotBlank() && !isValidIpv4(gatewayText)
587586
OutlinedTextField(
588587
value = gatewayText,
589588
onValueChange = { v ->
590589
gatewayText = v
591-
if (isValidIpv4(v)) vm.config = vm.config.copy(gateway = v.trim())
590+
when {
591+
v.isBlank() -> vm.config = vm.config.copy(gateway = "")
592+
isValidIpv4(v) -> vm.config = vm.config.copy(gateway = v.trim())
593+
}
592594
},
593595
label = { Text(stringResource(R.string.gateway_ip_label)) },
594596
placeholder = { Text(stringResource(R.string.gateway_ip_placeholder)) },
@@ -614,6 +616,9 @@ fun MainScreen(
614616
)
615617
Spacer(Modifier.height(8.dp))
616618

619+
// DNS is VirtualAP's own L3 — irrelevant when a container owns
620+
// the LAN (it runs its own resolver), so hide it in managed mode.
621+
if (!vm.config.containerMode) {
617622
// DNS Servers
618623
var dnsText by remember(vm.config.dnsServers) { mutableStateOf(vm.config.dnsServers) }
619624
val dnsError = !isValidDnsServers(dnsText)
@@ -648,7 +653,7 @@ fun MainScreen(
648653
modifier = Modifier.fillMaxWidth()
649654
)
650655
Spacer(Modifier.height(8.dp))
651-
} // end !containerMode (Gateway IP + DNS)
656+
} // end !containerMode (DNS)
652657

653658
// Hide SSID
654659
SwitchItem(

Android/app/src/main/java/com/virtualap/app/ui/viewmodel/APViewModel.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ data class APConfig(
2727
val channel: String = "",
2828
val width: String = "auto",
2929
val upstream: String = "auto",
30-
val gateway: String = "192.168.42.1",
30+
val gateway: String = "", // blank = APViewModel.DEFAULT_GATEWAY
3131
val dnsServers: String = "",
3232
val hidden: Boolean = false,
3333
val security: String = "wpa2", // open | wpa2 | wpa2wpa3 | wpa3
@@ -49,7 +49,8 @@ class APViewModel(application: Application) : AndroidViewModel(application) {
4949
channel = validChannelForBand(prefs.apBand, prefs.apChannel),
5050
width = prefs.apWidth,
5151
upstream = prefs.apUpstream,
52-
gateway = prefs.apGateway,
52+
// Normalize a legacy stored default to blank so it shows as a hint.
53+
gateway = prefs.apGateway.takeUnless { it == DEFAULT_GATEWAY } ?: "",
5354
dnsServers = prefs.apDnsServers,
5455
hidden = prefs.apHidden,
5556
security = prefs.apSecurity,
@@ -211,7 +212,7 @@ class APViewModel(application: Application) : AndroidViewModel(application) {
211212
cfg.ssid, cfg.password, cfg.upstream, cfg.band,
212213
cfg.channel.takeIf { it.isNotBlank() },
213214
cfg.width,
214-
cfg.gateway, cfg.dnsServers.takeIf { it.isNotBlank() },
215+
cfg.gateway.ifBlank { DEFAULT_GATEWAY }, cfg.dnsServers.takeIf { it.isNotBlank() },
215216
cfg.hidden,
216217
cfg.security, cfg.pmf,
217218
if (cfg.containerMode) cfg.containerName else ""
@@ -249,6 +250,9 @@ class APViewModel(application: Application) : AndroidViewModel(application) {
249250
fun dismissActionLogs() { showActionLogs = false }
250251

251252
companion object {
253+
/** Default AP/LAN gateway when the gateway field is left blank. */
254+
const val DEFAULT_GATEWAY = "192.168.42.1"
255+
252256
// Must be companion (not instance method) — called from property initializer
253257
// before the instance exists.
254258
fun validChannelForBand(band: String, channel: String): String {

Android/app/src/main/java/com/virtualap/app/util/PreferencesManager.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,10 @@ class PreferencesManager private constructor(context: Context) {
7373
get() = prefs.getString(Constants.KEY_AP_UPSTREAM, "auto") ?: "auto"
7474
set(value) { prefs.edit().putString(Constants.KEY_AP_UPSTREAM, value).apply() }
7575

76+
// Blank = use the default gateway (APViewModel.DEFAULT_GATEWAY). Stored blank
77+
// so the field shows the default as a hint rather than a prefilled value.
7678
var apGateway: String
77-
get() = prefs.getString(Constants.KEY_AP_GATEWAY, "192.168.42.1") ?: "192.168.42.1"
79+
get() = prefs.getString(Constants.KEY_AP_GATEWAY, "") ?: ""
7880
set(value) { prefs.edit().putString(Constants.KEY_AP_GATEWAY, value).apply() }
7981

8082
var apDnsServers: String

Android/app/src/main/res/values/strings.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@
9494
<string name="pmf_label">Protected Management Frames</string>
9595
<string name="pmf_desc">Adds 802.11w protection to WPA2. Leave off if older devices fail to connect</string>
9696
<string name="gateway_ip_label">Gateway IP</string>
97-
<string name="gateway_ip_desc">Custom gateway IP address for the AP subnet</string>
98-
<string name="gateway_ip_placeholder">e.g. 192.168.42.1</string>
97+
<string name="gateway_ip_desc">Leave blank to use the default (192.168.42.1)</string>
98+
<string name="gateway_ip_placeholder">192.168.42.1</string>
9999
<string name="gateway_ip_error">Enter a valid IPv4 address (e.g. 192.168.42.1)</string>
100100
<string name="dns_servers_label">DNS Servers</string>
101101
<string name="dns_servers_desc">Custom upstream DNS servers (comma-separated). Leave blank for auto.</string>

backend/start-ap

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ VAP_BRIDGE="vap-br0" # host-side bridge
6868
VAP_VETH_HOST="vap-v0" # host-side veth (bridge port)
6969
VAP_VETH_PEER="vap-p0" # peer veth before it enters the container
7070
VAP_PORT="vaplan0" # interface name inside the container
71-
VAP_LAN_GW="192.168.40.1" # LAN gateway we provision inside OpenWRT (distinct from ds-br0/ap0)
72-
VAP_LAN_NET="192.168.40.0/24"
71+
# The LAN provisioned inside the container reuses the configured gateway/subnet
72+
# (IP_GW / IP_NET, default 192.168.42.1) - the same one routed mode uses, so a
73+
# custom -g gateway applies in both modes.
7374

7475
# Droidspaces CLI: prefer the install path, fall back to PATH.
7576
if [ -x "/data/local/Droidspaces/bin/droidspaces" ]; then
@@ -715,12 +716,12 @@ ip_up_retry() {
715716

716717
# OpenWrt auto-provisioning: a LAN on VAP_PORT with its own DHCP + NAT out WAN.
717718
provision_openwrt() {
718-
log "Provisioning OpenWrt LAN ($VAP_LAN_GW) on $VAP_PORT..."
719+
log "Provisioning OpenWrt LAN ($IP_GW) on $VAP_PORT..."
719720

720721
ds_run uci set network.vaplan=interface
721722
ds_run uci set network.vaplan.device="$VAP_PORT"
722723
ds_run uci set network.vaplan.proto=static
723-
ds_run uci set network.vaplan.ipaddr="$VAP_LAN_GW"
724+
ds_run uci set network.vaplan.ipaddr="$IP_GW"
724725
ds_run uci set network.vaplan.netmask=255.255.255.0
725726
ds_run uci commit network
726727

@@ -747,8 +748,8 @@ provision_openwrt() {
747748
ds_run /etc/init.d/firewall reload >/dev/null 2>&1
748749
log "OpenWrt firewall (fw3) reloaded - '$VAP_PORT' masqueraded via its wan zone."
749750
else
750-
ds_run iptables-legacy -t nat -D POSTROUTING -s "$VAP_LAN_NET" ! -d "$VAP_LAN_NET" -j MASQUERADE 2>/dev/null
751-
if ds_run iptables-legacy -t nat -A POSTROUTING -s "$VAP_LAN_NET" ! -d "$VAP_LAN_NET" -j MASQUERADE; then
751+
ds_run iptables-legacy -t nat -D POSTROUTING -s "$IP_NET" ! -d "$IP_NET" -j MASQUERADE 2>/dev/null
752+
if ds_run iptables-legacy -t nat -A POSTROUTING -s "$IP_NET" ! -d "$IP_NET" -j MASQUERADE; then
752753
log "OpenWrt NAT installed (iptables-legacy MASQUERADE)."
753754
else
754755
warn "OpenWrt: failed to add iptables-legacy MASQUERADE rule."
@@ -810,7 +811,7 @@ bridge=$VAP_BRIDGE
810811
band=$BAND
811812
channel=$CHANNEL
812813
ssid=$SSID
813-
gateway=$VAP_LAN_GW
814+
gateway=$IP_GW
814815
started=$($DATE '+%Y-%m-%d %H:%M:%S')
815816
EOF
816817

@@ -920,7 +921,7 @@ cmd_start() {
920921
log "VirtualAP is ACTIVE (managed by container '$CONTAINER')!"
921922
log " SSID : $SSID (${BAND}GHz, channel $CHANNEL, ${EFFECTIVE_WIDTH}MHz)"
922923
log " Upstream : container '$CONTAINER' via $VAP_BRIDGE -> $VAP_PORT"
923-
log " LAN : served by the container ($VAP_LAN_GW)"
924+
log " LAN : served by the container ($IP_GW)"
924925
else
925926
# --- Routed mode: classic VirtualAP L3 ---
926927
resolve_upstream || exit 1
@@ -988,7 +989,7 @@ cmd_status() {
988989
elif $GREP -q '^wpa_key_mgmt=SAE' "$RUN_DIR/hostapd.conf"; then $ECHO "security=wpa3"
989990
else $ECHO "security=wpa2"; fi
990991
fi
991-
# gateway/ssid/etc. come from the state file (routed: IP_GW; bridged: VAP_LAN_GW)
992+
# gateway/ssid/etc. come from the state file (IP_GW in both routed + bridged)
992993
if [ -f "$STATE_FILE" ]; then
993994
$GREP -E '^(ssid|band|channel|upstream|upstream_table|upstream_iface|gateway|dns_servers|container|started)=' "$STATE_FILE"
994995
else
@@ -1078,7 +1079,7 @@ while getopts "s:p:o:b:c:W:w:g:d:H:A:M:K:h" opt 2>/dev/null; do
10781079
c) CHANNEL="$OPTARG" ;;
10791080
W) WIDTH="$OPTARG" ;;
10801081
w) PHY_IFACE="$OPTARG" ;;
1081-
g) IP_GW="$OPTARG" ;;
1082+
g) IP_GW="${OPTARG:-192.168.42.1}" ;; # empty -g falls back to the default
10821083
d) DNS_SERVERS="$OPTARG" ;;
10831084
H) HIDDEN="$OPTARG" ;;
10841085
A) SECURITY="$OPTARG" ;;

0 commit comments

Comments
 (0)