mirror of
				https://git.proxmox.com/git/mirror_iproute2
				synced 2025-10-31 19:18:00 +00:00 
			
		
		
		
	 20ed7b24df
			
		
	
	
		20ed7b24df
		
	
	
	
	
		
			
			/tmp is a dangerous place and better to put log files in /var/log. Based on patch by Vasiliy Kulikov <segoon@openwall.com>
		
			
				
	
	
		
			447 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			447 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
| #!/bin/bash
 | |
| #
 | |
| # dhclient-script for Linux.
 | |
| #
 | |
| #		This program is free software; you can redistribute it and/or
 | |
| #		modify it under the terms of the GNU General Public License
 | |
| #		as published by the Free Software Foundation; either version
 | |
| #		2 of the License, or (at your option) any later version.
 | |
| #
 | |
| # Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 | |
| #
 | |
| # Probably, I did not understand, what this funny feature as "alias"
 | |
| # means exactly. For now I suppose, that it is a static address, which
 | |
| # we should install and preserve.
 | |
| #
 | |
| 
 | |
| exec >> /var/log/DHS.log 2>&1
 | |
| 
 | |
| echo dhc-script $* reason=$reason
 | |
| set | grep "^\(old_\|new_\|check_\)"
 | |
| 
 | |
| LOG () {
 | |
|     echo LOG $* ;
 | |
| }
 | |
| 
 | |
| # convert 8bit mask to length
 | |
| # arg: $1 = mask
 | |
| #
 | |
| Mask8ToLen() {
 | |
| 	local l=0;
 | |
| 
 | |
| 	while [ $l -le 7 ]; do
 | |
| 		if [ $[ ( 1 << $l ) + $1 ] -eq 256 ]; then
 | |
| 			return	$[ 8 - $l ]
 | |
| 		fi
 | |
| 		l=$[ $l + 1 ]
 | |
| 	done
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| # convert inet dotted quad mask to length
 | |
| # arg: $1 = dotquad mask
 | |
| #
 | |
| MaskToLen() {
 | |
|  local masklen=0
 | |
|  local mask8=$1
 | |
| 
 | |
|  case $1 in
 | |
|  0.0.0.0)
 | |
| 	return 0;
 | |
| 	;;
 | |
|  255.*.0.0)
 | |
| 	masklen=8
 | |
| 	mask8=${mask8#255.}
 | |
| 	mask8=${mask8%.0.0}
 | |
| 	;;
 | |
|  255.255.*.0)
 | |
| 	masklen=16
 | |
| 	mask8=${mask8#255.255.}
 | |
| 	mask8=${mask8%.0}
 | |
| 	;;
 | |
|  255.255.255.*)
 | |
| 	masklen=24
 | |
| 	mask8=${mask8#255.255.255.}
 | |
| 	;;
 | |
|  *)
 | |
| 	return 255
 | |
| 	;;
 | |
|  esac
 | |
|  Mask8ToLen $mask8
 | |
|  return $[ $? + $masklen ]
 | |
| }
 | |
| 
 | |
| # calculate ABC "natural" mask
 | |
| # arg: $1 = dotquad address
 | |
| #
 | |
| ABCMask () {
 | |
|  local class;
 | |
| 
 | |
|  class=${1%%.*}
 | |
| 
 | |
|  if [ "$1" = "255.255.255.255" ]; then
 | |
|     echo $1
 | |
|  elif [ "$1" = "0.0.0.0" ]; then
 | |
|     echo $1
 | |
|  elif [ $class -ge 224 ]; then
 | |
|     echo 240.0.0.0
 | |
|  elif [ $class -ge 192 ]; then
 | |
|     echo 255.255.255.0
 | |
|  elif [ $class -ge 128 ]; then
 | |
|     echo 255.255.0.0
 | |
|  else
 | |
|     echo 255.0.0.0
 | |
|  fi
 | |
| }
 | |
| 
 | |
| # calculate ABC "natural" mask length
 | |
| # arg: $1 = dotquad address
 | |
| #
 | |
| ABCMaskLen () {
 | |
|  local class;
 | |
| 
 | |
|  class=${1%%.*}
 | |
| 
 | |
|  if [ "$1" = "255.255.255.255" ]; then
 | |
|     return 32
 | |
|  elif [ "$1" = "0.0.0.0" ]; then
 | |
|     return 0
 | |
|  elif [ $class -ge 224 ]; then
 | |
|     return 4;
 | |
|  elif [ $class -ge 192 ]; then
 | |
|     return 24;
 | |
|  elif [ $class -ge 128 ]; then
 | |
|     return 16;
 | |
|  else
 | |
|     return 8;
 | |
|  fi
 | |
| }
 | |
