| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- package netutil
- import (
- "errors"
- "net"
- "net/netip"
- )
- // DefaultInterfacePortable looks up the current default interface using a portable lookup method that
- // works on most systems with a BSD style socket interface.
- //
- // Returns the interface name and IP address of the default route interface.
- //
- // If the default cannot be determined, an error is returned.
- // Requires that there is a route on the system servicing UDP IPv4.
- func DefaultInterfacePortable() (string, netip.Addr, error) {
- // Note: UDP dial just performs a connect(2), and doesn't actually send a packet.
- c, err := net.Dial("udp4", "8.8.8.8:53")
- if err != nil {
- return "", netip.Addr{}, err
- }
- laddr := c.LocalAddr().(*net.UDPAddr)
- c.Close()
- ifs, err := net.Interfaces()
- if err != nil {
- return "", netip.Addr{}, err
- }
- var (
- iface *net.Interface
- ipnet *net.IPNet
- )
- for _, ifc := range ifs {
- addrs, err := ifc.Addrs()
- if err != nil {
- return "", netip.Addr{}, err
- }
- for _, addr := range addrs {
- if ipn, ok := addr.(*net.IPNet); ok {
- if ipn.Contains(laddr.IP) {
- if ipnet == nil {
- ipnet = ipn
- iface = &ifc
- } else {
- newSize, _ := ipn.Mask.Size()
- oldSize, _ := ipnet.Mask.Size()
- if newSize > oldSize {
- ipnet = ipn
- iface = &ifc
- }
- }
- }
- }
- }
- }
- if iface == nil {
- return "", netip.Addr{}, errors.New("no default interface")
- }
- return iface.Name, laddr.AddrPort().Addr(), nil
- }
|