dhcpserver6.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. package hostdhcp
  15. import (
  16. "net"
  17. "time"
  18. "github.com/google/gopacket/layers"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. guestman "yunion.io/x/onecloud/pkg/hostman/guestman/types"
  22. "yunion.io/x/onecloud/pkg/util/dhcp"
  23. "yunion.io/x/onecloud/pkg/util/hashcache"
  24. "yunion.io/x/onecloud/pkg/util/icmp6"
  25. "yunion.io/x/onecloud/pkg/util/netutils2"
  26. )
  27. const (
  28. DEFAULT_DHCP6_SERVER_PORT = 547
  29. // DEFAULT_DHCP_CLIENT_PORT = 68
  30. DEFAULT_DHCP6_RELAY_PORT = 546
  31. )
  32. type SGuestDHCP6Server struct {
  33. server *dhcp.DHCP6Server
  34. relay *SDHCP6Relay
  35. conn *dhcp.Conn
  36. ifaceDev *netutils2.SNetInterface
  37. raExitCh chan struct{}
  38. raReqCh chan net.HardwareAddr
  39. raReqQueue map[string]*sRARequest
  40. gwMacCache *hashcache.Cache
  41. }
  42. func NewGuestDHCP6Server(iface string, port int, relay *SDHCPRelayUpstream) (*SGuestDHCP6Server, error) {
  43. var (
  44. err error
  45. guestdhcp = new(SGuestDHCP6Server)
  46. )
  47. dev := netutils2.NewNetInterface(iface)
  48. if dev.GetHardwareAddr() == nil {
  49. return nil, errors.Wrapf(errors.ErrInvalidStatus, "iface %s no mac", iface)
  50. }
  51. guestdhcp.ifaceDev = dev
  52. guestdhcp.server, guestdhcp.conn, err = dhcp.NewDHCP6Server2(iface, DEFAULT_DHCP6_SERVER_PORT)
  53. if err != nil {
  54. return nil, errors.Wrap(err, "dhcp.NewDHCP6Server2")
  55. }
  56. if relay != nil {
  57. guestdhcp.relay, err = NewDHCP6Relay(guestdhcp.conn, relay)
  58. if err != nil {
  59. return nil, errors.Wrap(err, "NewDHCP6Relay")
  60. }
  61. }
  62. guestdhcp.raExitCh = make(chan struct{})
  63. guestdhcp.raReqCh = make(chan net.HardwareAddr, 1024)
  64. guestdhcp.raReqQueue = make(map[string]*sRARequest)
  65. guestdhcp.gwMacCache = hashcache.NewCache(1024, 5*time.Minute)
  66. return guestdhcp, nil
  67. }
  68. func (s *SGuestDHCP6Server) Start(blocking bool) {
  69. log.Infof("SGuestDHCP6Server %s starting (blocking: %v) ...", s.ifaceDev.String(), blocking)
  70. serve := func() {
  71. defer s.stopRAServer()
  72. go s.startRAServer()
  73. err := s.server.ListenAndServe(s)
  74. if err != nil {
  75. log.Errorf("DHCP serve error: %s", err)
  76. }
  77. }
  78. if blocking {
  79. serve()
  80. } else {
  81. go serve()
  82. }
  83. }
  84. func (s *SGuestDHCP6Server) RelaySetup(addr string) error {
  85. if s.relay != nil {
  86. return s.relay.Setup(addr)
  87. }
  88. return nil
  89. }
  90. func (s *SGuestDHCP6Server) getConfig(cliMac net.HardwareAddr) *dhcp.ResponseConfig {
  91. if guestman.GuestDescGetter == nil {
  92. return nil
  93. }
  94. var (
  95. ip, port = "", ""
  96. isCandidate = false
  97. )
  98. guestDesc, guestNic := guestman.GuestDescGetter.GetGuestNicDesc(cliMac.String(), ip, port, s.ifaceDev.String(), isCandidate)
  99. if guestNic == nil {
  100. guestDesc, guestNic = guestman.GuestDescGetter.GetGuestNicDesc(cliMac.String(), ip, port, s.ifaceDev.String(), !isCandidate)
  101. }
  102. if guestNic != nil && !guestNic.Virtual && len(guestNic.Ip6) > 0 {
  103. return getGuestConfig(guestDesc, guestNic, s.ifaceDev.GetHardwareAddr())
  104. }
  105. return nil
  106. }
  107. func (s *SGuestDHCP6Server) ServeDHCP(pkt dhcp.Packet, cliMac net.HardwareAddr, addr *net.UDPAddr) (dhcp.Packet, []string, error) {
  108. pkg, err := s.serveDHCPInternal(pkt, cliMac, addr)
  109. return pkg, nil, err
  110. }
  111. func (s *SGuestDHCP6Server) OnRecvICMP6(pkt dhcp.Packet) error {
  112. msg, err := icmp6.DecodePacket(pkt)
  113. if err != nil {
  114. return errors.Wrap(err, "icmp6.DecodePacket")
  115. }
  116. // log.Infof("SGuestDHCP6Server recv ICMP6 message %s", msg.String())
  117. switch msg.ICMP6TypeCode().Type() {
  118. case layers.ICMPv6TypeRouterSolicitation:
  119. // Router Solicitation
  120. return s.handleRouterSolicitation(msg.(*icmp6.SRouterSolicitation))
  121. case layers.ICMPv6TypeRouterAdvertisement:
  122. // Router Advertisement
  123. return s.handleRouterAdvertisement(msg.(*icmp6.SRouterAdvertisement))
  124. case layers.ICMPv6TypeNeighborSolicitation:
  125. // Neighbor Solicitation
  126. return s.handleNeighborSolicitation(msg.(*icmp6.SNeighborSolicitation))
  127. case layers.ICMPv6TypeNeighborAdvertisement:
  128. // Neighbor Advertisement
  129. return s.handleNeighborAdvertisement(msg.(*icmp6.SNeighborAdvertisement))
  130. default:
  131. log.Errorf("SGuestDHCP6Server recv unknown ICMP6 message %s", msg.String())
  132. return errors.Wrapf(errors.ErrNotSupported, "unknown ICMP6 message %s", msg.String())
  133. }
  134. }
  135. func (s *SGuestDHCP6Server) serveDHCPInternal(pkt dhcp.Packet, cliMac net.HardwareAddr, addr *net.UDPAddr) (dhcp.Packet, error) {
  136. var conf = s.getConfig(cliMac)
  137. if conf != nil {
  138. log.Infof("Make DHCPv6 Reply %s TO %s %s", conf.ClientIP6, cliMac.String(), addr.String())
  139. // Guest request ip
  140. return dhcp.MakeDHCP6Reply(pkt, conf)
  141. } else if s.relay != nil && s.relay.server != nil {
  142. // Host agent as dhcp relay, relay to baremetal
  143. return s.relay.Relay(pkt, cliMac, addr)
  144. }
  145. return nil, nil
  146. }
  147. func (s *SGuestDHCP6Server) InitRAQueue() {
  148. macs := guestman.GuestDescGetter.GetAllGuestIPv6Macs(s.ifaceDev.String())
  149. for _, mac := range macs {
  150. hw, err := net.ParseMAC(mac)
  151. if err != nil {
  152. log.Errorf("ParseMAC %s: %v", mac, err)
  153. continue
  154. }
  155. s.requestRA(hw)
  156. }
  157. }