serve.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright 2018-present the CoreDHCP Authors. All rights reserved
  2. // This source code is licensed under the MIT license found in the
  3. // LICENSE file in the root directory of this source tree.
  4. package server
  5. import (
  6. "fmt"
  7. "io"
  8. "net"
  9. "golang.org/x/net/ipv4"
  10. "golang.org/x/net/ipv6"
  11. "github.com/coredhcp/coredhcp/config"
  12. "github.com/coredhcp/coredhcp/handler"
  13. "github.com/coredhcp/coredhcp/logger"
  14. "github.com/coredhcp/coredhcp/plugins"
  15. "github.com/insomniacslk/dhcp/dhcpv4/server4"
  16. "github.com/insomniacslk/dhcp/dhcpv6/server6"
  17. )
  18. var log = logger.GetLogger("server")
  19. type listener6 struct {
  20. *ipv6.PacketConn
  21. net.Interface
  22. handlers []handler.Handler6
  23. }
  24. type listener4 struct {
  25. *ipv4.PacketConn
  26. net.Interface
  27. handlers []handler.Handler4
  28. }
  29. type listener interface {
  30. io.Closer
  31. }
  32. // Servers contains state for a running server (with possibly multiple interfaces/listeners)
  33. type Servers struct {
  34. listeners []listener
  35. errors chan error
  36. }
  37. func listen4(a *net.UDPAddr) (*listener4, error) {
  38. var err error
  39. l4 := listener4{}
  40. udpConn, err := server4.NewIPv4UDPConn(a.Zone, a)
  41. if err != nil {
  42. return nil, err
  43. }
  44. l4.PacketConn = ipv4.NewPacketConn(udpConn)
  45. var ifi *net.Interface
  46. if a.Zone != "" {
  47. ifi, err = net.InterfaceByName(a.Zone)
  48. if err != nil {
  49. return nil, fmt.Errorf("DHCPv4: Listen could not find interface %s: %v", a.Zone, err)
  50. }
  51. l4.Interface = *ifi
  52. } else {
  53. // When not bound to an interface, we need the information in each
  54. // packet to know which interface it came on
  55. err = l4.SetControlMessage(ipv4.FlagInterface, true)
  56. if err != nil {
  57. return nil, err
  58. }
  59. }
  60. if a.IP.IsMulticast() {
  61. err = l4.JoinGroup(ifi, a)
  62. if err != nil {
  63. return nil, err
  64. }
  65. }
  66. return &l4, nil
  67. }
  68. func listen6(a *net.UDPAddr) (*listener6, error) {
  69. l6 := listener6{}
  70. udpconn, err := server6.NewIPv6UDPConn(a.Zone, a)
  71. if err != nil {
  72. return nil, err
  73. }
  74. l6.PacketConn = ipv6.NewPacketConn(udpconn)
  75. var ifi *net.Interface
  76. if a.Zone != "" {
  77. ifi, err = net.InterfaceByName(a.Zone)
  78. if err != nil {
  79. return nil, fmt.Errorf("DHCPv4: Listen could not find interface %s: %v", a.Zone, err)
  80. }
  81. l6.Interface = *ifi
  82. } else {
  83. // When not bound to an interface, we need the information in each
  84. // packet to know which interface it came on
  85. err = l6.SetControlMessage(ipv6.FlagInterface, true)
  86. if err != nil {
  87. return nil, err
  88. }
  89. }
  90. if a.IP.IsMulticast() {
  91. err = l6.JoinGroup(ifi, a)
  92. if err != nil {
  93. return nil, err
  94. }
  95. }
  96. return &l6, nil
  97. }
  98. // Start will start the server asynchronously. See `Wait` to wait until
  99. // the execution ends.
  100. func Start(config *config.Config) (*Servers, error) {
  101. handlers4, handlers6, err := plugins.LoadPlugins(config)
  102. if err != nil {
  103. return nil, err
  104. }
  105. srv := Servers{
  106. errors: make(chan error),
  107. }
  108. // listen
  109. if config.Server6 != nil {
  110. log.Println("Starting DHCPv6 server")
  111. for _, addr := range config.Server6.Addresses {
  112. var l6 *listener6
  113. l6, err = listen6(addr)
  114. if err != nil {
  115. goto cleanup
  116. }
  117. l6.handlers = handlers6
  118. srv.listeners = append(srv.listeners, l6)
  119. go func() {
  120. srv.errors <- l6.Serve()
  121. }()
  122. }
  123. }
  124. if config.Server4 != nil {
  125. log.Println("Starting DHCPv4 server")
  126. for _, addr := range config.Server4.Addresses {
  127. var l4 *listener4
  128. l4, err = listen4(addr)
  129. if err != nil {
  130. goto cleanup
  131. }
  132. l4.handlers = handlers4
  133. srv.listeners = append(srv.listeners, l4)
  134. go func() {
  135. srv.errors <- l4.Serve()
  136. }()
  137. }
  138. }
  139. return &srv, nil
  140. cleanup:
  141. srv.Close()
  142. return nil, err
  143. }
  144. // Wait waits until the end of the execution of the server.
  145. func (s *Servers) Wait() error {
  146. log.Debug("Waiting")
  147. err := <-s.errors
  148. s.Close()
  149. return err
  150. }
  151. // Close closes all listening connections
  152. func (s *Servers) Close() {
  153. for _, srv := range s.listeners {
  154. if srv != nil {
  155. srv.Close()
  156. }
  157. }
  158. }