123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- package main
- import (
- "github.com/abh/geodns/countries"
- "github.com/miekg/dns"
- )
- type Options struct {
- Serial int
- Ttl int
- MaxHosts int
- Contact string
- }
- type Record struct {
- RR dns.RR
- Weight int
- }
- type Records []Record
- func (s Records) Len() int { return len(s) }
- func (s Records) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
- type RecordsByWeight struct{ Records }
- func (s RecordsByWeight) Less(i, j int) bool { return s.Records[i].Weight > s.Records[j].Weight }
- type Label struct {
- Label string
- MaxHosts int
- Ttl int
- Records map[uint16]Records
- Weight map[uint16]int
- }
- type labels map[string]*Label
- type Zones map[string]*Zone
- type Zone struct {
- Origin string
- Labels labels
- LenLabels int
- Options Options
- }
- func (l *Label) firstRR(dnsType uint16) dns.RR {
- return l.Records[dnsType][0].RR
- }
- func (z *Zone) SoaRR() dns.RR {
- return z.Labels[""].firstRR(dns.TypeSOA)
- }
- func (z *Zone) findLabels(s, cc string, qtype uint16) *Label {
- if qtype == dns.TypeANY {
- // short-circuit mostly to avoid subtle bugs later
- // to be correct we should run through all the selectors and
- // pick types not already picked
- return z.Labels[s]
- }
- selectors := []string{}
- if len(cc) > 0 {
- continent := countries.CountryContinent[cc]
- if len(s) > 0 {
- cc = s + "." + cc
- if len(continent) > 0 {
- continent = s + "." + continent
- }
- }
- selectors = append(selectors, cc, continent)
- }
- selectors = append(selectors, s)
- for _, name := range selectors {
- if label, ok := z.Labels[name]; ok {
- // look for aliases
- if label.Records[dns.TypeMF] != nil {
- name = label.firstRR(dns.TypeMF).(*dns.MF).Mf
- // BUG(ask) - restructure this so it supports chains of aliases
- label, ok = z.Labels[name]
- if label == nil {
- continue
- }
- }
- // return the label if it has the right records
- // TODO(ask) Should this also look for CNAME records?
- if label.Records[qtype] != nil && len(label.Records[qtype]) > 0 {
- return label
- }
- }
- }
- return z.Labels[s]
- }
|