Compare commits

..

No commits in common. "15d9f9769360b1cb8c748de8ee995030ade5eb35" and "2d1e3213261bee4640c11d8e1f526fcb6234e037" have entirely different histories.

25 changed files with 1185 additions and 1730 deletions

25
args.go
View File

@ -18,14 +18,11 @@ var args struct {
VerboseDNS bool `arg:"--verbose-dns" help:"debug your dns settings"` VerboseDNS bool `arg:"--verbose-dns" help:"debug your dns settings"`
} }
var NOW log.LogFlag
var INFO log.LogFlag
var NET log.LogFlag var NET log.LogFlag
var DNS log.LogFlag var NOW log.LogFlag
var PROC log.LogFlag var PROC log.LogFlag
var SPEW log.LogFlag var SPEW log.LogFlag
var CHANGE log.LogFlag var CHANGE log.LogFlag
var STATUS log.LogFlag
func init() { func init() {
arg.MustParse(&args) arg.MustParse(&args)
@ -37,24 +34,12 @@ func init() {
NOW.Desc = "temp debugging stuff" NOW.Desc = "temp debugging stuff"
NOW.Register() NOW.Register()
INFO.B = false
INFO.Name = "INFO"
INFO.Subsystem = "cpdns"
INFO.Desc = "normal debugging stuff"
INFO.Register()
NET.B = false NET.B = false
NET.Name = "NET" NET.Name = "NET"
NET.Subsystem = "cpdns" NET.Subsystem = "cpdns"
NET.Desc = "Network logging" NET.Desc = "Network logging"
NET.Register() NET.Register()
DNS.B = false
DNS.Name = "DNS"
DNS.Subsystem = "cpdns"
DNS.Desc = "dnsStatus.update()"
DNS.Register()
PROC.B = false PROC.B = false
PROC.Name = "PROC" PROC.Name = "PROC"
PROC.Subsystem = "cpdns" PROC.Subsystem = "cpdns"
@ -67,18 +52,12 @@ func init() {
SPEW.Desc = "spew logging" SPEW.Desc = "spew logging"
SPEW.Register() SPEW.Register()
CHANGE.B = true CHANGE.B = false
CHANGE.Name = "CHANGE" CHANGE.Name = "CHANGE"
CHANGE.Subsystem = "cpdns" CHANGE.Subsystem = "cpdns"
CHANGE.Desc = "show droplet state changes" CHANGE.Desc = "show droplet state changes"
CHANGE.Register() CHANGE.Register()
STATUS.B = false
STATUS.Name = "STATUS"
STATUS.Subsystem = "cpdns"
STATUS.Desc = "updateStatus()"
STATUS.Register()
if debugger.ArgDebug() { if debugger.ArgDebug() {
log.Log(true, "INIT() gui debug == true") log.Log(true, "INIT() gui debug == true")
} else { } else {

View File

@ -1,314 +0,0 @@
/*
'dig'
This is essentially doing what the command 'dig' does
It performing DNS queries on TCP and UDP
against localhost, cloudflare & google
IPv4() and IPv6() return true if they are working
with the 'gui' package, it can also display the results
*/
package main
import (
"os"
"fmt"
"time"
"strings"
"reflect"
"errors"
"go.wit.com/log"
"go.wit.com/gui/gui"
"go.wit.com/gui/gadgets"
"go.wit.com/shell"
)
type digStatus struct {
ready bool
hidden bool
statusIPv4 string
statusIPv6 string
parent *gui.Node
window *gadgets.BasicWindow
group *gui.Node
grid *gui.Node
summary *gui.Node
status *gadgets.OneLiner
statusAAAA *gadgets.OneLiner
speed *gadgets.OneLiner
speedActual *gadgets.OneLiner
details *gui.Node
dsLocalhost *resolverStatus
dsLocalNetwork *resolverStatus
dsCloudflare *resolverStatus
dsGoogle *resolverStatus
DnsDigUDP *gui.Node
DnsDigTCP *gui.Node
httpGoWitCom *gadgets.OneLiner
statusHTTP *gadgets.OneLiner
}
func NewDigStatusWindow(p *gui.Node) *digStatus {
var ds *digStatus
ds = new(digStatus)
ds.ready = false
ds.hidden = true
ds.window = gadgets.NewBasicWindow(p, "DNS Resolver Status")
ds.window.Draw()
ds.window.Hide()
// summary of the current state of things
ds.summary = ds.window.Box().NewGroup("Summary")
g := ds.summary.NewGrid("LookupStatus", 2, 2)
g.Pad()
ds.status = gadgets.NewOneLiner(g, "status").Set("unknown")
ds.statusAAAA = gadgets.NewOneLiner(g, "IPv6 status").Set("unknown")
ds.statusHTTP = gadgets.NewOneLiner(g, "IPv6 via HTTP").Set("unknown")
ds.speed = gadgets.NewOneLiner(g, "speed").Set("unknown")
ds.speedActual = gadgets.NewOneLiner(g, "actual").Set("unknown")
// make the area to store the raw details
ds.details = ds.window.Box().NewGroup("Details")
ds.dsLocalhost = NewResolverStatus(ds.details, "(localhost)", "127.0.0.1:53", "go.wit.com")
ds.dsLocalNetwork = NewResolverStatus(ds.details, "(Local Network)", "192.168.86.1:53", "go.wit.com")
ds.dsCloudflare = NewResolverStatus(ds.details, "(cloudflare)", "1.1.1.1:53", "go.wit.com")
ds.dsGoogle = NewResolverStatus(ds.details, "(google)", "8.8.8.8:53", "go.wit.com")
ds.makeDnsStatusGrid()
ds.makeHttpStatusGrid()
ds.hidden = false
ds.ready = true
return ds
}
func (ds *digStatus) Update() {
log.Info("digStatus() Update() START")
if ds == nil {
log.Error(errors.New("digStatus() Update() ds == nil"))
return
}
duration := timeFunction(func () {
ds.updateDnsStatus()
})
s := fmt.Sprint(duration)
// ds.speedActual.Set(s)
me.digStatus.set(ds.speedActual, s)
if (duration > 500 * time.Millisecond ) {
me.digStatus.set(ds.speed, "SLOW")
} else if (duration > 100 * time.Millisecond ) {
me.digStatus.set(ds.speed, "OK")
} else {
me.digStatus.set(ds.speed, "FAST")
}
log.Info("digStatus() Update() END")
}
// Returns true if the status is valid
func (ds *digStatus) Ready() bool {
if ds == nil {return false}
return ds.ready
}
// Returns true if IPv4 is working
func (ds *digStatus) IPv4() bool {
if ! ds.Ready() {return false}
if (ds.statusIPv4 == "OK") {
return true
}
if (ds.statusIPv4 == "GOOD") {
return true
}
return false
}
// Returns true if IPv6 is working
func (ds *digStatus) IPv6() bool {
if ! ds.Ready() {return false}
if (ds.statusIPv6 == "GOOD") {
return true
}
return false
}
func (ds *digStatus) setIPv4status(s string) {
ds.statusIPv4 = s
if ! ds.Ready() {return}
me.digStatus.set(ds.status, s)
}
func (ds *digStatus) setIPv6status(s string) {
ds.statusIPv6 = s
if ! ds.Ready() {return}
me.digStatus.set(ds.statusAAAA, s)
}
func (ds *digStatus) SetIPv6(s string) {
if ! ds.Ready() {return}
log.Warn("Should SetIPv6() here to", s)
log.Warn("Should SetIPv6() here to", s)
log.Warn("Should SetIPv6() here to", s)
log.Warn("Should SetIPv6() here to", s)
me.DnsAAAA.Set(s)
// me.digStatus.set(ds.httpGoWitCom, addr)
}
func (ds *digStatus) set(a any, s string) {
if ! ds.Ready() {return}
if ds.hidden {
return
}
if a == nil {
return
}
var n *gui.Node
if reflect.TypeOf(a) == reflect.TypeOf(n) {
n = a.(*gui.Node)
n.SetText(s)
return
}
var ol *gadgets.OneLiner
if reflect.TypeOf(a) == reflect.TypeOf(ol) {
ol = a.(*gadgets.OneLiner)
ol.Set(s)
return
}
log.Warn("unknown type TypeOf(a) =", reflect.TypeOf(a), "a =", a)
os.Exit(0)
}
func (ds *digStatus) updateDnsStatus() {
var cmd, out string
var ipv4, ipv6 bool
log.Info("updateDnsStatus() START")
if (ds == nil) {
log.Error(errors.New("updateDnsStatus() not initialized yet. ds == nil"))
return
}
if (! ds.ready) {
log.Error(errors.New("updateDnsStatus() not ready yet"))
return
}
ipv4, ipv6 = ds.dsLocalhost.update()
ipv4, ipv6 = ds.dsLocalNetwork.update()
ipv4, ipv6 = ds.dsCloudflare.update()
ipv4, ipv6 = ds.dsGoogle.update()
if me.statusOS.ValidHostname() {
if ds.checkLookupDoH(me.statusOS.GetHostname()) {
log.Log(DNS, "updateDnsStatus() HTTP DNS lookups working")
me.digStatus.set(ds.statusHTTP, "WORKING")
} else {
log.Log(DNS, "updateDnsStatus() HTTP DNS lookups not working")
log.Log(DNS, "updateDnsStatus() It's really unlikely you are on the internet")
me.digStatus.set(ds.statusHTTP, "BROKEN")
}
} else {
me.digStatus.set(ds.statusHTTP, "INVALID HOSTNAME")
}
if (ipv4) {
log.Log(DNS, "updateDnsStatus() IPv4 A lookups working")
ds.setIPv4status("OK")
} else {
log.Log(DNS, "updateDnsStatus() IPv4 A lookups not working. No internet?")
ds.setIPv4status("No Internet?")
}
if (ipv6) {
log.Log(DNS, "updateDnsStatus() IPv6 AAAA lookups working")
ds.setIPv4status("GOOD")
ds.setIPv6status("GOOD")
} else {
log.Log(DNS, "updateDnsStatus() IPv6 AAAA lookups are not working")
ds.setIPv6status("Need VPN")
}
cmd = "dig +noall +answer www.wit.com A"
out = shell.Run(cmd)
log.Log(DNS, "makeDnsStatusGrid() dig", out)
me.digStatus.set(ds.DnsDigUDP, out)
cmd = "dig +noall +answer www.wit.com AAAA"
out = shell.Run(cmd)
log.Log(DNS, "makeDnsStatusGrid() dig", out)
me.digStatus.set(ds.DnsDigTCP, out)
}
func (ds *digStatus) makeHttpStatusGrid() {
group := ds.details.NewGroup("dns.google.com via HTTPS")
grid := group.NewGrid("LookupStatus", 2, 2)
ds.httpGoWitCom = gadgets.NewOneLiner(grid, "go.wit.com")
me.digStatus.set(ds.httpGoWitCom, "unknown")
group.Pad()
grid.Pad()
}
func (ds *digStatus) makeDnsStatusGrid() {
var cmd, out string
group := ds.details.NewGroup("dig results")
grid := group.NewGrid("LookupStatus", 2, 2)
cmd = "dig +noall +answer go.wit.com A"
grid.NewLabel(cmd)
ds.DnsDigUDP = grid.NewLabel("?")
out = shell.Run(cmd)
log.Log(DNS, "makeDnsStatusGrid() dig", out)
me.digStatus.set(ds.DnsDigUDP, out)
cmd = "dig +noall +answer go.wit.com AAAA"
grid.NewLabel(cmd)
ds.DnsDigTCP = grid.NewLabel("?")
out = shell.Run(cmd)
log.Log(DNS, "makeDnsStatusGrid() dig", out)
me.digStatus.set(ds.DnsDigTCP, out)
group.Pad()
grid.Pad()
}
func (ds *digStatus) checkLookupDoH(hostname string) bool {
var status bool = false
ipv6Addresses := lookupDoH(hostname, "AAAA")
log.Log(DNS, "IPv6 Addresses for ", hostname)
var s []string
for _, addr := range ipv6Addresses {
log.Log(DNS, addr)
s = append(s, addr)
status = true
}
me.digStatus.SetIPv6(strings.Join(s, "\n"))
return status
}
func (ds *digStatus) Show() {
log.Info("digStatus.Show() window")
if me.digStatus.hidden {
me.digStatus.window.Show()
}
me.digStatus.hidden = false
}
func (ds *digStatus) Hide() {
log.Info("digStatus.Hide() window")
if ! me.digStatus.hidden {
me.digStatus.window.Hide()
}
me.digStatus.hidden = true
}

View File

@ -2,27 +2,76 @@ package main
import ( import (
"fmt" "fmt"
"strings" "go.wit.com/log"
"io/ioutil" "io/ioutil"
"encoding/json" "encoding/json"
"net/http" "net/http"
"go.wit.com/log"
"github.com/miekg/dns"
) )
/*
func getAAAArecords() {
hostname := "go.wit.com"
ipv6Addresses, err := dnsLookupDoH(hostname)
if err != nil {
log.Error(err, "getAAAArecords")
return
}
fmt.Printf("IPv6 Addresses for %s:\n", hostname)
for _, addr := range ipv6Addresses {
log.Println(addr)
}
}
*/
// dnsLookupDoH performs a DNS lookup for AAAA records over HTTPS.
func dnsAAAAlookupDoH(domain string) ([]string, error) {
var ipv6Addresses []string
// Construct the URL for a DNS query with Google's DNS-over-HTTPS API
url := fmt.Sprintf("https://dns.google/resolve?name=%s&type=AAAA", domain)
log.Println("curl", url)
// Perform the HTTP GET request
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("error performing DNS-over-HTTPS request: %w", err)
}
defer resp.Body.Close()
// Read and unmarshal the response body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error reading response: %w", err)
}
var data struct {
Answer []struct {
Data string `json:"data"`
} `json:"Answer"`
}
if err := json.Unmarshal(body, &data); err != nil {
return nil, fmt.Errorf("error unmarshaling response: %w", err)
}
// Extract the IPv6 addresses
for _, answer := range data.Answer {
ipv6Addresses = append(ipv6Addresses, answer.Data)
}
return ipv6Addresses, nil
}
// dnsLookupDoH performs a DNS lookup for AAAA records over HTTPS. // dnsLookupDoH performs a DNS lookup for AAAA records over HTTPS.
func lookupDoH(hostname string, rrType string) []string { func lookupDoH(hostname string, rrType string) []string {
var values []string var values []string
// Construct the URL for a DNS query with Google's DNS-over-HTTPS API // Construct the URL for a DNS query with Google's DNS-over-HTTPS API
url := fmt.Sprintf("https://dns.google.com/resolve?name=%s&type=%s", hostname, rrType) url := fmt.Sprintf("https://dns.google/resolve?name=%s&type=%s", hostname, rrType)
log.Log(DNS, "lookupDoH()", url) log.Println("curl", url)
if hostname == "" {
log.Warn("lookupDoH() was sent a empty hostname")
return nil
}
// Perform the HTTP GET request // Perform the HTTP GET request
resp, err := http.Get(url) resp, err := http.Get(url)
@ -57,28 +106,3 @@ func lookupDoH(hostname string, rrType string) []string {
return values return values
} }
func digAAAA(hostname string) []string {
var blah, ipv6Addresses []string
// domain := hostname
recordType := dns.TypeAAAA // dns.TypeTXT
// Cloudflare's DNS server
blah, _ = dnsUdpLookup("1.1.1.1:53", hostname, recordType)
log.Println("digAAAA() has BLAH =", blah)
if (len(blah) == 0) {
log.Println("digAAAA() RUNNING dnsAAAAlookupDoH(domain)")
ipv6Addresses = lookupDoH(hostname, "AAAA")
log.Println("digAAAA() has ipv6Addresses =", strings.Join(ipv6Addresses, " "))
for _, addr := range ipv6Addresses {
log.Println(addr)
}
return ipv6Addresses
}
// TODO: check digDoH vs blah, if so, then port 53 TCP and/or UDP is broken or blocked
log.Println("digAAAA() has BLAH =", blah)
return blah
}

4
dns.go
View File

@ -111,10 +111,10 @@ func lookupNS(domain string) {
} }
tmp = shell.Chomp(tmp) tmp = shell.Chomp(tmp)
if (tmp != me.status.NSrr.Get()) { if (tmp != me.NSrr.S) {
me.changed = true me.changed = true
log.Log(CHANGE, "lookupNS() setting me.NSrr =", tmp) log.Log(CHANGE, "lookupNS() setting me.NSrr =", tmp)
me.status.NSrr.Set(tmp) me.NSrr.SetText(tmp)
} }
} }

476
dnsLookupStatus.go Normal file
View File

@ -0,0 +1,476 @@
/*
'dig'
This is essentially doing what the command 'dig' does
It performing DNS queries on TCP and UDP
against localhost, cloudflare & google
IPv4() and IPv6() return true if they are working
with the 'gui' package, it can also display the results
*/
package main
import (
"os"
"fmt"
"time"
"strconv"
"reflect"
"errors"
"go.wit.com/log"
"go.wit.com/gui/gui"
"go.wit.com/gui/gadgets"
"go.wit.com/shell"
"github.com/miekg/dns"
)
type digStatus struct {
ready bool
hidden bool
statusIPv4 string
statusIPv6 string
parent *gui.Node
window *gadgets.BasicWindow
group *gui.Node
grid *gui.Node
summary *gui.Node
status *gadgets.OneLiner
statusAAAA *gadgets.OneLiner
speed *gadgets.OneLiner
speedActual *gadgets.OneLiner
details *gui.Node
dsLocalhost *dnsStatus
dsLocalNetwork *dnsStatus
dsCloudflare *dnsStatus
dsGoogle *dnsStatus
DnsDigUDP *gui.Node
DnsDigTCP *gui.Node
httpGoWitCom *gadgets.OneLiner
statusHTTP *gadgets.OneLiner
}
type dnsStatus struct {
title string
server string // The DNS server. Example: "127.0.0.1:53" or "1.1.1.1:53"
hostname string // the hostname to lookup. Example: "www.google.com" or "go.wit.com"
parent *gui.Node
group *gui.Node
grid *gui.Node
// DNS setup options
udpA *gui.Node
tcpA *gui.Node
udpAAAA *gui.Node
tcpAAAA *gui.Node
// show the display
aFail *gui.Node
aSuccess *gui.Node
aaaaFail *gui.Node
aaaaSuccess *gui.Node
// interger counters
aFailc int
aSuccessc int
aaaaFailc int
aaaaSuccessc int
}
func NewDigStatusWindow(p *gui.Node) *digStatus {
var ds *digStatus
ds = new(digStatus)
ds.ready = false
ds.hidden = true
ds.window = gadgets.NewBasicWindow(p, "DNS Resolver Status")
ds.window.Draw()
ds.window.Hide()
// summary of the current state of things
ds.summary = ds.window.Box().NewGroup("Summary")
g := ds.summary.NewGrid("LookupStatus", 2, 2)
g.Pad()
ds.status = gadgets.NewOneLiner(g, "status").Set("unknown")
ds.statusAAAA = gadgets.NewOneLiner(g, "IPv6 status").Set("unknown")
ds.statusHTTP = gadgets.NewOneLiner(g, "IPv6 via HTTP").Set("unknown")
ds.speed = gadgets.NewOneLiner(g, "speed").Set("unknown")
ds.speedActual = gadgets.NewOneLiner(g, "actual").Set("unknown")
// make the area to store the raw details
ds.details = ds.window.Box().NewGroup("Details")
ds.dsLocalhost = NewDnsStatus(ds.details, "(localhost)", "127.0.0.1:53", "go.wit.com")
ds.dsLocalNetwork = NewDnsStatus(ds.details, "(Local Network)", "172.22.0.1:53", "go.wit.com")
ds.dsCloudflare = NewDnsStatus(ds.details, "(cloudflare)", "1.1.1.1:53", "go.wit.com")
ds.dsGoogle = NewDnsStatus(ds.details, "(google)", "8.8.8.8:53", "go.wit.com")
ds.makeDnsStatusGrid()
ds.makeHttpStatusGrid()
ds.hidden = false
ds.ready = true
return ds
}
func (ds *digStatus) Update() {
log.Info("digStatus() Update() START")
if ds == nil {
log.Error(errors.New("digStatus() Update() ds == nil"))
return
}
duration := timeFunction(func () {
ds.updateDnsStatus()
})
s := fmt.Sprint(duration)
// ds.speedActual.Set(s)
me.digStatus.set(ds.speedActual, s)
if (duration > 500 * time.Millisecond ) {
me.digStatus.set(ds.speed, "SLOW")
} else if (duration > 100 * time.Millisecond ) {
me.digStatus.set(ds.speed, "OK")
} else {
me.digStatus.set(ds.speed, "FAST")
}
log.Info("digStatus() Update() END")
}
// Returns true if the status is valid
func (ds *digStatus) Ready() bool {
if ds == nil {return false}
return ds.ready
}
// Returns true if IPv4 is working
func (ds *digStatus) IPv4() bool {
if ! ds.Ready() {return false}
if (ds.statusIPv4 == "OK") {
return true
}
if (ds.statusIPv4 == "GOOD") {
return true
}
return false
}
// Returns true if IPv6 is working
func (ds *digStatus) IPv6() bool {
if ! ds.Ready() {return false}
if (ds.statusIPv6 == "GOOD") {
return true
}
return false
}
func (ds *digStatus) setIPv4(s string) {
ds.statusIPv4 = s
if ! ds.Ready() {return}
me.digStatus.set(ds.status, s)
}
func (ds *digStatus) setIPv6(s string) {
ds.statusIPv6 = s
if ! ds.Ready() {return}
me.digStatus.set(ds.statusAAAA, s)
}
func (ds *digStatus) set(a any, s string) {
if ! ds.Ready() {return}
if ds.hidden {
return
}
if a == nil {
return
}
var n *gui.Node
if reflect.TypeOf(a) == reflect.TypeOf(n) {
n = a.(*gui.Node)
n.SetText(s)
return
}
var ol *gadgets.OneLiner
if reflect.TypeOf(a) == reflect.TypeOf(ol) {
ol = a.(*gadgets.OneLiner)
ol.Set(s)
return
}
log.Warn("unknown type TypeOf(a) =", reflect.TypeOf(a), "a =", a)
os.Exit(0)
}
func (ds *digStatus) updateDnsStatus() {
var cmd, out string
var ipv4, ipv6 bool
log.Info("updateDnsStatus() START")
if (ds == nil) {
log.Error(errors.New("updateDnsStatus() not initialized yet. ds == nil"))
return
}
if (! ds.ready) {
log.Error(errors.New("updateDnsStatus() not ready yet"))
return
}
ipv4, ipv6 = ds.dsLocalhost.update()
ipv4, ipv6 = ds.dsLocalNetwork.update()
ipv4, ipv6 = ds.dsCloudflare.update()
ipv4, ipv6 = ds.dsGoogle.update()
if ds.checkLookupDoH("go.wit.com") {
log.Println("updateDnsStatus() HTTP DNS lookups working")
me.digStatus.set(ds.statusHTTP, "WORKING")
} else {
log.Println("updateDnsStatus() HTTP DNS lookups not working")
log.Println("updateDnsStatus() It's really unlikely you are on the internet")
me.digStatus.set(ds.statusHTTP, "BROKEN")
}
if (ipv4) {
log.Println("updateDnsStatus() IPv4 A lookups working")
ds.setIPv4("OK")
} else {
log.Println("updateDnsStatus() IPv4 A lookups not working. No internet?")
ds.setIPv4("No Internet?")
}
if (ipv6) {
log.Println("updateDnsStatus() IPv6 AAAA lookups working")
ds.setIPv4("GOOD")
ds.setIPv6("GOOD")
} else {
log.Println("updateDnsStatus() IPv6 AAAA lookups are not working")
ds.setIPv6("Need VPN")
}
cmd = "dig +noall +answer www.wit.com A"
out = shell.Run(cmd)
log.Println("makeDnsStatusGrid() dig", out)
me.digStatus.set(ds.DnsDigUDP, out)
cmd = "dig +noall +answer www.wit.com AAAA"
out = shell.Run(cmd)
log.Println("makeDnsStatusGrid() dig", out)
me.digStatus.set(ds.DnsDigTCP, out)
}
// Makes a DNS Status Grid
func NewDnsStatus(p *gui.Node, title string, server string, hostname string) *dnsStatus {
var ds *dnsStatus
ds = new(dnsStatus)
ds.parent = p
ds.group = p.NewGroup(server + " " + title + " lookup")
ds.grid = ds.group.NewGrid("LookupStatus", 5, 2)
ds.server = server
ds.hostname = hostname
ds.grid.NewLabel("")
ds.grid.NewLabel("UDP")
ds.grid.NewLabel("TCP")
ds.grid.NewLabel("Success")
ds.grid.NewLabel("Fail")
ds.grid.NewLabel("A")
ds.udpA = ds.grid.NewLabel("?")
ds.tcpA = ds.grid.NewLabel("?")
ds.aSuccess = ds.grid.NewLabel("?")
ds.aFail = ds.grid.NewLabel("?")
ds.grid.NewLabel("AAAA")
ds.udpAAAA = ds.grid.NewLabel("?")
ds.tcpAAAA = ds.grid.NewLabel("?")
ds.aaaaSuccess = ds.grid.NewLabel("?")
ds.aaaaFail = ds.grid.NewLabel("?")
ds.group.Margin()
ds.grid.Margin()
ds.group.Pad()
ds.grid.Pad()
return ds
}
// special thanks to the Element Hotel wifi in Philidelphia that allowed me to
// easily debug this code since the internet connection here blocks port 53 traffic
func (ds *dnsStatus) update() (bool, bool) {
var results []string
var a bool = false
var aaaa bool = false
log.Println("dnsStatus.update() For server", ds.server, "on", ds.hostname)
results, _ = dnsUdpLookup(ds.server, ds.hostname, dns.TypeA)
log.Println("dnsStatus.update() UDP type A =", results)
if (len(results) == 0) {
me.digStatus.set(ds.udpA, "BROKEN")
ds.aFailc += 1
} else {
me.digStatus.set(ds.udpA, "WORKING")
ds.aSuccessc += 1
a = true
}
results, _ = dnsTcpLookup(ds.server, ds.hostname, dns.TypeA)
log.Println("dnsStatus.update() TCP type A =", results)
if (len(results) == 0) {
me.digStatus.set(ds.tcpA, "BROKEN")
ds.aFailc += 1
} else {
me.digStatus.set(ds.tcpA, "WORKING")
ds.aSuccessc += 1
a = true
}
me.digStatus.set(ds.aFail, strconv.Itoa(ds.aFailc))
me.digStatus.set(ds.aSuccess,strconv.Itoa(ds.aSuccessc))
results, _ = dnsUdpLookup(ds.server, ds.hostname, dns.TypeAAAA)
log.Println("dnsStatus.update() UDP type AAAA =", results)
if (len(results) == 0) {
me.digStatus.set(ds.udpAAAA, "BROKEN")
ds.aaaaFailc += 1
me.digStatus.set(ds.aaaaFail, strconv.Itoa(ds.aaaaFailc))
} else {
me.digStatus.set(ds.udpAAAA, "WORKING")
ds.aaaaSuccessc += 1
aaaa = true
}
results, _ = dnsTcpLookup(ds.server, ds.hostname, dns.TypeAAAA)
log.Println("dnsStatus.update() UDP type AAAA =", results)
if (len(results) == 0) {
me.digStatus.set(ds.tcpAAAA, "BROKEN")
ds.aaaaFailc += 1
me.digStatus.set(ds.aaaaFail, strconv.Itoa(ds.aaaaFailc))
} else {
me.digStatus.set(ds.tcpAAAA, "WORKING")
ds.aaaaSuccessc += 1
aaaa = true
}
me.digStatus.set(ds.aaaaFail, strconv.Itoa(ds.aaaaFailc))
me.digStatus.set(ds.aaaaSuccess,strconv.Itoa(ds.aaaaSuccessc))
return a, aaaa
}
func (ds *digStatus) makeHttpStatusGrid() {
group := ds.details.NewGroup("dns.google.com via HTTPS")
grid := group.NewGrid("LookupStatus", 2, 2)
ds.httpGoWitCom = gadgets.NewOneLiner(grid, "go.wit.com")
me.digStatus.set(ds.httpGoWitCom, "unknown")
group.Pad()
grid.Pad()
}
func (ds *digStatus) makeDnsStatusGrid() {
var cmd, out string
group := ds.details.NewGroup("dig results")
grid := group.NewGrid("LookupStatus", 2, 2)
cmd = "dig +noall +answer go.wit.com A"
grid.NewLabel(cmd)
ds.DnsDigUDP = grid.NewLabel("?")
out = shell.Run(cmd)
log.Println("makeDnsStatusGrid() dig", out)
me.digStatus.set(ds.DnsDigUDP, out)
cmd = "dig +noall +answer go.wit.com AAAA"
grid.NewLabel(cmd)
ds.DnsDigTCP = grid.NewLabel("?")
out = shell.Run(cmd)
log.Println("makeDnsStatusGrid() dig", out)
me.digStatus.set(ds.DnsDigTCP, out)
group.Pad()
grid.Pad()
}
// dnsLookup performs a DNS lookup for the specified record type (e.g., "TXT", "AAAA") for a given domain.
func dnsUdpLookup(server string, domain string, recordType uint16) ([]string, error) {
var records []string
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), recordType)
r, _, err := c.Exchange(m, server) // If server = "1.1.1.1:53" then use Cloudflare's DNS server
if err != nil {
return nil, err
}
for _, ans := range r.Answer {
records = append(records, ans.String())
}
return records, nil
}
func dnsTcpLookup(server string, domain string, recordType uint16) ([]string, error) {
var records []string
c := new(dns.Client)
c.Net = "tcp" // Specify to use TCP for the query
c.Timeout = time.Second * 5 // Set a 5-second timeout
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), recordType)
r, _, err := c.Exchange(m, server) // If server = "1.1.1.1:53" then use Cloudflare's DNS server
if err != nil {
return nil, err
}
for _, ans := range r.Answer {
records = append(records, ans.String())
}
return records, nil
}
func (ds *digStatus) checkLookupDoH(hostname string) bool {
var status bool = false
domain := "go.wit.com"
ipv6Addresses, err := dnsAAAAlookupDoH(domain)
if err != nil {
log.Error(err, "checkLookupDoH()")
return status
}
log.Println("IPv6 Addresses for %s:\n", domain)
for _, addr := range ipv6Addresses {
log.Println(addr)
me.digStatus.set(ds.httpGoWitCom, addr)
status = true
}
return status
}
func (ds *digStatus) Show() {
log.Info("digStatus.Show() window")
if me.digStatus.hidden {
me.digStatus.window.Show()
}
me.digStatus.hidden = false
}
func (ds *digStatus) Hide() {
log.Info("digStatus.Hide() window")
if ! me.digStatus.hidden {
me.digStatus.window.Hide()
}
me.digStatus.hidden = true
}

