mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-29 01:04:15 -04:00 
			
		
		
		
	This fixes a bug introduced in https://github.com/coredns/coredns/pull/6547 which resulted in the zone being added to IPv4 addresses. This bug results in a failure to start when binding to an interface with a link-local IPv4 address assigned to it, with the following error: $ ./coredns -conf=/etc/coredns/Corefile maxprocs: Leaving GOMAXPROCS=4: CPU quota undefined lookup 169.254.1.1%dummy0: no such host Signed-off-by: Mark Mickan <mark.mickan@openlms.net> Co-authored-by: Mark Mickan <mark.mickan@openlms.net>
		
			
				
	
	
		
			109 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package bind
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"net"
 | |
| 	"slices"
 | |
| 
 | |
| 	"github.com/coredns/caddy"
 | |
| 	"github.com/coredns/coredns/core/dnsserver"
 | |
| 	"github.com/coredns/coredns/plugin"
 | |
| 	"github.com/coredns/coredns/plugin/pkg/log"
 | |
| )
 | |
| 
 | |
| func setup(c *caddy.Controller) error {
 | |
| 	config := dnsserver.GetConfig(c)
 | |
| 	// addresses will be consolidated over all BIND directives available in that BlocServer
 | |
| 	all := []string{}
 | |
| 	ifaces, err := net.Interfaces()
 | |
| 	if err != nil {
 | |
| 		log.Warning(plugin.Error("bind", fmt.Errorf("failed to get interfaces list, cannot bind by interface name: %s", err)))
 | |
| 	}
 | |
| 
 | |
| 	for c.Next() {
 | |
| 		b, err := parse(c)
 | |
| 		if err != nil {
 | |
| 			return plugin.Error("bind", err)
 | |
| 		}
 | |
| 
 | |
| 		ips, err := listIP(b.addrs, ifaces)
 | |
| 		if err != nil {
 | |
| 			return plugin.Error("bind", err)
 | |
| 		}
 | |
| 
 | |
| 		except, err := listIP(b.except, ifaces)
 | |
| 		if err != nil {
 | |
| 			return plugin.Error("bind", err)
 | |
| 		}
 | |
| 
 | |
| 		for _, ip := range ips {
 | |
| 			if !slices.Contains(except, ip) {
 | |
| 				all = append(all, ip)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	config.ListenHosts = all
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func parse(c *caddy.Controller) (*bind, error) {
 | |
| 	b := &bind{}
 | |
| 	b.addrs = c.RemainingArgs()
 | |
| 	if len(b.addrs) == 0 {
 | |
| 		return nil, errors.New("at least one address or interface name is expected")
 | |
| 	}
 | |
| 	for c.NextBlock() {
 | |
| 		switch c.Val() {
 | |
| 		case "except":
 | |
| 			b.except = c.RemainingArgs()
 | |
| 			if len(b.except) == 0 {
 | |
| 				return nil, errors.New("at least one address or interface must be given to except subdirective")
 | |
| 			}
 | |
| 		default:
 | |
| 			return nil, fmt.Errorf("invalid option %q", c.Val())
 | |
| 		}
 | |
| 	}
 | |
| 	return b, nil
 | |
| }
 | |
| 
 | |
| // listIP returns a list of IP addresses from a list of arguments which can be either IP-Address or Interface-Name.
 | |
| func listIP(args []string, ifaces []net.Interface) ([]string, error) {
 | |
| 	all := []string{}
 | |
| 	var isIface bool
 | |
| 	for _, a := range args {
 | |
| 		isIface = false
 | |
| 		for _, iface := range ifaces {
 | |
| 			if a == iface.Name {
 | |
| 				isIface = true
 | |
| 				addrs, err := iface.Addrs()
 | |
| 				if err != nil {
 | |
| 					return nil, fmt.Errorf("failed to get the IP addresses of the interface: %q", a)
 | |
| 				}
 | |
| 				for _, addr := range addrs {
 | |
| 					if ipnet, ok := addr.(*net.IPNet); ok {
 | |
| 						ipa, err := net.ResolveIPAddr("ip", ipnet.IP.String())
 | |
| 						if err == nil {
 | |
| 							if ipnet.IP.To4() == nil &&
 | |
| 								(ipnet.IP.IsLinkLocalMulticast() || ipnet.IP.IsLinkLocalUnicast()) {
 | |
| 								if ipa.Zone == "" {
 | |
| 									ipa.Zone = iface.Name
 | |
| 								}
 | |
| 							}
 | |
| 							all = append(all, ipa.String())
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if !isIface {
 | |
| 			if net.ParseIP(a) == nil {
 | |
| 				return nil, fmt.Errorf("not a valid IP address or interface name: %q", a)
 | |
| 			}
 | |
| 			all = append(all, a)
 | |
| 		}
 | |
| 	}
 | |
| 	return all, nil
 | |
| }
 |