示例#1
0
void gdmaps_test_lookup_check(const gdmaps_t* gdmaps, const char* map_name, const char* addr_txt, const char* dclist_cmp, const unsigned scope_cmp) {
    const int rv = gdmaps_name2idx(gdmaps, map_name);
    if(rv < 0)
        log_fatal("Map name '%s' not found in configuration", map_name);

    const unsigned map_idx = (unsigned)rv;

    client_info_t cinfo;
    cinfo.edns_client_mask = 128U;
    unsigned scope = 175U;

    const int addr_err = gdnsd_anysin_getaddrinfo(addr_txt, NULL, &cinfo.edns_client);
    if(addr_err)
        log_fatal("Cannot parse address '%s': %s", addr_txt, gai_strerror(addr_err));

    const uint8_t* dclist = gdmaps_lookup(gdmaps, map_idx, &cinfo, &scope);

    ok(!strcmp((const char*)dclist, dclist_cmp),
        "gdmaps_lookup(%s, %s) returns dclist %s (got %s)",
            map_name, addr_txt,
            gdmaps_logf_dclist(gdmaps, map_idx, (const uint8_t*)dclist_cmp),
            gdmaps_logf_dclist(gdmaps, map_idx, dclist));

    ok(scope == scope_cmp,
        "gdmaps_lookup(%s, %s) returns scope %u (got %u)",
            map_name, addr_txt, scope_cmp, scope);
}
示例#2
0
F_NONNULL
static dc_t* config_res_perdc(const unsigned mapnum, const vscf_data_t* cfg, const char* resname) {
    dmn_assert(cfg); dmn_assert(resname);
    dmn_assert(vscf_is_hash(cfg));

    const unsigned num_dcs = vscf_hash_get_len(cfg);
    dc_t* store = calloc((num_dcs + 1), sizeof(dc_t));
    for(unsigned i = 0; i < num_dcs; i++) {
        const char* dcname = vscf_hash_get_key_byindex(cfg, i, NULL);
        const unsigned dc_idx = map_get_dcidx(mapnum, dcname);
        if(!dc_idx)
            log_fatal("plugin_" PNSTR ": resource '%s': datacenter name '%s' is not valid", resname, dcname);
        dmn_assert(dc_idx <= num_dcs);
        dc_t* this_dc = &store[dc_idx];
        this_dc->dc_name = strdup(dcname);
        const vscf_data_t* plugdata = vscf_hash_get_data_byindex(cfg, i);
        if(vscf_is_simple(plugdata)) {
            const char* textdata = vscf_simple_get_data(plugdata);
            if(*textdata == '%') {
                char* child_plugname = strdup(textdata + 1);
                this_dc->plugin_name = child_plugname;
                char* child_resname = strchr(child_plugname, '!');
                if(child_resname) {
                    *child_resname++ = '\0';
                    this_dc->res_name = strdup(child_resname);
                }
                if(!strcmp(this_dc->plugin_name, PNSTR) && !strcmp(this_dc->res_name, resname))
                    log_fatal("plugin_" PNSTR ": resource '%s': not allowed to reference itself!", resname);
            }
            else if(*textdata == '!') {
                this_dc->res_name = strdup(textdata + 1);
                const vscf_data_t* res_cfg = vscf_get_parent(cfg);
                this_dc->plugin_name = get_defaulted_plugname(res_cfg, resname, dcname);
                if(!strcmp(this_dc->plugin_name, PNSTR) && !strcmp(this_dc->res_name, resname))
                    log_fatal("plugin_" PNSTR ": resource '%s': not allowed to reference itself!", resname);
            }
            else {
                anysin_t tempsin;
                if(gdnsd_anysin_getaddrinfo(textdata, NULL, &tempsin)) {
                    // failed to parse as address, so set up direct CNAME if possible
                    uint8_t* dname = malloc(256);
                    dname_status_t dnstat = vscf_simple_get_as_dname(plugdata, dname);
                    if(dnstat == DNAME_INVALID)
                        log_fatal("plugin_" PNSTR ": resource '%s': CNAME for datacenter '%s' is not a legal domainname", resname, dcname);
                    if(dnstat == DNAME_VALID)
                        dname = dname_trim(dname);
                    this_dc->dname = dname;
                }
                else {
                    inject_child_plugin_config(this_dc, resname, (vscf_data_t*)plugdata);
                }
            }
        }
        else {
            inject_child_plugin_config(this_dc, resname, (vscf_data_t*)plugdata);
        }
    }
    return store;
}
示例#3
0
文件: proxy.c 项目: gdnsd/gdnsd
F_NONNULL
static size_t parse_proxy_v1(char* v1, const size_t dlen, gdnsd_anysin_t* sa)
{
    gdnsd_assert(dlen >= 8U);
    gdnsd_assert(!memcmp(v1, "PROXY ", 6));

    char* end = memchr(v1, '\r', dlen - 1U);
    if (unlikely(!end || end[1] != '\n' || (end - v1) < 16)) {
        log_debug("Proxy v1 parse from %s failed: no CRLF found or line too short", logf_anysin(sa));
        return 0;
    }
    *end = '\0'; // terminate whole string

    const char* proto = &v1[6]; // just after "PROXY "
    if (unlikely(memcmp(proto, "TCP4 ", 5U) && memcmp(proto, "TCP6 ", 5U))) {
        log_debug("Proxy v1 parse from %s failed: protocol must be TCP4 or TCP6", logf_anysin(sa));
        return 0;
    }

    char* srcaddr = &v1[11]; // just after "TCPx "
    char* dstaddr = strchr(srcaddr, ' ');
    if (unlikely(!dstaddr || dstaddr >= end)) {
        log_debug("Proxy v1 parse from %s failed: cannot find dest addr", logf_anysin(sa));
        return 0;
    }
    *dstaddr = '\0'; // terminate srcaddr
    dstaddr++;
    char* srcport = strchr(dstaddr, ' ');
    if (unlikely(!srcport || srcport >= end)) {
        log_debug("Proxy v1 parse from %s failed: cannot find source port", logf_anysin(sa));
        return 0;
    }
    *srcport = '\0'; // terminate dstaddr
    srcport++;
    char* dstport = strchr(srcport, ' ');
    if (unlikely(!dstport || dstport >= end)) {
        log_debug("Proxy v1 parse from %s failed: cannot find dest port", logf_anysin(sa));
        return 0;
    }
    *dstport = '\0'; // terminate srcport

    const int addr_err = gdnsd_anysin_getaddrinfo(srcaddr, srcport, sa);
    if (unlikely(addr_err)) {
        log_debug("Proxy v1 parse from %s: getaddrinfo('%s', '%s') failed: %s",
                  logf_anysin(sa), srcaddr, srcport, gai_strerror(addr_err));
        return 0;
    }

    gdnsd_assert(end >= v1);
    const size_t skip_read = (size_t)(end + 2 - v1); // skip header through CRLF
    gdnsd_assert(skip_read);
    gdnsd_assert(skip_read <= sizeof(proxy_hdr_t));
    return skip_read;
}
示例#4
0
F_NONNULL
static void do_lookup(const gdmaps_t* gdmaps, const char* map_name, const char* ip_arg) {
    dmn_assert(gdmaps); dmn_assert(map_name); dmn_assert(ip_arg);

    int map_idx = gdmaps_name2idx(gdmaps, map_name);
    if(map_idx < 0) {
        log_err("Mapping name '%s' not found in configuration", map_name);
        return;
    }

    client_info_t cinfo;

    // mostly ignored, but needs to be nonzero, and 150 is interesting in that
    //  it easily differentiates source -> scope copies from actual database scope netmasks,
    //  since it's larger than any legal netmask in the database.
    cinfo.edns_client_mask = 150U;

    const int addr_err = gdnsd_anysin_getaddrinfo(ip_arg, NULL, &cinfo.edns_client);
    if(addr_err) {
        log_err("Could not parse address '%s': %s", ip_arg, gai_strerror(addr_err));
        return;
    }

    // To void gdmaps fallback pitfalls
    memcpy(&cinfo.dns_source, &cinfo.edns_client, sizeof(dmn_anysin_t));

    // w/ edns_client_mask set, scope_mask should *always* be set by gdmaps_lookup();
    // (and regardless, dclist should also always be set and contain something)
    unsigned scope_mask = 175U;
    const uint8_t* dclist = gdmaps_lookup(gdmaps, map_idx, &cinfo, &scope_mask);
    dmn_assert(scope_mask != 175U);
    dmn_assert(dclist);

    // Scope was set to Source.  Since we always query as edns, this implies
    //  the database was V4-only and the address input was a non-v4-compat v6 address,
    //  and the lookup code fell back to the default dclist (1).
    if(scope_mask == 150U) {
        printf(
            "%s => %s => %s\n",
            map_name, dmn_logf_anysin_noport(&cinfo.edns_client),
            gdmaps_logf_dclist(gdmaps, map_idx, dclist)
        );
    }
    else {
        printf(
            "%s => %s/%u => %s\n",
            map_name, dmn_logf_anysin_noport(&cinfo.edns_client), scope_mask,
            gdmaps_logf_dclist(gdmaps, map_idx, dclist)
        );
    }

    dmn_fmtbuf_reset();
}
示例#5
0
文件: weighted.c 项目: fabled/gdnsd
F_NONNULL
static bool config_addr_group_addr(const char* lb_name, const unsigned lb_name_len, const vscf_data_t* lb_data, void* iaga_asvoid) {
    dmn_assert(lb_name); dmn_assert(lb_name_len); dmn_assert(lb_data); dmn_assert(iaga_asvoid);

    iaga_t* iaga = (iaga_t*)iaga_asvoid;

    addrset_t* addrset = iaga->addrset;
    res_aitem_t* res_item = iaga->res_item;
    unsigned lb_idx = iaga->lb_idx++;
    const char* res_name = iaga->res_name;
    const char* stanza = iaga->stanza;
    const char* item_name = iaga->item_name;
    const bool ipv6 = iaga->ipv6;
    const unsigned res_name_len = strlen(res_name);
    const unsigned item_name_len = strlen(item_name);

    long lb_weight = 0;
    if(!vscf_is_array(lb_data)
            || (2 != vscf_array_get_len(lb_data))
            || !vscf_is_simple(vscf_array_get_data(lb_data, 0))
            || !vscf_is_simple(vscf_array_get_data(lb_data, 1))
            || !vscf_simple_get_as_long(vscf_array_get_data(lb_data, 1), &lb_weight)
            || lb_weight < 1 || lb_weight > MAX_WEIGHT )
        log_fatal("plugin_weighted: resource '%s', group '%s': values in address group mode must be arrays of [ IPADDR, WEIGHT ], where weight must be an integer in the range 1 - " MAX_WEIGHT_STR, res_name, item_name);

    res_item->as[lb_idx].states = calloc(addrset->num_svcs, sizeof(mon_state_t));
    res_item->as[lb_idx].weight = lb_weight;

    const char* addr_txt = vscf_simple_get_data(vscf_array_get_data(lb_data, 0));
    int addr_err = gdnsd_anysin_getaddrinfo(addr_txt, NULL, &res_item->as[lb_idx].addr);
    if(addr_err)
        log_fatal("plugin_weighted: resource '%s', group '%s', addr '%s': parsing '%s' as an IP address failed: %s", res_name, item_name, lb_name, addr_txt, gai_strerror(addr_err));
    if(ipv6 && res_item->as[lb_idx].addr.sa.sa_family != AF_INET6)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': '%s' is IPv4, was expecting IPv6", res_name, stanza, item_name, addr_txt);
    else if(!ipv6 && res_item->as[lb_idx].addr.sa.sa_family != AF_INET)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': '%s' is IPv6, was expecting IPv4", res_name, stanza, item_name, addr_txt);

    for(unsigned i = 0; i < addrset->num_svcs; i++) {
        const unsigned svc_name_len = strlen(addrset->svc_names[i]);
        char *complete_desc = malloc(res_name_len + 1 + 4 + 1 + item_name_len + 1 + lb_name_len + 1 + svc_name_len + 1);
        sprintf(complete_desc, "%s/%s/%s/%s/%s", res_name, ipv6 ? "ipv6" : "ipv4", item_name, lb_name, addrset->svc_names[i]);
        mon_list.info = realloc(mon_list.info, sizeof(mon_info_t) * (mon_list.count + 1));
        mon_info_t* m = &mon_list.info[mon_list.count++];
        m->svctype = addrset->svc_names[i];
        m->desc = complete_desc;
        m->addr = addr_txt;
        m->state_ptr = &res_item->as[lb_idx].states[i];
    }

    log_debug("plugin_weighted: resource '%s' (%s), item '%s', address %s added with weight %u", res_name, stanza, item_name, addr_txt, res_item->as[lb_idx].weight);

    return true;
}
示例#6
0
void gdmaps_test_lookup_noop(const gdmaps_t* gdmaps, const char* map_name, const char* addr_txt) {
    const int rv = gdmaps_name2idx(gdmaps, map_name);
    if(rv < 0)
        log_fatal("Map name '%s' not found in configuration", map_name);
    const unsigned map_idx = (unsigned)rv;

    client_info_t cinfo;
    cinfo.edns_client_mask = 128U;
    unsigned scope = 175U;

    const int addr_err = gdnsd_anysin_getaddrinfo(addr_txt, NULL, &cinfo.edns_client);
    if(addr_err)
        log_fatal("Cannot parse address '%s': %s", addr_txt, gai_strerror(addr_err));

    gdmaps_lookup(gdmaps, map_idx, &cinfo, &scope);
    ok(1, "gdmaps_lookup(%s, %s) did not crash", map_name, addr_txt);
}
示例#7
0
文件: weighted.c 项目: fabled/gdnsd
F_NONNULL
static void config_item_addrs(res_aitem_t* res_item, const char* res_name, const char* stanza, const char* item_name, const bool ipv6, const vscf_data_t* cfg_data, addrset_t* addrset) {
    dmn_assert(res_name); dmn_assert(stanza); dmn_assert(item_name);
    dmn_assert(res_item); dmn_assert(cfg_data); dmn_assert(addrset);

    const unsigned res_name_len = strlen(res_name);
    const unsigned item_name_len = strlen(item_name);

    long wtemp = 0;
    if(!vscf_is_array(cfg_data)
            || (2 != vscf_array_get_len(cfg_data))
            || !vscf_is_simple(vscf_array_get_data(cfg_data, 0))
            || !vscf_is_simple(vscf_array_get_data(cfg_data, 1))
            || !vscf_simple_get_as_long(vscf_array_get_data(cfg_data, 1), &wtemp)
            || wtemp < 1 || wtemp > MAX_WEIGHT )
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': values in addrs mode must be arrays of [ IPADDR, WEIGHT ], where weight must be an integer in the range 1 - " MAX_WEIGHT_STR, res_name, stanza, item_name);

    res_item->count = 1;
    res_item->as = calloc(res_item->count, sizeof(addrstate_t));
    res_item->as[0].states = calloc(addrset->num_svcs, sizeof(mon_state_t));
    res_item->as[0].weight = wtemp;
    res_item->max_weight = wtemp;
    res_item->weight = wtemp;

    const char* addr_txt = vscf_simple_get_data(vscf_array_get_data(cfg_data, 0));
    int addr_err = gdnsd_anysin_getaddrinfo(addr_txt, NULL, &res_item->as[0].addr);
    if(addr_err)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': parsing '%s' as an IP address failed: %s", res_name, stanza, item_name, addr_txt, gai_strerror(addr_err));
    if(ipv6 && res_item->as[0].addr.sa.sa_family != AF_INET6)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': '%s' is IPv4, was expecting IPv6", res_name, stanza, item_name, addr_txt);
    else if(!ipv6 && res_item->as[0].addr.sa.sa_family != AF_INET)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': '%s' is IPv6, was expecting IPv4", res_name, stanza, item_name, addr_txt);

    for(unsigned i = 0; i < addrset->num_svcs; i++) {
        const unsigned svc_name_len = strlen(addrset->svc_names[i]);
        char *complete_desc = malloc(res_name_len + 1 + 4 + 1 + item_name_len + 1 + svc_name_len + 1);
        sprintf(complete_desc, "%s/%s/%s/%s", res_name, ipv6 ? "ipv6" : "ipv4", item_name, addrset->svc_names[i]);
        mon_list.info = realloc(mon_list.info, sizeof(mon_info_t) * (mon_list.count + 1));
        mon_info_t* m = &mon_list.info[mon_list.count++];
        m->svctype = addrset->svc_names[i];
        m->desc = complete_desc;
        m->addr = addr_txt;
        m->state_ptr = &res_item->as[0].states[i];
    }
    log_debug("plugin_weighted: resource '%s' (%s), item '%s': A '%s' added w/ weight %u", res_name, stanza, item_name, addr_txt, res_item->weight);
}
示例#8
0
文件: weighted.c 项目: jasperla/gdnsd
F_NONNULL
static bool config_addr_group_addr(const char* lb_name, const unsigned lb_name_len V_UNUSED, const vscf_data_t* lb_data, void* iaga_asvoid) {
    dmn_assert(lb_name); dmn_assert(lb_name_len); dmn_assert(lb_data); dmn_assert(iaga_asvoid);

    iaga_t* iaga = (iaga_t*)iaga_asvoid;

    addrset_t* addrset = iaga->addrset;
    res_aitem_t* res_item = iaga->res_item;
    unsigned lb_idx = iaga->lb_idx++;
    const char* res_name = iaga->res_name;
    const char* stanza = iaga->stanza;
    const char* item_name = iaga->item_name;
    const bool ipv6 = iaga->ipv6;

    long lb_weight = 0;
    if(!vscf_is_array(lb_data)
            || (2 != vscf_array_get_len(lb_data))
            || !vscf_is_simple(vscf_array_get_data(lb_data, 0))
            || !vscf_is_simple(vscf_array_get_data(lb_data, 1))
            || !vscf_simple_get_as_long(vscf_array_get_data(lb_data, 1), &lb_weight)
            || lb_weight < 1 || lb_weight > MAX_WEIGHT )
        log_fatal("plugin_weighted: resource '%s', group '%s': values in address group mode must be arrays of [ IPADDR, WEIGHT ], where weight must be an integer in the range 1 - " MAX_WEIGHT_STR, res_name, item_name);

    res_item->as[lb_idx].weight = lb_weight;

    const char* addr_txt = vscf_simple_get_data(vscf_array_get_data(lb_data, 0));
    int addr_err = gdnsd_anysin_getaddrinfo(addr_txt, NULL, &res_item->as[lb_idx].addr);
    if(addr_err)
        log_fatal("plugin_weighted: resource '%s', group '%s', addr '%s': parsing '%s' as an IP address failed: %s", res_name, item_name, lb_name, addr_txt, gai_strerror(addr_err));
    if(ipv6 && res_item->as[lb_idx].addr.sa.sa_family != AF_INET6)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': '%s' is IPv4, was expecting IPv6", res_name, stanza, item_name, addr_txt);
    else if(!ipv6 && res_item->as[lb_idx].addr.sa.sa_family != AF_INET)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': '%s' is IPv6, was expecting IPv4", res_name, stanza, item_name, addr_txt);

    if(addrset->num_svcs) {
        res_item->as[lb_idx].indices = malloc(addrset->num_svcs * sizeof(unsigned));
        for(unsigned i = 0; i < addrset->num_svcs; i++)
            res_item->as[lb_idx].indices[i] = gdnsd_mon_addr(addrset->svc_names[i], &res_item->as[lb_idx].addr);
    }

    log_debug("plugin_weighted: resource '%s' (%s), item '%s', address %s added with weight %u", res_name, stanza, item_name, addr_txt, res_item->as[lb_idx].weight);

    return true;
}
示例#9
0
void gdmaps_lookup_noop(const unsigned tnum, const gdmaps_t* gdmaps, const char* map_name, const char* addr_txt) {
    dmn_assert(gdmaps);
    dmn_assert(map_name);
    dmn_assert(addr_txt);

    log_info("Subtest %u starting", tnum);

    int map_idx = gdmaps_name2idx(gdmaps, map_name);
    if(map_idx < 0)
        log_fatal("Subtest %u failed: Map name '%s' not found in configuration", tnum, map_name);

    client_info_t cinfo;
    cinfo.edns_client_mask = 128U;
    unsigned scope = 175U;

    const int addr_err = gdnsd_anysin_getaddrinfo(addr_txt, NULL, &cinfo.edns_client);
    if(addr_err)
        log_fatal("Subtest %u failed: Cannot parse address '%s': %s", tnum, addr_txt, gai_strerror(addr_err));

    gdmaps_lookup(gdmaps, map_idx, &cinfo, &scope);
}
示例#10
0
void gdmaps_test_lookup_check(const unsigned tnum, const gdmaps_t* gdmaps, const char* map_name, const char* addr_txt, const char* dclist_cmp, const unsigned scope_cmp) {
    dmn_assert(gdmaps);
    dmn_assert(map_name);
    dmn_assert(addr_txt);
    dmn_assert(dclist_cmp);

    log_info("Subtest %u starting", tnum);

    int map_idx = gdmaps_name2idx(gdmaps, map_name);
    if(map_idx < 0)
        log_fatal("Subtest %u failed: Map name '%s' not found in configuration", tnum, map_name);

    client_info_t cinfo;
    cinfo.edns_client_mask = 150U;
    unsigned scope = 175U;

    const int addr_err = gdnsd_anysin_getaddrinfo(addr_txt, NULL, &cinfo.edns_client);
    if(addr_err)
        log_fatal("Subtest %u failed: Cannot parse address '%s': %s", tnum, addr_txt, gai_strerror(addr_err));

    // To void gdmaps fallback pitfalls
    memcpy(&cinfo.dns_source, &cinfo.edns_client, sizeof(anysin_t));
    const uint8_t* dclist = gdmaps_lookup(gdmaps, map_idx, &cinfo, &scope);

    // w/ edns_client_mask set, scope_mask should *always* be set by gdmaps_lookup();
    // (and regardless, dclist should also always be set and contain something)
    if(!dclist)
        log_fatal("Subtest %u failed: gdmaps_lookup(%s, %s) returned NULL", tnum, map_name, addr_txt);
    if(scope == 175U)
        log_fatal("Subtest %u failed: gdmaps_lookup(%s, %s) failed to set the scope mask", tnum, map_name, addr_txt);

    if(strcmp((const char*)dclist, dclist_cmp))
        log_fatal("Subtest %u failed: Wanted dclist %s, got dclist %s", tnum,
            gdmaps_logf_dclist(gdmaps, map_idx, (const uint8_t*)dclist_cmp),
            gdmaps_logf_dclist(gdmaps, map_idx, dclist));

    if(scope != scope_cmp)
        log_fatal("Subtest %u failed: Wanted scope mask %u, got %u", tnum, scope_cmp, scope);
}
示例#11
0
文件: weighted.c 项目: jasperla/gdnsd
F_NONNULL
static void config_item_addrs(res_aitem_t* res_item, const char* res_name, const char* stanza, const char* item_name, const bool ipv6, const vscf_data_t* cfg_data, addrset_t* addrset) {
    dmn_assert(res_name); dmn_assert(stanza); dmn_assert(item_name);
    dmn_assert(res_item); dmn_assert(cfg_data); dmn_assert(addrset);

    long wtemp = 0;
    if(!vscf_is_array(cfg_data)
            || (2 != vscf_array_get_len(cfg_data))
            || !vscf_is_simple(vscf_array_get_data(cfg_data, 0))
            || !vscf_is_simple(vscf_array_get_data(cfg_data, 1))
            || !vscf_simple_get_as_long(vscf_array_get_data(cfg_data, 1), &wtemp)
            || wtemp < 1 || wtemp > MAX_WEIGHT )
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': values in addrs mode must be arrays of [ IPADDR, WEIGHT ], where weight must be an integer in the range 1 - " MAX_WEIGHT_STR, res_name, stanza, item_name);

    res_item->count = 1;
    res_item->as = calloc(res_item->count, sizeof(addrstate_t));
    res_item->as[0].weight = wtemp;
    res_item->max_weight = wtemp;
    res_item->weight = wtemp;

    const char* addr_txt = vscf_simple_get_data(vscf_array_get_data(cfg_data, 0));
    int addr_err = gdnsd_anysin_getaddrinfo(addr_txt, NULL, &res_item->as[0].addr);
    if(addr_err)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': parsing '%s' as an IP address failed: %s", res_name, stanza, item_name, addr_txt, gai_strerror(addr_err));
    if(ipv6 && res_item->as[0].addr.sa.sa_family != AF_INET6)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': '%s' is IPv4, was expecting IPv6", res_name, stanza, item_name, addr_txt);
    else if(!ipv6 && res_item->as[0].addr.sa.sa_family != AF_INET)
        log_fatal("plugin_weighted: resource '%s' (%s): item '%s': '%s' is IPv6, was expecting IPv4", res_name, stanza, item_name, addr_txt);

    if(addrset->num_svcs) {
        res_item->as[0].indices = malloc(addrset->num_svcs * sizeof(unsigned));
        for(unsigned i = 0; i < addrset->num_svcs; i++)
            res_item->as[0].indices[i] = gdnsd_mon_addr(addrset->svc_names[i], &res_item->as[0].addr);
    }
    log_debug("plugin_weighted: resource '%s' (%s), item '%s': A '%s' added w/ weight %u", res_name, stanza, item_name, addr_txt, res_item->weight);
}
示例#12
0
文件: nets.c 项目: lastsky/gdnsd
// arguably, with at least some of the v4-like spaces we could simply translate and hope to de-dupe,
//   if we upgraded nlist_normalize1 to de-dupe matching dclists instead of failing them
F_NONNULL
static bool nets_parse(vscf_data_t* nets_cfg, dclists_t* dclists, const char* map_name, nlist_t* nl) {
    bool rv = false;

    const unsigned input_nnets = vscf_hash_get_len(nets_cfg);

    for(unsigned i = 0; i < input_nnets; i++) {
        // convert 192.0.2.0/24 -> anysin_t w/ mask in port field
        unsigned net_str_len = 0;
        const char* net_str_cfg = vscf_hash_get_key_byindex(nets_cfg, i, &net_str_len);
        char net_str[net_str_len + 1];
        memcpy(net_str, net_str_cfg, net_str_len + 1);

        char* mask_str = strchr(net_str, '/');
        if(!mask_str) {
            log_err("plugin_geoip: map '%s': nets entry '%s' does not parse as addr/mask", map_name, net_str);
            rv = true;
            break;
        }
        *mask_str++ = '\0';
        dmn_anysin_t tempsin;
        int addr_err = gdnsd_anysin_getaddrinfo(net_str, mask_str, &tempsin);
        if(addr_err) {
            log_err("plugin_geoip: map '%s': nets entry '%s/%s' does not parse as addr/mask: %s", map_name, net_str, mask_str, gai_strerror(addr_err));
            rv = true;
            break;
        }

        unsigned mask;
        uint8_t ipv6[16];

        // now store the anysin data into net_t
        if(tempsin.sa.sa_family == AF_INET6) {
            mask = ntohs(tempsin.sin6.sin6_port);
            if(mask > 128) {
                log_err("plugin_geoip: map '%s': nets entry '%s/%s': illegal IPv6 mask (>128)", map_name, net_str, mask_str);
                rv = true;
                break;
            }
            memcpy(ipv6, tempsin.sin6.sin6_addr.s6_addr, 16);
            if(check_v4_issues(ipv6, mask)) {
                log_err("plugin_geoip: map '%s': 'nets' entry '%s/%s' covers illegal IPv4-like space, see the documentation for more info", map_name, net_str, mask_str);
                rv = true;
                break;
            }
        }
        else {
            dmn_assert(tempsin.sa.sa_family == AF_INET);
            mask = ntohs(tempsin.sin.sin_port) + 96U;
            if(mask > 128) {
                log_err("plugin_geoip: map '%s': nets entry '%s/%s': illegal IPv4 mask (>32)", map_name, net_str, mask_str);
                rv = true;
                break;
            }
            memset(ipv6, 0, 16);
            memcpy(&ipv6[12], &tempsin.sin.sin_addr.s_addr, 4);
        }

        // get dclist integer from rhs
        vscf_data_t* dc_cfg = vscf_hash_get_data_byindex(nets_cfg, i);
        const uint32_t dclist = dclists_find_or_add_vscf(dclists, dc_cfg, map_name, false);
        dmn_assert(dclist <= DCLIST_MAX); // auto not allowed here
        nlist_append(nl, ipv6, mask, dclist);
    }

    return rv;
}
示例#13
0
文件: weighted.c 项目: fabled/gdnsd
F_NONNULL
static void config_cnameset(const char* res_name, const char* stanza, cnset_t* cnset, const vscf_data_t* cfg) {
    dmn_assert(res_name); dmn_assert(stanza); dmn_assert(cnset); dmn_assert(cfg);

    if(!vscf_is_hash(cfg))
        log_fatal("plugin_weighted: resource '%s' stanza '%s' value must be a hash", res_name, stanza);

    cnset->count = vscf_hash_get_len(cfg);

    if(cnset->count > MAX_ITEMS_PER_SET)
        log_fatal("plugin_weighted: resource '%s' (%s): number of cnames cannot be more than %u", res_name, stanza, MAX_ITEMS_PER_SET);
    if(!cnset->count)
        log_fatal("plugin_weighted: resource '%s' (%s): empty cname sets not allowed", res_name, stanza);

    cnset->items = calloc(cnset->count, sizeof(res_citem_t));
    cname_iter_data_t cid = {
        .cnset = cnset,
        .res_name = res_name,
        .stanza = stanza,
        .item_idx = 0,
    };
    vscf_hash_iterate(cfg, true, config_item_cname, &cid);

    cnset->weight = 0;
    for(unsigned i = 0; i < cnset->count; i++) {
        const unsigned cwt = cnset->items[i].weight;
        dmn_assert(cwt);
        cnset->weight += cwt;
    }

    dmn_assert(cnset->weight);
}

