types.go 1.9 KB

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