// A wrapper function to send a query and print the output onto stderr // int sendquery(val_context_t * context, const char *desc, char * name, int class_h, int type_h, u_int32_t flags, const int *result_ar, int trusted_only, struct val_response *resp) { int ret_val; struct val_result_chain *results = NULL; int err = 0; struct timeval start; if ((NULL == desc) || (NULL == name) || (NULL == result_ar) || (resp == NULL)) return -1; fprintf(stderr, "%s: ****START**** \n", desc); gettimeofday(&start, NULL); ret_val = val_resolve_and_check(context, name, class_h, type_h, flags, &results); if (ret_val == VAL_NO_ERROR) { ret_val = compose_answer(name, type_h, class_h, results, resp); if (result_ar) err = check_results(context, desc, name, class_h, type_h, result_ar, results, trusted_only, &start); val_free_result_chain(results); } else { fprintf(stderr, "%s: \t", desc); fprintf(stderr, "FAILED: Error in val_resolve_and_check(): %s\n", p_val_err(ret_val)); } results = NULL; return (err != 0); /* 0 success, 1 error */ }
int val_get_rrset(val_context_t *context, const char *name, int class_h, int type_h, u_int32_t flags, struct val_answer_chain **answers) { struct val_result_chain *results = NULL; int retval = VAL_NO_ERROR; val_context_t *ctx = NULL; if (name == NULL || answers == NULL) { return VAL_BAD_ARGUMENT; } ctx = val_create_or_refresh_context(context);/* does CTX_LOCK_POL_SH */ if (ctx == NULL) return VAL_INTERNAL_ERROR; if ((retval = val_resolve_and_check(ctx, name, class_h, type_h, flags, &results)) != VAL_NO_ERROR) { val_log(ctx, LOG_INFO, "get_addrinfo_from_dns(): val_resolve_and_check failed - %s", p_val_err(retval)); goto err; } retval = val_get_answer_from_result(ctx, name, class_h, type_h, &results, answers, 0); err: CTX_UNLOCK_POL(ctx); return retval; }
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 */ }
/* * Function: val_gethostbyname2_r * * Purpose: A validating DNSSEC-aware version of the reentrant gethostbyname2_r * function. This function supports both IPv4 and IPv6 addresses. * * Parameters: * ctx -- The validation context. Can be NULL for default value. * name -- The domain name or IP address in string format. * af -- Address family AF_INET or AF_INET6 * ret -- Pointer to a hostent variable to store the return value. * This parameter must not be NULL. * buf -- Pointer to a buffer to store auxiliary data. This * parameter must not be NULL. * buflen -- Length of the buffer 'buf'. * result -- Pointer to a variable of type (struct hostent *). This * parameter must not be NULL. *result will contain NULL on * failure and will point to the 'ret' parameter on success. * h_errnop -- Pointer to an integer variable to return the h_errno error * code. This parameter must not be NULL. * val_status -- A pointer to a val_status_t variable to hold the * returned validation-status value. This parameter * must not be NULL. * If successful, *val_status will contain a success * code. If there is a failure, *val_status will contain * the validator error code. To test whether the returned * error code represents a trustworthy status, the caller * can use the val_istrusted() function. * * Return value: 0 on success, and a non-zero error-code on failure. * * See also: val_gethostbyname2(), val_gethostbyname_r(), val_istrusted() */ int val_gethostbyname2_r(val_context_t * context, const char *name, int af, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop, val_status_t * val_status) { struct sockaddr_in sa; #if defined( WIN32 ) size_t addrlen4 = sizeof(struct sockaddr_in); #endif #ifdef VAL_IPV6 struct sockaddr_in6 sa6; #if defined( WIN32 ) size_t addrlen6 = sizeof(struct sockaddr_in6); #endif #endif int offset = 0; val_status_t local_ans_status = VAL_OOB_ANSWER; int trusted = 0; int retval; struct val_result_chain *results = NULL; u_int16_t type; val_context_t *ctx = NULL; *val_status = VAL_DONT_KNOW; if (!name || !ret || !h_errnop || !val_status || !result || !buf) { goto err; } ctx = val_create_or_refresh_context(context); /* does CTX_LOCK_POL_SH */ if (ctx == NULL) goto err; if (VAL_NO_ERROR == val_is_local_trusted(ctx, &trusted)) { if (trusted) { local_ans_status = VAL_TRUSTED_ANSWER; } } /* * Check if the address-family is AF_INET and the address is an IPv4 address */ if ((af == AF_INET) && (INET_PTON(AF_INET, name, ((struct sockaddr *)&sa), &addrlen4) > 0)) { memset(ret, 0, sizeof(struct hostent)); // Name ret->h_name = bufalloc(buf, buflen, &offset, strlen(name) + 1); if (ret->h_name == NULL) { goto err; } memcpy(ret->h_name, name, strlen(name) + 1); // Alias ret->h_aliases = (char **) bufalloc(buf, buflen, &offset, sizeof(char *)); if (ret->h_aliases == NULL) { goto err; } ret->h_aliases[0] = 0; // Address ret->h_addrtype = AF_INET; ret->h_length = sizeof(struct in_addr); ret->h_addr_list = (char **) bufalloc(buf, buflen, &offset, 2 * sizeof(char *)); if (ret->h_addr_list == NULL) { goto err; } ret->h_addr_list[0] = (char *) bufalloc(buf, buflen, &offset, sizeof(struct in_addr)); if (ret->h_addr_list[0] == NULL) { goto err; } memcpy(ret->h_addr_list[0], &sa.sin_addr, sizeof(struct in_addr)); ret->h_addr_list[1] = 0; *val_status = VAL_TRUSTED_ANSWER; *h_errnop = NETDB_SUCCESS; *result = ret; } #ifdef VAL_IPV6 /* * Check if the address-family is AF_INET6 and the address is an IPv6 address */ else if ((af == AF_INET6) && (INET_PTON(AF_INET6, name, ((struct sockaddr *)&sa6), &addrlen6) > 0)) { memset(ret, 0, sizeof(struct hostent)); // Name ret->h_name = bufalloc(buf, buflen, &offset, strlen(name) + 1); if (ret->h_name == NULL) { goto err; } memcpy(ret->h_name, name, strlen(name) + 1); // Alias ret->h_aliases = (char **) bufalloc(buf, buflen, &offset, sizeof(char *)); if (ret->h_aliases == NULL) { goto err; } ret->h_aliases[0] = 0; // Address ret->h_addrtype = AF_INET6; ret->h_length = sizeof(struct in6_addr); ret->h_addr_list = (char **) bufalloc(buf, buflen, &offset, 2 * sizeof(char *)); if (ret->h_addr_list == NULL) { goto err; } ret->h_addr_list[0] = (char *) bufalloc(buf, buflen, &offset, sizeof(struct in6_addr)); if (ret->h_addr_list[0] == NULL) { goto err; } memcpy(ret->h_addr_list[0], &sa6.sin6_addr, sizeof(struct in6_addr)); ret->h_addr_list[1] = 0; *val_status = VAL_TRUSTED_ANSWER; *h_errnop = NETDB_SUCCESS; *result = ret; } #endif else if (NULL != (*result = get_hostent_from_etc_hosts(ctx, name, af, ret, buf, buflen, &offset))) { /* * First check the ETC_HOSTS file * XXX: TODO check the order in the ETC_HOST_CONF file */ *val_status = local_ans_status; *h_errnop = NETDB_SUCCESS; } else { #ifdef VAL_IPV6 if (af == AF_INET6) type = ns_t_aaaa; else #endif type = ns_t_a; /* * Query the validator */ if (VAL_NO_ERROR == (retval = val_resolve_and_check(ctx, name, ns_c_in, type, 0, &results))) { /* * Convert the validator result into hostent */ *result = get_hostent_from_response(ctx, af, ret, results, h_errnop, buf, buflen, &offset, val_status); } else { val_log(ctx, LOG_ERR, "val_gethostbyname2_r(): val_resolve_and_check failed - %s", p_val_err(retval)); } if (*result == NULL) { goto err; } else { val_free_result_chain(results); results = NULL; *h_errnop = NETDB_SUCCESS; } } val_log(ctx, LOG_DEBUG, "val_gethostbyname2_r returned success, herrno = %d, val_status = %s", *h_errnop, val_status? p_val_status(*val_status) : NULL); CTX_UNLOCK_POL(ctx); return 0; err: if (result) { *result = NULL; } if (h_errnop) *h_errnop = NO_RECOVERY; if (ctx) { val_log(ctx, LOG_DEBUG, "val_gethostbyname2_r returned failure, herrno = %d, val_status = %s", *h_errnop, val_status? p_val_status(*val_status) : NULL); CTX_UNLOCK_POL(ctx); } return (NO_RECOVERY); }