Por que o atraso após o ifconfig down é necessário antes de se alterar o endereço MAC?

3

Oi eu fiz script bash para colocar minha interface, alterar o endereço MAC e buscá-lo novamente.

#!/bin/bash

INTERFACE_STATUS=$( cat /sys/class/net/eth0/operstate )

echo "$INTERFACE_STATUS"

if [ "$INTERFACE_STATUS" == "up" ]
then
    echo  "Putting down eth0"
    sudo ifconfig eth0 down
    # putting down eth0 works only when I sleep 10 seconds after using command
    #sleep 10
    echo "$( cat /sys/class/net/eth0/operstate )"
#     TRIES=0
#     while [ "$( cat /sys/class/net/eth0/operstate )" == "up" ]
#     do
#         sleep 1
#         TRIES=$(($TRIES + 1))
#         if [ "$TRIES" == "7" ]
#         then
#             echo Could not put down eth0
#             exit 1
#         fi
#     done
fi

sudo ifconfig eth0 hw ether "91:91:91:91:91:91"

sudo ifconfig eth0 up

O problema é que não funciona. Imediatamente depois de colocar eth0 /sys/class/net/eth0/operstate muda para down , mas parece que ainda não está baixo. Eu levo 10 segundos para colocar a interface eth0, então a única maneira de fazer isso funcionar é adicionar sleep 10 depois de colocar eth0.

Então, minha pergunta é como verificar se o eht0 está realmente errado?

// EDITAR

É como o comando ifconfig eth0 up é usado antecipadamente porque nunca se levanta com o novo endereço MAC. Eu preciso colocá-lo para baixo, espere 10 s, mude o MAC e coloque-o de volta. Eu suspeito que colocar eth0 leva alguns segundos e colocá-lo novamente muito cedo não funciona.

// EDIT 2

Eu verifiquei o endereço MAC novamente e parece que ele mudou, então agora eu acho que poderia ser algo com DNS, porque quando eu estou usando o ping no google recebo um host desconhecido. Mas o mesmo método com sleep 10 funciona.

// EDIT 3

Depois de usar o script sem sleep 10 , tentei usar o ping:

piotrek@piotrek-Vostro-2520:~$ ping 212.77.100.101
connect: Network is unreachable
piotrek@piotrek-Vostro-2520:~$ ping -n 212.77.100.101
connect: Network is unreachable
piotrek@piotrek-Vostro-2520:~$ ifconfig 
eth0      Link encap:Ethernet  HWaddr 08:3e:8e:2d:36:55  
        inet addr:10.36.253.122  Bcast:10.36.253.255  Mask:255.255.255.0
        inet6 addr: fe80::a3e:8eff:fe2d:3655/64 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:74297 errors:0 dropped:0 overruns:0 frame:0
        TX packets:38597 errors:0 dropped:0 overruns:0 carrier:0                                                                                           
        collisions:0 txqueuelen:1000                                                                                                                       
        RX bytes:32417366 (32.4 MB)  TX bytes:5201537 (5.2 MB)0                                                                                           
      collisions:0 txqueuelen:1000                                                                                                                       
      RX bytes:32417366 (32.4 MB)  TX bytes:5201537 (5.2 MB)

// EDIT 4 SUM UP

piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down; sudo ifconfig eth0 hw ether 08:3e:8e:2d:36:55 ; sudo ifconfig eth0 up
piotrek@piotrek-Vostro-2520:~$ ping -n 212.77.100.101
connect: Network is unreachable
piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down; sleep 10; sudo ifconfig eth0 hw ether 08:3e:8e:2d:36:55 ; sudo ifconfig eth0 up
piotrek@piotrek-Vostro-2520:~$ ping -n 212.77.100.101
PING 212.77.100.101 (212.77.100.101) 56(84) bytes of data.
64 bytes from 212.77.100.101: icmp_req=1 ttl=246 time=8.91 ms
64 bytes from 212.77.100.101: icmp_req=2 ttl=246 time=8.76 ms
64 bytes from 212.77.100.101: icmp_req=3 ttl=246 time=8.52 ms
^C
--- 212.77.100.101 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 8.523/8.734/8.917/0.194 ms

