F_NONNULL static gen_func_ptr plugin_dlsym(void* handle, const char* pname, const char* sym_suffix) { dmn_assert(handle); dmn_assert(pname); dmn_assert(sym_suffix); // If you see an aliasing warning here, it's ok to ignore it char* symname = gdnsd_str_combine_n(4, "plugin_", pname, "_", sym_suffix); gen_func_ptr rval; *(void**)(&rval) = dlsym(handle, symname); free(symname); return rval; }
static char* gdnsd_resolve_path(const path_typ_t p, const char* inpath, const char* pfx) { dmn_assert(gdnsd_dirs[p]); char* out = NULL; if(inpath && inpath[0] == '/') { out = strdup(inpath); } else if(pfx) { if(inpath) out = gdnsd_str_combine_n(5, gdnsd_dirs[p], "/", pfx, "/", inpath); else out = gdnsd_str_combine_n(3, gdnsd_dirs[p], "/", pfx); } else { if(inpath) out = gdnsd_str_combine_n(3, gdnsd_dirs[p], "/", inpath); else out = strdup(gdnsd_dirs[p]); } return out; }
// Technically we could/should check for duplicates here. The plugin will // still fail later though: when a resource is defined, the datacenter // names go into a hash requiring uniqueness, and the count is required // to match (ditto for auto_dc_coords never succeeding with dupes in the // datacenters list). void dcinfo_init(dcinfo_t* info, vscf_data_t* dc_cfg, vscf_data_t* dc_auto_cfg, vscf_data_t* dc_auto_limit_cfg, const char* map_name, monreg_func_t mrf) { const unsigned num_dcs = vscf_array_get_len(dc_cfg); unsigned num_auto = num_dcs; if (!num_dcs) log_fatal("plugin_geoip: map '%s': 'datacenters' must be an array of one or more strings", map_name); if (num_dcs > MAX_NUM_DCS) log_fatal("plugin_geoip: map '%s': %u datacenters is too many, this code only supports up to %i", map_name, num_dcs, MAX_NUM_DCS); info->num_dcs = num_dcs; info->dcs = xmalloc_n(num_dcs, sizeof(*info->dcs)); for (unsigned i = 0; i < num_dcs; i++) { vscf_data_t* dcname_cfg = vscf_array_get_data(dc_cfg, i); if (!dcname_cfg || !vscf_is_simple(dcname_cfg)) log_fatal("plugin_geoip: map '%s': 'datacenters' must be an array of one or more strings", map_name); info->dcs[i].name = xstrdup(vscf_simple_get_data(dcname_cfg)); if (!strcmp(info->dcs[i].name, "auto")) log_fatal("plugin_geoip: map '%s': datacenter name 'auto' is illegal", map_name); char* map_mon_desc = gdnsd_str_combine_n(4, "geoip/", map_name, "/", info->dcs[i].name); if (mrf) info->dcs[i].mon_index = mrf(map_mon_desc); free(map_mon_desc); } if (dc_auto_cfg) num_auto = dcinfo_init_auto(info, dc_auto_cfg, map_name); if (dc_auto_limit_cfg) { unsigned long auto_limit_ul; if (!vscf_is_simple(dc_auto_limit_cfg) || !vscf_simple_get_as_ulong(dc_auto_limit_cfg, &auto_limit_ul)) log_fatal("plugin_geoip: map '%s': auto_dc_limit must be a single unsigned integer value", map_name); if (auto_limit_ul > num_auto || !auto_limit_ul) auto_limit_ul = num_auto; info->auto_limit = auto_limit_ul; } else { info->auto_limit = (num_auto > 3) ? 3 : num_auto; } }
F_NONNULL static void* plugin_dlopen(const char* pname) { dmn_assert(pname); dmn_assert(psearch); struct stat plugstat; const char* try_path; const char** psptr = psearch; while((try_path = *psptr++)) { char* pp = gdnsd_str_combine_n(4, try_path, "/plugin_", pname, ".so"); log_debug("Looking for plugin '%s' at pathname '%s'", pname, pp); if(0 == stat(pp, &plugstat) && S_ISREG(plugstat.st_mode)) { void* phandle = dlopen(pp, RTLD_NOW | RTLD_LOCAL); if(!phandle) log_fatal("Failed to dlopen() the '%s' plugin from path '%s' (%s). The plugin may need to be recompiled due to binary compatibility issues", pname, pp, dlerror()); free(pp); return phandle; } free(pp); } log_fatal("Failed to locate plugin '%s' in the plugin search path", pname); }