From 7f497011aee03f141a5bd055222ca337383f43a3 Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Tue, 25 Feb 2014 14:22:22 +0100 Subject: Factor out DHCP client support Support for additional DHCP clients is now easy to add. --- Makefile | 3 +- docs/netctl.profile.5.txt | 16 +++++---- src/lib/connections/README | 2 +- src/lib/dhcp/README | 34 +++++++++++++++++++ src/lib/dhcp/dhclient | 27 +++++++++++++++ src/lib/dhcp/dhcpcd | 28 ++++++++++++++++ src/lib/ip | 83 ++++++++++++++-------------------------------- 7 files changed, 126 insertions(+), 67 deletions(-) create mode 100644 src/lib/dhcp/README create mode 100644 src/lib/dhcp/dhclient create mode 100644 src/lib/dhcp/dhcpcd diff --git a/Makefile b/Makefile index b22fbe0..08ad462 100644 --- a/Makefile +++ b/Makefile @@ -15,9 +15,10 @@ install: install -d $(DESTDIR)/etc/netctl/{examples,hooks,interfaces} install -m644 docs/examples/* $(DESTDIR)/etc/netctl/examples/ # Libs - install -d $(DESTDIR)/usr/lib/network/connections + install -d $(DESTDIR)/usr/lib/network/{connections,dhcp} install -m644 src/lib/{globals,ip,rfkill,wpa} $(DESTDIR)/usr/lib/network/ install -m644 src/lib/connections/* $(DESTDIR)/usr/lib/network/connections/ + install -m644 src/lib/dhcp/* $(DESTDIR)/usr/lib/network/dhcp/ install -m755 src/lib/{auto.action,network} $(DESTDIR)/usr/lib/network/ # Scripts install -d $(DESTDIR)/usr/bin diff --git a/docs/netctl.profile.5.txt b/docs/netctl.profile.5.txt index dfc13bb..2cf0285 100644 --- a/docs/netctl.profile.5.txt +++ b/docs/netctl.profile.5.txt @@ -137,18 +137,20 @@ network. In particular, these connection types are +ethernet+, An array of custom routes of the form + `**
** via ****'. -'DHCPClient=' [requires a DHCP setting]:: - The name of the preferred DHCP client. Supported options are - `dhcpcd' and `dhclient'. Defaults to `dhcpcd'. +'DHCPClient=' [requires 'IP=dhcp']:: + The name of the DHCP client to use. Clients may accept additional + options through client-specific variables. By default, *netctl* + comes with support for `dhcpcd' and `dhclient'. Defaults to + `++dhcpcd++'. + +'DHCP6Client=' [requires 'IP6=dhcp' or 'IP6=dhcp-noaddr']:: + The name of the DHCPv6 client to use. By default, only `dhclient' + is supported. Defaults to `++dhclient++'. 'DHCPReleaseOnStop=':: Set to `++yes++' to release the DHCP lease when the profile is stopped. -'DhcpcdOptions=', 'DhclientOptions=', 'DhclientOptions6=':: - Additional options to be passed to the DHCP client. Do not use this - unless you know what you are doing. - 'IPCustom=()':: An array of argument lines to pass to `ip`. This can be used to achieve complicated configurations within the framework of *netctl*. diff --git a/src/lib/connections/README b/src/lib/connections/README index 6d8db9b..2dd4b7b 100644 --- a/src/lib/connections/README +++ b/src/lib/connections/README @@ -10,7 +10,7 @@ for the aviancarrier connection type will be provided by the file: Files that implement support for a connection type should NOT be executable. Such files should contain valid Bash code, among which two functions, namely _up and _down. For -the aviancarrier file this would be: +the aviancarrier file these would be: aviancarrier_up aviancarrier_down diff --git a/src/lib/dhcp/README b/src/lib/dhcp/README new file mode 100644 index 0000000..f55a06e --- /dev/null +++ b/src/lib/dhcp/README @@ -0,0 +1,34 @@ +Support for dhcp clients is implemented by files in + + /usr/lib/network/dhcp/ + +The file name determines the name of the client for the profile, so +support for a client named dhcpcd is provided by the file: + + /usr/lib/network/connections/dhcpcd + +Files that implement support for a connection type should NOT be +executable. Such files should contain valid Bash code, among which two +functions, namely _start and _stop. For +the client named dhcpcd these would be: + + dhcpcd_start + dhcpcd_stop + +These functions are responsible for starting and stopping the dhcp +client. When the functions are called, three bash files are already +sourced, so all functions and variables in those files are available. +The readily sourced files are: + + /usr/lib/network/network + /usr/lib/network/globals + /etc/netctl/ + +Here, is the profile file specifying the desired network +configuration. + +When called, the start and stop functions get as their first argument +the version of the IP protocol that the dhcp client is expected to use. +In the case of starting the client for IPv6, an additional second +argument 'noaddr' may be supplied, which indicates that the dhcp client +should configure everything but an IP address. diff --git a/src/lib/dhcp/dhclient b/src/lib/dhcp/dhclient new file mode 100644 index 0000000..42b5f14 --- /dev/null +++ b/src/lib/dhcp/dhclient @@ -0,0 +1,27 @@ +type dhclient &> /dev/null || return + +dhclient_start() { + local options pidfile="/run/dhclient$1-$Interface.pid" + case $1 in + 4) options=$DhclientOptions;; + 6) options=$DhclientOptions6;; + *) return 1;; + esac + [[ $2 == "noaddr" ]] && options+=" -S" + rm -f "$pidfile" + if ! do_debug dhclient -$1 -q -e "TIMEOUT=${TimeoutDHCP:-30}" -pf "$pidfile" $options "$Interface"; then + report_error "DHCP IPv$1 lease attempt failed on interface '$Interface'" + return 1 + fi +} + +dhclient_stop() { + local stop="-x" pidfile="/run/dhclient$1-$Interface.pid" + if [[ -f $pidfile ]]; then + is_yes "${DHCPReleaseOnStop:-no}" && stop="-r" + do_debug dhclient -$1 -q $stop "$Interface" -pf "$pidfile" > /dev/null + fi +} + + +# vim: ft=sh ts=4 et sw=4: diff --git a/src/lib/dhcp/dhcpcd b/src/lib/dhcp/dhcpcd new file mode 100644 index 0000000..42f33ef --- /dev/null +++ b/src/lib/dhcp/dhcpcd @@ -0,0 +1,28 @@ +type dhcpcd &> /dev/null || return + +dhcpcd_start() { + if [[ $1 != "4" ]]; then + report_error "Using 'dhcpcd' for IPv6 is currently not possible in netctl" + return 1 + fi + rm -f "/run/dhcpcd-$Interface".{pid,cache} + # If using own dns, tell dhcpcd to NOT replace resolv.conf + [[ $DNS ]] && DhcpcdOptions+=" -C resolv.conf" + do_debug dhcpcd -4qL -t "${TimeoutDHCP:-30}" $DhcpcdOptions "$Interface" |& report_debug "$(cat)" + # The first array value of PIPESTATUS is the exit status of dhcpcd + if (( PIPESTATUS != 0 )); then + report_error "DHCP IP lease attempt failed on interface '$Interface'" + return 1 + fi +} + +dhcpcd_stop() { + local stop="-x" + if [[ -f "/run/dhcpcd-$Interface.pid" ]]; then + is_yes "${DHCPReleaseOnStop:-no}" && stop="-k" + do_debug dhcpcd -q $stop "$Interface" > /dev/null + fi +} + + +# vim: ft=sh ts=4 et sw=4: diff --git a/src/lib/ip b/src/lib/ip index 4698595..e737fc5 100644 --- a/src/lib/ip +++ b/src/lib/ip @@ -1,6 +1,26 @@ ## /usr/lib/network/globals needs to be sourced before this file +## Interface a DHCP client +# $1: DHCP client +# $2: command +# $3...: additional arguments +dhcp_call() { + local client="$1" command="$2" + shift 2 + + if [[ ! -r "$SUBR_DIR/dhcp/$client" ]]; then + report_error "DHCP client '$client' is unsupported" + return 127 + fi + if ! source "$SUBR_DIR/dhcp/$client"; then + report_error "DHCP client '$client' is not installed or not ready" + return 127 + fi + "${client}_$command" "$@" +} + + ## Add resolv.conf entries for an interface # $1: interface name # $2...: entries, one line per variable @@ -43,30 +63,7 @@ ip_set() { case $IP in dhcp) - case ${DHCPClient:-dhcpcd} in - dhcpcd) - rm -f "/run/dhcpcd-$Interface".{pid,cache} - # If using own dns, tell dhcpcd to NOT replace resolv.conf - [[ $DNS ]] && DhcpcdOptions+=" -C resolv.conf" - do_debug dhcpcd -4qL -t "${TimeoutDHCP:-30}" $DhcpcdOptions "$Interface" |& report_debug "$(cat)" - # The first array value of PIPESTATUS is the exit status of dhcpcd - if (( PIPESTATUS != 0 )); then - report_error "DHCP IP lease attempt failed on interface '$Interface'" - return 1 - fi - ;; - dhclient) - rm -f "/run/dhclient-${Interface}.pid" - if ! do_debug dhclient -4 -q -e "TIMEOUT=${TimeoutDHCP:-30}" -pf "/run/dhclient-$Interface.pid" $DhclientOptions "$Interface"; then - report_error "DHCP IP lease attempt failed on interface '$Interface'" - return 1 - fi - ;; - *) - report_error "Unsupported DHCP client: '$DHCPClient'" - return 1 - ;; - esac + dhcp_call "${DHCPClient:-dhcpcd}" start 4 || return ;; static) for addr in "${Address[@]}"; do @@ -103,17 +100,8 @@ ip_set() { fi case "$IP6" in - dhcp*) - if ! type dhclient &>/dev/null; then - report_error "You need to install dhclient to use DHCPv6" - return 1 - fi - [[ $IP6 == "dhcp-noaddr" ]] && DhclientOptions6+=" -S" - rm -f "/run/dhclient6-${Interface}.pid" - if ! do_debug dhclient -6 -q -e "TIMEOUT=${TimeoutDHCP:-30}" -pf "/run/dhclient6-${Interface}.pid" $DhclientOptions6 "$Interface"; then - report_error "DHCPv6 IP lease attempt failed on interface '$Interface'" - return 1 - fi + dhcp|dhcp-noaddr) + dhcp_call "${DHCP6Client:-dhclient}" start 6 ${IP6:5} || return ;; stateless|static) for addr in "${Address6[@]}"; do @@ -179,29 +167,8 @@ ip_set() { # $IP: type of IPv4 configuration # $IP6: type of IPv6 configuration ip_unset() { - local stop="-x" - if [[ $IP == "dhcp" ]]; then - case ${DHCPClient:-dhcpcd} in - dhcpcd) - if [[ -f "/run/dhcpcd-$Interface.pid" ]]; then - is_yes "${DHCPReleaseOnStop:-no}" && stop="-k" - do_debug dhcpcd -q $stop "$Interface" >/dev/null - fi - ;; - dhclient) - if [[ -f "/run/dhclient-$Interface.pid" ]]; then - is_yes "${DHCPReleaseOnStop:-no}" && stop="-r" - do_debug dhclient -q $stop "$Interface" -pf "/run/dhclient-$Interface.pid" >/dev/null - fi - ;; - esac - fi - if [[ $IP6 == dhcp* ]]; then - if [[ -f "/run/dhclient6-$Interface.pid" ]]; then - do_debug dhclient -6 -q -x "$Interface" -pf "/run/dhclient6-$Interface.pid" >/dev/null - fi - fi - + [[ $IP == "dhcp" ]] && dhcp_call "${DHCPClient:-dhcpcd}" stop 4 + [[ $IP6 == dhcp* ]] && dhcp_call "${DHCP6Client:-dhclient}" stop 6 [[ $DNS ]] && resolvconf -d "$Interface" ip route flush dev "$Interface" &>/dev/null ip -6 route flush dev "$Interface" &>/dev/null -- cgit v1.2.3-24-g4f1b