#!/bin/bash
set -e
#WARNING - add "-e" to the above line before distribution!!!!!!!!!!
#For those who actually read code, welcome.  Please note: there appears to be support for
#accepting "ipchains -L -n -x -v" input.  It sorta works, it generally doesn't.  Until I 
#can get it working as well as I'd like, I'm not going to announce it.  Play with it 
#if you'd like.

cat <<EOTEXT1 >/dev/null
	(The above line allows me to put the documentation right in the
script... Cool, eh?)

>>>>>>>>>>>>>>>If you read nothing else, please read this<<<<<<<<<<<<<<<<

	This program offers an aid to creating firewall rules.  It offers
ABSOLUTELY NO intelligence in deciding what should be allowed or
disallowed.  It has ABSOLUTELY NO ability to understand your security
policy and implement it.  YOU are responsible for reviewing the rules and
massaging them to fit your needs.
	While the documentation in mason.txt attempts to provide some
general guidelines on how to use Mason, please remember:  the author has
no knowledge of what you want your firewall to do and has not tailored the
documentation or program to specially fit your needs.  If there is ever a
discrepancy between your needs and the program output or your needs and
the documentation, the program and/or documentation are _dead_ _wrong_. 


Copyleft:
	Mason interactively creates a Linux packet filtering firewall.
	Copyright (C) 1998, 1999 William Stearns <wstearns@pobox.com>

	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.

	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.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

	The author can also be reached at:
        William Stearns
email:  wstearns@pobox.com				(preferred)
web:    http://www.pobox.com/~wstearns
snail:  544 Winchester Place
        Colchester VT, 05446, USA


	This code is entirely owned by William Stearns
(wstearns@pobox.com) and has no relation to any employer or employer
sponsored project.  

------------------------------ Mason ------------------------------
	The Mason script interactively builds a (fire)wall on a Linux
machine. For more details about how this is done, please see mason.txt,
which gives background, theory of operation, a quick start, and additional
documentation on firewalls and firewall gotchas. 
	mason.txt and related documentation should have been installed to
/usr/doc/mason-{version}/ .  If they are missing or you would like to make
sure you have the latest version, please go to
http://www.pobox.com/~wstearns/mason/ . 
	All configuration of this program is done in the /etc/masonrc
file.  This script should probably not be directly edited.

- Bill Stearns

The EOTEXT line is the end of the text and the start of the code. 
EOTEXT1

CKPTMASON=" mason: Ground0" ; #ckpt $CKPTMASON

MASONDIR=${MASONDIR:-"/var/lib/mason/"}
MASONCONF=${MASONCONF:-"/etc/masonrc"}
MASONLIB=${MASONLIB:-"/var/lib/mason/masonlib"}
if [ -f $MASONLIB ]; then
	. $MASONLIB
else
	echo Missing $MASONLIB library file.  Please get a complete copy of Mason from >/dev/stderr
	echo http://www.pobox.com/~wstearns/mason/ .  Exiting. >/dev/stderr
	exit
fi

trap preexit 0


#-------------------------------------------------------------------------
# Start setting up.
#-------------------------------------------------------------------------
CKPTMASON=" mason: Setup" ; #ckpt $CKPTMASON

LOGCHAINSEXIST="yes"

LAST1="" ; LAST2="" ; LAST3="" ; LAST4="" ; LAST5="" ; LAST6="" ; LAST7="" ; LAST8="" ; CURRENT=""
EXITMASON=${EXITMASON:-"NO"}

trap sigexitscript SIGHUP		#Ctrl-C too?
trap loadconf SIGUSR1


#---------- Start of Main code ----------
CKPTMASON=" mason: Start main" ; #ckpt $CKPTMASON
echo "---- Mason firewall builder for Linux                         ----" >/dev/stderr
echo "---- see http://www.pobox.com/~wstearns/mason/ for more info. ----" >/dev/stderr
echo "---- William Stearns <wstearns@pobox.com>                     ----" >/dev/stderr 
loadconf
checksys
SIGGED="NO"

#NAMECACHE Support has been disabled
##Hmmm... I _hate_ overwriting /etc/passwd...
#if [ -L $NAMECACHE ]; then
#	rm -f $NAMECACHE
#fi
#
##Create the name cache file if it doesn't exist
#if [ ! -e $NAMECACHE ]; then
#	touch $NAMECACHE
#	#This is a security-related program.  I don't want to let people know who we're even talking to.
#	chmod og-rwx $NAMECACHE
#fi

for ONEIF in $DYNIF ; do
	cat <<EOTEXT
$CMNT ${CMNT}export ${ONEIF}ADDR="0/0"		${CMNT}Use this version if you want to match any IP address.
export ${ONEIF}ADDR="\`ifconfig $ONEIF | grep 'inet addr' | awk '{print \$2}' | sed -e 's/.*://'\`$SINGLEMACHSPEC"
EOTEXT
	eval ${ONEIF}ADDR=`ifconfig $ONEIF | grep 'inet addr' | awk '{print $2}' | sed -e 's/.*://'`
done

#ipchains-save is under development; use at your own risk. ;-)
#FIXME - output this header even if we switch to ipchains-save, but only once per mason run.
if [ "$ECHOCOMMAND" = "ipchains-save" ]; then
	for ONECHAIN in input forward output ; do
		echo ':'$ONECHAIN $DEFAULTPOLICY
	done
	if [ -n "$NOLOGSUFFIX" ]; then
		for ONECHAIN in input forward output ; do
			echo ':'$ONECHAIN$NOLOGSUFFIX '-'
		done
	fi
fi

#Get the first log entry
CKPTMASON=" mason: Get log entry" ; #ckpt $CKPTMASON
unset ACK COMMENT CURRCHAIN DEST DESTHOST DESTIP DESTPORT DIR DIRLETTER \
DOACK ECHOACK IF IGNOREPORT ISLOGLINE \
J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 \
      O3 O4 O5 O6 O7 O8 O9 O10 O11 O12 O13 \
      A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 \
LINEHASDYNAMIC LOGTHIS MESSPOL NUMBYTES NUMPACKETS PROTO SRC SRCHOST SRCIP SRCPORT TAIL TOS || true
#unset DFFLAG FFLAG FOFLAG IFLAG LFLAG SFLAG TFLAG || true			#These fields are not used at this time.
if [ -n "$MINMARK" ]; then INCMINMARK="0" ; fi
TOS=""
if ! read J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 ; then
	if [ "$SIGGED" != "YES" ]; then EXITMASON="YES" ; fi
fi

while [ "$SIGGED" = "YES" ]; do
	SIGGED="NO"
	if ! read J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 ; then
		if [ "$SIGGED" != "YES" ]; then EXITMASON="YES" ; fi
	fi
done

CKPTMASON=" mason: post get log entry" ; #ckpt $CKPTMASON

while [ "$EXITMASON" != "YES" ] && [ -n "$J1" ]; do
CKPTMASON=" mason: In main loop" ; #ckpt $CKPTMASON
#Only do the work if the line is a firewalling log entry.
	if [ "$J6 $J7" = "Packet log:" ]; then		#Load variables from ipchains log entry
		INFORMAT="ipchains-log"
		case $J8 in
		output)		DIR='output ' ;	DIRLETTER='O'				;;
		input)		DIR='input  ' ;	DIRLETTER='I'				;;
		forward)	DIR='forward' ;	DIRLETTER='F'				;;
		*)	echo Unknown direction $J8 >/dev/stderr				;;
		esac
		IF="$J10"
		protonum2name "${J11##PROTO=}"
		SRC="$J12" ; DEST="$J13"
		SRCPORT=${SRC##*:}
		DESTPORT=${DEST##*:}
		SRCIP=${SRC%%:*}
		DESTIP=${DEST%%:*}
		#Even if there were a way to extract a mark value from the log line, it wouldn't seem correct to use it.
		#MESSPOL="$J9" ; LFLAG="$J14" ; SFLAG="$J15" ; IFLAG="$J16" ; FFLAG="$J17" ; TFLAG="$J18"		#Unused
		ISLOGLINE="YES"
	elif [ "$J5 $J6" = "kernel: IP" ]; then	#Load variables from ipfwadm log entry
		INFORMAT="ipfwadm-log"
		case $J7 in				#Formerly [ "`echo $J7 | cut -b 1-3`" = "fw-" ]
		fw-out|fw-in|fw-fwd)
			case $J7 in
			fw-out)	DIR='output ' ;	DIRLETTER='O'					;;
			fw-in)	DIR='input  ' ;	DIRLETTER='I'					;;
			fw-fwd)	DIR='forward' ;	DIRLETTER='F'					;;
			*)	echo Unknown direction $J7 >/dev/stderr				;;
			esac
			IF="$J9"
			PROTO=`echo $J10 | tr A-Z a-z`
			SRC="$J11" ; DEST="$J12"
			SRCIP=${SRC%%:*}
			DESTIP=${DEST%%:*}
			#MESSPOL="$J8" ; LFLAG="$J13" ; SFLAG="$J14" ; IFLAG="$J15" ; FOFLAG="$J16" ; TFLAG="$J17" ; DFFLAG="$J18"		#Unused
#Break up ipfwadmin's habit of gluing the icmp port onto the protocol.
			if [ "${PROTO%%/*}" = "icmp" ]; then
				SRCPORT=${PROTO##*/}
				PROTO="icmp"
				DESTPORT=""
				if [ "$DEBUG" = "YES" ]; then echo proto= $PROTO srcport= $SRCPORT destport= $DESTPORT >/dev/stderr ; fi
			else
				SRCPORT=${SRC##*:}
				DESTPORT=${DEST##*:}
			fi
			ISLOGLINE="YES"
																;;
		esac
	elif [ "$J1" = "Chain" ]; then	#Load variables from ipchains -Lv listing; this is a header line.
		CURRCHAIN=$J2
		INFORMAT="ipchains-lv"
	elif [ "$J6" = "0xFF" ] || [ "$J6" = "0x01" ]; then	#Load variables from ipchains -Lv listing; this is a data line.
		case $J7 in
		0x*)
			ISLOGLINE="YES"
			INFORMAT="ipchains-lv"
			case $CURRCHAIN in
			output)		DIR='output' ;		DIRLETTER='O'							;;
			input)		DIR='input' ;		DIRLETTER='I'							;;
			forward)	DIR='forward' ;		DIRLETTER='F'							;;
			"")		echo No chain name has been registered.  Mason cannot process this entry. >/dev/stderr ; ISLOGLINE=""	;;
			*)			DIR="$CURRCHAIN" ;	DIRLETTER='Q'
						if [ -z "$OTHERCHAINWARNISSUED" ]; then
							case "$ECHOCOMMAND" in
							ipchains|ipchains-lv)	:									;;
							*)
								echo "$CMNT Any following rules with a direction of \"Q\" need to be edited.  They"
								echo "$CMNT came from an ipchains rule other than input, output, or forward."
								OTHERCHAINWARNISSUED="YES"
																						;;
							esac
						fi
																					;;
			esac
			case $J5 in
#FIXME - formalize this parsing.  double check these, check other flag fields.
			-y*)	ACK="! -k"										;;
			!y*)	ACK="-k"										;;
			*l-)	LOGTHIS="-l"									;;
			--*)	ACK=""											;;
			esac
			MESSPOL=$J3
			if [ "$J8" = "*" ]; then	IF="" ; else	IF="$J8" ; fi
			if [ "$J4" = "all" ]; then	PROTO="" ; else	PROTO=$J4 ; fi
			if [ "$J6 $J7" != "0xFF 0x00" ]; then TOS=" -t $J6 $J7" ; else TOS="" ; fi
