# Class `luci.ip`

LuCI IP calculation and netlink access library.

## Functions

new (address, netmask) | Construct a new luci.ip.cidr instance and autodetect the address family.
IPv4 (address, netmask) | Construct a new IPv4 luci.ip.cidr instance.
IPv6 (address, netmask) | Construct a new IPv6 luci.ip.cidr instance.
MAC (address, netmask) | Construct a new MAC luci.ip.cidr instance.
checkip4 (address) | Verify an IPv4 address.
checkip6 (address) | Verify an IPv6 address.
checkmac (address) | Verify an ethernet MAC address.
route (address) | Determine the route leading to the given destination.
routes (filter, callback) | Fetch all routes, optionally matching the given criteria.
neighbors (filter, callback) | Fetches entries from the IPv4 ARP and IPv6 neighbour kernel table
link (device) | Fetch basic device information

## Functions

new (address, netmask)
  Construct a new luci.ip.cidr instance and autodetect the address family. Throws an error if the given strings do not represent a valid address or if the given optional netmask is of a different family.

  ### Parameters

  - address: String containing a valid IPv4 or IPv6 address, optionally with prefix size (CIDR notation) or netmask separated by slash.
  - netmask: String containing a valid IPv4 or IPv6 netmask or number containing a prefix size in bits (`0..32` for IPv4, `0..128` for IPv6). Overrides mask embedded in the first argument if specified. (optional)

  ### Usage:

      addr = luci.ip.new("10.24.0.1/24")
      addr = luci.ip.new("10.24.0.1/255.255.255.0")
      addr = luci.ip.new("10.24.0.1", "255.255.255.0")        -- separate netmask
      addr = luci.ip.new("10.24.0.1/24", 16)                  -- override netmask

      addr6 = luci.ip.new("fe80::221:63ff:fe75:aa17/64")
      addr6 = luci.ip.new("fe80::221:63ff:fe75:aa17/ffff:ffff:ffff:ffff::")
      addr6 = luci.ip.new("fe80::221:63ff:fe75:aa17", "ffff:ffff:ffff:ffff::")
      addr6 = luci.ip.new("fe80::221:63ff:fe75:aa17/64", 128) -- override netmask

  ### Return value:

  A `luci.ip.cidr` object representing the given address/mask range.

  ### See also:

  - IPv4
  - IPv6
  - MAC
IPv4 (address, netmask)
  Construct a new IPv4 luci.ip.cidr instance. Throws an error if the given string does not represent a valid IPv4 address or if the given optional netmask is of a different family.

  ### Parameters

  - address: String containing a valid IPv4, optionally with prefix size (CIDR notation) or netmask separated by slash.
  - netmask: String containing a valid IPv4 netmask or number containing a prefix size between `0` and `32` bit. Overrides mask embedded in the first argument if specified. (optional)

  ### Usage:

      addr = luci.ip.IPv4("10.24.0.1/24")
      addr = luci.ip.IPv4("10.24.0.1/255.255.255.0")
      addr = luci.ip.IPv4("10.24.0.1", "255.255.255.0")        -- separate netmask
      addr = luci.ip.IPv4("10.24.0.1/24", 16)                  -- override netmask

  ### Return value:

  A `luci.ip.cidr` object representing the given IPv4 range.

  ### See also:

  - IPv6
  - MAC
IPv6 (address, netmask)
  Construct a new IPv6 luci.ip.cidr instance. Throws an error if the given string does not represent a valid IPv6 address or if the given optional netmask is of a different family.

  ### Parameters

  - address: String containing a valid IPv6, optionally with prefix size (CIDR notation) or netmask separated by slash.
  - netmask: String containing a valid IPv4 netmask or number containing a prefix size between `0` and `128` bit. Overrides mask embedded in the first argument if specified. (optional)

  ### Usage:

      addr6 = luci.ip.IPv6("fe80::221:63ff:fe75:aa17/64")
      addr6 = luci.ip.IPv6("fe80::221:63ff:fe75:aa17/ffff:ffff:ffff:ffff::")
      addr6 = luci.ip.IPv6("fe80::221:63ff:fe75:aa17", "ffff:ffff:ffff:ffff::")
      addr6 = luci.ip.IPv6("fe80::221:63ff:fe75:aa17/64", 128) -- override netmask

  ### Return value:

  A `luci.ip.cidr` object representing the given IPv6 range.

  ### See also:

  - IPv4
  - MAC
