#!/bin/sh
#------------------------------------------------------------------------
#
# $Sendmail: dynamic,v 8.13.8 2006-12-08 20:21:10 cowboy Exp $
#
# Shell functions to handle dynamic network updates.
# Supports ppp, dhcp, ifup/down, etc.
#
# Copyright (c) 2004-2005 Richard Nelson.  All Rights Reserved.
#
#------------------------------------------------------------------------
#

provider_m4='/etc/mail/m4/provider.m4';
dialup_m4='/etc/mail/m4/dialup.m4';

# Default values
SM_ignore=1;
SM_changed=0;
SM_delay=0;
SM_interface='';
SM_state='down';
SM_provider='';
SM_ip='';
SM_host='';
SM_debug=1;

# Path to other sendmail helpers
if [ -x ./update_sendmail ]; then
	sm_path='.';
elif [ -x $(dirname $0)/update_sendmail ]; then
	sm_path=$(dirname $0);
else
	sm_path=/usr/share/sendmail;
	fi;
# Bring in sendmail.conf for the network definitions
if [ ! -f /etc/mail/sendmail.conf ]; then
	if [ -x $sm_path/update_conf ]; then
		$sm_path/update_conf;
		fi;
	fi;
DAEMON_NETMODE='Static';
DAEMON_NETIF='';
HANDS_OFF='No';
LOG_CMDS='No';
if [ -f /etc/mail/sendmail.conf ]; then
	. /etc/mail/sendmail.conf;
	fi;

# Record information on an interface and its status
update_interface() {
	SM_interface="$1";
	SM_reason="$2";
	# Do absolutely nothing if they say so...
	if [ "$HANDS_OFF" != 'No' ]; then
		return;
		fi;
	if [ -z "$SM_interface" ]; then
		SM_ignore=1;
		return;
		fi;

	# Check to see if we care about this interface
	for if in $DAEMON_NETIF; do
		if [ "$if" = "$SM_interface" ]; then
			SM_ignore=0;
			break;
			fi;
		done;
	
	case "$SM_reason" in
		 DOWN|EXPIRE|FAIL|RELEASE|STOP)	 # and TIMEOUT too ??
			SM_state='down';
			;;
		UP|BOUND|RENEW|REBIND|REBOOT|TIMEOUT)
			SM_state='up';
			if [ "$SM_reason" = "BOUND" ]; then
				SM_changed=1;
				fi;
			;;
		esac;

	# Mark what we're doing...
	local msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host";
	if [ "$LOG_CMDS" != 'No' ]; then
		logger -i -p mail.debug -- "$0 update_interface: $msg";
		fi;
	};

