|
|
@@ -35,33 +35,21 @@ func GetDefaultHost() (string, error) {
|
|
|
return "", rerr
|
|
|
}
|
|
|
|
|
|
- attrs, aerr := syscall.ParseNetlinkRouteAttr(rmsg)
|
|
|
- if aerr != nil {
|
|
|
- return "", aerr
|
|
|
- }
|
|
|
-
|
|
|
- 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)
|
|
|
- }
|
|
|
+ host, oif, err := parsePREFSRC(rmsg)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
}
|
|
|
-
|
|
|
- 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
|
|
|
+}
|