157 lines
3.5 KiB
Go
157 lines
3.5 KiB
Go
|
package errors
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"github.com/miekg/dns"
|
||
|
"net"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
UDP_TRANSPORT = 17
|
||
|
TCP_TRANSPORT = 6
|
||
|
)
|
||
|
|
||
|
var PROTO_TO_STR = map[int]string{
|
||
|
TCP_TRANSPORT: "TCP",
|
||
|
UDP_TRANSPORT: "UDP",
|
||
|
}
|
||
|
|
||
|
var STR_TO_PROTO = map[string]int{
|
||
|
"": UDP_TRANSPORT,
|
||
|
"TCP": TCP_TRANSPORT,
|
||
|
"tcp": TCP_TRANSPORT,
|
||
|
"UDP": UDP_TRANSPORT,
|
||
|
"udp": UDP_TRANSPORT,
|
||
|
}
|
||
|
|
||
|
type serializedServfailError struct {
|
||
|
Type string `json:"type"`
|
||
|
Qname string `json:"qname"`
|
||
|
Qtype string `json:"qtype"`
|
||
|
Addr string `json:"ip"`
|
||
|
Proto string `json:"protocol"`
|
||
|
}
|
||
|
|
||
|
type ServfailError struct {
|
||
|
qname string
|
||
|
qtype uint16
|
||
|
addr net.IP
|
||
|
proto int
|
||
|
}
|
||
|
|
||
|
func NewServfailError(qname string, qtype uint16, addr net.IP, proto int) *ServfailError {
|
||
|
se := new(ServfailError)
|
||
|
se.qname = qname
|
||
|
se.qtype = qtype
|
||
|
se.addr = addr
|
||
|
se.proto = proto
|
||
|
return se
|
||
|
}
|
||
|
|
||
|
func (se *ServfailError) MarshalJSON() ([]byte, error) {
|
||
|
sse := new(serializedServfailError)
|
||
|
sse.Type = dns.RcodeToString[dns.RcodeServerFailure]
|
||
|
sse.Qname = se.qname
|
||
|
sse.Qtype = dns.TypeToString[se.qtype]
|
||
|
sse.Addr = se.addr.String()
|
||
|
sse.Proto = PROTO_TO_STR[se.proto]
|
||
|
return json.Marshal(sse)
|
||
|
}
|
||
|
|
||
|
func (se *ServfailError) UnmarshalJSON(bstr []byte) error {
|
||
|
sse := new(serializedServfailError)
|
||
|
if err := json.Unmarshal(bstr, sse); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
se.qname = sse.Qname
|
||
|
se.qtype = dns.StringToType[sse.Qtype]
|
||
|
se.addr = net.ParseIP(sse.Addr)
|
||
|
se.proto = STR_TO_PROTO[sse.Proto]
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (se *ServfailError) Error() string {
|
||
|
return fmt.Sprintf("received a SERVFAIL while trying to query %s %s? from %s with %s", se.qname, dns.TypeToString[se.qtype], se.addr.String(), PROTO_TO_STR[se.proto])
|
||
|
}
|
||
|
|
||
|
type serializedNXDomainError struct {
|
||
|
Type string `json:"type"`
|
||
|
Qname string `json:"qname"`
|
||
|
Qtype string `json:"qtype"`
|
||
|
Addr string `json:"ip"`
|
||
|
Proto string `json:"protocol"`
|
||
|
}
|
||
|
|
||
|
type NXDomainError struct {
|
||
|
qname string
|
||
|
qtype uint16
|
||
|
addr net.IP
|
||
|
proto int
|
||
|
}
|
||
|
|
||
|
func NewNXDomainError(qname string, qtype uint16, addr net.IP, proto int) *NXDomainError {
|
||
|
nx := new(NXDomainError)
|
||
|
nx.qname = qname
|
||
|
nx.qtype = qtype
|
||
|
nx.addr = addr
|
||
|
nx.proto = proto
|
||
|
return nx
|
||
|
}
|
||
|
func (nx *NXDomainError) Error() string {
|
||
|
return fmt.Sprintf("received a NXDomain while trying to query %s %s? from %s with %s", nx.qname, dns.TypeToString[nx.qtype], nx.addr.String(), PROTO_TO_STR[nx.proto])
|
||
|
}
|
||
|
|
||
|
func (nx *NXDomainError) MarshalJSON() ([]byte, error) {
|
||
|
snx := new(serializedNXDomainError)
|
||
|
snx.Type = dns.RcodeToString[dns.RcodeNameError]
|
||
|
snx.Qname = nx.qname
|
||
|
snx.Qtype = dns.TypeToString[nx.qtype]
|
||
|
snx.Addr = nx.addr.String()
|
||
|
snx.Proto = PROTO_TO_STR[nx.proto]
|
||
|
return json.Marshal(snx)
|
||
|
}
|
||
|
|
||
|
func (nx *NXDomainError) UnmarshalJSON(bstr []byte) error {
|
||
|
snx := new(serializedNXDomainError)
|
||
|
if err := json.Unmarshal(bstr, snx); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
nx.qname = snx.Qname
|
||
|
nx.qtype = dns.StringToType[snx.Qtype]
|
||
|
nx.addr = net.ParseIP(snx.Addr)
|
||
|
nx.proto = STR_TO_PROTO[snx.Proto]
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type serializedNoNameError struct {
|
||
|
Name string `json:"name"`
|
||
|
}
|
||
|
|
||
|
type NoNameServerError struct {
|
||
|
name string
|
||
|
}
|
||
|
|
||
|
func (ne *NoNameServerError) MarshalJSON() ([]byte, error) {
|
||
|
sne := new(serializedNoNameError)
|
||
|
sne.Name = ne.name
|
||
|
return json.Marshal(sne)
|
||
|
}
|
||
|
|
||
|
func (ne *NoNameServerError) UnmarshalJSON(bstr []byte) error {
|
||
|
sne := new(serializedNoNameError)
|
||
|
if err := json.Unmarshal(bstr, sne); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
ne.name = sne.Name
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func NewNoNameServerError(name string) *NoNameServerError {
|
||
|
return &NoNameServerError{name}
|
||
|
}
|
||
|
|
||
|
func (ne *NoNameServerError) Error() string {
|
||
|
return fmt.Sprintf("%s has no nameservers", ne.name)
|
||
|
}
|