AFTR Remote Configuration Protocol

0. Edit History
2010-05-27 first draft
2010-06-02 remove DISCUSS sections
2010-06-08 add delete-tunnel functionality
2010-06-24 <get> on an empty table returns empty <conf/>

1. Introduction

This document specifies a protocol for remotely managing the static
binding table for ISC AFTR.

This protocol is an XML-encoded RPC mechanism, which borrows heavily
from NETCONF, but is trimmed down to the specific needs of AFTR
configuration.

2. Transport Considerations

RPC transactions can be layered on different transport protocols.
Transport connections can be secured or unsecured, depending on the
needs of the operator.

Three transport protocols that spring to mind are the following.

2.1 HTTP/HTTPS

RPC requests can be transported in HTTP or HTTPS POST.

2.2 SSH

RPC transactions could be transported over an SSH channel.  Unlike
NETCONF, there would be no transport-specific message framing (NETCONF
uses the magic string "]]>]]>" between messages).  Instead, the next
top-level tag element (e.g. <rpc>) marks the beginning of the next
message.

2.3 TCP Socket

If no security is needed, RPC transactions could be transported over
a plain TCP socket.  Aside from connection setup, operation would be
identical to the SSH case.

3. XML Consisderations

RPC transactions are encoded in XML.

All protocol elements are defined in the following namespace:
http://aftr.isc.org/mapping/1.0

Any future (post-deployment) changes to the protocol will require
changes to the namespace (e.g. by updating the version number).

4. RPC Model

This protocol uses an RPC-based communications model.

The provisioning system always initiates the transaction with an <rpc>
element, and the AFTR always completes the transaction with an
<rpc-reply> element.

4.1 <rpc> Element

The <rpc> element is used to enclose a configuration request from the
provisioning system to the AFTR.

***only one operation is supported***
The <rpc> element encloses one or more operations (see section 5).  
If multiple operations are requested, all operations will be carried
out before returning an <rpc-reply>, regardless of whether errors or
warnings were encountered in the execution of any individual
operation.

Any attributes in the <rpc> element will be returned in the
corresponding <rpc-reply> element.  Attributes could include a
NETCONF-style message-id, or any other opaque cookie to identify the
transaction.  Attributes are optional, and are not interpreted by the
AFTR.

4.2 <rpc-reply> Element

The <rpc-reply> message is sent in response to an <rpc> operation.

Any attributes in the <rpc> element are returned in the corresponding
<rpc-reply> element.

The <rpc-reply> message encloses one or more <ok> or <rpc-error>
elements.

4.3 <rpc-error> Element

The <rpc-error> element is sent in <rpc-reply> messages if an error or
warning occurs during the processing of an <rpc> request.

The <rpc-error> element encloses a text string describing the error
condition.

If an <rpc> request contains multiple operations, the <rpc-reply> will
contain one <rpc-error> for each operation that encountered an error
or warning.

4.4 <ok> Element

The <ok> element is sent in an <rpc-reply> message if no errors or
warnings occurred during the processing of an <rpc> request.

If the <rpc-reply> element encloses <rpc-error> elements, then any
<ok> elements that are also enclosed MUST include sufficient
contextual information to identify the successful operations.

If all operations within an <rpc> request complete without error or
warning, then the <rpc-reply> element MAY contain a single <ok>.

4.5 Pipelining and Batching

<rpc> requests MUST be processed serially by the AFTR.  Additional
<rpc> requests MAY be sent before previous ones have been completed.
The AFTR MUST send responses only in the order the requests were
received.

As discussed in section 4.1, each <rpc> request MAY contain multiple
operations.  Operations will be processed serially, but the
<rpc-reply> will not be sent until all operations have been processed.

5. Protocol Operations

The following protocol operations may appear within an <rpc> element.

5.1 <create>

This operation creates a static NAT binding.

The required elements for <create> are

  <tunnel> - the IPv6 address of the customer's B4

  <protocol> - udp or tcp

  <sourceAddress> - the IPv4 address of the customer's device

  <sourcePort> - an application port on the customer's device

  <nattedAddress> - the requested external IPv4 address

  <nattedPort> - the requested external port

