tun_darwin.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. //go:build !ios && !e2e_testing
  2. // +build !ios,!e2e_testing
  3. package overlay
  4. import (
  5. "fmt"
  6. "io"
  7. "net"
  8. "os"
  9. "syscall"
  10. "unsafe"
  11. "github.com/sirupsen/logrus"
  12. "github.com/slackhq/nebula/cidr"
  13. "github.com/slackhq/nebula/iputil"
  14. netroute "golang.org/x/net/route"
  15. "golang.org/x/sys/unix"
  16. )
  17. type tun struct {
  18. io.ReadWriteCloser
  19. Device string
  20. cidr *net.IPNet
  21. DefaultMTU int
  22. Routes []Route
  23. routeTree *cidr.Tree4
  24. l *logrus.Logger
  25. // cache out buffer since we need to prepend 4 bytes for tun metadata
  26. out []byte
  27. }
  28. type sockaddrCtl struct {
  29. scLen uint8
  30. scFamily uint8
  31. ssSysaddr uint16
  32. scID uint32
  33. scUnit uint32
  34. scReserved [5]uint32
  35. }
  36. type ifReq struct {
  37. Name [16]byte
  38. Flags uint16
  39. pad [8]byte
  40. }
  41. func ioctl(a1, a2, a3 uintptr) error {
  42. _, _, errno := unix.Syscall(unix.SYS_IOCTL, a1, a2, a3)
  43. if errno != 0 {
  44. return errno
  45. }
  46. return nil
  47. }
  48. var sockaddrCtlSize uintptr = 32
  49. const (
  50. _SYSPROTO_CONTROL = 2 //define SYSPROTO_CONTROL 2 /* kernel control protocol */
  51. _AF_SYS_CONTROL = 2 //#define AF_SYS_CONTROL 2 /* corresponding sub address type */
  52. _PF_SYSTEM = unix.AF_SYSTEM //#define PF_SYSTEM AF_SYSTEM
  53. _CTLIOCGINFO = 3227799043 //#define CTLIOCGINFO _IOWR('N', 3, struct ctl_info)
  54. utunControlName = "com.apple.net.utun_control"
  55. )
  56. type ifreqAddr struct {
  57. Name [16]byte
  58. Addr unix.RawSockaddrInet4
  59. pad [8]byte
  60. }
  61. type ifreqMTU struct {
  62. Name [16]byte
  63. MTU int32
  64. pad [8]byte
  65. }
  66. func newTun(l *logrus.Logger, name string, cidr *net.IPNet, defaultMTU int, routes []Route, _ int, _ bool) (*tun, error) {
  67. routeTree, err := makeRouteTree(l, routes, false)
  68. if err != nil {
  69. return nil, err
  70. }
  71. ifIndex := -1
  72. if name != "" && name != "utun" {
  73. _, err := fmt.Sscanf(name, "utun%d", &ifIndex)
  74. if err != nil || ifIndex < 0 {
  75. // NOTE: we don't make this error so we don't break existing
  76. // configs that set a name before it was used.
  77. l.Warn("interface name must be utun[0-9]+ on Darwin, ignoring")
  78. ifIndex = -1
  79. }
  80. }
  81. fd, err := unix.Socket(_PF_SYSTEM, unix.SOCK_DGRAM, _SYSPROTO_CONTROL)
  82. if err != nil {
  83. return nil, fmt.Errorf("system socket: %v", err)
  84. }
  85. var ctlInfo = &struct {
  86. ctlID uint32
  87. ctlName [96]byte
  88. }{}
  89. copy(ctlInfo.ctlName[:], utunControlName)
  90. err = ioctl(uintptr(fd), uintptr(_CTLIOCGINFO), uintptr(unsafe.Pointer(ctlInfo)))
  91. if err != nil {
  92. return nil, fmt.Errorf("CTLIOCGINFO: %v", err)
  93. }
  94. sc := sockaddrCtl{
  95. scLen: uint8(sockaddrCtlSize),
  96. scFamily: unix.AF_SYSTEM,
  97. ssSysaddr: _AF_SYS_CONTROL,
  98. scID: ctlInfo.ctlID,
  99. scUnit: uint32(ifIndex) + 1,
  100. }
  101. _, _, errno := unix.RawSyscall(
  102. unix.SYS_CONNECT,
  103. uintptr(fd),
  104. uintptr(unsafe.Pointer(&sc)),
  105. sockaddrCtlSize,
  106. )
  107. if errno != 0 {
  108. return nil, fmt.Errorf("SYS_CONNECT: %v", errno)
  109. }
  110. var ifName struct {
  111. name [16]byte
  112. }
  113. ifNameSize := uintptr(len(ifName.name))
  114. _, _, errno = syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd),
  115. 2, // SYSPROTO_CONTROL
  116. 2, // UTUN_OPT_IFNAME
  117. uintptr(unsafe.Pointer(&ifName)),
  118. uintptr(unsafe.Pointer(&ifNameSize)), 0)
  119. if errno != 0 {
  120. return nil, fmt.Errorf("SYS_GETSOCKOPT: %v", errno)
  121. }
  122. name = string(ifName.name[:ifNameSize-1])
  123. err = syscall.SetNonblock(fd, true)
  124. if err != nil {
  125. return nil, fmt.Errorf("SetNonblock: %v", err)
  126. }
  127. file := os.NewFile(uintptr(fd), "")
  128. tun := &tun{
  129. ReadWriteCloser: file,
  130. Device: name,
  131. cidr: cidr,
  132. DefaultMTU: defaultMTU,
  133. Routes: routes,
  134. routeTree: routeTree,
  135. l: l,
  136. }
  137. return tun, nil
  138. }
  139. func (t *tun) deviceBytes() (o [16]byte) {
  140. for i, c := range t.Device {
  141. o[i] = byte(c)
  142. }
  143. return
  144. }
  145. func newTunFromFd(_ *logrus.Logger, _ int, _ *net.IPNet, _ int, _ []Route, _ int) (*tun, error) {
  146. return nil, fmt.Errorf("newTunFromFd not supported in Darwin")
  147. }
  148. func (t *tun) Close() error {
  149. if t.ReadWriteCloser != nil {
  150. return t.ReadWriteCloser.Close()
  151. }
  152. return nil
  153. }
  154. func (t *tun) Activate() error {
  155. devName := t.deviceBytes()
  156. var addr, mask [4]byte
  157. copy(addr[:], t.cidr.IP.To4())
  158. copy(mask[:], t.cidr.Mask)
  159. s, err := unix.Socket(
  160. unix.AF_INET,
  161. unix.SOCK_DGRAM,
  162. unix.IPPROTO_IP,
  163. )
  164. if err != nil {
  165. return err
  166. }
  167. fd := uintptr(s)
  168. ifra := ifreqAddr{
  169. Name: devName,
  170. Addr: unix.RawSockaddrInet4{
  171. Family: unix.AF_INET,
  172. Addr: addr,
  173. },
  174. }
  175. // Set the device ip address
  176. if err = ioctl(fd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&ifra))); err != nil {
  177. return fmt.Errorf("failed to set tun address: %s", err)
  178. }
  179. // Set the device network
  180. ifra.Addr.Addr = mask
  181. if err = ioctl(fd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&ifra))); err != nil {
  182. return fmt.Errorf("failed to set tun netmask: %s", err)
  183. }
  184. // Set the device name
  185. ifrf := ifReq{Name: devName}
  186. if err = ioctl(fd, unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
  187. return fmt.Errorf("failed to set tun device name: %s", err)
  188. }
  189. // Set the MTU on the device
  190. ifm := ifreqMTU{Name: devName, MTU: int32(t.DefaultMTU)}
  191. if err = ioctl(fd, unix.SIOCSIFMTU, uintptr(unsafe.Pointer(&ifm))); err != nil {
  192. return fmt.Errorf("failed to set tun mtu: %v", err)
  193. }
  194. /*
  195. // Set the transmit queue length
  196. ifrq := ifreqQLEN{Name: devName, Value: int32(t.TXQueueLen)}
  197. if err = ioctl(fd, unix.SIOCSIFTXQLEN, uintptr(unsafe.Pointer(&ifrq))); err != nil {
  198. // If we can't set the queue length nebula will still work but it may lead to packet loss
  199. l.WithError(err).Error("Failed to set tun tx queue length")
  200. }
  201. */
  202. // Bring up the interface
  203. ifrf.Flags = ifrf.Flags | unix.IFF_UP
  204. if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
  205. return fmt.Errorf("failed to bring the tun device up: %s", err)
  206. }
  207. routeSock, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
  208. if err != nil {
  209. return fmt.Errorf("unable to create AF_ROUTE socket: %v", err)
  210. }
  211. defer func() {
  212. unix.Shutdown(routeSock, unix.SHUT_RDWR)
  213. err := unix.Close(routeSock)
  214. if err != nil {
  215. t.l.WithError(err).Error("failed to close AF_ROUTE socket")
  216. }
  217. }()
  218. routeAddr := &netroute.Inet4Addr{}
  219. maskAddr := &netroute.Inet4Addr{}
  220. linkAddr, err := getLinkAddr(t.Device)
  221. if err != nil {
  222. return err
  223. }
  224. if linkAddr == nil {
  225. return fmt.Errorf("unable to discover link_addr for tun interface")
  226. }
  227. copy(routeAddr.IP[:], addr[:])
  228. copy(maskAddr.IP[:], mask[:])
  229. err = addRoute(routeSock, routeAddr, maskAddr, linkAddr)
  230. if err != nil {
  231. return err
  232. }
  233. // Run the interface
  234. ifrf.Flags = ifrf.Flags | unix.IFF_UP | unix.IFF_RUNNING
  235. if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
  236. return fmt.Errorf("failed to run tun device: %s", err)
  237. }
  238. // Unsafe path routes
  239. for _, r := range t.Routes {
  240. if r.Via == nil {
  241. // We don't allow route MTUs so only install routes with a via
  242. continue
  243. }
  244. copy(routeAddr.IP[:], r.Cidr.IP.To4())
  245. copy(maskAddr.IP[:], net.IP(r.Cidr.Mask).To4())
  246. err = addRoute(routeSock, routeAddr, maskAddr, linkAddr)
  247. if err != nil {
  248. return err
  249. }
  250. // TODO how to set metric
  251. }
  252. return nil
  253. }
  254. func (t *tun) RouteFor(ip iputil.VpnIp) iputil.VpnIp {
  255. r := t.routeTree.MostSpecificContains(ip)
  256. if r != nil {
  257. return r.(iputil.VpnIp)
  258. }
  259. return 0
  260. }
  261. // Get the LinkAddr for the interface of the given name
  262. // TODO: Is there an easier way to fetch this when we create the interface?
  263. // Maybe SIOCGIFINDEX? but this doesn't appear to exist in the darwin headers.
  264. func getLinkAddr(name string) (*netroute.LinkAddr, error) {
  265. rib, err := netroute.FetchRIB(unix.AF_UNSPEC, unix.NET_RT_IFLIST, 0)
  266. if err != nil {
  267. return nil, err
  268. }
  269. msgs, err := netroute.ParseRIB(unix.NET_RT_IFLIST, rib)
  270. if err != nil {
  271. return nil, err
  272. }
  273. for _, m := range msgs {
  274. switch m := m.(type) {
  275. case *netroute.InterfaceMessage:
  276. if m.Name == name {
  277. sa, ok := m.Addrs[unix.RTAX_IFP].(*netroute.LinkAddr)
  278. if ok {
  279. return sa, nil
  280. }
  281. }
  282. }
  283. }
  284. return nil, nil
  285. }
  286. func addRoute(sock int, addr, mask *netroute.Inet4Addr, link *netroute.LinkAddr) error {
  287. r := netroute.RouteMessage{
  288. Version: unix.RTM_VERSION,
  289. Type: unix.RTM_ADD,
  290. Flags: unix.RTF_UP,
  291. Seq: 1,
  292. Addrs: []netroute.Addr{
  293. unix.RTAX_DST: addr,
  294. unix.RTAX_GATEWAY: link,
  295. unix.RTAX_NETMASK: mask,
  296. },
  297. }
  298. data, err := r.Marshal()
  299. if err != nil {
  300. return fmt.Errorf("failed to create route.RouteMessage: %v", err)
  301. }
  302. _, err = unix.Write(sock, data[:])
  303. if err != nil {
  304. return fmt.Errorf("failed to write route.RouteMessage to socket: %v", err)
  305. }
  306. return nil
  307. }
  308. func (t *tun) Read(to []byte) (int, error) {
  309. buf := make([]byte, len(to)+4)
  310. n, err := t.ReadWriteCloser.Read(buf)
  311. copy(to, buf[4:])
  312. return n - 4, err
  313. }
  314. // Write is only valid for single threaded use
  315. func (t *tun) Write(from []byte) (int, error) {
  316. buf := t.out
  317. if cap(buf) < len(from)+4 {
  318. buf = make([]byte, len(from)+4)
  319. t.out = buf
  320. }
  321. buf = buf[:len(from)+4]
  322. if len(from) == 0 {
  323. return 0, syscall.EIO
  324. }
  325. // Determine the IP Family for the NULL L2 Header
  326. ipVer := from[0] >> 4
  327. if ipVer == 4 {
  328. buf[3] = syscall.AF_INET
  329. } else if ipVer == 6 {
  330. buf[3] = syscall.AF_INET6
  331. } else {
  332. return 0, fmt.Errorf("unable to determine IP version from packet")
  333. }
  334. copy(buf[4:], from)
  335. n, err := t.ReadWriteCloser.Write(buf)
  336. return n - 4, err
  337. }
  338. func (t *tun) Cidr() *net.IPNet {
  339. return t.cidr
  340. }
  341. func (t *tun) Name() string {
  342. return t.Device
  343. }
  344. func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) {
  345. return nil, fmt.Errorf("TODO: multiqueue not implemented for darwin")
  346. }