DNS Lua Agent

Introduction

The DnsLuaAgent is an asynchronous helper for Lua scripts running within the LogicApp. It is used for sending out DNS (typically ENUM) client requests to a suitably configured DNS/ENUM server.

The DnsLuaAgent communicates with one or more instances of the DnsClientApp which can be used to communicate with one or more external DNS servers.

The DnsLuaAgent communicates with the DnsClientApp using the DNS-C-… messages.

DNS Agent API methods are accessed via the “n2.n2svcd.dns_agent” module:

local dns_agent = require "n2.n2svcd.dns_agent"

Configuring DnsLuaAgent

The DnsLuaAgent is configured within a LogicApp.

    <?xml version="1.0" encoding="utf-8"?>
    <n2svcd>
      ...
      <applications>
        ...
        <application name="Logic" module="LogicApp">
          <include>
            <lib>../apps/logic/lib</lib>
          </include>
          <parameters>
            ...
            <parameter name="default_dns_app_name" value="DNS-CLIENT"/>
          </parameters>
          <config>
            <services>
              ...
            </services>
            <agents>
              <agent module="DnsClientApp::DnsLuaAgent" libs="../apps/dns/lib"/>
            </agents>
          </config>
        </application>
        ...
      </application>
      ...
    </n2svcd>

Under normal installation, following agent attributes apply:

Parameter Name Type XML Type Description
module DnsClientApp:: DnsLuaAgent Attribute [Required] The module name containing the Lua Agent code.
libs ../apps/dns/lib Attribute Location of the module for DnsLuaAgent.

In addition, the DnsLuaAgent must be configured with the name of the DnsClientApp with which it will communicate. This is configured within the parameters of the containing LogicApp.

Parameter Name Type XML Type Description
parameters Array Element Array of name = value Parameters for this Application instance.
.default_dns_app_name String Attribute Default name for the DnsClientApp with which DnsLuaAgent will communicate.
.dns_app_name_ String Attribute Use this format when DnsLuaAgent will communicate with more than one DnsClientApp.
(Default = DnsLuaAgent uses only the default route/DNS end-point).

The DnsLuaAgent API

All methods may raise a Lua Error in the case of exception, including:

The following cases will not raise a Lua error, but will return to script processing.

.request_response [Asynchronous]

The request_response method accepts an request object parameter with the following attributes.

Field Type Description
route String The identifier of the DNS endpoint to access, or nil for the default.
request Object Container for the parameters of the DNS request that we are to send.

The request method returns an response object with the following attributes.

Parameter Type Description
response Object Container for response fields copied from the DNS-C-RESPONSE message.
.flags Integer An integer representation of the top-level DNS message two-byte flags field.
.authoritative_answer 0 / 1 [Required] The returned value of the 1-bit AA value in the top-level flags.
.recursion_available 0 / 1 [Required] The returned value of the 1-bit RA value in the top-level flags.
.authenticated_data 0 / 1 [Required] The returned value of the 1-bit AD value in the top-level flags.
.reply_code Integer [Required] The DNS top-level Reply Code.
A value of 0 indicates success. A non-zero value is a failed lookup.
.queries Array of Object The list of Query records parsed from the DNS response Response (see below for object structure).
.authorities Array of Object The list of Authority response records parsed from the DNS response Response (see below for object structure).
.additional Array of Object The list of Additional response records parsed from the DNS response Response (see below for object structure).
.answers Array of Object The list of Answer response records parsed from the DNS response Response (see below for object structure).

The queries Object in the response has the following structure.

Field Type Description
.name String [Required] The name of the record as a dot-notation string.
.type Integer [Required] The integer value of the Type, e.g. 35 indicating NAPTR.
.class Integer [Required] The integer value of the Class, e.g. 1 indicating IN.

The answers, authorities, and additional Objects in the response have the following structure.

Note that the sub-fields name, type, class, ttl are common to all DNS response records. All other sub-fields are specific to individual record Types. At this time the only supported response record types for which extra sub-fields will be decoded are the following:

Field Type Description
.name String [Required] The name of the record as a dot-notation string.
.type Integer [Required] The integer value of the Type, e.g. 35 indicating NAPTR.
.class Integer [Required] The integer value of the Class, e.g. 1 indicating IN.
.order Integer [Required for NAPTR (Type = 35)] The Order value (0-65535) returned in the NAPTR response record.
.preference Integer [Required for NAPTR (Type = 35)] The Preference value (0-65535) returned in the NAPTR response record.
.flags Hex String [Required for NAPTR (Type = 35)] A hex representation of the Flags returned in the NAPTR response record.
.service String [Required for NAPTR (Type = 35)] The Service string returned in the NAPTR response record.
.regex String [Required for NAPTR (Type = 35)] The Regex string (if any) returned in the NAPTR response record.
.replacement String [Required for NAPTR (Type = 35)] The Replacement domain name (if any) returned in the NAPTR response record, expressed as a dot-separated domain name.

Example (DNS Client Request):

local n2svcd = require "n2.n2svcd"
local match = require "n2.n2svcd.tester.match"
local dns_agent = require "n2.n2svcd.dns_agent"

local args, extra_args = ...

-- This entry should exist in our DNS server.
local response = dns_agent.request_response (nil, dns_agent.e164_request ('+16133957218'))

if (response.reply_code ~= 0) then
    error ("Reply code error (non-zero) = " .. response.reply_code)
end

if (not response.answers) then
    error ("Digits not found (no answers).")
end

local answer1 = response.answers[1]
print ("[1] Service = " .. answer1.service)
print ("[1] RegEX = " .. answer1.regex)

return "OK"

This example passes nil as the DNS endpoint identifier. This routes the DNS request to the default configured DnsClientApp name. If more than one DNS endpoint is present, then the first parameter is the “route”, or DNS endpoint key.

.e164_request [Pure Lua]

The e164_request method is a helper method to facilitate the construction of ENUM NAPTR lookup requests.

This method accepts the following parameters:

Field Type Description
digits String [Required] The E.164 digit string with optional leading + which will be removed.
suffix Table An optional override for the E.164 suffix string to append to the name.
(Default = 'e164.org').

This method returns a table structure suitable for passing as the request parameter of the .request_response method.

[Fragment] Example:

    dns_agent.e164_request ('+16133957218')

This will return the table value:

    { queries = { { name = '8.1.2.7.5.9.3.3.1.6.1.e164.org', type = dns_agent.TYPE_NAPTR, class = dns_agent.CLASS_IN } } }

Constants

The following DNS and DNS constants are defined on the returned dns_agent object.

See:

-- ENUM default suffix for NAPTR E.164 queries
dns_agent.DEFAULT_E164_SUFFIX = 'e164.org'

-- DNS Type Constants.
dns_agent.TYPE_NS = 2
dns_agent.TYPE_NAPTR = 35

-- DNS Class Constants.
dns_agent.CLASS_IN = 1

-- DNS OPCODE Constants.
dns_agent.OPCODE_QUERY = 0
dns_agent.OPCODE_IQUERY = 1
dns_agent.OPCODE_STATUS = 2