From f88d93f6f054c3286a765b2b9a8b4d9ad7a8390c Mon Sep 17 00:00:00 2001 From: lauralani Date: Sat, 1 Apr 2023 16:18:18 +0200 Subject: [PATCH] fix detection of correct zone --- cmd/ip-add.go | 142 ++++++------ cmd/powerdns.go | 596 ++++++++++++++++++++++++------------------------ 2 files changed, 368 insertions(+), 370 deletions(-) diff --git a/cmd/ip-add.go b/cmd/ip-add.go index 7c80821..2a1ed31 100644 --- a/cmd/ip-add.go +++ b/cmd/ip-add.go @@ -5,96 +5,96 @@ Copyright © 2023 Laura Kalb 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") } diff --git a/cmd/powerdns.go b/cmd/powerdns.go index 789d44a..ae55a92 100644 --- a/cmd/powerdns.go +++ b/cmd/powerdns.go @@ -5,32 +5,32 @@ Copyright © 2023 Laura Kalb 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 }