From 322f28b39224cc3f3922e064e131aafb3c14f73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Solano=20G=C3=B3mez?= Date: Fri, 5 Apr 2013 19:13:12 -0500 Subject: [PATCH] Add DHCPv6 support via dhclient This adds DHCPv6 support to OpenRC in Linux using dhclient as outlined by Stuart Longland at . The main place where the new support is added is via a modified copy of the dhclient.sh script that: - Renames functions using a 'v6' suffix - Uses a different pid file - Uses the '-6' argument when invoking dhclient - Recognizes new DHCPv6-specific configuration variables with a fallback to the DHCP configuration variables. Additionally: 1. The iproute2 and Linux ifconfig scripts have been ammended to be able to return IPv6 addresses using new '_get_inet6_address' and '_get_inet6_addresses' functions. 2. The 'net.lo' init script now has a '_show_address6' function. 3. The documentation in the Linux net.example now contains some DHCPv6 information. Reported-by: Dustin C. Hatch x-Gentoo-Bug: 150908 x-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=150908 --- doc/net.example.Linux.in | 35 +++++++++++++++++++++ init.d/net.lo.in | 5 +++ net/Makefile | 2 +- net/dhclientv6.sh | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ net/ifconfig.sh.Linux.in | 26 +++++++++++++-- net/iproute2.sh | 19 +++++++++-- 6 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 net/dhclientv6.sh diff --git a/doc/net.example.Linux.in b/doc/net.example.Linux.in index d8fa084..540fe75 100644 --- a/doc/net.example.Linux.in +++ b/doc/net.example.Linux.in @@ -473,6 +473,41 @@ # use any of them. #----------------------------------------------------------------------------- +# DHCPv6 +# DHCPv6 can be provided by dhclient +# +# dhclient: emerge net-misc/dhcp +# +# If you have more than one DHCP client installed, you should probably +# explicitly use 'dhclient' to use dhclient for both DHCP and DHCPv6, +# otherwise the default DHCP client will be used. dhcpcd has some stateless +# IPv6 autoconfiguration support which may clash with DHCPv6. +#modules="dhclient" # to select dhclient over dhcpcd + +# Regardless of which DHCP client you prefer, you configure them the +# same way using one of following depending on which interface modules +# you're using. +#config_eth0="dhcpv6" + +# You can also use both DHCP and DHCPv6 on a dual-stack network: +#config_eth0="dhcp +#dhcpv6" + +# To pass runtime arguments to dhclient for DHCPv6, you do it similarly to +# setting runtime arguments for DHCP. Note that you can set options for +# DHCPv6 separately or in addition the dhclient arguments for DHCP. +#dhclientv6_eth0="..." # options for DHCPv6 only +#dhclient_eth0='..." # options for DHCP (also for DHCPv6 when no +# # dhclientv6_eth0 is defined) + +# GENERIC DHCPv6 OPTIONS +# Set generic DHCPv6 options just as with generic DHCP options. +#dhcpv6_eth0="release nodns nontp nonis nogateway nosendhost" + +# If no generic DHCPv6 options are set, the default is to fall back to the +# DHCP generic options. + +#----------------------------------------------------------------------------- # For APIPA support, emerge net-misc/iputils or net-analyzer/arping # APIPA is a module that tries to find a free address in the range diff --git a/init.d/net.lo.in b/init.d/net.lo.in index cc3bfd0..f6031bd 100644 --- a/init.d/net.lo.in +++ b/init.d/net.lo.in @@ -214,6 +214,11 @@ _show_address() einfo "received address $(_get_inet_address "${IFACE}")" } +_show_address6() +{ + einfo "received address $(_get_inet6_address "${IFACE}")" +} + # Basically sorts our modules into order and saves the list _gen_module_list() { diff --git a/net/Makefile b/net/Makefile index cc24a80..7bde5e1 100644 --- a/net/Makefile +++ b/net/Makefile @@ -13,7 +13,7 @@ SRCS-Linux= iwconfig.sh.in INC-Linux= adsl.sh apipa.sh arping.sh bonding.sh br2684ctl.sh bridge.sh \ ccwgroup.sh clip.sh ethtool.sh iproute2.sh ifplugd.sh ip6to4.sh \ ipppd.sh iwconfig.sh netplugd.sh pppd.sh pump.sh tuntap.sh udhcpc.sh \ - vlan.sh macvlan.sh ip6rd.sh firewalld.sh + vlan.sh macvlan.sh ip6rd.sh firewalld.sh dhclientv6.sh SRCS-NetBSD= INC-NetBSD= ifwatchd.sh diff --git a/net/dhclientv6.sh b/net/dhclientv6.sh new file mode 100644 index 0000000..f87ed4d --- /dev/null +++ b/net/dhclientv6.sh @@ -0,0 +1,82 @@ +# Copyright (c) 2007-2008 Roy Marples +# Released under the 2-clause BSD license. + +dhclientv6_depend() +{ + after interface + program start /sbin/dhclient + provide dhcpv6 +} + +_config_vars="$_config_vars dhcp dhclient dhcpv6 dhclientv6" + +dhclientv6_start() +{ + local args= opt= opts= pidfile="/var/run/dhclientv6-${IFACE}.pid" + local sendhost=true dconf= + + # Get our options + # These options only work in Gentoo, and maybe RedHat + eval args=\$dhclientv6_${IFVAR} + [ -z "${args}" ] && eval args=\$dhclient_${IFVAR} + eval opts=\$dhcpv6_${IFVAR} + [ -z "${opts}" ] && opts=${dhcpv6} + [ -z "${opts}" ] && eval opts=\$dhcp_${IFVAR} + [ -z "${opts}" ] && opts=${dhcp} + + for opt in ${opts}; do + case "${opt}" in + nodns) args="${args} -e PEER_DNS=no";; + nontp) args="${args} -e PEER_NTP=no";; + nogateway) args="${args} -e PEER_ROUTERS=no";; + nosendhost) sendhost=false;; + esac + done + + # Add our route metric + [ "${metric:-0}" != "0" ] && args="${args} -e IF_METRIC=${metric}" + + if ${sendhost}; then + local hname="$(hostname)" + if [ "${hname}" != "(none)" -a "${hname}" != "localhost" ]; then + dhconf="${dhconf} interface \"${IFACE}\" {" + dhconf="${dhconf} send fqdn.fqdn \"${hname}\";" + dhconf="${dhconf} send fqdn.encoded on;" + dhconf="${dhconf} send fqdn.server-update on;" + dhconf="${dhconf} send fqdn.no-client-update on;" + dhconf="${dhconf}}" + fi + fi + + # Bring up DHCP for this interface + ebegin "Running dhclient -6" + echo "${dhconf}" | start-stop-daemon --start --exec /sbin/dhclient \ + --pidfile "${pidfile}" \ + -- -6 ${args} -q -1 -pf "${pidfile}" "${IFACE}" + eend $? || return 1 + + _show_address6 + return 0 +} + +dhclientv6_stop() +{ + local pidfile="/var/run/dhclientv6-${IFACE}.pid" opts= + [ ! -f "${pidfile}" ] && return 0 + + # Get our options + if [ -x /sbin/dhclient ]; then + eval opts=\$dhcp_${IFVAR} + [ -z "${opts}" ] && opts=${dhcp} + fi + + ebegin "Stopping dhclient -6 on ${IFACE}" + case " ${opts} " in + *" release "*) dhclient -6 -q -r -pf "${pidfile}" "${IFACE}";; + *) + start-stop-daemon --stop --quiet \ + --exec /sbin/dhclient --pidfile "${pidfile}" + ;; + esac + eend $? +} diff --git a/net/ifconfig.sh.Linux.in b/net/ifconfig.sh.Linux.in index 2afa66c..80aeb1d 100644 --- a/net/ifconfig.sh.Linux.in +++ b/net/ifconfig.sh.Linux.in @@ -86,21 +86,41 @@ _get_inet_address() echo "/$(_netmask2cidr "$1")" } -_get_inet_addresses() +_get_inet6_address() +{ + set -- $(LC_ALL=C ifconfig "${IFACE}" | + sed -n -e 's/.*\(inet6 addr:\|inet6\) \([^ /]*\)\(\/\| *prefixlen \)\([^ ]*\).*/\2\/\4/p') + [ -z "$1" ] && return 1 + + echo -n "$1" +} + +_get_addresses_fn() { + local fn="$1" local iface=${IFACE} i=0 - local addrs="$(_get_inet_address)" + local addrs="$($fn)" while true; do local IFACE="${iface}:${i}" _exists || break - local addr="$(_get_inet_address)" + local addr="$($fn)" [ -n "${addr}" ] && addrs="${addrs}${addrs:+ }${addr}" : $(( i += 1 )) done echo "${addrs}" } +_get_inet_addresses() +{ + _get_addresses_fn _get_inet_address +} + +_get_inet6_addresses() +{ + _get_addresses_fn _get_inet6_address +} + _cidr2netmask() { local cidr="$1" netmask="" done=0 i=0 sum=0 cur=128 diff --git a/net/iproute2.sh b/net/iproute2.sh index 3bab7b7..81fefae 100644 --- a/net/iproute2.sh +++ b/net/iproute2.sh @@ -84,8 +84,16 @@ _set_mac_address() _get_inet_addresses() { - LC_ALL=C ip -family inet addr show "${IFACE}" | \ - sed -n -e 's/.*inet \([^ ]*\).*/\1/p' + local family="$1"; + if [ -z "$family" ]; then + family="inet" + fi + LC_ALL=C ip -family $family addr show "${IFACE}" | \ + sed -n -e 's/.*inet6\? \([^ ]*\).*/\1/p' +} + +_get_inet6_addresses() { + _get_inet_addresses "inet6" } _get_inet_address() @@ -95,6 +103,13 @@ _get_inet_address() echo "$1" } +_get_inet6_address() +{ + set -- $(_get_inet6_addresses) + [ $# = "0" ] && return 1 + echo "$1" +} + _add_address() { if [ "$1" = "127.0.0.1/8" -a "${IFACE}" = "lo" ]; then -- 1.8.3.2