package dns
import (
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"net"
"strconv"
)
const (
EDNS0LLQ = 0x1
EDNS0UL = 0x2
EDNS0NSID = 0x3
EDNS0ESU = 0x4
EDNS0DAU = 0x5
EDNS0DHU = 0x6
EDNS0N3U = 0x7
EDNS0SUBNET = 0x8
EDNS0EXPIRE = 0x9
EDNS0COOKIE = 0xa
EDNS0TCPKEEPALIVE = 0xb
EDNS0PADDING = 0xc
EDNS0EDE = 0xf
EDNS0LOCALSTART = 0xFDE9
EDNS0LOCALEND = 0xFFFE
_DO = 1 << 15
_CO = 1 << 14
)
func makeDataOpt(code uint16 ) EDNS0 {
switch code {
case EDNS0LLQ :
return new (EDNS0_LLQ )
case EDNS0UL :
return new (EDNS0_UL )
case EDNS0NSID :
return new (EDNS0_NSID )
case EDNS0DAU :
return new (EDNS0_DAU )
case EDNS0DHU :
return new (EDNS0_DHU )
case EDNS0N3U :
return new (EDNS0_N3U )
case EDNS0SUBNET :
return new (EDNS0_SUBNET )
case EDNS0EXPIRE :
return new (EDNS0_EXPIRE )
case EDNS0COOKIE :
return new (EDNS0_COOKIE )
case EDNS0TCPKEEPALIVE :
return new (EDNS0_TCP_KEEPALIVE )
case EDNS0PADDING :
return new (EDNS0_PADDING )
case EDNS0EDE :
return new (EDNS0_EDE )
case EDNS0ESU :
return new (EDNS0_ESU )
default :
e := new (EDNS0_LOCAL )
e .Code = code
return e
}
}
type OPT struct {
Hdr RR_Header
Option []EDNS0 `dns:"opt"`
}
func (rr *OPT ) String () string {
s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv .Itoa (int (rr .Version ())) + "; "
if rr .Do () {
if rr .Co () {
s += "flags: do, co; "
} else {
s += "flags: do; "
}
} else {
s += "flags:; "
}
if rr .Hdr .Ttl &0x7FFF != 0 {
s += fmt .Sprintf ("MBZ: 0x%04x, " , rr .Hdr .Ttl &0x7FFF )
}
s += "udp: " + strconv .Itoa (int (rr .UDPSize ()))
for _ , o := range rr .Option {
switch o .(type ) {
case *EDNS0_NSID :
s += "\n; NSID: " + o .String ()
h , e := o .pack ()
var r string
if e == nil {
for _ , c := range h {
r += "(" + string (c ) + ")"
}
s += " " + r
}
case *EDNS0_SUBNET :
s += "\n; SUBNET: " + o .String ()
case *EDNS0_COOKIE :
s += "\n; COOKIE: " + o .String ()
case *EDNS0_EXPIRE :
s += "\n; EXPIRE: " + o .String ()
case *EDNS0_TCP_KEEPALIVE :
s += "\n; KEEPALIVE: " + o .String ()
case *EDNS0_UL :
s += "\n; UPDATE LEASE: " + o .String ()
case *EDNS0_LLQ :
s += "\n; LONG LIVED QUERIES: " + o .String ()
case *EDNS0_DAU :
s += "\n; DNSSEC ALGORITHM UNDERSTOOD: " + o .String ()
case *EDNS0_DHU :
s += "\n; DS HASH UNDERSTOOD: " + o .String ()
case *EDNS0_N3U :
s += "\n; NSEC3 HASH UNDERSTOOD: " + o .String ()
case *EDNS0_LOCAL :
s += "\n; LOCAL OPT: " + o .String ()
case *EDNS0_PADDING :
s += "\n; PADDING: " + o .String ()
case *EDNS0_EDE :
s += "\n; EDE: " + o .String ()
case *EDNS0_ESU :
s += "\n; ESU: " + o .String ()
}
}
return s
}
func (rr *OPT ) len (off int , compression map [string ]struct {}) int {
l := rr .Hdr .len (off , compression )
for _ , o := range rr .Option {
l += 4
lo , _ := o .pack ()
l += len (lo )
}
return l
}
func (*OPT ) parse (c *zlexer , origin string ) *ParseError {
return &ParseError {err : "OPT records do not have a presentation format" }
}
func (rr *OPT ) isDuplicate (r2 RR ) bool { return false }
func (rr *OPT ) Version () uint8 {
return uint8 (rr .Hdr .Ttl & 0x00FF0000 >> 16 )
}
func (rr *OPT ) SetVersion (v uint8 ) {
rr .Hdr .Ttl = rr .Hdr .Ttl &0xFF00FFFF | uint32 (v )<<16
}
func (rr *OPT ) ExtendedRcode () int {
return int (rr .Hdr .Ttl &0xFF000000 >>24 ) << 4
}
func (rr *OPT ) SetExtendedRcode (v uint16 ) {
rr .Hdr .Ttl = rr .Hdr .Ttl &0x00FFFFFF | uint32 (v >>4 )<<24
}
func (rr *OPT ) UDPSize () uint16 {
return rr .Hdr .Class
}
func (rr *OPT ) SetUDPSize (size uint16 ) {
rr .Hdr .Class = size
}
func (rr *OPT ) Do () bool {
return rr .Hdr .Ttl &_DO == _DO
}
func (rr *OPT ) SetDo (do ...bool ) {
if len (do ) == 1 {
if do [0 ] {
rr .Hdr .Ttl |= _DO
} else {
rr .Hdr .Ttl &^= _DO
}
} else {
rr .Hdr .Ttl |= _DO
}
}
func (rr *OPT ) Co () bool {
return rr .Hdr .Ttl &_CO == _CO
}
func (rr *OPT ) SetCo (co ...bool ) {
if len (co ) == 1 {
if co [0 ] {
rr .Hdr .Ttl |= _CO
} else {
rr .Hdr .Ttl &^= _CO
}
} else {
rr .Hdr .Ttl |= _CO
}
}
func (rr *OPT ) Z () uint16 {
return uint16 (rr .Hdr .Ttl & 0x3FFF )
}
func (rr *OPT ) SetZ (z uint16 ) {
rr .Hdr .Ttl = rr .Hdr .Ttl &^0x3FFF | uint32 (z &0x3FFF )
}
type EDNS0 interface {
Option () uint16
pack() ([]byte , error )
unpack([]byte ) error
String () string
copy() EDNS0
}
type EDNS0_NSID struct {
Code uint16
Nsid string
}
func (e *EDNS0_NSID ) pack () ([]byte , error ) {
h , err := hex .DecodeString (e .Nsid )
if err != nil {
return nil , err
}
return h , nil
}
func (e *EDNS0_NSID ) Option () uint16 { return EDNS0NSID }
func (e *EDNS0_NSID ) unpack (b []byte ) error { e .Nsid = hex .EncodeToString (b ); return nil }
func (e *EDNS0_NSID ) String () string { return e .Nsid }
func (e *EDNS0_NSID ) copy () EDNS0 { return &EDNS0_NSID {e .Code , e .Nsid } }
type EDNS0_SUBNET struct {
Code uint16
Family uint16
SourceNetmask uint8
SourceScope uint8
Address net .IP
}
func (e *EDNS0_SUBNET ) Option () uint16 { return EDNS0SUBNET }
func (e *EDNS0_SUBNET ) pack () ([]byte , error ) {
b := make ([]byte , 4 )
binary .BigEndian .PutUint16 (b [0 :], e .Family )
b [2 ] = e .SourceNetmask
b [3 ] = e .SourceScope
switch e .Family {
case 0 :
if e .SourceNetmask != 0 {
return nil , errors .New ("dns: bad address family" )
}
case 1 :
if e .SourceNetmask > net .IPv4len *8 {
return nil , errors .New ("dns: bad netmask" )
}
if len (e .Address .To4 ()) != net .IPv4len {
return nil , errors .New ("dns: bad address" )
}
ip := e .Address .To4 ().Mask (net .CIDRMask (int (e .SourceNetmask ), net .IPv4len *8 ))
needLength := (e .SourceNetmask + 8 - 1 ) / 8
b = append (b , ip [:needLength ]...)
case 2 :
if e .SourceNetmask > net .IPv6len *8 {
return nil , errors .New ("dns: bad netmask" )
}
if len (e .Address ) != net .IPv6len {
return nil , errors .New ("dns: bad address" )
}
ip := e .Address .Mask (net .CIDRMask (int (e .SourceNetmask ), net .IPv6len *8 ))
needLength := (e .SourceNetmask + 8 - 1 ) / 8
b = append (b , ip [:needLength ]...)
default :
return nil , errors .New ("dns: bad address family" )
}
return b , nil
}
func (e *EDNS0_SUBNET ) unpack (b []byte ) error {
if len (b ) < 4 {
return ErrBuf
}
e .Family = binary .BigEndian .Uint16 (b )
e .SourceNetmask = b [2 ]
e .SourceScope = b [3 ]
switch e .Family {
case 0 :
if e .SourceNetmask != 0 {
return errors .New ("dns: bad address family" )
}
e .Address = net .IPv4 (0 , 0 , 0 , 0 )
case 1 :
if e .SourceNetmask > net .IPv4len *8 || e .SourceScope > net .IPv4len *8 {
return errors .New ("dns: bad netmask" )
}
addr := make (net .IP , net .IPv4len )
copy (addr , b [4 :])
e .Address = addr .To16 ()
case 2 :
if e .SourceNetmask > net .IPv6len *8 || e .SourceScope > net .IPv6len *8 {
return errors .New ("dns: bad netmask" )
}
addr := make (net .IP , net .IPv6len )
copy (addr , b [4 :])
e .Address = addr
default :
return errors .New ("dns: bad address family" )
}
return nil
}
func (e *EDNS0_SUBNET ) String () (s string ) {
if e .Address == nil {
s = "<nil>"
} else if e .Address .To4 () != nil {
s = e .Address .String ()
} else {
s = "[" + e .Address .String () + "]"
}
s += "/" + strconv .Itoa (int (e .SourceNetmask )) + "/" + strconv .Itoa (int (e .SourceScope ))
return
}
func (e *EDNS0_SUBNET ) copy () EDNS0 {
return &EDNS0_SUBNET {
e .Code ,
e .Family ,
e .SourceNetmask ,
e .SourceScope ,
e .Address ,
}
}
type EDNS0_COOKIE struct {
Code uint16
Cookie string
}
func (e *EDNS0_COOKIE ) pack () ([]byte , error ) {
h , err := hex .DecodeString (e .Cookie )
if err != nil {
return nil , err
}
return h , nil
}
func (e *EDNS0_COOKIE ) Option () uint16 { return EDNS0COOKIE }
func (e *EDNS0_COOKIE ) unpack (b []byte ) error { e .Cookie = hex .EncodeToString (b ); return nil }
func (e *EDNS0_COOKIE ) String () string { return e .Cookie }
func (e *EDNS0_COOKIE ) copy () EDNS0 { return &EDNS0_COOKIE {e .Code , e .Cookie } }
type EDNS0_UL struct {
Code uint16
Lease uint32
KeyLease uint32
}
func (e *EDNS0_UL ) Option () uint16 { return EDNS0UL }
func (e *EDNS0_UL ) String () string { return fmt .Sprintf ("%d %d" , e .Lease , e .KeyLease ) }
func (e *EDNS0_UL ) copy () EDNS0 { return &EDNS0_UL {e .Code , e .Lease , e .KeyLease } }
func (e *EDNS0_UL ) pack () ([]byte , error ) {
var b []byte
if e .KeyLease == 0 {
b = make ([]byte , 4 )
} else {
b = make ([]byte , 8 )
binary .BigEndian .PutUint32 (b [4 :], e .KeyLease )
}
binary .BigEndian .PutUint32 (b , e .Lease )
return b , nil
}
func (e *EDNS0_UL ) unpack (b []byte ) error {
switch len (b ) {
case 4 :
e .KeyLease = 0
case 8 :
e .KeyLease = binary .BigEndian .Uint32 (b [4 :])
default :
return ErrBuf
}
e .Lease = binary .BigEndian .Uint32 (b )
return nil
}
type EDNS0_LLQ struct {
Code uint16
Version uint16
Opcode uint16
Error uint16
Id uint64
LeaseLife uint32
}
func (e *EDNS0_LLQ ) Option () uint16 { return EDNS0LLQ }
func (e *EDNS0_LLQ ) pack () ([]byte , error ) {
b := make ([]byte , 18 )
binary .BigEndian .PutUint16 (b [0 :], e .Version )
binary .BigEndian .PutUint16 (b [2 :], e .Opcode )
binary .BigEndian .PutUint16 (b [4 :], e .Error )
binary .BigEndian .PutUint64 (b [6 :], e .Id )
binary .BigEndian .PutUint32 (b [14 :], e .LeaseLife )
return b , nil
}
func (e *EDNS0_LLQ ) unpack (b []byte ) error {
if len (b ) < 18 {
return ErrBuf
}
e .Version = binary .BigEndian .Uint16 (b [0 :])
e .Opcode = binary .BigEndian .Uint16 (b [2 :])
e .Error = binary .BigEndian .Uint16 (b [4 :])
e .Id = binary .BigEndian .Uint64 (b [6 :])
e .LeaseLife = binary .BigEndian .Uint32 (b [14 :])
return nil
}
func (e *EDNS0_LLQ ) String () string {
s := strconv .FormatUint (uint64 (e .Version ), 10 ) + " " + strconv .FormatUint (uint64 (e .Opcode ), 10 ) +
" " + strconv .FormatUint (uint64 (e .Error ), 10 ) + " " + strconv .FormatUint (e .Id , 10 ) +
" " + strconv .FormatUint (uint64 (e .LeaseLife ), 10 )
return s
}
func (e *EDNS0_LLQ ) copy () EDNS0 {
return &EDNS0_LLQ {e .Code , e .Version , e .Opcode , e .Error , e .Id , e .LeaseLife }
}
type EDNS0_DAU struct {
Code uint16
AlgCode []uint8
}
func (e *EDNS0_DAU ) Option () uint16 { return EDNS0DAU }
func (e *EDNS0_DAU ) pack () ([]byte , error ) { return cloneSlice (e .AlgCode ), nil }
func (e *EDNS0_DAU ) unpack (b []byte ) error { e .AlgCode = cloneSlice (b ); return nil }
func (e *EDNS0_DAU ) String () string {
s := ""
for _ , alg := range e .AlgCode {
if a , ok := AlgorithmToString [alg ]; ok {
s += " " + a
} else {
s += " " + strconv .Itoa (int (alg ))
}
}
return s
}
func (e *EDNS0_DAU ) copy () EDNS0 { return &EDNS0_DAU {e .Code , e .AlgCode } }
type EDNS0_DHU struct {
Code uint16
AlgCode []uint8
}
func (e *EDNS0_DHU ) Option () uint16 { return EDNS0DHU }
func (e *EDNS0_DHU ) pack () ([]byte , error ) { return cloneSlice (e .AlgCode ), nil }
func (e *EDNS0_DHU ) unpack (b []byte ) error { e .AlgCode = cloneSlice (b ); return nil }
func (e *EDNS0_DHU ) String () string {
s := ""
for _ , alg := range e .AlgCode {
if a , ok := HashToString [alg ]; ok {
s += " " + a
} else {
s += " " + strconv .Itoa (int (alg ))
}
}
return s
}
func (e *EDNS0_DHU ) copy () EDNS0 { return &EDNS0_DHU {e .Code , e .AlgCode } }
type EDNS0_N3U struct {
Code uint16
AlgCode []uint8
}
func (e *EDNS0_N3U ) Option () uint16 { return EDNS0N3U }
func (e *EDNS0_N3U ) pack () ([]byte , error ) { return cloneSlice (e .AlgCode ), nil }
func (e *EDNS0_N3U ) unpack (b []byte ) error { e .AlgCode = cloneSlice (b ); return nil }
func (e *EDNS0_N3U ) String () string {
s := ""
for _ , alg := range e .AlgCode {
if a , ok := HashToString [alg ]; ok {
s += " " + a
} else {
s += " " + strconv .Itoa (int (alg ))
}
}
return s
}
func (e *EDNS0_N3U ) copy () EDNS0 { return &EDNS0_N3U {e .Code , e .AlgCode } }
type EDNS0_EXPIRE struct {
Code uint16
Expire uint32
Empty bool
}
func (e *EDNS0_EXPIRE ) Option () uint16 { return EDNS0EXPIRE }
func (e *EDNS0_EXPIRE ) copy () EDNS0 { return &EDNS0_EXPIRE {e .Code , e .Expire , e .Empty } }
func (e *EDNS0_EXPIRE ) pack () ([]byte , error ) {
if e .Empty {
return []byte {}, nil
}
b := make ([]byte , 4 )
binary .BigEndian .PutUint32 (b , e .Expire )
return b , nil
}
func (e *EDNS0_EXPIRE ) unpack (b []byte ) error {
if len (b ) == 0 {
e .Empty = true
return nil
}
if len (b ) < 4 {
return ErrBuf
}
e .Expire = binary .BigEndian .Uint32 (b )
e .Empty = false
return nil
}
func (e *EDNS0_EXPIRE ) String () (s string ) {
if e .Empty {
return ""
}
return strconv .FormatUint (uint64 (e .Expire ), 10 )
}
type EDNS0_LOCAL struct {
Code uint16
Data []byte
}
func (e *EDNS0_LOCAL ) Option () uint16 { return e .Code }
func (e *EDNS0_LOCAL ) String () string {
return strconv .FormatInt (int64 (e .Code ), 10 ) + ":0x" + hex .EncodeToString (e .Data )
}
func (e *EDNS0_LOCAL ) copy () EDNS0 {
return &EDNS0_LOCAL {e .Code , cloneSlice (e .Data )}
}
func (e *EDNS0_LOCAL ) pack () ([]byte , error ) {
return cloneSlice (e .Data ), nil
}
func (e *EDNS0_LOCAL ) unpack (b []byte ) error {
e .Data = cloneSlice (b )
return nil
}
type EDNS0_TCP_KEEPALIVE struct {
Code uint16
Timeout uint16
Length uint16
}
func (e *EDNS0_TCP_KEEPALIVE ) Option () uint16 { return EDNS0TCPKEEPALIVE }
func (e *EDNS0_TCP_KEEPALIVE ) pack () ([]byte , error ) {
if e .Timeout > 0 {
b := make ([]byte , 2 )
binary .BigEndian .PutUint16 (b , e .Timeout )
return b , nil
}
return nil , nil
}
func (e *EDNS0_TCP_KEEPALIVE ) unpack (b []byte ) error {
switch len (b ) {
case 0 :
case 2 :
e .Timeout = binary .BigEndian .Uint16 (b )
default :
return fmt .Errorf ("dns: length mismatch, want 0/2 but got %d" , len (b ))
}
return nil
}
func (e *EDNS0_TCP_KEEPALIVE ) String () string {
s := "use tcp keep-alive"
if e .Timeout == 0 {
s += ", timeout omitted"
} else {
s += fmt .Sprintf (", timeout %dms" , e .Timeout *100 )
}
return s
}
func (e *EDNS0_TCP_KEEPALIVE ) copy () EDNS0 { return &EDNS0_TCP_KEEPALIVE {e .Code , e .Timeout , e .Length } }
type EDNS0_PADDING struct {
Padding []byte
}
func (e *EDNS0_PADDING ) Option () uint16 { return EDNS0PADDING }
func (e *EDNS0_PADDING ) pack () ([]byte , error ) { return cloneSlice (e .Padding ), nil }
func (e *EDNS0_PADDING ) unpack (b []byte ) error { e .Padding = cloneSlice (b ); return nil }
func (e *EDNS0_PADDING ) String () string { return fmt .Sprintf ("%0X" , e .Padding ) }
func (e *EDNS0_PADDING ) copy () EDNS0 { return &EDNS0_PADDING {cloneSlice (e .Padding )} }
const (
ExtendedErrorCodeOther uint16 = iota
ExtendedErrorCodeUnsupportedDNSKEYAlgorithm
ExtendedErrorCodeUnsupportedDSDigestType
ExtendedErrorCodeStaleAnswer
ExtendedErrorCodeForgedAnswer
ExtendedErrorCodeDNSSECIndeterminate
ExtendedErrorCodeDNSBogus
ExtendedErrorCodeSignatureExpired
ExtendedErrorCodeSignatureNotYetValid
ExtendedErrorCodeDNSKEYMissing
ExtendedErrorCodeRRSIGsMissing
ExtendedErrorCodeNoZoneKeyBitSet
ExtendedErrorCodeNSECMissing
ExtendedErrorCodeCachedError
ExtendedErrorCodeNotReady
ExtendedErrorCodeBlocked
ExtendedErrorCodeCensored
ExtendedErrorCodeFiltered
ExtendedErrorCodeProhibited
ExtendedErrorCodeStaleNXDOMAINAnswer
ExtendedErrorCodeNotAuthoritative
ExtendedErrorCodeNotSupported
ExtendedErrorCodeNoReachableAuthority
ExtendedErrorCodeNetworkError
ExtendedErrorCodeInvalidData
ExtendedErrorCodeSignatureExpiredBeforeValid
ExtendedErrorCodeTooEarly
ExtendedErrorCodeUnsupportedNSEC3IterValue
ExtendedErrorCodeUnableToConformToPolicy
ExtendedErrorCodeSynthesized
ExtendedErrorCodeInvalidQueryType
)
var ExtendedErrorCodeToString = map [uint16 ]string {
ExtendedErrorCodeOther : "Other" ,
ExtendedErrorCodeUnsupportedDNSKEYAlgorithm : "Unsupported DNSKEY Algorithm" ,
ExtendedErrorCodeUnsupportedDSDigestType : "Unsupported DS Digest Type" ,
ExtendedErrorCodeStaleAnswer : "Stale Answer" ,
ExtendedErrorCodeForgedAnswer : "Forged Answer" ,
ExtendedErrorCodeDNSSECIndeterminate : "DNSSEC Indeterminate" ,
ExtendedErrorCodeDNSBogus : "DNSSEC Bogus" ,
ExtendedErrorCodeSignatureExpired : "Signature Expired" ,
ExtendedErrorCodeSignatureNotYetValid : "Signature Not Yet Valid" ,
ExtendedErrorCodeDNSKEYMissing : "DNSKEY Missing" ,
ExtendedErrorCodeRRSIGsMissing : "RRSIGs Missing" ,
ExtendedErrorCodeNoZoneKeyBitSet : "No Zone Key Bit Set" ,
ExtendedErrorCodeNSECMissing : "NSEC Missing" ,
ExtendedErrorCodeCachedError : "Cached Error" ,
ExtendedErrorCodeNotReady : "Not Ready" ,
ExtendedErrorCodeBlocked : "Blocked" ,
ExtendedErrorCodeCensored : "Censored" ,
ExtendedErrorCodeFiltered : "Filtered" ,
ExtendedErrorCodeProhibited : "Prohibited" ,
ExtendedErrorCodeStaleNXDOMAINAnswer : "Stale NXDOMAIN Answer" ,
ExtendedErrorCodeNotAuthoritative : "Not Authoritative" ,
ExtendedErrorCodeNotSupported : "Not Supported" ,
ExtendedErrorCodeNoReachableAuthority : "No Reachable Authority" ,
ExtendedErrorCodeNetworkError : "Network Error" ,
ExtendedErrorCodeInvalidData : "Invalid Data" ,
ExtendedErrorCodeSignatureExpiredBeforeValid : "Signature Expired Before Valid" ,
ExtendedErrorCodeTooEarly : "Too Early" ,
ExtendedErrorCodeUnsupportedNSEC3IterValue : "Unsupported NSEC3 Iterations Value" ,
ExtendedErrorCodeUnableToConformToPolicy : "Unable To Conform To Policy" ,
ExtendedErrorCodeSynthesized : "Synthesized" ,
ExtendedErrorCodeInvalidQueryType : "Invalid Query Type" ,
}
var StringToExtendedErrorCode = reverseInt16 (ExtendedErrorCodeToString )
type EDNS0_EDE struct {
InfoCode uint16
ExtraText string
}
func (e *EDNS0_EDE ) Option () uint16 { return EDNS0EDE }
func (e *EDNS0_EDE ) copy () EDNS0 { return &EDNS0_EDE {e .InfoCode , e .ExtraText } }
func (e *EDNS0_EDE ) String () string {
info := strconv .FormatUint (uint64 (e .InfoCode ), 10 )
if s , ok := ExtendedErrorCodeToString [e .InfoCode ]; ok {
info += fmt .Sprintf (" (%s)" , s )
}
return fmt .Sprintf ("%s: (%s)" , info , e .ExtraText )
}
func (e *EDNS0_EDE ) pack () ([]byte , error ) {
b := make ([]byte , 2 +len (e .ExtraText ))
binary .BigEndian .PutUint16 (b [0 :], e .InfoCode )
copy (b [2 :], e .ExtraText )
return b , nil
}
func (e *EDNS0_EDE ) unpack (b []byte ) error {
if len (b ) < 2 {
return ErrBuf
}
e .InfoCode = binary .BigEndian .Uint16 (b [0 :])
e .ExtraText = string (b [2 :])
return nil
}
type EDNS0_ESU struct {
Code uint16
Uri string
}
func (e *EDNS0_ESU ) Option () uint16 { return EDNS0ESU }
func (e *EDNS0_ESU ) String () string { return e .Uri }
func (e *EDNS0_ESU ) copy () EDNS0 { return &EDNS0_ESU {e .Code , e .Uri } }
func (e *EDNS0_ESU ) pack () ([]byte , error ) { return []byte (e .Uri ), nil }
func (e *EDNS0_ESU ) unpack (b []byte ) error {
e .Uri = string (b )
return nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .