summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6/server6/server.go
diff options
context:
space:
mode:
authorAnatole Denis <natolumin@unverle.fr>2019-09-17 11:18:47 +0200
committerAnatole Denis <natolumin@unverle.fr>2019-09-17 16:16:58 +0200
commitc20a7603ebe7f3246901e85d22ccc6476bcfbc96 (patch)
tree32c3793c0a52525270920c43b7cd98998f0608a9 /dhcpv6/server6/server.go
parent834a63bade8aa8927af8b4c9842f0ad0345289d4 (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.go53
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
}