| 
 | |
| # Delete IP address
 | |
| # args: $1 = interface
 | |
| #       $2 = address
 | |
| #       $3 = mask
 | |
| #       $4 = broadcast
 | |
| #       $5 = label
 | |
| #
 | |
| DelINETAddr () {
 | |
|   local masklen=32
 | |
|   local addrid=$1
 | |
| 
 | |
|   LOG DelINETAddr $*
 | |
| 
 | |
|   if [ "$5" ]; then
 | |
|     addrid=$addrid:$5
 | |
|   fi
 | |
|   LOG ifconfig $addrid down
 | |
|   ifconfig $addrid down
 | |
| }
 | |
| 
 | |
| # Add IP address
 | |
| # args: $1 = interface
 | |
| #       $2 = address
 | |
| #       $3 = mask
 | |
| #       $4 = broadcast
 | |
| #       $5 = label
 | |
| #
 | |
| AddINETAddr () {
 | |
|   local mask_arg
 | |
|   local brd_arg
 | |
|   local addrid=$1
 | |
| 
 | |
|   LOG AddINETAddr $*
 | |
| 
 | |
|   if [ "$5" ]; then
 | |
|     addrid=$addrid:$5
 | |
|   fi
 | |
|   if [ "$3" ]; then
 | |
|     mask_arg="netmask $3"
 | |
|   fi
 | |
|   if [ "$4" ]; then
 | |
|     brd_arg="broadcast $4"
 | |
|   fi
 | |
| 
 | |
|   LOG ifconfig $addrid $2 $mask_arg $brd_arg up
 | |
|   ifconfig $addrid $2 $mask_arg $brd_arg up
 | |
| }
 | |
| 
 | |
| # Add default routes
 | |
| # args: $1 = routers list
 | |
| #
 | |
| AddDefaultRoutes() {
 | |
|     local router
 | |
| 
 | |
|     if [ "$1" ]; then
 | |
|       LOG AddDefaultRoutes $*
 | |
|       for router in $1; do
 | |
|         LOG route add default gw $router
 | |
|         route add default gw $router
 | |
|       done ;
 | |
|     fi
 | |
| }
 | |
| 
 | |
| # Delete default routes
 | |
| # args: $1 = routers list
 | |
| #
 | |
| DelDefaultRoutes() {
 | |
|     local router
 | |
| 
 | |
|     if [ "$1" ]; then
 | |
|       LOG DelDefaultRoutes $*
 | |
| 
 | |
|       for router in $1; do
 | |
|         LOG route del default gw $router
 | |
|         route del default gw $router
 | |
|       done
 | |
|     fi
 | |
| }
 | |
| 
 | |
| # ping a host
 | |
| # args: $1 = dotquad address of the host
 | |
| #
 | |
