Beispiel #1
0
// 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
}
Beispiel #2
0
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)
		}
	}
}
Beispiel #4
0
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
}
Beispiel #5
0
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)
	}
}
Beispiel #6
0
// 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)
		}
	}
}
Beispiel #8
0
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
}
Beispiel #9
0
// 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
}
Beispiel #10
0
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
}
Beispiel #11
0
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)
}
Beispiel #12
0
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)
	}
}