2011-07-21 22:32:02 +10:00
|
|
|
package dns
|
|
|
|
|
|
|
|
// Parse RRs
|
|
|
|
// With the thankful help of gdnsd and the Go examples for Ragel.
|
|
|
|
//
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"io"
|
|
|
|
"net"
|
2011-07-22 20:26:31 +10:00
|
|
|
"strings"
|
2011-07-21 22:32:02 +10:00
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
|
|
|
const _IOBUF = 65365
|
|
|
|
|
2011-07-22 20:26:31 +10:00
|
|
|
// Return the rdata fields as a slice. All starting whitespace deleted
|
|
|
|
func fields(s string, i int) (rdf []string) {
|
|
|
|
rdf = strings.Split(strings.TrimSpace(s), " ", i)
|
|
|
|
for i, _ := range rdf {
|
|
|
|
rdf[i] = strings.TrimSpace(rdf[i])
|
|
|
|
}
|
|
|
|
if len(rdf) != i {
|
|
|
|
panic("not enough rdata seen")
|
|
|
|
}
|
|
|
|
return
|
2011-07-21 22:32:02 +10:00
|
|
|
}
|
|
|
|
|
2011-07-22 20:26:31 +10:00
|
|
|
func atoi(s string) int {
|
|
|
|
i, err := strconv.Atoi(s)
|
|
|
|
if err != nil {
|
|
|
|
panic("not a number")
|
|
|
|
}
|
|
|
|
return i
|
2011-07-21 22:32:02 +10:00
|
|
|
}
|
2011-07-21 22:33:17 +10:00
|
|
|
|
2011-07-22 20:26:31 +10:00
|
|
|
/*
|
2011-07-21 22:32:02 +10:00
|
|
|
func rdata_ds(hdr RR_Header, tok *token) RR {
|
|
|
|
rr := new(RR_DS)
|
|
|
|
rr.Hdr = hdr;
|
|
|
|
rr.Hdr.Rrtype = TypeDS
|
|
|
|
rr.KeyTag = uint16(tok.N[0])
|
|
|
|
rr.Algorithm = uint8(tok.N[1])
|
|
|
|
rr.DigestType = uint8(tok.N[2])
|
|
|
|
rr.Digest = tok.T[0]
|
|
|
|
return rr
|
|
|
|
}
|
|
|
|
func rdata_dnskey(hdr RR_Header, tok *token) RR {
|
|
|
|
rr := new(RR_DNSKEY)
|
|
|
|
rr.Hdr = hdr;
|
|
|
|
rr.Hdr.Rrtype = TypeDNSKEY
|
|
|
|
rr.Flags = uint16(tok.N[0])
|
|
|
|
rr.Protocol = uint8(tok.N[1])
|
|
|
|
rr.Algorithm = uint8(tok.N[2])
|
|
|
|
rr.PublicKey = tok.T[0]
|
|
|
|
return rr
|
|
|
|
}
|
|
|
|
func rdata_rrsig(hdr RR_Header, tok *token) RR {
|
|
|
|
rr := new(RR_RRSIG)
|
|
|
|
rr.Hdr = hdr;
|
|
|
|
rr.Hdr.Rrtype = TypeRRSIG
|
|
|
|
rr.TypeCovered = uint16(tok.N[0])
|
|
|
|
rr.Algorithm = uint8(tok.N[1])
|
|
|
|
rr.Labels = uint8(tok.N[2])
|
|
|
|
rr.OrigTtl = uint32(tok.N[3])
|
|
|
|
rr.Expiration = uint32(tok.N[4])
|
|
|
|
rr.Inception = uint32(tok.N[5])
|
|
|
|
rr.KeyTag = uint16(tok.N[6])
|
|
|
|
rr.SignerName = tok.T[0]
|
|
|
|
rr.Signature = tok.T[1]
|
|
|
|
return rr
|
|
|
|
}
|
2011-07-22 20:26:31 +10:00
|
|
|
*/
|
2011-07-21 22:32:02 +10:00
|
|
|
|
|
|
|
%%{
|
|
|
|
machine z;
|
|
|
|
write data;
|
|
|
|
}%%
|
|
|
|
|
|
|
|
// SetString
|
|
|
|
// All the NewReader stuff is expensive...
|
|
|
|
// only works for short io.Readers as we put the whole thing
|
|
|
|
// in a string -- needs to be extended for large files (sliding window).
|
|
|
|
func Zparse(q io.Reader) (z *Zone, err os.Error) {
|
|
|
|
buf := make([]byte, _IOBUF)
|
|
|
|
n, err := q.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
buf = buf[:n]
|
|
|
|
z = new(Zone)
|
|
|
|
|
|
|
|
data := string(buf)
|
|
|
|
cs, p, pe := 0, 0, len(data)
|
|
|
|
eof := len(data)
|
|
|
|
|
2011-07-22 20:26:31 +10:00
|
|
|
// brace := false
|
2011-07-21 22:32:02 +10:00
|
|
|
lines := 0
|
|
|
|
mark := 0
|
|
|
|
hdr := new(RR_Header)
|
|
|
|
|
|
|
|
%%{
|
|
|
|
action mark { mark = p }
|
2011-07-22 20:26:31 +10:00
|
|
|
action setQname { hdr.Name = data[mark:p] }
|
|
|
|
action setQclass { hdr.Class = Str_class[data[mark:p]] }
|
2011-07-21 22:32:02 +10:00
|
|
|
action defTtl { /* ... */ }
|
|
|
|
action setTtl { ttl, _ := strconv.Atoi(data[mark:p]); hdr.Ttl = uint32(ttl) }
|
2011-07-22 20:26:31 +10:00
|
|
|
action lineCount { lines++ }
|
2011-07-21 22:32:02 +10:00
|
|
|
|
2011-07-22 20:26:31 +10:00
|
|
|
# action openBrace { if brace { println("Brace already open")} ; brace = true }
|
|
|
|
# action closeBrace { if !brace { println("Brace already closed")}; brace = false }
|
|
|
|
# action brace { brace }
|
2011-07-21 22:32:02 +10:00
|
|
|
|
2011-07-22 20:26:31 +10:00
|
|
|
include "types.rl";
|
2011-07-21 22:32:02 +10:00
|
|
|
|
2011-07-22 20:26:31 +10:00
|
|
|
nl = [\n]+ $lineCount;
|
|
|
|
comment = ';' [^\n]*;
|
|
|
|
ttl = digit+;
|
|
|
|
# bl = ( [ \t]+
|
|
|
|
# | '(' $openBrace
|
|
|
|
# | ')' $closeBrace
|
|
|
|
# | (comment? nl)+ when brace
|
|
|
|
# )+ %mark;
|
|
|
|
bl = [ \t]+;
|
|
|
|
|
|
|
|
# rdata = [a-zA-Z0-9.]+ >mark;
|
|
|
|
rdata = [^\n]+ >mark;
|
|
|
|
qname = [a-zA-Z0-9.\-_]+ >mark %setQname;
|
|
|
|
qclass = ('IN'i|'CH'i|'HS'i) >mark %setQclass;
|
2011-07-21 22:32:02 +10:00
|
|
|
|
|
|
|
lhs = qname? bl %defTtl (
|
|
|
|
(ttl %setTtl bl (qclass bl)?)
|
|
|
|
| (qclass bl (ttl %setTtl bl)?)
|
|
|
|
)?;
|
|
|
|
|
2011-07-22 20:26:31 +10:00
|
|
|
rhs = (
|
|
|
|
( 'A'i rdata ) %setA
|
|
|
|
| ( 'AAAA'i rdata ) %setAAAA
|
|
|
|
| ( 'SOA'i rdata ) %setSOA
|
|
|
|
| ( 'CNAME'i rdata ) %setCNAME
|
|
|
|
| ( 'NS'i rdata ) %setNS
|
|
|
|
| ( 'MX'i rdata ) %setMX
|
|
|
|
);
|
|
|
|
|
|
|
|
rr = lhs rhs;
|
|
|
|
# main := (rr? bl? ((comment? nl) when !brace))*;
|
|
|
|
main := (rr? nl)*;
|
2011-07-21 22:32:02 +10:00
|
|
|
|
|
|
|
write init;
|
|
|
|
write exec;
|
|
|
|
}%%
|
|
|
|
|
|
|
|
if eof > -1 {
|
|
|
|
if cs < z_first_final {
|
|
|
|
// No clue what I'm doing what so ever
|
|
|
|
if p == pe {
|
|
|
|
println("unexpected eof")
|
|
|
|
return z, nil
|
|
|
|
} else {
|
|
|
|
println("error at position ", p, "\"",data[mark:p],"\"")
|
|
|
|
return z, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return z, nil
|
|
|
|
}
|