v0.0.2 next step: acutally try to nsupdate
upto the point where DNS update is next. start displaying real AAAA & naming buttons add RFC 2136 defining nsupdate. Vixie et al in 1997 Personal thansk to Paul for meeting with me some years back ready to pull DNS records starting a checkDNS() function dampen output. actually track IPs poll every 2 seconds (netlink is not the right thing here) ready to start looking for changes screw everything about logging. I hate log.whatthefuck*(){} Do you know what I don't care about? log() You shouldn't care either. Ignore it until you need it that is what logging is for. building something that works. So, here you go. a damn log() function in one place Also, because I'm annoyed today sleep() and exit() Because, when I want you to sleep or exit, I don't want to go to the top of a file and declare stupid shit related to nanoseconds or add "import os.Exit" or whatever the hell stop wasting my time. life is short. if he sit tunnelbroker down add IsRealIP() and IsIPv6() need a netlink function to trigger on changes (nope) put the gui plugin's in the debian package for now set the window title build a .deb package Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
4c348438f3
commit
041e3a0c6e
|
@ -1 +1,3 @@
|
|||
control-panel-dns
|
||||
/files/*
|
||||
/*.deb
|
||||
|
|
|
@ -20,6 +20,9 @@ clean:
|
|||
|
||||
extract:
|
||||
mkdir -p ../files/usr/bin
|
||||
mkdir -p ../files/usr/lib/control-panel-dns/
|
||||
-cp ~/go/src/git.wit.org/wit/gui/toolkit/*.so ../files/usr/lib/control-panel-dns/
|
||||
cp ../README.md ../files/usr/lib/control-panel-dns/
|
||||
cp ../control-panel-dns ../files/usr/bin/
|
||||
|
||||
# makes the DEBIAN/ directory
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
Source: go-wit-gui
|
||||
Source: control-panel-dns
|
||||
Build-Depends: golang
|
||||
Package: go-wit-gui
|
||||
Package: control-panel-dns
|
||||
Maintainer: Jeff Carr <jcarr@wit.com>
|
||||
Architecture: amd64
|
||||
Depends:
|
||||
Recommends: libgtk-3-0
|
||||
Description: a abstraction layer for Go visual elements (GTK, QT, etc)
|
||||
Package gui implements a abstraction layer for Go visual elements.
|
||||
Recommends: libgtk-3-0, ddclient, ddupdate
|
||||
Description: a control panel for DNS and IPv6 settings
|
||||
Goals: show the settings, validate & update DNS
|
||||
|
|
|
@ -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,76 @@
|
|||
package main
|
||||
|
||||
// Watches for changes to a directory. Works cross-platform
|
||||
|
||||
import (
|
||||
"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 {
|
||||
exit(err)
|
||||
}
|
||||
defer watcher.Close()
|
||||
|
||||
// Start listening for events.
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log("event:", event)
|
||||
if event.Has(fsnotify.Write) {
|
||||
log("modified file:", event.Name)
|
||||
}
|
||||
case err, ok := <-watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log("error:", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Add a path.
|
||||
err = watcher.Add("/tmp")
|
||||
if err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
||||
// 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("fsnotifyNetworkInterfaceChanges() event =", event)
|
||||
if event.Op&fsnotify.Create == fsnotify.Create {
|
||||
// Do something on network interface creation
|
||||
}
|
||||
case err := <-watcher.Errors:
|
||||
log("fsnotifyNetworkInterfaceChanges() event err =", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#!/bin/bash -x
|
||||
|
||||
## Tunnel ID: 818143
|
||||
# Creation Date:Feb 12, 2023
|
||||
# Description:
|
||||
# IPv6 Tunnel Endpoints
|
||||
# Server IPv4 Address:184.105.253.14
|
||||
# Server IPv6 Address:2001:470:1f10:2a::1/64
|
||||
# Client IPv4 Address:74.87.91.117
|
||||
# Client IPv6 Address:2001:470:1f10:2a::2/64
|
||||
# Routed IPv6 Prefixes
|
||||
# Routed /64:2001:470:1f11:2a::/64
|
||||
# Routed /48:Assign /48
|
||||
# DNS Resolvers
|
||||
# Anycast IPv6 Caching Nameserver:2001:470:20::2
|
||||
# Anycast IPv4 Caching Nameserver:74.82.42.42
|
||||
# DNS over HTTPS / DNS over TLS:ordns.he.net
|
||||
# rDNS DelegationsEdit
|
||||
# rDNS Delegated NS1:
|
||||
# rDNS Delegated NS2:
|
||||
# rDNS Delegated NS3:
|
||||
# rDNS Delegated NS4:
|
||||
# rDNS Delegated NS5:
|
||||
|
||||
# ifconfig sit0 up
|
||||
# ifconfig sit0 inet6 tunnel ::184.105.253.14
|
||||
# ifconfig sit1 up
|
||||
# ifconfig sit1 inet6 add 2001:470:1f10:2a::2/64
|
||||
# route -A inet6 add ::/0 dev sit1
|
||||
|
||||
if [ "$1" = "down" ]; then
|
||||
ip tunnel del he-ipv6
|
||||
rmmod sit
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$1" = "ping" ]; then
|
||||
ping -c 3 2001:470:1f10:13d::1
|
||||
exit
|
||||
fi
|
||||
|
||||
modprobe ipv6
|
||||
ip tunnel add he-ipv6 mode sit remote 184.105.253.14 local 40.132.180.131 ttl 255
|
||||
ip link set he-ipv6 up
|
||||
ip addr add 2001:470:1f10:13d::2/64 dev he-ipv6
|
||||
ip route add ::/0 dev he-ipv6
|
||||
ip -f inet6 addr
|
||||
ifconfig he-ipv6 mtu 1460
|
||||
|
||||
|
||||
# old attempt from the something or pabtz hotel
|
||||
# modprobe ipv6
|
||||
# ip tunnel add he-ipv6 mode sit remote 184.105.253.14 local 74.87.91.117 ttl 255
|
||||
# ip link set he-ipv6 up
|
||||
# ip addr add 2001:470:1f10:2a::2/64 dev he-ipv6
|
||||
# ip route add ::/0 dev he-ipv6
|
||||
# ip -f inet6 addr
|
|
@ -0,0 +1,45 @@
|
|||
// 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 "net"
|
||||
|
||||
// will try to get this hosts FQDN
|
||||
import "github.com/Showmax/go-fqdn"
|
||||
|
||||
// this is the king of dns libraries
|
||||
import "github.com/miekg/dns"
|
||||
|
||||
// dnssec IPv6 socket library
|
||||
import "git.wit.org/jcarr/dnssecsocket"
|
||||
|
||||
func getHostname() {
|
||||
var err error
|
||||
me.fqdn, err = fqdn.FqdnHostname()
|
||||
if (err != nil) {
|
||||
log("FQDN hostname error =", err)
|
||||
exit()
|
||||
return
|
||||
}
|
||||
log("FQDN hostname is", me.fqdn)
|
||||
|
||||
var aaaa []string
|
||||
aaaa = getAAAA(me.fqdn)
|
||||
log("AAAA =", aaaa)
|
||||
}
|
||||
|
||||
func getAAAA(s string) []string {
|
||||
// lookup the IP address from DNS
|
||||
dnsRR := dnssecsocket.Dnstrace(s, "AAAA")
|
||||
log(args.VerboseDNS, SPEW, dnsRR)
|
||||
if (dnsRR == nil) {
|
||||
return nil
|
||||
}
|
||||
ipaddr1 := dns.Field(dnsRR, 1)
|
||||
ipaddr2 := dns.Field(dnsRR, 2)
|
||||
log("ipaddr", ipaddr1, ipaddr2)
|
||||
return []string{ipaddr1, ipaddr2}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
// I like things to be easy. Why can't the standard language be like this?
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
golog "log"
|
||||
"time"
|
||||
"reflect"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
// "net"
|
||||
)
|
||||
|
||||
var LOGOFF bool = false // turn this off, all logging stops
|
||||
var WARN bool
|
||||
var INFO bool
|
||||
|
||||
type spewt struct {
|
||||
a bool
|
||||
}
|
||||
|
||||
var SPEW spewt
|
||||
|
||||
|
||||
/*
|
||||
sleep() # you know what this does? sleeps for 1 second. yep. dump. easy.
|
||||
sleep(.1) # you know what this does? yes, it sleeps for 1/10th of a second
|
||||
*/
|
||||
func sleep(a ...any) {
|
||||
if (a == nil) {
|
||||
time.Sleep(time.Second)
|
||||
return
|
||||
}
|
||||
|
||||
log(args.Verbose, "sleep", a[0])
|
||||
|
||||
switch a[0].(type) {
|
||||
case int:
|
||||
time.Sleep(time.Duration(a[0].(int)) * time.Second)
|
||||
case float64:
|
||||
time.Sleep(time.Duration(a[0].(float64) * 1000) * time.Millisecond)
|
||||
default:
|
||||
log("sleep a[0], type = ", a[0], reflect.TypeOf(a[0]))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
exit() # yep. exits. I guess everything must be fine
|
||||
exit(3) # I guess 3 it is then
|
||||
exit("dont like apples") # ok. I'll make a note of that
|
||||
*/
|
||||
func exit(a ...any) {
|
||||
log("exit", a)
|
||||
//if (a) {
|
||||
// os.Exit(a)
|
||||
//}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
/*
|
||||
I've spent, am spending, too much time thinking about 'logging'. 'log', 'logrus', 'zap', whatever.
|
||||
I'm not twitter. i don't give a fuck about how many nanoseconds it takes to log. Anyway, this
|
||||
implementation is probably faster than all of those because you just set one bool to FALSE
|
||||
and it all stops.
|
||||
Sometimes I need to capture to stdout, sometimes stdout can't
|
||||
work because it doesn't exist for the user. This whole thing is a PITA. Then it's spread
|
||||
over 8 million references in every .go file. I'm tapping out and putting
|
||||
it in one place. here it is. Also, this makes having debug levels really fucking easy.
|
||||
You can define whatever level of logging you want from anywhere (command line) etc.
|
||||
|
||||
log() # doesn't do anything
|
||||
log(stuff) # sends it to whatever log you define in a single place. here is the place
|
||||
*/
|
||||
|
||||
func log(a ...any) {
|
||||
if (LOGOFF) {
|
||||
return
|
||||
}
|
||||
|
||||
if (a == nil) {
|
||||
return
|
||||
}
|
||||
var blah bool
|
||||
if (reflect.TypeOf(a[0]) == reflect.TypeOf(blah)) {
|
||||
// golog.Println("\t a[0] = bool")
|
||||
if (a[0] == false) {
|
||||
return
|
||||
}
|
||||
a = a[1:]
|
||||
}
|
||||
|
||||
if (reflect.TypeOf(a[0]) == reflect.TypeOf(SPEW)) {
|
||||
a = a[1:]
|
||||
spew.Dump(a)
|
||||
return
|
||||
}
|
||||
|
||||
golog.Println(a...)
|
||||
// golog.Println("\t a[0] =", a[0])
|
||||
// for argNum, arg := range a {
|
||||
// golog.Println("\t", argNum, arg)
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
/*
|
||||
import "log"
|
||||
import "github.com/miekg/dns"
|
||||
|
||||
import "git.wit.org/jcarr/dnssecsocket"
|
||||
|
||||
import "github.com/davecgh/go-spew/spew"
|
||||
// import "github.com/Showmax/go-fqdn"
|
||||
|
||||
func lookupAAAA(hostname string) string {
|
||||
// lookup the IP address from DNS
|
||||
dnsRR := dnssecsocket.Dnstrace(hostname, "AAAA")
|
||||
spew.Dump(dnsRR)
|
||||
if (dnsRR == nil) {
|
||||
return "BROKEN"
|
||||
}
|
||||
ipaddr := dns.Field(dnsRR, 1)
|
||||
log.Println("ipaddr", ipaddr)
|
||||
return ipaddr
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
func main() {
|
||||
hostname := "check.lab.wit.org"
|
||||
// 2604:bbc0:2:248:5054:f0ff:fe00:156
|
||||
|
||||
lookupAAAA(hostname)
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,223 @@
|
|||
// This creates a simple hello world window
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
// "git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
var DEBUGNET bool = false
|
||||
|
||||
// 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(DEBUGNET, "watchNet()")
|
||||
// Start goroutine to watch for changes
|
||||
go func() {
|
||||
log(DEBUGNET, "watchNet() func")
|
||||
for {
|
||||
log(DEBUGNET, "forever loop start")
|
||||
// Check for changes in each interface
|
||||
for _, i := range interfaces {
|
||||
log(DEBUGNET, "something on i =", i)
|
||||
if status := i.Flags & net.FlagUp; status != 0 {
|
||||
notification <- i
|
||||
log(DEBUGNET, "something on i =", i)
|
||||
}
|
||||
}
|
||||
log(DEBUGNET, "forever loop end")
|
||||
}
|
||||
}()
|
||||
}
|
||||
*/
|
||||
|
||||
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(DEBUGNET, "\t\tIP is Real = false")
|
||||
return false
|
||||
} else {
|
||||
log(DEBUGNET, "\t\tIP is Real = true")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func IsReal(ip *net.IP) bool {
|
||||
if (ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkLocalUnicast()) {
|
||||
log(DEBUGNET, "\t\tIP is Real = false")
|
||||
return false
|
||||
} else {
|
||||
log(DEBUGNET, "\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(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.ipchange = true
|
||||
return
|
||||
}
|
||||
me.ifmap[i.Index].gone = false
|
||||
log(args.VerboseNet, "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(val.iface.Name, "has changed to it's name to", i.Name)
|
||||
me.ifmap[i.Index].iface = &i
|
||||
me.ipchange = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
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 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("\tIP is Real ", ipt, i.Index, i.Name, s)
|
||||
if (t.ipv6) {
|
||||
ipv6s[s] = t
|
||||
} else {
|
||||
ipv4s[s] = t
|
||||
}
|
||||
} else {
|
||||
log("\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(args.VerboseNet, "\t\taddr.(type) = *net.IPNet")
|
||||
log(args.VerboseNet, "\t\taddr.(type) =", ip)
|
||||
var realip string
|
||||
realip = ip.IP.String()
|
||||
|
||||
val, ok := me.ipmap[realip]
|
||||
if ok {
|
||||
log(args.VerboseNet, 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"
|
||||
} else {
|
||||
me.ipmap[realip].ipv6 = false
|
||||
me.ipmap[realip].ipv4 = true
|
||||
}
|
||||
if (IsReal(&ip.IP)) {
|
||||
log("\tIP is Real ", t, i.Index, i.Name, realip)
|
||||
} else {
|
||||
log("\tIP is not Real", t, i.Index, i.Name, realip)
|
||||
}
|
||||
log(args.VerboseNet, "\t\tIP is IsPrivate() =", ip.IP.IsPrivate())
|
||||
log(args.VerboseNet, "\t\tIP is IsLoopback() =", ip.IP.IsLoopback())
|
||||
log(args.VerboseNet, "\t\tIP is IsLinkLocalUnicast() =", ip.IP.IsLinkLocalUnicast())
|
||||
// log("HERE HERE", "realip =", realip, "me.ip[realip]=", me.ipmap[realip])
|
||||
return true
|
||||
}
|
||||
|
||||
func scanInterfaces() {
|
||||
me.ipchange = false
|
||||
ifaces, _ := net.Interfaces()
|
||||
// me.ifnew = ifaces
|
||||
log(DEBUGNET, SPEW, ifaces)
|
||||
for _, i := range ifaces {
|
||||
addrs, _ := i.Addrs()
|
||||
// log("range ifaces = ", i)
|
||||
checkInterface(i)
|
||||
log(args.VerboseNet, "*net.Interface.Name = ", i.Name, i.Index)
|
||||
log(args.VerboseNet, SPEW, i)
|
||||
log(DEBUGNET, SPEW, addrs)
|
||||
for _, addr := range addrs {
|
||||
log(DEBUGNET, "\taddr =", addr)
|
||||
log(DEBUGNET, SPEW, addrs)
|
||||
ips, _ := net.LookupIP(addr.String())
|
||||
log(DEBUGNET, "\tLookupIP(addr) =", ips)
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
checkIP(v, i)
|
||||
// log("\t\tIP is () =", ip.())
|
||||
default:
|
||||
log(DEBUGNET, "\t\taddr.(type) = NO IDEA WHAT TO DO HERE v =", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
deleteChanges()
|
||||
}
|
||||
|
||||
// delete network interfaces and ip addresses from the gui
|
||||
func deleteChanges() {
|
||||
for i, t := range me.ifmap {
|
||||
if (t.gone) {
|
||||
log("DELETE int =", i, "name =", t.name, t.iface)
|
||||
delete(me.ifmap, i)
|
||||
}
|
||||
t.gone = true
|
||||
}
|
||||
for s, t := range me.ipmap {
|
||||
if (t.gone) {
|
||||
log("DELETE name =", s, "IPv4 =", t.ipv4)
|
||||
log("DELETE name =", s, "IPv6 =", t.ipv6)
|
||||
log("DELETE name =", s, "iface =", t.iface)
|
||||
log("DELETE name =", s, "ip =", t.ip)
|
||||
delete(me.ipmap, s)
|
||||
}
|
||||
t.gone = true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package main
|
||||
|
||||
// examples of what ifconfig does
|
||||
// example of AF_NETLINK change:
|
||||
// https://stackoverflow.com/questions/579783/how-to-detect-ip-address-change-programmatically-in-linux/2353441#2353441
|
||||
// from that page, a link to watch for any ip event:
|
||||
// https://github.com/angt/ipevent/blob/master/ipevent.c
|
||||
|
||||
// https://github.com/mdlayher/talks : Linux, Netlink, and Go in 7 minutes or less! (GopherCon 2018, lightning talk)
|
||||
|
||||
/*
|
||||
c example from ipevent.c :
|
||||
int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
|
||||
struct sockaddr_nl snl = {
|
||||
.nl_family = AF_NETLINK,
|
||||
.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR,
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
import (
|
||||
// "os"
|
||||
// "os/exec"
|
||||
// "log"
|
||||
// "net"
|
||||
// "unix"
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/jsimonetti/rtnetlink"
|
||||
// "git.wit.org/wit/gui"
|
||||
// "github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
// In golang, write a function to register with netlink to detect changes to any network interface Use tab indentation. Do not include example usage.
|
||||
|
||||
func registerNetlink() error {
|
||||
// Create netlink socket
|
||||
sock, err := netlink.Socket(rtnetlink.NETLINK_ROUTE, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Register for interface change events
|
||||
err = netlink.AddMembership(sock, netlink.RTNLGRP_LINK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Close the socket
|
||||
defer sock.Close()
|
||||
// Handle incoming notifications
|
||||
for {
|
||||
msgs, _, err := sock.Receive()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
switch msg.Header.Type {
|
||||
case unix.RTM_NEWLINK:
|
||||
// Do something with new link
|
||||
case unix.RTM_DELLINK:
|
||||
// Do something with deleted link
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,24 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/jsimonetti/rtnetlink"
|
||||
)
|
||||
|
||||
// List all interfaces
|
||||
func Example_listLink() {
|
||||
// Dial a connection to the rtnetlink socket
|
||||
conn, err := rtnetlink.Dial(nil)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Request a list of interfaces
|
||||
msg, err := conn.Link.List()
|
||||
if err != nil {
|
||||
log(err)
|
||||
}
|
||||
|
||||
log("%#v", msg)
|
||||
log(SPEW, msg)
|
||||
}
|
24
unix.go
24
unix.go
|
@ -7,7 +7,6 @@ package main
|
|||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"log"
|
||||
"net"
|
||||
// "git.wit.org/wit/gui"
|
||||
// "github.com/davecgh/go-spew/spew"
|
||||
|
@ -19,13 +18,13 @@ func CheckSuperuser() bool {
|
|||
|
||||
func Escalate() {
|
||||
if os.Getuid() != 0 {
|
||||
cmd := exec.Command("sudo", "./control-panel-dns")
|
||||
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.Fatal(err)
|
||||
exit(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,16 +38,29 @@ func DumpPublicDNSZone(zone string) {
|
|||
panic(err)
|
||||
}
|
||||
for _, entry := range entries {
|
||||
log.Println(entry)
|
||||
log(entry)
|
||||
}
|
||||
}
|
||||
|
||||
func dumpIPs(host string) {
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
exit(err)
|
||||
}
|
||||
for _, ip := range ips {
|
||||
log.Println(host, ip)
|
||||
log(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() {
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue