Tag Archives: net_dns2

Net_DNS2 v2: Breaking a Decade of Backwards Compatibility

I have maintained Net_DNS2 since 2010. It started as a cleanup of the old PEAR Net_DNS library, and for most of its life the guiding rule was simple: do not break anyone. That rule held through PHP 5.3, 5.4, 7.x, and into 8.x. With v2.0 I broke it deliberately, and I think it was overdue.

What PEAR-Era Naming Costs You

Net_DNS2 predates PSR-4, namespaces, and any modern autoloading convention. The class naming reflected that:

$r = new Net_DNS2_Resolver(['nameservers' => ['8.8.8.8']]);
$result = $r->query('example.com', 'MX');

Underscores as a pseudo-namespace worked, and it left the library carrying an autoloader that mapped underscores to directory separators, class names that grew to Net_DNS2_RR_OPENPGPKEY, and no way to use any of the type machinery PHP had spent a decade adding. Every resource record type was a loosely typed bag of public properties. Every enumerated value was an integer or a bare string, validated by convention.

The practical cost was in the bug reports. A meaningful share were people passing the wrong type into something, getting no error, and finding out later when the wire format came out malformed. The library could not tell them, because it had no way to say what it expected.

v2.0 Requires PHP 8.1

The v2.0 rewrite moved to PSR-4 and real namespaces, with the parallel rename you would expect:

$r = new \NetDNS2\Resolver(['nameservers' => ['8.8.8.8']]);
$result = $r->query('example.com', 'MX');

The floor is PHP 8.1, which is what enums require. That version choice is the entire reason the break was worth making. DNS is a protocol built almost entirely out of small enumerated sets: record types, classes, opcodes, response codes, DNSSEC algorithms, digest types. Modelling those as integer constants means every function that accepts one accepts any integer. Modelling them as backed enums means the type system rejects nonsense before a packet is ever assembled.

Most class, method, and property names survived the move. Someone upgrading is mostly changing Net_DNS2_Thing to \NetDNS2\Thing and raising their PHP requirement, which is a mechanical change a search and replace handles. That was the design constraint I set for myself: break the naming, keep the shape.

Deciding to Break Compatibility

The argument against was straightforward. Net_DNS2 has a long tail of users on old PHP, often embedded in something they inherited and do not want to touch. A hard PHP 8.1 floor strands all of them.

What changed my mind was noticing that I was writing new code to work around the absence of types, then writing tests to catch the bugs that the absent types would have caught, then answering issues from people who hit those bugs anyway. The library was subsidising PHP 5 compatibility with permanent complexity, and the people paying that tax were mostly not the people benefiting from it.

The compromise is that v1.x still exists and still gets fixes. That is the part I would recommend to anyone in the same position. A hard break is much easier to justify when the old branch does not disappear the same day, and tagging a final v1 release that people can pin to costs almost nothing.

What I Would Do Differently

I would have done it sooner. The signal was there for years: every feature request that involved better validation ran into the same wall, and I kept routing around it. Deprecation cycles have a cost too, and carrying a compatibility promise you have quietly stopped believing in is worse than announcing the break.

I would also have been more aggressive about the enum conversion in one pass. Doing it incrementally meant a stretch where some values were enums and some were still integers, and the mixed state was more confusing than either endpoint. If you are going to break, break cleanly and finish.

If you use the library and are still on v1, there is no urgency. If you are starting something new on PHP 8.1 or later, start on v2. The DNS lookup tool on mrdns.com runs on this code, so it gets exercised against real-world responses continuously, which has caught more parsing edge cases than my test suite ever did.

Net_DNS2 v1.4.4 – Bugfixes and Updates for PHP 7.2

I’ve released version 1.4.4 of the PEAR Net_DNS2 library- this release is primarily just bug fixes.

You can install it now through the command line PEAR installer:

pear install Net_DNS2

Or, you can also add it to your project using composer:

composer require pear/net_dns2

Version 1.4.4

  • Bugfix when returning an empty bitmap-type in BitMap.php – patch from BugMaster510945.
  • Added the BIND 9 private record RR (TYPE65534) – patch from BugMaster510945.
  • Added DNSSEC algorithms 13-16 (ECDSAP256SHA256, ECDSAP384SHA384, ED25519, and ED448).
  • Added SSHFP algoritm ED25519.
  • Modified Net_DNS2::sendPacket() to use current()/next() rather than the deprecated each() (deprecated in 7.2).

Net_DNS2 v1.4.3 – Interim Bugfix Release

I’ve released version 1.4.3 of the PEAR Net_DNS2 library- this release is primarily just bug fixes.

You can install it now through the command line PEAR installer:

pear install Net_DNS2

Or, you can also add it to your project using composer:

composer require pear/net_dns2

Version 1.4.3

  • fixed an issue when looking up . or com., when using the strict_query_mode flag.
  • fixed a bug in the caching logic where I was loading the content more than once per instance, when really I only need to do it once.
  • changed the Net_DNS2::sock array to use the SOCK_DGRAM and SOCK_STREAM defines, rather than the strings ‘tcp’ or ‘udp’.
  • fixed a bug in the Net_DNS2_Header and Net_DNS2_Question classes, where I was using the wrong bit-shift operators when parsing some of the values. This only became apparent when somebody was trying to use the CAA class (id 257); it was causing this to roll over to the next 8 bit value, and returning 1 (RR A) instead of the CAA class.
  • fixed a bug that occurs when a DNS lookup request times out, and then the same class is reused for a subsequent request. Because I’m caching the sockets, the timed out data could eventually come in, and end up being seen as the result for a subsequent lookup.
  • fixed a couple cases in NSAP.php where I was comparing a string to an integer.

Net_DNS2 v1.4.2 – SMIMEA and AVC Resource Records and SHA-256 SSHFP

I’ve released version 1.4.2 of the PEAR Net_DNS2 library- you can install it now through the command line PEAR installer:

pear install Net_DNS2

Or, you can also add it to your project using composer:

composer require pear/net_dns2

Version 1.4.2

  • changed the role for the README.md file to doc.
  • parse the resolv.conf options line; right now I just support the timeout and rotate options.
  • the options values only work if you set the new option use_resolv_options to true; this is to keep backwards compatibility.
  • added support for RFC 6594; support for SHA-256 and ECDSA in the SSHFP resource record.
  • added the SMIMEA resource record; this just extends the TLSA record.
  • added the AVC resource records; this just extends the TXT record.
  • added error and EDNS0 defines for DNS Cookies (RFC7873).
  • added EDNS0 defines to the lookup class.
  • dropped the Net_DNS2_Packet::formatIPv6() function; this was deprecated in v1.1.3.
  • re-wrote the Net_DNS2::expandIPv6() function. Based on testing, the new version is about twice as fast.

Net_DNS2 Moved to GitHub

I’ve never been a bit fan of git- I’ve got used to using SVN over the years, and never saw a compelling reason to change- until now- that Google is shutting down the Google Code service- so I’m forced to move.

Luckily I can still keep using SVN with GitHub- I can put off actually using git for the foreseeable future!

The new Net_DNS2 repository is officially moved to GitHub:

https://github.com/mikepultz/netdns2