2014-09-19 13:04:53 +10:00
package dns
2014-09-19 23:40:24 +10:00
import (
"strings"
)
// PrivateRData is an interface to implement non-RFC dictated resource records. See also dns.PrivateRR, dns.RegisterPrivateRR and dns.UnregisterPrivateRR
type PrivateRData interface {
2014-09-19 13:04:53 +10:00
String ( ) string
ReadText ( [ ] string ) error
Write ( [ ] byte ) ( int , error )
Read ( [ ] byte ) ( int , error )
2014-09-19 23:40:24 +10:00
CopyTo ( PrivateRData ) error
RdataLen ( ) int
2014-09-19 13:04:53 +10:00
}
2014-09-19 23:40:24 +10:00
// PrivateRR represents RR that uses PrivateRData user-defined type. It mocks normal RRs and implements dns.RR interface.
type PrivateRR struct {
2014-09-19 13:04:53 +10:00
Hdr RR_Header
2014-09-19 23:40:24 +10:00
Data PrivateRData
2014-09-19 13:04:53 +10:00
}
2014-09-19 23:40:24 +10:00
// Header returns Private RR header.
func ( r * PrivateRR ) Header ( ) * RR_Header { return & r . Hdr }
// String returns text representation of a Private Resource Record.
func ( r * PrivateRR ) String ( ) string { return r . Hdr . String ( ) + r . Data . String ( ) }
// Private len and copy parts to satisfy RR interface.
func ( r * PrivateRR ) len ( ) int { return r . Hdr . len ( ) + r . Data . RdataLen ( ) }
func ( r * PrivateRR ) copy ( ) RR {
2014-09-19 13:04:53 +10:00
// make new RR like this:
rrfunc , ok := typeToRR [ r . Hdr . Rrtype ]
if ! ok {
2014-09-19 23:40:24 +10:00
panic ( "dns: invalid operation with Private RR " + r . Hdr . String ( ) )
2014-09-19 13:04:53 +10:00
}
rr := rrfunc ( )
r . Header ( ) . CopyTo ( rr )
2014-09-19 23:40:24 +10:00
rrcust , ok := rr . ( * PrivateRR )
2014-09-19 13:04:53 +10:00
if ! ok {
2014-09-19 23:40:24 +10:00
panic ( "dns: Private RR generator returned wrong interface value" )
2014-09-19 13:04:53 +10:00
}
err := r . Data . CopyTo ( rrcust . Data )
if err != nil {
2014-09-19 23:40:24 +10:00
panic ( "dns: got value that could not be used to copy Private rdata" )
2014-09-19 13:04:53 +10:00
}
return rr
}
2014-09-19 23:40:24 +10:00
// RegisterPrivateRR adds support for user-defined resource record type to internals of dns library. Requires
// string and numeric representation of RR type and generator function as argument.
func RegisterPrivateRR ( rtypestr string , rtype uint16 , generator func ( ) PrivateRData ) {
rtypestr = strings . ToUpper ( rtypestr )
2014-09-19 13:04:53 +10:00
2014-09-19 23:40:24 +10:00
typeToRR [ rtype ] = func ( ) RR { return & PrivateRR { RR_Header { } , generator ( ) } }
2014-09-19 13:04:53 +10:00
TypeToString [ rtype ] = rtypestr
StringToType [ rtypestr ] = rtype
2014-09-19 23:40:24 +10:00
setPrivateRR := func ( h RR_Header , c chan lex , o , f string ) ( RR , * ParseError , string ) {
2014-09-19 13:04:53 +10:00
rrfunc := typeToRR [ h . Rrtype ]
2014-09-19 23:40:24 +10:00
rr , ok := rrfunc ( ) . ( * PrivateRR )
2014-09-19 13:04:53 +10:00
if ! ok {
2014-09-19 23:40:24 +10:00
panic ( "dns: invalid handler registered for Private RR " + rtypestr )
2014-09-19 13:04:53 +10:00
}
h . CopyTo ( rr )
var l lex
text := make ( [ ] string , 0 )
for end := false ; ! end ; {
switch l = <- c ; l . value {
case _NEWLINE , _EOF :
end = true
case _STRING :
text = append ( text , l . token )
case _BLANK :
continue
}
}
err := rr . Data . ReadText ( text )
if err != nil {
return nil , & ParseError { f , err . Error ( ) , l } , ""
}
return rr , nil , ""
}
2014-09-19 23:40:24 +10:00
typeToparserFunc [ rtype ] = parserFunc { setPrivateRR , false }
2014-09-19 13:04:53 +10:00
}
2014-09-19 23:40:24 +10:00
// UnregisterPrivateRR removes defenitions required to support user RR type.
func UnregisterPrivateRR ( rtype uint16 ) {
2014-09-19 13:04:53 +10:00
rtypestr , ok := TypeToString [ rtype ]
if ok {
delete ( typeToRR , rtype )
delete ( TypeToString , rtype )
delete ( typeToparserFunc , rtype )
delete ( StringToType , rtypestr )
}
return
}