#FIXME - handle case of existing or missing mark and outsize fields
			#SRC="$J11" ; DEST="$J12"	#SRC and DEST are only temporary variables for ipfwadm and ipchains formats to split into SRCIP and SRCPORT in a mo.
			case $J9 in
			*/*)	SRCIP="$J9"		;;
			*)		SRCIP="$J9/32"	;;
			esac
			case $J10 in
			*/*)	DESTIP="$J10"		;;
			*)		DESTIP="$J10/32"	;;
			esac
			NUMPACKETS=$J1 ; NUMBYTES=$J2
			#LFLAG="$J13" ; SFLAG="$J14" ; IFLAG="$J15" ; FOFLAG="$J16" ; TFLAG="$J17" ; DFFLAG="$J18"		#Unused

			case $J11 in
			n/a)	SRCPORT=""																				;;
			'*')	SRCPORT=""																				;;
			*:*)	if [ "${J11%%:*}" = "${J11##*:}" ]; then SRCPORT=${J11%%:*} ; else SRCPORT=$J11 ; fi	;;
			*)		SRCPORT=$J11																			;;
			esac
			case $J13 in
			'*')	DESTPORT=""																				;;
			*:*)	if [ "${J13%%:*}" = "${J13##*:}" ]; then DESTPORT=${J13%%:*} ; else DESTPORT=$J13 ; fi	;;
			*)		DESTPORT=$J13																			;;
			esac
																;;
		esac
	fi
	#echo SRC-DEST:X $SRCIP X $DESTIP X

	if [ "$INFORMAT" = "ipchains-lv" ] && [ "$DOCOMMAND" = "ipchains" ]; then	#We actually use the policy in each line in ipchains-lv entries
		case "$MESSPOL" in
		accept|ACCEPT)	LCPOLICY="accept" ;	UCPOLICY="ACCEPT"	;;
		reject|REJECT)	LCPOLICY="reject" ;	UCPOLICY="REJECT"	;;
		deny|DENY)		LCPOLICY="deny" ;	UCPOLICY="DENY"		;;
		"-")			LCPOLICY="" ;		UCPOLICY=""			;;
		*)				LCPOLICY=$MESSPOL ; UCPOLICY=$MESSPOL	;;
		esac
	elif [ "$INFORMAT" = "ipchains-lv" ]; then	#We actually use the policy in each line in ipchains-lv entries
		case "$MESSPOL" in
		accept|ACCEPT)	LCPOLICY="accept" ;	UCPOLICY="ACCEPT"	;;
		reject|REJECT)	LCPOLICY="reject" ;	UCPOLICY="REJECT"	;;
		deny|DENY)		LCPOLICY="deny" ;	UCPOLICY="DENY"		;;
		"-")	#FIXME - technically these should be accounting rules for I and O, a warning for F.
			case "$NEWRULEPOLICY" in
			a*|A*)		LCPOLICY="accept" ; UCPOLICY="ACCEPT"	;;
			r*|R*)		LCPOLICY="reject" ; UCPOLICY="REJECT"	;;
			d*|D*)		LCPOLICY="deny"   ; UCPOLICY="DENY"		;;
			esac
																;;
		*)				LCPOLICY=$MESSPOL ; UCPOLICY=$MESSPOL	;;
		esac
	else
		case "$NEWRULEPOLICY" in
		a*|A*)			LCPOLICY="accept" ; UCPOLICY="ACCEPT"	;;
		r*|R*)			LCPOLICY="reject" ; UCPOLICY="REJECT"	;;
		d*|D*)			LCPOLICY="deny"   ; UCPOLICY="DENY"		;;
		esac
	fi

	CKPTMASON=" mason: Process line" ; #ckpt $CKPTMASON
	if [ "$ISLOGLINE" = "YES" ]; then
#Handle AUTOMASQ feature.  Masquerade packets forwarded to requested interfaces if source 
#address is a reserved (rfc1918) address.
		if [ "$DIRLETTER" = "F" ] && [ -n "$AUTOMASQIF" ] && [ "$LCPOLICY" = "accept" ] && reservedip $SRCIP ; then
			for ANIF in $AUTOMASQIF ; do
				if [ "$ANIF" = "$IF" ]; then
					UCPOLICY="MASQ"				#For ipchains 
					LCPOLICY="accept -m"		#For ipfwadm
				fi
			done
		fi #If forwarding and automasq requested.

#Quickly put in a completely specific rule for this packet to stop the flow - it will be deleted later
		#in masonlib: LCPOLICY, UCPOLICY
		#from above: IF, DIR, DIRLETTER, PROTO, SRCIP, SRCPORT, DESTIP, DESTPORT
		#not set? ACK, SRCHOST, DESTHOST, TOS, DOACK
		UNDOSPECIFICRULE=""
		if [ "$DOCOMMAND" = "ipfwadm" ]; then
			/sbin/ipfwadm -i $LCPOLICY ${IF:+"-W"} $IF -$DIRLETTER ${PROTO:+"-P"} $PROTO -S $SRCIP $SRCPORT -D $DESTIP $DESTPORT
			UNDOSPECIFICRULE="/sbin/ipfwadm -d $LCPOLICY ${IF:+"-W"} $IF -$DIRLETTER ${PROTO:+"-P"} $PROTO -S $SRCIP $SRCPORT -D $DESTIP $DESTPORT"
		elif [ "$DOCOMMAND" = "ipchains" ]; then
			case $DIRLETTER in
			I)		DODIR="input$NOLOGSUFFIX"					;;
			O)		DODIR="output$NOLOGSUFFIX"					;;
			F)		DODIR="forward$NOLOGSUFFIX"					;;
			esac
			CKPTMASON=" mason: pre specific rule" ; #ckpt $CKPTMASON
			#ckpt CHAIN -I $DODIR 1 ${IF:+"-i "}$IF ${PROTO:+"-p "}$PROTO -s $SRCIP $SRCPORT -d $DESTIP $DESTPORT ${UCPOLICY:+"-j"} $UCPOLICY
			/sbin/ipchains -I $DODIR 1 ${IF:+"-i"} $IF ${PROTO:+"-p"} $PROTO -s $SRCIP $SRCPORT -d $DESTIP $DESTPORT ${UCPOLICY:+"-j"} $UCPOLICY
			CKPTMASON=" mason: post specific rule" ; #ckpt $CKPTMASON
			UNDOSPECIFICRULE="/sbin/ipchains -D $DODIR ${IF:+"-i"} $IF ${PROTO:+"-p"} $PROTO -s $SRCIP $SRCPORT -d $DESTIP $DESTPORT ${UCPOLICY:+"-j"} $UCPOLICY"
			unset DODIR || true
		fi # no need to handle DOCOMMAND=none :-)

#Put the dynamic IP addresses in the current environment.
#FIXME - do we need to do this every time?
		for ONEIF in $DYNIF ; do
			eval ${ONEIF}ADDR=$(eval echo \${$(eval echo ${ONEIF}ADDR)})	#No, really.  That's the IP address.
		done

		CKPTMASON=" mason: gen ip" ; #ckpt $CKPTMASON
		if [ "$INFORMAT" = "ipchains-lv" ]; then
			SRCHOST=$SRCIP
			DESTHOST=$DESTIP
		elif [ "$IGNOREPORT" = "YES" ]; then		#For non tcp/udp/icmp protocols (w/o port numbers), restrict to machine to machine
			HOLDIPCONV="$IPCONV"	#Convert to hostname, but honor Dynamic IP macros.  Temporarily set IPCONV to HOST to do this.
			IPCONV="HOST"
			SRCHOST=`generalizeip $SRCIP`
			DESTHOST=`generalizeip $DESTIP`
			IPCONV="$HOLDIPCONV"
		else
