#!/bin/sh #------------------------------------------------------------------------ # # $Sendmail: dynamic,v @sm_version@ @sm_date@ @sm_time@ cowboy Exp $ # # Shell functions to handle dynamic network updates. # Supports ppp, dhcp, ifup/down, etc. # # Copyright (c) 2004-@SM_CPYRT@ Richard Nelson. All Rights Reserved. # # This script is called from the following places: # /etc/ppp/ip-down.d/sendmail #\ # /etc/ppp/ip-up.d/sendmail # | These are deprecated # /etc/dhcp3/dhclient-exit-hooks.d/sendmail #/ # /etc/network/if-down.d/sendmail #standard # /etc/network/if-post-down.d/sendmail #standard # /etc/network/if-up.d/sendmail #standard # /etc/resolvconf/update-libc.d/sendmail #More or less useless :( # # The other half of the logic is in /etc/mail/sendmail.conf # # DAEMON_NETMODE="Dynamic"; Keyword SMTP network mode # static: Do not monitor any network interfaces for changes # dynamic: Monitor one or more interfaces for changes # # DAEMON_NETIF="eth0"; string SMTP interface(s) # This parameter defines the network interface(s) that the daemon # will monitor for status changes (via ppp, dhcp, ifup/down hooks). # # NOTES: # 1) Only list more than one interfaces if they only used for fallback, # otherwise the daemon will wind up ping-ponging between interfaces. # 2) Do not use 'lo' unless your daemon only listens on the localhost. # # LOG_CMDS="No"; Binary command logging flag # Will cause syslog entries for many of the sendmail related commands # like runq, mailq, etc - you'll also see cron jobs (if enabled). # # HANDS_OFF="No"; Binary Do *NOT* touch the configuration # Set this *ONLY* if you are going to be fully responsible for the entire # setup of sendmail - the directories, permissions, databases, etc. With # this variable set to "Yes", nothing will be done for you during # updates. # # In other words, "The blood be upon your hands" if you set this... # My ability to help with problems will be greatly reduced ! # # "Well, a pet peeve of mine is people who directly edit the # .cf file instead of using the m4 configuration files. # Don't do it! [laughs] I treat the .cf file as a binary # file - you should too." # -- Eric Allman 1999/10/18 # #------------------------------------------------------------------------ # # The files we may alter provider_m4='@sysconfdir@/mail/m4/provider.m4'; dialup_m4='@sysconfdir@/mail/m4/dialup.m4'; # Default values SM_ignore=0; # Ignore any changes SM_changed=0; # Something has changed, dunno what SM_delay=0; # Expect another call soon, do work then SM_interface=''; # The interface that changed SM_state=''; # How the interface changed SM_provider=''; # ISP/domain name/IPPARM/etc SM_ip=''; # IP for the interface SM_host=''; # Reverse FQDN of IP SM_debug=1; # Of minimal value # Path to other sendmail helpers if [ -x ./update_sendmail ]; then sm_path='.'; elif [ -x $(/usr/bin/dirname $0)/update_sendmail ]; then sm_path=$(/usr/bin/dirname $0); else sm_path=@datadir@/sendmail; fi; # Bring in sendmail.conf for the network definitions if [ ! -f @sysconfdir@/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='Yes'; if [ -f @sysconfdir@/mail/sendmail.conf ]; then . @sysconfdir@/mail/sendmail.conf; fi; # Record information on an interface and its status update_interface() { SM_interface="$1"; SM_reason="$2"; # Translate DHCP style actions to a simple up/down case "$SM_reason" in DOWN|EXPIRE|FAIL|RELEASE|STOP) # and TIMEOUT too ??? SM_state='down'; ;; UP|BOUND|RENEW|REBIND|REBOOT|TIMEOUT) # why TIMEOUT here ??? SM_state='up'; if [ "$SM_reason" = "BOUND" ]; then SM_changed=1; fi; ;; *) SM_state='unknown'; ;; esac; # Mark what we're doing... local msg; msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host"; if [ "$LOG_CMDS" != 'No' ]; then /usr/bin/logger -i -p mail.debug -- "$0 (dynamic) update_interface: $msg"; fi; # Do absolutely nothing if they say so... if [ "$HANDS_OFF" != 'No' -o "$DAEMON_NETMODE" = 'Static' ]; then SM_ignore=1; fi; if [ -z "$SM_interface" ]; then SM_ignore=1; fi; # Check to see if we care about this interface if [ $SM_ignore -eq 0 ]; then SM_ignore=1; for if in $DAEMON_NETIF; do if [ "$if" = "$SM_interface" ]; then SM_ignore=0; break; fi; done; fi; if [ $SM_ignore -ne 0 ]; then return; fi; }; # Record information about the upstream provider update_provider() { SM_provider="$1"; # Mark what we're doing... local msg; msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host"; if [ "$LOG_CMDS" != 'No' ]; then /usr/bin/logger -i -p mail.debug -- "$0 (dynamic) update_provider: $msg"; fi; # Do absolutely nothing if they say so... if [ "$HANDS_OFF" != 'No' -o "$DAEMON_NETMODE" = 'Static' ]; then SM_ignore=1; fi; if [ $SM_ignore -ne 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 "@sysconfdir@/mail/peers/$SM_provider" ]; then SM_provider='default'; fi; if [ -e "@sysconfdir@/mail/peers/$SM_provider" ] \ && [ ! -L "$provider_m4" ]; then SM_changed=1; cat <<-EOT > "$provider_m4"; LOCAL_CONFIG #------------------------------------------------------------ # # Dynamic provider updates from $0: # Device=$SM_interface # State=$SM_state # Provider=$SM_provider # # NOTE: The following line *MUST* be in @sysconfdir@/mail/sendmail.mc #dnl include(\`@sysconfdir@/mail/provider.m4')dnl # # You may also need to include this file in submit.mc ! # # Provider information from @sysconfdir@/mail/peers/$SM_provider EOT cat "@sysconfdir@/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; msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host"; if [ "$LOG_CMDS" != 'No' ]; then /usr/bin/logger -i -p mail.debug -- "$0 (dynamic) update_host: $msg"; fi; # Do absolutely nothing if they say so... if [ "$HANDS_OFF" != 'No' -o "$DAEMON_NETMODE" = 'Static' ]; then SM_ignore=1; fi; if [ $SM_ignore -ne 0 ]; then return; fi; if [ -z "$SM_ip" ]; then return; fi; find_host; if [ $SM_ignore -ne 0 ]; then return; fi; # 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: # Device=$SM_interface # State=$SM_state # Provider=$SM_provider # IP=$SM_ip # Host=$SM_host # # NOTE: The following line *MUST* be in @sysconfdir@/mail/sendmail.mc #dnl include(\`@sysconfdir@/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 [ -z "$SM_host" ]; then cat <<-EOT >> "$dialup_m4"; # # Rats... FQDN lookup failed, your kit is incomplete :( EOT else 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; }; # DNS support changed, we may (or may not) have a new name # but in any case, we may have stale host info in the queue update_resolv() { # Mark what we're doing... local msg; msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host"; if [ "$LOG_CMDS" != 'No' ]; then /usr/bin/logger -i -p mail.debug -- "$0 (dynamic) update_resolv: $msg"; fi; # Do absolutely nothing if they say so... if [ "$HANDS_OFF" != 'No' -o "$DAEMON_NETMODE" = 'Static' ]; then SM_ignore=1; fi; if [ $SM_ignore -ne 0 ]; then return; fi; # Ideally, we should re-check our IP if we didn't find the # FQDN previously - but we need a state file to do that :( # # Hell, we don't even know what IF is, and if it is up or down :( #SM_interface='?'; #\ #SM_state='up'; # \ #SM_provider='?'; # | Need to get these from somewhere ! #SM_ip='?'; # / #SM_host='?'; #/ #find_host; # Purge any latent host status that might cause us to *NOT* send mail if [ -x @sysconfdir@/init.d/sendmail ]; then if [ "$SM_state" = 'up' ]; then @sysconfdir@/init.d/sendmail purgestat now; fi; fi; # resolvconf is called as a DHCP pre-exit, so we'll defer any changes SM_changed=0; } # Attempt to locate our FQDN 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); # continue scanning if we get this: # ;; connection timed out; no servers could be reached if [ "$test" = ";;" ]; then SM_host=''; elif [ "$test" != "**" ]; then break; fi; sleep 1s; done; # See if we actually found a host ! if [ -z "$SM_host" ]; then # Drats, no host name :( # We have a few choices - none pretty # 1) Do not start sendmail # 2) Use the info we have (ip) - but # then we may not accept mail we should, # accept mail we should not, # and our ougoing name may be wrong # 3) Use the last known hostname # If it is not correct, we have the same # exposurs as option 2 ! # # For the nonce, I choose option 2 : fi; if [ $SM_debug -ne 0 ]; then echo "addr=$SM_ip, name=$SM_host"; fi; }; # If our state has changed in any way, update sendmail update_sendmail() { SM_caller="$1"; SM_opts="$2"; # Mark what we're doing... local msg; msg="$SM_interface $SM_state $SM_provider $SM_ip $SM_host"; if [ "$LOG_CMDS" != 'No' ]; then /usr/bin/logger -i -p mail.debug -- "$0 (dynamic) update_sendmail: $msg"; fi; # Do absolutely nothing if they say so... if [ "$HANDS_OFF" != 'No' -o "$DAEMON_NETMODE" = 'Static' ]; then SM_ignore=1; fi; if [ $SM_ignore -ne 0 ]; then return; fi; # Check for a delayed restart (for DHCP/PPP) case "$SM_opts" 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 #------------------------------------------------------------ # Dynamic host/ip updates from $0: # Device=$SM_interface # State=$SM_state # Provider=$SM_provider # IP=$SM_ip # Host=$SM_host # # NOTE: The following line *MUST* be in @sysconfdir@/mail/sendmail.mc #dnl include(\`@sysconfdir@/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 -eq 1 ]; then # Build a new sendmail.cf from sendmail.mc, including our address. /usr/bin/make -f @sysconfdir@/mail/Makefile sendmail.cf; /usr/bin/make -f @sysconfdir@/mail/Makefile; # Purge any latent host status that might cause us to *NOT* send mail # Reload sendmail, IFF already running if [ -x @sysconfdir@/init.d/sendmail ]; then if [ "$SM_state" = 'up' ]; then @sysconfdir@/init.d/sendmail purgestat now; fi; @sysconfdir@/init.d/sendmail reload-if-running & # up, or down fi; fi; # Process the sendmail queue # (background so as to not defer other ip-up work) # This can be fatal on IF ping-pongs :( # runq & };