1package dns
2
3// MsgAcceptFunc is used early in the server code to accept or reject a message with RcodeFormatError.
4// It returns a MsgAcceptAction to indicate what should happen with the message.
5type MsgAcceptFunc func(dh Header) MsgAcceptAction
6
7// DefaultMsgAcceptFunc checks the request and will reject if:
8//
9// * isn't a request (don't respond in that case)
10//
11// * opcode isn't OpcodeQuery or OpcodeNotify
12//
13// * Zero bit isn't zero
14//
15// * has more than 1 question in the question section
16//
17// * has more than 1 RR in the Answer section
18//
19// * has more than 0 RRs in the Authority section
20//
21// * has more than 2 RRs in the Additional section
22//
23var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
24
25// MsgAcceptAction represents the action to be taken.
26type MsgAcceptAction int
27
28// Allowed returned values from a MsgAcceptFunc.
29const (
30	MsgAccept               MsgAcceptAction = iota // Accept the message
31	MsgReject                                      // Reject the message with a RcodeFormatError
32	MsgIgnore                                      // Ignore the error and send nothing back.
33	MsgRejectNotImplemented                        // Reject the message with a RcodeNotImplemented
34)
35
36func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
37	if isResponse := dh.Bits&_QR != 0; isResponse {
38		return MsgIgnore
39	}
40
41	// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
42	opcode := int(dh.Bits>>11) & 0xF
43	if opcode != OpcodeQuery && opcode != OpcodeNotify {
44		return MsgRejectNotImplemented
45	}
46
47	if dh.Qdcount != 1 {
48		return MsgReject
49	}
50	// NOTIFY requests can have a SOA in the ANSWER section. See RFC 1996 Section 3.7 and 3.11.
51	if dh.Ancount > 1 {
52		return MsgReject
53	}
54	// IXFR request could have one SOA RR in the NS section. See RFC 1995, section 3.
55	if dh.Nscount > 1 {
56		return MsgReject
57	}
58	if dh.Arcount > 2 {
59		return MsgReject
60	}
61	return MsgAccept
62}
63