Skip to content

Commit

Permalink
Merge pull request #733 from badrabubker/mdns
Browse files Browse the repository at this point in the history
Enhance mDNS Functionality
  • Loading branch information
DanStough authored Jul 8, 2024
2 parents fca5ddd + 9ef33a9 commit af974b8
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 25 deletions.
34 changes: 31 additions & 3 deletions cmd/serf/command/agent/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ func (c *Command) readConfig() *Config {
"tag pair, specified as key=value")
cmdFlags.StringVar(&cmdConfig.Discover, "discover", "", "mDNS discovery name")
cmdFlags.StringVar(&cmdConfig.Interface, "iface", "", "interface to bind to")
cmdFlags.StringVar(&cmdConfig.MDNS.Interface, "mdns-iface", "", "interface to use for mDNS")
cmdFlags.BoolVar(&cmdConfig.MDNS.DisableIPv4, "mdns-disable-ipv4", false, "disable IPv4 for mDNS")
cmdFlags.BoolVar(&cmdConfig.MDNS.DisableIPv6, "mdns-disable-ipv6", false, "disable IPv6 for mDNS")
cmdFlags.StringVar(&cmdConfig.TagsFile, "tags-file", "", "tag persistence file")
cmdFlags.BoolVar(&cmdConfig.EnableSyslog, "syslog", false,
"enable logging to syslog facility")
Expand Down Expand Up @@ -176,6 +179,24 @@ func (c *Command) readConfig() *Config {
return nil
}

if config.MDNS.Interface != "" {
if config.Discover == "" {
c.Ui.Error("mDNS interface specified without enabling mDNS discovery")
return nil
}

if _, err := net.InterfaceByName(config.MDNS.Interface); err != nil {
c.Ui.Error(fmt.Sprintf("Invalid mDNS network interface: %s", err))
return nil
}

// Check for a valid mdns ip mode
if config.MDNS.DisableIPv4 && config.MDNS.DisableIPv6 {
c.Ui.Error("Invalid mDNS configuration: both IPv4 and IPv6 are disabled")
return nil
}
}

