Merge pull request #1802 from hashicorp/b-ping-leak

Updates memberlist to get goroutine leak fix for TCP pings.
This commit is contained in:
James Phillips 2016-03-07 10:44:14 -08:00
commit ea0aafce38
5 changed files with 67 additions and 37 deletions

2
Godeps/Godeps.json generated
View File

@ -100,7 +100,7 @@
}, },
{ {
"ImportPath": "github.com/hashicorp/memberlist", "ImportPath": "github.com/hashicorp/memberlist",
"Rev": "9888dc523910e5d22c5be4f6e34520943df21809" "Rev": "cef12ad58224d55cf26caa9e3d239c2fcb3432a2"
}, },
{ {
"ImportPath": "github.com/hashicorp/net-rpc-msgpackrpc", "ImportPath": "github.com/hashicorp/net-rpc-msgpackrpc",

View File

@ -280,7 +280,7 @@ func (m *Memberlist) setAlive() error {
if ip.To4() == nil { if ip.To4() == nil {
continue continue
} }
if !isPrivateIP(ip.String()) { if !IsPrivateIP(ip.String()) {
continue continue
} }
@ -305,7 +305,7 @@ func (m *Memberlist) setAlive() error {
// Check if this is a public address without encryption // Check if this is a public address without encryption
addrStr := net.IP(advertiseAddr).String() addrStr := net.IP(advertiseAddr).String()
if !isPrivateIP(addrStr) && !isLoopbackIP(addrStr) && !m.config.EncryptionEnabled() { if !IsPrivateIP(addrStr) && !isLoopbackIP(addrStr) && !m.config.EncryptionEnabled() {
m.logger.Printf("[WARN] memberlist: Binding to public address without encryption!") m.logger.Printf("[WARN] memberlist: Binding to public address without encryption!")
} }

View File

@ -282,7 +282,7 @@ func (m *Memberlist) probeNode(node *nodeState) {
// member who understands version 3 of the protocol, regardless of // member who understands version 3 of the protocol, regardless of
// which protocol version we are speaking. That's why we've included a // which protocol version we are speaking. That's why we've included a
// config option to turn this off if desired. // config option to turn this off if desired.
fallbackCh := make(chan bool) fallbackCh := make(chan bool, 1)
if (!m.config.DisableTcpPings) && (node.PMax >= 3) { if (!m.config.DisableTcpPings) && (node.PMax >= 3) {
destAddr := &net.TCPAddr{IP: node.Addr, Port: int(node.Port)} destAddr := &net.TCPAddr{IP: node.Addr, Port: int(node.Port)}
go func() { go func() {

View File

@ -1,28 +0,0 @@
#!/bin/bash
#
# This script makes sure that 127.0.0.x is routable. On Darwin, there
# is a bug that it isn't routable and this causes errors.
#
# Check if loopback is setup
ping -c 1 -W 10 127.0.0.2 > /dev/null 2>&1
if [ $? -eq 0 ]
then
exit
fi
# If we're not on OS X, then error
case $OSTYPE in
darwin*)
;;
*)
echo "Can't setup interfaces on non-Mac. Error!"
exit 1
;;
esac
# Setup loopback
for ((i=2;i<256;i++))
do
sudo ifconfig lo0 alias 127.0.0.$i up
done

View File

@ -24,8 +24,11 @@ const pushPullScaleThreshold = 32
/* /*
* Contains an entry for each private block: * Contains an entry for each private block:
* 10.0.0.0/8 * 10.0.0.0/8
* 100.64.0.0/10
* 127.0.0.0/8
* 169.254.0.0/16
* 172.16.0.0/12 * 172.16.0.0/12
* 192.168/16 * 192.168.0.0/16
*/ */
var privateBlocks []*net.IPNet var privateBlocks []*net.IPNet
@ -41,25 +44,44 @@ func init() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
// Add each private block // Add each private block
privateBlocks = make([]*net.IPNet, 3) privateBlocks = make([]*net.IPNet, 6)
_, block, err := net.ParseCIDR("10.0.0.0/8") _, block, err := net.ParseCIDR("10.0.0.0/8")
if err != nil { if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err)) panic(fmt.Sprintf("Bad cidr. Got %v", err))
} }
privateBlocks[0] = block privateBlocks[0] = block
_, block, err = net.ParseCIDR("172.16.0.0/12") _, block, err = net.ParseCIDR("100.64.0.0/10")
if err != nil { if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err)) panic(fmt.Sprintf("Bad cidr. Got %v", err))
} }
privateBlocks[1] = block privateBlocks[1] = block
_, block, err = net.ParseCIDR("192.168.0.0/16") _, block, err = net.ParseCIDR("127.0.0.0/8")
if err != nil { if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err)) panic(fmt.Sprintf("Bad cidr. Got %v", err))
} }
privateBlocks[2] = block privateBlocks[2] = block
_, block, err = net.ParseCIDR("169.254.0.0/16")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[3] = block
_, block, err = net.ParseCIDR("172.16.0.0/12")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[4] = block
_, block, err = net.ParseCIDR("192.168.0.0/16")
if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err))
}
privateBlocks[5] = block
_, block, err = net.ParseCIDR("127.0.0.0/8") _, block, err = net.ParseCIDR("127.0.0.0/8")
if err != nil { if err != nil {
panic(fmt.Sprintf("Bad cidr. Got %v", err)) panic(fmt.Sprintf("Bad cidr. Got %v", err))
@ -85,6 +107,42 @@ func encode(msgType messageType, in interface{}) (*bytes.Buffer, error) {
return buf, err return buf, err
} }
// GetPrivateIP returns the first private IP address found in a list of
// addresses.
func GetPrivateIP(addresses []net.Addr) (net.IP, error) {
var candidates []net.IP
// Find private IPv4 address
for _, rawAddr := range addresses {
var ip net.IP
switch addr := rawAddr.(type) {
case *net.IPAddr:
ip = addr.IP
case *net.IPNet:
ip = addr.IP
default:
continue
}
if ip.To4() == nil {
continue
}
if !IsPrivateIP(ip.String()) {
continue
}
candidates = append(candidates, ip)
}
numIps := len(candidates)
switch numIps {
case 0:
return nil, fmt.Errorf("No private IP address found")
case 1:
return candidates[0], nil
default:
return nil, fmt.Errorf("Multiple private IPs found. Please configure one.")
}
}
// Returns a random offset between 0 and n // Returns a random offset between 0 and n
func randomOffset(n int) int { func randomOffset(n int) int {
if n == 0 { if n == 0 {
@ -252,7 +310,7 @@ func decodeCompoundMessage(buf []byte) (trunc int, parts [][]byte, err error) {
} }
// Returns if the given IP is in a private block // Returns if the given IP is in a private block
func isPrivateIP(ip_str string) bool { func IsPrivateIP(ip_str string) bool {
ip := net.ParseIP(ip_str) ip := net.ParseIP(ip_str)
for _, priv := range privateBlocks { for _, priv := range privateBlocks {
if priv.Contains(ip) { if priv.Contains(ip) {