mirror of
https://github.com/jetkvm/kvm.git
synced 2026-05-21 05:20:35 +00:00
72d27ac85e
* fix: add custom broadcast IP option to Wake-on-LAN (#1238) Add support for specifying a custom subnet broadcast IP when sending WOL magic packets, enabling wake across different subnets. Backend: - Add broadcastIP optional parameter to rpcSendWOLMagicPacket - Add OptionalParams support to RPCHandler for params with zero defaults - Pass broadcastIP query param through HTTP handler UI: - Add broadcast address dropdown (Auto/Custom) to WOL dialog - Show subnet broadcast IP input when Custom is selected - Pass broadcastIP to RPC call when custom mode is active * fix: move broadcast address field to add form only, default to Auto (#1238) * fix(ui): simplify WoL broadcast dropdown and indent custom field - Rename "Auto (global broadcast)" to "Auto" in the broadcast address dropdown - Wrap the custom subnet IP input in a nested indent with left border, matching the settings page pattern (NestedSettingsGroup style) * fix(i18n): use localization system for WoL broadcast address labels Replace hardcoded English strings with m.xxx() calls in the broadcast address UI and add the 4 new keys to all 14 locale files.
86 lines
2.0 KiB
Go
86 lines
2.0 KiB
Go
package kvm
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
|
)
|
|
|
|
var (
|
|
wolPackets = promauto.NewCounter(
|
|
prometheus.CounterOpts{
|
|
Name: "jetkvm_wol_sent_packets_total",
|
|
Help: "Total number of Wake-on-LAN magic packets sent.",
|
|
},
|
|
)
|
|
wolErrors = promauto.NewCounter(
|
|
prometheus.CounterOpts{
|
|
Name: "jetkvm_wol_sent_packet_errors_total",
|
|
Help: "Total number of Wake-on-LAN magic packets errors.",
|
|
},
|
|
)
|
|
)
|
|
|
|
// SendWOLMagicPacket sends a Wake-on-LAN magic packet to the specified MAC address.
|
|
// broadcastIP optionally overrides the default 255.255.255.255 broadcast address.
|
|
func rpcSendWOLMagicPacket(macAddress string, broadcastIP string) error {
|
|
// Parse the MAC address
|
|
mac, err := net.ParseMAC(macAddress)
|
|
if err != nil {
|
|
wolErrors.Inc()
|
|
return ErrorfL(wolLogger, "invalid MAC address", err)
|
|
}
|
|
|
|
// Determine broadcast address
|
|
target := "255.255.255.255"
|
|
if broadcastIP != "" {
|
|
if ip := net.ParseIP(broadcastIP); ip == nil || ip.To4() == nil {
|
|
wolErrors.Inc()
|
|
return ErrorfL(wolLogger, "invalid broadcast IP address", fmt.Errorf("invalid IP: %s", broadcastIP))
|
|
}
|
|
target = broadcastIP
|
|
}
|
|
|
|
// Create the magic packet
|
|
packet := createMagicPacket(mac)
|
|
|
|
// Set up UDP connection
|
|
conn, err := net.Dial("udp", target+":9")
|
|
if err != nil {
|
|
wolErrors.Inc()
|
|
return ErrorfL(wolLogger, "failed to establish UDP connection", err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
// Send the packet
|
|
_, err = conn.Write(packet)
|
|
if err != nil {
|
|
wolErrors.Inc()
|
|
return ErrorfL(wolLogger, "failed to send WOL packet", err)
|
|
}
|
|
|
|
wolLogger.Info().Str("mac", macAddress).Msg("WOL packet sent")
|
|
wolPackets.Inc()
|
|
|
|
return nil
|
|
}
|
|
|
|
// createMagicPacket creates a Wake-on-LAN magic packet
|
|
func createMagicPacket(mac net.HardwareAddr) []byte {
|
|
var buf bytes.Buffer
|
|
|
|
// Write 6 bytes of 0xFF
|
|
buf.Write(bytes.Repeat([]byte{0xFF}, 6))
|
|
|
|
// Write the target MAC address 16 times
|
|
for range 16 {
|
|
_ = binary.Write(&buf, binary.BigEndian, mac)
|
|
}
|
|
|
|
return buf.Bytes()
|
|
}
|