Repository navigation
Expand file tree
/
Copy pathChanges
More file actions
2293 lines (1779 loc) · 107 KB
/
Copy pathChanges
File metadata and controls
2293 lines (1779 loc) · 107 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Revision history for Perl extension NetAddr::IP
{{$NEXT}}
4.080_09 2026-11-10 00:24:39+11:00 Australia/Sydney (TRIAL RELEASE)
- Add `.perltidyrc` and document how to run `perltidy` in `AGENTS.md`.
Reformat tracked Perl source and tests with the new configuration.
4.080_08 2026-11-07 01:17:12+11:00 Australia/Sydney (TRIAL RELEASE)
- Fix GH#268: The configure step chooses XS or pure Perl by testing
the compiler and linker the build will use: CC= and LD= given to
Makefile.PL, else perl's own. It tested the CC environment
variable first and took LD, CFLAGS and LDFLAGS from the
environment, which the build ignores, so a build could fail after
the test passed, or install pure Perl where XS would have built.
- Fix GH#263: Running perl Makefile.PL again in a directory that
holds an XS build no longer installs the generated Util.c and
Util.o beside the modules. The configure step deletes them on
every run, where it did so only for a pure Perl build.
- Fix GH#261: Importing :old_nth or :old_storable warns that the tag
is deprecated and will be removed in version 5, as the README
already said. Neither tag changes what it does. The variable
$NetAddr::IP::Lite::Old_nth is deprecated with :old_nth but does not
warn. Code that makes warnings fatal now dies at the import, so this
is a breaking change for it.
- Fix GH#259: The split methods croak when a plan puts a piece at an
address that is not a multiple of its own size, as split(30, 29) on
192.0.2.0/28 did with 192.0.2.4/29, a /29 whose network is
192.0.2.0. A plan ordered from the largest piece to the smallest
splits as before. Plans that 4.079 accepted now croak, so this is a
breaking change.
- Fix GH#256: The test helpers bcdn2bin() and bcdn2txt() croak on a
packed digit above 9, as bcd2bin() does on a character outside 0-9.
The XS build used such a digit as its value, and the pure Perl build
read it as 0 with a warning or as a letter, so the two builds gave
different answers.
- Fix GH#253: An RFC 1918 address held in an IPv6 object as a mapped
address, such as ::ffff:10.0.0.1, is RFC 1918 under is_rfc1918(),
the same as its IPv4 form, where it gave false. This follows
is_local(), which answers ::ffff:127.0.0.1 as local since GH#27.
- Fix GH#252: An IPv4 address sorts before the IPv6 address that
holds the same 128 bits, so 192.0.2.4/24 comes before
::192.0.2.4/120. The two compared as equal under <=> and cmp, while
== and eq said they differ. Now <=> gives 0 only when == is true,
and cmp only when eq is.
- Fix GH#251: The :nofqdn test skips its check when the resolver
cannot find arin.net, where it stopped with an error.
4.080_07 2026-11-05 08:59:56+11:00 Australia/Sydney (TRIAL RELEASE)
- Fix GH#237: Add new4(), which reads its input as new() does and
returns undef unless the result is IPv4. IPv4-mapped text such as
::ffff:192.0.2.1 gives that IPv4 address. A call to new4()
rebuilds an IPv4 object from numeric() when the mask is above
128. A numeric mask of 0 is still prefix length 0, so 0.0.0.5/0
comes back as 5.0.0.0/0.
- Fix GH#237: The new6() constructor reads a whole number as a
128-bit value, so new6('5', 8) gives 0:0:0:0:0:0:0:5/8 where it
gave 0:0:0:0:0:0:500:0/104. A call to new6() rebuilds an IPv6
object from numeric(), ::/0 and ::1/0 included. Dotted text keeps
its IPv4 prefix length, so new6('127.0/8') is still
0:0:0:0:0:0:7F00:0/104, but new6('127/8') is now
0:0:0:0:0:0:0:7F/8. A negative number gives undef. The
constructors new6FFFF() and new_cis6() use this same reading, so
new6FFFF('5', 8) is 0:0:0:0:0:FFFF:0:5/8 where it was
0:0:0:0:0:FFFF:500:0/104, and a negative number is undef from
both. An IPv4 reading still gains the mapped prefix. An IPv6
address stays as new6 gives it.
- Fix GH#236: An IPv4 address with a mask written as a whole number
wider than 32 bits needs the 96 leading ones, as the same mask in
IPv6 form already did. So new('192.0.2.4', N), with N the number
for ffff::, gives undef where it gave 192.0.2.4/0.
- Fix GH#235: A small number given with a mask written as a whole
number, as numeric() returns it, is read as the address value. So
new(5, 4294967292) gives 0.0.0.5/30 where it gave 5.0.0.0/30. A
numeric mask of 0 is still prefix length 0, so 0.0.0.5/0 comes
back as 5.0.0.0/0 and ::1/0 comes back as ::100:0/96. With a
prefix length the number is still the first octet: new('10', 8)
is 10.0.0.0/8.
- Fix GH#234: The new6FFFF constructor maps only an IPv4 address.
It wrote ffff into every address, so 2001:db8::1 came back as
2001:db8::ffff:0:1 and ::1 as ::ffff:0:1. An IPv6 address,
including ::192.0.2.1 and a keyword such as loopback, now comes
back as new6 gives it.
- Fix GH#233: Calling compactref on an object with no list, as in
$ip->compactref(), gives the object's network, as $ip->compact()
does, where it gave blocks built from the host addresses inside it,
or croaked "netlimit exceeded" on a large network.
- Fix GH#232: The coalesce method and the Coalesce function count
each address once. A subnet listed twice, or a subnet inside
another one in the list, no longer counts its addresses twice,
so two copies of 192.0.2.1/32 count 1, not 2.
- Fix GH#231: Comparing an address with the string NetAddr::IP or
NetAddr::IP::Lite, or giving either to within() or contains(),
answers as for any other string, where it died.
- Fix GH#230: The POD lists compactref() with Compact(\@list), which
it describes, where it sat under coalesce().
- Fix GH#229: Calling coalesce, compact or compactref on the class
name, as in NetAddr::IP->coalesce(24, 2, @list), croaks with a
message that names the right calls, where it died with Perl's own
"Can't use string as a HASH ref". Calling coalesce on a
NetAddr::IP::Lite object, or with those objects in the list, and
calling compactref on one, works, where these croaked or died.
- Fix GH#228: Comparing an address with a string, a number or undef
no longer dies. The operators <=>, <, >, <= and >= give undef or
false, as == does, and cmp, lt, gt, le and ge compare the text, as
eq does.
- Fix GH#241: A short range such as 192.0.2.5-6 or 192.1-2. gives
undef unless it covers exactly one subnet, as the POD says and as
the full form 192.0.2.5-192.0.2.6 already did. So 192.0.2.5-6
gives undef where it gave 192.0.2.5/30, a network that also holds
192.0.2.4 and 192.0.2.7. A call to new6() uses the same reading,
so new6('192.0.2.5-6') is undef where it was
0:0:0:0:0:0:C000:205/126. An aligned range is unchanged, so
new6('192.0.2.4-7') stays 0:0:0:0:0:0:C000:204/126.
- Fix GH#212: The documentation of :old_storable says what the tag
does. The tag makes Storable freeze objects as a plain hash. Reading
data frozen that way does not need it. Importing the tag stops a
CIDR-string freeze from thawing in the program, or in the calling
thread under ithreads.
- Fix GH#219: A keyword given to new6() uses the caller's mask on
the keyword's IPv6 address. That covers a separate mask, a mask
written in the string and an undef mask. The calls
new6('loopback', 64) and new6('loopback/64') give
0:0:0:0:0:0:0:1/64, and new6('loopback', undef) gives
0:0:0:0:0:0:0:1/128. A separate mask used to keep the keyword's
own prefix, and a mask in the string or an undef mask used the
IPv4 keyword. A mask that is not valid gives undef.
- Fix GH#98: An IPv4-mapped address from canon() comes back in
RFC 5952 section 5 mixed form, such as ::ffff:192.0.2.1, not
hex. The IPv4-compatible, IPv4-translated and NAT64 prefixes
stay hex, as do short(), addr() and stringification, so canon()
and short() no longer agree on a mapped address, and re() and
re6() do not match its canon() form. This changes canon()
strings for mapped addresses.
- Fix GH#222: The IPv6 regex from re6() and re() no longer matches
an address inside a longer one, so the regex for 2001:db8::1/128
does not match 2001:db8::10 or 2001:db8:2001:db8::1, as the IPv4
regex from re() does not match 192.0.2.10 for 192.0.2.1/32. A
label ending in a hex digit, such as src:2001:db8::1, and a port
after a dot, such as 2001:db8::1.443, do not match either.
- Fix GH#221: A range with a space or tab on only one side of the
dash, such as 192.0.2.0 -192.0.2.255, gives the same network as
with spaces on both sides or none, where it gave undef.
- Fix GH#215: An IPv6 split(), splitref(), rsplit() or rsplitref()
with a mask 54 or more bits longer than the subnet's returns the
right pieces. It could return overlapping pieces or a piece outside
the subnet, return pieces where it should croak "netlimit exceeded",
or croak "netmask error" in its place.
- Fix GH#214: A Math::BigInt address or mask keeps its sign, so
Math::BigInt->new(-5) gives 255.255.255.251/32, as the text -5 does,
where it gave 0.0.0.5/32. A Math::BigInt NaN or infinity gives undef,
where it took the digits of the caller's last regex match as an
address and gave /0 as a mask.
- Fix GH#213: The POD no longer says that NetAddr::IP::Util accepts
the :lower and :upper import tags. Importing either still dies, as
it always has. The tags stay documented on the modules that
accept them: NetAddr::IP::InetBase, NetAddr::IP::Lite, and
NetAddr::IP.
- Fix GH#200: Subtraction takes every constant that addition takes. A
constant from 2**63 + 1 to 2**64 - 1 no longer croaks, and a
Math::BigInt of magnitude 2**64 or more croaks instead of wrapping.
- Fix GH#202: An index of 2**64 - 1 or more no longer makes nth()
croak. An index inside the subnet returns its address, and one past
the end returns undef.
- Fix GH#201: An IPv6-form mask of 1 to 95 ones on an IPv4 address
makes new() return undef, where it gave a negative prefix length
such as 192.0.2.4/-80.
- Fix GH#203: An IPv6 literal in brackets with the mask as a separate
argument, such as new('[2001:db8::1]', 64), gets the same mask as
without the brackets. The mask was read as an IPv4 prefix.
- Fix GH#211: The ipv6 mask on default, any, loopback or unspecified
gives the IPv6 address, such as 0:0:0:0:0:0:0:1/128 from
new('loopback', 'ipv6'), where it gave an IPv4 object, 0.0.0.1/32.
- Fix GH#147: Add NetAddr::IP::Count, a new implementation of the
interface of NetAddr-IP-Count 2.01 by Luis E. Munoz, whose valcount
method was contributed by Alvaro Carvajal. An address now counts once
in every group with a subnet that contains it, where 2.01 counted it in
one of them, chosen by hash order and the order of the addresses.
Anything but a NetAddr::IP object where an address or subnet belongs,
or anything but a number where a value belongs, croaks before any
total changes. The cache size is still accepted and reported, but no
longer affects counting.
- Fix GH#170: A host name passed to the constructors is resolved
with one getaddrinfo call. The IPv4 constructor uses an IPv4
answer when there is one. The IPv6 constructor uses an IPv6
answer when there is one, unless that answer is an IPv4-mapped
or IPv4-compatible address and an IPv4 answer exists. A short
IPv4 text such as 127.1 is packed by naip_gethostbyname() without
a lookup, as the constructors already did. Under :noSock6, names
still go to gethostbyname. A name whose only answer is an IPv6
address in ::/96, such as ip6-localhost at ::1, now gives that
address from both constructors, where glibc's gethostbyname gave
127.0.0.1. Text ending in a number or a 0x hex label, such as
host.123, is refused without a lookup.
- Fix GH#165: inet_ntop and AF_INET6 come from core Socket.
IPv6 names go through getaddrinfo. Socket6 is no longer
recommended. fake_AF_INET6 is deprecated, returns 0, and will
be removed in version 5.
- Fix GH#196: A bare number such as 10 now gets undef from inet_any2n()
instead of being read as the IPv6 address ::10.
- Fix GH#195: The constructors, new() and new6() among them, refuse a
leading zero in the upper bound of a short range, such as 192.0.2.8-011,
and in a negative number, such as -012, as they do in any other part of
an IPv4 address. Through new_no() they still read as decimal.
- Fix GH#194: Text with a NUL byte is refused by fillIPv4(), inet_aton()
and naip_gethostbyname(). The C resolver stopped reading at the NUL, so
192.0.2.010 followed by a NUL read as 192.0.2.8.
- Fix GH#193: A 0x or 0b literal wider than 32 bits is no longer cut to
its low 32 bits by new(); it is not an IPv4 address, and new() returns
undef without a warning.
- Fix GH#159: Threads parsing literal IPv4 addresses at once no
longer swap answers. A host name still goes to gethostbyname.
- Fix GH#174: In the XS build, add128() and sub128() take a list
prototype, so their two addresses can come from an array, as in the
pure Perl build.
- Fix GH#169: In the XS build, add128 and sub128 copy the first
address before reading the second. A second argument that
reassigns the first no longer makes them read freed memory.
Both builds copy that address before the second argument's get
magic, so a tied value cannot replace the first address.
On the XS build a short first address is now reported before an
undefined second, as pure Perl already does.
- Fix GH#189: In the pure Perl build, simple_pack() takes the prototype
$;@, as it does in the XS build.
- Fix GH#188: In the pure Perl build, bcdn2bin() takes the prototype $;@,
as it does in the XS build.
- Fix GH#187: In the pure Perl build, bcd2bin() takes the prototype $;@,
as it does in the XS build.
- Fix GH#186: In the pure Perl build, shiftleft() takes the prototype $;@,
as it does in the XS build.
- Fix GH#185: In the pure Perl build, ipv6to4() takes the prototype $;@,
as it does in the XS build.
- Fix GH#184: In the pure Perl build, comp128() takes the prototype $;@,
as it does in the XS build.
- Fix GH#183: In the pure Perl build, notcontiguous() takes the prototype
$, as it does in the XS build.
- Fix GH#182: In the pure Perl build, maskanyto6() takes the prototype $,
as it does in the XS build.
- Fix GH#181: In the pure Perl build, mask4to6() takes the prototype $, as
it does in the XS build.
- Fix GH#180: In the pure Perl build, ipv4to6() takes the prototype $, as
it does in the XS build.
- Fix GH#179: In the pure Perl build, ipanyto6() takes the prototype $, as
it does in the XS build.
- Fix GH#178: In the pure Perl build, bin2bcdn() takes the prototype $, as
it does in the XS build.
- Fix GH#177: In the pure Perl build, bin2bcd() takes the prototype $, as
it does in the XS build.
- Fix GH#176: In the pure Perl build, bcdn2txt() takes the prototype $, as
it does in the XS build.
- Fix GH#175: In the pure Perl build, hasbits() takes the prototype $,
as it does in the XS build, so a call without brackets and a call
whose argument returns a list read the argument alike in both builds.
- Fix GH#138: $NetAddr::IP::netlimit holds the netlimit() exponent,
so local scopes it. The function still returns 2**n.
- Fix GH#138: Name the package variables local can scope: the IPv6
case, name lookup, and the old nth() behaviour. :old_storable has
no variable and stays process-wide.
- Document new_no() as the constructor for IPv4 text with a leading
zero, read as decimal.
- Fix GH#162: Without Socket6, inet_pton(AF_INET) now accepts only four
decimal parts 0-255 with dots. Before, it used inet_aton and also
took short forms like "10.1", single numbers like "0", and host names.
Now it matches Socket6 and core Socket on all hosts. Tests in t/031
were added.
- Fix GH#163: Pure Perl now measures packed arguments in bytes, not
characters. Before, a string of wide characters (above 0xFF) that had
the "right" count would pass the length checks. Those calls then gave
wrong answers or died inside UtilPP. Now they croak "Wide character in
NetAddr::IP::Util::func" at the caller's line. A UTF-8 string that
holds only bytes still works. Tests in t/076 were updated.
4.080_06 2026-10-22 23:19:25+11:00 Australia/Sydney (TRIAL RELEASE)
- Fix GH#160: Refuse a packed argument holding a character above 0xFF in
the NetAddr::IP::InetBase functions that measure one, as the XS
functions of NetAddr::IP::Util already do. The length checks counted
characters, so 16 such characters passed the 16 byte check. Then
ipv6_n2x, ipv6_n2d and inet_ntoa returned a wrong answer, as did
ipv6_ntoa without Socket6, and from perl 5.28 isIPv4, isAnyIPv4 and
isNewIPv4 died inside InetBase.pm. Each now croaks with
"Wide character in" and the full name of the function that measures
the argument, at the caller's line. A string upgraded to UTF-8 is read
as its bytes, so ipv6_ntoa with Socket6 converts one rather than dying
in Socket6::inet_ntop.
- Take no leading zero in any part of an IPv4 address, and read the
whole string as the address in the InetBase and Util text functions.
A part such as the 010 in 192.0.2.010 is octal 8 to the C library's
inet_aton and decimal 10 to a person. Through gethostbyname, inet_aton
and new() read it as octal, while ipv6_aton and inet_any2n read it as
decimal, so the same text named two addresses. Such text is now not an
address anywhere except new_no(), which reads it as decimal as before.
The patterns of fillIPv4 and of the dotted quad tail in ipv6_aton
ended in $, which matches before a final newline, so one trailing
newline was ignored on some forms and not others. They now end in \z,
and inet_aton and naip_gethostbyname return undef for text with
whitespace without asking the resolver. The constructors keep
stripping surrounding whitespace from the address, as they have since
4.080_01 (GH#5), now strip it from a separate mask as well, and under
:aton keep the ends only of a string of four or sixteen bytes. A
prefix length keeps its leading zeros, so 192.0.2.0/024 is still
192.0.2.0/24. Against 4.079 these change:
call 4.079 now
inet_aton("192.0.2.1\n") 192.0.2.1 undef
inet_aton("192.0.2.010") 192.0.2.8 undef
ipv6_aton("::ffff:192.0.2.1\n") ::ffff:192.0.2.1 undef
inet_any2n("192.0.2.010") ::192.0.2.10 undef
new("010") 0.0.0.10/32 undef
new("192.0.2.010") 192.0.2.8/32 undef
new("::ffff:192.0.2.010") ::ffff:192.0.2.10 undef
new("192.0.2.0", "24\n") undef 192.0.2.0/24
- Fix GH#39: Coalesce no longer returns an empty list for a list holding
both IPv4 and IPv6 subnets. The families are now coalesced separately,
with the same mask length applied to each, and the IPv4 results come
before the IPv6 results. A list of one family is unchanged.
- Measure the argument of ipv6_ntoa in ipv6_ntoa itself, so a length
other than 16 bytes is reported by ipv6_ntoa, at the caller's line, on
every host. The argument went straight to inet_ntop, whose error named
Socket6::inet_ntop and a line inside InetBase.pm where Socket6 is
installed, and 'ipv6_n2x' where it is not. Every such length was
already refused, including a 4 byte IPv4 address, so nothing that
converted before is refused now.
- Name the caller's line in errors from NetAddr::IP::InetBase, as the XS
and pure Perl NetAddr::IP::Util errors already do, rather than a line
inside InetBase.pm. The functions croak where they used to die, and
the message before " at" is unchanged.
- Fix GH#156: isNewIPv4 croaks on an argument that is not 16 bytes, as
isIPv4 and isAnyIPv4 do, naming itself. It used to xor a short
argument against the mapped prefix, which pads it out to 16 bytes, so an
empty or 4 byte string gave false and a 12 to 15 byte string that began
with ten zero bytes and ffff gave true. Only a longer argument croaked.
The POD on both pages now says the same for all three.
- Refuse a family that is not a number in inet_ntop and inet_pton without
Socket6, before the comparison can warn. The string 'AF_INET' died
with the right message, but only after perl's "isn't numeric" warning,
raised inside InetBase.pm where the caller's no warnings cannot reach
it. It now dies with the same message and no warning. A number
followed by text, such as '2abc', was read as its leading digits and
accepted, and is now refused, the rule GH#89 set for addition and
subtraction. Padded, signed, decimal and exponent forms such as ' 2',
'+2', '2.0' and '2e0' are unaffected.
- Fix GH#148: README.md carries a repology packaging status badge, linking
to the list of packaged versions.
- Read the file list in t/001-no-pod-outside-lib.t from MANIFEST rather
than walking the working tree. On Windows the dependencies are installed
into local/lib/perl5 inside the checkout, so the walk read cpanel_json_xs
in local/bin, found POD there, and failed all five Windows jobs. MANIFEST
is the list of what ships, so nothing outside it can be read at all.
- Fix GH#146: Indent the text that Makefile.PL writes to Util_IS.pm, so
MetaCPAN no longer lists Makefile.PL as the documentation for
NetAddr::IP::Util_IS. The generated module is unchanged.
4.080_05 2026-10-15 13:40:32+11:00 Australia/Sydney (TRIAL RELEASE)
- Fix GH#142: Use Socket's own AF_INET6 where the Socket module has one,
rather than guess it from the operating system name
- Fix GH#140: Build the XS by default on macOS when a C compiler works;
Windows, Cygwin and DOS still default to pure Perl
- Declare perl 5.014 for the configure phase as well as runtime and test.
The configure prereqs carried 5.010, the version [MinimumPerl] found in
lib/ and copied there, and the shipped Makefile.PL opened with use
5.010. It now opens with use 5.014, passes MIN_PERL_VERSION 5.014
without a header override, and asks for ExtUtils::MakeMaker 6.5702,
which perl 5.14 ships as 6.57_05.
- RT #114495: Document that network() keeps the netmask; addr() gives the
address alone.
- Relicense to MIT, agreed by all three copyright holders. The
distribution was dual-licensed under GPL v2 and the Artistic License.
Prior releases remain under prior licenses.
4.080_04 2026-10-09 19:50:39+11:00 Australia/Sydney (TRIAL RELEASE)
- Fix GH#109: The wrap check in the Util EXAMPLES compared addresses as
strings, so text order stood in for address order. Two snippets stepped
an address with the overloaded ++ and decided whether the host part had
wrapped by comparing the string forms before and after. As text
192.0.2.10 sorts before 192.0.2.9, so the step from .9 to .10 read as a
wrap, and the real wrap from .11 back to .8 sorted after, so it read as
no wrap. Both snippets happened to print what the page said: the first
never wrapped, so its addconst branch never ran, and every address in
the loop had three digits in the last octet, where text order and
address order agree.
- Stepping every aligned subnet of 192.0.2.0/24 from /24 to /31, 255 nets
and 2048 steps, each net wrapping once, the string test reported 13
false wraps and missed 6 of the 255 real ones, in 192.0.2.64/26,
192.0.2.96/27, 192.0.2.96/28, 192.0.2.8/29, 192.0.2.96/29 and
192.0.2.8/30. Six IPv6 nets in 2001:db8::/32 gave 3 false wraps and no
missed ones. Comparing the objects got all 2048 IPv4 steps and all 4648
IPv6 steps right on both builds.
- Both snippets now take $before = $ip->copy and test $ip < $before, the
overloaded comparison, which subtracts the two 128 bit addresses and is
address order for either family. A step inside the net raises the
address and a wrap drops it to the network address, so the new address
is the lower one only at a wrap. The first snippet starts at
192.0.2.127/26 and steps by 64, so it takes the wrap branch and shows
the addconst list assignment the paragraph above it is about; it prints
192.0.2.128/26, where the string test prints 192.0.2.64/26. The loop
starts at 192.0.2.8/30, which passes both failure points, and its output
follows as result comments. The paragraph between them had called the
overloaded < the wrong test, when it is the right one, and had said
comparing string forms is what detects the wrap; the only fault in the
original test was $ip-copy(), which is not Perl. No code outside the
examples changes.
- Fix GH#111: Build XS by default where a compiler works, and delete the
checkout Makefile.PL. Three edits for GH#101 combined to disable the
compiler test: $useXS was initialised to 0 rather than left undefined,
which also made the new "!defined $useXS" test in the Windows rule
permanently false; the probe condition became "if ($useXS)" rather than
"unless (defined $useXS)", so it ran only when --xs was given; and a
successful probe no longer set $useXS = 1. So a plain "perl Makefile.PL"
wrote the pure Perl Makefile everywhere. That is the command cpan and
cpanm run, so an install from the next release would have built pure
Perl even where a compiler works, and the Linux CI job meant to test the
XS has been testing pure Perl while staying green. The same commit also
dropped the closing brace of an "if ($useXS)" block, so the checked-out
Makefile.PL no longer compiled at all.
- header.pl leaves $useXS undefined until an option or the platform rule
sets it, runs the probe when neither --xs nor -noxs was given, and sets
$useXS = 1 when a compiler works. That restores the 4.079 default while
keeping the GH#101 change that lets --xs override the Windows rule. With
--xs the probe is skipped and the build is XS, as in 4.079; a broken
compiler now fails at make instead of falling back to pure Perl, which
is what asking for the XS explicitly should mean.
- Each of the four build jobs now checks the mode it got rather than
passing as whichever build it happened to produce. t/033-util-mode.t
cannot do this: it derives its expectation from Util_IS->not_pure, so it
agrees with the build either way. The macOS job asserts Pure Perl, which
is the point of pinning it down, since it gets there by the accident
that "darwin" contains "win" and so matches the /win/i platform rule.
- The checked-out Makefile.PL is deleted rather than repaired. It is
excluded from the distribution, nothing regenerates it, and it had
drifted from inc/MakeMaker: it still used the older %makeparms spelling
instead of @mm_args, and carried a realclean naming xs/config.h,
xs/config.log and xs/config.status, which GH#101 stopped generating,
plus a clean override protecting lib/NetAddr/IP/Util.c, which GH#96
established is not tracked in git. README.md now says so and gives the
dzil build path.
- Restoring the XS build exposed a fault in the clean list that the pure
Perl default had been hiding. make clean did not remove
lib/NetAddr/IP/Util.o, because ExtUtils::MakeMaker only knows about
C_FILES and OBJECT when the XS branch fills them in, so the file
survived a clean, then a later perl Makefile.PL -noxs in the same tree
copied it into blib as though it were a module, which dragged the
postamble's xsubpp rule into a pure Perl build where $(XSUBPP) is unset.
That failed on "-ypemap". The clean list now names Util.c, Util.o and
Util.c.xsc as well. All three are generated, and in a pure Perl tree
naming absent files costs nothing.
- Fix GH#114: The XS build had not compiled since GH#106, so CI never
noticed: its Linux XS job builds pure Perl, see GH#111. The file carried
two definitions of _num_arg and two of have128 with no body. It was
missing _128x10plusbcd, which _bcdn2bin still called, and the unused
_isipv4. It used k and nv in comp128 and bcd2bin without declaring them,
and read the packed argument with SvPV rather than SvPVbyte in seven
functions. Restored GH#106 as filed, tests included: the duplicate is
gone, have128 keeps its GH#102 unaligned access fix, the missing helpers
are back, the packed argument is read with SvPVbyte while the digit text
in bcd2bin and simple_pack stays SvPV, and a count or constant is read
before a pointer into the address is taken. A fifth defect in the same
area: a packed address reached through get magic looked undefined.
_packed_ok runs the magic once and reports whether the value is then
defined, _packed_bytes reads the bytes without running the magic again
and through a downgraded copy when the argument is upgraded.
SvPVbyte_nomg would do this in one call but needs perl 5.31.4, so this
uses only calls available from 5.9.2.
- Fix GH#101: Remove the autoconf/configure step. The XS build ran one of
two autoconf scripts to write xs/config.h, and the C code takes exactly
two facts from that file: the host byte order and a pair of 32-bit
integer types. Both have been in perl.h since at least 5.005_03. The
configure step can go: four files, 31 percent of the compressed tarball,
about 60 lines of the Makefile.PL header, and the reason the module has
historically given for building pure Perl on Windows.
- Fix GH#102: Four helpers in xs/Util.xs read the caller's packed address
as 32-bit words through a cast of the Perl string buffer. That is
undefined behaviour in C whenever the buffer is not 4-byte aligned, and
Perl hands the XSUBs unaligned buffers in ordinary use. A string whose
leading bytes were removed in place keeps its allocation and moves its
start. On x86 and arm64 the loads still give the right answer, which is
why nothing has failed; on hardware that traps misaligned loads, SPARC
above all, the process dies with SIGBUS. The fix copies the bytes into
local words with memcpy, which compiles to the same instructions where
unaligned loads are cheap.
- Fix GH#7: Document that uppercase is the effective default, not
lowercase. InetBase said "This module defaults to lowercase", which
holds only when it is loaded on its own. NetAddr::IP::Util loads it with
:upper, so every program that uses NetAddr::IP prints uppercase. The
case setting is process wide and the last import or call wins, so a
lower() anywhere changes what every object prints. InetBase, IP.pm and
Lite.pm now say so.
- Fix GH#12: The :aton packed input is corrupted by lc for bytes 0x41 to
0x5A. The _xnew() function in Lite.pm ran $ip = lc $ip; before checking
whether the input was a packed binary address, so bytes 0x41-0x5A (A-Z)
became 0x61-0x7a (a-z). Fixed by preserving the original input in $raw
before lowercasing, and using it for the binary IP detection path.
- Fix GH#21: ipv6_aton accepts a single leading or trailing colon, which
RFC 4291 section 2.2 does not allow. The pure-Perl build shares this
code and behaves the same way. Fixed by adding explicit checks for a
single leading or trailing colon before processing.
- Final polish: constructor entry cleanup and import tag refinement.
- Unify the argument names and finish the import tag tables (GH#100, C5
and C7), the last two items from the structure list.
- C5 named one concept six ways across the three function pages. For a
16 byte string there were $ipv6naddr, $ipv6addr, $pv6naddr, $bits128
and $netaddr. Now $bits128 is the 16 byte string, $ipv6naddr an
address being converted, and $netaddr a 4 byte one:
$bits128 52 -> 60 uses, after the sweep
$ipv6naddr 48 -> 50
$netaddr 29
$ipv6addr 8 -> 0
$pv6naddr 2 -> 0
- $pv6naddr was a typo for $ipv6naddr, in two places. Checked first that
every occurrence of both names was POD or POD inside a comment, so no
code was renamed:
$ipv6addr in non-POD code 0 lines in each of the three files
- C7, three pages carried an import tag section and Lite.pm carried none,
and none of them said what happens when :lower and :upper are both
given. Verified rather than assumed, in both classes:
NetAddr::IP :lower 2001:db8:0:0:0:0:0:1
NetAddr::IP :upper 2001:DB8:0:0:0:0:0:1
NetAddr::IP :lower :upper 2001:DB8:0:0:0:0:0:1
NetAddr::IP :upper :lower 2001:DB8:0:0:0:0:0:1
- :upper wins either way, because :lower is handled first in import.
Lite.pm now has an IMPORT TAGS section covering the five tags it
accepts, each marked process-wide, and the precedence stated. Which is
the five was measured, since :old_storable and :rfc3021 belong to
NetAddr::IP alone:
:old_storable rejected by Lite
:rfc3021 rejected by Lite
:aton accepted
:old_nth accepted
:nofqdn accepted
- Documentation only, no code change.
- Group the remaining method and function entries (GH#100, C2 and the
grouped layout). IP.pm was grouped in the previous commit; this does
the other four.
Util.pm 34 entries into Text to binary, Binary to text, Case,
Family tests, Widening and narrowing, Arithmetic,
Decimal strings, Resolver, Build mode
InetBase.pm 21 entries into Text to binary, Binary to text,
Family tests, Address family, Short IPv4 text, Case
UtilPP.pm 13 entries into Family test and shift, Arithmetic,
Widening and narrowing, Decimal strings
Lite.pm 27 entries into the six groups it has, the same names
IP.pm uses where they overlap
- Each entry block was moved whole and checked to have survived
verbatim, and both the definition count and the POD item count are
unchanged in all six modules:
IP.pm 31 subs, 67 items
Lite.pm 50 subs, 39 items
Util.pm 7 subs, 41 items
InetBase.pm 29 subs, 25 items
UtilPP.pm 28 subs, 13 items
Constants.pm 0 subs, 14 items
- Two things worth recording about how this went.
- podchecker needs =head2 outside an =over, so each group is its own
list rather than headings inside one list. It also needs a blank line
before =back, or the =back is swallowed as ordinary text and the list
reads as unclosed. That only bit one group, because the group whose
entries happened to be last in the old order had no trailing blank
line to inherit. The error pointed at the next =head2, which sent the
first two attempts looking for an imbalance that was not there; the
cause only showed up when the block was reproduced in three lines.
- UtilPP.pm had two =head1 DESCRIPTION sections, one of them a single
line left over from the step 2 rewrite, and no FUNCTIONS heading at
all. Both fixed here.
- C3 finished at the same time: INSTALLATION is now gone from every
module. It was already gone from Util.pm, InetBase.pm, UtilPP.pm and
Constants.pm; IP.pm and Lite.pm still had it, so the build steps live
in README.md alone, and the two pages point at it from DESCRIPTION.
Nothing linked to the removed sections.
- Documentation only, no code change.
- Fix README.md (GH#100, step 4, the last one). It had errors of its own,
and three of them meant a reader's first attempt at the advanced
methods died.
- The four calling conventions in the advanced section were all wrong.
They were written as functions called on the class name, where the
arguments land in $_[0] where an object is expected:
NetAddr::IP->split($base,$bits)
dies: Can't use string ("NetAddr::IP") as a HASH ref
NetAddr::IP->rsplit($base,$target)
dies: Can't use string ("NetAddr::IP") as a HASH ref
NetAddr::IP->hostenum($ips)
dies: Can't use string ("NetAddr::IP") as a HASH ref
NetAddr::IP->compact(@ips)
dies: Can't use string ("NetAddr::IP") as a HASH ref
NetAddr::IP->coalesce(@ips)
returns one value, silently
- Every one of them is a method on an object:
$ip->split(26) $ip->rsplit(28,29,28,29,26)
$ip->splitref(26) $ip->rsplitref(28,29,28,29,26)
$ip->hostenum $ip->hostenumref
$ip->compact(@other) $ip->compactref(\@other)
$ip->coalesce($masklen,$number,@other)
- The coalesce case is the nastiest, because it returns rather than
dying, which is the same silent-wrong-answer shape as GH#39.
- The examples used 192.168.1.123 and fe80::1. Replaced with the RFC
5737 and RFC 3849 documentation addresses, so nothing in the README
points at a range someone might own, and the IPv6 outputs are the real
ones, which are not what a reader would guess:
new('2001:db8::1/64')->network 2001:DB8:0:0:0:0:0:0/64
new('2001:db8::1/64')->broadcast 2001:DB8:0:0:0:FFFF:FFFF:FFFF:FFFF/64
- InetBase was described as "low-level inet address conversion (mostly
XS)". It is pure Perl on every host; UtilPP is the pure Perl half and
Util is the XS one. The module list also said four modules and gave
no mention of UtilPP or Constants, so all six are now listed, with
NetAddr::IP::Util_IS noted as generated.
- is_local was described as "true for 127.x.x.x or ::1", which misses
the two IPv6 forms the code accepts:
127.0.0.1=1 ::1=1 ::127.0.0.1=1 ::ffff:127.0.0.1=1
- The export tag table omitted :old_storable, :aton and :rfc3021. All
three are added and marked deprecated, and the entry for :rfc3021
says why it is no longer needed.
- Added what was missing rather than only fixing: the mask-argument
trap, the array deref overload and the two croaking operators, the
comparison order, the /31 and /127 host count, the split croak, a
worked example showing split and rsplitref actually differing on the
same plan, and a Functions section for Compact, Coalesce and
netlimit, which had no home at all.
- The Authors section listed two of the three, and gave an address for
Michael Robinton that is not the one in dist.ini. It now matches
META.json.
- Documentation only. No module was touched, checked by counting
definitions before and after: IP.pm 31/31, Lite.pm 50/50, Util.pm
7/7, InetBase.pm 29/29, UtilPP.pm 28/28, Constants.pm 0/0.
- Group the IP.pm methods, rewrite its SYNOPSIS, and document netlimit
(GH#100, step 3 continued). The Methods section was one flat =over of
forty-eight entries, so a reader looking for how to enumerate hosts
scanned forty-eight headings. It is now ten =head2 groups, each its
own =over:
Constructors new new6 new_no new_from_aton
new_cis new_cis6
Address and mask addr mask masklen bits version cidr aton
Boundaries network broadcast first last range
Numeric forms numeric bigint
Text forms short canon full full6 full6m prefix
nprefix wildcard
Containment contains within is_rfc1918 is_local
Splitting split splitref rsplit rsplitref
Set operations compact compactref coalesce
Hosts num nth hostenum hostenumref
Regular expressions re re6
- That reorders entries, so each block was moved whole and checked to
have survived verbatim; 48 of 48 did, and the POD item count is
unchanged at 63. podchecker needs =head2 outside an =over, so each
group is its own list rather than one list with headings inside it.
- The SYNOPSIS was 113 lines: an import list, every signature, the
case policy, the FQDN note, Storable, Compact, Coalesce and
netlimit, all of it mixed together. It is now fifteen pasteable lines
with results in comments, and the material that was not a synopsis
moved to its own IMPORT TAGS section:
print $ip->addr, "\n"; # 192.0.2.1
print $ip->mask, "\n"; # 255.255.255.0
print $ip->network, "\n"; # 192.0.2.0/24
print $ip->broadcast, "\n"; # 192.0.2.255/24
print "$ip\n"; # 192.0.2.1/24
my $next = $ip + 5; # 192.0.2.6/24
my @halves = $ip->split(25); # 192.0.2.0/25, 192.0.2.128/25
- B11, netlimit was documented only inside the SYNOPSIS, which is where
the code lived too, and it returns the new limit rather than "true on
success". It has a FUNCTIONS section now, and the values are the
measured ones:
netlimit(20) 1048576
netlimit(16) 65536
netlimit(24) 16777216
netlimit(10) undef, below the default
netlimit(25) undef, above the maximum
- B4 through B7 are documented under the constructor, where the
abbreviated accepted-forms list is, with the mask-argument trap
spelled out since it is the one that surprises:
new('10.1') 10.0.0.1/32
new('10.1', 8) 10.1.0.0/8
new('10.1.2') 10.1.0.2/32
new('10.1.2', 24) 10.1.2.0/24
new('192.0.2.4-7') 192.0.2.4/30
new('192.0-3.') 192.0.0.0/14
new('[2001:db8::1]/64') 2001:DB8:0:0:0:0:0:1/64
new('[192.0.2.1]/24') undef
new('broadcast') 255.255.255.255/32
new6('broadcast') undef, IPv4 keywords only
new('loopback') 127.0.0.1/8, not /32
- And one correction to what I wrote in the previous commit for this
step: moving the SYNOPSIS deleted the netlimit sub and its $_netlimit
default, because the code sat between that heading and INSTALLATION
and the replacement spanned both. perl -c did not catch it and the
suite still passed 2535 tests, since nothing calls netlimit. What
caught it was documenting the function and finding
NetAddr::IP->can("netlimit") was undef. Restored, in the FUNCTIONS
section this time. Every edited file was then checked for lost
definitions:
IP.pm 31 subs before, 31 after, identical set
Lite.pm 50/50, Util.pm 7/7, InetBase.pm 29/29,
UtilPP.pm 28/28, Constants.pm 0/0
- plus the glob aliases, which also match.
- Fix NetAddr::IP and NetAddr::IP::Lite (GH#100, step 3). The two pages
carry the same object API and have drifted, so they go in one commit
and the merged text is written once.
- A4, both said splitref "returns undef when bits ... will not fit". It
croaks:
NetAddr::IP->new('192.0.2.0/24')->splitref(16);
`# netmask error: overrange or spurious bits`
- A6, the IP.pm SYNOPSIS listed inet_any2d and inetanyto6. Neither
exists; they are inet_any2n and ipanyto6, both of which Util has.
- A11, both new() entries said 'See "STRINGIFICATION" below.' There is
no such section on either page.
- A12, "The first two methods create..." followed by "The third method
new_no", after six constructors had been listed. new6FFFF was absent
from IP.pm's list altogether and works through inheritance, so the
entry now names it and shows the object it makes:
NetAddr::IP->new6FFFF('192.0.2.1');
`# 0:0:0:0:0:FFFF:C000:201/128`
- A13 is Util.pm, A17 is below. A19, IP.pm's DESCRIPTION promised
NetAddr::IP "will work with older versions of Perl". META.json says
5.014, so that is now stated.
- A20 and A22 are the drift between the two pages. IP.pm listed two
is_local forms where Lite.pm listed four, and Lite.pm's within()
carried a sentence about comparing addr() that IP.pm lacked. Both are
merged, verified against the code:
127.0.0.1 is_local=1
::1 is_local=1
::127.0.0.1 is_local=1
::ffff:127.0.0.1 is_local=1
::ffff:10.0.0.1 is_local=0
128.0.0.1 is_local=0
- The entries are now byte-identical between the two files, which is
checkable:
is_local() identical mask() identical first() identical
within() identical bits() identical last() identical
- A21, Lite.pm carried the numeric() float-comparison warning and IP.pm
did not. It is on both now, with the hazard shown rather than
described, because it is silent:
$x->numeric == $y->numeric same for 2001:db8::1 and ::2
$x == $y different
$x->bigint == $y->bigint different
- A23, both new_cis item headings had an unbalanced quote.
- A25, prefix() was documented as including the broadcast address. The
range starts at first(), not network():
192.0.2.4/30 -> 192.0.2.5-7
192.0.2.0/24 -> 192.0.2.
192.0.2.0/20 -> 192.0.0-15.
192.0.2.9/32 -> 192.0.2.9
- A27, both pages warned that comparing objects of differing CIDR "may
produce indeterminate - unexpected results". It is deterministic:
address first, then the mask as a number. The warning was wrong, and
the real caveat is that the order is not the one most people mean by
"bigger", so it says that instead and shows the sort order.
- A28, both listed "a netaddr as returned by 'inet_aton'" among the
accepted forms without saying it needs the deprecated :aton tag.
Without it a packed string returns undef, which is now stated. The
RFC 1884 citations became RFC 4291 s2.2 on both pages.
- A17, the IP.pm NOTES / BUGS section said in the first person that the
author lacked the resources to get the configure step working on
Windows and asked for volunteers. It now states the fact and where it
comes from, which is that header.pl selects pure Perl when $^O
matches /win/i, and points at README.md for the build steps.
- B1 and B2, the @{} overload and the croaking neg and abs, were
undocumented on both pages:
scalar @{$ip} 14 for a /28
-$ip cannot negate a NetAddr::IP object
abs $ip cannot take the absolute value of a NetAddr::IP object
- B3, the sort order is now given as part of the comparison entry.
- C4, version history inside method text is gone from nth() and num() on
both pages. Both entries carry measured output instead:
/32 nth(0) is the address itself, num 1
/31 nth(0) is the network address, num 2
/30 nth(0) is the first host, num 2
/28 num 14
- and the C<:old_nth> tag still restores the old behaviour, verified:
old_nth 192.0.2.0/30 nth 0 undef, 1..3 the hosts, num 3
- C9, IP.pm's HISTORY section, which said only "See the Changes file",
is removed and the internal link now points at DEPRECATED.
- Also fixed in passing: "array contest" for "array context" in IP.pm
and Lite.pm numeric(), a doubled space in Lite.pm bigint(), and the
C3.02 version note in compact().
- POD only, no code change. Still outstanding from this step: the
=head2 method groups, the SYNOPSIS rewrite, and B4 through B12 for the
constructor entry, which is where the accepted-forms list lives and is
long enough to need more than a correction.
- Fix NetAddr::IP::InetBase and NetAddr::IP::UtilPP (GH#100, step 2,
continued). The two carry copies of the entries fixed in Util.pm, so
they go in the same step.
- A7, the InetBase SYNOPSIS said "use NetAddr::IP::Base qw(...)", and
the module is NetAddr::IP::InetBase, so the line as printed could not
run. It was also followed by a NetAddr::IP::Util line pasted from
Util.pm showing Util's tags, which InetBase does not have. Both are
gone; the SYNOPSIS is now InetBase's own nineteen names with measured
output, and its four tags are listed with their real contents,
recovered by importing each into a scratch package:
:ipv4 fillIPv4 inet_aton inet_ntoa, three names
:ipv6 eleven names
- The old list for :ipv6 was missing four of those.
- A8, InetBase documented ipv4to6. It is neither defined nor exported
there; the function belongs to NetAddr::IP::Util, and
InetBase->can("ipv4to6") is undef. The entry is removed.
- A9, InetBase said lower() "is the default" and Util.pm said upper()
"is the default", and both were right about themselves and wrong
about the reader's program. Measured:
InetBase alone: ipv6_n2x = 2001:db8:0:0:0:0:0:1
after InetBase::upper() ipv6_n2x = 2001:DB8:0:0:0:0:0:1
Util loaded: ipv6_n2x = 2001:DB8:0:0:0:0:0:1
- InetBase defaults to lowercase, and loading Util, Lite or NetAddr::IP
imports :upper for you, so in practice uppercase is the default for
nearly every program. There is now one section, THE CASE POLICY, that
says so once, shows the process-wide behaviour where an unrelated
package importing :lower changes the output for everyone else, and
points at GH#7 for the open question of what the policy should be.
ipv6_ntoa and inet_ntop are called out as always lowercase.
- Worth recording, since the old entries implied otherwise: neither
lower nor upper is importable from either module.
NetAddr::IP::InetBase->can("lower") undef
NetAddr::IP::Util->can("lower") undef
- They must be called fully qualified, NetAddr::IP::InetBase::upper(),
and the entries now say so.
- fillIPv4 was documented as converting "127.1 to the long form
127.0.0.1", which is right, but nothing said what it does with
anything else, and it is not what a reader would guess. Measured:
fillIPv4('192.0.2.1') 192.0.2.1
fillIPv4('192.0.2') 192.0.0.2
fillIPv4('192.0') 192.0.0.0
fillIPv4('10') 0.0.0.10
fillIPv4('example.com') example.com, unchanged
fillIPv4('256.1.1.1') undef
- The argument is text, not a packed address, which is the trap: a
packed string does not match, so it comes back unchanged. It is also
the BSD inet_aton convention and not RFC 791, which is the note
table D asks for, and which belongs here rather than on inet_aton.
- A14, the missing paren in the hasbits example was in this file too,
at UtilPP.pm:111, so it is fixed in both.
- A15, the UtilPP EXPORT_OK list ended with "threads", which is not a
function of that module nor of NetAddr::IP::Util; it never existed.
Removed, and the list now cross references NetAddr::IP::Util instead
of being a bare list of eighteen names.
- A18's rfc1844 typo was here as well as in Util.pm, and the two rfc1884
citations became RFC 4291 s2.2.
- UtilPP gets a DESCRIPTION, which it did not have beyond one sentence.
It explains when the module is selected, that the two implementations
are meant to be interchangeable and agree down to the error message
wording, and that README.md carries the build steps, so no page
discusses building.
- INSTALLATION is removed from InetBase too, per C3.
- A new section on InetBase, SOCKET6 SUBSTITUTION, names the three
symbols that come from Socket6 when it is installed, says the choice
is made at load time, and points at GH#99 and GH#21 for where the two
paths disagree.
- POD only, no code change. The grouped =head2 sections the issue asks
for across all three function pages, and the table D note about
inet_aton short forms, are still outstanding.
- Fix NetAddr::IP::Util (GH#100, step 2 of the POD overhaul). The
SYNOPSIS was a 118 line import list followed by every signature, a
table of contents rather than a synopsis; it is now about forty lines
that a reader can paste, and every value in it is the measured output
rather than a placeholder. INSTALLATION is removed, per the rules,