#If this is a DNS request and the server is one of those listed in /etc/resolv.conf, don't generalize the ip address.
#Also, don't generalize if this is one of the Sparse Server or Sparse Client protocols.

			HOLDIPCONV="$IPCONV" ; HOLDHOSTLOOKUP="$HOSTLOOKUP"
			if [ "$SRCPORT" = "53" ] && ( [ "$PROTO" = "udp" ] || [ "$PROTO" = "tcp" ] ) ; then
				for ONEDNSSERVER in $DNSSERVERS ; do
					if [ "$SRCIP" = "$ONEDNSSERVER" ]; then 
						if [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi
						if [ "$HOSTLOOKUP" = "FULL" ]; then HOSTLOOKUP="FILESONLY" ; fi
					fi
				done
			fi
			for ONESPARSE in $SSP ; do
				if [ "$SRCPORT/$PROTO" = "$ONESPARSE" ] && [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi
			done
			for ONESPARSE in $SCP ; do
				if [ "$DESTPORT/$PROTO" = "$ONESPARSE" ] && [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi
			done
			SRCHOST=`generalizeip $SRCIP`
			IPCONV="$HOLDIPCONV" ; HOSTLOOKUP="$HOLDHOSTLOOKUP"

			HOLDIPCONV="$IPCONV" ; HOLDHOSTLOOKUP="$HOSTLOOKUP"
			if [ "$DESTPORT" = "53" ] && ( [ "$PROTO" = "udp" ] || [ "$PROTO" = "tcp" ] ) ; then
				for ONEDNSSERVER in $DNSSERVERS ; do
					if [ "$DESTIP" = "$ONEDNSSERVER" ]; then
						if [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi
						if [ "$HOSTLOOKUP" = "FULL" ]; then HOSTLOOKUP="FILESONLY" ; fi
					fi
				done
			fi
			for ONESPARSE in $SSP ; do
				if [ "$DESTPORT/$PROTO" = "$ONESPARSE" ] && [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi
			done
			for ONESPARSE in $SCP ; do
				if [ "$SRCPORT/$PROTO" = "$ONESPARSE" ] && [ "$IPCONV" = "NETWORK" ]; then IPCONV="HOST" ; fi
			done
			DESTHOST=`generalizeip $DESTIP`
			IPCONV="$HOLDIPCONV" ; HOSTLOOKUP="$HOLDHOSTLOOKUP"
		fi


#Clean up protocol type and number fields, visualize source and dest port fields, set ack flag.
#If port not in /etc/services and >=1024, generalize to "high port"
		CKPTMASON=" mason: port range and comment" ; #ckpt $CKPTMASON
		COMMENT2="" ;	COMMENT="$CMNT" ; SRCCISCOPORTSPEC="" ; DESTCISCOPORTSPEC=""
		
		if [ "$PROTO" = "tcp" ] || [ "$PROTO" = "udp" ]; then
			if [ -n "$SRCPORT" ]; then
				serverportrange "$SRCPORT" "$PROTO"
				if [ "$INFORMAT" = "ipchains-lv" ]; then SRCSERVICE="$SRCPORT" ; else SRCSERVICE="$READABLEPORT" ; fi
				SRCCOMMENT="$PARTIALCOMMENT"
			fi

			if [ -n "$DESTPORT" ]; then
				serverportrange "$DESTPORT" "$PROTO"
				if [ "$INFORMAT" = "ipchains-lv" ]; then DESTSERVICE="$DESTPORT" ; else DESTSERVICE="$READABLEPORT" ; fi
				DESTCOMMENT="$PARTIALCOMMENT"
			fi
			CKPTMASON=" mason: src $SRCSERVICE $SRCCOMMENT dest $DESTSERVICE $DESTCOMMENT" ; #ckpt $CKPTMASON

			if [ "$INFORMAT" != "ipchains-lv" ]; then 
				if [ -n "$SRCSERVICE" ] && [ -z "$DESTSERVICE" ] && [ "$PROTO" = "tcp" ] && [ "$INFORMAT" != "ipchains-lv" ]; then
					#The ack flag should be set if port=tcp and source port is a server service.
					#The one tcpdump I've seen of an ftp connection seems to indicate that the 
					#ftp-data connection is from the _server_ to the client - backwards.
					#Passive mode FTP is supposed to reverse this.  Ugh.  And again, I say, Ugh.
#FIXME - use the SYN / PENANCE flag Rusty's putting into later 2.2's.  Thanks, Rusty!
					if [ "$SRCPORT/$PROTO" != "20/tcp" ]; then
						ACK="-k"
						#If we're in this section we already know PROTO=tcp
						if [ "$GENERALIZETCPACK" = "YES" ] && [ "$UCPOLICY" = "ACCEPT" ] && isdigits "$SRCPORT"; then
							if [ $SRCPORT -ge 0 ] && [ $SRCPORT -le 1023 ]; then
								SRCSERVICE="0:1023"
							elif [ $SRCPORT -ge "$PORT_MASQ_BEGIN" ] && [ $SRCPORT -le "$PORT_MASQ_END" ]; then
								SRCSERVICE="$PORT_MASQ_BEGIN:$PORT_MASQ_END"
							elif [ $SRCPORT -ge "1024" ] && [ $SRCPORT -le "65535" ]; then
								SRCSERVICE="1024:65535"
							fi
							SRCCOMMENT="GENERALIZED TCP RESPONSE - place last"
						fi
						if [ "$GENERALIZETCPACK" = "YES" ] && [ "$UCPOLICY" = "MASQ" ] && isdigits "$SRCPORT"; then
							if [ $SRCPORT -ge 0 ] && [ $SRCPORT -le 1023 ]; then
								SRCSERVICE="0:1023"
							elif [ $SRCPORT -ge "$PORT_MASQ_BEGIN" ] && [ $SRCPORT -le "$PORT_MASQ_END" ]; then
								SRCSERVICE="$PORT_MASQ_BEGIN:$PORT_MASQ_END"
							elif [ $SRCPORT -ge "1024" ] && [ $SRCPORT -le "65535" ]; then
								SRCSERVICE="1024:65535"
							fi
							SRCCOMMENT="GENERALIZED TCP RESPONSE - place last"
						fi
						if [ "$GENERALIZETCPACK" = "YES" ] && [ "$UCPOLICY" = "ACCEPT" ] && isdigits "$DESTPORT"; then
							if [ $DESTPORT -ge 0 ] && [ $DESTPORT -le 1023 ]; then
								DESTSERVICE="0:1023"
							elif [ $DESTPORT -ge "$PORT_MASQ_BEGIN" ] && [ $DESTPORT -le "$PORT_MASQ_END" ]; then
								DESTSERVICE="$PORT_MASQ_BEGIN:$PORT_MASQ_END"
							elif [ $DESTPORT -ge "1024" ] && [ $DESTPORT -le "65535" ]; then
								DESTSERVICE="1024:65535"
							fi
							DESTCOMMENT="GENERALIZED TCP RESPONSE - place last"
						fi
						if [ "$GENERALIZETCPACK" = "YES" ] && [ "$UCPOLICY" = "MASQ" ] && isdigits "$DESTPORT"; then
							if [ $DESTPORT -ge 0 ] && [ $DESTPORT -le 1023 ]; then
								DESTSERVICE="0:1023"
							elif [ $DESTPORT -ge "$PORT_MASQ_BEGIN" ] && [ $DESTPORT -le "$PORT_MASQ_END" ]; then
								DESTSERVICE="$PORT_MASQ_BEGIN:$PORT_MASQ_END"
							elif [ $DESTPORT -ge "1024" ] && [ $DESTPORT -le "65535" ]; then
								DESTSERVICE="1024:65535"
							fi
							DESTCOMMENT="GENERALIZED TCP RESPONSE - place last"
						fi
					fi

				fi
				CKPTMASON=" mason: port and service sservice $SRCSERVICE dservice $DESTSERVICE" ; #ckpt $CKPTMASON
				if [ -n "$SRCSERVICE" ] && [ -n "$DESTSERVICE" ]; then		# Both source and destination ports are servers.  Rare, but possible.
					SRCPORT=$SRCSERVICE
					DESTPORT=$DESTSERVICE
				elif [ -n "$SRCSERVICE" ]; then								# Source port is a server port.
					DESTPORT=`clientportrange "$DESTPORT" "$SRCPORT" "$PROTO" "$ACK"`
					settos "$SRCPORT" "$SRCSERVICE" "$PROTO"
					SRCPORT=$SRCSERVICE
				elif [ -n "$DESTSERVICE" ]; then							# Dest port is a server port.
					SRCPORT=`clientportrange "$SRCPORT" "$DESTPORT" "$PROTO" "$ACK"`
					settos "$DESTPORT" "$DESTSERVICE" "$PROTO"
					DESTPORT=$DESTSERVICE
				else														# Neither source nor dest is a server port.
					#COMMENT2="$CMNT$CMNT S=`nameof $SRCIP`:$SRCPORT D=`nameof $DESTIP`:$DESTPORT"
#FIXME - put in case to test for null, */0, otherwise display
					COMMENT2="$CMNT$CMNT"
					if [ -n "$SRCIP" ]; then	COMMENT2="$COMMENT2 S=`nameof $SRCIP`" ; 	fi
					if [ -n "$SRCPORT" ]; then	COMMENT2="$COMMENT2:$SRCPORT" ;				fi
					if [ -n "$DESTIP" ]; then	COMMENT2="$COMMENT2 D=`nameof $DESTIP`" ;	fi
					if [ -n "$DESTPORT" ]; then	COMMENT2="$COMMENT2:$DESTPORT" ;			fi
					ORIGSRCPORT=$SRCPORT
					SRCPORT=`clientportrange "$SRCPORT" "$DESTPORT" "$PROTO" "$ACK"`
					DESTPORT=`clientportrange "$DESTPORT" "$ORIGSRCPORT" "$PROTO" "$ACK"`
					unset ORIGSRCPORT
					#if [ "$INFORMAT" != "ipchains-lv" ]; then TOS=" -t 0x01 0x08" ; fi		#Maximize throughput on the assumption that this is FTP data or irc dcc?

					#If we have a high port to high port connection (darn ftp and irc dcc), do _not_ generalize to anywhere
					if [ "$SRCPORT" = "1024:65535" ] && [ "$DESTPORT" = "1024:65535" ]; then
						if [ "$SRCHOST" = "0/0" ]; then
							HOLDIPCONV="$IPCONV" ; IPCONV="HOST" ; SRCHOST=`generalizeip $SRCIP` ; IPCONV="$HOLDIPCONV"
						fi
						if [ "$DESTHOST" = "0/0" ]; then
							HOLDIPCONV="$IPCONV" ; IPCONV="HOST" ; DESTHOST=`generalizeip $DESTIP` ; IPCONV="$HOLDIPCONV"
						fi
					fi
				fi
				if [ -n "$SRCCOMMENT" ]; then COMMENT="$COMMENT $SRCCOMMENT" ; fi
				if [ -n "$DESTCOMMENT" ]; then
					if [ "$SRCCOMMENT" != "$DESTCOMMENT" ]; then COMMENT="$COMMENT $DESTCOMMENT" ; fi
				fi
				COMMENT="$COMMENT ($DIRLETTER)"
				SRCCISCOPORTSPEC="`port2ciscoport $SRCPORT $PROTO`"
				DESTCISCOPORTSPEC="`port2ciscoport $DESTPORT $PROTO`"
			fi
		elif [ "$PROTO" = "icmp" ]; then	#Handle ICMP comments
			convicmpcode $SRCPORT $DESTPORT
			if [ -n "$DESTPORT" ]; then		#FIXME - maybe someday we'll do the cisco conversions to names too.
				DESTCISCOPORTSPEC=" $SRCPORT $DESTPORT"
			else
				DESTCISCOPORTSPEC=" $SRCPORT"
			fi
		else	#Handle non tcp/udp/icmp protocols
			COMMENT="$CMNT $PROTO ($DIRLETTER)"
			#COMMENT2="$CMNT$CMNT S=`nameof $SRCIP` D=`nameof $DESTIP`"
			COMMENT2="$CMNT$CMNT"
#FIXME - put in case to test for null, */0, otherwise display
			if [ -n "$SRCIP" ]; then	COMMENT2="$COMMENT2 S=`nameof $SRCIP`" ; 	fi
			if [ -n "$DESTIP" ]; then	COMMENT2="$COMMENT2 D=`nameof $DESTIP`" ; 	fi
		fi
		if [ -n "$NUMPACKETS" ]; then	COMMENT2="$COMMENT2 ^ $NUMPACKETS" ; fi
		if [ -n "$NUMBYTES" ]; then		COMMENT2="$COMMENT2 @ $NUMBYTES" ; fi

		#if [ "$LINEHASDYNAMIC" = "YES" ]; then COMMENT="$COMMENT DynamicIP" ; fi
		#LINEHASDYNAMIC is not exported because generalizeip is a function.  Not used.

		CKPTMASON=" mason: var debug" ; #ckpt $CKPTMASON
		if [ "$DEBUG" = "YES" ]; then
			echo J1=$J1 J2=$J2 J3=$J3 J4=$J4 J5=$J5 J6=$J6 J7=$J7 J8=$J8 >/dev/stderr 
			echo J9=$J9 J10=$J10 J11=$J11 J12=$J12 J13=$J13 J14=$J14 J15=$J15 J16=$J16 >/dev/stderr
			echo J17=$J17 J18=$J18 J19=$J19 DIR=$DIR DIRLETTER=$DIRLETTER >/dev/stderr
			echo MESSPOL=$MESSPOL IF=$IF PROTO=$PROTO SRC=$SRC DEST=$DEST LFLAG=$LFLAG >/dev/stderr
			echo SFLAG=$SFLAG IFLAG=$IFLAG FOFLAG=$FOFLAG FFLAG=$FFLAG TFLAG=$TFLAG DFFLAG=$DFFLAG TAIL=$TAIL >/dev/stderr
			echo Unused: DFFLAG, FFLAG, FOFLAG, IFLAG, LFLAG, MESSPOL, SFLAG, TFLAG >/dev/stderr
		fi


#Actually create and implement the firewall command to display.
		CKPTMASON=" mason: Display" ; #ckpt $CKPTMASON
		DODISPLAY="YES"
		if [ "$IGNOREPORT" = "YES" ]; then SRCPORT="" ; DESTPORT="" ; fi
		case "$ECHOCOMMAND" in
		#CURRENT=`awk "BEGIN {printf \"%x %0.0s %-12s %s x \n\", 57005, \"$AA$BB\", \"aaa\", \"cheeky\"}"`
		ipchains)
			CKPTMASON=" mason: ipchains display" ; #ckpt $CKPTMASON
			case "$ACK" in
			""|"  ")	ECHOACK=""									;;
			"-k")		ECHOACK="! -y"								;;
			"! -k")		ECHOACK="-y"								;;
			esac
			if [ -n "$LOGTHIS" ]; then LOGTHIS="-l" ; fi
#Handle 0/0 host spec or missing port spec - thanks, Rusty!
			case $SRCHOST in
			*/0|*/0.0.0.0)	if [ -n "$SRCPORT" ]; then SRCSPEC="--sport $SRCPORT " ;		else SRCSPEC="" ; fi					;;
			*)				if [ -n "$SRCPORT" ]; then SRCSPEC="-s $SRCHOST $SRCPORT " ;	else SRCSPEC="-s $SRCHOST " ; fi		;;
			esac
			case $DESTHOST in
			*/0|*/0.0.0.0)	if [ -n "$DESTPORT" ]; then DESTSPEC="--dport $DESTPORT" ;		else DESTSPEC="" ; fi				;;
			*)				if [ -n "$DESTPORT" ]; then DESTSPEC="-d $DESTHOST $DESTPORT" ;	else DESTSPEC="-d $DESTHOST" ; fi	;;	
			esac
			#CURRENT="/sbin/ipchains -A $DIR ${IF:+"-i "}$IF ${PROTO:+"-p "}$PROTO $ECHOACK $SRCSPEC$DESTSPEC$TOS ${UCPOLICY:+"-j"} $UCPOLICY $LOGTHIS" #TOS is either blank or has a leading space
