#!/usr/bin/env bash
set -euo pipefail
# set -x

(
cat <<'EOF'
// NOTE: generated by gendoc.sh

/*
Dnsclay implements a DNS server that translates DNS UPDATE (RFC 2136) and DNS
AXFR (RFC 5936, zone transfers) requests to the many custom cloud DNS operator
APIs for managing DNS records/zones. Dnsclay keeps a local copy of the records,
periodically synchronizes its copy with authoritative data at the cloud DNS
operator, and sends DNS NOTIFY (RFC 1996) messages to configured listeners when
any records changed. Dnsclay also has a web interface for managing the
configured zones, and for viewing and editing records.

Most cloud DNS operators implement their own custom APIs for changing DNS
records. Application developers are tempted to add support for long lists
of those custom APIs to their applications so they can make automated DNS
changes (even just for handling ACME verification through DNS). This is
time-consuming and error-prone. Developers can instead settle on the standard
DNS interfaces with UPDATE/AXFR/NOTIFY, talking either directly to DNS servers
that implement them (like BIND, Knot), or talking to dnsclay which does the
translating.

Dnsclay implements TLS with the option for client certificate authentication
(mutual TLS) based on public keys (ignoring certificate
name/expiration/constraints, keeping it simple). DNS TSIG (RFC 8945) is also
supported.

Dnsclay helps diagnosing errors by returning error responses with Extended DNS
Errors (RFC 8914) to requests with EDNS0.

Dnsclay does not answer regular DNS queries for records (recursive or
authoritative), with the exception of giving authoritative answers to SOA
queries. Clients can use this to check if the zone has been updated before
deciding to do an AXFR of the full zone.

One of the implemented backend providers, "rfc2136", connects to DNS servers
implementing the standard DNS UPDATE/AXFR protocols, making dnsclay a web-based
zone editor for standard DNS servers.

Like secondary DNS servers, dnsclay can periodically fetch the SOA record from
authoritative name servers, fetching the full zone and synchronizing it into
its local state if the zone serial in the SOA record changes.  Dnsclay also
periodically does a full sync regardless of SOA serial, since some DNS
operators don't change the serial when a zone changes. In such cases, dnsclay
will keep track of its own serial, so its clients can properly detect zone
changes. The "refresh interval" from the SOA record is not used, since it is
often configured to work only with the setup of the primary/secondary servers
of the DNS operator.  After a change to a zone, either because of DNS UPDATE
through dnsclay or by dnsclay detecting a record change at the DNS operator,
dnsclay will temporarily increase the interval with which it checks again for a
new update, speculating more changes are coming. Timely notification of DNS
record changes are useful during lock-step changes like key rollovers. Cloud
DNS operators typically don't have a mechanism to notify applications of
changes to records.

# Limitations

DNS UPDATE/AXFR/NOTIFY may look relatively complicated to application
developers interested in making automated DNS changes. They may be expecting a
HTTP/JSON API. If one is standardized, dnsclay could implement it.

Changes in a DNS UPDATE request must be applied atomically: Either all the
changes in a request must be applied, or none. Dnsclay cannot implement this
requirement for all requests. With the libdns API, records cannot be added and
removed atomically.

Cloud DNS operators may have unexpected limitations. If standard DNS resource
record types are not implemented, adding them may result in an error.

The dnsclay server does not process multiple messages on a single TCP connection
in parallel. It reads a request, process it, and writes a response, then starts
on the next request. Multiple connections, and UDP packets, are handled in
parallel.

EOF

function usage() {
cat <<EOF
# Usage for "$@"

EOF
set +e
cd testdata # prevent finding local root fs
../$@ -h 2>../gendoc.tmp
cd ..
set -e
cat gendoc.tmp | sed 's/^/	/g'
rm gendoc.tmp

}

usage dnsclay
usage dnsclay serve
usage dnsclay dns notify
usage dnsclay dns update
usage dnsclay dns xfr

cat <<EOF
# Providers

The following providers are implemented in dnsclay, with community-provided
implementations maintained at https://github.com/libdns:

EOF
for i in $(cat providers.txt | cut -f2 -d' ' | sed 's/"//g'); do
	echo "  - https://$i"
done

cat <<EOF
*/
package main
EOF
) >doc.go
gofmt -w doc.go
