coredhcp.go 3.9 KB

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