44
fix.go
View File

@ -1,44 +0,0 @@
// This creates a simple hello world window
package main
import (
"go.wit.com/log"
)
func fix() bool {
log.Warn("")
if ! me.status.Ready() {
log.Warn("The IPv6 Control Panel is not Ready() yet")
return false
}
if me.statusOS.ValidHostname() {
log.Warn("Your hostname is VALID:", me.statusOS.GetHostname())
} else {
log.Warn("You must first fix your hostname:", me.statusOS.GetHostname())
return false
}
if me.digStatus.IPv4() {
log.Warn("IPv4 addresses are resolving")
} else {
log.Warn("You must first figure out why you can't look up IPv4 addresses")
log.Warn("Are you on the internet at all?")
return false
}
if me.digStatus.IPv6() {
log.Warn("IPv6 addresses are resolving")
} else {
log.Warn("You must first figure out why you can't look up IPv6 addresses")
return false
}
if ! me.status.IPv4() {
log.Warn("You do not have real IPv4 addresses. Nothing to fix here")
}
if ! me.status.IPv6() {
log.Warn("IPv6 DNS is broken. Check what is broken here")
log.Warn("What are my IPv6 addresses?")
log.Warn("What are the AAAA resource records in DNS?")
return false
}
log.Warn("YOU SHOULD BE IN IPv6 BLISS")
return true
}

