plugin.go 4.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package example
  2. // This is an example plugin that inspects a packet and prints it out. The code
  3. // is commented in a way that should walk you through the implementation of your
  4. // own plugins.
  5. // Feedback is welcome!
  6. import (
  7. "github.com/coredhcp/coredhcp/handler"
  8. "github.com/coredhcp/coredhcp/logger"
  9. "github.com/coredhcp/coredhcp/plugins"
  10. "github.com/insomniacslk/dhcp/dhcpv4"
  11. "github.com/insomniacslk/dhcp/dhcpv6"
  12. )
  13. // We use a customizable logger, as part of the `logger` package. You can use
  14. // `logger.GetLogger()` to get a singleton instance of the logger. Then just use
  15. // it with the `logrus` interface (https://github.com/sirupsen/logrus). More
  16. // information in the docstring of the logger package.
  17. var log = logger.GetLogger()
  18. // In the main package, you need to register your plugin at import time. To do
  19. // this, just do a blank import of this package, e.g.
  20. // import (
  21. // _ "github.com/coredhcp/coredhcp/plugins/example"
  22. // )
  23. //
  24. // This guarantees that `init` will be called at import time, and your plugin
  25. // is correctly registered.
  26. //
  27. // The `init` function then should call `plugins.RegisterPlugin`, specifying the
  28. // plugin name, the setup function for DHCPv6 packets, and the setup function
  29. // for DHCPv4 packets. The setup functions must implement the
  30. // `plugin.SetupFunc6` and `plugin.Setup4` interfaces.
  31. // A `nil` setup function means that that protocol won't be handled by this
  32. // plugin.
  33. //
  34. // Note that importing the plugin is not enough: you have to explicitly specify
  35. // its use in the `config.yml` file, in the plugins section. For example:
  36. //
  37. // server6:
  38. // listen: '[::]547'
  39. // - example:
  40. // - server_id: LL aa:bb:cc:dd:ee:ff
  41. // - file: "leases.txt"
  42. //
  43. func init() {
  44. plugins.RegisterPlugin("example", setupExample6, setupExample4)
  45. }
  46. // setupExample6 is the setup function to initialize the handler for DHCPv6
  47. // traffic. This function implements the `plugin.SetupFunc6` interface.
  48. // This function returns a `handler.Handler6` function, and an error if any.
  49. // In this example we do very little in the setup function, and just return the
  50. // `exampleHandler6` function. Such function will be called for every DHCPv6
  51. // packet that the server receives. Remember that a handler may not be called
  52. // for each packet, if the handler chain is interrupted before reaching it.
  53. func setupExample6(args ...string) (handler.Handler6, error) {
  54. log.Printf("plugins/example: loaded plugin for DHCPv6.")
  55. return exampleHandler6, nil
  56. }
  57. // setupExample4 behaves like setupExample6, but for DHCPv4 packets. It
  58. // implements the `plugin.SetupFunc4` interface.
  59. func setupExample4(args ...string) (handler.Handler4, error) {
  60. log.Printf("plugins/example: loaded plugin for DHCPv4.")
  61. return exampleHandler4, nil
  62. }
  63. // exampleHandler6 handles DHCPv6 packets for the example plugin. It implements
  64. // the `handler.Handler6` interface. The input arguments are the request packet
  65. // that the server received from a client, and the response packet that has been
  66. // computed so far. This function returns the response packet to be sent back to
  67. // the client, and a boolean.
  68. // The response can be either the same response packet received as input, a
  69. // modified response packet, or nil. If nil, the server will not reply to the
  70. // client, basically dropping the request.
  71. // The returned boolean indicates to the server whether the chain of plugins
  72. // should continue or not. If `true`, the server will stop at this plugin, and
  73. // respond to the client (or drop the response, if nil). If `false`, the server
  74. // will call the next plugin in the chan, using the returned response packet as
  75. // input for the next plugin.
  76. func exampleHandler6(req, resp dhcpv6.DHCPv6) (dhcpv6.DHCPv6, bool) {
  77. log.Printf("plugins/example: received DHCPv6 packet: %s", req.Summary())
  78. // return the unmodified response, and false. This means that the next
  79. // plugin in the chain will be called, and the unmodified response packet
  80. // will be used as its input.
  81. return resp, false
  82. }
  83. // exampleHandler4 behaves like exampleHandler6, but for DHCPv4 packets. It
  84. // implements the `handler.Handler4` interface.
  85. func exampleHandler4(req, resp *dhcpv4.DHCPv4) (*dhcpv4.DHCPv4, bool) {
  86. // TODO check the MAC address in the request
  87. // if it is present in StaticRecords, forge a response
  88. // and stop processing.
  89. return resp, true
  90. }