Por que sleep 10 é importante?

// EDIT 5

Está ficando muito estranho. Quando eu uso sleep funciona bem. Quando tento sem sleep , parece que o IP está ok, a interface está ativa, mas a rede não funciona. Quando eu tento colocar eth0 com sudo ifconfig eth0 down depois de alguns segundos, meu sistema operacional (Ubuntu 12.10) me reconecta automaticamente com meu endereço MAC antigo e recebo um novo IP. Com o segundo uso de sudo ifconfig eth0 down , posso colocar completamente eth0 .

piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down; sleep 10; sudo ifconfig eth0 hw ether 08:3e:8e:2d:36:55 ; sudo ifconfig eth0 up
piotrek@piotrek-Vostro-2520:~$ sudo ifconfig
eth0      Link encap:Ethernet  HWaddr 08:3e:8e:2d:36:55  
        inet addr:10.36.253.241  Bcast:10.36.253.255  Mask:255.255.255.0
        inet6 addr: fe80::a3e:8eff:fe2d:3655/64 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:439341 errors:0 dropped:0 overruns:0 frame:0
        TX packets:224187 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000 
        RX bytes:400718780 (400.7 MB)  TX bytes:26246307 (26.2 MB)

piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down; sudo ifconfig eth0 hw ether 08:3e:8e:2d:36:55 ; sudo ifconfig eth0 up
piotrek@piotrek-Vostro-2520:~$ ping -n 212.77.100.101
connect: Network is unreachable
piotrek@piotrek-Vostro-2520:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr 08:3e:8e:2d:36:55  
        inet addr:10.36.253.241  Bcast:10.36.253.255  Mask:255.255.255.0
        inet6 addr: fe80::a3e:8eff:fe2d:3655/64 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:439656 errors:0 dropped:0 overruns:0 frame:0
        TX packets:224321 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000 
        RX bytes:400827185 (400.8 MB)  TX bytes:26267012 (26.2 MB)

piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down
piotrek@piotrek-Vostro-2520:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr e0:db:55:97:de:cc  
        inet addr:10.36.253.122  Bcast:10.36.253.255  Mask:255.255.255.0
        inet6 addr: fe80::e2db:55ff:fe97:decc/64 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:440302 errors:0 dropped:0 overruns:0 frame:0
        TX packets:224862 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000 
        RX bytes:401129508 (401.1 MB)  TX bytes:26323176 (26.3 MB)

piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down
piotrek@piotrek-Vostro-2520:~$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr e0:db:55:97:de:cc  
        BROADCAST MULTICAST  MTU:1500  Metric:1
        RX packets:440437 errors:0 dropped:0 overruns:0 frame:0
        TX packets:224881 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000 
        RX bytes:401147424 (401.1 MB)  TX bytes:26326068 (26.3 MB)

// EDIT 6

Eu tentei a solução sugerida por @Moreaki, mas a mesma coisa acontece. O script é executado em torno de um segundo, mas minha rede está inacessível depois de usá-lo. Este é o código de @Moreaki:

#!/usr/bin/env bash

INTF=eth0
INTERFACE_STATUS=$(cat /sys/class/net/${INTF}/operstate)
echo "$INTERFACE_STATUS"

if [ "$INTERFACE_STATUS" == "up" ]; then
    echo "Putting down ${INTF}"
    # if you need to remove all IP addresses associated with ${INTF}
    sudo ip addr flush dev ${INTF}
    # set the interface status down
    sudo ip link set dev ${INTF} down
    # flush neighbour cache
    sudo ip neigh flush dev ${INTF}
    # flush routing cache entries pertaining to ${INTF}
    sudo ip route flush table cache dev ${INTF}
    echo "New state: $(cat /sys/class/net/${INTF}/operstate)"
fi

sudo ip link set dev ${INTF} address "08:3e:8e:2d:36:55"
sudo ip link set dev ${INTF} up

Depois de usá-lo, recebo:

piotrek@piotrek-Vostro-2520:~$ ./mac_test.sh 
up
Putting down eth0
New state: down

E depois de tentar o ping:

