Repository: fail2ban/fail2ban

Issue:
An IP address has a PTR record
In sendmail-geoip-lines action




Discussion:
Should it be against 0.9?

[![Coverage Status](https://coveralls.io/builds/9786020/badge)](https://coveralls.io/builds/9786020)

Coverage increased (+0.009%) to 96.384% when pulling **fb1c7e57b09da6d0059200ab7034a1eb9a8c3a6f on szepeviktor:patch-10** into **e8a155656248ffc8784de8c254bd26dd939c3595 on fail2ban:0.10**.


[![Coverage Status](https://coveralls.io/builds/9786020/badge)](https://coveralls.io/builds/9786020)

Coverage increased (+0.009%) to 96.384% when pulling **fb1c7e57b09da6d0059200ab7034a1eb9a8c3a6f on szepeviktor:patch-10** into **e8a155656248ffc8784de8c254bd26dd939c3595 on fail2ban:0.10**.


[![Coverage Status](https://coveralls.io/builds/9786020/badge)](https://coveralls.io/builds/9786020)

Coverage increased (+0.009%) to 96.384% when pulling **fb1c7e57b09da6d0059200ab7034a1eb9a8c3a6f on szepeviktor:patch-10** into **e8a155656248ffc8784de8c254bd26dd939c3595 on fail2ban:0.10**.

Would it be possible to merge this one?

Resolving patch:
diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py
--- a/fail2ban/server/actions.py
+++ b/fail2ban/server/actions.py
@@ -291,6 +291,7 @@ class ActionInfo(CallingMap):
 		AI_DICT = {
 			"ip":				lambda self: self.__ticket.getIP(),
 			"ip-rev":		lambda self: self['ip'].getPTR(''),
+			"ip-host":	lambda self: self['ip'].getHost(),
 			"fid":			lambda self: self.__ticket.getID(),
 			"failures":	lambda self: self.__ticket.getAttempt(),
 			"time":			lambda self: self.__ticket.getTime(),
diff --git a/fail2ban/server/ipdns.py b/fail2ban/server/ipdns.py
--- a/fail2ban/server/ipdns.py
+++ b/fail2ban/server/ipdns.py
@@ -376,6 +376,11 @@ def getPTR(self, suffix=None):
 
 		return "%s.%s" % (".".join(reversed(exploded_ip)), suffix)
 
+	def getHost(self):
+		"""Return the host name (DNS) of the provided IP address object
+		"""
+		return DNSUtils.ipToName(self.ntoa)
+
 	@property
 	def isIPv4(self):
 		"""Either the IP object is of address family AF_INET


Test patch:
diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py
--- a/fail2ban/tests/servertestcase.py
+++ b/fail2ban/tests/servertestcase.py
@@ -38,7 +38,9 @@
 from ..server.ipdns import IPAddr
 from ..server.jail import Jail
 from ..server.jailthread import JailThread
+from ..server.ticket import BanTicket
 from ..server.utils import Utils
+from .dummyjail import DummyJail
 from .utils import LogCaptureTestCase
 from ..helpers import getLogger, PREFER_ENC
 from .. import version
@@ -1677,7 +1679,7 @@ def testComplexMailActionMultiLog(self):
 				# complain --
 				('j-complain-abuse', 
 					'complain['
-					  'name=%(__name__)s, grepopts="-m 1", grepmax=2, mailcmd="mail -s",' +
+					  'name=%(__name__)s, grepopts="-m 1", grepmax=2, mailcmd="mail -s Hostname: <ip-host> - ",' +
 					  # test reverse ip:
 					  'debug=1,' +
 						# 2 logs to test grep from multiple logs:
@@ -1692,14 +1694,14 @@ def testComplexMailActionMultiLog(self):
 						'testcase01.log:Dec 31 11:59:59 [sshd] error: PAM: Authentication failure for kevin from 87.142.124.10',
 						'testcase01a.log:Dec 31 11:55:01 [sshd] error: PAM: Authentication failure for test from 87.142.124.10',
 						# both abuse mails should be separated with space:
-						'mail -s Abuse from 87.142.124.10 abuse-1@abuse-test-server abuse-2@abuse-test-server',
+						'mail -s Hostname: test-host - Abuse from 87.142.124.10 abuse-1@abuse-test-server abuse-2@abuse-test-server',
 					),
 					'ip6-ban': (
 						# test reverse ip:
 						'try to resolve 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.abuse-contacts.abusix.org',
 						'Lines containing failures of 2001:db8::1 (max 2)',
 						# both abuse mails should be separated with space:
-						'mail -s Abuse from 2001:db8::1 abuse-1@abuse-test-server abuse-2@abuse-test-server',
+						'mail -s Hostname: test-host - Abuse from 2001:db8::1 abuse-1@abuse-test-server abuse-2@abuse-test-server',
 					),
 				}),
 			)
@@ -1723,6 +1725,7 @@ def testComplexMailActionMultiLog(self):
 
 			ipv4 = IPAddr('87.142.124.10')
 			ipv6 = IPAddr('2001:db8::1');
+			dmyjail = DummyJail()
 			for jail, act, tests in testJailsActions:
 				# print(jail, jails[jail])
 				for a in jails[jail].actions:
@@ -1736,7 +1739,8 @@ def testComplexMailActionMultiLog(self):
 					for (test, ip) in (('ip4-ban', ipv4), ('ip6-ban', ipv6)):
 						if not tests.get(test): continue
 						self.pruneLog('# === %s ===' % test)
-						ticket = _actions.CallingMap({
-							'ip': ip, 'ip-rev': lambda self: self['ip'].getPTR(''), 'failures': 100,})
+						ticket = BanTicket(ip)
+						ticket.setAttempt(100)
+						ticket = _actions.Actions.ActionInfo(ticket, dmyjail)
 						action.ban(ticket)
 						self.assertLogged(*tests[test], all=True)
diff --git a/fail2ban/tests/utils.py b/fail2ban/tests/utils.py
--- a/fail2ban/tests/utils.py
+++ b/fail2ban/tests/utils.py
@@ -273,6 +273,9 @@ def F2B_SkipIfNoNetwork():
 		c.set('192.0.2.%s' % i, None)
 		c.set('198.51.100.%s' % i, None)
 		c.set('203.0.113.%s' % i, None)
+		c.set('2001:db8::%s' %i, 'test-host')
+	# some legal ips used in our test cases (prevent slow dns-resolving and failures if will be changed later):
+	c.set('87.142.124.10', 'test-host')
 	if unittest.F2B.no_network: # pragma: no cover
 		# precache all wrong dns to ip's used in test cases:
 		c = DNSUtils.CACHE_nameToIp