NetAddr::IP 4.080_05: Please Smoke Test

NetAddr::IP 4.079 was released in 2016 and has sat there since. I have started working on it recently, and 4.080_05 is the fifth trial release since. It is on CPAN now, and the tarball is ready for you to install!

Most of what changed is a matter of course: about a hundred fixes to bugs and to documentation that had drifted from the code, and a set of three breaking changes that fix behaviour the documentation said should not happen. NetAddr::IP is now MIT licensed, was dual licensed under GPL v2 or the Artistic License, and deprecations collected under one heading are going in version 5.

The XS build

The XS, which is the C implementation, is the part with the least testing behind it. It stopped compiling early in the 4.080 work and nobody noticed, because the Linux job in the GitHub CI ran a plain perl Makefile.PL, got a pure Perl build, and passed. Restoring the compiler then turned up a fault in the makefile clean list that stopped the XS being rebuilt at all (GH#114).

Where it gets built:

  • Linux and the BSDs build it by default (GH#111), falling back to pure Perl when no compiler is found.
  • macOS builds it by default (GH#140), having defaulted to pure Perl since 2013 for a reason that no longer applied.
  • Windows still defaults to pure Perl, by rule rather than by limitation. The old NOTES in IP.pm blamed the configure step, and the build did run it: it shelled out to configure.gcc or configure.cc for a config.h and fell back to pure Perl when neither produced one. That step is gone, the XS compiles on Windows, and the GitHub CI builds and tests it. What is left is MSWin32 named in the platform list in inc/MakeMaker/header.pl, and asking for the XS there takes perl Makefile.PL --xs.

The XS is thread safe by construction: every helper is static and there is no state at file scope. The GitHub CI runs it under threads on Windows only, since the Linux and macOS runners use perls built without ithreads.

Around the build: the 2006-era autoconf step is gone (GH#101), along with four generated files and about 60 lines of configure logic that fetched byte order and integer widths perl has had since 5.005. The XS takes both from perl.h now. Four XS arithmetic helpers were reading the caller's packed address wrongly (GH#102). The pure Perl was right, so a caller could get one answer from the XS and a different one from pure Perl.

So find out which build you ended up with:

perl -MNetAddr::IP::Util -e 'print NetAddr::IP::Util::mode(), "\n"'

It prints CC XS or Pure Perl. The XS is the one I hope people will test most rigorously, and it is the one that will not get tested unless someone installs it on purpose.

Socket6 became a recommendation rather than a hard prerequisite (GH#54), so a minimal install no longer needs it, and neither does anything that depends on NetAddr::IP. What you get without it is the module's own inet_pton and inet_ntop rather than the platform's. The places where the two disagree are now documented, including how ipv6_ntoa and inet_ntop render an address with an IPv4 address in the low 32 bits (GH#99).

Breaking changes

Three, and each one fixes something the documentation said should not happen.

  • re() on an IPv6 object in IPv4 space no longer returns a regex that cannot match (GH#34).
  • re6() returns a non-capturing group, (?:...) (GH#50). The old capturing group was rarely what a caller wanted.
  • new(undef) returns undef (GH#29) rather than quietly handing back the default route.

Deprecations

The deprecation notes are now in one DEPRECATED section under EXPORT_OK, each item naming its replacement, and everything listed there is going in version 5:

  • :rfc3021 is deprecated (GH#26). hostenum and hostenumref return 2 hosts for /31 and /127 unconditionally, matching the RFC, and the dead $rfc3021 variable is gone (GH#63).
  • :aton, new_cis and new_cis6 now warn in the deprecated category, naming the replacement (GH#49). None of the three warned before. Behaviour is unchanged, except under use warnings FATAL => 'all', where the new warning dies.

:old_nth and :old_storable stay. They were never formally deprecated and have no replacement.

AF_INET6 comes from Socket now

The probe meant to read Socket's own AF_INET6 called an unqualified AF_INET6() that was not defined at that point, so it always died. Without Socket6 installed, that left the module guessing the value from a table keyed on the operating system name. The table happens to be right on Linux, macOS and Windows, which is why nobody saw it, and wrong on DragonFly BSD, MidnightBSD, AIX, QNX, Haiku and GNU/Hurd (GH#142). The value now comes from Socket wherever Socket has it, and fake_AF_INET6() is true only when a guess was actually needed.

Licence

The distribution is relicensed under MIT, agreed by all three copyright holders (GH#134). MIT is one permissive licence with no copyleft obligations beyond keeping the copyright notice, and it covers every file the same way, so nobody has to work out which of two licences applies to which.

It does not widen where the code can go. The code could not be dropped into a Perl 5 licensed project before either, and it still cannot be. What changed is the burden on the user, not the reach.

The history of the licence it replaces is worth mentioning in more detail, because it was not what the metadata said. The modules were dual licensed, "either GPL v2 or the Artistic License". That is similar to how Perl5 is licensed with one key difference: Perl5 is GPL v1 or Artistic 1.0, and GPL v2 is not compatible with GPL v1. The XS was GPL v2 on its own, with no Artistic option, so the terms were not the same from file to file. The CPAN metadata claimed Perl_5, which did not match the grant the modules actually made, and in 4.079 it declared no licence at all (GH#56). Earlier releases keep the licences they shipped under, if you would like to borrow that code into your own project.

Other fixes

About a hundred entries in the Changes file cover this release. A selection:

  • coalesce counts subnet addresses rather than usable hosts (GH#37), works on subclass objects (GH#38), and croaks on bad arguments (GH#40).
  • new6() returns the compatible form for IPv4-only hosts, not the mapped one, and prefers AAAA over A for a dual-stack host name (GH#32).
  • canon and short compress the first equal-length zero run, per RFC 5952 (GH#13).
  • Addition and subtraction croak on a constant that is not a number. The old result was a silent no-op, or a wrap, or an added string (GH#24, GH#25).
  • Decimal literals that overflow 32 bits return undef from the constructor instead of wrapping (GH#19).
  • 0b and 0x literals parse through oct() rather than a string eval (GH#4), and non-ASCII digits are rejected outright.
  • Bracket notation: [addr]/mask is accepted (GH#2), text outside the brackets no longer matches (GH#68), and a bracketed IPv4 literal is rejected (GH#60).
  • within() rejects cross-family and non-object arguments, nth() rejects a non-integer index (GH#10), and compact no longer mutates its arguments when it merges IPv4 with IPv6 (GH#15).
  • neg and abs are overloaded, with error messages that say what was wrong (GH#67).
  • The module loads on a host whose resolver answers nothing, such as a program that hooks gethostbyname (GH#69), and is_local now sees an IPv4 loopback held in an IPv6 object (GH#27).
  • :nofqdn sets the flag it always meant to (RT#111301), re6() handles compressed IPv6 text, and network() keeps the netmask where addr() gives the address alone (RT#114495).
  • Math::BigInt 1.99 is required, the last release before Perl 5.14 (GH#44). The fallback that emulated it is gone.

Documentation and tests

The whole test suite was converted to Test2::V1, then reformatted with perltidy. It is 165 files and 2,753 tests on a plain run. The GitHub CI runs it on Perl 5.14 to 5.42 on Linux and on four macOS images, and on 5.24 to 5.30 on Windows. Every one of those builds checks the mode it actually built rather than assuming it, so a build that quietly fell back to pure Perl fails the job instead of passing as the other build (GH#61).

Perl 5.014 is the declared floor in every phase now, where the configure phase still claimed 5.010. The four separately distributed sub-modules are also one distribution now, on the conventional Dist::Zilla layout.

The POD was overhauled in the same way. Every method and function entry was rewritten so the two modules sharing them carry identical text, the SYNOPSIS no longer imports behaviour-changing tags by default, the export tag table is complete, and the examples use RFC 5737 addresses. Several examples printed results that were wrong, including the arithmetic ones, which compared string order where they meant address order.

Try It Out

Please install a trial and run your own code against it. It is on CPAN as a development release, and the metadata there is worth a look before you do: NetAddr-IP-4.080_05, licence MIT, perl 5.14. Install it with cpanm:

cpanm DJZORT/NetAddr-IP-4.080_05.tar.gz

A plain cpanm NetAddr::IP still gives you 4.079, so use the tarball.

Or clone it from GitHub and run the suite:

git clone https://github.com/cpan-authors/perl-NetAddr-IP.git
cd perl-NetAddr-IP
dzil test

Either way, run the suite a second time with -noxs as well, so both halves of the distribution get exercised on your platform.

What I would most like from you is a macOS and a Windows machine running the XS. macOS gets it by default now, so a report either confirms that or finds a reason it should not, and Windows is one line in header.pl from the same. If something breaks, open an issue with the perl version, the operating system, whether you built the XS or pure Perl, and the output of mode().

Leave a comment

About Dean

user-pic I blog about Perl. I am back in Sydney