From 8e95e254428c7a47b9259a08170ca80f5db12c4c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 26 Jun 2018 09:04:05 +0200 Subject: [PATCH] radvd: announce link-local ipv6 address for DNS --- integration/radvd/radvd_test.go | 2 +- internal/radvd/radvd.go | 41 ++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/integration/radvd/radvd_test.go b/integration/radvd/radvd_test.go index 2bce53e..9f6fd2b 100644 --- a/integration/radvd/radvd_test.go +++ b/integration/radvd/radvd_test.go @@ -89,7 +89,7 @@ Neighbor discovery proxy : No Router lifetime : 1800 (0x00000708) seconds Reachable time : unspecified (0x00000000) Retransmit time : unspecified (0x00000000) - Recursive DNS server : 2a02:168:4a00::1 + Recursive DNS server : fe80::73:53ff:fe00:cafe DNS server lifetime : 1800 (0x00000708) seconds Prefix : 2a02:168:4a00::/64 On-link : Yes diff --git a/internal/radvd/radvd.go b/internal/radvd/radvd.go index 1a682c9..2372104 100644 --- a/internal/radvd/radvd.go +++ b/internal/radvd/radvd.go @@ -143,7 +143,7 @@ func (o prefixInfo) Marshal() layers.ICMPv6Option { type rdnss struct { lifetime uint32 // seconds - server [16]byte + server []byte } func (o rdnss) Marshal() layers.ICMPv6Option { @@ -157,6 +157,14 @@ func (o rdnss) Marshal() layers.ICMPv6Option { } } +var ipv6LinkLocal = func(cidr string) *net.IPNet { + _, net, err := net.ParseCIDR(cidr) + if err != nil { + panic(err) + } + return net +}("fe80::/10") + func (s *Server) sendAdvertisement(addr net.Addr) error { if s.prefixes == nil { return nil // nothing to do @@ -196,16 +204,27 @@ func (s *Server) sendAdvertisement(addr net.Addr) error { }).Marshal()) } if len(s.prefixes) > 0 { - prefix := s.prefixes[0] - var server [16]byte - copy(server[:], prefix.IP) - // pick the first address of the prefix, e.g. address 2a02:168:4a00::1 - // for prefix 2a02:168:4a00::/48 - server[len(server)-1] = 1 - options = append(options, (rdnss{ - lifetime: 1800, // seconds - server: server, - }).Marshal()) + addrs, err := s.iface.Addrs() + if err != nil { + return err + } + var linkLocal net.IP + for _, addr := range addrs { + ipnet, ok := addr.(*net.IPNet) + if !ok { + continue + } + if ipv6LinkLocal.Contains(ipnet.IP) { + linkLocal = ipnet.IP + break + } + } + if !linkLocal.Equal(net.IPv6zero) { + options = append(options, (rdnss{ + lifetime: 1800, // seconds + server: linkLocal, + }).Marshal()) + } } s.mu.Unlock()