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
28const (
29	MsgAccept               MsgAcceptAction = iota // Accept the message
30	MsgReject                                      // Reject the message with a RcodeFormatError
31	MsgIgnore                                      // Ignore the error and send nothing back.
32	MsgRejectNotImplemented                        // Reject the message with a RcodeNotImplemented
33)
34
35func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
36	if isResponse := dh.Bits&_QR != 0; isResponse {
37		return MsgIgnore
38	}
39
40	// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
41	opcode := int(dh.Bits>>11) & 0xF
42	if opcode != OpcodeQuery && opcode != OpcodeNotify {
43		return MsgRejectNotImplemented
44	}
45
46	if dh.Qdcount != 1 {
47		return MsgReject
48	}
49	// NOTIFY requests can have a SOA in the ANSWER section. See RFC 1996 Section 3.7 and 3.11.
50	if dh.Ancount > 1 {
51		return MsgReject
52	}
53	// IXFR request could have one SOA RR in the NS section. See RFC 1995, section 3.
54	if dh.Nscount > 1 {
55		return MsgReject
56	}
57	if dh.Arcount > 2 {
58		return MsgReject
59	}
60	return MsgAccept
61}
62