1 /* Copyright © 2012 Brandon L Black <blblack@gmail.com>
2  *
3  * This file is part of gdnsd.
4  *
5  * gdnsd is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * gdnsd is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with gdnsd.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef GDNSD_PLUGAPI_H
21 #define GDNSD_PLUGAPI_H
22 
23 #include <gdnsd/vscf.h>
24 #include <gdnsd/net.h>
25 #include <gdnsd/mon.h>
26 
27 #include <inttypes.h>
28 
29 #include <ev.h>
30 
31 // The bopts header is sort of like a "config.h" for plugin binary compat
32 // It defines only features that affect binary compatibility between plugins
33 // and the core code, so that plugins can be rejected as needing a recompile
34 // if they were built against a compatible gdnsd version but with incompatible
35 // build options.
36 #ifndef GDNSD_SOURCE_TREE
37 #include <gdnsd/bopts.h>
38 #endif
39 
40 /***
41  * Plugin API version, bumped on any change that's not backwards-compat.
42  * This is hardcoded as the return value of plugin_foo_get_api_version()
43  *   in gdnsd/plugin.h, and also compiled into the gdnsd code.  The two
44  *   values are compared at plugin load time to ensure that plugin code
45  *   which doesn't match the API of the gdnsd binary is not allowed.
46  * (Of course, in many cases the plugin never even makes it that far,
47  *   because libgdnsd is missing symbols it wants to link against that
48  *   were dropped in the new API.  This is just to protect other cases).
49  ***/
50 
51 // We have room for 16 option bits here coming from bopts.h/config.h
52 #define API_B_OPT_QSBR_ ((GDNSD_B_QSBR ? 1 : 0) << 0)
53 #define API_B_OPTS_ (API_B_OPT_QSBR_)
54 #define API_ACTUAL_VERSION_ 17
55 #define GDNSD_PLUGIN_API_VERSION (((API_B_OPTS_) << 16) | (API_ACTUAL_VERSION_))
56 
57 #pragma GCC visibility push(default)
58 
59 // Called by resolver plugins during configuration load callback
60 // Indicates the maximum count of each address family that the plugin
61 //   will add to result structures at runtime.  A plugin *cannot* exceed
62 //   the limits it sets for itself here at startup, and every resolver
63 //   plugin that can return addresses *must* call this function!
64 void gdnsd_dyn_addr_max(unsigned v4, unsigned v6);
65 
66 /*** Data Types ***/
67 
68 // read-only for plugins
69 typedef struct {
70     dmn_anysin_t dns_source;       // address of last source DNS cache/forwarder
71     dmn_anysin_t edns_client;      // edns-client-subnet address portion
72     unsigned edns_client_mask; // edns-client-subnet mask portion
73 } client_info_t;               //  ^(if zero, edns_client is invalid (was not sent))
74 
75 // Private result structure for dynamic resolution plugins
76 // Modified via the functions below...
77 struct dyn_result;
78 typedef struct dyn_result dyn_result_t;
79 
80 // NOTE the rules for the result-modifying functions below:
81 //   A plugin cannot add more addresses of a given family than it indicated
82 //     during its call to gdnsd_dyn_addr_max().
83 //   A plugin cannot add both addresses and a CNAME to the same result.
84 //   A plugin cannot add more than one CNAME to the same result.
85 
86 // Push an dmn_anysin_t (v4 or v6 addr) into dyn_result_t storage.
87 F_NONNULL
88 void gdnsd_result_add_anysin(dyn_result_t* result, const dmn_anysin_t* asin);
89 
90 // Push a CNAME into dyn_result_t storage.
91 F_NONNULL
92 void gdnsd_result_add_cname(dyn_result_t* result, const uint8_t* dname, const uint8_t* origin);
93 
94 // Wipe a result_t's storage completely, removing all addresses or the CNAME stored within
95 // (this function is valid at all times, never fails, and resets to the original state)
96 // (does not affect scope mask!)
97 F_NONNULL
98 void gdnsd_result_wipe(dyn_result_t* result);
99 
100 // Wipe just one address family from a result.  Does not affect the other address family,
101 //   and has no effect at all if the result contained a CNAME instead.
102 // (does not affect scope mask!)
103 F_NONNULL
104 void gdnsd_result_wipe_v4(dyn_result_t* result);
105 F_NONNULL
106 void gdnsd_result_wipe_v6(dyn_result_t* result);
107 
108 // Resets the edns scope mask to the default value of zero, meaning global (unspecified) scope
109 F_NONNULL
110 void gdnsd_result_reset_scope_mask(dyn_result_t* result);
111 
112 // Set the edns scope mask of the result to the minimum scope (numerically-larger) of
113 //   the current setting and the new input.  This is correct if more than one independent
114 //   calculation of scope applies to the result.
115 F_NONNULL
116 void gdnsd_result_add_scope_mask(dyn_result_t* result, unsigned scope);
117 
118 /**** Typedefs for plugin callbacks ****/
119 
120 typedef unsigned (*gdnsd_apiv_cb_t)(void);
121 typedef void (*gdnsd_load_config_cb_t)(vscf_data_t* pc, const unsigned num_threads);
122 typedef int (*gdnsd_map_res_cb_t)(const char* resname, const uint8_t* origin);
123 typedef void (*gdnsd_pre_run_cb_t)(void);
124 typedef void (*gdnsd_iothread_init_cb_t)(unsigned threadnum);
125 typedef gdnsd_sttl_t (*gdnsd_resolve_cb_t)(unsigned resnum, const uint8_t* origin, const client_info_t* cinfo, dyn_result_t* result);
126 typedef void (*gdnsd_exit_cb_t)(void);
127 
128 /**** New callbacks for monitoring plugins ****/
129 
130 typedef void (*gdnsd_add_svctype_cb_t)(const char* name, vscf_data_t* svc_cfg, const unsigned interval, const unsigned timeout);
131 typedef void (*gdnsd_add_mon_addr_cb_t)(const char* desc, const char* svc_name, const char* cname, const dmn_anysin_t* addr, const unsigned idx);
132 typedef void (*gdnsd_add_mon_cname_cb_t)(const char* desc, const char* svc_name, const char* cname, const unsigned idx);
133 typedef void (*gdnsd_init_monitors_cb_t)(struct ev_loop* mon_loop);
134 typedef void (*gdnsd_start_monitors_cb_t)(struct ev_loop* mon_loop);
135 
136 // This is the data type for a plugin itself, holding function
137 //  pointers for all of the possibly-documented callbacks
138 typedef struct {
139     const char* name;
140     bool config_loaded;
141     gdnsd_load_config_cb_t load_config;
142     gdnsd_map_res_cb_t map_res;
143     gdnsd_pre_run_cb_t pre_run;
144     gdnsd_iothread_init_cb_t iothread_init;
145     gdnsd_resolve_cb_t resolve;
146     gdnsd_exit_cb_t exit;
147     gdnsd_add_svctype_cb_t add_svctype;
148     gdnsd_add_mon_addr_cb_t add_mon_addr;
149     gdnsd_add_mon_cname_cb_t add_mon_cname;
150     gdnsd_init_monitors_cb_t init_monitors;
151     gdnsd_start_monitors_cb_t start_monitors;
152 } plugin_t;
153 
154 // Find a(nother) plugin by name.  Not valid at load_config() time,
155 //   use later.
156 F_NONNULL F_PURE
157 plugin_t* gdnsd_plugin_find(const char* plugin_name);
158 
159 // convenient macro for logging a config error and returning
160 //  the error value -1 in a resolver plugin's map_res() callback
161 //  without a bunch of extra clutter and bracing
162 #define map_res_err(...) \
163     do {\
164         log_err(__VA_ARGS__);\
165         return -1;\
166     } while(0)
167 
168 #pragma GCC visibility pop
169 
170 #endif // GDNSD_PLUGINAPI_H
171