|
3 | 3 | package fingerprint
|
4 | 4 |
|
5 | 5 | import (
|
| 6 | + "errors" |
6 | 7 | "fmt"
|
7 | 8 | "io/ioutil"
|
8 | 9 | "log"
|
@@ -38,10 +39,14 @@ func (f *NetworkFingerprint) Fingerprint(cfg *config.Config, node *structs.Node)
|
38 | 39 | if "darwin" == runtime.GOOS {
|
39 | 40 | defaultDevice = "en0"
|
40 | 41 | }
|
| 42 | + // User-defined override for the default interface |
| 43 | + if cfg.NetworkInterface != "" { |
| 44 | + defaultDevice = cfg.NetworkInterface |
| 45 | + } |
41 | 46 |
|
42 | 47 | newNetwork.Device = defaultDevice
|
43 | 48 |
|
44 |
| - if ip := f.ifConfig(defaultDevice); ip != "" { |
| 49 | + if ip := f.ipAddress(defaultDevice); ip != "" { |
45 | 50 | node.Attributes["network.ip-address"] = ip
|
46 | 51 | newNetwork.IP = ip
|
47 | 52 | newNetwork.CIDR = newNetwork.IP + "/32"
|
@@ -129,6 +134,56 @@ func (f *NetworkFingerprint) linkSpeedEthtool(path, device string) int {
|
129 | 134 | return mbs
|
130 | 135 | }
|
131 | 136 |
|
| 137 | +// ipAddress returns the first IPv4 address on the configured default interface |
| 138 | +// Tries Golang native functions and falls back onto ifconfig |
| 139 | +func (f *NetworkFingerprint) ipAddress(device string) string { |
| 140 | + if ip, err := f.nativeIpAddress(device); err == nil { |
| 141 | + return ip |
| 142 | + } |
| 143 | + |
| 144 | + return f.ifConfig(device) |
| 145 | +} |
| 146 | + |
| 147 | +func (f *NetworkFingerprint) nativeIpAddress(device string) (string, error) { |
| 148 | + // Find IP address on configured interface |
| 149 | + var ip string |
| 150 | + ifaces, err := net.Interfaces() |
| 151 | + if err != nil { |
| 152 | + return "", errors.New("could not retrieve interface list") |
| 153 | + } |
| 154 | + |
| 155 | + // TODO: should we handle IPv6 here? How do we determine precedence? |
| 156 | + for _, i := range ifaces { |
| 157 | + if i.Name != device { |
| 158 | + continue |
| 159 | + } |
| 160 | + |
| 161 | + addrs, err := i.Addrs() |
| 162 | + if err != nil { |
| 163 | + return "", errors.New("could not retrieve interface IP addresses") |
| 164 | + } |
| 165 | + |
| 166 | + for _, a := range addrs { |
| 167 | + switch v := a.(type) { |
| 168 | + case *net.IPNet: |
| 169 | + if v.IP.To4() != nil { |
| 170 | + ip = v.IP.String() |
| 171 | + } |
| 172 | + case *net.IPAddr: |
| 173 | + if v.IP.To4() != nil { |
| 174 | + ip = v.IP.String() |
| 175 | + } |
| 176 | + } |
| 177 | + } |
| 178 | + } |
| 179 | + |
| 180 | + if net.ParseIP(ip) == nil { |
| 181 | + return "", errors.New(fmt.Sprintf("could not parse IP address `%s`", ip)) |
| 182 | + } |
| 183 | + |
| 184 | + return ip, nil |
| 185 | +} |
| 186 | + |
132 | 187 | // ifConfig returns the IP Address for this node according to ifConfig, for the
|
133 | 188 | // specified device.
|
134 | 189 | func (f *NetworkFingerprint) ifConfig(device string) string {
|
|
0 commit comments