{"id":13725154,"url":"https://github.com/paulc/dnslib","last_synced_at":"2025-05-14T02:06:07.241Z","repository":{"id":16698957,"uuid":"19455587","full_name":"paulc/dnslib","owner":"paulc","description":"A Python library to encode/decode DNS wire-format packets ","archived":false,"fork":false,"pushed_at":"2025-03-02T21:42:51.000Z","size":939,"stargazers_count":313,"open_issues_count":0,"forks_count":84,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-05-12T07:40:18.141Z","etag":null,"topics":["dns","python","python3"],"latest_commit_sha":null,"homepage":"https://github.com/paulc/dnslib","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"JayFang1993/ScanBook","license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paulc.png","metadata":{"files":{"readme":"README","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-05-05T12:52:48.000Z","updated_at":"2025-05-11T05:57:58.000Z","dependencies_parsed_at":"2024-01-03T01:07:22.977Z","dependency_job_id":"2b0b922c-544b-43ab-9b8e-8f9623445496","html_url":"https://github.com/paulc/dnslib","commit_stats":{"total_commits":288,"total_committers":25,"mean_commits":11.52,"dds":0.3680555555555556,"last_synced_commit":"0b2855f5e0fe0010e9d0c8393f1eb3091e86941d"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulc%2Fdnslib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulc%2Fdnslib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulc%2Fdnslib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulc%2Fdnslib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paulc","download_url":"https://codeload.github.com/paulc/dnslib/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254052692,"owners_count":22006716,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dns","python","python3"],"created_at":"2024-08-03T01:02:14.481Z","updated_at":"2025-05-14T02:06:02.229Z","avatar_url":"https://github.com/paulc.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"\n\n#### From Version 0.9.12 the master repository for _dnslib_ has been moved to GitHub (https://github.com/paulc/dnslib). Please update any links to the original BitBucket repository as this will no longer be maintained.\n\n#### ~~Release 0.9.24 (2024-01-02) will be the last release supporting Python 2.7 and Python \u003c3.7. Supporting old Python versions is increasingly painful and holds back adoption of new features so it's probably time to move on.~~\n\n#### Given the scale of the changes (and API changes) add typing support/modernise the codebase I've decided to leave dnslib as is in maintenance mode for users who are relying on the old API (and Python2 support). I'll try to fix any minor bugs but there isnt going to be any more active development (which is more or less the status quo anyway). \n\n\ndnslib\n------\n\nA library to encode/decode DNS wire-format packets supporting both\nPython 2.7 and Python 3.2+.\n\nThe library provides:\n\n * Support for encoding/decoding DNS packets between wire format,\n   python objects, and Zone/DiG textual representation (dnslib.dns)\n\n * A server framework allowing the simple creation of custom DNS\n   resolvers (dnslib.server) and a number of example servers\n   created using this framework\n\n * A number of utilities for testing (dnslib.client, dnslib.proxy,\n   dnslib.intercept)\n\nPython 3 support was added in Version 0.9.0 which represented a fairly\nmajor update to the library - the key changes include:\n\n * Python 2.7/3.2+ support (the last version supporting Python 2.6\n   or earlier was version 0.8.3)\n\n * The 'Bimap' interface was changed significantly to explicitly\n   split forward (value-\u003etext) lookups via __getitem__ and\n   reverse (text-\u003evalue) lookups via __getattr__. Applications\n   using the old interface will need to be updated.\n\n * Hostnames are now returned with a trailing dot by default (in\n   line with RFC)\n\n * Most object attributes are now typed in line with the record\n   definitions to make it harder to generate invalid packets\n\n * Support for encoding/decoding resource records in 'Zone' (BIND)\n   file format\n\n * Support for encoding/decoding packets in 'DiG' format\n\n * Server framework allowing (in most cases) custom resolvers to\n   be created by just subclassing the DNSResolver class and\n   overriding the 'resolve' method\n\n * A lot of fixes to error detection/handling which should make\n   the library much more robust to invalid/unsupported data. The\n   library should now either return a valid DNSRecord instance\n   when parsing a packet or raise DNSError (tested via fuzzing)\n\n * Improved utilities (dnslib.client, dnslib.proxy, dnslib.intercept)\n\n * Improvements to encoding/decoding tests including the ability\n   to generate test data automatically in test_decode.py (comparing\n   outputs against DiG)\n\n * Ability to compare and diff DNSRecords\n\nClasses\n-------\n\nThe key DNS packet handling classes are in dnslib.dns and map to the\nstandard DNS packet sections:\n\n * DNSRecord - container for DNS packet. Contains:\n    - DNSHeader\n    - Question section containing zero or more DNSQuestion objects\n    - Answer section containing zero or more RR objects\n    - Authority section containing zero or more RR objects\n    - Additional section containing zero or more RR objects\n * DNS RRs (resource records) contain an RR header and an RD object)\n * Specific RD types are implemented as subclasses of RD\n * DNS labels are represented by a DNSLabel class - in most cases\n   this handles conversion to/from textual representation however\n   does support arbitatry labels via a tuple of bytes objects\n\nUsage\n-----\n\nTo decode a DNS packet:\n\n    \u003e\u003e\u003e packet = binascii.unhexlify(b'd5ad818000010005000000000377777706676f6f676c6503636f6d0000010001c00c0005000100000005000803777777016cc010c02c0001000100000005000442f95b68c02c0001000100000005000442f95b63c02c0001000100000005000442f95b67c02c0001000100000005000442f95b93')\n    \u003e\u003e\u003e d = DNSRecord.parse(packet)\n    \u003e\u003e\u003e d\n    \u003cDNS Header: id=0xd5ad type=RESPONSE opcode=QUERY flags=RD,RA rcode='NOERROR' q=1 a=5 ns=0 ar=0\u003e\n    \u003cDNS Question: 'www.google.com.' qtype=A qclass=IN\u003e\n    \u003cDNS RR: 'www.google.com.' rtype=CNAME rclass=IN ttl=5 rdata='www.l.google.com.'\u003e\n    \u003cDNS RR: 'www.l.google.com.' rtype=A rclass=IN ttl=5 rdata='66.249.91.104'\u003e\n    \u003cDNS RR: 'www.l.google.com.' rtype=A rclass=IN ttl=5 rdata='66.249.91.99'\u003e\n    \u003cDNS RR: 'www.l.google.com.' rtype=A rclass=IN ttl=5 rdata='66.249.91.103'\u003e\n    \u003cDNS RR: 'www.l.google.com.' rtype=A rclass=IN ttl=5 rdata='66.249.91.147'\u003e\n\nThe default text representation of the DNSRecord is in zone file format:\n\n    \u003e\u003e\u003e print(d)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: 54701\n    ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;www.google.com.                IN      A\n    ;; ANSWER SECTION:\n    www.google.com.         5       IN      CNAME   www.l.google.com.\n    www.l.google.com.       5       IN      A       66.249.91.104\n    www.l.google.com.       5       IN      A       66.249.91.99\n    www.l.google.com.       5       IN      A       66.249.91.103\n    www.l.google.com.       5       IN      A       66.249.91.147\n\nTo create a DNS Request Packet:\n\n    \u003e\u003e\u003e d = DNSRecord.question(\"google.com\")\n\n(This is equivalent to: d = DNSRecord(q=DNSQuestion(\"google.com\") )\n\n    \u003e\u003e\u003e d\n    \u003cDNS Header: id=... type=QUERY opcode=QUERY flags=RD rcode='NOERROR' q=1 a=0 ns=0 ar=0\u003e\n    \u003cDNS Question: 'google.com.' qtype=A qclass=IN\u003e\n\n    \u003e\u003e\u003e str(DNSRecord.parse(d.pack())) == str(d)\n    True\n\n    \u003e\u003e\u003e print(d)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;google.com.                    IN      A\n\n    \u003e\u003e\u003e d = DNSRecord.question(\"google.com\",\"MX\")\n\n(This is equivalent to: d = DNSRecord(q=DNSQuestion(\"google.com\",QTYPE.MX) )\n\n    \u003e\u003e\u003e str(DNSRecord.parse(d.pack())) == str(d)\n    True\n\n    \u003e\u003e\u003e print(d)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;google.com.                    IN      MX\n\nTo create a DNS Response Packet:\n\n    \u003e\u003e\u003e d = DNSRecord(DNSHeader(qr=1,aa=1,ra=1),\n    ...               q=DNSQuestion(\"abc.com\"),\n    ...               a=RR(\"abc.com\",rdata=A(\"1.2.3.4\")))\n    \u003e\u003e\u003e d\n    \u003cDNS Header: id=... type=RESPONSE opcode=QUERY flags=AA,RD,RA rcode='NOERROR' q=1 a=1 ns=0 ar=0\u003e\n    \u003cDNS Question: 'abc.com.' qtype=A qclass=IN\u003e\n    \u003cDNS RR: 'abc.com.' rtype=A rclass=IN ttl=0 rdata='1.2.3.4'\u003e\n    \u003e\u003e\u003e str(DNSRecord.parse(d.pack())) == str(d)\n    True\n\n    \u003e\u003e\u003e print(d)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;abc.com.                       IN      A\n    ;; ANSWER SECTION:\n    abc.com.                0       IN      A       1.2.3.4\n\nIt is also possible to create RRs from a string in zone file format\n\n    \u003e\u003e\u003e RR.fromZone(\"abc.com IN A 1.2.3.4\")\n    [\u003cDNS RR: 'abc.com.' rtype=A rclass=IN ttl=0 rdata='1.2.3.4'\u003e]\n\n    (Note: this produces a list of RRs which should be unpacked if being\n    passed to add_answer/add_auth/add_ar etc)\n\n    \u003e\u003e\u003e q = DNSRecord.question(\"abc.com\")\n    \u003e\u003e\u003e a = q.reply()\n    \u003e\u003e\u003e a.add_answer(*RR.fromZone(\"abc.com 60 A 1.2.3.4\"))\n    \u003e\u003e\u003e print(a)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;abc.com.                       IN      A\n    ;; ANSWER SECTION:\n    abc.com.                60      IN      A       1.2.3.4\n\nThe zone file can contain multiple entries and supports most of the normal\nformat defined in RFC1035 (specifically not $INCLUDE)\n\n    \u003e\u003e\u003e z = '''\n    ...         $TTL 300\n    ...         $ORIGIN abc.com\n    ...\n    ...         @       IN      MX      10  mail.abc.com.\n    ...         www     IN      A       1.2.3.4\n    ...                 IN      TXT     \"Some Text\"\n    ...         mail    IN      CNAME   www.abc.com.\n    ... '''\n    \u003e\u003e\u003e for rr in RR.fromZone(textwrap.dedent(z)):\n    ...     print(rr)\n    abc.com.                300     IN      MX      10 mail.abc.com.\n    www.abc.com.            300     IN      A       1.2.3.4\n    www.abc.com.            300     IN      TXT     \"Some Text\"\n    mail.abc.com.           300     IN      CNAME   www.abc.com.\n\nTo create a skeleton reply to a DNS query:\n\n    \u003e\u003e\u003e q = DNSRecord(q=DNSQuestion(\"abc.com\",QTYPE.ANY))\n    \u003e\u003e\u003e a = q.reply()\n    \u003e\u003e\u003e a.add_answer(RR(\"abc.com\",QTYPE.A,rdata=A(\"1.2.3.4\"),ttl=60))\n    \u003e\u003e\u003e str(DNSRecord.parse(a.pack())) == str(a)\n    True\n    \u003e\u003e\u003e print(a)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;abc.com.                       IN      ANY\n    ;; ANSWER SECTION:\n    abc.com.                60      IN      A       1.2.3.4\n\nAdd additional RRs:\n\n    \u003e\u003e\u003e a.add_answer(RR(\"xxx.abc.com\",QTYPE.A,rdata=A(\"1.2.3.4\")))\n    \u003e\u003e\u003e a.add_answer(RR(\"xxx.abc.com\",QTYPE.AAAA,rdata=AAAA(\"1234:5678::1\")))\n    \u003e\u003e\u003e str(DNSRecord.parse(a.pack())) == str(a)\n    True\n    \u003e\u003e\u003e print(a)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;abc.com.                       IN      ANY\n    ;; ANSWER SECTION:\n    abc.com.                60      IN      A       1.2.3.4\n    xxx.abc.com.            0       IN      A       1.2.3.4\n    xxx.abc.com.            0       IN      AAAA    1234:5678::1\n\n\nIt is also possible to create a reply from a string in zone file format:\n\n    \u003e\u003e\u003e q = DNSRecord(q=DNSQuestion(\"abc.com\",QTYPE.ANY))\n    \u003e\u003e\u003e a = q.replyZone(\"abc.com 60 IN CNAME xxx.abc.com\")\n    \u003e\u003e\u003e print(a)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;abc.com.                       IN      ANY\n    ;; ANSWER SECTION:\n    abc.com.                60      IN      CNAME   xxx.abc.com.\n\n    \u003e\u003e\u003e str(DNSRecord.parse(a.pack())) == str(a)\n    True\n\n    \u003e\u003e\u003e q = DNSRecord(q=DNSQuestion(\"abc.com\",QTYPE.ANY))\n    \u003e\u003e\u003e a = q.replyZone(textwrap.dedent(z))\n    \u003e\u003e\u003e print(a)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0\n    ;; QUESTION SECTION:\n    ;abc.com.                       IN      ANY\n    ;; ANSWER SECTION:\n    abc.com.                300     IN      MX      10 mail.abc.com.\n    www.abc.com.            300     IN      A       1.2.3.4\n    www.abc.com.            300     IN      TXT     \"Some Text\"\n    mail.abc.com.           300     IN      CNAME   www.abc.com.\n\nTo send a DNSSEC request (EDNS OPT record with DO flag \u0026 header AD flag):\n\n    \u003e\u003e\u003e q = DNSRecord(q=DNSQuestion(\"abc.com\",QTYPE.A))\n    \u003e\u003e\u003e q.add_ar(EDNS0(flags=\"do\",udp_len=4096))\n    \u003e\u003e\u003e q.header.ad = 1\n    \u003e\u003e\u003e print(q)\n    ;; -\u003e\u003eHEADER\u003c\u003c- opcode: QUERY, status: NOERROR, id: ...\n    ;; flags: rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1\n    ;; QUESTION SECTION:\n    ;abc.com.                       IN      A\n    ;; ADDITIONAL SECTION:\n    ;; OPT PSEUDOSECTION\n    ; EDNS: version: 0, flags: do; udp: 4096\n\nNote that when using the library you should always validate the received TXID \n\n    q = DNSRecord.question(\"abc.com\")\n    a_pkt = q.send(address,port,tcp=args.tcp)\n    a = DNSRecord.parse(a_pkt)\n    if q.header.id != a.header.id:\n        raise DNSError('Response transaction id does not match query transaction id')\n\nThe library also includes a simple framework for generating custom DNS\nresolvers in dnslib.server (see module docs). In most cases this just\nrequires implementing a custom 'resolve' method which receives a question\nobject and returns a response.\n\nA number of sample resolvers are provided as examples (see CLI --help):\n\n * dnslib.fixedresolver    - Respond to all requests with fixed response\n * dnslib.zoneresolver     - Respond from Zone file\n * dnslib.shellresolver    - Call shell script to generate response\n\nThe library includes a number of client utilities:\n\n * DiG like client library\n\n        # python -m dnslib.client --help\n\n * DNS Proxy Server\n\n        # python -m dnslib.proxy --help\n\n * Intercepting DNS Proxy Server (replace proxy responses for specified domains)\n\n        # python -m dnslib.intercept --help\n\n\nChangelog:\n----------\n\n```\n *   0.1     2010-09-19  Initial Release\n *   0.2     2010-09-22  Minor fixes\n *   0.3     2010-10-02  Add DNSLabel class to support arbitrary labels (embedded '.')\n *   0.4     2012-02-26  Merge with dbslib-circuits\n *   0.5     2012-09-13  Add support for RFC2136 DDNS updates\n                         Patch provided by Wesley Shields \u003cwxs@FreeBSD.org\u003e - thanks\n *   0.6     2012-10-20  Basic AAAA support\n *   0.7     2012-10-20  Add initial EDNS0 support (untested)\n *   0.8     2012-11-04  Add support for NAPTR, Authority RR and additional RR\n                         Patch provided by Stefan Andersson (https://bitbucket.org/norox) - thanks\n *   0.8.1   2012-11-05  Added NAPTR test case and fixed logic error\n                         Patch provided by Stefan Andersson (https://bitbucket.org/norox) - thanks\n *   0.8.2   2012-11-11  Patch to fix IPv6 formatting\n                         Patch provided by Torbjorn Lonnemark (https://bitbucket.org/tobbezz) - thanks\n *   0.8.3   2013-04-27  Don't parse rdata if rdlength is 0\n                         Patch provided by Wesley Shields \u003cwxs@FreeBSD.org\u003e - thanks\n *   0.9.0   2014-05-05  Major update including Py3 support (see docs)\n *   0.9.1   2014-05-05  Minor fixes\n *   0.9.2   2014-08-26  Fix Bimap handling of unknown mappings to avoid exception in printing\n                         Add typed attributes to classes\n                         Misc fixes from James Mills - thanks\n *   0.9.3   2014-08-26  Workaround for argparse bug which raises AssertionError if [] is\n                         present in option text (really?)\n *   0.9.4   2015-04-10  Fix to support multiple strings in TXT record\n                         Patch provided by James Cherry (https://bitbucket.org/james_cherry) - thanks\n                         NOTE: For consistency this patch changes the 'repr' output for\n                               TXT records to always be quoted\n *   0.9.5   2015-10-27  Add threading \u0026 timeout handling to DNSServer\n *   0.9.6   2015-10-28  Replace strftime in RRSIG formatting to avoid possible locale issues\n                         Identified by Bryan Everly - thanks\n *   0.9.7   2017-01-15  Sort out CAA/TYPE257 DiG parsing mismatch\n *   0.9.8   2019-02-25  Force DNSKEY key to be bytes object\n                         Catch Bimap __wrapped__ attr (used by inspect module in 3.7)\n *   0.9.9   2019-03-19  Add support for DNSSEC flag getters/setters (from \u003craul@dinosec.com\u003e - thanks)\n                         Added --dnssec flags to dnslib.client \u0026 dnslib.test_decode (sets EDNS0 DO flag)\n                         Added EDNS0 support to dnslib.digparser\n *   0.9.10  2019-03-24  Fixes to DNSSEC support\n                         Add NSEC RR support\n                         Add --dnssec flag to dnslib.client \u0026 dnslib.test_decode\n                         Quote/unquote non-printable characters in DNS labels\n                         Update test data\n                         (Thanks to \u003craul@dinosec.com\u003e for help)\n *   0.9.11  2019-12-17  Encode NOTIFY Opcode (Issue #26)\n *   0.9.12  2019-12-17  Transition master repository to Github (Bitbucket shutting down hg)\n *   0.9.13  2020-06-01  Handle truncated requests in server.py (Issue #9)\n                         Replace thred.isAlive with thread.is_alive (Deprecated in Py3.9)\n                         Merged Pull Request #4 (Extra options for intercept.py) - thanks to @nolanl\n *   0.9.14  2020-06-09  Merged Pull Request #10 (Return doctest status via exit code)\n                         Thanks to @mgorny\n *   0.9.15  2021-05-07  DNSServer fixes - support IPv6 (from Pull Request #21) - thanks to @mikma\n                                         - deamon threads (Pull Request #19) - thanks to @wojons\n                         Add unsupported RR types (Issue #27)\n *   0.9.16  2021-05-07  Merge pull request #23 from Tugzrida/patch-1\n                            Add support for all RR types to NSEC type bitmap\n                         Merge pull request #17 from sunds/issue_16\n                            Issue 16: uncaught exceptions leak open sockets\n *   0.9.18  2022-01-09  Validate TXID in client.py (Issue #30 - thanks to @daniel4x)\n *   0.9.19  2022-01-09  Allow custom log function (logf) in  DNSLogger\n                            (Issue #31 - thanks to @DmitryFrolovTri)\n *   0.9.20  2022-07-17  Fix DeprecationWarnings about invalid escape sequences\n                            (Pull-Request #39 - thanks to @brianmaissy)\n                         Make DNSLabel matchSuffix and stripSuffix case-insensitive\n                            (Pull-Request #37 - thanks to @NiKiZe)\n                         Add support for HTTPS RR\n                            (Pull-Request #35 - thanks to @jkl-caliber)\n                         Fix display of non-printable characters in TXT records\n                            (Issue #32 - thanks to @sbv-csis)\n                         Add --strip-aaaa option to dnslib.proxy \n *   0.9.21  2022-09-19  Minor clean-up / add wheels to distro\n *   0.9.22  2022-09027  Issue #43 (0.9.21 Raises TypeError instead of DNSError when failing to parse HTTPS records)\n                         Note that we just fix the exception - there still seems to be a problem with parsing HTTPS records\n                         (Thanks to @robinlandstrom)\n *   0.9.23  2022-10-28  Issue #43: HTTPS reads after RD end (thanks to @robinlandstrom for pull request)\n                         Issue #45: Dnslib fails to handle unknown RR types in NSEC RD type bitmap\n                            Bimap now supports a function to map unknown types which we use to\n                            dynamically map from rtype \u003c-\u003e TYPExxxx for unknown record types\n                            RR zone representation updated to match RFC3597\n                         Pull Request #47: Add support for DS, SSHFP, and TLSA records (thanks to @rmbolger)\n *   0.9.24  2024-01-02  Merge multiple PRs\n                            #49 - Generate README.md (via symlink)\n                            #51 - Update Github CI checkout \u0026 setup-python actions (and remove Python 2.7 CI support)\n                                  (thanks to @SpencerIsGiddy)\n                            #54 - Support for RP records (thanks to @ryan-gang)\n                            #57 - Support for LOC records (thanks to @valentinesd)\n *   0.9.25  2024-07-08  Minor fixes:\n                            #60 - SyntaxWarning with Python 3.12 (@kitterma)\n                            #63 - Records with empty rdata causes pack() to fail (@peteralm80)\n                            #66 - DNS SRV \"target\" names are compressed (@bobstanden)\n```\n\nLicense:\n--------\n\nBSD\n\nAuthor:\n-------\n\n *   PaulC\n\nMaster Repository/Issues:\n-------------------------\n\n *   https://github.com/paulc/dnslib\n\n (Note: https://bitbucket.org/paulc/dnslib has been deprecated and will not be updated)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulc%2Fdnslib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaulc%2Fdnslib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulc%2Fdnslib/lists"}