piotrek@piotrek-Vostro-2520:~$ ping google.com
ping: unknown host google.com
piotrek@piotrek-Vostro-2520:~$ ping 8.8.8.8
connect: Network is unreachable

// EDIT 7

Usando script de roteamento de @Moreaki meu roteamento antes de alterar o endereço MAC se parece com isso:

piotrek@piotrek-Vostro-2520:~$ ./routing.sh 
Destination        Gateway         Source             Iface    R_Type RT_table  
default            10.36.253.1     10.36.253.122      eth0            main      
10.36.253.0/24     0.0.0.0         10.36.253.122      eth0            main      
169.254.0.0/16     0.0.0.0         10.36.253.122      eth0            main

E depois de alterar o endereço MAC usando meu script com atraso de 10s :

piotrek@piotrek-Vostro-2520:~$ ./routing.sh 
Destination        Gateway         Source             Iface    R_Type RT_table  
default            10.36.253.1     10.36.253.241      eth0            main      
10.36.253.0/24     0.0.0.0         10.36.253.241      eth0            main      
169.254.0.0/16     0.0.0.0         10.36.253.241      eth0            main

Roteamento após o uso do script @Moreaki:

piotrek@piotrek-Vostro-2520:~$ ./routing.sh
Destination        Gateway         Source             Iface    R_Type RT_table

@Moreaki também sugeriu comentar a linha sudo ip addr flush dev ${INTF} , mas ainda recebo connect: Network is unreachable . Meu roteamento depois de usar o script com a linha comentada é assim:

piotrek@piotrek-Vostro-2520:~$ ./routing.sh
Destination        Gateway         Source             Iface    R_Type RT_table  
10.36.253.0/24     0.0.0.0         10.36.253.122      eth0
    
por piotrekkr 19.08.2013 / 10:39

3 respostas

1

O atraso em derrubar a interface provavelmente está relacionado ao driver e / ou hardware da interface. Se isso estiver correto, não há uma maneira padrão de saber quando o driver ou o hardware realmente desativou a interface.

Ao ler mais o restante da solução de problemas, parece que pode haver um processo concorrente em andamento - especialmente a parte sobre a interface voltando "por conta própria". Talvez haja uma ferramenta que executa e coloca a interface de volta após a tentativa de derrubá-la?

Isso seria um pouco difícil de detectar, mas não impossível. Não consigo pensar em nenhuma maneira rápida e fácil de sugerir que você possa detectá-lo.

    
por 07.01.2014 / 03:58
1

Eu não acho que um atraso seja necessário. Antes de colocar a interface para baixo, você deve poder se desconectar fisicamente do endereço MAC antigo. Estou sem fio no momento, então não posso testar isso agora, mas olhe para o ifconfig --help. Algo parecido com isto?:

ifconfig <interface> del <address>

Em sem fio, quando eu me desconecto, eu corro um pequeno script que limpa tudo, incluindo o endereço MAC do AP:

sudo dhcpcd --release "$INTERFACE"
sudo iwconfig "$INTERFACE" essid off
sudo iwconfig "$INTERFACE" ap off
sudo ifconfig "$INTERFACE" down
    
por 06.02.2014 / 23:16
-1

Ainda não posso comentar, por isso espero que a minha opinião lance alguma luz sobre o seu comportamento observado. Em geral, eu não recomendaria usar ifconfig para mexer com suas configurações de interface no Linux. De fato, foi "depreciado" há dez anos. Dito isto, obviamente, ainda deve funcionar, pois as distros continuam a enviar ifconfig e route.

Você pode verificar se essa abordagem muda o comportamento que você está vendo:

#!/usr/bin/env bash

INTF=eth0
INTERFACE_STATUS=$(cat /sys/class/net/${INTF}/operstate)
echo "$INTERFACE_STATUS"

if [ "$INTERFACE_STATUS" == "up" ]; then
    echo "Putting down ${INTF}"
    # if you need to remove all IP addresses associated with ${INTF}
    sudo ip addr flush dev ${INTF}
    # set the interface status down
    sudo ip link set dev ${INTF} down
    # flush neighbour cache
    sudo ip neigh flush dev ${INTF}
    # flush routing cache entries pertaining to ${INTF}
    sudo ip route flush table cache dev ${INTF}
    echo "New state: $(cat /sys/class/net/${INTF}/operstate)"
