1// DNS server implementation. 2 3package dns 4 5import ( 6 "bytes" 7 "context" 8 "crypto/tls" 9 "encoding/binary" 10 "errors" 11 "io" 12 "net" 13 "strings" 14 "sync" 15 "sync/atomic" 16 "time" 17) 18 19// Default maximum number of TCP queries before we close the socket. 20const maxTCPQueries = 128 21 22// The maximum number of idle workers. 23// 24// This controls the maximum number of workers that are allowed to stay 25// idle waiting for incoming requests before being torn down. 26// 27// If this limit is reached, the server will just keep spawning new 28// workers (goroutines) for each incoming request. In this case, each 29// worker will only be used for a single request. 30const maxIdleWorkersCount = 10000 31 32// The maximum length of time a worker may idle for before being destroyed. 33const idleWorkerTimeout = 10 * time.Second 34 35// aLongTimeAgo is a non-zero time, far in the past, used for 36// immediate cancelation of network operations. 37var aLongTimeAgo = time.Unix(1, 0) 38 39// Handler is implemented by any value that implements ServeDNS. 40type Handler interface { 41 ServeDNS(w ResponseWriter, r *Msg) 42} 43 44// The HandlerFunc type is an adapter to allow the use of 45// ordinary functions as DNS handlers. If f is a function 46// with the appropriate signature, HandlerFunc(f) is a 47// Handler object that calls f. 48type HandlerFunc func(ResponseWriter, *Msg) 49 50// ServeDNS calls f(w, r). 51func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) { 52 f(w, r) 53} 54 55// A ResponseWriter interface is used by an DNS handler to 56// construct an DNS response. 57type ResponseWriter interface { 58 // LocalAddr returns the net.Addr of the server 59 LocalAddr() net.Addr 60 // RemoteAddr returns the net.Addr of the client that sent the current request. 61 RemoteAddr() net.Addr 62 // WriteMsg writes a reply back to the client. 63 WriteMsg(*Msg) error 64 // Write writes a raw buffer back to the client. 65 Write([]byte) (int, error) 66 // Close closes the connection. 67 Close() error 68 // TsigStatus returns the status of the Tsig. 69 TsigStatus() error 70 // TsigTimersOnly sets the tsig timers only boolean. 71 TsigTimersOnly(bool) 72 // Hijack lets the caller take over the connection. 73 // After a call to Hijack(), the DNS package will not do anything with the connection. 74 Hijack() 75} 76 77// A ConnectionStater interface is used by a DNS Handler to access TLS connection state 78// when available. 79type ConnectionStater interface { 80 ConnectionState() *tls.ConnectionState 81} 82 83type response struct { 84 msg []byte 85 hijacked bool // connection has been hijacked by handler 86 tsigTimersOnly bool 87 tsigStatus error 88 tsigRequestMAC string 89 tsigSecret map[string]string // the tsig secrets 90 udp *net.UDPConn // i/o connection if UDP was used 91 tcp net.Conn // i/o connection if TCP was used 92 udpSession *SessionUDP // oob data to get egress interface right 93 writer Writer // writer to output the raw DNS bits 94 wg *sync.WaitGroup // for gracefull shutdown 95} 96 97// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets. 98func HandleFailed(w ResponseWriter, r *Msg) { 99 m := new(Msg) 100 m.SetRcode(r, RcodeServerFailure) 101 // does not matter if this write fails 102 w.WriteMsg(m) 103} 104 105// ListenAndServe Starts a server on address and network specified Invoke handler 106// for incoming queries. 107func ListenAndServe(addr string, network string, handler Handler) error { 108 server := &Server{Addr: addr, Net: network, Handler: handler} 109 return server.ListenAndServe() 110} 111 112// ListenAndServeTLS acts like http.ListenAndServeTLS, more information in 113// http://golang.org/pkg/net/http/#ListenAndServeTLS 114func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error { 115 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 116 if err != nil { 117 return err 118 } 119 120 config := tls.Config{ 121 Certificates: []tls.Certificate{cert}, 122 } 123 124 server := &Server{ 125 Addr: addr, 126 Net: "tcp-tls", 127 TLSConfig: &config, 128 Handler: handler, 129 } 130 131 return server.ListenAndServe() 132} 133 134// ActivateAndServe activates a server with a listener from systemd, 135// l and p should not both be non-nil. 136// If both l and p are not nil only p will be used. 137// Invoke handler for incoming queries. 138func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error { 139 server := &Server{Listener: l, PacketConn: p, Handler: handler} 140 return server.ActivateAndServe() 141} 142 143// Writer writes raw DNS messages; each call to Write should send an entire message. 144type Writer interface { 145 io.Writer 146} 147 148// Reader reads raw DNS messages; each call to ReadTCP or ReadUDP should return an entire message. 149type Reader interface { 150 // ReadTCP reads a raw message from a TCP connection. Implementations may alter 151 // connection properties, for example the read-deadline. 152 ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) 153 // ReadUDP reads a raw message from a UDP connection. Implementations may alter 154 // connection properties, for example the read-deadline. 155 ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) 156} 157 158// defaultReader is an adapter for the Server struct that implements the Reader interface 159// using the readTCP and readUDP func of the embedded Server. 160type defaultReader struct { 161 *Server 162} 163 164func (dr *defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) { 165 return dr.readTCP(conn, timeout) 166} 167 168func (dr *defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) { 169 return dr.readUDP(conn, timeout) 170} 171 172// DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader. 173// Implementations should never return a nil Reader. 174type DecorateReader func(Reader) Reader 175 176// DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer. 177// Implementations should never return a nil Writer. 178type DecorateWriter func(Writer) Writer 179 180// A Server defines parameters for running an DNS server. 181type Server struct { 182 // Address to listen on, ":dns" if empty. 183 Addr string 184 // if "tcp" or "tcp-tls" (DNS over TLS) it will invoke a TCP listener, otherwise an UDP one 185 Net string 186 // TCP Listener to use, this is to aid in systemd's socket activation. 187 Listener net.Listener 188 // TLS connection configuration 189 TLSConfig *tls.Config 190 // UDP "Listener" to use, this is to aid in systemd's socket activation. 191 PacketConn net.PacketConn 192 // Handler to invoke, dns.DefaultServeMux if nil. 193 Handler Handler 194 // Default buffer size to use to read incoming UDP messages. If not set 195 // it defaults to MinMsgSize (512 B). 196 UDPSize int 197 // The net.Conn.SetReadTimeout value for new connections, defaults to 2 * time.Second. 198 ReadTimeout time.Duration 199 // The net.Conn.SetWriteTimeout value for new connections, defaults to 2 * time.Second. 200 WriteTimeout time.Duration 201 // TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966). 202 IdleTimeout func() time.Duration 203 // Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2). 204 TsigSecret map[string]string 205 // Unsafe instructs the server to disregard any sanity checks and directly hand the message to 206 // the handler. It will specifically not check if the query has the QR bit not set. 207 Unsafe bool 208 // If NotifyStartedFunc is set it is called once the server has started listening. 209 NotifyStartedFunc func() 210 // DecorateReader is optional, allows customization of the process that reads raw DNS messages. 211 DecorateReader DecorateReader 212 // DecorateWriter is optional, allows customization of the process that writes raw DNS messages. 213 DecorateWriter DecorateWriter 214 // Maximum number of TCP queries before we close the socket. Default is maxTCPQueries (unlimited if -1). 215 MaxTCPQueries int 216 // Whether to set the SO_REUSEPORT socket option, allowing multiple listeners to be bound to a single address. 217 // It is only supported on go1.11+ and when using ListenAndServe. 218 ReusePort bool 219 220 // UDP packet or TCP connection queue 221 queue chan *response 222 // Workers count 223 workersCount int32 224 225 // Shutdown handling 226 lock sync.RWMutex 227 started bool 228 shutdown chan struct{} 229 conns map[net.Conn]struct{} 230 231 // A pool for UDP message buffers. 232 udpPool sync.Pool 233} 234 235func (srv *Server) isStarted() bool { 236 srv.lock.RLock() 237 started := srv.started 238 srv.lock.RUnlock() 239 return started 240} 241 242func (srv *Server) worker(w *response) { 243 srv.serve(w) 244 245 for { 246 count := atomic.LoadInt32(&srv.workersCount) 247 if count > maxIdleWorkersCount { 248 return 249 } 250 if atomic.CompareAndSwapInt32(&srv.workersCount, count, count+1) { 251 break 252 } 253 } 254 255 defer atomic.AddInt32(&srv.workersCount, -1) 256 257 inUse := false 258 timeout := time.NewTimer(idleWorkerTimeout) 259 defer timeout.Stop() 260LOOP: 261 for { 262 select { 263 case w, ok := <-srv.queue: 264 if !ok { 265 break LOOP 266 } 267 inUse = true 268 srv.serve(w) 269 case <-timeout.C: 270 if !inUse { 271 break LOOP 272 } 273 inUse = false 274 timeout.Reset(idleWorkerTimeout) 275 } 276 } 277} 278 279func (srv *Server) spawnWorker(w *response) { 280 select { 281 case srv.queue <- w: 282 default: 283 go srv.worker(w) 284 } 285} 286 287func makeUDPBuffer(size int) func() interface{} { 288 return func() interface{} { 289 return make([]byte, size) 290 } 291} 292 293func (srv *Server) init() { 294 srv.queue = make(chan *response) 295 296 srv.shutdown = make(chan struct{}) 297 srv.conns = make(map[net.Conn]struct{}) 298 299 if srv.UDPSize == 0 { 300 srv.UDPSize = MinMsgSize 301 } 302 303 srv.udpPool.New = makeUDPBuffer(srv.UDPSize) 304} 305 306func unlockOnce(l sync.Locker) func() { 307 var once sync.Once 308 return func() { once.Do(l.Unlock) } 309} 310 311// ListenAndServe starts a nameserver on the configured address in *Server. 312func (srv *Server) ListenAndServe() error { 313 unlock := unlockOnce(&srv.lock) 314 srv.lock.Lock() 315 defer unlock() 316 317 if srv.started { 318 return &Error{err: "server already started"} 319 } 320 321 addr := srv.Addr 322 if addr == "" { 323 addr = ":domain" 324 } 325 326 srv.init() 327 defer close(srv.queue) 328 329 switch srv.Net { 330 case "tcp", "tcp4", "tcp6": 331 l, err := listenTCP(srv.Net, addr, srv.ReusePort) 332 if err != nil { 333 return err 334 } 335 srv.Listener = l 336 srv.started = true 337 unlock() 338 return srv.serveTCP(l) 339 case "tcp-tls", "tcp4-tls", "tcp6-tls": 340 if srv.TLSConfig == nil || (len(srv.TLSConfig.Certificates) == 0 && srv.TLSConfig.GetCertificate == nil) { 341 return errors.New("dns: neither Certificates nor GetCertificate set in Config") 342 } 343 network := strings.TrimSuffix(srv.Net, "-tls") 344 l, err := listenTCP(network, addr, srv.ReusePort) 345 if err != nil { 346 return err 347 } 348 l = tls.NewListener(l, srv.TLSConfig) 349 srv.Listener = l 350 srv.started = true 351 unlock() 352 return srv.serveTCP(l) 353 case "udp", "udp4", "udp6": 354 l, err := listenUDP(srv.Net, addr, srv.ReusePort) 355 if err != nil { 356 return err 357 } 358 u := l.(*net.UDPConn) 359 if e := setUDPSocketOptions(u); e != nil { 360 return e 361 } 362 srv.PacketConn = l 363 srv.started = true 364 unlock() 365 return srv.serveUDP(u) 366 } 367 return &Error{err: "bad network"} 368} 369 370// ActivateAndServe starts a nameserver with the PacketConn or Listener 371// configured in *Server. Its main use is to start a server from systemd. 372func (srv *Server) ActivateAndServe() error { 373 unlock := unlockOnce(&srv.lock) 374 srv.lock.Lock() 375 defer unlock() 376 377 if srv.started { 378 return &Error{err: "server already started"} 379 } 380 381 srv.init() 382 defer close(srv.queue) 383 384 pConn := srv.PacketConn 385 l := srv.Listener 386 if pConn != nil { 387 // Check PacketConn interface's type is valid and value 388 // is not nil 389 if t, ok := pConn.(*net.UDPConn); ok && t != nil { 390 if e := setUDPSocketOptions(t); e != nil { 391 return e 392 } 393 srv.started = true 394 unlock() 395 return srv.serveUDP(t) 396 } 397 } 398 if l != nil { 399 srv.started = true 400 unlock() 401 return srv.serveTCP(l) 402 } 403 return &Error{err: "bad listeners"} 404} 405 406// Shutdown shuts down a server. After a call to Shutdown, ListenAndServe and 407// ActivateAndServe will return. 408func (srv *Server) Shutdown() error { 409 return srv.ShutdownContext(context.Background()) 410} 411 412// ShutdownContext shuts down a server. After a call to ShutdownContext, 413// ListenAndServe and ActivateAndServe will return. 414// 415// A context.Context may be passed to limit how long to wait for connections 416// to terminate. 417func (srv *Server) ShutdownContext(ctx context.Context) error { 418 srv.lock.Lock() 419 if !srv.started { 420 srv.lock.Unlock() 421 return &Error{err: "server not started"} 422 } 423 424 srv.started = false 425 426 if srv.PacketConn != nil { 427 srv.PacketConn.SetReadDeadline(aLongTimeAgo) // Unblock reads 428 } 429 430 if srv.Listener != nil { 431 srv.Listener.Close() 432 } 433 434 for rw := range srv.conns { 435 rw.SetReadDeadline(aLongTimeAgo) // Unblock reads 436 } 437 438 srv.lock.Unlock() 439 440 if testShutdownNotify != nil { 441 testShutdownNotify.Broadcast() 442 } 443 444 var ctxErr error 445 select { 446 case <-srv.shutdown: 447 case <-ctx.Done(): 448 ctxErr = ctx.Err() 449 } 450 451 if srv.PacketConn != nil { 452 srv.PacketConn.Close() 453 } 454 455 return ctxErr 456} 457 458var testShutdownNotify *sync.Cond 459 460// getReadTimeout is a helper func to use system timeout if server did not intend to change it. 461func (srv *Server) getReadTimeout() time.Duration { 462 rtimeout := dnsTimeout 463 if srv.ReadTimeout != 0 { 464 rtimeout = srv.ReadTimeout 465 } 466 return rtimeout 467} 468 469// serveTCP starts a TCP listener for the server. 470func (srv *Server) serveTCP(l net.Listener) error { 471 defer l.Close() 472 473 if srv.NotifyStartedFunc != nil { 474 srv.NotifyStartedFunc() 475 } 476 477 var wg sync.WaitGroup 478 defer func() { 479 wg.Wait() 480 close(srv.shutdown) 481 }() 482 483 for srv.isStarted() { 484 rw, err := l.Accept() 485 if err != nil { 486 if !srv.isStarted() { 487 return nil 488 } 489 if neterr, ok := err.(net.Error); ok && neterr.Temporary() { 490 continue 491 } 492 return err 493 } 494 srv.lock.Lock() 495 // Track the connection to allow unblocking reads on shutdown. 496 srv.conns[rw] = struct{}{} 497 srv.lock.Unlock() 498 wg.Add(1) 499 srv.spawnWorker(&response{ 500 tsigSecret: srv.TsigSecret, 501 tcp: rw, 502 wg: &wg, 503 }) 504 } 505 506 return nil 507} 508 509// serveUDP starts a UDP listener for the server. 510func (srv *Server) serveUDP(l *net.UDPConn) error { 511 defer l.Close() 512 513 if srv.NotifyStartedFunc != nil { 514 srv.NotifyStartedFunc() 515 } 516 517 reader := Reader(&defaultReader{srv}) 518 if srv.DecorateReader != nil { 519 reader = srv.DecorateReader(reader) 520 } 521 522 var wg sync.WaitGroup 523 defer func() { 524 wg.Wait() 525 close(srv.shutdown) 526 }() 527 528 rtimeout := srv.getReadTimeout() 529 // deadline is not used here 530 for srv.isStarted() { 531 m, s, err := reader.ReadUDP(l, rtimeout) 532 if err != nil { 533 if !srv.isStarted() { 534 return nil 535 } 536 if netErr, ok := err.(net.Error); ok && netErr.Temporary() { 537 continue 538 } 539 return err 540 } 541 if len(m) < headerSize { 542 if cap(m) == srv.UDPSize { 543 srv.udpPool.Put(m[:srv.UDPSize]) 544 } 545 continue 546 } 547 wg.Add(1) 548 srv.spawnWorker(&response{ 549 msg: m, 550 tsigSecret: srv.TsigSecret, 551 udp: l, 552 udpSession: s, 553 wg: &wg, 554 }) 555 } 556 557 return nil 558} 559 560func (srv *Server) serve(w *response) { 561 if srv.DecorateWriter != nil { 562 w.writer = srv.DecorateWriter(w) 563 } else { 564 w.writer = w 565 } 566 567 if w.udp != nil { 568 // serve UDP 569 srv.serveDNS(w) 570 571 w.wg.Done() 572 return 573 } 574 575 defer func() { 576 if !w.hijacked { 577 w.Close() 578 } 579 580 srv.lock.Lock() 581 delete(srv.conns, w.tcp) 582 srv.lock.Unlock() 583 584 w.wg.Done() 585 }() 586 587 reader := Reader(&defaultReader{srv}) 588 if srv.DecorateReader != nil { 589 reader = srv.DecorateReader(reader) 590 } 591 592 idleTimeout := tcpIdleTimeout 593 if srv.IdleTimeout != nil { 594 idleTimeout = srv.IdleTimeout() 595 } 596 597 timeout := srv.getReadTimeout() 598 599 limit := srv.MaxTCPQueries 600 if limit == 0 { 601 limit = maxTCPQueries 602 } 603 604 for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ { 605 var err error 606 w.msg, err = reader.ReadTCP(w.tcp, timeout) 607 if err != nil { 608 // TODO(tmthrgd): handle error 609 break 610 } 611 srv.serveDNS(w) 612 if w.tcp == nil { 613 break // Close() was called 614 } 615 if w.hijacked { 616 break // client will call Close() themselves 617 } 618 // The first read uses the read timeout, the rest use the 619 // idle timeout. 620 timeout = idleTimeout 621 } 622} 623 624func (srv *Server) disposeBuffer(w *response) { 625 if w.udp != nil && cap(w.msg) == srv.UDPSize { 626 srv.udpPool.Put(w.msg[:srv.UDPSize]) 627 } 628 w.msg = nil 629} 630 631func (srv *Server) serveDNS(w *response) { 632 req := new(Msg) 633 err := req.Unpack(w.msg) 634 if err != nil { // Send a FormatError back 635 x := new(Msg) 636 x.SetRcodeFormatError(req) 637 w.WriteMsg(x) 638 } 639 if err != nil || !srv.Unsafe && req.Response { 640 srv.disposeBuffer(w) 641 return 642 } 643 644 w.tsigStatus = nil 645 if w.tsigSecret != nil { 646 if t := req.IsTsig(); t != nil { 647 if secret, ok := w.tsigSecret[t.Hdr.Name]; ok { 648 w.tsigStatus = TsigVerify(w.msg, secret, "", false) 649 } else { 650 w.tsigStatus = ErrSecret 651 } 652 w.tsigTimersOnly = false 653 w.tsigRequestMAC = req.Extra[len(req.Extra)-1].(*TSIG).MAC 654 } 655 } 656 657 srv.disposeBuffer(w) 658 659 handler := srv.Handler 660 if handler == nil { 661 handler = DefaultServeMux 662 } 663 664 handler.ServeDNS(w, req) // Writes back to the client 665} 666 667func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) { 668 // If we race with ShutdownContext, the read deadline may 669 // have been set in the distant past to unblock the read 670 // below. We must not override it, otherwise we may block 671 // ShutdownContext. 672 srv.lock.RLock() 673 if srv.started { 674 conn.SetReadDeadline(time.Now().Add(timeout)) 675 } 676 srv.lock.RUnlock() 677 678 l := make([]byte, 2) 679 n, err := conn.Read(l) 680 if err != nil || n != 2 { 681 if err != nil { 682 return nil, err 683 } 684 return nil, ErrShortRead 685 } 686 length := binary.BigEndian.Uint16(l) 687 if length == 0 { 688 return nil, ErrShortRead 689 } 690 m := make([]byte, int(length)) 691 n, err = conn.Read(m[:int(length)]) 692 if err != nil || n == 0 { 693 if err != nil { 694 return nil, err 695 } 696 return nil, ErrShortRead 697 } 698 i := n 699 for i < int(length) { 700 j, err := conn.Read(m[i:int(length)]) 701 if err != nil { 702 return nil, err 703 } 704 i += j 705 } 706 n = i 707 m = m[:n] 708 return m, nil 709} 710 711func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) { 712 srv.lock.RLock() 713 if srv.started { 714 // See the comment in readTCP above. 715 conn.SetReadDeadline(time.Now().Add(timeout)) 716 } 717 srv.lock.RUnlock() 718 719 m := srv.udpPool.Get().([]byte) 720 n, s, err := ReadFromSessionUDP(conn, m) 721 if err != nil { 722 srv.udpPool.Put(m) 723 return nil, nil, err 724 } 725 m = m[:n] 726 return m, s, nil 727} 728 729// WriteMsg implements the ResponseWriter.WriteMsg method. 730func (w *response) WriteMsg(m *Msg) (err error) { 731 var data []byte 732 if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check) 733 if t := m.IsTsig(); t != nil { 734 data, w.tsigRequestMAC, err = TsigGenerate(m, w.tsigSecret[t.Hdr.Name], w.tsigRequestMAC, w.tsigTimersOnly) 735 if err != nil { 736 return err 737 } 738 _, err = w.writer.Write(data) 739 return err 740 } 741 } 742 data, err = m.Pack() 743 if err != nil { 744 return err 745 } 746 _, err = w.writer.Write(data) 747 return err 748} 749 750// Write implements the ResponseWriter.Write method. 751func (w *response) Write(m []byte) (int, error) { 752 switch { 753 case w.udp != nil: 754 n, err := WriteToSessionUDP(w.udp, m, w.udpSession) 755 return n, err 756 case w.tcp != nil: 757 lm := len(m) 758 if lm < 2 { 759 return 0, io.ErrShortBuffer 760 } 761 if lm > MaxMsgSize { 762 return 0, &Error{err: "message too large"} 763 } 764 l := make([]byte, 2, 2+lm) 765 binary.BigEndian.PutUint16(l, uint16(lm)) 766 m = append(l, m...) 767 768 n, err := io.Copy(w.tcp, bytes.NewReader(m)) 769 return int(n), err 770 default: 771 panic("dns: Write called after Close") 772 } 773} 774 775// LocalAddr implements the ResponseWriter.LocalAddr method. 776func (w *response) LocalAddr() net.Addr { 777 switch { 778 case w.udp != nil: 779 return w.udp.LocalAddr() 780 case w.tcp != nil: 781 return w.tcp.LocalAddr() 782 default: 783 panic("dns: LocalAddr called after Close") 784 } 785} 786 787// RemoteAddr implements the ResponseWriter.RemoteAddr method. 788func (w *response) RemoteAddr() net.Addr { 789 switch { 790 case w.udpSession != nil: 791 return w.udpSession.RemoteAddr() 792 case w.tcp != nil: 793 return w.tcp.RemoteAddr() 794 default: 795 panic("dns: RemoteAddr called after Close") 796 } 797} 798 799// TsigStatus implements the ResponseWriter.TsigStatus method. 800func (w *response) TsigStatus() error { return w.tsigStatus } 801 802// TsigTimersOnly implements the ResponseWriter.TsigTimersOnly method. 803func (w *response) TsigTimersOnly(b bool) { w.tsigTimersOnly = b } 804 805// Hijack implements the ResponseWriter.Hijack method. 806func (w *response) Hijack() { w.hijacked = true } 807 808// Close implements the ResponseWriter.Close method 809func (w *response) Close() error { 810 // Can't close the udp conn, as that is actually the listener. 811 if w.tcp != nil { 812 e := w.tcp.Close() 813 w.tcp = nil 814 return e 815 } 816 return nil 817} 818 819// ConnectionState() implements the ConnectionStater.ConnectionState() interface. 820func (w *response) ConnectionState() *tls.ConnectionState { 821 type tlsConnectionStater interface { 822 ConnectionState() tls.ConnectionState 823 } 824 if v, ok := w.tcp.(tlsConnectionStater); ok { 825 t := v.ConnectionState() 826 return &t 827 } 828 return nil 829} 830