#FIXME - dont pad variables any more.     -------------15----12----9----12---5---83 = 136
			CKPTMASON=" mason: ipchains display - awk" ; #ckpt $CKPTMASON
			CURRENT=`awk "BEGIN {printf \"/sbin/ipchains %-11s %-8s %-11s %4s %-83s\", \
					\"${DIR:+"-A "}$DIR\", \
					\"${IF:+"-i "}$IF\", \
					\"${PROTO:+"-p "}$PROTO\", \
					\"$ECHOACK\", \
					\"$SRCSPEC$DESTSPEC$TOS${MINMARK:+" -m "}$MINMARK${UCPOLICY:+" -j "}$UCPOLICY${LOGTHIS:+" "}$LOGTHIS\" \
					}"`
			if [ -n "$MINMARK" ]; then INCMINMARK="1" ; fi
																				;;
		ipchains-save)		#Currently experimental
			CKPTMASON=" mason: ipchains-save display" ; #ckpt $CKPTMASON
			case "$ACK" in
			"  ")		ECHOACK=""									;;
			"-k")		ECHOACK="! -y"								;;
			"! -k")		ECHOACK="-y"								;;
			esac
			if [ -n "$LOGTHIS" ]; then LOGTHIS="-l" ; fi
			case $SRCHOST in
			*/0|*/0.0.0.0)	SRCSPEC=" -s 0.0.0.0/0.0.0.0"											;;
			*)				SRCSPEC=" -s ${SRCHOST%%/*}/`bits2mask ${SRCHOST##*/}`"					;;
			esac
			case "$SRCPORT" in		#serverportrange should have returned a numeric port for ipchains-save
			"")				SRCSPEC="$SRCSPEC 0:65535"												;;
			*:*)			SRCSPEC="$SRCSPEC $SRCPORT"												;;
			*)				SRCSPEC="$SRCSPEC $SRCPORT:$SRCPORT"									;;
			esac
			case $DESTHOST in
			*/0|*/0.0.0.0)	DESTSPEC=" -d 0.0.0.0/0.0.0.0"											;;
			*)				DESTSPEC=" -d ${DESTHOST%%/*}/`bits2mask ${DESTHOST##*/}`"				;;
			esac
			case "$DESTPORT" in
			"")				DESTSPEC="$DESTSPEC 0:65535"											;;
			*:*)			DESTSPEC="$DESTSPEC $DESTPORT"											;;
			*)				DESTSPEC="$DESTSPEC $DESTPORT:$DESTPORT"								;;
			esac
			PROTONUMBER=`grep -i "^$PROTO[[:space:]]" /etc/protocols | awk '{print $2}'`	#Head -1?
			if [ -z "$PROTONUMBER" ]; then
				#CURRENT="-A $DIR $SRCSPEC $DESTSPEC ${IF:+"-i "}$IF ${PROTO:+"-p "}$PROTO $TOS ${UCPOLICY:+"-j "}$UCPOLICY $LOGTHIS $ECHOACK ${MINMARK:+"-m"} $MINMARK" #TOS is either blank or has a leading space
				CURRENT=`awk "BEGIN {printf \"%-111s\", \
						\"${DIR:+"-A "}$DIR$SRCSPEC$DESTSPEC${IF:+" -i "}$IF${PROTO:+" -p "}$PROTO$TOS${UCPOLICY:+" -j "}$UCPOLICY${LOGTHIS:+" "}$LOGTHIS${ECHOACK:+" "}$ECHOACK${MINMARK:+" -m "}$MINMARK\" }"`
			else
				#CURRENT="-A $DIR $SRCSPEC $DESTSPEC ${IF:+"-i "}$IF ${PROTONUMBER:+"-p "}$PROTONUMBER $TOS ${UCPOLICY:+"-j "}$UCPOLICY $LOGTHIS $ECHOACK ${MINMARK:+"-m"} $MINMARK" #TOS is either blank or has a leading space
				CURRENT=`awk "BEGIN {printf \"%-111s\", \
						\"${DIR:+"-A "}$DIR$SRCSPEC$DESTSPEC${IF:+" -i "}$IF${PROTONUMBER:+" -p "}$PROTONUMBER$TOS${UCPOLICY:+" -j "}$UCPOLICY${LOGTHIS:+" "}$LOGTHIS${ECHOACK:+" "}$ECHOACK${MINMARK:+" -m "}$MINMARK\" }"`
			fi
																				;;
		ipfwadm)
			CKPTMASON=" mason: ipfwadm display" ; #ckpt $CKPTMASON
			if [ -n "$LOGTHIS" ]; then LOGTHIS="-o" ; fi
			#CURRENT="/sbin/ipfwadm -a $LCPOLICY ${IF:+"-W "}$IF ${DIRLETTER:+"-"}$DIRLETTER ${PROTO:+"-P "}$PROTO $ACK -S $SRCHOST $SRCPORT -D $DESTHOST $DESTPORT$TOS $LOGTHIS"
			CURRENT=`awk "BEGIN {printf \"/sbin/ipfwadm  %-9s %-8s %-2s %-11s %4s %-72s\", \
					\"${LCPOLICY:+"-a "}$LCPOLICY\", \
					\"${IF:+"-W "}$IF\", \
					\"${DIRLETTER:+"-"}$DIRLETTER\", \
					\"${PROTO:+"-P "}$PROTO\", \
					\"$ACK\", \
					\"-S $SRCHOST $SRCPORT -D $DESTHOST $DESTPORT$TOS $LOGTHIS\" \
					}"`
																				;;
		cisco)