fi

sudo ip link set dev ${INTF} address "91:91:91:91:91:91"
sudo ip link set dev ${INTF} up

ADENDO 1: lendo seu feedback, você pode querer oferecer mais informações sobre sua configuração de roteamento. Eu desenterrei alguns scripts antigos que escrevi há mais de uma década. Este deve mostrar a saída da tabela de roteamento semelhante a netstat (a raiz é necessária para executar isso):

#!/usr/bin/env bash

# 08/2000: Initial code to beautify iproute2 routing table output
# 08/2013: Updated it for the new decade and removed swearing.

: ${IPTOOL:=/sbin/ip}
: ${DEBUG:=0}

print_format="%-18s %-15s %-18s %-8s %-6s %-10s\n"

if [ "x$1" == "x-v" -o "x$1" == "x--verbose" ]; then
    DEBUG=1
fi

dbg_log(){
    if [ $DEBUG -eq 1 ]; then
        echo "$*"
    fi
}

printme(){
    if [ "x$via" == "x" -a $src_route -eq 0 ]; then
        via="0.0.0.0"
    fi
    if [ "x$src" == "x" ]; then
        src=$(${IPTOOL} addr show dev $dev label $dev | awk '/inet/ {print $2}')
        src=${src%%/*}
    fi
    printf "$print_format" "$net" "$via" "$src" "$dev" "$type" "$table_id"
}

eval_route(){
    not_parsed=0

    while read net rest; do
        if [ $src_route -eq 0 ]; then
            src=
            type=
        fi
        table_id="${TABLE_ID}"
        dev=
        via=
        set -- $rest
        while [ $# -ne 0 ]; do
            case $1 in
                proto)  shift 1;;
                scope)  shift 1;;
                metric) shift 1;;
                dev)    shift 1; dev=$1;;
                via)    shift 1; via=$1;;
                src)    shift 1; src=$1
                   # As soon as I've figured out, how to get back the
                   # interface/label definition from a given src IP
                   # I will adjust this ugly hack. --rn, 08/2000
                   if [ "x${src%.*}" != "x${net%.*}" ]; then
                       dev=$(${IPTOOL} addr show dev $dev to $src | \
                           awk -v check_ip=${temp_ip%%/*} 'BEGIN {/$check_ip/} END {print $7}')
                   fi
                   ;;
                *) dbg_log "option $1 not parsed"; not_parsed=1;;
            esac
            shift 1
        done
        # Check for 'throw, blackhole, unreachable, prohibit'
        # Since we only check for non-numeric strings, we have
        # to exclude the default target too.
        if [ "x${net//[0-9.]/}" == "x$net" -a "x$net" != "xdefault" ]; then
            type=${net:0:2}
            type=${type~~}
            net=$rest
            dev="all"
            src="0.0.0.0/0"
            not_parsed=0
        fi
        [ $not_parsed -eq 0 ] && printme
        not_parsed=0
    done < <(${IPTOOL} route show table $TABLE_ID)
}

src_route=0
printf "$print_format" "Destination" "Gateway" "Source" "Iface" "R_Type" "RT_table"
while read RULE_ID rest; do
    RULE_ID=${RULE_ID//:/}
    fromIP=
    toIP=
    TABLE_ID=
    set -- ${rest}
    while [ $# -ne 0 ]; do
        case $1 in
            from)   fromIP=$2  ; shift 2;;
            to)     toIP=$2    ; shift 2;;
            lookup) TABLE_ID=$2; shift 2;;
            *)                   shift 1;;
        esac
    done
    if [ $RULE_ID -ne 0 ]; then
        dbg_log "+------------------[RULE: $RULE_ID]------------------+"
        if [ "x$fromIP" != "xall" ]; then
            src_route=1
            src="$IP"
            type=SR
        fi
        eval_route
        src_route=0
    fi
done < <(${IPTOOL} rule show)
    
por 24.08.2013 / 22:34