diff --git a/archive.json b/archive.json new file mode 100644 index 0000000..98db2ae --- /dev/null +++ b/archive.json @@ -0,0 +1,1224 @@ +{ + "magic": "E!vIA5L86J2I", + "timestamp": "2021-10-26T00:09:03.810894+00:00", + "repo": "anr-bmbf-pivot/draft-dns-over-coap", + "labels": [ + { + "name": "bug", + "description": "Something isn't working", + "color": "d73a4a" + }, + { + "name": "documentation", + "description": "Improvements or additions to documentation", + "color": "0075ca" + }, + { + "name": "duplicate", + "description": "This issue or pull request already exists", + "color": "cfd3d7" + }, + { + "name": "enhancement", + "description": "New feature or request", + "color": "a2eeef" + }, + { + "name": "help wanted", + "description": "Extra attention is needed", + "color": "008672" + }, + { + "name": "good first issue", + "description": "Good for newcomers", + "color": "7057ff" + }, + { + "name": "invalid", + "description": "This doesn't seem right", + "color": "e4e669" + }, + { + "name": "question", + "description": "Further information is requested", + "color": "d876e3" + }, + { + "name": "wontfix", + "description": "This will not be worked on", + "color": "ffffff" + } + ], + "issues": [ + { + "number": 1, + "id": "MDU6SXNzdWU5NjM4NTYwODA=", + "title": "Create OSCORE section", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/issues/1", + "state": "OPEN", + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "assignees": [ + "chrysn" + ], + "labels": [ + "enhancement" + ], + "body": "It *probably* doesn't need to say much more than that it largely does the same as DTLS with the respective security considerations applied -- and that applications can just use whatever they already ship code for.\r\n\r\nPotential aspects to point out for the reader's convenience:\r\n* It's relatively cheap to have a dedicated security context for DNS separate from other applications, making it easy to separate privileges on the server side. In such cases, the URI path that lends itself to the application is `/` as that makes the most compact requests.\r\n* ... anything else?", + "createdAt": "2021-08-09T10:29:10Z", + "updatedAt": "2021-08-10T10:05:50Z", + "closedAt": null, + "comments": [ + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> * ... anything else?\r\n\r\nCan we validate server identity with OSCORE? If not, DTLS+OSCORE still has a use case that should be mentioned (given of course DTLS is used in a mode where the server identity can be validated ;-)).", + "createdAt": "2021-08-10T09:03:29Z", + "updatedAt": "2021-08-10T09:03:29Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "> Can we validate server identity with OSCORE?\n\nYes; that's determined at setup time. (For example, when established\nthrough EDHOC, the client has authenticated the server from a\ncertificate or a known RPK).\n\n(Server identity is even validated in group mode).\n", + "createdAt": "2021-08-10T10:05:50Z", + "updatedAt": "2021-08-10T10:05:50Z" + } + ] + }, + { + "number": 2, + "id": "MDU6SXNzdWU5NjM4NjEyNTQ=", + "title": "Is it practical to have the GET version altogether?", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/issues/2", + "state": "CLOSED", + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "All I've found so far on why there's both the GET and the POST version of DoH in HTTP is that GETs are cachable.\r\n\r\nIn CoAP, we have [FETCH](https://datatracker.ietf.org/doc/html/rfc8132), which is just there for cases like this, and does away with both contender's downsides:\r\n* Compared to POST, it's cachable (and safe and thus idempotent)\r\n* Compared to GET, it doesn't need\r\n * URI template handling (which I'd discourage in an embedded context -- it's reasonably simple here, but I wouldn't want to have to think of the different rules that'd apply if the template occurs in the path or query string), and\r\n * base64 encoding (which adds both processing and wire overhead).\r\n\r\nThe only upside I see of keeping GET/POST over FETCH is that DoC could then be implemented by just cross-proxying to a DoH server, but given that such a proxy is unconstrained, reasonably straightforward to implement on its own and can thus take load off the constrained client, I advocate going all FETCH.", + "createdAt": "2021-08-09T10:36:35Z", + "updatedAt": "2021-10-22T12:53:38Z", + "closedAt": "2021-10-22T12:53:38Z", + "comments": [ + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "I was also thinking about getting rid of GET. However, apart from the cross-proxying argument you gave, I also wanted to provide a method for \"legacy CoAP\" (so a CoAP implementation where FETCH is not implemented).\r\n\r\nBut then again, FETCH-support is relatively easy to deploy on the client side (you literally just need to provide the number for it). Mhh...", + "createdAt": "2021-08-09T11:08:38Z", + "updatedAt": "2021-08-09T11:08:38Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> * URI template handling (which I'd discourage in an embedded context -- it's reasonably simple here, but I wouldn't want to have to think of the different rules that'd apply if the template occurs in the path or query string), and\r\n\r\nIMHO a URI template processor does not need to have more complexity than say a URI parser (which in some cases we need with CoAP). The one [I provided for RIOT](https://github.com/RIOT-OS/RIOT/pull/16702) takes ~400 bytes of ROM on a Cortex-M0. Once that's there, the question of adding a URI-Query option is just a matter of checking if the `dns` query is there or not when the URI template is resolved.", + "createdAt": "2021-08-09T11:13:06Z", + "updatedAt": "2021-08-09T11:13:41Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "There haven't been implementer complaints about FETCH in 2019 when\nOSCORE was finalized, which indicates that FETCH was indeed simple to\nsupport.\n\n> IMHO a URI template processor does not need to have more complexity\n> than say a URI parser (which in some cases we need with CoAP).\n\nI have hopes that many CoAP clients can do without a URI parser when the\nefforts of CoRAL and [CRI](https://datatracker.ietf.org/doc/draft-ietf-core-href/) bear fruit.\n\n> The one [I provided for\n> RIOT](https://github.com/RIOT-OS/RIOT/pull/16702) takes ~400 bytes of\n> ROM on a Cortex-M0. Once that's there the question of adding a\n> URI-Query option is just a matter of checking if the `dns` query is\n> there or not when the URI template is resolved.\n\nThat does indeed look like a comprehensive implementation testing for\nseveral of the pitfalls. But it's still 400 byte (and a lot of\ncode-to-be-maintained), and compatibility dangers from implementers who\ndon't go all the way but just `s/{?dns}/?dns=$QUERY/` because that's all\nthey've ever seen -- especially when the alternative is so much easier.\n", + "createdAt": "2021-08-09T11:37:38Z", + "updatedAt": "2021-08-09T11:37:38Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "Another drawback of GET (as [pointed out in the current draft version](https://github.com/anr-bmbf-pivot/draft-dns-over-coaps/blob/f5950cf75af68c6a4addec55942b76573aac27ec/draft-lenders-dns-over-coaps.md#dns-queries-in-coap-requests)) is that with it block-wise transfer is not possible with large requests.", + "createdAt": "2021-08-10T06:18:32Z", + "updatedAt": "2021-08-10T06:18:32Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "Ok, I think we agree for now that in the long run, we should remove GET and POST. However, at least for version `-00` of the draft I would like to keep it in for two reasons: a) to document our thought process for posterity and b) in case we find a use case that requires GET and need to revert back to the current version of CoAP messaging. I documented the future removal of GET and POST by linking this issue in the future Change Log section in https://github.com/anr-bmbf-pivot/draft-dns-over-coaps/commit/a8dcfd4ab3087682aa2191169ff2cb93554b4616. ", + "createdAt": "2021-08-10T08:40:38Z", + "updatedAt": "2021-08-10T08:41:11Z" + }, + { + "author": "waehlisch", + "authorAssociation": "MEMBER", + "body": "Do we have an overview of `FETCH` support in CoAP implementations?", + "createdAt": "2021-08-10T09:04:48Z", + "updatedAt": "2021-08-10T09:04:48Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "I don't; Francesca and I started [preparing a survey](https://github.com/core-wg/wiki/wiki/Implementations-overview), but didn't even finish the requirements.", + "createdAt": "2021-08-10T09:30:52Z", + "updatedAt": "2021-08-10T09:30:52Z" + }, + { + "author": "waehlisch", + "authorAssociation": "MEMBER", + "body": "oops, ... then we do a brief survey offline. we need an overview, which implementation supports `FETCH`, for example.", + "createdAt": "2021-08-10T09:37:31Z", + "updatedAt": "2021-08-10T09:37:31Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "If it's a helpful data point: In all the interops and implementation discussions around OSCORE that I can remember (and I've been in many of them), never has any implementer complained about the use of FETCH that'd have kept them from using OSCORE with that library.", + "createdAt": "2021-08-10T09:40:14Z", + "updatedAt": "2021-08-10T09:40:14Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> oops, ... then we do a brief survey offline. we need an overview, which implementation supports FETCH, for example.\r\n\r\nIs that really necessary? As [mentioned above](https://github.com/anr-bmbf-pivot/draft-dns-over-coaps/issues/2#issuecomment-895136457), adding `FETCH` support is just a matter of adding a FETCH = 5 constant and using it in an application in accordance with RFC 8132. Checking all implementations in [the list](http://coap.technology/impls.html) if they do that, on the other hand, seems like much more work.", + "createdAt": "2021-08-10T09:42:52Z", + "updatedAt": "2021-08-10T09:45:13Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "The only nodes where FETCH is interesting is at proxies that cache. Here an (equally minor) adaptation needs to be made, that the payload of a FETCH request is considered for the cache key.", + "createdAt": "2021-08-10T09:46:35Z", + "updatedAt": "2021-08-10T09:46:35Z" + }, + { + "author": "waehlisch", + "authorAssociation": "MEMBER", + "body": "hard to follow. will talk offline.", + "createdAt": "2021-08-10T13:28:39Z", + "updatedAt": "2021-08-10T13:28:39Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> Is that really necessary? As [mentioned above](https://github.com/anr-bmbf-pivot/draft-dns-over-coaps/issues/2#issuecomment-895136457), adding `FETCH` support is just a matter of adding a FETCH = 5 constant and using it in an application in accordance with RFC 8132. Checking all implementations in [the list](http://coap.technology/impls.html) if they do that, on the other hand, seems like much more work.\r\n\r\nRegardless, I looked a bit into this, and the data is a bit crushing. Of the 19 implementations I looked into so far, only 6 support FETCH. Granted, most of these implementations haven't received an update in years (many last before the publication of RFC8132), but even some implementations I would call reference implementations such as Erbium (in all its flavors known to me, Contiki, Contiki-NG, and Wakaama) do not support FETCH. :confused: ", + "createdAt": "2021-08-11T13:30:32Z", + "updatedAt": "2021-08-11T13:30:32Z" + } + ] + }, + { + "number": 4, + "id": "MDU6SXNzdWU5NjM5OTY0MTM=", + "title": "Request text duplication", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/issues/4", + "state": "OPEN", + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "Using the application/dns-message format means following general DNS practice that the request is more or less echoed in the response. (The queries are part of the response). This makes sense in DNS where there's only the transaction ID, but less so in CoAP where there's cryptographic request/response protection.\r\n\r\nAre there any mechanisms of DNS that'd allow us to elide the queries from the response?\r\n\r\nIf so, I suggest we recommend them with some level of normativity.\r\n\r\nIf not, then this probably won't change short of using alternative serializations (which I understand to be in scope for add-ons in this document), but should be pointed out, stating that wire efficiency is traded here for cognitive (transferring established DNS concepts) and implementation (where responses are fed to a local DNS-ish processor) complexity.", + "createdAt": "2021-08-09T13:27:09Z", + "updatedAt": "2021-09-07T11:22:54Z", + "closedAt": null, + "comments": [ + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "Looking a bit deeper into how DNS packets are made up, I learned that there is internal lookup compression used when a name's text starts with 0b11 (where otherwise there are zeros from a label being less than 64 byte long). I found no specification that'd describe other use of other patterns there (say, a 0b01 that'd indicate a string offset in the request rather the response), so probably there's no such specification and we fall to the \"If not\" branch.\r\n\r\n(It would barely pay to send responses without the requests without such cross-references, as without the internal lookup the response records would just again contain all the long text from the requests).", + "createdAt": "2021-08-09T13:51:38Z", + "updatedAt": "2021-08-09T13:51:38Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "One could just set `qdcount` field of a DNS response to 0 and not include the question section. All information needed to figure out to what question the record is an answer for should be present in the answer section. However, any change to the message format makes the implementation of a simple DoC-to-DNS-proxy more complicated. Currently such a proxy would only need to replace the transaction ID of the DNS query and response (in case the client implementation decides to honor the SHALL on setting that field to 0 for cache-friendlyness) as the only modification to the DNS messages.", + "createdAt": "2021-08-09T13:59:06Z", + "updatedAt": "2021-08-09T13:59:06Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "With the compression inside the response, that alone won't do much good; it'd turn a response that currently has a `c0 xx` name reference into one that repeats the name just again.\r\n\r\nAs for implementation complexity, the nice thing about application/dns-message is that a simpler server can just not do any of these tricks -- but alas, there seem to be no existing viable tricks.", + "createdAt": "2021-08-09T14:23:40Z", + "updatedAt": "2021-08-09T14:23:40Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "So the question is if we should skip `application/dns-message` altogether in the draft opting for a more compressed format or to move the latter to a follow-up draft. In my opinion, we should stick to `application/dns-message` for now, point out the drawbacks and add considerations on a later format (e.g. based on CBOR).", + "createdAt": "2021-08-10T08:08:45Z", + "updatedAt": "2021-08-10T08:08:45Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "I agree with you. As we can't do anything *within the existing* dns-message (that we can recommend or even make mandatory), all this becomes just a point to be documented. Text suggestion:\r\n\r\n> For a CoAP based protocol, the use of application/dns-message is suboptimal: The requested names are sent in the response, even though the protocol and its security mechanisms provide strong request-response bindings that this information could be implied.\r\n> The message format is used nonetheless because its ease of integration with existing DNS applications. Alternative media types can be used that perform better on the wire, but they can not be expected to be supported by DoC servers unless advertised.\r\n> Note that just leaving the question section of the response empty would do little for the message sizes, as the names are part of the response. They are usually compressed using the DNS format's internal message compression ({{rfc1035}} Section 4.1.4), so eliding questions would just make larger answers.\r\n\r\nAlternative formats (either DNS serialized in CBOR with consideration for request-response binding, or even more getaddrinfo-like subsets of DNS) can still be added later on, in follow-ups or appendices, and be optional and to-be-negotiated.", + "createdAt": "2021-08-10T08:29:24Z", + "updatedAt": "2021-08-10T08:29:24Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": ">> The message format is used nonetheless because its ease of integration with existing DNS applications. Alternative media types can be used that perform better on the wire, but they can not be expected to be supported by DoC servers unless advertised.\r\n\r\n\"[\u2026] existing DNS applicaitons *and use cases*.\", I would say, but otherwise it makes sense to add this. Question is where.\r\n", + "createdAt": "2021-08-10T08:34:59Z", + "updatedAt": "2021-08-10T08:34:59Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "> Question is where\r\n\r\nThat's why this is not a PR ;-) -- I'll just try to keep it in mind while the document grows and place it when the right point presents itself.", + "createdAt": "2021-08-10T08:47:13Z", + "updatedAt": "2021-08-10T08:47:13Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "[RFC 8427](https://datatracker.ietf.org/doc/html/rfc8427) (Representing DNS Messages in JSON) could be of interest when it comes to other serialization formats of DNS messages ;-).", + "createdAt": "2021-09-07T11:22:54Z", + "updatedAt": "2021-09-07T11:22:54Z" + } + ] + }, + { + "number": 5, + "id": "MDU6SXNzdWU5NjQwNDQ3NjE=", + "title": "TTL vs. Max-Age", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/issues/5", + "state": "OPEN", + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "Interpreting times relative to a cached request's request time is tricky, and AFAIK there is no good precedent in CoRE. ([SenML](https://www.rfc-editor.org/rfc/rfc8428.html) speaks of 'roughly \"now\"', without talking about Max-Age). Trouble arises when there's an application-unaware caching proxy on the line (which is generally to be expected).\r\n\r\nThe simple thing to do (and I think that's the direction currently taken, but just not in text or I missed it) is that clients generally ignore the stated DNS lifetimes, and only use the request for Max-Age. The downside here is that a) information about longer-lived parts of the response is lost (not sure if that's an issue), and b) that the response can't be plugged as-is into a local DNS system (for that'd see the times and happily cache for 5 more minutes, even though the response may have been sitting in a cache for almost that time).\r\n\r\nOptions IMO are:\r\n* State that we want it to behave like this, and that any client is to consider all lifetimes in the response clamped to Max-Age.\r\n* About the same, but ask it from the server. (\"MUST NOT set a longer Max-Age than the shortest lifetime, and MUST zero all lifetimes\").\r\n* (Most complex server-side, but still easy to use minimally on the client and IMO most powerful) Interpret all times relative to the expiry of the cache, and ask DoC servers to pick a Max-Age such that the smallest lifetime become zero (or as small as practical).\r\n This allows an unaware cache (typically in a proxy) to keep the response available for as long as it is usable, and still allows aware clients to push the limits.\r\n\r\nIf you even want to explore the 3rd option, I can start a discussion on core@ietf.org on whether taking the max-age expiry as a reference point is a practical pattern.", + "createdAt": "2021-08-09T14:16:45Z", + "updatedAt": "2021-08-10T11:59:38Z", + "closedAt": null, + "comments": [ + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "In [DoH](https://datatracker.ietf.org/doc/html/rfc8484#section-5.1) this is accounted for by using the Age header.\r\n\r\n> [RFC7234] when calculating the DNS TTL of a response. For example,\r\n> if an RRset is received with a DNS TTL of 600, but the Age header\r\n> field indicates that the response has been cached for 250 seconds,\r\n> the remaining lifetime of the RRset is 350 seconds. This requirement\r\n> applies to both DoH client HTTP caches and DoH client DNS caches.\r\n\r\nCouldn't we do something similar with `Max-Age`? If `Max-Age` is lesser than the smallest TTL in the response, the difference between that smallest TTL and the `Max-Age` option value must be subtracted from all TTLs in the DNS response by the client.", + "createdAt": "2021-08-09T14:45:32Z", + "updatedAt": "2021-08-09T14:51:16Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "I think that'd amount to the same thing, and may be easier to implement. Asking on core@ for experience there.", + "createdAt": "2021-08-09T14:49:23Z", + "updatedAt": "2021-08-09T14:49:23Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "I'd assume that it's easier for a client to add Max-Age than to traverse all records to find the difference, but let's see what CoRE says.", + "createdAt": "2021-08-09T14:59:58Z", + "updatedAt": "2021-08-09T14:59:58Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "See also https://mailarchive.ietf.org/arch/msg/core/CzRQTARwPgIwJN0s_kmlLRCNMKY", + "createdAt": "2021-08-09T15:05:47Z", + "updatedAt": "2021-08-09T15:05:47Z" + }, + { + "author": "ektrah", + "authorAssociation": "NONE", + "body": "@chrysn makes a good point about application-unaware caching proxies on the path. I guess, as soon as you have multiple such proxies involved that all do their own Max-Age and ETag processing, any kind of time indications relative to the time of a request (that is not visible to the whole chain of proxies) or a response (that may have been cached for a while and then validated via ETag) become pretty meaningless...\r\n\r\nWhile DNS resolvers can update responses on the granularity of record, the caching in CoAP really revolves around avoiding the transmission of whole responses (either by reusing a previous response from a cache because it\u2019s still valid for the same request or because it can be quickly validated to be still valid).\r\n\r\nMaybe it would be possible to define a FETCH format where the client states what is has and what is missing, so that the server can \u201cpatch\u201d the information the client already has, but that sounds like a lot of work to specify. IMHO, the easiest solution would be to acknowledge that DNS over CoAP isn\u2019t as powerful and efficient as the original DNS protocol (whole-response caching only) and to optimize the whole thing for use cases where using the original DNS protocol isn\u2019t feasible (\u201cbetter this than nothing\u201d).\r\n\r\nOver OSCORE, this would mean that there\u2019s no caching happening on the path between the client and the origin server. Over everything else, this would mean any non-absolute time information in representations is meaningless.", + "createdAt": "2021-08-10T11:59:38Z", + "updatedAt": "2021-08-10T11:59:38Z" + } + ] + }, + { + "number": 6, + "id": "MDU6SXNzdWU5NjQxNDE0NjI=", + "title": "Retransmission Issue", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/issues/6", + "state": "OPEN", + "author": "cgundogan", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": ">General CoAP proxy problem, but what to do when DoC server is a DNS proxy, response came not yet in but retransmission by DoC client was received\r\n\r\nThe CoAP spec does not really flesh out \"corner cases\" of certain proxy operations. In previous work, we addressed this retransmission issue in two different ways:\r\n\r\n1. a proxy immediately sends an empty response, thereby stopping the retransmission of the DoC client. Any (later) response from the proxy SHOULD then be confirmable.\r\n2. a proxy keeps request state and aggregates request retransmissions from downstream (similar to what NDN is doing). Therefore, no additional retransmissions propagate upstream.", + "createdAt": "2021-08-09T15:58:56Z", + "updatedAt": "2021-08-10T10:17:38Z", + "closedAt": null, + "comments": [ + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "\"General CoAP proxy problem\" ... well, that's exactly what empty ACKs do and are designed for. Depending on the complexity of the proxy, the ACK can be sent right away, or a bit later depending on the retransmission characteristics. Working with CONs without keeping state isn't much of an option anyway.", + "createdAt": "2021-08-09T16:02:59Z", + "updatedAt": "2021-08-09T16:02:59Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "Then this might not be a problem at all. Do we want to remove that TBD then?", + "createdAt": "2021-08-10T09:18:55Z", + "updatedAt": "2021-08-10T09:18:55Z" + }, + { + "author": "cgundogan", + "authorAssociation": "COLLABORATOR", + "body": "While `empty ACKs are designed for it`, I think there is no proper explanation in the CoAP spec (w.r.t. proxy operation). Would probably be helpful to mention the empty ACK usage for this specific use case in this draft. Maybe as appendix on \"best practices\".", + "createdAt": "2021-08-10T09:33:23Z", + "updatedAt": "2021-08-10T09:33:43Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "The CoAP spec doesn't talk about it because it's nothing that is particular to a proxy. Reliable and unreliable transmission are things handled hop-by-hop, so as far as the proxy case is concerned, it is \"just\" a server that doesn't know precisely when it will have a response ready.\r\n\r\nI do see value in pointing these things out as matters of best practice, possibly in this document (that is, unless there is a better suited document around, say \"lightweight implementation guidance for CoAP proxies\").", + "createdAt": "2021-08-10T10:11:55Z", + "updatedAt": "2021-08-10T10:11:55Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "In the meantime [I added a bullet point](https://github.com/anr-bmbf-pivot/draft-dns-over-coaps/commit/6047281c3a871d3fc6d8b974de27fb400e42ca3f) to the TBD list in the proxy-section on that.", + "createdAt": "2021-08-10T10:17:38Z", + "updatedAt": "2021-08-10T10:17:38Z" + } + ] + }, + { + "number": 7, + "id": "MDU6SXNzdWU5NjQzOTc4OTU=", + "title": "overview figure", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/issues/7", + "state": "CLOSED", + "author": "waehlisch", + "authorAssociation": "MEMBER", + "assignees": [], + "labels": [], + "body": "the introduction should include an overview figure that presents all important components. the current state makes it surprisingly hard to follow. for example, reading the Introduction and then Selection of DoC Server, i doubt that the reader easily understands what a URI template is and why it is needed. a decent figure could easily close this gap. (i know that RFC 8484 is not a good poster child here.)", + "createdAt": "2021-08-09T21:19:36Z", + "updatedAt": "2021-08-10T10:38:44Z", + "closedAt": "2021-08-10T10:38:44Z", + "comments": [ + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "See d1a8674.", + "createdAt": "2021-08-10T05:56:19Z", + "updatedAt": "2021-08-10T05:56:19Z" + } + ] + }, + { + "number": 10, + "id": "MDU6SXNzdWU5ODI5NDgxNzc=", + "title": "CoRE technology dependencies", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/issues/10", + "state": "OPEN", + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "I find some text around CoRE dependencies needlessly constraining -- not without precedent in CoRE documents, but maybe we can do better.\r\n\r\nExample:\r\n\r\n> If the FETCH or POST method are used and block-wise transfer [RFC7959] is supported by the client, more than one CoAP request message MAY be used. If more than one CoAP request message is used to encode the DNS query, it must be chained together using the Block1 option in those CoAP requests.\r\n\r\nI see no good reason why CoD can't be used with any successor to the original Block options -- but this text rules it out. (Yeah it's not a normative MUST but still strong-worded).\r\n\r\nI think it'd be better for general composability of the components if we phrased this more openly; the strictness can still be in an MTI set of base things, maybe like this:\r\n\r\n> The block-wise transfer mechsnism of CoAP [RFC7959] enables the transfer of large DNS requests in FETCH and POST; DoC servers SHOULD support it. Clients MAY use any mechanism to send large requests \\, but (if they send large requests in the first place) SHOULD fall back to using Block1 if the server does not support them.\r\n\r\n(We can discuss whether these are to be SHOULDs or MUSTs, but that's not this discussion.)", + "createdAt": "2021-08-30T16:00:07Z", + "updatedAt": "2021-08-30T16:00:07Z", + "closedAt": null, + "comments": [] + } + ], + "pulls": [ + { + "number": 3, + "id": "MDExOlB1bGxSZXF1ZXN0NzA2NTEwOTgy", + "title": "Text for ETag", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/pull/3", + "state": "MERGED", + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "", + "createdAt": "2021-08-09T13:14:17Z", + "updatedAt": "2021-08-09T14:29:04Z", + "baseRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "baseRefName": "main", + "baseRefOid": "045462286afadbcacbf3ec4ad7a7dafe48733a1e", + "headRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "headRefName": "etag", + "headRefOid": "53e31c8e315e6410dbebb108c32bb2ed04e891f6", + "closedAt": "2021-08-09T14:29:00Z", + "mergedAt": "2021-08-09T14:29:00Z", + "mergedBy": "miri64", + "mergeCommit": { + "oid": "e007e87399cfba2963de64e69cd5b78efb7e4c80" + }, + "comments": [ + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "Yes, moved. (Positioning / text flow is probably not perfect, but then again, the caching/proxy chapter will likely get more structure anyway as it grows).", + "createdAt": "2021-08-09T14:20:12Z", + "updatedAt": "2021-08-09T14:20:12Z" + } + ], + "reviews": [ + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzI1MzY5MTQ0", + "commit": { + "abbreviatedOid": "85cac16" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "Now that the Caching section is [somewhat written out](https://github.com/anr-bmbf-pivot/draft-dns-over-coaps/commit/c0fed40ba3303f0dd69a81a7dfea9f9ea7532ad8), does it make sense to move it there?", + "createdAt": "2021-08-09T13:19:00Z", + "updatedAt": "2021-08-09T13:19:00Z", + "comments": [] + } + ] + }, + { + "number": 8, + "id": "MDExOlB1bGxSZXF1ZXN0NzA3NDUzMzE1", + "title": "Removal of GET and POST usage", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/pull/8", + "state": "MERGED", + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "Resolves #2.", + "createdAt": "2021-08-10T15:40:24Z", + "updatedAt": "2021-10-22T12:54:49Z", + "baseRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "baseRefName": "main", + "baseRefOid": "2020578671e000961ba9b2a45a2733641da54569", + "headRepository": "miri64/draft-dns-over-coap", + "headRefName": "rm-get-post", + "headRefOid": "a4bacc7975d3fa52b755e15b18f56fee16430f11", + "closedAt": "2021-10-22T12:53:38Z", + "mergedAt": "2021-10-22T12:53:38Z", + "mergedBy": "chrysn", + "mergeCommit": { + "oid": "14bac2882c81525f765dd02152969d477eb450ee" + }, + "comments": [ + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "I've rebased and adapted the PR to the current state in master.", + "createdAt": "2021-08-12T10:24:15Z", + "updatedAt": "2021-08-12T10:24:15Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "And another rebase. If we agree with the current state, I'd like to have this merged soon (and maybe even publish `-01` soon after).", + "createdAt": "2021-08-12T17:12:45Z", + "updatedAt": "2021-08-12T17:12:45Z" + }, + { + "author": "waehlisch", + "authorAssociation": "MEMBER", + "body": "> And another rebase. If we agree with the current state, I'd like to have this merged soon (and maybe even publish `-01` soon after).\r\n\r\nas i said earlier. i would like to have a discussion in the CoRE WG before we change this. this discussion can be kicked off after your vacation @miri64.", + "createdAt": "2021-08-12T20:31:36Z", + "updatedAt": "2021-08-12T20:31:36Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "Rebased and adapted in accordance to the points raised during the [CoRE interim](https://notes.ietf.org/notes-ietf-interim-2021-core-12-core#DNS-over-CoAP-20-min).", + "createdAt": "2021-10-13T16:39:11Z", + "updatedAt": "2021-10-13T16:39:11Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "Note to self: Need to check if the current text is contradicting the [MUST for the Content-Format option of FETCH requests](https://datatracker.ietf.org/doc/html/rfc8132#section-2.3.1).", + "createdAt": "2021-10-15T10:44:00Z", + "updatedAt": "2021-10-15T10:44:00Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> Note to self: Need to check if the current text is contradicting the [MUST for the Content-Format option of FETCH requests](https://datatracker.ietf.org/doc/html/rfc8132#section-2.3.1).\r\n\r\nAdded a clarifying half-sentence in a4bacc7975d3fa52b755e15b18f56fee16430f11.", + "createdAt": "2021-10-15T13:22:41Z", + "updatedAt": "2021-10-15T13:22:41Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "Ping? Reminder that [draft cutoff is on Monday](https://datatracker.ietf.org/meeting/important-dates/). Can this go in?", + "createdAt": "2021-10-22T10:58:33Z", + "updatedAt": "2021-10-22T10:58:33Z" + } + ], + "reviews": [ + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzI3NDMwMzEz", + "commit": { + "abbreviatedOid": "1b05ac8" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "APPROVED", + "body": "", + "createdAt": "2021-08-11T12:38:58Z", + "updatedAt": "2021-08-11T12:39:08Z", + "comments": [ + { + "originalPosition": 8, + "body": "I'm fine with this appendix, but why is PUT introduced? Unlike POST which has intentionally vague semantics, PUT has defined semantics (\"that the resource [...] be updated or created with the enclosed representation\") that don't match what's being done here.", + "createdAt": "2021-08-11T12:38:58Z", + "updatedAt": "2021-08-11T12:39:08Z" + } + ] + }, + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzI3NDM1MTAz", + "commit": { + "abbreviatedOid": "b41c7e7" + }, + "author": "waehlisch", + "authorAssociation": "MEMBER", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-08-11T12:43:50Z", + "updatedAt": "2021-08-11T12:43:51Z", + "comments": [ + { + "originalPosition": 8, + "body": "i agree that this approach could be a good compromise. but this also means that we abandon the C-H-Proxy argument right away.", + "createdAt": "2021-08-11T12:43:51Z", + "updatedAt": "2021-08-11T12:43:51Z" + } + ] + }, + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzI3NDQwMDc4", + "commit": { + "abbreviatedOid": "b41c7e7" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-08-11T12:48:38Z", + "updatedAt": "2021-08-11T12:48:38Z", + "comments": [ + { + "originalPosition": 8, + "body": "> I'm fine with this appendix, but why is PUT introduced?\r\n\r\nI guess I was in \"people might do anything if they don't get propper instructions\"-mode here. I can remove it again, if it is more distracting than useful.\r\n\r\n> but this also means that we abandon the C-H-Proxy argument right away.\r\n\r\nI was thinking about adding a sentence or two about how C-H-Proxies could be implemented in \u00a75. Of course, for this recommendations should be amended here as well then.", + "createdAt": "2021-08-11T12:48:38Z", + "updatedAt": "2021-08-11T12:48:38Z" + } + ] + }, + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzI3NDQyMDg0", + "commit": { + "abbreviatedOid": "b41c7e7" + }, + "author": "waehlisch", + "authorAssociation": "MEMBER", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-08-11T12:50:33Z", + "updatedAt": "2021-08-11T12:50:34Z", + "comments": [ + { + "originalPosition": 8, + "body": "we cannot propose C-H-Proxies in the body of the draft and specify the required building blocks in the Appendix. if we move GET to the Appendix, the proxy option is out-of-scope for the draft.", + "createdAt": "2021-08-11T12:50:34Z", + "updatedAt": "2021-08-11T12:50:34Z" + } + ] + }, + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzI3NDUwMTkx", + "commit": { + "abbreviatedOid": "b41c7e7" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-08-11T12:58:10Z", + "updatedAt": "2021-08-11T12:58:10Z", + "comments": [ + { + "originalPosition": 8, + "body": "> we cannot propose C-H-Proxies in the body of the draft and specify the required building blocks in the Appendix.\r\n\r\nThat was not what I intended. The building blocks specific to the main part of the draft would of course be specified in the main part of the draft. Recommendations specific to the appendix (such as how to handle GET/POST at a C-H-Proxy) would go to the appendix.", + "createdAt": "2021-08-11T12:58:10Z", + "updatedAt": "2021-08-11T12:58:10Z" + } + ] + }, + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzI4OTI2ODM3", + "commit": { + "abbreviatedOid": "6059e02" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "APPROVED", + "body": "", + "createdAt": "2021-08-12T18:06:25Z", + "updatedAt": "2021-08-12T18:06:25Z", + "comments": [] + } + ] + }, + { + "number": 9, + "id": "MDExOlB1bGxSZXF1ZXN0NzIyNjAzMjU0", + "title": "reword: Successful responses can't disobey Accept", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/pull/9", + "state": "MERGED", + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "", + "createdAt": "2021-08-30T15:45:17Z", + "updatedAt": "2021-10-25T19:24:35Z", + "baseRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "baseRefName": "main", + "baseRefOid": "25cee27c8a30b6f59691e3302488921be432b5c0", + "headRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "headRefName": "accept-must-be-followed", + "headRefOid": "0d22da5fccfe101cfa9ce08cbade78d887507e9e", + "closedAt": "2021-10-25T19:24:32Z", + "mergedAt": "2021-10-25T19:24:32Z", + "mergedBy": "miri64", + "mergeCommit": { + "oid": "bbc713e9862c6effffdf59d4794c7b53f218a64c" + }, + "comments": [ + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "Moving the server-side requirement over (and referencing it here) sounds good.\r\n\r\nOn the understanding side, maybe the confusion (quite possibly me misunderstanding the current text) is that the use of Accept kind of implies that different C-Fs could be in use too. For example, the client may first using a hypothetical application/dns+cbor -- and then the server needs to err back rather than accepting the request but providing the response in another format.\r\n\r\nGotta go over all involved sections again...", + "createdAt": "2021-08-31T07:39:54Z", + "updatedAt": "2021-08-31T07:39:54Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> [\u2026] that the use of Accept kind of implies that different C-Fs could be in use too.\r\n\r\nThat is the intention, yes.\r\n\r\n\r\n\r\n\r\n\r\n> For example, the client may first using a hypothetical application/dns+cbor -- and then the server needs to err back rather than accepting the request but providing the response in another format.\r\n\r\nThat would be the way to go... not sure how the current text contradicts that...", + "createdAt": "2021-08-31T08:29:11Z", + "updatedAt": "2021-08-31T08:29:11Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "I didn't find any mention that the sever needs to support application/dns-message for output, adding that to get this PR mergable and updating the rest to match.\r\n\r\n(Although personally I'd prefer to say less about representation negotiation at all, as that's provided by CoAP, and leave it at an elaborate version of \"We describe application/dns-message, which is MTI for interoperability for requests and responses, server- and client-side; use CoAP's advertisement and negotiation if you want more.\")", + "createdAt": "2021-10-14T15:43:29Z", + "updatedAt": "2021-10-14T15:43:29Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "I've moved the client-side requirement to the response part because only there it made sense to add the server mandate to be able to produce that response format.", + "createdAt": "2021-10-14T16:48:35Z", + "updatedAt": "2021-10-14T16:48:35Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "Needs rebase, due to #8 being merged.", + "createdAt": "2021-10-25T18:47:56Z", + "updatedAt": "2021-10-25T18:47:56Z" + } + ], + "reviews": [ + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzQxOTQzMDQy", + "commit": { + "abbreviatedOid": "dccda0f" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "DISMISSED", + "body": "We discussed this issue offline, but I am still not quite 100% sure what the problem is. From how I understood it in our conversation offline, the problem is this sentence in [RFC 7252, section 5.10.4](https://www.rfc-editor.org/rfc/rfc7252#section-5.10.4):\r\n\r\n> If the preferred Content-Format cannot be returned, then a 4.06 \"Not Acceptable\" MUST be sent as a response, unless another error code takes precedence for this response.\r\n\r\nSo, if the server (for what ever reason) is unable to send \"application/dns-message\", we have a problem. However, (1) as the text currently stands, the Accept option is optional (but \"defaults\" to \"application/dns-message\") and (2) I don't see how the new wording fixes that issue.\r\n\r\nShouldn't there rather be an additional requirement for the DoC Server in 4.3 that it MUST be able to compose responses in the \"application/dns-message\" to alleviate this issue?", + "createdAt": "2021-08-30T18:27:38Z", + "updatedAt": "2021-10-14T16:58:17Z", + "comments": [ + { + "originalPosition": 7, + "body": "I don't think the Accept option is strictly necessary (\"MUST [\u2026] request with Accept [option?]\", however, can be read as such) and as it stands it somewhat contradicts the sentence before \"[\u2026] SHOULD include an Accept option [\u2026]\".", + "createdAt": "2021-08-30T18:27:39Z", + "updatedAt": "2021-08-30T18:34:26Z" + } + ] + }, + { + "id": "PRR_kwDOF27TLs4ufwxR", + "commit": { + "abbreviatedOid": "ba74219" + }, + "author": "waehlisch", + "authorAssociation": "MEMBER", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-10-14T17:52:50Z", + "updatedAt": "2021-10-14T17:53:04Z", + "comments": [ + { + "originalPosition": 21, + "body": "i'm confused. my understanding was (1) if a client does not send the `Accept` field, a server replies with `application/dns-message` by default, and (2) a client implements at least CF `application/dns-message`.\r\n\r\nre: (1): the current text (\"when requested\") leaves it open which CF the server must use if no `Accept` field was set.\r\n\r\nre: (2): the current text (\"when it does not send an Accept option.\") does not require that client understands CF `application/dns-message`. \r\n\r\nalso, i suggest to replace \"that format\" by \"in the Content-Format \"application/dns-message\"\" to be more precise.", + "createdAt": "2021-10-14T17:52:50Z", + "updatedAt": "2021-10-14T17:53:04Z" + } + ] + }, + { + "id": "PRR_kwDOF27TLs4uxbJR", + "commit": { + "abbreviatedOid": "ba74219" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-10-20T16:08:52Z", + "updatedAt": "2021-10-20T16:08:52Z", + "comments": [ + { + "originalPosition": 21, + "body": "Currently we have a choice to prescribe whether\r\n\r\na) not sending anything forces the default (which means ever requesting application/dns-message is wastefully overexplicit), or\r\nb) no Accept means that the server can send whatever it thinks is best (but still stating that application/dns-message is MTI, so a client better fall back to it if all else fails).\r\n\r\nPreviously I think we're not clear about it, and for the PR I've picked b) which I prefer because it interferes less with CoAP's selections. (In particular, it doesn't raise any question in case an Accept-Any-Of ever gets added).\r\n\r\nIf you think a) is the better choice I can change it over, I can change it.\r\n\r\n---\r\n\r\nI'm revisiting the PR to ensure (2) is covered (it was my intention to keep it MTI for the client, even in the b) variation) and the \"that format\" edit.", + "createdAt": "2021-10-20T16:08:52Z", + "updatedAt": "2021-10-20T16:08:52Z" + } + ] + }, + { + "id": "PRR_kwDOF27TLs4uxdpE", + "commit": { + "abbreviatedOid": "4bd27bc" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-10-20T16:17:52Z", + "updatedAt": "2021-10-20T16:17:53Z", + "comments": [ + { + "originalPosition": 21, + "body": "\"that format\" clarified.\r\n\r\nAs for (2), the current \"A DoC client MUST be prepared to process responses in a/d-m format when it does not send an Accept option.\" implies understanding it to me. (Or is this just about the wording \"prepared to process\"? Would \"MUST understand\" be better?). Sure we could add \"or when it explicitly requests [the format] via Accept\", but that already follows from the semantics of Accept.", + "createdAt": "2021-10-20T16:17:53Z", + "updatedAt": "2021-10-20T16:17:53Z" + } + ] + }, + { + "id": "PRR_kwDOF27TLs4u_T1I", + "commit": { + "abbreviatedOid": "4bd27bc" + }, + "author": "waehlisch", + "authorAssociation": "MEMBER", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-10-25T16:22:35Z", + "updatedAt": "2021-10-25T16:22:35Z", + "comments": [ + { + "originalPosition": 21, + "body": "yes, \"MUST understand\" sounds less ambiguous.", + "createdAt": "2021-10-25T16:22:35Z", + "updatedAt": "2021-10-25T16:22:35Z" + } + ] + }, + { + "id": "PRR_kwDOF27TLs4u_9SU", + "commit": { + "abbreviatedOid": "d9ae74c" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-10-25T19:17:57Z", + "updatedAt": "2021-10-25T19:17:57Z", + "comments": [ + { + "originalPosition": 21, + "body": "Rebased and old change squashed; with the change to \"MUST understand\" now applied as a yet-to-be-squashed commit.", + "createdAt": "2021-10-25T19:17:57Z", + "updatedAt": "2021-10-25T19:17:57Z" + } + ] + }, + { + "id": "PRR_kwDOF27TLs4u_-aR", + "commit": { + "abbreviatedOid": "0d22da5" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "APPROVED", + "body": "Added a minor formatting fix. IMHO this can go in now.", + "createdAt": "2021-10-25T19:23:16Z", + "updatedAt": "2021-10-25T19:23:16Z", + "comments": [] + } + ] + }, + { + "number": 11, + "id": "MDExOlB1bGxSZXF1ZXN0NzIyNjE5MzA2", + "title": "train of pairs: Use block-wise terminology", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/pull/11", + "state": "MERGED", + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "\"body\" and \"payload\" are distinguished there, as are \"operation\" and\r\n\"exchange\"; both explained here briefly.\r\n\r\n(As much as I like the train metaphor, there *is* already terminology.)", + "createdAt": "2021-08-30T16:06:54Z", + "updatedAt": "2021-08-31T14:31:06Z", + "baseRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "baseRefName": "main", + "baseRefOid": "c31c990d32ce7df932200d2ecbbf5ced31c228c2", + "headRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "headRefName": "train-is-leaving", + "headRefOid": "e667d52aa9f4a4632b6aedbd2bb244ebddb528a9", + "closedAt": "2021-08-31T14:15:01Z", + "mergedAt": "2021-08-31T14:15:01Z", + "mergedBy": "miri64", + "mergeCommit": { + "oid": "229e8cfb92d7e7a2ac8e619ca4b1a7814aeabc9f" + }, + "comments": [ + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "Thanks, all applied and squashed.", + "createdAt": "2021-08-31T07:35:31Z", + "updatedAt": "2021-08-31T07:35:31Z" + }, + { + "author": "waehlisch", + "authorAssociation": "MEMBER", + "body": "we should add a reference to the terminology in \\S 2. Terminology.", + "createdAt": "2021-08-31T07:55:38Z", + "updatedAt": "2021-08-31T07:55:38Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> we should add a reference to the terminology in \\S 2. Terminology.\r\n\r\nSo something like\r\n\r\n> The terms CoAP payload and CoAP body are used as defined in RFC7959.\r\n\r\n?\r\n\r\nWe maybe also should have a closer look into the rest of the text where we use \"payload\" and mean actually \"body\".", + "createdAt": "2021-08-31T08:19:56Z", + "updatedAt": "2021-08-31T08:33:57Z" + }, + { + "author": "waehlisch", + "authorAssociation": "MEMBER", + "body": "> The terms CoAP payload and CoAP body are used as defined in RFC7959.\r\n\r\nuse quotation marks (\"CoAP payload\" and \"CoAP body\"). otherwise, it is fine.", + "createdAt": "2021-08-31T14:17:44Z", + "updatedAt": "2021-08-31T14:17:44Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> > The terms CoAP payload and CoAP body are used as defined in RFC7959.\r\n> \r\n> use quotation marks (\"CoAP payload\" and \"CoAP body\"). otherwise, it is fine.\r\n\r\nSee 424aacc\r\n\r\n> We maybe also should have a closer look into the rest of the text where we use \"payload\" and mean actually \"body\".\r\n\r\nOnly the request section did it wrong, see 8db32998f9c343a70ab2a3ed6", + "createdAt": "2021-08-31T14:28:53Z", + "updatedAt": "2021-08-31T14:30:55Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "(updated body/payload commit hash in edit)", + "createdAt": "2021-08-31T14:31:06Z", + "updatedAt": "2021-08-31T14:31:06Z" + } + ], + "reviews": [ + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzQxOTQ5Njc2", + "commit": { + "abbreviatedOid": "3f0fb20" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "CHANGES_REQUESTED", + "body": "Mostly wording nits.", + "createdAt": "2021-08-30T18:35:28Z", + "updatedAt": "2021-08-30T18:36:41Z", + "comments": [ + { + "originalPosition": 11, + "body": "```suggestion\r\nblock-wise transfer is involved. DNS responses are provided in the body (which is the\r\n```\r\n?", + "createdAt": "2021-08-30T18:35:28Z", + "updatedAt": "2021-08-30T18:36:41Z" + }, + { + "originalPosition": 11, + "body": "```suggestion\r\nblock-wise is involved. DNS responses are provided in the body (i.e. the\r\n```\r\n?", + "createdAt": "2021-08-30T18:35:59Z", + "updatedAt": "2021-08-30T18:36:41Z" + }, + { + "originalPosition": 12, + "body": "```suggestion\r\npayload, or the concatenated payloads) of a CoAP response. A DoC server MUST\r\n```\r\n\r\nor\r\n\r\n```suggestion\r\npayload, or the concatenated payloads) of the CoAP response. A DoC server MUST\r\n```", + "createdAt": "2021-08-30T18:36:27Z", + "updatedAt": "2021-08-30T18:36:41Z" + } + ] + }, + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzQyMzk3NDky", + "commit": { + "abbreviatedOid": "639f4b0" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-08-31T07:55:36Z", + "updatedAt": "2021-08-31T07:55:36Z", + "comments": [ + { + "originalPosition": 12, + "body": "This one is still there.", + "createdAt": "2021-08-31T07:55:36Z", + "updatedAt": "2021-08-31T07:55:36Z" + } + ] + }, + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzQyNzc4MzI5", + "commit": { + "abbreviatedOid": "e667d52" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-08-31T14:07:26Z", + "updatedAt": "2021-08-31T14:07:26Z", + "comments": [ + { + "originalPosition": 12, + "body": "Sorry, committed.", + "createdAt": "2021-08-31T14:07:26Z", + "updatedAt": "2021-08-31T14:07:26Z" + } + ] + }, + { + "id": "MDE3OlB1bGxSZXF1ZXN0UmV2aWV3NzQyNzg4MDg3", + "commit": { + "abbreviatedOid": "e667d52" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "APPROVED", + "body": "ACK. Will fix @waehlisch's comment out-of-band.", + "createdAt": "2021-08-31T14:14:48Z", + "updatedAt": "2021-08-31T14:14:48Z", + "comments": [] + } + ] + }, + { + "number": 12, + "id": "PR_kwDOF27TLs4tcdXo", + "title": "Expand for DoQ and DoT", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/pull/12", + "state": "MERGED", + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [], + "body": "During the CoRE interim it was argued that we need to stronger distinguish DoC from the other DNS-over-X approaches. For the most part, this was already done (DoH, DoT, and DNS-over-DTLS). This adds a few sentences on DNS over QUIC (DoQ), mostly arguing on similar size requirement problems as we do for DoH/DoT.", + "createdAt": "2021-10-20T14:50:56Z", + "updatedAt": "2021-10-25T19:14:44Z", + "baseRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "baseRefName": "main", + "baseRefOid": "c6d4ea2ed011de4777082e00d48e2b7e05738870", + "headRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "headRefName": "doq", + "headRefOid": "52168e83d9bb3979a2c0aeebe9a21132fa89eb8f", + "closedAt": "2021-10-25T19:14:40Z", + "mergedAt": "2021-10-25T19:14:40Z", + "mergedBy": "miri64", + "mergeCommit": { + "oid": "25cee27c8a30b6f59691e3302488921be432b5c0" + }, + "comments": [ + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> I was about to complain about the 50KiB (\"the optimized version is only 32 KiB\"), but adding picotls again it's really at least 50KiB.\r\n\r\nEven 32 KiB could be too much for just the transport, IMHO. I can change the value if you like.\r\n\r\nAfter thinking about this a bit more, I think it might also be of value to add the classic congestion control vs. lossy networks here. People not as familiar with the subject matter might need a hint in that direction for HTTPS, TLS, and QUIC.", + "createdAt": "2021-10-20T17:20:04Z", + "updatedAt": "2021-10-20T17:20:04Z" + }, + { + "author": "waehlisch", + "authorAssociation": "MEMBER", + "body": "not sure that the text serves the purpose. another implementation might need less resources?\r\n\r\n@chrysn, what do you mean with \"again\"?", + "createdAt": "2021-10-20T17:27:03Z", + "updatedAt": "2021-10-20T17:27:03Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "ad \"again\": I looked at at the figure 1 numbers, where the \"QUIC\" block started out as 50k but went down to 32k. But when later I looked more closely, I saw that there's still ~20k of TLS implementation too (not counting cifra and micro-ecc as something like these would be shared across any security layer), which then brings the number up to ~50k \"again\".", + "createdAt": "2021-10-20T17:45:26Z", + "updatedAt": "2021-10-20T17:45:26Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> not sure that the text serves the purpose. another implementation might need less resources?\r\n\r\nYes, that was my concern as well. That's why I (also) wanted to add the congestion control argument.", + "createdAt": "2021-10-20T17:54:13Z", + "updatedAt": "2021-10-20T17:54:13Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "> > not sure that the text serves the purpose. another implementation might need less resources?\r\n> \r\n> Yes, that was my concern as well. That's why I (also) wanted to add the congestion control argument.\r\n\r\nDone. I also removed the size argumentation altogether.", + "createdAt": "2021-10-21T10:05:44Z", + "updatedAt": "2021-10-21T10:05:44Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "Rebased, squashed and applied changes proposed by @waehlisch offline. This should be ready to merge now.", + "createdAt": "2021-10-25T18:46:21Z", + "updatedAt": "2021-10-25T18:46:21Z" + } + ], + "reviews": [ + { + "id": "PRR_kwDOF27TLs4uxRCf", + "commit": { + "abbreviatedOid": "5eaa4d4" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "DISMISSED", + "body": "I was about to complain about the 50KiB (\"the optimized version is only 32 KiB\"), but adding picotls again it's really at least 50KiB.", + "createdAt": "2021-10-20T15:35:24Z", + "updatedAt": "2021-10-20T17:20:25Z", + "comments": [] + }, + { + "id": "PRR_kwDOF27TLs4u56xC", + "commit": { + "abbreviatedOid": "2f25a49" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-10-22T14:39:39Z", + "updatedAt": "2021-10-22T14:39:39Z", + "comments": [ + { + "originalPosition": 19, + "body": "Added this quantifier, since CoAP also is datagram-based communication, just with a message recovery layer on top.", + "createdAt": "2021-10-22T14:39:39Z", + "updatedAt": "2021-10-22T14:39:39Z" + } + ] + } + ] + }, + { + "number": 13, + "id": "PR_kwDOF27TLs4ti12j", + "title": "Add note on ETag and response codes", + "url": "https://github.com/anr-bmbf-pivot/draft-dns-over-coap/pull/13", + "state": "MERGED", + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "assignees": [], + "labels": [ + "enhancement" + ], + "body": "While reading up on ETags again, I noticed, that our statements on response codes in 4.3.1 might cause confusion, when it comes to the ETag options in responses:\r\n\r\n> It is RECOMMENDED that CoAP responses that carry any valid DNS response use a \"2.xx Success\" response code. A response to a GET or FETCH request SHOULD use the \"2.05 Content\" code. A response to a POST request SHOULD use the \"2.01 Created\" code.\r\n\r\nor\r\n\r\n> It is RECOMMENDED that CoAP responses that carry any valid DNS response use a \"2.05 Content\" response code.\r\n\r\nin https://github.com/anr-bmbf-pivot/draft-dns-over-coap/pull/8 respectively.\r\n\r\nThis serves as a reminder, that in accordance with RFCs 7252 and 8132, servers that respond to a requested ETag that is valid, MUST use the \"2.03 Valid\" response code and that the response MUST NOT carry any payload.", + "createdAt": "2021-10-22T11:24:12Z", + "updatedAt": "2021-10-22T14:24:27Z", + "baseRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "baseRefName": "main", + "baseRefOid": "2020578671e000961ba9b2a45a2733641da54569", + "headRepository": "anr-bmbf-pivot/draft-dns-over-coap", + "headRefName": "etag-response", + "headRefOid": "ee9c56d198ecb399cb0a300f7178e0942a5764b2", + "closedAt": "2021-10-22T14:24:24Z", + "mergedAt": "2021-10-22T14:24:24Z", + "mergedBy": "miri64", + "mergeCommit": { + "oid": "c6d4ea2ed011de4777082e00d48e2b7e05738870" + }, + "comments": [ + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "> Ad \"general advice\", do you mean by that to change the sentence in\n> 4.3.1 to something more in line to what you suggested?\n\nI was not referring to any concrete line but the general tone -- but\nyes, the \"A response to a GET or FETCH...\" sentences are what I'd\nsuggest to remove or tone down. (It just says before that 2.xx is how\nresponses are to come in, and unless a component like ETag / 2.03 Valid\nsays else, 2.05 *is* the successful response for a GET).\n\nAlso next paragraph: Why force no payload in the response? During\ndebugging that could well contain a stack trace. \"SHOULD be empty / MUST\nignore unrecognized payloads\" allows this to play nice with any other\nCoAP components like core-problem-details.\n\n-- \nTo use raw power is to make yourself infinitely vulnerable to greater powers.\n -- Bene Gesserit axiom\n", + "createdAt": "2021-10-22T12:21:01Z", + "updatedAt": "2021-10-22T12:21:01Z" + }, + { + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "body": "In that case, maybe it is better to reword the whole response code stuff with the responses instead of adding the sentence here. What do you think?", + "createdAt": "2021-10-22T13:25:22Z", + "updatedAt": "2021-10-22T13:25:22Z" + }, + { + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "body": "The current text is a gradual improvement; I think we should merge this here and take the time to work on #10 in a separate step (possibly after this submission).", + "createdAt": "2021-10-22T13:34:16Z", + "updatedAt": "2021-10-22T13:34:16Z" + } + ], + "reviews": [ + { + "id": "PRR_kwDOF27TLs4u5KMq", + "commit": { + "abbreviatedOid": "231c8bc" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-10-22T11:33:45Z", + "updatedAt": "2021-10-22T11:33:46Z", + "comments": [ + { + "originalPosition": 6, + "body": "```suggestion\r\nthe ETag is still valid, the response uses the \"2.03 Valid\" code and consequently\r\ncarries no payload.\r\n```\r\n\r\nI wouldn't use normative language here: We're pointing things out to readers who don't know these details of CoAP off their heads, not making any requirements that are ours to make.\r\n\r\n(My general advice on these things would be to talk normatively in terms of abstract CoAP interactions, in the style of \"the DNS message is transported as a representation in a successful response\", where concrete options like the use of ETag to revalidate, of block-wise and observation as possibilities pointed out, and not as normative components).", + "createdAt": "2021-10-22T11:33:46Z", + "updatedAt": "2021-10-22T11:33:46Z" + } + ] + }, + { + "id": "PRR_kwDOF27TLs4u5Nt7", + "commit": { + "abbreviatedOid": "ee9c56d" + }, + "author": "miri64", + "authorAssociation": "COLLABORATOR", + "state": "COMMENTED", + "body": "", + "createdAt": "2021-10-22T11:50:36Z", + "updatedAt": "2021-10-22T11:50:36Z", + "comments": [ + { + "originalPosition": 6, + "body": "Sounds sensible. Applied as suggested.\r\n\r\nAd \"general advice\", do you mean by that to change the sentence in 4.3.1 to something more in line to what you suggested?", + "createdAt": "2021-10-22T11:50:36Z", + "updatedAt": "2021-10-22T11:50:36Z" + } + ] + }, + { + "id": "PRR_kwDOF27TLs4u5caP", + "commit": { + "abbreviatedOid": "ee9c56d" + }, + "author": "chrysn", + "authorAssociation": "COLLABORATOR", + "state": "APPROVED", + "body": "", + "createdAt": "2021-10-22T12:55:20Z", + "updatedAt": "2021-10-22T12:55:20Z", + "comments": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/draft-ietf-core-dns-over-coap.html b/draft-ietf-core-dns-over-coap.html new file mode 100644 index 0000000..ea08316 --- /dev/null +++ b/draft-ietf-core-dns-over-coap.html @@ -0,0 +1,2102 @@ + + + + + + +DNS over CoAP (DoC) + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Internet-DraftDoCJuly 2023
Lenders, et al.Expires 11 January 2024[Page]
+
+
+
+
Workgroup:
+
CoRE
+
Internet-Draft:
+
draft-ietf-core-dns-over-coap-latest
+
Published:
+
+ +
+
Intended Status:
+
Standards Track
+
Expires:
+
+
Authors:
+
+
+
M. S. Lenders
+
FU Berlin
+
+
+
C. Amsüss
+
+
+
C. Gündoğan
+
Huawei Technologies
+
+
+
T. C. Schmidt
+
HAW Hamburg
+
+
+
M. Wählisch
+
FU Berlin
+
+
+
+
+

DNS over CoAP (DoC)

+
+

Abstract

+

This document defines a protocol for sending DNS messages over the +Constrained Application Protocol (CoAP). These CoAP messages are protected +by DTLS-Secured CoAP (CoAPS) or Object Security for Constrained RESTful +Environments (OSCORE) to provide encrypted DNS message exchange for +constrained devices in the Internet of Things (IoT).

+
+
+

+Discussion Venues +

+

This note is to be removed before publishing as an RFC.

+

Discussion of this document takes place on the + Constrained RESTful Environments Working Group mailing list (core@ietf.org), + which is archived at https://mailarchive.ietf.org/arch/browse/core/.

+

Source for this draft and an issue tracker can be found at + https://github.com/core-wg/draft-dns-over-coap.

+
+
+
+

+Status of This Memo +

+

+ This Internet-Draft is submitted in full conformance with the + provisions of BCP 78 and BCP 79.

+

+ Internet-Drafts are working documents of the Internet Engineering Task + Force (IETF). Note that other groups may also distribute working + documents as Internet-Drafts. The list of current Internet-Drafts is + at https://datatracker.ietf.org/drafts/current/.

+

+ Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress."

+

+ This Internet-Draft will expire on 11 January 2024.

+
+
+ +
+
+

+Table of Contents +

+ +
+
+
+
+

+1. Introduction +

+

This document defines DNS over CoAP (DoC), a protocol to send DNS +[RFC1035] queries and get DNS responses over the Constrained Application +Protocol (CoAP) [RFC7252]. Each DNS query-response pair is mapped into a +CoAP message exchange. Each CoAP message is secured by DTLS [RFC9147] or +Object Security for Constrained RESTful Environments (OSCORE) [RFC8613] +to ensure message integrity and confidentiality.

+

The application use case of DoC is inspired by DNS over HTTPS [RFC8484] +(DoH). DoC, however, aims for the deployment in the constrained Internet of +Things (IoT), which usually conflicts with the requirements introduced by +HTTPS.

+

To prevent TCP and HTTPS resource requirements, constrained IoT devices +could use DNS over DTLS [RFC8094]. In contrast to DNS over DTLS, DoC +utilizes CoAP features to mitigate drawbacks of datagram-based +communication. These features include: block-wise transfer, which solves +the Path MTU problem of DNS over DTLS (see [RFC8094], section 5); CoAP +proxies, which provide an additional level of caching; re-use of data +structures for application traffic and DNS information, which saves memory +on constrained devices.

+

To prevent resource requirements of DTLS or TLS on top of UDP (e.g., +introduced by DNS over QUIC [RFC9250]), DoC allows +for lightweight payload encryption based on OSCORE.

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FETCH + coaps://[2001:db8::1]/ + CoAP + request + [DNS + query] + DNS + query + DoC + DoC + DNS + Client + Server + Infrastructure + CoAP + response + DNS + response + [DNS + response] + DNS + over + CoAP + DNS + over + UDP/HTTPS/QUIC/.. + + +
+
+
Figure 1: +Basic DoC architecture +
+
+

The most important components of DoC can be seen in Figure 1: A DoC +client tries to resolve DNS information by sending DNS queries carried within +CoAP requests to a DoC server. +That DoC server is a DNS client (i.e., a stub or recursive resolver) that resolves DNS information by using other DNS transports such +as DNS over UDP [RFC1035], DNS over HTTPS [RFC8484], or DNS over QUIC [RFC9250] when communicating with the upstream +DNS infrastructure. +Using that information, the DoC server then replies to the queries of the DoC client with DNS +responses carried within CoAP responses.

+

Note that this specification is disjunct from DoH since the CoRE-specific FETCH method is used. +This was done to take benefit from having the DNS query in the payload as with POST, but still +having the caching advantages we would gain with GET. +Having the DNS query in the payload means we do not need extra base64 encoding, which would increase +code complexity and message sizes. +We are also able to transfer a query block-wise.

+
+
+
+
+

+2. Terminology +

+

A server that provides the service specified in this document is called a "DoC +server" to differentiate it from a classic "DNS server". +A DoC server acts either as a DNS stub resolver [RFC8499] or a DNS recursive resolver [RFC8499].

+

A client using the service specified in this document to retrieve the +DNS information is called a "DoC client".

+

The term "constrained nodes" is used as defined in [RFC7228].

+

The terms "CoAP payload" and "CoAP body" are used as defined in [RFC7959], Section 2.

+

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", +"MAY", and "OPTIONAL" in this document are to be interpreted as +described in BCP 14 [RFC2119] [RFC8174] when, and only when, they +appear in all capitals, as shown here.

+
+
+
+
+

+3. Selection of a DoC Server +

+

In this document, it is assumed that the DoC client knows the DoC server and the DNS resource at the +DoC server. +Possible options could be manual configuration of a URI [RFC3986] or CRI [I-D.ietf-core-href], +or automatic configuration, e.g., using a CoRE resource directory +[RFC9176], DHCP or Router Advertisement options [I-D.ietf-add-dnr]. +Automatic configuration SHOULD only be done from a trusted source.

+

TBD DNR Service Parameters + SVCB Resource Records (also see #22):

+ +

When discovering the DNS resource through a link mechanism that allows describing a resource type +(e.g., the Resource Type Attribute in [RFC6690]), the resource type "core.dns" can be +used to identify a generic DNS resolver that is available to the client.

+

While there is no path specified it is RECOMMENDED to use the root path "/" for the DNS resource to +keep the CoAP requests small.

+
+
+
+
+

+4. Basic Message Exchange +

+
+
+

+4.1. The "application/dns-message" Content-Format +

+

This document defines a CoAP Content-Format number for the Internet media type "application/dns-message" to be the mnemonic 553--based on the port assignment of DNS. +This media type is defined as in [RFC8484] Section 6, i.e., a single DNS message encoded in the DNS on-the-wire format [RFC1035]. +Both DoC client and DoC server MUST be able to parse contents in the "application/dns-message" format.

+
+
+
+
+

+4.2. DNS Queries in CoAP Requests +

+

A DoC client encodes a single DNS query in one or more CoAP request +messages that use the CoAP FETCH [RFC8132] method. +Requests SHOULD include an Accept option to indicate the type of content that can be parsed in the response.

+

Since CoAP provides reliability of the message layer (e.g. CON) the retransmission mechanism of the +DNS protocol as defined in [RFC1035] is not needed.

+
+
+

+4.2.1. Request Format +

+

When sending a CoAP request, a DoC client MUST include the DNS query in the body of the CoAP request. +As specified in [RFC8132] Section 2.3.1, the type of content of the body MUST be indicated using the Content-Format option. +This document specifies the usage of Content-Format "application/dns-message" (details see Section 4.1). +A DoC server MUST be able to parse requests of Content-Format "application/dns-message".

+
+
+
+
+

+4.2.2. Support of CoAP Caching +

+

The DoC client SHOULD set the ID field of the DNS header always to 0 to enable a CoAP cache (e.g., a CoAP proxy en-route) to respond to the same DNS queries with a cache entry. +This ensures that the CoAP Cache-Key (see [RFC8132] Section 2) does not change when multiple DNS queries for the same DNS data, carried in CoAP requests, are issued.

+
+
+
+
+

+4.2.3. Examples +

+

The following example illustrates the usage of a CoAP message to +resolve "example.org. IN AAAA" based on the URI "coaps://[2001:db8::1]/". The +CoAP body is encoded in "application/dns-message" Content Format.

+
+
+FETCH coaps://[2001:db8::1]/
+Content-Format: application/dns-message
+Accept: application/dns-message
+Payload: 00 00 01 20 00 02 00 00 00 00 00 00 07 65 78 61 [binary]
+         6d 70 6c 65 03 6f 72 67 00 00 1c 00 01 c0 0c 00 [binary]
+         01 00 01                                        [binary]
+
+
+
+
+
+
+
+
+

+4.3. DNS Responses in CoAP Responses +

+

Each DNS query-response pair is mapped to a CoAP REST request-response +operation. DNS responses are provided in the body of the CoAP response. +A DoC server MUST be able to produce responses in the "application/dns-message" +Content-Format (details see Section 4.1) when requested. +A DoC client MUST understand responses in "application/dns-message" format +when it does not send an Accept option. +Any other response format than "application/dns-message" MUST be indicated with +the Content-Format option by the DoC server.

+
+
+

+4.3.1. Response Codes and Handling DNS and CoAP errors +

+

A DNS response indicates either success or failure in the Response code of +the DNS header (see [RFC1035] Section 4.1.1). It is RECOMMENDED that +CoAP responses that carry any valid DNS response use a "2.05 Content" +response code.

+

CoAP responses use non-successful response codes MUST NOT contain a DNS response +and MUST only be used on errors in the CoAP layer or when a request does not +fulfill the requirements of the DoC protocol.

+

Communication errors with a DNS server (e.g., timeouts) SHOULD be indicated +by including a SERVFAIL DNS response in a successful CoAP response.

+

A DoC client might try to repeat a non-successful exchange unless otherwise prohibited. +The DoC client might also decide to repeat a non-successful exchange with a different URI, for instance, when the response indicates an unsupported Content-Format.

+
+
+
+
+

+4.3.2. Support of CoAP Caching +

+

For reliability and energy saving measures content decoupling and thus en-route caching on proxies takes a far greater role than it does, e.g., in HTTP. +Likewise, CoAP utilizes cache validation to refresh stale cache entries without large messages which often uses hashing over the message content for ETag generation. +As such, the approach to guarantee the same cache key for DNS responses as proposed in DoH ([RFC8484], section 5.1) is not sufficient and needs to be updated so that the TTLs in the response are more often the same regardless of query time.

+

The DoC server MUST ensure that any sum of the Max-Age value of a CoAP response and any TTL in the +DNS response is less or equal to the corresponding TTL received from an upstream DNS server. +This also includes the default Max-Age value of 60 seconds (see [RFC7252], section 5.10.5) when no Max-Age option is provided. +The DoC client MUST then add the Max-Age value of the carrying CoAP response to all TTLs in a DNS response on reception and use these calculated TTLs for the associated records.

+

The RECOMMENDED algorithm to assure the requirement for the DoC is to set the Max-Age option of a response to the minimum TTL of a DNS response and to subtract this value from all TTLs of that DNS response. +This prevents expired records unintentionally being served from an intermediate CoAP cache. +Additionally, it allows for the ETag value for cache validation, if it is based on the content of the response, not to change even if the TTL values are updated by an upstream DNS cache. +If only one record set per DNS response is assumed, a simplification of this algorithm is to just set all TTLs in the response to 0 and set the TTLs at the DoC client to the value of the Max-Age option.

+
+
+
+
+

+4.3.3. Examples +

+

The following examples illustrate the replies to the query "example.org. IN +AAAA record", recursion turned on. Successful responses carry one answer +record including address 2001:db8:1::1:2:3:4 and TTL 58719.

+

A successful response:

+
+
+2.05 Content
+Content-Format: application/dns-message
+Max-Age: 58719
+Payload: 00 00 81 a0 00 01 00 01 00 00 00 00 07 65 78 61 [binary]
+         6d 70 6c 65 03 6f 72 67 00 00 1c 00 01 c0 0c 00 [binary]
+         1c 00 01 00 01 37 49 00 10 20 01 0d b8 00 01 00 [binary]
+         00 00 01 00 02 00 03 00 04                      [binary]
+
+
+

When a DNS error (SERVFAIL in this case) is noted in the DNS response, the CoAP +response still indicates success:

+
+
+2.05 Content
+Content-Format: application/dns-message
+Payload: 00 00 81 a2 00 01 00 00 00 00 00 00 07 65 78 61 [binary]
+         6d 70 6c 65 03 6f 72 67 00 00 1c 00 01          [binary]
+
+
+

When an error occurs on the CoAP layer, the DoC server SHOULD respond with +an appropriate CoAP error, for instance "4.15 Unsupported Content-Format" +if the Content-Format option in the request was not set to +"application/dns-message" and the Content-Format is not otherwise supported by +the server.

+
+
+
+
+
+
+
+
+

+5. CoAP/CoRE Integration +

+
+
+

+5.1. DNS Push +

+

DNS Push requires additional overhead, which conflicts with constrained resources, +This is the reason why it is RECOMMENDED to use CoAP Observe [RFC7641] instead of DNS Push +in the DoC domain.

+

If the CoAP request indicates that the DoC client wants to observe a resource record, a DoC server +MAY use a DNS Subscribe message [RFC8765] instead of a classic DNS query to fetch the +information on behalf of a DoC client. +If this is not supported by the DoC server, it MUST act as if the resource were not observable.

+

Whenever the DoC server receives a DNS Push message [RFC8765] from the DNS +infrastructure for an observed resource record, the DoC server sends an appropriate Observe response +to the DoC client.

+

If no more DoC clients observe a resource record for which the DoC server has an open subscription, +the DoC server MUST use a DNS Unsubscribe message [RFC8765] to close its subscription to the +resource record as well.

+
+
+
+
+

+5.2. OSCORE +

+

It is RECOMMENDED to carry DNS messages encrypted using OSCORE [RFC8613] between the DoC client and the DoC server. +The exchange of the security context is out of scope of this document.

+
+
+
+
+

+5.3. Mapping DoC to DoH +

+

This document provides no specification how to map between DoC and DoH, e.g., at a CoAP-HTTP-proxy, +and it is NOT RECOMMENDED. +Rewriting the FETCH method (Section 4.2) and the TTL rewriting (Section 4.3.2) as +specified in this draft would be non-trivial. +It is RECOMMENDED to use a DNS forwarder to map between DoC and DoH, as would be the case for +mapping between any other DNS transport.

+
+
+
+
+
+
+

+6. Considerations for Unencrypted Use +

+

The use of DoC without a security mode of CoAP is NOT RECOMMENDED. +Without a security mode, a large number of possible attacks need to be evaluate in the context of +the application's threat model. +This includes threats that are mitigated even by DNS over UDP: +For example, the random ID of the DNS header afford some protection against off-path cache poisoning +attacks---a threat that might be mitigated by using random large token values in the CoAP request.

+
+
+
+
+

+7. Implementation Status +

+

This section records the status of known implementations of the protocol +defined by this specification at the time of posting of this +Internet-Draft, and is based on a proposal described in +[RFC7942]. The description of implementations in this +section is intended to assist the IETF in its decision processes in +progressing drafts to RFCs. Please note that the listing of any individual +implementation here does not imply endorsement by the IETF. Furthermore, +no effort has been spent to verify the information presented here that was +supplied by IETF contributors. This is not intended as, and must not be +construed to be, a catalog of available implementations or their features. +Readers are advised to note that other implementations may exist.

+

According to [RFC7942], "this will allow reviewers and +working groups to assign due consideration to documents that have the +benefit of running code, which may serve as evidence of valuable +experimentation and feedback that have made the implemented protocols more +mature. It is up to the individual working groups to use this information +as they see fit".

+
+
+

+7.1. DoC Client +

+

The authors of this document provide a DoC client implementation available +in the IoT operating system RIOT.

+
+
Level of maturity:
+
+

production

+
+
+
Version compability:
+
+

draft-ietf-core-dns-over-coap-02

+
+
+
License:
+
+

LGPL-2.1

+
+
+
Contact information:
+
+

Martine Lenders <m.lenders@fu-berlin.de>

+
+
+
Last update of this information:
+
+

March 2023

+
+
+
+
+
+
+
+

+7.2. DoC Server +

+

The authors of this document provide a DoC server implementation in +Python.

+
+
Level of maturity:
+
+

production

+
+
+
Version compability:
+
+

draft-ietf-core-dns-over-coap-02

+
+
+
License:
+
+

MIT

+
+
+
Contact information:
+
+

Martine Lenders <m.lenders@fu-berlin.de>

+
+
+
Last update of this information:
+
+

March 2023

+
+
+
+
+
+
+
+
+
+

+8. Security Considerations +

+

When using unencrypted CoAP (see Section 6), setting the ID of a DNS message to 0 as +specified in Section 4.2.2 opens open the DNS cache of a DoC client to cache poisoning attacks +via response spoofing. +This documents requires an unpredictable CoAP token in each DoC query from the client when CoAP is +not secured to mitigate such an attack over DoC (see Section 6).

+

For encrypted usage with DTLS or OSCORE the impact of a fixed ID on security is limited, as both +harden against injecting spoofed responses. +Consequently, it is of little concern to leverage the benefits of CoAP caching by setting the ID to +0.

+

TODO more security

+
+
+
+
+

+9. IANA Considerations +

+
+
+

+9.1. New "application/dns-message" Content-Format +

+

IANA is requested to assign CoAP Content-Format ID for the DNS message media +type in the "CoAP Content-Formats" sub-registry, within the "CoRE Parameters" +registry [RFC7252], corresponding to the "application/dns-message" media +type from the "Media Types" registry:

+

Media-Type: application/dns-message

+

Encoding: -

+

Id: 553

+

Reference: [TBD-this-spec]

+
+
+
+
+

+9.2. New "core.dns" Resource Type +

+

IANA is requested to assign a new Resource Type (rt=) Link Target Attribute, "core.dns" in the +"Resource Type (rt=) Link Target Attribute Values" sub-registry, within the "CoRE Parameters" +register [RFC6690].

+

Attribute Value: core.dns

+

Description: DNS over CoAP resource.

+

Reference: [TBD-this-spec] Section 3

+
+
+
+
+
+

+10. References +

+
+

+10.1. Normative References +

+
+
[RFC1035]
+
+Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, , <https://www.rfc-editor.org/rfc/rfc1035>.
+
+
[RFC2119]
+
+Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
+
+
[RFC7228]
+
+Bormann, C., Ersue, M., and A. Keranen, "Terminology for Constrained-Node Networks", RFC 7228, DOI 10.17487/RFC7228, , <https://www.rfc-editor.org/rfc/rfc7228>.
+
+
[RFC7252]
+
+Shelby, Z., Hartke, K., and C. Bormann, "The Constrained Application Protocol (CoAP)", RFC 7252, DOI 10.17487/RFC7252, , <https://www.rfc-editor.org/rfc/rfc7252>.
+
+
[RFC7641]
+
+Hartke, K., "Observing Resources in the Constrained Application Protocol (CoAP)", RFC 7641, DOI 10.17487/RFC7641, , <https://www.rfc-editor.org/rfc/rfc7641>.
+
+
[RFC7959]
+
+Bormann, C. and Z. Shelby, Ed., "Block-Wise Transfers in the Constrained Application Protocol (CoAP)", RFC 7959, DOI 10.17487/RFC7959, , <https://www.rfc-editor.org/rfc/rfc7959>.
+
+
[RFC8132]
+
+van der Stok, P., Bormann, C., and A. Sehgal, "PATCH and FETCH Methods for the Constrained Application Protocol (CoAP)", RFC 8132, DOI 10.17487/RFC8132, , <https://www.rfc-editor.org/rfc/rfc8132>.
+
+
[RFC8174]
+
+Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
+
+
[RFC8613]
+
+Selander, G., Mattsson, J., Palombini, F., and L. Seitz, "Object Security for Constrained RESTful Environments (OSCORE)", RFC 8613, DOI 10.17487/RFC8613, , <https://www.rfc-editor.org/rfc/rfc8613>.
+
+
[RFC9147]
+
+Rescorla, E., Tschofenig, H., and N. Modadugu, "The Datagram Transport Layer Security (DTLS) Protocol Version 1.3", RFC 9147, DOI 10.17487/RFC9147, , <https://www.rfc-editor.org/rfc/rfc9147>.
+
+
+
+
+

+10.2. Informative References +

+
+
[I-D.ietf-add-dnr]
+
+Boucadair, M., Reddy.K, T., Wing, D., Cook, N., and T. Jensen, "DHCP and Router Advertisement Options for the Discovery of Network-designated Resolvers (DNR)", Work in Progress, Internet-Draft, draft-ietf-add-dnr-16, , <https://datatracker.ietf.org/doc/html/draft-ietf-add-dnr-16>.
+
+
[I-D.ietf-core-href]
+
+Bormann, C. and H. Birkholz, "Constrained Resource Identifiers", Work in Progress, Internet-Draft, draft-ietf-core-href-12, , <https://datatracker.ietf.org/doc/html/draft-ietf-core-href-12>.
+
+
[RFC3986]
+
+Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/rfc/rfc3986>.
+
+
[RFC6690]
+
+Shelby, Z., "Constrained RESTful Environments (CoRE) Link Format", RFC 6690, DOI 10.17487/RFC6690, , <https://www.rfc-editor.org/rfc/rfc6690>.
+
+
[RFC7942]
+
+Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, DOI 10.17487/RFC7942, , <https://www.rfc-editor.org/rfc/rfc7942>.
+
+
[RFC8094]
+
+Reddy, T., Wing, D., and P. Patil, "DNS over Datagram Transport Layer Security (DTLS)", RFC 8094, DOI 10.17487/RFC8094, , <https://www.rfc-editor.org/rfc/rfc8094>.
+
+
[RFC8323]
+
+Bormann, C., Lemay, S., Tschofenig, H., Hartke, K., Silverajan, B., and B. Raymor, Ed., "CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets", RFC 8323, DOI 10.17487/RFC8323, , <https://www.rfc-editor.org/rfc/rfc8323>.
+
+
[RFC8484]
+
+Hoffman, P. and P. McManus, "DNS Queries over HTTPS (DoH)", RFC 8484, DOI 10.17487/RFC8484, , <https://www.rfc-editor.org/rfc/rfc8484>.
+
+
[RFC8499]
+
+Hoffman, P., Sullivan, A., and K. Fujiwara, "DNS Terminology", BCP 219, RFC 8499, DOI 10.17487/RFC8499, , <https://www.rfc-editor.org/rfc/rfc8499>.
+
+
[RFC8765]
+
+Pusateri, T. and S. Cheshire, "DNS Push Notifications", RFC 8765, DOI 10.17487/RFC8765, , <https://www.rfc-editor.org/rfc/rfc8765>.
+
+
[RFC9176]
+
+Amsüss, C., Ed., Shelby, Z., Koster, M., Bormann, C., and P. van der Stok, "Constrained RESTful Environments (CoRE) Resource Directory", RFC 9176, DOI 10.17487/RFC9176, , <https://www.rfc-editor.org/rfc/rfc9176>.
+
+
[RFC9250]
+
+Huitema, C., Dickinson, S., and A. Mankin, "DNS over Dedicated QUIC Connections", RFC 9250, DOI 10.17487/RFC9250, , <https://www.rfc-editor.org/rfc/rfc9250>.
+
+
+
+
+
+
+

+Appendix A. Change Log +

+
+
+

+A.1. Since draft-ietf-core-dns-over-coap-02 +

+
    +
  • Move implementation details to Implementation Status (in accordance with [RFC7942]) +
  • +
  • Recommend root path to keep the CoAP options small +
  • +
  • Set Content-Format for application/dns-message to 553 +
  • +
  • SVCB/DNR: Move to Server Selection Section but leave TBD based on DNSOP discussion for now +
  • +
  • Clarify that DoC and DoC are disjunct +
  • +
  • Clarify mapping between DoC and DoH +
  • +
  • Update considerations on unencrypted use +
  • +
  • Don't call OSCORE end-to-end encrypted +
  • +
+
+
+
+
+

+A.2. Since draft-ietf-core-dns-over-coap-01 +

+
    +
  • Specify DoC server role in terms of DNS terminology +
  • +
  • Clarify communication of DoC to DNS infrastructure is agnostic of the transport +
  • +
  • Add subsection on how to implement DNS Push in DoC +
  • +
  • Add appendix on reference implementation +
  • +
+
+
+
+
+

+A.3. Since draft-ietf-core-dns-over-coap-00 +

+
    +
  • SVGify ASCII art +
  • +
  • Move section on "DoC Server Considerations" (was Section 5.1) to its own draft +(draft-lenders-dns-cns) +
  • +
  • Replace layer violating statement for CON with statement of fact +
  • +
  • Add security considerations on ID=0 +
  • +
+
+
+
+
+

+A.4. Since draft-lenders-dns-over-coap-04 +

+
    +
  • Removed change log of draft-lenders-dns-over-coap +
  • +
+
+
+
+
+
+
+

+Acknowledgments +

+

The authors of this document want to thank Ben Schwartz and Tim Wicinski for their feedback and +comments.

+
+
+
+
+

+Authors' Addresses +

+
+
Martine Sophie Lenders
+
Freie Universität Berlin
+
Takustrasse 9
+
+D-14195 Berlin +
+
Germany
+ +
+
+
Christian Amsüss
+ +
+
+
Cenk Gündoğan
+
Huawei Technologies
+
Riesstrasse 25
+
+D-80992 Munich +
+
Germany
+ +
+
+
Thomas C. Schmidt
+
HAW Hamburg
+
Berliner Tor 7
+
+D-20099 Hamburg +
+
Germany
+ +
+
+
Matthias Wählisch
+
Freie Universität Berlin
+
Takustrasse 9
+
+D-14195 Berlin +
+
Germany
+ +
+
+
+ + + diff --git a/draft-ietf-core-dns-over-coap.txt b/draft-ietf-core-dns-over-coap.txt new file mode 100644 index 0000000..b9242b1 --- /dev/null +++ b/draft-ietf-core-dns-over-coap.txt @@ -0,0 +1,729 @@ + + + + +CoRE M. S. Lenders +Internet-Draft FU Berlin +Intended status: Standards Track C. Amsüss +Expires: 11 January 2024 + C. Gündoğan + Huawei Technologies + T. C. Schmidt + HAW Hamburg + M. Wählisch + FU Berlin + 10 July 2023 + + + DNS over CoAP (DoC) + draft-ietf-core-dns-over-coap-latest + +Abstract + + This document defines a protocol for sending DNS messages over the + Constrained Application Protocol (CoAP). These CoAP messages are + protected by DTLS-Secured CoAP (CoAPS) or Object Security for + Constrained RESTful Environments (OSCORE) to provide encrypted DNS + message exchange for constrained devices in the Internet of Things + (IoT). + +Discussion Venues + + This note is to be removed before publishing as an RFC. + + Discussion of this document takes place on the Constrained RESTful + Environments Working Group mailing list (core@ietf.org), which is + archived at https://mailarchive.ietf.org/arch/browse/core/. + + Source for this draft and an issue tracker can be found at + https://github.com/core-wg/draft-dns-over-coap. + +Status of This Memo + + This Internet-Draft is submitted in full conformance with the + provisions of BCP 78 and BCP 79. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF). Note that other groups may also distribute + working documents as Internet-Drafts. The list of current Internet- + Drafts is at https://datatracker.ietf.org/drafts/current/. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress." + + This Internet-Draft will expire on 11 January 2024. + +Copyright Notice + + Copyright (c) 2023 IETF Trust and the persons identified as the + document authors. All rights reserved. + + This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents (https://trustee.ietf.org/ + license-info) in effect on the date of publication of this document. + Please review these documents carefully, as they describe your rights + and restrictions with respect to this document. Code Components + extracted from this document must include Revised BSD License text as + described in Section 4.e of the Trust Legal Provisions and are + provided without warranty as described in the Revised BSD License. + +Table of Contents + + 1. Introduction + 2. Terminology + 3. Selection of a DoC Server + 4. Basic Message Exchange + 4.1. The "application/dns-message" Content-Format + 4.2. DNS Queries in CoAP Requests + 4.2.1. Request Format + 4.2.2. Support of CoAP Caching + 4.2.3. Examples + 4.3. DNS Responses in CoAP Responses + 4.3.1. Response Codes and Handling DNS and CoAP errors + 4.3.2. Support of CoAP Caching + 4.3.3. Examples + 5. CoAP/CoRE Integration + 5.1. DNS Push + 5.2. OSCORE + 5.3. Mapping DoC to DoH + 6. Considerations for Unencrypted Use + 7. Implementation Status + 7.1. DoC Client + 7.2. DoC Server + 8. Security Considerations + 9. IANA Considerations + 9.1. New "application/dns-message" Content-Format + 9.2. New "core.dns" Resource Type + 10. References + 10.1. Normative References + 10.2. Informative References + Appendix A. Change Log + A.1. Since draft-ietf-core-dns-over-coap-02 + A.2. Since draft-ietf-core-dns-over-coap-01 + A.3. Since draft-ietf-core-dns-over-coap-00 + A.4. Since draft-lenders-dns-over-coap-04 + Acknowledgments + Authors' Addresses + +1. Introduction + + This document defines DNS over CoAP (DoC), a protocol to send DNS + [RFC1035] queries and get DNS responses over the Constrained + Application Protocol (CoAP) [RFC7252]. Each DNS query-response pair + is mapped into a CoAP message exchange. Each CoAP message is secured + by DTLS [RFC9147] or Object Security for Constrained RESTful + Environments (OSCORE) [RFC8613] to ensure message integrity and + confidentiality. + + The application use case of DoC is inspired by DNS over HTTPS + [RFC8484] (DoH). DoC, however, aims for the deployment in the + constrained Internet of Things (IoT), which usually conflicts with + the requirements introduced by HTTPS. + + To prevent TCP and HTTPS resource requirements, constrained IoT + devices could use DNS over DTLS [RFC8094]. In contrast to DNS over + DTLS, DoC utilizes CoAP features to mitigate drawbacks of datagram- + based communication. These features include: block-wise transfer, + which solves the Path MTU problem of DNS over DTLS (see [RFC8094], + section 5); CoAP proxies, which provide an additional level of + caching; re-use of data structures for application traffic and DNS + information, which saves memory on constrained devices. + + To prevent resource requirements of DTLS or TLS on top of UDP (e.g., + introduced by DNS over QUIC [RFC9250]), DoC allows for lightweight + payload encryption based on OSCORE. + + . FETCH coaps://[2001:db8::1]/ + / + / + CoAP request + +------+ [DNS query] +------+ DNS query .---------------. + | DoC |---------------->| DoC |--- --- --- --->| DNS | + |Client|<----------------|Server|<--- --- --- ---| Infrastructure | + +------+ CoAP response +------+ DNS response '---------------' + [DNS response] + \ /\ / + '-----DNS over CoAP----' '--DNS over UDP/HTTPS/QUIC/...--' + + Figure 1: Basic DoC architecture + + The most important components of DoC can be seen in Figure 1: A DoC + client tries to resolve DNS information by sending DNS queries + carried within CoAP requests to a DoC server. That DoC server is a + DNS client (i.e., a stub or recursive resolver) that resolves DNS + information by using other DNS transports such as DNS over UDP + [RFC1035], DNS over HTTPS [RFC8484], or DNS over QUIC [RFC9250] when + communicating with the upstream DNS infrastructure. Using that + information, the DoC server then replies to the queries of the DoC + client with DNS responses carried within CoAP responses. + + Note that this specification is disjunct from DoH since the CoRE- + specific FETCH method is used. This was done to take benefit from + having the DNS query in the payload as with POST, but still having + the caching advantages we would gain with GET. Having the DNS query + in the payload means we do not need extra base64 encoding, which + would increase code complexity and message sizes. We are also able + to transfer a query block-wise. + +2. Terminology + + A server that provides the service specified in this document is + called a "DoC server" to differentiate it from a classic "DNS + server". A DoC server acts either as a DNS stub resolver [RFC8499] + or a DNS recursive resolver [RFC8499]. + + A client using the service specified in this document to retrieve the + DNS information is called a "DoC client". + + The term "constrained nodes" is used as defined in [RFC7228]. + + The terms "CoAP payload" and "CoAP body" are used as defined in + [RFC7959], Section 2. + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and + "OPTIONAL" in this document are to be interpreted as described in + BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all + capitals, as shown here. + +3. Selection of a DoC Server + + In this document, it is assumed that the DoC client knows the DoC + server and the DNS resource at the DoC server. Possible options + could be manual configuration of a URI [RFC3986] or CRI + [I-D.ietf-core-href], or automatic configuration, e.g., using a CoRE + resource directory [RFC9176], DHCP or Router Advertisement options + [I-D.ietf-add-dnr]. Automatic configuration SHOULD only be done from + a trusted source. + + TBD DNR Service Parameters + SVCB Resource Records (also see #22 + (https://github.com/core-wg/draft-dns-over-coap/issues/22)): + + * coap Exists already in TLS Application-Layer Protocol Negotiation + (ALPN) Protocol IDs registry [RFC8323] + + * Never mandated for DTLS, should be kept for CoAP over TLS; DTLS + needs its own ALPN ID + + * SVCB: Also needs to considering OSCORE/EDHOC + + When discovering the DNS resource through a link mechanism that + allows describing a resource type (e.g., the Resource Type Attribute + in [RFC6690]), the resource type "core.dns" can be used to identify a + generic DNS resolver that is available to the client. + + While there is no path specified it is RECOMMENDED to use the root + path "/" for the DNS resource to keep the CoAP requests small. + +4. Basic Message Exchange + +4.1. The "application/dns-message" Content-Format + + This document defines a CoAP Content-Format number for the Internet + media type "application/dns-message" to be the mnemonic 553--based on + the port assignment of DNS. This media type is defined as in + [RFC8484] Section 6, i.e., a single DNS message encoded in the DNS + on-the-wire format [RFC1035]. Both DoC client and DoC server MUST be + able to parse contents in the "application/dns-message" format. + +4.2. DNS Queries in CoAP Requests + + A DoC client encodes a single DNS query in one or more CoAP request + messages that use the CoAP FETCH [RFC8132] method. Requests SHOULD + include an Accept option to indicate the type of content that can be + parsed in the response. + + Since CoAP provides reliability of the message layer (e.g. CON) the + retransmission mechanism of the DNS protocol as defined in [RFC1035] + is not needed. + +4.2.1. Request Format + + When sending a CoAP request, a DoC client MUST include the DNS query + in the body of the CoAP request. As specified in [RFC8132] + Section 2.3.1, the type of content of the body MUST be indicated + using the Content-Format option. This document specifies the usage + of Content-Format "application/dns-message" (details see + Section 4.1). A DoC server MUST be able to parse requests of + Content-Format "application/dns-message". + +4.2.2. Support of CoAP Caching + + The DoC client SHOULD set the ID field of the DNS header always to 0 + to enable a CoAP cache (e.g., a CoAP proxy en-route) to respond to + the same DNS queries with a cache entry. This ensures that the CoAP + Cache-Key (see [RFC8132] Section 2) does not change when multiple DNS + queries for the same DNS data, carried in CoAP requests, are issued. + +4.2.3. Examples + + The following example illustrates the usage of a CoAP message to + resolve "example.org. IN AAAA" based on the URI + "coaps://[2001:db8::1]/". The CoAP body is encoded in "application/ + dns-message" Content Format. + + FETCH coaps://[2001:db8::1]/ + Content-Format: application/dns-message + Accept: application/dns-message + Payload: 00 00 01 20 00 02 00 00 00 00 00 00 07 65 78 61 [binary] + 6d 70 6c 65 03 6f 72 67 00 00 1c 00 01 c0 0c 00 [binary] + 01 00 01 [binary] + +4.3. DNS Responses in CoAP Responses + + Each DNS query-response pair is mapped to a CoAP REST request- + response operation. DNS responses are provided in the body of the + CoAP response. A DoC server MUST be able to produce responses in the + "application/dns-message" Content-Format (details see Section 4.1) + when requested. A DoC client MUST understand responses in + "application/dns-message" format when it does not send an Accept + option. Any other response format than "application/dns-message" + MUST be indicated with the Content-Format option by the DoC server. + +4.3.1. Response Codes and Handling DNS and CoAP errors + + A DNS response indicates either success or failure in the Response + code of the DNS header (see [RFC1035] Section 4.1.1). It is + RECOMMENDED that CoAP responses that carry any valid DNS response use + a "2.05 Content" response code. + + CoAP responses use non-successful response codes MUST NOT contain a + DNS response and MUST only be used on errors in the CoAP layer or + when a request does not fulfill the requirements of the DoC protocol. + + Communication errors with a DNS server (e.g., timeouts) SHOULD be + indicated by including a SERVFAIL DNS response in a successful CoAP + response. + + A DoC client might try to repeat a non-successful exchange unless + otherwise prohibited. The DoC client might also decide to repeat a + non-successful exchange with a different URI, for instance, when the + response indicates an unsupported Content-Format. + +4.3.2. Support of CoAP Caching + + For reliability and energy saving measures content decoupling and + thus en-route caching on proxies takes a far greater role than it + does, e.g., in HTTP. Likewise, CoAP utilizes cache validation to + refresh stale cache entries without large messages which often uses + hashing over the message content for ETag generation. As such, the + approach to guarantee the same cache key for DNS responses as + proposed in DoH ([RFC8484], section 5.1) is not sufficient and needs + to be updated so that the TTLs in the response are more often the + same regardless of query time. + + The DoC server MUST ensure that any sum of the Max-Age value of a + CoAP response and any TTL in the DNS response is less or equal to the + corresponding TTL received from an upstream DNS server. This also + includes the default Max-Age value of 60 seconds (see [RFC7252], + section 5.10.5) when no Max-Age option is provided. The DoC client + MUST then add the Max-Age value of the carrying CoAP response to all + TTLs in a DNS response on reception and use these calculated TTLs for + the associated records. + + The RECOMMENDED algorithm to assure the requirement for the DoC is to + set the Max-Age option of a response to the minimum TTL of a DNS + response and to subtract this value from all TTLs of that DNS + response. This prevents expired records unintentionally being served + from an intermediate CoAP cache. Additionally, it allows for the + ETag value for cache validation, if it is based on the content of the + response, not to change even if the TTL values are updated by an + upstream DNS cache. If only one record set per DNS response is + assumed, a simplification of this algorithm is to just set all TTLs + in the response to 0 and set the TTLs at the DoC client to the value + of the Max-Age option. + +4.3.3. Examples + + The following examples illustrate the replies to the query + "example.org. IN AAAA record", recursion turned on. Successful + responses carry one answer record including address + 2001:db8:1::1:2:3:4 and TTL 58719. + + A successful response: + + 2.05 Content + Content-Format: application/dns-message + Max-Age: 58719 + Payload: 00 00 81 a0 00 01 00 01 00 00 00 00 07 65 78 61 [binary] + 6d 70 6c 65 03 6f 72 67 00 00 1c 00 01 c0 0c 00 [binary] + 1c 00 01 00 01 37 49 00 10 20 01 0d b8 00 01 00 [binary] + 00 00 01 00 02 00 03 00 04 [binary] + + When a DNS error (SERVFAIL in this case) is noted in the DNS + response, the CoAP response still indicates success: + + 2.05 Content + Content-Format: application/dns-message + Payload: 00 00 81 a2 00 01 00 00 00 00 00 00 07 65 78 61 [binary] + 6d 70 6c 65 03 6f 72 67 00 00 1c 00 01 [binary] + + When an error occurs on the CoAP layer, the DoC server SHOULD respond + with an appropriate CoAP error, for instance "4.15 Unsupported + Content-Format" if the Content-Format option in the request was not + set to "application/dns-message" and the Content-Format is not + otherwise supported by the server. + +5. CoAP/CoRE Integration + +5.1. DNS Push + + DNS Push requires additional overhead, which conflicts with + constrained resources, This is the reason why it is RECOMMENDED to + use CoAP Observe [RFC7641] instead of DNS Push in the DoC domain. + + If the CoAP request indicates that the DoC client wants to observe a + resource record, a DoC server MAY use a DNS Subscribe message + [RFC8765] instead of a classic DNS query to fetch the information on + behalf of a DoC client. If this is not supported by the DoC server, + it MUST act as if the resource were not observable. + + Whenever the DoC server receives a DNS Push message [RFC8765] from + the DNS infrastructure for an observed resource record, the DoC + server sends an appropriate Observe response to the DoC client. + + If no more DoC clients observe a resource record for which the DoC + server has an open subscription, the DoC server MUST use a DNS + Unsubscribe message [RFC8765] to close its subscription to the + resource record as well. + +5.2. OSCORE + + It is RECOMMENDED to carry DNS messages encrypted using OSCORE + [RFC8613] between the DoC client and the DoC server. The exchange of + the security context is out of scope of this document. + +5.3. Mapping DoC to DoH + + This document provides no specification how to map between DoC and + DoH, e.g., at a CoAP-HTTP-proxy, and it is NOT RECOMMENDED. + Rewriting the FETCH method (Section 4.2) and the TTL rewriting + (Section 4.3.2) as specified in this draft would be non-trivial. It + is RECOMMENDED to use a DNS forwarder to map between DoC and DoH, as + would be the case for mapping between any other DNS transport. + +6. Considerations for Unencrypted Use + + The use of DoC without a security mode of CoAP is NOT RECOMMENDED. + Without a security mode, a large number of possible attacks need to + be evaluate in the context of the application's threat model. This + includes threats that are mitigated even by DNS over UDP: For + example, the random ID of the DNS header afford some protection + against off-path cache poisoning attacks---a threat that might be + mitigated by using random large token values in the CoAP request. + +7. Implementation Status + + This section records the status of known implementations of the + protocol defined by this specification at the time of posting of this + Internet-Draft, and is based on a proposal described in [RFC7942]. + The description of implementations in this section is intended to + assist the IETF in its decision processes in progressing drafts to + RFCs. Please note that the listing of any individual implementation + here does not imply endorsement by the IETF. Furthermore, no effort + has been spent to verify the information presented here that was + supplied by IETF contributors. This is not intended as, and must not + be construed to be, a catalog of available implementations or their + features. Readers are advised to note that other implementations may + exist. + + According to [RFC7942], "this will allow reviewers and working groups + to assign due consideration to documents that have the benefit of + running code, which may serve as evidence of valuable experimentation + and feedback that have made the implemented protocols more mature. + It is up to the individual working groups to use this information as + they see fit". + +7.1. DoC Client + + The authors of this document provide a DoC client implementation + available in the IoT operating system RIOT (https://doc.riot-os.org/ + group__net__gcoap__dns.html). + + Level of maturity: production + + Version compability: draft-ietf-core-dns-over-coap-02 + + License: LGPL-2.1 + + Contact information: Martine Lenders + + Last update of this information: March 2023 + +7.2. DoC Server + + The authors of this document provide a DoC server implementation in + Python (https://github.com/anr-bmbf-pivot/aiodnsprox). + + Level of maturity: production + + Version compability: draft-ietf-core-dns-over-coap-02 + + License: MIT + + Contact information: Martine Lenders + + Last update of this information: March 2023 + +8. Security Considerations + + When using unencrypted CoAP (see Section 6), setting the ID of a DNS + message to 0 as specified in Section 4.2.2 opens open the DNS cache + of a DoC client to cache poisoning attacks via response spoofing. + This documents requires an unpredictable CoAP token in each DoC query + from the client when CoAP is not secured to mitigate such an attack + over DoC (see Section 6). + + For encrypted usage with DTLS or OSCORE the impact of a fixed ID on + security is limited, as both harden against injecting spoofed + responses. Consequently, it is of little concern to leverage the + benefits of CoAP caching by setting the ID to 0. + + TODO more security + +9. IANA Considerations + +9.1. New "application/dns-message" Content-Format + + IANA is requested to assign CoAP Content-Format ID for the DNS + message media type in the "CoAP Content-Formats" sub-registry, within + the "CoRE Parameters" registry [RFC7252], corresponding to the + "application/dns-message" media type from the "Media Types" registry: + + Media-Type: application/dns-message + + Encoding: - + + Id: 553 + + Reference: [TBD-this-spec] + +9.2. New "core.dns" Resource Type + + IANA is requested to assign a new Resource Type (rt=) Link Target + Attribute, "core.dns" in the "Resource Type (rt=) Link Target + Attribute Values" sub-registry, within the "CoRE Parameters" register + [RFC6690]. + + Attribute Value: core.dns + + Description: DNS over CoAP resource. + + Reference: [TBD-this-spec] Section 3 + +10. References + +10.1. Normative References + + [RFC1035] Mockapetris, P., "Domain names - implementation and + specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, + November 1987, . + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, + DOI 10.17487/RFC2119, March 1997, + . + + [RFC7228] Bormann, C., Ersue, M., and A. Keranen, "Terminology for + Constrained-Node Networks", RFC 7228, + DOI 10.17487/RFC7228, May 2014, + . + + [RFC7252] Shelby, Z., Hartke, K., and C. Bormann, "The Constrained + Application Protocol (CoAP)", RFC 7252, + DOI 10.17487/RFC7252, June 2014, + . + + [RFC7641] Hartke, K., "Observing Resources in the Constrained + Application Protocol (CoAP)", RFC 7641, + DOI 10.17487/RFC7641, September 2015, + . + + [RFC7959] Bormann, C. and Z. Shelby, Ed., "Block-Wise Transfers in + the Constrained Application Protocol (CoAP)", RFC 7959, + DOI 10.17487/RFC7959, August 2016, + . + + [RFC8132] van der Stok, P., Bormann, C., and A. Sehgal, "PATCH and + FETCH Methods for the Constrained Application Protocol + (CoAP)", RFC 8132, DOI 10.17487/RFC8132, April 2017, + . + + [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC + 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, + May 2017, . + + [RFC8613] Selander, G., Mattsson, J., Palombini, F., and L. Seitz, + "Object Security for Constrained RESTful Environments + (OSCORE)", RFC 8613, DOI 10.17487/RFC8613, July 2019, + . + + [RFC9147] Rescorla, E., Tschofenig, H., and N. Modadugu, "The + Datagram Transport Layer Security (DTLS) Protocol Version + 1.3", RFC 9147, DOI 10.17487/RFC9147, April 2022, + . + +10.2. Informative References + + [I-D.ietf-add-dnr] + Boucadair, M., Reddy.K, T., Wing, D., Cook, N., and T. + Jensen, "DHCP and Router Advertisement Options for the + Discovery of Network-designated Resolvers (DNR)", Work in + Progress, Internet-Draft, draft-ietf-add-dnr-16, 27 April + 2023, . + + [I-D.ietf-core-href] + Bormann, C. and H. Birkholz, "Constrained Resource + Identifiers", Work in Progress, Internet-Draft, draft- + ietf-core-href-12, 6 March 2023, + . + + [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform + Resource Identifier (URI): Generic Syntax", STD 66, + RFC 3986, DOI 10.17487/RFC3986, January 2005, + . + + [RFC6690] Shelby, Z., "Constrained RESTful Environments (CoRE) Link + Format", RFC 6690, DOI 10.17487/RFC6690, August 2012, + . + + [RFC7942] Sheffer, Y. and A. Farrel, "Improving Awareness of Running + Code: The Implementation Status Section", BCP 205, + RFC 7942, DOI 10.17487/RFC7942, July 2016, + . + + [RFC8094] Reddy, T., Wing, D., and P. Patil, "DNS over Datagram + Transport Layer Security (DTLS)", RFC 8094, + DOI 10.17487/RFC8094, February 2017, + . + + [RFC8323] Bormann, C., Lemay, S., Tschofenig, H., Hartke, K., + Silverajan, B., and B. Raymor, Ed., "CoAP (Constrained + Application Protocol) over TCP, TLS, and WebSockets", + RFC 8323, DOI 10.17487/RFC8323, February 2018, + . + + [RFC8484] Hoffman, P. and P. McManus, "DNS Queries over HTTPS + (DoH)", RFC 8484, DOI 10.17487/RFC8484, October 2018, + . + + [RFC8499] Hoffman, P., Sullivan, A., and K. Fujiwara, "DNS + Terminology", BCP 219, RFC 8499, DOI 10.17487/RFC8499, + January 2019, . + + [RFC8765] Pusateri, T. and S. Cheshire, "DNS Push Notifications", + RFC 8765, DOI 10.17487/RFC8765, June 2020, + . + + [RFC9176] Amsüss, C., Ed., Shelby, Z., Koster, M., Bormann, C., and + P. van der Stok, "Constrained RESTful Environments (CoRE) + Resource Directory", RFC 9176, DOI 10.17487/RFC9176, April + 2022, . + + [RFC9250] Huitema, C., Dickinson, S., and A. Mankin, "DNS over + Dedicated QUIC Connections", RFC 9250, + DOI 10.17487/RFC9250, May 2022, + . + +Appendix A. Change Log + +A.1. Since draft-ietf-core-dns-over-coap-02 + (https://datatracker.ietf.org/doc/html/draft-ietf-core-dns-over- + coap-02) + + * Move implementation details to Implementation Status (in + accordance with [RFC7942]) + + * Recommend root path to keep the CoAP options small + + * Set Content-Format for application/dns-message to 553 + + * SVCB/DNR: Move to Server Selection Section but leave TBD based on + DNSOP discussion for now + + * Clarify that DoC and DoC are disjunct + + * Clarify mapping between DoC and DoH + + * Update considerations on unencrypted use + + * Don't call OSCORE end-to-end encrypted + +A.2. Since draft-ietf-core-dns-over-coap-01 + (https://datatracker.ietf.org/doc/html/draft-ietf-core-dns-over- + coap-01) + + * Specify DoC server role in terms of DNS terminology + + * Clarify communication of DoC to DNS infrastructure is agnostic of + the transport + + * Add subsection on how to implement DNS Push in DoC + + * Add appendix on reference implementation + +A.3. Since draft-ietf-core-dns-over-coap-00 + (https://datatracker.ietf.org/doc/html/draft-ietf-core-dns-over- + coap-00) + + * SVGify ASCII art + + * Move section on "DoC Server Considerations" (was Section 5.1) to + its own draft (draft-lenders-dns-cns + (https://datatracker.ietf.org/doc/draft-lenders-dns-cns/)) + + * Replace layer violating statement for CON with statement of fact + + * Add security considerations on ID=0 + +A.4. Since draft-lenders-dns-over-coap-04 + (https://datatracker.ietf.org/doc/html/draft-lenders-dns-over- + coap-04) + + * Removed change log of draft-lenders-dns-over-coap + +Acknowledgments + + The authors of this document want to thank Ben Schwartz and Tim + Wicinski for their feedback and comments. + +Authors' Addresses + + Martine Sophie Lenders + Freie Universität Berlin + Takustrasse 9 + D-14195 Berlin + Germany + Email: m.lenders@fu-berlin.de + + + Christian Amsüss + Email: christian@amsuess.com + + + Cenk Gündoğan + Huawei Technologies + Riesstrasse 25 + D-80992 Munich + Germany + Email: cenk.gundogan@huawei.com + + + Thomas C. Schmidt + HAW Hamburg + Berliner Tor 7 + D-20099 Hamburg + Germany + Email: t.schmidt@haw-hamburg.de + + + Matthias Wählisch + Freie Universität Berlin + Takustrasse 9 + D-14195 Berlin + Germany + Email: m.waehlisch@fu-berlin.de diff --git a/index.html b/index.html new file mode 100644 index 0000000..3cef320 --- /dev/null +++ b/index.html @@ -0,0 +1,48 @@ + + + + anr-bmbf-pivot/draft-dns-over-coap main preview + + + + +

Editor's drafts for main branch of anr-bmbf-pivot/draft-dns-over-coap

+

View saved issues, or the latest GitHub issues and pull requests in the repo.

+ + + + + + + + +
DoCplain textdatatrackerdiff with last submission
+ + + diff --git a/issues.html b/issues.html new file mode 100644 index 0000000..7afaf98 --- /dev/null +++ b/issues.html @@ -0,0 +1,103 @@ + + + + + Issue Viewer + + + + +
+ + + records +
+
+ + + + + + + + + + + + + +
IDTitleStateAuthorAssigneeLabels
+
+
+
+

This page shows GitHub issues in a simple form.

+

The filter box above accepts a set of filters, each separated by space.

+
    +
+

You can /sort on id, recent, or closed.

+

Pressing enter saves the current search. + Pressing esc leaves the text input area.

+

Outside the search box

+

Clicking an issue title displays details for the issue including comments. + Pressing n or j moves to the next issue, + and p or k move to the previous one.

+

Pressing esc closes the issue view, ' focuses search, and + c clears the search.

+
+
+ + diff --git a/issues.js b/issues.js new file mode 100644 index 0000000..632b674 --- /dev/null +++ b/issues.js @@ -0,0 +1,1050 @@ +function setStatus(msg) { + let status = document.getElementById('status'); + status.innerText = msg; +} + +function date(s) { + const d = Date.parse(s); + if (isNaN(d)) { + return 0; + } + return d; +} + +function stateString(issue) { + let str; + if (issue.pr) { + switch (issue.state) { + case 'MERGED': + str = 'merged'; + break; + case 'CLOSED': + str = 'discarded'; + break; + default: + str = 'pr'; + break; + } + } else { + str = issue.state.toLowerCase(); + } + return str; +} + +function stateOrder(issue) { + return ['open', 'pr', 'closed', 'merged', 'discarded'].indexOf(stateString(issue)); +} + +var sortKey = 'id'; +var sortInvert = false; +function invert(x) { + return x * (sortInvert ? -1 : 1); +} +function sort(k) { + sortInvert = (k === sortKey) ? !sortInvert : false; + k = k || sortKey; + let message = k; + switch (k) { + case 'id': + subset.sort((x, y) => invert(x.number - y.number)); + message = 'ID'; + break; + case 'recent': + subset.sort((x, y) => invert(date(y.updatedAt) - date(x.updatedAt))); + message = 'last modified'; + break; + case 'closed': + subset.sort((x, y) => invert(date(y.closedAt) - date(x.closedAt))); + message = 'time of closure'; + break; + case 'title': + subset.sort((x, y) => invert(x.title.localeCompare(y.title))); + break; + case 'state': + subset.sort((x, y) => invert(stateOrder(x) - stateOrder(y))); + break; + case 'author': + subset.sort((x, y) => invert(x.author.localeCompare(y.author))); + break; + default: + setStatus('no idea how to sort like that'); + return; + } + setStatus(`sorted by ${message}${(sortInvert) ? ' (reversed)' : ''}`); + sortKey = k; + list(subset); +} + +function sortSetup() { + ['id', 'title', 'state', 'author'].forEach(k => { + let el = document.getElementById(`sort-${k}`); + el.addEventListener('click', _ => sort(k)); + el.style.cursor = 'pointer'; + el.title = `Sort by ${el.innerText}`; + }); +} + +var db; +async function get() { + db = null; + const response = await fetch('archive.json'); + if (Math.floor(response.status / 100) !== 2) { + throw new Error(`Error loading <${url}>: ${response.status}`); + } + db = await response.json(); + db.pulls.forEach(pr => pr.pr = true); + subset = db.all = db.issues.concat(db.pulls); + db.labels = db.labels.reduce((all, l) => { + all[l.name] = l; + return all; + }, {}); + sort(); + document.title = `${db.repo} Issues`; + console.log(`Loaded ${db.all.length} issues for ${db.repo}.`); + console.log('Raw data for issues can be found in:'); + console.log(' db.all = all issues and pull requests'); + console.log(' subset = just the subset of issues that are shown'); + console.log('format(subset[, formatter]) to dump the current subset to the console'); +} + +var issueFilters = { + assigned: { + args: ['string'], + h: 'assigned to this user', + f: login => issue => { + if (login === '') { + return issue.assignees.length > 0; + } else { + return issue.assignees.some(assignee => assignee === login); + } + }, + }, + + author: { + args: ['string'], + h: 'created by this user', + f: login => issue => issue.author === login, + }, + + commenter: { + args: ['string'], + h: 'commented on by this user', + f: login => issue => { + return issue.author === login || + issue.comments.some(comment => comment.author === login) || + (issue.reviews || []).some(review => review.author === login); + }, + }, + + reviewer: { + args: ['string'], + h: 'reviewed by this user', + f: login => issue => { + return issue.reviews && + issue.reviews.some(review => review.author === login); + }, + }, + + user: { + args: ['string'], + h: 'mentions this user', + f: login => issue => { + return issue.author === login || + issue.assignees.some(assignee => assignee === login) || + issue.comments.some(comment => comment.author === login) || + (issue.reviews || []).some(review => review.author === login); + }, + }, + + closed: { + args: [], + h: 'is closed', + f: issue => issue.state === 'CLOSED', + }, + + open: { + args: [], + h: 'is open', + f: issue => issue.state === 'OPEN', + }, + + merged: { + args: [], + h: 'a merged pull request', + f: issue => issue.state == 'MERGED', + }, + + discarded: { + args: [], + h: 'a discarded pull request', + f: issue => issue.pr && issue.state === 'CLOSED' + }, + + n: { + args: ['integer'], + h: 'issue by number', + f: i => issue => issue.number === i, + }, + + label: { + args: ['string'], + h: 'has a specific label', + f: name => issue => issue.labels.some(label => label === name), + }, + + labelled: { + args: [], + h: 'has any label', + f: issue => issue.labels.length > 0, + }, + + title: { + args: ['string'], + h: 'search title with a regular expression', + f: function(re) { + re = new RegExp(re); + return issue => issue.title.match(re); + } + }, + + body: { + args: ['string'], + h: 'search body with a regular expression', + f: function(re) { + re = new RegExp(re); + return issue => issue.body.match(re); + } + }, + + text: { + args: ['string'], + h: 'search title and body with a regular expression', + f: function(re) { + re = new RegExp(re); + return issue => issue.title.match(re) || issue.body.match(re); + } + }, + + pr: { + args: [], + h: 'is a pull request', + f: issue => issue.pr, + }, + + issue: { + args: [], + h: 'is a plain issue, i.e., not(pr)', + f: function(issue) { + return !issue.pr; + } + }, + + or: { + args: ['filter', '...filter'], + h: 'union', + f: (...filters) => x => filters.some(filter => filter(x)), + }, + + and: { + args: ['filter', '...filter'], + h: 'intersection', + f: (...filters) => x => filters.every(filter => filter(x)), + }, + + + xor: { + args: ['filter', '...filter'], + h: 'for the insane', + f: (...filters) => + x => filters.slice(1).reduce((a, filter) => a ^ filter(x), filters[0](x)), + }, + + not: { + args: ['filter'], + h: 'exclusion', + f: a => issue => !a(issue), + }, + + closed_since: { + args: ['date'], + h: 'issues closed since the date and time', + f: since => issue => date(issue.closedAt) >= since, + }, + + updated_since: { + args: ['date'], + h: 'issues updated since the date and time', + f: since => issue => date(issue.updatedAt) >= since, + } +}; + +class Parser { + constructor(s) { + this.str = s; + this.skipws(); + } + + skipws() { + this.str = this.str.trimLeft(); + } + + jump(idx) { + this.str = this.str.slice(idx); + this.skipws(); + } + + get next() { + return this.str.charAt(0); + } + + parseName() { + let m = this.str.match(/^[a-zA-Z](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?/); + if (!m) { + return; + } + + this.jump(m[0].length); + return m[0]; + } + + parseSeparator(separator) { + if (this.next !== separator) { + throw new Error(`Expecting separator ${separator}`); + } + this.jump(1); + } + + parseString() { + let end = -1; + for (let i = 0; i < this.str.length; ++i) { + let v = this.str.charAt(i); + if (v === ')' || v === ',') { + end = i; + break; + } + } + if (end < 0) { + throw new Error(`Unterminated string`); + } + let s = this.str.slice(0, end).trim(); + this.jump(end); + return s; + } + + parseDate() { + let str = this.parseString(); + let time = Date.parse(str); + if (isNaN(time)) { + throw new Error(`not a valid date: ${str}`); + } + return time; + } + + parseNumber() { + let m = this.str.match(/^\d+/); + if (!m) { + return; + } + this.jump(m[0].length); + return parseInt(m[0], 10); + } + + parseFilter() { + if (this.next === '-') { + this.parseSeparator('-'); + return issueFilters.not.f.call(null, this.parseFilter()); + } + let name = this.parseName(); + if (!name) { + let n = this.parseNumber(); + if (!isNaN(n)) { + return issueFilters.n.f.call(null, n); + } + return; + } + let f = issueFilters[name]; + if (!f) { + throw new Error(`Unknown filter: ${name}`); + } + if (f.args.length === 0) { + return f.f; + } + let args = []; + for (let i = 0; i < f.args.length; ++i) { + let arg = f.args[i]; + let ellipsis = arg.slice(0, 3) === '...'; + if (ellipsis) { + arg = arg.slice(3); + } + + this.parseSeparator((i === 0) ? '(' : ','); + if (arg === 'string') { + args.push(this.parseString()); + } else if (arg === 'date') { + args.push(this.parseDate()); + } else if (arg === 'integer') { + args.push(this.parseNumber()); + } else if (arg === 'filter') { + args.push(this.parseFilter()); + } else { + throw new Error(`Error in filter ${name} definition`); + } + if (ellipsis && this.next === ',') { + --i; + } + } + this.parseSeparator(')'); + return f.f.apply(null, args); + } +} + +var subset = []; +function filterIssues(str) { + subset = db.all; + let parser = new Parser(str); + let f = parser.parseFilter(); + while (f) { + subset = subset.filter(f); + f = parser.parseFilter(); + } +} + +var formatter = { + brief: x => `* ${x.title} (#${x.number})`, + md: x => `* [#${x.number}](${x.url}): ${x.title}`, +}; + +function format(set, f) { + return (set || subset).map(f || formatter.brief).join('\n'); +} + +var debounces = {}; +var debounceSlowdown = 100; +function measureSlowdown() { + let start = Date.now(); + window.setTimeout(_ => { + let diff = Date.now() - start; + if (diff > debounceSlowdown) { + console.log(`slowed to ${diff} ms`); + debounceSlowdown = Math.min(1000, diff + debounceSlowdown / 2); + } + }, 0); +} +function debounce(f) { + let r = now => { + measureSlowdown(); + f(now); + }; + return e => { + if (debounces[f.name]) { + window.clearTimeout(debounces[f.name]); + delete debounces[f.name]; + } + if (e.key === 'Enter') { + r(true); + } else { + debounces[f.name] = window.setTimeout(_ => { + delete debounces[f.name]; + r(false) + }, 10 + debounceSlowdown); + } + } +} + +function cell(row, children, cellClass) { + let td = document.createElement('td'); + if (cellClass) { + td.className = cellClass; + } + if (Array.isArray(children)) { + children.forEach(c => { + td.appendChild(c); + td.appendChild(document.createTextNode(' ')); + }); + } else { + td.appendChild(children); + } + row.appendChild(td); +} + + +function loadAvatars(elements) { + elements.forEach(e => { + let avatar = new Image(16, 16); + avatar.addEventListener('load', _ => e.target.replaceWith(avatar)); + let user = e.target.dataset.user; + avatar.src = `https://github.com/${user}.png?size=16`; + }); +} +var intersection = new IntersectionObserver(loadAvatars, { rootMargin: '50px 0px 100px 0px' }); + +function author(x, click, userSearch) { + let user = x.author || x; + let sp = document.createElement('span'); + sp.classList.add('item', 'user'); + let ai = document.createElement('a'); + ai.href = `https://github.com/${user}`; + ai.className = 'avatar'; + let placeholder = document.createElement('span'); + placeholder.className = 'swatch'; + placeholder.innerText = '\uD83E\uDDD0'; + placeholder.dataset.user = user; + intersection.observe(placeholder); + ai.appendChild(placeholder); + sp.appendChild(ai); + + let au = document.createElement('a'); + au.href = `#${userSearch || 'user'}(${user})`; + au.innerText = user; + au.addEventListener('click', click); + sp.appendChild(au); + return sp; +} + +function issueState(issue, click) { + let st = document.createElement('span'); + st.classList.add('item', 'state'); + let a = document.createElement('a'); + a.innerText = stateString(issue); + a.href = `#${stateString(issue)}`; + if (click) { + a.addEventListener('click', click); + } + st.appendChild(a); + return st; +} + +function showBody(item) { + let div = document.createElement('div'); + div.className = 'body'; + let body = item.body.trim().replace(/\r\n?/g, '\n'); + + let list = null; + let el = null; + let pre = null; + function closeElement() { + if (el) { + if (list) { + list.appendChild(el); + } else { + div.appendChild(el); + } + } + el = null; + pre = null; + } + function closeBoth() { + closeElement(); + if (list) { + div.appendChild(list); + list = null; + } + } + function addText(t) { + if (pre) { + el.appendChild(document.createTextNode(t + '\n')); + return; + } + if (el.innerText !== '') { + el.appendChild(document.createElement('br')); + } + if (t !== '') { + el.appendChild(document.createTextNode(t)); + } + } + + body.split('\n').forEach(t => { + if (t.charAt(0) === ' ') { + t = t.substring(1); // This fixes lots of problems. + } + if (t.indexOf('```') === 0) { + let needNew = !el || !pre; + closeBoth(); + if (needNew) { + el = document.createElement('pre'); + pre = 'q'; + let language = t.substring(3).trim(); + if (language) { + el.dataset.language = language; + } + } + } else if (pre === 'q') { + addText(t); + } else if (!el && t.indexOf(' ') === 0) { + if (!pre) { + closeBoth(); + el = document.createElement('pre'); + pre = 's'; + } + addText(t.substring(3)); + } else if (t.trim() === '') { + closeElement(); + } else if (t.indexOf('# ') === 0) { + closeBoth(); + el = document.createElement('h2'); + addText(t.substring(2).trimLeft()); + closeElement(); + } else if (t.indexOf('## ') === 0) { + closeBoth(); + el = document.createElement('h3'); + addText(t.substring(3).trimLeft()); + closeElement(); + } else if (t.indexOf('### ') === 0) { + closeBoth(); + el = document.createElement('h4'); + addText(t.substring(4).trimLeft()); + closeElement(); + } else if (t.charAt(0) === '>') { + if (!el || el.tagName !== 'BLOCKQUOTE') { + closeElement(); + el = document.createElement('blockquote'); + } + addText(t.substring(1).trimLeft()); + } else if (t.indexOf('* ') === 0 || t.indexOf('- ') === 0) { + if (list && list.tagName !== 'UL') { + closeBoth(); + } else { + closeElement(); + } + if (!list) { + list = document.createElement('ul'); + } + el = document.createElement('li'); + addText(t.substring(2).trimLeft()); + } else if (t.match(/^(?:\(?\d+\)|\d+\.)/)) { + if (list && list.tagName !== 'OL') { + closeBoth(); + } else { + closeElement(); + } + if (!list) { + list = document.createElement('ol'); + } + el = document.createElement('li'); + let sep = t.match(/^(?:\(?\d+\)|\d+\.)/)[0].length; + addText(t.substring(sep).trimLeft()); + } else { + if (list && !el) { + div.appendChild(list); + list = null; + } + if (!el) { + el = document.createElement('p'); + } + addText(t); + } + }); + closeBoth(); + return div; +} + +function showDate(d, reference) { + let de = document.createElement('span'); + de.classList.add('item', 'date'); + const full = d.toISOString(); + const parts = full.split(/[TZ\.]/); + if (reference && parts[0] === reference.toISOString().split('T')[0]) { + de.innerText = parts[1]; + } else { + de.innerText = parts[0] + ' ' + parts[1]; + } + de.title = full; + return de; +} + +function narrow(e, extra) { + e.preventDefault(); + hideIssue(); + let cmd = document.getElementById('cmd'); + let v = `${cmd.value} ${extra}`; + cmd.value = v.trim(); + redraw(true); +} + +function narrowLabel(e) { + narrow(e, `label(${e.target.innerText})`); +} + +function narrowState(e) { + narrow(e, e.target.innerText); +} + +function narrowUser(userType) { + return function narrowUserInner(e) { + narrow(e, `${userType}(${e.target.innerText})`); + }; +} + +function showLabels(labels, click) { + return labels.map(label => { + let item = document.createElement('span'); + item.className = 'item'; + let sp = document.createElement('span'); + sp.className = 'swatch'; + item.appendChild(sp); + let a = document.createElement('a'); + a.innerText = label; + a.href = `#label(${label})`; + if (click) { + a.addEventListener('click', click); + } + if (db.labels.hasOwnProperty(label)) { + sp.style.backgroundColor = '#' + db.labels[label].color; + if (db.labels[label].description) { + item.title = db.labels[label].description; + } + } + item.appendChild(a); + return item; + }); +} + +// Make a fresh replacement element for the identified element. +function freshReplacement(id) { + let e = document.getElementById(id); + let r = document.createElement(e.tagName); + r.id = id; + e.replaceWith(r); + return r; +} + +var displayed = null; + +function show(index) { + if (index < 0 || index >= subset.length) { + hideIssue(); + return; + } + displayed = index; + const issue = subset[index]; + + document.getElementById('overlay').classList.add('active'); + let frame = freshReplacement('issue'); + frame.classList.add('active'); + + function showTitle() { + let title = document.createElement('h2'); + title.className = 'title'; + let number = document.createElement('a'); + number.className = 'number'; + number.href = issue.url; + number.innerText = `#${issue.number}`; + title.appendChild(number); + title.appendChild(document.createTextNode(': ')); + let name = document.createElement('a'); + name.href = issue.url; + name.innerText = issue.title; + title.appendChild(name); + return title; + } + + function showIssueLabels() { + let meta = document.createElement('div'); + meta.className = 'meta'; + showLabels(issue.labels, hideIssue).forEach(el => { + meta.appendChild(el); + meta.appendChild(document.createTextNode(' ')); + }); + return meta; + } + + function showIssueUsers() { + let meta = document.createElement('div'); + meta.className = 'meta'; + meta.appendChild(author(issue, hideIssue, 'author')); + if (issue.assignees && issue.assignees.length > 0) { + let arrow = document.createElement('span'); + arrow.innerText = ' \u279c'; + arrow.title = 'Assigned to'; + meta.appendChild(arrow); + issue.assignees.map(u => author(u, hideIssue, 'assigned')).forEach(el => { + meta.appendChild(document.createTextNode(' ')); + meta.appendChild(el); + }); + } + return meta; + } + + function showIssueDates() { + let meta = document.createElement('div'); + meta.className = 'meta'; + let created = new Date(issue.createdAt); + meta.appendChild(showDate(created)); + meta.appendChild(issueState(issue, hideIssue)); + if (issue.closedAt) { + meta.appendChild(showDate(new Date(issue.closedAt), created)); + } + return meta; + } + + let refdate = null; + function showComment(c) { + let row = document.createElement('tr'); + let cdate = new Date(c.createdAt); + cell(row, showDate(cdate, refdate), 'date'); + refdate = cdate; + cell(row, author(c, hideIssue, (c.commit) ? 'reviewer' : 'commenter'), 'user'); + + if (issue.pr) { + let icon = document.createElement('span'); + switch (c.state) { + case 'APPROVED': + icon.innerText = '\u2714'; + icon.title = 'Approved'; + break; + case 'CHANGES_REQUESTED': + icon.innerText = '\u2718'; + icon.title = 'Changes Requested'; + break; + default: + icon.innerText = '\uD83D\uDCAC'; + icon.title = 'Comment'; + break; + } + cell(row, icon); + } + + let body = showBody(c); + if (c.comments && c.comments.length > 0) { + let codeComments = document.createElement('div'); + codeComments.className = 'item'; + const s = (c.comments.length === 1) ? '' : 's'; + codeComments.innerText = `... ${c.comments.length} comment${s} on changes`; + body.appendChild(codeComments); + } + cell(row, body); + return row; + } + + frame.appendChild(showTitle()); + frame.appendChild(showIssueLabels()); + frame.appendChild(showIssueUsers()); + frame.appendChild(showIssueDates()); + frame.appendChild(showBody(issue)); + + let allcomments = (issue.comments || []).concat(issue.reviews || []); + allcomments.sort((a, b) => date(a.createdAt) - date(b.createdAt)); + let comments = document.createElement('table'); + comments.className = 'comments'; + allcomments.map(showComment).forEach(row => comments.appendChild(row)); + frame.appendChild(comments); + + frame.scroll(0, 0); + frame.focus(); +} + +function hideIssue() { + document.getElementById('help').classList.remove('active'); + document.getElementById('issue').classList.remove('active'); + document.getElementById('overlay').classList.remove('active'); + displayed = null; +} + +function step(n) { + if (displayed === null) { + if (n > 0) { + show(n - 1); + } else { + show(subset.length + n); + } + } else { + show(displayed + n); + } +} + +function makeRow(issue, index) { + function cellID() { + let a = document.createElement('a'); + a.innerText = issue.number; + a.href = issue.url; + a.onclick = e => { + e.preventDefault(); + show(index); + }; + return a; + } + + function cellTitle() { + let a = document.createElement('a'); + a.innerText = issue.title; + a.href = issue.url; + a.onclick = e => { + e.preventDefault(); + show(index); + }; + return a; + } + + let tr = document.createElement('tr'); + cell(tr, cellID(), 'id'); + cell(tr, cellTitle(), 'title'); + cell(tr, issueState(issue, narrowState), 'state'); + cell(tr, author(issue, narrowUser('author'), 'author'), 'user'); + cell(tr, (issue.assignees || []) + .map(u => author(u, narrowUser('assigned'), 'assigned')), 'assignees'); + cell(tr, showLabels(issue.labels, narrowLabel), 'labels'); + return tr; +} + +function list(issues) { + if (!issues) { + return; + } + + let body = freshReplacement('issuelist'); + body.innerHTML = ''; + issues.forEach((issue, index) => { + body.appendChild(makeRow(issue, index)); + }); +} + +var currentFilter = ''; +function filter(str, now) { + try { + filterIssues(str); + setStatus(`${subset.length} records selected`); + if (now) { + window.location.hash = str; + currentFilter = str; + } + } catch (e) { + if (now) { // Only show errors when someone hits enter. + setStatus(`Error: ${e.message}`); + console.log(e); + } + } +} + +function showHelp() { + setStatus('help shown'); + let h = document.getElementById('help'); + h.classList.add('active'); + h.scroll(0, 0); + h.focus(); + document.getElementById('overlay').classList.add('active'); +} + +function slashCmd(cmd) { + if (cmd[0] === 'help') { + document.getElementById('cmd').blur(); + showHelp(); + } else { + setStatus('unknown command: /' + cmd.join(' ')); + } +} + +function redraw(now) { + let cmd = document.getElementById('cmd'); + if (cmd.value.charAt(0) == '/') { + if (now) { + slashCmd(cmd.value.slice(1).split(' ').map(x => x.trim())); + cmd.value = currentFilter; + } + return; + } + + if (!db) { + if (now) { + showStatus('Still loading...'); + } + return; + } + + document.getElementById('help').classList.remove('active'); + filter(cmd.value, now); + list(subset); +} + +function generateHelp() { + let functionhelp = document.getElementById('functions'); + Object.keys(issueFilters).forEach(k => { + let li = document.createElement('li'); + let arglist = ''; + if (issueFilters[k].args.length > 0) { + arglist = '(' + issueFilters[k].args.map(x => '<' + x + '>').join(', ') + ')'; + } + let fn = document.createElement('tt'); + fn.innerText = k + arglist; + li.appendChild(fn); + let help = ''; + if (issueFilters[k].h) { + help = ' - ' + issueFilters[k].h; + } + li.appendChild(document.createTextNode(help)); + functionhelp.appendChild(li); + }); +} + +function addFileHelp() { + setStatus('error loading file'); + if (window.location.protocol !== 'file:') { + return; + } + let p = document.createElement('p'); + p.className = 'warning'; + p.innerHTML = 'Important: Browsers display files inconsistently.' + + ' You can work around this by running an HTTP server,' + + ' such as python3 -m http.server,' + + ' then view this file using that server.'; + document.getElementById('help').insertBefore(p, h.firstChild); +} + +function issueOverlaySetup() { + let overlay = document.getElementById('overlay'); + overlay.addEventListener('click', hideIssue); + window.addEventListener('keyup', e => { + if (e.target.id === 'cmd') { + if (e.key === 'Escape') { + e.preventDefault(); + e.target.blur(); + } + return; + } + if (e.key === 'Escape') { + e.preventDefault(); + hideIssue(); + } + }); + window.addEventListener('keypress', e => { + if (e.target.closest('input')) { + return; + } + if (e.key === 'p' || e.key === 'k') { + e.preventDefault(); + step(-1); + } else if (e.key === 'n' || e.key === 'j') { + e.preventDefault(); + step(1); + } else if (e.key === '?') { + e.preventDefault(); + showHelp(); + } else if (e.key === '\'') { + e.preventDefault(); + hideIssue(); + document.getElementById('cmd').focus(); + } else if (e.key === 'c') { + e.preventDefault(); + hideIssue(); + document.getElementById('cmd').value = ''; + redraw(true); + } + }) +} + +window.onload = () => { + let cmd = document.getElementById('cmd'); + let redrawHandler = debounce(redraw); + cmd.addEventListener('input', redrawHandler); + cmd.addEventListener('keypress', redrawHandler); + window.addEventListener('hashchange', e => { + cmd.value = decodeURIComponent(window.location.hash.substring(1)); + redrawHandler(e); + }); + if (window.location.hash) { + cmd.value = decodeURIComponent(window.location.hash.substring(1)); + } + sortSetup(); + generateHelp(); + issueOverlaySetup(); + get().then(redraw).catch(addFileHelp); +}