コード例 #1
0
int
main(int argc, char **argv) {
    int number = 100000;
    val_status_t    val_status;
    int retval;
    struct addrinfo *val_ainfo = NULL;
    char           *service = NULL;
    struct addrinfo hints;
    struct timeval starttime, endtime;
    int i;
    val_context_t *context;

    if (argc > 1) {
        number = atoi(argv[1]);
    }

    // run once to check various results
    memset(&hints, 0, sizeof(struct addrinfo));
    retval = val_getaddrinfo(NULL, LOOKUP_NAME, service, &hints, &val_ainfo, &val_status);

    if (!val_isvalidated(val_status)) {
        fprintf(stderr, "something very wrong; not validated response returned\n");
        exit(1);
    }
    fprintf(stderr, "validated response returned\n");

    // Note: this is without proper memory freeing

    // without a context
    fprintf(stderr, "starting %d queries without context....\n", number);

    // actually run the tests, timing them
    gettimeofday(&starttime, NULL);
    for (i = 0; i < number; i++) {
        retval = val_getaddrinfo(NULL, LOOKUP_NAME, service, &hints, &val_ainfo, &val_status);
    }
    gettimeofday(&endtime, NULL);
    fprintf(stderr, "time elapsed (ms) for %d queries: %d\n", number, timeofday_diff(&starttime, &endtime));

    // with context
    val_create_context(NULL, &context);
    fprintf(stderr, "starting %d queries with a context....\n", number);
    retval = val_getaddrinfo(context, LOOKUP_NAME, service, &hints, &val_ainfo, &val_status); // fully init it

    // actually run the tests, timing them
    gettimeofday(&starttime, NULL);
    for (i = 0; i < number; i++) {
        retval = val_getaddrinfo(context, LOOKUP_NAME, service, &hints, &val_ainfo, &val_status);
    }
    gettimeofday(&endtime, NULL);
    fprintf(stderr, "time elapsed (ms) for %d queries: %d\n", number, timeofday_diff(&starttime, &endtime));
}
コード例 #2
0
void
print_val_response(struct val_response *resp)
{
    if (resp == NULL) {
        printf("No answers returned. \n");
        return;
    }

    printf("DNSSEC status: %s [%d]\n",
           p_val_error(resp->vr_val_status), resp->vr_val_status);
    if (val_isvalidated(resp->vr_val_status)) {
        printf("Validated response:\n");
    } else if (val_istrusted(resp->vr_val_status)) {
        printf("Trusted but not validated response:\n");
    } else {
        printf("Untrusted response:\n");
    }
    print_response(resp->vr_response, resp->vr_length);
    printf("\n");
}
コード例 #3
0
ファイル: val_log.c プロジェクト: hardaker/dnssec-tools
void
val_log_authentication_chain(const val_context_t * ctx, int level,
                             const char * name_p, int class_h,
                             int type_h,
                             struct val_result_chain *results)
{
    struct val_result_chain *next_result;
    int real_type_h;
    int real_class_h;

    if (results == NULL) { 
        return;
    } 
    
