1 % JSON Domain Format as Implemented by Pdns-Pipe-Nmc
3 This document is based on
4 [Namecoin Domain Name Specification](https://wiki.namecoin.info/index.php?title=Domain_Name_Specification).
5 It tries to follow it closely, and clarify parts that are not
6 specified, or specified ambiguously, in the original document.
8 One notable deviation is the specification of `"delegate"` and `"import"`
9 attributes: domain objects to which their value point are
10 replacing/merging to the domain object in which they are defined.
11 This seems to be in line with at least one existing "real world"
14 This specification is implemented by the `pdns-pipe-nmc` program.
20 `DomObj` is a data structure that is associated with an FQDN. It is
21 either a `String` containing a dotted quad (see Note below), or a
22 JSON `Map`, with the following attributes, all optional:
24 | Key | Type | Comment |
25 |-------------|---------------------------------------|--------------------------------------------|
26 | service | Array(SrvObj) | Located two levels above position |
27 | ip | Array(String) | Dotted quad format "1.2.3.4" |
28 | ip6 | Array(String) | Semicolon format "DEAD::BEEF" |
29 | tor | String | Onion name |
31 | freenet | String | |
32 | alias | String | Nullifies other attributes |
33 | translate | String | Nullifies the "map" attribute |
34 | email | String | Used in `SOA` |
35 | loc | String | Format suitable for `LOC` |
36 | info | JsonObj | Currently unspecified |
37 | ns | Array(String) | Domain names as in `NS` |
38 | delegate | String | Replaces current object |
39 | import | Array(String) | "Deep" merges into current object |
40 | map | Map(String:DomObj) | Tree of subdomain objects |
41 | fingerprint | Array(String) | |
42 | tls | Map(String:Map(String:Array(TlsObj))) | Outer `Map` by `Protocol`, inner by `Port` |
43 | ds | Array(DsObj) | |
47 * Any attribute specified as `Array(String)` may be present in the
48 JSON document as a plain `String`, which is interpreted the same way
49 as an `Array` containing a single `String` element. In other words,
50 `"ip":"1.2.3.4"` is equivalent to `"ip":["1.2.3.4"]`. (This does not
51 apply to non-string-array attributes, like "service" or "ds".)
52 * If `DomObj` is a `String`, it is interpreted as an IPv4 address.
53 In other words, string `"1.2.3.4"` is the same as the Map
54 `"{\"ip\":\"1.2.3.4\"}"`. Such "shorthand" DomObj can be present at
55 the top level or as a value in the `"map"` attribute.
59 `SrvObj` is a heterogenous Array of fixed size containing 6 elements:
61 | N | Type | Meaning |
62 |---|--------|----------|
63 | 0 | String | Service |
64 | 1 | String | Protocol |
65 | 2 | Int | Priority |
72 * `Service` and `Protocol` are two elements of the domain name, without
74 * `SrvObj` with Service `"smtp"`, Protocol `"tcp"` and Port `25` is also
75 interpteted as an `MX` DNS resource at the domain level containing the
77 * When lookup is performed for `SRV` records at fqdn
78 `"_serv._proto.sub.dom.bit"`, domain object for `"sub.dom.bit"` must be
79 fetched, and in this object, `SrvObj`s for the Service `"serv"` and
80 Protocol `"proto"` selected from its `"service"` attribute.
84 `TlsObj` is a heterogenous Array of fixed size containing 3 elements:
86 | N | Type | Meaning |
87 |---|--------|-------------------------------------------------------|
88 | 0 | Int | Match type - 0:Exact, 1:SHA-256, 2:SHA-512 |
89 | 1 | String | Match value - certificate or hash of it as hex string |
90 | 2 | Int | Include subdomains - 0:No, 1:Yes |
94 * The fields of the object correspond to the attributes defined by
95 [RFC-6698](http://tools.ietf.org/html/rfc6698) ("DANE").
99 `DsObj` is a heterogenous Array of fixed size containing 4 elements:
101 | N | Type | Meaning |
102 |---|--------|--------------------------|
103 | 0 | Int | Key Tag |
104 | 1 | Int | Key Algorithm |
105 | 2 | Int | Hash Type |
106 | 3 | String | Hash Value as hex string |
110 * The fields of the object correspond to the attributes defined by
111 [RFC-3658](http://tools.ietf.org/html/rfc3658).
113 ## Data Interpretation
115 ### Semantics of the Attributes
117 #### service attribute
119 Translates to DNS `SRV` RR, only it is located in the subdomain tree
120 two levels higher than the `SRV` record would. For example, a
121 `"service"` attribute in the `"map"` hieararchy at the point
122 corresponding to the FQDN "sub.dom.bit" with the value
125 "service": [ ["imap", "tcp", 0, 0, 143, "mail.host.com" ],
126 ["smtp", "tcp", 0, 0, 25, "relay.host.com"] ]
129 corresponds to two `SRV` RRs at two different points in the
133 _imap._tcp.sub.dom.bit. IN SRV 0 0 143 mail.host.com.
134 _smtp._tcp.sub.dom.bit. IN SRV 0 0 25 relay.host.com.
137 In addition to these, an `MX` RR is syntesized at the "sub.dom.bit"
141 sub.dom.bit. IN MX 0 relay.host.com.
144 Note: Hostname element **must** be specified as fully qualified domain
145 name of the host, and **must not** terminate with a dot.
146 This requirement seems to be in line with many existing definitions in
147 the blockchain; however it deviates from the BIND zone file format, in
148 which names that have not terminating dot are automatically expanded
149 by attaching the current origin zone to the end of the name.
153 Contains a list of strings representing IPv4 addresses in dotted
154 quad notation. For example,
157 "ip": ["1.2.3.4", "5.6.7.8"]
160 translates into a series of `A` RRs:
169 Contains a list of strings representing IPv6 addresses in semicolon
170 quads notation. For example,
173 "ip6": ["2001:4860:0:1001::68"]
176 translates into one AAAA RR:
179 IN AAAA 2001:4860:0:1001::68
184 Does not translate into any DNS RR. Contains Tor hidden service address.
187 "tor": "eqt5g4fuenphqinx.onion"
192 Does not translate into any DNS RR. It is a JSON Map with three
193 optional String attributes: `"destination"`, `"name"` and `"b32"`.
196 "i2p": { "destination": "XaZscx...0jGAAAA"
197 , "name": "example.i2p"
198 , "b32" : "ukeu...nkdq.b32.i2p"
202 #### freenet attribute
204 Does not translate into any DNS RR. Contains Freesite key.
207 "freenet": "USK@0I8g...xbZ4,AQACAAE/Example/42/"
212 Translates into `CNAME` RR. Invalidates all other attributes.
215 "alias": "realhost.example.bit"
219 * Hostname **must** be specified as fully qualified domain
220 name of the host, and **must not** terminate with a dot.
221 * Element of the `"map"` with empty key, `"delegate"` and `"import"`
222 are processed before this invalidation takes place.
224 #### translate attribute
226 Translates into `DNAME` RR. Invalidates the contents of the `"map"`
230 "translate": "otherhost.bit"
234 * Hostname **must** be specified as fully qualified domain
235 name of the host, and **must not** terminate with a dot.
236 * Element of the `"map"` with empty key, `"delegate"` and `"import"`
237 are processed before this invalidation takes place.
241 Translates into the `email` element of the SOA and RP RRs. The
242 value `"email":"user@domain.tld"` becomes `user.domain.tld.`
246 "email": "hostmaster@example.bit"
251 Translates into `LOC` RR. Value must conform to the format defined
252 by [RFC-1876](http://tools.ietf.org/html/rfc1876).
255 "loc": "46 31 18.000 N 6 34 26.000 E 401.00m 1m 10000m 10m"
260 Does not translate into any DNS RR. Contains a JSON object with
261 format unspecified at the time of this writing. Intented for
262 the registrant information.
266 Translates into `NS` RR. Because it effectively delegates all
267 control over the domain to external nameservers, it also invalidates
268 all other attributes.
271 "ns": ["ns.myserver.net", "192.168.3.4"]
275 * Hostname **must** be specified as fully qualified domain
276 name of the host, and **must not** terminate with a dot.
277 * Element of the `"map"` with empty key, `"delegate"` and `"import"`
278 are processed before this invalidation takes place.
280 #### delegate attribute
282 Does not translate into any DNS RR. Instead, the value is used as
283 a key for namecoin lookup (i.e. the value must be specified with
284 the namespace prefix), and the result of the lookup replaces all
288 "delegate": "s/example74845"
292 * Element of the `"map"` with empty key, `"delegate"` and
293 `"import"` are processed before this invalidation takes place.
294 * Unlike many other attributes, this can only contain a single
295 string as the value, rather than a list.
297 #### import attribute
299 Does not translate into any DNS RR. Instead, the value is used as
300 the key for namecoin lookup (i.e. the value must be specified with
301 the namespace prefix), and the result of the lookup is merged with
302 the current domain object.
305 "import": ["dd/example", "s/example6473"]
310 JSON Map object containing subdomain names as its keys and domain
311 objects as values. Element of the map with empty key "" has special
312 meaning: the value of this map element is merged into the current
313 domain object. This operaton happens first when a new domain object
314 is analyzed, and is performed recursively. In the result of the
315 merge, the `"map"` does not contain the element with empty key.
316 Further operatons that can potentially modify the contents of the
317 current domain object (`import` and `delegate` lookups) start when
318 the empty element of the `"map"` has been recursively merged into
322 "map": { "www": { "alias" : "www.example.com" }
323 , "www2": { "delegate": "d/example" }
327 Note: When a key contains dots ".", it is converted to a nested
328 map. If empty element appears as a result of split, such as when
329 a dot is at the beginning or at the end of the key, or there are
330 consequitive dots, such elemets are ignored. For example,
333 "map": { "www.uk": { "alias" : "www.example.co.uk" }
334 , "www..us": { "alias" : "www.example.com" }
335 , "smtp.us.": { "alias" : "smtp.example.com" }
341 "map": { "uk": { "map": { "www": { "alias" : "www.example.co.uk" }}}
342 , "us": { "map": { "www": { "alias" : "www.example.com" }
343 , "smtp": { "alias" : "smtp.example.com" }}
348 #### fingerprint attribute
350 Does not translate into any DNS RR. Contains a list of TLS
351 certificate fingerprints. Deprecated.
355 Intended to carry attributes as per
356 [RFC-6698](http://tools.ietf.org/html/rfc6698) ("DANE").
361 { "443": [ [1, "660008F9...7621B787", 1] ]
362 , "25": [ [1, "660008F9...7621B787", 1] ]
371 _443._tcp TLSA (3 0 1 660008F9...7621B787)
372 _25._tcp TLSA (3 0 1 660008F9...7621B787)
375 The third element of the `TlsObj` heterogenous array is an extention
376 to the DANE definition. Value `0` means that this rule is not enforced
377 upon subdomains, value `1` means that it is enforced on subdomains.
378 Rule defined inside a subdomain `DomObj` that specifies `0` on a rule
379 existing in upper domain, that specifies `1` should be ignored. I.e.
380 subdomain rule cannot revoke enforcement imposed by an upper domain rule.
384 Translates into `DS` RR. Carries attributes defined by
385 [RFC-4034](http://tools.ietf.org/html/rfc4034).
388 "ds": [ [31381,8,1,"pA1W...ceTI="]
389 , [31381,8,2,"toHB...ndexitQ6j8E="]
395 Assuming a query is performed for
396 `sdN`++"."++{...}++"."++`sd2`++"."++`sd1`++"."++`dom`++".bit"
397 (`sdX` list possibly being empty), the lookup process starts by
398 querying the database for the object corresponding to `dom`.
399 Technically, it is easiest to populate a "seed" DomObj with a
400 single attribute `"import"` the value of which corresponds to the
401 `dom` name in the Namecoin namespace, which is `"d/" ++ dom`.
402 This domain object is then transformed by the following
405 1. Value of the element of the `"map"` attribute with the key `""`
406 (empty string) is recursively merged into the base domain. The
407 `""` element of the `"map"` is removed from the result.
408 2. If attribute `"delegate"` does not exist in the resulting object,
409 step 3 is is performed. If attribute `"delegate"` exists, in
410 the resulting object, lookup is performed for the values of this
411 attribute, and fetched object replaces the base domain completely.
412 The result is passed as base domain to step 1.
413 3. If attribute `"import"` does not exist in the resulting object,
414 recursion stops, and step 4 is performed on the result
415 If attribute `"import"` exists in the resulting object, lookup is
416 performed for the values of this attribute, and fetched objects
417 are recursively merged into the base domain. The `"import"`
418 attribute is removed from the result. Then the result is passed
419 as base domain to step 1.
420 4. If subdomain chain is empty, recursion stops, and step 5 is
421 performed on the result. If subdomain chain is not empty, next
422 element is taken out of the chain, and the `"map"` is looked
423 up for the element with the name matching the subdomain element.
424 The value of this element of the `"map"` is passed as base domain
425 to step 1. If matching element does not exist, lookup is considered
427 5. Domain object in which all `""` map elements and all `"delegate"`
428 and `"import"` elements are acted upon and removed, is then
429 "normalized" by removal of attributes that are nullified by the
430 presence of other attributes.
432 Note that the process involves recursion nested levels deep.
434 ### Merging Procedure
436 When a domain object `extra` needs merging into a domain object `base`,
437 the following rules are applied:
439 * Of `String` and other "scalar" attributes, one is chosen, the value
440 from the `base` taking precedence.
441 * On `Array` attribtes, `union` operation is performed. (Of equal
442 elements, only one copy is left.)
443 * On `Map` attributes, recursive merge is performed. On the top level,
444 elemens with keys that are only present in either `base` or `extra`
445 object are all put into result. The values of the elements that are
446 present in both `base` and `extra` objects are merged according to
447 the rules applicable to their type.