#FIXME handle comments to user for $IF, $DIRLETTER, fix "eq", TOS format? no forwarding rules (maybe in baserules?)
#FIXME - is this screwing up the DOCOMMAND=ipchains parameters?
			CKPTMASON=" mason: cico display" ; #ckpt $CKPTMASON
			if [ "$DIRLETTER" = "F" ]; then
				DODISPLAY="NO" ; echo "Forwarding rule skipped in cisco mode" >/dev/stderr
			elif [ "$IF" = "lo" ]; then
				DODISPLAY="NO" ; echo "Loopback interface skipped in cisco mode" >/dev/stderr
			else
				case "$LCPOLICY" in
				"reject"|"deny  "|"deny")						CISCOPOLICY="deny"		;;
				"accept"|"accept -m")							CISCOPOLICY="permit"	;;	#Cisco Masq? sorry, do not know how.
				*)												CISCOPOLICY="unknown"	;;
				esac
				case "$ACK" in
				"  ")		ECHOACK=""									;;
				"-k")		ECHOACK="established"						;;
				"! -k")		ECHOACK=""									;;
				esac
				if [ -n "$LOGTHIS" ]; then LOGTHIS="log" ; fi
				if [ -n "$TOS" ]; then CISCOTOS=" tos$TOS" ; else CISCOTOS="" ; fi
				case $IF in
				eth0)		CISCOIF="E0"	;;
				eth1)		CISCOIF="E1"	;;
				eth2)		CISCOIF="E2"	;;
				eth3)		CISCOIF="E3"	;;
				ppp0)		CISCOIF="S0"	;;
				ppp1)		CISCOIF="S1"	;;
				ppp2)		CISCOIF="S2"	;;
				ppp3)		CISCOIF="S3"	;;
				tr0)		CISCOIF="To0"	;;
				tr1)		CISCOIF="To1"	;;
				tr2)		CISCOIF="To2"	;;
				tr3)		CISCOIF="To3"	;;
				*)			CISCOIF="`echo "$IF" | sed -e 's/^eth/E/' -e 's/^ppp/S/' -e 's/^tr/To/'`"	;;
				esac
				#CURRENT="access-list $DIRLETTER$CISCOIF $CISCOPOLICY $PROTO $SRCHOST$SRCCISCOPORTSPEC $DESTHOST$DESTCISCOPORTSPEC$CISCOTOS $ECHOACK $LOGTHIS"
				CURRENT=`awk "BEGIN {printf \"access-list %-4s %-6s %-8s %-90s\", \
						\"$DIRLETTER$CISCOIF\", \
						\"$CISCOPOLICY\", \
						\"$PROTO\", \
						\"$SRCHOST$SRCCISCOPORTSPEC $DESTHOST$DESTCISCOPORTSPEC$CISCOTOS $ECHOACK $LOGTHIS\" \
						}"`
			fi
																				;;
		esac # No need to handle ECHOCOMMAND=none :-)
		CKPTMASON=" mason: finished display" ; #ckpt $CKPTMASON

		if [ "$DEBUG" = "YES" ]; then echo current= "$CURRENT" >/dev/stderr ; fi

		if [ -n "$UNDOSPECIFICRULE" ]; then eval "$UNDOSPECIFICRULE" ; fi

