restore the files after garbage collection
hopefully this actually is a valid git repo
This commit is contained in:
parent
94aa368cff
commit
fdac7e7b89
|
@ -0,0 +1,38 @@
|
||||||
|
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 init() {
|
||||||
|
full := "go.wit.com/control-panels/dns/linuxstatus"
|
||||||
|
short := "linux"
|
||||||
|
|
||||||
|
NOW = log.NewFlag( "NOW", true, full, short, "temp debugging stuff")
|
||||||
|
INFO = log.NewFlag("INFO", false, full, short, "normal debugging stuff")
|
||||||
|
NET = log.NewFlag( "NET", false, full, short, "Network logging")
|
||||||
|
DNS = log.NewFlag( "DNS", false, full, short, "dnsStatus.update()")
|
||||||
|
|
||||||
|
PROC = log.NewFlag("PROC", false, full, short, "/proc loggging")
|
||||||
|
WARN = log.NewFlag("WARN", true, full, short, "bad things")
|
||||||
|
SPEW = log.NewFlag("SPEW", false, full, short, "spew stuff")
|
||||||
|
|
||||||
|
CHANGE = log.NewFlag("CHANGE", true, full, short, "when host or dns change")
|
||||||
|
STATUS = log.NewFlag("STATUS", false, full, short, "Update() details")
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
// 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.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.workingIPv4 = gadgets.NewOneLiner(ls.grid, "Real IPv4 =")
|
||||||
|
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()
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
// figures out if your hostname is valid
|
||||||
|
// then checks if your DNS is setup correctly
|
||||||
|
package linuxstatus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"go.wit.com/log"
|
||||||
|
|
||||||
|
// 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() == "WORKING" {
|
||||||
|
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() != "WORKING") {
|
||||||
|
log.Log(CHANGE, "hostname", hostname, "is valid")
|
||||||
|
me.hostnameStatus.Set("WORKING")
|
||||||
|
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 {
|
||||||
|
content, err := ioutil.ReadFile("/etc/hostname")
|
||||||
|
if err != nil {
|
||||||
|
// this needs to be a fixWindow() error
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname := string(content)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
// GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
|
||||||
|
// Copyright (c) 2023 WIT.COM, Inc.
|
||||||
|
|
||||||
|
// This is a control panel for DNS
|
||||||
|
|
||||||
|
// This is the main Linux kernel / OS code
|
||||||
|
// to check your network settings are correct
|
||||||
|
// This does (and should do) no network or external checking
|
||||||
|
// This is just the state of your OS
|
||||||
|
|
||||||
|
package linuxstatus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func linuxLoop() {
|
||||||
|
me.changed = false
|
||||||
|
|
||||||
|
// checks for a VALID hostname
|
||||||
|
lookupHostname()
|
||||||
|
if me.changed {
|
||||||
|
log.Log(CHANGE, "lookupHostname() detected a change")
|
||||||
|
}
|
||||||
|
|
||||||
|
// scans the linux network intefaces for your available IPv4 & IPv6 addresses
|
||||||
|
scanInterfaces()
|
||||||
|
if me.changed {
|
||||||
|
log.Log(CHANGE, "scanInterfaces() detected a change")
|
||||||
|
}
|
||||||
|
for i, t := range me.ifmap {
|
||||||
|
log.Log(NET, strconv.Itoa(i) + " iface = " + t.iface.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all the real A records from all the network interfaces linux can see
|
||||||
|
a := realA()
|
||||||
|
sort.Strings(a)
|
||||||
|
tmp := strings.Join(a, "\n")
|
||||||
|
if tmp != me.workingIPv4.Get() {
|
||||||
|
log.Log(CHANGE, "realAAAA() your real IPv6 addresses changed")
|
||||||
|
me.changed = true
|
||||||
|
me.workingIPv4.Set(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all the real AAAA records from all the network interfaces linux can see
|
||||||
|
aaaa := realAAAA()
|
||||||
|
sort.Strings(aaaa)
|
||||||
|
tmp = strings.Join(aaaa, "\n")
|
||||||
|
if tmp != me.workingIPv6.Get() {
|
||||||
|
log.Log(CHANGE, "realAAAA() your real IPv6 addresses changed")
|
||||||
|
me.changed = true
|
||||||
|
me.workingIPv6.Set(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
user, _ := user.Current()
|
||||||
|
tmp = user.Username + " (" + strconv.Itoa(os.Getuid()) + ")"
|
||||||
|
if tmp != me.uid.Get() {
|
||||||
|
log.Log(CHANGE, "os.Getuid =", user.Username, os.Getuid())
|
||||||
|
me.changed = true
|
||||||
|
me.uid.Set(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
content, _ := ioutil.ReadFile("/etc/resolv.conf")
|
||||||
|
var ns []string
|
||||||
|
for _, line := range strings.Split(string(content), "\n") {
|
||||||
|
parts := strings.Split(line, " ")
|
||||||
|
if len(parts) > 1 {
|
||||||
|
if parts[0] == "nameserver" {
|
||||||
|
ns = append(ns, parts[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(ns)
|
||||||
|
newNS := strings.Join(ns, "\n")
|
||||||
|
if newNS != me.resolver.Get() {
|
||||||
|
log.Log(CHANGE, "resolver changed in /etc/resolv.conf to", ns)
|
||||||
|
me.changed = true
|
||||||
|
me.resolver.Set(newNS)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1,289 @@
|
||||||
|
// 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(NET, "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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinuxStatus) GetIPv6() []string {
|
||||||
|
if ! me.Ready() {return nil}
|
||||||
|
tmp := me.workingIPv6.Get()
|
||||||
|
return strings.Split(tmp, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinuxStatus) GetIPv4() []string {
|
||||||
|
if ! me.Ready() {return nil}
|
||||||
|
tmp := me.workingIPv4.Get()
|
||||||
|
return strings.Split(tmp, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ls *LinuxStatus) GetNameservers() []string {
|
||||||
|
if ! me.Ready() {return nil}
|
||||||
|
tmp := me.resolver.Get()
|
||||||
|
return strings.Split(tmp, "\n")
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
// 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
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/creack/pty"
|
||||||
|
"golang.org/x/term"
|
||||||
|
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func test() error {
|
||||||
|
// Create arbitrary command.
|
||||||
|
c := exec.Command("bash")
|
||||||
|
|
||||||
|
// Start the command with a pty.
|
||||||
|
ptmx, err := pty.Start(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Make sure to close the pty at the end.
|
||||||
|
defer func() { _ = ptmx.Close() }() // Best effort.
|
||||||
|
|
||||||
|
// Handle pty size.
|
||||||
|
ch := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(ch, syscall.SIGWINCH)
|
||||||
|
go func() {
|
||||||
|
for range ch {
|
||||||
|
if err := pty.InheritSize(os.Stdin, ptmx); err != nil {
|
||||||
|
log.Println("error resizing pty: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ch <- syscall.SIGWINCH // Initial resize.
|
||||||
|
defer func() { signal.Stop(ch); close(ch) }() // Cleanup signals when done.
|
||||||
|
|
||||||
|
// Set stdin in raw mode.
|
||||||
|
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
|
||||||
|
|
||||||
|
// Copy stdin to the pty and the pty to stdout.
|
||||||
|
// NOTE: The goroutine will keep reading until the next keystroke before returning.
|
||||||
|
go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
|
||||||
|
_, _ = io.Copy(os.Stdout, ptmx)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mainBash() {
|
||||||
|
if err := test(); err != nil {
|
||||||
|
log.Error(err, "exit in mainBash()")
|
||||||
|
log.Exit(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
https://pkg.go.dev/github.com/miekg/dns#section-readme
|
||||||
|
|
||||||
|
DYNAMIC UPDATES
|
||||||
|
|
||||||
|
Dynamic updates reuses the DNS message format, but renames three of the sections. Question is Zone, Answer is Prerequisite, Authority is Update, only the Additional is not renamed. See RFC 2136 for the gory details.
|
||||||
|
|
||||||
|
You can set a rather complex set of rules for the existence of absence of certain resource records or names in a zone to specify if resource records should be added or removed. The table from RFC 2136 supplemented with the Go DNS function shows which functions exist to specify the prerequisites.
|
||||||
|
|
||||||
|
3.2.4 - Table Of Metavalues Used In Prerequisite Section
|
||||||
|
|
||||||
|
CLASS TYPE RDATA Meaning Function
|
||||||
|
--------------------------------------------------------------
|
||||||
|
ANY ANY empty Name is in use dns.NameUsed
|
||||||
|
ANY rrset empty RRset exists (value indep) dns.RRsetUsed
|
||||||
|
NONE ANY empty Name is not in use dns.NameNotUsed
|
||||||
|
NONE rrset empty RRset does not exist dns.RRsetNotUsed
|
||||||
|
zone rrset rr RRset exists (value dep) dns.Used
|
||||||
|
|
||||||
|
The prerequisite section can also be left empty. If you have decided on the prerequisites you can tell what RRs should be added or deleted. The next table shows the options you have and what functions to call.
|
||||||
|
|
||||||
|
3.4.2.6 - Table Of Metavalues Used In Update Section
|
||||||
|
|
||||||
|
CLASS TYPE RDATA Meaning Function
|
||||||
|
---------------------------------------------------------------
|
||||||
|
ANY ANY empty Delete all RRsets from name dns.RemoveName
|
||||||
|
ANY rrset empty Delete an RRset dns.RemoveRRset
|
||||||
|
NONE rrset rr Delete an RR from RRset dns.Remove
|
||||||
|
zone rrset rr Add to an RRset dns.Insert
|
||||||
|
*/
|
|
@ -0,0 +1,81 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
// Watches for changes to a directory. Works cross-platform
|
||||||
|
|
||||||
|
/*
|
||||||
|
import (
|
||||||
|
"go.wit.com/log"
|
||||||
|
"github.com/fsnotify/fsnotify"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This would be a really dumb way to watch for new network interfaces
|
||||||
|
// since it then watches a linux only directory /sys/class/net for changes
|
||||||
|
|
||||||
|
func watchSysClassNet() {
|
||||||
|
// Create new watcher.
|
||||||
|
watcher, err := fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err, "watchSysClassNet() failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer watcher.Close()
|
||||||
|
|
||||||
|
// Start listening for events.
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event, ok := <-watcher.Events:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("event:", event)
|
||||||
|
if event.Has(fsnotify.Write) {
|
||||||
|
log.Println("modified file:", event.Name)
|
||||||
|
}
|
||||||
|
case err, ok := <-watcher.Errors:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("error:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Add a path.
|
||||||
|
err = watcher.Add("/tmp")
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err, "watchSysClassNet() watcher.Add() failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block main goroutine forever.
|
||||||
|
<-make(chan struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func fsnotifyNetworkInterfaceChanges() error {
|
||||||
|
watcher, err := fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer watcher.Close()
|
||||||
|
|
||||||
|
// Watch for network interface changes
|
||||||
|
err = watcher.Add("/sys/class/net")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event := <-watcher.Events:
|
||||||
|
log.Println("fsnotifyNetworkInterfaceChanges() event =", event)
|
||||||
|
if event.Op&fsnotify.Create == fsnotify.Create {
|
||||||
|
// Do something on network interface creation
|
||||||
|
}
|
||||||
|
case err := <-watcher.Errors:
|
||||||
|
log.Println("fsnotifyNetworkInterfaceChanges() event err =", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,34 @@
|
||||||
|
// inspired from:
|
||||||
|
// https://github.com/mactsouk/opensource.com.git
|
||||||
|
// and
|
||||||
|
// https://coderwall.com/p/wohavg/creating-a-simple-tcp-server-in-go
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
)
|
||||||
|
|
||||||
|
// ./go-nsupdate \
|
||||||
|
// --tsig-algorithm=hmac-sha512 \
|
||||||
|
// --tsig-secret="OWh5/ZHIyaz7B8J9m9ZDqZ8448Pke0PTpkYbZmFcOf5a6rEzgmcwrG91u1BHi1/4us+mKKEobDPLw1x6sD+ZJw==" \
|
||||||
|
// -i eno2 farm001.lab.wit.com
|
||||||
|
|
||||||
|
/*
|
||||||
|
func nsupdate() {
|
||||||
|
var tsigSecret string
|
||||||
|
log.Log(NET, "nsupdate() START")
|
||||||
|
cmd := "go-nsupdate --tsig-algorithm=hmac-sha512"
|
||||||
|
tsigSecret = os.Getenv("TIG_SECRET")
|
||||||
|
cmd += " --tig-secret=\"" + tsigSecret + "\""
|
||||||
|
cmd += " -i wlo1 " + me.statusOS.GetHostname()
|
||||||
|
log.Log(NET, "nsupdate() RUN:", cmd)
|
||||||
|
|
||||||
|
for s, t := range me.ipmap {
|
||||||
|
if (t.IsReal()) {
|
||||||
|
if (t.ipv6) {
|
||||||
|
log.Log(NET, "nsupdate() found real AAAA =", s, "on iface", t.iface.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,26 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jsimonetti/rtnetlink"
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// List all interfaces
|
||||||
|
func Example_listLink() {
|
||||||
|
// Dial a connection to the rtnetlink socket
|
||||||
|
conn, err := rtnetlink.Dial(nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err, "Example_listLink() failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Request a list of interfaces
|
||||||
|
msg, err := conn.Link.List()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("%#v", msg)
|
||||||
|
log.Println(SPEW, msg)
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
// Various Linux/Unix'y things
|
||||||
|
|
||||||
|
// https://wiki.archlinux.org/title/Dynamic_DNS
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
package linuxstatus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.wit.com/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProcessNameByPort(port int) string {
|
||||||
|
// Convert port to hex string
|
||||||
|
portHex := strconv.FormatInt(int64(port), 16)
|
||||||
|
|
||||||
|
// Function to search /proc/net/tcp or /proc/net/udp
|
||||||
|
searchProcNet := func(file string) string {
|
||||||
|
data, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
// log.Log(PROC, "searchProcNet() data:", string(data))
|
||||||
|
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
log.Log(PROC, "searchProcNet() portHex:", portHex)
|
||||||
|
if (len(fields) > 9) {
|
||||||
|
log.Log(PROC, "searchProcNet() fields[9]", fields[9])
|
||||||
|
}
|
||||||
|
log.Log(PROC, "searchProcNet() lines:", line)
|
||||||
|
if len(fields) > 1 {
|
||||||
|
parts := strings.Split(fields[1], ":")
|
||||||
|
if len(parts) > 1 {
|
||||||
|
// Convert the hexadecimal string to an integer
|
||||||
|
value, _ := strconv.ParseInt(parts[1], 16, 64)
|
||||||
|
log.Log(PROC, "searchProcNet() value, port =", value, port, "parts[1] =", parts[1])
|
||||||
|
if (port == int(value)) {
|
||||||
|
log.Log(PROC, "searchProcNet() THIS IS THE LINE:", fields)
|
||||||
|
return fields[9]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search TCP and then UDP
|
||||||
|
inode := searchProcNet("/proc/net/tcp")
|
||||||
|
if inode == "" {
|
||||||
|
inode = searchProcNet("/proc/net/udp")
|
||||||
|
}
|
||||||
|
log.Log(PROC, "searchProcNet() inode =", inode)
|
||||||
|
|
||||||
|
// Search for process with the inode
|
||||||
|
procs, _ := ioutil.ReadDir("/proc")
|
||||||
|
for _, proc := range procs {
|
||||||
|
if !proc.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fdPath := filepath.Join("/proc", proc.Name(), "fd")
|
||||||
|
fds, err := ioutil.ReadDir(fdPath)
|
||||||
|
if err != nil {
|
||||||
|
continue // Process might have exited; skip it
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fd := range fds {
|
||||||
|
fdLink, _ := os.Readlink(filepath.Join(fdPath, fd.Name()))
|
||||||
|
var s string
|
||||||
|
s = "socket:["+inode+"]"
|
||||||
|
if strings.Contains(fdLink, "socket:[") {
|
||||||
|
log.Log(PROC, "searchProcNet() fdLink has socket:", fdLink)
|
||||||
|
log.Log(PROC, "searchProcNet() proc.Name() =", proc.Name(), "s =", s)
|
||||||
|
}
|
||||||
|
if strings.Contains(fdLink, "socket:[35452]") {
|
||||||
|
log.Log(PROC, "searchProcNet() found proc.Name() =", proc.Name(), fdLink)
|
||||||
|
return proc.Name()
|
||||||
|
}
|
||||||
|
if strings.Contains(fdLink, "socket:[35450]") {
|
||||||
|
log.Log(PROC, "searchProcNet() found proc.Name() =", proc.Name(), fdLink)
|
||||||
|
return proc.Name()
|
||||||
|
}
|
||||||
|
if strings.Contains(fdLink, "socket:[35440]") {
|
||||||
|
log.Log(PROC, "searchProcNet() found proc.Name() =", proc.Name(), fdLink)
|
||||||
|
return proc.Name()
|
||||||
|
}
|
||||||
|
if strings.Contains(fdLink, "socket:[21303]") {
|
||||||
|
log.Log(PROC, "searchProcNet() found proc.Name() =", proc.Name(), fdLink)
|
||||||
|
// return proc.Name()
|
||||||
|
}
|
||||||
|
if strings.Contains(fdLink, "socket:["+inode+"]") {
|
||||||
|
return proc.Name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
workingIPv4 *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
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
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)
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim leading and trailing whitespace from each line
|
||||||
|
tmp := strings.TrimSpace(out.String())
|
||||||
|
// Output the results
|
||||||
|
log.Info("Command Output:", tmp)
|
||||||
|
|
||||||
|
return tmp
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue