gdnsd-plugin-api man page on Alpinelinux

Man page or keyword search:  
man Server   18016 pages
apropos Keyword Search (all sections)
Output format
Alpinelinux logo
[printable version]

gdnsd-plugin-api(3)		     gdnsd		   gdnsd-plugin-api(3)

NAME
       gdnsd-plugin-api - How to write gdnsd plugin code

SYNOPSIS
	 Mandatory preamble macro+header your source must include at the top:
	   #define GDNSD_PLUGIN_NAME foo
	   #include <gdnsd/plugin.h>

	 Callback hooks you may implement (all are optional, and executed in this order):
	   -- startup/config stuff:
	   # only 'checkconf', 'start', 'restart', 'condrestart' invoke plugin callbacks at all
	   mon_list_t* plugin_foo_load_config(const vscf_data_t* pc)
	   void plugin_foo_add_svctype(const char* name, const vscf_data_t* svc_cfg, const unsigned interval, const unsigned timeout)
	   void plugin_foo_full_config(unsigned num_threads)
	   void plugin_foo_add_monitor(const char* svc_name, mon_smgr_t* smgr)
	   # only 'start', 'restart', and 'condrestart' continue past this point
	   void plugin_foo_post_daemonize(void)
	   void plugin_foo_pre_privdrop(void)
	   void plugin_foo_init_monitors(struct ev_loop* mon_loop)
	   void plugin_foo_start_monitors(struct ev_loop* mon_loop)
	   void plugin_foo_pre_run(struct ev_loop* loop)
	   void plugin_foo_iothread_init(unsigned threadnum)

	   -- runtime stuff (called from iothread context, anytime after iothread_init())
	   bool plugin_foo_resolve_dynaddr(unsigned threadnum, unsigned resnum, const client_info_t* cinfo, dynaddr_result_t* result)
	   void plugin_foo_resolve_dyncname(unsigned threadnum, unsigned resnum, const uint8_t* origin, const client_info_t* cinfo, dyncname_result_t* result)

	   -- runtime stuff (called from main or zonefile thread, anytime after full_config())
	   --	(you won't get parallel calls to these, and in general they should be readonly
	   --	 operations anyways)
	   int plugin_foo_map_resource_dyna(const char* resname)
	   int plugin_foo_map_resource_dync(const char* resname, const uint8_t* origin)

	   -- cleanup stuff:
	   void plugin_foo_exit(void)

WARNING
       Please note that in general, gdnsd's plugin API is poorly documented
       and unstable.  It often goes through fairly large and abrupt changes
       during development cycles, although it tends to be stable for a given
       stable release series.  Write code against it at your own peril (or at
       least, let me know so I can give you some warning on upcoming changes
       and/or solicit your feedback!).

OVERVIEW
       This file documents version 12 of the gdnsd plugin API.

       gdnsd's plugin API offers the ability to write plugins that can do
       either (or both) of two roles:

       Dynamically generate virtual "A", "AAAA", and "CNAME" records according
       to whatever logic the plugin author wishes.  The plugin can make use of
       gdnsd's monitoring services for being failover-aware, and the actual
       zonefile records that trigger these lookups are "DYNA" for addresses
       and "DYNC" for CNAMEs.

       Provide custom protocols and implementations for the back-end of the
       monitoring code for use by any plugin.  In this case you mostly just
       implement the protocl check code against a standard libev event loop
       and use a helper function to report the results of each status check,
       and the core takes care of the rest.

       All callbacks can be implemented by all plugins; it is possible to
       create a combined plugin that performs both roles.  There is no clear
       distinction between plugin "types" internally.

USER-LEVEL CONFIGURATION FOR DYNA/DYNC
       If you haven't read the documentation for the overall configuration
       file (gdnsd.config) and the zonefiles (gdnsd.zonefile), you might want
       to read those before continuing.

       From a user's perspective, there are two parts to configuring plugins.
       The first is configuring the plugin via the gdnsd config file.  The
       config file has an optional "plugins" hash.  The keys of this hash are
       the names of plugins to load, and the values (which must be hashes) are
       the configuration data for the plugin itself.  e.g., to load two
       plugins named "foo" and "bar", the plugins hash might look like this:

	 plugins => {
	   foo => {
	      opts => {
		 something = "quux\000<-an_embedded_null!",
		 somethingelse = { Z => z },
	      },
	      xyz = [x, y, z]
	   }
	   bar => { x => y }
	 }

       Note that a short-form plugin name (e.g. "foo") maps to a shared
       library named plugin_foo.so.  Plugins will be loaded from the directory
       $PREFIX/lib/gdnsd/ by default, but this path can be overridden in the
       "options" section of the gdnsd configuration.

       The basic syntactic structure of your plugin's config hash follows the
       same rules as the gdnsd config as a whole.  This is the "vscf" syntax,
       which allows the user to specify nested data in the form of hashes,
       arrays, and simple values.  It's entirely up to the plugin author how
       the contents of the hash should be interpreted, and to document the
       plugin's config hash for users.

       The second part of the configuration is inserting "DYNA" and/or "DYNC"
       resource records into zonefiles.	 "DYNA" RRs use a plugin to
       dynamically generate "A" and/or "AAAA" RRs, while "DYNC" RRs use a
       plugin to dynamically generate "CNAME" RRs.

	 www	  300 DYNA foo!prod_web
	 www.test 300 DYNA foo!test_web
	 web	  300 DYNC bar!test_web_cname

       The initial parts (the left-hand domainname, TTL, and RR-type) follow
       the usual zonefile norms, other than the fact that "DYNA" is not a real
       resource record type in the DNS protocol.  The rdata section (e.g.
       "foo!prod_web") contains two parts separated by an "!": A plugin name,
       and a resource name.

       The meaning of the resource name is entirely up to the plugin.
       Typically it will reference a configuration key from the plugin's
       configuration hash as a mapping to a specific set of parameters for the
       plugin, but other uses of this field are possible.

       Plugins may implement DYNA, DYNC, or both.  The plugin signals which
       RRs it supports by which runtime resolve callbacks it implements.
       "plugin_foo_resolve_dynaddr" implies DYNA support, and
       "plugin_foo_resolv_dyncname" implies DYNC support.

USER-LEVEL CONFIGURATION FOR MONITORING
       DYNA/DYNC plugin code can optionally take advantage of monitoring
       services, e.g. to not return "dead" addresses from a pool.  Monitoring
       is configured as a set of "service_types", each representing a
       protocol, protocol-specific parameters, and some generic parameters
       related to timing and anti-flap.	 e.g.:

	   service_types = {
	       prod_web = {
		   plugin = http_status
		   # plugin-specific parameters
		   vhost = www.example.com
		   url_path = /checkme
		   ok_codes = [ 200, 201 ]
		   # generic parameters
		   up_thresh = 24
		   down_thresh = 16
		   ok_thresh = 8
		   interval = 8
		   timeout = 4
	       }
	   }

       A service type is meant to be re-used to monitor the same service at
       several different addresses.

       One of the service type parameters is "plugin", naming a custom
       monitoring plugin to load.  If this plugin was not listed directly in
       the "plugins" hash to give it global-level configuration, it will be
       loaded with no configuration at all ("_load_config(NULL)").
       "http_status" is the default plugin, which does simplistic HTTP/1.0
       requests and checks only the HTTP status code returned by the server.

PLUGIN SOURCE ORGANIZATION
       There must be one primary plugin source file which implements the
       callback hooks, and this file must include the following before any
       other code:

	   #define GDNSD_PLUGIN_NAME foo
	   #include <gdnsd/plugin.h>

       If you wish to split your implementation over multiple files, you can
       access the relevant API interfaces via the other "gdnsd-*.h" headers
       directly.  However all of the actual callback hooks must be implemented
       in the primary source file, and your other source files should not
       include "gdnsd/plugin.h".

