conn_linux.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Copyright 2019 Yunion
  15. // Copyright 2016 Google Inc.
  16. //
  17. // Licensed under the Apache License, Version 2.0 (the "License");
  18. // you may not use this file except in compliance with the License.
  19. // You may obtain a copy of the License at
  20. //
  21. // http://www.apache.org/licenses/LICENSE-2.0
  22. //
  23. // Unless required by applicable law or agreed to in writing, software
  24. // distributed under the License is distributed on an "AS IS" BASIS,
  25. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  26. // See the License for the specific language governing permissions and
  27. // limitations under the License.
  28. //go:build linux
  29. // +build linux
  30. package dhcp
  31. import (
  32. "net"
  33. "time"
  34. "github.com/google/gopacket"
  35. "github.com/google/gopacket/layers"
  36. "github.com/mdlayher/packet"
  37. "golang.org/x/net/bpf"
  38. "golang.org/x/sys/unix"
  39. "yunion.io/x/log"
  40. "yunion.io/x/pkg/errors"
  41. )
  42. type rawSocketConn struct {
  43. conn *packet.Conn
  44. iface *net.Interface
  45. ip net.IP
  46. serverPort uint16
  47. }
  48. func newRawSocketConn(iface string, filter []bpf.RawInstruction, serverPort uint16) (conn, error) {
  49. ifi, err := net.InterfaceByName(iface)
  50. if err != nil {
  51. return nil, errors.Wrap(err, "interface by name")
  52. }
  53. ip, err := interfaceToIPv4Addr(ifi)
  54. if err != nil {
  55. return nil, errors.Wrap(err, "interfaceToIPv4Addr")
  56. }
  57. // unix.ETH_P_ALL
  58. conn, err := packet.Listen(ifi, packet.Raw, unix.ETH_P_IP, &packet.Config{
  59. Filter: filter,
  60. })
  61. if err != nil {
  62. return nil, errors.Wrap(err, "packet.Listen")
  63. }
  64. log.Debugf("newRawSocketConn on %s %s", ifi.Name, ip)
  65. return &rawSocketConn{
  66. conn: conn,
  67. iface: ifi,
  68. ip: ip,
  69. serverPort: serverPort,
  70. }, nil
  71. }
  72. func (s *rawSocketConn) Close() error {
  73. return s.conn.Close()
  74. }
  75. func (s *rawSocketConn) Recv(b []byte) ([]byte, *net.UDPAddr, net.HardwareAddr, error) {
  76. // read packet
  77. n, addr, err := s.conn.ReadFrom(b)
  78. if err != nil {
  79. return nil, nil, nil, errors.Wrap(err, "Read from errror")
  80. }
  81. b = b[:n]
  82. srcMac, err := net.ParseMAC(addr.String())
  83. if err != nil {
  84. return nil, nil, nil, errors.Wrap(err, "Parse mac error")
  85. }
  86. p := gopacket.NewPacket(b, layers.LayerTypeEthernet, gopacket.Default)
  87. if p.ErrorLayer() != nil {
  88. return nil, nil, nil, errors.Wrap(p.ErrorLayer().Error(), "Failed to decode packet")
  89. }
  90. var srcIp net.IP
  91. {
  92. ipLayer := p.Layer(layers.LayerTypeIPv4)
  93. if ipLayer != nil {
  94. // ipv4
  95. ip4 := ipLayer.(*layers.IPv4)
  96. srcIp = ip4.SrcIP
  97. } else {
  98. return nil, nil, nil, errors.Wrap(p.ErrorLayer().Error(), "Expect IP packet")
  99. }
  100. }
  101. var srcPort uint16
  102. udpLayer := p.Layer(layers.LayerTypeUDP)
  103. if udpLayer != nil {
  104. udpInfo := udpLayer.(*layers.UDP)
  105. srcPort = uint16(udpInfo.SrcPort)
  106. } else {
  107. return nil, nil, nil, errors.Wrap(p.ErrorLayer().Error(), "Expect UDP packet")
  108. }
  109. dhcpLayer := p.Layer(layers.LayerTypeDHCPv4)
  110. if dhcpLayer != nil {
  111. // dhcpv4
  112. dhcp4 := dhcpLayer.(*layers.DHCPv4)
  113. sbf := gopacket.NewSerializeBuffer()
  114. if err := dhcp4.SerializeTo(sbf, gopacket.SerializeOptions{}); err != nil {
  115. return nil, nil, nil, errors.Wrap(err, "Serialize dhcp packet error")
  116. }
  117. return sbf.Bytes(), &net.UDPAddr{IP: srcIp, Port: int(srcPort)}, srcMac, nil
  118. } else {
  119. return nil, nil, nil, errors.Wrap(p.ErrorLayer().Error(), "Expect DHCP packet")
  120. }
  121. }
  122. func (s *rawSocketConn) Send(b []byte, addr *net.UDPAddr, destMac net.HardwareAddr) error {
  123. var dhcp = new(layers.DHCPv4)
  124. if err := dhcp.DecodeFromBytes(b, gopacket.NilDecodeFeedback); err != nil {
  125. return errors.Wrap(err, "Decode dhcp bytes error")
  126. }
  127. var eth = &layers.Ethernet{
  128. EthernetType: layers.EthernetTypeIPv4,
  129. SrcMAC: s.iface.HardwareAddr,
  130. DstMAC: destMac,
  131. }
  132. var ip = &layers.IPv4{
  133. Version: 4,
  134. TTL: 64,
  135. SrcIP: s.ip,
  136. DstIP: addr.IP,
  137. Protocol: layers.IPProtocolUDP,
  138. }
  139. var (
  140. srcPort = layers.UDPPort(s.serverPort)
  141. dstPort = layers.UDPPort(addr.Port)
  142. )
  143. var udp = &layers.UDP{
  144. SrcPort: srcPort,
  145. DstPort: dstPort,
  146. }
  147. udp.SetNetworkLayerForChecksum(ip)
  148. var (
  149. buf = gopacket.NewSerializeBuffer()
  150. opts = gopacket.SerializeOptions{ComputeChecksums: true, FixLengths: true}
  151. )
  152. if err := gopacket.SerializeLayers(buf, opts, eth, ip, udp, dhcp); err != nil {
  153. return errors.Wrap(err, "SerializeLayers error")
  154. }
  155. // s.conn.SetWriteDeadline(time.Now().Add(DefaultWriteTimeout)) // 2 second
  156. if _, err := s.conn.WriteTo(buf.Bytes(), &packet.Addr{HardwareAddr: destMac}); err != nil {
  157. return errors.Wrap(err, "Send dhcp packet error")
  158. }
  159. return nil
  160. }
  161. func (s *rawSocketConn) SetReadDeadline(t time.Time) error {
  162. return s.conn.SetReadDeadline(t)
  163. }
  164. func (s *rawSocketConn) SetWriteDeadline(t time.Time) error {
  165. return s.conn.SetWriteDeadline(t)
  166. }