diff --git a/debian/set_mac_wifi.sh b/debian/set_mac_wifi.sh index ffaf70a..38fb408 100644 --- a/debian/set_mac_wifi.sh +++ b/debian/set_mac_wifi.sh @@ -1,8 +1,6 @@ #!/bin/bash # Script Dinâmico de Configuração de Rede para Raspberry Pi -# Localização sugerida: /usr/local/bin/configure_network.sh -# Uso: sudo ./configure_network.sh [MAC_ADDRESS] -# Deve ser executado com privilégios de root. +# Localização: /usr/local/bin/configure_network.sh # --- Configurações --- LOG_FILE="/var/log/network_config.log" @@ -21,27 +19,25 @@ generate_unique_mac() { serial=$(awk '/Serial/ {print $3}' /proc/cpuinfo | tr -d ' ') if [ -z "$serial" ]; then - # Fallback aleatório printf '%02X:%02X:%02X:%02X:%02X:%02X' $((0x02 | (RANDOM % 256) & 0xFE)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) else local hash hash=$(echo -n "$serial-dm9601" | md5sum | cut -c1-10) - # 02 define como Local Admin Address echo "02:${hash:0:2}:${hash:2:2}:${hash:4:2}:${hash:6:2}:${hash:8:2}" fi } -# Função para definir MAC imediatamente (usada apenas na configuração inicial) +# Função para definir MAC imediatamente set_mac() { local interface="$1" local mac="$2" if ! ip link show "$interface" &> /dev/null; then - log "Interface $interface não encontrada." + log "Interface $interface não encontrada em set_mac." return 1 fi - log "A definir MAC $mac em $interface imediatamente..." + log "A definir MAC $mac em $interface..." if ip link set "$interface" down && \ ip link set dev "$interface" address "$mac" && \ ip link set "$interface" up; then @@ -53,99 +49,112 @@ set_mac() { fi } -# Função para criar regra Udev (Persistência) +# Função para criar regra Udev setup_udev_persistence() { local interface="$1" local target_mac="$2" - # Obtém o MAC original (físico) do adaptador local original_mac original_mac=$(ip link show "$interface" | awk '/ether/ {print $2}' | tr '[:upper:]' '[:lower:]') target_mac=$(echo "$target_mac" | tr '[:upper:]' '[:lower:]') if [ -z "$original_mac" ]; then - log "Não foi possível obter o MAC original para criar regra udev." + log "Erro crítico: Não foi possível obter o MAC original para criar regra udev." return 1 fi - # Cria a regra: Ao adicionar o dispositivo com o MAC original, define o novo MAC + # Cria o ficheiro de regras echo "ACTION==\"add\", SUBSYSTEM==\"net\", ATTR{address}==\"$original_mac\", RUN+=\"/usr/bin/ip link set dev \$name address $target_mac\"" > "$UDEV_RULES_FILE" udevadm control --reload-rules - log "Regra Udev criada em $UDEV_RULES_FILE para persistência." + log "Regra Udev criada/atualizada em $UDEV_RULES_FILE." return 0 } -# Função para verificar se a persistência já está configurada +# Função robusta para verificar persistência is_persistence_configured() { if [ -f "$UDEV_RULES_FILE" ]; then - return 0 + # Verifica se o ficheiro não está vazio (proteção extra) + if [ -s "$UDEV_RULES_FILE" ]; then + log "Ficheiro de persistência encontrado: $UDEV_RULES_FILE" + return 0 + else + log "Ficheiro de persistência existe mas está vazio. Invalidando." + return 1 + fi else + log "Ficheiro de persistência NÃO encontrado." return 1 fi } -# Tarefa em Background para monitorizar Ethernet e ativar Wi-Fi +# Tarefa em Background para monitorizar rede monitor_network_task() { - log "Iniciando tarefa de monitorização de rede (Background)..." - - # Espera inicial para o sistema estabilizar + log "Monitor: A iniciar verificação de rede (aguardando 60s)..." sleep 60 local interface="eth0" local wlan="wlan0" - # Loop infinito para verificação periódica (opcional, ou apenas uma vez) - # Aqui verificamos uma vez após o boot, conforme lógica original do disable_wifi - if ip link show "$interface" &> /dev/null; then - # Verifica 'NO-CARRIER' (cabo desligado) ou estado DOWN - if ip link show "$interface" | grep -q "NO-CARRIER" || ! ip link show "$interface" | grep -q "state UP"; then - log "Interface $interface sem ligação (cabo desligado?). A ativar Wi-Fi..." - + if ip link show "$interface" | grep -q "NO-CARRIER"; then + log "Monitor: Interface $interface sem cabo (NO-CARRIER). A ativar Wi-Fi..." if ip link show "$wlan" &> /dev/null; then ip link set "$wlan" up - # Opcional: Pode-se adicionar lógica para reiniciar o wpa_supplicant ou dhclient - # systemctl restart wpa_supplicant - log "Wi-Fi ($wlan) ativado." + log "Monitor: Wi-Fi ($wlan) ativado." fi else - log "Interface $interface está ativa com ligação. Wi-Fi mantido inalterado." + log "Monitor: Interface $interface ativa. Nenhuma ação necessária." fi - else - log "Interface $interface não encontrada para monitorização." fi } # --- Execução Principal --- -# Verificar root if [ "$(id -u)" -ne 0 ]; then echo "Este script deve ser executado como root." >&2 exit 1 fi -# Criar diretório de log se não existir mkdir -p "$(dirname "$LOG_FILE")" -# 1. Verificar se a persistência já está feita +# 1. Verificar Persistência Existente if is_persistence_configured; then - log "Persistência Udev já configurada. Ignorando configuração de MAC." - # Apenas lança a tarefa de monitorização de rede + log "Configuração já persistida no sistema. A saltar configuração de MAC." monitor_network_task & exit 0 fi -# 2. Determinar o MAC Address a utilizar +# 2. Esperar pela Interface de Rede (Importante para boot/curl) +# O script pode correr antes da interface estar pronta. +IFACE="eth0" +log "A aguardar pela interface $IFACE..." +for i in {1..30}; do + if ip link show "$IFACE" &> /dev/null; then + break + fi + sleep 1 +done + +if ! ip link show "$IFACE" &> /dev/null; then + log "Erro: Interface $IFACE não disponível após 30 segundos. A sair." + exit 1 +fi + +# 3. Determinar o MAC Address TARGET_MAC="" -# 2.1. Verificar argumento passado ao script +# Verificar argumento ($1) if [ -n "$1" ]; then TARGET_MAC="$1" log "MAC definido via argumento: $TARGET_MAC" else - # 2.2. Verificar se é uma execução interativa (terminal) - if [ -t 0 ]; then + # Verificar se é interativo + # IMPORTANTE: Ler de /dev/tty para funcionar com curl | bash + if [ -t 0 ] && [ -e /dev/tty ]; then + # Abre /dev/tty para ler input do utilizador + exec < /dev/tty + echo "Nenhum MAC definido. Deseja:" echo "1) Gerar um novo MAC único automático" echo "2) Introduzir um MAC manualmente" @@ -158,43 +167,38 @@ else ;; 2) read -p "Introduza o MAC (formato XX:XX:XX:XX:XX:XX): " TARGET_MAC - if [[ ! "$TARGET_MAC" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then - log "Formato de MAC inválido." - exit 1 - fi ;; *) - log "Opção inválida. A sair." + log "Opção inválida." exit 1 ;; esac + # Restaura stdin se necessário (embora geralmente não seja crítico aqui) else - # 2.3. Execução não interativa (ex: boot) sem argumentos -> Gerar automático - log "Execução não interativa sem argumentos. A gerar MAC único..." + # Modo não interativo (boot/curl) sem argumentos: Gerar automático + log "Execução não interativa. A gerar MAC único..." TARGET_MAC=$(generate_unique_mac) log "MAC gerado: $TARGET_MAC" fi fi -# 3. Aplicar Configuração (Imediata e Persistente) -# Detectar interface (assumindo eth0 ou primeira USB) -IFACE="eth0" -if ! ip link show "$IFACE" &> /dev/null; then - # Tenta encontrar interface USB alternativa - IFACE=$(ip -o link show | grep -v "wlan0" | grep -v "lo" | awk '{print $2}' | sed 's/://' | head -n 1) - [ -z "$IFACE" ] && { log "Nenhuma interface Ethernet encontrada."; exit 1; } +# Validação simples do MAC +if [[ ! "$TARGET_MAC" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then + log "MAC Address inválido ou vazio: $TARGET_MAC" + exit 1 fi -log "Interface detetada: $IFACE" +# 4. Aplicar Configuração +log "A configurar sistema com MAC: $TARGET_MAC" -# Aplicar agora (para a sessão atual) e criar regra para o futuro (udev) if set_mac "$IFACE" "$TARGET_MAC"; then setup_udev_persistence "$IFACE" "$TARGET_MAC" else - log "Erro ao aplicar configuração MAC." + log "Aviso: Falha ao definir MAC em tempo real, mas a tentar criar persistência..." + setup_udev_persistence "$IFACE" "$TARGET_MAC" fi -# 4. Lançar tarefa de monitorização em Background +# 5. Lançar Monitor de Rede monitor_network_task & exit 0 \ No newline at end of file