--- /dev/null
+
+
+
+
+ The "Artistic License"
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder. A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this
+Package. You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own. You may embed this Package's interpreter within
+an executable of yours (by linking); this shall be construed as a mere
+form of aggregation, provided that the complete Standard Version of the
+interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package. If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of this Package with a commercial distribution is always
+permitted provided that the use of this Package is embedded; that is,
+when no overt attempt is made to make this Package's interfaces visible
+to the end user of the commercial distribution. Such use shall not be
+construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
--- /dev/null
+Revision history for Perl extension NetAddr::IP
+
+4.058 Fri Nov 11 19:23:11 PST 2011
+ up rev for documentation update
+ update documentation in InetBase v0.06
+
+4.057 Fri Nov 11 15:04:20 PST 2011
+ Lite.pm v1.40
+ add call to InetBase::fillIPv4 to all uses of gethostbyname
+
+ break out the code in InetBase v0.05 that expands short IPv4
+ addresses into dotquad format to account for broken BSD
+ implementations of inet_aton and gethostbyname that do
+ not recognize the short format. EXPORT this as sub 'fillIPv4'
+
+ in Util.pm v1.45, add 'fillIPv4' to calls to gethostbyname to
+ work around broken inet_aton and gethostbyname implementations
+ in certain BSD implementations
+
+4.056 Wed Nov 2 19:15:31 PDT 2011
+ bump rev to incorporate
+ improved inet_aton in InetBase v0.04 to overcome broken
+ gethostbyname found in NetBSD and OpenBSD
+
+4.055 Fri Oct 28 11:41:22 PDT 2011
+ in Lite.pm v1.38
+ patch for bug 71869, issues with Math::BigInt varients
+
+4.054 Thu Oct 27 12:48:55 PDT 2011
+ In Lite.pm v1.37, remove Calc.pm
+ add detection of early Math::Bigint object structure
+ fix bug 71869 - a failed test routine
+
+4.053 Wed Oct 26 08:52:34 PDT 2011
+ In Lite.pm v1.36
+ fix bug #71925. A a sub-varient of #62521 that showed up only for
+ short notation for IPv4. i.e. 127/n, 127.0/n, 127.0.0/n but
+ not 127.0.0.0/n
+
+4.052 Tue Oct 25 16:18:38 PDT 2011
+ add test in Lite.pm v1.35 for api-version of Math::BigInt to
+ support versions earlier than 1.70, circa Dec 2003.
+ Thanks to Paul Howarth <paul@city-fan.org> for spotting that bug.
+
+4.051 Mon Oct 24 14:44:53 PDT 2011
+ fix bug 71869
+ in Lite.pm v1.34
+ use Math::BigInt::Calc for creating BigInt values and fall
+ back to NetAddr::IP::Calc if Math::BigInt is not present.
+
+ remove reference to Config{osname} in InetBase.pm v0.03
+ (Util 1.43)
+
+
+4.050 Sat Oct 22 01:58:57 PDT 2011
+ In Lite/Util/lib/NetAddr/IP/Lite/Util/InetBase.pm v0.02
+ Socket6 prior to version 0.23 does not have AF_INET6 in the
+ EXPORT_OK array, modify InetBase.pm v0.2 to work around this.
+
+ Add support for Math::BigInt to NetAddr::IP::Lite v1.33
+
+4.049 Sat Oct 15 22:15:10 PDT 2011
+ Updates to Lite.pm, Util.pm, new module InetBase.pm
+
+ In Lite v1.32
+ bug68723, add capability to parse input of the form
+ ->new6(12345,1). This should have been there but was
+ missing. Thanks to Andrei Benea for spotting this.
+
+ In Util v1.41
+ add inet_pton, inet_ntop, AF_INET, AF_INET6
+
+ modify inet_n2dx and inet_n2ad to
+ recognize the new 128 bit IPv4 format
+ ::FFFF:FFFF:0:0
+
+ replace isIPv4 with a pure perl version for portablity
+
+ split the following into NetAddr::IP::InetBase v0.01
+ to provide better long term support for IPv6
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ inet_n2dx
+ inet_n2ad
+ inet_ntop
+ inet_pton
+ packzeros
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ AF_INET
+ AF_INET6
+
+4.048 Sat Oct 8 01:33:44 PDT 2011
+ remove debug print statement from Util v1.40
+
+4.047 Thu Oct 6 23:41:42 PDT 2011
+ really correct missing reference in Util v1.39
+ doc update only in Lite.pm v1.30
+
+4.046 Thu Oct 6 20:20:33 PDT 2011 DEPRECATED
+ corrected missing reference to inet_4map6 in Util v1.38
+
+4.045 Thu Oct 6 18:23:04 PDT 2011 DEPRECATED
+ updated NetAddr::IP::Util 1.37
+ addid isAnyIPv4, isNewIPv4, inet_4map6
+ revised naip_gethostbyname
+ to conform to Perl's gethostbyname output
+
+4.044 Wed May 18 14:47:34 PDT 2011
+ added missing support for ->compactref(\@list) which is described
+ in the documentation but not implemented.
+
+ Thanks to Rusty Bourland codebard@gmail.com for spotting this
+ and providing both a patch and test code
+
+4.043 Wed Apr 6 11:31:19 PDT 2011
+ Update documentation on the use of "adding constants
+ to an IP address".
+
+4.042 Tue Mar 22 15:26:02 PDT 2011
+ Update Lite.pm v1.27 to encompass treatment of /31 and /127
+ point-to-point networks as described in RFC 3021
+
+ NOTE: for /31's and /127's
+ this changes the behavior of the following methods:
+ first returns the "network" address
+ last returns the "broadcast" address
+ nth index 0 returns "network" addr instead of undef
+ nth index 1 returns "broadcast" addr instead of undef
+ num returns 2 instead of 0 (zero)
+
+ "old_nth" behavior is unchanged
+
+ Thanks to Todd Caine todd.caine@gmail.com for pointing this out.
+
+4.041 Tue Mar 8 15:18:16 PST 2011
+ Updated Lite.pm v1.26, "sub num" to support usable IP ranges
+ greater than 2**32
+
+ Thanks to Jan Ploski jan@plosquare.com for finding this bug
+
+4.040 Sat Feb 19 10:04:00 PST 2011
+ correction to use of Util.pm package lexicals
+
+ thanks to mishikal@yahoo.com for spotting the bug and to
+ Mark Martinec mark.martinec+ama...@ijs.si for the solution.
+
+4.039 Wed Feb 16 15:48:03 PST 2011
+ Correct documentation for 'split' methods
+
+4.038 Fri Dec 17 17:47:47 PST 2010
+ Modify subs "new" and "new6" in Lite.pm to accomodate
+ Cisco mask syntax that uses space instead of "/" for a separator
+ This eliminates the need for "new_cis" and "newcis6" which are now
+ deprecated.
+
+ Modify LIte/t/v4-cnew.t and add Lite/t/v6-cnew.t to test the above
+
+4.037 Fri Nov 19 10:48:01 PST 2010
+ add :upper and :lower to Lite.pm v1.23
+ add comments about rfc5952 requirement for lowercase ipV6 notation
+ in Lite.pm v1.23 and IP.pm
+ add test for :lower in Lite.pm v1.23
+
+4.036 Tue Nov 16 16:28:37 PST 2010
+ In Util.pm v1.35, naip_gethostbyname modified to return undef
+ instead of 0 (zero) on failure
+
+ thanks to Terry Cassidy enaudishaylee@tc17.com for the bug report
+
+ In Util.pm v1.35, move sub's ipv6_n2d and ipv6_n2x to non-autosplit
+ portion of module to eliminate warnings during autosplit of "our"
+ variables
+
+ thanks to Nicholas Bamber <nicholas@periapt.co.uk>
+ Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=517361
+
+ In Lite.pm v1.22, update new6 to properly classify short ipv4 notation
+ i.e. 127/8 with test for ":" rather than match for \d.\d.\d.\d
+
+ thanks to Steve Huff (SHUFF) * shuff@cpan.org for
+ spotting that bug.
+
+ In Lite.pm v1.22, update t/v4-new.t for deprecated array syntax in
+ perl 5.13
+ was: qw(...stuff...)
+ is: (qw(...stuff...))
+
+ thanks to Todd Rinaldo <toddr@cpan.org> for reporting this
+
+4.035 Thu Oct 28 14:26:19 PDT 2010
+ fix bug in Lite v1.21 where new6 improperly assigns the mask value
+ for and ipv4 address in 32 bit space instead of 128 bit space
+
+ Thanks to Mark Martinec and Steve Huff (SHUFF) * shuff@cpan.org
+ for spotting and replicating that bug
+
+ added new_cis and new_cis6 to Lite.pm v1.21 to accomodate
+ Cisco syntax that has IP and MASK seperated by a space.
+
+ Updated typo in documentation that left out example
+ print new6 stuff
+
+4.034 Mon Oct 25 16:22:01 PDT 2010
+ Updated Lite::_xnew v1.20 to properly handle ipV6 notation of the form
+ xxxx:xxxx:xxxx:xxxx:xxxx:xxxx, DDD
+
+ Thanks to Dusty Mabe <Dusty.Mabe@tekelec.com> for spotting this bug
+
+4.033 Wed Sep 29 10:32:50 PDT 2010
+ Conditionalize import of AF_INET6 in Util.pm
+ NetAddr::IP::UtilPolluted
+
+4.032 Wed Sep 22 13:39:08 PDT 2010
+ Added overload => 'ne' and '!=' to Lite.pm v1.18
+
+4.031 Tue Sep 21 19:21:04 PDT 2010
+ Pull Socket6 stuff out of Lite 1.17 and put into
+ NetAddr::IP::Util.pm 1.33 in its own namespace
+
+4.030 Tue Jul 20 15:32:23 PDT 2010
+ Resolve named hosts in Lite.pm using gethostbyname, followed by
+ gethostbyname6 to determine whether to set ipV6 flag
+
+ Thanks to Dusty Mabe <Dusty.Mabe@tekelec.com> for spotting this bug
+
+4.029 Thu Jul 8 18:17:38 PDT 2010
+ In NetAddr::IP::Lite,
+ added support for the sub "new" to resolve host6 names
+ if the OPTIONAL perl Socket6 module is available
+
+ Thanks to "Mabe, Dusty" <Dusty.Mabe@tekelec.com> for spotting
+ this and suggesting a fix.
+
+4.028 Wed May 12 14:18:20 PDT 2010
+ In /Lite/Util/Util.xs v1.32,
+ changed netswap() to postincrement
+ *a++ = to *a and added increment after save to mollify some
+ picky compilers that return possible undefined behavior.
+
+ changed type of _128x10 to 'void'
+
+ Thanks to David Bolt <dbolt@davjam.org> for the above two patches
+
+4.027 Tue Jun 9 10:31:11 PDT 2009
+ In NetAddr::IP::Util v1.31,
+ ferret out shell value for Makefile.PL when calling
+ ./configure for systems where the 'x' bit gets lost
+ due to bug in Archive::Tar
+
+4.026 Sat Mar 7 16:35:33 PST 2009
+ make the compiler test check the environment for
+ CC before using Perl's default compiler
+
+4.025 Sat Mar 7 16:15:18 PST 2009
+ revised compiler test in Makefile.PL for Util v1.29
+ to accomodate picky Solaris "cc"
+
+4.024 Mon Jan 26 00:27:32 PST 2009
+ documentation update
+
+4.023 Fri Jan 16 14:30:40 PST 2009
+ added the capability to set the CASE of ipV6 text return
+ values to either upper or lower. Thanks to
+ Rob Riepel <riepel@networking.Stanford.EDU> for developing
+ this improvement and providing a comprehensive patch
+
+4.022 Sat Dec 20 13:05:01 PST 2008
+ In Util.xs 1.28
+ set uninitialized "carry" in XS bin2bcd to zero
+
+ This insidious bug only showed up on 64 bit hosts running perl 5.6.2
+ Thanks to Oliver Paukstadt <pstadt@sourcentral.org> for taking the
+ time to do the testing for me on his s390 system.
+
+4.021 Wed Dec 10 11:09:36 PST 2008
+ Removed test code that produces a warning about all perl versions,
+ OOPS!! instead of just the buggy 5.8.0 - 5.8.5 versions.
+ Thanks to paul@city-fan.org for reporting this.
+
+4.020 Tue Dec 9 16:25:46 PST 2008
+ cleaned up various typo's with good patch from
+ Rob Riepel <riepel@networking.Stanford.EDU>
+ thanks Rob.
+
+ revised UtilPP v1.7 to work around perl 5.8.4
+ failures with certain @_ operations of goto &sub...
+ see perl bug [ 23429]. Unfortunately, perl-5.8.4 is
+ the distribution of choice for many solaris boxes
+
+4.019 Sat Nov 29 15:15:30 PST 2008
+ in Lite/Util, add pure perl testing to XS build
+
+4.018 Fri Nov 28 23:19:01 PST 2008
+ revised XS code to be full re-entrant, thread safe in Util.xs v1.26
+ removed all traces of mutex locks in Util.xs v1.26
+ removed function 'threads' here an in UtilPP v1.6
+
+4.017 Sun Nov 23 19:32:59 PST 2008
+ Extended the capability of 'splitref' to allow splitting of
+ objects into multiple pieces with differing CIDR masks.
+ Returned object list can be split from bottom to top
+ or from top to bottom depending on which method is called
+
+ split, rsplit, splitref, rsplitref
+
+ Thanks to kashmish <kashmish@gmail.com> for the idea on
+ improving functionality of 'split'.
+
+ Thanks to Rob Riepel <riepel@networking.Stanford.EDU>
+ for a faster and more accurate _compV6 function.
+
+ in UtitPP v1.5
+ correct documentation error
+ add threads reporting (empty string)
+
+ in Util v1.25
+ add threads reporting that returns a comma separated
+ string of build headers.
+
+ added what is hopefully thread safe operation via
+ serialization. Must be invoked by "--with-threads"
+
+ in Lite v1.12
+ corrected missing Zeros subroutine
+ Zeros and Zero both will work
+
+ in Lite v1.12
+ added minus (-) overloading to allow the subtraction
+ of two NetAddr::IP objects to get the difference between
+ the object->{addr}'s as a numeric value
+ Thanks to Rob Riepel <riepel@networking.Stanford.EDU>
+ for the initial code and inspiration for this enhancement
+
+4.016 Wed Nov 5 18:13:20 PST 2008
+ in Util/ version 1.24
+ Clean up Makefile.PL to check actual required link
+ libraries against the perl build for consistency
+
+4.015 Sun Nov 2 10:10:38 PST 2008
+ in Util v1.23 add missing headers in configure and localconf.h
+ for Solaris inet_xton
+ thanks to Karl Bunch <karl@digilink.net> for spotting the bug.
+
+4.014 Sat Nov 1 15:13:48 PST 2008
+ in Lite.pm v1.11, add test for characters not allowed by
+ rfc952 before the call to gethostbyname in sub new() for those
+ people that insist on using deprecated functionality :aton
+ and OS's that fail to notice calls to gethostbyname with
+ binary arguments.
+
+4.013 Wed Oct 22 15:04:49 PDT 2008
+ In Lite.pm v1.10, add new no octal method for
+ improperly formatted ipV4 addresses
+
+ In Util.pm v1.22, eliminated dependence on PL_sawampersand
+ thanks to Mark Martinec <Mark.Martinec@ijs.si>
+ for spotting this and submitting a patch.
+
+ In Util.pm v1.22, force -noxs mode for Win32
+
+ In Util.pm v1.22, use autoconf to configure 'C' build
+
+4.012 Thu Oct 16 19:35:33 PDT 2008
+ clear build bug for Win32 in Util.pm v 1.21
+
+4.011 released Oct 6 13:10
+
+4.010 Sat Sep 27 17:00:28 PDT 2008
+ in NetAddr::IP::Util v0.19
+ updated test for ENDIANess in siteconf
+
+ add test in inet_aton to detect overange IP dot quad values
+ missed by some broken Socket implementations
+ i.e. 256.1.1.1 would fail to return undef
+
+NOTE: Versions 4.008 and 4.009 had limited release to tester only
+ and were not uploaded to CPAN. All of the v4.008, 4.009
+ changes are incorporated in v4.010
+
+4.009 Tue Sep 2 19:09:57 PDT 2008
+ In NetAddr::IP::Lite v1.07,
+ in the off chance that NetAddr::IP::Lite objects are created
+ and the caller later loads NetAddr::IP and expects to use
+ those objects, let the AUTOLOAD routine find and redirect
+ NetAddr::IP::Lite method and subroutine calls to NetAddr::IP.
+
+ updated Lite/t/v4-wnew.t so that non-existent
+ domains are "really" not there
+
+4.008 Sat Jun 7 14:01:55 PDT 2008
+ inherit method "new_from_aton" from NetAddr::IP::Lite
+ add related documentation
+
+ Inherited methods from Lite.pm updated as follows:
+
+ comparisons of the form <, >, <=, >=
+ 10.0.0.0/24 {operator} 10.0.0.0/16
+ return now return the comparison of the cidr value
+ when the address portion is equal.
+NOTE: this comparison returns the comparison of the NUMERIC
+ value of the CIDR. This produces the counter intuitive result
+ that /24 > /16. There is logic to this, really! For proper
+ operation of commands like "Compact" and "Coalesce", lists of
+ netaddr objects must sort in ascending order. However, this
+ conflicts with the requirement for larger netblocks to sort
+ FIRST so as to include smaller ones. This logic extends to
+ any requirement for a sort of netaddr objects. It should be
+ further noted that the mixing of netaddr objects with varying
+ IP addresses and CIDR allocations can lead to unexpected
+ results since the comparisons done first on the IP portion
+ and then on the CIDR portion. The documentation has been
+ updated appropriately.
+ Thanks to Peter DeVries for spotting this discrepancy
+
+4.007 Wed Jun 6 16:41:11 VET 2007
+ Update copyright dates
+
+4.006 Wed Jun 6 15:58:04 VET 2007
+
+ A patch from Michael got rid of $& and $` as reported by Daryl
+ O'Shea and documented at
+ http://issues.apache.org/SpamAssassin/show_bug.cgi?id=5312
+
+4.004 Wed Aug 16 16:01:54 PDT 2006
+ update to include/exclude files in corrupted distro
+
+4.003 Sun Aug 6 10:48:25 PDT 2006
+ correct SYNOPSIS documentation
+ add :old_nth
+
+ update Lite.pm documentation
+ update Util.pm documentation
+ Imported into distribution CVS tree - Some revision number
+ mismatches are to be expected
+ Latin-1 is back
+ Fixed some angle brackets so that they show up in the docs
+
+4.002 Fri Aug 4 14:14:16 PDT 2006
+ remove unused global variable $isV6
+
+ update Lite.pm to v1.02
+ $isV6 global converted to a lexical variable within sub "_xnew"
+ $Class global removed and replaced by calls to UNIVERSAL::isa
+ Thanks to julian@mehnle.net for spotting problems related to
+ using the Lite.pm with mod_perl
+
+4.001 Thu Jul 6 14:09:01 PDT 2006
+ various bug fixes courtesy of Luis Munoz:
+ changes to Lite.pm v1.01, Util.pm v0.17 see Changes in those distros.
+ update t/v6-re.t, addconst called as a scalar, should be called to
+ return the address value ()[1]
+
+4.000 Mon Jun 19 21:51:10 PDT 2006
+ initial release of version 4.000 which includes
+ full support of ipV6 addresses and drops the requirement
+ for Math::BigInt and will run on older versions of Perl
+ at least back to 5.005_03
+
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+#!/usr/bin/perl -w
+
+package NetAddr::IP;
+
+use strict;
+#use diagnostics;
+use NetAddr::IP::Lite 1.41 qw(Zero Zeros Ones V4mask V4net);
+use NetAddr::IP::Util 1.46 qw(
+ sub128
+ inet_aton
+ inet_any2n
+ ipv6_aton
+ isIPv4
+ ipv4to6
+ mask4to6
+ shiftleft
+ addconst
+ hasbits
+ notcontiguous
+);
+
+use AutoLoader qw(AUTOLOAD);
+
+use vars qw(
+ @EXPORT_OK
+ @EXPORT_FAIL
+ @ISA
+ $VERSION
+ $_netlimit
+);
+require Exporter;
+
+@EXPORT_OK = qw(Compact Coalesce Zero Zeros Ones V4mask V4net netlimit);
+@EXPORT_FAIL = qw($_netlimit);
+
+@ISA = qw(Exporter NetAddr::IP::Lite);
+
+$VERSION = do { sprintf " %d.%03d", (q$Revision: 4.58 $ =~ /\d+/g) };
+
+=pod
+
+=head1 NAME
+
+NetAddr::IP - Manages IPv4 and IPv6 addresses and subnets
+
+=head1 SYNOPSIS
+
+ use NetAddr::IP qw(
+ Compact
+ Coalesce
+ Zeros
+ Ones
+ V4mask
+ V4net
+ netlimit
+ :aton DEPRECATED
+ :lower
+ :upper
+ :old_storable
+ :old_nth
+ );
+
+ NOTE: NetAddr::IP::Util has a full complement of network address
+ utilities to convert back and forth between binary and text.
+
+ inet_aton, inet_ntoa, ipv6_aton, ipv6_ntoa
+ ipv6_n2x, ipv6_n2d inet_any2d, inet_n2dx,
+ inet_n2ad, inetanyto6, ipv6to4
+
+See L<NetAddr::IP::Util>
+
+
+ my $ip = new NetAddr::IP::Lite '127.0.0.1';
+ or if your prefer
+ my $ip = NetAddr::IP::Lite->new('127.0.0.1);
+ or from a packed IPv4 address
+ my $ip = new_from_aton NetAddr::IP::Lite (inet_aton('127.0.0.1'));
+ or from an octal filtered IPv4 address
+ my $ip = new_no NetAddr::IP::Lite '127.012.0.0';
+
+ print "The address is ", $ip->addr, " with mask ", $ip->mask, "\n" ;
+
+ if ($ip->within(new NetAddr::IP "127.0.0.0", "255.0.0.0")) {
+ print "Is a loopback address\n";
+ }
+
+ # This prints 127.0.0.1/32
+ print "You can also say $ip...\n";
+
+* The following four functions return ipV6 representations of:
+
+ :: = Zeros();
+ FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF = Ones();
+ FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:: = V4mask();
+ ::FFFF:FFFF = V4net();
+
+
+###### DEPRECATED, will be remove in version 5 ############
+
+ * To accept addresses in the format as returned by
+ inet_aton, invoke the module as:
+
+ use NetAddr::IP qw(:aton);
+
+###### USE new_from_aton instead ##########################
+
+* To enable usage of legacy data files containing NetAddr::IP
+objects stored using the L<Storable> module.
+
+ use NetAddr::IP qw(:old_storable);
+
+* To compact many smaller subnets (see: C<$me-E<gt>compact($addr1,$addr2,...)>
+
+ @compacted_object_list = Compact(@object_list)
+
+* Return a reference to list of C<NetAddr::IP> subnets of
+C<$masklen> mask length, when C<$number> or more addresses from
+C<@list_of_subnets> are found to be contained in said subnet.
+
+ $arrayref = Coalesce($masklen, $number, @list_of_subnets)
+
+* By default B<NetAddr::IP> functions and methods return string IPv6
+addresses in uppercase. To change that to lowercase:
+
+NOTE: the AUGUST 2010 RFC5952 states:
+
+ 4.3. Lowercase
+
+ The characters "a", "b", "c", "d", "e", and "f" in an IPv6
+ address MUST be represented in lowercase.
+
+It is recommended that all NEW applications using NetAddr::IP be
+invoked as shown on the next line.
+
+ use NetAddr::IP qw(:lower);
+
+* To ensure the current IPv6 string case behavior even if the default changes:
+
+ use NetAddr::IP qw(:upper);
+
+* To set a limit on the size of B<nets> processed or returned by NetAddr::IP.
+
+Set the maximum number of nets beyond which NetAddr::IP will return and
+error as a power of 2 (default 16 or 65536 nets). Each 2**16 consumes approximately 4 megs of
+memory. A 2**20 consumes 64 megs of memory, A 2**24 consumes 1 gigabyte of
+memory.
+
+ use NetAddr::IP qw(netlimit);
+ netlimit 20;
+
+The maximum B<netlimit> allowed is a 2**24. Attempts to set limits below the
+default of 16 or above the maximum of 24 are ignored.
+
+Returns true on success otherwise undef.
+
+=cut
+
+$_netlimit = 2 ** 16; # default
+
+sub netlimit($) {
+ return undef unless $_[0];
+ return undef if $_[0] =~ /\D/;
+ return undef if $_[0] < 16;
+ return undef if $_[0] > 24;
+ $_netlimit = 2 ** $_[0];
+};
+
+=head1 INSTALLATION
+
+Un-tar the distribution in an appropriate directory and type:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+B<NetAddr::IP> depends on B<NetAddr::IP::Util> which installs by default with its primary functions compiled
+using Perl's XS extensions to build a 'C' library. If you do not have a 'C'
+complier available or would like the slower Pure Perl version for some other
+reason, then type:
+
+ perl Makefile.PL -noxs
+ make
+ make test
+ make install
+
+=head1 DESCRIPTION
+
+This module provides an object-oriented abstraction on top of IP
+addresses or IP subnets, that allows for easy manipulations.
+Version 4.xx of NetAdder::IP will will work with older
+versions of Perl and is compatible with Math::BigInt.
+
+The internal representation of all IP objects is in 128 bit IPv6 notation.
+IPv4 and IPv6 objects may be freely mixed.
+
+=head2 Overloaded Operators
+
+Many operators have been overloaded, as described below:
+
+=cut
+
+ #############################################
+ # These are the overload methods, placed here
+ # for convenience.
+ #############################################
+
+use overload
+
+ '@{}' => sub {
+ return [ $_[0]->hostenum ];
+ };
+
+=pod
+
+=over
+
+=item B<Assignment (C<=>)>
+
+Has been optimized to copy one NetAddr::IP object to another very quickly.
+
+=item B<C<-E<gt>copy()>>
+
+The B<assignment (C<=>)> operation is only put in to operation when the
+copied object is further mutated by another overloaded operation. See
+L<overload> B<SPECIAL SYMBOLS FOR "use overload"> for details.
+
+B<C<-E<gt>copy()>> actually creates a new object when called.
+
+=item B<Stringification>
+
+An object can be used just as a string. For instance, the following code
+
+ my $ip = new NetAddr::IP '192.168.1.123';
+ print "$ip\n";
+
+Will print the string 192.168.1.123/32.
+
+=item B<Equality>
+
+You can test for equality with either C<eq> or C<==>. C<eq> allows the
+comparison with arbitrary strings as well as NetAddr::IP objects. The
+following example:
+
+ if (NetAddr::IP->new('127.0.0.1','255.0.0.0') eq '127.0.0.1/8')
+ { print "Yes\n"; }
+
+Will print out "Yes".
+
+Comparison with C<==> requires both operands to be NetAddr::IP objects.
+
+In both cases, a true value is returned if the CIDR representation of
+the operands is equal.
+
+=item B<Comparison via E<gt>, E<lt>, E<gt>=, E<lt>=, E<lt>=E<gt> and C<cmp>>
+
+Internally, all network objects are represented in 128 bit format.
+The numeric representation of the network is compared through the
+corresponding operation. Comparisons are tried first on the address portion
+of the object and if that is equal then the NUMERIC cidr portion of the
+masks are compared. This leads to the counterintuitive result that
+
+ /24 > /16
+
+Comparison should not be done on netaddr objects with different CIDR as
+this may produce indeterminate - unexpected results,
+rather the determination of which netblock is larger or smaller should be
+done by comparing
+
+ $ip1->masklen <=> $ip2->masklen
+
+=item B<Addition of a constant (C<+>)>
+
+Add a 32 bit signed constant to the address part of a NetAddr object.
+This operation changes the address part to point so many hosts above the
+current objects start address. For instance, this code:
+
+ print NetAddr::IP::Lite->new('127.0.0.1/8') + 5;
+
+will output 127.0.0.6/8. The address will wrap around at the broadcast
+back to the network address. This code:
+
+ print NetAddr::IP::Lite->new('10.0.0.1/24') + 255;
+
+ outputs 10.0.0.0/24.
+
+Returns the the unchanged object when the constant is missing or out of
+range.
+
+ 2147483647 <= constant >= -2147483648
+
+=item B<Subtraction of a constant (C<->)>
+
+The complement of the addition of a constant.
+
+=item B<Difference (C<->)>
+
+Returns the difference between the address parts of two NetAddr::IP::Lite
+objects address parts as a 32 bit signed number.
+
+Returns B<undef> if the difference is out of range.
+
+(See range restrictions on Addition above)
+
+=item B<Auto-increment>
+
+Auto-incrementing a NetAddr::IP object causes the address part to be
+adjusted to the next host address within the subnet. It will wrap at
+the broadcast address and start again from the network address.
+
+=item B<Auto-decrement>
+
+Auto-decrementing a NetAddr::IP object performs exactly the opposite
+of auto-incrementing it, as you would expect.
+
+=cut
+
+ #############################################
+ # End of the overload methods.
+ #############################################
+
+
+# Preloaded methods go here.
+
+=pod
+
+=back
+
+=head2 Serializing and Deserializing
+
+This module defines hooks to collaborate with L<Storable> for
+serializing C<NetAddr::IP> objects, through compact and human readable
+strings. You can revert to the old format by invoking this module as
+
+ use NetAddr::IP ':old_storable';
+
+You must do this if you have legacy data files containing NetAddr::IP
+objects stored using the L<Storable> module.
+
+=cut
+
+my $full_format = "%04X:%04X:%04X:%04X:%04X:%04X:%D.%D.%D.%D";
+my $full6_format = "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X";
+
+sub import
+{
+ if (grep { $_ eq ':old_storable' } @_) {
+ @_ = grep { $_ ne ':old_storable' } @_;
+ } else {
+ *{STORABLE_freeze} = sub
+ {
+ my $self = shift;
+ return $self->cidr(); # use stringification
+ };
+ *{STORABLE_thaw} = sub
+ {
+ my $self = shift;
+ my $cloning = shift; # Not used
+ my $serial = shift;
+
+ my $ip = new NetAddr::IP $serial;
+ $self->{addr} = $ip->{addr};
+ $self->{mask} = $ip->{mask};
+ $self->{isv6} = $ip->{isv6};
+ return;
+ };
+ }
+
+ if (grep { $_ eq ':aton' } @_)
+ {
+ $NetAddr::IP::Lite::Accept_Binary_IP = 1;
+ @_ = grep { $_ ne ':aton' } @_;
+ }
+ if (grep { $_ eq ':old_nth' } @_)
+ {
+ $NetAddr::IP::Lite::Old_nth = 1;
+ @_ = grep { $_ ne ':old_nth' } @_;
+ }
+ if (grep { $_ eq ':lower' } @_)
+ {
+ $full_format = lc($full_format);
+ $full6_format = lc($full6_format);
+ NetAddr::IP::Util::lower();
+ @_ = grep { $_ ne ':lower' } @_;
+ }
+ if (grep { $_ eq ':upper' } @_)
+ {
+ $full_format = uc($full_format);
+ $full6_format = uc($full6_format);
+ NetAddr::IP::Util::upper();
+ @_ = grep { $_ ne ':upper' } @_;
+ }
+ NetAddr::IP->export_to_level(1, @_);
+}
+
+sub compact {
+ return (ref $_[0] eq 'ARRAY')
+ ? compactref($_[0]) # Compact(\@list)
+ : @{compactref(\@_)}; # Compact(@list) or ->compact(@list)
+}
+
+*Compact = \&compact;
+
+sub Coalesce {
+ return &coalesce;
+}
+
+sub hostenumref($) {
+ my $r = _splitref(0,$_[0]);
+ unless ((notcontiguous($_[0]->{mask}))[1] == 128) {
+ splice(@$r, 0, 1);
+ splice(@$r, scalar @$r - 1, 1);
+ }
+ return $r;
+}
+
+sub splitref {
+ unshift @_, 0; # mark as no reverse
+# perl 5.8.4 fails with this operation. see perl bug [ 23429]
+# goto &_splitref;
+ &_splitref;
+}
+
+sub rsplitref {
+ unshift @_, 1; # mark as reversed
+# perl 5.8.4 fails with this operation. see perl bug [ 23429]
+# goto &_splitref;
+ &_splitref;
+}
+
+sub split {
+ unshift @_, 0; # mark as no reverse
+ my $rv = &_splitref;
+ return $rv ? @$rv : ();
+}
+
+sub rsplit {
+ unshift @_, 1; # mark as reversed
+ my $rv = &_splitref;
+ return $rv ? @$rv : ();
+}
+
+sub full($) {
+ if (! $_[0]->{isv6} && isIPv4($_[0]->{addr})) {
+ my @hex = (unpack("n8",$_[0]->{addr}));
+ $hex[9] = $hex[7] & 0xff;
+ $hex[8] = $hex[7] >> 8;
+ $hex[7] = $hex[6] & 0xff;
+ $hex[6] >>= 8;
+ return sprintf($full_format,@hex);
+ } else {
+ &full6;
+ }
+}
+
+sub full6($) {
+ my @hex = (unpack("n8",$_[0]->{addr}));
+ return sprintf($full6_format,@hex);
+}
+
+sub DESTROY {};
+
+1;
+__END__
+
+sub do_prefix ($$$) {
+ my $mask = shift;
+ my $faddr = shift;
+ my $laddr = shift;
+
+ if ($mask > 24) {
+ return "$faddr->[0].$faddr->[1].$faddr->[2].$faddr->[3]-$laddr->[3]";
+ }
+ elsif ($mask == 24) {
+ return "$faddr->[0].$faddr->[1].$faddr->[2].";
+ }
+ elsif ($mask > 16) {
+ return "$faddr->[0].$faddr->[1].$faddr->[2]-$laddr->[2].";
+ }
+ elsif ($mask == 16) {
+ return "$faddr->[0].$faddr->[1].";
+ }
+ elsif ($mask > 8) {
+ return "$faddr->[0].$faddr->[1]-$laddr->[1].";
+ }
+ elsif ($mask == 8) {
+ return "$faddr->[0].";
+ }
+ else {
+ return "$faddr->[0]-$laddr->[0]";
+ }
+}
+
+=pod
+
+=head2 Methods
+
+=over
+
+=item C<-E<gt>new([$addr, [ $mask|IPv6 ]])>
+
+=item C<-E<gt>new6([$addr, [ $mask]])>
+
+=item C<-E<gt>new_no([$addr, [ $mask]])>
+
+=item C<-E<gt>new_from_aton($netaddr)>
+
+=item new_cis and new_cis6 are DEPRECATED
+
+=item C<-E<gt>new_cis("$addr $mask)>
+
+=item C<-E<gt>new_cis6("$addr $mask)>
+
+The first two methods create a new address with the supplied address in
+C<$addr> and an optional netmask C<$mask>, which can be omitted to get
+a /32 or /128 netmask for IPv4 / IPv6 addresses respectively.
+
+The third method C<new_no> is exclusively for IPv4 addresses and filters
+improperly formatted
+dot quad strings for leading 0's that would normally be interpreted as octal
+format by NetAddr per the specifications for inet_aton.
+
+B<new_from_aton> takes a packed IPv4 address and assumes a /32 mask. This
+function replaces the DEPRECATED :aton functionality which is fundamentally
+broken.
+
+The last two methods B<new_cis> and B<new_cis6> differ from B<new> and
+B<new6> only in that they except the common Cisco address notation for
+address/mask pairs with a B<space> as a separator instead of a slash (/)
+
+These methods are DEPRECATED because the functionality is now included
+in the other "new" methods
+
+ i.e. ->new_cis('1.2.3.0 24')
+ or
+ ->new_cis6('::1.2.3.0 120')
+
+C<-E<gt>new6> and
+C<-E<gt>new_cis6> mark the address as being in ipV6 address space even
+if the format would suggest otherwise.
+
+ i.e. ->new6('1.2.3.4') will result in ::102:304
+
+ addresses submitted to ->new in ipV6 notation will
+ remain in that notation permanently. i.e.
+ ->new('::1.2.3.4') will result in ::102:304
+ whereas new('1.2.3.4') would print out as 1.2.3.4
+
+ See "STRINGIFICATION" below.
+
+C<$addr> can be almost anything that can be resolved to an IP address
+in all the notations I have seen over time. It can optionally contain
+the mask in CIDR notation.
+
+B<prefix> notation is understood, with the limitation that the range
+specified by the prefix must match with a valid subnet.
+
+Addresses in the same format returned by C<inet_aton> or
+C<gethostbyname> can also be understood, although no mask can be
+specified for them. The default is to not attempt to recognize this
+format, as it seems to be seldom used.
+
+To accept addresses in that format, invoke the module as in
+
+ use NetAddr::IP ':aton'
+
+If called with no arguments, 'default' is assumed.
+
+C<$addr> can be any of the following and possibly more...
+
+ n.n
+ n.n/mm
+ n.n.n
+ n.n.n/mm
+ n.n.n.n
+ n.n.n.n/mm 32 bit cidr notation
+ n.n.n.n/m.m.m.m
+ loopback, localhost, broadcast, any, default
+ x.x.x.x/host
+ 0xABCDEF, 0b111111000101011110, (a bcd number)
+ a netaddr as returned by 'inet_aton'
+
+
+Any RFC1884 notation
+
+ ::n.n.n.n
+ ::n.n.n.n/mmm 128 bit cidr notation
+ ::n.n.n.n/::m.m.m.m
+ ::x:x
+ ::x:x/mmm
+ x:x:x:x:x:x:x:x
+ x:x:x:x:x:x:x:x/mmm
+ x:x:x:x:x:x:x:x/m:m:m:m:m:m:m:m any RFC1884 notation
+ loopback, localhost, unspecified, any, default
+ ::x:x/host
+ 0xABCDEF, 0b111111000101011110 within the limits
+ of perl's number resolution
+ 123456789012 a 'big' bcd number (bigger than perl likes)
+ and Math::BigInt
+
+If called with no arguments, 'default' is assumed.
+
+=item C<-E<gt>broadcast()>
+
+Returns a new object referring to the broadcast address of a given
+subnet. The broadcast address has all ones in all the bit positions
+where the netmask has zero bits. This is normally used to address all
+the hosts in a given subnet.
+
+=item C<-E<gt>network()>
+
+Returns a new object referring to the network address of a given
+subnet. A network address has all zero bits where the bits of the
+netmask are zero. Normally this is used to refer to a subnet.
+
+=item C<-E<gt>addr()>
+
+Returns a scalar with the address part of the object as an IPv4 or IPv6 text
+string as appropriate. This is useful for printing or for passing the
+address part of the NetAddr::IP object to other components that expect an IP
+address. If the object is an ipV6 address or was created using ->new6($ip)
+it will be reported in ipV6 hex format otherwise it will be reported in dot
+quad format only if it resides in ipV4 address space.
+
+=item C<-E<gt>mask()>
+
+Returns a scalar with the mask as an IPv4 or IPv6 text string as
+described above.
+
+=item C<-E<gt>masklen()>
+
+Returns a scalar the number of one bits in the mask.
+
+=item C<-E<gt>bits()>
+
+Returns the width of the address in bits. Normally 32 for v4 and 128 for v6.
+
+=item C<-E<gt>version()>
+
+Returns the version of the address or subnet. Currently this can be
+either 4 or 6.
+
+=item C<-E<gt>cidr()>
+
+Returns a scalar with the address and mask in CIDR notation. A
+NetAddr::IP object I<stringifies> to the result of this function.
+(see comments about ->new6() and ->addr() for output formats)
+
+=item C<-E<gt>aton()>
+
+Returns the address part of the NetAddr::IP object in the same format
+as the C<inet_aton()> or C<ipv6_aton> function respectively. If the object
+was created using ->new6($ip), the address returned will always be in ipV6
+format, even for addresses in ipV4 address space.
+
+=item C<-E<gt>range()>
+
+Returns a scalar with the base address and the broadcast address
+separated by a dash and spaces. This is called range notation.
+
+=item C<-E<gt>prefix()>
+
+Returns a scalar with the address and mask in ipV4 prefix
+representation. This is useful for some programs, which expect its
+input to be in this format. This method will include the broadcast
+address in the encoding.
+
+=cut
+
+# only applicable to ipV4
+sub prefix($) {
+ return undef if $_[0]->{isv6};
+ my $mask = (notcontiguous($_[0]->{mask}))[1];
+ return $_[0]->addr if $mask == 128;
+ $mask -= 96;
+ my @faddr = split (/\./, $_[0]->first->addr);
+ my @laddr = split (/\./, $_[0]->broadcast->addr);
+ return do_prefix $mask, \@faddr, \@laddr;
+}
+
+=item C<-E<gt>nprefix()>
+
+Just as C<-E<gt>prefix()>, but does not include the broadcast address.
+
+=cut
+
+# only applicable to ipV4
+sub nprefix($) {
+ return undef if $_[0]->{isv6};
+ my $mask = (notcontiguous($_[0]->{mask}))[1];
+ return $_[0]->addr if $mask == 128;
+ $mask -= 96;
+ my @faddr = split (/\./, $_[0]->first->addr);
+ my @laddr = split (/\./, $_[0]->last->addr);
+ return do_prefix $mask, \@faddr, \@laddr;
+}
+
+=pod
+
+=item C<-E<gt>numeric()>
+
+When called in a scalar context, will return a numeric representation
+of the address part of the IP address. When called in an array
+contest, it returns a list of two elements. The first element is as
+described, the second element is the numeric representation of the
+netmask.
+
+This method is essential for serializing the representation of a
+subnet.
+
+=item C<-E<gt>bigint()>
+
+When called in scalar context, will return a Math::BigInt
+representation of the address part of the IP address. When called in
+an array context, it returns a list of tow elements, The first
+element is as described, the second element is the Math::BigInt
+representation of the netmask.
+
+=item C<-E<gt>wildcard()>
+
+When called in a scalar context, returns the wildcard bits
+corresponding to the mask, in dotted-quad or ipV6 format as applicable.
+
+When called in an array context, returns a two-element array. The
+first element, is the address part. The second element, is the
+wildcard translation of the mask.
+
+=cut
+
+sub wildcard($) {
+ my $copy = $_[0]->copy;
+ $copy->{addr} = ~ $copy->{mask};
+ $copy->{addr} &= V4net unless $copy->{isv6};
+ if (wantarray) {
+ return ($_[0]->addr, $copy->addr);
+ }
+ return $copy->addr;
+}
+
+=pod
+
+=item C<-E<gt>short()>
+
+Returns the address part in a short or compact notation.
+
+ (ie, 127.0.0.1 becomes 127.1).
+
+Works with both, V4 and V6.
+
+=cut
+
+sub _compact_v6 ($) {
+ my $addr = shift;
+
+ my @o = split /:/, $addr;
+ return $addr unless @o and grep { $_ =~ m/^0+$/ } @o;
+
+ my @candidates = ();
+ my $start = undef;
+
+ for my $i (0 .. $#o)
+ {
+ if (defined $start)
+ {
+ if ($o[$i] !~ m/^0+$/)
+ {
+ push @candidates, [ $start, $i - $start ];
+ $start = undef;
+ }
+ }
+ else
+ {
+ $start = $i if $o[$i] =~ m/^0+$/;
+ }
+ }
+
+ push @candidates, [$start, 8 - $start] if defined $start;
+
+ my $l = (sort { $b->[1] <=> $a->[1] } @candidates)[0];
+
+ return $addr unless defined $l;
+
+ $addr = $l->[0] == 0 ? '' : join ':', @o[0 .. $l->[0] - 1];
+ $addr .= '::';
+ $addr .= join ':', @o[$l->[0] + $l->[1] .. $#o];
+ $addr =~ s/(^|:)0{1,3}/$1/g;
+
+ return $addr;
+}
+
+
+#sub _old_compV6 {
+# my @addr = split(':',shift);
+# my $found = 0;
+# my $v;
+# foreach(0..$#addr) {
+# ($v = $addr[$_]) =~ s/^0+//;
+# $addr[$_] = $v || 0;
+# }
+# @_ = reverse(1..$#addr);
+# foreach(@_) {
+# if ($addr[$_] || $addr[$_ -1]) {
+# last if $found;
+# next;
+# }
+# $addr[$_] = $addr[$_ -1] = '';
+# $found = '1';
+# }
+# (my $rv = join(':',@addr)) =~ s/:+:/::/;
+# return $rv;
+#}
+
+# thanks to Rob Riepel <riepel@networking.Stanford.EDU>
+# for this faster and more compact solution 11-17-08
+sub _compV6 ($) {
+ my $ip = shift;
+ return $ip unless my @candidates = $ip =~ /((?:^|:)0(?::0)+(?::|$))/g;
+ my $longest = (sort { length($b) <=> length($a) } @candidates)[0];
+ $ip =~ s/$longest/::/;
+ return $ip;
+}
+
+sub short($) {
+ my $addr = $_[0]->addr;
+ if (! $_[0]->{isv6} && isIPv4($_[0]->{addr})) {
+ my @o = split(/\./, $addr, 4);
+ splice(@o, 1, 2) if $o[1] == 0 and $o[2] == 0;
+ return join '.', @o;
+ }
+ return _compV6($addr);
+}
+
+=item C<-E<gt>full()>
+
+Returns the address part in FULL notation for
+ipV4 and ipV6 respectively.
+
+ i.e. for ipV4
+ 0000:0000:0000:0000:0000:0000:127.0.0.1
+
+ for ipV6
+ 0000:0000:0000:0000:0000:0000:0000:0000
+
+To force ipV4 addresses into full ipV6 format use:
+
+=item C<-E<gt>full6()>
+
+Returns the address part in FULL ipV6 notation
+
+=item C<$me-E<gt>contains($other)>
+
+Returns true when C<$me> completely contains C<$other>. False is
+returned otherwise and C<undef> is returned if C<$me> and C<$other>
+are not both C<NetAddr::IP> objects.
+
+=item C<$me-E<gt>within($other)>
+
+The complement of C<-E<gt>contains()>. Returns true when C<$me> is
+completely contained within C<$other>.
+
+Note that C<$me> and C<$other> must be C<NetAddr::IP> objects.
+
+=item C<-E<gt>splitref($bits,[optional $bits1,$bits2,...])>
+
+Returns a reference to a list of objects, representing subnets of C<bits> mask
+produced by splitting the original object, which is left
+unchanged. Note that C<$bits> must be longer than the original
+mask in order for it to be splittable.
+
+ERROR conditions:
+
+ ->splitref will DIE with the message 'netlimit exceeded'
+ if the number of return objects exceeds 'netlimit'.
+ See function 'netlimit' above (default 2**16 or 65536 nets).
+
+ ->splitref returns undef when C<bits> or the (bits list)
+ will not fit within the original object.
+
+ ->splitref returns undef if a supplied ipV4, ipV6, or NetAddr
+ mask in inappropriately formatted,
+
+B<bits> may be a CIDR mask, a dot quad or ipV6 string or a NetAddr::IP object.
+If C<bits> is missing, the object is split for into all available addresses
+within the ipV4 or ipV6 object ( auto-mask of CIDR 32, 128 respectively ).
+
+With optional additional C<bits> list, the original object is split into
+parts sized based on the list. NOTE: a short list will replicate the last
+item. If the last item is too large to for what remains of the object after
+splitting off the first parts of the list, a "best fits" list of remaining
+objects will be returned based on an increasing sort of the CIDR values of
+the C<bits> list.
+
+ i.e. my $ip = new NetAddr::IP('192.168.0.0/24');
+ my $objptr = $ip->split(28, 29, 28, 29, 26);
+
+ has split plan 28 29 28 29 26 26 26 28
+ and returns this list of objects
+
+ 192.168.0.0/28
+ 192.168.0.16/29
+ 192.168.0.24/28
+ 192.168.0.40/29
+ 192.168.0.48/26
+ 192.168.0.112/26
+ 192.168.0.176/26
+ 192.168.0.240/28
+
+NOTE: that /26 replicates twice beyond the original request and /28 fills
+the remaining return object requirement.
+
+=item C<-E<gt>rsplitref($bits,[optional $bits1,$bits2,...])>
+
+C<-E<gt>rsplitref> is the same as C<-E<gt>splitref> above except that the split plan is
+applied to the original object in reverse order.
+
+ i.e. my $ip = new NetAddr::IP('192.168.0.0/24');
+ my @objects = $ip->split(28, 29, 28, 29, 26);
+
+ has split plan 28 26 26 26 29 28 29 28
+ and returns this list of objects
+
+ 192.168.0.0/28
+ 192.168.0.16/26
+ 192.168.0.80/26
+ 192.168.0.144/26
+ 192.168.0.208/29
+ 192.168.0.216/28
+ 192.168.0.232/29
+ 192.168.0.240/28
+
+=item C<-E<gt>split($bits,[optional $bits1,$bits2,...])>
+
+Similar to C<-E<gt>splitref> above but returns the list rather than a list
+reference. You may not want to use this if a large number of objects is
+expected.
+
+=item C<-E<gt>rsplit($bits,[optional $bits1,$bits2,...])>
+
+Similar to C<-E<gt>rsplitref> above but returns the list rather than a list
+reference. You may not want to use this if a large number of objects is
+expected.
+
+=cut
+
+# input: $naip,
+# @bits, list of masks for splits
+#
+# returns: empty array request will not fit in submitted net
+# (\@bits,undef) if there is just one plan item i.e. return original net
+# (\@bits,\%masks) for a real plan
+#
+sub _splitplan {
+ my($ip,@bits) = @_;
+ my $addr = $ip->addr();
+ my $isV6 = $ip->{isv6};
+ unless (@bits) {
+ $bits[0] = $isV6 ? 128 : 32;
+ }
+ my $basem = $ip->masklen();
+
+ my(%nets,$dif);
+ my $denom = 0;
+
+ my($x,$maddr);
+ foreach(@bits) {
+ if (ref $_) { # is a NetAddr::IP
+ $x = $_->{isv6} ? $_->{addr} : $_->{addr} | V4mask;
+ ($x,$maddr) = notcontiguous($x);
+ return () if $x; # spurious bits
+ $_ = $isV6 ? $maddr : $maddr - 96;
+ }
+ elsif ( $_ =~ /^d+$/ ) { # is a negative number of the form -nnnn
+ ;
+ }
+ elsif ($_ = NetAddr::IP->new($addr,$_,$isV6)) { # will be undefined if bad mask and will fall into oops!
+ $_ = $_->masklen();
+ }
+ else {
+ return (); # oops!
+ }
+ $dif = $_ - $basem; # for normalization
+ return () if $dif < 0; # overange nets not allowed
+ return (\@bits,undef) unless ($dif || $#bits); # return if original net = mask alone
+ $denom = $dif if $dif > $denom;
+ next if exists $nets{$_};
+ $nets{$_} = $_ - $basem; # for normalization
+ }
+
+# $denom is the normalization denominator, since these are all exponents
+# normalization can use add/subtract to accomplish normalization
+#
+# keys of %nets are the masks used by this split
+# values of %nets are the normalized weighting for
+# calculating when the split is "full" or complete
+# %masks values contain the actual masks for each split subnet
+# @bits contains the masks in the order the user actually wants them
+#
+ my %masks; # calculate masks
+ my $maskbase = $isV6 ? 128 : 32;
+ foreach( keys %nets ) {
+ $nets{$_} = 2 ** ($denom - $nets{$_});
+ $masks{$_} = shiftleft(Ones, $maskbase - $_);
+ }
+
+ my @plan;
+ my $idx = 0;
+ $denom = 2 ** $denom;
+ PLAN:
+ while ($denom > 0) { # make a net plan
+ my $nexmask = ($idx < $#bits) ? $bits[$idx] : $bits[$#bits];
+ ++$idx;
+ unless (($denom -= $nets{$nexmask}) < 0) {
+ return () if (push @plan, $nexmask) > $_netlimit;
+ next;
+ }
+# a fractional net is needed that is not in the mask list or the replicant
+ $denom += $nets{$nexmask}; # restore mistake
+ TRY:
+ foreach (sort { $a <=> $b } keys %nets) {
+ next TRY if $nexmask > $_;
+ do {
+ next TRY if $denom - $nets{$_} < 0;
+ return () if (push @plan, $_) > $_netlimit;
+ $denom -= $nets{$_};
+ } while $denom;
+ }
+ die 'ERROR: miscalculated weights' if $denom;
+ }
+ return () if $idx < @bits; # overrange original subnet request
+ return (\@plan,\%masks);
+}
+
+# input: $rev, # t/f
+# $naip,
+# @bits # list of masks for split
+#
+sub _splitref {
+ my $rev = shift;
+ my($plan,$masks) = &_splitplan;
+ return undef unless $plan;
+ my $net = $_[0]->network();
+ return [$net] unless $masks;
+ my $addr = $net->{addr};
+ my $isV6 = $net->{isv6};
+ my @plan = $rev ? reverse @$plan : @$plan;
+# print "plan @plan\n";
+
+# create splits
+ my @ret;
+ while ($_ = shift @plan) {
+ my $mask = $masks->{$_};
+ push @ret, $net->_new($addr,$mask,$isV6);
+ last unless @plan;
+ $addr = (sub128($addr,$mask))[1];
+ }
+ return \@ret;
+}
+
+=pod
+
+=item C<-E<gt>hostenum()>
+
+Returns the list of hosts within a subnet.
+
+ERROR conditions:
+
+ ->hostenum will DIE with the message 'netlimit exceeded'
+ if the number of return objects exceeds 'netlimit'.
+ See function 'netlimit' above (default 2**16 or 65536 nets).
+
+=cut
+
+sub hostenum ($) {
+ return @{$_[0]->hostenumref};
+}
+
+=pod
+
+=item C<-E<gt>hostenumref()>
+
+Faster version of C<-E<gt>hostenum()>, returning a reference to a list.
+
+=item C<$me-E<gt>compact($addr1, $addr2, ...)>
+
+=item C<@compacted_object_list = Compact(@object_list)>
+
+Given a list of objects (including C<$me>), this method will compact
+all the addresses and subnets into the largest (ie, least specific)
+subnets possible that contain exactly all of the given objects.
+
+Note that in versions prior to 3.02, if fed with the same IP subnets
+multiple times, these subnets would be returned. From 3.02 on, a more
+"correct" approach has been adopted and only one address would be
+returned.
+
+Note that C<$me> and all C<$addr>'s must be C<NetAddr::IP> objects.
+
+=item C<$me-E<gt>compactref(\@list)>
+
+=item C<$compacted_object_list = Compact(\@list)>
+
+As usual, a faster version of C<-E<gt>compact()> that returns a
+reference to a list. Note that this method takes a reference to a list
+instead.
+
+Note that C<$me> must be a C<NetAddr::IP> object.
+
+=cut
+
+sub compactref($) {
+# my @r = sort { NetAddr::IP::Lite::comp_addr_mask($a,$b) } @{$_[0]} # use overload 'cmp' function
+# or return [];
+# return [] unless @r;
+
+ my @r;
+ {
+ my $unr = [];
+ my $args = $_[0];
+
+ if (ref $_[0] eq __PACKAGE__ and ref $_[1] eq 'ARRAY') {
+ # ->compactref(\@list)
+ #
+ $unr = [$_[0], @{$_[1]}]; # keeping structures intact
+ }
+ else {
+ # Compact(@list) or ->compact(@list) or Compact(\@list)
+ #
+ $unr = $args;
+ }
+
+ return [] unless @$unr;
+
+ foreach(@$unr) {
+ $_->{addr} = $_->network->{addr};
+ }
+
+ @r = sort @$unr;
+ }
+
+ my $changed;
+ do {
+ $changed = 0;
+ for(my $i=0; $i <= $#r -1;$i++) {
+ if ($r[$i]->contains($r[$i +1])) {
+ splice(@r,$i +1,1);
+ ++$changed;
+ --$i;
+ }
+ elsif ((notcontiguous($r[$i]->{mask}))[1] == (notcontiguous($r[$i +1]->{mask}))[1]) { # masks the same
+ if (hasbits($r[$i]->{addr} ^ $r[$i +1]->{addr})) { # if not the same netblock
+ my $upnet = $r[$i]->copy;
+ $upnet->{mask} = shiftleft($upnet->{mask},1);
+ if ($upnet->contains($r[$i +1])) { # adjacent nets in next net up
+ $r[$i] = $upnet;
+ splice(@r,$i +1,1);
+ ++$changed;
+ --$i;
+ }
+ } else { # identical nets
+ splice(@r,$i +1,1);
+ ++$changed;
+ --$i;
+ }
+ }
+ }
+ } while $changed;
+ return \@r;
+}
+
+=pod
+
+=item C<$me-E<gt>coalesce($masklen, $number, @list_of_subnets)>
+
+=item C<$arrayref = Coalesce($masklen,$number,@list_of_subnets)>
+
+Will return a reference to list of C<NetAddr::IP> subnets of
+C<$masklen> mask length, when C<$number> or more addresses from
+C<@list_of_subnets> are found to be contained in said subnet.
+
+Subnets from C<@list_of_subnets> with a mask shorter than C<$masklen>
+are passed "as is" to the return list.
+
+Subnets from C<@list_of_subnets> with a mask longer than C<$masklen>
+will be counted (actually, the number of IP addresses is counted)
+towards C<$number>.
+
+Called as a method, the array will include C<$me>.
+
+WARNING: the list of subnet must be the same type. i.e ipV4 or ipV6
+
+=cut
+
+sub coalesce
+{
+ my $masklen = shift;
+ if (ref $masklen && ref $masklen eq __PACKAGE__ ) { # if called as a method
+ push @_,$masklen;
+ $masklen = shift;
+ }
+
+ my $number = shift;
+
+ # Addresses are at @_
+ return [] unless @_;
+ my %ret = ();
+ my $type = $_[0]->{isv6};
+ return [] unless defined $type;
+
+ for my $ip (@_)
+ {
+ return [] unless $ip->{isv6} == $type;
+ $type = $ip->{isv6};
+ my $n = NetAddr::IP->new($ip->addr . '/' . $masklen)->network;
+ if ($ip->masklen > $masklen)
+ {
+ $ret{$n} += $ip->num + $NetAddr::IP::Lite::Old_nth;
+ }
+ }
+
+ my @ret = ();
+
+ # Add to @ret any arguments with netmasks longer than our argument
+ for my $c (sort { $a->masklen <=> $b->masklen }
+ grep { $_->masklen <= $masklen } @_)
+ {
+ next if grep { $_->contains($c) } @ret;
+ push @ret, $c->network;
+ }
+
+ # Now add to @ret all the subnets with more than $number hits
+ for my $c (map { new NetAddr::IP $_ }
+ grep { $ret{$_} >= $number }
+ keys %ret)
+ {
+ next if grep { $_->contains($c) } @ret;
+ push @ret, $c;
+ }
+
+ return \@ret;
+}
+
+=pod
+
+=item C<-E<gt>first()>
+
+Returns a new object representing the first usable IP address within
+the subnet (ie, the first host address).
+
+=item C<-E<gt>last()>
+
+Returns a new object representing the last usable IP address within
+the subnet (ie, one less than the broadcast address).
+
+=item C<-E<gt>nth($index)>
+
+Returns a new object representing the I<n>-th usable IP address within
+the subnet (ie, the I<n>-th host address). If no address is available
+(for example, when the network is too small for C<$index> hosts),
+C<undef> is returned.
+
+Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite implements
+C<-E<gt>nth($index)> and C<-E<gt>num()> exactly as the documentation states.
+Previous versions behaved slightly differently and not in a consistent
+manner. See the README file for details.
+
+To use the old behavior for C<-E<gt>nth($index)> and C<-E<gt>num()>:
+
+ use NetAddr::IP::Lite qw(:old_nth);
+
+ old behavior:
+ NetAddr::IP->new('10/32')->nth(0) == undef
+ NetAddr::IP->new('10/32')->nth(1) == undef
+ NetAddr::IP->new('10/31')->nth(0) == undef
+ NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/31
+ NetAddr::IP->new('10/30')->nth(0) == undef
+ NetAddr::IP->new('10/30')->nth(1) == 10.0.0.1/30
+ NetAddr::IP->new('10/30')->nth(2) == 10.0.0.2/30
+ NetAddr::IP->new('10/30')->nth(3) == 10.0.0.3/30
+
+Note that in each case, the broadcast address is represented in the
+output set and that the 'zero'th index is alway undef except for
+a point-to-point /31 or /127 network where there are exactly two
+addresses in the network.
+
+ new behavior:
+ NetAddr::IP->new('10/32')->nth(0) == 10.0.0.0/32
+ NetAddr::IP->new('10.1/32'->nth(0) == 10.0.0.1/32
+ NetAddr::IP->new('10/31')->nth(0) == 10.0.0.0/32
+ NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/32
+ NetAddr::IP->new('10/30')->nth(0) == 10.0.0.1/30
+ NetAddr::IP->new('10/30')->nth(1) == 10.0.0.2/30
+ NetAddr::IP->new('10/30')->nth(2) == undef
+
+Note that a /32 net always has 1 usable address while a /31 has exactly
+two usable addresses for point-to-point addressing. The first
+index (0) returns the address immediately following the network address
+except for a /31 or /127 when it return the network address.
+
+=item C<-E<gt>num()>
+
+As of version 4.42 of NetAddr::IP and version 1.27 of NetAddr::IP::Lite
+a /31 and /127 with return a net B<num> value of 2 instead of 0 (zero)
+for point-to-point networks.
+
+Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite
+return the number of usable IP addresses within the subnet,
+not counting the broadcast or network address.
+
+Previous versions worked only for ipV4 addresses, returned a
+maximum span of 2**32 and returned the number of IP addresses
+not counting the broadcast address.
+ (one greater than the new behavior)
+
+To use the old behavior for C<-E<gt>nth($index)> and C<-E<gt>num()>:
+
+ use NetAddr::IP::Lite qw(:old_nth);
+
+WARNING:
+
+NetAddr::IP will calculate and return a numeric string for network
+ranges as large as 2**128. These values are TEXT strings and perl
+can treat them as integers for numeric calculations.
+
+Perl on 32 bit platforms only handles integer numbers up to 2**32
+and on 64 bit platforms to 2**64.
+
+If you wish to manipulate numeric strings returned by NetAddr::IP
+that are larger than 2**32 or 2**64, respectively, you must load
+additional modules such as Math::BigInt, bignum or some similar
+package to do the integer math.
+
+=item C<-E<gt>re()>
+
+Returns a Perl regular expression that will match an IP address within
+the given subnet. Defaults to ipV4 notation. Will return an ipV6 regex
+if the address in not in ipV4 space.
+
+=cut
+
+sub re ($)
+{
+ return &re6 unless isIPv4($_[0]->{addr});
+ my $self = shift->network; # Insure a "zero" host part
+ my ($addr, $mlen) = ($self->addr, $self->masklen);
+ my @o = split('\.', $addr, 4);
+
+ my $octet= '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
+ my @r = @o;
+ my $d;
+
+# for my $i (0 .. $#o)
+# {
+# warn "# $self: $r[$i] == $o[$i]\n";
+# }
+
+ if ($mlen != 32)
+ {
+ if ($mlen > 24)
+ {
+ $d = 2 ** (32 - $mlen) - 1;
+ $r[3] = '(?:' . join('|', ($o[3]..$o[3] + $d)) . ')';
+ }
+ else
+ {
+ $r[3] = $octet;
+ if ($mlen > 16)
+ {
+ $d = 2 ** (24 - $mlen) - 1;
+ $r[2] = '(?:' . join('|', ($o[2]..$o[2] + $d)) . ')';
+ }
+ else
+ {
+ $r[2] = $octet;
+ if ($mlen > 8)
+ {
+ $d = 2 ** (16 - $mlen) - 1;
+ $r[1] = '(?:' . join('|', ($o[1]..$o[1] + $d)) . ')';
+ }
+ else
+ {
+ $r[1] = $octet;
+ if ($mlen > 0)
+ {
+ $d = 2 ** (8 - $mlen) - 1;
+ $r[0] = '(?:' . join('|', ($o[0] .. $o[0] + $d)) . ')';
+ }
+ else { $r[0] = $octet; }
+ }
+ }
+ }
+ }
+
+ ### no digit before nor after (look-behind, look-ahead)
+ return "(?:(?<![0-9])$r[0]\\.$r[1]\\.$r[2]\\.$r[3](?![0-9]))";
+}
+
+=item C<-E<gt>re6()>
+
+Returns a Perl regular expression that will match an IP address within
+the given subnet. Always returns an ipV6 regex.
+
+=cut
+
+sub re6($) {
+ my @net = split('',sprintf("%04X%04X%04X%04X%04X%04X%04X%04X",unpack('n8',$_[0]->network->{addr})));
+ my @brd = split('',sprintf("%04X%04X%04X%04X%04X%04X%04X%04X",unpack('n8',$_[0]->broadcast->{addr})));
+
+ my @dig;
+
+ foreach(0..$#net) {
+ my $n = $net[$_];
+ my $b = $brd[$_];
+ my $m;
+ if ($n.'' eq $b.'') {
+ if ($n =~ /\d/) {
+ push @dig, $n;
+ } else {
+ push @dig, '['.(lc $n).$n.']';
+ }
+ } else {
+ my $n = $net[$_];
+ my $b = $brd[$_];
+ if ($n.'' eq 0 && $b =~ /F/) {
+ push @dig, 'x';
+ }
+ elsif ($n =~ /\d/ && $b =~ /\d/) {
+ push @dig, '['.$n.'-'.$b.']';
+ }
+ elsif ($n =~ /[A-F]/ && $b =~ /[A-F]/) {
+ $n .= '-'.$b;
+ push @dig, '['.(lc $n).$n.']';
+ }
+ elsif ($n =~ /\d/ && $b =~ /[A-F]/) {
+ $m = ($n == 9) ? 9 : $n .'-9';
+ if ($b =~ /A/) {
+ $m .= 'aA';
+ } else {
+ $b = 'A-'. $b;
+ $m .= (lc $b). $b;
+ }
+ push @dig, '['.$m.']';
+ }
+ elsif ($n =~ /[A-F]/ && $b =~ /\d/) {
+ if ($n =~ /A/) {
+ $m = 'aA';
+ } else {
+ $n .= '-F';
+ $m = (lc $n).$n;
+ }
+ if ($b == 9) {
+ $m .= 9;
+ } else {
+ $m .= $b .'-9';
+ }
+ push @dig, '['.$m.']';
+ }
+ }
+ }
+ my @grp;
+ do {
+ my $grp = join('',splice(@dig,0,4));
+ if ($grp =~ /^(0+)/) {
+ my $l = length($1);
+ if ($l == 4) {
+ $grp = '0{1,4}';
+ } else {
+ $grp =~ s/^${1}/0\{0,$l\}/;
+ }
+ }
+ if ($grp =~ /(x+)$/) {
+ my $l = length($1);
+ if ($l == 4) {
+ $grp = '[0-9a-fA-F]{1,4}';
+ } else {
+ $grp =~ s/x+/\[0\-9a\-fA\-F\]\{$l\}/;
+ }
+ }
+ push @grp, $grp;
+ } while @dig > 0;
+ return '('. join(':',@grp) .')';
+}
+
+sub mod_version {
+ return $VERSION;
+ &Compact; # suppress warnings about these symbols
+ &Coalesce;
+ &STORABLE_freeze;
+ &STORABLE_thaw;
+}
+
+=pod
+
+=back
+
+=head1 EXPORT_OK
+
+ Compact
+ Coalesce
+ Zeros
+ Ones
+ V4mask
+ V4net
+ netlimit
+
+=head1 NOTES / BUGS ... FEATURES
+
+NetAddr::IP only runs in Pure Perl mode on Windows boxes because I don't
+have the resources or know how to get the "configure" stuff working in the
+Windows environment. Volunteers WELCOME to port the "C" portion of this
+module to Windows.
+
+=head1 HISTORY
+
+=over 4
+
+See the Changes file
+
+=back
+
+=head1 AUTHORS
+
+Luis E. Muñoz E<lt>luismunoz@cpan.orgE<gt>,
+Michael Robinton E<lt>michael@bizsystems.comE<gt>
+
+=head1 WARRANTY
+
+This software comes with the same warranty as perl itself (ie, none),
+so by using it you accept any and all the liability.
+
+=head1 COPYRIGHT
+
+This software is (c) Luis E. Muñoz, 1999 - 2007, and (c) Michael
+Robinton, 2006 - 2011.
+
+All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ a) the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any
+ later version, or
+
+ b) the "Artistic License" which comes with this distribution.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
+the GNU General Public License or the Artistic License for more details.
+
+You should have received a copy of the Artistic License with this
+distribution, in the file named "Artistic". If not, I'll be glad to provide
+one.
+
+You should also have received a copy of the GNU General Public License
+along with this program in the file named "Copying". If not, write to the
+
+ Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330
+ Boston, MA 02111-1307, USA
+
+or visit their web page on the internet at:
+
+ http://www.gnu.org/copyleft/gpl.html.
+
+=head1 SEE ALSO
+
+ perl(1),NetAddr::IP::Lite, NetAddr::IP::Util.
+
+=cut
+
+1;
--- /dev/null
+Revision history for Perl extension NetAddr::IP::Lite
+
+1.41 Fri Nov 11 19:23:11 PST 2011
+ up rev for documentation update
+ update documentation in InetBase v0.06
+
+1.40 Fri Nov 11 13:20:32 PST 2011
+ add call to InetBase::fillIPv4 to all uses of gethostbyname
+
+ break out the code in InetBase v0.05 that expands short IPv4
+ addresses into dotquad format to account for broken BSD
+ implementations of inet_aton and gethostbyname that do
+ not recognize the short format. EXPORT this as sub 'fillIPv4'
+
+ in Util.pm v1.45, add 'fillIPv4' to calls to gethostbyname to
+ work around broken inet_aton and gethostbyname implementations
+ in certain BSD implementations
+
+1.39 Wed Nov 2 19:15:31 PDT 2011
+ bump rev to incorporate
+ improved inet_aton in InetBase v0.04 to overcome broken
+ gethostbyname found in NetBSD and OpenBSD
+
+1.38 Fri Oct 28 11:41:22 PDT 2011
+ patch for bug 71869, issues with Math::BigInt varients
+
+1.37 Thu Oct 27 12:48:55 PDT 2011
+ add detection of early Math::Bigint 0.01 object structures
+ circa perl 5.6.1
+
+ remove Calc.pm as part of above
+
+ fix bug 71869 - a failed test routine
+
+1.36 Wed Oct 26 08:52:34 PDT 2011
+ fix bug #71925. A a sub-varient of #62521 that showed up only for
+ short notation for IPv4. i.e. 127/n, 127.0/n, 127.0.0/n but
+ not 127.0.0.0/n
+
+1.35 Tue Oct 25 16:18:38 PDT 2011
+ add test for api-version of Math::BigInt to support versions
+ earlier than 1.70, circa Dec 2003.
+ Thanks to Paul Howarth <paul@city-fan.org> for spotting that bug.
+
+1.34 Mon Oct 24 14:38:16 PDT 2011
+ use Math::BigInt::Calc for creating BigInt values and fall
+ back to NetAddr::IP::Calc if Math::BigInt is not present.
+ Thanks to Paul Howarth <paul@city-fan.org> for spotting that bug.
+
+ remove reference to Config{osname} in InetBase.pm v0.03
+ (Util 1.43)
+
+1.33 Sat Oct 22 01:47:42 PDT 2011
+ In Lite/Util/lib/NetAddr/IP/Lite/Util/InetBase.pm v0.02
+ Socket6 prior to version 0.23 does not have AF_INET6 in the
+ EXPORT_OK array, modify InetBase.pm v0.2 to work around this.
+
+ Add support for Math::BigInt objects
+
+1.32 Sat Oct 15 22:05:23 PDT 2011
+ bug68723, add capability to parse input of the form
+ ->new6(12345,1). This should have been there but was
+ missing. Thanks to Andrei Benea for spotting this.
+
+ In Util v1.41
+ add inet_pton, inet_ntop, AF_INET, AF_INET6
+
+ modify inet_n2dx and inet_n2ad to
+ recognize the new 128 bit IPv4 format
+ ::FFFF:FFFF:0:0
+
+ replace isIPv4 with a pure perl version for portablity
+
+ split the following into NetAddr::IP::InetBase v0.01
+ to provide better long term support for IPv6
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ inet_n2dx
+ inet_n2ad
+ inet_ntop
+ inet_pton
+ packzeros
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ AF_INET
+ AF_INET6
+
+1.31 Sat Oct 8 01:33:44 PDT 2011
+ remove debug print statement from Util.pm v1.40
+
+1.30 Thu Oct 6 23:41:42 PDT 2011
+ correct internal variable reference in Util.pm 1.39
+
+1.29 Thu Oct 6 20:20:33 PDT 2011
+ updated to UTIL 1.38
+
+1.28 Wed Apr 6 11:31:19 PDT 2011
+ Update documentation on the use of "adding constants
+ to an IP address".
+
+1.27 Tue Mar 22 15:26:02 PDT 2011
+ Update Lite.pm to encompass treatment of /31 and /127
+ point-to-point networks as described in RFC 3021
+
+ NOTE: for /31's and /127's
+ this changes the behavior of the following methods:
+ first returns the "network" address
+ last returns the "broadcast" address
+ nth index 0 returns "network" addr instead of undef
+ nth index 1 returns "broadcast" addr instead of undef
+ num returns 2 instead of 0 (zero)
+
+ "old_nth" behavior is unchanged
+
+ Thanks to Todd Caine todd.caine@gmail.com for pointing this out.
+
+1.26 Tue Mar 8 15:18:16 PST 2011
+ Updated "sub num" to support usable IP ranges greater than 2**32
+
+ Thanks to Jan Ploski jan@plosquare.com for finding this bug
+
+1.25 Sat Feb 19 10:04:00 PST 2011
+ correction to use of Util.pm package lexicals
+
+ thanks to mishikal@yahoo.com for spotting the bug and to
+ Mark Martinec mark.martinec+ama...@ijs.si for the solution.
+
+1.24 Fri Dec 17 17:47:47 PST 2010
+ Modify subs "new" and "new6" to accomodate
+ Cisco mask syntax that uses space instead of "/" for a separator
+ This eliminates the need for "new_cis" and "newcis6" which are now
+ deprecated.
+
+ Modify t/v4-cnew.t and add t/v6-cnew.t to test the above
+
+1.23 Fri Nov 19 10:48:01 PST 2010
+ add :upper and :lower to Lite.pm v1.23
+ add comments about rfc5952 requirement for lowercase ipV6 notation
+ add test for :lower
+
+1.22 Tue Nov 16 16:28:37 PST 2010
+ update new6 to properly classify short ipv4 notation
+ i.e. 127/8 with test for ":" rather than match for \d.\d.\d.\d
+
+ thanks to Steve Huff (SHUFF) * shuff@cpan.org for
+ spotting that bug.
+
+ update t/v4-new.t for deprecated array syntax in perl 5.13
+ was: qw(...stuff...)
+ is: (qw(...stuff...))
+
+ thanks to Todd Rinaldo <toddr@cpan.org> for reporting this
+
+1.21 Thu Oct 28 14:26:19 PDT 2010
+ fix bug where new6 improperly assigns the mask value
+ for and ipv4 address in 32 bit space instead of 128 bit space
+
+ Thanks to Mark Martinec and Steve Huff (SHUFF) * shuff@cpan.org
+ for spotting and replicating that bug
+
+ added new_cis and new_cis6 to Lite.pm v1.21 to accomodate
+ Cisco syntax that has IP and MASK seperated by a space.
+
+ Updated typo in documentation that left out example
+ print new6 stuff
+
+1.20 Mon Oct 25 16:22:01 PDT 2010
+ Updated _xnew to properly handle ipV6 notation of the form
+ xxxx:xxxx:xxxx:xxxx:xxxx:xxxx, DDD
+
+ Thanks to Dusty Mabe <Dusty.Mabe@tekelec.com> for spotting this bug
+
+1.19 Wed Sep 29 10:32:50 PDT 2010
+ Conditionalize import of AF_INET6 in Util.pm
+ NetAddr::IP::UtilPolluted
+
+1.18 Wed Sep 22 13:39:08 PDT 2010
+ Added overload => 'ne' and '!=' to Lite.pm
+
+1.17 Tue Sep 21 17:50:50 PDT 2010
+ Pull Socket6 stuff out of Lite and put into
+ NetAddr::IP::Util.pm in its own namespace
+
+1.16 Wed Aug 11 12:45:49 PDT 2010
+ When using Socket6, pull in missing symbol PF_INET6, which may
+ or may not be present, from Socket.
+
+1.15 Tue Jul 20 15:32:23 PDT 2010
+ Resolve named hosts using gethostbyname, followed by gethostbyname6
+ to determine whether to set ipV6 flag
+
+ Thanks to Dusty Mabe <Dusty.Mabe@tekelec.com> for spotting this bug
+
+1.14 Thu Jul 8 18:17:38 PDT 2010
+ added support for the sub "new" to resolve host6 names
+ if the OPTIONAL perl Socket6 module is available
+
+1.13 Tue Dec 9 16:00:35 PST 2008
+ added missing regexp to classify arguments as BCD numbers,
+ apparently this has been missing from NetAddr::IP::Lite
+ since the first release.
+ Thanks to Carlos Vicente cvicente@cpan.org for reporting this bug.
+
+ revised UtilPP v1.7 to work around perl 5.8.4
+ failures with certain @_ operations of goto &sub...
+ see perl bug [ 23429]. Unfortunately, perl-5.8.4 is
+ the distribution of choice for many solaris boxes
+
+1.12 Sun Nov 23 19:32:59 PST 2008
+ repaired missing sub Zeros
+
+ added minus (-) overloading to allow the subtraction
+ of two NetAddr::IP objects to get the difference between
+ the object->{addr}'s as a numeric value
+ Thanks to Rob Riepel <riepel@networking.Stanford.EDU>
+ for the initial code and inspiration for this enhancement
+
+1.11 Sat Nov 1 15:13:48 PST 2008
+ add test for characters not allowed by rfc952 before
+ the call to gethostbyname in sub new() for those people
+ that insist on using deprecated functionality :aton
+ and OS's that fail to notice calls to gethostbyname
+ with binary arguments
+
+1.10 Wed Oct 22 14:54:12 PDT 2008
+ add new no octal method for improperly formatted ipV4 addresses
+
+ In Util.pm v1.22, eliminated dependence on PL_sawampersand
+ thanks to Mark Martinec <Mark.Martinec@ijs.si>
+ for spotting this and submitting a patch.
+
+ In Util.pm v1.22, force -noxs mode for Win32
+
+ In Util.pm v1.22, use autoconf to configure 'C' build
+
+1.09 Thu Oct 16 19:35:33 PDT 2008
+ again... clear build bug for Win32 in Util.pm v 1.21
+
+1.08 Sat Sep 27 12:27:28 PDT 2008
+ in Util v0.19
+ updated test for ENDIANess in siteconf
+
+ add test in inet_aton to detect overange IP dot quad values
+ missed by some broken Socket implementations
+ i.e. 256.1.1.1
+
+1.07 Tue Sep 2 19:09:57 PDT 2008
+ in the off chance that NetAddr::IP::Lite objects are created
+ and the caller later loads NetAddr::IP and expects to use
+ those objects, let the AUTOLOAD routine find and redirect
+ NetAddr::IP::Lite method and subroutine calls to NetAddr::IP.
+
+ updated t/v4-wnew.t so that non-existent
+ domains are "really" not there
+
+1.06 Sat Jun 7 12:57:18 PDT 2008
+ add method "new_from_aton" and related documentation
+
+ comparisons of the form <, >, <=, >=
+ 10.0.0.0/24 {operator} 10.0.0.0/16
+ return now return the comparison of the cidr value
+ when the address portion is equal.
+NOTE: this comparison returns the comparison of the NUMERIC
+ value of the CIDR. This produces the counter intuitive result
+ that /24 > /16. There is logic to this, really! For proper
+ operation of commands like "Compact" and "Coalesce", lists of
+ netaddr objects must sort in ascending order. However, this
+ conflicts with the requirement for larger netblocks to sort
+ FIRST so as to include smaller ones. This logic extends to
+ any requirement for a sort of netaddr objects. It should be
+ further noted that the mixing of netaddr objects with varying
+ IP addresses and CIDR allocations can lead to unexpected
+ results since the comparisons done first on the IP portion
+ and then on the CIDR portion. The documentation has been
+ updated appropriately.
+ Thanks to Peter DeVries for spotting this discrepancy
+
+1.05 undocumented
+1.04 undocumented
+
+1.03 Sun Aug 6 10:48:25 PDT 2006
+ update Util.pm v0.18 documentation
+
+1.02 Fri Aug 4 14:14:16 PDT 2006
+ $isV6 global converted to a lexical variable within sub "_xnew"
+ $Class global removed and replaced by calls to UNIVERSAL::isa
+ Thanks to julian@mehnle.net for spotting problems related to
+ using the Lite.pm with mod_perl
+
+1.01 Thu Jul 6 10:46:48 PDT 2006
+ update v4-wnew.t to warn user of possible long wait
+ update Util.pm v0.17 -- see Changes in that distro
+
+1.00 Mon Jun 26 13:34:00 PDT 2006
+ changed behavior of ->nth and ->num
+ to 'exactly' conform to the documentation
+
+ add :old_nth tag to preserve old behavior
+ and update tests to check both
+
+0.12 Sun Jun 25 16:13:00 PDT 2006
+ imported missing 'bcd2bin'
+
+ fixed Util->new() issues with long digit strings
+ ->new('::fffff') and non hex digits ->new('::foo').
+ Thanks to Radoslaw Zielinski <radek42@gmail.com>
+ for spotting these 3 bugs
+
+0.11 Wed Jun 14 14:53:21 PDT 2006
+ add 'sub new6' and related functionality to methods
+ that print or return v4/6 information or text.
+
+ add $self->{isv6} flag for hint to ipV6 status
+
+ corrected bug in sub num that miscalculated the number
+ of IP's in a net for /31 /32
+
+0.10 Tue Jun 13 14:07:46 PDT 2006
+ bring 'sub new' into full compliance with NetAddr::IP,
+ correct compatibility with for ==,>,<,=>,>=,<=>,cmp
+ and update documentation to reflect actual implementation
+
+ add 'copy' function that return a completely new object
+
+ export (Zero Ones V4mask V4net)
+
+ update Util.pm v0.15 so shiftleft returns original
+ argument when the shift count is zero or undefined
+
+0.09 Tue Jun 6 08:37:01 PDT 2006
+ update Util/Makefile.PM to check for link libraries
+ that ExtUtils::MakeMaker does not find properly
+
+ remove 'use warnings' from Lite.pm for backwards
+ compatibility with older perl versions
+
+0.08 Tue Jun 6 08:33:11 PDT 2006
+ update Util.xs for build on windoze
+
+0.07 Tue Jun 6 08:21:12 PDT 2006
+ update NetAddr::IP::Util to v0.12
+
+0.06 Mon Jun 5 21:34:28 PDT 2006
+ fix Sparc problems in Util v0.11
+ 1) add workaround for OS's that do not have inet_aton
+
+ 2) add workaround for compilers that do not understand
+ #if MACRO1 == MACRO2
+
+0.05 Sun May 7 18:06:43 PDT 2006
+ updated UtilPP.pm v0.06 to remove unnecessary pack(unpack) sequences
+ to speed up ipv6->4, ipv4->6 conversions
+
+0.04 Fri Apr 28 17:36:28 PDT 2006
+ left Util/Makefile.pl out of the top level distro
+
+0.03 Fri Apr 28 17:26:51 PDT 2006
+ oops! left prerequisite Util 0.08 in the Makefile
+ when it is include in this distro
+
+0.02 Fri Apr 28 16:11:00 PDT 2006
+ update Lite.pm to accept ->new('addr/mask')
+ where addr and mask are both in IP address format
+
+ add test for above t/netaddr.t
+
+0.01 Wed Apr 26 19:03:18 PDT 2006
+ initial release
--- /dev/null
+#!/usr/bin/perl
+
+package NetAddr::IP::Lite;
+
+use Carp;
+use strict;
+#use diagnostics;
+#use warnings;
+use NetAddr::IP::InetBase qw(
+ inet_any2n
+ isIPv4
+ inet_n2dx
+ inet_aton
+ ipv6_aton
+ ipv6_n2x
+ fillIPv4
+);
+use NetAddr::IP::Util qw(
+ addconst
+ sub128
+ ipv6to4
+ notcontiguous
+ shiftleft
+ hasbits
+ bin2bcd
+ bcd2bin
+ mask4to6
+ ipv4to6
+ naip_gethostbyname
+ havegethostbyname2
+);
+
+use vars qw(@ISA @EXPORT_OK $VERSION $Accept_Binary_IP $Old_nth $AUTOLOAD *Zero);
+
+$VERSION = do { my @r = (q$Revision: 1.41 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
+
+require Exporter;
+
+@ISA = qw(Exporter);
+
+@EXPORT_OK = qw(Zeros Zero Ones V4mask V4net);
+
+# Set to true, to enable recognizing of ipV4 && ipV6 binary notation IP
+# addresses. Thanks to Steve Snodgrass for reporting. This can be done
+# at the time of use-ing the module. See docs for details.
+
+$Accept_Binary_IP = 0;
+$Old_nth = 0;
+*Zero = \&Zeros;
+
+=head1 NAME
+
+NetAddr::IP::Lite - Manages IPv4 and IPv6 addresses and subnets
+
+=head1 SYNOPSIS
+
+ use NetAddr::IP::Lite qw(
+ Zeros
+ Ones
+ V4mask
+ V4net
+ :aton DEPRECATED !
+ :old_nth
+ :upper
+ :lower
+ );
+
+ my $ip = new NetAddr::IP::Lite '127.0.0.1';
+ or if your prefer
+ my $ip = NetAddr::IP::Lite->new('127.0.0.1);
+ or from a packed IPv4 address
+ my $ip = new_from_aton NetAddr::IP::Lite (inet_aton('127.0.0.1'));
+ or from an octal filtered IPv4 address
+ my $ip = new_no NetAddr::IP::Lite '127.012.0.0';
+
+ print "The address is ", $ip->addr, " with mask ", $ip->mask, "\n" ;
+
+ if ($ip->within(new NetAddr::IP::Lite "127.0.0.0", "255.0.0.0")) {
+ print "Is a loopback address\n";
+ }
+
+ # This prints 127.0.0.1/32
+ print "You can also say $ip...\n";
+
+ The following four functions return ipV6 representations of:
+
+ :: = Zeros();
+ FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF = Ones();
+ FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:: = V4mask();
+ ::FFFF:FFFF = V4net();
+
+=head1 INSTALLATION
+
+Un-tar the distribution in an appropriate directory and type:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+B<NetAddr::IP::Lite> depends on B<NetAddr::IP::Util> which installs by default with its primary functions compiled
+using Perl's XS extensions to build a 'C' library. If you do not have a 'C'
+complier available or would like the slower Pure Perl version for some other
+reason, then type:
+
+ perl Makefile.PL -noxs
+ make
+ make test
+ make install
+
+=head1 DESCRIPTION
+
+This module provides an object-oriented abstraction on top of IP
+addresses or IP subnets, that allows for easy manipulations. Most of the
+operations of NetAddr::IP are supported. This module will work with older
+versions of Perl and is compatible with Math::BigInt.
+
+* By default B<NetAddr::IP> functions and methods return string IPv6
+addresses in uppercase. To change that to lowercase:
+
+NOTE: the AUGUST 2010 RFC5952 states:
+
+ 4.3. Lowercase
+
+ The characters "a", "b", "c", "d", "e", and "f" in an IPv6
+ address MUST be represented in lowercase.
+
+It is recommended that all NEW applications using NetAddr::IP::Lite be
+invoked as shown on the next line.
+
+ use NetAddr::IP::Lite qw(:lower);
+
+* To ensure the current IPv6 string case behavior even if the default changes:
+
+ use NetAddr::IP::Lite qw(:upper);
+
+
+The internal representation of all IP objects is in 128 bit IPv6 notation.
+IPv4 and IPv6 objects may be freely mixed.
+
+The supported operations are described below:
+
+=cut
+
+# in the off chance that NetAddr::IP::Lite objects are created
+# and the caller later loads NetAddr::IP and expects to use
+# those objects, let the AUTOLOAD routine find and redirect
+# NetAddr::IP::Lite method and subroutine calls to NetAddr::IP.
+#
+
+my $parent = 'NetAddr::IP';
+
+# test function
+#
+# input: subroutine name in NetAddr::IP
+# output: t/f if sub name exists in NetAddr::IP namespace
+#
+#sub sub_exists {
+# my $other = $parent .'::';
+# return exists ${$other}{$_[0]};
+#}
+
+sub DESTROY {};
+
+sub AUTOLOAD {
+ no strict;
+ my ($pkg,$func) = ($AUTOLOAD =~ /(.*)::([^:]+)$/);
+ my $other = $parent .'::';
+
+ if ($pkg =~ /^$other/o && exists ${$other}{$func}) {
+ $other .= $func;
+ goto &{$other};
+ }
+
+ my @stack = caller(0);
+
+ if ( $pkg eq ref $_[0] ) {
+ $other = qq|Can't locate object method "$func" via|;
+ }
+ else {
+ $other = qq|Undefined subroutine \&$AUTOLOAD not found in|;
+ }
+ die $other . qq| package "$parent" or "$pkg" (did you forgot to load a module?) at $stack[1] line $stack[2].\n|;
+}
+
+=head2 Overloaded Operators
+
+=cut
+
+# these really should be packed in Network Long order but since they are
+# symmetrical, that extra internal processing can be skipped
+
+my $_v4zero = pack('L',0);
+my $_zero = pack('L4',0,0,0,0);
+my $_ones = ~$_zero;
+my $_v4mask = pack('L4',0xffffffff,0xffffffff,0xffffffff,0);
+my $_v4net = ~ $_v4mask;
+
+sub Zeros() {
+ return $_zero;
+}
+sub Ones() {
+ return $_ones;
+}
+sub V4mask() {
+ return $_v4mask;
+}
+sub V4net() {
+ return $_v4net;
+}
+
+ #############################################
+ # These are the overload methods, placed here
+ # for convenience.
+ #############################################
+
+use overload
+
+ '+' => \&plus,
+
+ '-' => \&minus,
+
+ '++' => \&plusplus,
+
+ '--' => \&minusminus,
+
+ "=" => \©,
+
+ '""' => sub { $_[0]->cidr(); },
+
+ 'eq' => sub {
+ my $a = (UNIVERSAL::isa($_[0],__PACKAGE__)) ? $_[0]->cidr : $_[0];
+ my $b = (UNIVERSAL::isa($_[1],__PACKAGE__)) ? $_[1]->cidr : $_[1];
+ $a eq $b;
+ },
+
+ 'ne' => sub {
+ my $a = (UNIVERSAL::isa($_[0],__PACKAGE__)) ? $_[0]->cidr : $_[0];
+ my $b = (UNIVERSAL::isa($_[1],__PACKAGE__)) ? $_[1]->cidr : $_[1];
+ $a ne $b;
+ },
+
+ '==' => sub {
+ return 0 unless UNIVERSAL::isa($_[0],__PACKAGE__) && UNIVERSAL::isa($_[1],__PACKAGE__);
+ $_[0]->cidr eq $_[1]->cidr;
+ },
+
+ '!=' => sub {
+ return 1 unless UNIVERSAL::isa($_[0],__PACKAGE__) && UNIVERSAL::isa($_[1],__PACKAGE__);
+ $_[0]->cidr ne $_[1]->cidr;
+ },
+
+ '>' => sub {
+ return &comp_addr_mask > 0 ? 1 : 0;
+ },
+
+ '<' => sub {
+ return &comp_addr_mask < 0 ? 1 : 0;
+ },
+
+ '>=' => sub {
+ return &comp_addr_mask < 0 ? 0 : 1;
+ },
+
+ '<=' => sub {
+ return &comp_addr_mask > 0 ? 0 : 1;
+ },
+
+ '<=>' => \&comp_addr_mask,
+
+ 'cmp' => \&comp_addr_mask;
+
+sub comp_addr_mask {
+ my($c,$rv) = sub128($_[0]->{addr},$_[1]->{addr});
+ return -1 unless $c;
+ return 1 if hasbits($rv);
+ ($c,$rv) = sub128($_[0]->{mask},$_[1]->{mask});
+ return -1 unless $c;
+ return hasbits($rv) ? 1 : 0;
+}
+
+#sub comp_addr {
+# my($c,$rv) = sub128($_[0]->{addr},$_[1]->{addr});
+# return -1 unless $c;
+# return hasbits($rv) ? 1 : 0;
+#}
+
+=pod
+
+=over
+
+=item B<Assignment (C<=>)>
+
+Has been optimized to copy one NetAddr::IP::Lite object to another very quickly.
+
+=item B<C<-E<gt>copy()>>
+
+The B<assignment (C<=>)> operation is only put in to operation when the
+copied object is further mutated by another overloaded operation. See
+L<overload> B<SPECIAL SYMBOLS FOR "use overload"> for details.
+
+B<C<-E<gt>copy()>> actually creates a new object when called.
+
+=cut
+
+sub copy {
+ return _new($_[0],$_[0]->{addr}, $_[0]->{mask});
+}
+
+=item B<Stringification>
+
+An object can be used just as a string. For instance, the following code
+
+ my $ip = new NetAddr::IP::Lite '192.168.1.123';
+ print "$ip\n";
+
+Will print the string 192.168.1.123/32.
+
+ my $ip = new6 NetAddr::IP::Lite '192.168.1.123';
+ print "$ip\n";
+
+Will print the string 0:0:0:0:0:0:C0A8:17B/128
+
+=item B<Equality>
+
+You can test for equality with either C<eq>, C<ne>, C<==> or C<!=>. C<eq>, C<ne> allows the
+comparison with arbitrary strings as well as NetAddr::IP::Lite objects. The
+following example:
+
+ if (NetAddr::IP::Lite->new('127.0.0.1','255.0.0.0') eq '127.0.0.1/8')
+ { print "Yes\n"; }
+
+Will print out "Yes".
+
+Comparison with C<==> and C<!=> requires both operands to be NetAddr::IP::Lite objects.
+
+=item B<Comparison via E<gt>, E<lt>, E<gt>=, E<lt>=, E<lt>=E<gt> and C<cmp>>
+
+Internally, all network objects are represented in 128 bit format.
+The numeric representation of the network is compared through the
+corresponding operation. Comparisons are tried first on the address portion
+of the object and if that is equal then the NUMERIC cidr portion of the
+masks are compared. This leads to the counterintuitive result that
+
+ /24 > /16
+
+Comparison should not be done on netaddr objects with different CIDR as
+this may produce indeterminate - unexpected results,
+rather the determination of which netblock is larger or smaller should be
+done by comparing
+
+ $ip1->masklen <=> $ip2->masklen
+
+=item B<Addition of a constant (C<+>)>
+
+Add a 32 bit signed constant to the address part of a NetAddr object.
+This operation changes the address part to point so many hosts above the
+current objects start address. For instance, this code:
+
+ print NetAddr::IP::Lite->new('127.0.0.1/8') + 5;
+
+will output 127.0.0.6/8. The address will wrap around at the broadcast
+back to the network address. This code:
+
+ print NetAddr::IP::Lite->new('10.0.0.1/24') + 255;
+
+outputs 10.0.0.0/24.
+
+Returns the the unchanged object when the constant is missing or out of range.
+
+ 2147483647 <= constant >= -2147483648
+
+=cut
+
+sub plus {
+ my $ip = shift;
+ my $const = shift;
+
+ return $ip unless $const &&
+ $const < 2147483648 &&
+ $const > -2147483649;
+
+ my $a = $ip->{addr};
+ my $m = $ip->{mask};
+
+ my $lo = $a & ~$m;
+ my $hi = $a & $m;
+
+ my $new = ((addconst($lo,$const))[1] & ~$m) | $hi;
+
+ return _new($ip,$new,$m);
+}
+
+=item B<Subtraction of a constant (C<->)>
+
+The complement of the addition of a constant.
+
+=item B<Difference (C<->)>
+
+Returns the difference between the address parts of two NetAddr::IP::Lite
+objects address parts as a 32 bit signed number.
+
+Returns B<undef> if the difference is out of range.
+
+=cut
+
+my $_smsk = pack('L3N',0xffffffff,0xffffffff,0xffffffff,0x80000000);
+
+sub minus {
+ my $ip = shift;
+ my $arg = shift;
+ unless (ref $arg) {
+ return plus($ip, -$arg);
+ }
+ my($carry,$dif) = sub128($ip->{addr},$arg->{addr});
+ if ($carry) { # value is positive
+ return undef if hasbits($dif & $_smsk); # all sign bits should be 0's
+ return (unpack('L3N',$dif))[3];
+ } else {
+ return undef if hasbits(($dif & $_smsk) ^ $_smsk); # sign is 1's
+ return (unpack('L3N',$dif))[3] - 4294967296;
+ }
+}
+
+ # Auto-increment an object
+
+=item B<Auto-increment>
+
+Auto-incrementing a NetAddr::IP::Lite object causes the address part to be
+adjusted to the next host address within the subnet. It will wrap at
+the broadcast address and start again from the network address.
+
+=cut
+
+sub plusplus {
+ my $ip = shift;
+
+ my $a = $ip->{addr};
+ my $m = $ip->{mask};
+
+ my $lo = $a & ~ $m;
+ my $hi = $a & $m;
+
+ $ip->{addr} = ((addconst($lo,1))[1] & ~ $m) | $hi;
+ return $ip;
+}
+
+=item B<Auto-decrement>
+
+Auto-decrementing a NetAddr::IP::Lite object performs exactly the opposite
+of auto-incrementing it, as you would expect.
+
+=cut
+
+sub minusminus {
+ my $ip = shift;
+
+ my $a = $ip->{addr};
+ my $m = $ip->{mask};
+
+ my $lo = $a & ~$m;
+ my $hi = $a & $m;
+
+ $ip->{addr} = ((addconst($lo,-1))[1] & ~$m) | $hi;
+ return $ip;
+}
+
+ #############################################
+ # End of the overload methods.
+ #############################################
+
+# Preloaded methods go here.
+
+ # This is a variant to ->new() that
+ # creates and blesses a new object
+ # without the fancy parsing of
+ # IP formats and shorthands.
+
+# return a blessed IP object without parsing
+# input: prototype, naddr, nmask
+# returns: blessed IP object
+#
+sub _new ($$$) {
+ my $proto = shift;
+ my $class = ref($proto) || die "reference required";
+ $proto = $proto->{isv6};
+ my $self = {
+ addr => $_[0],
+ mask => $_[1],
+ isv6 => $proto,
+ };
+ return bless $self, $class;
+}
+
+=pod
+
+=back
+
+=head2 Methods
+
+=over
+
+=item C<-E<gt>new([$addr, [ $mask|IPv6 ]])>
+
+=item C<-E<gt>new6([$addr, [ $mask]])>
+
+=item C<-E<gt>new_no([$addr, [ $mask]])>
+
+=item C<-E<gt>new_from_aton($netaddr)>
+
+=item new_cis and new_cis6 are DEPRECATED
+
+=item C<-E<gt>new_cis("$addr $mask)>
+
+=item C<-E<gt>new_cis6("$addr $mask)>
+
+The first two methods create a new address with the supplied address in
+C<$addr> and an optional netmask C<$mask>, which can be omitted to get
+a /32 or /128 netmask for IPv4 / IPv6 addresses respectively.
+
+The third method C<new_no> is exclusively for IPv4 addresses and filters
+improperly formatted
+dot quad strings for leading 0's that would normally be interpreted as octal
+format by NetAddr per the specifications for inet_aton.
+
+B<new_from_aton> takes a packed IPv4 address and assumes a /32 mask. This
+function replaces the DEPRECATED :aton functionality which is fundamentally
+broken.
+
+The last two methods B<new_cis> and B<new_cis6> differ from B<new> and
+B<new6> only in that they except the common Cisco address notation for
+address/mask pairs with a B<space> as a separator instead of a slash (/)
+
+These methods are DEPRECATED because the functionality is now included
+in the other "new" methods
+
+ i.e. ->new_cis('1.2.3.0 24')
+ or
+ ->new_cis6('::1.2.3.0 120')
+
+C<-E<gt>new6> and
+C<-E<gt>new_cis6> mark the address as being in ipV6 address space even
+if the format would suggest otherwise.
+
+ i.e. ->new6('1.2.3.4') will result in ::102:304
+
+ addresses submitted to ->new in ipV6 notation will
+ remain in that notation permanently. i.e.
+ ->new('::1.2.3.4') will result in ::102:304
+ whereas new('1.2.3.4') would print out as 1.2.3.4
+
+ See "STRINGIFICATION" below.
+
+C<$addr> can be almost anything that can be resolved to an IP address
+in all the notations I have seen over time. It can optionally contain
+the mask in CIDR notation. If the OPTIONAL perl module Socket6 is
+available in the local library it will autoload and ipV6 host6
+names will be resolved as well as ipV4 hostnames.
+
+B<prefix> notation is understood, with the limitation that the range
+specified by the prefix must match with a valid subnet.
+
+Addresses in the same format returned by C<inet_aton> or
+C<gethostbyname> can also be understood, although no mask can be
+specified for them. The default is to not attempt to recognize this
+format, as it seems to be seldom used.
+
+###### DEPRECATED, will be remove in version 5 ############
+To accept addresses in that format, invoke the module as in
+
+ use NetAddr::IP::Lite ':aton'
+
+###### USE new_from_aton instead ##########################
+
+If called with no arguments, 'default' is assumed.
+
+C<$addr> can be any of the following and possibly more...
+
+ n.n
+ n.n/mm
+ n.n mm
+ n.n.n
+ n.n.n/mm
+ n.n.n mm
+ n.n.n.n
+ n.n.n.n/mm 32 bit cidr notation
+ n.n.n.n mm
+ n.n.n.n/m.m.m.m
+ n.n.n.n m.m.m.m
+ loopback, localhost, broadcast, any, default
+ x.x.x.x/host
+ 0xABCDEF, 0b111111000101011110, (or a bcd number)
+ a netaddr as returned by 'inet_aton'
+
+
+Any RFC1884 notation
+
+ ::n.n.n.n
+ ::n.n.n.n/mmm 128 bit cidr notation
+ ::n.n.n.n/::m.m.m.m
+ ::x:x
+ ::x:x/mmm
+ x:x:x:x:x:x:x:x
+ x:x:x:x:x:x:x:x/mmm
+ x:x:x:x:x:x:x:x/m:m:m:m:m:m:m:m any RFC1884 notation
+ loopback, localhost, unspecified, any, default
+ ::x:x/host
+ 0xABCDEF, 0b111111000101011110 within the limits
+ of perl's number resolution
+ 123456789012 a 'big' bcd number (bigger than perl likes)
+ and Math::BigInt
+
+If called with no arguments, 'default' is assumed.
+
+=cut
+
+my $lbmask = inet_aton('255.0.0.0');
+my $_p4broad = inet_any2n('255.255.255.255');
+my $_p4loop = inet_any2n('127.0.0.1');
+my $_p4mloop = inet_aton('255.0.0.0');
+ $_p4mloop = mask4to6($_p4mloop);
+my $_p6loop = inet_any2n('::1');
+
+my %fip4 = (
+ default => Zeros,
+ any => Zeros,
+ broadcast => $_p4broad,
+ loopback => $_p4loop,
+ unspecified => undef,
+);
+my %fip4m = (
+ default => Zeros,
+ any => Zeros,
+ broadcast => Ones,
+ loopback => $_p4mloop,
+ unspecified => undef, # not applicable for ipV4
+ host => Ones,
+);
+
+my %fip6 = (
+ default => Zeros,
+ any => Zeros,
+ broadcast => undef, # not applicable for ipV6
+ loopback => $_p6loop,
+ unspecified => Zeros,
+);
+
+my %fip6m = (
+ default => Zeros,
+ any => Zeros,
+ broadcast => undef, # not applicable for ipV6
+ loopback => Ones,
+ unspecified => Ones,
+ host => Ones,
+);
+
+my $ff000000 = pack('L3N',0xffffffff,0xffffffff,0xffffffff,0xFF000000);
+my $ffff0000 = pack('L3N',0xffffffff,0xffffffff,0xffffffff,0xFFFF0000);
+my $ffffff00 = pack('L3N',0xffffffff,0xffffffff,0xffffffff,0xFFFFFF00);
+
+sub _obits ($$) {
+ my($lo,$hi) = @_;
+
+ return 0xFF if $lo == $hi;
+ return (~ ($hi ^ $lo)) & 0xFF;
+}
+
+sub new_no($;$$) {
+ unshift @_, -1;
+ goto &_xnew;
+}
+
+sub new($;$$) {
+ unshift @_, 0;
+ goto &_xnew;
+}
+
+sub new_from_aton($$) {
+ my $proto = shift;
+ my $class = ref $proto || $proto || __PACKAGE__;
+ my $ip = shift;
+ return undef unless defined $ip;
+ my $addrlen = length($ip);
+ return undef unless $addrlen == 4;
+ my $self = {
+ addr => ipv4to6($ip),
+ mask => &Ones,
+ isv6 => 0,
+ };
+ return bless $self, $class;
+}
+
+sub new6($;$$) {
+ unshift @_, 1;
+ goto &_xnew;
+}
+
+sub new_cis($;$$) {
+ my @in = @_;
+ if ( $in[1] && $in[1] =~ m!^(.+)\s+(.+)$! ) {
+ $in[1] = $1 .'/'. $2;
+ }
+ @_ = (0,@in);
+ goto &_xnew;
+}
+
+sub new_cis6($;$$) {
+ my @in = @_;
+ if ( $in[1] && $in[1] =~ m!^(.+)\s+(.+)$! ) {
+ $in[1] = $1 .'/'. $2;
+ }
+ @_ = (1,@in);
+ goto &_xnew;
+}
+
+sub _no_octal {
+ $_[0] =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
+ return sprintf("%d.%d.%d.%d",$1,$2,$3,$4);
+}
+
+sub _xnew($$;$$) {
+ my $noctal = 0;
+ my $isV6 = shift;
+ if ($isV6 < 0) { # flag for no octal?
+ $isV6 = 0;
+ $noctal = 1;
+ }
+ my $proto = shift;
+ my $class = ref $proto || $proto || __PACKAGE__;
+ my $ip = shift;
+
+ $ip = 'default' unless defined $ip;
+ $ip = _retMBIstring($ip) # treat as big bcd string
+ if ref $ip && ref $ip eq 'Math::BigInt'; # can /CIDR notation
+ my $hasmask = 1;
+ my($mask,$tmp);
+
+# IP to lower case AFTER ref test for Math::BigInt. 'lc' strips blessing
+
+ $ip = lc $ip;
+
+ while (1) {
+# process IP's with no CIDR or that have the CIDR as part of the IP argument string
+ unless (@_) {
+# if ($ip =~ m!^(.+)/(.+)$!) {
+ if ($ip !~ /\D/) { # binary number notation
+ $ip = bcd2bin($ip);
+ $mask = Ones;
+ last;
+ }
+ elsif ($ip =~ m!^([a-z0-9.:-]+)(?:/|\s+)([a-z0-9.:-]+)$!) {
+ $ip = $1;
+ $mask = $2;
+ } elsif (grep($ip eq $_,(qw(default any broadcast loopback unspecified)))) {
+ $isV6 = 1 if $ip eq 'unspecified';
+ if ($isV6) {
+ $mask = $fip6m{$ip};
+ return undef unless defined ($ip = $fip6{$ip});
+ } else {
+ $mask = $fip4m{$ip};
+ return undef unless defined ($ip = $fip4{$ip});
+ }
+ last;
+ }
+ }
+# process "ipv6" token and default IP's
+ elsif (defined $_[0]) {
+ if ($_[0] =~ /ipv6/i || $isV6) {
+ if (grep($ip eq $_,(qw(default any loopback unspecified)))) {
+ $mask = $fip6m{$ip};
+ $ip = $fip6{$ip};
+ last;
+ } else {
+ return undef unless $isV6;
+# add for ipv6 notation "12345, 1"
+ }
+# $mask = lc $_[0];
+# } else {
+# $mask = lc $_[0];
+ }
+# extract mask
+ $mask = $_[0];
+ }
+###
+### process mask
+ unless (defined $mask) {
+ $hasmask = 0;
+ $mask = 'host';
+ }
+
+# two kinds of IP's can turn on the isV6 flag
+# 1) big digits that are over the IPv4 boundry
+# 2) IPv6 IP syntax
+#
+# check these conditions and set isV6 as appropriate
+#
+ my $try;
+ $isV6 = 1 if # check big bcd and IPv6 rfc1884
+ ( $ip !~ /\D/ && # ip is all decimal
+ (length($ip) > 3 || $ip > 255) && # exclude a single digit in the range of zero to 255, could be funny IPv4
+ ($try = bcd2bin($ip)) && ! isIPv4($try)) || # precedence so $try is not corrupted
+ (index($ip,':') >= 0 && ($try = ipv6_aton($ip))); # fails if not an rfc1884 address
+
+# if either of the above conditions is true, $try contains the NetAddr 128 bit address
+
+# checkfor Math::BigInt mask
+ $mask = _retMBIstring($mask) # treat as big bcd string
+ if ref $mask && ref $mask eq 'Math::BigInt';
+
+# MASK to lower case AFTER ref test for Math::BigInt, 'lc' strips blessing
+
+ $mask = lc $mask;
+
+ if ($mask !~ /\D/) { # bcd or CIDR notation
+ my $isCIDR = length($mask) < 4 && $mask < 129;
+ if ($isV6) {
+ if ($isCIDR) {
+ my($dq1,$dq2,$dq3,$dq4);
+ if ($ip =~ /^(\d+)(?:|\.(\d+)(?:|\.(\d+)(?:|\.(\d+))))$/ &&
+ do {$dq1 = $1;
+ $dq2 = $2 || 0;
+ $dq3 = $3 || 0;
+ $dq4 = $4 || 0;
+ 1;
+ } &&
+ $dq1 >= 0 && $dq1 < 256 &&
+ $dq2 >= 0 && $dq2 < 256 &&
+ $dq3 >= 0 && $dq3 < 256 &&
+ $dq4 >= 0 && $dq4 < 256
+ ) { # corner condition of IPv4 with isV6
+ $ip = join('.',$dq1,$dq2,$dq3,$dq4);
+ $try = ipv4to6(inet_aton($ip));
+ if ($mask < 32) {
+ $mask = shiftleft(Ones,32 -$mask);
+ }
+ elsif ($mask == 32) {
+ $mask = Ones;
+ } else {
+ return undef; # undoubtably an error
+ }
+ }
+ elsif ($mask < 128) {
+ $mask = shiftleft(Ones,128 -$mask); # small cidr
+ } else {
+ $mask = Ones();
+ }
+ } else {
+ $mask = bcd2bin($mask);
+ }
+ }
+ elsif ($isCIDR && $mask < 33) { # is V4
+ if ($mask < 32) {
+ $mask = shiftleft(Ones,32 -$mask);
+ }
+ elsif ( $mask == 32) {
+ $mask = Ones;
+ } else {
+ $mask = bcd2bin($mask);
+ $mask |= $_v4mask; # v4 always
+ }
+ } else { # also V4
+ $mask = bcd2bin($mask);
+ $mask |= $_v4mask;
+ }
+ if ($try) { # is a big number
+ $ip = $try;
+ last;
+ }
+ } elsif ($mask =~ m/^\d+\.\d+\.\d+\.\d+$/) { # ipv4 form of mask
+ $mask = _no_octal($mask) if $noctal; # filter for octal
+ return undef unless defined ($mask = inet_aton($mask));
+ $mask = mask4to6($mask);
+ } elsif (grep($mask eq $_,qw(default any broadcast loopback unspecified host))) {
+ if (index($ip,':') < 0 && ! $isV6) {
+ return undef unless defined ($mask = $fip4m{$mask});
+ } else {
+ return undef unless defined ($mask = $fip6m{$mask});
+ }
+ } else {
+ return undef unless defined ($mask = ipv6_aton($mask)); # try ipv6 form of mask
+ }
+
+# process remaining IP's
+
+ if (index($ip,':') < 0) { # ipv4 address
+ if ($ip =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
+ ; # the common case
+ }
+ elsif (grep($ip eq $_,(qw(default any broadcast loopback)))) {
+ return undef unless defined ($ip = $fip4{$ip});
+ last;
+ }
+ elsif ($ip =~ m/^(\d+)\.(\d+)$/) {
+ $ip = ($hasmask)
+ ? "${1}.${2}.0.0"
+ : "${1}.0.0.${2}";
+ }
+ elsif ($ip =~ m/^(\d+)\.(\d+)\.(\d+)$/) {
+ $ip = ($hasmask)
+ ? "${1}.${2}.${3}.0"
+ : "${1}.${2}.0.${3}";
+ }
+ elsif ($ip =~ /^(\d+)$/ && $hasmask && $1 >= 0 and $1 < 256) { # pure numeric
+ $ip = sprintf("%d.0.0.0",$1);
+ }
+# elsif ($ip =~ /^\d+$/ && !$hasmask) { # a big integer
+ elsif ($ip =~ /^\d+$/ ) { # a big integer
+ $ip = bcd2bin($ip);
+ last;
+ }
+# these next three might be broken??? but they have been in the code a long time and no one has complained
+ elsif ($ip =~ /^0[xb]\d+$/ && $hasmask &&
+ (($tmp = eval "$ip") || 1) &&
+ $tmp >= 0 && $tmp < 256) {
+ $ip = sprintf("%d.0.0.0",$tmp);
+ }
+ elsif ($ip =~ /^-?\d+$/) {
+ $ip += 2 ** 32 if $ip < 0;
+ $ip = pack('L3N',0,0,0,$ip);
+ last;
+ }
+ elsif ($ip =~ /^-?0[xb]\d+$/) {
+ $ip = eval "$ip";
+ $ip = pack('L3N',0,0,0,$ip);
+ last;
+ }
+
+# notations below include an implicit mask specification
+
+ elsif ($ip =~ m/^(\d+)\.$/) {
+ $ip = "${1}.0.0.0";
+ $mask = $ff000000;
+ }
+ elsif ($ip =~ m/^(\d+)\.(\d+)-(\d+)\.?$/ && $2 <= $3 && $3 < 256) {
+ $ip = "${1}.${2}.0.0";
+ $mask = pack('L3C4',0xffffffff,0xffffffff,0xffffffff,255,_obits($2,$3),0,0);
+ }
+ elsif ($ip =~ m/^(\d+)-(\d+)\.?$/ and $1 <= $2 && $2 < 256) {
+ $ip = "${1}.0.0.0";
+ $mask = pack('L3C4',0xffffffff,0xffffffff,0xffffffff,_obits($1,$2),0,0,0)
+ }
+ elsif ($ip =~ m/^(\d+)\.(\d+)\.$/) {
+ $ip = "${1}.${2}.0.0";
+ $mask = $ffff0000;
+ }
+ elsif ($ip =~ m/^(\d+)\.(\d+)\.(\d+)-(\d+)\.?$/ && $3 <= $4 && $4 < 256) {
+ $ip = "${1}.${2}.${3}.0";
+ $mask = pack('L3C4',0xffffffff,0xffffffff,0xffffffff,255,255,_obits($3,$4),0);
+ }
+ elsif ($ip =~ m/^(\d+)\.(\d+)\.(\d+)\.$/) {
+ $ip = "${1}.${2}.${3}.0";
+ $mask = $ffffff00;
+ }
+ elsif ($ip =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)-(\d+)$/ && $4 <= $5 && $5 < 256) {
+ $ip = "${1}.${2}.${3}.${4}";
+ $mask = pack('L3C4',0xffffffff,0xffffffff,0xffffffff,255,255,255,_obits($4,$5));
+ }
+ elsif ($ip =~ m/^(\d+\.\d+\.\d+\.\d+)
+ \s*-\s*(\d+\.\d+\.\d+\.\d+)$/x) {
+ if ($noctal) {
+ return undef unless ($ip = inet_aton(_no_octal($1)));
+ return undef unless ($tmp = inet_aton(_no_octal($2)));
+ } else {
+ return undef unless ($ip = inet_aton($1));
+ return undef unless ($tmp = inet_aton($2));
+ }
+# check for left side greater than right side
+# save numeric difference in $mask
+ return undef if ($tmp = unpack('N',$tmp) - unpack('N',$ip)) < 0;
+ $ip = ipv4to6($ip);
+ $tmp = pack('L3N',0,0,0,$tmp);
+ $mask = ~$tmp;
+ return undef if notcontiguous($mask);
+# check for non-aligned left side
+ return undef if hasbits($ip & $tmp);
+ last;
+ }
+# check for resolvable IPv4 hosts
+ elsif ($ip !~ /[^a-zA-Z0-9\.-]/ && ($tmp = gethostbyname(fillIPv4($ip))) && $tmp ne $_v4zero && $tmp ne $_zero ) {
+ $ip = ipv4to6($tmp);
+ last;
+ }
+# check for resolvable IPv6 hosts
+ elsif ($ip !~ /[^a-zA-Z0-9\.-]/ && havegethostbyname2() && ($tmp = naip_gethostbyname($ip))) {
+ $ip = $tmp;
+ $isV6 = 1;
+ last;
+ }
+ elsif ($Accept_Binary_IP && ! $hasmask) {
+ if (length($ip) == 4) {
+ $ip = ipv4to6($ip);
+ } elsif (length($ip) == 16) {
+ $isV6 = 1;
+ } else {
+ return undef;
+ }
+ last;
+ } else {
+ return undef;
+ }
+ return undef unless defined ($ip = inet_aton($ip));
+ $ip = ipv4to6($ip);
+ last;
+ }
+########## continuing
+ else { # ipv6 address
+ $isV6 = 1;
+ if (defined ($tmp = ipv6_aton($ip))) {
+ $ip = $tmp;
+ last;
+ }
+ last if grep($ip eq $_,(qw(default any loopback unspecified))) &&
+ defined ($ip = $fip6{$ip});
+ return undef;
+ }
+ } # end while (1)
+ return undef if notcontiguous($mask); # invalid if not contiguous
+
+ my $self = {
+ addr => $ip,
+ mask => $mask,
+ isv6 => $isV6,
+ };
+ return bless $self, $class;
+}
+
+=item C<-E<gt>broadcast()>
+
+Returns a new object referring to the broadcast address of a given
+subnet. The broadcast address has all ones in all the bit positions
+where the netmask has zero bits. This is normally used to address all
+the hosts in a given subnet.
+
+=cut
+
+sub broadcast ($) {
+ my $ip = _new($_[0],$_[0]->{addr} | ~$_[0]->{mask},$_[0]->{mask});
+ $ip->{addr} &= V4net unless $ip->{isv6};
+ return $ip;
+}
+
+=item C<-E<gt>network()>
+
+Returns a new object referring to the network address of a given
+subnet. A network address has all zero bits where the bits of the
+netmask are zero. Normally this is used to refer to a subnet.
+
+=cut
+
+sub network ($) {
+ return _new($_[0],$_[0]->{addr} & $_[0]->{mask},$_[0]->{mask});
+}
+
+=item C<-E<gt>addr()>
+
+Returns a scalar with the address part of the object as an IPv4 or IPv6 text
+string as appropriate. This is useful for printing or for passing the address
+part of the NetAddr::IP::Lite object to other components that expect an IP
+address. If the object is an ipV6 address or was created using ->new6($ip)
+it will be reported in ipV6 hex format otherwise it will be reported in dot
+quad format only if it resides in ipV4 address space.
+
+=cut
+
+sub addr ($) {
+ return ($_[0]->{isv6})
+ ? ipv6_n2x($_[0]->{addr})
+ : inet_n2dx($_[0]->{addr});
+}
+
+=item C<-E<gt>mask()>
+
+Returns a scalar with the mask as an IPv4 or IPv6 text string as
+described above.
+
+=cut
+
+sub mask ($) {
+ return ipv6_n2x($_[0]->{mask}) if $_[0]->{isv6};
+ my $mask = isIPv4($_[0]->{addr})
+ ? $_[0]->{mask} & V4net
+ : $_[0]->{mask};
+ return inet_n2dx($mask);
+}
+
+=item C<-E<gt>masklen()>
+
+Returns a scalar the number of one bits in the mask.
+
+=cut
+
+sub masklen ($) {
+ my $len = (notcontiguous($_[0]->{mask}))[1];
+ return 0 unless $len;
+ return $len if $_[0]->{isv6};
+ return isIPv4($_[0]->{addr})
+ ? $len -96
+ : $len;
+}
+
+=item C<-E<gt>bits()>
+
+Returns the width of the address in bits. Normally 32 for v4 and 128 for v6.
+
+=cut
+
+sub bits {
+ return $_[0]->{isv6} ? 128 : 32;
+}
+
+=item C<-E<gt>version()>
+
+Returns the version of the address or subnet. Currently this can be
+either 4 or 6.
+
+=cut
+
+sub version {
+ my $self = shift;
+ return $self->{isv6} ? 6 : 4;
+}
+
+=item C<-E<gt>cidr()>
+
+Returns a scalar with the address and mask in CIDR notation. A
+NetAddr::IP::Lite object I<stringifies> to the result of this function.
+(see comments about ->new6() and ->addr() for output formats)
+
+=cut
+
+sub cidr ($) {
+ return $_[0]->addr . '/' . $_[0]->masklen;
+}
+
+=item C<-E<gt>aton()>
+
+Returns the address part of the NetAddr::IP::Lite object in the same format
+as the C<inet_aton()> or C<ipv6_aton> function respectively. If the object
+was created using ->new6($ip), the address returned will always be in ipV6
+format, even for addresses in ipV4 address space.
+
+=cut
+
+sub aton {
+ return $_[0]->{addr} if $_[0]->{isv6};
+ return isIPv4($_[0]->{addr})
+ ? ipv6to4($_[0]->{addr})
+ : $_[0]->{addr};
+}
+
+=item C<-E<gt>range()>
+
+Returns a scalar with the base address and the broadcast address
+separated by a dash and spaces. This is called range notation.
+
+=cut
+
+sub range ($) {
+ return $_[0]->network->addr . ' - ' . $_[0]->broadcast->addr;
+}
+
+=item C<-E<gt>numeric()>
+
+When called in a scalar context, will return a numeric representation
+of the address part of the IP address. When called in an array
+context, it returns a list of two elements. The first element is as
+described, the second element is the numeric representation of the
+netmask.
+
+This method is essential for serializing the representation of a
+subnet.
+
+=cut
+
+sub numeric ($) {
+ if (wantarray) {
+ if (! $_[0]->{isv6} && isIPv4($_[0]->{addr})) {
+ return ( sprintf("%u",unpack('N',ipv6to4($_[0]->{addr}))),
+ sprintf("%u",unpack('N',ipv6to4($_[0]->{mask}))));
+ }
+ else {
+ return ( bin2bcd($_[0]->{addr}),
+ bin2bcd($_[0]->{mask}));
+ }
+ }
+ return (! $_[0]->{isv6} && isIPv4($_[0]->{addr}))
+ ? sprintf("%u",unpack('N',ipv6to4($_[0]->{addr})))
+ : bin2bcd($_[0]->{addr});
+}
+
+=item C<-E<gt>bigint()>
+
+When called in a scalar context, will return a Math::BigInt representation
+of the address part of the IP address. When called in an array
+contest, it returns a list of two elements. The first element is as
+described, the second element is the Math::BigInt representation of the
+netmask.
+
+=cut
+
+my $biloaded;
+my $bi2strng;
+my $no_mbi_emu = 1;
+
+# function to force into test development mode
+#
+sub _force_bi_emu {
+ undef $biloaded;
+ undef $bi2strng;
+ $no_mbi_emu = 0;
+ print STDERR "\n\n\tWARNING: test development mode, this
+\tmessage SHOULD NEVER BE SEEN IN PRODUCTION!
+set my \$no_mbi_emu = 1 in t/bigint.t to remove this warning\n\n";
+}
+
+# function to stringify various flavors of Math::BigInt objects
+# tests to see if the object is a hash or a signed scalar
+
+sub _bi_stfy {
+ "$_[0]" =~ /(\d+)/; # stringify and remove '+' if present
+ $1;
+}
+
+sub _fakebi2strg {
+ ${$_[0]} =~ /(\d+)/;
+ $1;
+}
+
+# fake new from bi string Math::BigInt 0.01
+#
+sub _bi_fake {
+ bless \('+'. $_[1]), 'Math::BigInt';
+}
+
+# as of this writing there are three known flavors of Math::BigInt
+# v0.01 MBI::new returns a scalar ref
+# v1.?? - 1.69 CALC::_new takes a reference to a scalar, returns an array, MBI returns a hash ref
+# v1.70 and up CALC::_new takes a scalar, returns and array, MBI returns a hash ref
+
+sub _loadMBI { # load Math::BigInt on demand
+ if (eval {$no_mbi_emu && require Math::BigInt}) { # any version should work, three known
+ import Math::BigInt;
+ $biloaded = \&Math::BigInt::new;
+ $bi2strng = \&_bi_stfy;
+ } else {
+ $biloaded = \&_bi_fake;
+ $bi2strng = \&_fakebi2strg;
+ }
+}
+
+sub _retMBIstring {
+ _loadMBI unless $biloaded; # load Math::BigInt on demand
+ $bi2strng->(@_);
+}
+
+sub _biRef {
+ _loadMBI unless $biloaded; # load Math::BigInt on demand
+ $biloaded->('Math::BigInt',$_[0]);
+}
+
+sub bigint($) {
+ my($addr,$mask);
+ if (wantarray) {
+ if (! $_[0]->{isv6} && isIPv4($_[0]->{addr})) {
+ $addr = $_[0]->{addr}
+ ? sprintf("%u",unpack('N',ipv6to4($_[0]->{addr})))
+ : 0;
+ $mask = $_[0]->{mask}
+ ? sprintf("%u",unpack('N',ipv6to4($_[0]->{mask})))
+ : 0;
+ }
+ else {
+ $addr = $_[0]->{addr}
+ ? bin2bcd($_[0]->{addr})
+ : 0;
+ $mask = $_[0]->{mask}
+ ? bin2bcd($_[0]->{mask})
+ : 0;
+ }
+ (_biRef($addr),_biRef($mask));
+
+ } else { # not wantarray
+
+ if (! $_[0]->{isv6} && isIPv4($_[0]->{addr})) {
+ $addr = $_[0]->{addr}
+ ? sprintf("%u",unpack('N',ipv6to4($_[0]->{addr})))
+ : 0;
+ } else {
+ $addr = $_[0]->{addr}
+ ? bin2bcd($_[0]->{addr})
+ : 0;
+ }
+ _biRef($addr);
+ }
+}
+
+=item C<$me-E<gt>contains($other)>
+
+Returns true when C<$me> completely contains C<$other>. False is
+returned otherwise and C<undef> is returned if C<$me> and C<$other>
+are not both C<NetAddr::IP::Lite> objects.
+
+=cut
+
+sub contains ($$) {
+ return within(@_[1,0]);
+}
+
+=item C<$me-E<gt>within($other)>
+
+The complement of C<-E<gt>contains()>. Returns true when C<$me> is
+completely contained within C<$other>, undef if C<$me> and C<$other>
+are not both C<NetAddr::IP::Lite> objects.
+
+=cut
+
+sub within ($$) {
+ return 1 unless hasbits($_[1]->{mask}); # 0x0 contains everything
+ my $netme = $_[0]->{addr} & $_[0]->{mask};
+ my $brdme = $_[0]->{addr} | ~ $_[0]->{mask};
+ my $neto = $_[1]->{addr} & $_[1]->{mask};
+ my $brdo = $_[1]->{addr} | ~ $_[1]->{mask};
+ return (sub128($netme,$neto) && sub128($brdo,$brdme))
+ ? 1 : 0;
+}
+
+=item C<-E<gt>first()>
+
+Returns a new object representing the first usable IP address within
+the subnet (ie, the first host address).
+
+=cut
+
+my $_cidr127 = pack('N4',0xffffffff,0xffffffff,0xffffffff,0xfffffffe);
+
+sub first ($) {
+ if (hasbits($_[0]->{mask} ^ $_cidr127)) {
+ return $_[0]->network + 1;
+ } else {
+ return $_[0]->network;
+ }
+# return $_[0]->network + 1;
+}
+
+=item C<-E<gt>last()>
+
+Returns a new object representing the last usable IP address within
+the subnet (ie, one less than the broadcast address).
+
+=cut
+
+sub last ($) {
+ if (hasbits($_[0]->{mask} ^ $_cidr127)) {
+ return $_[0]->broadcast - 1;
+ } else {
+ return $_[0]->broadcast;
+ }
+# return $_[0]->broadcast - 1;
+}
+
+=item C<-E<gt>nth($index)>
+
+Returns a new object representing the I<n>-th usable IP address within
+the subnet (ie, the I<n>-th host address). If no address is available
+(for example, when the network is too small for C<$index> hosts),
+C<undef> is returned.
+
+Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite implements
+C<-E<gt>nth($index)> and C<-E<gt>num()> exactly as the documentation states.
+Previous versions behaved slightly differently and not in a consistent
+manner.
+
+To use the old behavior for C<-E<gt>nth($index)> and C<-E<gt>num()>:
+
+ use NetAddr::IP::Lite qw(:old_nth);
+
+ old behavior:
+ NetAddr::IP->new('10/32')->nth(0) == undef
+ NetAddr::IP->new('10/32')->nth(1) == undef
+ NetAddr::IP->new('10/31')->nth(0) == undef
+ NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/31
+ NetAddr::IP->new('10/30')->nth(0) == undef
+ NetAddr::IP->new('10/30')->nth(1) == 10.0.0.1/30
+ NetAddr::IP->new('10/30')->nth(2) == 10.0.0.2/30
+ NetAddr::IP->new('10/30')->nth(3) == 10.0.0.3/30
+
+Note that in each case, the broadcast address is represented in the
+output set and that the 'zero'th index is alway undef except for
+a point-to-point /31 or /127 network where there are exactly two
+addresses in the network.
+
+ new behavior:
+ NetAddr::IP->new('10/32')->nth(0) == 10.0.0.0/32
+ NetAddr::IP->new('10.1/32'->nth(0) == 10.0.0.1/32
+ NetAddr::IP->new('10/31')->nth(0) == 10.0.0.0/32
+ NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/32
+ NetAddr::IP->new('10/30')->nth(0) == 10.0.0.1/30
+ NetAddr::IP->new('10/30')->nth(1) == 10.0.0.2/30
+ NetAddr::IP->new('10/30')->nth(2) == undef
+
+Note that a /32 net always has 1 usable address while a /31 has exactly
+two usable addresses for point-to-point addressing. The first
+index (0) returns the address immediately following the network address
+except for a /31 or /127 when it return the network address.
+
+=cut
+
+sub nth ($$) {
+ my $self = shift;
+ my $count = shift;
+
+ my $slash31 = ! hasbits($self->{mask} ^ $_cidr127);
+ if ($Old_nth) {
+ return undef if $slash31 && $count != 1;
+ return undef if ($count < 1 or $count > $self->num ());
+ }
+ elsif ($slash31) {
+ return undef if ($count && $count != 1); # only index 0, 1 allowed for /31
+ } else {
+ ++$count;
+ return undef if ($count < 1 or $count > $self->num ());
+ }
+ return $self->network + $count;
+}
+
+=item C<-E<gt>num()>
+
+As of version 4.42 of NetAddr::IP and version 1.27 of NetAddr::IP::Lite
+a /31 and /127 with return a net B<num> value of 2 instead of 0 (zero)
+for point-to-point networks.
+
+Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite
+return the number of usable IP addresses within the subnet,
+not counting the broadcast or network address.
+
+Previous versions worked only for ipV4 addresses, returned a
+maximum span of 2**32 and returned the number of IP addresses
+not counting the broadcast address.
+ (one greater than the new behavior)
+
+To use the old behavior for C<-E<gt>nth($index)> and C<-E<gt>num()>:
+
+ use NetAddr::IP::Lite qw(:old_nth);
+
+WARNING:
+
+NetAddr::IP will calculate and return a numeric string for network
+ranges as large as 2**128. These values are TEXT strings and perl
+can treat them as integers for numeric calculations.
+
+Perl on 32 bit platforms only handles integer numbers up to 2**32
+and on 64 bit platforms to 2**64.
+
+If you wish to manipulate numeric strings returned by NetAddr::IP
+that are larger than 2**32 or 2**64, respectively, you must load
+additional modules such as Math::BigInt, bignum or some similar
+package to do the integer math.
+
+=cut
+
+sub num ($) {
+ if ($Old_nth) {
+ my @net = unpack('L3N',$_[0]->{mask} ^ Ones);
+# number of ip's less broadcast
+ return 0xfffffffe if $net[0] || $net[1] || $net[2]; # 2**32 -1
+ return $net[3] if $net[3];
+ } else { # returns 1 for /32 /128, 2 for /31 /127 else n-2 up to 2**32
+ (undef, my $net) = addconst($_[0]->{mask},1);
+ return 1 unless hasbits($net); # ipV4/32 or ipV6/128
+ $net = $net ^ Ones;
+ return 2 unless hasbits($net); # ipV4/31 or ipV6/127
+ return bin2bcd($net);
+ }
+}
+
+# deprecated
+#sub num ($) {
+# my @net = unpack('L3N',$_[0]->{mask} ^ Ones);
+# if ($Old_nth) {
+## number of ip's less broadcast
+# return 0xfffffffe if $net[0] || $net[1] || $net[2]; # 2**32 -1
+# return $net[3] if $net[3];
+# } else { # returns 1 for /32 /128, 0 for /31 /127 else n-2 up to 2**32
+## number of usable IP's === number of ip's less broadcast & network addys
+# return 0xfffffffd if $net[0] || $net[1] || $net[2]; # 2**32 -2
+# return 1 unless $net[3];
+# $net[3]--;
+# }
+# return $net[3];
+#}
+
+=pod
+
+=back
+
+=cut
+
+sub import {
+ if (grep { $_ eq ':aton' } @_) {
+ $Accept_Binary_IP = 1;
+ @_ = grep { $_ ne ':aton' } @_;
+ }
+ if (grep { $_ eq ':old_nth' } @_) {
+ $Old_nth = 1;
+ @_ = grep { $_ ne ':old_nth' } @_;
+ }
+ if (grep { $_ eq ':lower' } @_)
+ {
+ NetAddr::IP::Util::lower();
+ @_ = grep { $_ ne ':lower' } @_;
+ }
+ if (grep { $_ eq ':upper' } @_)
+ {
+ NetAddr::IP::Util::upper();
+ @_ = grep { $_ ne ':upper' } @_;
+ }
+ NetAddr::IP::Lite->export_to_level(1, @_);
+}
+
+=head1 EXPORT_OK
+
+ Zeros
+ Ones
+ V4mask
+ V4net
+ :aton DEPRECATED
+ :old_nth
+ :upper
+ :lower
+
+=head1 AUTHORS
+
+Luis E. Muñoz E<lt>luismunoz@cpan.orgE<gt>,
+Michael Robinton E<lt>michael@bizsystems.comE<gt>
+
+=head1 WARRANTY
+
+This software comes with the same warranty as perl itself (ie, none),
+so by using it you accept any and all the liability.
+
+=head1 COPYRIGHT
+
+ This software is (c) Luis E. Muñoz, 1999 - 2005
+ and (c) Michael Robinton, 2006 - 2011.
+
+All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ a) the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any
+ later version, or
+
+ b) the "Artistic License" which comes with this distribution.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
+the GNU General Public License or the Artistic License for more details.
+
+You should have received a copy of the Artistic License with this
+distribution, in the file named "Artistic". If not, I'll be glad to provide
+one.
+
+You should also have received a copy of the GNU General Public License
+along with this program in the file named "Copying". If not, write to the
+
+ Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330
+ Boston, MA 02111-1307, USA
+
+or visit their web page on the internet at:
+
+ http://www.gnu.org/copyleft/gpl.html.
+
+=head1 SEE ALSO
+
+NetAddr::IP(3), NetAddr::IP::Util(3), NetAddr::IP::InetBase(3)
+
+=cut
+
+1;
--- /dev/null
+MANIFEST
+MANIFEST.SKIP
+Changes
+Lite.pm
+Makefile.PL
+META.yml
+README
+bug2742981
+t/addr.t
+t/aton.t
+t/bigint.t
+t/bignums.t
+t/bin_ips.t
+t/bits.t
+t/broadcast.t
+t/bug62521.t
+t/cidr.t
+t/constants.t
+t/contains.t
+t/copy.t
+t/firstlast.t
+t/lemasklen.t
+t/loops.t
+t/lower.t
+t/mask.t
+t/masklen.t
+t/netaddr.t
+t/network.t
+t/new-nth.t
+t/new-num.t
+t/numeric.t
+t/old-nth.t
+t/old-num.t
+t/over-qq.t
+t/over_comp.t
+t/over_copy.t
+t/over_equal.t
+t/over_math.t
+t/overminus.t
+t/pathological.t
+t/range.t
+t/relops.t
+t/v4-aton.t
+t/v4-badnm.t
+t/v4-base.t
+t/v4-basem.t
+t/v4-cidr.t
+t/v4-cnew.t
+t/v4-contains.t
+t/v4-last.t
+t/v4-new-first.t
+t/v4-new_from_aton.t
+t/v4-new.t
+t/v4_new_cis.t
+t/v4-no_octal.t
+t/v4-num.t
+t/v4-numeric.t
+t/v4-old-first.t
+t/v4-range.t
+t/v4-snew.t
+t/v4-wnew.t
+t/v6-cnew.t
+t/v6-contains.t
+t/v6-inc.t
+t/v6-new_cis6_base.t
+t/v6-new_cis_base.t
+t/v6-new-base.t
+t/v6-num.t
+t/v6-numeric.t
+t/v6-old-base.t
+t/version.t
+t/within.t
+Util/MANIFEST
+Util/MANIFEST.SKIP
+Util/Changes
+Util/configure
+Util/configure.ac
+Util/config.h.in
+Util/lib/NetAddr/IP/UtilPP.pm
+Util/tlib/NetAddr/IP/Util_IS.pm
+Util/localconf.h
+Util/Makefile.PL
+Util/README
+Util/t/4to6.t
+Util/t/add128.t
+Util/t/addconst.t
+Util/t/af_inet6.t
+Util/t/anyto6.t
+Util/t/badd.t
+Util/t/bcd2bin.t
+Util/t/bcdn2bin.t
+Util/t/bin.t
+Util/t/comp128.t
+Util/t/croak.t
+Util/t/hasbits.t
+Util/t/inet_4map6.t
+Util/t/inet_n2ad.t
+Util/t/inet_n2dx.t
+Util/t/ipv4_inet.t
+Util/t/ipv6_any2n.t
+Util/t/ipv6func.t
+Util/t/ipv6to4.t
+Util/t/isIPv4.t
+Util/t/leftshift.t
+Util/t/mode.t
+Util/t/notcontiguous.t
+Util/t/simple_pack.t
+Util/t/sub128.t
+Util/typemap
+Util/Util.pm
+Util/Util.xs
+Util/lib/NetAddr/IP/InetBase.pm
+Util/t/binet_n2ad.t
+Util/t/binet_n2dx.t
+Util/t/binet_pton.t
+Util/t/bipv4_inet.t
+Util/t/bipv6_any2n.t
+Util/t/bipv6func.t
+Util/t/bisIPv4.t
+Util/t/bpackzeros.t
+Util/t/inet_pton.t
+Util/t/packzeros.t
+Util/t/binet_ntoa.t
+Util/t/ipv6_ntoa.t
+Util/t/naip_gethostbyname.t
+Util/t/no6_naip_gethostbyname.t
--- /dev/null
+^Build$
+^_build/
+^blib/
+^blibdirs
+Makefile$
+Makefile\.[a-z]+$
+pm_to_blib
+CVS/.*
+\.cvs
+,v$
+^tmp/
+\.old$
+\.bak$
+\.tmp$
+\.xsc$
+~$
+^#
+\.shar$
+\.tar$
+\.tgz$
+\.tar\.gz$
+\.zip$
+_uu$
+Util_IS\.pm$
+Util\.(bs|[co])$
+localStuff\.h$
+config\.log$
+config\.h$
+config\.status
+localperl\.h
+
--- /dev/null
+# http://module-build.sourceforge.net/META-spec.html
+#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
+name: NetAddr-IP-Lite
+version: 0.10
+version_from: Lite.pm
+installdirs: site
+requires:
+
+distribution_type: module
+generated_by: ExtUtils::MakeMaker version 6.30
--- /dev/null
+use ExtUtils::MakeMaker;
+use Config;
+
+my $pkg = 'NetAddr::IP::Lite';
+$pkg =~ /[^:]+$/;
+my $module = $& .'.pm';
+
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+
+my %makeparms = (
+ 'NAME' => $pkg,
+ 'VERSION_FROM' => $module, # finds $VERSION
+ 'PREREQ_PM' => {Test::More => 0,
+ },
+ 'clean' => { FILES => "*~ tmp*"},
+ 'dist' => {COMPRESS=>'gzip', SUFFIX=>'gz'}
+);
+
+sub MY::top_targets {
+ package MY;
+ my $inherited = shift->SUPER::top_targets(@_);
+ $inherited =~ s/(pure_all\s+::.+)/$1 README/;
+ $inherited;
+}
+
+sub MY::post_constants {
+ my $post_constants = q|
+MY_POD2TEXT = |. $Config{scriptdirexp} .'/pod2text' .q|
+|;
+}
+
+sub MY::postamble {
+ package MY;
+ my $postamble = q|
+README : |. $module .q|
+ @$(MY_POD2TEXT) |. $module .q| > README
+
+|;
+}
+
+WriteMakefile(%makeparms);
--- /dev/null
+NAME
+ NetAddr::IP::Lite - Manages IPv4 and IPv6 addresses and subnets
+
+SYNOPSIS
+ use NetAddr::IP::Lite qw(
+ Zeros
+ Ones
+ V4mask
+ V4net
+ :aton DEPRECATED !
+ :old_nth
+ :upper
+ :lower
+ );
+
+ my $ip = new NetAddr::IP::Lite '127.0.0.1';
+ or if your prefer
+ my $ip = NetAddr::IP::Lite->new('127.0.0.1);
+ or from a packed IPv4 address
+ my $ip = new_from_aton NetAddr::IP::Lite (inet_aton('127.0.0.1'));
+ or from an octal filtered IPv4 address
+ my $ip = new_no NetAddr::IP::Lite '127.012.0.0';
+
+ print "The address is ", $ip->addr, " with mask ", $ip->mask, "\n" ;
+
+ if ($ip->within(new NetAddr::IP::Lite "127.0.0.0", "255.0.0.0")) {
+ print "Is a loopback address\n";
+ }
+
+ # This prints 127.0.0.1/32
+ print "You can also say $ip...\n";
+
+ The following four functions return ipV6 representations of:
+
+ :: = Zeros();
+ FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF = Ones();
+ FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:: = V4mask();
+ ::FFFF:FFFF = V4net();
+
+INSTALLATION
+ Un-tar the distribution in an appropriate directory and type:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+ NetAddr::IP::Lite depends on NetAddr::IP::Util which installs by default
+ with its primary functions compiled using Perl's XS extensions to build
+ a 'C' library. If you do not have a 'C' complier available or would like
+ the slower Pure Perl version for some other reason, then type:
+
+ perl Makefile.PL -noxs
+ make
+ make test
+ make install
+
+DESCRIPTION
+ This module provides an object-oriented abstraction on top of IP
+ addresses or IP subnets, that allows for easy manipulations. Most of the
+ operations of NetAddr::IP are supported. This module will work with
+ older versions of Perl and is compatible with Math::BigInt.
+
+ * By default NetAddr::IP functions and methods return string IPv6
+ addresses in uppercase. To change that to lowercase:
+
+ NOTE: the AUGUST 2010 RFC5952 states:
+
+ 4.3. Lowercase
+
+ The characters "a", "b", "c", "d", "e", and "f" in an IPv6
+ address MUST be represented in lowercase.
+
+ It is recommended that all NEW applications using NetAddr::IP::Lite be
+ invoked as shown on the next line.
+
+ use NetAddr::IP::Lite qw(:lower);
+
+ * To ensure the current IPv6 string case behavior even if the default
+ changes:
+
+ use NetAddr::IP::Lite qw(:upper);
+
+ The internal representation of all IP objects is in 128 bit IPv6
+ notation. IPv4 and IPv6 objects may be freely mixed.
+
+ The supported operations are described below:
+
+ Overloaded Operators
+
+ Assignment ("=")
+ Has been optimized to copy one NetAddr::IP::Lite object to another
+ very quickly.
+
+ "->copy()"
+ The assignment ("=") operation is only put in to operation when the
+ copied object is further mutated by another overloaded operation.
+ See the overload manpage SPECIAL SYMBOLS FOR "use overload" for
+ details.
+
+ "->copy()" actually creates a new object when called.
+
+ Stringification
+ An object can be used just as a string. For instance, the following
+ code
+
+ my $ip = new NetAddr::IP::Lite '192.168.1.123';
+ print "$ip\n";
+
+ Will print the string 192.168.1.123/32.
+
+ my $ip = new6 NetAddr::IP::Lite '192.168.1.123';
+ print "$ip\n";
+
+ Will print the string 0:0:0:0:0:0:C0A8:17B/128
+
+ Equality
+ You can test for equality with either "eq", "ne", "==" or "!=".
+ "eq", "ne" allows the comparison with arbitrary strings as well as
+ NetAddr::IP::Lite objects. The following example:
+
+ if (NetAddr::IP::Lite->new('127.0.0.1','255.0.0.0') eq '127.0.0.1/8')
+ { print "Yes\n"; }
+
+ Will print out "Yes".
+
+ Comparison with "==" and "!=" requires both operands to be
+ NetAddr::IP::Lite objects.
+
+ Comparison via >, <, >=, <=, <=> and "cmp"
+ Internally, all network objects are represented in 128 bit format.
+ The numeric representation of the network is compared through the
+ corresponding operation. Comparisons are tried first on the address
+ portion of the object and if that is equal then the NUMERIC cidr
+ portion of the masks are compared. This leads to the
+ counterintuitive result that
+
+ /24 > /16
+
+ Comparison should not be done on netaddr objects with different CIDR
+ as this may produce indeterminate - unexpected results, rather the
+ determination of which netblock is larger or smaller should be done
+ by comparing
+
+ $ip1->masklen <=> $ip2->masklen
+
+ Addition of a constant ("+")
+ Add a 32 bit signed constant to the address part of a NetAddr
+ object. This operation changes the address part to point so many
+ hosts above the current objects start address. For instance, this
+ code:
+
+ print NetAddr::IP::Lite->new('127.0.0.1/8') + 5;
+
+ will output 127.0.0.6/8. The address will wrap around at the
+ broadcast back to the network address. This code:
+
+ print NetAddr::IP::Lite->new('10.0.0.1/24') + 255;
+
+ outputs 10.0.0.0/24.
+
+ Returns the the unchanged object when the constant is missing or out
+ of range.
+
+ 2147483647 <= constant >= -2147483648
+
+ Subtraction of a constant ("-")
+ The complement of the addition of a constant.
+
+ Difference ("-")
+ Returns the difference between the address parts of two
+ NetAddr::IP::Lite objects address parts as a 32 bit signed number.
+
+ Returns undef if the difference is out of range.
+
+ Auto-increment
+ Auto-incrementing a NetAddr::IP::Lite object causes the address part
+ to be adjusted to the next host address within the subnet. It will
+ wrap at the broadcast address and start again from the network
+ address.
+
+ Auto-decrement
+ Auto-decrementing a NetAddr::IP::Lite object performs exactly the
+ opposite of auto-incrementing it, as you would expect.
+
+ Methods
+
+ "->new([$addr, [ $mask|IPv6 ]])"
+ "->new6([$addr, [ $mask]])"
+ "->new_no([$addr, [ $mask]])"
+ "->new_from_aton($netaddr)"
+ new_cis and new_cis6 are DEPRECATED
+ "->new_cis("$addr $mask)"
+ "->new_cis6("$addr $mask)"
+ The first two methods create a new address with the supplied address
+ in "$addr" and an optional netmask "$mask", which can be omitted to
+ get a /32 or /128 netmask for IPv4 / IPv6 addresses respectively.
+
+ The third method "new_no" is exclusively for IPv4 addresses and
+ filters improperly formatted dot quad strings for leading 0's that
+ would normally be interpreted as octal format by NetAddr per the
+ specifications for inet_aton.
+
+ new_from_aton takes a packed IPv4 address and assumes a /32 mask.
+ This function replaces the DEPRECATED :aton functionality which is
+ fundamentally broken.
+
+ The last two methods new_cis and new_cis6 differ from new and new6
+ only in that they except the common Cisco address notation for
+ address/mask pairs with a space as a separator instead of a slash
+ (/)
+
+ These methods are DEPRECATED because the functionality is now
+ included in the other "new" methods
+
+ i.e. ->new_cis('1.2.3.0 24')
+ or
+ ->new_cis6('::1.2.3.0 120')
+
+ "->new6" and "->new_cis6" mark the address as being in ipV6 address
+ space even if the format would suggest otherwise.
+
+ i.e. ->new6('1.2.3.4') will result in ::102:304
+
+ addresses submitted to ->new in ipV6 notation will
+ remain in that notation permanently. i.e.
+ ->new('::1.2.3.4') will result in ::102:304
+ whereas new('1.2.3.4') would print out as 1.2.3.4
+
+ See "STRINGIFICATION" below.
+
+ "$addr" can be almost anything that can be resolved to an IP address
+ in all the notations I have seen over time. It can optionally
+ contain the mask in CIDR notation. If the OPTIONAL perl module
+ Socket6 is available in the local library it will autoload and ipV6
+ host6 names will be resolved as well as ipV4 hostnames.
+
+ prefix notation is understood, with the limitation that the range
+ specified by the prefix must match with a valid subnet.
+
+ Addresses in the same format returned by "inet_aton" or
+ "gethostbyname" can also be understood, although no mask can be
+ specified for them. The default is to not attempt to recognize this
+ format, as it seems to be seldom used.
+
+ ###### DEPRECATED, will be remove in version 5 ############ To
+ accept addresses in that format, invoke the module as in
+
+ use NetAddr::IP::Lite ':aton'
+
+ ###### USE new_from_aton instead ##########################
+
+ If called with no arguments, 'default' is assumed.
+
+ "$addr" can be any of the following and possibly more...
+
+ n.n
+ n.n/mm
+ n.n mm
+ n.n.n
+ n.n.n/mm
+ n.n.n mm
+ n.n.n.n
+ n.n.n.n/mm 32 bit cidr notation
+ n.n.n.n mm
+ n.n.n.n/m.m.m.m
+ n.n.n.n m.m.m.m
+ loopback, localhost, broadcast, any, default
+ x.x.x.x/host
+ 0xABCDEF, 0b111111000101011110, (or a bcd number)
+ a netaddr as returned by 'inet_aton'
+
+ Any RFC1884 notation
+
+ ::n.n.n.n
+ ::n.n.n.n/mmm 128 bit cidr notation
+ ::n.n.n.n/::m.m.m.m
+ ::x:x
+ ::x:x/mmm
+ x:x:x:x:x:x:x:x
+ x:x:x:x:x:x:x:x/mmm
+ x:x:x:x:x:x:x:x/m:m:m:m:m:m:m:m any RFC1884 notation
+ loopback, localhost, unspecified, any, default
+ ::x:x/host
+ 0xABCDEF, 0b111111000101011110 within the limits
+ of perl's number resolution
+ 123456789012 a 'big' bcd number (bigger than perl likes)
+ and Math::BigInt
+
+ If called with no arguments, 'default' is assumed.
+
+ "->broadcast()"
+ Returns a new object referring to the broadcast address of a given
+ subnet. The broadcast address has all ones in all the bit positions
+ where the netmask has zero bits. This is normally used to address
+ all the hosts in a given subnet.
+
+ "->network()"
+ Returns a new object referring to the network address of a given
+ subnet. A network address has all zero bits where the bits of the
+ netmask are zero. Normally this is used to refer to a subnet.
+
+ "->addr()"
+ Returns a scalar with the address part of the object as an IPv4 or
+ IPv6 text string as appropriate. This is useful for printing or for
+ passing the address part of the NetAddr::IP::Lite object to other
+ components that expect an IP address. If the object is an ipV6
+ address or was created using ->new6($ip) it will be reported in ipV6
+ hex format otherwise it will be reported in dot quad format only if
+ it resides in ipV4 address space.
+
+ "->mask()"
+ Returns a scalar with the mask as an IPv4 or IPv6 text string as
+ described above.
+
+ "->masklen()"
+ Returns a scalar the number of one bits in the mask.
+
+ "->bits()"
+ Returns the width of the address in bits. Normally 32 for v4 and 128
+ for v6.
+
+ "->version()"
+ Returns the version of the address or subnet. Currently this can be
+ either 4 or 6.
+
+ "->cidr()"
+ Returns a scalar with the address and mask in CIDR notation. A
+ NetAddr::IP::Lite object *stringifies* to the result of this
+ function. (see comments about ->new6() and ->addr() for output
+ formats)
+
+ "->aton()"
+ Returns the address part of the NetAddr::IP::Lite object in the same
+ format as the "inet_aton()" or "ipv6_aton" function respectively. If
+ the object was created using ->new6($ip), the address returned will
+ always be in ipV6 format, even for addresses in ipV4 address space.
+
+ "->range()"
+ Returns a scalar with the base address and the broadcast address
+ separated by a dash and spaces. This is called range notation.
+
+ "->numeric()"
+ When called in a scalar context, will return a numeric
+ representation of the address part of the IP address. When called in
+ an array context, it returns a list of two elements. The first
+ element is as described, the second element is the numeric
+ representation of the netmask.
+
+ This method is essential for serializing the representation of a
+ subnet.
+
+ "->bigint()"
+ When called in a scalar context, will return a Math::BigInt
+ representation of the address part of the IP address. When called in
+ an array contest, it returns a list of two elements. The first
+ element is as described, the second element is the Math::BigInt
+ representation of the netmask.
+
+ "$me->contains($other)"
+ Returns true when "$me" completely contains "$other". False is
+ returned otherwise and "undef" is returned if "$me" and "$other" are
+ not both "NetAddr::IP::Lite" objects.
+
+ "$me->within($other)"
+ The complement of "->contains()". Returns true when "$me" is
+ completely contained within "$other", undef if "$me" and "$other"
+ are not both "NetAddr::IP::Lite" objects.
+
+ "->first()"
+ Returns a new object representing the first usable IP address within
+ the subnet (ie, the first host address).
+
+ "->last()"
+ Returns a new object representing the last usable IP address within
+ the subnet (ie, one less than the broadcast address).
+
+ "->nth($index)"
+ Returns a new object representing the *n*-th usable IP address
+ within the subnet (ie, the *n*-th host address). If no address is
+ available (for example, when the network is too small for "$index"
+ hosts), "undef" is returned.
+
+ Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite
+ implements "->nth($index)" and "->num()" exactly as the
+ documentation states. Previous versions behaved slightly differently
+ and not in a consistent manner.
+
+ To use the old behavior for "->nth($index)" and "->num()":
+
+ use NetAddr::IP::Lite qw(:old_nth);
+
+ old behavior:
+ NetAddr::IP->new('10/32')->nth(0) == undef
+ NetAddr::IP->new('10/32')->nth(1) == undef
+ NetAddr::IP->new('10/31')->nth(0) == undef
+ NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/31
+ NetAddr::IP->new('10/30')->nth(0) == undef
+ NetAddr::IP->new('10/30')->nth(1) == 10.0.0.1/30
+ NetAddr::IP->new('10/30')->nth(2) == 10.0.0.2/30
+ NetAddr::IP->new('10/30')->nth(3) == 10.0.0.3/30
+
+ Note that in each case, the broadcast address is represented in the
+ output set and that the 'zero'th index is alway undef except for a
+ point-to-point /31 or /127 network where there are exactly two
+ addresses in the network.
+
+ new behavior:
+ NetAddr::IP->new('10/32')->nth(0) == 10.0.0.0/32
+ NetAddr::IP->new('10.1/32'->nth(0) == 10.0.0.1/32
+ NetAddr::IP->new('10/31')->nth(0) == 10.0.0.0/32
+ NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/32
+ NetAddr::IP->new('10/30')->nth(0) == 10.0.0.1/30
+ NetAddr::IP->new('10/30')->nth(1) == 10.0.0.2/30
+ NetAddr::IP->new('10/30')->nth(2) == undef
+
+ Note that a /32 net always has 1 usable address while a /31 has
+ exactly two usable addresses for point-to-point addressing. The
+ first index (0) returns the address immediately following the
+ network address except for a /31 or /127 when it return the network
+ address.
+
+ "->num()"
+ As of version 4.42 of NetAddr::IP and version 1.27 of
+ NetAddr::IP::Lite a /31 and /127 with return a net num value of 2
+ instead of 0 (zero) for point-to-point networks.
+
+ Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite
+ return the number of usable IP addresses within the subnet, not
+ counting the broadcast or network address.
+
+ Previous versions worked only for ipV4 addresses, returned a maximum
+ span of 2**32 and returned the number of IP addresses not counting
+ the broadcast address. (one greater than the new behavior)
+
+ To use the old behavior for "->nth($index)" and "->num()":
+
+ use NetAddr::IP::Lite qw(:old_nth);
+
+ WARNING:
+
+ NetAddr::IP will calculate and return a numeric string for network
+ ranges as large as 2**128. These values are TEXT strings and perl
+ can treat them as integers for numeric calculations.
+
+ Perl on 32 bit platforms only handles integer numbers up to 2**32
+ and on 64 bit platforms to 2**64.
+
+ If you wish to manipulate numeric strings returned by NetAddr::IP
+ that are larger than 2**32 or 2**64, respectively, you must load
+ additional modules such as Math::BigInt, bignum or some similar
+ package to do the integer math.
+
+EXPORT_OK
+ Zeros
+ Ones
+ V4mask
+ V4net
+ :aton DEPRECATED
+ :old_nth
+ :upper
+ :lower
+
+AUTHORS
+ Luis E. Muñoz <luismunoz@cpan.org>, Michael Robinton
+ <michael@bizsystems.com>
+
+WARRANTY
+ This software comes with the same warranty as perl itself (ie, none), so
+ by using it you accept any and all the liability.
+
+COPYRIGHT
+ This software is (c) Luis E. Muñoz, 1999 - 2005
+ and (c) Michael Robinton, 2006 - 2011.
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of either:
+
+ a) the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any
+ later version, or
+
+ b) the "Artistic License" which comes with this distribution.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
+ General Public License or the Artistic License for more details.
+
+ You should have received a copy of the Artistic License with this
+ distribution, in the file named "Artistic". If not, I'll be glad to
+ provide one.
+
+ You should also have received a copy of the GNU General Public License
+ along with this program in the file named "Copying". If not, write to
+ the
+
+ Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330
+ Boston, MA 02111-1307, USA
+
+ or visit their web page on the internet at:
+
+ http://www.gnu.org/copyleft/gpl.html.
+
+SEE ALSO
+ NetAddr::IP(3), NetAddr::IP::Util(3), NetAddr::IP::InetBase(3)
+
--- /dev/null
+1.46 Fri Nov 11 19:23:11 PST 2011
+ update documentation in InetBase v0.06
+
+1.45 Fri Nov 11 13:20:32 PST 2011
+ break out the code in InetBase v0.05 that expands short IPv4
+ addresses into dotquad format to account for broken BSD
+ implementations of inet_aton and gethostbyname that do
+ not recognize the short format. EXPORT this as sub 'fillIPv4'
+
+ in Util.pm, add 'fillIPv4' to calls to gethostbyname to
+ work around broken inet_aton and gethostbyname implementations
+ in certain BSD implementations
+
+1.44 Wed Nov 2 19:15:31 PDT 2011
+ improve inet_aton in InetBase v0.04 to overcome broken
+ gethostbyname found in NetBSD and OpenBSD
+
+1.43 Mon Oct 24 13:25:09 PDT 2011
+ remove reference to Config{osname} in InetBase.pm v0.03
+
+1.42 Fri Oct 21 10:34:46 PDT 2011
+ Socket6 prior to version 0.23 does not have AF_INET6 in the
+ EXPORT_OK array, modify InetBase.pm v0.02 to work around this.
+
+1.41 Sat Oct 15 17:26:21 PDT 2011
+ add inet_pton, inet_ntop, AF_INET, AF_INET6
+
+ modify inet_n2dx and inet_n2ad to
+ recognize the new 128 bit IPv4 format
+ ::FFFF:FFFF:0:0
+
+ replace isIPv4 with a pure perl version for portablity
+
+ split the following into NetAddr::IP::InetBase v0.01
+ to provide better long term support for IPv6
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ inet_n2dx
+ inet_n2ad
+ inet_ntop
+ inet_pton
+ packzeros
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ AF_INET
+ AF_INET6
+
+1.40 Sat Oct 8 01:33:44 PDT 2011
+ remove debug print statement from Util.pm
+
+1.39 Thu Oct 6 23:41:42 PDT 2011
+ really correct missing internal reference
+
+1.38 Thu Oct 6 20:20:33 PDT 2011
+ corrected missing internal reference to inet_4map6
+
+1.37 Thu Oct 6 18:23:04 PDT 2011
+ addid isAnyIPv4, isNewIPv4, inet_4map6
+ revised naip_gethostbyname
+ to conform to Perl's gethostbyname output
+
+1.36 Sat Feb 19 10:04:00 PST 2011
+ correction to use of package lexicals
+
+ thanks to mishikal@yahoo.com for spotting the bug and to
+ Mark Martinec mark.martinec+ama...@ijs.si for the solution.
+
+1.35 Tue Nov 16 16:28:37 PST 2010
+ naip_gethostbyname modified to return undef instead of
+ 0 (zero) on failure
+
+ thanks to Terry Cassidy enaudishaylee@tc17.com for the bug report
+
+ move sub's ipv6_n2d and ipv6_n2x to non-autosplit portion
+ of module to eliminate warnings during autosplit of "our" variables
+
+ thanks to Nicholas Bamber <nicholas@periapt.co.uk>
+ Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=517361
+
+1.34 Wed Sep 29 10:32:50 PDT 2010
+ Conditionalize import of AF_INET6 in Util.pm
+ NetAddr::IP::UtilPolluted
+
+1.33 Tue Sep 21 17:50:50 PDT 2010
+ Add UtilPolluted namespace to contain name space pollution
+ created by "use Socket" when invoking Socket6.
+
+1.32 Wed May 12 14:18:20 PDT 2010
+ In Util.xs,
+ changed netswap() to postincrement
+ *a++ = to *a and added increment after save to mollify some
+ picky compilers that return possible undefined behavior.
+
+ changed type of _128x10 to 'void'
+
+1.31 Tue Jun 9 10:31:11 PDT 2009
+ ferret out shell value for Makefile.PL when calling
+ ./configure for systems where the 'x' bit gets lost
+ due to bug in Archive::Tar
+
+1.30 Sat Mar 7 16:35:33 PST 2009
+ make the compiler test check the environment for
+ CC before using Perl's default compiler
+
+1.29 Sat Mar 7 16:15:18 PST 2009
+ revised compiler test in Makefile.PL for Util v1.29
+ to accomodate picky Solaris "cc"
+
+1.28 Wed Dec 17 14:14:06 PST 2008
+ set uninitialized "carry" in XS bin2bcd to zero
+
+1.27 Tue Dec 9 12:00:08 PST 2008
+ revised UtilPP v1.7 to work around perl 5.8.4
+ failures with certain @_ operations of goto &sub...
+ see perl bug [ 23429]. Unfortunately, perl-5.8.4 is
+ the distribution of choice for many solaris boxes
+
+1.26 Fri Nov 28 23:19:01 PST 2008
+ revised XS code to be full re-entrant... thread safe.
+ removed all traces of mutex locks
+ removed function 'threads' here an in UtilPP v1.6
+
+1.25 Tue Nov 18 19:08:56 PST 2008
+ correct documentation error in Util_PP v1.5
+
+ add threads reporting to Util.xs and UtilPP
+
+ added what is hopefully thread safe operation via
+ serialization. Must be invoked by "--with-threads"
+
+1.24 Wed Nov 5 18:13:20 PST 2008
+ Clean up Makefile.PL to check actual required link
+ libraries against the perl build for consistency
+
+1.23 Sun Nov 2 10:10:38 PST 2008
+ add missing headers in configure and localconf.h for Solaris inet_xton
+ thanks to Karl Bunch <karl@digilink.net> for spotting the bug.
+
+1.22 Wed Oct 22 14:54:12 PDT 2008
+ eliminated dependence on PL_sawampersand
+ thanks to Mark Martinec <Mark.Martinec@ijs.si>
+ for spotting this and submitting a patch.
+
+ force -noxs mode for Win32
+
+ use autoconf to configure 'C' build
+
+1.21 Thu Oct 16 19:35:33 PDT 2008
+ again... clear build bug for Win32
+ and lets get the version number right since it appears
+ that it was up-rev'd at some point to 1.xx
+
+0.20 Mon Oct 6 13:07:34 PDT 2008
+ clear build bug for Win32
+
+0.19 Sat Sep 27 13:36:58 PDT 2008
+ updated test for ENDIANess in siteconf
+
+ add test in inet_aton to detect overange IP dot quad values
+ missed by some broken Socket implementations
+ i.e. 256.1.1.1
+
+0.18 Sun Aug 6 10:48:25 PDT 2006
+ correct shiftleft documentation
+ correct mask4to6 documentation
+
+0.17 Thu Jul 6 10:46:48 PDT 2006
+ update 'siteconf line 1608' to fix empty variable in inet_aton test
+ update 'siteconf line 1636' to fix empty variable in inet_pton test
+ add missing colon at t/notcontiguous.t line 66
+
+0.16 Sun Jun 25 16:13:00 PDT 2006
+ fixed ->new() issues with long digit strings ->new('::fffff')
+ and non hex digits ->new('::foo').
+ Thanks to Radoslaw Zielinski <radek42@gmail.com>
+ for spotting those bugs
+
+0.15 Tue Jun 13 14:42:34 PDT 2006
+ UtilPP.pm v0.07 & Util.xs 'shiftleft' so that the original
+ argument is returned when the shift count is '0' or missing
+
+0.14 Tue Jun 6 08:37:01 PDT 2006
+ add logic to check LIBS => [-lfiles]
+ individually. ExtUtils::xxx does a bad job and
+ leaves libs that do not exist in the list
+ which causes 'siteconf' to blow up on missing libs
+ on perl 5.053 (and probably others)
+
+0.13 Tue Jun 6 08:33:11 PDT 2006
+ added to xs file, 'hopefully' to allow build on windoze platforms
+
+0.12 Tue Jun 6 08:21:12 PDT 2006
+ add logic to makefile so 'siteconfig' and C libs
+ are not used in PurePerl mode
+
+0.11 Mon Jun 5 14:45:09 PDT 2006
+ fix Sparc problems
+ 1) add workaround for OS's that do not have inet_aton
+
+ 2) add workaround for compilers that do not understand
+ #if MACRO1 == MACRO2
+
+0.10 Sat Jun 3 19:07:51 PDT 2006
+ add site configuration to supply u_intxx_t vars
+ for Sun OS and others that don't have them
+
+0.09 Sun May 7 18:06:43 PDT 2006
+ UtilPP.pm v0.06, removed unnecessary pack(unpack) sequences
+ to speed up ipv4->6, ipv6->4 conversions
+
+0.08 Wed Apr 26 18:33:12 PDT 2006
+ correct documentation error
+ add ipv6to4
+
+0.07 Sun Apr 23 16:11:56 PDT 2006
+ correct reporting error in UtilPP v0.04 for
+ incorrect argument length in ipv4 -> 6 conversions
+
+ add conditional netaddr conversion functions
+ ipanyto6, maskanyto6 to Util.xs and UtilPP v0.05
+
+0.06 Tue Apr 18 16:50:53 PDT 2006
+ add ipv4to6, mask4to6 to Util.pm and UtilPP.pm v0.03
+
+0.05 Sat Apr 15 15:48:17 PDT 2006
+ Fixed some typo's in Makefile.PL that
+ failed to update README during build
+
+0.04 Wed Apr 12 15:43:33 PDT 2006
+ add Util_IS.pm to guarantee that the XS lib is not
+ loaded if a previous incarnation of the same version
+ has previously been installed on the system and the
+ module is built with -noxs
+
+0.03 Tue Apr 4 21:55:35 PDT 2006
+ update minisocket to perl-5.9.3, add header
+ file for backwards compatibility
+
+ add function 'notcontiguous' to return cidr size
+ and check for spurious bits in the network mask
+
+0.02 Fri Mar 31 12:44:15 PST 2006
+ added test for illegal characters to ipv6_aton
+
+ added UtilPP for Pure Perl functionality for the
+ WinTel folks that don't have gcc on their systems
+
+0.01 Tue Mar 28 16:42:44 PST 2006
+ initial release
+
--- /dev/null
+Changes
+MANIFEST This list of files
+MANIFEST.SKIP
+Makefile.PL
+README
+Util.pm
+Util.xs
+config.h.in
+configure
+configure.ac
+lib/NetAddr/IP/InetBase.pm
+lib/NetAddr/IP/UtilPP.pm
+localconf.h
+t/4to6.t
+t/add128.t
+t/addconst.t
+t/af_inet6.t
+t/anyto6.t
+t/badd.t
+t/bcd2bin.t
+t/bcdn2bin.t
+t/bin.t
+t/binet_n2ad.t
+t/binet_n2dx.t
+t/binet_pton.t
+t/bipv4_inet.t
+t/binet_ntoa.t
+t/bipv6_any2n.t
+t/bipv6func.t
+t/bisIPv4.t
+t/bpackzeros.t
+t/comp128.t
+t/croak.t
+t/hasbits.t
+t/inet_4map6.t
+t/inet_n2ad.t
+t/inet_n2dx.t
+t/inet_pton.t
+t/ipv4_inet.t
+t/ipv6_ntoa.t
+t/ipv6_any2n.t
+t/ipv6func.t
+t/ipv6to4.t
+t/isIPv4.t
+t/leftshift.t
+t/mode.t
+t/notcontiguous.t
+t/packzeros.t
+t/simple_pack.t
+t/sub128.t
+t/naip_gethostbyname.t
+t/no6_naip_gethostbyname.t
+typemap
--- /dev/null
+^Build$
+^_build/
+^blib/
+^blibdirs
+Makefile$
+Makefile\.[a-z]+$
+pm_to_blib
+CVS/.*
+\.cvs
+,v$
+^tmp/
+\.old$
+\.bak$
+\.tmp$
+\.xsc$
+~$
+^#
+\.shar$
+\.tar$
+\.tgz$
+\.tar\.gz$
+\.zip$
+_uu$
+Util\.(bs|[co])$
+localStuff\.h$
+config\.log$
+config\.h$
+config\.status
+localperl\.h
+tlib/NetAddr/IP/Util_IS.pm
+Util_IS.pm
--- /dev/null
+use ExtUtils::MakeMaker qw(
+ WriteMakefile
+ prompt
+);
+use Config;
+use Cwd;
+use Getopt::Long qw(
+ GetOptions
+);
+
+my $pwd = getcwd();
+
+unlink 'Makefile'; # remove Makefile to stabilize CC test
+
+#
+# get any command line arguments
+#
+my($useXS);
+GetOptions(
+ 'xs!' => \$useXS,
+ 'pm' => sub {
+ warn "\n\t".'WARNING: Use of "--pm" is deprecated, use "-noxs" instead'."\n\n";
+ $useXS = 0;
+ },
+);
+
+if ($^O eq 'MSWin32') {
+ $useXS = 0; # force NOXS mode for windows
+}
+
+my $pkg = 'NetAddr::IP::Util';
+$pkg =~ /[^:]+$/;
+my $module = $& .'.pm';
+my $cfile = $& .'.c';
+
+my %makeparms = (
+ NAME => $pkg,
+ VERSION_FROM => $module, # finds $VERSION
+# depend => {$cfile => q[xs_include/miniSocket.inc localconf.h config.h localperl.h],
+ depend => {$cfile => q[ localconf.h config.h localperl.h ],
+ },
+# PREREQ_PM => { Socket6 => 0.23, can't do this
+# },
+ LIBS => [],
+ XS => {},
+ C => [],
+ clean => { FILES => "*.bs *.o *.c *~ tmp* Util_IS.pm localperl.h auto*"},
+ realclean => { FILES => "config.h config.log config.status"},
+ dist => {COMPRESS=>'gzip', SUFFIX=>'gz'}
+
+);
+
+#
+# Check if we have a C compiler
+
+unless (defined $useXS) {
+ if (test_cc()) {
+ print "You have a working compiler.\n";
+ $useXS = 1;
+# $makeparms{'MYEXTLIB'} = 'netdns$(LIB_EXT)',
+
+ } else {
+ $useXS = 0;
+ print <<END;
+
+I cannot determine if you have a C compiler. I will install the
+perl-only implementation.
+
+You can force installation of the XS version with:
+
+ perl Makefile.PL --xs
+END
+
+# $makeparms{'MYEXTLIB'} = '',
+ }
+}
+
+my $begin = '';
+
+if ($useXS) {
+ # turn the XS bits on.
+ delete $makeparms{'XS'};
+ delete $makeparms{'C'};
+
+ unless (-e './config.h') {
+ system $Config{sh}, 'configure';
+ }
+ my @LIBS;
+ open(F,'config.h') or die "could not open config.h\n";
+ foreach(<F>) {
+ if ($_ =~ /^#define LIBS([ a-zA-Z-]+)/) {
+ @LIBS = ($1 =~ /[a-zA-Z0-9-]+/g);
+
+ $makeparms{LIBS} = [$1];
+ last;
+ }
+ }
+ close F;
+ my $link = '';
+ foreach(@libs) {
+ if ($Config{libs} =~ /$_\b/) {
+ $link .= $_ .' ';
+ }
+ }
+ chop $link;
+ $makeparms{LIBS} = [$link];
+
+ open(F,'>localperl.h') or die "could not open localperl.h for write\n";
+ print F q|
+/* Written by Makefile.PL
+ *
+ * Do not modify this file, modify Makefile.PL instead
+ *
+ */
+|;
+ close F;
+
+ $begin = q|
+config :: config.h
+ @$(NOOP)
+
+config.h :
+ $(SHELL) configure
+|;
+}
+
+open(F,'>Util_IS.pm');
+print F q|#!/usr/bin/perl
+#
+# DO NOT ALTER THIS FILE
+# IT IS WRITTEN BY Makefile.PL
+# EDIT THAT INSTEAD
+#
+package NetAddr::IP::Util_IS;
+use vars qw($VERSION);
+$VERSION = 1.00;
+
+
+sub pure {
+ return |, (($useXS) ? 0 : 1), q|;
+}
+sub not_pure {
+ return |, (($useXS) ? 1 : 0), q|;
+}
+1;
+__END__
+
+=head1 NAME
+
+NetAddr::IP::Util_IS - Tell about Pure Perl
+
+=head1 SYNOPSIS
+
+ use NetAddr::IP::Util_IS;
+
+ $rv = NetAddr::IP::Util_IS->pure;
+ $rv = NetAddr::IP::Util_IS->not_pure;
+
+=head1 DESCRIPTION
+
+Util_IS indicates whether or not B<NetAddr::IP::Util> was compiled in Pure
+Perl mode.
+
+=over 4
+
+=item * $rv = NetAddr::IP::Util_IS->pure;
+
+Returns true if PurePerl mode, else false.
+
+=item * $rv = NetAddr::IP::Util_IS->not_pure;
+
+Returns true if NOT PurePerl mode, else false
+
+=back
+
+=cut
+
+1;
+|;
+
+sub test_cc {
+ #
+ # The perl/C check borrowed and modified from
+ # Graham Barr's Scalar-List-Utils distribution.
+ #
+ print "Testing if you have a C compiler and the needed header files....\n";
+
+ unless (open(F, ">compile.c")) {
+ warn "Cannot write compile.c, skipping test compilation and installing pure Perl version.\n";
+ return;
+ }
+
+ my $CC = $ENV{CC} || $Config{ccname};
+ my $command = qq|$CC compile.c -o compile.output|;
+
+ print F <<'EOF';
+int main() { return 0; }
+EOF
+
+ close(F) or return;
+
+ print STDERR $command,"\n";
+
+ my $rv = system($command);
+
+ foreach my $file (glob('compile*')) {
+ unlink($file) || warn "Could not delete $file: $!\n";
+ }
+
+ return ($rv == 0);
+}
+
+sub MY::top_targets {
+ package MY;
+ my $inherited = shift->SUPER::top_targets(@_);
+ $inherited =~ s/(pure_all\s+::.+)/$1 README/;
+ $begin . $inherited;
+}
+
+sub MY::post_constants {
+ my $post_constants = q|
+MY_POD2TEXT = |. $Config{scriptdirexp} .'/pod2text' .q|
+|;
+}
+
+sub MY::postamble {
+ package MY;
+ my $postamble = q|
+README : |. $module .q|
+ @$(MY_POD2TEXT) |. $module .q| > README
+
+|;
+}
+
+WriteMakefile(%makeparms);
--- /dev/null
+NAME
+ NetAddr::IP::Util -- IPv4/6 and 128 bit number utilities
+
+SYNOPSIS
+ use NetAddr::IP::Util qw(
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_ntoa
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ hasbits
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ inet_n2dx
+ inet_n2ad
+ inet_pton
+ inet_ntop
+ inet_4map6
+ ipv4to6
+ mask4to6
+ ipanyto6
+ maskanyto6
+ ipv6to4
+ packzeros
+ shiftleft
+ addconst
+ add128
+ sub128
+ notcontiguous
+ bin2bcd
+ bcd2bin
+ mode
+ AF_INET
+ AF_INET6
+ naip_gethostbyname
+ );
+
+ use NetAddr::IP::Util qw(:all :inet :ipv4 :ipv6 :math)
+
+ :inet => inet_aton, inet_ntoa, ipv6_aton
+ ipv6_ntoa, ipv6_n2x, ipv6_n2d,
+ inet_any2n, inet_n2dx, inet_n2ad,
+ inet_pton, inet_ntop, inet_4map6,
+ ipv4to6, mask4to6, ipanyto6, packzeros
+ maskanyto6, ipv6to4, naip_gethostbyname
+
+ :ipv4 => inet_aton, inet_ntoa
+
+ :ipv6 => ipv6_aton, ipv6_ntoa, ipv6_n2x,
+ ipv6_n2d, inet_any2n, inet_n2dx,
+ inet_n2ad, inet_pton, inet_ntop,
+ inet_4map6, ipv4to6, mask4to6,
+ ipanyto6, maskanyto6, ipv6to4,
+ packzeros, naip_gethostbyname
+
+ :math => hasbits, isIPv4, isNewIPv4, isAnyIPv4,
+ addconst, add128, sub128, notcontiguous,
+ bin2bcd, bcd2bin, shiftleft
+
+ $dotquad = inet_ntoa($netaddr);
+ $netaddr = inet_aton($dotquad);
+ $ipv6naddr = ipv6_aton($ipv6_text);
+ $ipv6_text = ipvt_ntoa($ipv6naddr);
+ $hex_text = ipv6_n2x($ipv6naddr);
+ $dec_text = ipv6_n2d($ipv6naddr);
+ $hex_text = packzeros($hex_text);
+ $ipv6naddr = inet_any2n($dotquad or $ipv6_text);
+ $ipv6naddr = inet_4map6($netaddr or $ipv6naddr);
+ $rv = hasbits($bits128);
+ $rv = isIPv4($bits128);
+ $rv = isNewIPv4($bits128);
+ $rv = isAnyIPv4($bits128);
+ $dotquad or $hex_text = inet_n2dx($ipv6naddr);
+ $dotquad or $dec_text = inet_n2ad($ipv6naddr);
+ $netaddr = inet_pton($AF_family,$hex_text);
+ $hex_text = inet_ntop($AF_family,$netaddr);
+ $ipv6naddr = ipv4to6($netaddr);
+ $ipv6naddr = mask4to6($netaddr);
+ $ipv6naddr = ipanyto6($netaddr);
+ $ipv6naddr = maskanyto6($netaddr);
+ $netaddr = ipv6to4($pv6naddr);
+ $bitsX2 = shiftleft($bits128,$n);
+ $carry = addconst($ipv6naddr,$signed_32con);
+ ($carry,$ipv6naddr)=addconst($ipv6naddr,$signed_32con);
+ $carry = add128($ipv6naddr1,$ipv6naddr2);
+ ($carry,$ipv6naddr)=add128($ipv6naddr1,$ipv6naddr2);
+ $carry = sub128($ipv6naddr1,$ipv6naddr2);
+ ($carry,$ipv6naddr)=sub128($ipv6naddr1,$ipv6naddr2);
+ ($spurious,$cidr) = notcontiguous($mask128);
+ $bcdtext = bin2bcd($bits128);
+ $bits128 = bcd2bin($bcdtxt);
+ $modetext = mode;
+ ($name,$aliases,$addrtype,$length,@addrs)=naip_gethostbyname(NAME);
+ $trueif = havegethostbyname2();
+
+ NetAddr::IP::Util::lower();
+ NetAddr::IP::Util::upper();
+
+INSTALLATION
+ Un-tar the distribution in an appropriate directory and type:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+ NetAddr::IP::Util installs by default with its primary functions
+ compiled using Perl's XS extensions to build a 'C' library. If you do
+ not have a 'C' complier available or would like the slower Pure Perl
+ version for some other reason, then type:
+
+ perl Makefile.PL -noxs
+ make
+ make test
+ make install
+
+DESCRIPTION
+ NetAddr::IP::Util provides a suite of tools for manipulating and
+ converting IPv4 and IPv6 addresses into 128 bit string context and back
+ to text. The strings can be manipulated with Perl's logical operators:
+
+ and &
+ or |
+ xor ^
+ ~ compliment
+
+ in the same manner as 'vec' strings.
+
+ The IPv6 functions support all rfc1884 formats.
+
+ i.e. x:x:x:x:x:x:x:x:x
+ x:x:x:x:x:x:x:d.d.d.d
+ ::x:x:x
+ ::x:d.d.d.d
+ and so on...
+
+ * $dotquad = inet_ntoa($netaddr);
+ Convert a packed IPv4 network address to a dot-quad IP address.
+
+ input: packed network address
+ returns: IP address i.e. 10.4.12.123
+
+ * $netaddr = inet_aton($dotquad);
+ Convert a dot-quad IP address into an IPv4 packed network address.
+
+ input: IP address i.e. 192.5.16.32
+ returns: packed network address
+
+ * $ipv6addr = ipv6_aton($ipv6_text);
+ Takes an IPv6 address of the form described in rfc1884 and returns a
+ 128 bit binary RDATA string.
+
+ input: ipv6 text
+ returns: 128 bit RDATA string
+
+ * $ipv6_text = ipv6_ntoa($ipv6naddr);
+ Convert a 128 bit binary IPv6 address to compressed rfc 1884 text
+ representation.
+
+ input: 128 bit RDATA string
+ returns: ipv6 text
+
+ * $hex_text = ipv6_n2x($ipv6addr);
+ Takes an IPv6 RDATA string and returns an 8 segment IPv6 hex address
+
+ input: 128 bit RDATA string
+ returns: x:x:x:x:x:x:x:x
+
+ * $dec_text = ipv6_n2d($ipv6addr);
+ Takes an IPv6 RDATA string and returns a mixed hex - decimal IPv6
+ address with the 6 uppermost chunks in hex and the lower 32 bits in
+ dot-quad representation.
+
+ input: 128 bit RDATA string
+ returns: x:x:x:x:x:x:d.d.d.d
+
+ * $ipv6naddr = inet_any2n($dotquad or $ipv6_text);
+ This function converts a text IPv4 or IPv6 address in text format in
+ any standard notation into a 128 bit IPv6 string address. It
+ prefixes any dot-quad address (if found) with '::' and passes it to
+ ipv6_aton.
+
+ input: dot-quad or rfc1844 address
+ returns: 128 bit IPv6 string
+
+ * $rv = hasbits($bits128);
+ This function returns true if there are one's present in the 128 bit
+ string and false if all the bits are zero.
+
+ i.e. if (hasbits($bits128)) {
+ &do_something;
+ }
+
+ or if (hasbits($bits128 & $mask128) {
+ &do_something;
+ }
+
+ This allows the implementation of logical functions of the form of:
+
+ if ($bits128 & $mask128) {
+ ...
+
+ input: 128 bit IPv6 string
+ returns: true if any bits are present
+
+ * $ipv6naddr = inet_4map6($netaddr or $ipv6naddr
+ This function returns an ipV6 network address with the first 80 bits
+ set to zero and the next 16 bits set to one, while the last 32 bits
+ are filled with the ipV4 address.
+
+ input: ipV4 netaddr
+ or ipV6 netaddr
+ returns: ipV6 netaddr
+
+ returns: undef on error
+
+ An ipV6 network address must be in one of the two compatible ipV4
+ mapped address spaces. i.e.
+
+ ::ffff::d.d.d.d or ::d.d.d.d
+
+ * $rv = isIPv4($bits128);
+ This function returns true if there are no on bits present in the
+ IPv6 portion of the 128 bit string and false otherwise.
+
+ i.e. the address must be of the form - ::d.d.d.d
+
+ Note: this is an old and deprecated ipV4 compatible ipV6 address
+
+ * $rv = isNewIPv4($bits128);
+ This function return true if the IPv6 128 bit string is of the form
+
+ ::ffff::d.d.d.d
+
+ * $rv = isAnyIPv4($bits128);
+ This function return true if the IPv6 bit string is of the form
+
+ ::d.d.d.d or ::ffff::d.d.d.d
+
+ * $dotquad or $hex_text = inet_n2dx($ipv6naddr);
+ This function does the right thing and returns the text for either a
+ dot-quad IPv4 or a hex notation IPv6 address.
+
+ input: 128 bit IPv6 string
+ returns: ddd.ddd.ddd.ddd
+ or x:x:x:x:x:x:x:x
+
+ * $dotquad or $dec_text = inet_n2ad($ipv6naddr);
+ This function does the right thing and returns the text for either a
+ dot-quad IPv4 or a hex::decimal notation IPv6 address.
+
+ input: 128 bit IPv6 string
+ returns: ddd.ddd.ddd.ddd
+ or x:x:x:x:x:x:ddd.ddd.ddd.dd
+
+ * $netaddr = inet_pton($AF_family,$hex_text);
+ This function takes an IP address in IPv4 or IPv6 text format and
+ converts it into binary format. The type of IP address conversion is
+ controlled by the FAMILY argument.
+
+ * $hex_text = inet_ntop($AF_family,$netaddr);
+ This function takes and IP address in binary format and converts it
+ into text format. The type of IP address conversion is controlled by
+ the FAMILY argument.
+
+ NOTE: inet_ntop ALWAYS returns lowercase characters.
+
+ * $hex_text = packzeros($hex_text);
+ This function optimizes and rfc 1884 IPv6 hex address to reduce the
+ number of long strings of zero bits as specified in rfc 1884, 2.2
+ (2) by substituting :: for the first occurence of the longest string
+ of zeros in the address.
+
+ * $ipv6naddr = ipv4to6($netaddr);
+ Convert an ipv4 network address into an IPv6 network address.
+
+ input: 32 bit network address
+ returns: 128 bit network address
+
+ * $ipv6naddr = mask4to6($netaddr);
+ Convert an ipv4 network address/mask into an ipv6 network mask.
+
+ input: 32 bit network/mask address
+ returns: 128 bit network/mask address
+
+ NOTE: returns the high 96 bits as one's
+
+ * $ipv6naddr = ipanyto6($netaddr);
+ Similar to ipv4to6 except that this function takes either an IPv4 or
+ IPv6 input and always returns a 128 bit IPv6 network address.
+
+ input: 32 or 128 bit network address
+ returns: 128 bit network address
+
+ * $ipv6naddr = maskanyto6($netaddr);
+ Similar to mask4to6 except that this function takes either an IPv4
+ or IPv6 netmask and always returns a 128 bit IPv6 netmask.
+
+ input: 32 or 128 bit network mask
+ returns: 128 bit network mask
+
+ * $netaddr = ipv6to4($pv6naddr);
+ Truncate the upper 96 bits of a 128 bit address and return the lower
+ 32 bits. Returns an IPv4 address as returned by inet_aton.
+
+ input: 128 bit network address
+ returns: 32 bit inet_aton network address
+
+ * $bitsXn = shiftleft($bits128,$n);
+ input: 128 bit string variable,
+ number of shifts [optional]
+ returns: bits X n shifts
+
+ NOTE: a single shift is performed
+ if $n is not specified
+
+ * addconst($ipv6naddr,$signed_32con);
+ Add a signed constant to a 128 bit string variable.
+
+ input: 128 bit IPv6 string,
+ signed 32 bit integer
+ returns: scalar carry
+ array (carry, result)
+
+ * add128($ipv6naddr1,$ipv6naddr2);
+ Add two 128 bit string variables.
+
+ input: 128 bit string var1,
+ 128 bit string var2
+ returns: scalar carry
+ array (carry, result)
+
+ * sub128($ipv6naddr1,$ipv6naddr2);
+ Subtract two 128 bit string variables.
+
+ input: 128 bit string var1,
+ 128 bit string var2
+ returns: scalar carry
+ array (carry, result)
+
+ Note: The carry from this operation is the result of adding the
+ one's complement of ARG2 +1 to the ARG1. It is logically NOT borrow.
+
+ i.e. if ARG1 >= ARG2 then carry = 1
+ or if ARG1 < ARG2 then carry = 0
+
+ * ($spurious,$cidr) = notcontiguous($mask128);
+ This function counts the bit positions remaining in the mask when
+ the rightmost '0's are removed.
+
+ input: 128 bit netmask
+ returns true if there are spurious
+ zero bits remaining in the
+ mask, false if the mask is
+ contiguous one's,
+ 128 bit cidr number
+
+ * $bcdtext = bin2bcd($bits128);
+ Convert a 128 bit binary string into binary coded decimal text
+ digits.
+
+ input: 128 bit string variable
+ returns: string of bcd text digits
+
+ * $bits128 = bcd2bin($bcdtxt);
+ Convert a bcd text string to 128 bit string variable
+
+ input: string of bcd text digits
+ returns: 128 bit string variable
+
+ * $modetext = mode;
+ Returns the operating mode of this module.
+
+ input: none
+ returns: "Pure Perl"
+ or "CC XS"
+
+ * ($name,$aliases,$addrtype,$length,@addrs)=naip_gethostbyname(NAME);
+ Replacement for Perl's gethostbyname if Socket6 is available
+
+ In ARRAY context, returns a list of five elements, the hostname or
+ NAME, a space seperated list of C_NAMES, AF family, length of the
+ address structure, and an array of one or more netaddr's
+
+ In SCALAR context, returns the first netaddr.
+
+ This function ALWAYS returns an IPv6 address, even on IPv4 only
+ systems. IPv4 addresses are mapped into IPv6 space in the form:
+
+ ::FFFF:FFFF:d.d.d.d
+
+ This is NOT the expected result from Perl's gethostbyname2. It is
+ instead equivalent to:
+
+ On an IPv4 only system:
+ $ipv6naddr = ipv4to6 scalar ( gethostbyname( name ));
+
+ On a system with Socket6 and a working gethostbyname2:
+ $ipv6naddr = gethostbyname2( name, AF_INET6 );
+ and if that fails, the IPv4 conversion above.
+
+ For a gethostbyname2 emulator that behave like Socket6, see: the
+ Net::DNS::Dig manpage
+
+ * $trueif = havegethostbyname2();
+ This function returns TRUE if Socket6 has a functioning
+ gethostbyname2, otherwise it returns FALSE. See the comments above
+ about the behavior of naip_gethostbyname.
+
+ * NetAddr::IP::Util::lower();
+ Return IPv6 strings in lowercase.
+
+ * NetAddr::IP::Util::upper();
+ Return IPv6 strings in uppercase. This is the default.
+
+EXAMPLES
+ # convert any textual IP address into a 128 bit vector
+ #
+ sub text2vec {
+ my($anyIP,$anyMask) = @_;
+
+ # not IPv4 bit mask
+ my $notiv4 = ipv6_aton('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::');
+
+ my $vecip = inet_any2n($anyIP);
+ my $mask = inet_any2n($anyMask);
+
+ # extend mask bits for IPv4
+ my $bits = 128; # default
+ unless (hasbits($mask & $notiv4)) {
+ $mask |= $notiv4;
+ $bits = 32;
+ }
+ return ($vecip, $mask, $bits);
+ }
+
+ ... alternate implementation, a little faster
+
+ sub text2vec {
+ my($anyIP,$anyMask) = @_;
+
+ # not IPv4 bit mask
+ my $notiv4 = ipv6_aton('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::');
+
+ my $vecip = inet_any2n($anyIP);
+ my $mask = inet_any2n($anyMask);
+
+ # extend mask bits for IPv4
+ my $bits = 128; # default
+ if (isIPv4($mask)) {
+ $mask |= $notiv4;
+ $bits = 32;
+ }
+ return ($vecip, $mask, $bits);
+ }
+
+ ... elsewhere
+ $nip = {
+ addr => $vecip,
+ mask => $mask,
+ bits => $bits,
+ };
+
+ # return network and broadcast addresses from IP and Mask
+ #
+ sub netbroad {
+ my($nip) = shift;
+ my $notmask = ~ $nip->{mask};
+ my $bcast = $nip->{addr} | $notmask;
+ my $network = $nip->{addr} & $nip->{mask};
+ return ($network, $broadcast);
+ }
+
+ # check if address is within a network
+ #
+ sub within {
+ my($nip,$net) = @_;
+ my $addr = $nip->{addr}
+ my($nw,$bc) = netbroad($net);
+ # arg1 >= arg2, sub128 returns true
+ return (sub128($addr,$nw) && sub128($bc,$addr))
+ ? 1 : 0;
+ }
+
+ # truely hard way to do $ip++
+ # add a constant, wrapping at netblock boundaries
+ # to subtract the constant, negate it before calling
+ # 'addwrap' since 'addconst' will extend the sign bits
+ #
+ sub addwrap {
+ my($nip,$const) = @_;
+ my $addr = $nip->{addr};
+ my $mask = $nip->{mask};
+ my $bits = $nip->{bits};
+ my $notmask = ~ $mask;
+ my $hibits = $addr & $mask;
+ $addr = addconst($addr,$const);
+ my $wraponly = $addr & $notmask;
+ my $newip = {
+ addr => $hibits | $wraponly,
+ mask => $mask,
+ bits => $bits,
+ };
+ # bless $newip as appropriate
+ return $newip;
+ }
+
+ # something more useful
+ # increment a /24 net to the NEXT net at the boundry
+
+ my $nextnet = 256; # for /24
+ LOOP:
+ while (...continuing) {
+ your code....
+ ...
+ my $lastip = $ip-copy();
+ $ip++;
+ if ($ip < $lastip) { # host part wrapped?
+ # discard carry
+ (undef, $ip->{addr} = addconst($ip->{addr}, $nextnet);
+ }
+ next LOOP;
+ }
+
+EXPORT_OK
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_ntoa
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ hasbits
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ inet_n2dx
+ inet_n2ad
+ inet_pton
+ inet_ntop
+ inet_4map6
+ ipv4to6
+ mask4to6
+ ipanyto6
+ maskanyto6
+ ipv6to4
+ packzeros
+ shiftleft
+ addconst
+ add128
+ sub128
+ notcontiguous
+ bin2bcd
+ bcd2bin
+ mode
+ naip_gethostbyname
+ havegethostbyname2
+
+AUTHOR
+ Michael Robinton <michael@bizsystems.com>
+
+COPYRIGHT
+ Copyright 2003 - 2011, Michael Robinton <michael@bizsystems.com>
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of either:
+
+ a) the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any
+ later version, or
+
+ b) the "Artistic License" which comes with this distribution.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
+ General Public License or the Artistic License for more details.
+
+ You should have received a copy of the Artistic License with this
+ distribution, in the file named "Artistic". If not, I'll be glad to
+ provide one.
+
+ You should also have received a copy of the GNU General Public License
+ along with this program in the file named "Copying". If not, write to
+ the
+
+ Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330
+ Boston, MA 02111-1307, USA
+
+ or visit their web page on the internet at:
+
+ http://www.gnu.org/copyleft/gpl.html.
+
+AUTHOR
+ Michael Robinton <michael@bizsystems.com>
+
+SEE ALSO
+ NetAddr::IP(3), NetAddr::IP::Lite(3), NetAddr::IP::InetBase(3)
+
--- /dev/null
+#!/usr/bin/perl
+package NetAddr::IP::Util;
+
+use strict;
+#use diagnostics;
+#use lib qw(blib/lib);
+
+use vars qw($VERSION @EXPORT_OK @ISA %EXPORT_TAGS $Mode);
+use AutoLoader qw(AUTOLOAD);
+use NetAddr::IP::Util_IS;
+use NetAddr::IP::InetBase qw(
+ :upper
+ :all
+);
+
+*NetAddr::IP::Util::upper = \&NetAddr::IP::InetBase::upper;
+*NetAddr::IP::Util::lower = \&NetAddr::IP::InetBase::lower;
+
+require DynaLoader;
+require Exporter;
+
+@ISA = qw(Exporter DynaLoader);
+
+$VERSION = do { my @r = (q$Revision: 1.46 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
+
+@EXPORT_OK = qw(
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_ntoa
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ hasbits
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ inet_n2dx
+ inet_n2ad
+ inet_pton
+ inet_ntop
+ inet_4map6
+ shiftleft
+ addconst
+ add128
+ sub128
+ notcontiguous
+ bin2bcd
+ bcd2bin
+ mode
+ ipv4to6
+ mask4to6
+ ipanyto6
+ maskanyto6
+ ipv6to4
+ bin2bcdn
+ bcdn2txt
+ bcdn2bin
+ simple_pack
+ comp128
+ packzeros
+ AF_INET
+ AF_INET6
+ naip_gethostbyname
+ havegethostbyname2
+);
+
+%EXPORT_TAGS = (
+ all => [@EXPORT_OK],
+ inet => [qw(
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_ntoa
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ inet_n2dx
+ inet_n2ad
+ inet_pton
+ inet_ntop
+ inet_4map6
+ ipv4to6
+ mask4to6
+ ipanyto6
+ maskanyto6
+ ipv6to4
+ packzeros
+ naip_gethostbyname
+ )],
+ math => [qw(
+ shiftleft
+ hasbits
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ addconst
+ add128
+ sub128
+ notcontiguous
+ bin2bcd
+ bcd2bin
+ )],
+ ipv4 => [qw(
+ inet_aton
+ inet_ntoa
+ )],
+ ipv6 => [qw(
+ ipv6_aton
+ ipv6_ntoa
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ inet_n2dx
+ inet_n2ad
+ inet_pton
+ inet_ntop
+ inet_4map6
+ ipv4to6
+ mask4to6
+ ipanyto6
+ maskanyto6
+ ipv6to4
+ packzeros
+ naip_gethostbyname
+ )],
+);
+
+if (NetAddr::IP::Util_IS->not_pure) {
+ eval { ## attempt to load 'C' version of utilities
+ bootstrap NetAddr::IP::Util $VERSION;
+ };
+}
+if (NetAddr::IP::Util_IS->pure || $@) { ## load the pure perl version if 'C' lib missing
+ require NetAddr::IP::UtilPP;
+ import NetAddr::IP::UtilPP qw( :all );
+# require Socket;
+# import Socket qw(inet_ntoa);
+# *yinet_aton = \&Socket::inet_aton;
+ $Mode = 'Pure Perl';
+}
+else {
+ $Mode = 'CC XS';
+}
+
+# if Socket lib is broken in some way, check for overange values
+#
+#my $overange = yinet_aton('256.1') ? 1:0;
+#my $overange = gethostbyname('256.1') ? 1:0;
+
+sub mode() { $Mode };
+
+my $_newV4compat = pack('L4',0,0,0xffffffff,0);
+
+sub inet_4map6 {
+ my $naddr = shift;
+ if (length($naddr) == 4) {
+ $naddr = ipv4to6($naddr);
+ }
+ elsif (length($naddr) == 16) {
+ ; # is OK
+ return undef unless isAnyIPv4($naddr);
+ } else {
+ return undef;
+ }
+ $naddr |= $_newV4compat;
+ return $naddr;
+}
+
+sub DESTROY {};
+
+my $havegethostbyname2 = 0;
+
+my $mygethostbyname;
+
+my $_Sock6ok = 1; # for testing gethostbyname
+
+sub havegethostbyname2 {
+ return $_Sock6ok
+ ? $havegethostbyname2
+ : 0;
+}
+
+sub import {
+ if (grep { $_ eq ':noSock6' } @_) {
+ $_Sock6ok = 0;
+ @_ = grep { $_ ne ':noSock6' } @_;
+ }
+ NetAddr::IP::Util->export_to_level(1,@_);
+}
+
+package NetAddr::IP::UtilPolluted;
+
+# Socket pollutes the name space with all of its symbols. Since
+# we don't want them all, confine them to this name space.
+
+use strict;
+use Socket;
+
+my $_v4zero = pack('L',0);
+my $_zero = pack('L4',0,0,0,0);
+
+# invoke replacement subroutine for Perl's "gethostbyname"
+# if Socket6 is available.
+#
+# NOTE: in certain BSD implementations, Perl's gethostbyname is broken
+# we will use our own InetBase::inet_aton instead
+
+sub _end_gethostbyname {
+# my ($name,$aliases,$addrtype,$length,@addrs) = @_;
+ my @rv = @_;
+# first ip address = rv[4]
+ my $tip = $rv[4];
+ unless ($tip && $tip ne $_v4zero && $tip ne $_zero) {
+ @rv = ();
+ }
+# length = rv[3]
+ elsif ($rv[3] && $rv[3] == 4) {
+ foreach (4..$#rv) {
+ $rv[$_] = NetAddr::IP::Util::inet_4map6(NetAddr::IP::Util::ipv4to6($rv[$_]));
+ }
+ $rv[3] = 16; # unconditionally set length to 16
+ }
+ elsif ($rv[3] == 16) {
+ ; # is ok
+ } else {
+ @rv = ();
+ }
+ return @rv;
+}
+
+unless ( eval { require Socket6 }) {
+ $mygethostbyname = sub {
+# SEE NOTE above about broken BSD
+ my @tip = gethostbyname(NetAddr::IP::InetBase::fillIPv4($_[0]));
+ return &_end_gethostbyname(@tip);
+ };
+} else {
+ import Socket6 qw( gethostbyname2 getipnodebyname );
+ my $try = eval { my @try = gethostbyname2('127.0.0.1',NetAddr::IP::Util::AF_INET()); $try[4] };
+ if (! $@ && $try && $try eq INADDR_LOOPBACK()) {
+ *_ghbn2 = \&Socket6::gethostbyname2;
+ $havegethostbyname2 = 1;
+ } else {
+ *_ghbn2 = sub { return () }; # use failure branch below
+ }
+
+ $mygethostbyname = sub {
+ my @tip;
+ unless ($_Sock6ok && (@tip = _ghbn2($_[0],NetAddr::IP::Util::AF_INET6())) && @tip > 1) {
+# SEE NOTE above about broken BSD
+ @tip = gethostbyname(NetAddr::IP::InetBase::fillIPv4($_[0]));
+ }
+ return &_end_gethostbyname(@tip);
+ };
+}
+
+package NetAddr::IP::Util;
+
+sub naip_gethostbyname {
+# turn off complaint from Socket6 about missing numeric argument
+ undef local $^W;
+ my @rv = &$mygethostbyname($_[0]);
+ return wantarray
+ ? @rv
+ : $rv[4];
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+NetAddr::IP::Util -- IPv4/6 and 128 bit number utilities
+
+=head1 SYNOPSIS
+
+ use NetAddr::IP::Util qw(
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_ntoa
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ hasbits
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ inet_n2dx
+ inet_n2ad
+ inet_pton
+ inet_ntop
+ inet_4map6
+ ipv4to6
+ mask4to6
+ ipanyto6
+ maskanyto6
+ ipv6to4
+ packzeros
+ shiftleft
+ addconst
+ add128
+ sub128
+ notcontiguous
+ bin2bcd
+ bcd2bin
+ mode
+ AF_INET
+ AF_INET6
+ naip_gethostbyname
+ );
+
+ use NetAddr::IP::Util qw(:all :inet :ipv4 :ipv6 :math)
+
+ :inet => inet_aton, inet_ntoa, ipv6_aton
+ ipv6_ntoa, ipv6_n2x, ipv6_n2d,
+ inet_any2n, inet_n2dx, inet_n2ad,
+ inet_pton, inet_ntop, inet_4map6,
+ ipv4to6, mask4to6, ipanyto6, packzeros
+ maskanyto6, ipv6to4, naip_gethostbyname
+
+ :ipv4 => inet_aton, inet_ntoa
+
+ :ipv6 => ipv6_aton, ipv6_ntoa, ipv6_n2x,
+ ipv6_n2d, inet_any2n, inet_n2dx,
+ inet_n2ad, inet_pton, inet_ntop,
+ inet_4map6, ipv4to6, mask4to6,
+ ipanyto6, maskanyto6, ipv6to4,
+ packzeros, naip_gethostbyname
+
+ :math => hasbits, isIPv4, isNewIPv4, isAnyIPv4,
+ addconst, add128, sub128, notcontiguous,
+ bin2bcd, bcd2bin, shiftleft
+
+ $dotquad = inet_ntoa($netaddr);
+ $netaddr = inet_aton($dotquad);
+ $ipv6naddr = ipv6_aton($ipv6_text);
+ $ipv6_text = ipvt_ntoa($ipv6naddr);
+ $hex_text = ipv6_n2x($ipv6naddr);
+ $dec_text = ipv6_n2d($ipv6naddr);
+ $hex_text = packzeros($hex_text);
+ $ipv6naddr = inet_any2n($dotquad or $ipv6_text);
+ $ipv6naddr = inet_4map6($netaddr or $ipv6naddr);
+ $rv = hasbits($bits128);
+ $rv = isIPv4($bits128);
+ $rv = isNewIPv4($bits128);
+ $rv = isAnyIPv4($bits128);
+ $dotquad or $hex_text = inet_n2dx($ipv6naddr);
+ $dotquad or $dec_text = inet_n2ad($ipv6naddr);
+ $netaddr = inet_pton($AF_family,$hex_text);
+ $hex_text = inet_ntop($AF_family,$netaddr);
+ $ipv6naddr = ipv4to6($netaddr);
+ $ipv6naddr = mask4to6($netaddr);
+ $ipv6naddr = ipanyto6($netaddr);
+ $ipv6naddr = maskanyto6($netaddr);
+ $netaddr = ipv6to4($pv6naddr);
+ $bitsX2 = shiftleft($bits128,$n);
+ $carry = addconst($ipv6naddr,$signed_32con);
+ ($carry,$ipv6naddr)=addconst($ipv6naddr,$signed_32con);
+ $carry = add128($ipv6naddr1,$ipv6naddr2);
+ ($carry,$ipv6naddr)=add128($ipv6naddr1,$ipv6naddr2);
+ $carry = sub128($ipv6naddr1,$ipv6naddr2);
+ ($carry,$ipv6naddr)=sub128($ipv6naddr1,$ipv6naddr2);
+ ($spurious,$cidr) = notcontiguous($mask128);
+ $bcdtext = bin2bcd($bits128);
+ $bits128 = bcd2bin($bcdtxt);
+ $modetext = mode;
+ ($name,$aliases,$addrtype,$length,@addrs)=naip_gethostbyname(NAME);
+ $trueif = havegethostbyname2();
+
+ NetAddr::IP::Util::lower();
+ NetAddr::IP::Util::upper();
+
+=head1 INSTALLATION
+
+Un-tar the distribution in an appropriate directory and type:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+B<NetAddr::IP::Util> installs by default with its primary functions compiled
+using Perl's XS extensions to build a 'C' library. If you do not have a 'C'
+complier available or would like the slower Pure Perl version for some other
+reason, then type:
+
+ perl Makefile.PL -noxs
+ make
+ make test
+ make install
+
+=head1 DESCRIPTION
+
+B<NetAddr::IP::Util> provides a suite of tools for manipulating and
+converting IPv4 and IPv6 addresses into 128 bit string context and back to
+text. The strings can be manipulated with Perl's logical operators:
+
+ and &
+ or |
+ xor ^
+ ~ compliment
+
+in the same manner as 'vec' strings.
+
+The IPv6 functions support all rfc1884 formats.
+
+ i.e. x:x:x:x:x:x:x:x:x
+ x:x:x:x:x:x:x:d.d.d.d
+ ::x:x:x
+ ::x:d.d.d.d
+ and so on...
+
+=over 4
+
+=item * $dotquad = inet_ntoa($netaddr);
+
+Convert a packed IPv4 network address to a dot-quad IP address.
+
+ input: packed network address
+ returns: IP address i.e. 10.4.12.123
+
+=item * $netaddr = inet_aton($dotquad);
+
+Convert a dot-quad IP address into an IPv4 packed network address.
+
+ input: IP address i.e. 192.5.16.32
+ returns: packed network address
+
+=item * $ipv6addr = ipv6_aton($ipv6_text);
+
+Takes an IPv6 address of the form described in rfc1884
+and returns a 128 bit binary RDATA string.
+
+ input: ipv6 text
+ returns: 128 bit RDATA string
+
+=item * $ipv6_text = ipv6_ntoa($ipv6naddr);
+
+Convert a 128 bit binary IPv6 address to compressed rfc 1884
+text representation.
+
+ input: 128 bit RDATA string
+ returns: ipv6 text
+
+=item * $hex_text = ipv6_n2x($ipv6addr);
+
+Takes an IPv6 RDATA string and returns an 8 segment IPv6 hex address
+
+ input: 128 bit RDATA string
+ returns: x:x:x:x:x:x:x:x
+
+=item * $dec_text = ipv6_n2d($ipv6addr);
+
+Takes an IPv6 RDATA string and returns a mixed hex - decimal IPv6 address
+with the 6 uppermost chunks in hex and the lower 32 bits in dot-quad
+representation.
+
+ input: 128 bit RDATA string
+ returns: x:x:x:x:x:x:d.d.d.d
+
+=item * $ipv6naddr = inet_any2n($dotquad or $ipv6_text);
+
+This function converts a text IPv4 or IPv6 address in text format in any
+standard notation into a 128 bit IPv6 string address. It prefixes any
+dot-quad address (if found) with '::' and passes it to B<ipv6_aton>.
+
+ input: dot-quad or rfc1844 address
+ returns: 128 bit IPv6 string
+
+=item * $rv = hasbits($bits128);
+
+This function returns true if there are one's present in the 128 bit string
+and false if all the bits are zero.
+
+ i.e. if (hasbits($bits128)) {
+ &do_something;
+ }
+
+ or if (hasbits($bits128 & $mask128) {
+ &do_something;
+ }
+
+This allows the implementation of logical functions of the form of:
+
+ if ($bits128 & $mask128) {
+ ...
+
+ input: 128 bit IPv6 string
+ returns: true if any bits are present
+
+=item * $ipv6naddr = inet_4map6($netaddr or $ipv6naddr
+
+This function returns an ipV6 network address with the first 80 bits
+set to zero and the next 16 bits set to one, while the last 32 bits
+are filled with the ipV4 address.
+
+ input: ipV4 netaddr
+ or ipV6 netaddr
+ returns: ipV6 netaddr
+
+ returns: undef on error
+
+An ipV6 network address must be in one of the two compatible ipV4
+mapped address spaces. i.e.
+
+ ::ffff::d.d.d.d or ::d.d.d.d
+
+=item * $rv = isIPv4($bits128);
+
+This function returns true if there are no on bits present in the IPv6
+portion of the 128 bit string and false otherwise.
+
+ i.e. the address must be of the form - ::d.d.d.d
+
+Note: this is an old and deprecated ipV4 compatible ipV6 address
+
+=item * $rv = isNewIPv4($bits128);
+
+This function return true if the IPv6 128 bit string is of the form
+
+ ::ffff::d.d.d.d
+
+=item * $rv = isAnyIPv4($bits128);
+
+This function return true if the IPv6 bit string is of the form
+
+ ::d.d.d.d or ::ffff::d.d.d.d
+
+=item * $dotquad or $hex_text = inet_n2dx($ipv6naddr);
+
+This function B<does the right thing> and returns the text for either a
+dot-quad IPv4 or a hex notation IPv6 address.
+
+ input: 128 bit IPv6 string
+ returns: ddd.ddd.ddd.ddd
+ or x:x:x:x:x:x:x:x
+
+=item * $dotquad or $dec_text = inet_n2ad($ipv6naddr);
+
+This function B<does the right thing> and returns the text for either a
+dot-quad IPv4 or a hex::decimal notation IPv6 address.
+
+ input: 128 bit IPv6 string
+ returns: ddd.ddd.ddd.ddd
+ or x:x:x:x:x:x:ddd.ddd.ddd.dd
+
+=item * $netaddr = inet_pton($AF_family,$hex_text);
+
+This function takes an IP address in IPv4 or IPv6 text format and converts it into
+binary format. The type of IP address conversion is controlled by the FAMILY
+argument.
+
+=item * $hex_text = inet_ntop($AF_family,$netaddr);
+
+This function takes and IP address in binary format and converts it into
+text format. The type of IP address conversion is controlled by the FAMILY
+argument.
+
+NOTE: inet_ntop ALWAYS returns lowercase characters.
+
+=item * $hex_text = packzeros($hex_text);
+
+This function optimizes and rfc 1884 IPv6 hex address to reduce the number of
+long strings of zero bits as specified in rfc 1884, 2.2 (2) by substituting
+B<::> for the first occurence of the longest string of zeros in the address.
+
+=item * $ipv6naddr = ipv4to6($netaddr);
+
+Convert an ipv4 network address into an IPv6 network address.
+
+ input: 32 bit network address
+ returns: 128 bit network address
+
+=item * $ipv6naddr = mask4to6($netaddr);
+
+Convert an ipv4 network address/mask into an ipv6 network mask.
+
+ input: 32 bit network/mask address
+ returns: 128 bit network/mask address
+
+NOTE: returns the high 96 bits as one's
+
+=item * $ipv6naddr = ipanyto6($netaddr);
+
+Similar to ipv4to6 except that this function takes either an IPv4 or IPv6
+input and always returns a 128 bit IPv6 network address.
+
+ input: 32 or 128 bit network address
+ returns: 128 bit network address
+
+=item * $ipv6naddr = maskanyto6($netaddr);
+
+Similar to mask4to6 except that this function takes either an IPv4 or IPv6
+netmask and always returns a 128 bit IPv6 netmask.
+
+ input: 32 or 128 bit network mask
+ returns: 128 bit network mask
+
+=item * $netaddr = ipv6to4($pv6naddr);
+
+Truncate the upper 96 bits of a 128 bit address and return the lower
+32 bits. Returns an IPv4 address as returned by inet_aton.
+
+ input: 128 bit network address
+ returns: 32 bit inet_aton network address
+
+=item * $bitsXn = shiftleft($bits128,$n);
+
+ input: 128 bit string variable,
+ number of shifts [optional]
+ returns: bits X n shifts
+
+ NOTE: a single shift is performed
+ if $n is not specified
+
+=item * addconst($ipv6naddr,$signed_32con);
+
+Add a signed constant to a 128 bit string variable.
+
+ input: 128 bit IPv6 string,
+ signed 32 bit integer
+ returns: scalar carry
+ array (carry, result)
+
+=item * add128($ipv6naddr1,$ipv6naddr2);
+
+Add two 128 bit string variables.
+
+ input: 128 bit string var1,
+ 128 bit string var2
+ returns: scalar carry
+ array (carry, result)
+
+=item * sub128($ipv6naddr1,$ipv6naddr2);
+
+Subtract two 128 bit string variables.
+
+ input: 128 bit string var1,
+ 128 bit string var2
+ returns: scalar carry
+ array (carry, result)
+
+Note: The carry from this operation is the result of adding the one's
+complement of ARG2 +1 to the ARG1. It is logically
+B<NOT borrow>.
+
+ i.e. if ARG1 >= ARG2 then carry = 1
+ or if ARG1 < ARG2 then carry = 0
+
+
+=item * ($spurious,$cidr) = notcontiguous($mask128);
+
+This function counts the bit positions remaining in the mask when the
+rightmost '0's are removed.
+
+ input: 128 bit netmask
+ returns true if there are spurious
+ zero bits remaining in the
+ mask, false if the mask is
+ contiguous one's,
+ 128 bit cidr number
+
+=item * $bcdtext = bin2bcd($bits128);
+
+Convert a 128 bit binary string into binary coded decimal text digits.
+
+ input: 128 bit string variable
+ returns: string of bcd text digits
+
+=item * $bits128 = bcd2bin($bcdtxt);
+
+Convert a bcd text string to 128 bit string variable
+
+ input: string of bcd text digits
+ returns: 128 bit string variable
+
+=cut
+
+#=item * $onescomp=NetAddr::IP::Util::comp128($ipv6addr);
+#
+#This function is not exported because it is more efficient to use perl " ~ "
+#on the bit string directly. This interface to the B<C> routine is published for
+#module testing purposes because it is used internally in the B<sub128> routine. The
+#function is very fast, but calling if from perl directly is very slow. It is almost
+#33% faster to use B<sub128> than to do a 1's comp with perl and then call
+#B<add128>.
+#
+#=item * $bcdpacked = NetAddr::IP::Util::bin2bcdn($bits128);
+#
+#Convert a 128 bit binary string into binary coded decimal digits.
+#This function is not exported.
+#
+# input: 128 bit string variable
+# returns: string of packed decimal digits
+#
+# i.e. text = unpack("H*", $bcd);
+#
+#=item * $bcdtext = NetAddr::IP::Util::bcdn2txt($bcdpacked);
+#
+#Convert a packed bcd string into text digits, suppress the leading zeros.
+#This function is not exported.
+#
+# input: string of packed decimal digits
+# returns: hexadecimal digits
+#
+#Similar to unpack("H*", $bcd);
+#
+#=item * $bcdpacked = NetAddr::IP::Util::simple_pack($bcdtext);
+#
+#Convert a numeric string into a packed bcd string, left fill with zeros
+#
+# input: string of decimal digits
+# returns: string of packed decimal digits
+#
+#Similar to pack("H*", $bcdtext);
+
+=item * $modetext = mode;
+
+Returns the operating mode of this module.
+
+ input: none
+ returns: "Pure Perl"
+ or "CC XS"
+
+=item * ($name,$aliases,$addrtype,$length,@addrs)=naip_gethostbyname(NAME);
+
+Replacement for Perl's gethostbyname if Socket6 is available
+
+In ARRAY context, returns a list of five elements, the hostname or NAME,
+a space seperated list of C_NAMES, AF family, length of the address
+structure, and an array of one or more netaddr's
+
+In SCALAR context, returns the first netaddr.
+
+This function ALWAYS returns an IPv6 address, even on IPv4 only systems.
+IPv4 addresses are mapped into IPv6 space in the form:
+
+ ::FFFF:FFFF:d.d.d.d
+
+This is NOT the expected result from Perl's gethostbyname2. It is instead equivalent to:
+
+ On an IPv4 only system:
+ $ipv6naddr = ipv4to6 scalar ( gethostbyname( name ));
+
+ On a system with Socket6 and a working gethostbyname2:
+ $ipv6naddr = gethostbyname2( name, AF_INET6 );
+ and if that fails, the IPv4 conversion above.
+
+For a gethostbyname2 emulator that behave like Socket6, see:
+L<Net::DNS::Dig>
+
+=item * $trueif = havegethostbyname2();
+
+This function returns TRUE if Socket6 has a functioning B<gethostbyname2>,
+otherwise it returns FALSE. See the comments above about the behavior of
+B<naip_gethostbyname>.
+
+=item * NetAddr::IP::Util::lower();
+
+Return IPv6 strings in lowercase.
+
+=item * NetAddr::IP::Util::upper();
+
+Return IPv6 strings in uppercase. This is the default.
+
+=back
+
+=head1 EXAMPLES
+
+
+ # convert any textual IP address into a 128 bit vector
+ #
+ sub text2vec {
+ my($anyIP,$anyMask) = @_;
+
+ # not IPv4 bit mask
+ my $notiv4 = ipv6_aton('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::');
+
+ my $vecip = inet_any2n($anyIP);
+ my $mask = inet_any2n($anyMask);
+
+ # extend mask bits for IPv4
+ my $bits = 128; # default
+ unless (hasbits($mask & $notiv4)) {
+ $mask |= $notiv4;
+ $bits = 32;
+ }
+ return ($vecip, $mask, $bits);
+ }
+
+ ... alternate implementation, a little faster
+
+ sub text2vec {
+ my($anyIP,$anyMask) = @_;
+
+ # not IPv4 bit mask
+ my $notiv4 = ipv6_aton('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF::');
+
+ my $vecip = inet_any2n($anyIP);
+ my $mask = inet_any2n($anyMask);
+
+ # extend mask bits for IPv4
+ my $bits = 128; # default
+ if (isIPv4($mask)) {
+ $mask |= $notiv4;
+ $bits = 32;
+ }
+ return ($vecip, $mask, $bits);
+ }
+
+
+ ... elsewhere
+ $nip = {
+ addr => $vecip,
+ mask => $mask,
+ bits => $bits,
+ };
+
+ # return network and broadcast addresses from IP and Mask
+ #
+ sub netbroad {
+ my($nip) = shift;
+ my $notmask = ~ $nip->{mask};
+ my $bcast = $nip->{addr} | $notmask;
+ my $network = $nip->{addr} & $nip->{mask};
+ return ($network, $broadcast);
+ }
+
+ # check if address is within a network
+ #
+ sub within {
+ my($nip,$net) = @_;
+ my $addr = $nip->{addr}
+ my($nw,$bc) = netbroad($net);
+ # arg1 >= arg2, sub128 returns true
+ return (sub128($addr,$nw) && sub128($bc,$addr))
+ ? 1 : 0;
+ }
+
+ # truely hard way to do $ip++
+ # add a constant, wrapping at netblock boundaries
+ # to subtract the constant, negate it before calling
+ # 'addwrap' since 'addconst' will extend the sign bits
+ #
+ sub addwrap {
+ my($nip,$const) = @_;
+ my $addr = $nip->{addr};
+ my $mask = $nip->{mask};
+ my $bits = $nip->{bits};
+ my $notmask = ~ $mask;
+ my $hibits = $addr & $mask;
+ $addr = addconst($addr,$const);
+ my $wraponly = $addr & $notmask;
+ my $newip = {
+ addr => $hibits | $wraponly,
+ mask => $mask,
+ bits => $bits,
+ };
+ # bless $newip as appropriate
+ return $newip;
+ }
+
+ # something more useful
+ # increment a /24 net to the NEXT net at the boundry
+
+ my $nextnet = 256; # for /24
+ LOOP:
+ while (...continuing) {
+ your code....
+ ...
+ my $lastip = $ip-copy();
+ $ip++;
+ if ($ip < $lastip) { # host part wrapped?
+ # discard carry
+ (undef, $ip->{addr} = addconst($ip->{addr}, $nextnet);
+ }
+ next LOOP;
+ }
+
+
+=head1 EXPORT_OK
+
+ inet_aton
+ inet_ntoa
+ ipv6_aton
+ ipv6_ntoa
+ ipv6_n2x
+ ipv6_n2d
+ inet_any2n
+ hasbits
+ isIPv4
+ isNewIPv4
+ isAnyIPv4
+ inet_n2dx
+ inet_n2ad
+ inet_pton
+ inet_ntop
+ inet_4map6
+ ipv4to6
+ mask4to6
+ ipanyto6
+ maskanyto6
+ ipv6to4
+ packzeros
+ shiftleft
+ addconst
+ add128
+ sub128
+ notcontiguous
+ bin2bcd
+ bcd2bin
+ mode
+ naip_gethostbyname
+ havegethostbyname2
+
+=head1 AUTHOR
+
+Michael Robinton <michael@bizsystems.com>
+
+=head1 COPYRIGHT
+
+Copyright 2003 - 2011, Michael Robinton E<lt>michael@bizsystems.comE<gt>
+
+All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ a) the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any
+ later version, or
+
+ b) the "Artistic License" which comes with this distribution.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
+the GNU General Public License or the Artistic License for more details.
+
+You should have received a copy of the Artistic License with this
+distribution, in the file named "Artistic". If not, I'll be glad to provide
+one.
+
+You should also have received a copy of the GNU General Public License
+along with this program in the file named "Copying". If not, write to the
+
+ Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330
+ Boston, MA 02111-1307, USA
+
+or visit their web page on the internet at:
+
+ http://www.gnu.org/copyleft/gpl.html.
+
+=head1 AUTHOR
+
+Michael Robinton <michael@bizsystems.com>
+
+=head1 SEE ALSO
+
+NetAddr::IP(3), NetAddr::IP::Lite(3), NetAddr::IP::InetBase(3)
+
+=cut
+
+1;
--- /dev/null
+
+/*
+ * Copyright 2006 - 2010, Michael Robinton <michael@bizsystems.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _CYGWIN
+#include <windows.h>
+#endif
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+/* needed for testing with 'printf'
+#include <stdio.h>
+ */
+
+#ifdef _CYGWIN
+#include <Win32-Extensions.h>
+#endif
+
+#include "localconf.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+/* workaround for OS's without inet_aton */
+/* #include "xs_include/inet_aton.c" removed 10-12-11 */
+
+typedef union
+{
+ u_int32_t u[4];
+ unsigned char c[16];
+} n128;
+
+char * is_ipv6to4 = "ipv6to4", * is_shiftleft = "shiftleft", * is_comp128 = "comp128";
+char * is_sub128 = "sub128", * is_add128 = "add128";
+char * is_hasbits = "hasbits";
+/* , * is_isIPv4 = "isIPv4"; */
+char * is_bcd2bin = "bcd2bin", * is_simple_pack = "simple_pack", * is_bcdn2bin = "bcdn2bin";
+char * is_mask4to6 = "mask4to6", * is_ipv4to6 = "ipv4to6";
+char * is_maskanyto6 = "maskanyto6", * is_ipanyto6 = "ipanyto6";
+
+typedef struct bcdstuff
+{ /* character array of 40 bytes */
+ char txt[21]; /* 20 bytes + string terminator */
+ u_int32_t bcd[5]; /* 20 bytes, 40 digits */
+} BCD;
+
+#define zero ('0' & 0x7f)
+
+/* useful for debug, prints the 128 bits of 8, 16 bit registers */
+void
+printb128(char * b)
+{
+ int c;
+ for(c=0;c<16;c++) {
+ if (b[c] &0x80)
+ printf("1");
+ else
+ printf("0");
+ if (b[c] &0x40)
+ printf("1");
+ else
+ printf("0");
+ if (b[c] &0x20)
+ printf("1");
+ else
+ printf("0");
+ if (b[c] &0x10)
+ printf("1");
+ else
+ printf("0");
+ if (b[c] &0x8)
+ printf("1");
+ else
+ printf("0");
+ if (b[c] &0x4)
+ printf("1");
+ else
+ printf("0");
+ if (b[c] &0x2)
+ printf("1");
+ else
+ printf("0");
+ if (b[c] &0x1)
+ printf("1");
+ else
+ printf("0");
+ if (c == 3 || c == 7 || c == 11)
+ printf("\n");
+ }
+ printf("\n\n");
+}
+
+void
+extendipv4(void * aa, void * ux)
+{
+ register u_int32_t * a = ux;
+ *a++ = 0;
+ *a++ = 0;
+ *a++ = 0;
+ *a = *((u_int32_t *)aa);
+}
+
+void
+extendmask4(void * aa, void * ux)
+{
+ register u_int32_t * a = ux;
+ *a++ = 0xffffffff;
+ *a++ = 0xffffffff;
+ *a++ = 0xffffffff;
+ *a = *((u_int32_t *)aa);
+}
+
+void
+fastcomp128(void * aa)
+{
+ register u_int32_t * a = aa;
+
+ *a++ ^= 0xffffffff;
+ *a++ ^= 0xffffffff;
+ *a++ ^= 0xffffffff;
+ *a++ ^= 0xffffffff;
+}
+
+/* add two 128 bit numbers
+ return the carry
+ */
+
+int
+adder128(void * aa, void * bb, n128 * ap128, int carry)
+{
+ int i;
+ register u_int32_t a, b, r;
+
+ for (i=3; i >= 0; i--) {
+ a = *((u_int32_t *)aa + i);
+ b = *((u_int32_t *)bb + i);
+ r = a + b;
+ a = 0; /* ripple carry forward */
+ if ( r < a || r < b) /* if overflow */
+ a = 1;
+
+ b = r + carry; /* carry propagate in */
+ if (b < r) /* ripple carry forward */
+ carry = 1; /* if overflow */
+ else
+ carry = a;
+
+ *((u_int32_t *)(ap128->u) + i) = b;
+ }
+ return carry;
+}
+
+int
+addercon(void * aa, u_int32_t * bb, n128 * ap128, int32_t con)
+{
+ register u_int32_t tmp = 0x80000000;
+
+ if (con & tmp)
+ tmp = 0xffffffff;
+ else
+ tmp = 0;
+
+ bb[0] = tmp;
+ bb[1] = tmp;
+ bb[2] = tmp;
+ bb[3] = (u_int32_t)con;
+ return adder128(aa,bb,ap128,0);
+}
+
+int
+have128(void * bp)
+{
+ register u_int32_t * p = bp;
+
+ if (*p++ || *p++ || *p++ || *p++)
+ return 1;
+ return 0;
+}
+
+int
+_isipv4(void * bp)
+{
+ register u_int32_t * p = bp;
+
+ if (*p++ || *p++ || *p++)
+ return 0;
+ return 1;
+}
+
+/* network byte swap and copy */
+void
+netswap_copy(void * dest, void * src, int len)
+{
+ register u_int32_t * d = dest, * s = src;
+
+ for (/* -- */;len>0;len--) {
+#ifdef host_is_LITTLE_ENDIAN
+ *d++ = (((*s & 0xff000000) >> 24) | ((*s & 0x00ff0000) >> 8) | \
+ ((*s & 0x0000ff00) << 8) | ((*s & 0x000000ff) << 24));
+#else
+# ifdef host_is_BIG_ENDIAN
+ *d++ = *s;
+# else
+# error ENDIANness not defined
+# endif
+#endif
+ s++;
+ }
+}
+
+/* do ntohl / htonl changes as necessary for this OS
+ */
+void
+netswap(void * ap, int len)
+{
+#ifdef host_is_LITTLE_ENDIAN
+ register u_int32_t * a = ap;
+ for (/* -- */;len >0;len--) {
+ *a = (((*a & 0xff000000) >> 24) | ((*a & 0x00ff0000) >> 8) | \
+ ((*a & 0x0000ff00) << 8) | ((*a & 0x000000ff) << 24));
+ a++;
+ }
+#endif
+}
+
+/* shift right to purge '0's,
+ return mask bit count and remainder value,
+ left fill with ones
+ */
+unsigned char
+_countbits(void *ap)
+{
+ register u_int32_t * p0 = (u_int32_t *)ap, * p1 = p0 +1, * p2 = p1 +1, * p3 = p2 +1;
+ unsigned char count = 128;
+
+ fastcomp128(ap);
+
+ do {
+ if (!(*p3 & 1))
+ break;
+ count--;
+ *p3 >>= 1;
+ if (*p2 & 1)
+ *p3 |= 0x80000000;
+ *p2 >>= 1;
+ if (*p1 & 1)
+ *p2 |= 0x80000000;
+ *p1 >>= 1;
+ if (*p0 & 1)
+ *p1 |= 0x80000000;
+ *p0 >>= 1;
+ } while (count > 0);
+ return count;
+}
+
+/* multiply 128 bit number x 2
+ */
+void
+_128x2(u_int32_t * ap)
+{
+ register u_int32_t * p = ap +3, tmpc, carry = 0;
+
+ do {
+ tmpc = *p & 0x80000000; /* propagate hi bit to next word */
+ *p <<= 1;
+ if (carry)
+ *p += 1;
+ carry = tmpc;
+ } while (p-- > ap);
+/* printf("2o %04X:%04X:%04X:%04X\n",*(ap),*(ap +1),*(ap +2),*(ap +3)); */
+}
+
+/* multiply 128 bit number X10
+ */
+void
+_128x10(n128 * ap128, n128 * tp128)
+{
+ register u_int32_t * ap = ap128->u, * tp = tp128->u;
+ _128x2(ap); /* multiply by two */
+ *tp = *ap; /* temp save */
+ *(tp +1) = *(ap +1);
+ *(tp +2) = *(ap +2);
+ *(tp +3) = *(ap +3);
+ _128x2(ap);
+ _128x2(ap); /* times 8 */
+ (void) adder128(ap,tp,ap128,0);
+/* printf("x %04X:%04X:%04X:%04X\n",*((u_int32_t *)ap),*((u_int32_t *)ap +1),*((u_int32_t *)ap +2),*((u_int32_t *)ap +3)); */
+}
+
+/* multiply 128 bit number by 10, add bcd digit to result
+ */
+void
+_128x10plusbcd(n128 * ap128, n128 * tp128, char digit)
+{
+ register u_int32_t * ap = ap128->u, * tp = tp128->u;
+/* printf("digit %X + %X = ",digit,*(ap +3)); */
+ _128x10(ap128,tp128);
+ *tp = 0;
+ *(tp + 1) = 0;
+ *(tp + 2) = 0;
+ *(tp + 3) = digit;
+ (void) adder128(ap,tp,ap128,0);
+/* printf("%d %04X:%04X:%04X:%04X\n",digit,*((u_int32_t *)ap),*((u_int32_t *)ap +1),*((u_int32_t *)ap +2),*((u_int32_t *)ap +3)); */
+}
+
+char
+_simple_pack(void * str,int len, BCD * n)
+{
+ int i = len -1, j=19, lo=1;
+ register unsigned char c, * bcdn = (unsigned char *)(n->bcd), * sp = (unsigned char *) str;
+
+ if (len > 40)
+ return '*'; /* error, input string too long */
+
+ memset (bcdn, 0, 20);
+
+ do {
+ c = *(sp + i) & 0x7f;
+ if (c < zero || c > (zero + 9))
+ return c; /* error, out of range */
+
+ if (lo) { /* lo byte ? */
+ *(bcdn + j) = c & 0xF;
+ lo = 0;
+ }
+ else {
+ c <<= 4;
+ *(bcdn + j) |= c;
+ lo = 1; /* lo byte next */
+ j--;
+ }
+ } while (i-- > 0);
+ return 0;
+}
+
+/* convert a packed bcd string to 128 bit binary string
+ */
+void
+_bcdn2bin(void * bp, n128 * ap128, n128 * cp128, int len)
+{
+ int i = 0, hasdigits = 0, lo;
+ register unsigned char c, * cp = (unsigned char *)bp;
+
+ memset(ap128->c, 0, 16);
+ memset(cp128->c, 0, 16);
+
+ while (i < len ) {
+ c = *cp++;
+ for (lo=0;lo<2;lo+=1) {
+ if (lo) {
+ if (hasdigits) /* suppress leading zero multiplications */
+ _128x10plusbcd(ap128, cp128, c & 0xF);
+ else {
+ if (c & 0xF) {
+ hasdigits = 1;
+ ap128->u[3] = c & 0xF;
+ }
+ }
+ }
+ else {
+ if (hasdigits) /* suppress leading zero multiplications */
+ _128x10plusbcd(ap128, cp128, c >> 4);
+ else {
+ if (c & 0XF0) {
+ hasdigits = 1;
+ ap128->u[3] = c >> 4;
+ }
+ }
+ }
+ i++;
+ if (i >= len)
+ break;
+ }
+ }
+}
+
+/* convert a 128 bit number string to a bcd number string
+ returns the length of the bcd string === 20
+ */
+int
+_bin2bcd (unsigned char * binary, BCD * n)
+{
+ register u_int32_t tmp, add3, msk8, bcd8, carry = 0;
+ u_int32_t word;
+ unsigned char binmsk = 0;
+ int c = 0,i, j, p;
+
+ memset (n->bcd, 0, 20);
+
+ for (p=0;p<128;p++) { /* bit pointer */
+ if (! binmsk) {
+ word = *((unsigned char *)binary + c);
+ binmsk = 0x80;
+ c++;
+ }
+ carry = word & binmsk; /* bit to convert */
+ binmsk >>= 1;
+ for (i=4;i>=0;i--) {
+ bcd8 = n->bcd[i];
+ if (carry | bcd8) { /* if something to do */
+ add3 = 3;
+ msk8 = 8;
+
+ for (j=0;j<8;j++) { /* prep bcd digits for X2 */
+ tmp = bcd8 + add3;
+ if (tmp & msk8)
+ bcd8 = tmp;
+ add3 <<= 4;
+ msk8 <<= 4;
+ }
+ tmp = bcd8 & 0x80000000; /* propagated carry */
+ bcd8 <<= 1; /* x 2 */
+ if (carry)
+ bcd8 += 1;
+ n->bcd[i] = bcd8;
+ carry = tmp;
+ }
+ }
+ }
+ netswap(n->bcd,5);
+ return 20;
+}
+
+/* convert a bcd number string to a bcd text string
+ returns the number of digits
+ */
+int
+_bcd2txt(unsigned char * bcd2p, BCD * n)
+{
+ register unsigned char bcd, dchar;
+ int i, j = 0;
+
+ for (i=0;i<20;i++) {
+ dchar = *(bcd2p + i);
+ bcd = dchar >> 4;
+ if (j || bcd) {
+ n->txt[j] = bcd + zero;
+ j++;
+ }
+ bcd = dchar & 0xF;
+ if (j || bcd || i == 19) { /* must be at least one digit */
+ n->txt[j] = bcd + zero;
+ j++;
+ }
+ }
+ n->txt[j] = 0; /* string terminator */
+ return j;
+}
+
+/* INCLUDE: xs_include/miniSocket.inc removed 10-12-11 */
+
+
+
+MODULE = NetAddr::IP::Util PACKAGE = NetAddr::IP::Util
+
+PROTOTYPES: ENABLE
+
+void
+comp128(s,...)
+ SV * s
+ALIAS:
+ NetAddr::IP::Util::ipv6to4 = 2
+ NetAddr::IP::Util::shiftleft = 1
+PREINIT:
+ unsigned char * ap;
+ char * subname;
+ u_int32_t wa[4];
+ STRLEN len;
+ int i;
+PPCODE:
+ ap = (unsigned char *) SvPV(s,len);
+ if (len != 16) {
+ if (ix == 2)
+ subname = is_ipv6to4;
+ else if (ix == 1)
+ subname = is_shiftleft;
+ else
+ subname = is_comp128;
+ croak("Bad arg length for %s%s, length is %d, should be %d",
+ "NetAddr::IP::Util::",subname,len *8,128);
+ }
+ if (ix == 2) {
+ XPUSHs(sv_2mortal(newSVpvn((char *)(ap +12),4)));
+ XSRETURN(1);
+ }
+ else if (ix == 1) {
+ if (items < 2) {
+ memcpy(wa,ap,16);
+ }
+ else if ((i = SvIV(ST(1))) == 0) {
+ memcpy(wa,ap,16);
+ }
+ else if (i < 0 || i > 128) {
+ croak("Bad arg value for %s, is %d, should be 0 thru 128",
+ "NetAddr::IP::Util::shiftleft",i);
+ }
+ else {
+ netswap_copy(wa,ap,4);
+ do {
+ _128x2(wa);
+ i--;
+ } while (i > 0);
+ netswap(wa,4);
+ }
+ }
+ else {
+ memcpy(wa,ap,16);
+ fastcomp128(wa);
+ }
+ XPUSHs(sv_2mortal(newSVpvn((char *)wa,16)));
+ XSRETURN(1);
+
+void
+add128(as,bs)
+ SV * as
+ SV * bs
+ALIAS:
+ NetAddr::IP::Util::sub128 = 1
+PREINIT:
+ unsigned char * ap, *bp;
+ char * subname;
+ u_int32_t wa[4], wb[4];
+ n128 a128;
+ STRLEN len;
+PPCODE:
+ ap = (unsigned char *) SvPV(as,len);
+ if (len != 16) {
+ Bail:
+ if (ix == 1)
+ subname = is_sub128;
+ else
+ subname = is_add128;
+ croak("Bad arg length for %s%s, length is %d, should be %d",
+ "NetAddr::IP::Util::",subname,len *8,128);
+ }
+
+ bp = (unsigned char *) SvPV(bs,len);
+ if (len != 16) {
+ goto Bail;
+ }
+ netswap_copy(wa,ap,4);
+ netswap_copy(wb,bp,4);
+ if (ix == 1) {
+ fastcomp128(wb);
+ XPUSHs(sv_2mortal(newSViv((I32)adder128(wa,wb,&a128,1))));
+ }
+ else {
+ XPUSHs(sv_2mortal(newSViv((I32)adder128(wa,wb,&a128,0))));
+ }
+ if (GIMME_V == G_ARRAY) {
+ netswap(a128.u,4);
+ XPUSHs(sv_2mortal(newSVpvn((char *)a128.c,16)));
+ XSRETURN(2);
+ }
+ XSRETURN(1);
+
+void
+addconst(s,cnst)
+ SV * s
+ I32 cnst
+PREINIT:
+ n128 a128;
+ unsigned char * ap;
+ u_int32_t wa[4], wb[4];
+ STRLEN len;
+PPCODE:
+ ap = (unsigned char *) SvPV(s,len);
+ if (len != 16) {
+ croak("Bad arg length for %s, length is %d, should be %d",
+ "NetAddr::IP::Util::addconst",len *8,128);
+ }
+ netswap_copy(wa,ap,4);
+ XPUSHs(sv_2mortal(newSViv((I32)addercon(wa,wb,&a128,cnst))));
+ if (GIMME_V == G_ARRAY) {
+ netswap(a128.u,4);
+ XPUSHs(sv_2mortal(newSVpvn((char *)a128.c,16)));
+ XSRETURN(2);
+ }
+ XSRETURN(1);
+
+
+int
+hasbits(s)
+ SV * s
+PREINIT:
+ unsigned char * bp;
+ char * subname;
+ STRLEN len;
+CODE:
+ bp = (unsigned char *) SvPV(s,len);
+ if (len != 16) {
+ subname = is_hasbits;
+ croak("Bad arg length for %s%s, length is %d, should be %d",
+ "NetAddr::IP::Util::",subname,len *8,128);
+ }
+ RETVAL = have128(bp);
+OUTPUT:
+ RETVAL
+
+void
+bin2bcd(s)
+ SV * s
+ALIAS:
+ NetAddr::IP::Util::bcdn2txt = 2
+ NetAddr::IP::Util::bin2bcdn = 1
+PREINIT:
+ BCD n;
+ unsigned char * cp;
+ STRLEN len;
+PPCODE:
+ cp = (unsigned char *) SvPV(s,len);
+ if (ix == 0) {
+ if (len != 16) {
+ croak("Bad arg length for %s, length is %d, should be %d",
+ "NetAddr::IP::Util::bin2bcd",len *8,128);
+ }
+ (void) _bin2bcd(cp,&n);
+ XPUSHs(sv_2mortal(newSVpvn((char *)n.txt,_bcd2txt((unsigned char *)n.bcd,&n))));
+ }
+ else if (ix == 1) {
+ if (len != 16) {
+ croak("Bad arg length for %s, length is %d, should be %d",
+ "NetAddr::IP::Util::bin2bcdn",len *8,128);
+ }
+ XPUSHs(sv_2mortal(newSVpvn((char *)n.bcd,_bin2bcd(cp,&n))));
+ }
+ else {
+ if (len > 20) {
+ croak("Bad arg length for %s, length is %d, should %d digits or less",
+ "NetAddr::IP::Util::bcdn2txt",len *2,40);
+ }
+ XPUSHs(sv_2mortal(newSVpvn((char *)n.txt,_bcd2txt(cp,&n))));
+ }
+ XSRETURN(1);
+
+#*
+#* the second argument 'len' is the number of bcd digits for
+#* the bcdn2bin conversion. Pack looses track of the number
+#* digits so this is needed to do the "right thing".
+#* NOTE: that simple_pack always returns 40 digits
+#*
+void
+bcd2bin(s,...)
+ SV * s
+ALIAS:
+ NetAddr::IP::Util::bcdn2bin = 2
+ NetAddr::IP::Util::simple_pack = 1
+PREINIT:
+ BCD n;
+ n128 c128, a128;
+ unsigned char * cp, badc;
+ char * subname;
+ STRLEN len;
+PPCODE:
+ cp = (unsigned char *) SvPV(s,len);
+ if (len > 40) {
+ if (ix == 0)
+ subname = is_bcd2bin;
+ else if (ix ==1)
+ subname = is_simple_pack;
+ Badigits:
+ croak("Bad arg length for %s%s, length is %d, should be %d digits or less",
+ "NetAddr::IP::Util::",subname,len,40);
+ }
+ if (ix == 2) {
+ if (len > 20) {
+ len <<= 1; /* times 2 */
+ subname = is_bcdn2bin;
+ goto Badigits;
+ }
+ if (items < 2) {
+ croak("Bad usage, should have %s('packedbcd,length)",
+ "NetAddr::IP::Util::bcdn2bin");
+ }
+ len = SvIV(ST(1));
+ _bcdn2bin(cp,&a128,&c128,(int)len);
+ netswap(a128.u,4);
+ XPUSHs(sv_2mortal(newSVpvn((char *)a128.c,16)));
+ XSRETURN(1);
+ }
+ badc = _simple_pack(cp,(int)len, &n);
+ if (badc) {
+ if (ix == 1)
+ subname = is_simple_pack;
+ else
+ subname = is_bcd2bin;
+ croak("Bad char in string for %s%s, character is '%c', allowed are 0-9",
+ "NetAddr::IP::Util::",subname,badc);
+ }
+ if (ix == 0) {
+ _bcdn2bin((void *)n.bcd,&a128,&c128,40);
+ netswap(a128.u,4);
+ XPUSHs(sv_2mortal(newSVpvn((char *)a128.c,16)));
+ }
+ else { /* ix == 1 */
+ XPUSHs(sv_2mortal(newSVpvn((char *)n.bcd,20)));
+ }
+ XSRETURN(1);
+
+void
+notcontiguous(s)
+ SV * s
+PREINIT:
+ unsigned char * ap, count;
+ u_int32_t wa[4];
+ STRLEN len;
+PPCODE:
+ ap = (unsigned char *) SvPV(s,len);
+ if (len != 16) {
+ croak("Bad arg length for %s, length is %d, should be %d",
+ "NetAddr::IP::Util::countbits",len *8,128);
+ }
+ netswap_copy(wa,ap,4);
+ count = _countbits(wa);
+ XPUSHs(sv_2mortal(newSViv((I32)have128(wa))));
+ if (GIMME_V == G_ARRAY) {
+ XPUSHs(sv_2mortal(newSViv((I32)count)));
+ XSRETURN(2);
+ }
+ XSRETURN(1);
+
+void
+ipv4to6(s)
+ SV * s
+ALIAS:
+ NetAddr::IP::Util::mask4to6 = 1
+PREINIT:
+ unsigned char * ip;
+ char * subname;
+ u_int32_t wa[4];
+ STRLEN len;
+PPCODE:
+ ip = (unsigned char *) SvPV(s,len);
+ if (len != 4) {
+ if (ix == 1)
+ subname = is_mask4to6;
+ else
+ subname = is_ipv4to6;
+ croak("Bad arg length for %s%s, length is %d, should be 32",
+ "NetAddr::IP::Util::",subname,len *8);
+ }
+ if (ix == 0)
+ extendipv4(ip, wa);
+ else
+ extendmask4(ip, wa);
+ XPUSHs(sv_2mortal(newSVpvn((char *)wa,16)));
+ XSRETURN(1);
+
+void
+ipanyto6(s)
+ SV * s
+ALIAS:
+ NetAddr::IP::Util::maskanyto6 = 1
+PREINIT:
+ unsigned char * ip;
+ char * subname;
+ u_int32_t wa[4];
+ STRLEN len;
+PPCODE:
+ ip = (unsigned char *) SvPV(s,len);
+ if (len == 16) /* if already 128 bits, return input */
+ XPUSHs(sv_2mortal(newSVpvn((char *)ip,16)));
+ else if (len == 4) {
+ if (ix == 0)
+ extendipv4(ip, wa);
+ else
+ extendmask4(ip, wa);
+ XPUSHs(sv_2mortal(newSVpvn((char *)wa,16)));
+ }
+ else {
+ if (ix == 1)
+ subname = is_maskanyto6;
+ else
+ subname = is_ipanyto6;
+ croak("Bad arg length for %s%s, length is %d, should be 32 or 128",
+ "NetAddr::IP::Util::",subname,len *8);
+ }
+ XSRETURN(1);
+
--- /dev/null
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if function 'gethostbyname' is present */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if function 'inet_addr' is present */
+#undef HAVE_INET_ADDR
+
+/* Define to 1 if function 'inet_aton' is present */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if function 'inet_pton' is present */
+#undef HAVE_INET_PTON
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if library library 'nsl' is present */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Extra libraries */
+#undef LIBS
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of `uint16_t', as computed by sizeof. */
+#undef SIZEOF_UINT16_T
+
+/* The size of `uint32_t', as computed by sizeof. */
+#undef SIZEOF_UINT32_T
+
+/* The size of `uint8_t', as computed by sizeof. */
+#undef SIZEOF_UINT8_T
+
+/* The size of `u_int16_t', as computed by sizeof. */
+#undef SIZEOF_U_INT16_T
+
+/* The size of `u_int32_t', as computed by sizeof. */
+#undef SIZEOF_U_INT32_T
+
+/* The size of `u_int8_t', as computed by sizeof. */
+#undef SIZEOF_U_INT8_T
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT32_T
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT8_T
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to the type of a signed integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#undef int32_t
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint16_t
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint32_t
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint8_t
--- /dev/null
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+GREP
+EGREP
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else