mirror of
https://github.com/unraid/webgui.git
synced 2026-05-05 01:09:25 -05:00
Update go code
This commit is contained in:
@@ -1,25 +0,0 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2021, Scott Ellis
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,14 +0,0 @@
|
||||
module github.com/SimonFair/unraidwold/v2
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/google/gopacket v1.1.19
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
golang.org/x/net v0.5.0 // indirect
|
||||
golang.org/x/sys v0.4.0 // indirect
|
||||
golang.org/x/text v0.6.0 // indirect
|
||||
)
|
||||
@@ -1,63 +0,0 @@
|
||||
github.com/antchfx/xmlquery v1.3.15 h1:aJConNMi1sMha5G8YJoAIF5P+H+qG1L73bSItWHo8Tw=
|
||||
github.com/antchfx/xmlquery v1.3.15/go.mod h1:zMDv5tIGjOxY/JCNNinnle7V/EwthZ5IT8eeCGJKRWA=
|
||||
github.com/antchfx/xpath v1.2.3 h1:CCZWOzv5bAqjVv0offZ2LVgVYFbeldKQVuLNbViZdes=
|
||||
github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/digitalocean/go-libvirt v0.0.0-20221205150000-2939327a8519 h1:OpkN/n40cmKenDQS+IOAeW9DLhYy4DADSeZnouCEV/E=
|
||||
github.com/digitalocean/go-libvirt v0.0.0-20221205150000-2939327a8519/go.mod h1:WyJJyfmJ0gWJvjV+ZH4DOgtOYZc1KOvYyBXWCLKxsUU=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
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.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1,236 +0,0 @@
|
||||
// Copyright (c) 2021, Scott Ellis
|
||||
// All rights reserved.
|
||||
// Copyright (c) 2023 Limetech, Simon Fairweather.
|
||||
//
|
||||
// Unraid Wake-on-LAN(V1.0.0)
|
||||
//
|
||||
// Listens for a WOL magic packet (UDP) and ether frame type 0x0842
|
||||
// If a matching VM/Docker or LXC is found, it is started (if not already running) and resumed if paused
|
||||
//
|
||||
// Filters on ether proto 0x0842 or udp port 9
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"log/syslog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/pcap"
|
||||
"github.com/google/gopacket/layers"
|
||||
|
||||
)
|
||||
|
||||
var logger *log.Logger
|
||||
|
||||
func main() {
|
||||
var logOutput io.Writer
|
||||
var (
|
||||
appVersion bool
|
||||
interfaceName string
|
||||
logFile string
|
||||
promiscuous bool
|
||||
)
|
||||
|
||||
flag.BoolVar(&appVersion, "version", false, "Print the version and copyright information")
|
||||
flag.StringVar(&interfaceName, "interface", "", "Network interface name (required)")
|
||||
flag.StringVar(&logFile, "log", "", "Log file path")
|
||||
flag.BoolVar(&promiscuous, "promiscuous", false, "Enable promiscuous mode")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
versionInfo := "Unraid Wake-on-LAN (V1.0.0)\nCopyright (c) 2021, Scott Ellis\nAll rights reserved.\nCopyright (c) 2023 Limetech, Simon Fairweather.\n"
|
||||
|
||||
// Check if the version flag is set
|
||||
if appVersion {
|
||||
fmt.Println(versionInfo)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the required --interface flag is provided
|
||||
if interfaceName == "" {
|
||||
fmt.Println("Error: The --interface flag is required")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
deviceError := deviceExists(interfaceName)
|
||||
if (! deviceError) {
|
||||
fmt.Println("Error: The --interface network address is not valid")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
||||
// Set up logging
|
||||
|
||||
if logFile != "" {
|
||||
// If a log file is specified, create or append to the file
|
||||
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
//defer file.Close()
|
||||
logOutput = io.MultiWriter(file, os.Stdout) // Log to both file and stdout
|
||||
} else {
|
||||
// If no log file is specified, log to syslog
|
||||
syslogWriter, err := syslog.New(syslog.LOG_INFO|syslog.LOG_DAEMON, "Unraidwold")
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
logOutput = syslogWriter
|
||||
}
|
||||
|
||||
// Create a logger that writes to the specified output
|
||||
logger = log.New(logOutput, "", log.LstdFlags)
|
||||
|
||||
|
||||
var filter = "ether proto 0x0842 or udp port 9"
|
||||
|
||||
// Create a PID file
|
||||
pidFile := "/var/run/unraidwold.pid" // Change the path as needed
|
||||
err := writePIDFile(pidFile)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
logger.Println("Processing WOL Requests.")
|
||||
// Check if promiscuous mode is enabled
|
||||
if promiscuous {
|
||||
logger.Println("Promiscuous mode is enabled")
|
||||
}
|
||||
|
||||
|
||||
handle, err := pcap.OpenLive(interfaceName, 1600, promiscuous, pcap.BlockForever)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
if err := handle.SetBPFFilter(filter); err != nil {
|
||||
log.Fatalf("Something in the BPF went wrong!: %v", err)
|
||||
}
|
||||
defer handle.Close()
|
||||
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
doneChan := make(chan bool, 1)
|
||||
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go processPackets(handle, signalChan, doneChan)
|
||||
|
||||
// Wait for a signal to exit
|
||||
<-doneChan
|
||||
//fmt.Println("Exiting...")
|
||||
removePIDFile(pidFile)
|
||||
logger.Println("Stopping WOL Daemon.")
|
||||
// Close down.
|
||||
os.Exit(1)
|
||||
//return
|
||||
}
|
||||
|
||||
func writePIDFile(pidFile string) error {
|
||||
pid := os.Getpid()
|
||||
pidStr := fmt.Sprintf("%d\n", pid)
|
||||
return ioutil.WriteFile(pidFile, []byte(pidStr), 0644)
|
||||
}
|
||||
|
||||
func removePIDFile(pidFile string) {
|
||||
err := os.Remove(pidFile)
|
||||
if err != nil {
|
||||
logger.Printf("Error removing PID file: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func processPackets(handle *pcap.Handle, signalChan chan os.Signal, doneChan chan bool) error {
|
||||
var mac string
|
||||
|
||||
source := gopacket.NewPacketSource(handle, handle.LinkType())
|
||||
for {
|
||||
select {
|
||||
case packet := <-source.Packets():
|
||||
ethLayer := packet.Layer(layers.LayerTypeEthernet)
|
||||
udpLayer := packet.Layer(layers.LayerTypeUDP)
|
||||
|
||||
if ethLayer != nil {
|
||||
ethernetPacket, _ := ethLayer.(*layers.Ethernet)
|
||||
if ethernetPacket.EthernetType == 0x0842 {
|
||||
payload := ethernetPacket.Payload
|
||||
mac = fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", payload[6], payload[7], payload[8], payload[9], payload[10], payload[11])
|
||||
}
|
||||
}
|
||||
|
||||
if udpLayer != nil {
|
||||
udpPacket, _ := udpLayer.(*layers.UDP)
|
||||
if udpPacket.DstPort == layers.UDPPort(9) {
|
||||
appPacket := packet.ApplicationLayer()
|
||||
if appPacket != nil {
|
||||
payload := appPacket.Payload()
|
||||
mac = fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", payload[12], payload[13], payload[14], payload[15], payload[16], payload[17])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go runcmd(mac)
|
||||
|
||||
case sig := <-signalChan:
|
||||
fmt.Printf("Received signal: %v\n", sig)
|
||||
doneChan <- true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func runcmd(mac string) bool {
|
||||
app := "/usr/local/emhttp/plugins/dynamix/include/WOLrun.php"
|
||||
arg := mac
|
||||
cmd := exec.Command(app, arg)
|
||||
stdout, err := cmd.Output()
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return false
|
||||
}
|
||||
// Print the output
|
||||
logger.Println(string(stdout))
|
||||
return true
|
||||
}
|
||||
|
||||
// Return the first MAC address seen in the UDP WOL packet
|
||||
func GrabMACAddrUDP(packet gopacket.Packet) (string, error) {
|
||||
app := packet.ApplicationLayer()
|
||||
if app != nil {
|
||||
payload := app.Payload()
|
||||
mac := fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", payload[12], payload[13], payload[14], payload[15], payload[16], payload[17])
|
||||
//fmt.Printf("found MAC: %s\n", mac)
|
||||
return mac, nil
|
||||
}
|
||||
return "", errors.New("no MAC found in packet")
|
||||
}
|
||||
|
||||
// Check if the network device exists
|
||||
func deviceExists(interfacename string) bool {
|
||||
if interfacename == "" {
|
||||
fmt.Printf("No valid interface to listen on specified\n\n")
|
||||
return false
|
||||
}
|
||||
devices, err := pcap.FindAllDevs()
|
||||
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
for _, device := range devices {
|
||||
if device.Name == interfacename {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user