|
@@ -79,12 +79,24 @@ func (s *Server) Run(ctx context.Context) error {
|
|
|
AuthRequired: true,
|
|
AuthRequired: true,
|
|
|
}
|
|
}
|
|
|
payload, _ := json.Marshal(resp)
|
|
payload, _ := json.Marshal(resp)
|
|
|
- if _, err := writeToUDP(conn, payload, remote, packetInfo, net.ParseIP(lan2IP)); err != nil {
|
|
|
|
|
- s.log.Warn("failed to send udp discovery response", "remote", remote.String(), "local_ip", lan2IP, "interface_index", packetInfo.ifIndex, "error", err.Error())
|
|
|
|
|
|
|
+ responseSourceIP := findResponseSourceIP(packetInfo.ifIndex, remote.IP)
|
|
|
|
|
+ responseTarget := remote
|
|
|
|
|
+ broadcastResponse := false
|
|
|
|
|
+ if responseSourceIP == nil && packetInfo.ifIndex > 0 {
|
|
|
|
|
+ responseSourceIP = net.ParseIP(lan2IP)
|
|
|
|
|
+ responseTarget = broadcastResponseTarget(remote)
|
|
|
|
|
+ broadcastResponse = true
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := writeToUDP(conn, payload, responseTarget, packetInfo, responseSourceIP); err != nil {
|
|
|
|
|
+ s.log.Warn("failed to send udp discovery response", "remote", remote.String(), "target", responseTarget.String(), "source_ip", responseSourceIP.String(), "maintenance_ip", lan2IP, "interface_index", packetInfo.ifIndex, "broadcast", broadcastResponse, "error", err.Error())
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func broadcastResponseTarget(remote *net.UDPAddr) *net.UDPAddr {
|
|
|
|
|
+ return &net.UDPAddr{IP: net.IPv4bcast, Port: remote.Port}
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
type udpPacketInfo struct {
|
|
type udpPacketInfo struct {
|
|
|
localIP net.IP
|
|
localIP net.IP
|
|
|
ifIndex int
|
|
ifIndex int
|
|
@@ -96,6 +108,7 @@ func (s *Server) maintenanceEndpoint(packetInfo udpPacketInfo) (string, string)
|
|
|
if lan2IP != "" {
|
|
if lan2IP != "" {
|
|
|
return lan2IP, mac
|
|
return lan2IP, mac
|
|
|
}
|
|
}
|
|
|
|
|
+ return "", ""
|
|
|
}
|
|
}
|
|
|
if packetInfo.localIP != nil {
|
|
if packetInfo.localIP != nil {
|
|
|
lan2IP, mac := findLinkLocalEndpointByInterfaceIP(packetInfo.localIP.String())
|
|
lan2IP, mac := findLinkLocalEndpointByInterfaceIP(packetInfo.localIP.String())
|
|
@@ -112,6 +125,43 @@ func (s *Server) maintenanceEndpoint(packetInfo udpPacketInfo) (string, string)
|
|
|
return findFirstLinkLocalEndpoint()
|
|
return findFirstLinkLocalEndpoint()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func findResponseSourceIP(interfaceIndex int, remoteIP net.IP) net.IP {
|
|
|
|
|
+ if interfaceIndex <= 0 {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+ iface, err := net.InterfaceByIndex(interfaceIndex)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+ addresses, err := iface.Addrs()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+ return bestSourceIPForRemote(addresses, remoteIP)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func bestSourceIPForRemote(addresses []net.Addr, remoteIP net.IP) net.IP {
|
|
|
|
|
+ remoteIPv4 := remoteIP.To4()
|
|
|
|
|
+ if remoteIPv4 == nil {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+ var best net.IP
|
|
|
|
|
+ bestPrefix := -1
|
|
|
|
|
+ for _, address := range addresses {
|
|
|
|
|
+ ipNet, ok := address.(*net.IPNet)
|
|
|
|
|
+ if !ok || ipNet.IP.To4() == nil || !ipNet.Contains(remoteIPv4) {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ prefix, bits := ipNet.Mask.Size()
|
|
|
|
|
+ if bits != 32 || prefix <= bestPrefix {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ best = ipNet.IP.To4()
|
|
|
|
|
+ bestPrefix = prefix
|
|
|
|
|
+ }
|
|
|
|
|
+ return best
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func findLinkLocalEndpointByInterfaceIndex(index int) (string, string) {
|
|
func findLinkLocalEndpointByInterfaceIndex(index int) (string, string) {
|
|
|
iface, err := net.InterfaceByIndex(index)
|
|
iface, err := net.InterfaceByIndex(index)
|
|
|
if err != nil {
|
|
if err != nil {
|