tun_freebsd.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. //go:build !e2e_testing
  2. // +build !e2e_testing
  3. package overlay
  4. import (
  5. "bytes"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "io/fs"
  10. "log/slog"
  11. "net/netip"
  12. "os"
  13. "sync/atomic"
  14. "syscall"
  15. "time"
  16. "unsafe"
  17. "github.com/gaissmai/bart"
  18. "github.com/slackhq/nebula/config"
  19. "github.com/slackhq/nebula/routing"
  20. "github.com/slackhq/nebula/util"
  21. netroute "golang.org/x/net/route"
  22. "golang.org/x/sys/unix"
  23. )
  24. const (
  25. // FIODGNAME is defined in sys/sys/filio.h on FreeBSD
  26. // For 32-bit systems, use FIODGNAME_32 (not defined in this file: 0x80086678)
  27. FIODGNAME = 0x80106678
  28. TUNSIFMODE = 0x8004745e
  29. TUNSIFHEAD = 0x80047460
  30. OSIOCAIFADDR_IN6 = 0x8088691b
  31. IN6_IFF_NODAD = 0x0020
  32. )
  33. type fiodgnameArg struct {
  34. length int32
  35. pad [4]byte
  36. buf unsafe.Pointer
  37. }
  38. type ifreqRename struct {
  39. Name [unix.IFNAMSIZ]byte
  40. Data uintptr
  41. }
  42. type ifreqDestroy struct {
  43. Name [unix.IFNAMSIZ]byte
  44. pad [16]byte
  45. }
  46. type ifReq struct {
  47. Name [unix.IFNAMSIZ]byte
  48. Flags uint16
  49. }
  50. type ifreqMTU struct {
  51. Name [unix.IFNAMSIZ]byte
  52. MTU int32
  53. }
  54. type addrLifetime struct {
  55. Expire uint64
  56. Preferred uint64
  57. Vltime uint32
  58. Pltime uint32
  59. }
  60. type ifreqAlias4 struct {
  61. Name [unix.IFNAMSIZ]byte
  62. Addr unix.RawSockaddrInet4
  63. DstAddr unix.RawSockaddrInet4
  64. MaskAddr unix.RawSockaddrInet4
  65. VHid uint32
  66. }
  67. type ifreqAlias6 struct {
  68. Name [unix.IFNAMSIZ]byte
  69. Addr unix.RawSockaddrInet6
  70. DstAddr unix.RawSockaddrInet6
  71. PrefixMask unix.RawSockaddrInet6
  72. Flags uint32
  73. Lifetime addrLifetime
  74. VHid uint32
  75. }
  76. type tun struct {
  77. Device string
  78. vpnNetworks []netip.Prefix
  79. MTU int
  80. Routes atomic.Pointer[[]Route]
  81. routeTree atomic.Pointer[bart.Table[routing.Gateways]]
  82. linkAddr *netroute.LinkAddr
  83. l *slog.Logger
  84. fd int
  85. shutdownR int // read end of the shutdown pipe; closing the write end wakes blocked polls
  86. shutdownW int // write end of the shutdown pipe; closing this signals shutdown to any blocked reader/writer
  87. readPoll [2]unix.PollFd
  88. writePoll [2]unix.PollFd
  89. closed atomic.Bool
  90. }
  91. // blockOnRead waits until the tun fd is readable or shutdown has been signaled.
  92. // Returns os.ErrClosed if Close was called.
  93. func (t *tun) blockOnRead() error {
  94. const problemFlags = unix.POLLHUP | unix.POLLNVAL | unix.POLLERR
  95. var err error
  96. for {
  97. _, err = unix.Poll(t.readPoll[:], -1)
  98. if err != unix.EINTR {
  99. break
  100. }
  101. }
  102. tunEvents := t.readPoll[0].Revents
  103. shutdownEvents := t.readPoll[1].Revents
  104. t.readPoll[0].Revents = 0
  105. t.readPoll[1].Revents = 0
  106. if err != nil {
  107. return err
  108. }
  109. if shutdownEvents&(unix.POLLIN|problemFlags) != 0 {
  110. return os.ErrClosed
  111. }
  112. if tunEvents&problemFlags != 0 {
  113. return os.ErrClosed
  114. }
  115. return nil
  116. }
  117. func (t *tun) blockOnWrite() error {
  118. const problemFlags = unix.POLLHUP | unix.POLLNVAL | unix.POLLERR
  119. var err error
  120. for {
  121. _, err = unix.Poll(t.writePoll[:], -1)
  122. if err != unix.EINTR {
  123. break
  124. }
  125. }
  126. tunEvents := t.writePoll[0].Revents
  127. shutdownEvents := t.writePoll[1].Revents
  128. t.writePoll[0].Revents = 0
  129. t.writePoll[1].Revents = 0
  130. if err != nil {
  131. return err
  132. }
  133. if shutdownEvents&(unix.POLLIN|problemFlags) != 0 {
  134. return os.ErrClosed
  135. }
  136. if tunEvents&problemFlags != 0 {
  137. return os.ErrClosed
  138. }
  139. return nil
  140. }
  141. func (t *tun) Read(to []byte) (int, error) {
  142. for {
  143. n, err := unix.Read(t.fd, to)
  144. if err == nil {
  145. return n, nil
  146. }
  147. switch err {
  148. case unix.EAGAIN:
  149. if berr := t.blockOnRead(); berr != nil {
  150. return 0, berr
  151. }
  152. case unix.EINTR:
  153. // retry
  154. case unix.EBADF:
  155. return 0, os.ErrClosed
  156. default:
  157. return 0, err
  158. }
  159. }
  160. }
  161. func (t *tun) Write(from []byte) (int, error) {
  162. for {
  163. n, err := unix.Write(t.fd, from)
  164. if err == nil {
  165. return n, nil
  166. }
  167. switch err {
  168. case unix.EAGAIN:
  169. if berr := t.blockOnWrite(); berr != nil {
  170. return 0, berr
  171. }
  172. case unix.EINTR:
  173. // retry
  174. case unix.EBADF:
  175. return 0, os.ErrClosed
  176. default:
  177. return 0, err
  178. }
  179. }
  180. }
  181. func (t *tun) Close() error {
  182. if t.closed.Swap(true) {
  183. return nil
  184. }
  185. // Closing the write end of the shutdown pipe causes any blocked Poll to
  186. // return with POLLHUP on the shutdown fd, so readers/writers wake up and
  187. // exit with os.ErrClosed.
  188. if t.shutdownW >= 0 {
  189. _ = unix.Close(t.shutdownW)
  190. t.shutdownW = -1
  191. }
  192. if t.fd >= 0 {
  193. if err := unix.Close(t.fd); err != nil {
  194. t.l.Error("Error closing device", "error", err)
  195. }
  196. t.fd = -1
  197. }
  198. if t.shutdownR >= 0 {
  199. _ = unix.Close(t.shutdownR)
  200. t.shutdownR = -1
  201. }
  202. c := make(chan struct{})
  203. go func() {
  204. // destroying the interface can block if a read() is still pending. Do this asynchronously.
  205. defer close(c)
  206. s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_IP)
  207. if err == nil {
  208. defer syscall.Close(s)
  209. ifreq := ifreqDestroy{Name: t.deviceBytes()}
  210. err = ioctl(uintptr(s), syscall.SIOCIFDESTROY, uintptr(unsafe.Pointer(&ifreq)))
  211. }
  212. if err != nil {
  213. t.l.Error("Error destroying tunnel", "error", err)
  214. }
  215. }()
  216. // wait up to 1 second so we start blocking at the ioctl
  217. select {
  218. case <-c:
  219. case <-time.After(1 * time.Second):
  220. }
  221. return nil
  222. }
  223. func newTunFromFd(_ *config.C, _ *slog.Logger, _ int, _ []netip.Prefix) (*tun, error) {
  224. return nil, fmt.Errorf("newTunFromFd not supported in FreeBSD")
  225. }
  226. func newTun(c *config.C, l *slog.Logger, vpnNetworks []netip.Prefix, _ bool) (*tun, error) {
  227. // Try to open existing tun device
  228. var fd int
  229. var err error
  230. deviceName := c.GetString("tun.dev", "")
  231. if deviceName != "" {
  232. fd, err = unix.Open("/dev/"+deviceName, os.O_RDWR, 0)
  233. }
  234. if errors.Is(err, fs.ErrNotExist) || deviceName == "" {
  235. // If the device doesn't already exist, request a new one and rename it
  236. fd, err = unix.Open("/dev/tun", os.O_RDWR, 0)
  237. }
  238. if err != nil {
  239. return nil, err
  240. }
  241. if err = unix.SetNonblock(fd, true); err != nil {
  242. _ = unix.Close(fd)
  243. return nil, fmt.Errorf("failed to set tun device as nonblocking: %w", err)
  244. }
  245. // Shutdown pipe lets Close wake any reader/writer blocked in Poll.
  246. var pipeFds [2]int
  247. if err = unix.Pipe2(pipeFds[:], unix.O_CLOEXEC|unix.O_NONBLOCK); err != nil {
  248. _ = unix.Close(fd)
  249. return nil, fmt.Errorf("failed to create shutdown pipe: %w", err)
  250. }
  251. shutdownR, shutdownW := pipeFds[0], pipeFds[1]
  252. closeOnErr := true
  253. defer func() {
  254. if closeOnErr {
  255. _ = unix.Close(fd)
  256. _ = unix.Close(shutdownR)
  257. _ = unix.Close(shutdownW)
  258. }
  259. }()
  260. // Read the name of the interface
  261. var name [16]byte
  262. arg := fiodgnameArg{length: 16, buf: unsafe.Pointer(&name)}
  263. ctrlErr := ioctl(uintptr(fd), FIODGNAME, uintptr(unsafe.Pointer(&arg)))
  264. if ctrlErr == nil {
  265. // set broadcast mode and multicast
  266. ifmode := uint32(unix.IFF_BROADCAST | unix.IFF_MULTICAST)
  267. ctrlErr = ioctl(uintptr(fd), TUNSIFMODE, uintptr(unsafe.Pointer(&ifmode)))
  268. }
  269. if ctrlErr == nil {
  270. // turn on link-layer mode, to support ipv6
  271. ifhead := uint32(1)
  272. ctrlErr = ioctl(uintptr(fd), TUNSIFHEAD, uintptr(unsafe.Pointer(&ifhead)))
  273. }
  274. if ctrlErr != nil {
  275. return nil, ctrlErr
  276. }
  277. ifName := string(bytes.TrimRight(name[:], "\x00"))
  278. if deviceName == "" {
  279. deviceName = ifName
  280. }
  281. // If the name doesn't match the desired interface name, rename it now
  282. if ifName != deviceName {
  283. s, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)
  284. if err != nil {
  285. return nil, err
  286. }
  287. defer syscall.Close(s)
  288. var fromName [16]byte
  289. var toName [16]byte
  290. copy(fromName[:], ifName)
  291. copy(toName[:], deviceName)
  292. ifrr := ifreqRename{
  293. Name: fromName,
  294. Data: uintptr(unsafe.Pointer(&toName)),
  295. }
  296. // Set the device name
  297. _ = ioctl(uintptr(s), syscall.SIOCSIFNAME, uintptr(unsafe.Pointer(&ifrr)))
  298. }
  299. t := &tun{
  300. Device: deviceName,
  301. vpnNetworks: vpnNetworks,
  302. MTU: c.GetInt("tun.mtu", DefaultMTU),
  303. l: l,
  304. fd: fd,
  305. shutdownR: shutdownR,
  306. shutdownW: shutdownW,
  307. readPoll: [2]unix.PollFd{
  308. {Fd: int32(fd), Events: unix.POLLIN},
  309. {Fd: int32(shutdownR), Events: unix.POLLIN},
  310. },
  311. writePoll: [2]unix.PollFd{
  312. {Fd: int32(fd), Events: unix.POLLOUT},
  313. {Fd: int32(shutdownR), Events: unix.POLLIN},
  314. },
  315. }
  316. err = t.reload(c, true)
  317. if err != nil {
  318. return nil, err
  319. }
  320. closeOnErr = false
  321. c.RegisterReloadCallback(func(c *config.C) {
  322. err := t.reload(c, false)
  323. if err != nil {
  324. util.LogWithContextIfNeeded("failed to reload tun device", err, t.l)
  325. }
  326. })
  327. return t, nil
  328. }
  329. func (t *tun) addIp(cidr netip.Prefix) error {
  330. if cidr.Addr().Is4() {
  331. ifr := ifreqAlias4{
  332. Name: t.deviceBytes(),
  333. Addr: unix.RawSockaddrInet4{
  334. Len: unix.SizeofSockaddrInet4,
  335. Family: unix.AF_INET,
  336. Addr: cidr.Addr().As4(),
  337. },
  338. DstAddr: unix.RawSockaddrInet4{
  339. Len: unix.SizeofSockaddrInet4,
  340. Family: unix.AF_INET,
  341. Addr: getBroadcast(cidr).As4(),
  342. },
  343. MaskAddr: unix.RawSockaddrInet4{
  344. Len: unix.SizeofSockaddrInet4,
  345. Family: unix.AF_INET,
  346. Addr: prefixToMask(cidr).As4(),
  347. },
  348. VHid: 0,
  349. }
  350. s, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)
  351. if err != nil {
  352. return err
  353. }
  354. defer syscall.Close(s)
  355. // Note: unix.SIOCAIFADDR corresponds to FreeBSD's OSIOCAIFADDR
  356. if err := ioctl(uintptr(s), unix.SIOCAIFADDR, uintptr(unsafe.Pointer(&ifr))); err != nil {
  357. return fmt.Errorf("failed to set tun address %s: %s", cidr.Addr().String(), err)
  358. }
  359. return nil
  360. }
  361. if cidr.Addr().Is6() {
  362. ifr := ifreqAlias6{
  363. Name: t.deviceBytes(),
  364. Addr: unix.RawSockaddrInet6{
  365. Len: unix.SizeofSockaddrInet6,
  366. Family: unix.AF_INET6,
  367. Addr: cidr.Addr().As16(),
  368. },
  369. PrefixMask: unix.RawSockaddrInet6{
  370. Len: unix.SizeofSockaddrInet6,
  371. Family: unix.AF_INET6,
  372. Addr: prefixToMask(cidr).As16(),
  373. },
  374. Lifetime: addrLifetime{
  375. Expire: 0,
  376. Preferred: 0,
  377. Vltime: 0xffffffff,
  378. Pltime: 0xffffffff,
  379. },
  380. Flags: IN6_IFF_NODAD,
  381. }
  382. s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_DGRAM, syscall.IPPROTO_IP)
  383. if err != nil {
  384. return err
  385. }
  386. defer syscall.Close(s)
  387. if err := ioctl(uintptr(s), OSIOCAIFADDR_IN6, uintptr(unsafe.Pointer(&ifr))); err != nil {
  388. return fmt.Errorf("failed to set tun address %s: %s", cidr.Addr().String(), err)
  389. }
  390. return nil
  391. }
  392. return fmt.Errorf("unknown address type %v", cidr)
  393. }
  394. func (t *tun) Activate() error {
  395. // Setup our default MTU
  396. err := t.setMTU()
  397. if err != nil {
  398. return err
  399. }
  400. linkAddr, err := getLinkAddr(t.Device)
  401. if err != nil {
  402. return err
  403. }
  404. if linkAddr == nil {
  405. return fmt.Errorf("unable to discover link_addr for tun interface")
  406. }
  407. t.linkAddr = linkAddr
  408. for i := range t.vpnNetworks {
  409. err := t.addIp(t.vpnNetworks[i])
  410. if err != nil {
  411. return err
  412. }
  413. }
  414. return t.addRoutes(false)
  415. }
  416. func (t *tun) setMTU() error {
  417. // Set the MTU on the device
  418. s, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)
  419. if err != nil {
  420. return err
  421. }
  422. defer syscall.Close(s)
  423. ifm := ifreqMTU{Name: t.deviceBytes(), MTU: int32(t.MTU)}
  424. err = ioctl(uintptr(s), unix.SIOCSIFMTU, uintptr(unsafe.Pointer(&ifm)))
  425. return err
  426. }
  427. func (t *tun) reload(c *config.C, initial bool) error {
  428. change, routes, err := getAllRoutesFromConfig(c, t.vpnNetworks, initial)
  429. if err != nil {
  430. return err
  431. }
  432. if !initial && !change {
  433. return nil
  434. }
  435. routeTree, err := makeRouteTree(t.l, routes, false)
  436. if err != nil {
  437. return err
  438. }
  439. // Teach nebula how to handle the routes before establishing them in the system table
  440. oldRoutes := t.Routes.Swap(&routes)
  441. t.routeTree.Store(routeTree)
  442. if !initial {
  443. // Remove first, if the system removes a wanted route hopefully it will be re-added next
  444. err := t.removeRoutes(findRemovedRoutes(routes, *oldRoutes))
  445. if err != nil {
  446. util.LogWithContextIfNeeded("Failed to remove routes", err, t.l)
  447. }
  448. // Ensure any routes we actually want are installed
  449. err = t.addRoutes(true)
  450. if err != nil {
  451. // Catch any stray logs
  452. util.LogWithContextIfNeeded("Failed to add routes", err, t.l)
  453. }
  454. }
  455. return nil
  456. }
  457. func (t *tun) RoutesFor(ip netip.Addr) routing.Gateways {
  458. r, _ := t.routeTree.Load().Lookup(ip)
  459. return r
  460. }
  461. func (t *tun) Networks() []netip.Prefix {
  462. return t.vpnNetworks
  463. }
  464. func (t *tun) Name() string {
  465. return t.Device
  466. }
  467. func (t *tun) SupportsMultiqueue() bool {
  468. return false
  469. }
  470. func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) {
  471. return nil, fmt.Errorf("TODO: multiqueue not implemented for freebsd")
  472. }
  473. func (t *tun) addRoutes(logErrors bool) error {
  474. routes := *t.Routes.Load()
  475. for _, r := range routes {
  476. if len(r.Via) == 0 || !r.Install {
  477. // We don't allow route MTUs so only install routes with a via
  478. continue
  479. }
  480. err := addRoute(r.Cidr, t.linkAddr)
  481. if err != nil {
  482. retErr := util.NewContextualError("Failed to add route", map[string]any{"route": r}, err)
  483. if logErrors {
  484. retErr.Log(t.l)
  485. } else {
  486. return retErr
  487. }
  488. } else {
  489. t.l.Info("Added route", "route", r)
  490. }
  491. }
  492. return nil
  493. }
  494. func (t *tun) removeRoutes(routes []Route) error {
  495. for _, r := range routes {
  496. if !r.Install {
  497. continue
  498. }
  499. err := delRoute(r.Cidr, t.linkAddr)
  500. if err != nil {
  501. t.l.Error("Failed to remove route", "error", err, "route", r)
  502. } else {
  503. t.l.Info("Removed route", "route", r)
  504. }
  505. }
  506. return nil
  507. }
  508. func (t *tun) deviceBytes() (o [16]byte) {
  509. for i, c := range t.Device {
  510. o[i] = byte(c)
  511. }
  512. return
  513. }
  514. func addRoute(prefix netip.Prefix, gateway netroute.Addr) error {
  515. sock, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
  516. if err != nil {
  517. return fmt.Errorf("unable to create AF_ROUTE socket: %v", err)
  518. }
  519. defer unix.Close(sock)
  520. route := &netroute.RouteMessage{
  521. Version: unix.RTM_VERSION,
  522. Type: unix.RTM_ADD,
  523. Flags: unix.RTF_UP,
  524. Seq: 1,
  525. }
  526. if prefix.Addr().Is4() {
  527. route.Addrs = []netroute.Addr{
  528. unix.RTAX_DST: &netroute.Inet4Addr{IP: prefix.Masked().Addr().As4()},
  529. unix.RTAX_NETMASK: &netroute.Inet4Addr{IP: prefixToMask(prefix).As4()},
  530. unix.RTAX_GATEWAY: gateway,
  531. }
  532. } else {
  533. route.Addrs = []netroute.Addr{
  534. unix.RTAX_DST: &netroute.Inet6Addr{IP: prefix.Masked().Addr().As16()},
  535. unix.RTAX_NETMASK: &netroute.Inet6Addr{IP: prefixToMask(prefix).As16()},
  536. unix.RTAX_GATEWAY: gateway,
  537. }
  538. }
  539. data, err := route.Marshal()
  540. if err != nil {
  541. return fmt.Errorf("failed to create route.RouteMessage: %w", err)
  542. }
  543. _, err = unix.Write(sock, data[:])
  544. if err != nil {
  545. if errors.Is(err, unix.EEXIST) {
  546. // Try to do a change
  547. route.Type = unix.RTM_CHANGE
  548. data, err = route.Marshal()
  549. if err != nil {
  550. return fmt.Errorf("failed to create route.RouteMessage for change: %w", err)
  551. }
  552. _, err = unix.Write(sock, data[:])
  553. fmt.Println("DOING CHANGE")
  554. return err
  555. }
  556. return fmt.Errorf("failed to write route.RouteMessage to socket: %w", err)
  557. }
  558. return nil
  559. }
  560. func delRoute(prefix netip.Prefix, gateway netroute.Addr) error {
  561. sock, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
  562. if err != nil {
  563. return fmt.Errorf("unable to create AF_ROUTE socket: %v", err)
  564. }
  565. defer unix.Close(sock)
  566. route := netroute.RouteMessage{
  567. Version: unix.RTM_VERSION,
  568. Type: unix.RTM_DELETE,
  569. Seq: 1,
  570. }
  571. if prefix.Addr().Is4() {
  572. route.Addrs = []netroute.Addr{
  573. unix.RTAX_DST: &netroute.Inet4Addr{IP: prefix.Masked().Addr().As4()},
  574. unix.RTAX_NETMASK: &netroute.Inet4Addr{IP: prefixToMask(prefix).As4()},
  575. unix.RTAX_GATEWAY: gateway,
  576. }
  577. } else {
  578. route.Addrs = []netroute.Addr{
  579. unix.RTAX_DST: &netroute.Inet6Addr{IP: prefix.Masked().Addr().As16()},
  580. unix.RTAX_NETMASK: &netroute.Inet6Addr{IP: prefixToMask(prefix).As16()},
  581. unix.RTAX_GATEWAY: gateway,
  582. }
  583. }
  584. data, err := route.Marshal()
  585. if err != nil {
  586. return fmt.Errorf("failed to create route.RouteMessage: %w", err)
  587. }
  588. _, err = unix.Write(sock, data[:])
  589. if err != nil {
  590. return fmt.Errorf("failed to write route.RouteMessage to socket: %w", err)
  591. }
  592. return nil
  593. }
  594. // getLinkAddr Gets the link address for the interface of the given name
  595. func getLinkAddr(name string) (*netroute.LinkAddr, error) {
  596. rib, err := netroute.FetchRIB(unix.AF_UNSPEC, unix.NET_RT_IFLIST, 0)
  597. if err != nil {
  598. return nil, err
  599. }
  600. msgs, err := netroute.ParseRIB(unix.NET_RT_IFLIST, rib)
  601. if err != nil {
  602. return nil, err
  603. }
  604. for _, m := range msgs {
  605. switch m := m.(type) {
  606. case *netroute.InterfaceMessage:
  607. if m.Name == name {
  608. sa, ok := m.Addrs[unix.RTAX_IFP].(*netroute.LinkAddr)
  609. if ok {
  610. return sa, nil
  611. }
  612. }
  613. }
  614. }
  615. return nil, nil
  616. }
  617. // TunPrefixLen reports the 4-byte BSD AF_INET / AF_INET6 protocol-family
  618. // marker the kernel prepends on read and expects on write.
  619. func (t *tun) TunPrefixLen() int { return 4 }