For example
  <rpc message-id=101>
    <create>
      <tunnel>2001:0:0:1::2</tunnel>
      <protocol>tcp</protocol>
      <sourceAddress>10.0.1.2</sourceAddress>
      <sourcePort>5001</sourcePort>
      <nattedAddress>198.18.200.2</nattedAddress>
      <nattedPort>5001</nattedPort>
    </create>
  </rpc>

If the operation succeeds, the AFTR returns <ok>.

If the requested binding already exists, the AFTR returns <ok>.

***not yet supported***
If the ipv6/proto/src-addr/src-port 4-tuple is already bound to a
different external port, the AFTR deletes the old binding, creates the
new binding, and returns <ok>.

***not yet supported***
If the requested proto/ext-addr/ext-port binding is already assigned
to a different internal address/port, the AFTR deletes the old
binding, creates the new binding, and returns <ok>.

If the requested proto/ext-addr/ext-port binding is already assigned
to a different tunnel, the AFTR returns "ERROR: port assigned to
another subscriber".

If the requested external address not managed by the AFTR, the AFTR
returns "ERROR: external address not managed".

If the requested external port is inside the pre-configured dynamic
port range, the AFTR returns "ERROR: external port out-of-range".

5.2 <delete>

This operation deletes a static NAT binding.

The required elements for <delete> are

  <tunnel> - the IPv6 address of the customer's B4

  <protocol> - udp or tcp

  <sourceAddress> - the IPv4 address of the customer's device

  <sourcePort> - an application port on the customer's device

  <nattedAddress> - the external IPv4 address

  <nattedPort> - the external port

For example
  <rpc message-id=102>
    <delete>
      <tunnel>2001:0:0:1::2</tunnel>
      <protocol>tcp</protocol>
      <sourceAddress>10.0.1.2</sourceAddress>
      <sourcePort>5001</sourcePort>
      <nattedAddress>198.18.200.2</nattedAddress>
      <nattedPort>5001</nattedPort>
    </delete>
  </rpc>

Note that, to uniquely identify a binding, the provisioning system MAY
send either tunnel/protocol/sourceAddress/sourcePort or protocol/
nattedAddress/nattedPort.  One subset or the other may be preferred,
depending on how the AFTR is implemented.  If the provisioning system
does not know which subset the AFTR requires, it SHOULD send all
elements.

For example, either of the following will identify a static mapping.

  <delete>
    <tunnel>2001:0:0:1::2</tunnel>
    <protocol>tcp</protocol>
    <sourceAddress>10.0.1.2</sourceAddress>
    <sourcePort>5001</sourcePort>
  </delete>
OR
  <delete>
    <protocol>tcp</protocol>
    <nattedAddress>198.18.200.2</nattedAddress>
    <nattedPort>5001</nattedPort>
  </delete>

If the <delete> operation contains just a <tunnel> element, the AFTR
will delete all bindings associated with that tunnel address.

If the operation succeeds, the AFTR returns <ok>.

If the requested binding does not exist, the AFTR returns "ERROR: no
mapping found".

5.3 <get>

This operation requests all or part of the static mapping table.

With no attributes, the <get> operation returns the entire table.

For example
  <rpc message-id=103>
    <get/>
  </rpc>

There is an optional 'tunnel' attribute, which specifies the IPv6
address of a customer.  In this case, the <get> operation returns the
static mappings for that customer.

For example
  <rpc message-id=103>
    <get tunnel="2001:0:0:1::2"/>
  </rpc>

If the operation succeeds, the AFTR returns a <conf> element, which in
turn encloses zero or more <natEntry> elements.

For example
  <rpc-reply message-id=103>
    <conf>
      <natEntry>
        <tunnel>2001:0:0:1::2</tunnel>
        <protocol>tcp</protocol>
        <sourceAddress>10.0.1.2</sourceAddress>
        <sourcePort>5001</sourcePort>
        <nattedAddress>198.18.200.2</nattedAddress>
        <nattedPort>5001</nattedPort>
      </natEntry>
      <natEntry>
        <tunnel>2001:0:0:1::2</tunnel>
        <protocol>udp</protocol>
        <sourceAddress>10.0.1.2</sourceAddress>
        <sourcePort>5001</sourcePort>
        <nattedAddress>198.18.200.2</nattedAddress>
        <nattedPort>5001</nattedPort>
      </natEntry>
    </conf>
  </rpc-reply>

5.4 <flush>

