pkg/netutil: get default interface for tc commands

Fix https://github.com/coreos/etcd/issues/6841.
This commit is contained in:
Gyu-Ho Lee
2016-11-17 00:05:40 -08:00
parent 68b04b7067
commit 097cdbd0e4
4 changed files with 108 additions and 22 deletions

View File

@ -35,33 +35,21 @@ func GetDefaultHost() (string, error) {
return "", rerr
}
attrs, aerr := syscall.ParseNetlinkRouteAttr(rmsg)
if aerr != nil {
return "", aerr
host, oif, err := parsePREFSRC(rmsg)
if err != nil {
return "", err
}
oif := uint32(0)
for _, attr := range attrs {
if attr.Attr.Type == syscall.RTA_PREFSRC {
return net.IP(attr.Value).String(), nil
}
if attr.Attr.Type == syscall.RTA_OIF {
oif = binary.LittleEndian.Uint32(attr.Value)
}
}
if oif == 0 {
return "", errNoDefaultRoute
if host != "" {
return host, nil
}
// prefsrc not detected, fall back to getting address from iface
ifmsg, ierr := getIface(oif)
if ierr != nil {
return "", ierr
}
attrs, aerr = syscall.ParseNetlinkRouteAttr(ifmsg)
attrs, aerr := syscall.ParseNetlinkRouteAttr(ifmsg)
if aerr != nil {
return "", aerr
}
@ -131,3 +119,60 @@ func getIface(idx uint32) (*syscall.NetlinkMessage, error) {
return nil, errNoDefaultRoute
}
var errNoDefaultInterface = fmt.Errorf("could not find default interface")
func GetDefaultInterface() (string, error) {
rmsg, rerr := getDefaultRoute()
if rerr != nil {
return "", rerr
}
_, oif, err := parsePREFSRC(rmsg)
if err != nil {
return "", err
}
ifmsg, ierr := getIface(oif)
if ierr != nil {
return "", ierr
}
attrs, aerr := syscall.ParseNetlinkRouteAttr(ifmsg)
if aerr != nil {
return "", aerr
}
for _, attr := range attrs {
if attr.Attr.Type == syscall.IFLA_IFNAME {
return string(attr.Value[:len(attr.Value)-1]), nil
}
}
return "", errNoDefaultInterface
}
// parsePREFSRC returns preferred source address and output interface index (RTA_OIF).
func parsePREFSRC(m *syscall.NetlinkMessage) (host string, oif uint32, err error) {
var attrs []syscall.NetlinkRouteAttr
attrs, err = syscall.ParseNetlinkRouteAttr(m)
if err != nil {
return "", 0, err
}
for _, attr := range attrs {
if attr.Attr.Type == syscall.RTA_PREFSRC {
host = net.IP(attr.Value).String()
}
if attr.Attr.Type == syscall.RTA_OIF {
oif = binary.LittleEndian.Uint32(attr.Value)
}
if host != "" && oif != uint32(0) {
break
}
}
if oif == 0 {
err = errNoDefaultRoute
}
return
}