#Don't do anything if this is the same as one of the last 5 rules.  This 
#reduces the occurence of repeated rules showing up.
		CKPTMASON=" mason: Implement new rule" ; #ckpt $CKPTMASON
		#Yank mark values before comparing
		case `echo $CURRENT | sed -e 's/ -m [0-9][0-9]* //'` in
		$LAST1|$LAST2|$LAST3|$LAST4|$LAST5|$LAST6|$LAST7|$LAST8)
			if [ "$HEARTBEAT" = "YES" ]; then echo -n "-" >/dev/stderr ; NEEDLF="YES" ; fi
																;;
		*)
			if [ "$NEEDLF" = "YES" ]; then echo >/dev/stderr ; NEEDLF="NO" ; fi
			if [ "$DOBEEP" = "YES" ]; then echo -n -e "\a" >/dev/stderr ; fi
			if [ "$DODISPLAY" = "YES" ]; then
				case $ECHOCOMMAND in
				ipchains|ipfwadm|cisco)	echo "$CURRENT $COMMENT $COMMENT2"		;;
				ipchains-save)			echo $CURRENT							;;
				esac
			fi


#Put a real rule in the rule chain so that we don't log it again.  We need to use eval since ${xxxHOST} may be a $DYNIP 
#and may need to be evaluated to its real value.
			if [ "$DOCOMMAND" = "ipfwadm" ]; then
				if [ -n "$LOGTHIS" ]; then LOGTHIS="-o" ; fi
				eval "/sbin/ipfwadm ${LCPOLICY:+"-i"} $LCPOLICY ${IF:+"-W"} $IF -$DIRLETTER ${PROTO:+"-P"} $PROTO $ACK -S $SRCHOST $SRCPORT -D $DESTHOST $DESTPORT $TOS $LOGTHIS"
			elif [ "$DOCOMMAND" = "ipchains" ]; then
				case "$ACK" in
				""|"  ")	DOACK=""									;;
				"-k")		DOACK="! -y"								;;
				"! -k")		DOACK="-y"									;;
				esac
				if [ -n "$LOGTHIS" ]; then LOGTHIS="-l" ; fi
				case $DIRLETTER in
				I)		DIR="input$NOLOGSUFFIX"					;;
				O)		DIR="output$NOLOGSUFFIX"				;;
				F)		DIR="forward$NOLOGSUFFIX"				;;
				esac
				eval "/sbin/ipchains ${DIR:+"-I"} $DIR 1 ${IF:+"-i"} $IF ${PROTO:+"-p"} $PROTO $DOACK -s $SRCHOST $SRCPORT -d $DESTHOST $DESTPORT $TOS ${MINMARK:+"-m"} $MINMARK ${UCPOLICY:+"-j"} $UCPOLICY $LOGTHIS"
				if [ -n "$MINMARK" ]; then INCMINMARK="1" ; fi
			fi # no need to handle DOCOMMAND=none :-)
			LAST8=$LAST7
			LAST7=$LAST6
			LAST6=$LAST5
			LAST5=$LAST4
			LAST4=$LAST3
			LAST3=$LAST2
			LAST2=$LAST1
			LAST1=`echo $CURRENT | sed -e 's/ -m [0-9][0-9]* //'`	;;
		esac

		if [ "$DEBUG" = "YES" ]; then  echo src= $SRCIP $SRCPORT dest= $DESTIP $DESTPORT if= $IF proto= $PROTO >/dev/stderr ; fi

		if [ "$LCPOLICY" = "accept -m" ]; then	#Reset policy to non-masq for the next rule.
			UCPOLICY="ACCEPT" ; LCPOLICY="accept"
		fi
	fi #if ISLOGLINE

	if [ -n "$MINMARK" ]; then MINMARK=$[ $MINMARK + $INCMINMARK ] ; fi

