Merge pull request 'Fix DNS Zone matching for PowerDNS API integration' (#8) from bug-1 into main

Reviewed-on: https://codeberg.org/lauralani/ipam/pulls/8
This commit is contained in:
Adora Laura Kalb 2023-04-01 14:36:55 +00:00
commit 34e4e6fc3e
3 changed files with 370 additions and 371 deletions

3
.gitignore vendored
View file

@ -23,5 +23,6 @@ go.work
# build output
bin/
# vs code stuff
# IDE stuff
.vscode/
.idea/

View file

@ -5,96 +5,96 @@ Copyright © 2023 Laura Kalb <dev@lauka.net>
package cmd
import (
"fmt"
"net/netip"
"os"
"os/user"
"time"
"fmt"
"net/netip"
"os"
"os/user"
"time"
"github.com/spf13/cobra"
"github.com/spf13/cobra"
)
var ipaddCmd = &cobra.Command{
Use: "add ipaddress [hostname]",
Short: "Add new IP address",
Long: `Add new IP address`,
Aliases: []string{"a"},
Args: cobra.RangeArgs(1, 2),
Run: func(cmd *cobra.Command, args []string) {
var ipaddress, hostname string
Use: "add ipaddress [hostname]",
Short: "Add new IP address",
Long: `Add new IP address`,
Aliases: []string{"a"},
Args: cobra.RangeArgs(1, 2),
Run: func(cmd *cobra.Command, args []string) {
var ipaddress, hostname string
if len(args) == 1 {
ipaddress = args[0]
hostname = ""
} else {
ipaddress = args[0]
hostname = args[1]
}
if len(args) == 1 {
ipaddress = args[0]
hostname = ""
} else {
ipaddress = args[0]
hostname = args[1]
}
ip, parseerr := netip.ParseAddr(ipaddress)
ip, parseerr := netip.ParseAddr(ipaddress)
// Exit if parsed value is no valid IP
if parseerr != nil {
fmt.Println("[ERROR]", parseerr)
os.Exit(1)
}
// Exit if parsed value is no valid IP
if parseerr != nil {
fmt.Println("[ERROR]", parseerr)
os.Exit(1)
}
// Exit if parsed value is an IPv6 Address
// TODO: Implement IPv6 support
//if !ip.Is4() {
// fmt.Printf("[ERROR] IPv6 is not yet supported!\n")
// os.Exit(1)
//}
// Exit if parsed value is an IPv6 Address
// TODO: Implement IPv6 support
//if !ip.Is4() {
// fmt.Printf("[ERROR] IPv6 is not yet supported!\n")
// os.Exit(1)
//}
subnet, subnetexists := FindBestSubnet(ip)
subnet, subnetexists := FindBestSubnet(ip)
if !subnetexists {
fmt.Printf("[ERROR] Found no suitable subnet for IP %v\n", ipaddress)
fmt.Printf("[ERROR] Maybe you need to add it first?\n")
os.Exit(1)
}
if !subnetexists {
fmt.Printf("[ERROR] Found no suitable subnet for IP %v\n", ipaddress)
fmt.Printf("[ERROR] Maybe you need to add it first?\n")
os.Exit(1)
}
if subnet.HasIP(ip) {
fmt.Printf("[ERROR] IP %v already exists in subnet %v\n", ip.String(), subnet.Subnet.String())
os.Exit(1)
}
if subnet.HasIP(ip) {
fmt.Printf("[ERROR] IP %v already exists in subnet %v\n", ip.String(), subnet.Subnet.String())
os.Exit(1)
}
currentuser, _ := user.Current()
timestamp := time.Now()
currentuser, _ := user.Current()
timestamp := time.Now()
subnet.Addresses = append(subnet.Addresses, Address{ip, hostname, timestamp, currentuser.Username})
subnet.ChangedBy = currentuser.Username
subnet.ChangedAt = timestamp
subnet.Addresses = append(subnet.Addresses, Address{ip, hostname, timestamp, currentuser.Username})
subnet.ChangedBy = currentuser.Username
subnet.ChangedAt = timestamp
writeerr := subnet.WriteSubnet()
if writeerr != nil {
fmt.Println("[ERROR]", writeerr)
os.Exit(1)
}
writeerr := subnet.WriteSubnet()
if writeerr != nil {
fmt.Println("[ERROR]", writeerr)
os.Exit(1)
}
if hostname == "" {
fmt.Printf("added ip:\nip: %v\n", ipaddress)
} else {
fmt.Printf("added ip:\nip: %v\nhostname: %v\n", ipaddress, hostname)
dnserr := AddDNSFqdn(hostname, ip)
if dnserr != nil {
fmt.Println("[ERROR]", writeerr)
os.Exit(1)
}
}
},
if hostname == "" {
fmt.Printf("added ip:\nip: %v\n", ipaddress)
} else {
fmt.Printf("added ip:\nip: %v\nhostname: %v\n", ipaddress, hostname)
dnserr := AddDNSFqdn(hostname, ip)
if dnserr != nil {
fmt.Println("[ERROR]", dnserr)
os.Exit(1)
}
}
},
}
func init() {
ipCmd.AddCommand(ipaddCmd)
ipCmd.AddCommand(ipaddCmd)
// Here you will define your flags and configuration settings.
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// addCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// addCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// addCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// addCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

View file

@ -5,32 +5,32 @@ Copyright © 2023 Laura Kalb <dev@lauka.net>
package cmd
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/netip"
"strings"
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/netip"
"strings"
"github.com/spf13/viper"
"github.com/spf13/viper"
)
type DNSZone struct {
ID string `json:"id"`
Name string `json:"name"`
Kind string `json:"kind"`
RRsets []DNSRecordSet `json:"rrsets"`
Metadata map[string]string `json:"metadata"`
DNSSEC bool `json:"dnssec"`
NSEC3Param string `json:"nsec3param,omitempty"`
Account string `json:"account,omitempty"`
Serial int `json:"serial"`
ID string `json:"id"`
Name string `json:"name"`
Kind string `json:"kind"`
RRsets []DNSRecordSet `json:"rrsets"`
Metadata map[string]string `json:"metadata"`
DNSSEC bool `json:"dnssec"`
NSEC3Param string `json:"nsec3param,omitempty"`
Account string `json:"account,omitempty"`
Serial int `json:"serial"`
}
type Patch struct {
Rrsets []DNSRecordSet `json:"rrsets"`
Rrsets []DNSRecordSet `json:"rrsets"`
}
// GetRecord checks if a given Record already exists in the DNSRecordSet list.
@ -38,106 +38,102 @@ type Patch struct {
// Returns the DNSRecordSet and true if record exists, empty
// DNSRecordSet and false if not.
func (z DNSZone) GetRecord(fqdn string, rtype string, rcontent string) (DNSRecordSet, bool) {
if !strings.HasSuffix(fqdn, ".") {
fqdn = fqdn + "."
}
if (rtype == "PTR") && !strings.HasSuffix(rcontent, ".") {
rcontent = rcontent + "."
}
for _, recordset := range z.RRsets {
if recordset.Name == fqdn && recordset.Type == rtype {
for _, record := range recordset.Records {
if record.Content == rcontent {
return recordset, true
}
}
}
}
return DNSRecordSet{}, false
if !strings.HasSuffix(fqdn, ".") {
fqdn = fqdn + "."
}
if (rtype == "PTR") && !strings.HasSuffix(rcontent, ".") {
rcontent = rcontent + "."
}
for _, recordset := range z.RRsets {
if recordset.Name == fqdn && recordset.Type == rtype {
for _, record := range recordset.Records {
if record.Content == rcontent {
return recordset, true
}
}
}
}
return DNSRecordSet{}, false
}
// SendPATCH sends a PATCH API request for DNSZone z. Returns error or nil
//
// Example args for "test.example.com IN A 127.0.0.1"
//
// z.Name = "example.com."
// record = "test"
// value = "127.0.0.1"
// recordtype = "A"
// changetype = "REPLACE"
// z.Name = "example.com."
// record = "test"
// value = "127.0.0.1"
// recordtype = "A"
// changetype = "REPLACE"
func (z DNSZone) SendPATCH(record string, value string, recordtype string, changetype string) error {
pdnsendpoint := viper.GetString("powerdnsendpoint")
pdnsapikey := viper.GetString("powerdnsapikey")
debug, _ := rootCmd.Flags().GetBool("debug")
pdnsendpoint := viper.GetString("powerdnsendpoint")
pdnsapikey := viper.GetString("powerdnsapikey")
debug, _ := rootCmd.Flags().GetBool("debug")
if !viper.GetBool("powerdnsenabled") {
return nil
}
if !viper.GetBool("powerdnsenabled") {
return nil
}
url := pdnsendpoint + "/api/v1/servers/localhost/zones/" + z.Name
if debug {
fmt.Println("[DEBUG] PowerDNS URL: " + url)
}
url := pdnsendpoint + "/api/v1/servers/localhost/zones/" + z.Name
if debug {
fmt.Println("[DEBUG] PowerDNS URL: " + url)
}
rset := DNSRecordSet{}
rset.Changetype = changetype
rset.Name = strings.Join([]string{record, z.Name}, ".")
rset.TTL = 3600
rset.Type = recordtype
rec := DNSRecord{}
if recordtype == "PTR" {
rec.Content = value + "."
} else {
rec.Content = value
}
rset.Records = append(rset.Records, rec)
rset := DNSRecordSet{}
rset.Changetype = changetype
rset.Name = strings.Join([]string{record, z.Name}, ".")
rset.TTL = 3600
rset.Type = recordtype
rec := DNSRecord{}
if recordtype == "PTR" {
rec.Content = value + "."
} else {
rec.Content = value
}
rset.Records = append(rset.Records, rec)
patch := Patch{}
patch.Rrsets = append(patch.Rrsets, rset)
patch := Patch{}
patch.Rrsets = append(patch.Rrsets, rset)
payload, marsherr := json.Marshal(patch)
if marsherr != nil {
return marsherr
}
payload, marsherr := json.Marshal(patch)
if marsherr != nil {
return marsherr
}
req, reqerr := http.NewRequest("PATCH", url, bytes.NewBuffer(payload))
if reqerr != nil {
return reqerr
}
req, reqerr := http.NewRequest("PATCH", url, bytes.NewBuffer(payload))
if reqerr != nil {
return reqerr
}
req.Header.Add("X-API-Key", pdnsapikey)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("X-API-Key", pdnsapikey)
req.Header.Add("Content-Type", "application/json")
client := &http.Client{}
resp, resperr := client.Do(req)
if resperr != nil {
return resperr
}
client := &http.Client{}
resp, _ := client.Do(req)
if resp.StatusCode != 204 {
defer resp.Body.Close()
if resp.StatusCode != 204 {
defer resp.Body.Close()
body, readerr := io.ReadAll(resp.Body)
if readerr != nil {
fmt.Println(readerr)
}
return errors.New("HTTP Error: " + resp.Status + "\n" + string(body))
}
return nil
body, readerr := io.ReadAll(resp.Body)
if readerr != nil {
fmt.Println(readerr)
}
return fmt.Errorf("[HTTP ERROR] %v: %q", resp.Status, string(body))
}
return nil
}
type DNSRecordSet struct {
Name string `json:"name"`
Type string `json:"type"`
TTL int `json:"ttl"`
Records []DNSRecord `json:"records"`
Changetype string `json:"changetype,omitempty"`
Name string `json:"name"`
Type string `json:"type"`
TTL int `json:"ttl"`
Records []DNSRecord `json:"records"`
Changetype string `json:"changetype,omitempty"`
}
type DNSRecord struct {
Content string `json:"content"`
Disabled bool `json:"disabled,omitempty"`
SetPTR bool `json:"set-ptr,omitempty"`
Content string `json:"content"`
Disabled bool `json:"disabled,omitempty"`
SetPTR bool `json:"set-ptr,omitempty"`
}
// GetDNSZone retrieves the corresponding DNSZone for string zone
@ -146,45 +142,45 @@ type DNSRecord struct {
// Returns the DNSZone and nil if successful, empty DNSZone and an
// error otherwise
func GetDNSZone(zone string) (DNSZone, error) {
if !strings.HasSuffix(zone, ".") {
zone = zone + "."
}
pdnsendpoint := viper.GetString("powerdnsendpoint")
pdnsapikey := viper.GetString("powerdnsapikey")
if !strings.HasSuffix(zone, ".") {
zone = zone + "."
}
pdnsendpoint := viper.GetString("powerdnsendpoint")
pdnsapikey := viper.GetString("powerdnsapikey")
url := pdnsendpoint + "/api/v1/servers/localhost/zones/" + zone
url := pdnsendpoint + "/api/v1/servers/localhost/zones/" + zone
req, reqerr := http.NewRequest("GET", url, nil)
if reqerr != nil {
fmt.Println(reqerr)
return DNSZone{}, reqerr
}
req, reqerr := http.NewRequest("GET", url, nil)
if reqerr != nil {
fmt.Println(reqerr)
return DNSZone{}, reqerr
}
req.Header.Add("X-API-Key", pdnsapikey)
req.Header.Add("Accept", "application/json")
req.Header.Add("X-API-Key", pdnsapikey)
req.Header.Add("Accept", "application/json")
client := &http.Client{}
resp, resperr := client.Do(req)
if resperr != nil {
fmt.Println(resperr)
return DNSZone{}, resperr
}
defer resp.Body.Close()
client := &http.Client{}
resp, resperr := client.Do(req)
if resperr != nil {
fmt.Println(resperr)
return DNSZone{}, resperr
}
defer resp.Body.Close()
body, readerr := io.ReadAll(resp.Body)
if readerr != nil {
fmt.Println(readerr)
return DNSZone{}, readerr
}
body, readerr := io.ReadAll(resp.Body)
if readerr != nil {
fmt.Println(readerr)
return DNSZone{}, readerr
}
var zoneobj DNSZone
marsherr := json.Unmarshal(body, &zoneobj)
if marsherr != nil {
fmt.Println(marsherr)
return DNSZone{}, marsherr
}
var zoneobj DNSZone
marsherr := json.Unmarshal(body, &zoneobj)
if marsherr != nil {
fmt.Println(marsherr)
return DNSZone{}, marsherr
}
return zoneobj, nil
return zoneobj, nil
}
// GetBestDNSZone requests a list of all zones from PowerDNS
@ -193,70 +189,70 @@ func GetDNSZone(zone string) (DNSZone, error) {
// Returns the found DNSZone and nil if a suitable zone was
// found, an empty DNSZone object and an error if not.
func GetBestDNSZone(fqdn string) (DNSZone, error) {
pdnsendpoint := viper.GetString("powerdnsendpoint")
pdnsapikey := viper.GetString("powerdnsapikey")
fqdn = fqdn + "."
pdnsendpoint := viper.GetString("powerdnsendpoint")
pdnsapikey := viper.GetString("powerdnsapikey")
fqdn = fqdn + "."
if !viper.GetBool("powerdnsenabled") {
return DNSZone{}, errors.New("PowerDNS integration not enabled")
}
if !viper.GetBool("powerdnsenabled") {
return DNSZone{}, errors.New("PowerDNS integration not enabled")
}
url := pdnsendpoint + "/api/v1/servers/localhost/zones"
url := pdnsendpoint + "/api/v1/servers/localhost/zones"
req, reqerr := http.NewRequest("GET", url, nil)
if reqerr != nil {
fmt.Println(reqerr)
return DNSZone{}, reqerr
}
req, reqerr := http.NewRequest("GET", url, nil)
if reqerr != nil {
fmt.Println(reqerr)
return DNSZone{}, reqerr
}
req.Header.Add("X-API-Key", pdnsapikey)
req.Header.Add("X-API-Key", pdnsapikey)
client := &http.Client{}
resp, resperr := client.Do(req)
if resperr != nil {
fmt.Println(resperr)
return DNSZone{}, resperr
}
defer resp.Body.Close()
client := &http.Client{}
resp, resperr := client.Do(req)
if resperr != nil {
fmt.Println(resperr)
return DNSZone{}, resperr
}
defer resp.Body.Close()
body, readerr := io.ReadAll(resp.Body)
if readerr != nil {
fmt.Println(readerr)
return DNSZone{}, readerr
}
body, readerr := io.ReadAll(resp.Body)
if readerr != nil {
fmt.Println(readerr)
return DNSZone{}, readerr
}
var zones []DNSZone
marsherr := json.Unmarshal(body, &zones)
if marsherr != nil {
fmt.Println(marsherr)
return DNSZone{}, marsherr
}
var zones []DNSZone
marsherr := json.Unmarshal(body, &zones)
if marsherr != nil {
fmt.Println(marsherr)
return DNSZone{}, marsherr
}
var bestmatch DNSZone
var matchfound bool = false
var bestmatch DNSZone
var matchfound bool = false
for _, zone := range zones {
if strings.HasSuffix(fqdn, zone.Name) {
if !matchfound {
matchfound = true
bestmatch = zone
}
if matchfound && len(zone.Name) > len(bestmatch.Name) {
bestmatch = zone
}
}
}
for _, zone := range zones {
if strings.HasSuffix(fqdn, "."+zone.Name) {
if !matchfound {
matchfound = true
bestmatch = zone
}
if matchfound && len(zone.Name) > len(bestmatch.Name) {
bestmatch = zone
}
}
}
if !matchfound {
return DNSZone{}, errors.New("No suitable zone found for " + fqdn)
}
if !matchfound {
return DNSZone{}, errors.New("No suitable zone found for " + fqdn)
}
zone, geterr := GetDNSZone(bestmatch.ID)
if geterr != nil {
return DNSZone{}, geterr
}
zone, geterr := GetDNSZone(bestmatch.ID)
if geterr != nil {
return DNSZone{}, geterr
}
return zone, nil
return zone, nil
}
// AddDNSFqdn tries to create forward and reverse lookup records
@ -265,74 +261,76 @@ func GetBestDNSZone(fqdn string) (DNSZone, error) {
//
// Returns nil on success, error otherwise
func AddDNSFqdn(fqdn string, addr netip.Addr) error {
debug, _ := rootCmd.Flags().GetBool("debug")
if !viper.GetBool("powerdnsenabled") {
if debug {
fmt.Println("[INFO] PowerDNS integration disabled, skipping DNS operations.")
}
return nil
}
debug, _ := rootCmd.Flags().GetBool("debug")
if !viper.GetBool("powerdnsenabled") {
if debug {
fmt.Println("[INFO] PowerDNS integration disabled, skipping DNS operations.")
}
return nil
}
var recordtype string
if addr.Is4() {
recordtype = "A"
} else if addr.Is6() {
recordtype = "AAAA"
} else {
return errors.New(addr.String() + " is not a valid IP address")
}
var recordtype string
if addr.Is4() {
recordtype = "A"
} else if addr.Is6() {
recordtype = "AAAA"
} else {
return errors.New(addr.String() + " is not a valid IP address")
}
fzone, fzoneerr := GetBestDNSZone(fqdn)
if fzoneerr != nil {
fmt.Printf("[DNS] No suitable zone found for %v, skipping DNS op\n", fqdn)
} else {
fzone, fzoneerr := GetBestDNSZone(fqdn)
if fzoneerr != nil {
fmt.Printf("[DNS] No suitable zone found for %v, skipping DNS op\n", fqdn)
} else {
_, frecordexists := fzone.GetRecord(fqdn, recordtype, addr.String())
_, frecordexists := fzone.GetRecord(fqdn, recordtype, addr.String())
if frecordexists {
fmt.Printf("[DNS] DNS Record for %v already exists, no need to change DNS.\n", fqdn)
} else {
fpatcherr := fzone.SendPATCH(strings.Replace(fqdn+".", "."+fzone.Name, "", 1), addr.String(), recordtype, "REPLACE")
if fpatcherr != nil {
return fpatcherr
}
fmt.Printf("[DNS] + %v IN %v %v\n", fqdn, recordtype, addr.String())
}
}
if frecordexists {
fmt.Printf("[DNS] DNS Record for %v already exists, no need to change DNS.\n", fqdn)
} else {
var dotfqdn, dotfzone string = fqdn + ".", "." + fzone.Name
record := strings.Replace(dotfqdn, dotfzone, "", 1)
fpatcherr := fzone.SendPATCH(record, addr.String(), recordtype, "REPLACE")
if fpatcherr != nil {
return fpatcherr
}
fmt.Printf("[DNS] + %v IN %v %v\n", fqdn, recordtype, addr.String())
}
}
baseip := addr.StringExpanded()
var rfqdn string
if addr.Is4() {
a := strings.Split(baseip, ".")
b := reverse(a)
rfqdn = strings.Join(b, ".") + ".in-addr.arpa"
} else if addr.Is6() {
a := strings.Replace(baseip, ":", "", -1)
b := strings.Split(a, "")
c := reverse(b)
rfqdn = strings.Join(c, ".") + ".ip6.arpa"
}
baseip := addr.StringExpanded()
var rfqdn string
if addr.Is4() {
a := strings.Split(baseip, ".")
b := reverse(a)
rfqdn = strings.Join(b, ".") + ".in-addr.arpa"
} else if addr.Is6() {
a := strings.Replace(baseip, ":", "", -1)
b := strings.Split(a, "")
c := reverse(b)
rfqdn = strings.Join(c, ".") + ".ip6.arpa"
}
rzone, rzoneerr := GetBestDNSZone(rfqdn)
if rzoneerr != nil {
fmt.Printf("[DNS] No suitable zone found for %v, skipping DNS op\n", rfqdn)
} else {
rzone, rzoneerr := GetBestDNSZone(rfqdn)
if rzoneerr != nil {
fmt.Printf("[DNS] No suitable zone found for %v, skipping DNS op\n", rfqdn)
} else {
_, rrecordexists := rzone.GetRecord(rfqdn, "PTR", fqdn)
rhost := strings.Replace(rfqdn+".", "."+rzone.Name, "", 1)
_, rrecordexists := rzone.GetRecord(rfqdn, "PTR", fqdn)
rhost := strings.Replace(rfqdn+".", "."+rzone.Name, "", 1)
if rrecordexists {
fmt.Printf("[DNS] Reverse DNS Record for %v already exists, no need to change DNS.\n", addr.String())
} else {
rpatcherr := rzone.SendPATCH(rhost, fqdn, "PTR", "REPLACE")
if rpatcherr != nil {
return rpatcherr
}
fmt.Printf("[DNS] + %v IN %v %v\n", rfqdn, "PTR", fqdn)
}
}
if rrecordexists {
fmt.Printf("[DNS] Reverse DNS Record for %v already exists, no need to change DNS.\n", addr.String())
} else {
rpatcherr := rzone.SendPATCH(rhost, fqdn, "PTR", "REPLACE")
if rpatcherr != nil {
return rpatcherr
}
fmt.Printf("[DNS] + %v IN %v %v\n", rfqdn, "PTR", fqdn)
}
}
return nil
return nil
}
// DeleteDNSFqdn tries to delete the corresponding record for
@ -340,70 +338,70 @@ func AddDNSFqdn(fqdn string, addr netip.Addr) error {
//
// Returns nil on success, error otherwise
func DeleteDNSFqdn(fqdn string, addr netip.Addr) error {
debug, _ := rootCmd.Flags().GetBool("debug")
if !viper.GetBool("powerdnsenabled") {
if debug {
fmt.Println("[INFO] PowerDNS integration disabled, skipping DNS operations.")
}
return nil
}
debug, _ := rootCmd.Flags().GetBool("debug")
if !viper.GetBool("powerdnsenabled") {
if debug {
fmt.Println("[INFO] PowerDNS integration disabled, skipping DNS operations.")
}
return nil
}
var recordtype string
if addr.Is4() {
recordtype = "A"
} else if addr.Is6() {
recordtype = "AAAA"
} else {
return errors.New(addr.String() + " is not a valid IP address")
}
var recordtype string
if addr.Is4() {
recordtype = "A"
} else if addr.Is6() {
recordtype = "AAAA"
} else {
return errors.New(addr.String() + " is not a valid IP address")
}
fzone, fzoneerr := GetBestDNSZone(fqdn)
if fzoneerr != nil {
fmt.Printf("[DNS] No suitable zone found for %v, skipping DNS delete op\n", fqdn)
} else {
_, frecordexists := fzone.GetRecord(fqdn, recordtype, addr.String())
fzone, fzoneerr := GetBestDNSZone(fqdn)
if fzoneerr != nil {
fmt.Printf("[DNS] No suitable zone found for %v, skipping DNS delete op\n", fqdn)
} else {
_, frecordexists := fzone.GetRecord(fqdn, recordtype, addr.String())
if !frecordexists {
fmt.Printf("[DNS] DNS Record for %v doesn't exists, no need to change DNS.\n", fqdn)
} else {
fpatcherr := fzone.SendPATCH(strings.Replace(fqdn+".", "."+fzone.Name, "", 1), addr.String(), recordtype, "DELETE")
if fpatcherr != nil {
return fpatcherr
}
fmt.Printf("[DNS] - %v IN %v %v\n", fqdn, recordtype, addr.String())
}
}
if !frecordexists {
fmt.Printf("[DNS] DNS Record for %v doesn't exists, no need to change DNS.\n", fqdn)
} else {
fpatcherr := fzone.SendPATCH(strings.Replace(fqdn+".", "."+fzone.Name, "", 1), addr.String(), recordtype, "DELETE")
if fpatcherr != nil {
return fpatcherr
}
fmt.Printf("[DNS] - %v IN %v %v\n", fqdn, recordtype, addr.String())
}
}
baseip := addr.StringExpanded()
var rfqdn string
if addr.Is4() {
a := strings.Split(baseip, ".")
b := reverse(a)
rfqdn = strings.Join(b, ".") + ".in-addr.arpa"
} else if addr.Is6() {
a := strings.Replace(baseip, ":", "", -1)
b := strings.Split(a, "")
c := reverse(b)
rfqdn = strings.Join(c, ".") + ".ip6.arpa"
}
baseip := addr.StringExpanded()
var rfqdn string
if addr.Is4() {
a := strings.Split(baseip, ".")
b := reverse(a)
rfqdn = strings.Join(b, ".") + ".in-addr.arpa"
} else if addr.Is6() {
a := strings.Replace(baseip, ":", "", -1)
b := strings.Split(a, "")
c := reverse(b)
rfqdn = strings.Join(c, ".") + ".ip6.arpa"
}
rzone, rzoneerr := GetBestDNSZone(rfqdn)
if rzoneerr != nil {
fmt.Printf("[DNS] No suitable zone found for %v, skipping DNS delete op\n", rfqdn)
} else {
_, rrecordexists := rzone.GetRecord(rfqdn, "PTR", fqdn)
rhost := strings.Replace(rfqdn+".", "."+rzone.Name, "", 1)
rzone, rzoneerr := GetBestDNSZone(rfqdn)
if rzoneerr != nil {
fmt.Printf("[DNS] No suitable zone found for %v, skipping DNS delete op\n", rfqdn)
} else {
_, rrecordexists := rzone.GetRecord(rfqdn, "PTR", fqdn)
rhost := strings.Replace(rfqdn+".", "."+rzone.Name, "", 1)
if !rrecordexists {
fmt.Printf("[DNS] Reverse DNS Record for %v doesn't exists, no need to change DNS.\n", addr.String())
} else {
rpatcherr := rzone.SendPATCH(rhost, fqdn, "PTR", "DELETE")
if rpatcherr != nil {
return rpatcherr
}
fmt.Printf("[DNS] - %v IN %v %v\n", rfqdn, "PTR", fqdn)
}
}
if !rrecordexists {
fmt.Printf("[DNS] Reverse DNS Record for %v doesn't exists, no need to change DNS.\n", addr.String())
} else {
rpatcherr := rzone.SendPATCH(rhost, fqdn, "PTR", "DELETE")
if rpatcherr != nil {
return rpatcherr
}
fmt.Printf("[DNS] - %v IN %v %v\n", rfqdn, "PTR", fqdn)
}
}
return nil
return nil
}