uncommitted - hash-slinger

Ready changes

Summary

Import uploads missing from VCS:

Diff

diff --git a/CHANGES b/CHANGES
index bc741a3..a6b4bf8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,19 @@
-v2.7 (Jan 2, 2015)
+v3.1 (January 14, 2020)
+- tlsa: bug fixes [Peter van Dijk, Dirk Stöcker]
+- tlsa: separate duplicate output due to multiple IP addresses [Dirk Stöcker]
+- openpgpkey: update docs [Arsen Stasic]
+- sshfp: Support for xmss [Kishan Takoordyal]
+
+v3.0 (November 3, 2019)
+- upgrade to python version 3 [Frank Crawford]
+
+v2.8 (April 13, 2019)
+- tlsa: add submission port (587) to starttls support [Dirk Stöcker]
+- tlsa: fixes for newer m2crypto [Dirk Stöcker]
+- tlsa: small fixes in error handling [Dirk Stöcker]
+- documentation fixes [Jakub Wilk]
+
+v2.7 (Jan 2, 2016)
 - openpgpkey: Add --keyid option to select key on keyid [Paul]
 - openpgpkey: fix --rootanchor option handling [Ondřej Surý]
 - openpgpkey: print keyid as bind zone style comment [Carsten Strotmann]
@@ -8,7 +23,7 @@ v2.7 (Jan 2, 2015)
 - tlsa: Support --starttls for imap, pop3, smtp and ftp [Dirk Stöcker]
 - Remove DLV which is being sunset [Paul]
 
