summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouke Witteveen <j.witteveen@gmail.com>2012-05-17 11:01:10 +0200
committerJouke Witteveen <j.witteveen@gmail.com>2012-05-17 11:01:10 +0200
commit0d3e56bf3809b03e1c60a5dce0d7bb8510720369 (patch)
tree78473972a45d9bc675d3c543009c873637024d90
parent91ff1c8c4ee490d113ac25fbca0f4596ca069a7d (diff)
downloadnetctl-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.txt7
-rwxr-xr-xscripts/wifi-menu2
-rw-r--r--src/connections/ethernet58
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:
-