server.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package coredhcp
  2. import (
  3. "errors"
  4. "log"
  5. "net"
  6. "github.com/coredhcp/coredhcp/config"
  7. "github.com/coredhcp/coredhcp/handler"
  8. "github.com/coredhcp/coredhcp/plugins"
  9. "github.com/insomniacslk/dhcp/dhcpv4"
  10. "github.com/insomniacslk/dhcp/dhcpv6"
  11. )
  12. // Server is a CoreDHCP server structure that holds information about
  13. // DHCPv6 and DHCPv4 servers, and their respective handlers.
  14. type Server struct {
  15. Handlers6 []handler.Handler6
  16. Handlers4 []handler.Handler4
  17. Config *config.Config
  18. Server6 *dhcpv6.Server
  19. Server4 *dhcpv4.Server
  20. errors chan error
  21. }
  22. // LoadPlugins reads a Viper configuration and loads the plugins
  23. // as specified in the `plugins` section, in order. For a plugin to
  24. // be available, it must have been previously registered with
  25. // plugins.RegisterPlugin. This is normally done at plugin import.
  26. func (s *Server) LoadPlugins(conf *config.Config) ([]*plugins.Plugin, error) {
  27. log.Print("Loading plugins...")
  28. loadedPlugins := make([]*plugins.Plugin, 0)
  29. if conf.Server4 != nil {
  30. return nil, errors.New("plugin loading for DHCPv4 not implemented yet")
  31. }
  32. // load v6 plugins
  33. if conf.Server6 == nil {
  34. return nil, errors.New("no configuration found for DHCPv6 server")
  35. }
  36. // now load the plugins. We need to call its setup function with
  37. // the arguments extracted above. The setup function is mapped in
  38. // plugins.RegisteredPlugins .
  39. for _, pluginConf := range conf.Server6.Plugins {
  40. if plugin, ok := plugins.RegisteredPlugins[pluginConf.Name]; ok {
  41. log.Printf("Loading plugin `%s`", pluginConf.Name)
  42. h6, err := plugin.Setup6(pluginConf.Args...)
  43. if err != nil {
  44. return nil, err
  45. }
  46. loadedPlugins = append(loadedPlugins, plugin)
  47. if h6 == nil {
  48. return nil, config.ConfigErrorFromString("no DHCPv6 handler for plugin %s", pluginConf.Name)
  49. }
  50. s.Handlers6 = append(s.Handlers6, h6)
  51. //s.Handlers4 = append(s.Handlers4, h4)
  52. } else {
  53. return nil, config.ConfigErrorFromString("unknown plugin `%s`", pluginConf.Name)
  54. }
  55. }
  56. return loadedPlugins, nil
  57. }
  58. // MainHandler6 runs for every received DHCPv6 packet. It will run every
  59. // registered handler in sequence, and reply with the resulting response.
  60. // It will not reply if the resulting response is `nil`.
  61. func (s *Server) MainHandler6(conn net.PacketConn, peer net.Addr, req dhcpv6.DHCPv6) {
  62. var (
  63. resp dhcpv6.DHCPv6
  64. stop bool
  65. )
  66. for _, handler := range s.Handlers6 {
  67. resp, stop = handler(req, resp)
  68. if stop {
  69. break
  70. }
  71. }
  72. if resp != nil {
  73. if _, err := conn.WriteTo(resp.ToBytes(), peer); err != nil {
  74. log.Printf("conn.Write to %v failed: %v", peer, err)
  75. }
  76. } else {
  77. log.Print("Dropping request because response is nil")
  78. }
  79. }
  80. // MainHandler4 is like MainHandler6, but for DHCPv4 packets.
  81. func (s *Server) MainHandler4(conn net.PacketConn, peer net.Addr, d *dhcpv4.DHCPv4) {
  82. log.Print(d.Summary())
  83. }
  84. // Start will start the server asynchronously. See `Wait` to wait until
  85. // the execution ends.
  86. func (s *Server) Start() error {
  87. _, err := s.LoadPlugins(s.Config)
  88. if err != nil {
  89. return err
  90. }
  91. // listen
  92. if s.Config.Server6 != nil {
  93. log.Printf("Starting DHCPv6 listener on %v", s.Config.Server6.Listener)
  94. s.Server6 = dhcpv6.NewServer(*s.Config.Server6.Listener, s.MainHandler6)
  95. go func() {
  96. s.errors <- s.Server6.ActivateAndServe()
  97. }()
  98. }
  99. if s.Config.Server4 != nil {
  100. log.Printf("Starting DHCPv4 listener on %v", s.Config.Server6.Listener)
  101. s.Server4 = dhcpv4.NewServer(*s.Config.Server4.Listener, s.MainHandler4)
  102. go func() {
  103. s.errors <- s.Server4.ActivateAndServe()
  104. }()
  105. }
  106. return nil
  107. }
  108. // Wait waits until the end of the execution of the server.
  109. func (s *Server) Wait() error {
  110. log.Print("Waiting")
  111. if s.Server6 != nil {
  112. s.Server6.Close()
  113. }
  114. if s.Server4 != nil {
  115. s.Server4.Close()
  116. }
  117. return <-s.errors
  118. }
  119. // NewServer creates a Server instance with the provided configuration.
  120. func NewServer(config *config.Config) *Server {
  121. return &Server{Config: config, errors: make(chan error, 1)}
  122. }