conn_linux.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //go:build linux
  2. // +build linux
  3. package socket
  4. import (
  5. "context"
  6. "os"
  7. "unsafe"
  8. "golang.org/x/net/bpf"
  9. "golang.org/x/sys/unix"
  10. )
  11. // IoctlKCMClone wraps ioctl(2) for unix.KCMClone values, but returns a Conn
  12. // rather than a raw file descriptor.
  13. func (c *Conn) IoctlKCMClone() (*Conn, error) {
  14. const op = "ioctl"
  15. var (
  16. info *unix.KCMClone
  17. err error
  18. )
  19. doErr := c.control(context.Background(), op, func(fd int) error {
  20. info, err = unix.IoctlKCMClone(fd)
  21. return err
  22. })
  23. if doErr != nil {
  24. return nil, doErr
  25. }
  26. if err != nil {
  27. return nil, os.NewSyscallError(op, err)
  28. }
  29. // Successful clone, wrap in a Conn for use by the caller.
  30. return New(int(info.Fd), c.name)
  31. }
  32. // IoctlKCMAttach wraps ioctl(2) for unix.KCMAttach values.
  33. func (c *Conn) IoctlKCMAttach(info unix.KCMAttach) error {
  34. return c.controlErr(context.Background(), "ioctl", func(fd int) error {
  35. return unix.IoctlKCMAttach(fd, info)
  36. })
  37. }
  38. // IoctlKCMUnattach wraps ioctl(2) for unix.KCMUnattach values.
  39. func (c *Conn) IoctlKCMUnattach(info unix.KCMUnattach) error {
  40. return c.controlErr(context.Background(), "ioctl", func(fd int) error {
  41. return unix.IoctlKCMUnattach(fd, info)
  42. })
  43. }
  44. // PidfdGetfd wraps pidfd_getfd(2) for a Conn which wraps a pidfd, but returns a
  45. // Conn rather than a raw file descriptor.
  46. func (c *Conn) PidfdGetfd(targetFD, flags int) (*Conn, error) {
  47. const op = "pidfd_getfd"
  48. var (
  49. outFD int
  50. err error
  51. )
  52. doErr := c.control(context.Background(), op, func(fd int) error {
  53. outFD, err = unix.PidfdGetfd(fd, targetFD, flags)
  54. return err
  55. })
  56. if doErr != nil {
  57. return nil, doErr
  58. }
  59. if err != nil {
  60. return nil, os.NewSyscallError(op, err)
  61. }
  62. // Successful getfd, wrap in a Conn for use by the caller.
  63. return New(outFD, c.name)
  64. }
  65. // PidfdSendSignal wraps pidfd_send_signal(2) for a Conn which wraps a Linux
  66. // pidfd.
  67. func (c *Conn) PidfdSendSignal(sig unix.Signal, info *unix.Siginfo, flags int) error {
  68. return c.controlErr(context.Background(), "pidfd_send_signal", func(fd int) error {
  69. return unix.PidfdSendSignal(fd, sig, info, flags)
  70. })
  71. }
  72. // SetBPF attaches an assembled BPF program to a Conn.
  73. func (c *Conn) SetBPF(filter []bpf.RawInstruction) error {
  74. // We can't point to the first instruction in the array if no instructions
  75. // are present.
  76. if len(filter) == 0 {
  77. return os.NewSyscallError("setsockopt", unix.EINVAL)
  78. }
  79. prog := unix.SockFprog{
  80. Len: uint16(len(filter)),
  81. Filter: (*unix.SockFilter)(unsafe.Pointer(&filter[0])),
  82. }
  83. return c.SetsockoptSockFprog(unix.SOL_SOCKET, unix.SO_ATTACH_FILTER, &prog)
  84. }
  85. // RemoveBPF removes a BPF filter from a Conn.
  86. func (c *Conn) RemoveBPF() error {
  87. // 0 argument is ignored.
  88. return c.SetsockoptInt(unix.SOL_SOCKET, unix.SO_DETACH_FILTER, 0)
  89. }
  90. // SetsockoptPacketMreq wraps setsockopt(2) for unix.PacketMreq values.
  91. func (c *Conn) SetsockoptPacketMreq(level, opt int, mreq *unix.PacketMreq) error {
  92. return c.controlErr(context.Background(), "setsockopt", func(fd int) error {
  93. return unix.SetsockoptPacketMreq(fd, level, opt, mreq)
  94. })
  95. }
  96. // SetsockoptSockFprog wraps setsockopt(2) for unix.SockFprog values.
  97. func (c *Conn) SetsockoptSockFprog(level, opt int, fprog *unix.SockFprog) error {
  98. return c.controlErr(context.Background(), "setsockopt", func(fd int) error {
  99. return unix.SetsockoptSockFprog(fd, level, opt, fprog)
  100. })
  101. }
  102. // TODO(mdlayher): we accidentally called these GetSockopt rather than
  103. // Getsockopt by package unix convention. Consider fixing.
  104. // GetSockoptTpacketStats wraps getsockopt(2) for unix.TpacketStats values.
  105. func (c *Conn) GetSockoptTpacketStats(level, name int) (*unix.TpacketStats, error) {
  106. const op = "getsockopt"
  107. var (
  108. stats *unix.TpacketStats
  109. err error
  110. )
  111. doErr := c.control(context.Background(), op, func(fd int) error {
  112. stats, err = unix.GetsockoptTpacketStats(fd, level, name)
  113. return err
  114. })
  115. if doErr != nil {
  116. return nil, doErr
  117. }
  118. return stats, os.NewSyscallError(op, err)
  119. }
  120. // GetSockoptTpacketStatsV3 wraps getsockopt(2) for unix.TpacketStatsV3 values.
  121. func (c *Conn) GetSockoptTpacketStatsV3(level, name int) (*unix.TpacketStatsV3, error) {
  122. const op = "getsockopt"
  123. var (
  124. stats *unix.TpacketStatsV3
  125. err error
  126. )
  127. doErr := c.control(context.Background(), op, func(fd int) error {
  128. stats, err = unix.GetsockoptTpacketStatsV3(fd, level, name)
  129. return err
  130. })
  131. if doErr != nil {
  132. return nil, doErr
  133. }
  134. return stats, os.NewSyscallError(op, err)
  135. }
  136. // Waitid wraps waitid(2).
  137. func (c *Conn) Waitid(idType int, info *unix.Siginfo, options int, rusage *unix.Rusage) error {
  138. return c.readErr(context.Background(), "waitid", func(fd int) error {
  139. return unix.Waitid(idType, fd, info, options, rusage)
  140. })
  141. }