normalize errors

This commit is contained in:
Miek Gieben 2011-03-25 11:19:35 +01:00
parent 9ac4df6b1d
commit 8aa88a0bd3
8 changed files with 53 additions and 46 deletions

30
dns.go
View File

@ -4,7 +4,7 @@
// Extended and bugfixes by Miek Gieben // Extended and bugfixes by Miek Gieben
// Package dns implements a full featured interface to the DNS. // Package dns implements a full featured interface to the DNS.
// The package allows full control over what is send out to the DNS. // The package allows complete control over what is send out to the DNS.
// //
// Resource records are native types. They are not stored in wire format. // Resource records are native types. They are not stored in wire format.
// Basic usage pattern for creating a new resource record: // Basic usage pattern for creating a new resource record:
@ -16,7 +16,8 @@
// The package dns supports querying, incoming/outgoing Axfr/Ixfr, TSIG, EDNS0, // The package dns supports querying, incoming/outgoing Axfr/Ixfr, TSIG, EDNS0,
// dynamic updates, notifies and DNSSEC validation/signing. // dynamic updates, notifies and DNSSEC validation/signing.
// //
// Basic use pattern for creating a resolver: // Querying the DNS is done by using a Resolver structure. Basic use pattern for creating
// a resolver:
// //
// res := new(Resolver) // res := new(Resolver)
// res.Servers = []string{"127.0.0.1"} // res.Servers = []string{"127.0.0.1"}
@ -26,7 +27,7 @@
// m.Question[0] = Question{"miek.nl", TypeSOA, ClassINET} // m.Question[0] = Question{"miek.nl", TypeSOA, ClassINET}
// in, err := res.Query(m) // in, err := res.Query(m)
// //
// // Server side programming is also supported.
// Basic use pattern for creating an UDP DNS server: // Basic use pattern for creating an UDP DNS server:
// //
// func handle(d *dns.Conn, i *dns.Msg) { /* handle request */ } // func handle(d *dns.Conn, i *dns.Msg) { /* handle request */ }
@ -40,9 +41,8 @@
// //
package dns package dns
// ErrShortWrite is defined in io, use that!
import ( import (
"io"
"os" "os"
"net" "net"
"strconv" "strconv"
@ -123,7 +123,7 @@ func (d *Conn) ReadMsg(m *Msg) os.Error {
in = in[:n] in = in[:n]
ok := m.Unpack(in) ok := m.Unpack(in)
if !ok { if !ok {
return &Error{Error: "Failed to unpack"} return ErrUnpack
} }
return nil return nil
} }
@ -133,7 +133,7 @@ func (d *Conn) ReadMsg(m *Msg) os.Error {
func (d *Conn) WriteMsg(m *Msg) os.Error { func (d *Conn) WriteMsg(m *Msg) os.Error {
out, ok := m.Pack() out, ok := m.Pack()
if !ok { if !ok {
return &Error{Error: "Failed to pack"} return ErrPack
} }
_, err := d.Write(out) _, err := d.Write(out)
if err != nil { if err != nil {
@ -147,7 +147,7 @@ func (d *Conn) WriteMsg(m *Msg) os.Error {
// reading that error is returned; otherwise err is nil. // reading that error is returned; otherwise err is nil.
func (d *Conn) Read(p []byte) (n int, err os.Error) { func (d *Conn) Read(p []byte) (n int, err os.Error) {
if d.UDP != nil && d.TCP != nil { if d.UDP != nil && d.TCP != nil {
return 0, &Error{Error: "UDP and TCP or both non-nil"} return 0, ErrConn
} }
switch { switch {
case d.UDP != nil: case d.UDP != nil:
@ -160,7 +160,7 @@ func (d *Conn) Read(p []byte) (n int, err os.Error) {
d.Port = addr.(*net.UDPAddr).Port d.Port = addr.(*net.UDPAddr).Port
case d.TCP != nil: case d.TCP != nil:
if len(p) < 1 { if len(p) < 1 {
return 0, &Error{Error: "Buffer too small to read"} return 0, io.ErrShortBuffer
} }
n, err = d.TCP.Read(p[0:2]) n, err = d.TCP.Read(p[0:2])
if err != nil || n != 2 { if err != nil || n != 2 {
@ -170,10 +170,10 @@ func (d *Conn) Read(p []byte) (n int, err os.Error) {
d.Port = d.TCP.RemoteAddr().(*net.TCPAddr).Port d.Port = d.TCP.RemoteAddr().(*net.TCPAddr).Port
l, _ := unpackUint16(p[0:2], 0) l, _ := unpackUint16(p[0:2], 0)
if l == 0 { if l == 0 {
return 0, &Error{Error: "received nil msg length", Server: d.Addr} return 0, ErrShortRead
} }
if int(l) > len(p) { if int(l) > len(p) {
return int(l), &Error{Error: "Buffer too small to read"} return int(l), io.ErrShortBuffer
} }
n, err = d.TCP.Read(p[:l]) n, err = d.TCP.Read(p[:l])
if err != nil { if err != nil {
@ -204,7 +204,7 @@ func (d *Conn) Read(p []byte) (n int, err os.Error) {
// that error is returned; otherwise err is nil // that error is returned; otherwise err is nil
func (d *Conn) Write(p []byte) (n int, err os.Error) { func (d *Conn) Write(p []byte) (n int, err os.Error) {
if d.UDP != nil && d.TCP != nil { if d.UDP != nil && d.TCP != nil {
return 0, &Error{Error: "UDP and TCP or both non-nil"} return 0, ErrConn
} }
var attempts int var attempts int
@ -248,7 +248,7 @@ func (d *Conn) Write(p []byte) (n int, err os.Error) {
return n, err return n, err
} }
if n != 2 { if n != 2 {
return n, &Error{Error: "Write failure"} return n, io.ErrShortWrite
} }
n, err = d.TCP.Write(q) n, err = d.TCP.Write(q)
if err != nil { if err != nil {
@ -279,7 +279,7 @@ func (d *Conn) Write(p []byte) (n int, err os.Error) {
// errors are returned in err; otherwise it is nil. // errors are returned in err; otherwise it is nil.
func (d *Conn) Close() (err os.Error) { func (d *Conn) Close() (err os.Error) {
if d.UDP != nil && d.TCP != nil { if d.UDP != nil && d.TCP != nil {
return &Error{Error: "UDP and TCP or both non-nil"} return ErrConn
} }
switch { switch {
case d.UDP != nil: case d.UDP != nil:
@ -295,7 +295,7 @@ func (d *Conn) Close() (err os.Error) {
func (d *Conn) SetTimeout() (err os.Error) { func (d *Conn) SetTimeout() (err os.Error) {
var sec int64 var sec int64
if d.UDP != nil && d.TCP != nil { if d.UDP != nil && d.TCP != nil {
return &Error{Error: "UDP and TCP or both non-nil"} return ErrConn
} }
sec = int64(d.Timeout) sec = int64(d.Timeout)
if sec == 0 { if sec == 0 {

View File

@ -5,7 +5,7 @@ import (
"encoding/hex" "encoding/hex"
) )
// EDNS0 Options // EDNS0 Option codes.
const ( const (
_ = iota _ = iota
OptionCodeLLQ // not used OptionCodeLLQ // not used

View File

@ -23,14 +23,14 @@ func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) {
switch r.Algorithm { switch r.Algorithm {
case AlgRSAMD5, AlgRSASHA1, AlgRSASHA256: case AlgRSAMD5, AlgRSASHA1, AlgRSASHA256:
if bits < 512 || bits > 4096 { if bits < 512 || bits > 4096 {
return nil, &Error{Error: "Size not in range [512..4096]"} return nil, ErrKeySize
} }
case AlgRSASHA512: case AlgRSASHA512:
if bits < 1024 || bits > 4096 { if bits < 1024 || bits > 4096 {
return nil, &Error{Error: "Size not in range [1024..4096]"} return nil, ErrKeySize
} }
default: default:
return nil, &Error{Error: "Algorithm not recognized"} return nil, ErrAlg
} }
switch r.Algorithm { switch r.Algorithm {
@ -100,12 +100,12 @@ func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader) (PrivateKey, os.Error) {
switch left { switch left {
case "Private-key-format:": case "Private-key-format:":
if right != "v1.3" { if right != "v1.3" {
return nil, &Error{Error: "v1.3 supported"} return nil, ErrPrivKey
} }
case "Algorithm:": case "Algorithm:":
a, _ := strconv.Atoi(right) a, _ := strconv.Atoi(right)
if a == 0 { if a == 0 {
return nil, &Error{Error: "incorrect algorithm"} return nil, ErrAlg
} }
k.Algorithm = uint8(a) k.Algorithm = uint8(a)
case "Modulus:", "PublicExponent:", "PrivateExponent:", "Prime1:", "Prime2:": case "Modulus:", "PublicExponent:", "PrivateExponent:", "Prime1:", "Prime2:":
@ -140,13 +140,13 @@ func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader) (PrivateKey, os.Error) {
case "Created:", "Publish:", "Activate:": case "Created:", "Publish:", "Activate:":
/* not used in Go (yet) */ /* not used in Go (yet) */
default: default:
return nil, &Error{Error: "Private key file not recognized"} return nil, ErrKey
} }
} }
line, _, err = r.ReadLine() line, _, err = r.ReadLine()
} }
if ! k.setPublicKeyRSA(p.PublicKey.E, p.PublicKey.N) { if ! k.setPublicKeyRSA(p.PublicKey.E, p.PublicKey.N) {
return nil, &Error{Error: "Failed to set public key"} return nil, ErrKey
} }
return p, nil return p, nil
} }

15
msg.go
View File

@ -27,6 +27,21 @@ import (
"encoding/hex" "encoding/hex"
) )
var ErrUnpack os.Error = &Error{Error: "unpacking failed"}
var ErrPack os.Error = &Error{Error: "packing failed"}
var ErrId os.Error = &Error{Error: "id mismatch"}
var ErrShortRead os.Error = &Error{Error: "short read"}
var ErrConn os.Error = &Error{Error: "conn holds both UDP and TCP connection"}
var ErrServ os.Error = &Error{Error: "no servers could be reached"}
var ErrKey os.Error = &Error{Error: "bad key"}
var ErrPrivKey os.Error = &Error{Error: "bad private key"}
var ErrKeySize os.Error = &Error{Error: "bad key size"}
var ErrAlg os.Error = &Error{Error: "bad algorithm"}
var ErrTime os.Error = &Error{Error: "bad time"}
var ErrSig os.Error = &Error{Error: "bad signature"}
var ErrSigGen os.Error = &Error{Error: "bad signature generation"}
var ErrXfrSoa os.Error = &Error{Error: "no SOA seen"}
// A manually-unpacked version of (id, bits). // A manually-unpacked version of (id, bits).
// This is in its own struct for easy printing. // This is in its own struct for easy printing.
type MsgHdr struct { type MsgHdr struct {

View File

@ -12,14 +12,6 @@ import (
"time" "time"
) )
// Todo(MG) put in dns.go
const ErrPack = "Failed to pack message"
const ErrUnpack = ""
const ErrServ = "No servers could be reached"
const ErrTsigKey = ""
const ErrTsigTime = ""
const ErrTsig = ""
type Resolver struct { type Resolver struct {
Servers []string // servers to use Servers []string // servers to use
Search []string // suffixes to append to local name Search []string // suffixes to append to local name
@ -50,7 +42,7 @@ func (res *Resolver) QueryTsig(q *Msg, tsig *Tsig) (d *Msg, err os.Error) {
sending, ok := q.Pack() sending, ok := q.Pack()
if !ok { if !ok {
return nil, &Error{Error: ErrPack} return nil, ErrPack
} }
if res.Mangle != nil { if res.Mangle != nil {
sending = res.Mangle(sending) sending = res.Mangle(sending)

12
tsig.go
View File

@ -101,7 +101,7 @@ func (t *Tsig) Generate(msg []byte) ([]byte, os.Error) {
// Create TSIG and add it to the message. // Create TSIG and add it to the message.
q := new(Msg) q := new(Msg)
if !q.Unpack(msg) { if !q.Unpack(msg) {
return nil, &Error{Error: "Failed to unpack"} return nil, ErrUnpack
} }
rr := new(RR_TSIG) rr := new(RR_TSIG)
@ -116,7 +116,7 @@ func (t *Tsig) Generate(msg []byte) ([]byte, os.Error) {
q.Extra = append(q.Extra, rr) q.Extra = append(q.Extra, rr)
send, ok := q.Pack() send, ok := q.Pack()
if !ok { if !ok {
return send, &Error{Error: "Failed to pack"} return send, ErrPack
} }
return send, nil return send, nil
} }
@ -132,7 +132,7 @@ func (t *Tsig) Verify(msg []byte) (bool, os.Error) {
// Stipped the TSIG from the incoming msg // Stipped the TSIG from the incoming msg
stripped, ok := stripTsig(msg) stripped, ok := stripTsig(msg)
if !ok { if !ok {
return false, &Error{Error: "Failed to strip tsig"} return false, ErrSigGen
} }
buf, err := t.Buffer(stripped) buf, err := t.Buffer(stripped)
@ -162,7 +162,7 @@ func (t *Tsig) Buffer(msg []byte) ([]byte, os.Error) {
macbuf = make([]byte, len(t.RequestMAC)) // reqmac should be twice as long macbuf = make([]byte, len(t.RequestMAC)) // reqmac should be twice as long
n, ok := packStruct(m, macbuf, 0) n, ok := packStruct(m, macbuf, 0)
if !ok { if !ok {
return nil, &Error{Error: "Failed to pack request mac"} return nil, ErrSigGen
} }
macbuf = macbuf[:n] macbuf = macbuf[:n]
} }
@ -174,7 +174,7 @@ func (t *Tsig) Buffer(msg []byte) ([]byte, os.Error) {
tsig.Fudge = t.Fudge tsig.Fudge = t.Fudge
n, ok1 := packStruct(tsig, tsigvar, 0) n, ok1 := packStruct(tsig, tsigvar, 0)
if !ok1 { if !ok1 {
return nil, &Error{Error: "Failed to pack timers"} return nil, ErrSigGen
} }
tsigvar = tsigvar[:n] tsigvar = tsigvar[:n]
} else { } else {
@ -190,7 +190,7 @@ func (t *Tsig) Buffer(msg []byte) ([]byte, os.Error) {
tsig.OtherData = "" tsig.OtherData = ""
n, ok1 := packStruct(tsig, tsigvar, 0) n, ok1 := packStruct(tsig, tsigvar, 0)
if !ok1 { if !ok1 {
return nil, &Error{Error: "Failed to pack tsig variables"} return nil, ErrSigGen
} }
tsigvar = tsigvar[:n] tsigvar = tsigvar[:n]
} }

View File

@ -61,7 +61,7 @@ const (
TypeTKEY = 249 TypeTKEY = 249
TypeTSIG = 250 TypeTSIG = 250
// valid Question.qtype only // valid Question.Qtype only
TypeIXFR = 251 TypeIXFR = 251
TypeAXFR = 252 TypeAXFR = 252
TypeMAILB = 253 TypeMAILB = 253
@ -73,7 +73,7 @@ const (
TypeTA = 32768 TypeTA = 32768
TypeDLV = 32769 TypeDLV = 32769
// valid Question.qclass // valid Question.Qclass
ClassINET = 1 ClassINET = 1
ClassCSNET = 2 ClassCSNET = 2
ClassCHAOS = 3 ClassCHAOS = 3

12
xfr.go
View File

@ -35,7 +35,7 @@ func (d *Conn) XfrRead(q *Msg, m chan Xfr) {
case TypeIXFR: case TypeIXFR:
d.ixfrRead(q, m) d.ixfrRead(q, m)
default: default:
m <- Xfr{true, nil, &Error{Error: "Qtype not recognized"}} m <- Xfr{true, nil, &Error{Error: "Xfr Qtype not recognized"}}
close(m) close(m)
} }
} }
@ -51,7 +51,7 @@ func (d *Conn) XfrWrite(q *Msg, m chan Xfr) {
case TypeIXFR: case TypeIXFR:
// d.ixfrWrite(q, m) // d.ixfrWrite(q, m)
default: default:
m <- Xfr{true, nil, &Error{Error: "Qtype not recognized"}} m <- Xfr{true, nil, &Error{Error: "Xfr Qtype not recognized"}}
close(m) close(m)
} }
} }
@ -67,13 +67,13 @@ func (d *Conn) axfrRead(q *Msg, m chan Xfr) {
return return
} }
if in.Id != q.Id { if in.Id != q.Id {
m <- Xfr{true, nil, &Error{Error: "Id mismatch"}} m <- Xfr{true, nil, ErrId}
return return
} }
if first { if first {
if !checkXfrSOA(in, true) { if !checkXfrSOA(in, true) {
m <- Xfr{true, nil, &Error{Error: "SOA not first record"}} m <- Xfr{true, nil, ErrXfrSoa}
return return
} }
first = !first first = !first
@ -152,7 +152,7 @@ func (d *Conn) ixfrRead(q *Msg, m chan Xfr) {
return return
} }
if in.Id != q.Id { if in.Id != q.Id {
m <- Xfr{true, nil, &Error{Error: "Id mismatch"}} m <- Xfr{true, nil, ErrId}
return return
} }
@ -164,7 +164,7 @@ func (d *Conn) ixfrRead(q *Msg, m chan Xfr) {
// But still check if the returned answer is ok // But still check if the returned answer is ok
if !checkXfrSOA(in, true) { if !checkXfrSOA(in, true) {
m <- Xfr{true, nil, &Error{Error: "SOA not first record"}} m <- Xfr{true, nil, ErrXfrSoa}
return return
} }
// This serial is important // This serial is important