MAC (address, netmask)
  Construct a new MAC luci.ip.cidr instance. Throws an error if the given string does not represent a valid ethernet MAC address or if the given optional mask is of a different family.

  ### Parameters

  - address: String containing a valid ethernet MAC address, optionally with prefix size (CIDR notation) or mask separated by slash.
  - netmask: String containing a valid MAC address mask or number containing a prefix size between `0` and `48` bit. Overrides mask embedded in the first argument if specified. (optional)

  ### Usage:

      intel_macs = luci.ip.MAC("C0:B6:F9:00:00:00/24")
      intel_macs = luci.ip.MAC("C0:B6:F9:00:00:00/FF:FF:FF:0:0:0")
      intel_macs = luci.ip.MAC("C0:B6:F9:00:00:00", "FF:FF:FF:0:0:0")
      intel_macs = luci.ip.MAC("C0:B6:F9:00:00:00/24", 48) -- override mask

  ### Return value:

  A `luci.ip.cidr` object representing the given MAC address range.

  ### See also:

  - IPv4
  - IPv6
checkip4 (address)
  Verify an IPv4 address. Checks whether given argument is a preexisting luci.ip.cidr IPv4 address instance or a string literal convertible to an IPv4 address and returns a plain Lua string containing the canonical representation of the address. If the argument is not a valid address, returns nothing. This function is intended to aid in safely verifying address literals without having to deal with exceptions.

  ### Parameters

  - address: String containing a valid IPv4 address or existing luci.ip.cidr IPv4 instance.

  ### Usage:

      ipv4 = luci.ip.checkip4(luci.ip.new("127.0.0.1"))  -- "127.0.0.1"
      ipv4 = luci.ip.checkip4("127.0.0.1")               -- "127.0.0.1"
      ipv4 = luci.ip.checkip4("nonesense")               -- nothing
      ipv4 = luci.ip.checkip4(123)                       -- nothing
      ipv4 = luci.ip.checkip4(nil)                       -- nothing
      ipv4 = luci.ip.checkip4()                          -- nothing

  ### Return value:

  A string representing the given IPv4 address.

  ### See also:

  - checkip6
  - checkmac
checkip6 (address)
  Verify an IPv6 address. Checks whether given argument is a preexisting luci.ip.cidr IPv6 address instance or a string literal convertible to an IPv6 address and returns a plain Lua string containing the canonical representation of the address. If the argument is not a valid address, returns nothing. This function is intended to aid in safely verifying address literals without having to deal with exceptions.

  ### Parameters

  - address: String containing a valid IPv6 address or existing luci.ip.cidr IPv6 instance.

  ### Usage:

      ipv6 = luci.ip.checkip6(luci.ip.new("0:0:0:0:0:0:0:1"))  -- "::1"
      ipv6 = luci.ip.checkip6("0:0:0:0:0:0:0:1")               -- "::1"
      ipv6 = luci.ip.checkip6("nonesense")                     -- nothing
      ipv6 = luci.ip.checkip6(123)                             -- nothing
      ipv6 = luci.ip.checkip6(nil)                             -- nothing
      ipv6 = luci.ip.checkip6()                                -- nothing

  ### Return value:

  A string representing the given IPv6 address.

  ### See also:

  - checkip4
  - checkmac
