aboutsummaryrefslogtreecommitdiffstats
path: root/README.rst
diff options
context:
space:
mode:
Diffstat (limited to 'README.rst')
-rw-r--r--README.rst370
1 files changed, 370 insertions, 0 deletions
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..f151bee
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,370 @@
+=========================================
+``inet`` - an IP address mangling library
+=========================================
+
+``inet`` is meant to make it fun to do IP address calculations.
+
+::
+
+ local inet = require 'inet'
+
+ -- get first address of the 3rd /64 in a /56
+ inet('2001:db8::/56') / 64 * 3 + 1 -- returns inet('2001:db8:0:3::1/64')
+
+ -- get last /64 in a /56
+ inet('2001:db8::/56') * 1 / 64 * -1 -- returns inet('2001:db8:0:ff::/64')
+
+
+Dependencies
+============
+
+- Lua_ version 5.2 or 5.3
+- LPeg_ - Parsing Expression Grammars For Lua
+
+API
+===
+
+``inet`` module
+---------------
+
+======================= =====================================================
+API Description
+======================= =====================================================
+``inet(...)`` Parse address and build ``inet4`` or ``inet6`` table
+``inet.is(foo)`` is ``foo`` an ``inet*`` table
+``inet.is4(foo)`` is ``foo`` an ``inet4`` table
+``inet.is6(foo)`` is ``foo`` an ``inet6`` table
+``inet.set4()`` get new empty IPv4 set
+``inet.set6()`` get new empty IPv6 set
+``inet.mixed_networks`` IPv6 mixed notation set
+``inet.version`` API version (currently ``1``)
+======================= =====================================================
+
+IPv6 mixed notation configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``inet.mixed_networks`` can be used to configure which IPv6 networks
+should use mixed notation, ie. last 32 bits formatted as IPv4,
+as per `RFC 5952`_ section 5.
+
+Initially the set only contains the well-known ``::ffff:0.0.0.0/96`` network.
+
+Common ``inet*`` API
+--------------------
+
+================= ======================================
+Operator Description
+================= ======================================
+``+`` Addition
+``-`` Subtract
+``/`` Change mask (absolute)
+``^`` Change mask (relative)
+``*`` Move network
+``<`` is less than
+``<=`` is less than or equal
+``==`` equals
+``>=`` is greater or equal
+``>`` is greater than
+``~=`` not equals
+``#`` number of network bits
+``:contains()`` contains
+``:network()`` extract network part of address
+``tostring(net)`` convert to network
+``:ipstring()`` ip as string without prefix
+``:cidrstring()`` format CIDR notation
+``:netmask()`` generate netmask as address
+``:flip()`` flip the least significant network bit
+================= ======================================
+
+
+Additional ``inet6`` methods
+-----------------------------
+
+inet6 has these additional methods:
+
+================ =====================================
+Operator Description
+================ =====================================
+``:ipstring4()`` string formatted in mixed notation
+``:ipstring6()`` string formatted in standard notation
+================ =====================================
+
+
+``set`` API
+-----------
+
+================== =================================
+API Description
+================== =================================
+``set:list()`` list networks in set
+``set:add()`` add network to set
+``set:remove()`` remove network from set
+``set:contains()`` is network contained in set?
+``set:flush()`` empty the set
+================== =================================
+
+
+Creating
+--------
+
+There is a multitude of different ways to create ``inet*`` instances.
+
+::
+
+ -- IPv4
+ inet('192.0.2.0') -- returns inet('192.0.2.0/32')
+ inet('192.0.2.0', 24) -- returns inet('192.0.2.0/24')
+ inet({192,0,2,0}, 24) -- returns inet('192.0.2.0/24')
+ inet(3221225985, 32) -- returns inet('192.0.2.1')
+
+ -- IPv6
+ inet('2001:db8::') -- returns inet('2001:db8::/128')
+ inet('2001:db8::', 56) -- returns inet('2001:db8::/56')
+
+ -- its possible to wrap inet instances
+ inet(inet('192.0.2.0/24')) -- returns inet('192.0.2.0/24')
+ inet(inet('2001:db8::')) -- returns inet('2001:db8::')
+
+ -- when wrapped additional mask takes precedence
+ inet(inet('192.0.2.0/32'), 24) -- returns inet('192.0.2.0/24')
+ inet(inet('2001:db8::/128'), 64) -- returns inet('2001:db8::/64')
+
+ -- various error examples
+ inet('192.0.2.0/24', 32) -- returns nil, 'multiple masks supplied'
+ inet('2001:db8::/64', 56) -- returns nil, 'multiple masks supplied'
+ inet('foobar') -- returns nil, 'parse error'
+ inet('foo::bar') -- returns nil, 'parse error'
+ inet('192.0.2.0', 33) -- returns nil, 'invalid mask'
+ inet('2001:db8::', 129) -- returns nil, 'invalid mask'
+
+Mangling
+--------
+
+All of the ``inet*`` mangling operators and methods returns a new instance, and does
+not modify the original instance.
+
+``foo + bar``
+~~~~~~~~~~~~~
+
+Addition
+
+::
+
+ inet('2001:db8::/64') + 5 -- returns inet('2001:db8::5/64')
+
+ inet('::ffff:0.0.0.0/96') + inet('192.0.2.24') -- XXXreturns inet('192.0.2.24')
+
+``foo - bar``
+~~~~~~~~~~~~~
+
+Subtract
+
+::
+
+ inet('2001:db8::5/64') - 5 -- returns inet('2001:db8::/64')
+
+ inet('2001:db8::5/64') - inet('2001:db8::') -- XXXreturns 5
+
+``foo / bar``
+~~~~~~~~~~~~~
+
+Change mask (absolute)
+
+::
+
+ inet('2001:db8::/32') / 64 -- returns inet('2001:db8::/64')
+ inet('2001:db8::1/32') / 64 -- returns inet('2001:db8::1/64')
+
+``foo ^ bar``
+~~~~~~~~~~~~~
+
+Change mask (relative)
+
+::
+
+ inet('2001:db8::/64') ^ -8 -- returns inet('2001:db8::/56')
+ inet('2001:db8::2/48') ^ 8 -- returns inet('2001:db8::2/56')
+
+``foo * bar``
+~~~~~~~~~~~~~
+
+Move network
+
+::
+
+ inet('2001:db8::/64') * 1 -- returns inet('2001:db8:0:1::/64')
+ inet('2001:db8:1::/64') * -16 -- returns inet('2001:db8:0:fff0::/64')
+
+
+``foo:network()``
+~~~~~~~~~~~~~~~~~
+
+Reset the host bits.
+
+::
+
+ inet('192.0.2.4/24'):network() -- returns inet('192.0.2.0/24')
+
+
+``foo:netmask()``
+~~~~~~~~~~~~~~~~~
+
+Build an IP address mask with the netmask of ``foo``.
+
+::
+
+ inet('192.0.2.0/24'):netmask() -- returns inet('255.255.255.0')
+
+``foo:flip()``
+~~~~~~~~~~~~~~
+
+Flip the least significant network bit, to find the complimentary network.
+
+::
+
+ inet('192.0.2.0/26'):flip() -- returns inet('192.0.2.64/26')
+ inet('192.0.2.64/26'):flip() -- returns inet('192.0.2.0/26')
+ inet('192.0.2.0/25'):flip() -- returns inet('192.0.2.128/25')
+
+Tests
+-----
+
+``<``, ``<=``, ``>=`` and ``>``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Compares ``inet`` instances according to the sort order.
+
+::
+
+ inet('192.0.2.0/26') < inet('192.0.2.64/26') -- returns true
+ inet('192.0.2.0/24') < inet('192.0.2.0/26') -- returns true
+ inet('192.0.2.0/26') < inet('192.0.2.1/26') -- returns true
+
+
+``==`` and ``~=``
+~~~~~~~~~~~~~~~~~
+
+Checks if two ``inet`` instances are of the same family, address and mask, or not.
+
+::
+
+ inet('192.0.2.0/24') == inet('192.0.2.0/24') -- returns true
+ inet('192.0.2.0/24') ~= inet('192.0.2.0/24') -- returns false
+ inet('192.0.2.0/24') == inet('192.0.2.0/26') -- returns false
+ inet('192.0.2.0/24') == inet('192.0.2.1/24') -- returns false
+ inet('192.0.2.0/24') == inet('2001:db8::') -- returns false
+
+``#foo``
+~~~~~~~~
+
+Returns the amount of significant network bits.
+
+::
+
+ #inet('192.0.2.0/24') -- returns 24
+ #inet('2001:db8::/48') -- returns 48
+
+``foo:contains(bar)``
+~~~~~~~~~~~~~~~~~~~~~~
+
+``:contains()`` tests for subnet inclusion. It considers only the network parts of the two addresses, ignoring any host part, and determine whether one network part is a subnet of the other.
+
+::
+
+ inet('192.0.2.0/24'):contains(inet('192.0.2.64/26')) -- returns true
+ inet('192.0.2.0/24'):contains(inet('192.0.2.0/26')) -- returns true
+ inet('192.0.2.0/24'):contains(inet('192.0.2.0/24')) -- returns false
+ inet('192.0.2.64/26'):contains(inet('192.0.2.0/24')) -- returns false
+
+Text representation
+-------------------
+
+``inet6`` implements `RFC 5952`_ providing a standardized textual representation of IPv6 addresses.
+
+``tostring(foo)``
+~~~~~~~~~~~~~~~~~
+
+String representation of ``foo``. If ``foo`` represents a host address, then just the address is returned, otherwise CIDR notation is used.
+
+::
+
+ tostring(inet('192.0.2.0/24')) -- returns '192.0.2.0/24'
+ tostring(inet('192.0.2.0/32')) -- returns '192.0.2.0'
+
+For IPv6, if the network is contained by ``inet.mixed_networks``, then mixed notation is used.
+
+``foo:cidrstring(foo)``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Like ``tostring(foo)``, but always return the address in CIDR notation, as specified in `RFC 4632`_.
+
+::
+
+ inet('192.0.2.0/32'):cidrstring() -- returns '192.0.2.0/32'
+
+``foo:ipstring()``
+~~~~~~~~~~~~~~~~~~
+
+Like ``tostring(foo)``, but always just return the IP address.
+
+::
+
+ inet('192.0.2.0/24'):ipstring() -- returns '192.0.2.0'
+
+``foo:ipstring4()``
+~~~~~~~~~~~~~~~~~~~
+
+Like ``foo:ipstring()``, but always uses mixed notation.
+
+``foo:ipstring6()``
+~~~~~~~~~~~~~~~~~~~
+
+Like ``tostring(foo)``, but never uses mixed notation.
+
+Sets
+----
+
+``set:list()``
+~~~~~~~~~~~~~~
+
+list networks in set
+
+``set:add(foo)``
+~~~~~~~~~~~~~~~~
+
+add network to set
+
+``set:remove(foo)``
+~~~~~~~~~~~~~~~~~~~
+
+remove network from set
+
+``set:contains(foo)``
+~~~~~~~~~~~~~~~~~~~~~
+
+is network contained in set?
+
+``set:flush()``
+~~~~~~~~~~~~~~~
+
+Empties the set.
+
+History
+=======
+
+* ``inet`` was brewed in Labitat_ in late 2014.
+* Since then it has been battle-tested in production at the danish ISP Fiberby_.
+* In July 2019 ``inet`` was finally polished up and released to the world.
+
+License
+=======
+
+This project is licensed under `GNU Lesser General Public License version 3`_ or later.
+
+.. _Labitat: https://labitat.dk/
+.. _Fiberby: https://peeringdb.com/asn/42541
+.. _Lua: http://www.lua.org/
+.. _LPeg: http://www.inf.puc-rio.br/~roberto/lpeg/
+.. _RFC 4632: https://tools.ietf.org/html/rfc4632
+.. _RFC 5952: https://tools.ietf.org/html/rfc5952
+.. _GNU Lesser General Public License version 3: https://www.gnu.org/licenses/lgpl-3.0.en.html