1#!/bin/sh
2#echo "run $@" 1>&2
3#set -x
4# $1 command
5# $2 rulename
6# $3 protocol
7# $4 address
8# $5 mask
9# $6 port
10# $7 id
11
12pf=
13if [ -f "/etc/ipfw-blacklist.rc" ]; then
14	pf="ipfw"
15	. /etc/ipfw-blacklist.rc
16	ipfw_offset=${ipfw_offset:-2000}
17fi
18
19if [ -z "$pf" ]; then
20	for f in npf pf ipf; do
21		if [ -f "/etc/$f.conf" ]; then
22			pf="$f"
23			break
24		fi
25	done
26fi
27
28if [ -z "$pf" ]; then
29	echo "$0: Unsupported packet filter" 1>&2
30	exit 1
31fi
32
33if [ -n "$3" ]; then
34	proto="proto $3"
35fi
36
37if [ -n "$6" ]; then
38	port="port $6"
39fi
40
41addr="$4"
42mask="$5"
43case "$4" in
44::ffff:*.*.*.*)
45	if [ "$5" = 128 ]; then
46		mask=32
47		addr=${4#::ffff:}
48	fi;;
49esac
50
51case "$1" in
52add)
53	case "$pf" in
54	ipf)
55		/sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1
56		echo block in quick $proto from $addr/$mask to \
57		    any port=$6 head port$6 | \
58		    /sbin/ipf -I -f - -s >/dev/null 2>&1 && echo OK
59		;;
60	ipfw)
61		# use $ipfw_offset+$port for rule number
62		rule=$(($ipfw_offset + $6))
63		tname="port$6"
64		/sbin/ipfw table $tname create type addr 2>/dev/null
65		/sbin/ipfw -q table $tname add "$addr/$mask"
66		# if rule number $rule does not already exist, create it
67		/sbin/ipfw show $rule >/dev/null 2>&1 || \
68			/sbin/ipfw add $rule drop $3 from \
69			table"("$tname")" to any dst-port $6 >/dev/null && \
70			echo OK
71		;;
72	npf)
73		/sbin/npfctl rule "$2" add block in final $proto from \
74		    "$addr/$mask" to any $port
75		;;
76	pf)
77		# if the filtering rule does not exist, create it
78		/sbin/pfctl -a "$2/$6" -sr 2>/dev/null | \
79		    grep -q "<port$6>" || \
80		    echo "block in quick $proto from <port$6> to any $port" | \
81		    /sbin/pfctl -a "$2/$6" -f -
82		# insert $ip/$mask into per-protocol/port anchored table
83		/sbin/pfctl -qa "$2/$6" -t "port$6" -T add "$addr/$mask" && \
84		    /sbin/pfctl -qk "$addr" && echo OK
85		;;
86	esac
87	;;
88rem)
89	case "$pf" in
90	ipf)
91		/sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1
92		echo block in quick $proto from $addr/$mask to \
93		    any port=$6 head port$6 | \
94		    /sbin/ipf -I -r -f - -s >/dev/null 2>&1 && echo OK
95		;;
96	ipfw)
97		/sbin/ipfw table "port$6" delete "$addr/$mask" 2>/dev/null && \
98		    echo OK
99		;;
100	npf)
101		/sbin/npfctl rule "$2" rem-id "$7"
102		;;
103	pf)
104		/sbin/pfctl -qa "$2/$6" -t "port$6" -T delete "$addr/$mask" && \
105		    echo OK
106		;;
107	esac
108	;;
109flush)
110	case "$pf" in
111	ipf)
112		/sbin/ipf -Z -I -Fi -s > /dev/null && echo OK
113		;;
114	ipfw)
115		/sbin/ipfw table "port$6" flush 2>/dev/null && echo OK
116		;;
117	npf)
118		/sbin/npfctl rule "$2" flush
119		;;
120	pf)
121		# dynamically determine which anchors exist
122		for anchor in $(/sbin/pfctl -a "$2" -s Anchors); do
123			/sbin/pfctl -a $anchor -t "port${anchor##*/}" -T flush
124			/sbin/pfctl -a $anchor -F rules
125		done
126		echo OK
127		;;
128	esac
129	;;
130*)
131	echo "$0: Unknown command '$1'" 1>&2
132	exit 1
133	;;
134esac
135