checkmac (address)
  Verify an ethernet MAC address. Checks whether given argument is a preexisting luci.ip.cidr MAC address instance or a string literal convertible to an ethernet MAC and returns a plain Lua string containing the canonical representation of the address. If the argument is not a valid address, returns nothing. This function is intended to aid in safely verifying address literals without having to deal with exceptions.

  ### Parameters

  - address: String containing a valid MAC address or existing luci.ip.cidr MAC address instance.

  ### Usage:

      mac = luci.ip.checkmac(luci.ip.new("00-11-22-cc-dd-ee"))  -- "00:11:22:CC:DD:EE"
      mac = luci.ip.checkmac("00:11:22:cc:dd:ee")               -- "00:11:22:CC:DD:EE"
      mac = luci.ip.checkmac("nonesense")                       -- nothing
      mac = luci.ip.checkmac(123)                               -- nothing
      mac = luci.ip.checkmac(nil)                               -- nothing
      mac = luci.ip.checkmac()                                  -- nothing

  ### Return value:

  A string representing the given MAC address.

  ### See also:

  - checkip4
  - checkip6
route (address)
  Determine the route leading to the given destination.

  ### Parameters

  - address: A `luci.ip.cidr` instance or a string containing a valid IPv4 or IPv6 range as specified by `luci.ip.new()`.

  ### Usage:

  - Find default gateway by getting route to Google's public NS server

        rt = luci.ip.route("8.8.8.8")
        if rt ~= nil then
        	print("gateway is", rt.gw)
        end

  - Determine IPv6 upstream interface

        rt = luci.ip.route("2001::/7")
        if rt ~= nil then
        	print("ipv6 upstream device is", rt.dev)
        end

  ### Return value:

  Table containing the fields described below.

  Field | Description
  --- | ---
  `type` | Route type with one of the following numeric values:
  `1` | `RTN_UNICAST` - Gateway or direct route
  `2` | `RTN_LOCAL` - Accept locally
  `3` | `RTN_BROADCAST` - Accept locally as broadcast send as broadcast
  `4` | `RTN_ANYCAST` - Accept locally as broadcast but send as unicast
  `5` | `RTN_MULTICAST` - Multicast route
  `family` | Number containing the route family, `4` for IPv4 or `6` for IPv6
  `dest` | Destination `luci.ip.cidr` instance
  `gw` | Gateway `luci.ip.cidr` instance (optional)
  `from` | Source address `luci.ip.cidr` instance (optional)
  `src` | Preferred source `luci.ip.cidr` instance (optional)
  `dev` | String containing the name of the outgoing interface
  `iif` | String containing the name of the incoming interface (optional)
  `table` | Number of the associated routing table (`0..65535`)
  `proto` | Number of the associated routing protocol
  `scope` | Number describing the scope of the route, most commonly `0` for global or `253` for on-link
  `metric` | Number describing the route metric (optional)
  `expires` | Number of seconds the prefix is valid (IPv6 only, optional)
  `error` | Route destination error code (optional)

  ### See also:

  - routes
routes (filter, callback)
  Fetch all routes, optionally matching the given criteria.

  ### Parameters

  - filter:

    Table containing one or more of the possible filter critera described below (optional)

    Field | Description
    --- | ---
    `family` | Number describing the address family to return - `4` selects IPv4 routes, `6` IPv6 ones. Any other value selects both.
    `iif` | String containing the incoming route interface to match.
    `oif` | String containing the outgoing route interface to match.
    `type` | Numeric type to match, e.g. `1` for unicast.
    `scope` | Numeric scope to match, e.g. `253` for onlink.
    `proto` | Numeric protocol to match, e.g. `2` for boot.
    `table` | Numeric routing table to match (`0..65535`).
    `gw` | String containing the gateway address to match. Can be in any notation specified by `luci.ip.new()`. Prefix matching is performed when comparing the routes, e.g. "192.168.1.0/24" would select routes with gateway addresses `192.168.1.1 .. 192.168.1.255`.
    `dest` | String containing the destination to match. Prefix matching is performed.
    `from` | String containing the source address to match. Prefix matching is performed.
    `src` | String containing the preferred source address to match. Prefix matching is performed.
    `dest_exact` | String containing the destination to match. Exact matching is performed, e.g. `dest = "0.0.0.0/0"` would match any IPv4 route while `dest_exact = "0.0.0.0/0"` will only match the default route.
    `from_exact` | String containing the source address to match. Exact matching is performed.

  - callback:

    Callback function to invoke for each found route instead of returning one table of route objects (optional)

  ### Usage:

  - Find all IPv4 default routes:

        luci.ip.routes({ dest_exact = "0.0.0.0/0" }, function(rt)
        	print(rt.type, rt.gw, rt.dev)
        end)

  - Find all global IPv6 prefixes on the current system:

        luci.ip.routes({ from = "2001::/7" }, function(rt)
        	print(rt.from)
        end)

  - Fetch all IPv4 routes:

        routes = luci.ip.routes({ family = 4 })
        for _, rt in ipairs(routes) do
        	print(rt.dest, rt.gw, rt.dev)
        end

  ### Return value:

  If no callback function is provided, a table of routes as specified by `luci.ip.route()` is returned. If a callback function is given, it is invoked for each route and nothing is returned.

  ### See also:

  - route
