added a real IPv6 record
first time deleting cloudflare AAAA record can find wit.com on cloudflare ready to add cloudflare.Delete() remove code since --gui-debug works Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
867b69f555
commit
ec5cbbe203
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
run: build
|
run: build
|
||||||
# ./control-panel-dns >/tmp/witgui.log.stderr 2>&1
|
# ./control-panel-dns >/tmp/witgui.log.stderr 2>&1
|
||||||
./control-panel-dns
|
./control-panel-dns --gui-debug
|
||||||
|
|
||||||
install:
|
install:
|
||||||
go install -v go.wit.com/control-panel-dns@latest
|
go install -v go.wit.com/control-panel-dns@latest
|
||||||
|
|
|
@ -99,7 +99,7 @@ func SetRow(dnsRow *RRT) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetZonefile(c *ConfigT) *DNSRecords {
|
func GetZonefile(c *ConfigT) *DNSRecords {
|
||||||
var url = cloudflareURL + c.ZoneID + "/dns_records/"
|
var url = cloudflareURL + c.ZoneID + "/dns_records/?per_page=100"
|
||||||
log.Println("getZonefile()", c.Domain, url)
|
log.Println("getZonefile()", c.Domain, url)
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -162,7 +162,7 @@ func makeJSON(dnsRow *RRT) string {
|
||||||
|
|
||||||
// https://api.cloudflare.com/client/v4/zones
|
// https://api.cloudflare.com/client/v4/zones
|
||||||
func GetZones(auth, email string) *DNSRecords {
|
func GetZones(auth, email string) *DNSRecords {
|
||||||
var url = "https://api.cloudflare.com/client/v4/zones"
|
var url = "https://api.cloudflare.com/client/v4/zones?per_page=100"
|
||||||
log.Println("getZones()", url)
|
log.Println("getZones()", url)
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
This will attempt to create a RR in a DNS zone file.
|
||||||
|
|
||||||
|
Create("wit.com", "test.wit.com", "1.1.1.1"
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cloudflare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Create(zone string, hostname string, value string) bool {
|
||||||
|
log.Info("cloudflare.Create() START", zone, hostname, value)
|
||||||
|
key := os.Getenv("CF_API_KEY")
|
||||||
|
email := os.Getenv("CF_API_EMAIL")
|
||||||
|
|
||||||
|
if (key == "") {
|
||||||
|
log.Warn("cloudflare.Create() MISSING environment variable CF_API_KEY")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (email == "") {
|
||||||
|
log.Warn("cloudflare.Create() MISSING environment variable CF_API_EMAIL")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
GetZones(key, email)
|
||||||
|
var z *ConfigT
|
||||||
|
for d, v := range Config {
|
||||||
|
log.Info("cloudflare.Create() zone =", d, "value =", v)
|
||||||
|
if (zone == d) {
|
||||||
|
z = Config[zone]
|
||||||
|
log.Info("cloudflare.Create() FOUND ZONE", zone, "ID =", z.ZoneID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (z == nil) {
|
||||||
|
log.Warn("cloudflare.Create() COULD NOT FIND ZONE", zone)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
log.Info("cloudflare.Create() FOUND ZONE", z)
|
||||||
|
|
||||||
|
// make a json record to send on port 80 to cloudflare
|
||||||
|
var data string
|
||||||
|
data = `{"content": "` + value + `", `
|
||||||
|
data += `"name": "` + hostname + `", `
|
||||||
|
data += `"type": "AAAA", `
|
||||||
|
data += `"ttl": "1", `
|
||||||
|
data += `"comment": "WIT DNS Control Panel"`
|
||||||
|
data += `}`
|
||||||
|
|
||||||
|
result := doCurlCreate(key, email, z.ZoneID, data)
|
||||||
|
pretty, _ := FormatJSON(result)
|
||||||
|
log.Info("cloudflare.Create() result =", pretty)
|
||||||
|
return true
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
This will attempt to delete a RR in a DNS zone file.
|
||||||
|
|
||||||
|
Delete("wit.com", "test.wit.com", "1.1.1.1"
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cloudflare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Delete(zone string, hostname string, value string) bool {
|
||||||
|
// CFdialog.emailNode.SetText(os.Getenv("CF_API_EMAIL"))
|
||||||
|
// CFdialog.apiNode.SetText(os.Getenv("CF_API_KEY"))
|
||||||
|
|
||||||
|
log.Info("cloudflare.Delete() START", zone, hostname, value)
|
||||||
|
key := os.Getenv("CF_API_KEY")
|
||||||
|
email := os.Getenv("CF_API_EMAIL")
|
||||||
|
|
||||||
|
if (key == "") {
|
||||||
|
log.Warn("cloudflare.Delete() MISSING environment variable CF_API_KEY")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (email == "") {
|
||||||
|
log.Warn("cloudflare.Delete() MISSING environment variable CF_API_EMAIL")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
GetZones(key, email)
|
||||||
|
var z *ConfigT
|
||||||
|
for d, v := range Config {
|
||||||
|
log.Info("cloudflare.Delete() zone =", d, "value =", v)
|
||||||
|
if (zone == d) {
|
||||||
|
z = Config[zone]
|
||||||
|
log.Info("cloudflare.Delete() FOUND ZONE", zone, "ID =", z.ZoneID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (z == nil) {
|
||||||
|
log.Warn("cloudflare.Delete() COULD NOT FIND ZONE", zone)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
log.Info("cloudflare.Delete() FOUND ZONE", z)
|
||||||
|
|
||||||
|
records := GetZonefile(z)
|
||||||
|
for i, record := range records.Result {
|
||||||
|
if (record.Name == hostname) {
|
||||||
|
log.Info("cloudflare.Delete() FOUND hostname:", i, record.ID, record.Type, record.Name, record.Content)
|
||||||
|
}
|
||||||
|
if (record.Content == value) {
|
||||||
|
log.Info("cloudflare.Delete() FOUND CONTENT:", i, record.ID, record.Type, record.Name, record.Content)
|
||||||
|
log.Info("cloudflare.Delete() DO THE ACTUAL cloudflare DELETE here")
|
||||||
|
result := doCurlDelete(key, email, z.ZoneID, record.ID)
|
||||||
|
pretty, _ := FormatJSON(result)
|
||||||
|
log.Info("cloudflare.Delete() result =", pretty)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("cloudflare.Delete() NEVER FOUND cloudflare value:", value)
|
||||||
|
return false
|
||||||
|
}
|
|
@ -2,10 +2,11 @@
|
||||||
package cloudflare
|
package cloudflare
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -26,6 +27,88 @@ curl --request POST \
|
||||||
}'
|
}'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
func doCurlDelete(auth string, email string, zoneId string, rrId string) string {
|
||||||
|
var err error
|
||||||
|
var req *http.Request
|
||||||
|
|
||||||
|
if zoneId == "" {
|
||||||
|
log.Warn("doCurlDelete() zoneId == nil")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if rrId == "" {
|
||||||
|
log.Warn("doCurlDelete() rrId == nil")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
data := []byte("")
|
||||||
|
|
||||||
|
url := "https://api.cloudflare.com/client/v4/zones/" + zoneId + "/dns_records/" + rrId
|
||||||
|
|
||||||
|
req, err = http.NewRequest(http.MethodDelete, url, bytes.NewBuffer(data))
|
||||||
|
|
||||||
|
// Set headers
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("X-Auth-Key", auth)
|
||||||
|
req.Header.Set("X-Auth-Email", email)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doCurlCreate(auth string, email string, zoneId string, data string) string {
|
||||||
|
var err error
|
||||||
|
var req *http.Request
|
||||||
|
|
||||||
|
if zoneId == "" {
|
||||||
|
log.Warn("doCurlDelete() zoneId == nil")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "https://api.cloudflare.com/client/v4/zones/" + zoneId + "/dns_records/"
|
||||||
|
|
||||||
|
log.Info("doCurlCreate() POST url =", url)
|
||||||
|
log.Info("doCurlCreate() POST Auth =", auth)
|
||||||
|
log.Info("doCurlCreate() POST Email =", email)
|
||||||
|
log.Info("doCurlCreate() POST data =", data)
|
||||||
|
|
||||||
|
req, err = http.NewRequest(http.MethodPost, url, bytes.NewBuffer( []byte(data) ))
|
||||||
|
|
||||||
|
// Set headers
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("X-Auth-Key", auth)
|
||||||
|
req.Header.Set("X-Auth-Email", email)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(body)
|
||||||
|
}
|
||||||
|
|
||||||
func doCurl(method string, rr *RRT) string {
|
func doCurl(method string, rr *RRT) string {
|
||||||
var err error
|
var err error
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
|
|
11
gui.go
11
gui.go
|
@ -2,7 +2,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
@ -85,16 +84,6 @@ func debugTab(title string) {
|
||||||
|
|
||||||
g2 = tab.NewGroup("Real Stuff")
|
g2 = tab.NewGroup("Real Stuff")
|
||||||
|
|
||||||
g2.NewButton("gui.DebugWindow()", func () {
|
|
||||||
gui.DebugWindow()
|
|
||||||
})
|
|
||||||
|
|
||||||
g2.NewButton("Load 'gocui'", func () {
|
|
||||||
// this set the xterm and mate-terminal window title. maybe works generally?
|
|
||||||
fmt.Println("\033]0;" + title + "blah \007")
|
|
||||||
myGui.LoadToolkit("gocui")
|
|
||||||
})
|
|
||||||
|
|
||||||
g2.NewButton("Network Interfaces", func () {
|
g2.NewButton("Network Interfaces", func () {
|
||||||
for i, t := range me.ifmap {
|
for i, t := range me.ifmap {
|
||||||
log.Println("name =", t.iface.Name)
|
log.Println("name =", t.iface.Name)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
"go.wit.com/gui"
|
"go.wit.com/gui"
|
||||||
"go.wit.com/gui/gadgets"
|
"go.wit.com/gui/gadgets"
|
||||||
|
"go.wit.com/control-panel-dns/cloudflare"
|
||||||
)
|
)
|
||||||
|
|
||||||
type hostnameStatus struct {
|
type hostnameStatus struct {
|
||||||
|
@ -25,21 +26,31 @@ type hostnameStatus struct {
|
||||||
|
|
||||||
window *gui.Node
|
window *gui.Node
|
||||||
|
|
||||||
|
// Primary Directives
|
||||||
status *gadgets.OneLiner
|
status *gadgets.OneLiner
|
||||||
summary *gadgets.OneLiner
|
summary *gadgets.OneLiner
|
||||||
speed *gadgets.OneLiner
|
|
||||||
speedActual *gadgets.OneLiner
|
|
||||||
|
|
||||||
dnsA *gadgets.OneLiner
|
|
||||||
dnsAAAA *gadgets.OneLiner
|
|
||||||
dnsAPI *gadgets.OneLiner
|
|
||||||
|
|
||||||
statusIPv4 *gadgets.OneLiner
|
statusIPv4 *gadgets.OneLiner
|
||||||
statusIPv6 *gadgets.OneLiner
|
statusIPv6 *gadgets.OneLiner
|
||||||
|
|
||||||
// Details Group
|
// Details Group
|
||||||
|
hostShort *gadgets.OneLiner
|
||||||
|
domainname *gadgets.OneLiner
|
||||||
|
|
||||||
|
// what the current IP address your network has given you
|
||||||
currentIPv4 *gadgets.OneLiner
|
currentIPv4 *gadgets.OneLiner
|
||||||
currentIPv6 *gadgets.OneLiner
|
currentIPv6 *gadgets.OneLiner
|
||||||
|
|
||||||
|
// what the DNS servers have
|
||||||
|
dnsA *gadgets.OneLiner
|
||||||
|
dnsAAAA *gadgets.OneLiner
|
||||||
|
dnsAPI *gadgets.OneLiner
|
||||||
|
|
||||||
|
speed *gadgets.OneLiner
|
||||||
|
speedActual *gadgets.OneLiner
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
dnsValue *gui.Node
|
||||||
|
dnsAction *gui.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
|
func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
|
||||||
|
@ -69,23 +80,79 @@ func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
|
||||||
group = box.NewGroup("Details")
|
group = box.NewGroup("Details")
|
||||||
grid = group.NewGrid("LookupDetails", 2, 2)
|
grid = group.NewGrid("LookupDetails", 2, 2)
|
||||||
|
|
||||||
|
hs.hostShort = gadgets.NewOneLiner(grid, "hostname -s")
|
||||||
|
hs.domainname = gadgets.NewOneLiner(grid, "domain name")
|
||||||
hs.currentIPv4 = gadgets.NewOneLiner(grid, "Current IPv4")
|
hs.currentIPv4 = gadgets.NewOneLiner(grid, "Current IPv4")
|
||||||
hs.currentIPv6 = gadgets.NewOneLiner(grid, "Current IPv6")
|
hs.currentIPv6 = gadgets.NewOneLiner(grid, "Current IPv6")
|
||||||
|
|
||||||
hs.dnsAPI = gadgets.NewOneLiner(grid, "dns API provider").Set("unknown")
|
hs.dnsAPI = gadgets.NewOneLiner(grid, "dns API provider").Set("unknown")
|
||||||
hs.dnsA = gadgets.NewOneLiner(grid, "dns IPv4 resource records").Set("unknown")
|
hs.dnsA = gadgets.NewOneLiner(grid, "dns IPv4 resource records").Set("unknown")
|
||||||
hs.dnsAAAA = gadgets.NewOneLiner(grid, "dns IPv6 resource records").Set("unknown")
|
hs.dnsAAAA = gadgets.NewOneLiner(grid, "dns IPv6 resource records").Set("unknown")
|
||||||
|
|
||||||
hs.speed = gadgets.NewOneLiner(grid, "speed").Set("unknown")
|
hs.speed = gadgets.NewOneLiner(grid, "speed").Set("unknown")
|
||||||
hs.speedActual = gadgets.NewOneLiner(grid, "actual").Set("unknown")
|
hs.speedActual = gadgets.NewOneLiner(grid, "actual").Set("unknown")
|
||||||
|
|
||||||
group.Pad()
|
group.Pad()
|
||||||
grid.Pad()
|
grid.Pad()
|
||||||
|
|
||||||
|
group = box.NewGroup("Actions")
|
||||||
|
grid = group.NewGrid("LookupDetails", 2, 2)
|
||||||
|
|
||||||
|
hs.dnsValue = grid.NewLabel("3.4.5.6")
|
||||||
|
hs.dnsAction = grid.NewButton("CHECK", func () {
|
||||||
|
log.Info("should", hs.dnsAction.S, "here for", hs.dnsValue.S)
|
||||||
|
if (hs.dnsAction.S == "DELETE") {
|
||||||
|
hs.deleteDNSrecord(hs.dnsValue.S)
|
||||||
|
}
|
||||||
|
if (hs.dnsAction.S == "CREATE") {
|
||||||
|
hs.createDNSrecord(hs.dnsValue.S)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
group.Pad()
|
||||||
|
grid.Pad()
|
||||||
|
|
||||||
hs.hidden = false
|
hs.hidden = false
|
||||||
hs.ready = true
|
hs.ready = true
|
||||||
return hs
|
return hs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hs *hostnameStatus) Domain() string {
|
||||||
|
if ! hs.Ready() {return ""}
|
||||||
|
return hs.domainname.Get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs *hostnameStatus) API() string {
|
||||||
|
if ! hs.Ready() {return ""}
|
||||||
|
return hs.dnsAPI.Get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs *hostnameStatus) deleteDNSrecord(value string) bool {
|
||||||
|
log.Info("deleteDNSrecord() START for", value)
|
||||||
|
log.Info("deleteDNSrecord() hostname =", me.hostname)
|
||||||
|
log.Info("deleteDNSrecord() domain =", hs.Domain())
|
||||||
|
log.Info("deleteDNSrecord() DNS API Provider =", hs.API())
|
||||||
|
|
||||||
|
if (hs.API() == "cloudflare") {
|
||||||
|
log.Info("deleteDNSrecord() Try to delete via cloudflare")
|
||||||
|
return cloudflare.Delete(hs.Domain(), me.hostname, value)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hs *hostnameStatus) createDNSrecord(value string) bool {
|
||||||
|
log.Info("createDNSrecord() START for", value)
|
||||||
|
log.Info("createDNSrecord() hostname =", me.hostname)
|
||||||
|
log.Info("createDNSrecord() domain =", hs.Domain())
|
||||||
|
log.Info("createDNSrecord() DNS API Provider =", hs.API())
|
||||||
|
|
||||||
|
if (hs.API() == "cloudflare") {
|
||||||
|
log.Info("createDNSrecord() Try to delete via cloudflare")
|
||||||
|
return cloudflare.Create(hs.Domain(), me.hostname, value)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (hs *hostnameStatus) Update() {
|
func (hs *hostnameStatus) Update() {
|
||||||
log.Info("hostnameStatus() Update() START")
|
log.Info("hostnameStatus() Update() START")
|
||||||
if hs == nil {
|
if hs == nil {
|
||||||
|
@ -174,23 +241,45 @@ func (hs *hostnameStatus) set(a any, s string) {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// figure out if I'm missing any IPv6 address in DNS
|
||||||
|
func (hs *hostnameStatus) missingAAAA() bool {
|
||||||
|
var aaaa []string
|
||||||
|
aaaa = dhcpAAAA()
|
||||||
|
for _, s := range aaaa {
|
||||||
|
debug(LogNet, "my actual AAAA = ",s)
|
||||||
|
hs.dnsValue.SetText(s)
|
||||||
|
hs.dnsAction.SetText("CREATE")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (hs *hostnameStatus) updateStatus() {
|
func (hs *hostnameStatus) updateStatus() {
|
||||||
var s string
|
var s string
|
||||||
var vals []string
|
var vals []string
|
||||||
log.Info("updateStatus() START")
|
log.Info("updateStatus() START")
|
||||||
if ! hs.Ready() { return }
|
if ! hs.Ready() { return }
|
||||||
|
|
||||||
|
hs.hostShort.Set(me.hostshort.S)
|
||||||
|
hs.domainname.Set(me.domainname.S)
|
||||||
|
|
||||||
vals = lookupDoH(hs.hostname, "AAAA")
|
vals = lookupDoH(hs.hostname, "AAAA")
|
||||||
|
|
||||||
log.Println("IPv6 Addresses for ", hs.hostname, "=", vals)
|
log.Println("DNS IPv6 Addresses for ", hs.hostname, "=", vals)
|
||||||
if len(vals) == 0 {
|
if len(vals) == 0 {
|
||||||
s = "(none)"
|
s = "(none)"
|
||||||
hs.setIPv6("NEED VPN")
|
hs.setIPv6("Check for real IPv6 addresses here")
|
||||||
|
if hs.missingAAAA() {
|
||||||
|
hs.setIPv6("Add the missing IPv6 address")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, addr := range vals {
|
for _, addr := range vals {
|
||||||
log.Println(addr)
|
log.Println(addr)
|
||||||
s += addr + " (DELETE)"
|
s += addr + " (DELETE)"
|
||||||
hs.setIPv6("NEEDS DELETE")
|
hs.setIPv6("NEEDS DELETE")
|
||||||
|
hs.dnsValue.SetText(addr)
|
||||||
|
hs.dnsAction.SetText("DELETE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hs.set(hs.dnsAAAA, s)
|
hs.set(hs.dnsAAAA, s)
|
||||||
|
|
Loading…
Reference in New Issue