void plugin_http_status_add_svctype(const char* name, const vscf_data_t* svc_cfg, const unsigned interval, const unsigned timeout) { dmn_assert(name); // defaults const char* url_path = "/"; const char* vhost = NULL; unsigned port = 80; service_types = realloc(service_types, (num_http_svcs + 1) * sizeof(http_svc_t)); http_svc_t* this_svc = &service_types[num_http_svcs++]; this_svc->name = strdup(name); this_svc->num_ok_codes = 0; this_svc->ok_codes = NULL; bool ok_codes_set = false; if(svc_cfg) { SVC_OPT_STR(svc_cfg, name, url_path); SVC_OPT_STR(svc_cfg, name, vhost); SVC_OPT_UINT(svc_cfg, name, port, 1LU, 65534LU); const vscf_data_t* ok_codes_cfg = vscf_hash_get_data_byconstkey(svc_cfg, "ok_codes", true); if(ok_codes_cfg) { ok_codes_set = true; this_svc->num_ok_codes = vscf_array_get_len(ok_codes_cfg); this_svc->ok_codes = malloc(sizeof(unsigned long) * this_svc->num_ok_codes); for(unsigned i = 0; i < this_svc->num_ok_codes; i++) { const vscf_data_t* code_cfg = vscf_array_get_data(ok_codes_cfg, i); if(!vscf_simple_get_as_ulong(code_cfg, &this_svc->ok_codes[i])) log_fatal("plugin_http_status: service type '%s': illegal ok_codes value '%s', must be numeric http status code (100-999)", this_svc->name, vscf_simple_get_data(code_cfg)); if(this_svc->ok_codes[i] < 100LU || this_svc->ok_codes[i] > 999LU) log_fatal("plugin_http_status: service type '%s': illegal ok_codes value '%lu', must be numeric http status code (100-999)", this_svc->name, this_svc->ok_codes[i]); } } } // no config at all, but not the empty array... if(!ok_codes_set) { this_svc->num_ok_codes = 1; this_svc->ok_codes = malloc(sizeof(unsigned long)); this_svc->ok_codes[0] = 200LU; } make_req_data(this_svc, url_path, vhost); this_svc->port = port; this_svc->timeout = timeout; this_svc->interval = interval; }
// 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; } }
// 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). dcinfo_t* dcinfo_new(const vscf_data_t* dc_cfg, const vscf_data_t* dc_auto_cfg, const vscf_data_t* dc_auto_limit_cfg, const char* map_name) { dmn_assert(dc_cfg); dmn_assert(map_name); dcinfo_t* info = malloc(sizeof(dcinfo_t)); 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 > 254) log_fatal("plugin_geoip: map '%s': %u datacenters is too many, this code only supports up to 254", map_name, num_dcs); info->names = malloc(sizeof(char*) * num_dcs); info->num_dcs = num_dcs; for(unsigned i = 0; i < num_dcs; i++) { const 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->names[i] = strdup(vscf_simple_get_data(dcname_cfg)); if(!strcmp(info->names[i], "auto")) log_fatal("plugin_geoip: map '%s': datacenter name 'auto' is illegal", map_name); } if(dc_auto_cfg) { if(!vscf_is_hash(dc_auto_cfg)) log_fatal("plugin_geoip: map '%s': auto_dc_coords must be a key-value hash", map_name); num_auto = vscf_hash_get_len(dc_auto_cfg); info->coords = malloc(num_dcs * 2 * sizeof(double)); for(unsigned i = 0; i < 2*num_dcs; i++) info->coords[i] = NAN; for(unsigned i = 0; i < num_auto; i++) { const char* dcname = vscf_hash_get_key_byindex(dc_auto_cfg, i, NULL); unsigned dcidx; for(dcidx = 0; dcidx < num_dcs; dcidx++) { if(!strcmp(dcname, info->names[dcidx])) break; } if(dcidx == num_dcs) log_fatal("plugin_geoip: map '%s': auto_dc_coords key '%s' not matched from 'datacenters' list", map_name, dcname); if(!isnan(info->coords[(dcidx*2)])) log_fatal("plugin_geoip: map '%s': auto_dc_coords key '%s' defined twice", map_name, dcname); const vscf_data_t* coord_cfg = vscf_hash_get_data_byindex(dc_auto_cfg, i); const vscf_data_t* lat_cfg; const vscf_data_t* lon_cfg; double lat, lon; if( !vscf_is_array(coord_cfg) || vscf_array_get_len(coord_cfg) != 2 || !(lat_cfg = vscf_array_get_data(coord_cfg, 0)) || !(lon_cfg = vscf_array_get_data(coord_cfg, 1)) || !vscf_is_simple(lat_cfg) || !vscf_is_simple(lon_cfg) || !vscf_simple_get_as_double(lat_cfg, &lat) || !vscf_simple_get_as_double(lon_cfg, &lon) || lat > 90.0 || lat < -90.0 || lon > 180.0 || lon < -180.0 ) log_fatal("plugin_geoip: map '%s': auto_dc_coords value for datacenter '%s' must be an array of two floating-point values representing a legal latitude and longitude in decimal degrees", map_name, dcname); info->coords[(dcidx * 2)] = lat * DEG2RAD; info->coords[(dcidx * 2) + 1] = lon * DEG2RAD; } } else { info->coords = NULL; } 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; } return info; }