zone.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. package zone
  2. import (
  3. "fmt"
  4. "net"
  5. "git.giaever.org/joachimmg/m-dns/config"
  6. "git.giaever.org/joachimmg/m-dns/errors"
  7. "git.giaever.org/joachimmg/m-dns/host"
  8. "github.com/miekg/dns"
  9. )
  10. type Zone interface {
  11. Records(q dns.Question)
  12. }
  13. type ZoneRecord struct {
  14. Instance host.HostString
  15. TXT []string
  16. sAddr string
  17. iAddr string
  18. eAddr string
  19. *host.Host
  20. }
  21. func New(instance, service, domain, hostname string, port int, ips []net.IP, txt []string) (*ZoneRecord, error) {
  22. zr := new(ZoneRecord)
  23. zr.Host = new(host.Host)
  24. if len(instance) == 0 {
  25. return nil, errors.ZoneInstanseIsEmpty
  26. }
  27. zr.Instance = host.HostString(instance)
  28. if err := zr.SetService(service); err != nil {
  29. return nil, err
  30. }
  31. if err := zr.SetDomain(domain); err != nil {
  32. return nil, err
  33. }
  34. if err := zr.SetHostname(hostname); err != nil {
  35. return nil, err
  36. }
  37. if err := zr.SetPort(port); err != nil {
  38. return nil, err
  39. }
  40. zr.TXT = txt
  41. zr.sAddr = fmt.Sprintf("%s.%s.",
  42. zr.GetService().TrimDot(),
  43. zr.GetDomain().TrimDot(),
  44. )
  45. zr.iAddr = fmt.Sprintf("%s.%s.%s.",
  46. zr.Instance.TrimDot,
  47. zr.GetService().TrimDot(),
  48. zr.GetDomain().TrimDot(),
  49. )
  50. zr.eAddr = fmt.Sprintf("_services._dns-ds._udp.%s.",
  51. zr.GetDomain().TrimDot(),
  52. )
  53. return zr, nil
  54. }
  55. func (zr *ZoneRecord) Records(q dns.Question) []dns.RR {
  56. switch q.Name {
  57. case zr.sAddr:
  58. return zr.sRecords(q)
  59. case zr.iAddr:
  60. return zr.iRecords(q)
  61. case zr.eAddr:
  62. return zr.sEnum(q)
  63. case zr.GetHostname().String():
  64. switch q.Qtype {
  65. case dns.TypeA, dns.TypeAAAA:
  66. return zr.iRecords(q)
  67. }
  68. fallthrough
  69. default:
  70. return nil
  71. }
  72. }
  73. func (zr *ZoneRecord) sRecords(q dns.Question) []dns.RR {
  74. switch q.Qtype {
  75. case dns.TypeANY, dns.TypePTR:
  76. sr := []dns.RR{
  77. &dns.PTR{
  78. Hdr: dns.RR_Header{
  79. Name: q.Name,
  80. Rrtype: dns.TypePTR,
  81. Class: dns.ClassINET,
  82. Ttl: config.DefaultTTL,
  83. },
  84. Ptr: zr.iAddr,
  85. },
  86. }
  87. return append(sr, zr.Records(
  88. dns.Question{
  89. Name: zr.iAddr,
  90. Qtype: dns.TypeANY,
  91. },
  92. )...)
  93. default:
  94. return nil
  95. }
  96. }
  97. func (zr *ZoneRecord) iRecords(q dns.Question) []dns.RR {
  98. switch q.Qtype {
  99. case dns.TypeANY:
  100. ir := zr.Records(
  101. dns.Question{
  102. Name: zr.iAddr,
  103. Qtype: dns.TypeSRV,
  104. },
  105. )
  106. return append(ir, zr.Records(
  107. dns.Question{
  108. Name: zr.iAddr,
  109. Qtype: dns.TypeTXT,
  110. },
  111. )...)
  112. case dns.TypeA:
  113. var ir []dns.RR
  114. for _, ip := range zr.GetIPs() {
  115. switch ip.Type() {
  116. case host.IPv4:
  117. ir = append(ir, &dns.A{
  118. Hdr: dns.RR_Header{
  119. Name: zr.GetHostname().String(),
  120. Rrtype: dns.TypeA,
  121. Class: dns.ClassINET,
  122. Ttl: config.DefaultTTL,
  123. },
  124. })
  125. case host.IPv6:
  126. continue
  127. }
  128. }
  129. return ir
  130. case dns.TypeAAAA:
  131. var ir []dns.RR
  132. for _, ip := range zr.GetIPs() {
  133. switch ip.Type() {
  134. case host.IPv4:
  135. continue
  136. case host.IPv6:
  137. ir = append(ir, &dns.AAAA{
  138. Hdr: dns.RR_Header{
  139. Name: zr.GetHostname().String(),
  140. Rrtype: dns.TypeAAAA,
  141. Class: dns.ClassINET,
  142. Ttl: config.DefaultTTL,
  143. },
  144. AAAA: ip.AsIP().To16(),
  145. })
  146. }
  147. }
  148. return ir
  149. case dns.TypeSRV:
  150. ir := []dns.RR{
  151. &dns.SRV{
  152. Hdr: dns.RR_Header{
  153. Name: q.Name,
  154. Rrtype: dns.TypeSRV,
  155. Class: dns.ClassINET,
  156. Ttl: config.DefaultTTL,
  157. },
  158. Priority: 10,
  159. Weight: 1,
  160. Port: zr.GetPort().Uint16(),
  161. Target: zr.GetHostname().String(),
  162. },
  163. }
  164. ir = append(ir, zr.Records(
  165. dns.Question{
  166. Name: zr.iAddr,
  167. Qtype: dns.TypeA,
  168. },
  169. )...)
  170. return append(ir, zr.Records(
  171. dns.Question{
  172. Name: zr.iAddr,
  173. Qtype: dns.TypeAAAA,
  174. },
  175. )...)
  176. case dns.TypeTXT:
  177. return []dns.RR{
  178. &dns.TXT{
  179. Hdr: dns.RR_Header{
  180. Name: q.Name,
  181. Rrtype: dns.TypeTXT,
  182. Class: dns.ClassINET,
  183. Ttl: config.DefaultTTL,
  184. },
  185. },
  186. }
  187. default:
  188. return nil
  189. }
  190. }
  191. func (zr *ZoneRecord) sEnum(q dns.Question) []dns.RR {
  192. switch q.Qtype {
  193. case dns.TypeANY, dns.TypePTR:
  194. return []dns.RR{
  195. &dns.PTR{
  196. Hdr: dns.RR_Header{
  197. Name: q.Name,
  198. Rrtype: dns.TypePTR,
  199. Class: dns.ClassINET,
  200. Ttl: config.DefaultTTL,
  201. },
  202. Ptr: zr.sAddr,
  203. },
  204. }
  205. default:
  206. return nil
  207. }
  208. }