diff --git a/vendor.conf b/vendor.conf index c9abe95a13..ab599fb2df 100644 --- a/vendor.conf +++ b/vendor.conf @@ -54,7 +54,7 @@ github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e github.com/docker/libkv 458977154600b9f23984d9f4b82e79570b5ae12b github.com/vishvananda/netns 0a2b9b5464df8343199164a0321edf3313202f7e github.com/vishvananda/netlink f049be6f391489d3f374498fe0c8df8449258372 # v1.1.0 -github.com/moby/ipvs 8f137da6850a975020f4f739c589d293dd3a9d7b # v1.0.0 +github.com/moby/ipvs 4566ccea0e08d68e9614c3e7a64a23b850c4bb35 # v1.0.1 # When updating, consider updating TOMLV_COMMIT in hack/dockerfile/install/tomlv.installer accordingly github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 # v0.3.1 diff --git a/vendor/github.com/moby/ipvs/netlink.go b/vendor/github.com/moby/ipvs/netlink.go index 1a822da4b6..ac48d05a31 100644 --- a/vendor/github.com/moby/ipvs/netlink.go +++ b/vendor/github.com/moby/ipvs/netlink.go @@ -5,6 +5,7 @@ package ipvs import ( "bytes" "encoding/binary" + "errors" "fmt" "net" "os/exec" @@ -449,7 +450,7 @@ func assembleDestination(attrs []syscall.NetlinkRouteAttr) (*Destination, error) d.ActiveConnections = int(native.Uint16(attr.Value)) case ipvsDestAttrInactiveConnections: d.InactiveConnections = int(native.Uint16(attr.Value)) - case ipvsSvcAttrStats: + case ipvsDestAttrStats: stats, err := assembleStats(attr.Value) if err != nil { return nil, err @@ -458,6 +459,19 @@ func assembleDestination(attrs []syscall.NetlinkRouteAttr) (*Destination, error) } } + // in older kernels (< 3.18), the destination address family attribute doesn't exist so we must + // assume it based on the destination address provided. + if d.AddressFamily == 0 { + // we can't check the address family using net stdlib because netlink returns + // IPv4 addresses as the first 4 bytes in a []byte of length 16 where as + // stdlib expects it as the last 4 bytes. + addressFamily, err := getIPFamily(addressBytes) + if err != nil { + return nil, err + } + d.AddressFamily = addressFamily + } + // parse Address after parse AddressFamily incase of parseIP error if addressBytes != nil { ip, err := parseIP(addressBytes, d.AddressFamily) @@ -470,6 +484,37 @@ func assembleDestination(attrs []syscall.NetlinkRouteAttr) (*Destination, error) return &d, nil } +// getIPFamily parses the IP family based on raw data from netlink. +// For AF_INET, netlink will set the first 4 bytes with trailing zeros +// 10.0.0.1 -> [10 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0] +// For AF_INET6, the full 16 byte array is used: +// 2001:db8:3c4d:15::1a00 -> [32 1 13 184 60 77 0 21 0 0 0 0 0 0 26 0] +func getIPFamily(address []byte) (uint16, error) { + if len(address) == 4 { + return syscall.AF_INET, nil + } + + if isZeros(address) { + return 0, errors.New("could not parse IP family from address data") + } + + // assume IPv4 if first 4 bytes are non-zero but rest of the data is trailing zeros + if !isZeros(address[:4]) && isZeros(address[4:]) { + return syscall.AF_INET, nil + } + + return syscall.AF_INET6, nil +} + +func isZeros(b []byte) bool { + for i := 0; i < len(b); i++ { + if b[i] != 0 { + return false + } + } + return true +} + // parseDestination given a ipvs netlink response this function will respond with a valid destination entry, an error otherwise func (i *Handle) parseDestination(msg []byte) (*Destination, error) { var dst *Destination