1 /* Copyright © 2012 Brandon L Black <blblack@gmail.com>
2 *
3 * This file is part of gdnsd.
4 *
5 * gdnsd-plugin-geoip 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-plugin-geoip 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 #include <config.h>
21
22 #define GDNSD_PLUGIN_NAME geoip
23 #include <gdnsd/plugin.h>
24
25 #include <gdmaps.h>
26
27 #include <string.h>
28 #include <stdlib.h>
29 #include <inttypes.h>
30 #include <stdbool.h>
31
32 static gdmaps_t* gdmaps;
33
34 F_NONNULL
res_get_mapnum(vscf_data_t * res_cfg,const char * res_name)35 static unsigned res_get_mapnum(vscf_data_t* res_cfg, const char* res_name) {
36 // Get 'map' name, convert to gdmaps index
37 vscf_data_t* map_cfg = vscf_hash_get_data_byconstkey(res_cfg, "map", true);
38 if(!map_cfg)
39 log_fatal("plugin_geoip: resource '%s': required key 'map' is missing", res_name);
40 if(!vscf_is_simple(map_cfg))
41 log_fatal("plugin_geoip: resource '%s': 'map' must be a string", res_name);
42 const char* map_name = vscf_simple_get_data(map_cfg);
43 const int rv = gdmaps_name2idx(gdmaps, map_name);
44 if(rv < 0)
45 log_fatal("plugin_geoip: resource '%s': map '%s' does not exist", res_name, map_name);
46 return (unsigned)rv;
47 }
48
map_get_len(const unsigned mapnum)49 static unsigned map_get_len(const unsigned mapnum) {
50 return gdmaps_get_dc_count(gdmaps, mapnum);
51 }
52
map_get_dcidx(const unsigned mapnum,const char * dcname)53 static unsigned map_get_dcidx(const unsigned mapnum, const char* dcname) {
54 return gdmaps_dcname2num(gdmaps, mapnum, dcname);
55 }
56
57 F_NONNULL
top_config_hook(vscf_data_t * top_config)58 static bool top_config_hook(vscf_data_t* top_config) {
59 dmn_assert(vscf_is_hash(top_config));
60
61 vscf_data_t* maps = vscf_hash_get_data_byconstkey(top_config, "maps", true);
62 if(!maps)
63 log_fatal("plugin_geoip: config has no 'maps' stanza");
64 if(!vscf_is_hash(maps))
65 log_fatal("plugin_geoip: 'maps' stanza must be a hash");
66 if(!vscf_hash_get_len(maps))
67 log_fatal("plugin_geoip: 'maps' stanza must contain one or more maps");
68
69 gdmaps = gdmaps_new(maps);
70
71 bool undef_dc_ok = false;
72 vscf_data_t* undef_dc_ok_vscf = vscf_hash_get_data_byconstkey(top_config, "undefined_datacenters_ok", true);
73 if(undef_dc_ok_vscf) {
74 if(!vscf_is_simple(undef_dc_ok_vscf) || !vscf_simple_get_as_bool(undef_dc_ok_vscf, &undef_dc_ok))
75 log_fatal("plugin_geoip: 'undef_dc_ok' must be a boolean value ('true' or 'false')");
76 }
77
78 return undef_dc_ok;
79 }
80
bottom_config_hook(void)81 static void bottom_config_hook(void) {
82 dmn_assert(gdmaps);
83 gdmaps_load_databases(gdmaps);
84 }
85
plugin_geoip_pre_run(void)86 void plugin_geoip_pre_run(void) {
87 dmn_assert(gdmaps);
88 gdmaps_setup_watchers(gdmaps);
89 }
90
91 F_NONNULL
map_get_dclist(const unsigned mapnum,const client_info_t * cinfo,unsigned * scope_out)92 static const uint8_t* map_get_dclist(const unsigned mapnum, const client_info_t* cinfo, unsigned* scope_out) {
93 dmn_assert(gdmaps);
94 return gdmaps_lookup(gdmaps, mapnum, cinfo, scope_out);
95 }
96
map_get_mon_idx(const unsigned mapnum,const unsigned dcnum)97 static unsigned map_get_mon_idx(const unsigned mapnum, const unsigned dcnum) {
98 return gdmaps_map_mon_idx(gdmaps, mapnum, dcnum);
99 }
100
101 #define PNSTR "geoip"
102 #define CB_LOAD_CONFIG plugin_geoip_load_config
103 #define CB_MAP plugin_geoip_map_res
104 #define CB_RES plugin_geoip_resolve
105 #define META_MAP_ADMIN 1
106 #include "meta_core.inc"
107