RUNTIME CALLBACK FLOW
       To understand how plugins operate and how to write plugins, it is
       necessary to understand the overall flow of gdnsd's execution, and
       where in that flow various callbacks are made into the code of the
       loaded plugins.	If you haven't yet read the main gdnsd daemon
       documentation at this point, now would be a good time, as it covers
       some basic info about how gdnsd acts as its own initscript.  All
       callbacks have the name of the plugin in the function name, and we will
       use the example name "foo" for documentation purposes.  A brief summary
       of all of the API interfaces and semantics follows in a later section,
       but it would be good to read through this lengthy prose explanation at
       least once.

   CONFIGURATION
       Anytime the gdnsd binary is executed (assuming there is no immediate
       error in parsing the commandline arguments), if (and only if) the
       action is "checkconf", or one of the startup actions ("start",
       "restart", "condrestart"), it will load the gdnsd configuration file.
	Other actions (such as "stop" or "status") do not load the daemon
       config file, and do not load plugins or invoke their callbacks.

       As soon as the configuration file as a whole has been validated and
       loaded, gdnsd goes about setting various internal parameters from this
       data.  When it encounters the "plugins" hash, it will load and
       configure the named plugins.  Immediately after loading each plugin, it
       will execute the "plugin_foo_load_config()" callback, providing the
       plugin code with its vscf configuration hash.  At this time the plugin
       should walk (and validate) the provided configuration data and set up
       its own internal parameters based on this data.	In the case of many
       simple daemon actions (e.g. "stop"), there will be no further plugin
       callbacks after this point, and execution will cease shortly.  Because
       of this, any expensive configuration steps should be avoided in the
       load_config callback.  Your goal in load_config is to validate your
       configuration data and store it somewhere, nothing more.

       You may also return a "mon_list_t*" from load_config (or NULL if not
       applicable).  This defines the resources your plugin wants the core
       daemon to monitor via its internal HTTP state checker, so that you can
       implement simple failover policies easily.

       Next, "service_types" are processed from the config.  These may
       autoload additional plugins that were not specified in the "plugins"
       hash.  They will also receive a "plugin_foo_load_config(NULL)" call if
       autoloaded.

       For each service type that uses a given plugin, the plugin will receive
       a "plugin_foo_add_svctype()" callback.  Use this to set up local data
       structures for each service type you've been assigned.

       Next, all of the "mon_list_t*"'s that were returned by all
       "plugin_foo_load_config()" calls will be processed, which results in
       per-address callbacks to monitoring plugins'
       "plugin_foo_add_monitor()".  This is when a monitoring plugin sets up
       per-address data structures.

       The next callback will be "plugin_foo_full_config()".  This is an ideal
       time for a monitoring plugin to do any global config/setup operations
       that need to happen after all "plugin_foo_add_monitor()", or for a
       resolver plugin to initialize per-iothread data.	 The sole argument
       provided to this callback is num_threads, which is the total count of
       I/O threads that will exist at runtime, in case you need it in order to
       allocate per-thread data.  They are numbered from zero to num_threads -
       1.  The thread number of the calling thread will be passed to to other
       relevant callbacks later, when they are executed in I/O thread context.

       After full_config, the daemon loads and parses all zonefiles,
       constructing the internal runtime DNS database.	During the zonefile
       loading phase, when it encounters "DYNA" RRs in zonefiles, they will
       trigger the plugin callback "plugin_foo_map_resource_dyna" once for
       every "DYNA" RR.	 The same occurs with all "DYNC" RRs and
       "plugin_foo_map_resource_dync".	In the "DYNA" case, you get the
       resource name and are expected to return an integer resource number.
       In the "DYNC" case, you get both the resource name and an origin
       argument indicating the current $ORIGIN in effect for the RR, and again
       are expected to return an integer resource number which is greater than
       or equal to zero.

       The meaning and mapping of these resource numbers is entirely up to the
       plugin.	Any time the given RR is resolved at runtime, the resource
       number you returned here will be passed back to your code for dynamic
       resolution.

       If your DYNC plugin supports variable origins (e.g. the same resource
       name can be re-used in multiple zonefiles, and prepends some standard
       domainname fragment to origin in effect for the given RR), it is
       important that you validate that you can construct a legal domainname
       (length limits) from the given origin, resource name, and your own
       config at this time.  This validation is the only reason the "origin"
       parameter is provided for "plugin_foo_map_resource_dync".

       Plugins should not return different resource numbers for the same
       resname argument, even in the DYNC case where "origin" varies.  You
       will break things if you do so.

       If your map_resource operation fails (e.g. unknown resource name, or
       illegal origin-based CNAME construction), log the error and return -1.
       Do not fail fatally, as these calls happen at runtime during dynamic
       zonefile reloads.

       In the case of the action "checkconf", execution stops here.  Only the
       "start" and "restart" actions continue on to become full-fledged daemon
       instances.

   RUNTIME
       At this point in time, more daemon setup occurs, including the act of
       daemonization if applicable.  The next callback you will receive is
       "plugin_foo_post_daemonize()".  After that, the daemon does some
       runtime setup such as creating DNS listening sockets, etc.

       The next callback you will receive is "plugin_foo_pre_privdrop".	 This
       is your plugin's last chance to take any actions which may require
       special operating system privileges (such as opening low-numbered
       listening sockets, or opening most files in general).  Immediately
       after the pre_privdrop callback, the daemon will "chroot()" itself into
       the configured chroot directory and drop all privileges (if
       applicable).

       After dropping privileges, gdnsd will initialize (but not yet enter)
       the libev event loop which controls the primary thread of execution at
       runtime.	 This primary thread of execution handles all functionality
       other than the actual handling of DNS requests.	This includes such
       things as reacting to process signals, reporting stats data to syslog
       and to users via HTTP, and doing all monitoring-plugin actions to
       monitor address resources.  Two monitoring plugin callbacks happen at
       this stage:

       The first is "plugin_foo_init_monitors()".  You will be passed the
       event loop, and you are expected to set up events that will do a single
       monitoring check on all monitored resources and then clear themselves
       and not repeat.	When all plugins have done their init_monitors(), the
       loop will be run, and it is expected to terminate after a few seconds
       when all monitoring states have been initialized with real-world data.

       The next is "plugin_foo_start_monitors()".  Again you are passed the
       same libev loop, and you add all of your monitored resource callbacks,
       but this time it's permanent: they're expected to repeat their
       monitoring checks endlessly the next time the loop is invoked.

       When your libev monitoring callbacks have determined a success or
       failure for a monitored resource, they're expected to call the helper
       function "gdnsd_mon_state_updater()" from gdnsd/mon.h to send the state
       info upstream for anti-flap calculations and re-destribution to plugins
       which are monitoring the given resource.

       If your plugin (of any type) has asynchronous maintenance/management
       tasks that can be implemented as libev watchers (sockets, timeouts,
       etc), you may register libev events into the main loop at this time,
       via the optional callback "plugin_foo_pre_run".	The callback will be
       provided with a pointer to the libev loop.  You should not invoke the
       loop, or alter any loop-global settings.	 The loop will already have
       several watchers defined in it when your callback is executed which you
       should not touch.

       After pre_run, gdnsd will spawn the runtime DNS I/O threads.  For each
       such thread, the callback "plugin_foo_iothread_init" will be called
       from within each I/O thread with the global thread number as the only
       argument (0 through num_threads-1, where num_threads was provided to
       you back at full_config).  This would be the ideal time to malloc()
       writable per-thread data structures from within the threads themselves,
       so that a thread-aware malloc can avoid false sharing.

       At this point, gdnsd is ready to begin serving DNS queries.  After all
       I/O threads have finished initialization (and thus moved on to already
       serving requests), the primary thread will enter the libev loop
       mentioned above and remain under its control until daemon exit time.
       During this time the only direct callbacks your plugin will receive are
       "plugin_foo_resolve_dynaddr" and/or "plugin_foo_resolve_dyncname".
       They will only be called from I/O thread context.  If you registered
       any libev watchers during pre_run, you will also receive relevant
       callbacks there in the main thread's execution context.

       As a general style rule, the runtime resolver callbacks are not allowed
       to block or fail.  They are expected to respond immediately with valid
       response data.  It is your job as the plugin author to ensure this is
       the case.  That means pre-allocating memory, pre-loading data, and/or
       pre-calculating anything expensive during earlier callbacks.  Worst
       case, you can return meaningless data, e.g. 0.0.0.0 for "DYNA" or some
       hostname like "plugin.is.broken." for "DYNC", but ideally all possible
       error conditions have been checked out beforehand.

       "resolve_dynaddr" is supplied with a resource number, a thread number,
       a result structure your code can use to supply address information to
       the client, and a "client_info_t" structure giving network information
       about the querying client.

       The "client_info_t" structure contains the querying DNS cache's address
       as well as optional edns-client-subnet address+mask information.	 If
       the mask is zero, there was no (useful) edns-client-subnet information,
       and the plugin must fall back to using the cache's address.  When edns-
       client-subnet information is present, the edns-client-subnet output
       "scope" mask must be set in the result structure (to zero if the
       information went unused, or to a specific scope as defined in the edns-
       client-subnet draft (could be shorter or longer than the client's
       specified mask)).

       There is no distinction between A and AAAA requests (for that matter,
       your plugin could be invoked to provide Additional-section addresses
       for other requested types like MX or SRV).  You must answer with all
       applicable IPv4 and IPv6 addresses on every call.  Generally speaking,
       gdnsd treats A and AAAA much like a single RR-set.  Both are always
       included in the additional section when appropriate.  In response to a
       direct query for A or AAAA, the daemon returns the queried address RR
       type in the answer section and the other in the additional section.

       "resolve_dyncname" is similar, but also receives an origin argument in
       "dname" format, and uses a different results structure.	The origin
       argument is always fully qualified, and can be used to construct a
       complete domainname from a user configuration which specifies un-
       terminated short names.	Again, a pre-allocated results structure is
       supplied for your code to fill out.

       In both resolve callbacks' result structures, TTLs are pre-set from the
       effective TTL of the triggering record in the zonefile, but can be
       modified by the plugin (for example, to shorten the TTL during failure
       or near-failure events for a plugin that uses monitoring).

       "resolve_dynaddr" has a boolean return value.  If your plugin makes use
       of some sort of monitoring, and you detected what your plugin would
       call "total failure", (or at least, failure to some threshold limit
       that you consider very bad), you should return "false".	If there's no
       monitoring involved, or the monitored status was reasonably ok, return
       "true".	The idea here is a higher-level nested plugin will use this
       result to consider your entire resource "dead" for possibly failing
       over to an alternate resource that it knows about.  You should still
       return a valid address set (probably the whole set would be the best
       bet in this scenario, for example).

       When a signal is sent to stop the daemon, the primary thread's libev
       loop will return and no further watcher callbacks (set up via pre_run()
       or start_monitors()) will be invoked.  The main daemon will syslog()
       some final stats output and invoke "exit()" to terminate the process.
       This in turn unwinds the stack of "atexit()" handlers.  First will be a
       handler which cancels and joins all of the outstanding I/O threads,
       then comes another which invokes each plugin's "plugin_foo_exit()" from
       the main thread's context.  You can log any stats output you wish here,
       and/or destruct any resources you wish (no worry about races from io
       thread access, they're all dead now).

       The "map_resource_dyna" amd "map_resource_dync" callbacks may also be
       called at any time during normal runtime as a result of zonefiles being
       dynamically reloaded.  These should be readonly operations so there
       shouldn't be any locking concerns.  It's important that these calls
       never fail fatally.  Simply log an error and return -1.

THREADING
       gdnsd uses POSIX threads.  Only the runtime resolve callbacks (
       "plugin_foo_resolve_dynaddr" and "plugin_foo_resolve_dyncname") need to
       concern themselves with thread safety.  They can and will be called
       from multiple POSIX threads simultaneously for runtime requests.

       The simplest (but least-performant) way to ensure thread-safety would
       be to wrap the contents of these functions in a pthread mutex.
       However, for most imaginable cases, it should be trivial to structure
       your data and code such that these functions can be both lock-free and
       thread-safe.

CORE API DETAILS
       These are the functions exported by the core gdnsd code, which are
       available for your plugin to call at runtime.  They're implemented in a
       library named "libgdnsd", which the gdnsd daemon has already loaded
       before loading your plugin.  You don't need to (and shouldn't)
       explicitly link against libgdnsd.  The interfaces are defined in a set
       of header files grouped by functionality.  Note that in your primary
       plugin source file which includes gdnsd/plugin.h, all of these header
       files have already been included for you indirectly.

       For now, the documentation of these interfaces exists solely in the
       header files themselves.	 I'm still trying to sort out how to document
       them correctly, probably doxygen.

       gdnsd/compiler.h
       gdnsd/plugapi.h
       gdnsd/vscf.h
       gdnsd/net.h
       gdnsd/misc.h
       gdnsd/log.h
       gdnsd/mon.h
       gdnsd/dname.h