| PingNode() {
 | |
|     LOG PingNode $*
 | |
|     if ping -q -c 1 -w 2 $1 ; then
 | |
| 	return 0;
 | |
|     fi
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| # Check (and add route, if alive) default routers
 | |
| # args: $1 = routers list
 | |
| # returns: 0 if at least one router is alive.
 | |
| #
 | |
| CheckRouterList() {
 | |
|     local router
 | |
|     local succeed=1
 | |
| 
 | |
|     LOG CheckRouterList $*
 | |
| 
 | |
|     for router in $1; do
 | |
|       if PingNode $router ; then
 | |
| 	succeed=0
 | |
|         route add default gw $router
 | |
|       fi
 | |
|     done
 | |
|     return $succeed
 | |
| }
 | |
| 
 | |
| # Delete/create static routes.
 | |
| # args: $1 = operation (del/add)
 | |
| #       $2 = routes list in format "dst1 nexthop1 dst2 ..."
 | |
| #
 | |
| # BEWARE: this feature of DHCP is obsolete, because does not
 | |
| #         support subnetting.
 | |
| #
 | |
| X-StaticRouteList() {
 | |
|     local op=$1
 | |
|     local lst="$2"
 | |
|     local masklen
 | |
| 
 | |
|     LOG X-StaticRouteList $*
 | |
| 
 | |
|     if [ "$lst" ]; then
 | |
|       set $lst
 | |
|       while [ $# -gt 1 ]; do
 | |
| 	route $op -net $1 netmask `ABCMask "$1"` gw $2
 | |
| 	shift; shift;
 | |
|       done
 | |
|    fi
 | |
| }
 | |
| 
 | |
| # Create static routes.
 | |
| # arg: $1 = routes list in format "dst1 nexthop1 dst2 ..."
 | |
| #
 | |
| AddStaticRouteList() {
 | |
|     LOG AddStaticRouteList $*
 | |
|     X-StaticRouteList add "$1"
 | |
| }
 | |
| 
 | |
| # Delete static routes.
 | |
| # arg: $1 = routes list in format "dst1 nexthop1 dst2 ..."
 | |
| #
 | |
| DelStaticRouteList() {
 | |
|     LOG DelStaticRouteList $*
 | |
|     X-StaticRouteList del "$1"
 | |
| }
 | |
| 
 | |
| # Broadcast unsolicited ARP to update neighbours' caches.
 | |
| # args: $1 = interface
 | |
| #       $2 = address
 | |
| #
 | |
| UnsolicitedARP() {
 | |
|     if [ -f /sbin/arping ]; then
 | |
| 	/sbin/arping -A -c 1 -I "$1" "$2" &
 | |
| 	(sleep 2 ; /sbin/arping -U -c 1 -I "$1" "$2" ) &
 | |
|     fi
 | |
| }
 | |
| 
 | |
| # Duplicate address detection.
 | |
| # args: $1 = interface
 | |
| #       $2 = test address
 | |
| # returns: 0, if DAD succeeded.
 | |
| DAD() {
 | |
|   if [ -f /sbin/arping ]; then
 | |
| 	/sbin/arping -c 2 -w 3 -D -I "$1" "$2"
 | |
| 	return $?
 | |
|   fi
 | |
|   return 0
 | |
| }
 | |
| 
 | |
| 
 | |
| # Setup resolver.
 | |
| # args: NO
 | |
| #       domain and nameserver list are passed in global variables.
 | |
| #
 | |
| # NOTE: we try to be careful and not to break user supplied resolv.conf.
 | |
| #       The script mangles it, only if it has dhcp magic signature.
 | |
| #
 | |
| UpdateDNS() {
 | |
|     local nameserver
 | |
|     local idstring="#### Generated by DHCPCD"
 | |
| 
 | |
|     LOG UpdateDNS $*
 | |
| 
 | |
|     if [ "$new_domain_name" = "" -a "$new_domain_name_servers" = "" ]; then
 | |
| 	return 0;
 | |
|     fi
 | |
| 
 | |
|     echo $idstring > /etc/resolv.conf.dhcp
 | |
|     if [ "$new_domain_name" ]; then
 | |
| 	echo search $new_domain_name >> /etc/resolv.conf.dhcp
 | |
|     fi
 | |
|     echo options ndots:1 >> /etc/resolv.conf.dhcp
 | |
| 
 | |
|     if [ "$new_domain_name_servers" ]; then
 | |
| 	for nameserver in $new_domain_name_servers; do
 | |
| 	    echo nameserver $nameserver >> /etc/resolv.conf.dhcp
 | |
| 	done
 | |
|     else
 | |
| 	echo nameserver 127.0.0.1 >> /etc/resolv.conf.dhcp
 | |
|     fi
 | |
| 
 | |
|     if [ -f /etc/resolv.conf ]; then
 | |
| 	if [ "`head -1 /etc/resolv.conf`" != "$idstring" ]; then
 | |
| 	    return 0
 | |
| 	fi
 | |
| 	if [ "$old_domain_name" = "$new_domain_name" -a
 | |
| 	     "$new_domain_name_servers" = "$old_domain_name_servers" ]; then
 | |
| 	     return 0
 | |
| 	fi
 | |
|     fi
 | |
|     mv /etc/resolv.conf.dhcp /etc/resolv.conf
 | |
| }
 | |
| 
 | |
| case $reason in
 | |
| NBI)
 | |
|   exit 1
 | |
|   ;;
 | |
| 
 | |
| MEDIUM)
 | |
|   exit 0
 | |
|   ;;
 | |
| 
 | |
| PREINIT)
 | |
|   ifconfig $interface:dhcp down
 | |
|   ifconfig $interface:dhcp1 down
 | |
|   if [ -d /proc/sys/net/ipv4/conf/$interface ]; then
 | |
|     ifconfig $interface:dhcp 10.10.10.10 netmask 255.255.255.255
 | |
|     ifconfig $interface:dhcp down
 | |
|     if [ -d /proc/sys/net/ipv4/conf/$interface ]; then
 | |
| 	LOG The interface $interface already configured.
 | |
|     fi
 | |
|   fi
 | |
|   ifconfig $interface:dhcp up
 | |
|   exit 0
 | |