# Record information about the upstream provider
update_provider() {
	SM_provider="$1";
	# Mark what we're doing...
	local msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host";
	if [ "$LOG_CMDS" != 'No' ]; then
		logger -i -p mail.debug -- "$0 update_provider: $msg";
		fi;

	# Do absolutely nothing if they say so...
	if [ "$HANDS_OFF" != 'No' ]; then
		return;
		fi;
	if [ $SM_ignore != 0 ]; then
		return;
		fi;
	# Add smarthost information (if any)...
	# But not if provider.m4 is a link !
	if [ -z "$SM_provider" ]; then
		return;
		fi;
	if [ ! -e "/etc/mail/peers/$SM_provider" ]; then
		SM_provider='default';
		fi;
	if [ -e "/etc/mail/peers/$SM_provider" ] \
	&& [ ! -L "$provider_m4" ]; then
		SM_changed=1;
		cat <<-EOT > "$provider_m4";
			LOCAL_CONFIG
			#------------------------------------------------------------
			#
			# Dynamic provider updates from $0
			#
			# NOTE: the following line *MUST* be in /etc/mail/sendmail.mc
			dnl include(\`/etc/mail/provider.m4')dnl
			# You may also need to include this file in submit.mc !
			#
			# Provider information from /etc/mail/peers/$SM_provider
			EOT
		cat "/etc/mail/peers/$SM_provider" >> "$provider_m4";
		cat <<-EOT >> "$provider_m4";
			#------------------------------------------------------------
			EOT
		fi;
	};

# Record information on an ip/host
update_host() {
	SM_ip="$1";
	# Mark what we're doing...
	local msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host";
	if [ "$LOG_CMDS" != 'No' ]; then
		logger -i -p mail.debug -- "$0 update_host: $msg";
		fi;

	# Do absolutely nothing if they say so...
	if [ "$HANDS_OFF" != 'No' ]; then
		return;
		fi;
	if [ $SM_ignore != 0 ]; then
		return;
		fi;
	if [ -z "$SM_ip" ]; then
		return;
		fi;
	find_host;
	# Add ip related information (if any)...
	# But not if dialup.m4 is a link !
	if [ ! -L "$dialup_m4" ]; then
		SM_changed=1;
		cat <<-EOT > "$dialup_m4";
			LOCAL_CONFIG
			#------------------------------------------------------------
			#
			# Dynamic host/ip updates from $0
			#
			# NOTE: the following line *MUST* be in /etc/mail/sendmail.mc
			dnl include(\`/etc/mail/dialup.m4')dnl
			# This should *NOT* be included in submit.mc !
			#
			# Make sure we accept mail as this ip (for bounces, etc)
			Cw$SM_ip
			EOT
		if [ -n "$SM_host" ]; then
			cat <<-EOT >> "$dialup_m4";
				#
				# Define our true hostname (from our ISP) - becomes \$j
				define(\`confDOMAIN_NAME', \`$SM_host')dnl
				#
				# Make sure we accept mail as this name (for bounces, etc)
				Cw$SM_host
				#
				# Add our hostname to class G for genericstable support
				CG$SM_host
				#------------------------------------------------------------
				EOT
			fi;
		fi;
	};

find_host() {
	# Determine our fqdn from our ISP
	maxloop=30;
	cntr=0;
	SM_host='';
	until (test ! -z "$SM_host"); do
		cntr=`expr $cntr + 1`;
		if [ $cntr -gt $maxloop ]; then
			SM_host='';
			break;
			fi;
		rev=$(host $SM_ip);
		SM_host=$(echo "$rev" | grep '^Name:' | awk '{print $2}');
		if [ -z "$SM_host" ]; then
			test=$(echo "$rev" | egrep -e 'not found:');
			if [ -n "$test" ]; then
				continue;
			else
				SM_host=${rev##*domain name pointer };
				SM_host=${SM_host%.};
				fi;
			fi;
		test=$(echo $SM_host | cut -d ' ' -f 1);
		if [ "$test" = ";;" ]; then
			:;
		elif [ "$test" != "**" ]; then
			break;
			fi;
		sleep 1s;
		done;
	echo "addr=$SM_ip,		 name=$SM_host";
	};

update_sendmail() {
	# Mark what we're doing...
	local msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host";
	if [ "$LOG_CMDS" != 'No' ]; then
		logger -i -p mail.debug -- "$0 update_sendmail: $msg";
		fi;

	# Do absolutely nothing if they say so...
	if [ "$HANDS_OFF" != 'No' ]; then
		return;
		fi;
	if [ $SM_ignore != 0 ]; then	  
		return;
		fi;

	# Check for a delayed restart (for DHCP)
	case "$1" in
		[Dd]*)
			if [ "$SM_state" = 'up' ]; then
				SM_delay=1;
				fi;
			;;
		esac;

	if [ "$SM_state" = 'down' ]; then
		SM_changed=1;
		cat <<-EOT > "$dialup_m4";
			LOCAL_CONFIG
			#------------------------------------------------------------
			#
			# $SM_interface is $SM_state
			#
			# NOTE: the following line *MUST* be in /etc/mail/sendmail.mc
			dnl include(\`/etc/mail/dialup.m4')dnl
			# This should *NOT* be included in submit.mc !
			#
			# sendmail is to only queue messages until connected again
			define(\`confDELIVERY_MODE', \`deferred')dnl
			#
			# Allow the queue to age without carping every four hours
			define(\`confTO_QUEUEWARN',\`1d')dnl
			#
			# Don't keep host status while the network is down
			define(\`confHOST_STATUS_DIRECTORY')dnl
			#------------------------------------------------------------
			EOT
		fi;

	if  [ $SM_changed = 1 ]; then
		# Build a new sendmail.cf from sendmail.mc, including our address.
		make -f /etc/mail/Makefile sendmail.cf;
		make -f /etc/mail/Makefile;

		# Purge any latent host status that might cause us to *NOT* send mail
		if [ "$SM_state" = "up" ]; then
			AM='-Am';
			if [ ! -f /usr/share/sendmail/cf/feature/msp.m4 ]; then
				AM='';
				fi;
			if [ -x /usr/lib/sm.bin/sendmail ]; then
				/usr/lib/sm.bin/sendmail $AM -bH -O Timeout.hoststatus=1s;
				fi;
			fi;

		# reload (but don't start) sendmail as needed
		if [  $SM_delay = 0 ]; then
			if [ -x /etc/init.d/sendmail ]; then
				/etc/init.d/sendmail reload-if-running;  # up, or down
				fi;
			fi;
		fi;

	# Process the sendmail queue 
	# (background so as to not defer other ip-up work)
	# runq &
	};

