diff options
author | Anatole Denis <natolumin@unverle.fr> | 2019-09-17 11:18:47 +0200 |
---|---|---|
committer | Anatole Denis <natolumin@unverle.fr> | 2019-09-17 16:16:58 +0200 |
commit | c20a7603ebe7f3246901e85d22ccc6476bcfbc96 (patch) | |
tree | 32c3793c0a52525270920c43b7cd98998f0608a9 /dhcpv6/server6/server.go | |
parent | 834a63bade8aa8927af8b4c9842f0ad0345289d4 (diff) |
server6: Fix listening on multicast addresses
Joining a multicast group with an address that can't be received on a
socket is ineffective, at least on linux.
This updates the logic of NewServer in a mostly backwards-compatible
way, to enable listening on arbitrary multicast addresses:
* Unicast addresses see no user-visible change, but don't join a
multicast group for which they don't receive traffic anyway
* Multicast addresses start actually receiving traffic for the group
they represent, and don't join the default group. **this is a
behaviour change**: previously they would receive traffic for the
default group if it was on the same port and **not** for the group
they represent. I consider that previous behaviour a bug
* Wildcard addresses, if on the proper port, will join both
AllDHCPRelayAgentsAndServers and AllDHCPServers **this is a behaviour
change**: previously only AllDHCPRelayAgentsAndServers was joined
* Wildcard addresses on another port: no visible change, same as
unicast case
Signed-off-by: Anatole Denis <natolumin@unverle.fr>
Diffstat (limited to 'dhcpv6/server6/server.go')
-rw-r--r-- | dhcpv6/server6/server.go | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/dhcpv6/server6/server.go b/dhcpv6/server6/server.go index ab9cb32..4506195 100644 --- a/dhcpv6/server6/server.go +++ b/dhcpv6/server6/server.go @@ -126,31 +126,46 @@ func NewServer(ifname string, addr *net.UDPAddr, handler Handler, opt ...ServerO o(s) } - if s.conn == nil { - // no connection provided by the user, create a new one - conn, err := net.ListenUDP("udp6", addr) + if s.conn != nil { + return s, nil + } + + var err error + // no connection provided by the user, create a new one + s.conn, err = net.ListenUDP("udp6", addr) + if err != nil { + return nil, err + } + + var iface *net.Interface + if ifname == "" { + iface = nil + } else { + iface, err = net.InterfaceByName(ifname) if err != nil { return nil, err } - // join multicast group on the specified interface - var iface *net.Interface - if ifname == "" { - iface = nil - } else { - iface, err = net.InterfaceByName(ifname) - if err != nil { + } + + p := ipv6.NewPacketConn(s.conn) + if addr.IP.IsMulticast() { + if err := p.JoinGroup(iface, addr); err != nil { + return nil, err + } + } else if addr.IP.IsUnspecified() && addr.Port == dhcpv6.DefaultServerPort { + // For wildcard addresses on the correct port, listen on both multicast + // addresses defined in the RFC as a "default" behaviour + for _, g := range []net.IP{dhcpv6.AllDHCPRelayAgentsAndServers, dhcpv6.AllDHCPServers} { + group := net.UDPAddr{ + IP: g, + Port: dhcpv6.DefaultServerPort, + } + if err := p.JoinGroup(iface, &group); err != nil { return nil, err } + } - group := net.UDPAddr{ - IP: dhcpv6.AllDHCPRelayAgentsAndServers, - Port: dhcpv6.DefaultServerPort, - } - p := ipv6.NewPacketConn(conn) - if err := p.JoinGroup(iface, &group); err != nil { - return nil, err - } - s.conn = conn } + return s, nil } |