main.go 4.3 KB

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