194
gui.go
View File

@ -4,15 +4,18 @@ package main
import ( import (
"time" "time"
"os" "os"
"os/user"
"strconv"
// "net"
"strings" "strings"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/shell"
"go.wit.com/gui/gui" "go.wit.com/gui/gui"
"go.wit.com/gui/gadgets" "go.wit.com/gui/gadgets"
"go.wit.com/gui/cloudflare" "go.wit.com/gui/cloudflare"
"go.wit.com/gui/debugger" "go.wit.com/gui/debugger"
"go.wit.com/control-panels/dns/linuxstatus"
) )
// This setups up the dns control panel window // This setups up the dns control panel window
@ -22,7 +25,56 @@ func setupControlPanelWindow() {
// setup the main tab // setup the main tab
mainWindow("DNS and IPv6 Control Panel") mainWindow("DNS and IPv6 Control Panel")
detailsTab("OS Details")
debugTab("Debug") debugTab("Debug")
// me.digStatus = NewDigStatusWindow(me.window)
}
func detailsTab(title string) {
var g2 *gui.Node
me.details = gadgets.NewBasicWindow(me.myGui, title)
me.details.Draw()
me.details.Hide()
g2 = me.details.Box().NewGroup("Real Stuff")
grid := g2.NewGrid("gridnuts", 2, 2)
grid.SetNext(1,1)
grid.NewLabel("domainname =")
me.domainname = grid.NewLabel("domainname")
grid.NewLabel("hostname -s =")
me.hostshort = grid.NewLabel("hostname -s")
grid.NewLabel("NS records =")
me.NSrr = grid.NewLabel("NS RR's")
grid.NewLabel("UID =")
me.uid = grid.NewLabel("my uid")
grid.NewLabel("Current IPv4 =")
me.IPv4 = grid.NewLabel("?")
grid.NewLabel("Current IPv6 =")
me.IPv6 = grid.NewLabel("?")
grid.NewLabel("Working Real IPv6 =")
me.workingIPv6 = grid.NewLabel("?")
grid.NewLabel("interfaces =")
me.Interfaces = grid.NewCombobox("Interfaces")
grid.NewLabel("refresh speed")
me.LocalSpeedActual = grid.NewLabel("unknown")
grid.Margin()
grid.Pad()
me.details.Hide()
} }
func debugTab(title string) { func debugTab(title string) {
@ -38,20 +90,18 @@ func debugTab(title string) {
debugger.DebugWindow(me.myGui) debugger.DebugWindow(me.myGui)
}) })
g2.NewButton("getHostname() looks at the OS settings", func () {
getHostname()
})
g2.NewButton("dig A & AAAA DNS records", func () { g2.NewButton("dig A & AAAA DNS records", func () {
log.Println("updateDNS()") log.Println("updateDNS()")
updateDNS() updateDNS()
}) })
g2.NewButton("dig +trace", func () { g2.NewButton("dig +trace", func () {
log.Log(NOW, "TODO: redo this") o := shell.Run("dig +trace +noadditional DS " + me.hostname + " @8.8.8.8")
// o := shell.Run("dig +trace +noadditional DS " + me.hostname + " @8.8.8.8") log.Println(o)
// log.Println(o)
})
g2.NewButton("getProcessNameByPort()", func () {
processName := getProcessNameByPort(53)
log.Info("Process with port 53:", processName)
}) })
g2 = me.debug.Box().NewGroup("debugging options") g2 = me.debug.Box().NewGroup("debugging options")
@ -98,15 +148,15 @@ func missingAAAA() string {
// it just updates the GUI // it just updates the GUI
func displayDNS() string { func displayDNS() string {
var aaaa []string var aaaa []string
aaaa = append(aaaa, "blah", "more") aaaa = dhcpAAAA() // your AAAA records right now
// h := me.hostname h := me.hostname
var all string var all string
var broken string = "unknown" var broken string = "unknown"
for _, s := range aaaa { for _, s := range aaaa {
log.Log(STATUS, "host", "fixme", "DNS AAAA =", s, "ipmap[s] =", me.ipmap[s]) log.Log(NOW, "host", h, "DNS AAAA =", s, "ipmap[s] =", me.ipmap[s])
all += s + "\n" all += s + "\n"
if ( me.ipmap[s] == nil) { if ( me.ipmap[s] == nil) {
log.Warn("THIS IS THE WRONG AAAA DNS ENTRY: host", "fixme", "DNS AAAA =", s) log.Warn("THIS IS THE WRONG AAAA DNS ENTRY: host", h, "DNS AAAA =", s)
broken = "wrong AAAA entry" broken = "wrong AAAA entry"
} else { } else {
if (broken == "unknown") { if (broken == "unknown") {
@ -114,16 +164,21 @@ func displayDNS() string {
} }
} }
} }
all = sortLines(all)
if (me.workingIPv6.S != all) {
log.Warn("workingIPv6.SetText() to:", all)
me.workingIPv6.SetText(all)
}
var a []string var a []string
a = realA() a = realA()
all = sortLines(strings.Join(a, "\n")) all = sortLines(strings.Join(a, "\n"))
if (all == "") { if (all == "") {
log.Log(NOW, "THERE IS NOT a real A DNS ENTRY") log.Info("THERE IS NOT a real A DNS ENTRY")
all = "CNAME ipv6.wit.com" all = "CNAME ipv6.wit.com"
} }
if (me.DnsA.S != all) { if (me.DnsA.S != all) {
log.Log(NOW, "DnsA.SetText() to:", all) log.Warn("DnsA.SetText() to:", all)
me.DnsA.SetText(all) me.DnsA.SetText(all)
} }
return broken return broken
@ -137,20 +192,26 @@ func myDefaultExit(n *gui.Node) {
func mainWindow(title string) { func mainWindow(title string) {
me.window = gadgets.NewBasicWindow(me.myGui, title) me.window = gadgets.NewBasicWindow(me.myGui, title)
gr := me.window.Box().NewGroup("dns update") me.mainStatus = me.window.Box().NewGroup("dns update")
grid := gr.NewGrid("gridnuts", 2, 2) grid := me.mainStatus.NewGrid("gridnuts", 2, 2)
grid.SetNext(1,1) grid.SetNext(1,1)
me.hostname = gadgets.NewOneLiner(grid, "hostname =").Set("unknown") grid.NewLabel("hostname =")
me.DnsAAAA = gadgets.NewOneLiner(grid, "DNS AAAA =").Set("unknown") me.fqdn = grid.NewLabel("?")
me.hostname = ""
grid.NewLabel("DNS AAAA =")
me.DnsAAAA = grid.NewLabel("?")
grid.NewLabel("DNS A =") grid.NewLabel("DNS A =")
me.DnsA = grid.NewLabel("?") me.DnsA = grid.NewLabel("?")
// This is where you figure out what to do next to fix the problems me.digStatus = NewDigStatusWindow(me.myGui)
gr.NewButton("fix", func () { me.hostnameStatus = NewHostnameStatusWindow(me.myGui)
fix()
me.hostnameStatusButton = me.mainStatus.NewButton("Fix hostname DNS", func () {
me.hostnameStatus.window.Toggle()
}) })
grid.Margin() grid.Margin()
@ -158,44 +219,20 @@ func mainWindow(title string) {
statusGrid(me.window.Box()) statusGrid(me.window.Box())
gr = me.window.Box().NewGroup("debugging") gr := me.window.Box().NewGroup("debugging")
gr.NewButton("hostname status", func () { gr.NewButton("GO GUI Debugger", func () {
if ! me.status.Ready() {return} debugger.DebugWindow(me.myGui)
me.status.window.Toggle()
}) })
gr.NewButton("OS Details", func () {
gr.NewButton("linuxstatus.New()", func () { me.details.Toggle()
if (me.statusOS == nil) {
me.statusOS = linuxstatus.New()
}
me.statusOS.SetParent(me.myGui)
me.statusOS.InitWindow()
me.statusOS.Make()
me.statusOS.Draw2()
}) })
gr.NewButton("statusOS.Ready()", func () { gr.NewButton("DNS Debug", func () {
me.statusOS.Ready() me.debug.Toggle()
}) })
gr.NewButton("statusOS.Draw()", func () { gr.NewButton("Resolver Status", func () {
me.statusOS.Draw()
me.statusOS.Draw2()
})
gr.NewButton("statusOS.Update()", func () {
me.statusOS.Update()
})
gr.NewButton("Linux Status", func () {
me.statusOS.Toggle()
})
gr.NewButton("resolver status", func () {
if ! me.digStatus.Ready() {return} if ! me.digStatus.Ready() {return}
me.digStatus.window.Toggle() me.digStatus.window.Toggle()
}) })
gr.NewButton("cloudflare wit.com", func () {
cloudflare.CreateRR(me.myGui, "wit.com", "3777302ac4a78cd7fa4f6d3f72086d06")
})
gr.NewButton("Debug", func () {
me.debug.Toggle()
})
} }
func statusGrid(n *gui.Node) { func statusGrid(n *gui.Node) {
@ -203,15 +240,15 @@ func statusGrid(n *gui.Node) {
gridP := problems.NewGrid("nuts", 2, 2) gridP := problems.NewGrid("nuts", 2, 2)
gridP.NewLabel("hostname =")
me.hostnameStatus = gridP.NewLabel("invalid")
gridP.NewLabel("DNS Status =") gridP.NewLabel("DNS Status =")
me.DnsStatus = gridP.NewLabel("unknown") me.DnsStatus = gridP.NewLabel("unknown")
me.statusIPv6 = gadgets.NewOneLiner(gridP, "IPv6 working") me.statusIPv6 = gadgets.NewOneLiner(gridP, "IPv6 working")
me.statusIPv6.Set("known") me.statusIPv6.Set("known")
gridP.NewLabel("hostname =")
me.hostnameStatusOLD = gridP.NewLabel("invalid")
gridP.NewLabel("dns resolution") gridP.NewLabel("dns resolution")
me.DnsSpeed = gridP.NewLabel("unknown") me.DnsSpeed = gridP.NewLabel("unknown")
@ -242,27 +279,29 @@ func statusGrid(n *gui.Node) {
// run everything because something has changed // run everything because something has changed
func updateDNS() { func updateDNS() {
var aaaa []string
h := me.hostname
if (h == "") {
h = "test.wit.com"
}
me.digStatus.Update() me.digStatus.Update()
me.status.Update() me.hostnameStatus.Update()
// log.Println("digAAAA()") // log.Println("digAAAA()")
if me.statusOS.ValidHostname() {
var aaaa []string
h := me.statusOS.GetHostname()
aaaa = digAAAA(h) aaaa = digAAAA(h)
log.Log(NOW, "digAAAA() for", h, "=", aaaa) log.Log(NOW, "digAAAA() =", aaaa)
// log.Println(SPEW, me) // log.Println(SPEW, me)
if (aaaa == nil) { if (aaaa == nil) {
log.Warn("There are no DNS AAAA records for hostname: ", h) log.Warn("There are no DNS AAAA records for hostname: ", h)
me.DnsAAAA.Set("(none)") me.DnsAAAA.SetText("(none)")
if (cloudflare.CFdialog.TypeNode != nil) { if (cloudflare.CFdialog.TypeNode != nil) {
cloudflare.CFdialog.TypeNode.SetText("AAAA new") cloudflare.CFdialog.TypeNode.SetText("AAAA new")
} }
if (cloudflare.CFdialog.NameNode != nil) { if (cloudflare.CFdialog.NameNode != nil) {
cloudflare.CFdialog.NameNode.SetText(h) cloudflare.CFdialog.NameNode.SetText(me.hostname)
} }
d := deleteAAA() d := deleteAAA()
@ -288,7 +327,6 @@ func updateDNS() {
*/ */
} }
} }
}
status := displayDNS() // update the GUI based on dig results status := displayDNS() // update the GUI based on dig results
me.DnsStatus.SetText(status) me.DnsStatus.SetText(status)
@ -303,10 +341,32 @@ func updateDNS() {
// me.fix.Enable() // me.fix.Enable()
user, _ := user.Current()
log.Println("os.Getuid =", user.Username, os.Getuid())
if (me.uid != nil) {
me.uid.SetText(user.Username + " (" + strconv.Itoa(os.Getuid()) + ")")
}
// lookup the NS records for your domain // lookup the NS records for your domain
// if your host is test.wit.com, find the NS resource records for wit.com // if your host is test.wit.com, find the NS resource records for wit.com
lookupNS(me.statusOS.GetDomainName()) lookupNS(me.domainname.S)
log.Println("updateDNS() END") log.Println("updateDNS() END")
} }
func suggestProcDebugging() {
if (me.fixProc != nil) {
// me.fixProc.Disable()
return
}
me.fixProc = me.mainStatus.NewButton("Try debugging Slow DNS lookups", func () {
log.Warn("You're DNS lookups are very slow")
me.dbOn.Set(true)
me.dbProc.Set(true)
processName := getProcessNameByPort(53)
log.Info("Process with port 53:", processName)
})
// me.fixProc.Disable()
}

160
hostname.go Normal file
View File

@ -0,0 +1,160 @@
// figures out if your hostname is valid
// then checks if your DNS is setup correctly
package main
import (
"strings"
"go.wit.com/log"
"go.wit.com/shell"
"go.wit.com/gui/cloudflare"
"github.com/miekg/dns"
// will try to get this hosts FQDN
"github.com/Showmax/go-fqdn"
)
func getHostname() {
var err error
var s string = "gui.Label == nil"
s, err = fqdn.FqdnHostname()
if (err != nil) {
log.Error(err, "FQDN hostname error")
return
}
if (me.fqdn != nil) {
if (me.hostname != s) {
me.fqdn.SetText(s)
me.hostname = s
me.changed = true
}
}
log.Log(NET, "FQDN =", s)
dn := run("domainname")
if (me.domainname.S != dn) {
log.Log(CHANGE, "domainname has changed from", me.domainname.S, "to", dn)
me.domainname.SetText(dn)
me.changed = true
}
hshort := run("hostname -s")
if (me.hostshort.S != hshort) {
log.Log(CHANGE, "hostname -s has changed from", me.hostshort.S, "to", hshort)
me.hostshort.SetText(hshort)
me.changed = true
}
var test string
test = hshort + "." + dn
if (me.hostname != test) {
log.Info("me.hostname", me.hostname, "does not equal", test)
if (me.hostnameStatusOLD.S != "BROKEN") {
log.Log(CHANGE, "me.hostname", me.hostname, "does not equal", test)
me.changed = true
me.hostnameStatusOLD.SetText("BROKEN")
}
} else {
if (me.hostnameStatusOLD.S != "VALID") {
log.Log(CHANGE, "me.hostname", me.hostname, "is valid")
me.hostnameStatusOLD.SetText("VALID")
me.changed = true
}
// enable the cloudflare button if the provider is cloudflare
if (me.cloudflareB == nil) {
log.Log(CHANGE, "me.cloudflare == nil; me.DnsAPI.S =", me.DnsAPI.S)
if (me.DnsAPI.S == "cloudflare") {
me.cloudflareB = me.mainStatus.NewButton("cloudflare wit.com", func () {
cloudflare.CreateRR(me.myGui, "wit.com", "3777302ac4a78cd7fa4f6d3f72086d06")
})
}
}
}
}
// returns true if the hostname is good
// check that all the OS settings are correct here
// On Linux, /etc/hosts, /etc/hostname
// and domainname and hostname
func goodHostname(h string) bool {
hostname := shell.Chomp(shell.Cat("/etc/hostname"))
log.Log(NOW, "hostname =", hostname)
hs := run("hostname -s")
dn := run("domainname")
log.Log(NOW, "hostname short =", hs, "domainname =", dn)
tmp := hs + "." + dn
if (hostname == tmp) {
log.Log(NOW, "hostname seems to be good", hostname)
return true
}
return false
}
/*
func digAAAA(s string) []string {
var aaaa []string
// lookup the IP address from DNS
rrset := dnssecsocket.Dnstrace(s, "AAAA")
// log.Spew(args.VerboseDNS, SPEW, rrset)
for i, rr := range rrset {
ipaddr := dns.Field(rr, 1)
// how the hell do you detect a RRSIG AAAA record here?
if (ipaddr == "28") {
continue
}
log.Log(NOW, "r.Answer =", i, "rr =", rr, "ipaddr =", ipaddr)
aaaa = append(aaaa, ipaddr)
me.ipv6s[ipaddr] = rr
}
log.Info(args.VerboseDNS, "aaaa =", aaaa)
log.Println("digAAAA() returned =", aaaa)
log.Println("digAAAA() me.ipv6s =", me.ipv6s)
os.Exit(0)
return aaaa
}
*/
func digAAAA(hostname string) []string {
var blah, ipv6Addresses []string
// domain := hostname
recordType := dns.TypeAAAA // dns.TypeTXT
// Cloudflare's DNS server
blah, _ = dnsUdpLookup("1.1.1.1:53", hostname, recordType)
log.Println("digAAAA() has BLAH =", blah)
if (len(blah) == 0) {
log.Println("digAAAA() RUNNING dnsAAAAlookupDoH(domain)")
ipv6Addresses, _ = dnsAAAAlookupDoH(hostname)
log.Println("digAAAA() has ipv6Addresses =", strings.Join(ipv6Addresses, " "))
for _, addr := range ipv6Addresses {
log.Println(addr)
}
return ipv6Addresses
}
// TODO: check digDoH vs blah, if so, then port 53 TCP and/or UDP is broken or blocked
log.Println("digAAAA() has BLAH =", blah)
return blah
}
/*
func dnsHttpsLookup(domain string, recordType uint16) ([]string, error) {
domain := "google.com"
dnsLookupDoH(domain string) ([]string, error) {
ipv6Addresses, err := dnsLookupDoH(domain)
if err != nil {
log.Println("Error:", err)
return
}
log.Printf("IPv6 Addresses for %s:\n", domain)
for _, addr := range ipv6Addresses {
log.Println(addr)
}
}
*/

View File

@ -16,14 +16,14 @@ import (
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/gui" "go.wit.com/gui/gui"
"go.wit.com/gui/gadgets" "go.wit.com/gui/gadgets"
"go.wit.com/gui/cloudflare"
) )
type hostnameStatus struct { type hostnameStatus struct {
ready bool ready bool
hidden bool hidden bool
// hostname string // my hostname. Example: "test.wit.com" hostname string // my hostname. Example: "test.wit.com"
lastname string // used to watch for changes in the hostname
window *gadgets.BasicWindow window *gadgets.BasicWindow
@ -42,7 +42,6 @@ type hostnameStatus struct {
currentIPv6 *gadgets.OneLiner currentIPv6 *gadgets.OneLiner
// what the DNS servers have // what the DNS servers have
NSrr *gadgets.OneLiner
dnsA *gadgets.OneLiner dnsA *gadgets.OneLiner
dnsAAAA *gadgets.OneLiner dnsAAAA *gadgets.OneLiner
dnsAPI *gadgets.OneLiner dnsAPI *gadgets.OneLiner
@ -51,8 +50,8 @@ type hostnameStatus struct {
speedActual *gadgets.OneLiner speedActual *gadgets.OneLiner
// Actions // Actions
// dnsValue *gui.Node dnsValue *gui.Node
// dnsAction *gui.Node dnsAction *gui.Node
} }
func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus { func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
@ -61,9 +60,9 @@ func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
hs.ready = false hs.ready = false
hs.hidden = true hs.hidden = true
// hs.hostname = me.hostname hs.hostname = me.hostname
hs.window = gadgets.NewBasicWindow(p, "fix hostname here" + " Status") hs.window = gadgets.NewBasicWindow(p, hs.hostname + " Status")
hs.window.Draw() hs.window.Draw()
hs.window.Hide() hs.window.Hide()
@ -85,7 +84,6 @@ func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
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.NSrr = gadgets.NewOneLiner(grid, "dns NS records").Set("unknown")
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")
@ -96,7 +94,6 @@ func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
group.Pad() group.Pad()
grid.Pad() grid.Pad()
/*
group = hs.window.Box().NewGroup("Actions") group = hs.window.Box().NewGroup("Actions")
grid = group.NewGrid("LookupDetails", 2, 2) grid = group.NewGrid("LookupDetails", 2, 2)
@ -110,7 +107,6 @@ func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
hs.createDNSrecord(hs.dnsValue.S) hs.createDNSrecord(hs.dnsValue.S)
} }
}) })
*/
group.Pad() group.Pad()
grid.Pad() grid.Pad()
@ -120,12 +116,6 @@ func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
return hs return hs
} }
/*
func (hs *hostnameStatus) ValidHostname() bool {
return goodHostname()
}
*/
func (hs *hostnameStatus) Domain() string { func (hs *hostnameStatus) Domain() string {
if ! hs.Ready() {return ""} if ! hs.Ready() {return ""}
return hs.domainname.Get() return hs.domainname.Get()
@ -136,33 +126,31 @@ func (hs *hostnameStatus) API() string {
return hs.dnsAPI.Get() return hs.dnsAPI.Get()
} }
/*
func (hs *hostnameStatus) deleteDNSrecord(value string) bool { func (hs *hostnameStatus) deleteDNSrecord(value string) bool {
log.Info("deleteDNSrecord() START for", value) log.Info("deleteDNSrecord() START for", value)
log.Info("deleteDNSrecord() hostname =", me.status.GetHostname()) log.Info("deleteDNSrecord() hostname =", me.hostname)
log.Info("deleteDNSrecord() domain =", hs.Domain()) log.Info("deleteDNSrecord() domain =", hs.Domain())
log.Info("deleteDNSrecord() DNS API Provider =", hs.API()) log.Info("deleteDNSrecord() DNS API Provider =", hs.API())
if (hs.API() == "cloudflare") { if (hs.API() == "cloudflare") {
log.Info("deleteDNSrecord() Try to delete via cloudflare") log.Info("deleteDNSrecord() Try to delete via cloudflare")
return cloudflare.Delete(hs.Domain(), me.status.GetHostname(), value) return cloudflare.Delete(hs.Domain(), me.hostname, value)
} }
return false return false
} }
func (hs *hostnameStatus) createDNSrecord(value string) bool { func (hs *hostnameStatus) createDNSrecord(value string) bool {
log.Info("createDNSrecord() START for", value) log.Info("createDNSrecord() START for", value)
log.Info("createDNSrecord() hostname =", me.status.GetHostname()) log.Info("createDNSrecord() hostname =", me.hostname)
log.Info("createDNSrecord() domain =", hs.Domain()) log.Info("createDNSrecord() domain =", hs.Domain())
log.Info("createDNSrecord() DNS API Provider =", hs.API()) log.Info("createDNSrecord() DNS API Provider =", hs.API())
if (hs.API() == "cloudflare") { if (hs.API() == "cloudflare") {
log.Warn("createDNSrecord() Try to create via cloudflare:", me.status.GetHostname(), value) log.Warn("createDNSrecord() Try to delete via cloudflare:", me.hostname, value)
return cloudflare.Create(hs.Domain(), me.status.GetHostname(), value) return cloudflare.Create(hs.Domain(), me.hostname, value)
} }
return false return false
} }
*/
func (hs *hostnameStatus) Update() { func (hs *hostnameStatus) Update() {
log.Info("hostnameStatus() Update() START") log.Info("hostnameStatus() Update() START")
@ -241,10 +229,10 @@ func (hs *hostnameStatus) set(a any, s string) {
if reflect.TypeOf(a) == reflect.TypeOf(ol) { if reflect.TypeOf(a) == reflect.TypeOf(ol) {
ol = a.(*gadgets.OneLiner) ol = a.(*gadgets.OneLiner)
if ol == nil { if ol == nil {
// log.Println("ol = nil", reflect.TypeOf(a), "a =", a) log.Println("ol = nil", reflect.TypeOf(a), "a =", a)
return return
} }
// log.Println("SETTING ol:", ol) log.Println("SETTING ol:", ol)
ol.Set(s) ol.Set(s)
return return
} }
@ -252,67 +240,51 @@ func (hs *hostnameStatus) set(a any, s string) {
os.Exit(0) os.Exit(0)
} }
// returns true if AAAA record already exists in DNS
func (hs *hostnameStatus) existsAAAA(s string) bool {
log.Log(NOW, "existsAAAA() try to see if AAAA is already set", s)
return false
}
/*
// figure out if I'm missing any IPv6 address in DNS // figure out if I'm missing any IPv6 address in DNS
func (hs *hostnameStatus) missingAAAA() bool { func (hs *hostnameStatus) missingAAAA() bool {
var aaaa []string var aaaa []string
aaaa = dhcpAAAA() aaaa = dhcpAAAA()
for _, s := range aaaa { for _, s := range aaaa {
log.Log(NET, "my actual AAAA = ",s) log.Log(NET, "my actual AAAA = ",s)
if hs.existsAAAA(s) {
log.Log(NOW, "my actual AAAA already exists in DNS =",s)
} else {
log.Log(NOW, "my actual AAAA is missing from DNS",s)
hs.dnsValue.SetText(s) hs.dnsValue.SetText(s)
hs.dnsAction.SetText("CREATE") hs.dnsAction.SetText("CREATE")
return true return true
} }
}
return false return false
} }
*/
func (hs *hostnameStatus) updateStatus() { func (hs *hostnameStatus) updateStatus() {
if ! hs.Ready() { return }
var s string var s string
var vals []string var vals []string
log.Log(STATUS, "updateStatus() START") log.Info("updateStatus() START")
if ! hs.Ready() { return }
hs.hostShort.Set(me.statusOS.GetHostShort()) hs.hostShort.Set(me.hostshort.S)
hs.domainname.Set(me.statusOS.GetDomainName()) hs.domainname.Set(me.domainname.S)
if me.statusOS.ValidHostname() { vals = lookupDoH(hs.hostname, "AAAA")
vals = lookupDoH(me.statusOS.GetHostname(), "AAAA")
log.Log(STATUS, "DNS IPv6 Addresses for ", me.statusOS.GetHostname(), "=", vals) log.Println("DNS IPv6 Addresses for ", hs.hostname, "=", vals)
if len(vals) == 0 { if len(vals) == 0 {
s = "(none)" s = "(none)"
} else {
hs.setIPv6("Check for real IPv6 addresses here") hs.setIPv6("Check for real IPv6 addresses here")
/*
if hs.missingAAAA() { if hs.missingAAAA() {
hs.setIPv6("Add the missing IPv6 address") hs.setIPv6("Add the missing IPv6 address")
} }
*/ } else {
for _, addr := range vals { for _, addr := range vals {
log.Log(STATUS, addr) log.Println(addr)
s += addr + " (DELETE)" + "\n" s += addr + " (DELETE)"
hs.setIPv6("NEEDS DELETE") hs.setIPv6("NEEDS DELETE")
// hs.dnsValue.SetText(addr) hs.dnsValue.SetText(addr)
// hs.dnsAction.SetText("DELETE") hs.dnsAction.SetText("DELETE")
} }
} }
hs.set(hs.dnsAAAA, s) hs.set(hs.dnsAAAA, s)
vals = lookupDoH(me.statusOS.GetHostname(), "A") vals = lookupDoH(hs.hostname, "A")
log.Log(STATUS, "IPv4 Addresses for ", me.statusOS.GetHostname(), "=", vals) log.Println("IPv4 Addresses for ", hs.hostname, "=", vals)
s = strings.Join(vals, "\n") s = strings.Join(vals, "\n")
if (s == "") { if (s == "") {
s = "(none)" s = "(none)"
@ -320,20 +292,17 @@ func (hs *hostnameStatus) updateStatus() {
} }
hs.set(hs.dnsA, s) hs.set(hs.dnsA, s)
vals = lookupDoH(me.statusOS.GetHostname(), "CNAME") vals = lookupDoH(hs.hostname, "CNAME")
s = strings.Join(vals, "\n") s = strings.Join(vals, "\n")
if (s != "") { if (s != "") {
hs.set(hs.dnsA, "CNAME " + s) hs.set(hs.dnsA, "CNAME " + s)
hs.setIPv4("GOOD") hs.setIPv4("GOOD")
} }
}
// hs.currentIPv4.Set(me.IPv4.S) hs.currentIPv4.Set(me.IPv4.S)
// hs.currentIPv6.Set(me.IPv6.S) hs.currentIPv6.Set(me.IPv6.S)
hs.currentIPv4.Set("get this from linuxStatus")
hs.currentIPv6.Set("get this from linuxStatus")
if hs.IPv4() && hs.IPv6() { if hs.IPv4() && hs.IPv4() {
hs.status.Set("GOOD") hs.status.Set("GOOD")
} else { } else {
hs.status.Set("BROKEN") hs.status.Set("BROKEN")
@ -343,7 +312,7 @@ func (hs *hostnameStatus) updateStatus() {
} }
func (hs *hostnameStatus) Show() { func (hs *hostnameStatus) Show() {
log.Log(STATUS, "hostnameStatus.Show() window") log.Info("hostnameStatus.Show() window")
if hs.hidden { if hs.hidden {
hs.window.Show() hs.window.Show()
} }
@ -351,7 +320,7 @@ func (hs *hostnameStatus) Show() {
} }
func (hs *hostnameStatus) Hide() { func (hs *hostnameStatus) Hide() {
log.Log(STATUS, "hostnameStatus.Hide() window") log.Info("hostnameStatus.Hide() window")
if ! hs.hidden { if ! hs.hidden {
hs.window.Hide() hs.window.Hide()
} }

View File

@ -1,39 +0,0 @@
package linuxstatus
/*
this enables command line options from other packages like 'gui' and 'log'
*/
import (
"go.wit.com/log"
)
var NOW log.LogFlag
var INFO log.LogFlag
var NET log.LogFlag
var DNS log.LogFlag
var PROC log.LogFlag
var SPEW log.LogFlag
var WARN log.LogFlag
var CHANGE log.LogFlag
var STATUS log.LogFlag
func myreg(f *log.LogFlag, b bool, name string, desc string) {
f.B = b
f.Subsystem = "go.wit.com/control-panels/dns/linuxstatus"
f.Short = "linux"
f.Desc = desc
f.Name = name
f.Register()
}
func init() {
myreg(&NOW, true, "NOW", "temp debugging stuff")
myreg(&NET, false, "NET", "Network Logging")
myreg(&DNS, false, "DNS", "dnsStatus.update()")
myreg(&PROC, false, "PROC", "/proc logging")
myreg(&SPEW, false, "SPEW", "spew stuff")
myreg(&WARN, true, "WARN", "bad things")
myreg(&CHANGE, true, "CHANGE", "show droplet state changes")
myreg(&STATUS, false, "STATUS", "Update() details")
}

View File

@ -1,89 +0,0 @@
// This creates a simple hello world window
package linuxstatus
import (
"go.wit.com/log"
"go.wit.com/gui/gui"
)
// reports externally if something has changed
// since the last time it was asked about it
func (ls *LinuxStatus) Changed() bool {
if ! ls.Ready() {return false}
if ls.changed {
ls.changed = false
return true
}
return false
}
func (ls *LinuxStatus) Make() {
if ! ls.Ready() {return}
log.Log(CHANGE, "Make() window ready =", ls.ready)
ls.window.Make()
ls.ready = true
}
func (ls *LinuxStatus) Draw() {
if ! ls.Ready() {return}
log.Log(CHANGE, "Draw() window ready =", ls.ready)
ls.window.Draw()
ls.ready = true
}
func (ls *LinuxStatus) Draw2() {
if ! ls.Ready() {return}
log.Log(CHANGE, "draw(ls) ready =", ls.ready)
draw(ls)
}
func (ls *LinuxStatus) Show() {
if ! ls.Ready() {return}
log.Log(CHANGE, "Show() window ready =", ls.ready)
ls.window.Show()
ls.hidden = false
}
func (ls *LinuxStatus) Hide() {
if ! ls.Ready() {return}
log.Log(CHANGE, "Hide() window ready =", ls.ready)
ls.window.Hide()
ls.hidden = true
}
func (ls *LinuxStatus) Toggle() {
if ! ls.Ready() {return}
log.Log(CHANGE, "Toggle() window ready =", ls.ready)
if ls.hidden {
ls.Show()
} else {
ls.Hide()
}
}
func (ls *LinuxStatus) Ready() bool {
log.Log(SPEW, "Ready() maybe not ready? ls =", ls)
if me == nil {return false}
if ls == nil {return false}
if ls.window == nil {return false}
return me.ready
}
func (ls *LinuxStatus) Initialized() bool {
log.Log(CHANGE, "checking Initialized()")
if me == nil {return false}
if ls == nil {return false}
if ls.parent == nil {return false}
return true
}
func (ls *LinuxStatus) SetParent(p *gui.Node) {
log.Log(CHANGE, "Attempting SetParent")
if me == nil {return}
if ls == nil {return}
if ls.parent == nil {
log.Log(CHANGE, "SetParent =", p)
ls.parent = p
return
} else {
log.Log(CHANGE, "SetParent was already set to =", ls.parent)
}
}

View File

@ -1,38 +0,0 @@
// This creates a simple hello world window
package linuxstatus
import (
"go.wit.com/gui/gadgets"
)
// creates the actual widgets.
// it's assumed you are always passing in a box
func draw(ls *LinuxStatus) {
if ! ls.Ready() {return}
ls.group = ls.window.Box().NewGroup("What Linux Knows It Is")
ls.grid = ls.group.NewGrid("gridnuts", 2, 2)
ls.grid.SetNext(1,1)
ls.hostnameStatus = gadgets.NewOneLiner(ls.grid, "status")
ls.hostname = gadgets.NewOneLiner(ls.grid, "hostname -f")
ls.hostshort = gadgets.NewOneLiner(ls.grid, "hostname -s")
ls.domainname = gadgets.NewOneLiner(ls.grid, "domain name")
ls.resolver = gadgets.NewOneLiner(ls.grid, "nameservers =")
ls.resolver.Set("TODO")
ls.uid = gadgets.NewOneLiner(ls.grid, "UID =")
ls.IPv4 = gadgets.NewOneLiner(ls.grid, "Current IPv4 =")
ls.IPv6 = gadgets.NewOneLiner(ls.grid, "Current IPv6 =")
ls.workingIPv6 = gadgets.NewOneLiner(ls.grid, "Real IPv6 =")
// ls.nics = gadgets.NewOneLiner(ls.grid, "network intefaces =")
ls.grid.NewLabel("interfaces =")
ls.Interfaces = ls.grid.NewCombobox("Interfaces")
ls.speed = gadgets.NewOneLiner(ls.grid, "refresh speed =")
ls.speedActual = gadgets.NewOneLiner(ls.grid, "refresh speed =")
ls.grid.Margin()
ls.grid.Pad()
}

View File

@ -1,134 +0,0 @@
// figures out if your hostname is valid
// then checks if your DNS is setup correctly
package linuxstatus
import (
"go.wit.com/log"
"go.wit.com/shell"
// will try to get this hosts FQDN
"github.com/Showmax/go-fqdn"
)
func (ls *LinuxStatus) GetDomainName() string {
if ! me.Ready() {return ""}
return me.domainname.Get()
}
func (ls *LinuxStatus) setDomainName() {
if ! me.Ready() {return}
dn := run("domainname")
if (me.domainname.Get() != dn) {
log.Log(CHANGE, "domainname has changed from", me.GetDomainName(), "to", dn)
me.domainname.Set(dn)
me.changed = true
}
}
func (ls *LinuxStatus) GetHostname() string {
if ! me.Ready() {return ""}
return me.hostname.Get()
}
func (ls *LinuxStatus) ValidHostname() bool {
if ! me.Ready() {return false}
if me.hostnameStatus.Get() == "VALID" {
return true
}
return false
}
func (ls *LinuxStatus) setHostname(newname string) {
if ! me.Ready() {return}
if newname == me.hostname.Get() {
return
}
log.Log(CHANGE, "hostname has changed from", me.GetHostname(), "to", newname)
me.hostname.Set(newname)
me.changed = true
}
func (ls *LinuxStatus) GetHostShort() string {
if ! me.Ready() {return ""}
return me.hostshort.Get()
}
func (ls *LinuxStatus) setHostShort() {
if ! me.Ready() {return}
hshort := run("hostname -s")
if (me.hostshort.Get() != hshort) {
log.Log(CHANGE, "hostname -s has changed from", me.hostshort.Get(), "to", hshort)
me.hostshort.Set(hshort)
me.changed = true
}
}
func lookupHostname() {
if ! me.Ready() {return}
var err error
var hostfqdn string = "broken"
hostfqdn, err = fqdn.FqdnHostname()
if (err != nil) {
log.Error(err, "FQDN hostname error")
return
}
log.Log(NET, "full hostname should be: ", hostfqdn)
me.setDomainName()
me.setHostShort()
// these are authoritative
// if they work wrong, your linux configuration is wrong.
// Do not complain.
// Fix your distro if your box is otherwise not working this way
hshort := me.GetHostShort() // from `hostname -s`
dn := me.GetDomainName() // from `domanname`
hostname := me.GetHostname() // from `hostname -f`
if hostfqdn != hostname {
log.Log(WARN, "hostname", hostname, "does not equal fqdn.FqdnHostname()", hostfqdn)
// TODO: figure out what is wrong
}
var test string
test = hshort + "." + dn
me.setHostname(test)
if (hostname != test) {
log.Log(CHANGE, "hostname", hostname, "does not equal", test)
if (me.hostnameStatus.Get() != "BROKEN") {
log.Log(CHANGE, "hostname", hostname, "does not equal", test)
me.changed = true
me.hostnameStatus.Set("BROKEN")
}
} else {
if (me.hostnameStatus.Get() != "VALID") {
log.Log(CHANGE, "hostname", hostname, "is valid")
me.hostnameStatus.Set("VALID")
me.changed = true
}
}
}
// returns true if the hostname is good
// check that all the OS settings are correct here
// On Linux, /etc/hosts, /etc/hostname
// and domainname and hostname
func goodHostname() bool {
hostname := shell.Chomp(shell.Cat("/etc/hostname"))
log.Log(NOW, "hostname =", hostname)
hs := run("hostname -s")
dn := run("domainname")
log.Log(NOW, "hostname short =", hs, "domainname =", dn)
tmp := hs + "." + dn
if (hostname == tmp) {
log.Log(NOW, "hostname seems to be good", hostname)
return true
}
return false
}

View File

@ -1,49 +0,0 @@
// GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
// Copyright (c) 2023 WIT.COM, Inc.
// This is a control panel for DNS
package linuxstatus
import (
"os"
"os/user"
"strconv"
"strings"
"go.wit.com/log"
)
func linuxLoop() {
me.changed = false
duration := timeFunction(lookupHostname)
log.Log(INFO, "getHostname() execution Time: ", duration, "me.changed =", me.changed)
duration = timeFunction(scanInterfaces)
log.Log(NET, "scanInterfaces() execution Time: ", duration)
for i, t := range me.ifmap {
log.Log(NET, strconv.Itoa(i) + " iface = " + t.iface.Name)
}
// get all the real AAAA records from all the network interfaces linux can see
tmp := strings.Join(realAAAA(), "\n")
tmp = sortLines(tmp)
me.workingIPv6.Set(tmp)
user, _ := user.Current()
log.Log(INFO, "os.Getuid =", user.Username, os.Getuid())
if (me.uid != nil) {
me.uid.Set(user.Username + " (" + strconv.Itoa(os.Getuid()) + ")")
}
/*
processName := getProcessNameByPort(53)
fmt.Println("Process with port 53:", processName)
commPath := filepath.Join("/proc", proc.Name(), "comm")
comm, err := ioutil.ReadFile(commPath)
if err != nil {
return "", err // Error reading the process name
}
return strings.TrimSpace(string(comm)), nil
*/
}

View File

@ -1,271 +0,0 @@
// This creates a simple hello world window
package linuxstatus
import (
// "log"
"net"
"sort"
"strings"
"go.wit.com/log"
)
func IsIPv6(address string) bool {
return strings.Count(address, ":") >= 2
}
func (t *IPtype) IsReal() bool {
if (t.ip.IsPrivate() || t.ip.IsLoopback() || t.ip.IsLinkLocalUnicast()) {
log.Log(NET, "\t\tIP is Real = false")
return false
} else {
log.Log(NET, "\t\tIP is Real = true")
return true
}
}
func IsReal(ip *net.IP) bool {
if (ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkLocalUnicast()) {
log.Log(NET, "\t\tIP is Real = false")
return false
} else {
log.Log(NET, "\t\tIP is Real = true")
return true
}
}
func renameInterface(i *net.Interface) {
/*
/sbin/ip link set eth1 down
/sbin/ip link set eth1 name eth123
/sbin/ip link set eth123 up
*/
}
// Will figure out if an interface was just added
func checkInterface(i net.Interface) {
val, ok := me.ifmap[i.Index]
if ! ok {
log.Log(INFO, i.Name, "is a new network interface. The linux kernel index =", i.Index)
me.ifmap[i.Index] = new(IFtype)
me.ifmap[i.Index].gone = false
me.ifmap[i.Index].iface = &i
me.changed = true
if (me.Interfaces != nil) {
me.Interfaces.AddText(i.Name)
me.Interfaces.SetText(i.Name)
}
return
}
me.ifmap[i.Index].gone = false
log.Log(NET, "me.ifmap[i] does exist. Need to compare everything.", i.Index, i.Name, val.iface.Index, val.iface.Name)
if (val.iface.Name != i.Name) {
log.Log(INFO, val.iface.Name, "has changed to it's name to", i.Name)
me.ifmap[i.Index].iface = &i
me.changed = true
if (me.Interfaces != nil) {
me.Interfaces.AddText(i.Name)
me.Interfaces.SetText(i.Name)
}
return
}
}
/*
These are the real IP address you have been
given from DHCP
*/
func realAAAA() []string {
var aaaa []string
for s, t := range me.ipmap {
if (t.IsReal()) {
if (t.ipv6) {
aaaa = append(aaaa, s)
}
}
}
return aaaa
}
func realA() []string {
var a []string
for s, t := range me.ipmap {
if (t.IsReal()) {
if (t.ipv4) {
a = append(a, s)
}
}
}
return a
}
func checkDNS() (map[string]*IPtype, map[string]*IPtype) {
var ipv4s map[string]*IPtype
var ipv6s map[string]*IPtype
ipv4s = make(map[string]*IPtype)
ipv6s = make(map[string]*IPtype)
for s, t := range me.ipmap {
i := t.iface
ipt := "IPv4"
if (t.ipv6) {
ipt = "IPv6"
}
if (t.IsReal()) {
log.Log(INFO, "\tIP is Real ", ipt, i.Index, i.Name, s)
if (t.ipv6) {
ipv6s[s] = t
} else {
ipv4s[s] = t
}
} else {
log.Log(INFO, "\tIP is not Real", ipt, i.Index, i.Name, s)
}
}
return ipv6s, ipv4s
}
// Will figure out if an IP address is new
func checkIP(ip *net.IPNet, i net.Interface) bool {
log.Log(NET, "\t\taddr.(type) = *net.IPNet")
log.Log(NET, "\t\taddr.(type) =", ip)
var realip string
realip = ip.IP.String()
val, ok := me.ipmap[realip]
if ok {
log.Log(NET, val.ipnet.IP.String(), "is already a defined IP address")
me.ipmap[realip].gone = false
return false
}
me.ipmap[realip] = new(IPtype)
me.ipmap[realip].gone = false
me.ipmap[realip].ipv4 = true
me.ipmap[realip].ipnet = ip
me.ipmap[realip].ip = ip.IP
me.ipmap[realip].iface = &i
t := "IPv4"
if (IsIPv6(ip.String())) {
me.ipmap[realip].ipv6 = true
me.ipmap[realip].ipv4 = false
t = "IPv6"
if (me.IPv6 != nil) {
me.IPv6.Set(realip)
}
} else {
me.ipmap[realip].ipv6 = false
me.ipmap[realip].ipv4 = true
if (me.IPv4 != nil) {
me.IPv4.Set(realip)
}
}
if (IsReal(&ip.IP)) {
log.Log(INFO, "\tIP is Real ", t, i.Index, i.Name, realip)
} else {
log.Log(INFO, "\tIP is not Real", t, i.Index, i.Name, realip)
}
log.Log(NET, "\t\tIP is IsPrivate() =", ip.IP.IsPrivate())
log.Log(NET, "\t\tIP is IsLoopback() =", ip.IP.IsLoopback())
log.Log(NET, "\t\tIP is IsLinkLocalUnicast() =", ip.IP.IsLinkLocalUnicast())
// log.Log(INFO, "HERE HERE", "realip =", realip, "me.ip[realip]=", me.ipmap[realip])
return true
}
func scanInterfaces() {
log.Log(NET, "scanInterfaces() START")
ifaces, _ := net.Interfaces()
// me.ifnew = ifaces
log.Log(NET, SPEW, ifaces)
for _, i := range ifaces {
addrs, _ := i.Addrs()
// log.Log(INFO, "range ifaces = ", i)
checkInterface(i)
log.Log(NET, "*net.Interface.Name = ", i.Name, i.Index)
log.Log(NET, SPEW, i)
log.Log(NET, SPEW, addrs)
for _, addr := range addrs {
log.Log(NET, "\taddr =", addr)
log.Log(NET, SPEW, addrs)
ips, _ := net.LookupIP(addr.String())
log.Log(NET, "\tLookupIP(addr) =", ips)
switch v := addr.(type) {
case *net.IPNet:
if checkIP(v, i) {
log.Log(true, "scanInterfaces() IP is new () i =", v.IP.String())
}
default:
log.Log(NET, "\t\taddr.(type) = NO IDEA WHAT TO DO HERE v =", v)
}
}
}
if deleteChanges() {
me.changed = true
log.Log(NET, "deleteChanges() detected network changes")
}
updateRealAAAA()
log.Log(NET, "scanInterfaces() END")
}
// displays the IP address found on your network interfaces
func updateRealAAAA() {
var all4 []string
var all6 []string
for s, t := range me.ipmap {
if (t.ipv4) {
all4 = append(all4, s)
log.Log(NET, "IPv4 =", s)
} else if (t.ipv6) {
all6 = append(all6, s)
log.Log(NET, "IPv6 =", s)
} else {
log.Log(NET, "???? =", s)
}
}
// sort and create text
sort.Strings(all4)
sort.Strings(all6)
s4 := strings.Join(all4, "\n")
s6 := strings.Join(all6, "\n")
if (me.IPv4.Get() != s4) {
log.Log(CHANGE, "IPv4 addresses have changed", s4)
me.IPv4.Set(s4)
me.changed = true
}
if (me.IPv6.Get() != s6) {
log.Log(CHANGE, "IPv6 addresses have changed", s6)
me.IPv6.Set(s6)
me.changed = true
}
}
// delete network interfaces and ip addresses from the gui
func deleteChanges() bool {
var changed bool = false
for i, t := range me.ifmap {
if (t.gone) {
log.Log(CHANGE, "DELETE int =", i, "name =", t.name, t.iface)
delete(me.ifmap, i)
changed = true
}
t.gone = true
}
for s, t := range me.ipmap {
if (t.gone) {
log.Log(CHANGE, "DELETE name =", s, "IPv4 =", t.ipv4)
log.Log(CHANGE, "DELETE name =", s, "IPv6 =", t.ipv6)
log.Log(CHANGE, "DELETE name =", s, "iface =", t.iface)
log.Log(CHANGE, "DELETE name =", s, "ip =", t.ip)
delete(me.ipmap, s)
changed = true
}
t.gone = true
}
return changed
}

View File

@ -1,39 +0,0 @@
// This creates a simple hello world window
package linuxstatus
import (
"go.wit.com/log"
"go.wit.com/gui/gadgets"
)
func New() *LinuxStatus {
if me != nil {
log.Log(WARN, "You have done New() twice. You can only do this once")
return me
}
me = &LinuxStatus {
hidden: true,
ready: false,
}
me.ifmap = make(map[int]*IFtype)
me.ipmap = make(map[string]*IPtype)
return me
}
func (ls *LinuxStatus) InitWindow() {
if ! ls.Initialized() {
log.Log(WARN, "not initalized yet (no parent for the window?)")
return
}
if ls.window != nil {
log.Log(WARN, "You already have a window")
ls.ready = true
return
}
log.Log(WARN, "Creating the Window")
ls.window = gadgets.NewBasicWindow(ls.parent, "Linux OS Details")
ls.ready = true
}

View File

@ -1,60 +0,0 @@
/*
figures out if your hostname is valid
then checks if your DNS is setup correctly
*/
package linuxstatus
import (
"net"
"go.wit.com/gui/gui"
"go.wit.com/gui/gadgets"
)
var me *LinuxStatus
type LinuxStatus struct {
ready bool
hidden bool
changed bool
parent *gui.Node
ifmap map[int]*IFtype // the current interfaces
ipmap map[string]*IPtype // the current ip addresses
window *gadgets.BasicWindow
group *gui.Node
grid *gui.Node
hostnameStatus *gadgets.OneLiner
hostname *gadgets.OneLiner
hostshort *gadgets.OneLiner
domainname *gadgets.OneLiner
resolver *gadgets.OneLiner
uid *gadgets.OneLiner
IPv4 *gadgets.OneLiner
IPv6 *gadgets.OneLiner
workingIPv6 *gadgets.OneLiner
Interfaces *gui.Node
speed *gadgets.OneLiner
speedActual *gadgets.OneLiner
}
type IPtype struct {
gone bool // used to track if the ip exists
ipv6 bool // the future
ipv4 bool // the past
LinkLocal bool
iface *net.Interface
ip net.IP
ipnet *net.IPNet
}
type IFtype struct {
gone bool // used to track if the interface exists
name string // just a shortcut to the name. maybe this is dumb
// up bool // could be used to track ifup/ifdown
iface *net.Interface
}

View File

@ -1,36 +0,0 @@
package linuxstatus
import (
"time"
"sort"
"strings"
)
// timeFunction takes a function as an argument and returns the execution time.
func timeFunction(f func()) time.Duration {
startTime := time.Now() // Record the start time
f() // Execute the function
return time.Since(startTime) // Calculate the elapsed time
}
// sortLines takes a string, splits it on newlines, sorts the lines,
// and rejoins them with newlines.
func sortLines(input string) string {
lines := strings.Split(input, "\n")
// Trim leading and trailing whitespace from each line
for i, line := range lines {
lines[i] = strings.TrimSpace(line)
}
sort.Strings(lines)
tmp := strings.Join(lines, "\n")
tmp = strings.TrimLeft(tmp, "\n")
tmp = strings.TrimRight(tmp, "\n")
return tmp
}
func (ls *LinuxStatus) SetSpeedActual(s string) {
if ! ls.Ready() {return}
ls.speedActual.Set(s)
}

View File

@ -1,97 +0,0 @@
// Various Linux/Unix'y things
// https://wiki.archlinux.org/title/Dynamic_DNS
package linuxstatus
import (
"os"
"os/exec"
"net"
"bytes"
"fmt"
"strings"
"go.wit.com/log"
"go.wit.com/shell"
)
func CheckSuperuser() bool {
return os.Getuid() == 0
}
func Escalate() {
if os.Getuid() != 0 {
cmd := exec.Command("sudo", "./control-panel-dns") // TODO: get the actual path
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
log.Error(err, "exit in Escalate()")
log.Exit(err)
}
}
}
// You need permission to do a zone transfer. Otherwise:
// dig +noall +answer +multiline lab.wit.com any
// dig +all +multiline fire.lab.wit.com # gives the zonefile header (ttl vals)
func DumpPublicDNSZone(zone string) {
entries, err := net.LookupHost(zone)
if err != nil {
panic(err)
}
for _, entry := range entries {
log.Println(entry)
}
}
func dumpIPs(host string) {
ips, err := net.LookupIP(host)
if err != nil {
log.Error(err, "dumpIPs() failed")
}
for _, ip := range ips {
log.Println(host, ip)
}
}
/*
check if ddclient is installed, working, and/or configured
https://github.com/ddclient/ddclient
*/
func ddclient() {
}
/*
check if ddupdate is installed, working, and/or configured
*/
func ddupdate() {
}
func run(s string) string {
cmdArgs := strings.Fields(s)
// Define the command you want to run
// cmd := exec.Command(cmdArgs)
cmd := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
// Create a buffer to capture the output
var out bytes.Buffer
// Set the output of the command to the buffer
cmd.Stdout = &out
// Run the command
err := cmd.Run()
if err != nil {
fmt.Println("Error running command:", err)
return ""
}
tmp := shell.Chomp(out.String())
// Output the results
log.Info("Command Output:", tmp)
return tmp
}

View File

@ -1,40 +0,0 @@
package linuxstatus
import (
"fmt"
"time"
"errors"
"go.wit.com/log"
)
func (ls *LinuxStatus) Update() {
if ! ls.Ready() {
log.Log(WARN, "can't update yet. ready is false")
log.Error(errors.New("Update() is not ready yet"))
return
}
log.Log(INFO, "Update() START")
duration := timeFunction(func () {
linuxLoop()
})
ls.SetSpeed(duration)
log.Log(INFO, "Update() END")
}
func (ls *LinuxStatus) SetSpeed(duration time.Duration) {
s := fmt.Sprint(duration)
if ls.speedActual == nil {
log.Log(WARN, "can't actually warn")
return
}
ls.speedActual.Set(s)
if (duration > 500 * time.Millisecond ) {
ls.speed.Set("SLOW")
} else if (duration > 100 * time.Millisecond ) {
ls.speed.Set("OK")
} else {
ls.speed.Set("FAST")
}
}

58
main.go
View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"sort" "sort"
"strconv"
"runtime" "runtime"
"time" "time"
"embed" "embed"
@ -16,8 +17,6 @@ import (
"go.wit.com/gui/gui" "go.wit.com/gui/gui"
"go.wit.com/gui/debugger" "go.wit.com/gui/debugger"
"go.wit.com/control-panels/dns/linuxstatus"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@ -45,11 +44,6 @@ func main() {
log.Sleep(me.artificialSleep) log.Sleep(me.artificialSleep)
setupControlPanelWindow() setupControlPanelWindow()
me.digStatus = NewDigStatusWindow(me.myGui)
me.status = NewHostnameStatusWindow(me.myGui)
linuxstatus.New()
if debugger.ArgDebug() { if debugger.ArgDebug() {
log.Sleep(2) log.Sleep(2)
debugger.DebugWindow(me.myGui) debugger.DebugWindow(me.myGui)
@ -100,7 +94,7 @@ func checkNetworkChanges() {
if (runtime.GOOS == "linux") { if (runtime.GOOS == "linux") {
duration := timeFunction(linuxLoop) duration := timeFunction(linuxLoop)
s := fmt.Sprint(duration) s := fmt.Sprint(duration)
me.statusOS.SetSpeedActual(s) me.LocalSpeedActual.SetText(s)
} else { } else {
// TODO: make windows and macos diagnostics // TODO: make windows and macos diagnostics
log.Warn("Windows and MacOS don't work yet") log.Warn("Windows and MacOS don't work yet")
@ -127,15 +121,24 @@ func DNSloop() {
log.Info("dnsTTL() execution Time: ", duration) log.Info("dnsTTL() execution Time: ", duration)
var s, newSpeed string var s, newSpeed string
if (duration > 5000 * time.Millisecond ) { if (duration > 5000 * time.Millisecond ) {
newSpeed = "VERY SLOW" newSpeed = "VERY BAD"
suggestProcDebugging()
} else if (duration > 2000 * time.Millisecond ) { } else if (duration > 2000 * time.Millisecond ) {
newSpeed = "SLOWER" newSpeed = "BAD"
suggestProcDebugging()
} else if (duration > 500 * time.Millisecond ) { } else if (duration > 500 * time.Millisecond ) {
suggestProcDebugging()
newSpeed = "SLOW" newSpeed = "SLOW"
} else if (duration > 100 * time.Millisecond ) { } else if (duration > 100 * time.Millisecond ) {
newSpeed = "OK" newSpeed = "OK"
if (me.fixProc != nil) {
// me.fixProc.Disable()
}
} else { } else {
newSpeed = "FAST" newSpeed = "FAST"
if (me.fixProc != nil) {
// me.fixProc.Disable()
}
} }
if (newSpeed != me.DnsSpeedLast) { if (newSpeed != me.DnsSpeedLast) {
log.Log(CHANGE, "dns lookup speed changed =", newSpeed) log.Log(CHANGE, "dns lookup speed changed =", newSpeed)
@ -153,16 +156,45 @@ func dnsTTL() {
updateDNS() updateDNS()
} }
// run update on the LinuxStatus() window
func linuxLoop() { func linuxLoop() {
me.statusOS.Update() me.changed = false
log.Log(NET, "FQDN =", me.fqdn.GetText())
duration := timeFunction(getHostname)
log.Info("getHostname() execution Time: ", duration, "me.changed =", me.changed)
if (me.statusOS.Changed()) { duration = timeFunction(scanInterfaces)
log.Log(NET, "scanInterfaces() execution Time: ", duration)
for i, t := range me.ifmap {
log.Log(NET, strconv.Itoa(i) + " iface = " + t.iface.Name)
}
var aaaa []string
aaaa = dhcpAAAA()
var all string
for _, s := range aaaa {
log.Log(NET, "my actual AAAA = ",s)
all += s + "\n"
}
// me.IPv6.SetText(all)
if (me.changed) {
stamp := time.Now().Format("2006/01/02 15:04:05") stamp := time.Now().Format("2006/01/02 15:04:05")
log.Log(CHANGE, "Network things changed on", stamp) log.Log(CHANGE, "Network things changed on", stamp)
duration := timeFunction(updateDNS) duration := timeFunction(updateDNS)
log.Log(CHANGE, "updateDNS() execution Time: ", duration) log.Log(CHANGE, "updateDNS() execution Time: ", duration)
} }
/*
processName := getProcessNameByPort(53)
fmt.Println("Process with port 53:", processName)
commPath := filepath.Join("/proc", proc.Name(), "comm")
comm, err := ioutil.ReadFile(commPath)
if err != nil {
return "", err // Error reading the process name
}
return strings.TrimSpace(string(comm)), nil
*/
} }
/* /*

201
net.go
View File

@ -9,6 +9,35 @@ import (
"go.wit.com/log" "go.wit.com/log"
) )
// this doesn't work
/*
func watchNetworkInterfaces() {
// Get list of network interfaces
interfaces, _ := net.Interfaces()
// Set up a notification channel
notification := make(chan net.Interface)
log.Log(NET, "watchNet()")
// Start goroutine to watch for changes
go func() {
log.Log(NET, "watchNet() func")
for {
log.Log(NET, "forever loop start")
// Check for changes in each interface
for _, i := range interfaces {
log.Log(NET, "something on i =", i)
if status := i.Flags & net.FlagUp; status != 0 {
notification <- i
log.Log(NET, "something on i =", i)
}
}
log.Log(NET, "forever loop end")
}
}()
}
*/
func IsIPv6(address string) bool { func IsIPv6(address string) bool {
return strings.Count(address, ":") >= 2 return strings.Count(address, ":") >= 2
} }
@ -33,6 +62,43 @@ func IsReal(ip *net.IP) bool {
} }
} }
func renameInterface(i *net.Interface) {
/*
/sbin/ip link set eth1 down
/sbin/ip link set eth1 name eth123
/sbin/ip link set eth123 up
*/
}
// Will figure out if an interface was just added
func checkInterface(i net.Interface) {
val, ok := me.ifmap[i.Index]
if ! ok {
log.Info(i.Name, "is a new network interface. The linux kernel index =", i.Index)
me.ifmap[i.Index] = new(IFtype)
me.ifmap[i.Index].gone = false
me.ifmap[i.Index].iface = &i
me.changed = true
if (me.Interfaces != nil) {
me.Interfaces.AddText(i.Name)
me.Interfaces.SetText(i.Name)
}
return
}
me.ifmap[i.Index].gone = false
log.Log(NET, "me.ifmap[i] does exist. Need to compare everything.", i.Index, i.Name, val.iface.Index, val.iface.Name)
if (val.iface.Name != i.Name) {
log.Info(val.iface.Name, "has changed to it's name to", i.Name)
me.ifmap[i.Index].iface = &i
me.changed = true
if (me.Interfaces != nil) {
me.Interfaces.AddText(i.Name)
me.Interfaces.SetText(i.Name)
}
return
}
}
/* /*
These are the real IP address you have been These are the real IP address you have been
given from DHCP given from DHCP
@ -89,3 +155,138 @@ func checkDNS() (map[string]*IPtype, map[string]*IPtype) {
} }
return ipv6s, ipv4s return ipv6s, ipv4s
} }
// Will figure out if an IP address is new
func checkIP(ip *net.IPNet, i net.Interface) bool {
log.Log(NET, "\t\taddr.(type) = *net.IPNet")
log.Log(NET, "\t\taddr.(type) =", ip)
var realip string
realip = ip.IP.String()
val, ok := me.ipmap[realip]
if ok {
log.Log(NET, val.ipnet.IP.String(), "is already a defined IP address")
me.ipmap[realip].gone = false
return false
}
me.ipmap[realip] = new(IPtype)
me.ipmap[realip].gone = false
me.ipmap[realip].ipv4 = true
me.ipmap[realip].ipnet = ip
me.ipmap[realip].ip = ip.IP
me.ipmap[realip].iface = &i
t := "IPv4"
if (IsIPv6(ip.String())) {
me.ipmap[realip].ipv6 = true
me.ipmap[realip].ipv4 = false
t = "IPv6"
if (me.IPv6 != nil) {
me.IPv6.SetText(realip)
}
} else {
me.ipmap[realip].ipv6 = false
me.ipmap[realip].ipv4 = true
if (me.IPv4 != nil) {
me.IPv4.SetText(realip)
}
}
if (IsReal(&ip.IP)) {
log.Info("\tIP is Real ", t, i.Index, i.Name, realip)
} else {
log.Info("\tIP is not Real", t, i.Index, i.Name, realip)
}
log.Log(NET, "\t\tIP is IsPrivate() =", ip.IP.IsPrivate())
log.Log(NET, "\t\tIP is IsLoopback() =", ip.IP.IsLoopback())
log.Log(NET, "\t\tIP is IsLinkLocalUnicast() =", ip.IP.IsLinkLocalUnicast())
// log.Info("HERE HERE", "realip =", realip, "me.ip[realip]=", me.ipmap[realip])
return true
}
func scanInterfaces() {
log.Log(NET, "scanInterfaces() START")
ifaces, _ := net.Interfaces()
// me.ifnew = ifaces
log.Log(NET, SPEW, ifaces)
for _, i := range ifaces {
addrs, _ := i.Addrs()
// log.Info("range ifaces = ", i)
checkInterface(i)
log.Log(NET, "*net.Interface.Name = ", i.Name, i.Index)
log.Log(NET, SPEW, i)
log.Log(NET, SPEW, addrs)
for _, addr := range addrs {
log.Log(NET, "\taddr =", addr)
log.Log(NET, SPEW, addrs)
ips, _ := net.LookupIP(addr.String())
log.Log(NET, "\tLookupIP(addr) =", ips)
switch v := addr.(type) {
case *net.IPNet:
if checkIP(v, i) {
log.Log(true, "scanInterfaces() IP is new () i =", v.IP.String())
}
default:
log.Log(NET, "\t\taddr.(type) = NO IDEA WHAT TO DO HERE v =", v)
}
}
}
if deleteChanges() {
me.changed = true
log.Log(NET, "deleteChanges() detected network changes")
}
updateRealAAAA()
log.Log(NET, "scanInterfaces() END")
}
// displays the IP address found on your network interfaces
func updateRealAAAA() {
var all4 string
var all6 string
for s, t := range me.ipmap {
if (t.ipv4) {
all4 += s + "\n"
log.Log(NET, "IPv4 =", s)
} else if (t.ipv6) {
all6 += s + "\n"
log.Log(NET, "IPv6 =", s)
} else {
log.Log(NET, "???? =", s)
}
}
all4 = sortLines(all4)
all6 = sortLines(all6)
if (me.IPv4.S != all4) {
log.Log(NET, "IPv4 addresses have changed", all4)
me.IPv4.SetText(all4)
}
if (me.IPv6.S != all6) {
log.Log(NET, "IPv6 addresses have changed", all6)
me.IPv6.SetText(all6)
}
}
// delete network interfaces and ip addresses from the gui
func deleteChanges() bool {
var changed bool = false
for i, t := range me.ifmap {
if (t.gone) {
log.Log(CHANGE, "DELETE int =", i, "name =", t.name, t.iface)
delete(me.ifmap, i)
changed = true
}
t.gone = true
}
for s, t := range me.ipmap {
if (t.gone) {
log.Log(CHANGE, "DELETE name =", s, "IPv4 =", t.ipv4)
log.Log(CHANGE, "DELETE name =", s, "IPv6 =", t.ipv6)
log.Log(CHANGE, "DELETE name =", s, "iface =", t.iface)
log.Log(CHANGE, "DELETE name =", s, "ip =", t.ip)
delete(me.ipmap, s)
changed = true
}
t.gone = true
}
return changed
}

View File

@ -22,7 +22,7 @@ func nsupdate() {
cmd := "go-nsupdate --tsig-algorithm=hmac-sha512" cmd := "go-nsupdate --tsig-algorithm=hmac-sha512"
tsigSecret = os.Getenv("TIG_SECRET") tsigSecret = os.Getenv("TIG_SECRET")
cmd += " --tig-secret=\"" + tsigSecret + "\"" cmd += " --tig-secret=\"" + tsigSecret + "\""
cmd += " -i wlo1 " + me.statusOS.GetHostname() cmd += " -i wlo1 " + me.hostname
log.Log(NET, "nsupdate() RUN:", cmd) log.Log(NET, "nsupdate() RUN:", cmd)
for s, t := range me.ipmap { for s, t := range me.ipmap {

View File

@ -1,209 +0,0 @@
/*
Performs DNS queries on TCP and UDP
*/
package main
import (
"os"
"time"
"strconv"
"reflect"
"go.wit.com/log"
"go.wit.com/gui/gui"
"go.wit.com/gui/gadgets"
"github.com/miekg/dns"
)
type resolverStatus struct {
title string
server string // The DNS server. Example: "127.0.0.1:53" or "1.1.1.1:53"
hostname string // the hostname to lookup. Example: "www.google.com" or "go.wit.com"
parent *gui.Node
group *gui.Node
grid *gui.Node
// DNS setup options
udpA *gui.Node
tcpA *gui.Node
udpAAAA *gui.Node
tcpAAAA *gui.Node
// show the display
aFail *gui.Node
aSuccess *gui.Node
aaaaFail *gui.Node
aaaaSuccess *gui.Node
// interger counters
aFailc int
aSuccessc int
aaaaFailc int
aaaaSuccessc int
}
func (rs *resolverStatus) set(a any, s string) {
if a == nil {
return
}
var n *gui.Node
if reflect.TypeOf(a) == reflect.TypeOf(n) {
n = a.(*gui.Node)
n.SetText(s)
return
}
var ol *gadgets.OneLiner
if reflect.TypeOf(a) == reflect.TypeOf(ol) {
ol = a.(*gadgets.OneLiner)
ol.Set(s)
return
}
log.Warn("unknown type TypeOf(a) =", reflect.TypeOf(a), "a =", a)
os.Exit(0)
}
// Makes a DNS Status Grid
func NewResolverStatus(p *gui.Node, title string, server string, hostname string) *resolverStatus {
var rs *resolverStatus
rs = new(resolverStatus)
rs.parent = p
rs.group = p.NewGroup(server + " " + title + " lookup")
rs.grid = rs.group.NewGrid("LookupStatus", 5, 2)
rs.server = server
rs.hostname = hostname
rs.grid.NewLabel("")
rs.grid.NewLabel("UDP")
rs.grid.NewLabel("TCP")
rs.grid.NewLabel("Success")
rs.grid.NewLabel("Fail")
rs.grid.NewLabel("A")
rs.udpA = rs.grid.NewLabel("?")
rs.tcpA = rs.grid.NewLabel("?")
rs.aSuccess = rs.grid.NewLabel("?")
rs.aFail = rs.grid.NewLabel("?")
rs.grid.NewLabel("AAAA")
rs.udpAAAA = rs.grid.NewLabel("?")
rs.tcpAAAA = rs.grid.NewLabel("?")
rs.aaaaSuccess = rs.grid.NewLabel("?")
rs.aaaaFail = rs.grid.NewLabel("?")
rs.group.Margin()
rs.grid.Margin()
rs.group.Pad()
rs.grid.Pad()
return rs
}
// special thanks to the Element Hotel wifi in Philidelphia that allowed me to
// easily debug this code since the internet connection here blocks port 53 traffic
func (rs *resolverStatus) update() (bool, bool) {
var results []string
var a bool = false
var aaaa bool = false
log.Log(DNS, "resolverStatus.update() For server", rs.server, "on", rs.hostname)
results, _ = dnsUdpLookup(rs.server, rs.hostname, dns.TypeA)
log.Log(DNS, "resolverStatus.update() UDP type A =", results)
if (len(results) == 0) {
rs.set(rs.udpA, "BROKEN")
rs.aFailc += 1
} else {
rs.set(rs.udpA, "WORKING")
rs.aSuccessc += 1
a = true
}
results, _ = dnsTcpLookup(rs.server, rs.hostname, dns.TypeA)
log.Log(DNS, "resolverStatus.update() TCP type A =", results)
if (len(results) == 0) {
rs.set(rs.tcpA, "BROKEN")
rs.aFailc += 1
} else {
me.digStatus.set(rs.tcpA, "WORKING")
rs.aSuccessc += 1
a = true
}
me.digStatus.set(rs.aFail, strconv.Itoa(rs.aFailc))
me.digStatus.set(rs.aSuccess,strconv.Itoa(rs.aSuccessc))
results, _ = dnsUdpLookup(rs.server, rs.hostname, dns.TypeAAAA)
log.Log(DNS, "resolverStatus.update() UDP type AAAA =", results)
if (len(results) == 0) {
me.digStatus.set(rs.udpAAAA, "BROKEN")
rs.aaaaFailc += 1
me.digStatus.set(rs.aaaaFail, strconv.Itoa(rs.aaaaFailc))
} else {
me.digStatus.set(rs.udpAAAA, "WORKING")
rs.aaaaSuccessc += 1
aaaa = true
}
results, _ = dnsTcpLookup(rs.server, rs.hostname, dns.TypeAAAA)
log.Log(DNS, "resolverStatus.update() UDP type AAAA =", results)
if (len(results) == 0) {
me.digStatus.set(rs.tcpAAAA, "BROKEN")
rs.aaaaFailc += 1
me.digStatus.set(rs.aaaaFail, strconv.Itoa(rs.aaaaFailc))
} else {
me.digStatus.set(rs.tcpAAAA, "WORKING")
rs.aaaaSuccessc += 1
aaaa = true
}
me.digStatus.set(rs.aaaaFail, strconv.Itoa(rs.aaaaFailc))
me.digStatus.set(rs.aaaaSuccess,strconv.Itoa(rs.aaaaSuccessc))
return a, aaaa
}
// dnsLookup performs a DNS lookup for the specified record type (e.g., "TXT", "AAAA") for a given domain.
func dnsUdpLookup(server string, domain string, recordType uint16) ([]string, error) {
var records []string
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), recordType)
r, _, err := c.Exchange(m, server) // If server = "1.1.1.1:53" then use Cloudflare's DNS server
if err != nil {
return nil, err
}
for _, ans := range r.Answer {
records = append(records, ans.String())
}
return records, nil
}
func dnsTcpLookup(server string, domain string, recordType uint16) ([]string, error) {
var records []string
c := new(dns.Client)
c.Net = "tcp" // Specify to use TCP for the query
c.Timeout = time.Second * 5 // Set a 5-second timeout
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), recordType)
r, _, err := c.Exchange(m, server) // If server = "1.1.1.1:53" then use Cloudflare's DNS server
if err != nil {
return nil, err
}
for _, ans := range r.Answer {
records = append(records, ans.String())
}
return records, nil
}

View File

@ -6,8 +6,6 @@ import (
"time" "time"
"go.wit.com/gui/gui" "go.wit.com/gui/gui"
"go.wit.com/gui/gadgets" "go.wit.com/gui/gadgets"
"go.wit.com/control-panels/dns/linuxstatus"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@ -15,12 +13,14 @@ import (
var me Host var me Host
type Host struct { type Host struct {
status *hostnameStatus // keeps track of the hostname and it's status hostname string // mirrors
statusOS *linuxstatus.LinuxStatus // what the Linux OS sees domainname *gui.Node // kernel.org
hostshort *gui.Node // hostname -s
hostnameStatus *gui.Node // a summary for the user of where things are hostnameStatusOLD *gui.Node // is the hostname configured correctly in the OS?
hostname *gadgets.OneLiner // the hostname grabbed from gadget.linuxStatus // fqdn string // mirrors.kernel.org
// dnsTTL int `default:"3"` // Recheck DNS is working every TTL (in seconds)
// dnsTTLsleep float64 // sleep between loops
artificialSleep float64 `default:"0.7"` // artificial sleep on startup artificialSleep float64 `default:"0.7"` // artificial sleep on startup
artificialS string `default:"abc"` // artificial sleep on startup artificialS string `default:"abc"` // artificial sleep on startup
@ -42,35 +42,48 @@ type Host struct {
ipv6s map[string]dns.RR ipv6s map[string]dns.RR
window *gadgets.BasicWindow // the main window window *gadgets.BasicWindow // the main window
details *gadgets.BasicWindow // more details of the DNS state
debug *gadgets.BasicWindow // more attempts to debug the DNS state debug *gadgets.BasicWindow // more attempts to debug the DNS state
tab *gui.Node // the main dns tab tab *gui.Node // the main dns tab
notes *gui.Node // using this to put notes here notes *gui.Node // using this to put notes here
// local OS settings, network interfaces, etc // local OS settings, network interfaces, etc
// fqdn *gui.Node // display the full hostname uid *gui.Node // user
// Interfaces *gui.Node // Interfaces fqdn *gui.Node // display the full hostname
// LocalSpeedActual *gui.Node // the time it takes to check each network interface IPv4 *gui.Node // show valid IPv4 addresses
IPv6 *gui.Node // show valid IPv6 addresses
Interfaces *gui.Node // Interfaces
LocalSpeedActual *gui.Node // the time it takes to check each network interface
// DNS stuff // DNS stuff
NSrr *gui.Node // NS resource records for the domain name
DnsAPI *gui.Node // what DNS API to use? DnsAPI *gui.Node // what DNS API to use?
DnsAAAA *gadgets.OneLiner // the actual DNS AAAA results DnsAAAA *gui.Node // the actual DNS AAAA results
workingIPv6 *gui.Node // currently working AAAA
DnsA *gui.Node // the actual DNS A results (ignore for status since mostly never happens?) DnsA *gui.Node // the actual DNS A results (ignore for status since mostly never happens?)
DnsStatus *gui.Node // the current state of DNS DnsStatus *gui.Node // the current state of DNS
DnsSpeed *gui.Node // 'FAST', 'OK', 'SLOW', etc DnsSpeed *gui.Node // 'FAST', 'OK', 'SLOW', etc
DnsSpeedActual *gui.Node // the last actual duration DnsSpeedActual *gui.Node // the last actual duration
DnsSpeedLast string // the last state 'FAST', 'OK', etc DnsSpeedLast string // the last state 'FAST', 'OK', etc
// fix *gui.Node // button for the user to click fix *gui.Node // button for the user to click
// fixProc *gui.Node // button for the user to click fixProc *gui.Node // button for the user to click
// mainStatus *gui.Node // group for the main display of stuff mainStatus *gui.Node // group for the main display of stuff
// cloudflareB *gui.Node // cloudflare button cloudflareB *gui.Node // cloudflare button
dbOn *gui.Node // button for setting debugging on
dbNet *gui.Node // button for setting network debugging on
dbProc *gui.Node // button for setting proc debugging on
digStatus *digStatus digStatus *digStatus
statusIPv6 *gadgets.OneLiner statusIPv6 *gadgets.OneLiner
digStatusButton *gui.Node digStatusButton *gui.Node
hostnameStatus *hostnameStatus
hostnameStatusButton *gui.Node
myDebug *gui.Node myDebug *gui.Node
myGui *gui.Node myGui *gui.Node
} }