diff options
author | Jouke Witteveen <j.witteveen@gmail.com> | 2012-05-17 11:01:10 +0200 |
---|---|---|
committer | Jouke Witteveen <j.witteveen@gmail.com> | 2012-05-17 11:01:10 +0200 |
commit | 0d3e56bf3809b03e1c60a5dce0d7bb8510720369 (patch) | |
tree | 78473972a45d9bc675d3c543009c873637024d90 | |
parent | 91ff1c8c4ee490d113ac25fbca0f4596ca069a7d (diff) | |
download | netctl-0d3e56bf3809b03e1c60a5dce0d7bb8510720369.tar.gz netctl-0d3e56bf3809b03e1c60a5dce0d7bb8510720369.tar.xz |
Wait for DAD when using IPv6 (FS#28887)
In IPv6 you cannot bind to an address as long as it is not determined to be unique through Duplicate Address Detection. This can cause problems when routes in ROUTES6 reference a tentative source address or when something that starts after netcfg tries to.
This patch does a few things:
- Improve ROUTES(6) logic so that non-static connections can make use of them as intended according to the commit message of c8be1.
- Make additional arguments possible for ADDR6 addresses and ROUTES6 routes, such as ADDR6=('1234:5678:9abc:def::1/64 nodad').
- Introduce a DAD_TIMEOUT variable that governs how long to wait for DAD to finish.
- Move IPCFG processing to after IPv6 address set-up (it already was after IPv4 address set-up), so that custom commands can be sure to have working addresses.
WARNING: This changes make it impossible to use ROUTES6 and set the address through IPCFG instead of ADDR6. This was bad, unsupported practice, but sometimes needed as ADDR6 did not allow config flags to be used. Resolving this issue should be no problem: you should be able to properly use ADDR6 now. If not, then be a real hacker and set the routes through IPCFG too.
Many thanks to Steve Caligo for reporting this bug and helping out in finding a solution.
-rw-r--r-- | docs/netcfg-profiles.5.txt | 7 | ||||
-rwxr-xr-x | scripts/wifi-menu | 2 | ||||
-rw-r--r-- | src/connections/ethernet | 58 |
3 files changed, 41 insertions, 26 deletions
diff --git a/docs/netcfg-profiles.5.txt b/docs/netcfg-profiles.5.txt index c9a3380..daf2eb8 100644 --- a/docs/netcfg-profiles.5.txt +++ b/docs/netcfg-profiles.5.txt @@ -78,11 +78,11 @@ gain an IP address. IPv4 options ~~~~~~~~~~~~ +ADDR+ (requires +IP+ of `static'):: - A single IP address to configure a static IP. For example: + A single IP address to configure a static IP. +GATEWAY+ (requires +IP+ of `static'):: Set specified gateway +NETMASK+ (requires +IP+ of `static'):: - Set specified netmask. Defaults to 24 + Set specified netmask. Defaults to 24. +ROUTES+:: An array of custom routes (of the form _address range_ via _gateway_) @@ -98,6 +98,9 @@ IPv6 options The gateway address for IPv6 routing. +ROUTES6+:: An array of custom routes (of the form _address range_ via _gateway_) ++DAD_TIMEOUT+:: + Time to wait for Duplicate Address Detection to succeed. Defaults to + 3 seconds. DNS configuration ^^^^^^^^^^^^^^^^^ diff --git a/scripts/wifi-menu b/scripts/wifi-menu index 75bfede..96f6de1 100755 --- a/scripts/wifi-menu +++ b/scripts/wifi-menu @@ -203,7 +203,7 @@ fi cd / # We do not want to spawn anything that can block unmounting is_interface "$INTERFACE" || exit_fail "No such interface: $INTERFACE" -if [[ -z "$(ip link show up dev "$INTERFACE" 2> /dev/null)" ]]; then +if [[ -z "$(ip link show dev "$INTERFACE" up 2> /dev/null)" ]]; then [[ -f "$IFACE_DIR/$INTERFACE" ]] && . "$IFACE_DIR/$INTERFACE" bring_interface up "$INTERFACE" || exit_fail "Interface unavailable" SPAWNED_INTERFACE=1 diff --git a/src/connections/ethernet b/src/connections/ethernet index 41d0274..97875f8 100644 --- a/src/connections/ethernet +++ b/src/connections/ethernet @@ -14,6 +14,8 @@ report_iproute() } ethernet_up() { + local dad_timeout="${DAD_TIMEOUT:-3}" + load_profile "$1" SYSCTL_INTERFACE="${INTERFACE/.//}" @@ -23,7 +25,7 @@ ethernet_up() { fi fi - # Disable IPv6 before the interface to prevent SLAAC + # Disable IPv6 before bringing the interface up to prevent SLAAC if [[ "$IP6" == "no" ]]; then sysctl -q -w "net.ipv6.conf.$SYSCTL_INTERFACE.disable_ipv6=1" fi @@ -101,14 +103,6 @@ ethernet_up() { report_iproute "Could not configure interface" fi fi - if [[ -n "$ROUTES" ]]; then - for route in "${ROUTES[@]}"; do - report_debug ethernet_up ip route add $route dev "$INTERFACE" - if ! ip route add $route dev "$INTERFACE" ; then - report_iproute "Adding route '$route' failed" - fi - done - fi if [[ -n "$GATEWAY" ]]; then report_debug ethernet_up ip route add default via "$GATEWAY" dev "$INTERFACE" if ! ip route add default via "$GATEWAY" dev "$INTERFACE"; then @@ -123,12 +117,11 @@ ethernet_up() { ;; esac - if [[ -n "$IPCFG" ]]; then - for line in "${IPCFG[@]}"; do - - report_debug ethernet_up ip "$line" - if ! ip $line; then - report_iproute "Could not configure interface ($line)." + if [[ -n "$IP" && -n "$ROUTES" ]]; then + for route in "${ROUTES[@]}"; do + report_debug ethernet_up ip route add $route dev "$INTERFACE" + if ! ip route add $route dev "$INTERFACE"; then + report_iproute "Adding route '$route' failed" fi done fi @@ -175,9 +168,9 @@ ethernet_up() { sysctl -q -w "net.ipv6.conf.$SYSCTL_INTERFACE.accept_ra=0" if [[ -n "$ADDR6" ]]; then for addr in "${ADDR6[@]}"; do - report_debug ethernet_up ip -6 addr add "$addr" dev "$INTERFACE" - if ! ip -6 addr add "$addr" dev "$INTERFACE"; then - report_iproute "Could not add address $addr to interface" + report_debug ethernet_up ip -6 addr add $addr dev "$INTERFACE" + if ! ip -6 addr add $addr dev "$INTERFACE"; then + report_iproute "Could not add address '$addr' to interface" fi done fi @@ -187,18 +180,38 @@ ethernet_up() { report_iproute "Adding gateway $GATEWAY6 failed" fi fi + ;; + esac + + if [[ -n "$IP6" ]]; then + # Wait for DAD to finish (FS#28887) + report_debug ethernet_up ip -6 addr show dev "$INTERFACE" tentative + while [[ -n "$(ip -6 addr show dev "$INTERFACE" tentative)" ]]; do + if (( dad_timeout-- <= 0 )); then + report_iproute "Duplicate Address Detection is taking too long" + fi + sleep 1 + done # Add static IPv6 routes if [[ -n "$ROUTES6" ]]; then for route in "${ROUTES6[@]}"; do - report_debug ethernet_up ip -6 route add "$route" dev "$INTERFACE" - if ! ip -6 route add "$route" dev "$INTERFACE"; then + report_debug ethernet_up ip -6 route add $route dev "$INTERFACE" + if ! ip -6 route add $route dev "$INTERFACE"; then report_iproute "Adding route '$route' failed" fi done fi - ;; - esac + fi + + if [[ -n "$IPCFG" ]]; then + for line in "${IPCFG[@]}"; do + report_debug ethernet_up ip "$line" + if ! ip $line; then + report_iproute "Could not configure interface ($line)." + fi + done + fi # Set hostname if [[ -n "$HOSTNAME" ]]; then @@ -277,4 +290,3 @@ stop_80211x() { ethernet_$1 "$2" exit $? # vim: set ts=4 et sw=4: - |