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