F_NONNULL
static void config_auto(resource_t* res, const vscf_data_t* res_cfg) {
    dmn_assert(res); dmn_assert(res_cfg); dmn_assert(vscf_is_hash(res_cfg));

    // mark all possible parameter-keys
    vscf_hash_get_data_byconstkey(res_cfg, "service_types", true);
    vscf_hash_get_data_byconstkey(res_cfg, "multi", true);
    vscf_hash_get_data_byconstkey(res_cfg, "up_thresh", true);

    // make a copy that contains no parameters, only item-name keys
    vscf_data_t* res_cfg_noparams = vscf_clone(res_cfg, true);

    if(!vscf_hash_get_len(res_cfg_noparams))
        log_fatal("plugin_weighted: resource '%s' (direct) contains no weighted items", res->name);

    const char* first_name = vscf_hash_get_key_byindex(res_cfg_noparams, 0, NULL);
    const vscf_data_t* first_cfg = vscf_hash_get_data_byindex(res_cfg_noparams, 0);
    if(vscf_is_hash(first_cfg)) { // grouped address mode...
        if(!vscf_hash_get_len(first_cfg))
            log_fatal("plugin_weighted: resource '%s' (direct): group '%s': contains no addresses", res->name, first_name);
        const char* lb_name = vscf_hash_get_key_byindex(first_cfg, 0, NULL);
        const vscf_data_t* lb_cfg = vscf_hash_get_data_byindex(first_cfg, 0);
        if(!vscf_is_array(lb_cfg) || !vscf_array_get_len(lb_cfg) || !vscf_is_simple(vscf_array_get_data(lb_cfg, 0)))
            log_fatal("plugin_weighted: resource '%s' (direct): group '%s': item '%s': value must be an array of [ IP, weight ]", res->name, first_name, lb_name);
        const char* first_addr_txt = vscf_simple_get_data(vscf_array_get_data(lb_cfg, 0));
        anysin_t temp_sin;
        int addr_err = gdnsd_anysin_getaddrinfo(first_addr_txt, NULL, &temp_sin);
        if(addr_err)
            log_fatal("plugin_weighted: resource '%s' (direct): group '%s': item '%s': could not parse '%s' as an IP address: %s", res->name, first_name, lb_name, first_addr_txt, gai_strerror(addr_err));
        if(temp_sin.sa.sa_family == AF_INET6) {
            res->addrs_v6 = calloc(1, sizeof(addrset_t));
            config_addrset(res->name, "direct", true, res->addrs_v6, res_cfg);
        }
        else {
            dmn_assert(temp_sin.sa.sa_family == AF_INET);
            res->addrs_v4 = calloc(1, sizeof(addrset_t));
            config_addrset(res->name, "direct", false, res->addrs_v4, res_cfg);
        }
    }
    else if(vscf_is_array(first_cfg)) { // ungrouped address, or cnames
        const vscf_data_t* first_ac = vscf_array_get_data(first_cfg, 0);
        if(!first_ac || !vscf_is_simple(first_ac))
            log_fatal("plugin_weighted: resource '%s' (direct): item '%s': first element of array should be an IP address or CNAME string", res->name, first_name);
        anysin_t temp_sin;
        if(gdnsd_anysin_getaddrinfo(vscf_simple_get_data(first_ac), NULL, &temp_sin)) {
            // was not a valid address, try cnames mode
            res->cnames = calloc(1, sizeof(cnset_t));
            config_cnameset(res->name, "direct", res->cnames, res_cfg_noparams);
        }
        else {
            // was a valid address, try addrset mode
            if(temp_sin.sa.sa_family == AF_INET6) {
                res->addrs_v6 = calloc(1, sizeof(addrset_t));
                config_addrset(res->name, "direct", true, res->addrs_v6, res_cfg);
            }
            else {
                dmn_assert(temp_sin.sa.sa_family == AF_INET);
                res->addrs_v4 = calloc(1, sizeof(addrset_t));
                config_addrset(res->name, "direct", false, res->addrs_v4, res_cfg);
            }
        }
    }
    else {
        log_fatal("plugin_weighted: resource '%s' (direct): item '%s': resource type not detectable (should be array of [ IP, weight ], array of [ CNAME, weight ], or hashed address group ...)", res->name, first_name);
    }

    vscf_destroy(res_cfg_noparams);
}
示例#14
0
文件: weighted.c 项目: jasperla/gdnsd
F_NONNULL
static void config_cnameset(const char* res_name, const char* stanza, cnset_t* cnset, const vscf_data_t* cfg) {
    dmn_assert(res_name); dmn_assert(stanza); dmn_assert(cnset); dmn_assert(cfg);

    if(!vscf_is_hash(cfg))
        log_fatal("plugin_weighted: resource '%s' stanza '%s' value must be a hash", res_name, stanza);

    cnset->count = vscf_hash_get_len(cfg);

    // service_types
    cnset->num_svcs = 0;
    const vscf_data_t* res_stypes = vscf_hash_get_data_byconstkey(cfg, "service_types", true);
    if (res_stypes) {
        cnset->count--; // minus one for service_types entry
        cnset->num_svcs = vscf_array_get_len(res_stypes);
        if(cnset->num_svcs) {
            cnset->svc_names = malloc(cnset->num_svcs * sizeof(char*));
            for(unsigned i = 0; i < cnset->num_svcs; i++) {
                const vscf_data_t* this_svc_cfg = vscf_array_get_data(res_stypes, i);
                if(!vscf_is_simple(this_svc_cfg))
                    log_fatal("plugin_weighted: resource '%s' (%s): service_types values must be strings", res_name, stanza);
                cnset->svc_names[i] = strdup(vscf_simple_get_data(this_svc_cfg));
            }
        }
    }
    else {
        cnset->num_svcs = 1;
        cnset->svc_names = malloc(sizeof(char*));
        cnset->svc_names[0] = strdup(DEFAULT_SVCNAME);
    }

    // up threshold as double
    double up_thresh = 0.5;
    const vscf_data_t* thresh_cfg = vscf_hash_get_data_byconstkey(cfg, "up_thresh", true);
    if(thresh_cfg) {
        cnset->count--; // minus one for up_thresh entry
        if(!vscf_is_simple(thresh_cfg) || !vscf_simple_get_as_double(thresh_cfg, &up_thresh)
           || up_thresh <= 0.0 || up_thresh > 1.0)
            log_fatal("plugin_weighted: resource '%s' (%s): 'up_thresh' must be a floating point value in the range (0.0 - 1.0]", res_name, stanza);
    }

    // multi option is processed for count-correctness, but ignored (it's not legal
    //   here, but may be present due to inheritance of defaults!)
    if(vscf_hash_get_data_byconstkey(cfg, "multi", true))
        cnset->count--;

    if(cnset->count > MAX_ITEMS_PER_SET)
        log_fatal("plugin_weighted: resource '%s' (%s): number of cnames cannot be more than %u", res_name, stanza, MAX_ITEMS_PER_SET);
    if(!cnset->count)
        log_fatal("plugin_weighted: resource '%s' (%s): empty cname sets not allowed", res_name, stanza);

    cnset->items = calloc(cnset->count, sizeof(res_citem_t));
    cname_iter_data_t cid = {
        .cnset = cnset,
        .res_name = res_name,
        .stanza = stanza,
        .item_idx = 0,
    };
    vscf_hash_iterate(cfg, true, config_item_cname, &cid);

    cnset->weight = 0;
    for(unsigned i = 0; i < cnset->count; i++) {
        const unsigned cwt = cnset->items[i].weight;
        dmn_assert(cwt);
        cnset->weight += cwt;
    }

    dmn_assert(cnset->weight);

    cnset->up_weight = ceil(up_thresh * cnset->weight);
}

