|
|
@@ -40,9 +40,13 @@ func (s *Server) Run(ctx context.Context) error {
|
|
|
}()
|
|
|
|
|
|
s.log.Info("udp discovery listening", "addr", conn.LocalAddr().String())
|
|
|
+ if err := enableLocalAddrControl(conn); err != nil {
|
|
|
+ s.log.Warn("udp discovery local interface detection is unavailable", "error", err.Error())
|
|
|
+ }
|
|
|
+
|
|
|
buf := make([]byte, 2048)
|
|
|
for {
|
|
|
- n, remote, err := conn.ReadFromUDP(buf)
|
|
|
+ n, remote, packetInfo, err := readFromUDP(conn, buf)
|
|
|
if err != nil {
|
|
|
if ctx.Err() != nil {
|
|
|
return nil
|
|
|
@@ -55,7 +59,7 @@ func (s *Server) Run(ctx context.Context) error {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
- lan2IP, mac := s.maintenanceEndpoint()
|
|
|
+ lan2IP, mac := s.maintenanceEndpoint(packetInfo)
|
|
|
if lan2IP == "" {
|
|
|
s.log.Warn("skip discovery response because no 169.254 maintenance address was found")
|
|
|
continue
|
|
|
@@ -79,36 +83,83 @@ func (s *Server) Run(ctx context.Context) error {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (s *Server) maintenanceEndpoint() (string, string) {
|
|
|
+type udpPacketInfo struct {
|
|
|
+ localIP net.IP
|
|
|
+ ifIndex int
|
|
|
+}
|
|
|
+
|
|
|
+func (s *Server) maintenanceEndpoint(packetInfo udpPacketInfo) (string, string) {
|
|
|
if s.cfg.MaintenanceIP != "" {
|
|
|
mac := findMACByIP(s.cfg.MaintenanceIP)
|
|
|
if mac != "" {
|
|
|
return s.cfg.MaintenanceIP, mac
|
|
|
}
|
|
|
}
|
|
|
+ if packetInfo.ifIndex > 0 {
|
|
|
+ lan2IP, mac := findLinkLocalEndpointByInterfaceIndex(packetInfo.ifIndex)
|
|
|
+ if lan2IP != "" {
|
|
|
+ return lan2IP, mac
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if packetInfo.localIP != nil {
|
|
|
+ lan2IP, mac := findLinkLocalEndpointByInterfaceIP(packetInfo.localIP.String())
|
|
|
+ if lan2IP != "" {
|
|
|
+ return lan2IP, mac
|
|
|
+ }
|
|
|
+ }
|
|
|
return findFirstLinkLocalEndpoint()
|
|
|
}
|
|
|
|
|
|
+func findLinkLocalEndpointByInterfaceIndex(index int) (string, string) {
|
|
|
+ iface, err := net.InterfaceByIndex(index)
|
|
|
+ if err != nil {
|
|
|
+ return "", ""
|
|
|
+ }
|
|
|
+ return findLinkLocalEndpointOnInterface(*iface)
|
|
|
+}
|
|
|
+
|
|
|
+func findLinkLocalEndpointByInterfaceIP(ip string) (string, string) {
|
|
|
+ ifaces, err := net.Interfaces()
|
|
|
+ if err != nil {
|
|
|
+ return "", ""
|
|
|
+ }
|
|
|
+ for _, iface := range ifaces {
|
|
|
+ lan2IP, mac := findLinkLocalEndpointOnInterface(iface)
|
|
|
+ if lan2IP == ip {
|
|
|
+ return lan2IP, mac
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "", ""
|
|
|
+}
|
|
|
+
|
|
|
func findFirstLinkLocalEndpoint() (string, string) {
|
|
|
ifaces, err := net.Interfaces()
|
|
|
if err != nil {
|
|
|
return "", ""
|
|
|
}
|
|
|
for _, iface := range ifaces {
|
|
|
- if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 || len(iface.HardwareAddr) == 0 {
|
|
|
- continue
|
|
|
+ lan2IP, mac := findLinkLocalEndpointOnInterface(iface)
|
|
|
+ if lan2IP != "" {
|
|
|
+ return lan2IP, mac
|
|
|
}
|
|
|
- addrs, err := iface.Addrs()
|
|
|
- if err != nil {
|
|
|
+ }
|
|
|
+ return "", ""
|
|
|
+}
|
|
|
+
|
|
|
+func findLinkLocalEndpointOnInterface(iface net.Interface) (string, string) {
|
|
|
+ if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 || len(iface.HardwareAddr) == 0 {
|
|
|
+ return "", ""
|
|
|
+ }
|
|
|
+ addrs, err := iface.Addrs()
|
|
|
+ if err != nil {
|
|
|
+ return "", ""
|
|
|
+ }
|
|
|
+ for _, addr := range addrs {
|
|
|
+ current := ipv4FromAddr(addr)
|
|
|
+ if current == nil || !strings.HasPrefix(current.String(), "169.254.") {
|
|
|
continue
|
|
|
}
|
|
|
- for _, addr := range addrs {
|
|
|
- current := ipv4FromAddr(addr)
|
|
|
- if current == nil || !strings.HasPrefix(current.String(), "169.254.") {
|
|
|
- continue
|
|
|
- }
|
|
|
- return current.String(), iface.HardwareAddr.String()
|
|
|
- }
|
|
|
+ return current.String(), iface.HardwareAddr.String()
|
|
|
}
|
|
|
return "", ""
|
|
|
}
|