/** * Test that an ip address is within a range in the same address family (v4 or v6). * * @return AM_SUCCESS on match, else NOT_FOUND */ am_status_t ip_address_match(const char *ip, const char **list, unsigned int listsize, unsigned long instance_id) { unsigned int i; if (ip == NULL || list == NULL || listsize == 0) { return AM_EINVAL; } for (i = 0; i < listsize; i++) { const char *hp = strchr(list[i], '-'); const char *fs = strchr(list[i], '/'); if (hp != NULL && fs == NULL) { /* make sure we get address range here: 192.168.1.1-192.168.2.3 */ if (get_in_bounded_range_status(ip, list[i]) == AM_SUCCESS) { AM_LOG_INFO(instance_id, "ip_address_match(): found ip address %s in address range %s", ip, list[i]); return AM_SUCCESS; } } if (hp == NULL && fs != NULL) { /* and cidr spec here: 192.168.1.1/24 */ if (get_in_masked_range_status(ip, list[i]) == AM_SUCCESS) { AM_LOG_INFO(instance_id, "ip_address_match(): found ip address %s in address range %s", ip, list[i]); return AM_SUCCESS; } } } return AM_NOT_FOUND; }
/** * This is the simplest of tests to check we can log things without crashing. * * In fact, because of the way logging works (differently) in test mode than it does in "agent mode" * all we're really doing here is to test that logging in test mode isn't broken. This may or may not * bear any relation to whether logging works for the rest of the time. */ void test_logging_in_unit_test_mode(void** state) { static const char* text1 = "Now is the winter of our discontent,"; static const char* text2 = "Made glorious summer by this son of York"; AM_LOG_INFO(0, "instance id is zero and no args"); AM_LOG_INFO(0, "instance id is zero and incorrect args", text1); AM_LOG_INFO(0, "instance id is zero and more incorrect args", text1, text2); /* we're testing this will not crash */ AM_LOG_INFO(0, NULL, text1, text2); /* this will not appear, since the instance is greater than zero, but it should not crash either */ AM_LOG_ERROR(10, "%s %s", text1, text2); AM_LOG_INFO(0, "%s %s", text1, text2); AM_LOG_WARNING(0, "%s %s", text1, text2); AM_LOG_ERROR(0, "%s %s", text1, text2); AM_LOG_DEBUG(0, "%s %s", text1, text2); AM_LOG_AUDIT(0, "%s %s", text1, text2); AM_LOG_ALWAYS(0, "%s %s", text1, text2); AM_LOG_ALWAYS(0, "Now %s the %s of our %s, %s summ%s of York", "is", "winter", "discontent", "Made glorious", "er by this son"); /* attempt to overflow the buffer, although this will be ultimately unsuccessful because the * logging works differently in unit test mode than it does in "real life" mode. */ AM_LOG_ALWAYS(0, "\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n" "ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ"); }
void url_validator_worker(void *arg) { static const char *thisfunc = "url_validator_worker():"; struct url_validator_worker_data *w = (struct url_validator_worker_data *) arg; am_net_options_t *net_options; int i, validate_status; am_config_t *conf = NULL; time_t current_ts; struct url_valid_table *e, *t; int current_index, current_ok, current_fail, default_ok, next_ok; char **url_list; int url_list_sz = 0; int ping_diff; set_valid_url_instance_running(w->instance_id, AM_TRUE); conf = am_get_config_file(w->instance_id, w->config_path); if (conf == NULL) { AM_LOG_WARNING(w->instance_id, "%s failed to get agent configuration (%s)", thisfunc, LOGEMPTY(w->config_path)); set_valid_url_instance_running(w->instance_id, AM_FALSE); AM_FREE(w->config_path, w); return; } ping_diff = MAX(MIN_URL_VALIDATOR_TICK, conf->valid_ping); current_ts = time(NULL); /* this index corresponds to the naming.url multi-value index */ current_index = w->url_index; if (conf->valid_level > 1 || conf->naming_url_sz < 2 || conf->naming_url_sz != conf->valid_default_url_sz || (current_ts - w->last) < ping_diff) { /* a) validation is disabled; b) there is nothing to validate; * c) naming.url list and default.url list sizes do not match or * d) its not time yet to do any validation */ am_config_free(&conf); set_valid_url_instance_running(w->instance_id, AM_FALSE); AM_FREE(w->config_path, w); return; } if (current_index < 0 || current_index >= conf->naming_url_sz) { AM_LOG_WARNING(w->instance_id, "%s invalid current index value, defaulting to %s", thisfunc, conf->naming_url[0]); set_valid_url_index(w->instance_id, 0); am_config_free(&conf); set_valid_url_instance_running(w->instance_id, AM_FALSE); AM_FREE(w->config_path, w); return; } #define URL_LIST_FREE(l, s) do { \ int k; \ if (l == NULL) break; \ for (k = 0; k < s; k++) { \ am_free(l[k]); \ }\ free(l); \ } while (0) net_options = calloc(1, sizeof (am_net_options_t)); if (net_options == NULL) { AM_LOG_ERROR(w->instance_id, "%s memory allocation error", thisfunc); am_config_free(&conf); set_valid_url_instance_running(w->instance_id, AM_FALSE); AM_FREE(w->config_path, w); return; } url_list = (char **) calloc(1, conf->naming_url_sz * sizeof (char *)); if (url_list == NULL) { AM_LOG_ERROR(w->instance_id, "%s memory allocation error", thisfunc); am_config_free(&conf); set_valid_url_instance_running(w->instance_id, AM_FALSE); AM_FREE(net_options, w->config_path, w); return; } url_list_sz = conf->naming_url_sz; for (i = 0; i < url_list_sz; i++) { /* default.url.set contains fail-over order; * will keep internal value list index-ordered **/ int j = conf->valid_default_url[i]; url_list[i] = strdup(conf->naming_url[j]); if (url_list[i] == NULL) { URL_LIST_FREE(url_list, url_list_sz); am_config_free(&conf); set_valid_url_instance_running(w->instance_id, AM_FALSE); AM_FREE(net_options, w->config_path, w); return; } } am_net_options_create(conf, net_options, NULL); net_options->keepalive = AM_FALSE; net_options->local = net_options->cert_trust = AM_TRUE; net_options->net_timeout = 2; /* fixed for url validator; in sec */ /* do the actual url validation */ for (i = 0; i < url_list_sz; i++) { const char *url = url_list[i]; int ok = 0, fail = 0, httpcode = 0; get_validation_table_entry(w->instance_id, i, &ok, &fail, NULL); AM_LOG_DEBUG(w->instance_id, "%s validating %s", thisfunc, url); if (conf->valid_level == 1) { /* simple HEAD request */ validate_status = am_url_validate(w->instance_id, url, net_options, &httpcode); } else { /* full scale agent login-logout request */ char *agent_token = NULL; validate_status = am_agent_login(w->instance_id, url, conf->user, conf->pass, conf->realm, net_options, &agent_token, NULL, NULL, NULL); if (agent_token != NULL) { am_agent_logout(0, url, agent_token, net_options); free(agent_token); httpcode = 200; } } if (validate_status == AM_SUCCESS && httpcode != 0) { if (ok++ > conf->valid_ping_ok) { ok = conf->valid_ping_ok; } fail = 0; } else { if (fail++ > conf->valid_ping_miss) { fail = conf->valid_ping_miss; } ok = 0; } set_validation_table_entry(w->instance_id, i, ok, fail); } /* map stored index value to our ordered list index */ for (i = 0; i < conf->valid_default_url_sz; i++) { if (current_index == conf->valid_default_url[i]) { current_index = i; break; } } default_ok = current_ok = current_fail = 0; /* fetch validation table entry for the current_index * (which now corresponds to the default.url.set value/index) */ get_validation_table_entry(w->instance_id, current_index, ¤t_ok, ¤t_fail, &default_ok); /* do the fail-over logic */ do { if (current_ok > 0) { if (current_index > 0 && default_ok >= conf->valid_ping_ok) { set_valid_url_index(w->instance_id, conf->valid_default_url[0]); AM_LOG_INFO(w->instance_id, "%s fail-back to %s", thisfunc, url_list[0]); } else { set_valid_url_index(w->instance_id, conf->valid_default_url[current_index]); AM_LOG_INFO(w->instance_id, "%s continue with %s", thisfunc, url_list[current_index]); } break; } /* current index is not valid; check ping.miss.count */ if (current_ok == 0 && current_fail <= conf->valid_ping_miss) { set_valid_url_index(w->instance_id, conf->valid_default_url[current_index]); AM_LOG_INFO(w->instance_id, "%s still staying with %s", thisfunc, url_list[current_index]); break; } /* find next valid index value to fail-over to */ next_ok = 0; AM_MUTEX_LOCK(&table_mutex); AM_LIST_FOR_EACH(table, e, t) { if (e->instance_id == w->instance_id && e->index == 0) { default_ok = e->ok; } if (e->instance_id == w->instance_id && e->ok > 0) { next_ok = e->ok; i = e->index; break; } } AM_MUTEX_UNLOCK(&table_mutex); if (next_ok == 0) { AM_LOG_WARNING(w->instance_id, "%s none of the values are valid, defaulting to %s", thisfunc, url_list[0]); set_valid_url_index(w->instance_id, conf->valid_default_url[0]); break; } if (current_index > 0 && default_ok >= conf->valid_ping_ok) { AM_LOG_INFO(w->instance_id, "%s fail-back to %s", thisfunc, url_list[0]); set_valid_url_index(w->instance_id, conf->valid_default_url[0]); break; } AM_LOG_INFO(w->instance_id, "%s fail-over to %s", thisfunc, url_list[i]); set_valid_url_index(w->instance_id, conf->valid_default_url[i]); } while (0); am_net_options_delete(net_options); free(net_options); am_config_free(&conf); set_valid_url_instance_running(w->instance_id, AM_FALSE); AM_FREE(w->config_path, w); URL_LIST_FREE(url_list, url_list_sz); }