diff --git a/checkdnsbl.sh b/dronebl/checkdnsbl.sh
similarity index 100%
rename from checkdnsbl.sh
rename to dronebl/checkdnsbl.sh
diff --git a/dronebl/dronebl-tools_0.3.tar.gz b/dronebl/dronebl-tools_0.3.tar.gz
new file mode 100644
index 0000000..4f16c05
Binary files /dev/null and b/dronebl/dronebl-tools_0.3.tar.gz differ
diff --git a/dronebl/dronebl.py b/dronebl/dronebl.py
new file mode 100644
index 0000000..89096cb
--- /dev/null
+++ b/dronebl/dronebl.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# Copyright (c) 2008 DroneBL contributors
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of the author nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+class DroneBLClient:
+ """Class for accessing DroneBL."""
+ def __init__(self, rpckey=None, server="https://dronebl.org/RPC2"):
+ self.server = server
+ self.rpckey = rpckey
+ self.submitList = ""
+
+ def addIP(self, ip, type):
+ """Adds IP to DroneBL."""
+ self.submitList += "\t\n";
+
+ def lookupIP(self, ip):
+ """Adds a lookup request to the message."""
+ self.submitList += "\t\n"
+
+ def makeRequest(self):
+ """Generates the request."""
+ self.request = "\n\n" + self.submitList + ""
+
+ def showRequest(self):
+ """Shows the request."""
+ self.makeRequest()
+ print self.request
+
+ def makeConnection(self):
+ """Connects to the RPC server."""
+ import urllib
+ type, uri = urllib.splittype(self.server)
+ self.__host, self.__handler = urllib.splithost(uri)
+
+ import httplib
+ self.connection = httplib.HTTPConnection(self.__host)
+
+ def postRequest(self):
+ """Executes the request."""
+ self.makeRequest()
+ self.makeConnection()
+ self.connection.putrequest("POST", self.__handler)
+ self.connection.putheader("Content-Type", "text/xml")
+ self.connection.putheader("Content-Length", str(int(len(self.request))))
+ self.connection.endheaders()
+ self.connection.send(self.request)
+ self.__response = self.connection.getresponse()
+
+ def printResponse(self):
+ """Display the XML response."""
+ print self.__response.read()
+
diff --git a/dronebl/libdronebl-tcl_1.3.tar.gz b/dronebl/libdronebl-tcl_1.3.tar.gz
new file mode 100644
index 0000000..32fa24d
Binary files /dev/null and b/dronebl/libdronebl-tcl_1.3.tar.gz differ
diff --git a/dronebl/remove.sh b/dronebl/remove.sh
new file mode 100644
index 0000000..bb6d7e1
--- /dev/null
+++ b/dronebl/remove.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+cd "$(dirname "$0")"
+KEY="$("
+ while [ -n "$1" ] ; do
+ echo ""
+ shift
+ done
+ echo ""
+) \
+| curl -s --data @- https://dronebl.org/RPC2 \
+| (xmllint --xpath '/response/result/@id' - 2>/dev/null | sed -n -e 's, id="\([^"]*\)",\1\n,gp') \
+|(
+ echo ""
+ while read ID ; do
+ echo "Remove ID $ID" >&2
+ echo ""
+ done
+ echo ""
+) \
+| tee -a dronebl-remove.log \
+| curl -s --data @- https://dronebl.org/RPC2 | tee -a dronebl-remove.log | grep -q "\"success\""
+if [ $? -eq 0 ] ; then
+ echo "DRONEBL: successfully removed $@"
+else
+ echo "DRONEBL: error removing $@"
+fi
diff --git a/dronebl/submit.sh b/dronebl/submit.sh
new file mode 100644
index 0000000..aa62c4f
--- /dev/null
+++ b/dronebl/submit.sh
@@ -0,0 +1,175 @@
+#!/bin/bash
+# syntax: dronebl-submit.sh [bantype [host|IP|datafile [host|IP|datafile [etc.]]]
+# where datafile contains one host or IP per line.
+# This script will sort | uniq datafiles and query for existing active listings, so
+# duplicate entries are no problem.
+#
+# dependencies: bash, wget, standard GNU utils (host / sed / grep / sort / etc)
+#
+# Version history:
+# 2.1 -- fixed a logic error; removed the removal of /tmp/dronebl-*.xml files on error
+# 2.0 -- completely rewritten for RPC2 (although argument syntax is backward-
+# compatible)
+
+RPCKEY="/etc/fail2ban/dronebl.rpckey" # key, or path to file containing rpckey
+REPORT_TO="https://dronebl.org/RPC2"
+
+### end of user variables ###
+
+if [ ! -w "/tmp" ]; then
+ echo "Unable to write to /tmp. Please ensure the disk is not full, and that this account has appropriate permissions."
+ exit 1
+fi
+
+if [ -f "$RPCKEY" ]; then
+ if [ -r "$RPCKEY" ]; then
+ RPCKEY=`cat $RPCKEY`
+ else
+ echo "RPC key in $RPCKEY is unreadable. Exiting."
+ exit 1
+ fi
+fi
+
+function wash { # wash -- sets $IP by reference
+ ADDR=$1
+ TEST=`echo "${ADDR}." | grep -E "^([0-9]{1,3}\.){4}$"`
+ if [ "$TEST" ]; then
+ VALID=0
+ else
+ VALID=1
+ fi
+
+ if [ "$VALID" = "1" ]; then
+ echo -n "Looking up $ADDR... "
+ ADDR=`host $ADDR | grep -E -o -e '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'`
+ TEST=`echo "${ADDR}." | grep -E "^([0-9]{1,3}\.){4}$"`
+ if [ "$TEST" ]; then
+ echo "$ADDR"
+ else
+ echo "Unable to resolve. Skipping."
+ return 1
+ fi
+ fi
+ eval "IP=$ADDR"
+ return 0
+}
+
+function rinse { # rinse -- if bantype is contained in the deprecated list, exit
+ DEPRECATED=( 4 11 12 )
+ for dep in ${DEPRECATED[@]}; do
+ if [ "$BANTYPE" == "$dep" ]; then
+ echo "Bantype $BANTYPE has been deprecated. The DroneBL is probably not the appropriate listing service for this sort of activity. Please visit us on irc.atheme.org in #dronebl if you believe otherwise. Exiting."
+ exit 1
+ fi
+ done
+}
+
+function checkerror { #checkerror -- prints error messages from xml and exits
+ ERROR=`grep -i error $1`
+ if [ "$ERROR" ]; then
+ ERROR=`grep '' $1 | sed -r -e 's/<[^>]*>//g' -e 's/^\s*//g'`
+ ERROR="$ERROR: `grep '' $1 | sed -r -e 's/<[^>]*>//g' -e 's/^\s*//g'`"
+ echo "The server returned an error ($ERROR) -- see /tmp/dronebl-query.xml and /tmp/dronebl-response.xml for full details."
+ exit 1
+ fi
+}
+
+if [ "$2" = "" ]; then
+ echo -n 'Syntax:
+'$0' [bantype [host|IP|datafile [host|IP|datafile [etc.]]]]
+
+Types are as follows:
+2 = Sample
+3 = IRC Drone
+4 = Tor exit node (deprecated)
+5 = Bottler
+6 = Unknown spambot or drone
+7 = DDOS Drone
+8 = SOCKS Proxy
+9 = HTTP Proxy
+10 = ProxyChain
+11 = Machines and netblocks compromised or owned by MediaDefender (deprecated)
+12 = Trolls (deprecated)
+13 = Brute force attackers
+14 = Open Wingate
+15 = Open Router
+255 = Unknown
+
+Which type? '
+ read BANTYPE
+ rinse $BANTYPE
+ echo -n "What's the hostname / IP address? "
+ read ADDR
+ wash $ADDR
+ if [ $? ]; then
+ IPLIST[0]=$IP
+ else
+ echo "Unable to resolve $ADDR. Exiting."
+ exit 1
+ fi
+else
+ rinse $1
+ args=($@)
+ echo "A little housekeeping..."
+ for (( x=1; x<${#args[@]}; x++ )); do
+ if [ "${args[$x]}" != "" ]; then
+ filename="${args[$x]}"
+ if [ ! -r "$filename" ]; then filename="$PWD/${args[$x]}"; fi
+ if [ -r "$filename" ]; then
+ for i in `sort -u $PWD/${args[$x]}`; do
+ wash $i
+ if [ $? ]; then IPLIST[${#IPLIST[@]}]=$IP; fi
+ done
+ else
+ wash ${args[$x]}
+ if [ $? ]; then IPLIST[${#IPLIST[@]}]=$IP; fi
+ fi
+ fi
+ done
+ IPLIST=( `for (( x=0; x<${#IPLIST[@]}; x++ )) ; do echo ${IPLIST[$x]}; done | sort -u` )
+ BANTYPE=$1
+fi
+
+POSTFILE="/tmp/dronebl-query.xml"
+RESPONSEFILE="/tmp/dronebl-response.xml"
+
+echo "Housekeeping finished. Working with ${#IPLIST[@]} unique, valid addresses."
+if [ ${#IPLIST[@]} -eq 0 ]; then
+ echo "No hosts to report. Exiting."
+ exit 0
+fi
+
+echo "Checking for exiting entries... "
+echo "
+" >$POSTFILE
+for i in ${IPLIST[@]}; do
+ echo " " >>$POSTFILE
+done
+echo "" >>$POSTFILE
+wget -q --post-file="$POSTFILE" -O "$RESPONSEFILE" --header="Content-Type: text/xml" $REPORT_TO
+checkerror $RESPONSEFILE
+grepfor='type="'$BANTYPE'"'
+for i in `grep 'listed="1"' $RESPONSEFILE | grep $grepfor | grep -E -o -e '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort -u`; do
+ IPLIST=( ${IPLIST[@]%%$i} )
+ echo "$i is already active in the DroneBL database as ban type $BANTYPE. Removing."
+done
+
+if [ ${#IPLIST[@]} -eq 0 ]; then
+ echo "No hosts to report. Exiting."
+ exit 0
+elif [ ${#IPLIST[@]} -eq 1 ]; then
+ echo -n "Reporting ${IPLIST[@]} as ban type $BANTYPE... "
+else
+ echo -n "Reporting ${#IPLIST[@]} hosts as ban type $BANTYPE... "
+fi
+echo "
+" >$POSTFILE
+for i in ${IPLIST[@]}; do
+ if [ "`echo ${i}. | grep -E '^([0-9]{1,3}\.){4}$'`" != "" ]; then echo " " >>$POSTFILE; fi
+done
+echo "" >>$POSTFILE
+wget -q --post-file="$POSTFILE" -O "$RESPONSEFILE" --header="Content-Type: text/xml" $REPORT_TO
+checkerror $RESPONSEFILE
+echo "done."
+rm -f /tmp/dronebl*.xml
+exit 0