static getdns_return_t set_cookie(getdns_dict *exts, char *cookie) { uint8_t data[40]; size_t i; getdns_return_t r = GETDNS_RETURN_GENERIC_ERROR; getdns_bindata bindata; getdns_dict *opt_parameters = getdns_dict_create(); getdns_list *options = getdns_list_create(); getdns_dict *option = getdns_dict_create(); if (*cookie == '=') cookie++; for (i = 0; i < 40 && *cookie; i++) { if (*cookie >= '0' && *cookie <= '9') data[i] = (uint8_t)(*cookie - '0') << 4; else if (*cookie >= 'a' && *cookie <= 'f') data[i] = (uint8_t)(*cookie - 'a' + 10) << 4; else if (*cookie >= 'A' && *cookie <= 'F') data[i] = (uint8_t)(*cookie - 'A' + 10) << 4; else goto done; cookie++; if (*cookie >= '0' && *cookie <= '9') data[i] |= (uint8_t)(*cookie - '0'); else if (*cookie >= 'a' && *cookie <= 'f') data[i] |= (uint8_t)(*cookie - 'a' + 10); else if (*cookie >= 'A' && *cookie <= 'F') data[i] |= (uint8_t)(*cookie - 'A' + 10); else goto done; cookie++;; } bindata.data = data; bindata.size = i; if ((r = getdns_dict_set_int(option, "option_code", 65001))) goto done; if ((r = getdns_dict_set_bindata(option, "option_data", &bindata))) goto done; if ((r = getdns_list_set_dict(options, 0, option))) goto done; if ((r = getdns_dict_set_list(opt_parameters, "options", options))) goto done; r = getdns_dict_set_dict(exts, "add_opt_parameters", opt_parameters); done: getdns_dict_destroy(option); getdns_list_destroy(options); getdns_dict_destroy(opt_parameters); return r; }
/* convert an HPKP-style pin description to an appropriate getdns data structure. An example string is: (with the quotes, without any leading or trailing whitespace): pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" getdns_build_pin_from_string returns a dict created from ctx, or NULL if the string did not match. If ctx is NULL, the dict is created via getdns_dict_create(). It is the caller's responsibility to call getdns_dict_destroy when it is no longer needed. */ getdns_dict* getdns_pubkey_pin_create_from_string( getdns_context* context, const char* str) { BIO *bio = NULL; int i; uint8_t buf[SHA256_DIGEST_LENGTH]; char inbuf[B64_ENCODED_SHA256_LENGTH + 1]; getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf }; getdns_dict* out = NULL; /* we only do sha256 right now, make sure this is well-formed */ if (strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH)) return NULL; for (i = PIN_PREFIX_LENGTH; i < PIN_PREFIX_LENGTH + B64_ENCODED_SHA256_LENGTH - 1; i++) if (!((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= '0' && str[i] <= '9') || (str[i] == '+') || (str[i] == '/'))) return NULL; if (str[i++] != '=') return NULL; if (str[i++] != '"') return NULL; if (str[i++] != '\0') return NULL; /* openssl needs a trailing newline to base64 decode */ memcpy(inbuf, str + PIN_PREFIX_LENGTH, B64_ENCODED_SHA256_LENGTH); inbuf[B64_ENCODED_SHA256_LENGTH] = '\n'; bio = BIO_push(BIO_new(BIO_f_base64()), BIO_new_mem_buf(inbuf, sizeof(inbuf))); if (BIO_read(bio, buf, sizeof(buf)) != sizeof(buf)) goto fail; if (context) out = getdns_dict_create_with_context(context); else out = getdns_dict_create(); if (out == NULL) goto fail; if (getdns_dict_set_bindata(out, "digest", &sha256)) goto fail; if (getdns_dict_set_bindata(out, "value", &value)) goto fail; return out; fail: BIO_free_all(bio); getdns_dict_destroy(out); return NULL; }
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); }
/* convert an HPKP-style pin description to an appropriate getdns data structure. An example string is: (with the quotes, without any leading or trailing whitespace): pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" getdns_build_pin_from_string returns a dict created from ctx, or NULL if the string did not match. If ctx is NULL, the dict is created via getdns_dict_create(). It is the caller's responsibility to call getdns_dict_destroy when it is no longer needed. */ getdns_dict *getdns_pubkey_pin_create_from_string( const getdns_context *context, const char *str) { size_t i; uint8_t buf[SHA256_DIGEST_LENGTH]; getdns_bindata value = { .size = SHA256_DIGEST_LENGTH, .data = buf }; getdns_dict *out = NULL; /* we only do sha256 right now, make sure this is well-formed */ if (!str || strncmp(PIN_PREFIX, str, PIN_PREFIX_LENGTH)) return NULL; for (i = PIN_PREFIX_LENGTH; i < PIN_PREFIX_LENGTH + B64_ENCODED_SHA256_LENGTH - 1; i++) if (!((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= '0' && str[i] <= '9') || (str[i] == '+') || (str[i] == '/'))) return NULL; if (str[i++] != '=') return NULL; if (str[i++] != '"') return NULL; if (str[i++] != '\0') return NULL; if (_getdns_decode_base64(str + PIN_PREFIX_LENGTH, buf, sizeof(buf)) != GETDNS_RETURN_GOOD) goto fail; if (context) out = getdns_dict_create_with_context(context); else out = getdns_dict_create(); if (out == NULL) goto fail; if (getdns_dict_set_bindata(out, "digest", &sha256)) goto fail; if (getdns_dict_set_bindata(out, "value", &value)) goto fail; return out; fail: getdns_dict_destroy(out); return NULL; }
/** * test the copy and pretty print functions */ void tst_copy(void) { char *dictstr = NULL; struct getdns_dict *dict1 = NULL; struct getdns_dict *dict2 = NULL; tstmsg_case_begin("tst_copy"); tstmsg_case_msg("empty list cases"); getdns_dict_copy(NULL, NULL); dict1 = getdns_dict_create(); getdns_dict_copy(dict1, &dict2); getdns_dict_destroy(dict2); /* getdns_dict_copy(NULL, &dict1); */ tstmsg_case_msg("dict1 populate"); getdns_dict_set_int(dict1, "foo", 42); getdns_dict_set_int(dict1, "bar", 52); getdns_dict_set_int(dict1, "quz", 62); dictstr = getdns_pretty_print_dict(dict1); printf("%s\n", dictstr); free(dictstr); tstmsg_case_msg("getdns_dict_copy(dict1, &dict2)"); getdns_dict_copy(dict1, &dict2); dictstr = getdns_pretty_print_dict(dict2); printf("%s\n", dictstr); free(dictstr); getdns_dict_destroy(dict1); getdns_dict_destroy(dict2); tstmsg_case_end(); return; } /* tst_copy */
/** * test the create, destroy and allocation functions */ void tst_create(void) { struct getdns_dict *dict = NULL; /* make sure we can do a simple create/destroy first */ tstmsg_case_begin("tst_create"); tstmsg_case_msg("getdns_dict_create"); dict = getdns_dict_create(); if (dict != NULL) { tstmsg_case_msg("getdns_dict_destroy(dict)"); getdns_dict_destroy(dict); } tstmsg_case_msg("getdns_dict_destroy(NULL)"); getdns_dict_destroy(NULL); tstmsg_case_end(); return; } /* tst_create */
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) break; fprintf(stdout,"Found query: %s", line); } linev[0] = argv[0]; linec = 1; if ( ! (token = strtok(line, " \t\f\n\r"))) continue; do linev[linec++] = token; while (linec < 256 && (token = strtok(NULL, " \t\f\n\r"))); if ((r = parse_args(linec, linev))) { if (r == CONTINUE) 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 (r) goto done_destroy_extensions; if (!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); free(response_str); } else { r = GETDNS_RETURN_MEMORY_ERROR; fprintf( stderr , "Could not print response\n"); } } else if (r == GETDNS_RETURN_GOOD) fprintf(stdout, "Response code was: GOOD\n"); else if (interactive) fprintf(stderr, "An error occurred: %d\n", 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; if (r) fprintf(stderr, "An error occurred: %d\n", r); return r; }
getdns_return_t parse_args(int argc, char **argv) { getdns_return_t r = GETDNS_RETURN_GOOD; size_t i; char *arg, *c, *endptr; int t, print_api_info = 0, print_trust_anchors = 0; getdns_list *upstream_list = NULL; getdns_list *tas = NULL; size_t upstream_count = 0; for (i = 1; i < argc; i++) { arg = argv[i]; if ((t = get_rrtype(arg)) >= 0) { request_type = t; continue; } else if (arg[0] == '+') { if (arg[1] == 's' && arg[2] == 'i' && arg[3] == 't' && (arg[4] == '=' || arg[4] == '\0')) { if ((r = set_cookie(extensions, arg+4))) { fprintf(stderr, "Could not set cookie:" " %d", r); break; } } else if (arg[1] == '0') { /* Unset all existing extensions*/ getdns_dict_destroy(extensions); extensions = getdns_dict_create(); break; } else if ((r = getdns_dict_set_int(extensions, arg+1, GETDNS_EXTENSION_TRUE))) { fprintf(stderr, "Could not set extension " "\"%s\": %d\n", argv[i], r); break; } continue; } else if (arg[0] == '@') { getdns_dict *upstream = ipaddr_dict(context, arg + 1); if (upstream) { if (!upstream_list && !(upstream_list = getdns_list_create_with_context(context))){ fprintf(stderr, "Could not create upstream list\n"); return GETDNS_RETURN_MEMORY_ERROR; } getdns_list_set_dict(upstream_list, upstream_count++, upstream); } continue; } else if (arg[0] != '-') { name = arg; continue; } for (c = arg+1; *c; c++) { switch (*c) { case 'a': async = 1; break; case 'A': calltype = ADDRESS; break; case 'b': if (c[1] != 0 || ++i >= argc || !*argv[i]) { fprintf(stderr, "max_udp_payload_size " "expected after -b\n"); return GETDNS_RETURN_GENERIC_ERROR; } edns0_size = strtol(argv[i], &endptr, 10); if (*endptr || edns0_size < 0) { fprintf(stderr, "positive " "numeric max_udp_payload_size " "expected after -b\n"); return GETDNS_RETURN_GENERIC_ERROR; } getdns_context_set_edns_maximum_udp_payload_size( context, (uint16_t) edns0_size); goto next; case 'D': (void) getdns_context_set_edns_do_bit(context, 1); break; case 'd': (void) getdns_context_set_edns_do_bit(context, 0); break; case 'F': if (c[1] != 0 || ++i >= argc || !*argv[i]) { fprintf(stderr, "file name expected " "after -F\n"); return GETDNS_RETURN_GENERIC_ERROR; } query_file = argv[i]; interactive = 1; break; case 'G': calltype = GENERAL; break; case 'H': calltype = HOSTNAME; break; case 'h': print_usage(stdout, argv[0]); return CONTINUE; case 'i': print_api_info = 1; break; case 'I': interactive = 1; break; case 'j': json = 2; break; case 'J': json = 1; break; case 'k': print_trust_anchors = 1; break; case 'p': json = 0; case 'q': quiet = 1; break; case 'r': getdns_context_set_resolution_type( context, GETDNS_RESOLUTION_RECURSING); break; case 's': getdns_context_set_resolution_type( context, GETDNS_RESOLUTION_STUB); break; case 'S': calltype = SERVICE; break; case 't': if (c[1] != 0 || ++i >= argc || !*argv[i]) { fprintf(stderr, "timeout expected " "after -t\n"); return GETDNS_RETURN_GENERIC_ERROR; } timeout = strtol(argv[i], &endptr, 10); if (*endptr || timeout < 0) { fprintf(stderr, "positive " "numeric timeout expected " "after -t\n"); return GETDNS_RETURN_GENERIC_ERROR; } getdns_context_set_timeout( context, timeout); goto next; case 'e': if (c[1] != 0 || ++i >= argc || !*argv[i]) { fprintf(stderr, "idle timeout expected " "after -t\n"); return GETDNS_RETURN_GENERIC_ERROR; } timeout = strtol(argv[i], &endptr, 10); if (*endptr || timeout < 0) { fprintf(stderr, "positive " "numeric idle timeout expected " "after -t\n"); return GETDNS_RETURN_GENERIC_ERROR; } getdns_context_set_idle_timeout( context, timeout); goto next; case 'T': getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TCP_ONLY); break; case 'O': getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN); break; case 'L': getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN); break; case 'E': getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN); break; case 'R': getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN); break; case 'u': getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP); break; case 'U': getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_UDP_ONLY); break; case 'l': if (c[1] != 0 || ++i >= argc || !*argv[i]) { fprintf(stderr, "transport list expected " "after -l\n"); return GETDNS_RETURN_GENERIC_ERROR; } size_t transport_count = 0; getdns_transport_list_t transports[GETDNS_TRANSPORTS_MAX]; if ((r = fill_transport_list(context, argv[i], transports, &transport_count)) || (r = getdns_context_set_dns_transport_list(context, transport_count, transports))){ fprintf(stderr, "Could not set transports\n"); return r; } break; case 'B': batch_mode = 1; break; default: fprintf(stderr, "Unknown option " "\"%c\"\n", *c); for (i = 0; i < argc; i++) fprintf(stderr, "%d: \"%s\"\n", (int)i, argv[i]); return GETDNS_RETURN_GENERIC_ERROR; } } next: ; } if (r) return r; if (upstream_count && (r = getdns_context_set_upstream_recursive_servers( context, upstream_list))) { fprintf(stderr, "Error setting upstream recursive servers\n"); } if (print_api_info) { fprintf(stdout, "%s\n", getdns_pretty_print_dict( getdns_context_get_api_information(context))); return CONTINUE; } if (print_trust_anchors) { if ((tas = getdns_root_trust_anchor(NULL))) { fprintf(stdout, "%s\n", getdns_pretty_print_list(tas)); return CONTINUE; } else return CONTINUE_ERROR; } return r; }
getdns_dict* GNUtil::convertToDict(Local<Object> obj) { if (obj->IsRegExp() || obj->IsDate() || obj->IsFunction() || obj->IsUndefined() || obj->IsNull() || obj->IsArray()) { return NULL; } Local<Array> names = obj->GetOwnPropertyNames(); getdns_dict* result = getdns_dict_create(); for(unsigned int i = 0; i < names->Length(); i++) { Local<Value> nameVal = names->Get(i); Nan::Utf8String name(nameVal); Local<Value> val = obj->Get(nameVal); GetdnsType type = getGetdnsType(val); switch (type) { case IntType: getdns_dict_set_int(result, *name, val->ToUint32()->Value()); break; case BoolType: if (val->IsTrue()) { getdns_dict_set_int(result, *name, GETDNS_EXTENSION_TRUE); } else { getdns_dict_set_int(result, *name, GETDNS_EXTENSION_FALSE); } break; case StringType: { struct getdns_bindata strdata; String::Utf8Value utf8Str(val->ToString()); int len = utf8Str.length(); strdata.data = (uint8_t*) *utf8Str; strdata.size = len; getdns_dict_set_bindata(result, *name, &strdata); } break; case BinDataType: { struct getdns_bindata bdata; bdata.data = (uint8_t*) node::Buffer::Data(val); bdata.size = node::Buffer::Length(val); getdns_dict_set_bindata(result, *name, &bdata); } break; case ListType: { Local<Array> subArray = Local<Array>::Cast(val); struct getdns_list* sublist = GNUtil::convertToList(subArray); getdns_dict_set_list(result, *name, sublist); getdns_list_destroy(sublist); } break; case DictType: { Local<Object> subObj = val->ToObject(); struct getdns_dict* subdict = GNUtil::convertToDict(subObj); if (subdict) { getdns_dict_set_dict(result, *name, subdict); getdns_dict_destroy(subdict); } } break; default: break; } } return result; }
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; }
/** * test the dict get and set routines */ void tst_dictsetget(void) { char msg[TSTMSGBUF]; size_t index = 0; uint32_t ans_int; getdns_return_t retval; struct getdns_list *list = NULL; struct getdns_dict *dict = NULL; struct getdns_dict *ansdict = NULL; tstmsg_case_begin("tst_dictsetget"); list = getdns_list_create(); dict = getdns_dict_create(); /* test dict get function against empty list and with bogus params */ tstmsg_case_msg("getdns_list_get_dict() empty list"); retval = getdns_list_get_dict(NULL, index, &dict); snprintf(msg, sizeof(msg), "getdns_list_get_dict(NULL, index, &dict),retval = %d", retval); tstmsg_case_msg(msg); retval = getdns_list_get_dict(list, index, NULL); snprintf(msg, sizeof(msg), "getdns_list_get_dict(list, index, NULL),retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_list_get_dict(list, 0, &dict)"); retval = getdns_list_get_dict(list, 0, &dict); snprintf(msg, sizeof(msg), "getdns_list_get_dict,retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_list_get_dict(list, 1, &dict)"); retval = getdns_list_get_dict(list, 1, &dict); snprintf(msg, sizeof(msg), "getdns_list_get_dict,retval = %d", retval); tstmsg_case_msg(msg); /* test int set function against empty list with bogus params */ tstmsg_case_msg("getdns_list_set_dict(list, 0, dict)"); retval = getdns_list_set_dict(list, -1, dict); snprintf(msg, sizeof(msg), "getdns_list_set_dict,retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_list_set_dict(list, 1, dict)"); retval = getdns_list_set_dict(list, 1, dict); snprintf(msg, sizeof(msg), "getdns_list_set_dict,retval = %d", retval); tstmsg_case_msg(msg); /* test set and get legitimate use case */ getdns_dict_set_int(dict, "foo", 42); getdns_list_set_dict(list, index, dict); retval = getdns_list_get_dict(list, index, &ansdict); getdns_dict_get_int(ansdict, "foo", &ans_int); snprintf(msg, sizeof(msg), "getdns_list_set/get_dict,retval=%d, ans=%d", retval, ans_int); tstmsg_case_msg(msg); getdns_dict_destroy(dict); getdns_list_destroy(list); tstmsg_case_end(); return; } /* tst_dictsetget */
/** * test the bindata get and set routines */ void tst_bindatasetget(void) { char msg[TSTMSGBUF]; char key[20]; getdns_return_t retval; struct getdns_dict *dict = NULL; struct getdns_bindata *ans_bdata; struct getdns_bindata *bindata; tstmsg_case_begin("tst_bindatasetget"); dict = getdns_dict_create(); /* test int get function against empty dict and with bogus params */ strcpy(key, "foo"); tstmsg_case_msg("getdns_dict_get_bindata() empty dict"); retval = getdns_dict_get_bindata(NULL, key, &ans_bdata); snprintf(msg, sizeof(msg), "test 1: getdns_dict_get_bindata(NULL, key, &ans_bdata),retval = %d", retval); tstmsg_case_msg(msg); retval = getdns_dict_get_bindata(dict, key, NULL); snprintf(msg, sizeof(msg), "test 2: getdns_dict_get_bindata(dict, key, NULL),retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_bindata(dict, NULL, &ans_bindata)"); retval = getdns_dict_get_bindata(dict, NULL, &ans_bdata); snprintf(msg, sizeof(msg), "test 3: getdns_dict_get_bindata,retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_bindata(dict, key, &ans_bdata)"); retval = getdns_dict_get_bindata(dict, key, &ans_bdata); snprintf(msg, sizeof(msg), "test 4: getdns_list_get_bindata,retval = %d", retval); tstmsg_case_msg(msg); getdns_dict_destroy(dict); /* TODO: test getdns_dict_set functions with bogus params */ /* test set and get legitimate use case */ dict = getdns_dict_create(); strcpy(key, "foo"); bindata = (struct getdns_bindata *) malloc(sizeof(struct getdns_bindata)); bindata->size = strlen("foobar") + 1; bindata->data = (void *) strdup("foobar"); tstmsg_case_msg("getdns_dict_set_bindata(dict, key, bindata)"); retval = getdns_dict_set_bindata(dict, key, bindata); snprintf(msg, sizeof(msg), "test 5: getdns_dict_set_bindata,retval=%d,key=%s", retval, key); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_bindata(dict, key, &ans_bdata)"); retval = getdns_dict_get_bindata(dict, key, &ans_bdata); snprintf(msg, sizeof(msg), "test 6: getdns_dict_get_bindata,retval=%d,key=%s,data=%s", retval, key, ans_bdata->data); tstmsg_case_msg(msg); getdns_dict_destroy(dict); free(bindata->data); free(bindata); tstmsg_case_end(); return; } /* tst_bindatasetget */
/** * test the int get and set routines */ void tst_intsetget(void) { char msg[TSTMSGBUF]; char key[20]; uint32_t ans_int; uint32_t newint; getdns_return_t retval; struct getdns_dict *dict = NULL; getdns_data_type dtype; tstmsg_case_begin("tst_intsetget"); dict = getdns_dict_create(); /* test int get function against empty list and with bogus params */ strcpy(key, "foo"); tstmsg_case_msg("getdns_dict_get_int() empty dict"); retval = getdns_dict_get_int(NULL, key, &ans_int); snprintf(msg, sizeof(msg), "test 19: getdns_dict_get_int(NULL, key, &ans_int),retval = %d", retval); tstmsg_case_msg(msg); retval = getdns_dict_get_int(dict, key, NULL); snprintf(msg, sizeof(msg), "test 20: getdns_dict_get_int(dict, key, NULL),retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_int(dict, NULL, &ans_int)"); retval = getdns_dict_get_int(dict, NULL, &ans_int); snprintf(msg, sizeof(msg), "test 21: getdns_dict_get_int,retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_int(dict, key, &ans_int)"); retval = getdns_dict_get_int(dict, key, &ans_int); snprintf(msg, sizeof(msg), "test 22: getdns_list_get_int,retval = %d", retval); tstmsg_case_msg(msg); getdns_dict_destroy(dict); /* TODO: test getdns_dict_set functions with bogus params */ /* test set and get legitimate use case */ dict = getdns_dict_create(); strcpy(key, "foo"); newint = 42; tstmsg_case_msg("getdns_dict_set_int(dict, key, newint)"); retval = getdns_dict_set_int(dict, key, newint); snprintf(msg, sizeof(msg), "test 23: getdns_dict_set_int,retval=%d,key=%s,int=%d", retval, key, newint); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_int(dict, key, &ans_int)"); retval = getdns_dict_get_int(dict, key, &ans_int); snprintf(msg, sizeof(msg), "test 24: getdns_dict_get_int,retval=%d,key=%s,int=%d", retval, key, ans_int); tstmsg_case_msg(msg); strcpy(key, "bar"); newint = 52; tstmsg_case_msg("getdns_dict_set_int(dict, key, newint)"); retval = getdns_dict_set_int(dict, key, newint); snprintf(msg, sizeof(msg), "test 25: getdns_dict_set_int,retval=%d,key=%s,int=%d", retval, key, newint); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_int(dict, key, &ans_int)"); retval = getdns_dict_get_int(dict, key, &ans_int); snprintf(msg, sizeof(msg), "test 26: getdns_dict_get_int,retval=%d,key=%s,int=%d", retval, key, ans_int); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_data_type(dict, key, &dtype)"); retval = getdns_dict_get_data_type(dict, key, &dtype); snprintf(msg, sizeof(msg), "test 27: getdns_dict_get_data_type,retval=%d,key=%s,dtype=%d", retval, key, dtype); tstmsg_case_msg(msg); getdns_dict_destroy(dict); tstmsg_case_end(); return; } /* tst_intsetget */
/** * test the list get and set routines */ void tst_listsetget(void) { char msg[TSTMSGBUF]; char key[20]; size_t index; uint32_t int1; uint32_t int2; getdns_return_t retval; struct getdns_list *newlist; struct getdns_list *anslist; struct getdns_dict *dict = NULL; tstmsg_case_begin("tst_listsetget"); dict = getdns_dict_create(); /* test get function against empty list and with bogus params */ strcpy(key, "foo"); tstmsg_case_msg("getdns_dict_get_list() empty dict"); retval = getdns_dict_get_list(NULL, key, &anslist); snprintf(msg, sizeof(msg), "test 13: getdns_dict_get_list(NULL, key, &anslist),retval = %d", retval); tstmsg_case_msg(msg); retval = getdns_dict_get_list(dict, key, NULL); snprintf(msg, sizeof(msg), "test 14: getdns_dict_get_list(dict, key, NULL),retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_list(dict, NULL, &anslist)"); retval = getdns_dict_get_list(dict, NULL, &anslist); snprintf(msg, sizeof(msg), "test 15: getdns_dict_get_list,retval = %d", retval); tstmsg_case_msg(msg); tstmsg_case_msg("getdns_dict_get_list(dict, key, &anslist)"); retval = getdns_dict_get_list(dict, key, &anslist); snprintf(msg, sizeof(msg), "test 16: getdns_list_get_list,retval = %d", retval); tstmsg_case_msg(msg); getdns_dict_destroy(dict); /* TODO: test getdns_dict_set functions with bogus params */ /* test set and get legitimate use case */ dict = getdns_dict_create(); strcpy(key, "foo"); newlist = getdns_list_create(); getdns_list_add_item(newlist, &index); getdns_list_set_int(newlist, index, 42); getdns_list_add_item(newlist, &index); getdns_list_set_int(newlist, index, 52); tstmsg_case_msg("getdns_dict_set_list(dict, key, newlist)"); retval = getdns_dict_set_list(dict, key, newlist); snprintf(msg, sizeof(msg), "test 17: getdns_dict_set_list,retval=%d,key=%s", retval, key); tstmsg_case_msg(msg); getdns_list_destroy(newlist); tstmsg_case_msg("getdns_dict_get_list(dict, key, &anslist)"); retval = getdns_dict_get_list(dict, key, &anslist); getdns_list_get_int(anslist, 0, &int1); getdns_list_get_int(anslist, 1, &int2); snprintf(msg, sizeof(msg), "test 18: getdns_dict_get_list,retval=%d,key=%s,int1=%d,int2=%d", retval, key, int1, int2); tstmsg_case_msg(msg); getdns_dict_destroy(dict); tstmsg_case_end(); return; } /* tst_listsetget */
/** * exercise the getdns_dict_get_names function */ void tst_getnames(void) { size_t index; size_t llen; uint32_t ansint; int i; getdns_return_t result; getdns_data_type dtype; struct getdns_dict *dict = NULL; struct getdns_list *list = NULL; tstmsg_case_begin("tst_getnames"); dict = getdns_dict_create(); /* degenerative use cases */ tstmsg_case_msg("getdns_dict_get_names(NULL, &list)"); getdns_dict_get_names(NULL, &list); getdns_list_destroy(list); tstmsg_case_msg("getdns_dict_get_names(dict, NULL)"); getdns_dict_get_names(dict, NULL); tstmsg_case_msg ("getdns_dict_get_names(dict, &list), empty dictionary"); getdns_dict_get_names(dict, &list); getdns_list_destroy(list); /* legit use case, add items out of order to exercise tree */ /* TODO: add elements of type dict, bindata, list to the dict */ i = 0; getdns_dict_set_int(dict, "foo", i++); getdns_dict_set_int(dict, "bar", i++); getdns_dict_set_int(dict, "quz", i++); getdns_dict_set_int(dict, "alpha", i++); getdns_dict_get_names(dict, &list); result = getdns_list_get_length(list, &llen); if (result != GETDNS_RETURN_GOOD) { tstmsg_case_msg ("getdns_list_get_length failed, exiting"); return; } if (llen != i) { tstmsg_case_msg ("getdns_list_get_length returned unreasonable length, exiting"); return; } for (index = 0; index < llen; index++) { getdns_list_get_data_type(list, index, &dtype); printf(" list item %d: ", (int) index); switch (dtype) { case t_bindata: printf("NOTIMPLEMENTED"); break; case t_dict: printf("NOTIMPLEMENTED"); break; case t_int: getdns_list_get_int(list, index, &ansint); printf("t_int, value=%d\n", ansint); break; case t_list: printf("NOTIMPLEMENTED"); break; default: printf("data type invalid"); break; } } getdns_dict_destroy(dict); getdns_list_destroy(list); tstmsg_case_end(); } /* tst_getnames */
int main(int argc, char const * const argv[]) { getdns_return_t r; getdns_dict *rr_dict; getdns_bindata *dns_name; getdns_bindata address = { 4, "\xb9\x31\x8d\x25" }; getdns_bindata fourth = { 11, "last string" }; size_t length; char *str; uint8_t *wire, *prev_wire; size_t wire_len; getdns_list *rr_list; FILE *in; uint8_t wire_buf[8200]; size_t i; size_t uavailable; int available; char str_buf[10000]; int str_len = sizeof(str_buf); /* Convert string to rr_dict */ if ((r = getdns_str2rr_dict( "some.domain.tld. 60 IN TXT \"first string\" second \"and third\"", &rr_dict, NULL, 3600))) FAIL_r("getdns_str2rr_dict"); /* Add a fourth text element. */ if ((r = getdns_dict_set_bindata(rr_dict, "/rdata/txt_strings/-", &fourth))) FAIL_r("getdns_list_set_bindata"); print_dict(rr_dict); /* Convert to wireformat from rdata_raw. * Added fourth list element should NOT show. */ wire = NULL; if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); print_wire(wire, wire_len); free(wire); /* Convert to wireformat from parsing rdata fields. * Added fourth list element should show. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); printf("\nremoved \"/rdata/rdata_raw\":\n\n"); if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); print_wire(wire, wire_len); free(wire); /* Remove second and third string elements and show text format. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/1"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/1"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("\n%s", str); free(str); /* Remove all string elements and show text format. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/0"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/0"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); getdns_dict_destroy(rr_dict); /* Construct rr_dict and convert to string */ if (!(rr_dict = getdns_dict_create())) FAIL("getdns_dict_create returned NULL"); if ((r = getdns_convert_fqdn_to_dns_name("www.getdnsapi.net", &dns_name))) FAIL_r("getdns_convert_fqdn_to_dns_name"); r = getdns_dict_set_bindata(rr_dict, "name", dns_name); free(dns_name->data); free(dns_name); if (r) FAIL_r("getdns_dict_set_bindata"); if ((r = getdns_dict_set_int(rr_dict, "type", GETDNS_RRTYPE_A))) FAIL_r("getdns_dict_set_int"); if ((r = getdns_dict_set_bindata(rr_dict, "/rdata/ipv4_address", &address))) FAIL_r("getdns_dict_set_int"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("\n%s\n", str); free(str); if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); getdns_dict_destroy(rr_dict); print_wire(wire, wire_len); free(wire); /* Convert RR with special rdata fields and repeating last element * from string to rr_dict */ if ((r = getdns_str2rr_dict( "hip2 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com.", &rr_dict, "nlnetlabs.nl", 3600))) FAIL_r("getdns_str2rr_dict"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); printf("\n"); print_dict(rr_dict); /* Convert RR with special rdata fields and repeating last element * back to string. */ if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); /* Convert RR with special rdata fields without repeating last element * to string. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rendezvous_servers"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_get_bindata(rr_dict, "name", &dns_name))) FAIL_r("getdns_dict_get_bindata"); dns_name->data[4] = '0'; if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s\n", str); free(str); getdns_dict_destroy(rr_dict); /* Convert RR with repeat block from string to rr_dict */ if ((r = getdns_str2rr_dict( "apl APL 1:192.168.42.0/26 1:192.168.42.64/26 !1:192.168.42.128/25 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8", &rr_dict, "net-dns.org", 3600))) FAIL_r("getdns_str2rr_dict"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); print_dict(rr_dict); /* Convert repeat block from rr_dict back to string. */ if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); getdns_dict_destroy(rr_dict); if (!(in = fopen(argv[1], "r"))) FAIL("Could not fopen %s\n", argv[1]); if ((r = getdns_fp2rr_list(in, &rr_list, NULL, 0))) FAIL_r("getdns_fp2rr_list"); fclose(in); print_list(rr_list); print_json_list(rr_list, 1); /* Fill the wire_buf with wireformat RR's in rr_list * wire_buf is too small for last two rr's. */ wire = wire_buf; available = sizeof(wire_buf); for (i = 0; !(r = getdns_list_get_dict(rr_list, i, &rr_dict)); i++) { prev_wire = wire; if ((r = getdns_rr_dict2wire_scan(rr_dict,&wire,&available))) { if (r == GETDNS_RETURN_NEED_MORE_SPACE) { printf("record %.3zu, available buffer space: " "%d\n", i, available); /* The buffer was too small to fit the wire- * format representation. available now holds * a negative number. the wire pointer is this * much beyond the end of the buffer space. * * If we would add available to wire, wire * would be positioned at the end of the buffer * but would not be positioned at a clean RR * border. Therefore we have to remember the * previous position of wire, so we can reset * it at the end of the wireformat representa- * tion of the previously converted rr_dict. */ wire = prev_wire; break; } else FAIL_r("getdns_rr_dict2wire_scan"); } printf("record %3zu, available buffer space: " "%d\n", i, available); fflush(stdout); } if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM) r = GETDNS_RETURN_GOOD; getdns_list_destroy(rr_list); /* Now scan over the wireformat buffer and convert to rr_dicts again. * Then fill a string buffer with those rr_dicts. */ available = wire - wire_buf; if (available < 0) { fprintf(stderr, "Negative sized buffer!\n"); exit(EXIT_FAILURE); } uavailable = available; wire = wire_buf; str = str_buf; str_len = sizeof(str_buf); while (uavailable > 0 && str_len > 0) { rr_dict = NULL; if ((r = getdns_wire2rr_dict_scan( (const uint8_t **)&wire, &uavailable, &rr_dict))) FAIL_r("getdns_wire2rr_dict_scan"); if ((r = getdns_rr_dict2str_scan(rr_dict, &str, &str_len))) FAIL_r("getdns_rr_dict2str_scan"); getdns_dict_destroy(rr_dict); } *str = 0; /* Print the entire buffer */ printf("%s", str_buf); exit(EXIT_SUCCESS); }