format of MX and SRV needs one more tab
[pdns-pipe-nmc.git] / SPEC.md
1 % JSON Domain Format as Implemented by Pdns-Pipe-Nmc
2
3 ## Data Format
4
5 ### `DomObj` Object
6
7 `DomObj` either a `String` containing a dotted quad (see Note below),
8 or a JSON `Map`, with the following attributes, all optional:
9
10 | Key         | Type                                  | Comment                                    |
11 |-------------|---------------------------------------|--------------------------------------------|
12 | service     | Array(SrvObj)                         | Located two levels above position          |
13 | ip          | Array(String)                         | Dotted quad format "1.2.3.4"               |
14 | ip6         | Array(String)                         | Semicolon format "DEAD::BEEF"              |
15 | tor         | String                                | Onion name                                 |
16 | i2p         | I2pObj                                |                                            |
17 | freenet     | String                                |                                            |
18 | alias       | String                                | Nullifies other attributes                 |
19 | translate   | String                                | Nullifies other attributes                 |
20 | email       | String                                | Used in `SOA`                              |
21 | loc         | String                                | Format suitable for `LOC`                  |
22 | info        | JsonObj                               | Currently unspecified                      |
23 | ns          | Array(String)                         | Domain names as in `NS`                    |
24 | delegate    | String                                | Replaces current object                    |
25 | import      | Array(String)                         | "Deep" merges into current object          |
26 | map         | Map(String:DomObj)                    | Tree of subdomain objects                  |
27 | fingerprint | Array(String)                         |                                            |
28 | tls         | Map(String:Map(String:Array(TlsObj))) | Outer `Map` by `Protocol`, inner by `Port` |
29 | ds          | Array(DsObj)                          |                                            |
30
31 #### Notes:
32
33 * Any attribute specified as `Array(String)` may be present in the
34   JSON document as a plain `String`, which is interpreted the same way
35   as an `Array` containing a single `String` element. In other words,
36   `"ip":"1.2.3.4"` is equivalent to `"ip":["1.2.3.4"]`. (This does not
37   apply to non-string-array attributes, like "service" or "ds".)
38 * If `DomObj` is a `String`, it is interpreted as an IPv4 address.
39   In other words, string `"1.2.3.4"` is the same as the Map
40   `"{\"ip\":\"1.2.3.4\"}"`. Such "shorthand" DomObj can be present at
41   the top level or as a value in the `"map"` attribute.
42
43 ### `SrvObj` Object
44
45 `SrvObj` is a heterogenous Array of fixed size containing 6 elements:
46
47 | N | Type   | Meaning  |
48 |---|--------|----------|
49 | 0 | String | Service  |
50 | 1 | String | Protocol |
51 | 2 | Int    | Priority |
52 | 3 | Int    | Weight   |
53 | 4 | Int    | Port     |
54 | 5 | String | Hostname |
55
56 #### Notes
57
58 * `Service` and `Protocol` are two elements of the domain name, without
59   the undescore '_'.
60 * `SrvObj` with Service `"smtp"`, Protocol `"tcp"` and Port `25` is also
61   interpteted as an `MX` DNS resource at the domain level containing the
62   `"service"` object.
63 * When lookup is performed for `SRV` records at fqdn
64   `"_serv._proto.sub.dom.bit"`, domain object for `"sub.dom.bit"` must be
65   fetched, and in this object, `SrvObj`s for the Service `"serv"` and
66   Protocol `"proto"` selected from its `"service"` attribute.
67
68 ### `TlsObj` Object
69
70 `TlsObj` is a heterogenous Array of fixed size containing 3 elements:
71
72 | N | Type   | Meaning                                               |
73 |---|--------|-------------------------------------------------------|
74 | 0 | Int    | Match type - 0:Exact, 1:SHA-256, 2:SHA-512            |
75 | 1 | String | Match value - certificate or hash of it as hex string |
76 | 2 | Int    | Include subdomains - 0:No, 1:Yes                      |
77
78 #### Notes
79
80 * The fields of the object correspond to the attributes defined by
81   [RFC-6698](http://tools.ietf.org/html/rfc6698) ("DANE").
82
83 ### `DsObj` Object
84
85 `DsObj` is a heterogenous Array of fixed size containing 4 elements:
86
87 | N | Type   | Meaning                  |
88 |---|--------|--------------------------|
89 | 0 | Int    | Key Tag                  |
90 | 1 | Int    | Key Algorithm            |
91 | 2 | Int    | Hash Type                |
92 | 3 | String | Hash Value as hex string |
93
94 #### Notes
95
96 * The fields of the object correspond to the attributes defined by
97   [RFC-3658](http://tools.ietf.org/html/rfc3658).
98
99 ## Data Interpretation
100
101 ### Semantics of the Attributes
102
103 #### service attribute
104
105 Translates to DNS `SRV` RR, only it is located in the subdomain tree
106 two levels higher than the `SRV` record would. For example, a
107 `"service"` attribute in the `"map"` hieararchy at the point
108 corresponding to the FQDN "sub.dom.bit" with the value
109
110 ```
111 "service": [ ["imap", "tcp", 0, 0, 143, "mail.host.com." ],
112              ["smtp", "tcp", 0, 0,  25, "relay.host.com."] ]
113 ```
114
115 corresponds to two `SRV` RRs at two different points in the
116 subdomain tree:
117
118 ```
119 _imap._tcp.sub.dom.bit. IN SRV 0 0 143 mail.host.com.
120 _smtp._tcp.sub.dom.bit. IN SRV 0 0  25 relay.host.com.
121 ```
122
123 In addition to these, an `MX` RR is syntesized at the "sub.dom.bit"
124 level:
125
126 ```
127 sub.dom.bit. IN MX 0 relay.host.com.
128 ```
129
130 #### ip attribute
131
132 Contains a list of strings representing IPv4 addresses in dotted
133 quad notation. For example,
134
135 ```
136 "ip": ["1.2.3.4", "5.6.7.8"]
137 ```
138
139 translates into a series of `A` RRs:
140
141 ```
142         IN A 1.2.3.4
143         IN A 5.6.7.8
144 ```
145
146 #### ip6 attribute
147
148 Contains a list of strings representing IPv6 addresses in semicolon
149 quads notation. For example,
150
151 ```
152 "ip6": ["2001:4860:0:1001::68"]
153 ```
154
155 translates into one AAAA RR:
156
157 ```
158         IN AAAA 2001:4860:0:1001::68
159 ```
160
161 #### tor attribute
162
163 Does not translate into any DNS RR. Contains Tor hidden service address.
164
165 #### i2p attribute
166
167 Does not translate into any DNS RR. Contains an object with three
168 optional String attributes: `"destination"`, `"name"` and `"b32"`.
169
170 #### freenet attribute
171
172 Does not translate into any DNS RR. Contains Freesite key.
173
174 #### alias attribute
175
176 Translates into `CNAME` RR. Invalidates all other attributes except
177 the element of the `"map"` with empty key. Such element is analysed
178 and its contents merged into the base domain before the check.
179
180 #### translate attribute
181
182 Translates into `DNAME` RR. Invalidates the contents of the `"map"`
183 attribute, except the element of the `"map"` with empty key. Such
184 element is analysed and its contents merged into the base domain
185 before the check.
186
187 #### email attribute
188
189 Translates into the `email` element of the SOA and RP RRs. The
190 value `"email":"user@domain.tld"` becomes `user.domain.tld.`
191 in the DNS record.
192
193 #### loc attribute
194
195 Translates into `LOC` RR. Value must conform to the format defined
196 by [RFC-1876](http://tools.ietf.org/html/rfc1876).
197
198 #### info attribute
199
200 Does not translate into any DNS RR. Contains a JSON object with
201 format unspecified at the time of this writing.
202
203 #### ns attribute
204
205 Translates into `NS` RR. Invalidates all other attributes, except
206 the element of the `"map"` with empty key. Such element is analysed
207 and its contents merged into the base domain before the check.
208
209 #### delegate attribute
210
211 Does not translate into any DNS RR. Instead, the value is used as
212 a key for namecoin lookup (i.e. the value must be specified with
213 the namespace prefix), and the result of the lookup replaces all
214 other attributes, except the element of the `"map"` with empty key.
215 Such element is analysed and its contents merged into the base
216 domain before the check.
217
218 #### import attribute
219
220 Does not translate into any DNS RR. Instead, the value is used as
221 a key for namecoin lookup (i.e. the value must be specified with
222 the namespace prefix), and the result of the lookup is merged with
223 the current domain object.
224
225 #### map attribute
226
227 JSON Map object containing subdomain names as its keys and domain
228 objects as values. Element of the map with empty key "" has special
229 meaning: the value of this map element is merged into the current
230 domain object. This operaton happens first when a new domain object
231 is analyzed, and is performed recursively. In the result of the
232 merge, the `"map"` does not contain the element with empty key.
233 Further operatons that can potentially modify the contents of the
234 current domain object (`import` and `delegate` lookups) start when
235 the empty element of the `"map"` has been recursively merged into
236 the current object.
237
238 #### fingerprint attribute
239
240 Does not translate into any DNS RR. Contains a list of TLS
241 certificate fingerprints. Deprecated.
242
243 #### tls attribute
244
245 Intended to carry attributes as per
246 [RFC-6698](http://tools.ietf.org/html/rfc6698) ("DANE").
247 As of this writing, the specification is under discussion.
248
249 #### ds attribute
250
251 Translates into `DS` RR. Carries attributes defined by
252 [RFC-4034](http://tools.ietf.org/html/rfc4034).
253
254 ### Lookup Sequence
255
256 Assuming a query is performed for
257 `sdN`++"."++{...}++"."++`sd2`++"."++`sd1`++"."++`dom`++".bit"
258 (`sdX` list possibly being empty), the lookup process starts by
259 querying the database for the object corresponding to `dom`.
260 Technically, it is easiest to populate a "seed" DomObj with a
261 single attribute `"import"` the value of which corresponds to the
262 `dom` name in the Namecoin namespace, which is `"d/" ++ dom`.
263 This domain object is then transformed by the following
264 recursive sequece:
265
266 1. Value of the element of the `"map"` attribute with the key `""`
267    (empty string) is recursively merged into the base domain. The
268    `""` element of the `"map"` is removed from the result.
269 2. If attribute `"delegate"` does not exist in the resulting object,
270    step 3 is is performed. If attribute `"delegate"` exists, in
271    the resulting object, lookup is performed for the values of this
272    attribute, and fetched object replaces the base domain completely.
273    The result is passed as base domain to step 1.
274 3. If attribute `"import"` does not exist in the resulting object,
275    recursion stops, and step 4 is performed on the result
276    If attribute `"import"` exists in the resulting object, lookup is
277    performed for the values of this attribute, and fetched objects
278    are recursively merged into the base domain. The `"import"`
279    attribute is removed from the result. Then the result is passed
280    as base domain to step 1.
281 4. If subdomain chain is empty, recursion stops, and step 5 is
282    performed on the result. If subdomain chain is not empty, next
283    element is taken out of the chain, and the `"map"` is looked
284    up for the element with the name matching the subdomain element.
285    The value of this element of the `"map"` is passed as base domain
286    to step 1. If matching element does not exist, lookup is considered
287    failed.
288 5. Domain object in which all `""` map elements and all `"delegate"`
289    and `"import"` elements are acted upon and removed, is then
290    "normalized" by removal of attributes that are nullified by the
291    presence of other attributes.
292
293 Note that the process involves recursion nested to three levels.
294
295 ### Merging Procedure
296
297 When a domain object `extra` needs merging into a domain object `base`,
298 the following rules are applied:
299
300 * Of `String` and other "scalar" attributes, one is chosen, the value
301   from the `base` taking precedence.
302 * On `Array` attribtes, `union` operation is performed. (Of equal
303   elements, only one copy is left.)
304 * On `Map` attributes, recursive merge is performed. On the top level,
305   elemens with keys that are only present in either `base` or `extra`
306   object are all put into result. The values of the elements that are
307   present in both `base` and `extra` objects are merged according to
308   the rules applicable to their type.
309