Cleanup the PR a bit
Remove code and simplify some functions. Documentation is still on the todo. Also don't export any of these functions and/or types.
This commit is contained in:
parent
e4d735493c
commit
d161b9087e
24
server.go
24
server.go
|
@ -44,10 +44,10 @@ type response struct {
|
||||||
tsigTimersOnly bool
|
tsigTimersOnly bool
|
||||||
tsigRequestMAC string
|
tsigRequestMAC string
|
||||||
tsigSecret map[string]string // the tsig secrets
|
tsigSecret map[string]string // the tsig secrets
|
||||||
udp *UDPConn // i/o connection if UDP was used
|
udp *net.UDPConn // i/o connection if UDP was used
|
||||||
udpSession *UDPSession
|
tcp *net.TCPConn // i/o connection if TCP was used
|
||||||
tcp *net.TCPConn // i/o connection if TCP was used
|
udpSession *sessionUDP // oob data to get egress interface right
|
||||||
remoteAddr net.Addr // address of the client
|
remoteAddr net.Addr // address of the client
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeMux is an DNS request multiplexer. It matches the
|
// ServeMux is an DNS request multiplexer. It matches the
|
||||||
|
@ -244,12 +244,10 @@ func (srv *Server) ListenAndServe() error {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
ll, e := NewUDPConn(l)
|
if e := setUDPSocketOptions(l); e != nil {
|
||||||
if e != nil {
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
return srv.serveUDP(l)
|
||||||
return srv.serveUDP(ll)
|
|
||||||
}
|
}
|
||||||
return &Error{err: "bad network"}
|
return &Error{err: "bad network"}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +280,7 @@ func (srv *Server) serveTCP(l *net.TCPListener) error {
|
||||||
|
|
||||||
// serveUDP starts a UDP listener for the server.
|
// serveUDP starts a UDP listener for the server.
|
||||||
// Each request is handled in a seperate goroutine.
|
// Each request is handled in a seperate goroutine.
|
||||||
func (srv *Server) serveUDP(l *UDPConn) error {
|
func (srv *Server) serveUDP(l *net.UDPConn) error {
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
handler := srv.Handler
|
handler := srv.Handler
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
|
@ -304,7 +302,7 @@ func (srv *Server) serveUDP(l *UDPConn) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve a new connection.
|
// Serve a new connection.
|
||||||
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *UDPConn, s *UDPSession, t *net.TCPConn) {
|
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *sessionUDP, t *net.TCPConn) {
|
||||||
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
|
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
|
||||||
q := 0
|
q := 0
|
||||||
Redo:
|
Redo:
|
||||||
|
@ -392,9 +390,9 @@ func (srv *Server) readTCP(conn *net.TCPConn, timeout time.Duration) ([]byte, er
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) readUDP(conn *UDPConn, timeout time.Duration) ([]byte, *UDPSession, error) {
|
func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *sessionUDP, error) {
|
||||||
m := make([]byte, srv.UDPSize)
|
m := make([]byte, srv.UDPSize)
|
||||||
n, s, e := conn.ReadFromSessionUDP(m)
|
n, s, e := readFromSessionUDP(conn, m)
|
||||||
if e != nil || n == 0 {
|
if e != nil || n == 0 {
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, nil, e
|
return nil, nil, e
|
||||||
|
@ -430,7 +428,7 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
||||||
func (w *response) Write(m []byte) (int, error) {
|
func (w *response) Write(m []byte) (int, error) {
|
||||||
switch {
|
switch {
|
||||||
case w.udp != nil:
|
case w.udp != nil:
|
||||||
n, err := w.udp.WriteToSessionUDP(m, w.udpSession)
|
n, err := writeToSessionUDP(w.udp, m, w.udpSession)
|
||||||
return n, err
|
return n, err
|
||||||
case w.tcp != nil:
|
case w.tcp != nil:
|
||||||
lm := len(m)
|
lm := len(m)
|
||||||
|
|
41
udp.go
41
udp.go
|
@ -9,28 +9,19 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UDPSession struct {
|
type sessionUDP struct {
|
||||||
raddr *net.UDPAddr
|
raddr *net.UDPAddr
|
||||||
context []byte
|
context []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *UDPSession) RemoteAddr() net.Addr {
|
func (s *sessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||||
return session.raddr
|
|
||||||
}
|
|
||||||
|
|
||||||
// UDPConn wrap a net.UDPConn with dns.UDPConn struct
|
// setUDPSocketOptions sets the UDP socket options.
|
||||||
type UDPConn struct {
|
// This function is implemented on a per platform basis. See udp_*.go for more details
|
||||||
*net.UDPConn
|
func setUDPSocketOptions(conn *net.UDPConn) error {
|
||||||
}
|
|
||||||
|
|
||||||
// NewUDPConn return a new UDPConn.
|
|
||||||
// Initialize the underlying net.UDPConn for supporting "sessions"
|
|
||||||
// Sessions solve https://github.com/miekg/dns/issues/95
|
|
||||||
func NewUDPConn(conn *net.UDPConn) (*UDPConn, error) {
|
|
||||||
// this function is implemented on a per platform basis. See udp_*.go for more details
|
|
||||||
file, err := conn.File()
|
file, err := conn.File()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil,err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sa, err := syscall.Getsockname(int(file.Fd()))
|
sa, err := syscall.Getsockname(int(file.Fd()))
|
||||||
|
@ -39,34 +30,34 @@ func NewUDPConn(conn *net.UDPConn) (*UDPConn, error) {
|
||||||
// dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
|
// dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
|
||||||
v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
|
v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
SetUDPSocketOptions6(conn)
|
setUDPSocketOptions6(conn)
|
||||||
|
|
||||||
if v6only == 0 {
|
if v6only == 0 {
|
||||||
SetUDPSocketOptions4(conn)
|
setUDPSocketOptions4(conn)
|
||||||
}
|
}
|
||||||
case *syscall.SockaddrInet4:
|
case *syscall.SockaddrInet4:
|
||||||
SetUDPSocketOptions4(conn)
|
setUDPSocketOptions4(conn)
|
||||||
}
|
}
|
||||||
return &UDPConn{conn}, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFromSessionUDP ... Just like net.UDPConn.ReadFrom(), but returns a session object instead of net.UDPAddr
|
// readFromSessionUDP ... Just like net.UDPConn.ReadFrom(), but returns a session object instead of net.UDPAddr
|
||||||
// (RemoteAddr() is available from the UDPSession object)
|
// (RemoteAddr() is available from the UDPSession object)
|
||||||
func (conn *UDPConn) ReadFromSessionUDP(b []byte) (int, *UDPSession, error) {
|
func readFromSessionUDP(conn *net.UDPConn, b []byte) (int, *sessionUDP, error) {
|
||||||
oob := make([]byte, 40)
|
oob := make([]byte, 40)
|
||||||
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, nil, err
|
return n, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
session := &UDPSession{raddr, oob[:oobn]}
|
session := &sessionUDP{raddr, oob[:oobn]}
|
||||||
return n, session, err
|
return n, session, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteToSessionUDP Just like net.UDPConn.WritetTo(), but uses a session object instead of net.Addr
|
// writeToSessionUDP Just like net.UDPConn.WritetTo(), but uses a session object instead of net.Addr
|
||||||
func (conn *UDPConn) WriteToSessionUDP(b []byte, session *UDPSession) (int, error) {
|
func writeToSessionUDP(conn *net.UDPConn, b []byte, session *sessionUDP) (int, error) {
|
||||||
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
14
udp_linux.go
14
udp_linux.go
|
@ -10,7 +10,7 @@ package dns
|
||||||
// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
|
// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
|
||||||
// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
|
// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
|
||||||
//
|
//
|
||||||
// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outoging
|
// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing
|
||||||
// interface, this might not always be the correct one. This code will make sure the egress
|
// interface, this might not always be the correct one. This code will make sure the egress
|
||||||
// packet's interface matched the ingress' one.
|
// packet's interface matched the ingress' one.
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetUDPSocketOptions4 prepares the v4 socket for sessions.
|
// setUDPSocketOptions4 prepares the v4 socket for sessions.
|
||||||
func SetUDPSocketOptions4(conn *net.UDPConn) error {
|
func setUDPSocketOptions4(conn *net.UDPConn) error {
|
||||||
// We got the .File() in NewUDPConn, this this will work
|
// We got the .File() in NewUDPConn, this this will work.
|
||||||
file, _ := conn.File()
|
file, _ := conn.File()
|
||||||
err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1)
|
err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -30,9 +30,9 @@ func SetUDPSocketOptions4(conn *net.UDPConn) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUDPSocketOptions6 prepares the v6 socket for sessions.
|
// setUDPSocketOptions6 prepares the v6 socket for sessions.
|
||||||
func SetUDPSocketOptions6(conn *net.UDPConn) error {
|
func setUDPSocketOptions6(conn *net.UDPConn) error {
|
||||||
// We got the .File() in NewUDPConn, this this will work
|
// We got the .File() in NewUDPConn, this this will work.
|
||||||
file, _ := conn.File()
|
file, _ := conn.File()
|
||||||
err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1)
|
err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -12,5 +12,5 @@ import (
|
||||||
|
|
||||||
// These actually do nothing. See udp_linux.go for an example of how to implement this.
|
// These actually do nothing. See udp_linux.go for an example of how to implement this.
|
||||||
|
|
||||||
func SetUDPSocketOptions4(conn *net.UDPConn) error { return nil }
|
func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
|
||||||
func SetUDPSocketOptions6(conn *net.UDPConn) error { return nil }
|
func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
|
||||||
|
|
Loading…
Reference in New Issue