// Backward compatibility hack for 'Role'
if config.Role != "" {
c.Ui.Output("Deprecation warning: 'Role' has been replaced with 'Tags'")
Expand Down Expand Up @@ -432,10 +453,12 @@ func (c *Command) startAgent(config *Config, agent *Agent,
local := agent.Serf().Memberlist().LocalNode()

// Get the bind interface if any
iface, _ := config.NetworkInterface()
iface, _ := config.MDNSNetworkInterface()

c.logger.Printf("[INFO] agent: Starting mDNS listener on interface %s", iface.Name)

_, err := NewAgentMDNS(agent, logOutput, config.ReplayOnJoin,
config.NodeName, config.Discover, iface, local.Addr, int(local.Port))
config.NodeName, config.Discover, iface, local.Addr, int(local.Port), config.MDNS)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error starting mDNS listener: %s", err))
return nil
Expand Down Expand Up @@ -734,7 +757,12 @@ Options:
-bind if the interface is known but not the address.
If both are provided, then Serf verifies that the
interface has the bind address that is provided. This
flag also sets the multicast device used for -discover.
flag also sets the multicast device used for -discover,
if mdns-iface is not specified.
-mdns-iface Network interface to use for mDNS. If not provided, the
-iface value is used.
-mdns-disable-ipv4 Disable IPv4 for mDNS.
-mdns-disable-ipv6 Disable IPv6 for mDNS.
-advertise=0.0.0.0 Address to advertise to the other cluster members
-config-file=foo Path to a JSON file to read configuration from.
This can be specified multiple times.
Expand Down
35 changes: 34 additions & 1 deletion cmd/serf/command/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ func DefaultConfig() *Config {

type dirEnts []os.FileInfo

type MDNSConfig struct {
// Interface is used to provide a binding interface to use for mDNS.
// if not set, iface will be used.
Interface string `mapstructure:"interface"`
DisableIPv4 bool `mapstructure:"disable_ipv4"`
DisableIPv6 bool `mapstructure:"disable_ipv6"`
}

// Config is the configuration that can be set for an Agent. Some of these
// configurations are exposed as command-line flags to `serf agent`, whereas
// many of the more advanced configurations can only be set by creating
Expand Down Expand Up @@ -154,10 +162,12 @@ type Config struct {
// allows Serf agents to join each other with zero configuration.
Discover string `mapstructure:"discover"`

MDNS MDNSConfig `mapstructure:"mdns"`

// Interface is used to provide a binding interface to use. It can be
// used instead of providing a bind address, as Serf will discover the
// address of the provided interface. It is also used to set the multicast
// device used with `-discover`.
// device used with `-discover`, if `mdns-iface` is not set
Interface string `mapstructure:"interface"`

// ReconnectIntervalRaw is the string reconnect interval time. This interval
Expand Down Expand Up @@ -292,6 +302,16 @@ func (c *Config) NetworkInterface() (*net.Interface, error) {
return net.InterfaceByName(c.Interface)
}

func (c *Config) MDNSNetworkInterface() (*net.Interface, error) {
if c.MDNS.Interface == "" && c.Interface == "" {
return nil, nil
} else if c.MDNS.Interface != "" {
return net.InterfaceByName(c.MDNS.Interface)
} else {
return net.InterfaceByName(c.Interface)
}
}

// DecodeConfig reads the configuration from the given reader in JSON
// format and decodes it into a proper Config structure.
func DecodeConfig(r io.Reader) (*Config, error) {
Expand Down Expand Up @@ -436,6 +456,19 @@ func MergeConfig(a, b *Config) *Config {
if b.Interface != "" {
result.Interface = b.Interface
}

if b.MDNS.Interface != "" {
result.MDNS.Interface = b.MDNS.Interface
}

if b.MDNS.DisableIPv4 == true {
result.MDNS.DisableIPv4 = true
}

if b.MDNS.DisableIPv6 == true {
result.MDNS.DisableIPv6 = true
}

if b.ReconnectInterval != 0 {
result.ReconnectInterval = b.ReconnectInterval
}
Expand Down
43 changes: 25 additions & 18 deletions cmd/serf/command/agent/mdns.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@ const (
// AgentMDNS is used to advertise ourself using mDNS and to
// attempt to join peers periodically using mDNS queries.
type AgentMDNS struct {
agent *Agent
discover string
logger *log.Logger
seen map[string]struct{}
server *mdns.Server
replay bool
iface *net.Interface
agent *Agent
discover string
logger *log.Logger
seen map[string]struct{}
server *mdns.Server
replay bool
iface *net.Interface
ipModes []string
disableIPv4 bool
disableIPv6 bool
}

// NewAgentMDNS is used to create a new AgentMDNS
func NewAgentMDNS(agent *Agent, logOutput io.Writer, replay bool,
node, discover string, iface *net.Interface, bind net.IP, port int) (*AgentMDNS, error) {
node, discover string, iface *net.Interface, bind net.IP, port int, MDNSConfig MDNSConfig) (*AgentMDNS, error) {
// Create the service
service, err := mdns.NewMDNSService(
node,
Expand Down Expand Up @@ -60,13 +63,15 @@ func NewAgentMDNS(agent *Agent, logOutput io.Writer, replay bool,

// Initialize the AgentMDNS
m := &AgentMDNS{
agent: agent,
discover: discover,
logger: log.New(logOutput, "", log.LstdFlags),
seen: make(map[string]struct{}),
server: server,
replay: replay,
iface: iface,
agent: agent,
discover: discover,
logger: log.New(logOutput, "", log.LstdFlags),
seen: make(map[string]struct{}),
server: server,
replay: replay,
iface: iface,
disableIPv4: MDNSConfig.DisableIPv4,
disableIPv6: MDNSConfig.DisableIPv6,
}

// Start the background workers
Expand Down Expand Up @@ -123,9 +128,11 @@ func (m *AgentMDNS) run() {
// poll is invoked periodically to check for new hosts
func (m *AgentMDNS) poll(hosts chan *mdns.ServiceEntry) {
params := mdns.QueryParam{
Service: mdnsName(m.discover),
Interface: m.iface,
Entries: hosts,
Service: mdnsName(m.discover),
Interface: m.iface,
Entries: hosts,
DisableIPv4: m.disableIPv4,
DisableIPv6: m.disableIPv6,
}
if err := mdns.Query(&params); err != nil {
m.logger.Printf("[ERR] agent.mdns: Failed to poll for new hosts: %v", err)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/hashicorp/go-msgpack/v2 v2.1.2
github.com/hashicorp/go-syslog v1.0.0
github.com/hashicorp/logutils v1.0.0
github.com/hashicorp/mdns v1.0.4
github.com/hashicorp/mdns v1.0.5
github.com/hashicorp/memberlist v0.5.1
github.com/mitchellh/cli v1.1.5
github.com/mitchellh/mapstructure v1.5.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/mdns v1.0.5 h1:1M5hW1cunYeoXOqHwEb/GBDDHAFo0Yqb/uz/beC6LbE=
github.com/hashicorp/mdns v1.0.5/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.5.1 h1:mk5dRuzeDNis2bi6LLoQIXfMH7JQvAzt3mQD0vNZZUo=
github.com/hashicorp/memberlist v0.5.1/go.mod h1:zGDXV6AqbDTKTM6yxW0I4+JtFzZAJVoIPvss4hV8F24=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
Expand Down

0 comments on commit af974b8

Please sign in to comment.