Subject: Re: admin script for ipfilter
To: Jeremy C. Reed <reed@reedmedia.net>
From: Darren Reed <darrenr@NetBSD.org>
List: tech-userlevel
Date: 12/27/2006 00:04:47
--VbJkn9YxBvnuCH5J
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Tue, Dec 26, 2006 at 11:17:43AM -0600, Jeremy C. Reed wrote:
> On Tue, 26 Dec 2006, Darren Reed wrote:
> 
> > If there were to be a script that took over the role of enabling ipfilter
> > in netbsd at bootup, which file(s) should it use and how?
> > 
> > Should it, for example, modify /etc/rc.conf?
> > 
> > If it were to do this, should it create an /etc/rc.conf.lock to ensure
> > that only one program is updating that file or not bother?
> > 
> > Or should it modify files in /etc/rc.conf.d/?
> > Should it use .lock on files to serialise access ?
> > And how do settings in files there gel with /etc/rc.d?
> > Will it be intuitive for people to glance at rc.conf, see
> > ipfilter is enabled, but know that it is really disabled
> > because of a setting in /etc/rc.conf.d/ipfilter ?
> 
> /etc/rc.conf.d/ipfilter is correct to me. It is loaded after /etc/rc.conf.
> 
> The correct way to see the setting(s) is to run "/etc/rc.d/ipfilter 
> rcvar".

Ok, that makes things easy.

> As for locking that rc.d/ipfilter specific config, I wouldn't bother.

Well, just to be on the safe side, the convention I've used in the
attached script is to use /etc/rc.cond.d/ipfilter.d as a "locking
directory".

So...the attached script, "ipfadm", I'm curious for feedback on.

The idea is to do "ipfadm enable ipfilter" or "ipfadm disable ipfilter"
and it updates the relevant rc.d config file for you.

Ok, not catchy...

What I hope is of more interest is doing "ipfadm ipfilter status",
where it will tell you if it is enabled, disabled, enabled but no rules,
or disabled but rules loaded.

Feedback welcome.

Darren

--VbJkn9YxBvnuCH5J
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=ipfadm

#!/bin/sh

prog=$0

RCD=/etc/rc.conf.d

# /etc/rc.d/ipfilter
# /etc/rc.d/ipfs
# /etc/rc.d/ipnat
# /etc/rc.d/ipmon

usage() {
	echo "$prog status"
	echo "$prog ipfilter <enable|disable|reload|resync|start|status|stop>"
	echo "$prog ipfs <enable|disable|status|start|stop>"
	echo "$prog ipmon <enable|disable|restart|start|status|stop>"
	echo "$prog ipnat <enable|disable|reload|start|status|stop>"
	exit 1
}

enable() {
	old=${RCD}/$1.old
	new=${RCD}/$1
	mkdir ${RCD}/$1.d
	if [ $? -eq 0 ] ; then
		if [ -f ${RCD}/$1 ] ; then
			cp ${RCD}/$1 ${RCD}/$1.old
			sed -e "s/^${1} *\=.*/${1}\=YES/" ${old} > ${new}
			/bin/rm ${old}
		else
			echo "$1=YES" > ${RCD}/$1
			chmod go-wx ${RCD}/$1
		fi
		rmdir ${RCD}/$1.d
	fi
}

disable() {
	old=${RCD}/$1.old
	new=${RCD}/$1
	mkdir ${RCD}/$1.d
	if [ $? -eq 0 ] ; then
		if [ -f ${RCD}/$1 ] ; then
			cp ${RCD}/$1 ${RCD}/$1.old
			sed -e "s/^${1} *\=.*/${1}\=NO/" ${old} > ${new}
			/bin/rm ${old}
		else
			echo "$1=NO" > ${RCD}/$1
			chmod go-wx ${RCD}/$1
		fi
		rmdir ${RCD}/$1.d
	fi
}

status() {
	active=`/etc/rc.d/$1 rcvar|sed -ne "s/^$""${1}\=\(.*\)$/\1/p"`
	case $active in
	NO)
		return 0
		;;
	YES)
		return 1
		;;
	esac
	return 2
}

