types.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package main
  2. import (
  3. "github.com/abh/geodns/countries"
  4. "github.com/miekg/dns"
  5. )
  6. type Options struct {
  7. Serial int
  8. Ttl int
  9. MaxHosts int
  10. Contact string
  11. }
  12. type Record struct {
  13. RR dns.RR
  14. Weight int
  15. }
  16. type Records []Record
  17. func (s Records) Len() int { return len(s) }
  18. func (s Records) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  19. type RecordsByWeight struct{ Records }
  20. func (s RecordsByWeight) Less(i, j int) bool { return s.Records[i].Weight > s.Records[j].Weight }
  21. type Label struct {
  22. Label string
  23. MaxHosts int
  24. Ttl int
  25. Records map[uint16]Records
  26. Weight map[uint16]int
  27. }
  28. type labels map[string]*Label
  29. type Zones map[string]*Zone
  30. type Zone struct {
  31. Origin string
  32. Labels labels
  33. LenLabels int
  34. Options Options
  35. }
  36. func (l *Label) firstRR(dnsType uint16) dns.RR {
  37. return l.Records[dnsType][0].RR
  38. }
  39. func (z *Zone) SoaRR() dns.RR {
  40. return z.Labels[""].firstRR(dns.TypeSOA)
  41. }
  42. func (z *Zone) findLabels(s, cc string, qtype uint16) *Label {
  43. if qtype == dns.TypeANY {
  44. // short-circuit mostly to avoid subtle bugs later
  45. // to be correct we should run through all the selectors and
  46. // pick types not already picked
  47. return z.Labels[s]
  48. }
  49. selectors := []string{}
  50. if len(cc) > 0 {
  51. continent := countries.CountryContinent[cc]
  52. if len(s) > 0 {
  53. cc = s + "." + cc
  54. if len(continent) > 0 {
  55. continent = s + "." + continent
  56. }
  57. }
  58. selectors = append(selectors, cc, continent)
  59. }
  60. selectors = append(selectors, s)
  61. for _, name := range selectors {
  62. if label, ok := z.Labels[name]; ok {
  63. // look for aliases
  64. if label.Records[dns.TypeMF] != nil {
  65. name = label.firstRR(dns.TypeMF).(*dns.MF).Mf
  66. // BUG(ask) - restructure this so it supports chains of aliases
  67. label, ok = z.Labels[name]
  68. if label == nil {
  69. continue
  70. }
  71. }
  72. // return the label if it has the right records
  73. // TODO(ask) Should this also look for CNAME records?
  74. if label.Records[qtype] != nil && len(label.Records[qtype]) > 0 {
  75. return label
  76. }
  77. }
  78. }
  79. return z.Labels[s]
  80. }