netns_android.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. //go:build android
  4. package netns
  5. import (
  6. "fmt"
  7. "sync"
  8. "syscall"
  9. "tailscale.com/net/netmon"
  10. "tailscale.com/types/logger"
  11. )
  12. var (
  13. androidProtectFuncMu sync.Mutex
  14. androidProtectFunc func(fd int) error
  15. )
  16. // UseSocketMark reports whether SO_MARK is in use. Android does not use SO_MARK.
  17. func UseSocketMark() bool {
  18. return false
  19. }
  20. // SetAndroidProtectFunc register a func that Android provides that JNI calls into
  21. // https://developer.android.com/reference/android/net/VpnService#protect(int)
  22. // which is documented as:
  23. //
  24. // "Protect a socket from VPN connections. After protecting, data sent
  25. // through this socket will go directly to the underlying network, so
  26. // its traffic will not be forwarded through the VPN. This method is
  27. // useful if some connections need to be kept outside of VPN. For
  28. // example, a VPN tunnel should protect itself if its destination is
  29. // covered by VPN routes. Otherwise its outgoing packets will be sent
  30. // back to the VPN interface and cause an infinite loop. This method
  31. // will fail if the application is not prepared or is revoked."
  32. //
  33. // A nil func disables the use the hook.
  34. //
  35. // This indirection is necessary because this is the supported, stable
  36. // interface to use on Android, and doing the sockopts to set the
  37. // fwmark return errors on Android. The actual implementation of
  38. // VpnService.protect ends up doing an IPC to another process on
  39. // Android, asking for the fwmark to be set.
  40. func SetAndroidProtectFunc(f func(fd int) error) {
  41. androidProtectFuncMu.Lock()
  42. defer androidProtectFuncMu.Unlock()
  43. androidProtectFunc = f
  44. }
  45. func control(logger.Logf, *netmon.Monitor) func(network, address string, c syscall.RawConn) error {
  46. return controlC
  47. }
  48. // controlC marks c as necessary to dial in a separate network namespace.
  49. //
  50. // It's intentionally the same signature as net.Dialer.Control
  51. // and net.ListenConfig.Control.
  52. func controlC(network, address string, c syscall.RawConn) error {
  53. var sockErr error
  54. err := c.Control(func(fd uintptr) {
  55. androidProtectFuncMu.Lock()
  56. f := androidProtectFunc
  57. androidProtectFuncMu.Unlock()
  58. if f != nil {
  59. sockErr = f(int(fd))
  60. }
  61. })
  62. if err != nil {
  63. return fmt.Errorf("RawConn.Control on %T: %w", c, err)
  64. }
  65. return sockErr
  66. }