status_ipmon() {
	pid=`pgrep ipmon`
	status ipmon
	case $? in
	0)
		if [ -n "$pid" ] ; then
			echo "disabled-but-running"
		else
			echo "disabled"
		fi
		;;
	1)
		if [ -n "$pid" ] ; then
			echo "enabled"
		else
			echo "enabled-not-running"
		fi
		;;
	2)
		if [ -n "$pid" ] ; then
			echo "unknown-state-running"
		else
			echo "unknown-state"
		fi
		;;
	esac
}

status_ipfilter() {
	rules=`ipfstat -io 2>/dev/null`
	if [ -z "$x" ] ; then
		rules=`ipfstat -aio 2>/dev/null`
	fi

	status ipfilter
	case $? in
	0)
		if [ -n "$rules" ] ; then
			echo "disabled-rules-loaded"
		else
			echo "disabled"
		fi
		;;
	1)
		if [ -n "$rules" ] ; then
			echo "enabled"
		else
			echo "enabled-no-rules"
		fi
		;;
	2)
		if [ -n "$rules" ] ; then
			echo "unknown-rules-loaded"
		else
			echo "unknown-state"
		fi
		;;
	esac
}

status_ipnat() {
	rules=`ipnat -l 2>/dev/null | egrep '^map|rdr' 2>/dev/null`

	status ipnat
	case $? in
	0)
		if [ -n "$rules" ] ; then
			echo "disabled-rules-loaded"
		else
			echo "disabled"
		fi
		;;
	1)
		if [ -n "$rules" ] ; then
			echo "enabled"
		else
			echo "enabled-no-rules"
		fi
		;;
	2)
		if [ -n "$rules" ] ; then
			echo "unknown-rules-loaded"
		else
			echo "unknown-state"
		fi
		;;
	esac
}

status_ipfs() {
	status ipfs
	report ipfs $?
}

report() {
	echo -n "$1 "
	case $2 in
	0)
		echo "disabled"
		;;
	1)
		echo "enabled"
		;;
	2)
		echo "unknown-status"
		;;
	*)
		echo "$2"
		;;
	esac
}

do_ipfilter() {
	case $1 in
	enable)
		enable ipfilter
		;;
	disable)
		disable ipfilter
		;;
	reload)
		/etc/rc.d/ipfilter reload
		;;
	resync)
		/etc/rc.d/ipfilter resync
		;;
	start)
		/etc/rc.d/ipfilter start
		;;
	status)
		status_ipfilter
		;;
	stop)
		/etc/rc.d/ipfilter stop
		;;
	*)
		usage
		;;
	esac
}

do_ipfs() {
	case $1 in
	enable)
		enable ipfs
		;;
	disable)
		disble ipfs
		;;
	start)
		/etc/rc.d/ipfs start
		;;
	status)
		status_ipfs
		;;
	stop)
		/etc/rc.d/ipfs stop
		;;
	*)
		usage
		;;
	esac
}

do_ipmon() {
	case $1 in
	enable)
		enable ipmon
		;;
	disable)
		disble ipmon
		;;
	restart)
		/etc/rc.d/ipmon restart
		;;
	start)
		/etc/rc.d/ipmon start
		;;
	status)
		status_ipmon
		;;
	stop)
		/etc/rc.d/ipmon stop
		;;
	*)
		usage
		;;
	esac
}

do_ipnat() {
	case $1 in
	enable)
		enable ipnat
		;;
	disable)
		disable ipnat
		;;
	reload)
		/etc/rc.d/ipnat reload
		;;
	restart)
		/etc/rc.d/ipnat restart
		;;
	start)
		/etc/rc.d/ipnat start
		;;
	status)
		status_ipnat
		;;
	stop)
		/etc/rc.d/ipnat stop
		;;
	*)
		usage
		;;
	esac
}

do_status_all() {
	status_ipfilter
	status_ipfs
	status_ipmon
	status_ipnat
}

case $1 in
status)
	do_status_all
	;;
ipfilter)
	do_ipfilter $2
	;;
ipfs)
	do_ipfs $2
	;;
ipmon)
	do_ipmon $2
	;;
ipnat)
	do_ipnat $2
	;;
*)
	usage
	;;
esac
exit 0

--VbJkn9YxBvnuCH5J--