F_NONNULL
static void config_auto(resource_t* res, const vscf_data_t* res_cfg) {
    dmn_assert(res); dmn_assert(res_cfg); dmn_assert(vscf_is_hash(res_cfg));

    // mark all possible parameter-keys
    vscf_hash_get_data_byconstkey(res_cfg, "service_types", true);
    vscf_hash_get_data_byconstkey(res_cfg, "multi", true);
    vscf_hash_get_data_byconstkey(res_cfg, "up_thresh", true);

    // make a copy that contains no parameters, only item-name keys
    vscf_data_t* res_cfg_noparams = vscf_clone(res_cfg, true);

    if(!vscf_hash_get_len(res_cfg_noparams))
        log_fatal("plugin_weighted: resource '%s' (direct) contains no weighted items", res->name);

    const char* first_name = vscf_hash_get_key_byindex(res_cfg_noparams, 0, NULL);
    const vscf_data_t* first_cfg = vscf_hash_get_data_byindex(res_cfg_noparams, 0);
    if(vscf_is_hash(first_cfg)) { // grouped address mode...
        if(!vscf_hash_get_len(first_cfg))
            log_fatal("plugin_weighted: resource '%s' (direct): group '%s': contains no addresses", res->name, first_name);
        const char* lb_name = vscf_hash_get_key_byindex(first_cfg, 0, NULL);
        const vscf_data_t* lb_cfg = vscf_hash_get_data_byindex(first_cfg, 0);
        if(!vscf_is_array(lb_cfg) || !vscf_array_get_len(lb_cfg) || !vscf_is_simple(vscf_array_get_data(lb_cfg, 0)))
            log_fatal("plugin_weighted: resource '%s' (direct): group '%s': item '%s': value must be an array of [ IP, weight ]", res->name, first_name, lb_name);
        const char* first_addr_txt = vscf_simple_get_data(vscf_array_get_data(lb_cfg, 0));
        dmn_anysin_t temp_sin;
        int addr_err = gdnsd_anysin_getaddrinfo(first_addr_txt, NULL, &temp_sin);
        if(addr_err)
            log_fatal("plugin_weighted: resource '%s' (direct): group '%s': item '%s': could not parse '%s' as an IP address: %s", res->name, first_name, lb_name, first_addr_txt, gai_strerror(addr_err));
        if(temp_sin.sa.sa_family == AF_INET6) {
            res->addrs_v6 = calloc(1, sizeof(addrset_t));
            config_addrset(res->name, "direct", true, res->addrs_v6, res_cfg);
        }
        else {
            dmn_assert(temp_sin.sa.sa_family == AF_INET);
            res->addrs_v4 = calloc(1, sizeof(addrset_t));
            config_addrset(res->name, "direct", false, res->addrs_v4, res_cfg);
        }
    }
    else if(vscf_is_array(first_cfg)) { // ungrouped address, or cnames
        const vscf_data_t* first_ac = vscf_array_get_data(first_cfg, 0);
        if(!first_ac || !vscf_is_simple(first_ac))
            log_fatal("plugin_weighted: resource '%s' (direct): item '%s': first element of array should be an IP address or CNAME string", res->name, first_name);
        dmn_anysin_t temp_sin;
        if(gdnsd_anysin_getaddrinfo(vscf_simple_get_data(first_ac), NULL, &temp_sin)) {
            // was not a valid address, try cnames mode
            res->cnames = calloc(1, sizeof(cnset_t));
            config_cnameset(res->name, "direct", res->cnames, res_cfg);
        }
        else {
            // was a valid address, try addrset mode
            if(temp_sin.sa.sa_family == AF_INET6) {
                res->addrs_v6 = calloc(1, sizeof(addrset_t));
                config_addrset(res->name, "direct", true, res->addrs_v6, res_cfg);
            }
            else {
                dmn_assert(temp_sin.sa.sa_family == AF_INET);
                res->addrs_v4 = calloc(1, sizeof(addrset_t));
                config_addrset(res->name, "direct", false, res->addrs_v4, res_cfg);
            }
        }
    }
    else {
        log_fatal("plugin_weighted: resource '%s' (direct): item '%s': resource type not detectable (should be array of [ IP, weight ], array of [ CNAME, weight ], or hashed address group ...)", res->name, first_name);
    }

    vscf_destroy(res_cfg_noparams);
}