This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
238
unikernel/duniverse/ocaml-dns/server/dns_server.mli
Normal file
238
unikernel/duniverse/ocaml-dns/server/dns_server.mli
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
(* (c) 2017, 2018 Hannes Mehnert, all rights reserved *)
|
||||
|
||||
open Dns
|
||||
|
||||
(** DNS Server implementation *)
|
||||
|
||||
(** Authentication, stored in a Dns_trie with privileges to operations embedded in the name. *)
|
||||
module Authentication : sig
|
||||
(** A key is a pair of a [`raw Domain_name.t] and a [Dnskey.t]. In the name,
|
||||
operation privileges and potentially IP addresses are encoded, e.g.
|
||||
[foo._transfer.example.com] may do AXFR on [example.com] and any
|
||||
subdomain, e.g. [foo.example.com]. *)
|
||||
|
||||
type operation = [
|
||||
| `Update
|
||||
| `Transfer
|
||||
| `Notify
|
||||
]
|
||||
(** The type of operations, sorted by highest ot lowest privileges, an
|
||||
[`Update] may as well carry out a [`Transfer]. *)
|
||||
|
||||
val operation_to_string : operation -> string
|
||||
(** [operation_to_string op] is the string representation of [op]. *)
|
||||
|
||||
val all_ops : operation list
|
||||
(** [all_ops] is a list of all operations. *)
|
||||
|
||||
val access_granted : required:operation -> operation -> bool
|
||||
(** [access_granted ~required key_operation] is [true] if [key_operation] is
|
||||
authorised for [required] operation. *)
|
||||
|
||||
val zone_and_operation : 'a Domain_name.t -> ([`host] Domain_name.t * operation) option
|
||||
(** [zone_and_operation key] is [Some (zone, op)], the [zone] of the [key],
|
||||
and its operation [op]. If the [key] is not in the expected format, [None]
|
||||
is returned. *)
|
||||
|
||||
val access : ?key:'a Domain_name.t -> zone:'b Domain_name.t -> operation -> bool
|
||||
(** [access op ~key ~zone] checks whether [key] is authorised for [op] on
|
||||
[zone]. *)
|
||||
|
||||
type t
|
||||
(** Opaque type for storing authentication keys. *)
|
||||
end
|
||||
|
||||
type t = private {
|
||||
data : Dns_trie.t ;
|
||||
auth : Authentication.t ;
|
||||
unauthenticated_zone_transfer : bool ;
|
||||
rng : int -> string ;
|
||||
tsig_verify : Tsig_op.verify ;
|
||||
tsig_sign : Tsig_op.sign ;
|
||||
}
|
||||
(** The state of a DNS server. *)
|
||||
|
||||
val create : ?unauthenticated_zone_transfer:bool ->
|
||||
?tsig_verify:Tsig_op.verify ->
|
||||
?tsig_sign:Tsig_op.sign ->
|
||||
?auth:Authentication.t ->
|
||||
Dns_trie.t ->
|
||||
(int -> string) ->
|
||||
t
|
||||
(** [create ~unauthenticated_zone_transfer ~tsig_verify ~tsig_sign ~auth data rng]
|
||||
constructs a [t]. See {!Primary.create} and {!Secondary.create} for the
|
||||
logic running a primary or secondary server. *)
|
||||
|
||||
val with_data : t -> Dns_trie.t -> t
|
||||
(** [with_data t data] is [t'] where the [data] field is updated with the
|
||||
provided value. Be aware that this function breaks the semantics of a
|
||||
primary server with secondaries, since secondaries won't be notified and
|
||||
will be out of sync. Use if you know what you do. The data of a secondary
|
||||
will usually come via zone transfer from the primary name services. *)
|
||||
|
||||
val text : 'a Domain_name.t -> Dns_trie.t -> (string, [> `Msg of string ]) result
|
||||
(** [text name trie] results in a string representation (zonefile) of the trie. *)
|
||||
|
||||
val handle_question : t -> Packet.Question.t ->
|
||||
(Packet.Flags.t * Packet.Answer.t * Name_rr_map.t option,
|
||||
Rcode.t * Packet.Answer.t option) result
|
||||
(** [handle_question t question] handles the DNS query [question] by looking
|
||||
it up in the trie of [t]. The result is either an answer or an error. *)
|
||||
|
||||
val update_data : Dns_trie.t -> 'a Domain_name.t ->
|
||||
Dns.Packet.Update.prereq list Domain_name.Map.t
|
||||
* Dns.Packet.Update.update list Domain_name.Map.t ->
|
||||
( Dns_trie.t * (Domain_name.Set.elt * Dns.Soa.t) list,
|
||||
Dns.Rcode.t )
|
||||
result
|
||||
(** [update_data data domain update_content] applies the [update_content] to
|
||||
the [data] for [domain]. This function breaks the semantics of a primary
|
||||
server with secondaries, since the secondaries won't be notified of the
|
||||
update and will be out of sync. Use if you know what you are doing. *)
|
||||
|
||||
val handle_update : t -> proto -> [ `raw ] Domain_name.t option ->
|
||||
Packet.Question.t -> Packet.Update.t ->
|
||||
(Dns_trie.t * ([`raw] Domain_name.t * Soa.t) list, Rcode.t) result
|
||||
(** [handle_update t proto keyname question update] authenticates the update
|
||||
request and processes the update. This function breaks the semantics of a
|
||||
primary server with secondaries, since the secondaries won't be notified.
|
||||
Use if you know what you are doing. *)
|
||||
|
||||
val handle_axfr_request : t -> proto -> [ `raw ] Domain_name.t option ->
|
||||
Packet.Question.t -> (Packet.Axfr.t, Rcode.t) result
|
||||
(** [handle_axfr_request t proto keyname question] authenticates the zone
|
||||
transfer request and processes it. If the request is valid, and the zone
|
||||
available, a zone transfer is returned. *)
|
||||
|
||||
type trie_cache
|
||||
|
||||
val handle_ixfr_request : t -> trie_cache -> proto -> [ `raw ] Domain_name.t option ->
|
||||
Packet.Question.t -> Soa.t -> (Packet.Ixfr.t, Rcode.t) result
|
||||
(** [handle_ixfr_request t cache proto keyname question soa] authenticates the
|
||||
incremental zone transfer request and processes it. If valid, an incremental
|
||||
zone transfer is returned. *)
|
||||
|
||||
val handle_tsig : ?mac:string -> t -> Ptime.t -> Packet.t ->
|
||||
string -> (([ `raw ] Domain_name.t * Tsig.t * string * Dnskey.t) option,
|
||||
Tsig_op.e * string option) result
|
||||
(** [handle_tsig ~mac t now packet buffer] verifies the tsig
|
||||
signature if present, returning the keyname, tsig, mac, and used key. *)
|
||||
|
||||
type packet_callback = Packet.Question.t -> Packet.reply option
|
||||
(** [packet_callback question] either returns a reply to a DNS question [Some reply] or [None]. *)
|
||||
|
||||
module Primary : sig
|
||||
|
||||
type s
|
||||
(** The state of a primary DNS server. *)
|
||||
|
||||
val server : s -> t
|
||||
(** [server s] is the server of the primary. *)
|
||||
|
||||
val data : s -> Dns_trie.t
|
||||
(** [data s] is the data store of [s]. *)
|
||||
|
||||
val with_data : s -> Ptime.t -> int64 -> Dns_trie.t ->
|
||||
s * (Ipaddr.t * string list) list
|
||||
(** [with_data s now ts trie] replaces the current data with [trie] in [s].
|
||||
The returned notifications should be send out. *)
|
||||
|
||||
val with_keys : s -> Ptime.t -> int64 -> ('a Domain_name.t * Dnskey.t) list ->
|
||||
s * (Ipaddr.t * string list) list
|
||||
(** [with_keys s now ts keys] replaces the current keys with [keys] in [s],
|
||||
and generates notifications. *)
|
||||
|
||||
val trie_cache : s -> trie_cache
|
||||
(** [trie_cache s] is the trie cache of the server. *)
|
||||
|
||||
val create : ?trie_cache_entries:int -> ?keys:('a Domain_name.t * Dnskey.t) list ->
|
||||
?unauthenticated_zone_transfer:bool ->
|
||||
?tsig_verify:Tsig_op.verify -> ?tsig_sign:Tsig_op.sign ->
|
||||
rng:(int -> string) -> Dns_trie.t -> s
|
||||
(** [create ~trie_cache_entries ~keys ~unauthenticated_zone_transfer
|
||||
~tsig_verify ~tsig_sign ~rng data] creates a primary server. If
|
||||
[unauthenticated_zone_transfer] is provided and [true] (defaults to
|
||||
[false]), anyone can transfer the zones. [trie_cache_entries] is the
|
||||
backlog to keep in memory for incremental zone transfers (IXFR, default is 5). This
|
||||
affects memory usage. *)
|
||||
|
||||
val handle_packet : ?packet_callback:packet_callback -> s -> Ptime.t -> int64
|
||||
-> proto -> Ipaddr.t -> int -> Packet.t -> 'a Domain_name.t option ->
|
||||
s * Packet.t option * (Ipaddr.t * string list) list *
|
||||
[> `Notify of Soa.t option | `Keep ] option
|
||||
(** [handle_packet ~packet_callback s now ts src src_port proto key packet]
|
||||
handles the given [packet], returning new state, an answer, and
|
||||
potentially notify packets to secondary name servers. If [packet_callback]
|
||||
is specified, it is called for each incoming query. If it returns
|
||||
[Some reply], this reply is used instead of the usual lookup in the
|
||||
zone data. It can be used for custom query processing, such as for load
|
||||
balancing or transporting data. *)
|
||||
|
||||
val handle_buf : ?packet_callback:packet_callback -> s -> Ptime.t -> int64
|
||||
-> proto -> Ipaddr.t -> int -> string ->
|
||||
s * string list * (Ipaddr.t * string list) list *
|
||||
[ `Notify of Soa.t option | `Signed_notify of Soa.t option | `Keep ] option *
|
||||
[ `raw ] Domain_name.t option
|
||||
(** [handle_buf ~packet_callback s now ts proto src src_port buffer] decodes
|
||||
the [buffer], processes the DNS frame using {!handle_packet}, and encodes
|
||||
the reply. The result is a new state, potentially a list of answers to the
|
||||
requestor, a list of notifications to send out, information whether a
|
||||
notify (or signed notify) was received, and the hmac key used for
|
||||
authentication. If [packet_callback] is specified, it is called for each
|
||||
incoming query. If it returns [Some reply], this reply is used instead of
|
||||
the usual lookup in the zone data. This can be used for custom query
|
||||
processing, such as for load balancing or transporting data. *)
|
||||
|
||||
val closed : s -> Ipaddr.t -> s
|
||||
(** [closed s ip] marks the connection to [ip] closed. *)
|
||||
|
||||
val timer : s -> Ptime.t -> int64 ->
|
||||
s * (Ipaddr.t * string list) list
|
||||
(** [timer s now ts] may encode some notifications to secondary name servers
|
||||
if previous ones were not acknowledged. *)
|
||||
|
||||
val to_be_notified : s -> [ `host ] Domain_name.t ->
|
||||
(Ipaddr.t * [ `raw ] Domain_name.t option) list
|
||||
(** [to_be_notified s zone] returns a list of pairs of IP address and optional
|
||||
tsig key name of the servers to be notified for a zone change. This list
|
||||
is based on (a) NS entries for the zone, (b) registered TSIG transfer keys,
|
||||
and (c) active connection (which transmitted a signed SOA). *)
|
||||
end
|
||||
|
||||
module Secondary : sig
|
||||
|
||||
type s
|
||||
(** The state of a secondary DNS server. *)
|
||||
|
||||
val data : s -> Dns_trie.t
|
||||
(** [data s] is the zone data of [s]. *)
|
||||
|
||||
val with_data : s -> Dns_trie.t -> s
|
||||
(** [with_data s trie] is [s] with its data replaced by [trie]. *)
|
||||
|
||||
val create : ?primary:Ipaddr.t ->
|
||||
tsig_verify:Tsig_op.verify -> tsig_sign:Tsig_op.sign ->
|
||||
rng:(int -> string) -> ('a Domain_name.t * Dnskey.t) list -> s
|
||||
(** [create ~primary ~tsig_verify ~tsig_sign ~rng keys] creates a secondary
|
||||
DNS server state. *)
|
||||
|
||||
val handle_packet : ?packet_callback:packet_callback -> s -> Ptime.t -> int64 ->
|
||||
Ipaddr.t -> Packet.t -> 'a Domain_name.t option ->
|
||||
s * Packet.t option * (Ipaddr.t * string) option
|
||||
(** [handle_packet s now ts ip proto key t] handles the incoming packet. *)
|
||||
|
||||
val handle_buf : ?packet_callback:packet_callback -> s -> Ptime.t -> int64 ->
|
||||
proto -> Ipaddr.t -> string ->
|
||||
s * string option * (Ipaddr.t * string) option
|
||||
(** [handle_buf ~packet_callback s now ts proto src buf] decodes [buf], processes with
|
||||
{!handle_packet}, and encodes the results. *)
|
||||
|
||||
val timer : s -> Ptime.t -> int64 ->
|
||||
s * (Ipaddr.t * string list) list
|
||||
(** [timer s now ts] may request SOA or retransmit AXFR. *)
|
||||
|
||||
val closed : s -> Ptime.t -> int64 -> Ipaddr.t ->
|
||||
s * string list
|
||||
(** [closed s now ts ip] marks [ip] as closed, the returned buffers (SOA
|
||||
requests) should be sent to [ip]. *)
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue