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 +
`**<address range>** via **<gateway>**'.
-'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 <connection_type>_up and <connection_type>_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 <client_name>_start and <client_name>_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/<profile>
+
+Here, <profile> 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
--
1.9.0