Trying goscan
This commit is contained in:
parent
0c410d9458
commit
26f3759936
13 changed files with 254 additions and 107 deletions
2
.version
2
.version
|
|
@ -1 +1 @@
|
|||
internal/web/templates/version
|
||||
internal/web/public/version
|
||||
31
Makefile
31
Makefile
|
|
@ -1,10 +1,3 @@
|
|||
DUSER=aceberg
|
||||
DNAME=watchyourlan
|
||||
|
||||
IFACE=enp4s0
|
||||
DBPATH=/data/hosts.db
|
||||
SHOUTRRR_URL=gotify://192.168.2.1:8083/AwQqpAae.rrl5Ob/?title=Unknown host detected&DisableTLS=yes
|
||||
|
||||
mod:
|
||||
rm go.mod || true && \
|
||||
rm go.sum || true && \
|
||||
|
|
@ -14,7 +7,6 @@ mod:
|
|||
run:
|
||||
cd cmd/WatchYourLAN/ && \
|
||||
sudo \
|
||||
env IFACE=$(IFACE) DBPATH=$(DBPATH) THEME=$(THEME) \
|
||||
go run . #-c /data/config #-n http://192.168.2.3:8850
|
||||
|
||||
fmt:
|
||||
|
|
@ -25,26 +17,3 @@ lint:
|
|||
golint ./...
|
||||
|
||||
check: fmt lint
|
||||
|
||||
go-build:
|
||||
cd cmd/WatchYourLAN/ && \
|
||||
CGO_ENABLED=0 go build -o ../../tmp/WatchYourLAN .
|
||||
|
||||
docker-build:
|
||||
docker build -t $(DUSER)/$(DNAME) .
|
||||
|
||||
docker-run:
|
||||
docker rm wyl || true
|
||||
docker run --name wyl \
|
||||
-e "IFACE=$(IFACE)" \
|
||||
-e "SHOUTRRR_URL=$(SHOUTRRR_URL)" \
|
||||
-e "TZ=Asia/Novosibirsk" \
|
||||
--network="host" \
|
||||
-v ~/.dockerdata/wyl:/data \
|
||||
$(DUSER)/$(DNAME)
|
||||
|
||||
clean:
|
||||
rm src/$(DNAME) || true
|
||||
docker rmi -f $(DUSER)/$(DNAME)
|
||||
|
||||
dev: docker-build docker-run
|
||||
1
go.mod
1
go.mod
|
|
@ -4,6 +4,7 @@ go 1.22.4
|
|||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/spf13/viper v1.19.0
|
||||
)
|
||||
|
||||
|
|
|
|||
14
go.sum
14
go.sum
|
|
@ -33,6 +33,8 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG
|
|||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
|
|
@ -104,18 +106,30 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV
|
|||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
|||
57
internal/arp/arpscan.go
Normal file
57
internal/arp/arpscan.go
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package arp
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aceberg/WatchYourLAN/internal/models"
|
||||
)
|
||||
|
||||
func scanIface(iface string) string {
|
||||
cmd, err := exec.Command("arp-scan", "-glNx", "-I", iface).Output()
|
||||
if err != nil {
|
||||
return string("")
|
||||
}
|
||||
return string(cmd)
|
||||
}
|
||||
|
||||
func parseOutput(text string) []models.Host {
|
||||
var foundHosts = []models.Host{}
|
||||
|
||||
perString := strings.Split(text, "\n")
|
||||
currentTime := time.Now()
|
||||
|
||||
for _, host := range perString {
|
||||
if host != "" {
|
||||
var oneHost models.Host
|
||||
p := strings.Split(host, " ")
|
||||
oneHost.IP = p[0]
|
||||
oneHost.Mac = p[1]
|
||||
oneHost.Hw = p[2]
|
||||
oneHost.Date = currentTime.Format("2006-01-02 15:04:05")
|
||||
oneHost.Now = 1
|
||||
foundHosts = append(foundHosts, oneHost)
|
||||
}
|
||||
}
|
||||
|
||||
return foundHosts
|
||||
}
|
||||
|
||||
// Scan all interfaces
|
||||
func Scan(ifaces []string) []models.Host {
|
||||
var text string
|
||||
var foundHosts = []models.Host{}
|
||||
|
||||
for _, iface := range ifaces {
|
||||
text = scanIface(iface)
|
||||
|
||||
log.Println("INFO: scanning interface", iface)
|
||||
log.Println("INFO: found IPs:", text)
|
||||
|
||||
foundHosts = append(foundHosts, parseOutput(text)...)
|
||||
}
|
||||
|
||||
return foundHosts
|
||||
}
|
||||
156
internal/arp/goscan.go
Normal file
156
internal/arp/goscan.go
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
package arp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/google/gopacket/pcap"
|
||||
)
|
||||
|
||||
// GoScan - scan iface
|
||||
func GoScan() {
|
||||
|
||||
iface, _ := net.InterfaceByName("enp4s0")
|
||||
err := scan(iface)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
func scan(iface *net.Interface) error {
|
||||
// We just look for IPv4 addresses, so try to find if the interface has one.
|
||||
var addr *net.IPNet
|
||||
if addrs, err := iface.Addrs(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
for _, a := range addrs {
|
||||
if ipnet, ok := a.(*net.IPNet); ok {
|
||||
if ip4 := ipnet.IP.To4(); ip4 != nil {
|
||||
addr = &net.IPNet{
|
||||
IP: ip4,
|
||||
Mask: ipnet.Mask[len(ipnet.Mask)-4:],
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Sanity-check that the interface has a good address.
|
||||
if addr == nil {
|
||||
return errors.New("no good IP network found")
|
||||
} else if addr.IP[0] == 127 {
|
||||
return errors.New("skipping localhost")
|
||||
} else if addr.Mask[0] != 0xff || addr.Mask[1] != 0xff {
|
||||
return errors.New("mask means network is too large")
|
||||
}
|
||||
log.Printf("Using network range %v for interface %v", addr, iface.Name)
|
||||
|
||||
// Open up a pcap handle for packet reads/writes.
|
||||
handle, err := pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer handle.Close()
|
||||
|
||||
// Start up a goroutine to read in packet data.
|
||||
stop := make(chan struct{})
|
||||
go readARP(handle, iface, stop)
|
||||
defer close(stop)
|
||||
// for {
|
||||
// Write our scan packets out to the handle.
|
||||
if err := writeARP(handle, iface, addr); err != nil {
|
||||
log.Printf("error writing packets on %v: %v", iface.Name, err)
|
||||
return err
|
||||
}
|
||||
// We don't know exactly how long it'll take for packets to be
|
||||
// sent back to us, but 10 seconds should be more than enough
|
||||
// time ;)
|
||||
time.Sleep(10 * time.Second)
|
||||
// }
|
||||
return err
|
||||
}
|
||||
|
||||
// readARP watches a handle for incoming ARP responses we might care about, and prints them.
|
||||
//
|
||||
// readARP loops until 'stop' is closed.
|
||||
func readARP(handle *pcap.Handle, iface *net.Interface, stop chan struct{}) {
|
||||
src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
|
||||
in := src.Packets()
|
||||
for {
|
||||
var packet gopacket.Packet
|
||||
select {
|
||||
case <-stop:
|
||||
return
|
||||
case packet = <-in:
|
||||
arpLayer := packet.Layer(layers.LayerTypeARP)
|
||||
if arpLayer == nil {
|
||||
continue
|
||||
}
|
||||
arp := arpLayer.(*layers.ARP)
|
||||
if arp.Operation != layers.ARPReply || bytes.Equal([]byte(iface.HardwareAddr), arp.SourceHwAddress) {
|
||||
// This is a packet I sent.
|
||||
continue
|
||||
}
|
||||
// Note: we might get some packets here that aren't responses to ones we've sent,
|
||||
// if for example someone else sends US an ARP request. Doesn't much matter, though...
|
||||
// all information is good information :)
|
||||
log.Printf("IP %v is at %v", net.IP(arp.SourceProtAddress), net.HardwareAddr(arp.SourceHwAddress))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// writeARP writes an ARP request for each address on our local network to the
|
||||
// pcap handle.
|
||||
func writeARP(handle *pcap.Handle, iface *net.Interface, addr *net.IPNet) error {
|
||||
// Set up all the layers' fields we can.
|
||||
eth := layers.Ethernet{
|
||||
SrcMAC: iface.HardwareAddr,
|
||||
DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
EthernetType: layers.EthernetTypeARP,
|
||||
}
|
||||
arp := layers.ARP{
|
||||
AddrType: layers.LinkTypeEthernet,
|
||||
Protocol: layers.EthernetTypeIPv4,
|
||||
HwAddressSize: 6,
|
||||
ProtAddressSize: 4,
|
||||
Operation: layers.ARPRequest,
|
||||
SourceHwAddress: []byte(iface.HardwareAddr),
|
||||
SourceProtAddress: []byte(addr.IP),
|
||||
DstHwAddress: []byte{0, 0, 0, 0, 0, 0},
|
||||
}
|
||||
// Set up buffer and options for serialization.
|
||||
buf := gopacket.NewSerializeBuffer()
|
||||
opts := gopacket.SerializeOptions{
|
||||
FixLengths: true,
|
||||
ComputeChecksums: true,
|
||||
}
|
||||
// Send one packet for every address.
|
||||
for _, ip := range ips(addr) {
|
||||
arp.DstProtAddress = []byte(ip)
|
||||
gopacket.SerializeLayers(buf, opts, ð, &arp)
|
||||
if err := handle.WritePacketData(buf.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ips is a simple and not very good method for getting all IPv4 addresses from a
|
||||
// net.IPNet. It returns all IPs it can over the channel it sends back, closing
|
||||
// the channel when done.
|
||||
func ips(n *net.IPNet) (out []net.IP) {
|
||||
num := binary.BigEndian.Uint32([]byte(n.IP))
|
||||
mask := binary.BigEndian.Uint32([]byte(n.Mask))
|
||||
network := num & mask
|
||||
broadcast := network | ^mask
|
||||
for network++; network < broadcast; network++ {
|
||||
var buf [4]byte
|
||||
binary.BigEndian.PutUint32(buf[:], network)
|
||||
out = append(out, net.IP(buf[:]))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ func Get(path string) (config models.Conf) {
|
|||
viper.SetDefault("PORT", "8840")
|
||||
viper.SetDefault("THEME", "solar")
|
||||
viper.SetDefault("COLOR", "dark")
|
||||
viper.SetDefault("NODEPATH", "")
|
||||
|
||||
viper.SetConfigFile(path)
|
||||
viper.SetConfigType("yaml")
|
||||
|
|
@ -26,6 +27,7 @@ func Get(path string) (config models.Conf) {
|
|||
config.Port = viper.Get("PORT").(string)
|
||||
config.Theme = viper.Get("THEME").(string)
|
||||
config.Color = viper.Get("COLOR").(string)
|
||||
config.NodePath = viper.Get("NODEPATH").(string)
|
||||
|
||||
return config
|
||||
}
|
||||
|
|
@ -40,6 +42,7 @@ func Write(config models.Conf) {
|
|||
viper.Set("PORT", config.Port)
|
||||
viper.Set("THEME", config.Theme)
|
||||
viper.Set("COLOR", config.Color)
|
||||
viper.Set("NODEPATH", config.NodePath)
|
||||
|
||||
err := viper.WriteConfig()
|
||||
check.IfError(err)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ type Conf struct {
|
|||
Color string
|
||||
DirPath string
|
||||
ConfPath string
|
||||
DBPath string
|
||||
NodePath string
|
||||
Ifaces []string
|
||||
}
|
||||
|
||||
// Host - one host
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/aceberg/WatchYourLAN/internal/check"
|
||||
// "github.com/aceberg/WatchYourLAN/internal/conf"
|
||||
"github.com/aceberg/WatchYourLAN/internal/conf"
|
||||
"github.com/aceberg/WatchYourLAN/internal/models"
|
||||
)
|
||||
|
||||
|
|
@ -30,21 +30,13 @@ func configHandler(c *gin.Context) {
|
|||
|
||||
func saveConfigHandler(c *gin.Context) {
|
||||
|
||||
// appConfig.Host = c.PostForm("host")
|
||||
// appConfig.Port = c.PostForm("port")
|
||||
// appConfig.Theme = c.PostForm("theme")
|
||||
// appConfig.Color = c.PostForm("color")
|
||||
// tStr := c.PostForm("timeout")
|
||||
// hStr := c.PostForm("trim")
|
||||
appConfig.Host = c.PostForm("host")
|
||||
appConfig.Port = c.PostForm("port")
|
||||
appConfig.Theme = c.PostForm("theme")
|
||||
appConfig.Color = c.PostForm("color")
|
||||
appConfig.NodePath = c.PostForm("node")
|
||||
|
||||
// if tStr != "" {
|
||||
// appConfig.Timeout, _ = strconv.Atoi(tStr)
|
||||
// }
|
||||
// if hStr != "" {
|
||||
// appConfig.HistTrim, _ = strconv.Atoi(hStr)
|
||||
// }
|
||||
|
||||
// conf.Write(appConfig)
|
||||
conf.Write(appConfig)
|
||||
|
||||
slog.Info("writing new config to " + appConfig.ConfPath)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/aceberg/WatchYourLAN/internal/arp"
|
||||
"github.com/aceberg/WatchYourLAN/internal/models"
|
||||
)
|
||||
|
||||
|
|
@ -12,6 +14,11 @@ func indexHandler(c *gin.Context) {
|
|||
var guiData models.GuiData
|
||||
guiData.Config = appConfig
|
||||
|
||||
res := arp.Scan(appConfig.Ifaces)
|
||||
log.Println("ARPSCAN:", res)
|
||||
|
||||
go arp.GoScan()
|
||||
|
||||
c.HTML(http.StatusOK, "header.html", guiData)
|
||||
c.HTML(http.StatusOK, "index.html", guiData)
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 20 KiB |
|
|
@ -35,12 +35,8 @@
|
|||
</select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Timeout (minutes)</td>
|
||||
<td><input name="timeout" type="number" class="form-control" value="{{ .Config.Timeout }}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Trim History</td>
|
||||
<td><input name="trim" type="number" class="form-control" value="{{ .Config.HistTrim }}"></td>
|
||||
<td>Local node-bootstrap url</td>
|
||||
<td><input name="node" type="text" class="form-control" value="{{ .Config.NodePath }}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><button type="submit" class="btn btn-primary">Save</button></td>
|
||||
|
|
@ -58,59 +54,6 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-md mt-4">
|
||||
<div class="card border-primary">
|
||||
<div class="card-header">InfluxDB2 config</div>
|
||||
<div class="card-body table-responsive">
|
||||
<table class="table table-borderless">
|
||||
<form action="/config_influx/" method="post">
|
||||
<tr>
|
||||
<td>Enable</td>
|
||||
<td>
|
||||
<div class="form-check form-switch">
|
||||
{{ if .Config.InfluxEnable }}
|
||||
<input class="form-check-input" type="checkbox" name="enable" checked>
|
||||
{{ else }}
|
||||
<input class="form-check-input" type="checkbox" name="enable">
|
||||
{{ end }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Address</td>
|
||||
<td><input name="addr" type="text" class="form-control" value="{{ .Config.InfluxAddr }}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Token</td>
|
||||
<td><input name="token" type="text" class="form-control" value="{{ .Config.InfluxToken }}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Org</td>
|
||||
<td><input name="org" type="text" class="form-control" value="{{ .Config.InfluxOrg }}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bucket</td>
|
||||
<td><input name="bucket" type="text" class="form-control" value="{{ .Config.InfluxBucket }}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Skip TLS verify</td>
|
||||
<td>
|
||||
<div class="form-check form-switch">
|
||||
{{ if .Config.InfluxSkipTLS }}
|
||||
<input class="form-check-input" type="checkbox" name="skip" checked>
|
||||
{{ else }}
|
||||
<input class="form-check-input" type="checkbox" name="skip">
|
||||
{{ end }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><button type="submit" class="btn btn-primary">Save</button></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</form>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card border-primary mt-4 mb-4">
|
||||
<div class="card-header">About</div>
|
||||
<div class="card-body">
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ func Gui(dirPath, nodePath string) {
|
|||
appConfig.ConfPath = confPath
|
||||
appConfig.NodePath = nodePath
|
||||
|
||||
// temp
|
||||
appConfig.Ifaces = append(appConfig.Ifaces, "enp4s0")
|
||||
|
||||
slog.Info("config", "path", appConfig.DirPath)
|
||||
|
||||
address := appConfig.Host + ":" + appConfig.Port
|
||||
|
|
|
|||
Loading…
Reference in a new issue