diff options
author | tcely <tcely@users.noreply.github.com> | 2018-08-04 00:40:59 -0400 |
---|---|---|
committer | Leonardo Arena <rnalrd@alpinelinux.org> | 2019-02-08 09:46:19 +0000 |
commit | 04450f0183af6747be90e73ffb5a909f0fd3e566 (patch) | |
tree | bde2ff1d2afbd78aaecc52d374fcfd4e45c0d841 /main | |
parent | 23fac33a7652137d3ae308436229dd6edb9940f6 (diff) | |
download | aports-04450f0183af6747be90e73ffb5a909f0fd3e566.tar.bz2 aports-04450f0183af6747be90e73ffb5a909f0fd3e566.tar.xz |
main/dhcp: use alpine specific dhclient-script
This was checked with:
- checkbashisms
- shellcheck
Diffstat (limited to 'main')
-rw-r--r-- | main/dhcp/APKBUILD | 5 | ||||
-rw-r--r-- | main/dhcp/dhclient-script-alpine | 682 |
2 files changed, 686 insertions, 1 deletions
diff --git a/main/dhcp/APKBUILD b/main/dhcp/APKBUILD index a8fb8458b8..96af68a6b8 100644 --- a/main/dhcp/APKBUILD +++ b/main/dhcp/APKBUILD @@ -17,6 +17,7 @@ source="http://ftp.isc.org/isc/$pkgname/${_realver}/$pkgname-$_realver.tar.gz 01-dhclient-script-fix-bare-ip.patch 02-dhclient-script-remove-bashisms.patch dhcp-3.0-fix-perms.patch + dhclient-script-alpine dhcrelay.initd dhcrelay.confd dhcpd.confd @@ -58,7 +59,8 @@ package() { install -m755 -D "$srcdir"/dhcpd.initd "$pkgdir"/etc/init.d/dhcpd install -m644 -D "$srcdir"/dhcpd.confd "$pkgdir"/etc/conf.d/dhcpd - install -m751 -D "$builddir"/client/scripts/linux "$pkgdir"/sbin/dhclient-script + #install -m751 -D "$builddir"/client/scripts/linux "$pkgdir"/sbin/dhclient-script + install -m751 -D "$srcdir"/dhclient-script-alpine "$pkgdir"/sbin/dhclient-script install -d "$pkgdir"/var/lib/dhcp install -d "$pkgdir"/var/run/dhcp } @@ -92,6 +94,7 @@ sha512sums="684ae349f224918c9f8cec7bd6c55cd0b83ad2b5827375b2876ca088eb05b7ff1364 17e2b9588ee5d1bd9acb9c2e30f7a28308d29c9e797c2be14c1feff52e6e231ce8a94535f18badff1342aff4ae4003aab986e0f0473f0cd280292fdab044b148 01-dhclient-script-fix-bare-ip.patch a70e4a7e80ee65c8ced6b61db80f7ccd0f35015b5cccf2e7c51705ae129230aa49ba9926bb88f7418018e7a112c2a40451f24b88e04464b590ff20091e8d8709 02-dhclient-script-remove-bashisms.patch d5697a56fbbff25199962608986e7ffb533ed4afd3e344e3c79d2010dda73cc0b088f06c454e9f0c69eb054e09a374455fa71d3f73306e0c98fa76df4dd321b7 dhcp-3.0-fix-perms.patch +d1dce58875793316761f168e29feddc1d3454d1d917d063d43ae102b7b6aab256c3cb420478335c57ebcdb2b7c804afa4d8a1f9ab06a29a4dd23bc5d87db8df2 dhclient-script-alpine 0c3eee11ee9771a3bd7f8076827e57296136a36e6c00c3149e7274fb7a479feae4dc7d744f3c66ac78ffc96f036e14a7a5a0806095495441f98d76737a34faa6 dhcrelay.initd fd15dbaa4c61c3c26f407bf13dde859470a1adba134da064b653ccc152ce42635ee8de2fe113ae21ba8470e97e3caad8c1a47b69eb25e5e92b40e26790b96f6d dhcrelay.confd 7b7a77b7826b475a4113ebeee54501ce417cc56e85754301a82a185d88b4713d198f615a366e63e0e2b0aef988c8137dcd1e18c4036d993378257079da17693d dhcpd.confd diff --git a/main/dhcp/dhclient-script-alpine b/main/dhcp/dhclient-script-alpine new file mode 100644 index 0000000000..80b848b111 --- /dev/null +++ b/main/dhcp/dhclient-script-alpine @@ -0,0 +1,682 @@ +#!/bin/sh +# dhclient-script for Linux. Dan Halbert, March, 1997. +# Updated for Linux 2.[12] by Brian J. Murrell, January 1999. +# No guarantees about this. I'm a novice at the details of Linux +# networking. + +# Notes: + +# 0. This script is based on the netbsd script supplied with dhcp-970306. + +# 1. ifconfig down apparently deletes all relevant routes and flushes +# the arp cache, so this doesn't need to be done explicitly. + +# 2. The alias address handling here has not been tested AT ALL. +# I'm just going by the doc of modern Linux ip aliasing, which uses +# notations like eth0:0, eth0:1, for each alias. + +# 3. I have to calculate the network address, and calculate the broadcast +# address if it is not supplied. This might be much more easily done +# by the dhclient C code, and passed on. + +# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious +# of the $1 in its args. + +# 5. Script refresh in 2017. The aliasing code was too convoluted and needs +# to go away. Migrated DHCPv4 script to ip command from iproute2 suite. +# This is based on Debian script with some tweaks. ifconfig is no longer +# used. Everything is done using ip tool from ip-route2. + +# 'ip' just looks too weird. Also, we now have unit-tests! Those unit-tests +# overwirte this line to use a fake ip-echo tool. It's also convenient +# if your system holds ip tool in a non-standard location. +ip='/sbin/ip' + +# This is a dummy function to prevent shellcheck from complaining about these +# variables later in this script. It is not used during normal operation and +# should not slow down the execution of this script at all. +# If, given the above, it still bothers you, please feel free to delete it. +# SC2154: These specific variables are assigned external to this script. +# shellcheck disable=SC2154 +_shellcheck_external_variables() { + : alias_ip_address="$alias_ip_address" + : alias_subnet_mask="$alias_subnet_mask" + : cur_ip6_address="$cur_ip6_address" + : cur_ip6_prefixlen="$cur_ip6_prefixlen" + : dad_wait_time="$dad_wait_time" + : interface="$interface" + : new_broadcast_address="$new_broadcast_address" + : new_dhcp6_domain_search="$new_dhcp6_domain_search" + : new_dhcp6_name_servers="$new_dhcp6_name_servers" + : new_domain_name="$new_domain_name" + : new_domain_name_servers="$new_domain_name_servers" + : new_host_name="$new_host_name" + : new_interface_mtu="$new_interface_mtu" + : new_ip6_address="$new_ip6_address" + : new_ip6_prefixlen="$new_ip6_prefixlen" + : new_ip_address="$new_ip_address" + : new_max_life="$new_max_life" + : new_preferred_life="$new_preferred_life" + : new_rfc3442_classless_static_routes="$new_rfc3442_classless_static_routes" + : new_routers="$new_routers" + : new_subnet_mask="$new_subnet_mask" + : old_dhcp6_domain_search="$old_dhcp6_domain_search" + : old_dhcp6_name_servers="$old_dhcp6_name_servers" + : old_host_name="$old_host_name" + : old_ip6_address="$old_ip6_address" + : old_ip6_prefixlen="$old_ip6_prefixlen" + : old_ip_address="$old_ip_address" + : reason="$reason" +} + +print_nameservers() { + sed -n '/^[[:space:]]*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p' "${@}" +} + +# shellcheck disable=SC2039 +init_resolv_conf() { + local tmpfile + tmpfile="$(mktemp -q /etc/resolv.conf.dhclient-new.XXXXXXXXXX)" + if [ -z "${tmpfile}" ]; then + tmpfile='/etc/resolv.conf.dhclient-new' + rm -rf "${tmpfile}" + fi + : >>"${tmpfile}" + # shellcheck disable=SC2064 + trap "rm -f ${tmpfile}" EXIT + echo "${tmpfile}" +} + +# shellcheck disable=SC2039 +replace_resolv_conf() { + local src="${1}" + local dst='/etc/resolv.conf' + + if [ -f "${dst}" ]; then + chown --reference="${dst}" "${src}" + chmod --reference="${dst}" "${src}" + fi + mv -f "${src}" "${dst}" +} + +# update /etc/resolv.conf based on received values +# This updated version mostly follows Debian script by Andrew Pollock et al. +# shellcheck disable=SC2039 +make_resolv_conf() { + local nameserver + local new_resolv_conf + + # DHCPv4 + if [ -n "${new_domain_search}" ] || + [ -n "${new_domain_name}" ] || + [ -n "${new_domain_name_servers}" ] + then + new_resolv_conf="$(init_resolv_conf)" + + if [ -n "${new_domain_name}" ]; then + echo "domain ${new_domain_name%% *}" >>"${new_resolv_conf}" + fi + + if [ -n "${new_domain_search}" ]; then + if [ -n "${new_domain_name}" ]; then + local domain domain_in_search_list='' + for domain in ${new_domain_search}; do + if [ "${domain}" = "${new_domain_name}" ] || + [ "${domain}" = "${new_domain_name}." ] + then + domain_in_search_list='Yes' + fi + done + if [ -z "${domain_in_search_list}" ]; then + new_domain_search="${new_domain_name} ${new_domain_search}" + fi + fi + echo "search ${new_domain_search}" >>"${new_resolv_conf}" + elif [ -n "${new_domain_name}" ]; then + echo "search ${new_domain_name}" >>"${new_resolv_conf}" + fi + + if [ -n "${new_domain_name_servers}" ]; then + for nameserver in ${new_domain_name_servers}; do + echo "nameserver ${nameserver}" >>"${new_resolv_conf}" + done + else # keep 'old' nameservers + print_nameservers /etc/resolv.conf >>"${new_resolv_conf}" + fi + + replace_resolv_conf "${new_resolv_conf}" + # DHCPv6 + elif [ -n "${new_dhcp6_domain_search}" ] || + [ -n "${new_dhcp6_name_servers}" ] + then + new_resolv_conf="$(init_resolv_conf)" + + if [ -n "${new_dhcp6_domain_search}" ]; then + echo "search ${new_dhcp6_domain_search}" >>"${new_resolv_conf}" + fi + + if [ -n "${new_dhcp6_name_servers}" ]; then + for nameserver in ${new_dhcp6_name_servers}; do + # append %interface to link-local-address nameservers + if [ "${nameserver##fe80::}" != "${nameserver}" ] || + [ "${nameserver##FE80::}" != "${nameserver}" ] + then + nameserver="${nameserver}%${interface}" + fi + echo "nameserver ${nameserver}" >>"${new_resolv_conf}" + done + else # keep 'old' nameservers + print_nameservers /etc/resolv.conf >>"${new_resolv_conf}" + fi + + replace_resolv_conf "${new_resolv_conf}" + fi +} + +# set host name +# SC2039: our shell has local for function scope +# shellcheck disable=SC2039 +set_hostname() { + local current_hostname + + if [ -n "${new_host_name}" ]; then + current_hostname="$(hostname)" + + # current host name is empty, '(none)' or 'localhost' or + # differs from new one from DHCP + if [ -z "${current_hostname}" ] || + [ '(none)' = "${current_hostname}" ] || + [ 'localhost' = "${current_hostname}" ] || + [ "${old_host_name}" = "${current_hostname}" ] + then + if [ "${new_host_name}" != "${old_host_name}" ]; then + hostname "${new_host_name}" + fi + fi + fi +} + +# run given script +# shellcheck disable=SC2039,SC1090 +run_hook() { + local script + local exit_status + script="${1}" + + if [ -f "${script}" ]; then + . "${script}" + fi + + if [ -n "${exit_status}" ] && [ 0 != "${exit_status}" ]; then + logger -t dhclient-script -p daemon.err \ + "run_hook: ${script} returned non-zero exit status (${exit_status})" + [ "${exit_status}" -lt 256 ] 2>/dev/null || exit_status=255 + [ "${exit_status}" -gt 0 ] 2>/dev/null || exit_status=1 + fi + + return "${exit_status:-${?}}" +} + +# run scripts in given directory +# shellcheck disable=SC2039 +run_hookdir() { + local dir + local script + local exit_status + dir="${1}" + + if [ -d "${dir}" ]; then + for script in $(run-parts --list "${dir}"); do + if ! run_hook "${script}"; then + exit_status="${?}" + fi + done + fi + + return "${exit_status:-${?}}" +} + +# Must be used on exit. Invokes the local dhcp client exit hooks, if any. +# shellcheck disable=SC2039 +exit_with_hooks() { + local exit_status + exit_status="${1}" + + # Source the documented exit-hook script, if it exists + if ! run_hook /etc/dhclient-exit-hooks; then + exit_status="${?}" + fi + + # Now run scripts in the Debian-specific directory. + if ! run_hookdir /etc/dhclient-exit-hooks.d; then + exit_status="${?}" + fi + + exit "${exit_status}" +} + +ipv6_addr_del() { + "${ip}" -6 addr del "$@" dev "${interface}" +} + +# shellcheck disable=SC2039 +ipv6_addr_show() { + local dev + dev="${1}" + + "${ip}" -6 addr show ${dev:+dev "${dev}"} +} + +# shellcheck disable=SC2039 +ipv6_addr_filter() { + local dev + dev="${1}" + shift + + ipv6_addr_show "${dev}" | grep -F -e "${*}" +} + +# shellcheck disable=SC2039 +ipv6_addr_has_tentative() { + local dev + dev="${1}" + shift + + ipv6_addr_filter "${dev}" "${@}" | grep -F -e tentative >/dev/null 2>&1 +} + +ip_link_set() { + "${ip}" link set "${@}" +} + +link_set_up() { + ip_link_set dev "${interface}" up +} + +link_set_mtu() { + [ -n "${1}" ] || return 0 + + ip_link_set dev "${interface}" mtu "${1}" +} + +# shellcheck disable=SC2039 +_ip_addr_flush() { + local af + af="${1}" + shift + + case "${af}" in + (4|6) + ;; + (*) + return 1 + ;; + esac + + "${ip}" "-${af}" addr flush "${@}" +} + +#ip_addr_flush() { +# "${ip}" addr flush "${@}" +#} + +ipv4_addr_flush() { + _ip_addr_flush 4 "$@" +} + +ipv6_addr_flush() { + _ip_addr_flush 6 "$@" +} + +# shellcheck disable=SC2039 +addr_flush() { + local label + label="${1}" + + if [ -n "${label}" ]; then + ipv4_addr_flush dev "${interface}" label "${label}" + else + ipv4_addr_flush dev "${interface}" + fi +} + +ipv4_route_add() { + "${ip}" -4 route add "${@}" +} + +route_add() { + ipv4_route_add "$@" dev "${interface}" >/dev/null 2>&1 +} + +# shellcheck disable=SC2039 +route_add_default() { + local via + local metric + via="${1}" + metric="${2}" + + ipv4_route_add default via "${via}" \ + dev "${interface}" \ + ${metric:+metric "${metric}"} \ + >/dev/null 2>&1 +} + +# shellcheck disable=SC2039 +addr_add() { + local label + local addr + local mask + local broadcast + label="${1}" + addr="${2}" + mask="${3}" + broadcast="${4}" + + "${ip}" -4 addr add \ + "${addr}${mask:+/${mask}}" \ + ${broadcast:+broadcast "${broadcast}"} \ + dev "${label%%:*}" label "${label}" +} + +# This function was largely borrowed from dhclient-script that +# ships with Centos, authored by Jiri Popelka and David Cantrell +# of Redhat. Thanks guys. +# shellcheck disable=SC2039 +add_ipv6_addr_with_DAD() { + local _i + "${ip}" -6 addr replace "${new_ip6_address}/${new_ip6_prefixlen}" \ + dev "${interface}" scope global valid_lft "${new_max_life}" \ + preferred_lft "${new_preferred_life}" + + if [ "${dad_wait_time}" -le 0 ]; then + # if we're not waiting for DAD, assume we're good + return 0 + fi + + # Repeatedly test whether newly added address passed + # duplicate address detection (DAD) + for _i in $(seq 1 "${dad_wait_time}"); do + sleep 1 # give the DAD some time + + addr="$(ipv6_addr_filter "${interface}" \ + "${new_ip6_address}/${new_ip6_prefixlen}")" + + # tentative flag == DAD is still not complete + tentative="$(echo "${addr}" | grep tentative)" + # dadfailed flag == address is already in use somewhere else + dadfailed="$(echo "${addr}" | grep dadfailed)" + + if [ -n "${dadfailed}" ]; then + # address was added with valid_lft/preferred_lft 'forever', + # remove it + ipv6_addr_del "${new_ip6_address}/${new_ip6_prefixlen}" + + exit_with_hooks 3 + fi + + if [ -z "${tentative}" ]; then + if [ -n "${addr}" ]; then + # DAD is over + return 0 + else + # address was auto-removed (or not added at all) + exit_with_hooks 3 + fi + fi + done + + return 0 +} + +# shellcheck disable=SC2039 +init_if_metric() { + local _if_metric + + # set if_metric if IF_METRIC is set or there's more than one router + # shellcheck disable=SC2153 + _if_metric="${IF_METRIC}" + if [ "${new_routers%% *}" != "${new_routers}" ]; then + _if_metric="${_if_metric:-1}" + fi + + if_metric="${_if_metric}" + echo "${_if_metric}" +} + +# Invoke the local dhcp client enter hooks, if they exist. +run_hook /etc/dhclient-enter-hooks +run_hookdir /etc/dhclient-enter-hooks.d + +# Execute the operation +case "${reason}" in + + ### DHCPv4 Handlers + + MEDIUM|ARPCHECK|ARPSEND) + # Do nothing + ;; + PREINIT) + # The DHCP client is requesting that an interface be + # configured as required in order to send packets prior to + # receiving an actual address. - dhclient-script(8) + + # ensure interface is up + link_set_up + + if [ -n "${alias_ip_address}" ]; then + # flush alias IP from interface + addr_flush "${interface}:0" + fi + + ;; + + BOUND|RENEW|REBIND|REBOOT) + set_hostname + + if [ -n "${old_ip_address}" ] && [ -n "${alias_ip_address}" ] && + [ "${alias_ip_address}" != "${old_ip_address}" ]; then + # alias IP may have changed => flush it + addr_flush "${interface}:0" + fi + + if [ -n "${old_ip_address}" ] && + [ "${old_ip_address}" != "${new_ip_address}" ]; then + # leased IP has changed => flush it + addr_flush "${interface}" + fi + + if [ -z "${old_ip_address}" ] || + [ "${old_ip_address}" != "${new_ip_address}" ] || + [ "${reason}" = "BOUND" ] || [ "${reason}" = "REBOOT" ]; then + # new IP has been leased or leased IP changed => set it + addr_add "${interface}" \ + "${new_ip_address}" "${new_subnet_mask}" \ + "${new_broadcast_address}" + + link_set_mtu "${new_interface_mtu}" + + # if we have $new_rfc3442_classless_static_routes then we have to + # ignore $new_routers entirely + if [ -z "${new_rfc3442_classless_static_routes}" ]; then + if_metric="$(init_if_metric)" + for router in ${new_routers}; do + if [ "255.255.255.255" = "${new_subnet_mask}" ]; then + # point-to-point connection => set explicit route + route_add "${router}" + fi + + # set default route + route_add_default "${router}" "${if_metric}" + + if [ -n "${if_metric}" ]; then + if_metric="$((1+if_metric))" + fi + done + fi + fi + + if [ -n "${alias_ip_address}" ] && + [ "${new_ip_address}" != "${alias_ip_address}" ] + then + # separate alias IP given, which may have changed + # => flush it, set it & add host route to it + addr_flush "${interface}:0" + addr_add "${interface}:0" \ + "${alias_ip_address}" "${alias_subnet_mask}" + route_add "${alias_ip_address}" + fi + + # update /etc/resolv.conf + make_resolv_conf + + ;; + + EXPIRE|FAIL|RELEASE|STOP) + if [ -n "${alias_ip_address}" ]; then + # flush alias IP + addr_flush "${interface}:0" + fi + + if [ -n "${old_ip_address}" ]; then + # flush leased IP + addr_flush "${interface}" + fi + + if [ -n "${alias_ip_address}" ]; then + # alias IP given => set it & add host route to it + addr_add "${interface}:0" \ + "${alias_ip_address}" "${alias_subnet_mask}" + route_add "${alias_ip_address}" + fi + + ;; + + TIMEOUT) + if [ -n "${alias_ip_address}" ]; then + # flush alias IP + addr_flush "${interface}:0" + fi + + # set IP from recorded lease + addr_add "${interface}" \ + "${new_ip_address}" "${new_subnet_mask}" \ + "${new_broadcast_address}" + + link_set_mtu "${new_interface_mtu}" + + # if there is no router recorded in the lease + # or the 1st router answers pings + if [ -z "${new_routers}" ] || ping -q -c 1 "${new_routers%% *}"; then + # if we have $new_rfc3442_classless_static_routes then we have to + # ignore $new_routers entirely + if [ -z "${new_rfc3442_classless_static_routes}" ]; then + if [ -n "${alias_ip_address}" ] && + [ "${new_ip_address}" != "${alias_ip_address}" ] + then + # separate alias IP given => set up the alias IP & add host route to it + addr_add "${interface}:0" \ + "${alias_ip_address}" "${alias_subnet_mask}" + route_add "${alias_ip_address}" + fi + + if_metric="$(init_if_metric)" + for router in ${new_routers}; do + # set default route + route_add_default "${router}" "${if_metric}" + + if [ -n "${if_metric}" ]; then + if_metric="$((1+if_metric))" + fi + done + fi + + # update /etc/resolv.conf + make_resolv_conf + else + # flush all IPs from interface + addr_flush + exit_with_hooks 2 + fi + + ;; + + ### DHCPv6 Handlers + # TODO handle prefix change: ?based on ${old_ip6_prefix} and ${new_ip6_prefix}? + + PREINIT6) + # ensure interface is up + link_set_up + + # We need to give the kernel some time to active interface + interface_up_wait_time=5 + # shellcheck disable=SC2034 + for _i in $(seq 0 ${interface_up_wait_time}); do + if ifconfig "${interface}" | grep RUNNING >/dev/null 2>&1; then + break + fi + sleep 1 + done; unset -v _i + + # flush any stale global permanent IPs from interface + ipv6_addr_flush dev "${interface}" scope global permanent + + # Wait for duplicate address detection for this interface if the + # --dad-wait-time parameter has been specified and is greater than + # zero. + if [ "${dad_wait_time}" -gt 0 ]; then + # Check if any IPv6 address on this interface is marked as + # tentative. + if ipv6_addr_has_tentative "${interface}" inet6; then + # Wait for duplicate address detection to complete or for + # the timeout specified as --dad-wait-time. + # shellcheck disable=SC2034 + for _i in $(seq 0 "${dad_wait_time}"); do + # We're going to poll for the tentative flag every second. + sleep 1 + if ! ipv6_addr_has_tentative "${interface}" inet6; then + break + fi + done; unset -v _i + fi + fi + + ;; + + BOUND6|RENEW6|REBIND6) + if [ "${new_ip6_address}" ] && [ "${new_ip6_prefixlen}" ]; then + # set leased IP + add_ipv6_addr_with_DAD + fi + + # update /etc/resolv.conf + if [ "${reason}" = BOUND6 ] || + [ "${new_dhcp6_name_servers}" != "${old_dhcp6_name_servers}" ] || + [ "${new_dhcp6_domain_search}" != "${old_dhcp6_domain_search}" ]; then + make_resolv_conf + fi + + ;; + + DEPREF6) + if [ -z "${cur_ip6_prefixlen}" ]; then + exit_with_hooks 2 + fi + + # set preferred lifetime of leased IP to 0 + "${ip}" -6 addr change "${cur_ip6_address}/${cur_ip6_prefixlen}" \ + dev "${interface}" scope global preferred_lft 0 + + ;; + + EXPIRE6|RELEASE6|STOP6) + if [ -z "${old_ip6_address}" ] || [ -z "${old_ip6_prefixlen}" ]; then + exit_with_hooks 2 + fi + + # delete leased IP + ipv6_addr_del "${old_ip6_address}/${old_ip6_prefixlen}" + + ;; +esac + +exit_with_hooks 0 |