interface_android.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. package anet
  2. import (
  3. "bytes"
  4. "errors"
  5. "net"
  6. "os"
  7. "sync"
  8. "syscall"
  9. "time"
  10. "unsafe"
  11. )
  12. const (
  13. android11ApiLevel = 30
  14. )
  15. var (
  16. customAndroidApiLevel = -1
  17. errInvalidInterface = errors.New("invalid network interface")
  18. errInvalidInterfaceIndex = errors.New("invalid network interface index")
  19. errInvalidInterfaceName = errors.New("invalid network interface name")
  20. errNoSuchInterface = errors.New("no such network interface")
  21. errNoSuchMulticastInterface = errors.New("no such multicast network interface")
  22. )
  23. type ifReq [40]byte
  24. // Interfaces returns a list of the system's network interfaces.
  25. func Interfaces() ([]net.Interface, error) {
  26. if androidApiLevel() < android11ApiLevel {
  27. return net.Interfaces()
  28. }
  29. ift, err := interfaceTable(0)
  30. if err != nil {
  31. return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
  32. }
  33. if len(ift) != 0 {
  34. zoneCache.update(ift, true)
  35. zoneCacheX.update(ift, true)
  36. }
  37. return ift, nil
  38. }
  39. // InterfaceAddrs returns a list of the system's unicast interface
  40. // addresses.
  41. //
  42. // The returned list does not identify the associated interface; use
  43. // Interfaces and Interface.Addrs for more detail.
  44. func InterfaceAddrs() ([]net.Addr, error) {
  45. if androidApiLevel() < android11ApiLevel {
  46. return net.InterfaceAddrs()
  47. }
  48. ifat, err := interfaceAddrTable(nil)
  49. if err != nil {
  50. err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
  51. }
  52. return ifat, err
  53. }
  54. // InterfaceByIndex returns the interface specified by index.
  55. //
  56. // On Solaris, it returns one of the logical network interfaces
  57. // sharing the logical data link; for more precision use
  58. // InterfaceByName.
  59. func InterfaceByIndex(index int) (*net.Interface, error) {
  60. if androidApiLevel() < android11ApiLevel {
  61. return net.InterfaceByIndex(index)
  62. }
  63. if index <= 0 {
  64. return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex}
  65. }
  66. ift, err := interfaceTable(index)
  67. if err != nil {
  68. return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
  69. }
  70. ifi, err := interfaceByIndex(ift, index)
  71. if err != nil {
  72. err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
  73. }
  74. return ifi, err
  75. }
  76. // InterfaceByName returns the interface specified by name.
  77. func InterfaceByName(name string) (*net.Interface, error) {
  78. if name == "" {
  79. return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceName}
  80. }
  81. ift, err := interfaceTable(0)
  82. if err != nil {
  83. return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
  84. }
  85. if len(ift) != 0 {
  86. zoneCache.update(ift, true)
  87. zoneCacheX.update(ift, true)
  88. }
  89. for _, ifi := range ift {
  90. if name == ifi.Name {
  91. return &ifi, nil
  92. }
  93. }
  94. return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errNoSuchInterface}
  95. }
  96. // InterfaceAddrsByInterface returns a list of the system's unicast
  97. // interface addresses by specific interface.
  98. func InterfaceAddrsByInterface(ifi *net.Interface) ([]net.Addr, error) {
  99. if ifi == nil {
  100. return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
  101. }
  102. if androidApiLevel() < android11ApiLevel {
  103. return ifi.Addrs()
  104. }
  105. ifat, err := interfaceAddrTable(ifi)
  106. if err != nil {
  107. err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
  108. }
  109. return ifat, err
  110. }
  111. // SetAndroidVersion set the Android environment in which the program runs.
  112. // The Android system version number can be obtained through
  113. // `android.os.Build.VERSION.RELEASE` of the Android framework.
  114. // If version is 0 the actual version will be detected automatically if possible.
  115. func SetAndroidVersion(version uint) {
  116. switch {
  117. case version == 0:
  118. customAndroidApiLevel = -1
  119. case version >= 11:
  120. customAndroidApiLevel = android11ApiLevel
  121. default:
  122. customAndroidApiLevel = 0
  123. }
  124. }
  125. func androidApiLevel() int {
  126. if customAndroidApiLevel != -1 {
  127. // user-provided api level should be used
  128. return customAndroidApiLevel
  129. }
  130. // try to autodetect api level
  131. return androidDeviceApiLevel()
  132. }
  133. // An ipv6ZoneCache represents a cache holding partial network
  134. // interface information. It is used for reducing the cost of IPv6
  135. // addressing scope zone resolution.
  136. //
  137. // Multiple names sharing the index are managed by first-come
  138. // first-served basis for consistency.
  139. type ipv6ZoneCache struct {
  140. sync.RWMutex // guard the following
  141. lastFetched time.Time // last time routing information was fetched
  142. toIndex map[string]int // interface name to its index
  143. toName map[int]string // interface index to its name
  144. }
  145. //go:linkname zoneCache net.zoneCache
  146. var zoneCache ipv6ZoneCache
  147. //go:linkname zoneCacheX golang.org/x/net/internal/socket.zoneCache
  148. var zoneCacheX ipv6ZoneCache
  149. // update refreshes the network interface information if the cache was last
  150. // updated more than 1 minute ago, or if force is set. It reports whether the
  151. // cache was updated.
  152. func (zc *ipv6ZoneCache) update(ift []net.Interface, force bool) (updated bool) {
  153. zc.Lock()
  154. defer zc.Unlock()
  155. now := time.Now()
  156. if !force && zc.lastFetched.After(now.Add(-60*time.Second)) {
  157. return false
  158. }
  159. zc.lastFetched = now
  160. if len(ift) == 0 {
  161. var err error
  162. if ift, err = interfaceTable(0); err != nil {
  163. return false
  164. }
  165. }
  166. zc.toIndex = make(map[string]int, len(ift))
  167. zc.toName = make(map[int]string, len(ift))
  168. for _, ifi := range ift {
  169. zc.toIndex[ifi.Name] = ifi.Index
  170. if _, ok := zc.toName[ifi.Index]; !ok {
  171. zc.toName[ifi.Index] = ifi.Name
  172. }
  173. }
  174. return true
  175. }
  176. // If the ifindex is zero, interfaceTable returns mappings of all
  177. // network interfaces. Otherwise it returns a mapping of a specific
  178. // interface.
  179. func interfaceTable(ifindex int) ([]net.Interface, error) {
  180. tab, err := NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
  181. if err != nil {
  182. return nil, os.NewSyscallError("netlinkrib", err)
  183. }
  184. msgs, err := syscall.ParseNetlinkMessage(tab)
  185. if err != nil {
  186. return nil, os.NewSyscallError("parsenetlinkmessage", err)
  187. }
  188. var ift []net.Interface
  189. im := make(map[uint32]struct{})
  190. loop:
  191. for _, m := range msgs {
  192. switch m.Header.Type {
  193. case syscall.NLMSG_DONE:
  194. break loop
  195. case syscall.RTM_NEWADDR:
  196. ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
  197. if _, ok := im[ifam.Index]; ok {
  198. continue
  199. } else {
  200. im[ifam.Index] = struct{}{}
  201. }
  202. if ifindex == 0 || ifindex == int(ifam.Index) {
  203. ifi := newLink(ifam)
  204. if ifi != nil {
  205. ift = append(ift, *ifi)
  206. }
  207. if ifindex == int(ifam.Index) {
  208. break loop
  209. }
  210. }
  211. }
  212. }
  213. return ift, nil
  214. }
  215. func newLink(ifam *syscall.IfAddrmsg) *net.Interface {
  216. ift := &net.Interface{Index: int(ifam.Index)}
  217. name, err := indexToName(ifam.Index)
  218. if err != nil {
  219. return nil
  220. }
  221. ift.Name = name
  222. mtu, err := nameToMTU(name)
  223. if err != nil {
  224. return nil
  225. }
  226. ift.MTU = mtu
  227. flags, err := nameToFlags(name)
  228. if err != nil {
  229. return nil
  230. }
  231. ift.Flags = flags
  232. return ift
  233. }
  234. func linkFlags(rawFlags uint32) net.Flags {
  235. var f net.Flags
  236. if rawFlags&syscall.IFF_UP != 0 {
  237. f |= net.FlagUp
  238. }
  239. if rawFlags&syscall.IFF_RUNNING != 0 {
  240. f |= net.FlagRunning
  241. }
  242. if rawFlags&syscall.IFF_BROADCAST != 0 {
  243. f |= net.FlagBroadcast
  244. }
  245. if rawFlags&syscall.IFF_LOOPBACK != 0 {
  246. f |= net.FlagLoopback
  247. }
  248. if rawFlags&syscall.IFF_POINTOPOINT != 0 {
  249. f |= net.FlagPointToPoint
  250. }
  251. if rawFlags&syscall.IFF_MULTICAST != 0 {
  252. f |= net.FlagMulticast
  253. }
  254. return f
  255. }
  256. // If the ifi is nil, interfaceAddrTable returns addresses for all
  257. // network interfaces. Otherwise it returns addresses for a specific
  258. // interface.
  259. func interfaceAddrTable(ifi *net.Interface) ([]net.Addr, error) {
  260. tab, err := NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
  261. if err != nil {
  262. return nil, os.NewSyscallError("netlinkrib", err)
  263. }
  264. msgs, err := syscall.ParseNetlinkMessage(tab)
  265. if err != nil {
  266. return nil, os.NewSyscallError("parsenetlinkmessage", err)
  267. }
  268. var ift []net.Interface
  269. if ifi == nil {
  270. var err error
  271. ift, err = interfaceTable(0)
  272. if err != nil {
  273. return nil, err
  274. }
  275. }
  276. ifat, err := addrTable(ift, ifi, msgs)
  277. if err != nil {
  278. return nil, err
  279. }
  280. return ifat, nil
  281. }
  282. func addrTable(ift []net.Interface, ifi *net.Interface, msgs []syscall.NetlinkMessage) ([]net.Addr, error) {
  283. var ifat []net.Addr
  284. loop:
  285. for _, m := range msgs {
  286. switch m.Header.Type {
  287. case syscall.NLMSG_DONE:
  288. break loop
  289. case syscall.RTM_NEWADDR:
  290. ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
  291. if len(ift) != 0 || ifi.Index == int(ifam.Index) {
  292. attrs, err := syscall.ParseNetlinkRouteAttr(&m)
  293. if err != nil {
  294. return nil, os.NewSyscallError("parsenetlinkrouteattr", err)
  295. }
  296. ifa := newAddr(ifam, attrs)
  297. if ifa != nil {
  298. ifat = append(ifat, ifa)
  299. }
  300. }
  301. }
  302. }
  303. return ifat, nil
  304. }
  305. func newAddr(ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRouteAttr) net.Addr {
  306. var ipPointToPoint bool
  307. // Seems like we need to make sure whether the IP interface
  308. // stack consists of IP point-to-point numbered or unnumbered
  309. // addressing.
  310. for _, a := range attrs {
  311. if a.Attr.Type == syscall.IFA_LOCAL {
  312. ipPointToPoint = true
  313. break
  314. }
  315. }
  316. for _, a := range attrs {
  317. if ipPointToPoint && a.Attr.Type == syscall.IFA_ADDRESS {
  318. continue
  319. }
  320. switch ifam.Family {
  321. case syscall.AF_INET:
  322. return &net.IPNet{IP: net.IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: net.CIDRMask(int(ifam.Prefixlen), 8*net.IPv4len)}
  323. case syscall.AF_INET6:
  324. ifa := &net.IPNet{IP: make(net.IP, net.IPv6len), Mask: net.CIDRMask(int(ifam.Prefixlen), 8*net.IPv6len)}
  325. copy(ifa.IP, a.Value[:])
  326. return ifa
  327. }
  328. }
  329. return nil
  330. }
  331. func interfaceByIndex(ift []net.Interface, index int) (*net.Interface, error) {
  332. for _, ifi := range ift {
  333. if index == ifi.Index {
  334. return &ifi, nil
  335. }
  336. }
  337. return nil, errNoSuchInterface
  338. }
  339. func ioctl(fd int, req uint, arg unsafe.Pointer) error {
  340. _, _, e1 := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
  341. if e1 != 0 {
  342. return e1
  343. }
  344. return nil
  345. }
  346. func indexToName(index uint32) (string, error) {
  347. fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
  348. if err != nil {
  349. return "", err
  350. }
  351. defer syscall.Close(fd)
  352. var ifr ifReq
  353. *(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ])) = index
  354. err = ioctl(fd, syscall.SIOCGIFNAME, unsafe.Pointer(&ifr[0]))
  355. if err != nil {
  356. return "", err
  357. }
  358. return string(bytes.Trim(ifr[:syscall.IFNAMSIZ], "\x00")), nil
  359. }
  360. func nameToMTU(name string) (int, error) {
  361. // Leave room for terminating NULL byte.
  362. if len(name) >= syscall.IFNAMSIZ {
  363. return -1, syscall.EINVAL
  364. }
  365. fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
  366. if err != nil {
  367. return -1, err
  368. }
  369. defer syscall.Close(fd)
  370. var ifr ifReq
  371. copy(ifr[:], name)
  372. err = ioctl(fd, syscall.SIOCGIFMTU, unsafe.Pointer(&ifr[0]))
  373. if err != nil {
  374. return -1, err
  375. }
  376. return int(*(*int32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil
  377. }
  378. func nameToFlags(name string) (net.Flags, error) {
  379. // Leave room for terminating NULL byte.
  380. if len(name) >= syscall.IFNAMSIZ {
  381. return 0, syscall.EINVAL
  382. }
  383. fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0)
  384. if err != nil {
  385. return 0, err
  386. }
  387. defer syscall.Close(fd)
  388. var ifr ifReq
  389. copy(ifr[:], name)
  390. err = ioctl(fd, syscall.SIOCGIFFLAGS, unsafe.Pointer(&ifr[0]))
  391. if err != nil {
  392. return 0, err
  393. }
  394. return linkFlags(*(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil
  395. }