#Get the next log entry and start over.
	unset ACK COMMENT DEST DESTHOST DESTIP DESTPORT DIR DIRLETTER DOACK ECHOACK IF IGNOREPORT ISLOGLINE \
	LINEHASDYNAMIC LOGTHIS MESSPOL NUMBYTES NUMPACKETS PROTO SRC SRCHOST SRCIP SRCPORT TAIL TOS || true
	#unset DFFLAG FFLAG FOFLAG IFLAG LFLAG SFLAG TFLAG || true		#These are unused.
	if [ -n "$MINMARK" ]; then INCMINMARK="0" ; fi
	TOS=""
	A3=$O3 ; A4=$O4 ; A5=$O5 ; A6=$O6 ; A7=$O7 ; A8=$O8 ; A9=$O9 ; A10=$O10 ; A11=$O11 ; A12=$O12 ; A13=$O13
	O3=$J3 ; O4=$J4 ; O5=$J5 ; O6=$J6 ; O7=$J7 ; O8=$J8 ; O9=$J9 ; O10=$J10 ; O11=$J11 ; O12=$J12 ; O13=$J13
	CKPTMASON=" mason: reading next line" ; #ckpt $CKPTMASON
	if ! read J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 ; then
		if [ "$SIGGED" != "YES" ]; then EXITMASON="YES" ; fi
	fi
#Keep reading until a line with different firewall values is found.
	while { [ "$O3"  = "$J3"  ] && [ "$O4"  = "$J4"  ] && [ "$O5"  = "$J5"  ] && [ "$O6" = "$J6" ] && \
			[ "$O7"  = "$J7"  ] && [ "$O8"  = "$J8"  ] && [ "$O9"  = "$J9"  ] && [ "$O10" = "$J10" ] && \
			[ "$O11" = "$J11" ] && [ "$O12" = "$J12" ] && [ "$O13" = "$J13" ] ; } ||
		  { [ "$A3"  = "$J3"  ] && [ "$A4"  = "$J4"  ] && [ "$A5"  = "$J5"  ] && [ "$A6" = "$J6" ] && \
			[ "$A7"  = "$J7"  ] && [ "$A8"  = "$J8"  ] && [ "$A9"  = "$J9"  ] && [ "$A10" = "$J10" ] && \
			[ "$A11" = "$J11" ] && [ "$A12" = "$J12" ] && [ "$A13" = "$J13" ] ; } ||
		  { [ "$SIGGED" = "YES" ] ; } ; do
		CKPTMASON=" mason: duped line or sigged" ; #ckpt $CKPTMASON
		if [ "$SIGGED" = "YES" ]; then
			SIGGED="NO"
		else
			if [ "$HEARTBEAT" = "YES" ]; then echo -n "." >/dev/stderr ; NEEDLF="YES" ; fi
			A3=$O3 ; A4=$O4 ; A5=$O5 ; A6=$O6 ; A7=$O7 ; A8=$O8 ; A9=$O9 ; A10=$O10 ; A11=$O11 ; A12=$O12 ; A13=$O13
			O3=$J3 ; O4=$J4 ; O5=$J5 ; O6=$J6 ; O7=$J7 ; O8=$J8 ; O9=$J9 ; O10=$J10 ; O11=$J11 ; O12=$J12 ; O13=$J13
		fi
		if ! read J1 J2 J3 J4 J5 J6 J7 J8 J9 J10 J11 J12 J13 J14 J15 J16 J17 J18 J19 ; then
			if [ "$SIGGED" != "YES" ]; then EXITMASON="YES" ; fi
		fi
	done
done

CKPTMASON=" mason: outside of main loop" ; #ckpt $CKPTMASON
if [ "$NEEDLF" = "YES" ]; then echo >/dev/stderr ; NEEDLF="NO" ; fi
if [ "$EXITMASON" = "YES" ]; then
	echo Mason is exiting because of a SIGHUP or EXITMASON=YES. >/dev/stderr
else
	echo Mason is exiting because of an end of input data. >/dev/stderr
fi

CKPTMASON=""
