"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "client.go" between
dns-1.1.45.tar.gz and dns-1.1.46.tar.gz

About: GO DNS implements a DNS library in Go.

client.go  (dns-1.1.45):client.go  (dns-1.1.46)
skipping to change at line 21 skipping to change at line 21
"net" "net"
"strings" "strings"
"time" "time"
) )
const ( const (
dnsTimeout time.Duration = 2 * time.Second dnsTimeout time.Duration = 2 * time.Second
tcpIdleTimeout time.Duration = 8 * time.Second tcpIdleTimeout time.Duration = 8 * time.Second
) )
func isPacketConn(c net.Conn) bool {
if _, ok := c.(net.PacketConn); !ok {
return false
}
if ua, ok := c.LocalAddr().(*net.UnixAddr); ok {
return ua.Net == "unixgram"
}
return true
}
// A Conn represents a connection to a DNS server. // A Conn represents a connection to a DNS server.
type Conn struct { type Conn struct {
net.Conn // a net.Conn holding the connection net.Conn // a net.Conn holding the connection
UDPSize uint16 // minimum receive buffer for UDP messag es UDPSize uint16 // minimum receive buffer for UDP messag es
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<ba se64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<ba se64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operation s. TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operation s.
tsigRequestMAC string tsigRequestMAC string
} }
func (co *Conn) tsigProvider() TsigProvider {
if co.TsigProvider != nil {
return co.TsigProvider
}
// tsigSecretProvider will return ErrSecret if co.TsigSecret is nil.
return tsigSecretProvider(co.TsigSecret)
}
// A Client defines parameters for a DNS client. // A Client defines parameters for a DNS client.
type Client struct { type Client struct {
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP) Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
UDPSize uint16 // minimum receive buffer for UDP messages UDPSize uint16 // minimum receive buffer for UDP messages
TLSConfig *tls.Config // TLS connection configuration TLSConfig *tls.Config // TLS connection configuration
Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout, // Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and // WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
// Client.Dialer) or context.Context.Deadline (see ExchangeContext) // Client.Dialer) or context.Context.Deadline (see ExchangeContext)
Timeout time.Duration Timeout time.Duration
skipping to change at line 224 skipping to change at line 244
} }
co.SetWriteDeadline(writeDeadline) co.SetWriteDeadline(writeDeadline)
co.SetReadDeadline(readDeadline) co.SetReadDeadline(readDeadline)
co.TsigSecret, co.TsigProvider = c.TsigSecret, c.TsigProvider co.TsigSecret, co.TsigProvider = c.TsigSecret, c.TsigProvider
if err = co.WriteMsg(m); err != nil { if err = co.WriteMsg(m); err != nil {
return nil, 0, err return nil, 0, err
} }
if _, ok := co.Conn.(net.PacketConn); ok { if isPacketConn(co.Conn) {
for { for {
r, err = co.ReadMsg() r, err = co.ReadMsg()
// Ignore replies with mismatched IDs because they might be // Ignore replies with mismatched IDs because they might be
// responses to earlier queries that timed out. // responses to earlier queries that timed out.
if err != nil || r.Id == m.Id { if err != nil || r.Id == m.Id {
break break
} }
} }
} else { } else {
r, err = co.ReadMsg() r, err = co.ReadMsg()
skipping to change at line 262 skipping to change at line 282
} }
m := new(Msg) m := new(Msg)
if err := m.Unpack(p); err != nil { if err := m.Unpack(p); err != nil {
// If an error was returned, we still want to allow the user to u se // If an error was returned, we still want to allow the user to u se
// the message, but naively they can just check err if they don't want // the message, but naively they can just check err if they don't want
// to use an erroneous message // to use an erroneous message
return m, err return m, err
} }
if t := m.IsTsig(); t != nil { if t := m.IsTsig(); t != nil {
if co.TsigProvider != nil { // Need to work on the original message p, as that was used to ca
err = tsigVerifyProvider(p, co.TsigProvider, co.tsigReque lculate the tsig.
stMAC, false) err = tsigVerifyProvider(p, co.tsigProvider(), co.tsigRequestMAC,
} else { false)
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
return m, ErrSecret
}
// Need to work on the original message p, as that was us
ed to calculate the tsig.
err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.tsigReq
uestMAC, false)
}
} }
return m, err return m, err
} }
// ReadMsgHeader reads a DNS message, parses and populates hdr (when hdr is not nil). // ReadMsgHeader reads a DNS message, parses and populates hdr (when hdr is not nil).
// Returns message as a byte slice to be parsed with Msg.Unpack later on. // Returns message as a byte slice to be parsed with Msg.Unpack later on.
// Note that error handling on the message body is not possible as only the head er is parsed. // Note that error handling on the message body is not possible as only the head er is parsed.
func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) { func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
var ( var (
p []byte p []byte
n int n int
err error err error
) )
if _, ok := co.Conn.(net.PacketConn); ok { if isPacketConn(co.Conn) {
if co.UDPSize > MinMsgSize { if co.UDPSize > MinMsgSize {
p = make([]byte, co.UDPSize) p = make([]byte, co.UDPSize)
} else { } else {
p = make([]byte, MinMsgSize) p = make([]byte, MinMsgSize)
} }
n, err = co.Read(p) n, err = co.Read(p)
} else { } else {
var length uint16 var length uint16
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil { if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
return nil, err return nil, err
skipping to change at line 325 skipping to change at line 338
} }
return p, err return p, err
} }
// Read implements the net.Conn read method. // Read implements the net.Conn read method.
func (co *Conn) Read(p []byte) (n int, err error) { func (co *Conn) Read(p []byte) (n int, err error) {
if co.Conn == nil { if co.Conn == nil {
return 0, ErrConnEmpty return 0, ErrConnEmpty
} }
if _, ok := co.Conn.(net.PacketConn); ok { if isPacketConn(co.Conn) {
// UDP connection // UDP connection
return co.Conn.Read(p) return co.Conn.Read(p)
} }
var length uint16 var length uint16
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil { if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
return 0, err return 0, err
} }
if int(length) > len(p) { if int(length) > len(p) {
return 0, io.ErrShortBuffer return 0, io.ErrShortBuffer
skipping to change at line 347 skipping to change at line 360
return io.ReadFull(co.Conn, p[:length]) return io.ReadFull(co.Conn, p[:length])
} }
// WriteMsg sends a message through the connection co. // WriteMsg sends a message through the connection co.
// If the message m contains a TSIG record the transaction // If the message m contains a TSIG record the transaction
// signature is calculated. // signature is calculated.
func (co *Conn) WriteMsg(m *Msg) (err error) { func (co *Conn) WriteMsg(m *Msg) (err error) {
var out []byte var out []byte
if t := m.IsTsig(); t != nil { if t := m.IsTsig(); t != nil {
mac := "" // Set tsigRequestMAC for the next read, although only used in zo
if co.TsigProvider != nil { ne transfers.
out, mac, err = tsigGenerateProvider(m, co.TsigProvider, out, co.tsigRequestMAC, err = tsigGenerateProvider(m, co.tsigProv
co.tsigRequestMAC, false) ider(), co.tsigRequestMAC, false)
} else {
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
return ErrSecret
}
out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name]
, co.tsigRequestMAC, false)
}
// Set for the next read, although only used in zone transfers
co.tsigRequestMAC = mac
} else { } else {
out, err = m.Pack() out, err = m.Pack()
} }
if err != nil { if err != nil {
return err return err
} }
_, err = co.Write(out) _, err = co.Write(out)
return err return err
} }
// Write implements the net.Conn Write method. // Write implements the net.Conn Write method.
func (co *Conn) Write(p []byte) (int, error) { func (co *Conn) Write(p []byte) (int, error) {
if len(p) > MaxMsgSize { if len(p) > MaxMsgSize {
return 0, &Error{err: "message too large"} return 0, &Error{err: "message too large"}
} }
if _, ok := co.Conn.(net.PacketConn); ok { if isPacketConn(co.Conn) {
return co.Conn.Write(p) return co.Conn.Write(p)
} }
msg := make([]byte, 2+len(p)) msg := make([]byte, 2+len(p))
binary.BigEndian.PutUint16(msg, uint16(len(p))) binary.BigEndian.PutUint16(msg, uint16(len(p)))
copy(msg[2:], p) copy(msg[2:], p)
return co.Conn.Write(msg) return co.Conn.Write(msg)
} }
// Return the appropriate timeout for a specific request // Return the appropriate timeout for a specific request
 End of changes. 8 change blocks. 
29 lines changed or deleted 32 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)