    for (next_result = results; next_result;
         next_result = next_result->val_rc_next) {
        struct val_authentication_chain *next_as;
        int             i;

        /* Display the correct owner name, class,type for the record */
        if (next_result->val_rc_rrset) {
            real_type_h = next_result->val_rc_rrset->val_rrset_type; 
            real_class_h = next_result->val_rc_rrset->val_rrset_class; 
        } else {
            real_type_h = type_h;
            real_class_h = class_h;
        }

        if (val_isvalidated(next_result->val_rc_status)) {
            val_log(ctx, level, "Validation result for {%s, %s(%d), %s(%d)}: %s:%d (Validated)",
                    name_p, p_class(real_class_h), real_class_h,
                    p_type(real_type_h), real_type_h,
                    p_val_status(next_result->val_rc_status),
                    next_result->val_rc_status);
        } else if (val_istrusted(next_result->val_rc_status)) {
            val_log(ctx, level, "Validation result for {%s, %s(%d), %s(%d)}: %s:%d (Trusted but not Validated)",
                    name_p, p_class(real_class_h), real_class_h,
                    p_type(real_type_h), real_type_h,
                    p_val_status(next_result->val_rc_status),
                    next_result->val_rc_status);
        } else {
            val_log(ctx, level, "Validation result for {%s, %s(%d), %s(%d)}: %s:%d (Untrusted)",
                    name_p, p_class(real_class_h), real_class_h,
                    p_type(real_type_h), real_type_h,
                    p_val_status(next_result->val_rc_status),
                    next_result->val_rc_status);
        }

        for (next_as = next_result->val_rc_answer; next_as;
             next_as = next_as->val_ac_trust) {

            if (next_as->val_ac_rrset == NULL) {
                val_log(ctx, level, "    Assertion status = %s:%d",
                        p_ac_status(next_as->val_ac_status),
                        next_as->val_ac_status);
            } else {
                const char   *t_name;
                t_name = next_as->val_ac_rrset->val_rrset_name;
                if (t_name == NULL)
                    t_name = (const char *) "NULL_DATA";

                val_log_assertion_pfx(ctx, level, "    ", t_name,
                                      next_as);
                //                val_log_val_rrset_pfx(ctx, level, "     ",
                //                                  next_as->val_ac_rrset);
            }
        }

        for (i = 0; i < next_result->val_rc_proof_count; i++) {
            val_log(ctx, level, "    Proof of non-existence [%d of %d]", 
                    i+1, next_result->val_rc_proof_count);
            for (next_as = next_result->val_rc_proofs[i]; next_as;
                 next_as = next_as->val_ac_trust) {
                if (next_as->val_ac_rrset == NULL) {
                    val_log(ctx, level, "      Assertion status = %s:%d",
                            p_ac_status(next_as->val_ac_status),
                            next_as->val_ac_status);
                } else {
                    const char   *t_name;
                    t_name = next_as->val_ac_rrset->val_rrset_name;
                    if (t_name == NULL)
                        t_name = (const char *) "NULL_DATA";

                    val_log_assertion_pfx(ctx, level, "      ", t_name,
                                          next_as);
                }
            }
        }
    }
}
コード例 #4
0
ファイル: getquery.c プロジェクト: DNSSEC-Tools/DNSSEC-Tools
int
main(int argc, char *argv[])
{
    char           *node = NULL;
    val_log_t      *logp;
    u_int16_t      type_h = ns_t_a;
    int success = 0;
    int ret;
    val_status_t status;
    u_char buf[1024];

    while (1) {
        int             c;
#ifdef HAVE_GETOPT_LONG
        int             opt_index = 0;
#ifdef HAVE_GETOPT_LONG_ONLY
        c = getopt_long_only(argc, argv, "ho:t:V",
                             prog_options, &opt_index);
#else
        c = getopt_long(argc, argv, "ho:t:V", prog_options, &opt_index);
#endif
#else                           /* only have getopt */
        c = getopt(argc, argv, "ho:t:V");
#endif

        if (c == -1) {
            break;
        }

        switch (c) {
        case 'h':
            usage(argv[0]);
            return -1;
        case 'o':
            logp = val_log_add_optarg(optarg, 1);
            if (NULL == logp) { /* err msg already logged */
                usage(argv[0]);
                return -1;
            }
            break;

        case 't':
            type_h = res_nametotype(optarg, &success);
            if (!success) {
                fprintf(stderr, "Unrecognized type %s\n", optarg);
                usage (argv[0]);
                return -1;
            }
            break;
        case 'V':
            version();
            return 0;

        default:
            fprintf(stderr, "Invalid option %s\n", argv[optind - 1]);
            usage(argv[0]);
            return -1;
        }
    }

    if (optind < argc) {
        node = argv[optind++];
    } else {
        fprintf(stderr, "Error: node name not specified\n");
        usage(argv[0]);
        return -1;
    }

    //ret = val_res_query(NULL, "mail.marzot.net", 1, 15, buf, 1024, &status);
    //ret = val_res_query(NULL, "nosig-A.test.dnssec-tools.org.", 1, 1, buf, 1024, &status);
    //ret = val_res_query(NULL, "good-A.test.dnssec-tools.org", 1, 28, buf, 1024, &status);
    //ret = val_res_query(NULL, "vb.futz.org", 1, 1, buf, 1024, &status);
    
    ret = val_res_query(NULL, node, ns_c_in, type_h, buf, 1024, &status);
    printf("Return value %d\n", ret);
    printf("herrno value %d\n", h_errno);
    printf("Validation Status %s\n", p_val_status(status));
    if (ret > 0) {
        print_response(buf, ret);
    }

    if (val_isvalidated(status))
        return 2;
    else if (val_istrusted(status))
        return 1;
    return 0;
}
コード例 #5
0
ファイル: val_get_rrset.c プロジェクト: mcr/dnssec-tools
int
val_get_answer_from_result(val_context_t *context, const char *name, int class_h,
                           int type_h, struct val_result_chain **results,
                           struct val_answer_chain **answers,
                           unsigned int vgafr_flags)
{
    struct val_result_chain *res = NULL;
    struct val_answer_chain *ans = NULL;
    struct val_answer_chain *last_ans = NULL;
    int retval = VAL_NO_ERROR;
    const char *n = NULL;
    int len;
    char *name_alias = NULL;
    int trusted, validated;
    
    if (name == NULL || answers == NULL || results == NULL || answers == NULL) {
        return VAL_BAD_ARGUMENT;
    }

    *answers = NULL;
    last_ans = NULL;
   
    if (*results == NULL) {
        /* Construct a single val_answer_chain with the untrusted status */
        ans = (struct val_answer_chain *) MALLOC (sizeof(struct val_answer_chain));
        if (ans == NULL) {
            return VAL_OUT_OF_MEMORY;
        }
        ans->val_ans_name = strdup(name); 
        if (ans->val_ans_name == NULL) {
            FREE(ans);
            ans = NULL;
            return VAL_OUT_OF_MEMORY;
        } 
        ans->val_ans_status = VAL_UNTRUSTED_ANSWER;
        ans->val_ans_class = class_h;
        ans->val_ans_type = type_h;
        ans->val_ans = NULL;
        ans->val_ans_next = NULL;
        *answers = ans;
        return VAL_NO_ERROR;
    }

    trusted = 1;
    validated = 1;

    /* Construct the val_answer_chain linked list for returned results */
    for (res = *results; res; res=res->val_rc_next) {

        if (!validated || !val_isvalidated(res->val_rc_status))
            validated = 0;
        if (!trusted || !val_istrusted(res->val_rc_status))
            trusted = 0;

        /* 
         * we don't need cnames/dnames in the answer,
         * we only need the name that is being pointed to.
         */
        if (res->val_rc_alias) {
            name_alias = res->val_rc_alias;
            continue;
        }

        ans = (struct val_answer_chain *) MALLOC (sizeof(struct val_answer_chain));
        if (ans == NULL) {
            retval = VAL_OUT_OF_MEMORY;
            goto err;
        }

        /* add to end of chain */
        ans->val_ans_next = NULL;
        if (last_ans) {
            last_ans->val_ans_next = ans;
        } else {
            *answers = ans;
        }
        last_ans = ans;
        
        if (res->val_rc_rrset) {
            /* use values from the rrset */
            n = res->val_rc_rrset->val_rrset_name;
            ans->val_ans_class = res->val_rc_rrset->val_rrset_class; 
            ans->val_ans_type = res->val_rc_rrset->val_rrset_type; 
            ans->val_ans = (struct rr_rec *) (res->val_rc_rrset->val_rrset_data);
            res->val_rc_rrset->val_rrset_data = NULL;
        } else {
            if (name_alias) {
                n = name_alias; /* the last alias target */ 
            } else {
                n = name; /* the name being queried for */
            }
            ans->val_ans_class = class_h; 
            ans->val_ans_type = type_h; 
            ans->val_ans = NULL;
        } 

        /* Convert the name to a string */
        ans->val_ans_name = NULL;    
        len = strlen(n) + 1;
        ans->val_ans_name = (char *) MALLOC (len * sizeof (char));
        if (ans->val_ans_name == NULL) {
            retval = VAL_OUT_OF_MEMORY;
            goto err;
        }
        strcpy(ans->val_ans_name, n);

        /* 
         * if the current answer was validated or 
         * if the current answer was trusted use the exact status
         */
        if (validated || 
            (trusted && !val_isvalidated(res->val_rc_status))) {
           ans->val_ans_status = res->val_rc_status;
        } else if (trusted) {
        /*
         * If the combined answer was trusted but the current answer
         * was validated (implied), use the lower bounds of trust 
         */
            if (val_does_not_exist(res->val_rc_status)) {
                if (res->val_rc_status == VAL_NONEXISTENT_NAME)
                   ans->val_ans_status = VAL_NONEXISTENT_NAME_NOCHAIN; 
                else 
                   ans->val_ans_status = VAL_NONEXISTENT_TYPE_NOCHAIN; 
            } else {
                ans->val_ans_status = VAL_TRUSTED_ANSWER;
            }
        } else {
            ans->val_ans_status = VAL_UNTRUSTED_ANSWER;        
        }

        /* 
         * reset the below values so that we are able to handle different 
         * status values for different answers
         */
        validated = 1;
        trusted = 1;
    } 

    val_free_result_chain(*results);
    *results = NULL;
    return VAL_NO_ERROR;

err:
    val_free_answer_chain(*answers);
    *answers = NULL;
    val_free_result_chain(*results);
    *results = NULL;
    return retval;
} 
コード例 #6
0
ファイル: getaddr.c プロジェクト: mcr/dnssec-tools
int
main(int argc, char *argv[])
{
    const char     *allowed_args =
#ifndef VAL_NO_ASYNC
        "a"
#endif
        "hco:s:Vv:r:i:";
    char           *node = NULL;
    char           *service = NULL;
    struct addrinfo hints;
    struct addrinfo *val_ainfo = NULL;
    int             retval;
    int             getcanonname = 0;
    int             portspecified = 0;
    int             async = 0;
    val_log_t      *logp;
    val_status_t val_status;

    // Parse the command line
    while (1) {
        int             c;
#ifdef HAVE_GETOPT_LONG
        int             opt_index = 0;
#ifdef HAVE_GETOPT_LONG_ONLY
        c = getopt_long_only(argc, argv, allowed_args,
                             prog_options, &opt_index);
#else
        c = getopt_long(argc, argv, allowed_args, prog_options, &opt_index);
#endif
#else                           /* only have getopt */
        c = getopt(argc, argv, allowed_args);
#endif

        if (c == -1) {
            break;
        }

        switch (c) {
        case 'h':
            usage(argv[0]);
            return -1;
        case 'o':
            logp = val_log_add_optarg(optarg, 1);
            if (NULL == logp) { /* err msg already logged */
                usage(argv[0]);
                return -1;
            }
            break;

        case 's':
            portspecified = 1;
            service = optarg;
            break;
        case 'c':
            getcanonname = 1;
            break;

#ifndef VAL_NO_ASYNC
        case 'a':
            async = 1;
            break;
#endif

        case 'v':
            dnsval_conf_set(optarg);
            break;

        case 'i':
            root_hints_set(optarg);
            break;

        case 'r':
            resolv_conf_set(optarg);
            break;

        case 'V':
            version();
            return 0;
        default:
            fprintf(stderr, "Invalid option %s\n", argv[optind - 1]);
            usage(argv[0]);
            return -1;
        }
    }

    if (optind < argc) {
        node = argv[optind++];
    } else {
        fprintf(stderr, "Error: node name not specified\n");
        usage(argv[0]);
        return -1;
    }

    memset(&hints, 0, sizeof(struct addrinfo));
    if (getcanonname) {
        hints.ai_flags |= AI_CANONNAME;
    }

    if (!async) {
        retval = val_getaddrinfo(NULL, node, service, &hints, &val_ainfo, &val_status);
    }
    else {
#ifdef VAL_NO_ASYNC
        fprintf(stderr, "async support not available\n");
#else
        struct getaddr_s cb_data = { &retval, &val_ainfo, &val_status, 0 };
        val_gai_callback my_cb = &_callback;
        val_gai_status *status = NULL;
        struct timeval tv;
        val_context_t *context;
        /*
         * create a new context
         */
        val_create_context("getaddr", &context);
        if (context == NULL)
            return -1;
        /*
         * submit request
         */
        retval = val_getaddrinfo_submit(context, node, service, &hints,
                                        my_cb, &cb_data, 0, &status);
        /*
         * wait for it to complete
         */
        while(0 == cb_data.done) {
            tv.tv_sec = 4;
            tv.tv_usec = 567;
            val_async_check_wait(context, NULL, NULL, &tv, 0);
        }
        val_free_context(context);
#endif
    }

    printf("Return code = %d\n", retval);
    printf("Validator status code = %d (%s)\n", val_status,
           p_val_status(val_status));

    if (retval != 0) {
#ifdef HAVE_GAI_STRERROR
        printf("Error in val_getaddrinfo(): %s\n", gai_strerror(retval));
#else
        printf("Error in val_getaddrinfo(): %d\n", retval);
#endif
        return -1;
    }

    print_addrinfo(VAL_ADDRINFO_TYPE, val_ainfo);

    /*
     * cleanup 
     */
    val_freeaddrinfo(val_ainfo);
    if (val_isvalidated(val_status)) {
        return 2; 
    } 
    if (val_istrusted(val_status)) {
        return 1; 
    } 

    return 0;
}
コード例 #7
0
static int
get_results(val_context_t * context, const char *desc, char *name,
            int class_h, int type_h, u_char *response,
            int *response_size, int trusted_only)
{
    int             response_size_max, ret_val, err = 0;
    struct val_result_chain *results = NULL;
    struct val_response resp;

    if ((NULL == desc) || (NULL == name) || (NULL == response) ||
        (NULL == response_size))
        return -1;

    response_size_max = *response_size;
    *response_size = 0;

    fprintf(stderr, "%s: ****START**** \n", desc);

    /*
     * Query the validator
     */
    ret_val = val_resolve_and_check(context, name, class_h, type_h, 
                                    VAL_QUERY_AC_DETAIL, &results);

    if (ret_val == VAL_NO_ERROR) {

        ret_val = compose_answer(name, type_h, class_h, results, &resp);
        val_free_result_chain(results);

        if (VAL_NO_ERROR != ret_val) {
            fprintf(stderr, "%s: \t", desc);
            fprintf(stderr, "FAILED: Error in compose_answer(): %d\n",
                    ret_val);
        }
        else {
            if (resp.vr_response == NULL) {
                fprintf(stderr, "FAILED: No response\n");
            } else {
                printf("DNSSEC status: %s [%d]\n",
                       p_val_error(resp.vr_val_status), resp.vr_val_status);
                if (val_isvalidated(resp.vr_val_status)) {
                    printf("Validated response:\n");
                } else if (val_istrusted(resp.vr_val_status)) {
                    printf("Trusted but not validated response:\n");
                } else {
                    printf("Non-validated response:\n");
                }
                if (resp.vr_length > response_size_max) {
                    err = 1;
                }
                else {
                    print_response(resp.vr_response, resp.vr_length);
                    memcpy(response, resp.vr_response, resp.vr_length);
                    *response_size = resp.vr_length;
                }

                FREE(resp.vr_response);
            }
        }

    } else {
        fprintf(stderr, "%s: \t", desc);
        fprintf(stderr, "FAILED: Error in val_resolve_and_check(): %d, %s\n",
                ret_val, p_val_err(ret_val));
    }

    fprintf(stderr, "%s: ****END**** \n", desc);

    return (err != 0);          /* 0 success, 1 error */
}
コード例 #8
0
ファイル: val_gethostbyname.c プロジェクト: mcr/dnssec-tools
/*
 * A thread-safe, re-entrant version of val_gethostbyaddr 
 */