-v2.6 (Jan 6, 2015))
+v2.6 (Jan 6, 2015)
 - openpgpkey: Added --fetch option to fetch a public key from DNS [Paul]
 - openpgpkey: Update rrtype from private use to IANA allocation (#61) [Paul]
 - openpgpkey: Remove no longer needed --rrtype option [Paul]
diff --git a/README b/README
index a77329a..7a540e1 100644
--- a/README
+++ b/README
@@ -5,8 +5,7 @@ This package contains various tools to generate special DNS records
 sshfp		Generate RFC-4255 SSHFP DNS records from known_hosts
 		files or ssh-keyscan
 tlsa		Generate RFC-6698  TLSA DNS records via TLS
-openpgpkey	Generate draft-ietf-dane-openpgpkey-01 OPENPGPKEY DNS
-		records using gpg
+openpgpkey	Generate RFC-7929 OPENPGPKEY DNS records using gpg
 ipseckey	Generate RFC-4025 IPSECKEY DNS records on Libreswan
 		IPsec servers
 
@@ -25,14 +24,13 @@ Gerald Turner <gturner@unzane.com>
 Ondřej Surý <ondrej@sury.org>
 Jan Vcelak <jv@fcelda.cz>
 Dirk Stöcker <hashslinger@dstoecker.de>
+Frank Crawford <frank@crawford.emu.id.au>
 
 REQUIREMENTS:
 
-python-dns 	http://www.pythondns.org/
+python-dns 	http://www.dnspython.org/
 python-gnupg	http://pythonhosted.org/python-gnupg/
-python-ipaddr
-python-argparse	(for python < 2.7)
-M2Crypto	http://chandlerproject.org/Projects/MeTooCrypto
+m2crypto	http://gitlab.com/m2crypto/m2crypto/
 unbound-python	http://www.unbound.net/
 ssh-keygen	from openssh
 gpg		from gnupg
diff --git a/debian/changelog b/debian/changelog
index 202517b..b885da5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,22 @@
+hash-slinger (3.1-1.1) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Remove the unused dependency on python3-ipaddr. (Closes: #1003578)
+  * debian/control: Add Homepage.
+
+ -- Adrian Bunk <bunk@debian.org>  Thu, 10 Feb 2022 08:03:46 +0200
+
+hash-slinger (3.1-1) unstable; urgency=medium
+
+  * Update d/control (Closes: #899533)
+  * Update d/watch, update d/gbp.conf
+  * New upstream version 3.1 (Closes: #775048, #780498, #738494)
+  * d/control: Port to python3 (Closes: #927132, #834971, #738490
+  * Add ${python3:Depends} to Depends
+  * Final touches to d/control: policy version, priority optional
+
+ -- Ondřej Surý <ondrej@debian.org>  Sun, 14 Feb 2021 17:40:02 +0100
+
 hash-slinger (2.7-1) unstable; urgency=medium
 
   * Imported Upstream version 2.7 (Closes: #817894)
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index 45a4fb7..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-8
diff --git a/debian/control b/debian/control
index 3fa6196..c6d5fed 100644
--- a/debian/control
+++ b/debian/control
@@ -1,11 +1,14 @@
 Source: hash-slinger
 Section: utils
-Priority: extra
+Priority: optional
 Maintainer: Debian DNS Team <team+dns@tracker.debian.org>
 Uploaders: Ondřej Surý <ondrej@debian.org>
 Build-Depends: debhelper-compat (= 12),
+               dh-python,
+               python3,
                xmlto
-Standards-Version: 3.9.5
+Standards-Version: 4.5.1
+Homepage: https://github.com/letoams/hash-slinger
 Vcs-Git: https://salsa.debian.org/dns-team/hash-slinger.git
 Vcs-Browser: https://salsa.debian.org/dns-team/hash-slinger
 
@@ -14,14 +17,12 @@ Architecture: any
 Depends: ca-certificates,
          dns-root-data,
          openssh-client,
-         python,
-         python-argparse,
-         python-dnspython,
-         python-gnupg,
-         python-ipaddr,
-         python-m2crypto,
-         python-unbound,
+         python3-dnspython,
+         python3-gnupg (>= 0.3.7),
+         python3-m2crypto (>= 0.24.0),
+         python3-unbound,
          ${misc:Depends},
+         ${python3:Depends},
          ${shlibs:Depends}
 Replaces: sshfp
 Conflicts: sshfp
diff --git a/debian/patches/0001-Debian-default-root.key-resides-in-usr-share-dns-roo.patch b/debian/patches/0001-Debian-default-root.key-resides-in-usr-share-dns-roo.patch
index c237088..f5f8b76 100644
--- a/debian/patches/0001-Debian-default-root.key-resides-in-usr-share-dns-roo.patch
+++ b/debian/patches/0001-Debian-default-root.key-resides-in-usr-share-dns-roo.patch
@@ -1,4 +1,4 @@
-From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ondrej@sury.org>
+From: =?utf-8?b?T25kxZllaiBTdXLDvQ==?= <ondrej@sury.org>
 Date: Fri, 11 Mar 2016 14:37:51 +0100
 Subject: Debian default root.key resides in /usr/share/dns/root.key
 
@@ -8,7 +8,7 @@ Subject: Debian default root.key resides in /usr/share/dns/root.key
  2 files changed, 3 insertions(+), 3 deletions(-)
 
 diff --git a/openpgpkey b/openpgpkey
-index e7ca0e6..00b3c84 100755
+index e423817..d3b80ef 100755
 --- a/openpgpkey
 +++ b/openpgpkey
 @@ -95,7 +95,7 @@ if __name__ == '__main__':
@@ -21,7 +21,7 @@ index e7ca0e6..00b3c84 100755
  
  	parser.add_argument('--uid', action='store', default='', help='override the uid (email address) within the key')
 @@ -125,7 +125,7 @@ if __name__ == '__main__':
- 				print >> sys.stdout, 'openpgpkey: %s is not a file. Unable to use it as rootanchor' % args.rootanchor
+ 				print('openpgpkey: %s is not a file. Unable to use it as rootanchor' % args.rootanchor, file=sys.stdout)
  				sys.exit(1)
  		else:
 -			cauldron = ( "/var/lib/unbound/root.anchor", "/var/lib/unbound/root.key", "/etc/unbound/root.key" )
@@ -30,11 +30,11 @@ index e7ca0e6..00b3c84 100755
  				if os.path.isfile(root):
  					rootanchor=root
 diff --git a/tlsa b/tlsa
-index 65c4d60..ff8c6b3 100755
+index ae925ea..1c6c949 100755
 --- a/tlsa
 +++ b/tlsa
 @@ -37,7 +37,7 @@ from hashlib import sha256, sha512
- from ipaddr import IPv4Address, IPv6Address
+ from ipaddress import IPv4Address, IPv6Address
  
  ROOTKEY="none"
 -cauldron = ( "/var/lib/unbound/root.anchor", "/var/lib/unbound/root.key", "/etc/unbound/root.key" )
diff --git a/debian/rules b/debian/rules
index 57e590a..a134445 100755
--- a/debian/rules
+++ b/debian/rules
@@ -10,7 +10,7 @@
 #export DH_VERBOSE=1
 
 %:
-	dh $@
+	dh $@ --with python3
 
 override_dh_installchangelogs:
 	dh_installchangelogs CHANGES
diff --git a/fedora/hash-slinger.spec b/fedora/hash-slinger.spec
index 2640543..a85b9a3 100644
--- a/fedora/hash-slinger.spec
+++ b/fedora/hash-slinger.spec
@@ -1,15 +1,16 @@
 Summary: Generate and verify various DNS records such as SSHFP, TLSA and OPENPGPKEY
 Name: hash-slinger
-Version: 2.6
+Version: 3.1
 Release: 1%{?dist}
 License: GPLv2+
 Url:  http://people.redhat.com/pwouters/%{name}/
 Source:  http://people.redhat.com/pwouters/%{name}/%{name}-%{version}.tar.gz
-Group: Applications/Internet
 # Only to regenerate the man page, which is shipped per default
 # Buildrequires: xmlto
-Requires: python-dns, python-argparse, unbound-python, python-ipaddr, python-gnupg >= 0.3.5-2
-Requires: openssh-clients >= 4, m2crypto
+BuildRequires: python3-devel
+Requires: python3 >= 3.4
+Requires: python3-dns, python3-unbound
+Requires: openssh-clients >= 4, python3-m2crypto, python3-gnupg >= 0.3.7
 BuildArch: noarch
 Obsoletes: sshfp < 2.0
 Provides: sshfp  = %{version}
@@ -17,10 +18,13 @@ Provides: sshfp  = %{version}
 %description
 This package contains various tools to generate special DNS records:
 
-sshfp      Generate RFC-4255 SSHFP DNS records from known_hosts or ssh-keyscan
-tlsa       Generate RFC-6698  TLSA DNS records via TLS
-openpgpkey Generate RFC-<TBD> OPENPGPKEY DNS records
-ipseckey   Generate RFC-4025 IPSECKEY DNS records on Libreswan IPsec servers
+sshfp       Generate RFC-4255 SSHFP DNS records from known_hosts files
+            or ssh-keyscan
+tlsa        Generate RFC-6698  TLSA DNS records via TLS
+openpgpkey  Generate draft-ietf-dane-openpgpkey DNS records from OpenPGP
+            keyrings
+ipseckey    Generate RFC-4025 IPSECKEY DNS records on Libreswan
+	    IPsec servers
 
 This package has incorporated the old 'sshfp' and 'swede' commands/packages
 
@@ -34,15 +38,25 @@ make all
 rm -rf ${RPM_BUILD_ROOT}
 make DESTDIR=${RPM_BUILD_ROOT} install
 
-%clean
-rm -rf ${RPM_BUILD_ROOT}
-
 %files 
 %doc BUGS CHANGES README COPYING
 %{_bindir}/*
 %doc %{_mandir}/man1/*
 
 %changelog
+* Wed Sep 21 2016 Paul Wouters <pwouters@redhat.com> - 2.7-3
+- Remove Requires: for python-argparse which is now part of python core
+
+* Sun Jan 03 2016 Paul Wouters <pwouters@redhat.com> - 2.7-1
+- Updated to 2.7 (updates to latest IETF drafts and RFCs, STARTTLS support)
+
+* Tue Jan 06 2015 Paul Wouters <pwouters@redhat.com> - 2.6-1
+- Updated to 2.6. Adds ipseckey, bugfixes for sshfp and openpgpkey
+
+* Sat Jan 18 2014 Paul Wouters <pwouters@redhat.com> - 2.5-1
+- Update to 2.5 which has OPENPGPKEY (draft 02) support
+- Added python-gnupg requires
+
 * Mon Jan  6 2014 Paul Wouters <pwouters@redhat.com> - 2.4-1
 - Updated to 2.4 which updates OPENPGPKEY support
 
@@ -50,7 +64,7 @@ rm -rf ${RPM_BUILD_ROOT}
 - Updated to 2.3 which adds support for OPENPGPKEY
 
 * Mon Jun 24 2013 Paul Wouters <pwouters@redhat.com> - 2.2-1
-- New version
+- Updated to 2.2 which fixes tsla usage 0 and --ipv4/--ipv6 options
 
 * Sat Sep 15 2012 Paul Wouters <pwouters@redhat.com> - 2.1-1
 - Updated COPYING to properly reflect GPLv2 "or later"
diff --git a/ipseckey b/ipseckey
index f6158ad..a61f455 100755
--- a/ipseckey
+++ b/ipseckey
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 # Show IPSECKEY records generated by libreswan IPsec
 # might work on some versions of older openswan as well
 #
@@ -18,7 +18,7 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-VERSION = "2.7"
+VERSION = "3.1"
 
 import os
 import sys
@@ -32,11 +32,11 @@ ipsec = "/usr/sbin/ipsec"
 if not os.path.isfile(ipsec):
 	ipsec = "/usr/local/sbin/ipsec"
 if not os.path.isfile(ipsec):
-	print >> sys.stderr, "ipseckey: ipsec command not found (not a libreswan or openswan IPsec servers?)"
+	print("ipseckey: ipsec command not found (not a libreswan or openswan IPsec servers?)", file=sys.stderr)
 	sys.exit(1)
 
 def show_version():
-	print >> sys.stderr, "sshfp version: " + VERSION
+	print("sshfp version: " + VERSION, file=sys.stderr)
 
 def main():
 
@@ -52,13 +52,13 @@ def main():
 		sys.exit(0)
 
 	if os.geteuid() != 0:
-		print >> sys.stderr, "ipseckey: root access is needed to read the IPsec NSS database for the public key"
+		print("ipseckey: root access is needed to read the IPsec NSS database for the public key", file=sys.stderr)
 		sys.exit(2)
 
-        cmd = [ipsec, "showhostkey", "--ipseckey"]
-        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        (stdout, stderr) = process.communicate()
-        print stdout
+	cmd = [ipsec, "showhostkey", "--ipseckey"]
+	process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+	(stdout, stderr) = process.communicate()
+	print(stdout)
 
 if __name__ == "__main__":
 	main()
diff --git a/openpgpkey b/openpgpkey
index e7ca0e6..e423817 100755
--- a/openpgpkey
+++ b/openpgpkey
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 #
 # openpgpkey: create OPENPGPKEY DNS record from a key in your keychain.
 #
@@ -22,7 +22,7 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-VERSION="2.7"
+VERSION="3.1"
 OPENPGPKEY=61
 
 import sys
@@ -45,17 +45,17 @@ def createOPENPGPKEY(email, gpgdisk, keyid, output, debug):
 	euser = sha256trunc(user)
 
 	if output == "rfc" or output == "both":
-		print "; keyid: %s" % keyid
-		print "%s._openpgpkey.%s. IN OPENPGPKEY %s" % (euser, domain, ekey64)
+		print("; keyid: %s" % keyid)
+		print("%s._openpgpkey.%s. IN OPENPGPKEY %s" % (euser, domain, ekey64))
 	if output ==  "generic" or output == "both":
 		if debug:
-			print "Length for generic record is %s" % len(ekey)
-		print "; keyid: %s" % keyid
-		print "%s._openpgpkey.%s. IN TYPE61 \# %s %s" % (euser, domain, len(ekey), asctohex(ekey))
+			print("Length for generic record is %s" % len(ekey))
+		print("; keyid: %s" % keyid)
+		print("%s._openpgpkey.%s. IN TYPE61 \# %s %s" % (euser, domain, len(ekey), asctohex(ekey)))
 
 def sha256trunc(data):
 	"""Compute SHA2-256 hash truncated to 28 octets."""
-	return hashlib.sha256(data).hexdigest()[:56]
+	return hashlib.sha256(data.encode(encoding="utf-8")).hexdigest()[:56]
 
 def getOPENPGPKEY(email,insecure_ok):
 	"""This function queries for an OPENPGPKEY DNS Resource Record and compares it with the local gnupg keyring"""
@@ -76,7 +76,7 @@ def getOPENPGPKEY(email,insecure_ok):
 				# The data is insecure and a secure lookup was requested
 				sys.exit("Error: query data is not secured by DNSSEC - use --insecure to override")
 			else:
-				print >> sys.stderr, 'Warning: query data was not secured by DNSSEC.'
+				print('Warning: query data was not secured by DNSSEC.', file=sys.stderr)
 		# If we are here the data was either secure or insecure data is accepted
 		return result.data.raw
 	else:
@@ -122,7 +122,7 @@ if __name__ == '__main__':
 			if os.path.isfile(args.rootanchor):
 				rootanchor = args.rootanchor
 			else:
-				print >> sys.stdout, 'openpgpkey: %s is not a file. Unable to use it as rootanchor' % args.rootanchor
+				print('openpgpkey: %s is not a file. Unable to use it as rootanchor' % args.rootanchor, file=sys.stdout)
 				sys.exit(1)
 		else:
 			cauldron = ( "/var/lib/unbound/root.anchor", "/var/lib/unbound/root.key", "/etc/unbound/root.key" )
@@ -140,13 +140,13 @@ if __name__ == '__main__':
 			if os.path.isfile(args.resolvconf):
 				resolvconf = args.resolvconf
 			else:
-				print >> sys.stdout, 'openpgpkey: %s is not a file. Unable to use it as resolv.conf' % args.resolvconf
+				print('openpgpkey: %s is not a file. Unable to use it as resolv.conf' % args.resolvconf, file=sys.stdout)
 				sys.exit(1)
 		ctx.resolvconf(resolvconf)
 
 		openpgpkeys = getOPENPGPKEY(args.email, args.insecure)
 		if len(openpgpkeys) == 0:
-			print >> sys.stderr, 'openpgpkey: Received nothing?'
+			print('openpgpkey: Received nothing?', file=sys.stderr)
 			sys.exit(1)
 		fdir = tempfile.mkdtemp(".gpg","openpgpkey-","/tmp/")
 		gpgnet = gnupg.GPG(gnupghome=fdir)
@@ -158,21 +158,21 @@ if __name__ == '__main__':
 				if args.keyid:
 					pubkey = gpgnet.export_keys(args.keyid, minimal=True)
 					if not pubkey:
-						print >> sys.stderr, 'openpgpkey: Requested keyid not present in received OpenPGP data'
+						print('openpgpkey: Requested keyid not present in received OpenPGP data', file=sys.stderr)
 						sys.exit(1)
 				if args.uid:
 					pubkey = gpgnet.export_keys(args.uid, minimal=True)
 					if not pubkey:
-						print >> sys.stderr, 'openpgpkey: Requested uid not present in received OpenPGP data'
+						print('openpgpkey: Requested uid not present in received OpenPGP data', file=sys.stderr)
 						for id in  gpgnet.list_keys()[0]['uids']:
-							print >> sys.stderr, "# %s"%id
+							print("# %s"%id, file=sys.stderr)
 						sys.exit(1)
 				if not args.uid and not args.keyid:
 					pubkey = gpgnet.export_keys(args.email, minimal=True)
-					print >> sys.stderr, 'openpgpkey: Received OpenPGP data does not contain a key with keyid %s'%args.email
-					print >> sys.stderr, '(add --uid <uid> to override with any of the below received uids)'
+					print('openpgpkey: Received OpenPGP data does not contain a key with keyid %s'%args.email, file=sys.stderr)
+					print('(add --uid <uid> to override with any of the below received uids)', file=sys.stderr)
 					for id in  gpgnet.list_keys()[0]['uids']:
-						print >> sys.stderr, "# %s"%id
+						print("# %s"%id, file=sys.stderr)
 					sys.exit(1)
 
 				pubkey = pubkey.replace("Version:","Comment: %s key obtained from DNS\nVersion:"%args.email)
@@ -180,7 +180,7 @@ if __name__ == '__main__':
 					pubkey = pubkey.replace("Version:","Comment: NOT VALIDATED BY DNSSEC\nVersion:")
 				else:
 					pubkey = pubkey.replace("Version:","Comment: key transfer was protected by DNSSEC\nVersion:")
-				print pubkey
+				print(pubkey)
 
 		if args.fetch:
 			sys.exit(0)
@@ -191,11 +191,11 @@ if __name__ == '__main__':
 		disk_keys = gpgdisk.list_keys()
 		for pkey in received_keys:
 			if args.debug:
-				print >> sys.stderr, "Received from DNS: Key-ID:%s Fingerprint:%s"%(pkey["keyid"], pkey["fingerprint"])
+				print("Received from DNS: Key-ID:%s Fingerprint:%s"%(pkey["keyid"], pkey["fingerprint"]), file=sys.stderr)
 			found = False
 			for dkey in disk_keys:
 				if args.debug:
-					print >> sys.stderr, "Local disk: Key-ID:%s Fingerprint:%s"%(dkey["keyid"], dkey["fingerprint"])
+					print("Local disk: Key-ID:%s Fingerprint:%s"%(dkey["keyid"], dkey["fingerprint"]), file=sys.stderr)
 				if pkey["keyid"] == dkey["keyid"] and pkey["fingerprint"] == dkey["fingerprint"]:
 					found = True
 			if found == False:
@@ -203,8 +203,8 @@ if __name__ == '__main__':
 				sys.exit("Received key with keyid %s was not found"%pkey["keyid"])
 			else:
 				if args.debug:
-					print >> sys.stderr, "Received key with keyid %s was found"%pkey["keyid"]
-		print "All OPENPGPKEY records matched with content from the local keyring"
+					print("Received key with keyid %s was found"%pkey["keyid"], file=sys.stderr)
+		print("All OPENPGPKEY records matched with content from the local keyring")
 		shutil.rmtree(fdir)
 		sys.exit(0)
 
@@ -225,7 +225,7 @@ if __name__ == '__main__':
 				for uid in pgpkey["uids"]:
 					if "<%s>"%args.email in uid:
 						if args.debug:
-							print >> sys.stderr,  "Found matching KeyID: %s (%s) for %s"%(pgpkey["keyid"], pgpkey["fingerprint"], uid)
+							print("Found matching KeyID: %s (%s) for %s"%(pgpkey["keyid"], pgpkey["fingerprint"], uid), file=sys.stderr)
 						ekey = gpgdisk.export_keys(pgpkey["keyid"],minimal=True, secret=False, armor=False)
 						createOPENPGPKEY(args.email, gpgdisk, pgpkey["keyid"], args.output, args.debug)
 						found = True
diff --git a/openpgpkey.1 b/openpgpkey.1
index 9be09ee..be206db 100644
--- a/openpgpkey.1
+++ b/openpgpkey.1
@@ -40,7 +40,7 @@ openpgpkey [\fB\-\-create\fR] [\fB\-\-insecure\fR] [\fB\-\-resolv\&.conf /PATH/T
 \fIuser@domain\fR
 .SH "DESCRIPTION"
 .PP
-openpgpkey generates RFC\-TBD OPENPGPKEY DNS records\&. To generate these records for older nameserver implementations that do not yet support the OPENPGPKEY record, specify
+openpgpkey generates RFC\-7929 OPENPGPKEY DNS records\&. To generate these records for older nameserver implementations that do not yet support the OPENPGPKEY record, specify
 \fI\-\-output generic\fR
 to output the openpgpkey data in Generic Record (RFC\-3597) format\&. Records are generated by taking all keys with the specified email address associated with it from the user\*(Aqs local GnuPG keychain\&.
 .PP
diff --git a/openpgpkey.1.xml b/openpgpkey.1.xml
index 6c2c876..f7470fd 100644
--- a/openpgpkey.1.xml
+++ b/openpgpkey.1.xml
@@ -37,7 +37,7 @@
 </refsect1>
 
 <refsect1 id='description'><title>DESCRIPTION</title>
-<para>openpgpkey generates  RFC-TBD OPENPGPKEY DNS records. To generate these records for older nameserver
+<para>openpgpkey generates  RFC-7929 OPENPGPKEY DNS records. To generate these records for older nameserver
 implementations that do not yet support the OPENPGPKEY record, specify <emphasis remap='I'>--output generic</emphasis>
 to output the openpgpkey data in Generic Record (RFC-3597) format. Records are generated by taking all keys with the specified
 email address associated with it from the user's local GnuPG keychain.
diff --git a/sshfp b/sshfp
index 6e72752..2fa34aa 100755
--- a/sshfp
+++ b/sshfp
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 #
 # Generate SSHFP DNS records (RFC4255) from knownhosts files or ssh-keyscan
 #
@@ -7,6 +7,7 @@
 # Copyright 2014 Gerald Turner <gturner@unzane.com>
 # Copyright 2015 Jean-Michel Nirgal Vourgere <jmv_deb@nirgal.com>
 # Copyright 2015 Dirk Stoecker <github@dstoecker.de>
+# Copyright 2019 Kishan Takoordyal <kishan@cyberstorm.mu>
 #
 # 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
@@ -22,7 +23,7 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-VERSION = "2.7"
+VERSION = "3.1"
 
 import os
 import sys
@@ -39,10 +40,10 @@ try:
 	import dns.query
 	import dns.zone
 except ImportError:
-	print >> sys.stderr, "sshfp requires the python-dns package from http://www.pythondns.org/"
-	print >> sys.stderr, "Fedora: yum install python-dns"
-	print >> sys.stderr, "Debian: apt-get install python-dnspython   (NOT python-dns!)"
-	print >> sys.stderr, "openSUSE: zypper in python-dnspython"
+	print("sshfp requires the python-dns package from http://www.pythondns.org/", file=sys.stderr)
+	print("Fedora: yum install python-dns", file=sys.stderr)
+	print("Debian: apt-get install python-dnspython   (NOT python-dns!)", file=sys.stderr)
+	print("openSUSE: zypper in python-dnspython", file=sys.stderr)
 	sys.exit(1)
 
 global all_hosts
@@ -57,7 +58,7 @@ global algo
 DEFAULT_KNOWN_HOSTS_FILE = "~/.ssh/known_hosts"
 
 def show_version():
-	print >> sys.stderr, "sshfp version: " + VERSION
+	print("sshfp version: " + VERSION, file=sys.stderr)
 
 def create_sshfp(hostname, keytype, keyblob, digesttype):
 	"""Creates an SSH fingerprint"""
@@ -71,6 +72,8 @@ def create_sshfp(hostname, keytype, keyblob, digesttype):
 	elif keytype == "ssh-ed25519":
 		# TBD http://tools.ietf.org/html/draft-moonesamy-sshfp-ed25519-01
 		keytype = "4"
+	elif keytype == "ssh-xmss":
+		keytype = "5"
 	else:
 		return ""
 	if digesttype == "sha1":
@@ -84,7 +87,7 @@ def create_sshfp(hostname, keytype, keyblob, digesttype):
 	try:
 		rawkey = base64.b64decode(keyblob)
 	except TypeError:
-		print >> sys.stderr, "FAILED on hostname "+hostname+" with keyblob "+keyblob
+		print("FAILED on hostname "+hostname+" with keyblob "+keyblob, file=sys.stderr)
 		return "ERROR"
 	fp = digest(rawkey).hexdigest().upper()
 	# check for Reverse entries
@@ -108,10 +111,10 @@ def get_known_host_entry(known_hosts, host):
 
 	Uses the ssh-keygen utility."""
 	cmd = ["ssh-keygen", "-f", known_hosts, "-F", host]
-	process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+	process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
 	(stdout, stderr) = process.communicate()
 	if not quiet and stderr:
-		print >> sys.stderr, stderr
+		print(stderr, file=sys.stderr)
 	outputl = []
 	for e in stdout.split("\n"):
 		if not e.startswith("#"):
@@ -127,7 +130,7 @@ def sshfp_from_file(khfile, wantedHosts):
 	try:
 		khfp = open(known_hosts)
 	except IOError:
-		print >> sys.stderr, "ERROR: failed to open file "+ known_hosts
+		print("ERROR: failed to open file "+ known_hosts, file=sys.stderr)
 		sys.exit(1)
 	hashed_known_hosts = False
 	if khfp.readline().startswith("|1|"):
@@ -136,7 +139,7 @@ def sshfp_from_file(khfile, wantedHosts):
 
 	fingerprints = []
 	if hashed_known_hosts and all_hosts:
-		print >> sys.stderr, "ERROR: %s is hashed, cannot use with -a" % known_hosts
+		print("ERROR: %s is hashed, cannot use with -a" % known_hosts, file=sys.stderr)
 		sys.exit(1)
 	elif hashed_known_hosts: #only looking for some known hosts
 		for host in wantedHosts:
@@ -145,7 +148,7 @@ def sshfp_from_file(khfile, wantedHosts):
 		try:
 			khfp = open(known_hosts)
 		except IOError:
-			print >> sys.stderr, "ERROR: failed to open file "+ known_hosts
+			print("ERROR: failed to open file "+ known_hosts, file=sys.stderr)
 			sys.exit(1)
 		data = khfp.read()
 		khfp.close()
@@ -160,7 +163,7 @@ def check_keytype(keytype, hostname):
 		if algo in keytype:
 			return True
 	if not quiet:
-		print >> sys.stderr, "Could only find key type %s for %s" % (keytype, hostname)
+		print("Could only find key type %s for %s" % (keytype, hostname), file=sys.stderr)
 	return False
 
 def check_hashed(entry, hostnames):
@@ -192,7 +195,7 @@ def process_records(data, hostnames):
 			(host, keytype, key) = record.split(" ")[:3]
 		except ValueError:
 			if not quiet:
-				print >> sys.stdout, "Print unable to read record '%s'" % record
+				print("Print unable to read record '%s'" % record, file=sys.stdout)
 			continue
 		if "," in host:
 			host = host.split(",")[0]
@@ -227,25 +230,25 @@ def get_record(domain, qtype):
 		if qtype == "NS":
 			return str(rdata.target)
 		else:
-			print >> sys.stderr, "ERROR: error in get_record, unknown type " + qtype
+			print("ERROR: error in get_record, unknown type " + qtype, file=sys.stderr)
 			sys.exit(1)
 
 def get_axfr_record(domain, nameserver):
 	try:
 		zone = dns.zone.from_xfr(dns.query.xfr(nameserver, domain, rdtype=dns.rdatatype.AXFR))
 	except dns.exception.FormError:
-		raise dns.exception.FormError, domain
+		raise dns.exception.FormError(domain)
 	else:
 		return  zone
 
 def sshfp_from_axfr(domain, nameserver):
 	if " " in domain:
-		print >> sys.stderr, "ERROR: space in domain '"+domain+"' can't be right, aborted"
+		print("ERROR: space in domain '"+domain+"' can't be right, aborted", file=sys.stderr)
 		sys.exit(1)
 	if not nameserver:
 		nameserver = get_record(domain, "NS")
 		if not nameserver:
-			print >> sys.stderr, "WARNING: no NS record found for domain "+domain+". trying as host record instead"
+			print("WARNING: no NS record found for domain "+domain+". trying as host record instead", file=sys.stderr)
 			# better then nothing
 			return sshfp_from_dns([domain])
 	hosts = []
@@ -253,8 +256,8 @@ def sshfp_from_axfr(domain, nameserver):
 	try:
 		# print "trying axfr for "+domain+"@"+nameserver
 		axfr = get_axfr_record(domain, nameserver)
-	except dns.exception.FormError, badDomain:
-		print >> sys.stderr, "AXFR error: %s - No permission or not authorative for %s; aborting" % (nameserver, badDomain)
+	except dns.exception.FormError as badDomain:
+		print("AXFR error: %s - No permission or not authorative for %s; aborting" % (nameserver, badDomain), file=sys.stderr)
 		sys.exit(1)
 
 	for (name, ttl, rdata) in axfr.iterate_rdatas('A'):
@@ -273,14 +276,14 @@ def sshfp_from_dns(hosts):
 	global algos
 
 	if "dsa" in algos:
-		print >> sys.stderr, "WARNING: openssh has obsoleted dsa/dss keys"
+		print("WARNING: openssh has obsoleted dsa/dss keys", file=sys.stderr)
 
 	cmd = ["ssh-keyscan", "-p", str(port), "-T", str(timeout), "-t", ",".join(algos)] + hosts
-	process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+	process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
 	(stdout, stderr) = process.communicate()
 	stderr = re.sub("#.*\n", "", stderr) # strip scan comments
 	if not quiet:
-		print >> sys.stderr, stderr
+		print(stderr, file=sys.stderr)
 	khdns = stdout
 	return process_records(khdns, hosts)
 	
@@ -341,9 +344,9 @@ def main():
 			action="append",
 			type="choice",
 			dest="algo",
-			choices=["rsa", "ecdsa", "ed25519", "dsa"],
+			choices=["rsa", "ecdsa", "ed25519", "dsa", "xmss"],
 			default=[],
-			help="key type to fetch (may be specified more than once, default rsa,ecdsa,ed25519,dsa)")
+			help="key type to fetch (may be specified more than once, default rsa,ecdsa,ed25519,dsa,xmss)")
 	parser.add_option("--digest",
 			action="append",
 			type="choice",
@@ -369,7 +372,7 @@ def main():
 	data = ""
 	trailing = options.trailing_dot
 	timeout = options.timeout
-	algos = options.algo or ["rsa", "ecdsa", "ed25519"]
+	algos = options.algo or ["rsa", "ecdsa", "ed25519", "xmss"]
 	digests = options.digest or ["sha256"]
 	all_hosts = options.all_hosts
 	port = options.port
@@ -379,16 +382,16 @@ def main():
 		show_version()
 		sys.exit(0)
 	if not quiet and port != 22:
-		print >> sys.stderr, "WARNING: non-standard port numbers are not designated in SSHFP records"
+		print("WARNING: non-standard port numbers are not designated in SSHFP records", file=sys.stderr)
 	if not quiet and options.known_hosts and options.scan:
-		print >> sys.stderr, "WARNING: Ignoring known hosts option -k , -s was passed"
+		print("WARNING: Ignoring known hosts option -k , -s was passed", file=sys.stderr)
 	if options.nameserver and not options.scan and not options.all_hosts:
-		print >> sys.stderr, "ERROR: Cannot specify -n without -s and -a"
+		print("ERROR: Cannot specify -n without -s and -a", file=sys.stderr)
 		sys.exit(1)
 	if not options.scan and options.all_hosts and args:
-		print >> sys.stderr, "WARNING: -a and hosts both passed, ignoring manual host list"
+		print("WARNING: -a and hosts both passed, ignoring manual host list", file=sys.stderr)
 	if not args and (not all_hosts):
-		print >> sys.stderr, "WARNING: Assuming -a"
+		print("WARNING: Assuming -a", file=sys.stderr)
 		all_hosts = True
 
 	if options.scan and options.all_hosts:
@@ -402,7 +405,7 @@ def main():
 		data = "\n".join(datal)
 	elif options.scan:	# Scan specified hosts
 		if not args:
-			print >> sys.stderr, "ERROR: You asked me to scan, but didn't give any hosts to scan"
+			print("ERROR: You asked me to scan, but didn't give any hosts to scan", file=sys.stderr)
 			sys.exit(1)
 		data = sshfp_from_dns(args)
 	else: # known_hosts
@@ -412,13 +415,13 @@ def main():
 		try:
 			fp = open(output, "w")
 		except IOError:
-			print >> sys.stderr, "ERROR: can't open '%s'' for writing" % output
+			print("ERROR: can't open '%s'' for writing" % output, file=sys.stderr)
 			sys.exit(1)
 		else:
 			fp.write(data)
 			fp.close()
 	else:
-		print data
+		print(data)
 
 if __name__ == "__main__":
 	main()
diff --git a/sshfp.1 b/sshfp.1
index 84e33ac..5be9e25 100644
--- a/sshfp.1
+++ b/sshfp.1
@@ -44,7 +44,7 @@ sshfp
 <digest>] [\fB\-n <nameserver\fR>\fI] <domain1\fR> [\fIdomain2\fR] <\fIhost1\fR> [\fIhost2 \&.\&.\&.\fR] >
 .SH "DESCRIPTION"
 .PP
-sshfp generates RFC\-4255 SSHFP DNS records based on the public keys stored in a known_hosts file, which implies the user has previously trusted this key, or public keys can be obtained by using ssh\-keyscan (1)\&. Using ssh\-keyscan (1) implies a secure path to connect to the hosts being scanned\&. It also implies a trust in the DNS to obtain the IP address of the hostname to be scanned\&. If the nameserver of the domain allows zone tranfers (AXFR), an entire domain can be processed for all its A records\&.
+sshfp generates RFC\-4255 SSHFP DNS records based on the public keys stored in a known_hosts file, which implies the user has previously trusted this key, or public keys can be obtained by using ssh\-keyscan (1)\&. Using ssh\-keyscan (1) implies a secure path to connect to the hosts being scanned\&. It also implies a trust in the DNS to obtain the IP address of the hostname to be scanned\&. If the nameserver of the domain allows zone transfers (AXFR), an entire domain can be processed for all its A records\&.
 .SH "OPTIONS"
 .PP
 \fB\-s / \-\-scan\fR <\fIhostname1\fR> [hostname2 \&.\&.\&.]
@@ -59,12 +59,12 @@ Obtain public SSH keys from a known_hosts file\&. Defaults to using ~/\&.ssh/kno
 .PP
 \fB\-a / \-\-all\fR
 .RS 4
-Scan all hosts in the known_hosts file when used with \-k\&. When used with \-s, it will attempt an zone transfer (AXFR) to obtain all A records in the domain specified\&.
+Scan all hosts in the known_hosts file when used with \-k\&. When used with \-s, it will attempt a zone transfer (AXFR) to obtain all A records in the domain specified\&.
 .RE
 .PP
 \fB\-d / \-\-trailing\-dot\fR
 .RS 4
-Add a trailing dot to the hostname in the SSHFP records\&. It is not possible to determine whether a known_hosts or dns query is for a FQDN (eg www\&.redhat\&.com) or not (eg www) or not (unless \-d domainname \-a is used, in which case a trailing dot is always appended)\&. Non\-FQDN get their domainname appended through /etc/resolv\&.conf These non\-FQDN will happen when using a non\-FQDN (eg sshfp \-k www) or known_hosts entries obtained by running ssh www\&.sub where \&.domain\&.com is implied\&. When \-d is used, all hostnames not ending with a dot, that at least contain two parts in their hostname (eg www\&.sub but not www get a trailing dot\&. Note that the output of sshfp can also just be manually editted for trailing dots\&.
+Add a trailing dot to the hostname in the SSHFP records\&. It is not possible to determine whether a known_hosts or dns query is for a FQDN (eg www\&.redhat\&.com) or not (eg www) or not (unless \-d domainname \-a is used, in which case a trailing dot is always appended)\&. Non\-FQDN get their domainname appended through /etc/resolv\&.conf These non\-FQDN will happen when using a non\-FQDN (eg sshfp \-k www) or known_hosts entries obtained by running ssh www\&.sub where \&.domain\&.com is implied\&. When \-d is used, all hostnames not ending with a dot, that at least contain two parts in their hostname (eg www\&.sub but not www get a trailing dot\&. Note that the output of sshfp can also just be manually edited for trailing dots\&.
 .RE
 .PP
 \fB\-o / \-\-output\fR <\fIfilename\fR>
diff --git a/sshfp.1.xml b/sshfp.1.xml
index 1c969fe..8d71017 100644
--- a/sshfp.1.xml
+++ b/sshfp.1.xml
@@ -29,7 +29,7 @@ stored in a known_hosts file, which implies the user has
 previously trusted this key, or public keys can be obtained
 by using ssh-keyscan (1). Using ssh-keyscan (1) implies a secure path to connect to the hosts being scanned.
 It also implies a trust in the DNS to obtain the IP address of
-the hostname to be scanned. If the nameserver of the domain allows zone tranfers (AXFR), an entire domain can be processed for all its A records.</para>
+the hostname to be scanned. If the nameserver of the domain allows zone transfers (AXFR), an entire domain can be processed for all its A records.</para>
 </refsect1>
 
 <refsect1 id='options'><title>OPTIONS</title>
@@ -49,7 +49,7 @@ the hostname to be scanned. If the nameserver of the domain allows zone tranfers
   <varlistentry>
   <term><option>-a / --all</option></term>
   <listitem>
-<para>Scan all hosts in the known_hosts file when used with -k. When used with -s, it will attempt an zone transfer (AXFR) to obtain all A records in the domain specified.</para>
+<para>Scan all hosts in the known_hosts file when used with -k. When used with -s, it will attempt a zone transfer (AXFR) to obtain all A records in the domain specified.</para>
   </listitem>
   </varlistentry>
   <varlistentry>
@@ -63,7 +63,7 @@ These non-FQDN will happen when using a non-FQDN (eg sshfp -k www)
 or known_hosts entries obtained by running ssh www.sub where .domain.com is implied.
 When -d is used, all hostnames not ending with a dot, that at least contain two parts
 in their hostname (eg www.sub but not www get a trailing dot. Note that the output of
-sshfp can also just be manually editted for trailing dots.</para>
+sshfp can also just be manually edited for trailing dots.</para>
   </listitem>
   </varlistentry>
   <varlistentry>
diff --git a/tlsa b/tlsa
index 65c4d60..ae925ea 100755
--- a/tlsa
+++ b/tlsa
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 # tlsa - A tool to create DANE/TLSA records. (called 'swede' before)
 #
@@ -7,7 +7,7 @@
 #
 # Copyright 2012 Pieter Lexis <pieter.lexis@os3.nl>
 # Copyright 2014 Paul Wouters <pwouters@redhat.com>
-# Copyright 2015 Dirk Stoecker <hashslinger@dstoecker.de>
+# Copyright 2015-2019 Dirk Stoecker <hashslinger@dstoecker.de>
 #
 # 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
@@ -23,7 +23,7 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-VERSION="2.7"
+VERSION="3.1"
 
 import sys
 import os
@@ -32,9 +32,9 @@ import unbound
 import subprocess
 import re
 from M2Crypto import X509, SSL, BIO, m2
-from binascii import a2b_hex, b2a_hex
+from binascii import b2a_hex
 from hashlib import sha256, sha512
-from ipaddr import IPv4Address, IPv6Address
+from ipaddress import IPv4Address, IPv6Address
 
 ROOTKEY="none"
 cauldron = ( "/var/lib/unbound/root.anchor", "/var/lib/unbound/root.key", "/etc/unbound/root.key" )
@@ -71,17 +71,17 @@ def genTLSA(hostname, protocol, port, certificate, output='rfc', usage=1, select
 		return record.getRecord(generic=True)
 	return record.getRecord()
 
-def genRecords(hostname, protocol, port, chain, output='rfc', usage=1, selector=0, mtype=1):
+def genRecords(hostname, address, protocol, port, chain, output='rfc', usage=1, selector=0, mtype=1):
 	cert = None
 	chained = checkChainLink(chain)[0]
 	if not chained:
-		print "WARN: Certificates don't chain"
+		print("WARN: Certificates don't chain")
 	certsleft = len(chain)
 	for chaincert in chain:
 		certsleft -= 1
 		if usage == 1 or usage == 3:
 			# The first cert is the end-entity cert
-			print 'Got a certificate with Subject: %s' % chaincert.get_subject()
+			print('Got a certificate for %s with Subject: %s' % (address, chaincert.get_subject()))
 			cert = chaincert
 			break
 		else:
@@ -90,7 +90,7 @@ def genRecords(hostname, protocol, port, chain, output='rfc', usage=1, selector=
 					sys.stdout.write('Got a certificate with the following Subject:\n\t%s\nUse this as certificate to match? [y/N] ' % chaincert.get_subject())
 					input_ok = False
 					while not input_ok:
-						user_input = raw_input()
+						user_input = input()
 						if user_input in ['','n','N']:
 							input_ok=True
 						elif user_input in ['y', 'Y']:
@@ -106,37 +106,37 @@ def genRecords(hostname, protocol, port, chain, output='rfc', usage=1, selector=
 
 	if cert: # Print the requested records based on the retrieved certificates
 		if output == 'both':
-			print genTLSA(hostname, protocol, port, cert, 'draft', usage, selector, mtype)
-			print genTLSA(hostname, protocol, port, cert, 'rfc', usage, selector, mtype)
+			print(genTLSA(hostname, protocol, port, cert, 'draft', usage, selector, mtype))
+			print(genTLSA(hostname, protocol, port, cert, 'rfc', usage, selector, mtype))
 		else:
-			print genTLSA(hostname, protocol, port, cert, output, usage, selector, mtype)
+			print(genTLSA(hostname, protocol, port, cert, output, usage, selector, mtype))
 
 	# Clear the cert from memory (to stop M2Crypto from segfaulting)
 	cert=None
 
 def getA(hostname, secure=True):
 	"""Gets a list of A records for hostname, returns a list of ARecords"""
-	records = ""
+	records = []
 	try:
 		records = getRecords(hostname, rrtype='A', secure=secure)
-	except InsecureLookupException, e:
-		print str(e)
-	except DNSLookupError, e:
-		print 'Unable to resolve %s: %s' % (hostname, str(e))
+	except InsecureLookupException as e:
+		print(str(e))
+	except DNSLookupError as e:
+		print('Unable to resolve %s: %s' % (hostname, str(e)))
 	ret = []
 	for record in records:
 		ret.append(ARecord(hostname, str(IPv4Address(int(b2a_hex(record),16)))))
 	return ret
 
 def getAAAA(hostname, secure=True):
-	"""Gets a list of A records for hostname, returns a list of AAAARecords"""
-	records = ""
+	"""Gets a list of AAAA records for hostname, returns a list of AAAARecords"""
+	records = []
 	try:
 		records = getRecords(hostname, rrtype='AAAA', secure=secure)
-	except InsecureLookupException, e:
-		print str(e)
-	except DNSLookupError, e:
-		print 'Unable to resolve %s: %s' % (hostname, str(e))
+	except InsecureLookupException as e:
+		print(str(e))
+	except DNSLookupError as e:
+		print('Unable to resolve %s: %s' % (hostname, str(e)))
 	ret = []
 	for record in records:
 		ret.append(AAAARecord(hostname, str(IPv6Address(int(b2a_hex(record),16)))))
@@ -210,13 +210,13 @@ def getRecords(hostname, rrtype='A', secure=True, noresolver=False):
 			if secure:
 				if not noresolver and resolvconf:
 					retval = getRecords(hostname, rrtype, secure, True)
-					print >> sys.stderr, 'Warning: initial query using resolver config file was not secure (try option --resolvconf="").'
+					print('Warning: initial query using resolver config file was not secure (try option --resolvconf="").', file=sys.stderr)
 					resolvconf = None
 					return retval
 				# The data is insecure and a secure lookup was requested
 				raise InsecureLookupException('Error: Answer was not DNSSEC-secure')
 			else:
-				print >> sys.stderr, 'Warning: query data is not secure.'
+				print('Warning: query data is not secure.', file=sys.stderr)
 		# If we are here the data was either secure or insecure data is accepted
 		return result.data.raw
 	else:
@@ -230,21 +230,21 @@ def sslStartTLSConnect(connection, addr, starttls=None):
             # primitive method, no error checks yet
             if starttls == "smtp":
                 data = connection.socket.recv(500)
-                connection.socket.send("EHLO M2Crypto\r\n")
+                connection.socket.send("EHLO M2Crypto\r\n".encode('ascii'))
                 data = connection.socket.recv(500)
-                connection.socket.send("STARTTLS\r\n")
+                connection.socket.send("STARTTLS\r\n".encode('ascii'))
                 data = connection.socket.recv(500)
             elif starttls == "imap":
                 data = connection.socket.recv(500)
-                connection.socket.send(". STARTTLS\r\n")
+                connection.socket.send(". STARTTLS\r\n".encode('ascii'))
                 data = connection.socket.recv(500)
             elif starttls == "ftp":
                 data = connection.socket.recv(500)
-                connection.socket.send("AUTH TLS\r\n")
+                connection.socket.send("AUTH TLS\r\n".encode('ascii'))
                 data = connection.socket.recv(500)
             elif starttls == "pop3":
                 data = connection.socket.recv(500)
-                connection.socket.send("STLS\r\n")
+                connection.socket.send("STLS\r\n".encode('ascii'))
                 data = connection.socket.recv(500)
         connection.setup_ssl()
         connection.set_connect_state()
@@ -261,7 +261,7 @@ def getHash(certificate, mtype):
 	"""
 	certificate = certificate.as_der()
 	if mtype == 0:
-		return b2a_hex(certificate)
+		return certificate.hex()
 	elif mtype == 1:
 		return sha256(certificate).hexdigest()
 	elif mtype == 2:
@@ -285,19 +285,19 @@ def getTLSA(hostname, port=443, protocol='tcp', secure=True):
 			records = getRecords('*._%s.%s' % (protocol.lower(), hostname), rrtype=52, secure=secure)
 		else:
 			records = getRecords('_%s._%s.%s' % (port, protocol.lower(), hostname), rrtype=52, secure=secure)
-	except InsecureLookupException, e:
-		print str(e)
+	except InsecureLookupException as e:
+		print(str(e))
 		sys.exit(1)
-	except DNSLookupError, e:
-		print 'Unable to resolve %s: %s' % (hostname, str(e))
+	except DNSLookupError as e:
+		print('Unable to resolve %s: %s' % (hostname, str(e)))
 		sys.exit(1)
 	ret = []
 	for record in records:
 		hexdata = b2a_hex(record)
 		if port == '*':
-			ret.append(TLSARecord('*._%s.%s' % (protocol.lower(), hostname), int(hexdata[0:2],16), int(hexdata[2:4],16), int(hexdata[4:6],16), hexdata[6:]))
+			ret.append(TLSARecord('*._%s.%s' % (protocol.lower(), hostname), int(hexdata[0:2],16), int(hexdata[2:4],16), int(hexdata[4:6],16), hexdata[6:].decode('ascii')))
 		else:
-			ret.append(TLSARecord('_%s._%s.%s' % (port, protocol.lower(), hostname), int(hexdata[0:2],16), int(hexdata[2:4],16), int(hexdata[4:6],16), hexdata[6:]))
+			ret.append(TLSARecord('_%s._%s.%s' % (port, protocol.lower(), hostname), int(hexdata[0:2],16), int(hexdata[2:4],16), int(hexdata[4:6],16), hexdata[6:].decode('ascii')))
 	return ret
 
 def verifyCertMatch(record, cert):
@@ -351,13 +351,13 @@ def verifyCertNameWithHostName(cert, hostname, with_msg=False):
 			return True
 
 	if with_msg:
-		print 'WARNING: Name on the certificate (Subject: %s, SubjectAltName: %s) doesn\'t match requested hostname (%s).' % (str(cert.get_subject()), cert.get_ext('subjectAltName').get_value(), hostname)
+		print('WARNING: Name on the certificate (Subject: %s, SubjectAltName: %s) doesn\'t match requested hostname (%s).' % (str(cert.get_subject()), cert.get_ext('subjectAltName').get_value(), hostname))
 	return False
 
 def checkChainLink(chain, record=None):
 	previous_issuer = None
 	chained = True
-	matched = False
+	matched = None
 	for cert in chain:
 		if previous_issuer:
 			if not str(previous_issuer) == str(cert.get_subject()): # The chain cannot be valid
@@ -365,27 +365,35 @@ def checkChainLink(chain, record=None):
 				break
 		previous_issuer = cert.get_issuer()
 		if record and verifyCertMatch(record, cert):
-			matched = True
+			matched = cert
 	return chained, matched
 
 def getLocalChain(filename, debug):
 	"""Returns list of M2Crypto.X509.X509 objects and verification result"""
 	chain = []
 	bio = BIO.openfile(filename)
+	Err = None
 	while True:
-		cptr = m2.x509_read_pem(bio._ptr())
+		try:
+			cptr = m2.x509_read_pem(bio._ptr())
+		except Exception as e:
+			Err = e
+			break;
 		if not cptr:
 			break
 		chain.append(X509.X509(cptr, _pyfree=1))
 	if not chain:
-		raise X509Error(Err.get_error())
+		if Err:
+			raise
+		else:
+			raise Exception("Could not load %s" % filename)
 	# FIXME - is this possible using the library (without a call to openssl tool)?
 	cmd = ["openssl", "verify", filename]
 	process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 	(stdout, stderr) = process.communicate()
 	if debug:
-		print >> sys.stderr, stderr
-	if stdout.endswith("OK\n"):
+		print(stderr, file=sys.stderr)
+	if stdout.endswith(b"OK\n"):
 		verify_result = 0
 	else:
 		verify_result = "%s%s" % (stdout, stderr)
@@ -405,25 +413,25 @@ def verifyChain(chain, verify_result, pre_exit, local, source):
 
 	if not verifyCertNameWithHostName(cert=chain[0], hostname=str(args.host), with_msg=True):
 		# The name on the cert doesn't match the hostname... we don't verify the TLSA record
-		print 'Caution: %s does not match hostname (%s)' % (text_cert, source)
+		print('Caution: %s does not match hostname (%s)' % (text_cert, source))
 	ut = usageText(record.usage)
 	if record.usage == 1: # End-host cert
 		chained, matched = checkChainLink((chain[0],), record)
 		if not chained:
-			print "WARN: Certificates don't chain"
+			print("WARN: Certificates don't chain")
 		if matched:
 			if verify_result == 0: # The cert chains to a valid CA cert according to the system-certificates
-				print 'SUCCESS (%s): %s matches the one mentioned in the TLSA record and chains to a valid CA certificate (%s)' % (ut, text_cert, source)
+				print('SUCCESS (%s): %s matches the one mentioned in the TLSA record and chains to a valid CA certificate (%s)' % (ut, text_cert, source))
 			else:
 				if local:
 					reason = verify_result
 				else:
 					reason = getVerificationErrorReason(verify_result)
-				print 'FAIL (%s): %s matches the one mentioned in the TLSA record but the following error was raised during PKIX validation (%s): %s' % (ut, text_cert, source, reason)
+				print('FAIL (%s): %s matches the one mentioned in the TLSA record but the following error was raised during PKIX validation (%s): %s' % (ut, text_cert, source, reason))
 				if pre_exit == 0: pre_exit = 2
-			if args.debug: print 'The matched certificate has Subject: %s' % cert.get_subject()
+			if args.debug: print('The matched certificate has Subject: %s' % cert.get_subject())
 		else:
-			print 'FAIL: %s does not match the TLSA record (%s)' % (text_cert, source)
+			print('FAIL: %s does not match the TLSA record (%s)' % (text_cert, source))
 			if pre_exit == 0: pre_exit = 2
 
 	elif record.usage == 0: # CA constraint
@@ -435,24 +443,24 @@ def verifyChain(chain, verify_result, pre_exit, local, source):
 		# Remove the first (= End-Entity cert) from the chain
 		chained, matched = checkChainLink(chain[1:], record)
 		if not chained:
-			print "WARN: Certificates don't chain"
+			print("WARN: Certificates don't chain")
 		if matched:
 			if cert.check_ca():
 				if verify_result == 0:
-					print 'SUCCESS (%s): A %s matches the one mentioned in the TLSA record and is a CA certificate (%s)' % (ut, text_chain, source)
+					print('SUCCESS (%s): A %s matches the one mentioned in the TLSA record and is a CA certificate (%s)' % (ut, text_chain, source))
 				else:
 					if local:
 						reason = verify_result
 					else:
 						reason = getVerificationErrorReason(verify_result)
-					print 'FAIL (%s): A %s matches the one mentioned in the TLSA record and is a CA certificate, but the following error was raised during PKIX validation (%s): %s' % (ut, text_chain, source, reason)
+					print('FAIL (%s): A %s matches the one mentioned in the TLSA record and is a CA certificate, but the following error was raised during PKIX validation (%s): %s' % (ut, text_chain, source, reason))
 					if pre_exit == 0: pre_exit = 2
 			else:
-				print 'FAIL (%s): A %s matches the one mentioned in the TLSA record but is not a CA certificate (%s)' % (ut, text_chain, source)
+				print('FAIL (%s): A %s matches the one mentioned in the TLSA record but is not a CA certificate (%s)' % (ut, text_chain, source))
 				if pre_exit == 0: pre_exit = 2
-			if args.debug: print 'The matched certificate has Subject: %s' % cert.get_subject()
+			if args.debug: print('The matched certificate has Subject: %s' % cert.get_subject())
 		else:
-			print 'FAIL (%s): No %s matches the TLSA record (%s)' % (ut, text_chain, source)
+			print('FAIL (%s): No %s matches the TLSA record (%s)' % (ut, text_chain, source))
 			if pre_exit == 0: pre_exit = 2
 
 	elif record.usage == 2: # Usage 2, use the cert in the record as trust anchor
@@ -462,24 +470,24 @@ def verifyChain(chain, verify_result, pre_exit, local, source):
 		chained, matched = checkChainLink(chain, record)
 		if matched:
 			if not chained:
-				print "WARN: Certificates don't chain"
-			print 'SUCCESS (%s): A %s (including the end-entity certificate) matches the TLSA record (%s)' % (ut, text_chain, source)
-			if args.debug: print 'The matched certificate has Subject: %s' % cert.get_subject()
+				print("WARN: Certificates don't chain")
+			print('SUCCESS (%s): A %s (including the end-entity certificate) matches the TLSA record (%s)' % (ut, text_chain, source))
+			if args.debug: print('The matched certificate has Subject: %s' % matched.get_subject())
 		else:
 			if not chained:
-				print "FAIL: Certificates don't chain"
-			print 'FAIL (%s): No %s (including the end-entity certificate) matches the TLSA record (%s)' % (ut, text_chain, source)
+				print("FAIL: Certificates don't chain")
+			print('FAIL (%s): No %s (including the end-entity certificate) matches the TLSA record (%s)' % (ut, text_chain, source))
 			if pre_exit == 0: pre_exit = 2
 
 	elif record.usage == 3: # EE cert MUST match
 		chained, matched = checkChainLink((chain[0],), record)
 		if not chained:
-			print "WARN: Certificates don't chain"
+			print("WARN: Certificates don't chain")
 		if matched:
-			print 'SUCCESS (%s): %s matches the TLSA record (%s)' % (ut, text_cert, source)
-			if args.debug: print 'The matched certificate has Subject: %s' % chain[0].get_subject()
+			print('SUCCESS (%s): %s matches the TLSA record (%s)' % (ut, text_cert, source))
+			if args.debug: print('The matched certificate has Subject: %s' % chain[0].get_subject())
 		else:
-			print 'FAIL (%s): %s does not match the TLSA record (%s)' % (ut, text_cert, source)
+			print('FAIL (%s): %s does not match the TLSA record (%s)' % (ut, text_cert, source))
 			if pre_exit == 0: pre_exit = 2
 	return pre_exit
 
@@ -498,7 +506,7 @@ class TLSARecord:
 			self.usage = int(usage)
 			self.selector = int(selector)
 			self.mtype = int(mtype)
-			self.cert = str(cert)
+			self.cert = cert
 		except:
 			raise Exception('Invalid value passed, unable to create a TLSARecord')
 
@@ -654,20 +662,20 @@ if __name__ == '__main__':
 		if os.path.isfile(args.rootkey):
 			ROOTKEY = args.rootkey
 		else:
-			print ("ignored specified non-existing rootkey file %s"%args.rootkey)
+			print("ignored specified non-existing rootkey file %s"%args.rootkey)
 
 	# check whether it's ASCII or needs to be converted into Punnycode
 	try:
-		args.host.decode('ascii')
-	except UnicodeDecodeError:
-		args.host = unicode(args.host, 'utf-8').encode("idna")
+		args.host.encode('ascii')
+	except UnicodeEncodeError:
+		args.host = str(args.host.encode('idna'), 'utf-8')
 
 	if args.host[-1] != '.':
 		args.host += '.'
 	snihost = args.host[0:-1]
 
 	if not args.starttls:
-		if args.port == "25":
+		if args.port == "25" or args.port == "587":
 			args.starttls = "smtp"
 		elif args.port == "143":
 			args.starttls = "imap"
@@ -683,7 +691,7 @@ if __name__ == '__main__':
 		if os.path.isfile(args.resolvconf):
 			resolvconf = args.resolvconf
 		else:
-			print >> sys.stdout, '%s is not a file. Unable to use it as resolv.conf' % args.resolvconf
+			print('%s is not a file. Unable to use it as resolv.conf' % args.resolvconf, file=sys.stdout)
 			sys.exit(1)
 	else:
 		resolvconf = None
@@ -700,20 +708,20 @@ if __name__ == '__main__':
 			pre_exit = 0
 			# First, check if the first three fields have correct values.
 			if args.debug:
-				print 'Received the following record for name %s:' % record.name
-				print '\tUsage:\t\t\t\t%d (%s)' % (record.usage, {0:'CA Constraint [PKIX-CA]', 1:'End-Entity Constraint + chain to CA [PKIX-EE]', 2:'Trust Anchor [DANE-TA]', 3:'End-Entity [DANE-EE]'}.get(record.usage, 'INVALID'))
-				print '\tSelector:\t\t\t%d (%s)' % (record.selector, {0:'Certificate [Cert]', 1:'SubjectPublicKeyInfo [SPKI]'}.get(record.selector, 'INVALID'))
-				print '\tMatching Type:\t\t\t%d (%s)' % (record.mtype, {0:'Full Certificate', 1:'SHA-256', 2:'SHA-512'}.get(record.mtype, 'INVALID'))
-				print '\tCertificate for Association:\t%s' % record.cert
+				print('Received the following record for name %s:' % record.name)
+				print('\tUsage:\t\t\t\t%d (%s)' % (record.usage, {0:'CA Constraint [PKIX-CA]', 1:'End-Entity Constraint + chain to CA [PKIX-EE]', 2:'Trust Anchor [DANE-TA]', 3:'End-Entity [DANE-EE]'}.get(record.usage, 'INVALID')))
+				print('\tSelector:\t\t\t%d (%s)' % (record.selector, {0:'Certificate [Cert]', 1:'SubjectPublicKeyInfo [SPKI]'}.get(record.selector, 'INVALID')))
+				print('\tMatching Type:\t\t\t%d (%s)' % (record.mtype, {0:'Full Certificate', 1:'SHA-256', 2:'SHA-512'}.get(record.mtype, 'INVALID')))
+				print('\tCertificate for Association:\t%s' % record.cert)
 
 			try:
 				record.isValid(raiseException=True)
-			except RecordValidityException, e:
-				print >> sys.stderr, 'Error: %s' % str(e)
+			except RecordValidityException as e:
+				print('Error: %s' % str(e), file=sys.stderr)
 				continue
 			else:
 				if args.debug:
-					print 'This record is valid (well-formed).'
+					print('This record is valid (well-formed).')
 
 			if args.only_rr:
 				# Go to the next record
@@ -721,11 +729,11 @@ if __name__ == '__main__':
 
 			# When we are here, The user also wants to verify the certificates with the record
 			if args.protocol != 'tcp':
-				print >> sys.stderr, 'Only SSL over TCP is supported (sorry)'
+				print('Only SSL over TCP is supported (sorry)', file=sys.stderr)
 				sys.exit(0)
 
 			if args.debug:
-				print 'Attempting to verify the record with the TLS service...'
+				print('Attempting to verify the record with the TLS service...')
 
 			if not args.ipv4 and not args.ipv6:
 				addresses = getA(args.host, secure=secure) + getAAAA(args.host, secure=secure)
@@ -738,12 +746,12 @@ if __name__ == '__main__':
 				try:
 					chain, verify_result = getLocalChain(args.certificate, args.debug)
 					pre_exit = verifyChain(chain, verify_result, pre_exit, True, args.certificate)
-				except Exception, e:
-					print 'Could not verify local certificate: %s.' % e
+				except Exception as e:
+					print('Could not verify local certificate: %s.' % e)
 					sys.exit(0)
 			for address in addresses:
 				if args.debug:
-					print 'Got the following IP: %s' % str(address)
+					print('Got the following IP: %s' % str(address))
 				# We do the certificate handling here, as M2Crypto keeps segfaulting when we do it in a method
 				ctx = SSL.Context()
 				if os.path.isfile(args.ca_cert):
@@ -751,7 +759,7 @@ if __name__ == '__main__':
 				elif os.path.exists(args.ca_cert):
 					if ctx.load_verify_locations(capath=args.ca_cert) != 1: raise Exception('No CA certs')
 				else:
-					print >> sys.stderr, '%s is neither a file nor a directory, unable to continue' % args.ca_cert
+					print('%s is neither a file nor a directory, unable to continue' % args.ca_cert, file=sys.stderr)
 					sys.exit(1)
 				# Don't error when the verification fails in the SSL handshake
 				ctx.set_verify(SSL.verify_none, depth=9)
@@ -764,11 +772,11 @@ if __name__ == '__main__':
 				try:
 					connection.set_tlsext_host_name(snihost)
 					if(args.debug):
-						print 'Did set servername %s' % snihost
+						print('Did set servername %s' % snihost)
 				except AttributeError:
-					print 'Could not set SNI (old M2Crypto version?)'
+					print('Could not set SNI (old M2Crypto version?)')
 				except:
-					print 'Could not set SNI'
+					print('Could not set SNI')
 				try:
 					if args.starttls:
 						sslStartTLSConnect(connection, (str(address), int(args.port)), args.starttls)
@@ -778,11 +786,11 @@ if __name__ == '__main__':
 				#except TypeError:
 				#	print 'Cannot connect to %s (old M2Crypto version not supporting start script?)' % address
 				#	continue
-				except SSL.Checker.WrongHost, e:
+				except SSL.Checker.WrongHost as e:
 					# The name on the remote cert doesn't match the hostname because we connect on IP, not hostname (as we want secure lookup)
 					pass
-				except socket.error, e:
-					print 'Cannot connect to %s: %s' % (address, str(e))
+				except socket.error as e:
+					print('Cannot connect to %s: %s' % (address, str(e)))
 					continue
 				chain = connection.get_peer_cert_chain()
 				verify_result = connection.get_verify_result()
@@ -803,16 +811,16 @@ if __name__ == '__main__':
 		cert = None
 		if not args.certificate:
 			if args.protocol != 'tcp':
-				print >> sys.stderr, 'Only SSL over TCP is supported (sorry)'
+				print('Only SSL over TCP is supported (sorry)', file=sys.stderr)
 				sys.exit(1)
 			if args.debug:
-				print 'No certificate specified on the commandline, attempting to retrieve it from the server %s' % (args.host)
+				print('No certificate specified on the commandline, attempting to retrieve it from the server %s' % (args.host))
 			connection_port = args.port
 			if args.port == '*':
 				sys.stdout.write('The port specified on the commandline is *, please specify the port of the TLS service on %s (443): ' % args.host)
 				input_ok = False
 				while not input_ok:
-					user_input = raw_input()
+					user_input = input()
 					if user_input == '':
 						connection_port = 443
 						break
@@ -833,13 +841,13 @@ if __name__ == '__main__':
 				else:
 					addresses = getAAAA(args.host, secure=secure)
 
-			except InsecureLookupException, e:
-				print >> sys.stderr, str(e)
+			except InsecureLookupException as e:
+				print(str(e), file=sys.stderr)
 				sys.exit(1)
 
 			for address in addresses:
 				if args.debug:
-					print 'Attempting to get certificate from %s' % str(address)
+					print('Attempting to get certificate from %s' % str(address))
 				# We do the certificate handling here, as M2Crypto keeps segfaulting when try to do stuff with the cert if we don't
 				ctx = SSL.Context()
 				ctx.set_verify(SSL.verify_none, depth=9)
@@ -852,11 +860,11 @@ if __name__ == '__main__':
 				try:
 					connection.set_tlsext_host_name(snihost)
 					if(args.debug):
-						print 'Did set servername %s' % snihost
+						print('Did set servername %s' % snihost)
 				except AttributeError:
-					print 'Could not set SNI (old M2Crypto version?)'
+					print('Could not set SNI (old M2Crypto version?)')
 				except:
-					print 'Could not set SNI'
+					print('Could not set SNI')
 				try:
 					if args.starttls:
 						sslStartTLSConnect(connection, (str(address), int(connection_port)), args.starttls)
@@ -868,12 +876,12 @@ if __name__ == '__main__':
 				#	continue
 				except SSL.Checker.WrongHost:
 					pass
-				except socket.error, e:
-					print 'Cannot connect to %s: %s' % (address, str(e))
+				except socket.error as e:
+					print('Cannot connect to %s: %s' % (address, str(e)))
 					continue
 
 				chain = connection.get_peer_cert_chain()
-				genRecords(args.host, args.protocol, args.port, chain, args.output, args.usage, args.selector, args.mtype)
+				genRecords(args.host, address, args.protocol, args.port, chain, args.output, args.usage, args.selector, args.mtype)
 				# Cleanup the connection and context
 				connection.clear()
 				connection.close()
@@ -882,8 +890,8 @@ if __name__ == '__main__':
 		else: # Pass the path to the certificate to the genTLSA function
 			try:
 				chain, verify_result = getLocalChain(args.certificate, args.debug)
-			except Exception, e:
-				print 'Could not verify local certificate: %s.' % e
-			if args.usage == 0 or args.usage == 1 and not verify_result:
-				print 'Following error was raised during PKIX validation: %s' % verify_result
-			genRecords(args.host, args.protocol, args.port, chain, args.output, args.usage, args.selector, args.mtype)
+				if args.usage == 0 or args.usage == 1 and not verify_result:
+					print('Following error was raised during PKIX validation: %s' % verify_result)
+				genRecords(args.host, args.host, args.protocol, args.port, chain, args.output, args.usage, args.selector, args.mtype)
+			except Exception as e:
+				print('Could not verify local certificate: %s.' % e)
diff --git a/tlsa.1 b/tlsa.1
index f25d910..7310772 100644
--- a/tlsa.1
+++ b/tlsa.1
@@ -31,7 +31,7 @@
 tlsa \- Create and verify RFC\-6698 TLSA DNS records
 .SH "SYNTAX"
 .PP
-tlsa [\fB\-h\fR] [\fB\-\-verify\fR] [\fB\-create\fR] [\fB\-\-version\fR] [\fB\-4\fR] [\fB\-6\fR\fB\-\-insecure\fR] [\fB\-\-resolv\&.conf /PATH/TO/RESOLV\&.CONF\fR] [\fB\-\-port PORT\fR] [\fB\-\-starttls {auto,smtp,imap,pop3,ftp}\fR] [\fB\-\-protocol {tcp,udp,sctp}\fR] [\fB\-\-ponly\-rr\fR] [\fB\-\-rootkey /PATH/TO/ROOT\&.KEY\fR] [\fB\-\-ca\-cert /PATH/TO/CERTSTORE\fR] [\fB\-\-debug\fR] [\fB\-\-quiet\fR] [\fB\-\-certificate CERTIFICATE\fR] [\fB\-\-output {rfc,generic,both}\fR] [\fB\-\-usage {0,1,2,3}\fR] [\fB\-\-selector {0,1}\fR] [\fB\-mtype {0,1,2}\fR]
+tlsa [\fB\-h\fR] [\fB\-\-verify\fR] [\fB\-create\fR] [\fB\-\-version\fR] [\fB\-4\fR] [\fB\-6\fR] [\fB\-\-insecure\fR] [\fB\-\-resolv\&.conf /PATH/TO/RESOLV\&.CONF\fR] [\fB\-\-port PORT\fR] [\fB\-\-starttls {auto,smtp,imap,pop3,ftp}\fR] [\fB\-\-protocol {tcp,udp,sctp}\fR] [\fB\-\-only\-rr\fR] [\fB\-\-rootkey /PATH/TO/ROOT\&.KEY\fR] [\fB\-\-ca\-cert /PATH/TO/CERTSTORE\fR] [\fB\-\-debug\fR] [\fB\-\-quiet\fR] [\fB\-\-certificate CERTIFICATE\fR] [\fB\-\-output {rfc,generic,both}\fR] [\fB\-\-usage {0,1,2,3}\fR] [\fB\-\-selector {0,1}\fR] [\fB\-mtype {0,1,2}\fR]
 \fIhostname\fR
 .SH "DESCRIPTION"
 .PP
diff --git a/tlsa.1.xml b/tlsa.1.xml
index bfce0ec..e0bb24a 100644
--- a/tlsa.1.xml
+++ b/tlsa.1.xml
@@ -18,10 +18,10 @@
 
 <refsect1 id='syntax'><title>SYNTAX</title>
 <para>tlsa [<option>-h</option>] [<option>--verify</option>] [<option>-create</option>] [<option>--version</option>] 
-           [<option>-4</option>] [<option>-6</option><option>--insecure</option>]
+           [<option>-4</option>] [<option>-6</option>] [<option>--insecure</option>]
            [<option>--resolv.conf /PATH/TO/RESOLV.CONF</option>]
            [<option>--port PORT</option>] [<option>--starttls {auto,smtp,imap,pop3,ftp}</option>] 
-           [<option>--protocol {tcp,udp,sctp}</option>] [<option>--ponly-rr</option>]
+           [<option>--protocol {tcp,udp,sctp}</option>] [<option>--only-rr</option>]
            [<option>--rootkey /PATH/TO/ROOT.KEY</option>]
            [<option>--ca-cert /PATH/TO/CERTSTORE</option>]
            [<option>--debug</option>] [<option>--quiet</option>] [<option>--certificate CERTIFICATE</option>]

Run locally

More details

Full run details