From 107a8f0425e4ef5078fe83d1cf6418c62f8028ad Mon Sep 17 00:00:00 2001 From: Matt Layher Date: Sat, 9 May 2020 16:50:44 -0400 Subject: [PATCH] internal/radvd: switch to github.com/mdlayher/ndp types (#43) Signed-off-by: Matt Layher --- go.mod | 5 +- go.sum | 8 +++ integration/radvd/radvd_test.go | 2 +- internal/radvd/radvd.go | 89 ++++++++++++++++----------------- 4 files changed, 54 insertions(+), 50 deletions(-) diff --git a/go.mod b/go.mod index c8c4c51..d878547 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/insomniacslk/dhcp v0.0.0-20200420235442-ed3125c2efe7 github.com/jpillora/backoff v1.0.0 github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771 + github.com/mdlayher/ndp v0.0.0-20200509194142-8a50b5ef8b52 github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 github.com/miekg/dns v1.1.29 github.com/prometheus/client_golang v1.6.0 @@ -35,8 +36,8 @@ require ( github.com/vishvananda/netlink v1.1.0 golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 golang.org/x/net v0.0.0-20200506145744-7e3656a0809f - golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e - golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 + golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a + golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 golang.zx2c4.com/wireguard v0.0.20200320 // indirect golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200324154536-ceff61240acf diff --git a/go.sum b/go.sum index 8e69fba..f37002f 100644 --- a/go.sum +++ b/go.sum @@ -142,6 +142,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0= github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= +github.com/mdlayher/ndp v0.0.0-20200509194142-8a50b5ef8b52 h1:qWqNvHaKhGECNieU1gGusKRuoPeoR+rhlkaWdO1gyT8= +github.com/mdlayher/ndp v0.0.0-20200509194142-8a50b5ef8b52/go.mod h1:AXE3T2f7eg/MV02LS+DGHgH0c+ehknWViE4pgbHtZf8= github.com/mdlayher/netlink v0.0.0-20180912140650-18e318c2e5d1/go.mod h1:a3TlQHkJH2m32RF224Z7LhD5N4mpyR8eUbCoYHywrwg= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= @@ -265,6 +267,8 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f h1:Wku8eEdeJqIOFHtrfkYUByc4bCaTeA6fL0UJgfEiFMI= +gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:Tiuhl+njh/JIg0uS/sOJVYi0x2HEa5rc1OAaVsb5tAs= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -337,6 +341,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170809190605-e42485b6e20a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -385,6 +391,8 @@ golang.org/x/sys v0.0.0-20200428200454-593003d681fa h1:yMbJOvnfYkO1dSAviTu/ZguZW golang.org/x/sys v0.0.0-20200428200454-593003d681fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= diff --git a/integration/radvd/radvd_test.go b/integration/radvd/radvd_test.go index f0aa928..bf23f5d 100644 --- a/integration/radvd/radvd_test.go +++ b/integration/radvd/radvd_test.go @@ -98,7 +98,7 @@ func TestRouterAdvertisement(t *testing.T) { want := `Soliciting ff02::2 (ff02::2) on veth2b... Hop limit : 64 ( 0x40) -Stateful address conf. : Yes +Stateful address conf. : No Stateful other conf. : No Mobile home agent : No Router preference : medium diff --git a/internal/radvd/radvd.go b/internal/radvd/radvd.go index 3d641b9..07966cb 100644 --- a/internal/radvd/radvd.go +++ b/internal/radvd/radvd.go @@ -22,10 +22,9 @@ import ( "sync" "time" - "github.com/google/gopacket" "github.com/google/gopacket/layers" + "github.com/mdlayher/ndp" - "golang.org/x/net/icmp" "golang.org/x/net/ipv6" ) @@ -197,38 +196,14 @@ func (s *Server) sendAdvertisement(addr net.Addr) error { return nil // nothing to do } if addr == nil { - addr = &net.IPAddr{net.IPv6linklocalallnodes, s.iface.Name} - } - // TODO: cache the packet - msgbody := []byte{ - 0x40, // hop limit: 64 - 0x80, // flags: managed address configuration - 0x07, 0x08, // router lifetime (s): 1800 - 0x00, 0x00, 0x00, 0x00, // reachable time (ms): 0 - 0x00, 0x00, 0x00, 0x00, // retrans time (ms): 0 - } - - options := layers.ICMPv6Options{ - (sourceLinkLayerAddress{address: s.iface.HardwareAddr}).Marshal(), - (mtu{mtu: uint32(s.iface.MTU)}).Marshal(), - } - for _, prefix := range s.prefixes { - ones, _ := prefix.Mask.Size() - // Use the first /64 subnet within larger prefixes - if ones < 64 { - ones = 64 + addr = &net.IPAddr{ + IP: net.IPv6linklocalallnodes, + Zone: s.iface.Name, } - - var net [16]byte - copy(net[:], prefix.IP) - options = append(options, (prefixInfo{ - prefixLength: byte(ones), - flags: 0xc0, // TODO - validLifetime: 7200, // seconds - preferredLifetime: 1800, // seconds - prefix: net, - }).Marshal()) } + + var options []ndp.Option + if len(s.prefixes) > 0 { addrs, err := s.iface.Addrs() if err != nil { @@ -246,25 +221,45 @@ func (s *Server) sendAdvertisement(addr net.Addr) error { } } if !linkLocal.Equal(net.IPv6zero) { - options = append(options, (rdnss{ - lifetime: 1800, // seconds - server: linkLocal, - }).Marshal()) + options = append(options, &ndp.RecursiveDNSServer{ + Lifetime: 30 * time.Minute, + Servers: []net.IP{linkLocal}, + }) } } - buf := gopacket.NewSerializeBuffer() - if err := options.SerializeTo(buf, gopacket.SerializeOptions{FixLengths: true}); err != nil { - return err - } - msgbody = append(msgbody, buf.Bytes()...) + for _, prefix := range s.prefixes { + ones, _ := prefix.Mask.Size() + // Use the first /64 subnet within larger prefixes + if ones < 64 { + ones = 64 + } - msg := &icmp.Message{ - Type: ipv6.ICMPTypeRouterAdvertisement, - Code: 0, - Checksum: 0, // calculated by the kernel - Body: &icmp.DefaultMessageBody{msgbody}} - mb, err := msg.Marshal(nil) + options = append(options, &ndp.PrefixInformation{ + PrefixLength: uint8(ones), + OnLink: true, + AutonomousAddressConfiguration: true, + ValidLifetime: 2 * time.Hour, + PreferredLifetime: 30 * time.Minute, + Prefix: prefix.IP, + }) + } + + options = append(options, + ndp.NewMTU(uint32(s.iface.MTU)), + &ndp.LinkLayerAddress{ + Direction: ndp.Source, + Addr: s.iface.HardwareAddr, + }, + ) + + ra := &ndp.RouterAdvertisement{ + CurrentHopLimit: 64, + RouterLifetime: 30 * time.Minute, + Options: options, + } + + mb, err := ndp.MarshalMessage(ra) if err != nil { return err }