pkg/netutil: get default interface for tc commands
Fix https://github.com/coreos/etcd/issues/6841.
This commit is contained in:
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user