|   ;;
 | |
| 
 | |
| ARPSEND)
 | |
|   exit 0
 | |
|   ;;
 | |
| 
 | |
| ARPCHECK)
 | |
|   if DAD "$interface" "$check_ip_address" ; then
 | |
|     exit 0
 | |
|   fi
 | |
|   exit 1
 | |
|   ;;
 | |
| 
 | |
| BOUND|RENEW|REBIND|REBOOT)
 | |
|   if [ "$old_ip_address" -a "$alias_ip_address" -a \
 | |
| 	"$alias_ip_address" != "$old_ip_address" ]; then
 | |
|     DelINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
 | |
|   fi
 | |
|   if [ "$old_ip_address" -a "$old_ip_address" != "$new_ip_address" ]; then
 | |
|     DelINETAddr "$interface" "$old_ip_address" "$old_subnet_mask" "$old_broadcast_address" dhcp
 | |
|     DelDefaultRoutes "$old_routers"
 | |
|     DelStaticRouteList "$old_static_routes"
 | |
|   fi
 | |
|   if [ "$old_ip_address" = "" -o "$old_ip_address" != "$new_ip_address" -o \
 | |
|        "$reason" = "BOUND" -o "$reason" = "REBOOT" ]; then
 | |
|     AddINETAddr "$interface" "$new_ip_address" "$new_subnet_mask" "$new_broadcast_address" dhcp
 | |
|     AddStaticRouteList "$new_static_routes"
 | |
|     AddDefaultRoutes "$new_routers"
 | |
|     UnsolicitedARP "$interface" "$new_ip_address"
 | |
|   fi
 | |
|   if [ "$new_ip_address" != "$alias_ip_address" -a "$alias_ip_address" ]; then
 | |
|     AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
 | |
|   fi
 | |
|   UpdateDNS
 | |
|   exit 0
 | |
|   ;;
 | |
| 
 | |
| EXPIRE|FAIL)
 | |
|   if [ "$alias_ip_address" ]; then
 | |
|     DelINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
 | |
|   fi
 | |
|   if [ "$old_ip_address" ]; then
 | |
|     DelINETAddr "$interface" "$old_ip_address" "$old_subnet_mask" "$old_broadcast_address" dhcp
 | |
|     DelDefaultRoutes "$old_routers"
 | |
|     DelStaticRouteList "$old_static_routes"
 | |
|   fi
 | |
|   if [ "$alias_ip_address" ]; then
 | |
|     AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
 | |
|   fi
 | |
|   exit 0
 | |
|   ;;
 | |
| 
 | |
| TIMEOUT)
 | |
|   if [ "$alias_ip_address" ]; then
 | |
|     DelINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
 | |
|   fi
 | |
| # Seems, <null address> means, that no more old leases found.
 | |
| # Or does it mean bug in dhcpcd? 8) Fail for now.
 | |
|   if [ "$new_ip_address" = "<null address>" ]; then
 | |
|     if [ "$old_ip_address" ]; then
 | |
| 	DelINETAddr "$interface" "$old_ip_address" "$old_subnet_mask" "$old_broadcast_address" dhcp
 | |
|     fi
 | |
|     if [ "$alias_ip_address" ]; then
 | |
|         AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
 | |
|     fi
 | |
|     exit 1
 | |
|   fi
 | |
|   if DAD "$interface" "$new_ip_address" ; then
 | |
|     AddINETAddr "$interface" "$new_ip_address" "$new_subnet_mask" "$new_broadcast_address" dhcp
 | |
|     UnsolicitedARP "$interface" "$new_ip_address"
 | |
|     if [ "$alias_ip_address" -a "$alias_ip_address" != "$new_ip_address" ]; then
 | |
|       AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
 | |
|       UnsolicitedARP "$interface" "$alias_ip_address"
 | |
|     fi
 | |
|     if CheckRouterList "$new_routers" ; then
 | |
| 	AddStaticRouteList "$new_static_routes"
 | |
| 	UpdateDNS
 | |
| 	exit 0
 | |
|     fi
 | |
|   fi
 | |
|   DelINETAddr "$interface" "$new_ip_address" "$new_subnet_mask" "$new_broadcast_address" dhcp
 | |
|   DelDefaultRoutes "$old_routers"
 | |
|   DelStaticRouteList "$old_static_routes"
 | |
|   if [ "$alias_ip_address" ]; then
 | |
|     AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
 | |
|   fi
 | |
|   exit 1
 | |
|   ;;
 | |
| esac
 | |
| 
 | |
| exit 0
 |