Beispiel #1
0
/**
 * 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, &current_ok, &current_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);
}