GENERAL PLUGIN CODING CONVENTIONS, ETC
       All syslog/stderr -type output should be handled via the thread-safe
       "log_*()" and "logf_*()" calls provided by gdnsd.  Do not attempt to
       use stderr (or stdout/stdin) or syslog directly.	 To throw a fatal
       error and abort daemon execution, use "log_fatal()", which does not
       return.

       Build your plugin with "-DNDEBUG" unless you're actually debugging
       development code, and make liberal use of "assert()" and "log_debug()"
       where applicable.

       You do not declare function prototypes for the callback functions
       (plugin_foo_*).	The prototypes are declared for you when you include
       the gdnsd/plugin.h header.  You need merely define the functions
       themselves.

       There is an internal API version number documented at the top of this
       document and set in "gdnsd/plugapi.h".  This number is only incremented
       when incompatible changes are made to the plugin API interface or
       semantics which require recompiling plugins and/or updating their code.
       When gdnsd is compiled this version number is hardcoded into the daemon
       binary.	When plugins are compiled the API version they were built
       against is also hardcoded into the plugin object automatically.	When
       gdnsd loads a plugin object, it checks for an exact match of plugin API
       version.	 If the number does not match, a fatal error will be thrown
       telling the user the plugin needs to be rebuilt against the gdnsd
       version in use.

       The current API version number is available to your code as the macro
       "GDNSD_PLUGIN_API_VERSION".  If necessary, you can test this value via
       "#if" macro logic to use alternate code for different API versions (or
       simply to error out if the API version is too old for your plugin
       code).

