raw_linux.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // +build linux
  2. package raw
  3. import (
  4. "net"
  5. "os"
  6. "sync/atomic"
  7. "syscall"
  8. "time"
  9. "unsafe"
  10. "golang.org/x/net/bpf"
  11. "golang.org/x/sys/unix"
  12. )
  13. var (
  14. // Must implement net.PacketConn at compile-time.
  15. _ net.PacketConn = &packetConn{}
  16. )
  17. // packetConn is the Linux-specific implementation of net.PacketConn for this
  18. // package.
  19. type packetConn struct {
  20. ifi *net.Interface
  21. s socket
  22. pbe uint16
  23. // Should stats be accumulated instead of reset on each call?
  24. noCumulativeStats bool
  25. // Internal storage for cumulative stats.
  26. stats Stats
  27. }
  28. // socket is an interface which enables swapping out socket syscalls for
  29. // testing.
  30. type socket interface {
  31. Bind(unix.Sockaddr) error
  32. Close() error
  33. GetSockoptTpacketStats(level, name int) (*unix.TpacketStats, error)
  34. Recvfrom([]byte, int) (int, unix.Sockaddr, error)
  35. Sendto([]byte, int, unix.Sockaddr) error
  36. SetSockoptPacketMreq(level, name int, mreq *unix.PacketMreq) error
  37. SetSockoptSockFprog(level, name int, fprog *unix.SockFprog) error
  38. SetDeadline(time.Time) error
  39. SetReadDeadline(time.Time) error
  40. SetWriteDeadline(time.Time) error
  41. }
  42. // htons converts a short (uint16) from host-to-network byte order.
  43. // Thanks to mikioh for this neat trick:
  44. // https://github.com/mikioh/-stdyng/blob/master/afpacket.go
  45. func htons(i uint16) uint16 {
  46. return (i<<8)&0xff00 | i>>8
  47. }
  48. // listenPacket creates a net.PacketConn which can be used to send and receive
  49. // data at the device driver level.
  50. func listenPacket(ifi *net.Interface, proto uint16, cfg Config) (*packetConn, error) {
  51. filename := "eth-packet-socket"
  52. // Enabling overriding the socket type via config.
  53. typ := unix.SOCK_RAW
  54. if cfg.LinuxSockDGRAM {
  55. filename = "packet-socket"
  56. typ = unix.SOCK_DGRAM
  57. }
  58. // Open a packet socket using specified socket type. Do not specify
  59. // a protocol to avoid capturing packets which to not match cfg.Filter.
  60. // The later call to bind() will set up the correct protocol for us.
  61. sock, err := unix.Socket(unix.AF_PACKET, typ, 0)
  62. if err != nil {
  63. return nil, err
  64. }
  65. if err := unix.SetNonblock(sock, true); err != nil {
  66. return nil, err
  67. }
  68. // When using Go 1.12+, the SetNonblock call we just did puts the file
  69. // descriptor into non-blocking mode. In that case, os.NewFile
  70. // registers the file descriptor with the runtime poller, which is then
  71. // used for all subsequent operations.
  72. //
  73. // See also: https://golang.org/pkg/os/#NewFile
  74. f := os.NewFile(uintptr(sock), filename)
  75. sc, err := f.SyscallConn()
  76. if err != nil {
  77. return nil, err
  78. }
  79. // Wrap raw socket in socket interface.
  80. pc, err := newPacketConn(ifi, &sysSocket{f: f, rc: sc}, htons(proto), cfg.Filter)
  81. if err != nil {
  82. return nil, err
  83. }
  84. pc.noCumulativeStats = cfg.NoCumulativeStats
  85. return pc, nil
  86. }
  87. // newPacketConn creates a net.PacketConn using the specified network
  88. // interface, wrapped socket and big endian protocol number.
  89. //
  90. // It is the entry point for tests in this package.
  91. func newPacketConn(ifi *net.Interface, s socket, pbe uint16, filter []bpf.RawInstruction) (*packetConn, error) {
  92. pc := &packetConn{
  93. ifi: ifi,
  94. s: s,
  95. pbe: pbe,
  96. }
  97. if len(filter) > 0 {
  98. if err := pc.SetBPF(filter); err != nil {
  99. return nil, err
  100. }
  101. }
  102. // Bind the packet socket to the interface specified by ifi
  103. // packet(7):
  104. // Only the sll_protocol and the sll_ifindex address fields are used for
  105. // purposes of binding.
  106. // This overrides the protocol given to socket(AF_PACKET).
  107. err := s.Bind(&unix.SockaddrLinklayer{
  108. Protocol: pc.pbe,
  109. Ifindex: ifi.Index,
  110. })
  111. if err != nil {
  112. return nil, err
  113. }
  114. return pc, nil
  115. }
  116. // ReadFrom implements the net.PacketConn.ReadFrom method.
  117. func (p *packetConn) ReadFrom(b []byte) (int, net.Addr, error) {
  118. // Attempt to receive on socket
  119. n, addr, err := p.s.Recvfrom(b, 0)
  120. if err != nil {
  121. return n, nil, err
  122. }
  123. // Retrieve hardware address and other information from addr.
  124. sa, ok := addr.(*unix.SockaddrLinklayer)
  125. if !ok || sa.Halen < 6 {
  126. return n, nil, unix.EINVAL
  127. }
  128. // Use length specified to convert byte array into a hardware address slice.
  129. mac := make(net.HardwareAddr, sa.Halen)
  130. copy(mac, sa.Addr[:])
  131. // packet(7):
  132. // sll_hatype and sll_pkttype are set on received packets for your
  133. // information.
  134. // TODO(mdlayher): determine if similar fields exist and are useful on
  135. // non-Linux platforms
  136. return n, &Addr{
  137. HardwareAddr: mac,
  138. }, nil
  139. }
  140. // WriteTo implements the net.PacketConn.WriteTo method.
  141. func (p *packetConn) WriteTo(b []byte, addr net.Addr) (int, error) {
  142. // Ensure correct Addr type.
  143. a, ok := addr.(*Addr)
  144. if !ok || a.HardwareAddr == nil || len(a.HardwareAddr) < 6 {
  145. return 0, unix.EINVAL
  146. }
  147. // Convert hardware address back to byte array form.
  148. var baddr [8]byte
  149. copy(baddr[:], a.HardwareAddr)
  150. // Send message on socket to the specified hardware address from addr
  151. // packet(7):
  152. // When you send packets it is enough to specify sll_family, sll_addr,
  153. // sll_halen, sll_ifindex, and sll_protocol. The other fields should
  154. // be 0.
  155. // In this case, sll_family is taken care of automatically by unix.
  156. err := p.s.Sendto(b, 0, &unix.SockaddrLinklayer{
  157. Ifindex: p.ifi.Index,
  158. Halen: uint8(len(a.HardwareAddr)),
  159. Addr: baddr,
  160. Protocol: p.pbe,
  161. })
  162. return len(b), err
  163. }
  164. // Close closes the connection.
  165. func (p *packetConn) Close() error {
  166. return p.s.Close()
  167. }
  168. // LocalAddr returns the local network address.
  169. func (p *packetConn) LocalAddr() net.Addr {
  170. return &Addr{
  171. HardwareAddr: p.ifi.HardwareAddr,
  172. }
  173. }
  174. // SetDeadline implements the net.PacketConn.SetDeadline method.
  175. func (p *packetConn) SetDeadline(t time.Time) error {
  176. return p.s.SetDeadline(t)
  177. }
  178. // SetReadDeadline implements the net.PacketConn.SetReadDeadline method.
  179. func (p *packetConn) SetReadDeadline(t time.Time) error {
  180. return p.s.SetReadDeadline(t)
  181. }
  182. // SetWriteDeadline implements the net.PacketConn.SetWriteDeadline method.
  183. func (p *packetConn) SetWriteDeadline(t time.Time) error {
  184. return p.s.SetWriteDeadline(t)
  185. }
  186. // SetBPF attaches an assembled BPF program to a raw net.PacketConn.
  187. func (p *packetConn) SetBPF(filter []bpf.RawInstruction) error {
  188. prog := unix.SockFprog{
  189. Len: uint16(len(filter)),
  190. Filter: (*unix.SockFilter)(unsafe.Pointer(&filter[0])),
  191. }
  192. err := p.s.SetSockoptSockFprog(
  193. unix.SOL_SOCKET,
  194. unix.SO_ATTACH_FILTER,
  195. &prog,
  196. )
  197. if err != nil {
  198. return os.NewSyscallError("setsockopt", err)
  199. }
  200. return nil
  201. }
  202. // SetPromiscuous enables or disables promiscuous mode on the interface, allowing it
  203. // to receive traffic that is not addressed to the interface.
  204. func (p *packetConn) SetPromiscuous(b bool) error {
  205. mreq := unix.PacketMreq{
  206. Ifindex: int32(p.ifi.Index),
  207. Type: unix.PACKET_MR_PROMISC,
  208. }
  209. membership := unix.PACKET_ADD_MEMBERSHIP
  210. if !b {
  211. membership = unix.PACKET_DROP_MEMBERSHIP
  212. }
  213. return p.s.SetSockoptPacketMreq(unix.SOL_PACKET, membership, &mreq)
  214. }
  215. // Stats retrieves statistics from the Conn.
  216. func (p *packetConn) Stats() (*Stats, error) {
  217. stats, err := p.s.GetSockoptTpacketStats(unix.SOL_PACKET, unix.PACKET_STATISTICS)
  218. if err != nil {
  219. return nil, err
  220. }
  221. return p.handleStats(stats), nil
  222. }
  223. // handleStats handles creation of Stats structures from raw packet socket stats.
  224. func (p *packetConn) handleStats(s *unix.TpacketStats) *Stats {
  225. // Does the caller want instantaneous stats as provided by Linux? If so,
  226. // return the structure directly.
  227. if p.noCumulativeStats {
  228. return &Stats{
  229. Packets: uint64(s.Packets),
  230. Drops: uint64(s.Drops),
  231. }
  232. }
  233. // The caller wants cumulative stats. Add stats with the internal stats
  234. // structure and return a copy of the resulting stats.
  235. packets := atomic.AddUint64(&p.stats.Packets, uint64(s.Packets))
  236. drops := atomic.AddUint64(&p.stats.Drops, uint64(s.Drops))
  237. return &Stats{
  238. Packets: packets,
  239. Drops: drops,
  240. }
  241. }
  242. // sysSocket is the default socket implementation. It makes use of
  243. // Linux-specific system calls to handle raw socket functionality.
  244. type sysSocket struct {
  245. f *os.File
  246. rc syscall.RawConn
  247. }
  248. func (s *sysSocket) SetDeadline(t time.Time) error {
  249. return s.f.SetDeadline(t)
  250. }
  251. func (s *sysSocket) SetReadDeadline(t time.Time) error {
  252. return s.f.SetReadDeadline(t)
  253. }
  254. func (s *sysSocket) SetWriteDeadline(t time.Time) error {
  255. return s.f.SetWriteDeadline(t)
  256. }
  257. func (s *sysSocket) Bind(sa unix.Sockaddr) error {
  258. var err error
  259. cerr := s.rc.Control(func(fd uintptr) {
  260. err = unix.Bind(int(fd), sa)
  261. })
  262. if err != nil {
  263. return err
  264. }
  265. return cerr
  266. }
  267. func (s *sysSocket) Close() error {
  268. return s.f.Close()
  269. }
  270. func (s *sysSocket) GetSockoptTpacketStats(level, name int) (*unix.TpacketStats, error) {
  271. var stats *unix.TpacketStats
  272. var err error
  273. cerr := s.rc.Control(func(fd uintptr) {
  274. s, errno := unix.GetsockoptTpacketStats(int(fd), level, name)
  275. stats = s
  276. if errno != nil {
  277. err = os.NewSyscallError("getsockopt", errno)
  278. }
  279. })
  280. if err != nil {
  281. return stats, err
  282. }
  283. return stats, cerr
  284. }
  285. func (s *sysSocket) Recvfrom(p []byte, flags int) (n int, addr unix.Sockaddr, err error) {
  286. cerr := s.rc.Read(func(fd uintptr) bool {
  287. n, addr, err = unix.Recvfrom(int(fd), p, flags)
  288. // When the socket is in non-blocking mode, we might see EAGAIN
  289. // and end up here. In that case, return false to let the
  290. // poller wait for readiness. See the source code for
  291. // internal/poll.FD.RawRead for more details.
  292. //
  293. // If the socket is in blocking mode, EAGAIN should never occur.
  294. return err != unix.EAGAIN
  295. })
  296. if err != nil {
  297. return n, addr, err
  298. }
  299. return n, addr, cerr
  300. }
  301. func (s *sysSocket) Sendto(p []byte, flags int, to unix.Sockaddr) error {
  302. var err error
  303. cerr := s.rc.Write(func(fd uintptr) bool {
  304. err = unix.Sendto(int(fd), p, flags, to)
  305. // See comment in Recvfrom.
  306. return err != unix.EAGAIN
  307. })
  308. if err != nil {
  309. return err
  310. }
  311. return cerr
  312. }
  313. func (s *sysSocket) SetSockoptSockFprog(level, name int, fprog *unix.SockFprog) error {
  314. var err error
  315. cerr := s.rc.Control(func(fd uintptr) {
  316. errno := unix.SetsockoptSockFprog(int(fd), level, name, fprog)
  317. if errno != nil {
  318. err = os.NewSyscallError("setsockopt", errno)
  319. }
  320. })
  321. if err != nil {
  322. return err
  323. }
  324. return cerr
  325. }
  326. func (s *sysSocket) SetSockoptPacketMreq(level, name int, mreq *unix.PacketMreq) error {
  327. var err error
  328. cerr := s.rc.Control(func(fd uintptr) {
  329. errno := unix.SetsockoptPacketMreq(int(fd), level, name, mreq)
  330. if errno != nil {
  331. err = os.NewSyscallError("setsockopt", errno)
  332. }
  333. })
  334. if err != nil {
  335. return err
  336. }
  337. return cerr
  338. }