packet.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. package packet
  2. import (
  3. "net"
  4. "syscall"
  5. "time"
  6. "golang.org/x/net/bpf"
  7. )
  8. const (
  9. // network is the network reported in net.OpError.
  10. network = "packet"
  11. // Operation names which may be returned in net.OpError.
  12. opClose = "close"
  13. opGetsockopt = "getsockopt"
  14. opListen = "listen"
  15. opRawControl = "raw-control"
  16. opRawRead = "raw-read"
  17. opRawWrite = "raw-write"
  18. opRead = "read"
  19. opSet = "set"
  20. opSetsockopt = "setsockopt"
  21. opSyscallConn = "syscall-conn"
  22. opWrite = "write"
  23. )
  24. // Config contains options for a Conn.
  25. type Config struct {
  26. // Filter is an optional assembled BPF filter which can be applied to the
  27. // Conn before bind(2) is called.
  28. //
  29. // The Conn.SetBPF method serves the same purpose once a Conn has already
  30. // been opened, but setting Filter applies the BPF filter before the Conn is
  31. // bound. This ensures that unexpected packets will not be captured before
  32. // the Conn is opened.
  33. Filter []bpf.RawInstruction
  34. }
  35. // Type is a socket type used when creating a Conn with Listen.
  36. //enumcheck:exhaustive
  37. type Type int
  38. // Possible Type values. Note that the zero value is not valid: callers must
  39. // always specify one of Raw or Datagram when calling Listen.
  40. const (
  41. _ Type = iota
  42. Raw
  43. Datagram
  44. )
  45. // Listen opens a packet sockets connection on the specified interface, using
  46. // the given socket type and protocol values.
  47. //
  48. // The socket type must be one of the Type constants: Raw or Datagram.
  49. //
  50. // The Config specifies optional configuration for the Conn. A nil *Config
  51. // applies the default configuration.
  52. func Listen(ifi *net.Interface, socketType Type, protocol int, cfg *Config) (*Conn, error) {
  53. l, err := listen(ifi, socketType, protocol, cfg)
  54. if err != nil {
  55. return nil, opError(opListen, err, &Addr{HardwareAddr: ifi.HardwareAddr})
  56. }
  57. return l, nil
  58. }
  59. // TODO(mdlayher): we want to support FileConn for advanced use cases, but this
  60. // library would also need a big endian protocol value and an interface index.
  61. // For now we won't bother, but reconsider in the future.
  62. var (
  63. _ net.PacketConn = &Conn{}
  64. _ syscall.Conn = &Conn{}
  65. _ bpf.Setter = &Conn{}
  66. )
  67. // A Conn is an Linux packet sockets (AF_PACKET) implementation of a
  68. // net.PacketConn.
  69. type Conn struct {
  70. c *conn
  71. // Metadata about the local connection.
  72. addr *Addr
  73. ifIndex int
  74. protocol uint16
  75. }
  76. // Close closes the connection.
  77. func (c *Conn) Close() error {
  78. return c.opError(opClose, c.c.Close())
  79. }
  80. // LocalAddr returns the local network address. The Addr returned is shared by
  81. // all invocations of LocalAddr, so do not modify it.
  82. func (c *Conn) LocalAddr() net.Addr { return c.addr }
  83. // ReadFrom implements the net.PacketConn ReadFrom method.
  84. func (c *Conn) ReadFrom(b []byte) (int, net.Addr, error) {
  85. return c.readFrom(b)
  86. }
  87. // WriteTo implements the net.PacketConn WriteTo method.
  88. func (c *Conn) WriteTo(b []byte, addr net.Addr) (int, error) {
  89. return c.writeTo(b, addr)
  90. }
  91. // SetDeadline implements the net.PacketConn SetDeadline method.
  92. func (c *Conn) SetDeadline(t time.Time) error {
  93. return c.opError(opSet, c.c.SetDeadline(t))
  94. }
  95. // SetReadDeadline implements the net.PacketConn SetReadDeadline method.
  96. func (c *Conn) SetReadDeadline(t time.Time) error {
  97. return c.opError(opSet, c.c.SetReadDeadline(t))
  98. }
  99. // SetWriteDeadline implements the net.PacketConn SetWriteDeadline method.
  100. func (c *Conn) SetWriteDeadline(t time.Time) error {
  101. return c.opError(opSet, c.c.SetWriteDeadline(t))
  102. }
  103. // SetBPF attaches an assembled BPF program to the Conn.
  104. func (c *Conn) SetBPF(filter []bpf.RawInstruction) error {
  105. return c.opError(opSetsockopt, c.c.SetBPF(filter))
  106. }
  107. // SetPromiscuous enables or disables promiscuous mode on the Conn, allowing it
  108. // to receive traffic that is not addressed to the Conn's network interface.
  109. func (c *Conn) SetPromiscuous(enable bool) error {
  110. return c.setPromiscuous(enable)
  111. }
  112. // Stats contains statistics about a Conn reported by the Linux kernel.
  113. type Stats struct {
  114. // The total number of packets received.
  115. Packets uint32
  116. // The number of packets dropped.
  117. Drops uint32
  118. // The total number of times that a receive queue is frozen. May be zero if
  119. // the Linux kernel is not new enough to support TPACKET_V3 statistics.
  120. FreezeQueueCount uint32
  121. }
  122. // Stats retrieves statistics about the Conn from the Linux kernel.
  123. //
  124. // Note that calling Stats will reset the kernel's internal counters for this
  125. // Conn. If you want to maintain cumulative statistics by polling Stats over
  126. // time, you must do so in your calling code.
  127. func (c *Conn) Stats() (*Stats, error) { return c.stats() }
  128. // SyscallConn returns a raw network connection. This implements the
  129. // syscall.Conn interface.
  130. func (c *Conn) SyscallConn() (syscall.RawConn, error) {
  131. rc, err := c.c.SyscallConn()
  132. if err != nil {
  133. return nil, c.opError(opSyscallConn, err)
  134. }
  135. return &rawConn{
  136. rc: rc,
  137. addr: c.addr,
  138. }, nil
  139. }
  140. // opError is a convenience for the function opError that also passes the local
  141. // and remote addresses of the Conn.
  142. func (c *Conn) opError(op string, err error) error {
  143. return opError(op, err, c.addr)
  144. }
  145. // TODO(mdlayher): see if we can port smarter net.OpError logic into
  146. // socket.Conn's SyscallConn type to avoid the need for this wrapper.
  147. var _ syscall.RawConn = &rawConn{}
  148. // A rawConn is a syscall.RawConn that wraps an internal syscall.RawConn in order
  149. // to produce net.OpError error values.
  150. type rawConn struct {
  151. rc syscall.RawConn
  152. addr *Addr
  153. }
  154. // Control implements the syscall.RawConn Control method.
  155. func (rc *rawConn) Control(fn func(fd uintptr)) error {
  156. return rc.opError(opRawControl, rc.rc.Control(fn))
  157. }
  158. // Control implements the syscall.RawConn Read method.
  159. func (rc *rawConn) Read(fn func(fd uintptr) (done bool)) error {
  160. return rc.opError(opRawRead, rc.rc.Read(fn))
  161. }
  162. // Control implements the syscall.RawConn Write method.
  163. func (rc *rawConn) Write(fn func(fd uintptr) (done bool)) error {
  164. return rc.opError(opRawWrite, rc.rc.Write(fn))
  165. }
  166. // opError is a convenience for the function opError that also passes the
  167. // address of the rawConn.
  168. func (rc *rawConn) opError(op string, err error) error {
  169. return opError(op, err, rc.addr)
  170. }
  171. var _ net.Addr = &Addr{}
  172. // TODO(mdlayher): expose sll_hatype and sll_pkttype on receive Addr only.
  173. // An Addr is a physical-layer address.
  174. type Addr struct {
  175. HardwareAddr net.HardwareAddr
  176. }
  177. // Network returns the address's network name, "packet".
  178. func (a *Addr) Network() string { return network }
  179. // String returns the string representation of an Addr.
  180. func (a *Addr) String() string {
  181. return a.HardwareAddr.String()
  182. }
  183. // opError unpacks err if possible, producing a net.OpError with the input
  184. // parameters in order to implement net.PacketConn. As a convenience, opError
  185. // returns nil if the input error is nil.
  186. func opError(op string, err error, local net.Addr) error {
  187. if err == nil {
  188. return nil
  189. }
  190. // TODO(mdlayher): try to comply with net.PacketConn as best as we can; land
  191. // a nettest.TestPacketConn API upstream.
  192. return &net.OpError{
  193. Op: op,
  194. Net: network,
  195. Addr: local,
  196. Err: err,
  197. }
  198. }