API CHANGELOG
       Prior to API version 3, there wasn't any good API documentation and no
       known 3rd-party plugins.

   Version 4
       The API function gdnsd_mon_add() was removed completely.

       The prototype for plugin_foo_load_config() changed: the return value
       (previously void) is now "mon_list_t*".	If you were previously using
       gdnsd_mon_add() during plugin_foo_load_config(), you now return that
       data via the return value instead.  If you were not using
       gdnsd_mon_add(), you can simply update the return value type and return
       NULL from this callback now.

       Also, while not technically an API change, the configuration file
       format as a whole underwent some changes.  Hash keys and values are now
       separated by "=>" or "=" (rather than ":" or "="), and ":" is now
       allowed in literal, unquoted keys and values.

   Verion 5
       "plugin_foo_map_resource" was replaced with
       "plugin_foo_map_resource_dyna".

       Two new callbacks added for "DYNC" support:
       "plugin_foo_map_resource_dync" and "plugin_foo_resolve_dyncname".

       All plugin callback hooks are now optional.  Failure to implement
       map_resource callbacks maps all resources to the number zero, failure
       to implement load_config just means any plugin config hash information
       is ignored, etc.	 Obviously, a plugin that defines no callbacks would
       be useless.  Similarly, if you don't implement at least one of
       "plugin_foo_resolve_dynaddr" or "plugin_foo_resolve_dyncname" your
       plugin will be fairly useless as well.

   Version 9
       Note: Versions 6-8 existed in the long-running 1.5.x dev series, but
       never a release build, so the V9 info here summarizes all changes from
       V5 -> V9.

       "plugin_foo_resolve_dyna" and "plugin_foo_resolve_dyncname" had their
       "const anysin_t* client" arguments replaced with "const client_info_t*
       cinfo".	If you don't wish to deal immediately with the new
       complexities presented by the draft edns-client-subnet information in
       this new structure, you can preserve existing behavior by (a) updating
       your functions' arguments to the new prototype, and (b) adding the
       following near the top: "const anysin_t* client = &cinfo->dns_client;".

       Additionally, *if* your plugin makes dynamic decisions based on
       "cinfo->dns_client", it *needs* to set "result->edns_scope_mask =
       cinfo->edns_client_mask;" for correct behavior.	Plugins whose
       responses are static with regard to "cinfo" should not do so, as the
       result scope mask defaults to the appropriate value of 0.

       Previously an "extern bool dmn_debug" was available to query daemon
       debug status, this has been replaced with a function call "bool
       dmn_get_debug(void);".  This means any plugin with "log_debug()"
       statements loses binary compatibility and needs to be rebuilt, but
       doesn't require a source change.	 Other new dmn accessors were also
       added for previously unavailable information regarding
       privdrop/chroot/daemonization status as well.

       Added four new plugin callbacks to support pluggable monitoring:
	   void plugin_foo_add_svctype(const char* name, const vscf_data_t*
       svc_cfg, const unsigned interval, const unsigned timeout)
	   void plugin_foo_add_monitor(const char* svc_name, mon_smgr_t* smgr)
	   void plugin_foo_init_monitors(struct ev_loop* mon_loop)
	   void plugin_foo_start_monitors(struct ev_loop* mon_loop)

       The internal structure of the data type "anysin_t" changed.  The old
       typedef was:

	   typedef union {
	       struct sockaddr_in6 sin6;
	       struct sockaddr_in  sin;
	       struct sockaddr	   sa;
	   } anysin_t;

       ... and the new one is:

	   typedef struct {
	       union {
		   struct sockaddr_in6 sin6;
		   struct sockaddr_in  sin;
		   struct sockaddr     sa;
	       };
	       socklen_t len;
	   } anysin_t;

       Direct access to the union members via casting anysin_t to one of the
       sockaddr structs should still technically work, although it would be
       more proper to use the correct member.  If you are creating new
       anysin_t's in your plugin code, you need to set the "len" member
       correctly.  Generally, this would be the len returned by the library
       call that created the sockaddr struct, e.g.  ai_addrlen in the case of
       "getaddrinfo()", and in any case should correspond to the "sizeof()"
       one of the unioned sockaddr structs.

       If passing a blank anysin_t to be filled out by system library code
       (e.g.  as an argument to "accept()"), the appropriate socklen value is
       defined as "ANYSIN_MAXLEN", which is the length of the largest of the
       unioned sockaddr structs.  So set anysin_t.len to that, and pass
       &anysin_t.len as the "socklen_t*" argument the library call will use to
       fill in the correct value.

       Also added new API helper function "gdnsd_anysin_getaddrinfo()" which
       wraps the common process of converting a numeric string address +
       optional numeric string port into an anysin_t using "getaddrinfo()",
       and sets the len field correctly.  "plugin_foo_resolve_dynaddr()" now
       needs a return value of type "bool", was previously "void".  Return
       value should indicate whether other code can consider this resource
       effectively-dead for failover purposes.	You should still return some
       valid result-set (common practice would be to return all if
       everything's down, as if nothing in the resource were down).

   Version 11
       Note: Version 10 existed in the long-running 1.7.x dev series, but
       never a release build, so the V11 info here summarizes all changes from
       V9 -> V11.

       All header files renamed from the form "gdnsd-X.h" to "gdnsd/X.h".

       satom/mon stuff: The header file gdnsd/satom.h is no longer published,
       and plugin code which directly includes it or uses things only defined
       there (e.g.  satom_t and various satom_*() accessors) needs to stop
       doing so.  It was probably never a good idea to expose this or use it
       in the first place.  The replacement is intentionally undocumented for
       the plugin API.

       s/monio/mon/ in general on any types/symbols/macros referenced from the
       API include files, to clean up some package-internal naming conflict
       stuff.

       gdnsd_mon_min_state() renamed gdnsd_mon_get_min_state(), and is now the
       only documented official interface for resolve plugins to fetch
       monitored states.

       gdnsd_mon_state_updater() is now the required interface for monitoring
       plugins to send updates to the core, whereas it was merely recommended
       in the past.

       The embedded copy of libev was removed in favor of using an external
       installation as a dependency.  This means you'll need to have your own
       copy of libev's development headers in place to build 3rd-party
       plugins, and they should match the libev version gdnsd was built with.

       A few other minor changes require just a recompile, even if none of the
       above applies.

   Version 12
       This corresponds with the release of 1.10.0

       Only the vscf config-file API changed in this version, which only
       really affects plugins that were loading external vscf configuration
       files on their own (as opposed to just receiving data from the main
       config file's plugins stanza).  There aren't any 3rd party plugins
       doing this that I'm aware of, but it does technically warrant an API
       compatibility bump.

       The first of the vscf API changes was the removal of the fd and stream
       input functions vscf_scan_fd() and vscf_scan_stream(), leaving only the
       vscf_scan_filename() variant.

       The other change is that the data item returned by vscf_scan_filename()
       can now be a hash or an array, whereas before the syntax of vscf's
       config language only permitted it to be a hash.	Code which expects a
       hash must now explicitly check that the result was not an array.

SEE ALSO
       The source for the included addr/cname-resolution plugins "null",
       "reflect", "static", "simplefo", "multifo", "weighted", "metafo", and
       "geoip".	 The source for the included monitoring plugins "http_status",
       "tcp_connect", and "extmon".

       gdnsd(8), gdnsd.config(5), gdnsd.zonefile(5)

       The gdnsd manual.

COPYRIGHT AND LICENSE
       Copyright (c) 2012 Brandon L Black <blblack@gmail.com>

       This file is part of gdnsd.

       gdnsd is free software: you can redistribute it and/or modify it under
       the terms of the GNU General Public License as published by the Free
       Software Foundation, either version 3 of the License, or (at your
       option) any later version.

       gdnsd is distributed in the hope that it will be useful, but WITHOUT
       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       for more details.

       You should have received a copy of the GNU General Public License along
       with gdnsd.  If not, see <http://www.gnu.org/licenses/>.

gdnsd 1.11.0			  2013-12-06		   gdnsd-plugin-api(3)
[top]

List of man pages available for Alpinelinux

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net