fix(placa): Wi-Fi só vale se alcança o roteador da casa

Associar numa rede que não é a da casa fazia o serviço dar o Wi-Fi como
conectado, mover o cabo para .34 e responder pelo wlan0: a placa sumia da
rede. Agora:
- a conexão só conta quando o gateway responde pelo wlan0;
- falha com mensagem "conectei em X, mas não chego ao roteador";
- rotas do wlan0 com métrica 600 (o cabo continua preferido);
- ignore_routes_with_linkdown: cabo desligado não segura rota.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
julio
2026-10-08 03:17:28 -03:00
co-authored by Claude Opus 5.5
parent d7058aaa7a
commit f8d2ebf705
2 changed files with 23 additions and 6 deletions
+21 -5
View File
@@ -98,6 +98,16 @@ class Wifi:
link = sh('iw', 'dev', IFACE, 'link').stdout
return 'Connected to' in link
def gateway_wlan(self):
m = re.search(r'default via (\S+)', sh('ip', '-4', 'route', 'show', 'dev', IFACE).stdout)
return m.group(1) if m else (GATEWAY if (self.rede() or {}).get('ip_fixo', True) else '')
def chega_na_rede(self):
"""Associar não basta: o roteador tem que responder PELO Wi-Fi. Uma rede que não é a da casa
(outro roteador, rede de visitante) associa normalmente e deixaria a placa inacessível."""
gw = self.gateway_wlan()
return bool(gw) and sh('ping', '-c', '1', '-W', '2', '-I', IFACE, gw, timeout=6).returncode == 0
def ip_wlan(self):
m = re.search(r'inet (\d+\.\d+\.\d+\.\d+)', sh('ip', '-4', 'addr', 'show', IFACE).stdout)
return m.group(1) if m else ''
@@ -161,9 +171,11 @@ class Wifi:
self.filhos['wpa'] = subprocess.Popen(['wpa_supplicant', '-i', IFACE, '-D', 'nl80211', '-c', str(RUN / 'wpa.conf')],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if rede.get('ip_fixo', True):
conteudo = f'[Match]\nName={IFACE}\n\n[Network]\nAddress={IP_FIXO}/24\nGateway={GATEWAY}\nDNS={DNS}\n'
# rotas do Wi-Fi com métrica maior: com o cabo ligado, o cabo sempre ganha
conteudo = (f'[Match]\nName={IFACE}\n\n[Network]\nDNS={DNS}\n\n[Address]\nAddress={IP_FIXO}/24\nRouteMetric=600\n'
f'\n[Route]\nGateway={GATEWAY}\nMetric=600\n')
else:
conteudo = f'[Match]\nName={IFACE}\n\n[Network]\nDHCP=ipv4\n\n[DHCPv4]\nRouteMetric=100\n'
conteudo = f'[Match]\nName={IFACE}\n\n[Network]\nDHCP=ipv4\n\n[DHCPv4]\nRouteMetric=600\n'
gravar(NETWORK, conteudo, 0o644) # o systemd-networkd põe o endereço quando conectar
sh('networkctl', 'reload')
sh('networkctl', 'reconfigure', IFACE)
@@ -342,7 +354,7 @@ button{{padding:14px;border:0;border-radius:10px;background:var(--azul);color:#0
return
agora = time.time()
if self.modo == 'cliente':
if self.conectado() and self.ip_wlan():
if self.conectado() and self.ip_wlan() and self.chega_na_rede():
if not self.ok_em:
log('conectado em', self.rede()['ssid'], 'com', self.ip_wlan())
if self.rede().get('ip_fixo', True):
@@ -355,8 +367,12 @@ button{{padding:14px;border:0;border-radius:10px;background:var(--azul);color:#0
limite = QUEDA_TOLERADA if self.ok_em else ESPERA_CONECTAR
if agora - (self.ok_em or self.desde) > limite:
if not self.ok_em:
self.erro = (f'Não consegui conectar em “{self.rede()["ssid"]}”. Confira a senha e se a rede está '
'ligada, e tente de novo.')
if self.conectado():
self.erro = (f'Conectei em “{self.rede()["ssid"]}”, mas por ela não chego ao roteador da casa '
f'({self.gateway_wlan() or GATEWAY}). Escolha a rede onde ficam o PC e o celular do Carinha.')
else:
self.erro = (f'Não consegui conectar em “{self.rede()["ssid"]}”. Confira a senha e se a rede está '
'ligada, e tente de novo.')
if self.anterior is not False: # a rede nova falhou: a antiga continua salva
if self.anterior:
gravar(REDE, self.anterior)
+2 -1
View File
@@ -11,7 +11,8 @@ install -d -m 700 /etc/carinha-wifi
install -m 755 carinha_wifi.py /usr/local/sbin/carinha-wifi
install -m 644 carinha-wifi.service /etc/systemd/system/carinha-wifi.service
# Cabo e Wi-Fi na mesma rede: cada placa de rede só responde pelo próprio endereço (sem "ARP flux")
printf 'net.ipv4.conf.all.arp_ignore=1\nnet.ipv4.conf.all.arp_announce=2\n' > /etc/sysctl.d/90-carinha-arp.conf
# e cabo desconectado não segura rota: o tráfego passa direto para o Wi-Fi
printf 'net.ipv4.conf.all.arp_ignore=1\nnet.ipv4.conf.all.arp_announce=2\nnet.ipv4.conf.all.ignore_routes_with_linkdown=1\nnet.ipv4.conf.default.ignore_routes_with_linkdown=1\n' > /etc/sysctl.d/90-carinha-arp.conf
sysctl -q --system
systemctl daemon-reload
systemctl enable carinha-wifi