neighbors (filter, callback)
  Fetches entries from the IPv4 ARP and IPv6 neighbour kernel table

  ### Parameters

  - filter:

    Table containing one or more of the possible filter critera described below (optional)

    Field | Description
    --- | ---
    `family` | Number describing the address family to return - `4` selects IPv4 ARP, `6` select IPv6 neighbour entries. Any other value selects both.
    `dev` | String containing the associated interface to match.
    `dest` | String containing the associated address to match. Can be in any notation specified by `luci.ip.new()`. Prefix matching is performed when comparing the addresses, e.g. "192.168.1.0/24" would select ARP entries for `192.168.1.1 .. 192.168.1.255`.
    `mac` | String containing MAC address to match.

  - callback:

    Callback function to invoke for each found neighbour entry instead of returning one table of neighbour entries (optional)

  ### Usage:

  - Find all ARP neighbours in the LAN:

        luci.ip.neighbors({ dest = "192.168.0.0/16" }, function(n)
        	print(n.dest, n.mac)
        end)

  - Find all active IPv6 addresses of host with given MAC:

        luci.ip.neighbors({ family = 6, mac = "00:21:63:75:aa:17" },
        	function(n)
        		print(n.dest)
        	end)

  ### Return value:

  If no callback function is provided, a table of neighbour entries is returned. If a callback function is given, it is invoked for each entry and nothing is returned. A neighbour entry is a table containing the following fields:

  Field | Description
  --- | ---
  `family` | Number containing the neighbour entry family, `4` for IPv4 ARP or `6` for IPv6 NDP
  `dev` | String containing the associated device of the neighbour entry
  `dest` | IP address `luci.ip.cidr` instance
  `mac` | MAC address `luci.ip.cidr` instance
  `router` | Boolean "true" if the neighbour entry is a router (IPv6, optional)
  `proxy` | Boolean "true" if this is a proxy entry (optional)
  `incomplete` | Boolean "true" if the entry is in incomplete state (optional)
  `reachable` | Boolean "true" if the entry is in reachable state (optional)
  `stale` | Boolean "true" if the entry is stale (optional)
  `delay` | Boolean "true" if the entry is delayed (optional)
  `probe` | Boolean "true" if the entry is in probe state (optional)
  `failed` | Boolean "true" if the entry is in failed state (optional)
  `noarp` | Boolean "true" if the entry is not caused by NDP or ARP (optional)
  `permanent` | Boolean "true" if the entry was statically configured from userspace (optional)

link (device)
  Fetch basic device information

  ### Parameters

  - device: String containing the network device to query

  ### Usage:

  - Test whether device br-lan exists:

        print(luci.ip.link("br-lan").name ~= nil)

  - Query MAC address of eth0:

        print(luci.ip.link("eth0").mac)

  ### Return value:

  If the given interface is found, a table containing the fields described below is returned, else an empty table.

  Field | Description
  --- | ---
  `up` | Boolean indicating whether the device is in IFF_RUNNING state
  `type` | Numeric value indicating the type of the device, e.g. `1` for ethernet.
  `name` | String containing the name of the device
  `master` | If queried device is a bridge port, string containing the name of parent bridge device (optional)
  `mtu` | Number containing the current MTU of the device
  `qlen` | Number containing the TX queue length of the device
  `mac` | MAC address `luci.ip.cidr` instance representing the device ethernet address