blob: a25c3426e3e9e3bd414630e6fd90da4f0445ec9e [file] [log] [blame]
gioe72b54f2024-04-22 10:44:41 +04001package main
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +04002
3import (
4 "fmt"
5 "io"
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +04006 "net"
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +04007 "strings"
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +04008 "sync"
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +04009
10 "github.com/miekg/dns"
11)
12
gioe72b54f2024-04-22 10:44:41 +040013type RecordsFile struct {
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +040014 lock sync.Locker
15 rrs []dns.RR
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040016}
17
gioe72b54f2024-04-22 10:44:41 +040018func NewRecordsFile(r io.Reader) (*RecordsFile, error) {
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040019 rrs := make([]dns.RR, 0)
20 p := dns.NewZoneParser(r, "", "")
21 p.SetIncludeAllowed(false)
22 for {
23 if rr, ok := p.Next(); ok {
24 rrs = append(rrs, rr)
25 } else {
26 if err := p.Err(); err != nil {
27 return nil, err
28 }
29 break
30 }
31 }
gioe72b54f2024-04-22 10:44:41 +040032 return &RecordsFile{&sync.Mutex{}, rrs}, nil
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040033}
34
gioe72b54f2024-04-22 10:44:41 +040035func (z *RecordsFile) DeleteTxtRecord(name, value string) {
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +040036 z.lock.Lock()
37 defer z.lock.Unlock()
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040038 for i, rr := range z.rrs {
39 if txt, ok := rr.(*dns.TXT); ok {
40 if txt.Hdr.Name == name && strings.Join(txt.Txt, "") == value {
41 z.rrs = append(z.rrs[:i], z.rrs[i+1:]...)
42 }
43 }
44 }
45}
46
giof6ad2982024-08-23 17:42:49 +040047func (z *RecordsFile) DeleteARecord(name, value string) error {
48 z.lock.Lock()
49 defer z.lock.Unlock()
50 for i, rr := range z.rrs {
51 if a, ok := rr.(*dns.A); ok {
52 if a.Hdr.Name == name && a.A.String() == value {
53 z.rrs = append(z.rrs[:i], z.rrs[i+1:]...)
54 return nil
55 }
56 }
57 }
58 return fmt.Errorf("not found")
59}
60
gioe72b54f2024-04-22 10:44:41 +040061// func (z *RecordsFile) DeleteRecordsFor(name string) {
62// z.lock.Lock()
63// defer z.lock.Unlock()
64// rrs := make([]dns.RR, 0)
65// for _, rr := range z.rrs {
66// if rr.Header().Name != name {
67// rrs = append(rrs, rr)
68// }
69// }
70// z.rrs = rrs
71// }
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +040072
gioe72b54f2024-04-22 10:44:41 +040073func (z *RecordsFile) CreateOrReplaceTxtRecord(name, value string) {
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +040074 z.lock.Lock()
75 defer z.lock.Unlock()
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040076 for i, rr := range z.rrs {
77 if txt, ok := rr.(*dns.TXT); ok {
78 if txt.Hdr.Name == name && strings.Join(txt.Txt, "") == value {
79 txt.Txt = []string{value}
80 z.rrs = append(z.rrs[:i], z.rrs[i+1:]...)
81 z.rrs = append(z.rrs, txt)
82 return
83 }
84 }
85 }
86 z.rrs = append(z.rrs, &dns.TXT{
87 Hdr: dns.RR_Header{
88 Name: name,
89 Rrtype: dns.TypeTXT,
90 Class: dns.ClassINET,
91 Ttl: 300,
92 },
93 Txt: []string{value},
94 })
95}
96
gioe72b54f2024-04-22 10:44:41 +040097func (z *RecordsFile) CreateARecord(name, value string) {
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +040098 z.lock.Lock()
99 defer z.lock.Unlock()
100 z.rrs = append(z.rrs, &dns.A{
101 Hdr: dns.RR_Header{
102 Name: name,
103 Rrtype: dns.TypeA,
104 Class: dns.ClassINET,
105 Ttl: 300,
106 },
107 A: net.ParseIP(value),
108 })
109}
110
gioe72b54f2024-04-22 10:44:41 +0400111func (z *RecordsFile) Write(w io.Writer) error {
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +0400112 z.lock.Lock()
113 defer z.lock.Unlock()
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +0400114 for _, rr := range z.rrs {
115 if soa, ok := rr.(*dns.SOA); ok {
116 soa.Serial = NowUnix()
117 }
118 if _, err := fmt.Fprintf(w, "%s\n", rr.String()); err != nil {
119 return err
120 }
121 }
122 return nil
123}