/* *TODO: Check for and handle [_res.options & RES_USE_INET6] */ static getdns_return_t extract_addrtuple(struct gaih_addrtuple **result_addrtuple, response_bundle *response, char *intern_buffer, size_t buflen, uint32_t *respstatus) { if(!response) { log_warning("extract_addrtuple():error parsing response."); return GETDNS_RETURN_GENERIC_ERROR; }else if(response->ipv4_count + response->ipv6_count <= 0) { log_info("extract_addrtuple(): No answers: %s.", getdns_get_errorstr_by_id(response->respstatus)); *respstatus = GETDNS_RESPSTATUS_NO_NAME; return GETDNS_RETURN_GOOD; } size_t rec_count = 0, num_answers = 0; size_t idx, min_space, cname_len; num_answers = response->ipv4_count + response->ipv6_count; char *canon_name = response->cname; cname_len = strlen(canon_name) + 2; min_space = cname_len + (sizeof(struct gaih_addrtuple) * num_answers); if( buflen < min_space ) { log_critical("GETDNS: Buffer too small: %zd\n", buflen); return GETDNS_RETURN_MEMORY_ERROR; } struct gaih_addrtuple *gaih_ptr = *result_addrtuple; /*Fill in hostname*/ char *hname; hname = intern_buffer; memcpy(hname, canon_name, cname_len-2); memset(hname + cname_len-1, 0, sizeof(char)); idx = cname_len; if(response->ipv6_count > 0) { char **addr_list = malloc(sizeof(char*)*response->ipv6_count); assert(addr_list); int num = parse_addr_list(response->ipv6, addr_list, response->ipv6_count); for(rec_count = 0; rec_count < num; ++rec_count) { add_addrtuple(addr_list[rec_count], AF_INET6); } free(addr_list); } if(response->ipv4_count > 0) { char **addr_list = malloc(sizeof(char*)*response->ipv4_count); assert(addr_list); int num = parse_addr_list(response->ipv4, addr_list, response->ipv4_count); int addr_idx; for(addr_idx = 0; addr_idx < num; ++addr_idx) { add_addrtuple(addr_list[addr_idx], AF_INET); rec_count++; } free(addr_list); } assert(idx <= min_space); /*Check if we didn't write past the intended space...*/ *respstatus = rec_count > 0 ? GETDNS_RESPSTATUS_GOOD : GETDNS_RESPSTATUS_NO_NAME; return GETDNS_RETURN_GOOD; }
void callback(getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t trans_id) { char *response_str; if (callback_type == GETDNS_CALLBACK_COMPLETE) { /* This is a callback with data */; if (!quiet && (response_str = json ? getdns_print_json_dict(response, json == 1) : getdns_pretty_print_dict(response))) { fprintf(stdout, "ASYNC response:\n%s\n", response_str); validate_chain(response); free(response_str); } fprintf(stdout, "Result: The callback with ID %llu was successfull.\n", (unsigned long long)trans_id); } else if (callback_type == GETDNS_CALLBACK_CANCEL) fprintf(stderr, "Result: The callback with ID %llu was cancelled. Exiting.\n", (unsigned long long)trans_id); else { fprintf(stderr, "Result: The callback got a callback_type of %d. Exiting.\n", callback_type); fprintf(stderr, "Error : '%s'\n", getdns_get_errorstr_by_id(callback_type)); } getdns_dict_destroy(response); response = NULL; }
getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen) { const char *err_str = getdns_get_errorstr_by_id(err); (void) snprintf(buf, buflen, "%s", err_str ? err_str : "/* <unknown getdns value> */"); return GETDNS_RETURN_GOOD; } /* getdns_strerror */
getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen) { getdns_return_t retval = GETDNS_RETURN_GOOD; const char *err_str = getdns_get_errorstr_by_id(err); if (!err_str) { return GETDNS_RETURN_GENERIC_ERROR; } snprintf(buf, buflen, "%s", err_str); return retval; } /* getdns_strerror */
int main() { getdns_return_t r; getdns_context *ctx = NULL; if ((r = getdns_context_create(&ctx, 1))) fprintf(stderr, "Could not create context"); if (ctx) getdns_context_destroy(ctx); if (r) { fprintf(stderr, ": %s\n", getdns_get_errorstr_by_id(r)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
int main() { getdns_return_t r = GETDNS_RETURN_MEMORY_ERROR; getdns_dict *dict = NULL; unsigned char bladiebla_str[] = "bla die bla"; getdns_bindata bladiebla = { sizeof(bladiebla_str), bladiebla_str }; if (!(dict = getdns_dict_create())) fprintf(stderr, "Could not create dict"); else if ((r = getdns_dict_set_int(dict, "/bla/bloe/blie", 53280)) || (r = getdns_dict_set_int(dict, "/bla/hola", 53281)) || (r = getdns_dict_set_int(dict, "/bla/cola/-", 1)) || (r = getdns_dict_set_int(dict, "/bla/cola/-", 2)) || (r = getdns_dict_set_int(dict, "/bla/cola/-/drie", 3)) || (r = getdns_dict_set_int(dict, "/bla/cola/-", 4)) || (r = getdns_dict_set_int(dict, "/bla/cola/1", 5)) || (r = getdns_dict_set_int(dict, "/bla/cola/2/zes", 6)) || (r = getdns_dict_set_bindata(dict, "/die/bla", &bladiebla)) ) fprintf(stderr, "Error setting dict data"); else { char *dict_str = getdns_pretty_print_dict(dict); if (!dict_str) { fprintf(stderr, "Could not convert dict to string"); r = GETDNS_RETURN_MEMORY_ERROR; } else { printf("%s\n", dict_str); free(dict_str); } } if (r) fprintf(stderr, ": %s\n", getdns_get_errorstr_by_id(r)); if (dict) getdns_dict_destroy(dict); if (r) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); }
/* * This function combines both getaddrinfo() and getnameinfo(), so in short, everything the module does! * This was decided for simplicity purposes since this is just a wrapper around getdns which does all the work. */ getdns_return_t getdns_gethostinfo(const char *name, int af, struct addr_param *result_ptr, char *intern_buffer, size_t buflen, int32_t *ttlp, char **canonp, uint32_t *respstatus, uint32_t *dnssec_status) { getdns_return_t return_code; if(!intern_buffer || buflen < sizeof(char) || (!result_ptr)) { log_critical("getdns_gethostinfo: Memory error..."); return GETDNS_RETURN_MEMORY_ERROR; } *respstatus = GETDNS_RESPSTATUS_NO_NAME; if( (af != AF_INET) && (af != AF_INET6) && (af != AF_UNSPEC) ) { log_warning("getdns_gethostinfo: Address family not supported: %d .", af); return GETDNS_RETURN_WRONG_TYPE_REQUESTED; } memset(intern_buffer, 0, buflen); UNUSED_PARAM(ttlp); struct callback_fn_arg arg = {.result_ptr=result_ptr, .af=af, .buffer=intern_buffer, .buflen=buflen, .respstatus=respstatus, .dnssec_status=dnssec_status }; if((return_code = resolve(name, &arg)) != GETDNS_RETURN_GOOD) { log_info("getdns_gethostinfo(<%s>): Failed parsing response: ERROR < %d >\n", name, return_code); } /* This section is not complete: TODO: 1. Do all the getdns data structures need to be cleaned up, or does destroying the top-level node suffice? *Let's valgrind it and see, maybe?! */ if(canonp && *respstatus == GETDNS_RESPSTATUS_GOOD) { *canonp = result_ptr->addr_entry.p_hostent->h_name; } log_debug("Query(%s) => < %d > - DNSSEC STATUS: {%s}\n", name, *respstatus, getdns_get_errorstr_by_id(*dnssec_status)); return return_code; }
int main(int argc, char **argv) { getdns_dict *response = NULL; char *response_str; getdns_return_t r; getdns_dict *address = NULL; FILE *fp = NULL; name = the_root; if ((r = getdns_context_create(&context, 1))) { fprintf(stderr, "Create context failed: %d\n", r); return r; } extensions = getdns_dict_create(); if (! extensions) { fprintf(stderr, "Could not create extensions dict\n"); r = GETDNS_RETURN_MEMORY_ERROR; goto done_destroy_context; } if ((r = parse_args(argc, argv))) goto done_destroy_context; if (query_file) { fp = fopen(query_file, "rt"); if (fp == NULL) { fprintf(stderr, "Could not open query file: %s\n", query_file); goto done_destroy_context; } } /* Make the call */ do { char line[1024], *token, *linev[256]; int linec; if (interactive) { if (!query_file) { fprintf(stdout, "> "); if (!fgets(line, 1024, stdin) || !*line) break; } else { if (!fgets(line, 1024, fp) || !*line) { fprintf(stdout,"End of file."); break; } fprintf(stdout,"Found query: %s", line); } linev[0] = argv[0]; linec = 1; if ( ! (token = strtok(line, " \t\f\n\r"))) continue; if (*token == '#') { fprintf(stdout,"Result: Skipping comment\n"); continue; } do linev[linec++] = token; while (linec < 256 && (token = strtok(NULL, " \t\f\n\r"))); if ((r = parse_args(linec, linev))) { if (r == CONTINUE || r == CONTINUE_ERROR) continue; else goto done_destroy_context; } } if (calltype == HOSTNAME && !(address = ipaddr_dict(context, name))) { fprintf(stderr, "Could not convert \"%s\" " "to an IP address", name); continue; } if (async) { switch (calltype) { case GENERAL: r = getdns_general(context, name, request_type, extensions, &response, NULL, callback); break; case ADDRESS: r = getdns_address(context, name, extensions, &response, NULL, callback); break; case HOSTNAME: r = getdns_hostname(context, address, extensions, &response, NULL, callback); break; case SERVICE: r = getdns_service(context, name, extensions, &response, NULL, callback); break; default: r = GETDNS_RETURN_GENERIC_ERROR; break; } if (r) goto done_destroy_extensions; if (!batch_mode) getdns_context_run(context); } else { switch (calltype) { case GENERAL: r = getdns_general_sync(context, name, request_type, extensions, &response); break; case ADDRESS: r = getdns_address_sync(context, name, extensions, &response); break; case HOSTNAME: r = getdns_hostname_sync(context, address, extensions, &response); break; case SERVICE: r = getdns_service_sync(context, name, extensions, &response); break; default: r = GETDNS_RETURN_GENERIC_ERROR; break; } if (response && !quiet) { if ((response_str = json ? getdns_print_json_dict(response, json == 1) : getdns_pretty_print_dict(response))) { fprintf( stdout, "SYNC response:\n%s\n" , response_str); validate_chain(response); free(response_str); } else { r = GETDNS_RETURN_MEMORY_ERROR; fprintf( stderr , "Could not print response\n"); } } if (r == GETDNS_RETURN_GOOD) { uint32_t status; getdns_dict_get_int(response, "status", &status); fprintf(stdout, "Response code was: GOOD. Status was: %s\n", getdns_get_errorstr_by_id(status)); } else fprintf(stderr, "An error occurred: %d '%s'\n", r, getdns_get_errorstr_by_id(r)); } } while (interactive); if (batch_mode) getdns_context_run(context); /* Clean up */ done_destroy_extensions: getdns_dict_destroy(extensions); done_destroy_context: if (response) getdns_dict_destroy(response); getdns_context_destroy(context); if (fp) fclose(fp); if (r == CONTINUE) return 0; else if (r == CONTINUE_ERROR) return 1; fprintf(stdout, "\nAll done.\n"); return r; }
int main(int argc, char *argv[]) { char *name = "getdnsapi.net"; getdns_context *context; getdns_return_t ret; getdns_dict *extensions; getdns_dict *response; uint32_t status; uint32_t dnssec_status; uint32_t type; getdns_list *replies_tree; size_t nanswers; int i; char element[MAXELEM]; if (argc > 1) name = argv[1]; if ((ret = getdns_context_create(&context, 1)) != GETDNS_RETURN_GOOD) { fprintf(stderr, "getdns_context_create: %s\n", getdns_get_errorstr_by_id(ret)); return 1; } extensions = getdns_dict_create(); if ((ret = getdns_dict_set_int(extensions, "/dnssec_return_status", GETDNS_EXTENSION_TRUE)) != GETDNS_RETURN_GOOD) { fprintf(stderr, "getdns_dict_set_int(dnssec_return_status): %s\n", getdns_get_errorstr_by_id(ret)); return 1; } if ((ret = getdns_address_sync(context, name, extensions, &response)) != GETDNS_RETURN_GOOD) { fprintf(stderr, "getdns_address_sync: %s\n", getdns_get_errorstr_by_id(ret)); return 1; } (void)getdns_dict_get_int(response, "status", &status); if (status != GETDNS_RESPSTATUS_GOOD) { printf("Bad status: "); switch (status) { case GETDNS_RESPSTATUS_NO_NAME: printf("GETDNS_RESPSTATUS_NO_NAME\n"); break; case GETDNS_RESPSTATUS_ALL_TIMEOUT: printf("GETDNS_RESPSTATUS_ALL_TIMEOUT\n"); break; default: break; } } if ((ret = getdns_dict_get_list(response, "/replies_tree", &replies_tree)) != GETDNS_RETURN_GOOD) { fprintf(stderr, "getdns_dict_get_list(replies_tree): %s\n", getdns_get_errorstr_by_id(ret)); return 1; } (void)getdns_list_get_length(replies_tree, &nanswers); printf("%d answers\n", (int)nanswers); for ( i = 0 ; i < (int)nanswers ; i++ ) { snprintf(element, MAXELEM, "/replies_tree/%d/dnssec_status", i); (void)getdns_dict_get_int(response, element, &dnssec_status); snprintf(element, MAXELEM, "/replies_tree/%d/answer/0/type", i); (void)getdns_dict_get_int(response, element, &type); printf("dnssec_status for %s record: %s\n", address_type_to_string(type), dnssec_status_to_string(dnssec_status)); } /* * handy debugging tool - uncomment if wanted */ /* printf("%s\n", getdns_pretty_print_dict(response)); */ return 0; }