This operation deletes all static mappings from the AFTR.

For example
  <rpc message-id=104>
    <flush/>
  </rpc>

If the operation succeeds, the AFTR returns <ok>.

6. Security Considerations

If insecure transport (HTTP, TCP socket) is used, then other means
SHOULD be used to ensure that only authorized users can communicate
with the AFTR.

Appendix A: Schema in Relax NG Compact Format

namespace aftr = "http://aftr.isc.org/mapping/1.0"

rpc = element rpc {
    attribute message-id { text }?,
    (create* & delete* & get* & flush?) }

create = element create { binding }
delete = element delete { binding }
get = element get { attribute tunnel { ipv6Address }? }
flush = element flush { empty }

rpc-reply = element rpc-reply {
    attribute message-id { text }?,
    (ok* & rpc-error* & conf*) }

ok = element ok { (create | delete | get | flush)* }

rpc-error = element rpc-error {
    (create | delete | get | flush)?,
    element error-message { text } }

conf = element conf {
     element natEntry { binding }* }

ipv4Address = xsd:string { pattern = "[a-zA-Z0-9][a-zA-Z0-9.]*" }
ipv6Address = xsd:string { pattern = "[a-zA-Z0-9:][a-zA-Z0-9:.]*" }
port = xsd:decimal { minInclusive = "1" maxInclusive = "65535" }
binding = 
    element tunnel { ipv6Address },
    element protocol { "tcp" | "udp" },
    element sourceAddress { ipv4Address },
    element sourcePort { port },
    element nattedAddress { ipv4Address },
    element nattedPort { port }

Appendix B: Schema in XSD Format

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="rpc">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="create"/>
        <xs:element ref="delete"/>
        <xs:element ref="get"/>
        <xs:element ref="flush"/>
      </xs:choice>
      <xs:attribute name="message-id"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="create" type="binding"/>
  <xs:element name="delete" type="binding"/>
  <xs:element name="get">
    <xs:complexType>
      <xs:attribute name="tunnel" type="ipv6Address"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="flush">
    <xs:complexType/>
  </xs:element>
  <xs:element name="rpc-reply">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="ok"/>
        <xs:element ref="rpc-error"/>
        <xs:element ref="conf"/>
      </xs:choice>
      <xs:attribute name="message-id"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="ok">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="create"/>
        <xs:element ref="delete"/>
        <xs:element ref="get"/>
        <xs:element ref="flush"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
  <xs:element name="rpc-error">
    <xs:complexType>
      <xs:sequence>
        <xs:choice minOccurs="0">
          <xs:element ref="create"/>
          <xs:element ref="delete"/>
          <xs:element ref="get"/>
          <xs:element ref="flush"/>
        </xs:choice>
        <xs:element ref="error-message"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="error-message" type="xs:string"/>
  <xs:element name="conf">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="natEntry"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="natEntry" type="binding"/>
  <xs:simpleType name="ipv4Address">
    <xs:restriction base="xs:string">
      <xs:pattern value="[a-zA-Z0-9][a-zA-Z0-9.]*"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="ipv6Address">
    <xs:restriction base="xs:string">
      <xs:pattern value="[a-zA-Z0-9:][a-zA-Z0-9:.]*"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="port">
    <xs:restriction base="xs:decimal">
      <xs:minInclusive value="1"/>
      <xs:maxInclusive value="65535"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="binding">
    <xs:sequence>
      <xs:element ref="tunnel"/>
      <xs:element ref="protocol"/>
      <xs:element ref="sourceAddress"/>
      <xs:element ref="sourcePort"/>
      <xs:element ref="nattedAddress"/>
      <xs:element ref="nattedPort"/>
    </xs:sequence>
  </xs:complexType>
  <xs:element name="tunnel" type="ipv6Address"/>
  <xs:element name="protocol">
    <xs:simpleType>
      <xs:restriction base="xs:token">
        <xs:enumeration value="tcp"/>
        <xs:enumeration value="udp"/>
      </xs:restriction>
    </xs:simpleType>
  </xs:element>
  <xs:element name="sourceAddress" type="ipv4Address"/>
  <xs:element name="sourcePort" type="port"/>
  <xs:element name="nattedAddress" type="ipv4Address"/>
  <xs:element name="nattedPort" type="port"/>
</xs:schema>
