// ParseZone will attempt to parse a zone file from the provided filename and return a Zone. // ParseZone will return an error if the file provided does not exist or could not be properly parsed. func ParseZone(filename string) (*Zone, error) { var zone *Zone var err error zone = &Zone{ records: make([]dns.RR, 0), } // Open the file var file *os.File file, err = os.Open(filename) if err != nil { return nil, fmt.Errorf("could not parse zone file \"%s\": \"%s\"", filename, err) } defer file.Close() // Parse the file into records var tokens chan *dns.Token tokens = dns.ParseZone(file, "", "") for token := range tokens { if token.Error != nil { return nil, fmt.Errorf("could not parse zone file \"%s\": \"%s\"", filename, token.Error) } zone.records = append(zone.records, token.RR) } return zone, nil }
func parseBindFile(reader io.Reader, filename, origin string) []dns.RR { tokensch := dns.ParseZone(reader, origin, filename) records := []dns.RR{} for token := range tokensch { if token.Error != nil { fatalIfErr(token.Error) } record := parseComment(token.RR, token.Comment) records = append(records, record) } return records }
func init() { rootCache = newCache(strings.Count(root, "\n")) for t := range dns.ParseZone(strings.NewReader(root), "", "") { if t.Error != nil { continue } rr, ok := convertRR(t.RR) if ok { rootCache.add(rr.Name, rr) } } }
func parseBindFile(file, origin string) []dns.RR { rdr, err := os.Open(file) fatalIfErr(err) tokensch := dns.ParseZone(rdr, origin, file) records := []dns.RR{} for token := range tokensch { if token.Error != nil { fatalIfErr(token.Error) } record := parseComment(token.RR, token.Comment) records = append(records, record) } return records }
func TestPrivateZoneParser(t *testing.T) { dns.PrivateHandle("ISBN", TypeISBN, NewISBN) dns.PrivateHandle("VERSION", TypeVERSION, NewVersion) defer dns.PrivateHandleRemove(TypeISBN) defer dns.PrivateHandleRemove(TypeVERSION) r := strings.NewReader(smallzone) for x := range dns.ParseZone(r, ".", "") { if err := x.Error; err != nil { t.Fatal(err) } t.Log(x.RR) } }
// Parse parses the zone in filename and returns a new Zone or an error. func Parse(f io.Reader, origin, fileName string) (*Zone, error) { tokens := dns.ParseZone(f, dns.Fqdn(origin), fileName) z := NewZone(origin, fileName) for x := range tokens { if x.Error != nil { log.Printf("[ERROR] Failed to parse `%s': %v", origin, x.Error) return nil, x.Error } if err := z.Insert(x.RR); err != nil { return nil, err } } return z, nil }
func main() { zone := `$ORIGIN . $TTL 3600 ; 1 hour name IN SOA a6.nstld.com. hostmaster.nic.name. ( 203362132 ; serial 300 ; refresh (5 minutes) 300 ; retry (5 minutes) 1209600 ; expire (2 weeks) 300 ; minimum (5 minutes) ) $TTL 10800 ; 3 hours name. 10800 IN NS name. IN NS g6.nstld.com. 7200 NS h6.nstld.com. 3600 IN NS j6.nstld.com. IN 3600 NS k6.nstld.com. NS l6.nstld.com. NS a6.nstld.com. NS c6.nstld.com. NS d6.nstld.com. NS f6.nstld.com. NS m6.nstld.com. ( NS m7.nstld.com. ) $ORIGIN name. 0-0onlus NS ns7.ehiweb.it. NS ns8.ehiweb.it. 0-g MX 10 mx01.nic MX 10 mx02.nic MX 10 mx03.nic MX 10 mx04.nic $ORIGIN 0-g.name moutamassey NS ns01.yahoodomains.jp. NS ns02.yahoodomains.jp. ` for x := range dns.ParseZone(strings.NewReader(zone), "", "") { if x.Error != nil { fmt.Println(x.Error) } else { // Do something with x.RR fmt.Println(x.RR) fmt.Println(x.RR.Header()) fmt.Printf("Name:%s, Type:%s,Class:%s,RDLen:%d,TTL:%d\n ", x.Header().Name, dns.TypeToString[x.Header().Rrtype], dns.ClassToString[x.Header().Class], x.Header().Rdlength, x.Header().Ttl) } } }
func (c *config) loadZones(zones map[string]string) error { for n, f := range zones { c.debug(fmt.Sprintf("Parsing zone %s", n)) z := zone{name: n, rrs: []dns.RR{}} for t := range dns.ParseZone(strings.NewReader(f), n, n) { if t.Error != nil { log.Fatalf("Error parsing zone %s: %s", n, t.Error) } z.rrs = append(z.rrs, t.RR) } dns.HandleFunc(n, func(w dns.ResponseWriter, req *dns.Msg) { z.zoneHandler(c, w, req) }) c.debug(fmt.Sprintf("Registered handler for zone %s", n)) } return nil }
// ReadZoneFile reads a zone and adds it. func (c *Config) ReadZoneFile(origin, file string) error { f, e := os.Open(file) if e != nil { return e } z := dns.NewZone(origin) for rr := range dns.ParseZone(f, origin, file) { if rr.Error == nil { if e := z.Insert(rr.RR); e != nil { logPrintf("failed to insert record: %s\n", e.Error()) } } else { logPrintf("failed to parse: %s\n", rr.Error.Error()) } } c.Zones[origin] = z dns.HandleFunc(origin, func(w dns.ResponseWriter, req *dns.Msg) { serve(w, req, c.Zones[origin]) }) return nil }
func FetchRootZone(zones map[string]*Zone, addNew bool) error { res, err := Fetch(rootZoneURL) if err != nil { return err } defer res.Body.Close() color.Fprintf(os.Stderr, "@{.}Parsing %s\n", rootZoneURL) for token := range dns.ParseZone(res.Body, "", "") { if token.Error != nil { continue } h := token.RR.Header() if h.Rrtype != dns.TypeNS { continue } d := Normalize(h.Name) if d == "" { continue } // Identify the zone z := zones[d] if z == nil { if !addNew { continue } color.Fprintf(os.Stderr, "@{g}New domain: %s\n", d) z = &Zone{Domain: d} zones[d] = z } // Extract name server if ns, ok := token.RR.(*dns.NS); ok { if verifyNS(ns.Ns) == nil { z.NameServers = append(z.NameServers, Normalize(ns.Ns)) } } } return nil }
func main() { header := `------------------------------------------------------------------------------- StatZone (c) by Frederic Cambus 2012-2016 -------------------------------------------------------------------------------` fmt.Println(header + "\n") /* Check input parameters and show usage */ if len(os.Args) != 2 { fmt.Println("USAGE: statzone inputfile\n") fmt.Println("EXAMPLES: statzone arpa.zone\n") os.Exit(1) } inputFile := os.Args[1] fmt.Println("Parsing zone :", inputFile) domains := new(Domains) ns := map[string]int{} signed := map[string]int{} zoneFile, err := os.Open(inputFile) if err != nil { fmt.Println("ERROR : Can't open zone file.") } zone := dns.ParseZone(bufio.NewReader(zoneFile), "", "") var rrtypes [100]int for parsedLine := range zone { if parsedLine.RR != nil { rrtypes[parsedLine.RR.Header().Rrtype]++ switch parsedLine.RR.Header().Rrtype { case dns.TypeDS: /* Increment Signed Domains counter */ signed[parsedLine.RR.Header().Name]++ case dns.TypeNS: /* Increment NS counter */ ns[rdata(parsedLine)]++ if parsedLine.RR.Header().Name != domains.previous { // Unique domain /* Increment Domain counter */ domains.count++ domains.previous = parsedLine.RR.Header().Name /* Check if the domain is an IDN */ if strings.HasPrefix(strings.ToLower(parsedLine.RR.Header().Name), "xn--") { domains.idn++ } /* Display progression */ if domains.count%1000000 == 0 { fmt.Printf("*") } else if domains.count%100000 == 0 { fmt.Printf(".") } } } } else { fmt.Println("ERROR : A problem occured while parsing the zone file.") } /* Increment number of resource records parsed */ rrParsed++ } /* Don't count origin */ domains.count-- fmt.Println("\n---[ Parsing results ]---------------------------------------------------------\n") fmt.Println(rrParsed, "RRs parsed.") for loop := 0; loop < len(rrtypes); loop++ { rrtype := rrtypes[loop] if rrtype != 0 { fmt.Println(dns.TypeToString[uint16(loop)], "records :", rrtype) } } fmt.Println("\n---[ Results ]-----------------------------------------------------------------\n") fmt.Println("Domains : ", domains.count) fmt.Println("DNSSEC Signed : ", len(signed)) fmt.Println("IDNs : ", domains.idn) fmt.Println("NS : ", len(ns)) fmt.Println("\n---[ Creating result files ]---------------------------------------------------\n") /* Creating name servers list + number of zones served */ fmt.Println("Creating :", inputFile+".csv") outputFile, outputError := os.OpenFile(inputFile+".csv", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if outputError != nil { fmt.Printf("ERROR : Can't create output file.\n") return } defer outputFile.Close() outputWriter := bufio.NewWriter(outputFile) for item := range ns { outputWriter.WriteString(strings.ToLower(strings.TrimRight(item, ".")) + ";" + strconv.Itoa(ns[item]) + "\n") } outputWriter.Flush() fmt.Println("\n---[ CSV values ]--------------------------------------------------------------\n") fmt.Println("IPv4 Glue ; IPv6 Glue ; NS ; Unique NS ; DS ; Signed ; IDNs ; Domains") fmt.Println(rrtypes[dns.TypeA], ";", rrtypes[dns.TypeAAAA], ";", rrtypes[dns.TypeNS], ";", len(ns), ";", rrtypes[dns.TypeDS], ";", len(signed), ";", domains.idn, ";", domains.count) }
func main() { bytes, err := ioutil.ReadFile(*zoneFile) if err != nil { log.Panic(err) } zone := string(bytes) reader := strings.NewReader(zone) records := make(map[RecordKey]*TerraformRecord) for rr := range dns.ParseZone(reader, *domain, *zoneFile) { if rr.Error != nil { log.Printf("Error: %v\n", rr.Error) } else { header := rr.Header() recordType := dns.Type(header.Rrtype).String() isExcluded, ok := excludedTypes[recordType] if ok && isExcluded { continue } name := strings.ToLower(header.Name) data := strings.TrimPrefix(rr.String(), header.String()) if recordType == "CNAME" { data = strings.ToLower(data) } key := RecordKey{ Name: name, Type: recordType, } if rec, ok := records[key]; ok { rec.Data = append(rec.Data, data) if rr.Comment != "" { rec.Comments = append(rec.Comments, strings.TrimLeft(rr.Comment, ";")) } } else { comments := make([]string, 0) if rr.Comment != "" { comments = append(comments, strings.TrimLeft(rr.Comment, ";")) } records[key] = &TerraformRecord{ Name: key.Name, Type: key.Type, Ttl: header.Ttl, Data: []string{data}, Comments: comments, } } } } zoneName := strings.TrimRight(*domain, ".") ZoneTemplateData := ZoneTemplateData{ Id: strings.Replace(zoneName, ".", "-", -1), Domain: zoneName, } terraformZone := template.Must(template.New("zone").Parse(zoneTemplate)) terraformZone.Execute(os.Stdout, ZoneTemplateData) resource := template.Must(template.New("resource").Funcs(template.FuncMap{"ensureQuoted": ensureQuoted}).Parse(recordTemplate)) recordKeys := make(RecordKeySlice, 0, len(records)) for key, _ := range records { recordKeys = append(recordKeys, key) } sort.Sort(sort.Reverse(recordKeys)) for _, key := range recordKeys { rec := records[key] hyphenatedName := strings.Replace(strings.TrimRight(rec.Name, "."), ".", "-", -1) wildcardCleanedName := strings.Replace(hyphenatedName, "*", "wildcard", -1) id := fmt.Sprintf("%s-%s", wildcardCleanedName, rec.Type) info := RecordTemplateData{ ResourceId: id, Record: rec, Zone: ZoneTemplateData, } resource.Execute(os.Stdout, info) } }