Reply with NOTIMPL when Opcode is not supported (#982)
One of the test from DNS Compliance testing validates that if the opcode
is not supported, a NOTIMPL rcode is returned.
e0884144dd/genreport.c (L293)
This diff makes the default acceptfunc support this case and reply with
NOTIMPL instead of FORMERR.
This commit is contained in:
parent
ee62c8b086
commit
d89f1e3d4b
|
@ -19,9 +19,10 @@ var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
|
|||
type MsgAcceptAction int
|
||||
|
||||
const (
|
||||
MsgAccept MsgAcceptAction = iota // Accept the message
|
||||
MsgReject // Reject the message with a RcodeFormatError
|
||||
MsgIgnore // Ignore the error and send nothing back.
|
||||
MsgAccept MsgAcceptAction = iota // Accept the message
|
||||
MsgReject // Reject the message with a RcodeFormatError
|
||||
MsgIgnore // Ignore the error and send nothing back.
|
||||
MsgRejectNotImplemented // Reject the message with a RcodeNotImplemented
|
||||
)
|
||||
|
||||
func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
|
||||
|
@ -32,7 +33,7 @@ func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
|
|||
// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
|
||||
opcode := int(dh.Bits>>11) & 0xF
|
||||
if opcode != OpcodeQuery && opcode != OpcodeNotify {
|
||||
return MsgReject
|
||||
return MsgRejectNotImplemented
|
||||
}
|
||||
|
||||
if dh.Qdcount != 1 {
|
||||
|
|
12
server.go
12
server.go
|
@ -560,18 +560,24 @@ func (srv *Server) serveDNS(m []byte, w *response) {
|
|||
req := new(Msg)
|
||||
req.setHdr(dh)
|
||||
|
||||
switch srv.MsgAcceptFunc(dh) {
|
||||
switch action := srv.MsgAcceptFunc(dh); action {
|
||||
case MsgAccept:
|
||||
if req.unpack(dh, m, off) == nil {
|
||||
break
|
||||
}
|
||||
|
||||
fallthrough
|
||||
case MsgReject:
|
||||
case MsgReject, MsgRejectNotImplemented:
|
||||
opcode := req.Opcode
|
||||
req.SetRcodeFormatError(req)
|
||||
req.Zero = false
|
||||
if action == MsgRejectNotImplemented {
|
||||
req.Opcode = opcode
|
||||
req.Rcode = RcodeNotImplemented
|
||||
}
|
||||
|
||||
// Are we allowed to delete any OPT records here?
|
||||
req.Ns, req.Answer, req.Extra = nil, nil, nil
|
||||
req.Zero = false
|
||||
|
||||
w.WriteMsg(req)
|
||||
fallthrough
|
||||
|
|
|
@ -215,6 +215,35 @@ func TestServeIgnoresZFlag(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Verify that the server responds to a query with unsupported Opcode with a NotImplemented error and that Opcode is unchanged.
|
||||
func TestServeNotImplemented(t *testing.T) {
|
||||
HandleFunc("example.com.", AnotherHelloServer)
|
||||
opcode := 15
|
||||
|
||||
s, addrstr, err := RunLocalUDPServer(":0")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to run test server: %v", err)
|
||||
}
|
||||
defer s.Shutdown()
|
||||
|
||||
c := new(Client)
|
||||
m := new(Msg)
|
||||
|
||||
// Test that Opcode is like the unchanged from request Opcode and that Rcode is set to NotImplemnented
|
||||
m.SetQuestion("example.com.", TypeTXT)
|
||||
m.Opcode = opcode
|
||||
r, _, err := c.Exchange(m, addrstr)
|
||||
if err != nil {
|
||||
t.Fatal("failed to exchange example.com with +zflag", err)
|
||||
}
|
||||
if r.Opcode != opcode {
|
||||
t.Errorf("expected opcode %v, got %v", opcode, r.Opcode)
|
||||
}
|
||||
if r.Rcode != RcodeNotImplemented {
|
||||
t.Errorf("expected rcode %v, got %v", RcodeNotImplemented, r.Rcode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServingTLS(t *testing.T) {
|
||||
HandleFunc("miek.nl.", HelloServer)
|
||||
HandleFunc("example.com.", AnotherHelloServer)
|
||||
|
|
Loading…
Reference in New Issue