int
val_gethostbyaddr_r(val_context_t * context,
                    const char *addr,
                    int len,
                    int type,
                    struct hostent *ret,
                    char *buf,
                    int buflen,
                    struct hostent **result,
                    int *h_errnop, val_status_t * val_status)
{

    char            domain_string[NS_MAXDNAME];
    int             ret_status = 0, bufused = 0;
    struct val_answer_chain *val_res = NULL;
    struct val_answer_chain *res;
    int retval;
    val_context_t *ctx = NULL;
    
    /*
     * check misc parameters exist 
     */
    if (!addr || !ret || !buf || (buflen <= 0) ||
        !result || !h_errnop || !val_status) {
        if (h_errnop)
            *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    /*
     * default the input parameters 
     */
    *result = NULL;
    ret->h_name = NULL;
    ret->h_aliases = NULL;
    ret->h_addr_list = NULL;
    *h_errnop = 0;
    *val_status = VAL_UNTRUSTED_ANSWER;

    /*
     * get the address values, only support IPv4 and IPv6 
     */
    if (AF_INET == type && len >= sizeof(struct in_addr)) {
        ret->h_addrtype = type;
        ret->h_length = sizeof(struct in_addr);
    } 
#ifdef VAL_IPV6
    else if (AF_INET6 == type && len >= sizeof(struct in6_addr)) {
        ret->h_addrtype = type;
        ret->h_length = sizeof(struct in6_addr);
    } 
#endif
    else {
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    memset(domain_string, 0, sizeof(domain_string));

    if (0 !=
        (ret_status = address_to_reverse_domain(addr, type,
                                                domain_string, sizeof(domain_string)))
        ) {
        *h_errnop = ret_status;
        return ret_status;
    }

    /*
     * if there is memory, add the address to hostent's address list 
     */
    if ((buflen > bufused) && 
        ((buflen - bufused) >= (ret->h_length + (sizeof(char *) * 2)))) {
        ret->h_addr_list = (char **) (buf + bufused);
        bufused = bufused + (sizeof(char *) * 2);
        ret->h_addr_list[0] = buf + bufused;
        ret->h_addr_list[1] = NULL;
        bufused = bufused + ret->h_length;
        memcpy(ret->h_addr_list[0], addr, ret->h_length);
    } else {                    /* no memory, fail */
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    ctx = val_create_or_refresh_context(context); /* does CTX_LOCK_POL_SH */
    if (ctx == NULL) {
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    if (VAL_NO_ERROR != (retval = val_get_rrset(ctx,   /* val_context_t *  */
                                                domain_string, /* domain name */ 
                                                ns_c_in,   /* const u_int16_t q_class */
                                                ns_t_ptr,  /* const u_int16_t type */
                                                0,
                                                &val_res))) { /* struct val_answer_chain **results */
        val_log(ctx, LOG_ERR, 
                "val_gethostbyaddr_r(): val_get_rrset failed - %s", p_val_err(retval));
        CTX_UNLOCK_POL(ctx);
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    CTX_UNLOCK_POL(ctx);

    if (!val_res) {
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    for (res = val_res; res; res=res->val_ans_next) {

        struct rr_rec  *rr = res->val_ans;
        if (rr) {
            struct rr_rec  *rr_it = NULL;
            int             count = 0;
            int aliases_sz = 0;
            /*
             * if the buffer has enough room add the first host address 
             */
            if (rr->rr_length < (buflen - bufused - 1)) {
                /*
                 * setup hostent 
                 */
                ret->h_name = buf + bufused;
                ns_name_ntop(rr->rr_data, ret->h_name,
                             (buflen - bufused));
                bufused = bufused + strlen(ret->h_name) + 1;

                rr_it = rr->rr_next;
                /*
                 * are there other hostnames? 
                 */
                if (rr_it) {
                    /*
                     * calculate the amount of memory we need for aliases. 
                     */
                    do {
                        count++;
                        aliases_sz = aliases_sz + rr_it->rr_length + 1;
                    } while (NULL != (rr_it = rr_it->rr_next));

                    /*
                     * check that we have the space in the buffer 
                     */
                    if (buflen >=
                        (bufused + (sizeof(char *) * (count + 1)) +
                        aliases_sz)) {
                        /*
                         * assign the string pointer array 
                         */
                        ret->h_aliases = (char **) (buf + bufused);
                        bufused = bufused + (sizeof(char *) * (count + 1));

                        /*
                         * assign the strings 
                         */
                        rr_it = rr->rr_next;
                        count = 0;
                        do {
                            ret->h_aliases[count] = buf + bufused;
                            ns_name_ntop(rr_it->rr_data,
                                         ret->h_aliases[count],
                                        (buflen - bufused));
                            bufused =
                                bufused + strlen(ret->h_aliases[count]) + 1;
                            count++;
                        } while (NULL != (rr_it = rr_it->rr_next));
                        /*
                         * mark end of array 
                         */
                        ret->h_aliases[count] = NULL;
                    }
                    /*
                     * else we didn't have enough memory for the aliases.  They
                     * will be ignored with only one hostname returned 
                     */
                }                   /* else there are no other hostnames/aliases */

            } else {                /* else there is not enough room for even one host name, fail */
                ret->h_name = NULL;
                *h_errnop = NO_RECOVERY;
                return NO_RECOVERY;
            }
            break;

        } else if  (val_does_not_exist(res->val_ans_status)) {
                    
            if ((res->val_ans_status == VAL_NONEXISTENT_TYPE) ||
                (res->val_ans_status == VAL_NONEXISTENT_TYPE_NOCHAIN)) {
                    *h_errnop = NO_DATA;
            } else if ((res->val_ans_status == VAL_NONEXISTENT_NAME) ||
                       (res->val_ans_status == VAL_NONEXISTENT_NAME_NOCHAIN)) {
                    *h_errnop = HOST_NOT_FOUND;
            }

            *result = ret;
            return *h_errnop;
        }
    }

    if (!res) { /* no rrset, but a succesful return from the query?, fail */
        ret->h_name = NULL;
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    /* set the value of merged trusted and validated status values */
    if (val_isvalidated(res->val_ans_status))
        *val_status = VAL_VALIDATED_ANSWER; 
    else if (val_istrusted(res->val_ans_status))
        *val_status = VAL_TRUSTED_ANSWER; 

    /*
     * no error, set result 
     */
    *result = ret;
    return *h_errnop;

}                               /* val_getthostbyaddr_r */
コード例 #9
0
ファイル: val_gethostbyname.c プロジェクト: mcr/dnssec-tools
/*
 * Function: get_hostent_from_response
 *
 * Purpose: Converts the linked list of val_result_chain structures obtained
 *          as a result from the validator into a hostent structure.
 *
 * Parameters:
 *              ctx -- The validation context.
 *               af -- The address family: AF_INET or AF_INET6.
 *              ret -- Pointer to a hostent structure to return the result.
 *                     This parameter must not be NULL.
 *          results -- Pointer to a linked list of val_result_chain structures.
 *         h_errnop -- Pointer to an integer variable to store the h_errno value.
 *              buf -- A buffer to store auxiliary data.  This parameter must not be NULL.
 *           buflen -- Length of the buffer 'buf'.
 *           offset -- Pointer to an integer variable that contains the offset in the buffer
 *                     'buf', where data can be written.  When this function writes any data
 *                     in the auxiliary data, the offset is incremented accordingly.  This
 *                     parameter must not be NULL.
 *
 * Return value: Returns NULL on failure and 'ret' on success.
 *
 * See also: get_hostent_from_etc_hosts()
 */
static struct hostent *
get_hostent_from_response(val_context_t * ctx, int af, struct hostent *ret,
                          struct val_result_chain *results, int *h_errnop,
                          char *buf, int buflen, int *offset, 
                          val_status_t * val_status)
{
    int             alias_count = 0;
    int             alias_index = 0;
    int             addr_count = 0;
    int             addr_index = 0;
    int             orig_offset = 0;
    struct val_result_chain *res;
    int validated = 1;
    int trusted = 1;
    struct val_rrset_rec *rrset;
    char *alias_target = NULL;

    /*
     * Check parameter sanity 
     */
    if (!results || !h_errnop || !buf || !offset || !ret || !val_status) {
        return NULL;
    }

    *val_status = VAL_DONT_KNOW;
    *h_errnop = 0;
    
    orig_offset = *offset;
    memset(ret, 0, sizeof(struct hostent));

    /*
     * Count the number of aliases and addresses in the result 
     */
    for (res = results; res != NULL; res = res->val_rc_next) {
        rrset = res->val_rc_rrset;

        if (res->val_rc_alias && rrset) {
            val_log(ctx, LOG_DEBUG,
                    "get_hostent_from_response(): type of record = CNAME");
            alias_count++;
            continue;
        }

        // Get a count of aliases and addresses
        if (rrset) {
            struct val_rr_rec  *rr = rrset->val_rrset_data;

            while (rr) {

                if ((af == AF_INET)
                           && (rrset->val_rrset_type == ns_t_a)) {
                    val_log(ctx, LOG_DEBUG,
                            "get_hostent_from_response(): type of record = A");
                    addr_count++;
                } else if ((af == AF_INET6)
                           && (rrset->val_rrset_type == ns_t_aaaa)) {
                    val_log(ctx, LOG_DEBUG,
                            "get_hostent_from_response(): type of record = AAAA");
                    addr_count++;
                }

                rr = rr->rr_next;
            }
        }
    }

    ret->h_aliases =
        (char **) bufalloc(buf, buflen, offset,
                           (alias_count + 1) * sizeof(char *));
    if (ret->h_aliases == NULL) {
        goto err;
    }
    ret->h_aliases[alias_count] = NULL;

    ret->h_addr_list =
        (char **) bufalloc(buf, buflen, offset,
                           (addr_count + 1) * sizeof(char *));
    if (ret->h_addr_list == NULL) {
        goto err;
    }
    ret->h_addr_list[addr_count] = NULL;

    alias_index = alias_count - 1;

    if (results == NULL) {
        *val_status = VAL_UNTRUSTED_ANSWER;
        *h_errnop = HOST_NOT_FOUND; 
        goto err;
    } 
   
    /*
     * Process the result 
     */
    for (res = results; res != NULL; res = res->val_rc_next) {

        rrset = res->val_rc_rrset;

        if (!(validated && val_isvalidated(res->val_rc_status))) 
            validated = 0;
        if (!(trusted && val_istrusted(res->val_rc_status)))
            trusted = 0;

        /* save the non-existence state */
        if (val_does_not_exist(res->val_rc_status)) {
            *val_status = res->val_rc_status;
            if (res->val_rc_status == VAL_NONEXISTENT_NAME ||
                res->val_rc_status == VAL_NONEXISTENT_NAME_NOCHAIN) {

                *h_errnop = HOST_NOT_FOUND;
            } else { 
                *h_errnop = NO_DATA;
            }
            break;
        }

        if (res->val_rc_alias && rrset) {
            // Handle CNAME RRs
            if (alias_index >= 0) {
                ret->h_aliases[alias_index] =
                    (char *) bufalloc(buf, buflen, offset,
                                      (strlen(rrset->val_rrset_name) + 1) * sizeof(char));
                if (ret->h_aliases[alias_index] == NULL) {
                    goto err;
                }
                memcpy(ret->h_aliases[alias_index], rrset->val_rrset_name,
                       strlen(rrset->val_rrset_name) + 1);
                alias_index--;
            }

            /* save the alias target for later use */
            alias_target = res->val_rc_alias; 
        } else if (rrset) {

            if (((af == AF_INET)
                      && (rrset->val_rrset_type == ns_t_a))
                || ((af == AF_INET6)
                      && (rrset->val_rrset_type == ns_t_aaaa))) {

                struct val_rr_rec  *rr = rrset->val_rrset_data;

                if (!ret->h_name) {
                    ret->h_name =
                            (char *) bufalloc(buf, buflen, offset,
                                              (strlen(rrset->val_rrset_name) +
                                               1) * sizeof(char));
                    if (ret->h_name == NULL) {
                        goto err;
                    }
                    memcpy(ret->h_name, rrset->val_rrset_name, strlen(rrset->val_rrset_name) + 1);
                }

                while (rr) {
                    // Handle A and AAAA RRs
                    ret->h_length = rr->rr_rdata_length;
                    ret->h_addrtype = af;
                    ret->h_addr_list[addr_index] =
                            (char *) bufalloc(buf, buflen, offset,
                                              rr->rr_rdata_length *
                                              sizeof(char));
                    if (ret->h_addr_list[addr_index] == NULL) {
                        goto err;
                    }

                    memcpy(ret->h_addr_list[addr_index], rr->rr_rdata,
                               rr->rr_rdata_length);
                    addr_index++;

                    rr = rr->rr_next;
                }
            }
        }
    }
    /* pick up official name from the alias target */
    if (!ret->h_name && alias_target) {
        ret->h_name = (char *) bufalloc(buf, buflen, offset,
                          (strlen(alias_target) + 1) * sizeof(char));
        if (ret->h_name == NULL) {
            goto err;
        }
        memcpy(ret->h_name, alias_target, strlen(alias_target) + 1);
    }

    if (addr_count > 0) {
        *h_errnop = NETDB_SUCCESS;
        if (validated)
            *val_status = VAL_VALIDATED_ANSWER;
        else if (trusted)
            *val_status = VAL_TRUSTED_ANSWER;
        else 
            *val_status = VAL_UNTRUSTED_ANSWER; 
    } else if (alias_count == 0) {
        goto err;
    } else if (*h_errnop == 0)   {
        /* missing a proof of non-existence for alias */
        *val_status = VAL_UNTRUSTED_ANSWER;
        *h_errnop = NO_DATA;
    } 
    return ret;

err:
    *offset = orig_offset;
    return NULL;
    
}                               /* get_hostent_from_response() */