tun_freebsd.go 17 KB

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