diff --git a/sistema/wifi/carinha_wifi.py b/sistema/wifi/carinha_wifi.py index 86e92ac..74a65de 100644 --- a/sistema/wifi/carinha_wifi.py +++ b/sistema/wifi/carinha_wifi.py @@ -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) diff --git a/sistema/wifi/instalar.sh b/sistema/wifi/instalar.sh index 3c081da..51a3202 100644 --- a/sistema/wifi/instalar.sh +++ b/sistema/wifi/instalar.sh @@ -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