plugin.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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 example
  5. // This is an example plugin that inspects a packet and prints it out. The code
  6. // is commented in a way that should walk you through the implementation of your
  7. // own plugins.
  8. // Feedback is welcome!
  9. import (
  10. "github.com/coredhcp/coredhcp/handler"
  11. "github.com/coredhcp/coredhcp/logger"
  12. "github.com/coredhcp/coredhcp/plugins"
  13. "github.com/insomniacslk/dhcp/dhcpv4"
  14. "github.com/insomniacslk/dhcp/dhcpv6"
  15. )
  16. // We use a customizable logger, as part of the `logger` package. You can use
  17. // `logger.GetLogger()` to get a singleton instance of the logger. Then just use
  18. // it with the `logrus` interface (https://github.com/sirupsen/logrus). More
  19. // information in the docstring of the logger package.
  20. var log = logger.GetLogger("plugins/example")
  21. // Plugin wraps the information necessary to register a plugin.
  22. // In the main package, you need to export a `plugins.Plugin` object called
  23. // `Plugin`, so it can be registered into the plugin registry.
  24. // Just import your plugin, and fill the structure with plugin name and setup
  25. // functions:
  26. //
  27. // import (
  28. // "github.com/coredhcp/coredhcp/plugins"
  29. // "github.com/coredhcp/coredhcp/plugins/example"
  30. // )
  31. //
  32. // var Plugin = plugins.Plugin{
  33. // Name: "example",
  34. // Setup6: setup6,
  35. // Setup4: setup4,
  36. // }
  37. //
  38. // Name is simply the name used to register the plugin. It must be unique to
  39. // other registered plugins, or the operation will fail. In other words, don't
  40. // declare plugins with colliding names.
  41. //
  42. // Setup6 and Setup4 are the setup functions for DHCPv6 and DHCPv4 traffic
  43. // handlers. They conform to the `plugins.SetupFunc6` and `plugins.SetupFunc4`
  44. // interfaces, so they must return a `plugins.Handler6` and a `plugins.Handler4`
  45. // respectively.
  46. // A `nil` setup function means that that protocol won't be handled by this
  47. // plugin.
  48. //
  49. // Note that importing the plugin is not enough to use it: you have to
  50. // explicitly specify the intention to use it in the `config.yml` file, in the
  51. // plugins section. For example:
  52. //
  53. // server6:
  54. // listen: '[::]547'
  55. // - example:
  56. // - server_id: LL aa:bb:cc:dd:ee:ff
  57. // - file: "leases.txt"
  58. //
  59. var Plugin = plugins.Plugin{
  60. Name: "example",
  61. Setup6: setup6,
  62. Setup4: setup4,
  63. }
  64. // setup6 is the setup function to initialize the handler for DHCPv6
  65. // traffic. This function implements the `plugin.SetupFunc6` interface.
  66. // This function returns a `handler.Handler6` function, and an error if any.
  67. // In this example we do very little in the setup function, and just return the
  68. // `exampleHandler6` function. Such function will be called for every DHCPv6
  69. // packet that the server receives. Remember that a handler may not be called
  70. // for each packet, if the handler chain is interrupted before reaching it.
  71. func setup6(args ...string) (handler.Handler6, error) {
  72. log.Printf("loaded plugin for DHCPv6.")
  73. return exampleHandler6, nil
  74. }
  75. // setup4 behaves like setupExample6, but for DHCPv4 packets. It
  76. // implements the `plugin.SetupFunc4` interface.
  77. func setup4(args ...string) (handler.Handler4, error) {
  78. log.Printf("loaded plugin for DHCPv4.")
  79. return exampleHandler4, nil
  80. }
  81. // exampleHandler6 handles DHCPv6 packets for the example plugin. It implements
  82. // the `handler.Handler6` interface. The input arguments are the request packet
  83. // that the server received from a client, and the response packet that has been
  84. // computed so far. This function returns the response packet to be sent back to
  85. // the client, and a boolean.
  86. // The response can be either the same response packet received as input, a
  87. // modified response packet, or nil. If nil, the server will not reply to the
  88. // client, basically dropping the request.
  89. // The returned boolean indicates to the server whether the chain of plugins
  90. // should continue or not. If `true`, the server will stop at this plugin, and
  91. // respond to the client (or drop the response, if nil). If `false`, the server
  92. // will call the next plugin in the chan, using the returned response packet as
  93. // input for the next plugin.
  94. func exampleHandler6(req, resp dhcpv6.DHCPv6) (dhcpv6.DHCPv6, bool) {
  95. log.Printf("received DHCPv6 packet: %s", req.Summary())
  96. // return the unmodified response, and false. This means that the next
  97. // plugin in the chain will be called, and the unmodified response packet
  98. // will be used as its input.
  99. return resp, false
  100. }
  101. // exampleHandler4 behaves like exampleHandler6, but for DHCPv4 packets. It
  102. // implements the `handler.Handler4` interface.
  103. func exampleHandler4(req, resp *dhcpv4.DHCPv4) (*dhcpv4.DHCPv4, bool) {
  104. log.Printf("received DHCPv4 packet: %s", req.Summary())
  105. // return the unmodified response, and false. This means that the next
  106. // plugin in the chain will be called, and the unmodified response packet
  107. // will be used as its input.
  108. return resp, false
  109. }