mark_linux.go 822 B

12345678910111213141516171819202122232425262728293031323334353637
  1. //go:build linux
  2. package dialer
  3. import (
  4. "context"
  5. "net"
  6. "net/netip"
  7. "syscall"
  8. )
  9. func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ netip.Addr) {
  10. addControlToDialer(dialer, bindMarkToControl(mark))
  11. }
  12. func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, _ string) {
  13. addControlToListenConfig(lc, bindMarkToControl(mark))
  14. }
  15. func bindMarkToControl(mark int) controlFn {
  16. return func(ctx context.Context, network, address string, c syscall.RawConn) (err error) {
  17. addrPort, err := netip.ParseAddrPort(address)
  18. if err == nil && !addrPort.Addr().IsGlobalUnicast() {
  19. return
  20. }
  21. var innerErr error
  22. err = c.Control(func(fd uintptr) {
  23. innerErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
  24. })
  25. if innerErr != nil {
  26. err = innerErr
  27. }
  28. return
  29. }
  30. }