func setupZoneData(data map[string]interface{}, Zone *Zone) { recordTypes := map[string]uint16{ "a": dns.TypeA, "aaaa": dns.TypeAAAA, "alias": dns.TypeMF, "cname": dns.TypeCNAME, "mx": dns.TypeMX, "ns": dns.TypeNS, "txt": dns.TypeTXT, } for dk, dv_inter := range data { dv := dv_inter.(map[string]interface{}) //log.Printf("K %s V %s TYPE-V %T\n", dk, dv, dv) label := Zone.AddLabel(dk) for rType, rdata := range dv { switch rType { case "max_hosts": label.MaxHosts = valueToInt(rdata) continue case "ttl": label.Ttl = valueToInt(rdata) continue } dnsType, ok := recordTypes[rType] if !ok { log.Printf("Unsupported record type '%s'\n", rType) continue } if rdata == nil { //log.Printf("No %s records for label %s\n", rType, dk) continue } //log.Printf("rdata %s TYPE-R %T\n", rdata, rdata) records := make(map[string][]interface{}) switch rdata.(type) { case map[string]interface{}: // Handle NS map syntax, map[ns2.example.net:<nil> ns1.example.net:<nil>] tmp := make([]interface{}, 0) for rdataK, rdataV := range rdata.(map[string]interface{}) { if rdataV == nil { rdataV = "" } tmp = append(tmp, []string{rdataK, rdataV.(string)}) } records[rType] = tmp case string: // CNAME and alias tmp := make([]interface{}, 1) tmp[0] = rdata.(string) records[rType] = tmp default: records[rType] = rdata.([]interface{}) } //log.Printf("RECORDS %s TYPE-REC %T\n", Records, Records) label.Records[dnsType] = make(Records, len(records[rType])) for i := 0; i < len(records[rType]); i++ { //log.Printf("RT %T %#v\n", records[rType][i], records[rType][i]) record := new(Record) var h dns.RR_Header // log.Println("TTL OPTIONS", Zone.Options.Ttl) h.Ttl = uint32(label.Ttl) h.Class = dns.ClassINET h.Rrtype = dnsType h.Name = label.Label + "." + Zone.Origin + "." switch dnsType { case dns.TypeA, dns.TypeAAAA: rec := records[rType][i].([]interface{}) ip := rec[0].(string) var err error if len(rec) > 1 { switch rec[1].(type) { case string: record.Weight, err = strconv.Atoi(rec[1].(string)) if err != nil { panic("Error converting weight to integer") } case float64: record.Weight = int(rec[1].(float64)) } } switch dnsType { case dns.TypeA: if x := net.ParseIP(ip); x != nil { record.RR = &dns.A{Hdr: h, A: x} break } panic(fmt.Errorf("Bad A record %s for %s", ip, dk)) case dns.TypeAAAA: if x := net.ParseIP(ip); x != nil { record.RR = &dns.AAAA{Hdr: h, AAAA: x} break } panic(fmt.Errorf("Bad AAAA record %s for %s", ip, dk)) } case dns.TypeMX: rec := records[rType][i].(map[string]interface{}) pref := uint16(0) mx := rec["mx"].(string) if !strings.HasSuffix(mx, ".") { mx = mx + "." } if rec["weight"] != nil { record.Weight = valueToInt(rec["weight"]) } if rec["preference"] != nil { pref = uint16(valueToInt(rec["preference"])) } record.RR = &dns.MX{ Hdr: h, Mx: mx, Preference: pref} case dns.TypeCNAME: rec := records[rType][i] target := rec.(string) if !dns.IsFqdn(target) { target = target + "." + Zone.Origin } record.RR = &dns.CNAME{Hdr: h, Target: dns.Fqdn(target)} case dns.TypeMF: rec := records[rType][i] // MF records (how we store aliases) are not FQDNs record.RR = &dns.MF{Hdr: h, Mf: rec.(string)} case dns.TypeNS: rec := records[rType][i] if h.Ttl < 86400 { h.Ttl = 86400 } var ns string switch rec.(type) { case string: ns = rec.(string) case []string: recl := rec.([]string) ns = recl[0] if len(recl[1]) > 0 { log.Println("NS records with names syntax not supported") } default: log.Printf("Data: %T %#v\n", rec, rec) panic("Unrecognized NS format/syntax") } rr := &dns.NS{Hdr: h, Ns: dns.Fqdn(ns)} record.RR = rr case dns.TypeTXT: rec := records[rType][i] var txt string switch rec.(type) { case string: txt = rec.(string) case map[string]interface{}: recmap := rec.(map[string]interface{}) if weight, ok := recmap["weight"]; ok { record.Weight = valueToInt(weight) } if t, ok := recmap["txt"]; ok { txt = t.(string) } } if len(txt) > 0 { rr := &dns.TXT{Hdr: h, Txt: []string{txt}} record.RR = rr } else { log.Printf("Zero length txt record for '%s' in '%s'\n", label.Label, Zone.Origin) continue } default: log.Println("type:", rType) panic("Don't know how to handle this type") } if record.RR == nil { panic("record.RR is nil") } label.Weight[dnsType] += record.Weight label.Records[dnsType][i] = *record } if label.Weight[dnsType] > 0 { sort.Sort(RecordsByWeight{label.Records[dnsType]}) } } } setupSOA(Zone) //log.Println(Zones[k]) }
func setupZoneData(data map[string]interface{}, Zone *Zone) { recordTypes := map[string]uint16{ "a": dns.TypeA, "aaaa": dns.TypeAAAA, "alias": dns.TypeMF, "cname": dns.TypeCNAME, "mx": dns.TypeMX, "ns": dns.TypeNS, "txt": dns.TypeTXT, "spf": dns.TypeSPF, "srv": dns.TypeSRV, } for dk, dv_inter := range data { dv := dv_inter.(map[string]interface{}) //log.Printf("K %s V %s TYPE-V %T\n", dk, dv, dv) label := Zone.AddLabel(dk) for rType, rdata := range dv { switch rType { case "max_hosts": label.MaxHosts = valueToInt(rdata) continue case "ttl": label.Ttl = valueToInt(rdata) continue } dnsType, ok := recordTypes[rType] if !ok { log.Printf("Unsupported record type '%s'\n", rType) continue } if rdata == nil { //log.Printf("No %s records for label %s\n", rType, dk) continue } //log.Printf("rdata %s TYPE-R %T\n", rdata, rdata) records := make(map[string][]interface{}) switch rdata.(type) { case map[string]interface{}: // Handle NS map syntax, map[ns2.example.net:<nil> ns1.example.net:<nil>] tmp := make([]interface{}, 0) for rdataK, rdataV := range rdata.(map[string]interface{}) { if rdataV == nil { rdataV = "" } tmp = append(tmp, []string{rdataK, rdataV.(string)}) } records[rType] = tmp case string: // CNAME and alias tmp := make([]interface{}, 1) tmp[0] = rdata.(string) records[rType] = tmp default: records[rType] = rdata.([]interface{}) } //log.Printf("RECORDS %s TYPE-REC %T\n", Records, Records) label.Records[dnsType] = make(Records, len(records[rType])) for i := 0; i < len(records[rType]); i++ { //log.Printf("RT %T %#v\n", records[rType][i], records[rType][i]) record := new(Record) var h dns.RR_Header // log.Println("TTL OPTIONS", Zone.Options.Ttl) h.Ttl = uint32(label.Ttl) h.Class = dns.ClassINET h.Rrtype = dnsType switch len(label.Label) { case 0: h.Name = Zone.Origin + "." default: h.Name = label.Label + "." + Zone.Origin + "." } switch dnsType { case dns.TypeA, dns.TypeAAAA: str, weight := getStringWeight(records[rType][i].([]interface{})) ip := str record.Weight = weight switch dnsType { case dns.TypeA: if x := net.ParseIP(ip); x != nil { record.RR = &dns.A{Hdr: h, A: x} break } panic(fmt.Errorf("Bad A record %s for %s", ip, dk)) case dns.TypeAAAA: if x := net.ParseIP(ip); x != nil { record.RR = &dns.AAAA{Hdr: h, AAAA: x} break } panic(fmt.Errorf("Bad AAAA record %s for %s", ip, dk)) } case dns.TypeMX: rec := records[rType][i].(map[string]interface{}) pref := uint16(0) mx := rec["mx"].(string) if !strings.HasSuffix(mx, ".") { mx = mx + "." } if rec["weight"] != nil { record.Weight = valueToInt(rec["weight"]) } if rec["preference"] != nil { pref = uint16(valueToInt(rec["preference"])) } record.RR = &dns.MX{ Hdr: h, Mx: mx, Preference: pref} case dns.TypeSRV: rec := records[rType][i].(map[string]interface{}) priority := uint16(0) srv_weight := uint16(0) port := uint16(0) target := rec["target"].(string) if !dns.IsFqdn(target) { target = target + "." + Zone.Origin } if rec["srv_weight"] != nil { srv_weight = uint16(valueToInt(rec["srv_weight"])) } if rec["port"] != nil { port = uint16(valueToInt(rec["port"])) } if rec["priority"] != nil { priority = uint16(valueToInt(rec["priority"])) } record.RR = &dns.SRV{ Hdr: h, Priority: priority, Weight: srv_weight, Port: port, Target: target} case dns.TypeCNAME: rec := records[rType][i] var target string var weight int switch rec.(type) { case string: target = rec.(string) case []interface{}: target, weight = getStringWeight(rec.([]interface{})) } if !dns.IsFqdn(target) { target = target + "." + Zone.Origin } record.Weight = weight record.RR = &dns.CNAME{Hdr: h, Target: dns.Fqdn(target)} case dns.TypeMF: rec := records[rType][i] // MF records (how we store aliases) are not FQDNs record.RR = &dns.MF{Hdr: h, Mf: rec.(string)} case dns.TypeNS: rec := records[rType][i] if h.Ttl < 86400 { h.Ttl = 86400 } var ns string switch rec.(type) { case string: ns = rec.(string) case []string: recl := rec.([]string) ns = recl[0] if len(recl[1]) > 0 { log.Println("NS records with names syntax not supported") } default: log.Printf("Data: %T %#v\n", rec, rec) panic("Unrecognized NS format/syntax") } rr := &dns.NS{Hdr: h, Ns: dns.Fqdn(ns)} record.RR = rr case dns.TypeTXT: rec := records[rType][i] var txt string switch rec.(type) { case string: txt = rec.(string) case map[string]interface{}: recmap := rec.(map[string]interface{}) if weight, ok := recmap["weight"]; ok { record.Weight = valueToInt(weight) } if t, ok := recmap["txt"]; ok { txt = t.(string) } } if len(txt) > 0 { rr := &dns.TXT{Hdr: h, Txt: []string{txt}} record.RR = rr } else { log.Printf("Zero length txt record for '%s' in '%s'\n", label.Label, Zone.Origin) continue } // Initial SPF support added here, cribbed from the TypeTXT case definition - SPF records should be handled identically case dns.TypeSPF: rec := records[rType][i] var spf string switch rec.(type) { case string: spf = rec.(string) case map[string]interface{}: recmap := rec.(map[string]interface{}) if weight, ok := recmap["weight"]; ok { record.Weight = valueToInt(weight) } if t, ok := recmap["spf"]; ok { spf = t.(string) } } if len(spf) > 0 { rr := &dns.SPF{Hdr: h, Txt: []string{spf}} record.RR = rr } else { log.Printf("Zero length SPF record for '%s' in '%s'\n", label.Label, Zone.Origin) continue } default: log.Println("type:", rType) panic("Don't know how to handle this type") } if record.RR == nil { panic("record.RR is nil") } label.Weight[dnsType] += record.Weight label.Records[dnsType][i] = *record } if label.Weight[dnsType] > 0 { sort.Sort(RecordsByWeight{label.Records[dnsType]}) } } } // loop over exisiting labels, create zone records for missing sub-domains for k := range Zone.Labels { if strings.Contains(k, ".") { subLabels := strings.Split(k, ".") for i := 1; i < len(subLabels); i++ { subSubLabel := strings.Join(subLabels[i:len(subLabels)], ".") if _, ok := Zone.Labels[subSubLabel]; !ok { Zone.AddLabel(subSubLabel) } } } } setupSOA(Zone) //log.Println(Zones[k]) }