diff options
author | Christian Poessinger <christian@poessinger.com> | 2020-02-13 17:32:18 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-13 17:32:18 +0100 |
commit | 13bc01034d287ffdf1249138ddfbdbb1866b5a93 (patch) | |
tree | 755a97aa42b8e98699927543ffe7766f5b847a0f /src/etc/dhcp | |
parent | 233c463b4cf6f8ca4d3e2a1a3a30e5c62ce42061 (diff) | |
parent | e39f2ead18c17fa4a8fdfe35437202fb202e983a (diff) | |
download | vyos-1x-13bc01034d287ffdf1249138ddfbdbb1866b5a93.tar.gz vyos-1x-13bc01034d287ffdf1249138ddfbdbb1866b5a93.zip |
Merge pull request #218 from zdc/T1987
dhclient-script: T1987: Multiple fixes in dhclient-script
Diffstat (limited to 'src/etc/dhcp')
7 files changed, 255 insertions, 0 deletions
diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/01-vyos-logging b/src/etc/dhcp/dhclient-enter-hooks.d/01-vyos-logging new file mode 100644 index 000000000..121fb21be --- /dev/null +++ b/src/etc/dhcp/dhclient-enter-hooks.d/01-vyos-logging @@ -0,0 +1,20 @@ +# enable logging +LOG_ENABLE="yes" +LOG_STDERR="no" +LOG_TAG="dhclient-script-vyos" + +function logmsg () { + # log message to journal + case $1 in + error) LOG_PRIO="daemon.err" ;; + info) LOG_PRIO="daemon.info" ;; + esac + + if [ "${LOG_ENABLE}" == "yes" ] ; then + if [ "${LOG_STDERR}" == "yes" ] ; then + /usr/bin/logger -e --id=$$ -s -p ${LOG_PRIO} -t ${LOG_TAG} "${@:2}" + else + /usr/bin/logger -e --id=$$ -p ${LOG_PRIO} -t ${LOG_TAG} "${@:2}" + fi + fi +} diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/02-vyos-stopdhclient b/src/etc/dhcp/dhclient-enter-hooks.d/02-vyos-stopdhclient new file mode 100644 index 000000000..d5d90632c --- /dev/null +++ b/src/etc/dhcp/dhclient-enter-hooks.d/02-vyos-stopdhclient @@ -0,0 +1,27 @@ +# skip all of this if dhclient-script running by stop command defined below +if [ -z ${CONTROLLED_STOP} ] ; then + # stop dhclient for this interface, if it is not current one + # get PID for current dhclient + current_dhclient=`ps --no-headers --format ppid --pid $$ | awk '{ print $1 }'` + + # get PID for master process (current can be a fork) + master_dhclient=`ps --no-headers --format ppid --pid $current_dhclient | awk '{ print $1 }'` + + # get IP version for current dhclient + ipversion_arg=`ps --no-headers --format args --pid $current_dhclient | awk '{ print $2 }'` + + # get list of all dhclient running for current interface + dhclients_pids=(`ps --no-headers --format pid,args -C dhclient | awk -v IFACE="/sbin/dhclient $ipversion_arg .*$interface$" '$0 ~ IFACE { print $1 }'`) + + logmsg info "Current dhclient PID: $current_dhclient, Parent PID: $master_dhclient, IP version: $ipversion_arg, All dhclients for interface $interface: ${dhclients_pids[@]}" + # stop all dhclients for current interface, except current one + for dhclient in ${dhclients_pids[@]}; do + if ([ $dhclient -ne $current_dhclient ] && [ $dhclient -ne $master_dhclient ]); then + logmsg info "Stopping dhclient with PID: ${dhclient}" + # get path to PID-file of dhclient process + local dhclient_pidfile=`ps --no-headers --format args --pid $dhclient | awk 'match($0, ".*-pf (/.*pid) .*", PF) { print PF[1] }'` + # stop dhclient with native command - this will run dhclient-script with correct reason unlike simple kill + dhclient -e CONTROLLED_STOP=yes -x -pf $dhclient_pidfile + fi + done +fi diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper b/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper new file mode 100644 index 000000000..59f92703c --- /dev/null +++ b/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper @@ -0,0 +1,76 @@ +# redefine ip command to use FRR when it is available + +# get status of FRR +function frr_alive () { + /usr/lib/frr/watchfrr.sh all_status + if [ "$?" -eq "0" ] ; then + logmsg info "FRR status: running" + return 0 + else + logmsg info "FRR status: not running" + return 1 + fi +} + +# convert ip route command to vtysh +function iptovtysh () { + # prepare variables for vtysh command + VTYSH_DISTANCE="210" + VTYSH_TAG="210" + # convert default route to 0.0.0.0/0 + if [ "$4" == "default" ] ; then + VTYSH_NETADDR="0.0.0.0/0" + else + VTYSH_NETADDR=$4 + fi + # add /32 to ip addresses without netmasks + if [[ ! $VTYSH_NETADDR =~ ^.*/[[:digit:]]+$ ]] ; then + VTYSH_NETADDR="$VTYSH_NETADDR/32" + fi + # get gateway address + if [ "$5" == "via" ] ; then + VTYSH_GATEWAY=$6 + fi + # get device name + if [ "$5" == "dev" ]; then + VTYSH_DEV=$6 + elif [ "$7" == "dev" ]; then + VTYSH_DEV=$8 + fi + VTYSH_CMD="ip route $VTYSH_NETADDR $VTYSH_GATEWAY $VTYSH_DEV tag $VTYSH_TAG $VTYSH_DISTANCE" + # delete route if the command is "del" + if [ "$3" == "del" ] ; then + VTYSH_CMD="no $VTYSH_CMD" + fi + logmsg info "Converted vtysh command: \"$VTYSH_CMD\"" +} + +# delete the same route from kernel before adding new one +function delroute () { + logmsg info "Checking if the route presented in kernel: $@" + if /usr/sbin/ip route show $@ | grep -qx "$1 " ; then + logmsg info "Deleting IP route: \"/usr/sbin/ip route del $@\"" + /usr/sbin/ip route del $@ + fi +} + +# replace ip command with this wrapper +function ip () { + # pass comand to system `ip` if this is not related to routes change + if [ "$2" != "route" ] ; then + logmsg info "Passing command to /usr/sbin/ip: \"$@\"" + /usr/sbin/ip $@ + else + # if we want to work with routes, try to use FRR first + if frr_alive ; then + delroute ${@:4} + iptovtysh $@ + logmsg info "Sending command to vtysh" + vtysh -c "conf t" -c "$VTYSH_CMD" + else + # add ip route to kernel + logmsg info "Modifying routes in kernel: \"/usr/sbin/ip $@\"" + /usr/sbin/ip $@ + fi + fi +} diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/04-vyos-resolvconf b/src/etc/dhcp/dhclient-enter-hooks.d/04-vyos-resolvconf new file mode 100644 index 000000000..ea5562ea8 --- /dev/null +++ b/src/etc/dhcp/dhclient-enter-hooks.d/04-vyos-resolvconf @@ -0,0 +1,39 @@ +# modified make_resolv_conf () for Vyatta system below +make_resolv_conf() { + if [ -n "$new_domain_name" ]; then + logmsg info "Adding search-domain \"$new_domain_name\" via vyos-hostsd-client" + /usr/bin/vyos-hostsd-client --set-host-name --search-domain $new_domain_name + fi + + if [ -n "$new_dhcp6_domain_search" ]; then + logmsg info "Adding search-domain \"$new_dhcp6_domain_search\" via vyos-hostsd-client" + /usr/bin/vyos-hostsd-client --set-host-name --search-domain $new_dhcp6_domain_search + fi + + if [ -n "$new_domain_name_servers" ] && ! cli-shell-api existsEffective system disable-dhcp-nameservers && [ "$new_domain_name_servers" != "$old_domain_name_servers" ] ; then + logmsg info "Deleting nameservers with tag \"dhcp-$interface\" via vyos-hostsd-client" + vyos-hostsd-client --delete-name-servers --tag dhcp-$interface + NEW_SERVERS="" + for nameserver in $new_domain_name_servers; do + NEW_SERVERS="$NEW_SERVERS --name-server $nameserver" + done + logmsg info "Adding nameservers \"$NEW_SERVERS\" with tag \"dhcp-$interface\" via vyos-hostsd-client" + /usr/bin/vyos-hostsd-client --add-name-servers $NEW_SERVERS --tag dhcp-$interface + fi + + if [ -n "$new_dhcp6_name_servers" ] && ! cli-shell-api existsEffective system disable-dhcp-nameservers && [ "$new_dhcp6_name_servers" != "$old_dhcp6_name_servers" ] ; then + logmsg info "Deleting nameservers with tag \"dhcpv6-$interface\" via vyos-hostsd-client" + vyos-hostsd-client --delete-name-servers --tag dhcpv6-$interface + NEW_SERVERS="" + for nameserver in $new_dhcp6_name_servers; do + NEW_SERVERS="$NEW_SERVERS --name-server $nameserver" + done + logmsg info "Adding nameservers \"$NEW_SERVERS\" with tag \"dhcpv6-$interface\" via vyos-hostsd-client" + /usr/bin/vyos-hostsd-client --add-name-servers $NEW_SERVERS --tag dhcpv6-$interface + fi + + if cli-shell-api existsEffective service dns forwarding; then + logmsg info "Enabling DNS forwarding" + /usr/libexec/vyos/conf_mode/dns_forwarding.py --dhclient + fi +} diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/05-vyos-mtureplace b/src/etc/dhcp/dhclient-enter-hooks.d/05-vyos-mtureplace new file mode 100644 index 000000000..4a08765ba --- /dev/null +++ b/src/etc/dhcp/dhclient-enter-hooks.d/05-vyos-mtureplace @@ -0,0 +1,38 @@ +# replace MTU with value from configuration + +# get MTU value via Python +# as configuration is not available to cli-shell-api at the first boot, we must use vyos.config, which contain workaround for this, instead clean shell +function get_mtu { +python3 - <<PYEND +from vyos.config import Config +import os +import re + +# check if interface is not VLAN and fix name if necessary +interface_name = os.getenv('interface', '') +regex_filter = re.compile('^(?P<interface>\w+)\.(?P<vid>\d+)$') +if regex_filter.search(interface_name): + iface = regex_filter.search(interface_name).group('interface') + vid = regex_filter.search(interface_name).group('vid') + interface_name = "{} vif {}".format(iface, vid) + +# initialize config +config = Config() +if config.exists('interfaces'): + iface_types = config.list_nodes('interfaces') + for iface_type in iface_types: + # check if configuration contain MTU value for interface and return (print) it + if config.exists("interfaces {} {} mtu".format(iface_type, interface_name)): + print(format(config.return_value("interfaces {} {} mtu".format(iface_type, interface_name)))) +PYEND +} + +# check if DHCP server return MTU value +if [ -n "$new_interface_mtu" ]; then + # try to get MTU from config and replace original one + configured_mtu="$(get_mtu)" + if [[ -n $configured_mtu ]] ; then + logmsg info "Replacing MTU value for $interface with preconfigured one: $configured_mtu" + new_interface_mtu="$configured_mtu" + fi +fi diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup b/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup new file mode 100644 index 000000000..ce846f6c3 --- /dev/null +++ b/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup @@ -0,0 +1,16 @@ +if [[ $reason =~ (EXPIRE|FAIL|RELEASE|STOP) ]]; then + # delete dynamic nameservers from a configuration if lease was deleted + logmsg info "Deleting nameservers with tag \"dhcp-${interface}\" via vyos-hostsd-client" + vyos-hostsd-client --delete-name-servers --tag dhcp-${interface} + # try to delete default ip route (NOTE: here we use 'ip' wrapper, therefore a route will be actually deleted via /usr/sbin/ip or vtysh, according to the system state) + for router in $old_routers; do + logmsg info "Deleting default route: via $router dev ${interface}" + ip -4 route del default via $router dev ${interface} + done +fi + +if [[ $reason =~ (EXPIRE6|RELEASE6|STOP6) ]]; then + # delete dynamic nameservers from a configuration if lease was deleted + logmsg info "Deleting nameservers with tag \"dhcpv6-${interface}\" via vyos-hostsd-client" + vyos-hostsd-client --delete-name-servers --tag dhcpv6-${interface} +fi diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/vyatta-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/vyatta-dhclient-hook new file mode 100644 index 000000000..dcd06644f --- /dev/null +++ b/src/etc/dhcp/dhclient-exit-hooks.d/vyatta-dhclient-hook @@ -0,0 +1,39 @@ +#!/bin/sh + +# Author: Stig Thormodsrud <stig@vyatta.com> +# Date: 2007 +# Description: dhcp client hook + +# **** License **** +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# This code was originally developed by Vyatta, Inc. +# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008 Vyatta, Inc. +# All Rights Reserved. +# **** End License **** + +# To enable this script set the following variable to "yes" +RUN="yes" + +if [ "$RUN" = "yes" ]; then + LOG=/var/lib/dhcp/dhclient_"$interface"_lease + echo `date` > $LOG + + for i in reason interface new_expiry new_dhcp_lease_time medium \ + alias_ip_address new_ip_address new_broadcast_address \ + new_subnet_mask new_domain_name new_network_number \ + new_domain_name_servers new_routers new_static_routes \ + new_dhcp_server_identifier new_dhcp_message_type \ + old_ip_address old_subnet_mask old_domain_name \ + old_domain_name_servers old_routers \ + old_static_routes; do + echo $i=\'${!i}\' >> $LOG + done +fi |