blob: 6916a5e9a991151a250aba1314fea0b02f5ec1b5 [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()
gioe72b54f2024-04-22 10:44:41 +040038 fmt.Printf("%s %s\n", name, value)
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040039 for i, rr := range z.rrs {
gioe72b54f2024-04-22 10:44:41 +040040 fmt.Printf("%+v\n", rr)
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040041 if txt, ok := rr.(*dns.TXT); ok {
gioe72b54f2024-04-22 10:44:41 +040042 fmt.Printf("%+v\n", txt)
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040043 if txt.Hdr.Name == name && strings.Join(txt.Txt, "") == value {
44 z.rrs = append(z.rrs[:i], z.rrs[i+1:]...)
45 }
46 }
47 }
48}
49
gioe72b54f2024-04-22 10:44:41 +040050// func (z *RecordsFile) DeleteRecordsFor(name string) {
51// z.lock.Lock()
52// defer z.lock.Unlock()
53// rrs := make([]dns.RR, 0)
54// for _, rr := range z.rrs {
55// if rr.Header().Name != name {
56// rrs = append(rrs, rr)
57// }
58// }
59// z.rrs = rrs
60// }
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +040061
gioe72b54f2024-04-22 10:44:41 +040062func (z *RecordsFile) CreateOrReplaceTxtRecord(name, value string) {
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +040063 z.lock.Lock()
64 defer z.lock.Unlock()
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +040065 for i, rr := range z.rrs {
66 if txt, ok := rr.(*dns.TXT); ok {
67 if txt.Hdr.Name == name && strings.Join(txt.Txt, "") == value {
68 txt.Txt = []string{value}
69 z.rrs = append(z.rrs[:i], z.rrs[i+1:]...)
70 z.rrs = append(z.rrs, txt)
71 return
72 }
73 }
74 }
75 z.rrs = append(z.rrs, &dns.TXT{
76 Hdr: dns.RR_Header{
77 Name: name,
78 Rrtype: dns.TypeTXT,
79 Class: dns.ClassINET,
80 Ttl: 300,
81 },
82 Txt: []string{value},
83 })
84}
85
gioe72b54f2024-04-22 10:44:41 +040086func (z *RecordsFile) CreateARecord(name, value string) {
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +040087 z.lock.Lock()
88 defer z.lock.Unlock()
89 z.rrs = append(z.rrs, &dns.A{
90 Hdr: dns.RR_Header{
91 Name: name,
92 Rrtype: dns.TypeA,
93 Class: dns.ClassINET,
94 Ttl: 300,
95 },
96 A: net.ParseIP(value),
97 })
98}
99
gioe72b54f2024-04-22 10:44:41 +0400100func (z *RecordsFile) Write(w io.Writer) error {
Giorgi Lekveishvili109a5672023-12-07 16:05:42 +0400101 z.lock.Lock()
102 defer z.lock.Unlock()
Giorgi Lekveishvilie58fc592023-12-07 13:24:07 +0400103 for _, rr := range z.rrs {
104 if soa, ok := rr.(*dns.SOA); ok {
105 soa.Serial = NowUnix()
106 }
107 if _, err := fmt.Fprintf(w, "%s\n", rr.String()); err != nil {
108 return err
109 }
110 }
111 return nil
112}