diff --git a/CodingStyle b/CodingStyle new file mode 100644 index 00000000..5eedbc15 --- /dev/null +++ b/CodingStyle @@ -0,0 +1,481 @@ +/* $NetBSD: style,v 1.51 2013/03/08 16:50:02 christos Exp $ */ + +/* + * The revision control tag appears first, with a blank line after it. + * Copyright text appears after the revision control tag. + */ + +/* + * The NetBSD source code style guide. + * (Previously known as KNF - Kernel Normal Form). + * + * from: @(#)style 1.12 (Berkeley) 3/18/94 + */ +/* + * An indent(1) profile approximating the style outlined in + * this document lives in /usr/share/misc/indent.pro. It is a + * useful tool to assist in converting code to KNF, but indent(1) + * output generated using this profile must not be considered to + * be an authoritative reference. + */ + +/* + * Source code revision control identifiers appear after any copyright + * text. Use the appropriate macros from . Usually only one + * source file per program contains a __COPYRIGHT() section. + * Historic Berkeley code may also have an __SCCSID() section. + * Only one instance of each of these macros can occur in each file. + * Don't use newlines in the identifiers. + */ +#include +__COPYRIGHT("@(#) Copyright (c) 2008\ + The NetBSD Foundation, inc. All rights reserved."); +__RCSID("$NetBSD: style,v 1.51 2013/03/08 16:50:02 christos Exp $"); + +/* + * VERY important single-line comments look like this. + */ + +/* Most single-line comments look like this. */ + +/* + * Multi-line comments look like this. Make them real sentences. Fill + * them so they look like real paragraphs. + */ + +/* + * Attempt to wrap lines longer than 80 characters appropriately. + * Refer to the examples below for more information. + */ + +/* + * EXAMPLE HEADER FILE: + * + * A header file should protect itself against multiple inclusion. + * E.g, would contain something like: + */ +#ifndef _SYS_SOCKET_H_ +#define _SYS_SOCKET_H_ +/* + * Contents of #include file go between the #ifndef and the #endif at the end. + */ +#endif /* !_SYS_SOCKET_H_ */ +/* + * END OF EXAMPLE HEADER FILE. + */ + +/* + * If a header file requires structures, defines, typedefs, etc. from + * another header file it should include that header file and not depend + * on the including file for that header including both. If there are + * exceptions to this for specific headers it should be clearly documented + * in the headers and, if appropriate, the documentation. Nothing in this + * rule should suggest relaxation of the multiple inclusion rule and the + * application programmer should be free to include both regardless. + */ + +/* + * Kernel include files come first. + */ +#include /* first, */ +#include /* next, */ +#include /* and then the rest, */ +#include /* sorted lexicographically. */ +#include +#include /* Non-local includes in brackets. */ + +/* + * If it's a network program, put the network include files next. + * Group the includes files by subdirectory. + */ +#include +#include +#include +#include +#include + +/* + * Then there's a blank line, followed by the /usr include files. + * The /usr include files should be sorted lexicographically! + */ +#include +#include +#include +#include +#include + +/* + * Global pathnames are defined in /usr/include/paths.h. Pathnames local + * to the program go in pathnames.h in the local directory. + */ +#include + +/* Then, there's a blank line, and the user include files. */ +#include "pathnames.h" /* Local includes in double quotes. */ + +/* + * ANSI function declarations for private functions (i.e. functions not used + * elsewhere) and the main() function go at the top of the source module. + * Don't associate a name with the types. I.e. use: + * void function(int); + * Use your discretion on indenting between the return type and the name, and + * how to wrap a prototype too long for a single line. In the latter case, + * lining up under the initial left parenthesis may be more readable. + * In any case, consistency is important! + */ +static char *function(int, int, float, int); +static int dirinfo(const char *, struct stat *, struct dirent *, + struct statfs *, int *, char **[]); +static void usage(void) __dead; /* declare functions that don't return dead */ + +/* + * Macros are capitalized, parenthesized, and should avoid side-effects. + * Spacing before and after the macro name may be any whitespace, though + * use of TABs should be consistent through a file. + * If they are an inline expansion of a function, the function is defined + * all in lowercase, the macro has the same name all in uppercase. + * If the macro is an expression, wrap the expression in parenthesis. + * If the macro is more than a single statement, use ``do { ... } while (0)'', + * so that a trailing semicolon works. Right-justify the backslashes; it + * makes it easier to read. The CONSTCOND comment is to satisfy lint(1). + */ +#define MACRO(v, w, x, y) \ +do { \ + v = (x) + (y); \ + w = (y) + 2; \ +} while (/* CONSTCOND */ 0) + +#define DOUBLE(x) ((x) * 2) + +/* Enum types are capitalized. No comma on the last element. */ +enum enumtype { + ONE, + TWO +} et; + +/* + * When declaring variables in structures, declare them organized by use in + * a manner to attempt to minimize memory wastage because of compiler alignment + * issues, then by size, and then by alphabetical order. E.g, don't use + * ``int a; char *b; int c; char *d''; use ``int a; int b; char *c; char *d''. + * Each variable gets its own type and line, although an exception can be made + * when declaring bitfields (to clarify that it's part of the one bitfield). + * Note that the use of bitfields in general is discouraged. + * + * Major structures should be declared at the top of the file in which they + * are used, or in separate header files, if they are used in multiple + * source files. Use of the structures should be by separate declarations + * and should be "extern" if they are declared in a header file. + * + * It may be useful to use a meaningful prefix for each member name. + * E.g, for ``struct softc'' the prefix could be ``sc_''. + */ +struct foo { + struct foo *next; /* List of active foo */ + struct mumble amumble; /* Comment for mumble */ + int bar; + unsigned int baz:1, /* Bitfield; line up entries if desired */ + fuz:5, + zap:2; + uint8_t flag; +}; +struct foo *foohead; /* Head of global foo list */ + +/* Make the structure name match the typedef. */ +typedef struct BAR { + int level; +} BAR; + +/* C99 uintN_t is preferred over u_intN_t. */ +uint32_t zero; + +/* + * All major routines should have a comment briefly describing what + * they do. The comment before the "main" routine should describe + * what the program does. + */ +int +main(int argc, char *argv[]) +{ + long num; + int ch; + char *ep; + + /* + * At the start of main(), call setprogname() to set the program + * name. This does nothing on NetBSD, but increases portability + * to other systems. + */ + setprogname(argv[0]); + + /* + * For consistency, getopt should be used to parse options. + * Options should be sorted in the getopt call and the switch + * statement, unless parts of the switch cascade. For the + * sorting order, see the usage() example below. Don't forget + * to add option descriptions to the usage and the manpage. + * Elements in a switch statement that cascade should have a + * FALLTHROUGH comment. Numerical arguments should be checked + * for accuracy. Code that cannot be reached should have a + * NOTREACHED comment. + */ + while ((ch = getopt(argc, argv, "abn:")) != -1) { + switch (ch) { /* Indent the switch. */ + case 'a': /* Don't indent the case. */ + aflag = 1; + /* FALLTHROUGH */ + case 'b': + bflag = 1; + break; + case 'n': + errno = 0; + num = strtol(optarg, &ep, 10); + if (num <= 0 || *ep != '\0' || (errno == ERANGE && + (num == LONG_MAX || num == LONG_MIN)) ) + errx(1, "illegal number -- %s", optarg); + break; + case '?': + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + /* + * Space after keywords (while, for, return, switch). No braces are + * required for control statements with only a single statement, + * unless it's a long statement. + * + * Forever loops are done with for's, not while's. + */ + for (p = buf; *p != '\0'; ++p) + continue; /* Explicit no-op */ + for (;;) + stmt; + + /* + * Braces are required for control statements with a single statement + * that may expand to nothing. + */ +#ifdef DEBUG_FOO +#define DPRINTF(a) printf a +#else +#define DPRINTF(a) +#endif + if (broken) { + DPRINTF(("broken is %d\n", broken)); + } + + /* + * Parts of a for loop may be left empty. Don't put declarations + * inside blocks unless the routine is unusually complicated. + */ + for (; cnt < 15; cnt++) { + stmt1; + stmt2; + } + + /* Second level indents are four spaces. */ + while (cnt < 20) + z = a + really + long + statement + that + needs + two + lines + + gets + indented + four + spaces + on + the + second + + and + subsequent + lines; + + /* + * Closing and opening braces go on the same line as the else. + * Don't add braces that aren't necessary except in cases where + * there are ambiguity or readability issues. + */ + if (test) { + /* + * I have a long comment here. + */ +#ifdef zorro + z = 1; +#else + b = 3; +#endif + } else if (bar) { + stmt; + stmt; + } else + stmt; + + /* No spaces after function names. */ + if ((result = function(a1, a2, a3, a4)) == NULL) + exit(1); + + /* + * Unary operators don't require spaces, binary operators do. + * Don't excessively use parenthesis, but they should be used if + * statement is really confusing without them, such as: + * a = b->c[0] + ~d == (e || f) || g && h ? i : j >> 1; + */ + a = ((b->c[0] + ~d == (e || f)) || (g && h)) ? i : (j >> 1); + k = !(l & FLAGS); + + /* + * Exits should be EXIT_SUCCESS on success, and EXIT_FAILURE on + * failure. Don't denote all the possible exit points, using the + * integers 1 through 127. Avoid obvious comments such as "Exit + * 0 on success.". Since main is a function that returns an int, + * prefer returning from it, than calling exit. + */ + return EXIT_SUCCESS; +} + +/* + * The function type must be declared on a line by itself + * preceding the function. + */ +static char * +function(int a1, int a2, float fl, int a4) +{ + /* + * When declaring variables in functions declare them sorted by size, + * then in alphabetical order; multiple ones per line are okay. + * Function prototypes should go in the include file "extern.h". + * If a line overflows reuse the type keyword. + * + * DO NOT initialize variables in the declarations. + */ + extern u_char one; + extern char two; + struct foo three, *four; + double five; + int *six, seven; + char *eight, *nine, ten, eleven, twelve, thirteen; + char fourteen, fifteen, sixteen; + + /* + * Casts and sizeof's are not followed by a space. NULL is any + * pointer type, and doesn't need to be cast, so use NULL instead + * of (struct foo *)0 or (struct foo *)NULL. Also, test pointers + * against NULL. I.e. use: + * + * (p = f()) == NULL + * not: + * !(p = f()) + * + * The notable exception here is variadic functions. Since our + * code is designed to compile and work on different environments + * where we don't have control over the NULL definition (on NetBSD + * it is defined as ((void *)0), but on other systems it can be + * defined as (0) and both definitions are valid under ANSI C), it + * it advised to cast NULL to a pointer on varyadic functions, + * because on machines where sizeof(pointer) != sizeof(int) and in + * the absence of a prototype in scope, passing an un-casted NULL, + * will result in passing an int on the stack instead of a pointer. + * + * Don't use `!' for tests unless it's a boolean. + * E.g. use "if (*p == '\0')", not "if (!*p)". + * + * Routines returning ``void *'' should not have their return + * values cast to more specific pointer types. + * + * Prefer sizeof(*var) over sizeof(type) because if type changes, + * the change needs to be done in one place. + * + * Use err/warn(3), don't roll your own! + */ + if ((four = malloc(sizeof(*four))) == NULL) + err(1, NULL); + if ((six = (int *)overflow()) == NULL) + errx(1, "Number overflowed."); + + /* No parentheses are needed around the return value. */ + return eight; +} + +/* + * Use ANSI function declarations. ANSI function braces look like + * old-style (K&R) function braces. + * As per the wrapped prototypes, use your discretion on how to format + * the subsequent lines. + */ +static int +dirinfo(const char *p, struct stat *sb, struct dirent *de, struct statfs *sf, + int *rargc, char **rargv[]) +{ /* Insert an empty line if the function has no local variables. */ + + /* + * In system libraries, catch obviously invalid function arguments + * using _DIAGASSERT(3). + */ + _DIAGASSERT(p != NULL); + _DIAGASSERT(filedesc != -1); + + if (stat(p, sb) < 0) + err(1, "Unable to stat %s", p); + + /* + * To printf quantities that might be larger that "long", include + * , cast quantities to intmax_t or uintmax_t and use + * PRI?MAX constants. + */ + (void)printf("The size of %s is %" PRIdMAX " (%#" PRIxMAX ")\n", p, + (intmax_t)sb->st_size, (uintmax_t)sb->st_size); + + /* + * To printf quantities of known bit-width, use the corresponding + * defines (generally only done within NetBSD for quantities that + * exceed 32-bits). + */ + (void)printf("%s uses %" PRId64 " blocks and has flags %#" PRIx32 "\n", + p, sb->st_blocks, sb->st_flags); + + /* + * There are similar constants that should be used with the *scanf(3) + * family of functions: SCN?MAX, SCN?64, etc. + */ +} + +/* + * Functions that support variable numbers of arguments should look like this. + * (With the #include appearing at the top of the file with the + * other include files.) + */ +#include + +void +vaf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + STUFF; + va_end(ap); + /* No return needed for void functions. */ +} + +static void +usage(void) +{ + + /* + * Use printf(3), not fputs/puts/putchar/whatever, it's faster and + * usually cleaner, not to mention avoiding stupid bugs. + * Use snprintf(3) or strlcpy(3)/strlcat(3) instead of sprintf(3); + * again to avoid stupid bugs. + * + * Usage statements should look like the manual pages. + * Options w/o operands come first, in alphabetical order + * inside a single set of braces, upper case before lower case + * (AaBbCc...). Next are options with operands, in the same + * order, each in braces. Then required arguments in the + * order they are specified, followed by optional arguments in + * the order they are specified. A bar (`|') separates + * either/or options/arguments, and multiple options/arguments + * which are specified together are placed in a single set of + * braces. + * + * Use getprogname() instead of hardcoding the program name. + * + * "usage: f [-aDde] [-b b_arg] [-m m_arg] req1 req2 [opt1 [opt2]]\n" + * "usage: f [-a | -b] [-c [-de] [-n number]]\n" + */ + (void)fprintf(stderr, "usage: %s [-ab]\n", getprogname()); + exit(EXIT_FAILURE); +} diff --git a/configure.ac b/configure.ac index b47e47eb..a1374f1e 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ # AC_PREREQ([2.68]) -AC_INIT([getdns], [0.320], [melinda.shore@nomountain.net]) +AC_INIT([getdns], [0.1.0], [melinda.shore@nomountain.net]) AC_CONFIG_SRCDIR([src/getdns/getdns.h]) # AM_INIT_AUTOMAKE # LT_INIT @@ -60,10 +60,10 @@ AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T -AC_CONFIG_FILES([Makefile src/Makefile src/getdns/Makefile src/example/Makefile src/test/Makefile]) +AC_CONFIG_FILES([Makefile src/Makefile src/getdns/Makefile src/example/Makefile src/test/Makefile doc/Makefile]) if [ test -n "$DOXYGEN" ] then AC_CONFIG_FILES([src/Doxyfile]) fi -AC_CONFIG_SUBDIRS([src/ src/getdns/ src/example/ src/test/]) +AC_CONFIG_SUBDIRS([src/ src/getdns/ src/example/ src/test/ doc/]) AC_OUTPUT diff --git a/doc/getdns_address.3.in b/doc/getdns_address.3.in new file mode 100644 index 00000000..33e41887 --- /dev/null +++ b/doc/getdns_address.3.in @@ -0,0 +1,46 @@ +.TH libgetdns 3 "November 2013" "getdns 0.0.0" getdns +.SH NAME +getdns_address +.SH LIBRARY +DNS Resolver library (libgetdns, -lgetdns) + +.SH SYNOPSIS +#include + +getdns_return_t +.br +.B getdns_address +(getdns_context_t context, const char *name, struct getdns_dict *extensions, void *userarg, getdns_transaction_t *transaction_id, getdns_callback_t callbackfn); + +.SH DESCRIPTION + +.LP +THIS IS A WORK IN PROGRESS - MUCH TO ADD + +.LP +The getdns_address(3) and getdns_address_sync functions provide public entry points into the getdns API library to retrieve the address given a host name. It always returns both IPv4 and IPv6 addresses. + +.SH FILES +.br +/etc/hosts +.br +/etc/resolv.conf + +.SH EXAMPLES + +TBD + +.SH DIAGNOSTICS + +TBD + +.SH SEE ALSO +.BR libgetdns (3), +.BR getdns_address_sync (3), +.BR getdns_general (3), +.BR getdns_general_sync (3), +.BR getdns_hostname (3), +.BR getdns_hostname_sync (3), +.BR getdns_service (3), +.BR getdns_service_sync (3). + diff --git a/doc/libgetdns.3.in b/doc/libgetdns.3.in new file mode 100644 index 00000000..64ddc54a --- /dev/null +++ b/doc/libgetdns.3.in @@ -0,0 +1,70 @@ +.TH libgetdns 3 "November 2013" "getdns 0.0.0" getdns +.SH NAME +libgetdns +.Sh LIBRARY +DNS Resolver library (libgetdns, -lgetdns) + +.SH SYNOPSIS +.Lb libgetdns +#include + +THe public entry points are captured in separate man pages. + +.SH DESCRIPTION + +.LP +THIS IS A WORK IN PROGRESS - LOTS TO ADD + +.LP +This document describes a modern asynchronous DNS API. This new API is intended to be useful to application developers and operating system distributors as a way of making all types of DNS information easily available in many types of programs. The major features of this new API are: + +.RS 3 + Full support for event-driven programming + Supports DNSSEC in multiple ways + Mirroring of the resolution in getaddrinfo() + Easily supports all RRtypes, even those yet to be defined +.RE + +.LP +This implementation of the getdns API is licensed under the BSD license. + +.SH FILES +.br /etc/hosts +.br /etc/resolv.conf + +.SH EXAMPLES +TBD + +.SH DIAGNOSTICS +TBD + +.SH "SEE ALSO" +.BR getdns_address (3), +.BR getdns_address_sync (3), +.BR getdns_general (3), +.BR getdns_general_sync (3), +.BR getdns_hostname (3), +.BR getdns_hostname_sync (3), +.BR getdns_service (3), +.BR getdns_service_sync (3). + +.SH REPORTING PROBLEMS +Bug reports should be sent to the getdns-bugs@getdns.net + +.SH AUTHORS + +The getdns API was documented by Paul Hoffman. This implementation of the getdns API was written by: +.LP +.RS 3 +.br +Neel Goyal, Verisign Inc. +.br +Melinda Shore, No Mountain Software, LLC +.br +Willem Toorop, NLNet Labs +.br +Wouter Wijngaards, NLNet Labs +.br +Glen Wiley, Verisign Inc. +.RE + diff --git a/spec/example-all-functions.c b/spec/example-all-functions.c new file mode 100644 index 00000000..c4ad41c5 --- /dev/null +++ b/spec/example-all-functions.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include +#include +#include +#include + +#define UNUSED_PARAM(x) ((void)(x)) + +/* The return values */ +getdns_return_t retregular; +char * retcharstar; + +/* The args */ +bool boolarg; +char * charstararg; +getdns_callback_t callbackarg; +uint16_t regulararg; +uint16_t *regularptrarg; +getdns_transaction_t txidarg; +getdns_transaction_t * txidptrarg; + +getdns_data_type * datatypeptrarg; +struct getdns_bindata ** bindataptrarg; +struct getdns_dict * dictarg; +struct getdns_bindata * bindataarg; +struct getdns_list * listarg; +struct getdns_dict ** dictptrarg; +struct getdns_list ** listptrarg; + +size_t sizetarg; +size_t * sizetptrarg; +getdns_context_t contextarg = NULL; +uint8_t uint8arg; +uint16_t uint16arg; +uint32_t uint32arg; +uint8_t * uint8ptrarg; +uint16_t * uint16ptrarg; +uint32_t * uint32ptrarg; +void * arrayarg; +void allocfunctionarg(size_t foo) {UNUSED_PARAM(foo);} +void deallocfunctionarg(void* foo) {UNUSED_PARAM(foo);} +void setcallbackfunctionarg(struct getdns_context_t *foo1, uint16_t foo2) + {UNUSED_PARAM(foo1);UNUSED_PARAM(foo2);} + +int main() +{ + +retregular = getdns_general( + contextarg, + charstararg, + uint16arg, + dictarg, + arrayarg, + txidptrarg, + callbackarg +); + +retregular = getdns_address( + contextarg, + charstararg, + dictarg, + arrayarg, + txidptrarg, + callbackarg +); + +retregular = getdns_hostname( + contextarg, + dictarg, + dictarg, + arrayarg, + txidptrarg, + callbackarg +); + +retregular = getdns_service( + contextarg, + charstararg, + dictarg, + arrayarg, + txidptrarg, + callbackarg +); + +retregular = getdns_context_create( + &contextarg, + boolarg +); + +getdns_context_destroy( + contextarg +); + +retregular = getdns_cancel_callback( + contextarg, + txidarg +); + +retregular = getdns_general_sync( + contextarg, + charstararg, + uint16arg, + dictarg, + uint32ptrarg, + dictarg +); + +retregular = getdns_address_sync( + contextarg, + charstararg, + dictarg, + uint32ptrarg, + dictarg +); + +retregular = getdns_hostname_sync( + contextarg, + dictarg, + dictarg, + uint32ptrarg, + dictarg +); + +retregular = getdns_service_sync( + contextarg, + charstararg, + dictarg, + uint32ptrarg, + dictarg +); + +getdns_free_sync_request_memory( + dictarg +); + +retregular = getdns_list_get_length(listarg, sizetptrarg); +retregular = getdns_list_get_data_type(listarg, sizetarg, datatypeptrarg); +retregular = getdns_list_get_dict(listarg, sizetarg, dictptrarg); +retregular = getdns_list_get_list(listarg, sizetarg, listptrarg); +retregular = getdns_list_get_bindata(listarg, sizetarg, bindataptrarg); +retregular = getdns_list_get_int(listarg, sizetarg, uint32ptrarg); + +retregular = getdns_dict_get_names(dictarg, listptrarg); +retregular = getdns_dict_get_data_type(dictarg, charstararg, datatypeptrarg); +retregular = getdns_dict_get_dict(dictarg, charstararg, dictptrarg); +retregular = getdns_dict_get_list(dictarg, charstararg, listptrarg); +retregular = getdns_dict_get_bindata(dictarg, charstararg, bindataptrarg); +retregular = getdns_dict_get_int(dictarg, charstararg, uint32ptrarg); + +listarg = getdns_list_create(); +getdns_list_destroy(listarg); +retregular = getdns_list_set_dict(listarg, sizetarg, dictarg); +retregular = getdns_list_set_list(listarg, sizetarg, listarg); +retregular = getdns_list_set_bindata(listarg, sizetarg, bindataarg); +retregular = getdns_list_set_int(listarg, sizetarg, uint32arg); + +dictarg = getdns_dict_create(); +getdns_dict_destroy(dictarg); +retregular = getdns_dict_set_dict(dictarg, charstararg, dictarg); +retregular = getdns_dict_set_list(dictarg, charstararg, listarg); +retregular = getdns_dict_set_bindata(dictarg, charstararg, bindataarg); +retregular = getdns_dict_set_int(dictarg, charstararg, uint32arg); + +retcharstar = getdns_convert_fqdn_to_dns_name( + charstararg +); + +retcharstar = getdns_convert_dns_name_to_fqdn( + charstararg +); + +retcharstar = getdns_convert_ulabel_to_alabel( + charstararg +); + +retcharstar = getdns_convert_alabel_to_ulabel( + charstararg +); + +retregular = getdns_validate_dnssec( + bindataarg, + listarg, + listarg +); + +retcharstar = getdns_pretty_print_dict( + dictarg +); + +retcharstar = getdns_display_ip_address( + bindataarg +); + +retregular = getdns_context_set_context_update_callback( + contextarg, + setcallbackfunctionarg +); + +retregular = getdns_context_set_resolution_type( + contextarg, + regulararg +); + +retregular = getdns_context_set_namespaces( + contextarg, + sizetarg, + regularptrarg +); + +retregular = getdns_context_set_dns_transport( + contextarg, + regulararg +); + +retregular = getdns_context_set_limit_outstanding_queries( + contextarg, + uint16arg +); + +retregular = getdns_context_set_timeout( + contextarg, + uint16arg +); + +retregular = getdns_context_set_follow_redirects( + contextarg, + regulararg +); + +retregular = getdns_context_set_dns_root_servers( + contextarg, + listarg +); + +retregular = getdns_context_set_append_name( + contextarg, + regulararg +); + +retregular = getdns_context_set_suffix( + contextarg, + listarg +); + +retregular = getdns_context_set_dnssec_trust_anchors( + contextarg, + listarg +); + +retregular = getdns_context_set_dnssec_allowed_skew( + contextarg, + uint16arg +); + +retregular = getdns_context_set_stub_resolution( + contextarg, + listarg +); + +retregular = getdns_context_set_edns_maximum_udp_payload_size( + contextarg, + uint16arg +); + +retregular = getdns_context_set_edns_extended_rcode( + contextarg, + uint8arg +); + +retregular = getdns_context_set_edns_version( + contextarg, + uint8arg +); + +retregular = getdns_context_set_edns_do_bit( + contextarg, + uint8arg +); + +retregular = getdns_context_set_memory_allocator( + contextarg, + allocfunctionarg +); + +retregular = getdns_context_set_memory_deallocator( + contextarg, + deallocfunctionarg +); + +retregular = getdns_context_set_memory_reallocator( + contextarg, + deallocfunctionarg +); + +return(0); } /* End of main() */ diff --git a/spec/example-simple-answers.c b/spec/example-simple-answers.c new file mode 100644 index 00000000..031af9e2 --- /dev/null +++ b/spec/example-simple-answers.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +#include + +#define UNUSED_PARAM(x) ((void)(x)) + +/* Set up the callback function, which will also do the processing of the results */ +void this_callbackfn(struct getdns_context_t *this_context, + uint16_t this_callback_type, + struct getdns_dict *this_response, + void *this_userarg, + getdns_transaction_t this_transaction_id) +{ + UNUSED_PARAM(this_userarg); /* Not looking at the userarg for this example */ + UNUSED_PARAM(this_context); /* Not looking at the context for this example */ + getdns_return_t this_ret; /* Holder for all function returns */ + if (this_callback_type == GETDNS_CALLBACK_COMPLETE) /* This is a callback with data */ + { + /* Be sure the search returned something */ + uint32_t * this_error = NULL; + this_ret = getdns_dict_get_int(this_response, "status", this_error); // Ignore any error + if (*this_error != GETDNS_RESPSTATUS_GOOD) // If the search didn't return "good" + { + fprintf(stderr, "The search had no results, and a return value of %d. Exiting.", *this_error); + return; + } + struct getdns_list * just_the_addresses_ptr; + this_ret = getdns_dict_get_list(this_response, "just_address_answers", &just_the_addresses_ptr); + if (this_ret != GETDNS_RETURN_GOOD) // This check is really not needed, but prevents a compiler error under "pedantic" + { + fprintf(stderr, "Trying to get the answers failed: %d", this_ret); + return; + } + size_t * num_addresses_ptr = NULL; + this_ret = getdns_list_get_length(just_the_addresses_ptr, num_addresses_ptr); // Ignore any error + /* Go through each record */ + for ( size_t rec_count = 0; rec_count <= *num_addresses_ptr; ++rec_count ) + { + struct getdns_dict * this_address; + this_ret = getdns_list_get_dict(just_the_addresses_ptr, rec_count, &this_address); // Ignore any error + /* Just print the address */ + struct getdns_bindata * this_address_data; + this_ret = getdns_dict_get_bindata(this_address, "address_data", &this_address_data); // Ignore any error + printf("The address is %s", getdns_display_ip_address(this_address_data)); + } + } + else if (this_callback_type == GETDNS_CALLBACK_CANCEL) + fprintf(stderr, "The callback with ID %"PRIu64" was cancelled. Exiting.", this_transaction_id); + else + fprintf(stderr, "The callback got a callback_type of %d. Exiting.", this_callback_type); +} + +int main() +{ + /* Create the DNS context for this call */ + struct getdns_context_t *this_context = NULL; + getdns_return_t context_create_return = getdns_context_create(&this_context, true); + if (context_create_return != GETDNS_RETURN_GOOD) + { + fprintf(stderr, "Trying to create the context failed: %d", context_create_return); + return(GETDNS_RETURN_GENERIC_ERROR); + } + /* Create an event base and put it in the context using the unknown function name */ + struct event_base *this_event_base; + this_event_base = event_base_new(); + if (this_event_base == NULL) + { + fprintf(stderr, "Trying to create the event base failed."); + return(GETDNS_RETURN_GENERIC_ERROR); + } + (void)getdns_extension_set_libevent_base(this_context, this_event_base); + /* Set up the getdns call */ + const char * this_name = "www.example.com"; + char* this_userarg = "somestring"; // Could add things here to help identify this call + getdns_transaction_t this_transaction_id = 0; + + /* Make the call */ + getdns_return_t dns_request_return = getdns_address(this_context, this_name, + NULL, this_userarg, &this_transaction_id, this_callbackfn); + if (dns_request_return == GETDNS_RETURN_BAD_DOMAIN_NAME) + { + fprintf(stderr, "A bad domain name was used: %s. Exiting.", this_name); + return(GETDNS_RETURN_GENERIC_ERROR); + } + else + { + /* Call the event loop */ + int dispatch_return = event_base_dispatch(this_event_base); + UNUSED_PARAM(dispatch_return); + // TODO: check the return value above + } + /* Clean up */ + getdns_context_destroy(this_context); + /* Assuming we get here, leave gracefully */ + exit(EXIT_SUCCESS); +} diff --git a/spec/example-synchronous.c b/spec/example-synchronous.c new file mode 100644 index 00000000..513a3112 --- /dev/null +++ b/spec/example-synchronous.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +int main() +{ + getdns_return_t this_ret; /* Holder for all function returns */ + /* Create the DNS context for this call */ + struct getdns_context_t *this_context = NULL; + getdns_return_t context_create_return = getdns_context_create(&this_context, true); + if (context_create_return != GETDNS_RETURN_GOOD) + { + fprintf(stderr, "Trying to create the context failed: %d", context_create_return); + return(GETDNS_RETURN_GENERIC_ERROR); + } + /* Set up the getdns_sync_request call */ + const char * this_name = "www.example.com"; + uint8_t this_request_type = GETDNS_RRTYPE_A; + /* Get the A and AAAA records */ + struct getdns_dict * this_extensions = getdns_dict_create(); + this_ret = getdns_dict_set_int(this_extensions, "return_both_v4_and_v6", GETDNS_EXTENSION_TRUE); + if (this_ret != GETDNS_RETURN_GOOD) + { + fprintf(stderr, "Trying to set an extension do both IPv4 and IPv6 failed: %d", this_ret); + return(GETDNS_RETURN_GENERIC_ERROR); + } + uint32_t this_response_length; + struct getdns_dict * this_response = NULL; + + /* Make the call */ + getdns_return_t dns_request_return = getdns_general_sync(this_context, this_name, this_request_type, + this_extensions, &this_response_length, this_response); + if (dns_request_return == GETDNS_RETURN_BAD_DOMAIN_NAME) + { + fprintf(stderr, "A bad domain name was used: %s. Exiting.", this_name); + return(GETDNS_RETURN_GENERIC_ERROR); + } + else + { + /* Be sure the search returned something */ + uint32_t * this_error = NULL; + this_ret = getdns_dict_get_int(this_response, "status", this_error); // Ignore any error + if (*this_error != GETDNS_RESPSTATUS_GOOD) // If the search didn't return "good" + { + fprintf(stderr, "The search had no results, and a return value of %d. Exiting.", *this_error); + return(GETDNS_RETURN_GENERIC_ERROR); + } + struct getdns_list * just_the_addresses_ptr; + this_ret = getdns_dict_get_list(this_response, "just_address_answers", &just_the_addresses_ptr); // Ignore any error + size_t * num_addresses_ptr = NULL; + this_ret = getdns_list_get_length(just_the_addresses_ptr, num_addresses_ptr); // Ignore any error + /* Go through each record */ + for ( size_t rec_count = 0; rec_count <= *num_addresses_ptr; ++rec_count ) + { + struct getdns_dict * this_address; + this_ret = getdns_list_get_dict(just_the_addresses_ptr, rec_count, &this_address); // Ignore any error + /* Just print the address */ + struct getdns_bindata * this_address_data; + this_ret = getdns_dict_get_bindata(this_address, "address_data", &this_address_data); // Ignore any error + printf("The address is %s", getdns_display_ip_address(this_address_data)); + } + } + /* Clean up */ + getdns_context_destroy(this_context); + getdns_free_sync_request_memory(this_response); + /* Assuming we get here, leave gracefully */ + exit(EXIT_SUCCESS); +} diff --git a/spec/example-tree.c b/spec/example-tree.c new file mode 100644 index 00000000..9bda28ec --- /dev/null +++ b/spec/example-tree.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include + +#define UNUSED_PARAM(x) ((void)(x)) + +/* Set up the callback function, which will also do the processing of the results */ +void this_callbackfn(struct getdns_context_t *this_context, + getdns_return_t this_callback_type, + struct getdns_dict *this_response, + void *this_userarg, + getdns_transaction_t this_transaction_id) +{ + UNUSED_PARAM(this_userarg); /* Not looking at the userarg for this example */ + UNUSED_PARAM(this_context); /* Not looking at the context for this example */ + getdns_return_t this_ret; /* Holder for all function returns */ + if (this_callback_type == GETDNS_CALLBACK_COMPLETE) /* This is a callback with data */ + { + /* Be sure the search returned something */ + uint32_t * this_error = NULL; + this_ret = getdns_dict_get_int(this_response, "status", this_error); // Ignore any error + if (*this_error != GETDNS_RESPSTATUS_GOOD) // If the search didn't return "good" + { + fprintf(stderr, "The search had no results, and a return value of %d. Exiting.", *this_error); + return; + } + /* Find all the answers returned */ + struct getdns_list * these_answers; + this_ret = getdns_dict_get_list(this_response, "replies-tree", &these_answers); + if (this_ret == GETDNS_RETURN_NO_SUCH_DICT_NAME) + { + fprintf(stderr, "Weird: the response had no error, but also no replies-tree. Exiting."); + return; + } + size_t * num_answers_ptr = NULL; + this_ret = getdns_list_get_length(these_answers, num_answers_ptr); + /* Go through each answer */ + for ( size_t rec_count = 0; rec_count <= *num_answers_ptr; ++rec_count ) + { + struct getdns_dict * this_record; + this_ret = getdns_list_get_dict(these_answers, rec_count, &this_record); // Ignore any error + /* Get the answer section */ + struct getdns_list * this_answer; + this_ret = getdns_dict_get_list(this_record, "answer", &this_answer); // Ignore any error + /* Get each RR in the answer section */ + size_t * num_rrs_ptr = NULL; + this_ret = getdns_list_get_length(this_answer, num_rrs_ptr); + for ( size_t rr_count = 0; rr_count <= *num_rrs_ptr; ++rr_count ) + { + struct getdns_dict * this_rr = NULL; + this_ret = getdns_list_get_dict(this_answer, rr_count, &this_rr); // Ignore any error + /* Get the RDATA */ + struct getdns_dict * this_rdata = NULL; + this_ret = getdns_dict_get_dict(this_rr, "rdata", &this_rdata); // Ignore any error + /* Get the RDATA type */ + uint32_t * this_type = NULL; + this_ret = getdns_dict_get_int(this_rdata, "type", this_type); // Ignore any error + /* If it is type A or AAAA, print the value */ + if (*this_type == GETDNS_RRTYPE_A) + { + struct getdns_bindata * this_a_record = NULL; + this_ret = getdns_dict_get_bindata(this_rdata, "ipv4_address", &this_a_record); + if (this_ret == GETDNS_RETURN_NO_SUCH_DICT_NAME) + { + fprintf(stderr, "Weird: the A record at %d in record at %d had no address. Exiting.", + (int) rr_count, (int) rec_count); + return; + } + printf("The IPv4 address is %s", getdns_display_ip_address(this_a_record)); + } + else if (*this_type == GETDNS_RRTYPE_AAAA) + { + struct getdns_bindata * this_aaaa_record = NULL; + this_ret = getdns_dict_get_bindata(this_rdata, "ipv6_address", &this_aaaa_record); + if (this_ret == GETDNS_RETURN_NO_SUCH_DICT_NAME) + { + fprintf(stderr, "Weird: the AAAA record at %d in record at %d had no address. Exiting.", + (int) rr_count, (int) rec_count); + return; + } + printf("The IPv6 address is %s", getdns_display_ip_address(this_aaaa_record)); + } + } + } + } + else if (this_callback_type == GETDNS_CALLBACK_CANCEL) + fprintf(stderr, "The callback with ID %"PRIu64" was cancelled. Exiting.", this_transaction_id); + else + fprintf(stderr, "The callback got a callback_type of %d. Exiting.", this_callback_type); +} + +int main() +{ + /* Create the DNS context for this call */ + struct getdns_context_t *this_context = NULL; + getdns_return_t context_create_return = getdns_context_create(&this_context, true); + if (context_create_return != GETDNS_RETURN_GOOD) + { + fprintf(stderr, "Trying to create the context failed: %d", context_create_return); + return(GETDNS_RETURN_GENERIC_ERROR); + } + /* Create an event base and put it in the context using the unknown function name */ + struct event_base *this_event_base; + this_event_base = event_base_new(); + if (this_event_base == NULL) + { + fprintf(stderr, "Trying to create the event base failed."); + return(GETDNS_RETURN_GENERIC_ERROR); + } + (void)getdns_extension_set_libevent_base(this_context, this_event_base); + /* Set up the getdns call */ + const char * this_name = "www.example.com"; + char* this_userarg = "somestring"; // Could add things here to help identify this call + getdns_transaction_t this_transaction_id = 0; + + /* Make the call */ + getdns_return_t dns_request_return = getdns_address(this_context, this_name, + NULL, this_userarg, &this_transaction_id, this_callbackfn); + if (dns_request_return == GETDNS_RETURN_BAD_DOMAIN_NAME) + { + fprintf(stderr, "A bad domain name was used: %s. Exiting.", this_name); + return(GETDNS_RETURN_GENERIC_ERROR); + } + else + { + /* Call the event loop */ + int dispatch_return = event_base_dispatch(this_event_base); + UNUSED_PARAM(dispatch_return); + // TODO: check the return value above + } + /* Clean up */ + getdns_context_destroy(this_context); + /* Assuming we get here, leave gracefully */ + exit(EXIT_SUCCESS); +} diff --git a/spec/getdns_core_only.c b/spec/getdns_core_only.c new file mode 100644 index 00000000..60064440 --- /dev/null +++ b/spec/getdns_core_only.c @@ -0,0 +1,403 @@ +#include + +/* stuff to make it compile pedantically */ +#define UNUSED_PARAM(x) ((void)(x)) + +int main(){ return(0); } + +/* Function definitions */ + +getdns_return_t +getdns_general( + getdns_context_t context, + const char *name, + uint16_t request_type, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callback +) +{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(request_type); UNUSED_PARAM(extensions); UNUSED_PARAM(userarg); +UNUSED_PARAM(transaction_id); UNUSED_PARAM(callback); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_address( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callback +) +{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(extensions); UNUSED_PARAM(userarg); +UNUSED_PARAM(transaction_id); UNUSED_PARAM(callback); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_hostname( + getdns_context_t context, + struct getdns_dict *address, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callback +) +{ UNUSED_PARAM(context); UNUSED_PARAM(address); UNUSED_PARAM(extensions); UNUSED_PARAM(userarg); +UNUSED_PARAM(transaction_id); UNUSED_PARAM(callback); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_service( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callback +) +{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(extensions); UNUSED_PARAM(userarg); +UNUSED_PARAM(transaction_id); UNUSED_PARAM(callback); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_create( + getdns_context_t *context, + bool set_from_os +) +{ UNUSED_PARAM(context); UNUSED_PARAM(set_from_os); return GETDNS_RETURN_GOOD; } + +void +getdns_context_destroy( + getdns_context_t context +) +{ UNUSED_PARAM(context); } + +getdns_return_t +getdns_cancel_callback( + getdns_context_t context, + getdns_transaction_t transaction_id +) +{ UNUSED_PARAM(context); UNUSED_PARAM(transaction_id); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_general_sync( + getdns_context_t context, + const char *name, + uint16_t request_type, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +) +{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(request_type); UNUSED_PARAM(extensions); +UNUSED_PARAM(response_length); UNUSED_PARAM(response); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_address_sync( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +) +{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(extensions); +UNUSED_PARAM(response_length); UNUSED_PARAM(response); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_hostname_sync( + getdns_context_t context, + struct getdns_dict *address, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +) +{ UNUSED_PARAM(context); UNUSED_PARAM(address); UNUSED_PARAM(extensions); +UNUSED_PARAM(response_length); UNUSED_PARAM(response); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_service_sync( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +) +{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(extensions); +UNUSED_PARAM(response_length); UNUSED_PARAM(response); return GETDNS_RETURN_GOOD; } + +void +getdns_free_sync_request_memory( + struct getdns_dict *response +) +{ UNUSED_PARAM(response); } + +getdns_return_t getdns_list_get_length(struct getdns_list *this_list, size_t *answer) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_list_get_data_type(struct getdns_list *this_list, size_t index, getdns_data_type *answer) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_list_get_dict(struct getdns_list *this_list, size_t index, struct getdns_dict **answer) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_list_get_list(struct getdns_list *this_list, size_t index, struct getdns_list **answer) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_list_get_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata **answer) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_list_get_int(struct getdns_list *this_list, size_t index, uint32_t *answer) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_get_names(struct getdns_dict *this_dict, struct getdns_list **answer) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_get_data_type(struct getdns_dict *this_dict, char *name, getdns_data_type *answer) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_get_dict(struct getdns_dict *this_dict, char *name, struct getdns_dict **answer) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_get_list(struct getdns_dict *this_dict, char *name, struct getdns_list **answer) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_get_bindata(struct getdns_dict *this_dict, char *name, struct getdns_bindata **answer) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_get_int(struct getdns_dict *this_dict, char *name, uint32_t *answer) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; } + +struct getdns_list * getdns_list_create() +{ return NULL; } + +void getdns_list_destroy(struct getdns_list *this_list) +{ UNUSED_PARAM(this_list); } + +getdns_return_t getdns_list_set_dict(struct getdns_list *this_list, size_t index, struct getdns_dict *child_dict) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(child_dict); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_list_set_list(struct getdns_list *this_list, size_t index, struct getdns_list *child_list) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(child_list); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_list_set_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata *child_bindata) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(child_bindata); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_list_set_int(struct getdns_list *this_list, size_t index, uint32_t child_uint32) +{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(child_uint32); return GETDNS_RETURN_GOOD; } + +struct getdns_dict * getdns_dict_create() +{ return NULL; } + +void getdns_dict_destroy(struct getdns_dict *this_dict) +{ UNUSED_PARAM(this_dict); } + +getdns_return_t getdns_dict_set_dict(struct getdns_dict *this_dict, char *name, struct getdns_dict *child_dict) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(child_dict); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_set_list(struct getdns_dict *this_dict, char *name, struct getdns_list *child_list) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(child_list); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_set_bindata(struct getdns_dict *this_dict, char *name, struct getdns_bindata *child_bindata) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(child_bindata); return GETDNS_RETURN_GOOD; } + +getdns_return_t getdns_dict_set_int(struct getdns_dict *this_dict, char *name, uint32_t child_uint32) +{ UNUSED_PARAM(this_dict); UNUSED_PARAM(name); UNUSED_PARAM(child_uint32); return GETDNS_RETURN_GOOD; } + +char * +getdns_convert_dns_name_to_fqdn( + char *name_from_dns_response +) +{ UNUSED_PARAM(name_from_dns_response); return NULL; } + +char * +getdns_convert_fqdn_to_dns_name( + char *fqdn_as_string +) +{ UNUSED_PARAM(fqdn_as_string); return NULL; } + +char * +getdns_convert_ulabel_to_alabel( + char *ulabel +) +{ UNUSED_PARAM(ulabel); return NULL; } + +char * +getdns_convert_alabel_to_ulabel( + char *alabel +) +{ UNUSED_PARAM(alabel); return NULL; } + +getdns_return_t +getdns_validate_dnssec( + struct getdns_bindata *record_to_validate, + struct getdns_list *bundle_of_support_records, + struct getdns_list *trust_anchor_rdatas +) +{ UNUSED_PARAM(record_to_validate); UNUSED_PARAM(bundle_of_support_records); UNUSED_PARAM(trust_anchor_rdatas); +return GETDNS_RETURN_GOOD; } + + +char * +getdns_pretty_print_dict( + struct getdns_dict *some_dict +) +{ UNUSED_PARAM(some_dict); return NULL; } + +char * +getdns_display_ip_address( + struct getdns_bindata *bindata_of_ipv4_or_ipv6_address +) +{ UNUSED_PARAM(bindata_of_ipv4_or_ipv6_address); return NULL; } + +getdns_return_t +getdns_context_set_context_update_callback( + getdns_context_t context, + void (*value)(getdns_context_t context, uint16_t changed_item) +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_context_update( + getdns_context_t context, + uint16_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_resolution_type( + getdns_context_t context, + uint16_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_namespaces( + getdns_context_t context, + size_t namespace_count, + uint16_t *namespaces +) +{ UNUSED_PARAM(context); UNUSED_PARAM(namespace_count); UNUSED_PARAM(namespaces); +return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_dns_transport( + getdns_context_t context, + uint16_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_limit_outstanding_queries( + getdns_context_t context, + uint16_t limit +) +{ UNUSED_PARAM(context); UNUSED_PARAM(limit); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_timeout( + getdns_context_t context, + uint16_t timeout +) +{ UNUSED_PARAM(context); UNUSED_PARAM(timeout); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_follow_redirects( + getdns_context_t context, + uint16_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_dns_root_servers( + getdns_context_t context, + struct getdns_list *addresses +) +{ UNUSED_PARAM(context); UNUSED_PARAM(addresses); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_append_name( + getdns_context_t context, + uint16_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_suffix( + getdns_context_t context, + struct getdns_list *value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_dnssec_trust_anchors( + getdns_context_t context, + struct getdns_list *value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_dnssec_allowed_skew( + getdns_context_t context, + uint16_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_stub_resolution( + getdns_context_t context, + struct getdns_list *upstream_list +) +{ UNUSED_PARAM(context); UNUSED_PARAM(upstream_list); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_edns_maximum_udp_payload_size( + getdns_context_t context, + uint16_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_edns_extended_rcode( + getdns_context_t context, + uint8_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_edns_version( + getdns_context_t context, + uint8_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_edns_do_bit( + getdns_context_t context, + uint8_t value +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_memory_allocator( + getdns_context_t context, + void (*value)(size_t somesize) +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_memory_deallocator( + getdns_context_t context, + void (*value)(void*) +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_context_set_memory_reallocator( + getdns_context_t context, + void (*value)(void*) +) +{ UNUSED_PARAM(context); UNUSED_PARAM(value); return GETDNS_RETURN_GOOD; } + +getdns_return_t +getdns_extension_set_libevent_base( + getdns_context_t context, + struct event_base *this_event_base +) +{ UNUSED_PARAM(context); UNUSED_PARAM(this_event_base); return GETDNS_RETURN_GOOD; } + diff --git a/spec/getdns_core_only.h b/spec/getdns_core_only.h new file mode 100644 index 00000000..33d3bd32 --- /dev/null +++ b/spec/getdns_core_only.h @@ -0,0 +1,558 @@ +/* Created at 2013-04-02-16-59-04*/ +#ifndef GETDNS_H +#define GETDNS_H + +#include +#include +#include +#include + +#define GETDNS_COMPILATION_COMMENT The API implementation should fill in something here, such as a compilation version string and date, and change it each time the API is compiled. + +/* Return values */ +#define GETDNS_RETURN_GOOD 0 +#define GETDNS_RETURN_GOOD_TEXT Good +#define GETDNS_RETURN_GENERIC_ERROR 1 +#define GETDNS_RETURN_GENERIC_ERROR_TEXT Generic error +#define GETDNS_RETURN_BAD_DOMAIN_NAME 300 +#define GETDNS_RETURN_BAD_DOMAIN_NAME_TEXT Badly-formed domain name in first argument +#define GETDNS_RETURN_BAD_CONTEXT 301 +#define GETDNS_RETURN_BAD_CONTEXT_TEXT Bad value for a context type +#define GETDNS_RETURN_CONTEXT_UPDATE_FAIL 302 +#define GETDNS_RETURN_CONTEXT_UPDATE_FAIL_TEXT Did not update the context +#define GETDNS_RETURN_UNKNOWN_TRANSACTION 303 +#define GETDNS_RETURN_UNKNOWN_TRANSACTION_TEXT An attempt was made to cancel a callback with a transaction_id that is not recognized +#define GETDNS_RETURN_NO_SUCH_LIST_ITEM 304 +#define GETDNS_RETURN_NO_SUCH_LIST_ITEM_TEXT A helper function for lists had an index argument that was too high. +#define GETDNS_RETURN_NO_SUCH_DICT_NAME 305 +#define GETDNS_RETURN_NO_SUCH_DICT_NAME_TEXT A helper function for dicts had a name argument that for a name that is not in the dict. +#define GETDNS_RETURN_WRONG_TYPE_REQUESTED 306 +#define GETDNS_RETURN_WRONG_TYPE_REQUESTED_TEXT A helper function was supposed to return a certain type for an item, but the wrong type was given. +#define GETDNS_RETURN_NO_SUCH_EXTENSION 307 +#define GETDNS_RETURN_NO_SUCH_EXTENSION_TEXT A name in the extensions dict is not a valid extension. +#define GETDNS_RETURN_EXTENSION_MISFORMAT 308 +#define GETDNS_RETURN_EXTENSION_MISFORMAT_TEXT One or more of the extensions is has a bad format. +#define GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED 309 +#define GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED_TEXT A query was made with a context that is using stub resolution and a DNSSEC extension specified. + +/* DNSSEC values */ +#define GETDNS_DNSSEC_SECURE 400 +#define GETDNS_DNSSEC_SECURE_TEXT The record was determined to be secure in DNSSEC +#define GETDNS_DNSSEC_BOGUS 401 +#define GETDNS_DNSSEC_BOGUS_TEXT The record was determined to be bogus in DNSSEC +#define GETDNS_DNSSEC_INDETERMINATE 402 +#define GETDNS_DNSSEC_INDETERMINATE_TEXT The record was not determined to be any state in DNSSEC +#define GETDNS_DNSSEC_INSECURE 403 +#define GETDNS_DNSSEC_INSECURE_TEXT The record was determined to be insecure in DNSSEC +#define GETDNS_DNSSEC_NOT_PERFORMED 404 +#define GETDNS_DNSSEC_NOT_PERFORMED_TEXT DNSSEC validation was not performed (only used for debugging) + +/* Context Variables */ +#define GETDNS_CONTEXT_NAMESPACE_DNS 500 +#define GETDNS_CONTEXT_NAMESPACE_DNS_TEXT See getdns_context_set_namespaces() +#define GETDNS_CONTEXT_NAMESPACE_LOCALNAMES 501 +#define GETDNS_CONTEXT_NAMESPACE_LOCALNAMES_TEXT See getdns_context_set_namespaces() +#define GETDNS_CONTEXT_NAMESPACE_NETBIOS 502 +#define GETDNS_CONTEXT_NAMESPACE_NETBIOS_TEXT See getdns_context_set_namespaces() +#define GETDNS_CONTEXT_NAMESPACE_MDNS 503 +#define GETDNS_CONTEXT_NAMESPACE_MDNS_TEXT See getdns_context_set_namespaces() +#define GETDNS_CONTEXT_NAMESPACE_NIS 504 +#define GETDNS_CONTEXT_NAMESPACE_NIS_TEXT See getdns_context_set_namespaces() +#define GETDNS_CONTEXT_STUB 505 +#define GETDNS_CONTEXT_STUB_TEXT See getdns_context_set_resolution_type() +#define GETDNS_CONTEXT_RECURSING 506 +#define GETDNS_CONTEXT_RECURSING_TEXT See getdns_context_set_resolution_type() +#define GETDNS_CONTEXT_FOLLOW_REDIRECTS 507 +#define GETDNS_CONTEXT_FOLLOW_REDIRECTS_TEXT See getdns_context_set_follow_redirects() +#define GETDNS_CONTEXT_DO_NOT_FOLLOW_REDIRECTS 508 +#define GETDNS_CONTEXT_DO_NOT_FOLLOW_REDIRECTS_TEXT See getdns_context_set_follow_redirects() +#define GETDNS_CONTEXT_UDP_FIRST_AND_FALL_BACK_TO_TCP 509 +#define GETDNS_CONTEXT_UDP_FIRST_AND_FALL_BACK_TO_TCP_TEXT See getdns_context_set_use_udp_tcp() +#define GETDNS_CONTEXT_UDP_ONLY 510 +#define GETDNS_CONTEXT_UDP_ONLY_TEXT See getdns_context_set_use_udp_tcp() +#define GETDNS_CONTEXT_TCP_ONLY 511 +#define GETDNS_CONTEXT_TCP_ONLY_TEXT See getdns_context_set_use_udp_tcp() +#define GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN 512 +#define GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT See getdns_context_set_use_udp_tcp() +#define GETDNS_CONTEXT_APPEND_NAME_ALWAYS 513 +#define GETDNS_CONTEXT_APPEND_NAME_ALWAYS_TEXT See getdns_context_set_append_name() +#define GETDNS_CONTEXT_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE 514 +#define GETDNS_CONTEXT_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE_TEXT See getdns_context_set_append_name() +#define GETDNS_CONTEXT_GETDNS_CONTEXT_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE 515 +#define GETDNS_CONTEXT_GETDNS_CONTEXT_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE_TEXT See getdns_context_set_append_name() +#define GETDNS_CONTEXT_DO_NOT_APPEND_NAMES 516 +#define GETDNS_CONTEXT_DO_NOT_APPEND_NAMES_TEXT See getdns_context_set_append_name() + +/* Context codes */ +#define GETDNS_CONTEXT_CODE_NAMESPACES 600 +#define GETDNS_CONTEXT_CODE_NAMESPACES_TEXT Change related to getdns_context_set_namespaces +#define GETDNS_CONTEXT_CODE_RESOLUTION_TYPE 601 +#define GETDNS_CONTEXT_CODE_RESOLUTION_TYPE_TEXT Change related to getdns_context_set_resolution_type +#define GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS 602 +#define GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS_TEXT Change related to getdns_context_set_follow_redirects +#define GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS 603 +#define GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS_TEXT Change related to getdns_context_set_upstream_recursive_servers +#define GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS 604 +#define GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS_TEXT Change related to getdns_context_set_dns_root_servers +#define GETDNS_CONTEXT_CODE_USE_UDP_TCP 605 +#define GETDNS_CONTEXT_CODE_USE_UDP_TCP_TEXT Change related to getdns_context_set_use_udp_tcp +#define GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES 606 +#define GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES_TEXT Change related to getdns_context_set_limit_outstanding_queries +#define GETDNS_CONTEXT_CODE_APPEND_NAME 607 +#define GETDNS_CONTEXT_CODE_APPEND_NAME_TEXT Change related to getdns_context_set_append_name +#define GETDNS_CONTEXT_CODE_SUFFIX 608 +#define GETDNS_CONTEXT_CODE_SUFFIX_TEXT Change related to getdns_context_set_suffix +#define GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS 609 +#define GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS_TEXT Change related to getdns_context_set_dnssec_trust_anchors +#define GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE 610 +#define GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE_TEXT Change related to getdns_context_set_edns_maximum_udp_payload_size +#define GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE 611 +#define GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE_TEXT Change related to getdns_context_set_edns_extended_rcode +#define GETDNS_CONTEXT_CODE_EDNS_VERSION 612 +#define GETDNS_CONTEXT_CODE_EDNS_VERSION_TEXT Change related to getdns_context_set_edns_version +#define GETDNS_CONTEXT_CODE_EDNS_DO_BIT 613 +#define GETDNS_CONTEXT_CODE_EDNS_DO_BIT_TEXT Change related to getdns_context_set_edns_do_bit +#define GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW 614 +#define GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW_TEXT Change related to getdns_context_set_dnssec_allowed_skew +#define GETDNS_CONTEXT_CODE_MEMORY_ALLOCATOR 615 +#define GETDNS_CONTEXT_CODE_MEMORY_ALLOCATOR_TEXT Change related to getdns_context_set_memory_allocator +#define GETDNS_CONTEXT_CODE_MEMORY_DEALLOCATOR 616 +#define GETDNS_CONTEXT_CODE_MEMORY_DEALLOCATOR_TEXT Change related to getdns_context_set_memory_deallocator +#define GETDNS_CONTEXT_CODE_MEMORY_REALLOCATOR 617 +#define GETDNS_CONTEXT_CODE_MEMORY_REALLOCATOR_TEXT Change related to getdns_context_set_memory_reallocator + +/* Callback Type Variables */ +#define GETDNS_CALLBACK_COMPLETE 700 +#define GETDNS_CALLBACK_COMPLETE_TEXT The response has the requested data in it +#define GETDNS_CALLBACK_CANCEL 701 +#define GETDNS_CALLBACK_CANCEL_TEXT The calling program cancelled the callback; response is NULL +#define GETDNS_CALLBACK_TIMEOUT 702 +#define GETDNS_CALLBACK_TIMEOUT_TEXT The requested action timed out; response is NULL +#define GETDNS_CALLBACK_ERROR 703 +#define GETDNS_CALLBACK_ERROR_TEXT The requested action had an error; response is NULL + +/* Type Of Name Services */ +#define GETDNS_NAMETYPE_DNS 800 +#define GETDNS_NAMETYPE_DNS_TEXT Normal DNS (RFC 1035) +#define GETDNS_NAMETYPE_WINS 801 +#define GETDNS_NAMETYPE_WINS_TEXT The WINS name service (some reference needed) + +/* Status Codes for Responses */ +#define GETDNS_RESPSTATUS_GOOD 900 +#define GETDNS_RESPSTATUS_GOOD_TEXT At least one response was returned +#define GETDNS_RESPSTATUS_NO_NAME 901 +#define GETDNS_RESPSTATUS_NO_NAME_TEXT Queries for the name yielded all negative responses +#define GETDNS_RESPSTATUS_ALL_TIMEOUT 902 +#define GETDNS_RESPSTATUS_ALL_TIMEOUT_TEXT All queries for the name timed out +#define GETDNS_RESPSTATUS_NO_SECURE_ANSWERS 903 +#define GETDNS_RESPSTATUS_NO_SECURE_ANSWERS_TEXT The context setting for getting only secure responses was specified, and at least one DNS response was received, but no DNS response was determined to be secure through DNSSEC. + +/* Values Associated With Extensions */ +#define GETDNS_EXTENSION_TRUE 1000 +#define GETDNS_EXTENSION_TRUE_TEXT Turn on the extension +#define GETDNS_EXTENSION_FALSE 1001 +#define GETDNS_EXTENSION_FALSE_TEXT Do not turn on the extension + +/* Values Associated With DNS Errors Found By The API */ +#define GETDNS_BAD_DNS_CNAME_IN_TARGET 1100 +#define GETDNS_BAD_DNS_CNAME_IN_TARGET_TEXT A DNS query type that does not allow a target to be a CNAME pointed to a CNAME +#define GETDNS_BAD_DNS_ALL_NUMERIC_LABEL 1101 +#define GETDNS_BAD_DNS_ALL_NUMERIC_LABEL_TEXT One or more labels in a returned domain name is all-numeric; this is not legal for a hostname +#define GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE 1102 +#define GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE_TEXT A DNS query for a type other than CNAME returned a CNAME response + +/* Defines for RRtypes (from 2012-12) */ + +#define GETDNS_RRTYPE_A 1 +#define GETDNS_RRTYPE_NS 2 +#define GETDNS_RRTYPE_MD 3 +#define GETDNS_RRTYPE_MF 4 +#define GETDNS_RRTYPE_CNAME 5 +#define GETDNS_RRTYPE_SOA 6 +#define GETDNS_RRTYPE_MB 7 +#define GETDNS_RRTYPE_MG 8 +#define GETDNS_RRTYPE_MR 9 +#define GETDNS_RRTYPE_NULL 10 +#define GETDNS_RRTYPE_WKS 11 +#define GETDNS_RRTYPE_PTR 12 +#define GETDNS_RRTYPE_HINFO 13 +#define GETDNS_RRTYPE_MINFO 14 +#define GETDNS_RRTYPE_MX 15 +#define GETDNS_RRTYPE_TXT 16 +#define GETDNS_RRTYPE_RP 17 +#define GETDNS_RRTYPE_AFSDB 18 +#define GETDNS_RRTYPE_X25 19 +#define GETDNS_RRTYPE_ISDN 20 +#define GETDNS_RRTYPE_RT 21 +#define GETDNS_RRTYPE_NSAP 22 +#define GETDNS_RRTYPE_SIG 24 +#define GETDNS_RRTYPE_KEY 25 +#define GETDNS_RRTYPE_PX 26 +#define GETDNS_RRTYPE_GPOS 27 +#define GETDNS_RRTYPE_AAAA 28 +#define GETDNS_RRTYPE_LOC 29 +#define GETDNS_RRTYPE_NXT 30 +#define GETDNS_RRTYPE_EID 31 +#define GETDNS_RRTYPE_NIMLOC 32 +#define GETDNS_RRTYPE_SRV 33 +#define GETDNS_RRTYPE_ATMA 34 +#define GETDNS_RRTYPE_NAPTR 35 +#define GETDNS_RRTYPE_KX 36 +#define GETDNS_RRTYPE_CERT 37 +#define GETDNS_RRTYPE_A6 38 +#define GETDNS_RRTYPE_DNAME 39 +#define GETDNS_RRTYPE_SINK 40 +#define GETDNS_RRTYPE_OPT 41 +#define GETDNS_RRTYPE_APL 42 +#define GETDNS_RRTYPE_DS 43 +#define GETDNS_RRTYPE_SSHFP 44 +#define GETDNS_RRTYPE_IPSECKEY 45 +#define GETDNS_RRTYPE_RRSIG 46 +#define GETDNS_RRTYPE_NSEC 47 +#define GETDNS_RRTYPE_DNSKEY 48 +#define GETDNS_RRTYPE_DHCID 49 +#define GETDNS_RRTYPE_NSEC3 50 +#define GETDNS_RRTYPE_NSEC3PARAM 51 +#define GETDNS_RRTYPE_TLSA 52 +#define GETDNS_RRTYPE_HIP 55 +#define GETDNS_RRTYPE_NINFO 56 +#define GETDNS_RRTYPE_RKEY 57 +#define GETDNS_RRTYPE_TALINK 58 +#define GETDNS_RRTYPE_CDS 59 +#define GETDNS_RRTYPE_SPF 99 +#define GETDNS_RRTYPE_UINFO 100 +#define GETDNS_RRTYPE_UID 101 +#define GETDNS_RRTYPE_GID 102 +#define GETDNS_RRTYPE_UNSPEC 103 +#define GETDNS_RRTYPE_NID 104 +#define GETDNS_RRTYPE_L32 105 +#define GETDNS_RRTYPE_L64 106 +#define GETDNS_RRTYPE_LP 107 +#define GETDNS_RRTYPE_TKEY 249 +#define GETDNS_RRTYPE_TSIG 250 +#define GETDNS_RRTYPE_IXFR 251 +#define GETDNS_RRTYPE_AXFR 252 +#define GETDNS_RRTYPE_MAILB 253 +#define GETDNS_RRTYPE_MAILA 254 +#define GETDNS_RRTYPE_URI 256 +#define GETDNS_RRTYPE_CAA 257 +#define GETDNS_RRTYPE_TA 32768 +#define GETDNS_RRTYPE_DLV 32769 + +/* Various typedefs */ +typedef struct getdns_context_t *getdns_context_t; +typedef uint16_t getdns_return_t; +typedef uint64_t getdns_transaction_t; +typedef enum some_data_type { + t_dict, t_list, t_int, t_bindata +} getdns_data_type; +typedef struct getdns_bindata { + size_t size; + uint8_t *binary_stuff; +} some_bindata; +typedef struct getdns_dict some_dict; +typedef struct getdns_list some_list; + +/* Helper functions for data structures */ + +/* Lists: get the length, get the data_type of the value at a given + position, and get the data at a given position */ +getdns_return_t getdns_list_get_length(struct getdns_list *this_list, size_t *answer); +getdns_return_t getdns_list_get_data_type(struct getdns_list *this_list, size_t index, getdns_data_type *answer); +getdns_return_t getdns_list_get_dict(struct getdns_list *this_list, size_t index, struct getdns_dict **answer); +getdns_return_t getdns_list_get_list(struct getdns_list *this_list, size_t index, struct getdns_list **answer); +getdns_return_t getdns_list_get_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata **answer); +getdns_return_t getdns_list_get_int(struct getdns_list *this_list, size_t index, uint32_t *answer); + +/* Dicts: get the list of names, get the data_type of the + value at a given name, and get the data at a given name */ +getdns_return_t getdns_dict_get_names(struct getdns_dict *this_dict, struct getdns_list **answer); +getdns_return_t getdns_dict_get_data_type(struct getdns_dict *this_dict, char *name, getdns_data_type *answer); +getdns_return_t getdns_dict_get_dict(struct getdns_dict *this_dict, char *name, struct getdns_dict **answer); +getdns_return_t getdns_dict_get_list(struct getdns_dict *this_dict, char *name, struct getdns_list **answer); +getdns_return_t getdns_dict_get_bindata(struct getdns_dict *this_dict, char *name, struct getdns_bindata **answer); +getdns_return_t getdns_dict_get_int(struct getdns_dict *this_dict, char *name, uint32_t *answer); + + +/* Lists: create, destroy, and set the data at a given position */ +struct getdns_list * getdns_list_create(); +void getdns_list_destroy(struct getdns_list *this_list); +getdns_return_t getdns_list_set_dict(struct getdns_list *this_list, size_t index, struct getdns_dict *child_dict); +getdns_return_t getdns_list_set_list(struct getdns_list *this_list, size_t index, struct getdns_list *child_list); +getdns_return_t getdns_list_set_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata *child_bindata); +getdns_return_t getdns_list_set_int(struct getdns_list *this_list, size_t index, uint32_t child_uint32); + +/* Dicts: create, destroy, and set the data at a given name */ +struct getdns_dict * getdns_dict_create(); +void getdns_dict_destroy(struct getdns_dict *this_dict); +getdns_return_t getdns_dict_set_dict(struct getdns_dict *this_dict, char *name, struct getdns_dict *child_dict); +getdns_return_t getdns_dict_set_list(struct getdns_dict *this_dict, char *name, struct getdns_list *child_list); +getdns_return_t getdns_dict_set_bindata(struct getdns_dict *this_dict, char *name, struct getdns_bindata *child_bindata); +getdns_return_t getdns_dict_set_int(struct getdns_dict *this_dict, char *name, uint32_t child_uint32); + +/* Callback arguments */ +typedef void (*getdns_callback_t)( + getdns_context_t context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id); + +/* Function definitions */ + +getdns_return_t +getdns_general( + getdns_context_t context, + const char *name, + uint16_t request_type, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); +getdns_return_t +getdns_address( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); +getdns_return_t +getdns_hostname( + getdns_context_t context, + struct getdns_dict *address, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); +getdns_return_t +getdns_service( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); + +getdns_return_t +getdns_context_create( + getdns_context_t *context, + bool set_from_os +); + +void +getdns_context_destroy( + getdns_context_t context +); + +getdns_return_t +getdns_cancel_callback( + getdns_context_t context, + getdns_transaction_t transaction_id +); + +getdns_return_t +getdns_general_sync( + getdns_context_t context, + const char *name, + uint16_t request_type, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +); + +getdns_return_t +getdns_address_sync( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +); + +getdns_return_t +getdns_hostname_sync( + getdns_context_t context, + struct getdns_dict *address, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +); + +getdns_return_t +getdns_service_sync( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +); + +void +getdns_free_sync_request_memory( + struct getdns_dict *response +); + +char * +getdns_convert_dns_name_to_fqdn( + char *name_from_dns_response +); + +char * +getdns_convert_fqdn_to_dns_name( + char *fqdn_as_string +); + +char * +getdns_convert_ulabel_to_alabel( + char *ulabel +); + +char * +getdns_convert_alabel_to_ulabel( + char *alabel +); + +getdns_return_t +getdns_validate_dnssec( + struct getdns_bindata *record_to_validate, + struct getdns_list *bundle_of_support_records, + struct getdns_list *trust_anchor_rdatas +); + +char * +getdns_pretty_print_dict( + struct getdns_dict *some_dict +); + +char * +getdns_display_ip_address( + struct getdns_bindata *bindata_of_ipv4_or_ipv6_address +); + +getdns_return_t +getdns_context_set_context_update_callback( + getdns_context_t context, + void (*value)(getdns_context_t context, uint16_t changed_item) +); + +getdns_return_t +getdns_context_set_resolution_type( + getdns_context_t context, + uint16_t value +); + +getdns_return_t +getdns_context_set_namespaces( + getdns_context_t context, + size_t namespace_count, + uint16_t *namespaces +); + +getdns_return_t +getdns_context_set_dns_transport( + getdns_context_t context, + uint16_t value +); + +getdns_return_t +getdns_context_set_limit_outstanding_queries( + getdns_context_t context, + uint16_t limit +); + +getdns_return_t +getdns_context_set_timeout( + getdns_context_t context, + uint16_t timeout +); + +getdns_return_t +getdns_context_set_follow_redirects( + getdns_context_t context, + uint16_t value +); + +getdns_return_t +getdns_context_set_dns_root_servers( + getdns_context_t context, + struct getdns_list *addresses +); + +getdns_return_t +getdns_context_set_append_name( + getdns_context_t context, + uint16_t value +); + +getdns_return_t +getdns_context_set_suffix( + getdns_context_t context, + struct getdns_list *value +); + +getdns_return_t +getdns_context_set_dnssec_trust_anchors( + getdns_context_t context, + struct getdns_list *value +); + +getdns_return_t +getdns_context_set_dnssec_allowed_skew( + getdns_context_t context, + uint16_t value +); + +getdns_return_t +getdns_context_set_stub_resolution( + getdns_context_t context, + struct getdns_list *upstream_list +); + +getdns_return_t +getdns_context_set_edns_maximum_udp_payload_size( + getdns_context_t context, + uint16_t value +); + +getdns_return_t +getdns_context_set_edns_extended_rcode( + getdns_context_t context, + uint8_t value +); + +getdns_return_t +getdns_context_set_edns_version( + getdns_context_t context, + uint8_t value +); + +getdns_return_t +getdns_context_set_edns_do_bit( + getdns_context_t context, + uint8_t value +); + +getdns_return_t +getdns_context_set_memory_allocator( + getdns_context_t context, + void (*value)(size_t somesize) +); + +getdns_return_t +getdns_context_set_memory_deallocator( + getdns_context_t context, + void (*value)(void*) +); + +getdns_return_t +getdns_context_set_memory_reallocator( + getdns_context_t context, + void (*value)(void*) +); + +#endif /* GETDNS_H */ diff --git a/spec/getdns_libevent.h b/spec/getdns_libevent.h new file mode 100644 index 00000000..fd9effce --- /dev/null +++ b/spec/getdns_libevent.h @@ -0,0 +1,9 @@ +#include +#include + +/* For libevent, which we are using for these examples */ +getdns_return_t +getdns_extension_set_libevent_base( + getdns_context_t context, + struct event_base *this_event_base +); diff --git a/spec/index.html b/spec/index.html new file mode 100644 index 00000000..99c6218c --- /dev/null +++ b/spec/index.html @@ -0,0 +1,2182 @@ + +DNS API Description + + + + + +

Description of the getdns API

+

Paul Hoffman, Editor

+

Document version: "getdns April 2013"

+ +

This document describes a modern asynchronous DNS API. This new API is intended to be useful to +application developers and operating system distributors as a way of making +all types of DNS information easily available in many types of programs. The major features +of this new API are:

+ +
    +
  • Full support for event-driven programming
  • +
  • Supports DNSSEC in multiple ways
  • +
  • Mirroring of the resolution in getaddrinfo()
  • +
  • Easily supports all RRtypes, even those yet to be defined
  • +
+ +

There is more background into the design and future goals of this API +later in this document.

+ +

This document was discussed on the +getdns-api mailing list; future versions of the API might be discussed there as well. +(If you +want to contact the editor off-list, please send mail to paul.hoffman@vpnc.org.)

+ +

1. The getdns Async Functions

+ +

The API has four async functions:

+ +
    + +
  • getdns_address for doing getaddrinfo()-like address lookups
  • + +
  • getdns_hostname for doing getnameinfo()-like name lookups
  • + +
  • getdns_service for getting results from SRV lookups
  • + +
  • getdns_general for looking up any type of DNS record
  • + +
+ +

1.1 getdns_general()

+ +
getdns_return_t +getdns_general( + getdns_context_t context, + const char *name, + uint16_t request_type, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); +
+ +

context

+

A pointer to the DNS context that is to be used with this call. DNS contexts are +described later in this document. Note that a context must be created +before calling the function.

+ +

*name

+

The ASCII-based domain name to be looked up as a string. This can also be +an IPv4 or IPv6 address for request types that take addresses instead of domain names, +such as PTR. The values here follow the rules in section 2.1 of RFC 4343 +to allow non-ASCII octets and special characters in labels.

+ +

request_type

+

Specifies the RRtype for the query; the RRtype numbers are listed in the IANA +registry. For example, to get the NS records, request_type would be 2. The API also has +defined macros for most of the RRtypes by name; the definition names all start with +"GETDNS_RRTYPE_". For example, to get the NS records, you can also set the +request_type to GETDNS_RRTYPE_NS. +(The full list of request types is always +here.)

+ +

*extensions

+

Specifies the extensions for this request; the value may be NULL if there are no +extensions. See the section below for information on how to specify +the extensions used for a request.

+ +

*userarg

+

A void* that is passed to the function, which the funciton +returns to the callback function untouched. userarg can be used by the callback +function for any user-specific data needed. This can be NULL.

+ +

*transaction_id

+

A pointer to a value that is filled in by the +function to identify the callback being made. +This pointer can be NULL, in which case it is ignored and no value is assigned. +The getdns_cancel_callback() function uses the +transaction_id to determine which callback is to be cancelled. +If the function fails, +transaction_id is set to 0.

+ +

*callbackfn

+

A pointer to a callback function that is defined by the application. +Typically, the callback function will do all the processing on the results from +the API. The parameters of the callback are defined below. This really needs +to be a pointer to a function (and not something like NULL); otherwise, the +results are unpredictable.

+ +

The async getdns functions return GETDNS_RETURN_GOOD if the call was properly formatted. +It returns GETDNS_RETURN_BAD_DOMAIN_NAME if the API determines that the name passed to +the function was bad, GETDNS_RETURN_BAD_CONTEXT if the context pointer is bad, +GETDNS_RETURN_NO_SUCH_EXTENSION if one or more extensions do not exist, or +GETDNS_RETURN_EXTENSION_MISFORMAT if the contents of one or more of the +extensions is incorrect. All of the return values are given later in this document.

+ +

1.2 getdns_address()

+ +
getdns_return_t +getdns_address( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); +
+ +

There are three critical differences between getdns_address() and +getdns_general() beyond the missing request_type argument:

+ +
    + +
  • In getdns_address(), the name argument can only take a host name.
  • + +
  • You do not need to include a return_both_v4_and_v6 extension with the call in +getdns_address(): it will always return both IPv4 and IPv6 addresses.
  • + +
  • getdns_address() always uses all of namespaces from the context (to better emulate +getaddrinfo()), while getdns_general() only uses the DNS namespace.
  • + +
+ +

1.3 getdns_hostname()

+ +
getdns_return_t +getdns_hostname( + getdns_context_t context, + struct getdns_dict *address, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); +
+ +

The address is given as a getdns_dict data structure (defined below). The list must +have two names: address_type (whose value is a bindata; it is currently either "IPv4" +or "IPv6") and address_data (whose value is a bindata).

+ +

1.4 getdns_service()

+ +
getdns_return_t +getdns_service( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); +
+ +

name must be a domain name for an SRV lookup; the call returns the +relevant SRV information for the name.

+ +

1.5 Callback Functions for getdns

+ +

A call to the async getdns functions typically returns before any network or file I/O occurs. After +the API marshalls all the needed information, it calls the callback function that was passed by the +application. The callback function might be called at any time, even before the calling function +has returned. The API guarantees that the callback will be called exactly once unless the calling function +returned an error, in which case the callback function is never called.

+ +

The getdns calling function calls the callback with the parameters defined +as follows:

+
+typedef void (*getdns_callback_t)( + getdns_context_t context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id); +
+ +

context

+

The DNS context that was used in the calling function. See below for a description of the basic use of contexts, and later for more advanced use.

+ +

callback_type

+

Supplies the reason for the callback. See below for the codes and reasons.

+ +

*response

+

A response object with the response data. This is described below. The response +object is part of the API's memory space, and will be freed by the API with the callback returns.

+ +

*userarg

+

Identical to the *userarg passed to the calling function.

+ +

transaction_id

+

The transaction identifier that was assigned by the calling function.

+ +

The following are the values for callback_type.

+ +

GETDNS_CALLBACK_COMPLETE

+

The response has the requested data in it

+

GETDNS_CALLBACK_CANCEL

+

The calling program cancelled the callback; response is NULL

+

GETDNS_CALLBACK_TIMEOUT

+

The requested action timed out; response is NULL

+

GETDNS_CALLBACK_ERROR

+

The requested action had an error; response is NULL

+ + +

1.6 Setting Up The DNS Context

+ +

Calls to getdns functions require a DNS context, which is a group of API settings +that affect how DNS calls are made. For most applications, a default context is sufficient.

+ +

To create a new DNS context, use the function:

+ +
getdns_return_t +getdns_context_create( + getdns_context_t *context, + bool set_from_os +); +
+ +

The call to getdns_context_create immediately returns a context that can +be used with other API calls; that context contains the API's default values. Most applications will +want set_from_os set to true.

+ +

To clean up the context, including cleaning up all outstanding transactions that were called +using this context, use the function:

+ +
void +getdns_context_destroy( + getdns_context_t context +); +
+ +

When getdns_context_destroy() returns, the +application knows that all outstanding transactions associated with this +context will have been called; callbacks that had not been called before +getdns_context_destroy() was called will be called with a callback_type of +GETDNS_CALLBACK_CANCEL. getdns_context_destroy() returns after +all of the needed cleanup is done and callbacks are made.

+ +

1.7 Canceling a Callback

+ +

To cancel an outstanding callback, use the following function.

+ +
getdns_return_t +getdns_cancel_callback( + getdns_context_t context, + getdns_transaction_t transaction_id +); +
+ +

This causes the API to call the callback with a callback_type of +GETDNS_CALLBACK_CANCEL if the callback for this transaction_id has not +already been called. The callback code for cancellation should clean up any memory related to the +identified call, such as to deallocate the memory for the userarg. +getdns_cancel_callback() may return immediately, even before the callback finishes its +work and returns. Calling getdns_cancel_callback() with a transaction_id +of a callback that has already been called or an unknown transaction_id returns +GETDNS_RETURN_UNKNOWN_TRANSACTION; otherwise, getdns_cancel_callback() +returns GETDNS_RETURN_GOOD.

+ +

1.8 Event-driven Programs

+ +

Event-driven programs (sometimes called "async programs") require an event +base and event loop (among other things). Different event libraries have +different structures or the event base. Because of this, there is no standard +method to set the event base in the DNS API: those are all added as +extensions. The API is distributed as a core package and one or more sets of +extensions to align with event libraries. It is mandatory to use one of the extension +functions to set the event base in the DNS context; this is required before +calling any event-driven calls like the getdns functions.

+ +

Each implementation of the DNS API will specify an extension function that +tells the DNS context which event base is being used. For example, one +implementation of this API that uses the libevent event library might name +this function "getdns_extension_set_libevent_base()" while +another might name it +"getdns_extension_set_eventbase_for_libevent()"; the two +extension functions could have very different calling patterns and return +values. Thus, the application developer must read the API documentation +(not just this design document) in order to determine what extension function +to use to tell the API the event base to use.

+ +

The structure of a typical event-driven application might look like the following pseudocode. +The code in italics is specific to the event mechanism.

+ +
+Includes for one or more regular C libraries
+An include for the getdns library specific to the event library you use
+Definition of your callback function
+    Get the DNS data from the allocated pointer
+    Process that data
+    Check for errors
+Definition of main()
+    Create context
+    Set up your event base
+    Point the context to your event base
+    Set up the getdns call arguments
+    Make the getdns call
+    Check if the getdns return is good
+    Destroy the context
+    Exit
+
+ +

The API does not have direct support for a polling interface. Instead, the callback interface is +specifically designed to allow an application that wants to process results in polling instead of in +callbacks to be able to create its own polling interface fairly trivially. Such a program would +create a data structure for the calls, including their transaction_id and +userag. The userarg could be the polling data structure or have a pointer to it. +The application would have just +one callback function for all requests, and that function would copy the response into +application memory, update the data structure based on the transaction_id index, +and return from the callback. The polling code could then check the data structure for any updates +at its leisure.

+ +

1.9 Calling the API Synchronously (Without Events)

+ +

Thare are functions parallel to the four getdns async functions, +except that there is no callback. That is, when an application calls one of these +synchronous functions, the +API gathers all the required information and then returns the result. The value returned is exactly the +same as the response returned in the callback if you had used the async version of the function.

+ +
getdns_return_t +getdns_general_sync( + getdns_context_t context, + const char *name, + uint16_t request_type, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +); +
+ +
getdns_return_t +getdns_address_sync( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +); +
+ +
getdns_return_t +getdns_hostname_sync( + getdns_context_t context, + struct getdns_dict *address, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +); +
+ +
getdns_return_t +getdns_service_sync( + getdns_context_t context, + const char *name, + struct getdns_dict *extensions, + uint32_t *response_length, + struct getdns_dict *response +); +
+ +

When you are done with the data in the response, use the following function so that the API can +free the memory from its internal pool.

+ +
void +getdns_free_sync_request_memory( + struct getdns_dict *response +); +
+ +

2. Data structures in the API

+ +

The API returns data structures. The data structure is not a representational language like JSON: +it is really just a data structure. Data structures can have four types of members:

+ +
    + +
  • list is an ordered list, like JSON and Python lists. +The members of the list can be any of the four data types.
  • + +
  • dict is a name-value pair, like a JSON object or Python dict. The +name is a string literal, and the value can be any of the four data types. The order of the +name-value pairs in a dict is not important.
  • + +
  • int is an integer compatible with uint32_t.
  • + +
  • bindata is a struct to hold binary data. It is defined as +{ size_t size; uint8_t *binary_stuff; }.
  • + +
+ +

The API comes with helper functions to get data from the list and dict data types:

+ +
+/* Lists: get the length, get the data_type of the value at a given + position, and get the data at a given position */ +getdns_return_t getdns_list_get_length(struct getdns_list *this_list, size_t *answer); +getdns_return_t getdns_list_get_data_type(struct getdns_list *this_list, size_t index, getdns_data_type *answer); +getdns_return_t getdns_list_get_dict(struct getdns_list *this_list, size_t index, struct getdns_dict **answer); +getdns_return_t getdns_list_get_list(struct getdns_list *this_list, size_t index, struct getdns_list **answer); +getdns_return_t getdns_list_get_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata **answer); +getdns_return_t getdns_list_get_int(struct getdns_list *this_list, size_t index, uint32_t *answer); + +/* Dicts: get the list of names, get the data_type of the + value at a given name, and get the data at a given name */ +getdns_return_t getdns_dict_get_names(struct getdns_dict *this_dict, struct getdns_list **answer); +getdns_return_t getdns_dict_get_data_type(struct getdns_dict *this_dict, char *name, getdns_data_type *answer); +getdns_return_t getdns_dict_get_dict(struct getdns_dict *this_dict, char *name, struct getdns_dict **answer); +getdns_return_t getdns_dict_get_list(struct getdns_dict *this_dict, char *name, struct getdns_list **answer); +getdns_return_t getdns_dict_get_bindata(struct getdns_dict *this_dict, char *name, struct getdns_bindata **answer); +getdns_return_t getdns_dict_get_int(struct getdns_dict *this_dict, char *name, uint32_t *answer); +
+ +

All of these helper getter functions return GETDNS_RETURN_GOOD if the call is successful. +The list functions will return GETDNS_RETURN_NO_SUCH_LIST_ITEM if the index argument is +out of range; the dict functions will return GETDNS_RETURN_NO_SUCH_DICT_NAME if the name +argument doesn't exist in the dict. The functions also return GETDNS_RETURN_WRONG_TYPE_REQUESTED +if the requested data type doesn't match the contents of the indexed argument or name.

+ +

This document uses graphical representations of data structures. It is important to note that +this is only a graphical representation; the brackets, commas, quotation marks, comments, and so on +are not part of the data. Also, this document uses macro names instead of some of the int +arguments; of course, the data structures have the actual int in them.

+ +

2.1 Creating Data Structures

+ +

Some of the features of the API require that you create your own data structures to be used in +arguments passed to the API. For example, if you want to use any extensions for the calling functions, +you need to create a dict. The requisite functions are:

+ +
+/* Lists: create, destroy, and set the data at a given position */ +struct getdns_list * getdns_list_create(); +void getdns_list_destroy(struct getdns_list *this_list); +getdns_return_t getdns_list_set_dict(struct getdns_list *this_list, size_t index, struct getdns_dict *child_dict); +getdns_return_t getdns_list_set_list(struct getdns_list *this_list, size_t index, struct getdns_list *child_list); +getdns_return_t getdns_list_set_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata *child_bindata); +getdns_return_t getdns_list_set_int(struct getdns_list *this_list, size_t index, uint32_t child_uint32); + +/* Dicts: create, destroy, and set the data at a given name */ +struct getdns_dict * getdns_dict_create(); +void getdns_dict_destroy(struct getdns_dict *this_dict); +getdns_return_t getdns_dict_set_dict(struct getdns_dict *this_dict, char *name, struct getdns_dict *child_dict); +getdns_return_t getdns_dict_set_list(struct getdns_dict *this_dict, char *name, struct getdns_list *child_list); +getdns_return_t getdns_dict_set_bindata(struct getdns_dict *this_dict, char *name, struct getdns_bindata *child_bindata); +getdns_return_t getdns_dict_set_int(struct getdns_dict *this_dict, char *name, uint32_t child_uint32); +
+ +

These helper setter functions return GETDNS_RETURN_GOOD if the call is successful. +The list functions will return GETDNS_RETURN_NO_SUCH_LIST_ITEM if the index argument is +out of range; the dict functions will return GETDNS_RETURN_NO_SUCH_DICT_NAME if the name +argument doesn't exist in the dict. The functions also return GETDNS_RETURN_WRONG_TYPE_REQUESTED +if the requested data type doesn't match the contents of the indexed argument or name.

+ +

3. Extensions

+ +

Extensions are dict data structures. The names in the dict are the names of the extensions. +The definition of each extension describes the value associated with the name. For most extensions, +it is an on-off boolean, and the value is GETDNS_EXTENSION_TRUE. (There is +not currently a good reason to specify an extension name and give it a value of GETDNS_EXTENSION_FALSE, +but that is allowed by the API.)

+ +

For example, to create a dict for extensions and specify the extension to only return +results that have been validated with DNSSEC, you might use:

+ +
+/* . . . */
+struct getdns_dict * this_extensions = getdns_dict_create();
+this_ret = getdns_dict_set_int(this_extensions, "dnssec_return_only_secure", GETDNS_EXTENSION_TRUE);
+/* . . . Do some processing with the extensions and results . . . */
+/* Remember to clean up memory*/
+getdns_dict_destroy(this_extensions);
+
+ +

The extensions described in this section are are: + +

    + +
  • dnssec_return_status
  • + +
  • dnssec_return_only_secure
  • + +
  • dnssec_return_supporting_responses
  • + +
  • return_both_v4_and_v6
  • + +
  • add_opt_parameters
  • + +
  • add_warning_for_bad_dns
  • + +
  • specify_class
  • + +
  • return_api_information
  • + +
  • return_call_debugging
  • + +
+ +

3.1 Extensions for DNSSEC

+ +

If an application wants the API to do DNSSEC validation for a request, it must set one or more +DNSSEC-related extensions. Note that the default is for none of these extensions to be set and +the API will not perform DNSSEC, and thus will return results sooner.

+ +

To return the DNSSEC status for each DNS record in the replies_tree list, use the +dnssec_return_status extension. The extension's value (an int) is set to +GETDNS_EXTENSION_TRUE to cause the returned status to have the name +dnssec_status (an int) added to the other names in the record's dict ("header", +"question", and so on). The values for that name are GETDNS_DNSSEC_SECURE, +GETDNS_DNSSEC_BOGUS, GETDNS_DNSSEC_INDETERMINATE, and +GETDNS_DNSSEC_INSECURE. Thus, a reply might look like:

+ +
+    {     # This is the first reply
+      "dnssec_status": GETDNS_DNSSEC_INDETERMINATE,
+      "header": { "id": 23456, "qr": 1, "opcode": 0, ... },
+      . . .
+
+ +

If instead of returning the status, you want to only see secure results, use the +dnssec_return_only_secure extension. The extension's value (an int) is set to +GETDNS_EXTENSION_TRUE to cause only records that the API can validate as secure with +DNSSEC to be returned in the replies_tree and replies_full lists. No +additional names are added to the dict of the record; the change is that some records might not +appear in the results. When this context option is set, if the API receives DNS replies but none +are determined to be secure, the error code at the top level of the response object is +GETDNS_RESPSTATUS_NO_SECURE_ANSWERS.

+ +

Applications that want to do their own validation will want to have the DNSSEC-related records +for a particular response. Use the dnssec_return_supporting_responses extension. The +extension's value (an int) is set to GETDNS_EXTENSION_TRUE to cause a set +of additional DNSSEC-related records needed for validation to be returned in the response object. +This set comes as additional_dnssec (a list) at the top level of the response object. +This list includes any trust anchors needed for the validation. Thus, a reply might look like:

+ +
+{     # This is the response object
+  "additional_dnssec": [ <bindata of the first DNSSEC record>, <bindata of the second DNSSEC record> ... ],
+  "replies_tree":
+  [
+  . . .
+
+ +

If a request is using a context in which stub resolution is set, and that request also has +any of the dnssec_return_status, dnssec_return_only_secure, or +dnssec_return_supporting_responses extensions specified, the API will not perform +the request and will instead return an error of GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED.

+ +

3.2 Returning Both IPv4 and IPv6 Responses

+ +

Many applications want to get both IPv4 and IPv6 addresses in a single call so that the results +can be processed together. The getdns_address and getdns_address_sync +functions are able to do this automatically. If you are using the getdns_general or +getdns_general_sync function, you can enable this with the +return_both_v4_and_v6 extension. The extension's value (an int) is set to +GETDNS_EXTENSION_TRUE to cause the results to be the lookup of either A or AAAA records +to include any A and AAAA records for the queried name (otherwise, the extension does nothing). +These results are expected to be used with Happy Eyeballs systems that will find the best socket for +an application.

+ +

3.3 Setting Up OPT Resource Records

+ +

For lookups that need an OPT resource record in the Additional Data section, use the +add_opt_parameters extension. The extension's value (a dict) contains the +parameters; these are described in more detail in RFC 2671. They are:

+ +
    + +
  • maximum_udp_payload_size (an int), a value between 512 and 65535; if not specified, +this defaults to those from the DNS context
  • + +
  • extended_rcode (an int), a value between 0 and 255; if not specified, +this defaults to those from the DNS context
  • + +
  • version (an int), a value between 0 and 255; if not specified, this +defaults to 0
  • + +
  • do_bit (an int), a value between 0 and 1; if not specified, this defaults +to those from the DNS context
  • + +
  • options (a list) contains dicts for each option to be specified. +Each list time contains two names: option_code (an int) and option_data +(a bindata). The API marshalls the entire set of options into a properly-formatted RDATA +for the resource record.
  • + +
+ +

It is very important to note that the OPT resource record specified in the +add_opt_parameters extension might not be the same the one that the API sends in the +query. For example, if the application also includes any of the DNSSEC extensions, the API will make +sure that the OPT resource record sets the resource record appropriately, making the needed changes +to the settings from the add_opt_parameters extension.

+ +

The use of this extension can conflict with the values in the DNS context. For example, +the default for an OS might be a maximum payload size of 65535, but the extension might specify +1550. In such a case, the API will honor the values stated in the extension, but will honor the +values from the DNS context if values are not given in the extension.

+ +

3.4 Getting Warnings for Responses that Violate the DNS Standard

+ +

To receive a warning if a particular response violates some parts of the DNS standard, use +the add_warning_for_bad_dns extension. The extension's value (an int) is set to +GETDNS_EXTENSION_TRUE to cause each reply in the replies_tree +to contain an additional name, bad_dns (a list). The list is zero or more +ints that indicate types of bad DNS found in that reply. The list of values is: + +

GETDNS_BAD_DNS_CNAME_IN_TARGET

+

A DNS query type that does not allow a target to be a CNAME pointed to a CNAME

+

GETDNS_BAD_DNS_ALL_NUMERIC_LABEL

+

One or more labels in a returned domain name is all-numeric; this is not legal for a hostname

+

GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE

+

A DNS query for a type other than CNAME returned a CNAME response

+ + +

3.5 Using Other Class Types

+ +

The vast majority of DNS requests are made with the Internet (IN) class. To make a request in a +different DNS class, use, the specify_class extension. The extension's value (an int) +contains the class number. Few applications will ever use this extension.

+ +

3.6 Extensions Relating to the API

+ +

An application might want to see information about the API itself. Use the +return_api_information extension. An application that wants to get this information +before a "real" query is issued can add this extension to a PTR query for 127.0.0.1. +The extension's value (an int) is set to +GETDNS_EXTENSION_TRUE to add the following to the top level of the response object:

+ +
    + +
  • version_string (a bindata) represents the version string for this version of the DNS +API.
  • + +
  • implementation_string (a bindata) is a string set by the API implementer. It might +be human-readable, and it might have information in it useful to an application developer (but it doesn't +have to).
  • + +
  • resolver_type (an int) is the type of resolver that the API is acting as in this context: +GETDNS_CONTEXT_RECURSING or GETDNS_CONTEXT_STUB (it will be +a recursing resolver unless the application changed this in a context.
  • + +
  • all_context (a dict) with names for all the types of context. This can be used with +getdns_pretty_print_dict() for debugging.
  • + +
+ +

An application might want to see debugging information for queries such as the length of time it +takes for each query to return to the API. Use the return_call_debugging extension. The +extension's value (an int) is set to GETDNS_EXTENSION_TRUE to add the name +call_debugging (a list) to the top level of the response object. Each member of the +list is a dict that represents one call made for the call to the API. Each member has the following +names:

+ +
    +
  • query_name (a bindata) is the name that was sent
  • +
  • query_type (an int) is the type that was queried for
  • +
  • query_to (a bindata) is the address to which the query was sent
  • +
  • start_time (a bindata) is the time the query started in milliseconds since the epoch, +represented as a uint64_t
  • +
  • end_time (a bindata) is the time the query was received in milliseconds since the epoch, +represented as a uint64_t
  • +
  • entire_reply (a bindata) is the entire response received
  • +
  • dnssec_result (an int) is the DNSSEC status, or GETDNS_DNSSEC_NOT_PERFORMED +if DNSSEC validation was not performed
  • +
+ +

4. Response Data from Queries

+ +

The callback function contains a pointer to a response object. +A response object is always a dict. The response +object always contains at least three names: replies_full (a list) and +replies_tree (a list), and status (an int). +replies_full is a list of DNS replies (each is bindata) as they appear on the wire. +replies_tree is a list of DNS replies (each is a dict) with the various part of the +reply parsed out. status is a status code for the query.

+ +

Because the API might be extended in the future, a response object might also contain names other +than replies_full, replies_tree, and status. Similarly, any +of the dicts described here might be extended in later versions of the API. Thus, an application +using the API must not assume that it knows all possible names in a dict.

+ +

The following lists the status codes for response objects. Note that, if the status is that there +are no responses for the query, the lists in replies_full and replies_tree +will have zero length.

+ +

GETDNS_RESPSTATUS_GOOD

+

At least one response was returned

+

GETDNS_RESPSTATUS_NO_NAME

+

Queries for the name yielded all negative responses

+

GETDNS_RESPSTATUS_ALL_TIMEOUT

+

All queries for the name timed out

+

GETDNS_RESPSTATUS_NO_SECURE_ANSWERS

+

The context setting for getting only secure responses was specified, and at least one DNS response was received, but no DNS response was determined to be secure through DNSSEC.

+ + +

The top level of replies_tree can optionally have the following names: canonical_name (a +bindata), intermediate_aliases (a list), answer_ipv4_address (a bindata), +answer_ipv6_address (a bindata), and answer_type (an int).

+ +
    + +
  • The value of canonical_name is the name that the API used for its lookup. It is in +FQDN presentation format.
  • + +
  • The values in the intermediate_aliases list are domain names from any CNAME or +unsynthesized DNAME found when resolving the original query. The list might have zero entries +if there were no CNAMEs in the path. These may be useful, for example, for name comparisons +when following the rules in RFC 6125.
  • + +
  • The value of answer_ipv4_address and answer_ipv6_address are +the addresses of the server from which the answer was received.
  • + +
  • The value of answer_type is the type of name service that generated the response. +The values are:
  • + +
+ +

GETDNS_NAMETYPE_DNS

+

Normal DNS (RFC 1035)

+

GETDNS_NAMETYPE_WINS

+

The WINS name service (some reference needed)

+ + +

If the call was getdns_address or getdns_address_sync, the top level +of replies_tree has an additional name, just_address_answers (a list). +The value of just_address_answers is a list that contains all of the A and AAAA +records from the answer sections of any of the replies, in the order they appear in the replies. +Each item in the list is a dict with at least two names: address_type (whose value is +a bindata; it is currently either "IPv4" or "IPv6") and address_data (whose value is a bindata). +Note that the dnssec_return_only_secure extension affects +what will appear in the just_address_answers list. Also note if later versions of the +DNS return other address types, those types will appear in this list as well.

+ +

The API can make service discovery through SRV records easier. If +the call was getdns_service or getdns_service_sync, +the top level of replies_tree has an additional name, +srv_addresses (a list). +The list is ordered by priority and weight based on the weighting +algorithm in RFC 2782, lowest priority value first. Each element +of the list is dict has at least two names: port and domain_name. If the +API was able to determine the address of the target domain name (such as from its cache or from the +Additional section of responses), the dict for an element will also contain +address_type (whose value is a bindata; it is currently either "IPv4" or "IPv6") and +address_data (whose value is a bindata). Note that the +dnssec_return_only_secure extension affects what will appear in the +srv_addresses list.

+ +

4.1 Structure of DNS replies_tree

+ +

The names in each entry in the the replies_tree list for DNS responses include +header (a dict), question (a dict), answer (a list), +authority (a list), and additional (a list), corresponding to the sections +in the DNS message format. The answer, authority, and additional lists each contain zero or more +dicts, with each dict in each list representing a resource record.

+ +

The names in the header dict are all the fields from Section 4.1.1. of RFC 1035. +They are: id, qr, opcode, aa, tc, +rd, ra, z, rcode, qdcount, +ancount, nscount, and arcount. All are ints.

+ +

The names in the question dict are the three fields from Section 4.1.2. of RFC 1035: +qname (a bindata), qtype (an int), and qclass (an int).

+ +

Resource records are a bit different than headers and question sections in that the RDATA portion +often has its own structure. The other names in the resource record dicts are name (a +bindata), type (an int), class (an int), ttl (an int) and +rdata (a dict); there is no name equivalent to the RDLENGTH field.

+ +

The rdata dict has different names for each response type. There is a complete list of the types defined in the API. For names that end in +"-obsolete" or "-unknown", the bindata is the entire RDATA field. For example, the +rdata for an A record has a name ipv4_address (a bindata); the +rdata for an SRV record has the names priority (an int), +weight (an int), port (an int), and target (a bindata).

+ +

Each rdata dict also has a rdata_raw field (a bindata). This is useful +for types not defined in this version of the API. It also might be of value if a later version of +the API allows for additional parsers. Thus, doing a query for types not known by the API still will +return a result: an rdata with just a rdata_raw.

+ +

It is expected that later extensions to the API will give some DNS types different names. It is +also possible that later extensions will change the names for some of the DNS types listed above.

+ +

For example, a response to a getdns_address() call for www.example.com would +look something like this:

+ +
+{     # This is the response object
+  "replies_full": [ <bindata of the first response>, <bindata of the second response> ],
+  "just_address_answers": [ <bindata of 0x0a0b0c01>, <bindata of 0x33445566334455663344556633445566> ],
+  "canonical_name": <bindata for "www.example.com">,
+  "answer_type": GETDNS_NAMETYPE_DNS,
+  "intermediate_aliases": [],
+  "replies_tree":
+  [
+    {     # This is the first reply
+      "header": { "id": 23456, "qr": 1, "opcode": 0, ... },
+      "question": { "qname": <bindata for "www.example.com">, "qtype": 1, "qclass": 1 },
+      "answer":
+      [
+        {
+          "name": <bindata for "www.example.com">,
+          "type": 1,
+          "class": 1,
+          "ttl": 33000,
+          "rdata":
+          {
+            "ipv4_address": <bindata of 0x0a0b0c01>
+            "rdata_raw": <bindata of 0x0a0b0c01>
+          }
+        }
+      ],
+      "authority":
+      [
+        {
+          "name": <bindata for "ns1.example.com">,
+          "type": 1,
+          "class": 1,
+          "ttl": 600,
+          "rdata":
+          {
+            "ipv4_address": <bindata of 0x65439876>
+            "rdata_raw": <bindata of 0x65439876>
+          }
+        }
+      ]
+      "additional": [],
+      "canonical_name": <bindata for "www.example.com">,
+      "answer_type": GETDNS_NAMETYPE_DNS
+    },
+    {     # This is the second reply
+      "header": { "id": 47809, "qr": 1, "opcode": 0, ... },
+      "question": { "qname": <bindata for "www.example.com">, "qtype": 28, "qclass": 1 },
+      "answer":
+      [
+        {
+          "name": <bindata for "www.example.com">,
+          "type": 28,
+          "class": 1,
+          "ttl": 1000,
+          "rdata":
+          {
+            "ipv6_address": <bindata of 0x33445566334455663344556633445566>
+            "rdata_raw": <bindata of 0x33445566334455663344556633445566>
+          }
+       }
+      ],
+      "authority": [  # Same as for other record... ]
+      "additional": [],
+    },
+  ]
+}
+
+ +

In DNS responses, domain names are treated special. RFC 1035 describes a form of name compression +that requires that the entire record be available for analysis. The API deals with this by +converting compressed names into full names when returning names in the replies_tree. +This conversion happens for qname in question; name in the +answer, authority, and additional; and in domain names in the +data in names under rdata where the response type is AFSDB, CNAME, MX, NS, PTR, RP, RT, and SOA.

+ +

4.2 Converting Domain Names

+ +

Names in DNS fields are stored in a fashion very different from the normal presentation format +normally used in applications. The DNS format is described in the first paragraph in Section 3.1 of +RFC 1035; the presentation format here is a null-terminated string with interior dots. These helper +functions only work with names in the DNS format that are not compressed. They are useful for +converting domain names in the replies_tree to and from the FQDN presentation +format.

+ +

getdns_convert_dns_name_to_fqdn() converts a domain name in DNS format to the +presentation format. For example, the hex sequence 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 +6f 6d 00 would be converted to "www.example.com". +getdns_convert_fqdn_to_dns_name() does the reverse: it converts a null-terminated +string in FQDN format to bytes in DNS format.

+ +
+char * +getdns_convert_dns_name_to_fqdn( + char *name_from_dns_response +); + +char * +getdns_convert_fqdn_to_dns_name( + char *fqdn_as_string +); +
+ +

5. Additional Definitions and Descriptions

+ +

5.1 A Few Needed Definitions

+ +
typedef struct getdns_context_t *getdns_context_t; +typedef uint16_t getdns_return_t; +typedef uint64_t getdns_transaction_t; +typedef enum some_data_type { + t_dict, t_list, t_int, t_bindata +} getdns_data_type; +typedef struct getdns_bindata { + size_t size; + uint8_t *binary_stuff; +} some_bindata; +typedef struct getdns_dict some_dict; +typedef struct getdns_list some_list; +
+ +

5.2 Return Codes

+ +

The return codes for all the functions are:

+ +

GETDNS_RETURN_GOOD

+

Good

+

GETDNS_RETURN_GENERIC_ERROR

+

Generic error

+

GETDNS_RETURN_BAD_DOMAIN_NAME

+

Badly-formed domain name in first argument

+

GETDNS_RETURN_BAD_CONTEXT

+

Bad value for a context type

+

GETDNS_RETURN_CONTEXT_UPDATE_FAIL

+

Did not update the context

+

GETDNS_RETURN_UNKNOWN_TRANSACTION

+

An attempt was made to cancel a callback with a transaction_id that is not recognized

+

GETDNS_RETURN_NO_SUCH_LIST_ITEM

+

A helper function for lists had an index argument that was too high.

+

GETDNS_RETURN_NO_SUCH_DICT_NAME

+

A helper function for dicts had a name argument that for a name that is not in the dict.

+

GETDNS_RETURN_WRONG_TYPE_REQUESTED

+

A helper function was supposed to return a certain type for an item, but the wrong type was given.

+

GETDNS_RETURN_NO_SUCH_EXTENSION

+

A name in the extensions dict is not a valid extension.

+

GETDNS_RETURN_EXTENSION_MISFORMAT

+

One or more of the extensions is has a bad format.

+

GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED

+

A query was made with a context that is using stub resolution and a DNSSEC extension specified.

+ + +

5.3 Types of RDATA Returned in the API

+ +

The names in the rdata dicts in replies are:

+ + +

A (1)

+

ipv4_address (a bindata)

+ +

NS (2)

+

nsdname (a bindata)

+ +

MD (3)

+

madname (a bindata)

+ +

MF (4)

+

madname (a bindata)

+ +

CNAME (5)

+

cname (a bindata)

+ +

SOA (6)

+

mname (a bindata), rname (a bindata), +serial (an int), refresh (an int), refresh (an int), +retry (an int), and expire (an int)

+ +

MB (7)

+

madname (a bindata)

+ +

MG (8)

+

mgmname (a bindata)

+ +

MR (9)

+

newname (a bindata)

+ +

NULL (10)

+

anything (a bindata)

+ +

WKS (11)

+

address (a bindata), protocol (an int), +and bitmap (a bindata)

+ +

PTR (12)

+

ptrdname (a bindata)

+ +

HINFO (13)

+

cpu (a bindata) and os (a bindata)

+ +

MINFO (14)

+

rmailbx (a bindata) and emailbx (a bindata)

+ +

MX (15)

+

preference (an int) and exchange (a bindata)

+ +

TXT (16)

+

txt_strings (a list) which contains zero or more bindata elements +that are text strings

+ +

RP (17)

+

mbox_dname (a bindata) and txt_dname (a bindata)

+ +

AFSDB (18)

+

subtype (an int) and hostname (a bindata)

+ +

X25 (19)

+

psdn_address (a bindata)

+ +

ISDN (20)

+

isdn_address (a bindata) and sa (a bindata)

+ +

RT (21)

+

preference (an int) and intermediate_host (a bindata)

+ +

NSAP (22)

+

nsap (a bindata)

+ +

SIG (24)

+

sig_obsolete (a bindata)

+ +

KEY (25)

+

key_obsolete (a bindata)

+ +

PX (26)

+

preference (an int), map822 (a bindata), and mapx400 (a bindata)

+ +

GPOS (27)

+

longitude (a bindata), latitude (a bindata), and altitude (a bindata)

+ +

AAAA (28)

+

ipv6_address (a bindata)

+ +

LOC (29)

+

loc_obsolete (a bindata)

+ +

NXT (30)

+

nxt_obsolete (a bindata)

+ +

EID (31)

+

eid_unknown (a bindata)

+ +

NIMLOC (32)

+

nimloc_unknown (a bindata)

+ +

SRV (33)

+

priority (an int), weight (an int), +port (an int), and target (a bindata)

+ +

ATMA (34)

+

format (an int) and address (a bindata)

+ +

NAPTR (35)

+

order (an int), preference (an int), flags +(a bindata), service (a bindata), regexp (a bindata), and +replacement (a bindata).

+ +

KX (36)

+

preference (an int) and exchanger (a bindata)

+ +

CERT (37)

+

type (an int), key_tag (an int), algorithm (an int), +and certificate_or_crl (a bindata)

+ +

A6 (38)

+

a6_obsolete (a bindata)

+ +

DNAME (39)

+

target (a bindata)

+ +

SINK (40)

+

sink_unknown (a bindata)

+ +

OPT (41)

+

options (a list). Each element of the options list is a +dict with two names: option_code (an int) and option_data (a bindata).

+ +

APL (42)

+

address_family (an int), prefix (an int), +n (an int), and afdpart (a bindata)

+ +

DS (43)

+

key_tag (an int), algorithm (an int), digest_type (an int), +and digest (a bindata)

+ +

SSHFP (44)

+

algorithm (an int), fp_type (an int), +and fingerprint (a bindata)

+ +

IPSECKEY (45)

+

algorithm (an int), gateway_type (an int), precedence (an int), +gateway, and public_key (a bindata)

+ +

RRSIG (46)

+

type_covered (an int), algorithm (an int), +labels (an int), original_ttl (an int), signature_expiration +(an int), signature_inception (an int), key_tag (an int), +signers_name (a bindata), and signature (a bindata)

+ +

NSEC (47)

+

next_domain_name (a bindata) and type_bit_maps (a bindata)

+ +

DNSKEY (48)

+

flags (an int), protocol (an int), algorithm (an int), +and public_key (a bindata)

+ +

DHCID (49)

+

dhcid_opaque (a bindata)

+ +

NSEC3 (50)

+

hash_algorithm (an int), flags (an int), +iterations (an int), salt_length (an int), salt (a bindata), +hash_length (an int), next_hashed_owner_name (a bindata), and +type_bit_maps (a bindata)

+ +

NSEC3PARAM (51)

+

hash_algorithm (an int), flags (an int), +iterations (an int), salt_length (an int), and +salt (a bindata)

+ +

TLSA (52)

+

certificate_usage (an int), selector (an int), +matching_type (an int), and certificate_association_data (a +bindata).

+ +

HIP (55)

+

hit_length (an int), pk_algorithm (an int), +pk_length (an int), hit (a bindata), public_key +(a bindata), and rendezvous_servers (a bindata)

+ +

NINFO (56)

+

ninfo_unknown (a bindata)

+ +

RKEY (57)

+

rkey_unknown (a bindata)

+ +

TALINK (58)

+

talink_unknown (a bindata)

+ +

CDS (59)

+

cds_unknown (a bindata)

+ +

SPF (99)

+

text (a bindata)

+ +

UINFO (100)

+

uinfo_unknown (a bindata)

+ +

UID (101)

+

uid_unknown (a bindata)

+ +

GID (102)

+

gid_unknown (a bindata)

+ +

UNSPEC (103)

+

unspec_unknown (a bindata)

+ +

NID (104)

+

preference (an int) and +node_id (a bindata)

+ +

L32 (105)

+

preference (an int), locator32_msbs (a bindata), +and locator64_lsbs (a bindata)

+ +

L64 (106)

+

preference (an int) and locator64 (a bindata)

+ +

LP (107)

+

preference (an int) and fqdn (a bindata)

+ +

TKEY (249)

+

algorithm (a bindata), inception (an int), +expiration (an int), mode (an int), error (an int), +key_data (a bindata), and other_data (a bindata)

+ +

TSIG (250)

+

algorithm (a bindata), time_signed (a bindata), +fudge (an int), mac (a bindata), original_id (an int), +error (an int), and other_data (a bindata)

+ +

IXFR (251)

+

zones (a bindata)

+ +

AXFR (252)

+

zones (a bindata)

+ +

MAILB (253)

+

mailb-unknown (a bindata)

+ +

MAILA (254)

+

maila-unknown (a bindata)

+ +

URI (256)

+

priority (an int), weight (an int), +and target (a bindata)

+ +

CAA (257)

+

flags (an int), tag (a bindata), and value (a bindata)

+ +

TA (32768)

+

ta_unknown (a bindata)

+ +

DLV (32769)

+

Identical to DS (43)

+ + +

6. Examples

+ +

This section gives examples of code that calls the API to do many common tasks. +The purpose of the code here is to give application developers a quick hands-on +demo of using the API.

+ +

Note that the examples here all use getdns_libevent.h as the include that will call in the API +code as well as calling in libevent as the event library. They also use +getdns_context_set_libevent_base() as the name of the function to set the event base in +the DNS context. If you are using a different event library, you will of course use a different +#include at the beginning of your code, and a different name for the event base +function.

+ +

6.1 Get Both IPv4 and IPv6 Addresses for a Domain Name Using Quick Results

+ +

This is an example of a common call to getdns_address().

+ +
#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getdns_libevent.h>
+
+#define UNUSED_PARAM(x) ((void)(x))
+
+/* Set up the callback function, which will also do the processing of the results */
+void this_callbackfn(struct getdns_context_t *this_context,
+                     uint16_t     this_callback_type,
+                     struct getdns_dict *this_response, 
+                     void *this_userarg,
+                     getdns_transaction_t this_transaction_id)
+{
+    UNUSED_PARAM(this_userarg);  /* Not looking at the userarg for this example */
+    UNUSED_PARAM(this_context);  /* Not looking at the context for this example */
+    getdns_return_t this_ret;  /* Holder for all function returns */
+    if (this_callback_type == GETDNS_CALLBACK_COMPLETE)  /* This is a callback with data */
+    {
+        /* Be sure the search returned something */
+        uint32_t * this_error = NULL;
+        this_ret = getdns_dict_get_int(this_response, "status", this_error);  // Ignore any error
+        if (*this_error != GETDNS_RESPSTATUS_GOOD)  // If the search didn't return "good"
+        {
+            fprintf(stderr, "The search had no results, and a return value of %d. Exiting.", *this_error);
+            return;
+        }
+        struct getdns_list * just_the_addresses_ptr;
+        this_ret = getdns_dict_get_list(this_response, "just_address_answers", &just_the_addresses_ptr);
+        if (this_ret != GETDNS_RETURN_GOOD)  // This check is really not needed, but prevents a compiler error under "pedantic"
+        {
+            fprintf(stderr, "Trying to get the answers failed: %d", this_ret);
+            return;
+        }
+        size_t * num_addresses_ptr = NULL;
+        this_ret = getdns_list_get_length(just_the_addresses_ptr, num_addresses_ptr);  // Ignore any error
+        /* Go through each record */
+        for ( size_t rec_count = 0; rec_count <= *num_addresses_ptr; ++rec_count )
+        {
+            struct getdns_dict * this_address;
+            this_ret = getdns_list_get_dict(just_the_addresses_ptr, rec_count, &this_address);  // Ignore any error
+            /* Just print the address */
+            struct getdns_bindata * this_address_data;
+            this_ret = getdns_dict_get_bindata(this_address, "address_data", &this_address_data); // Ignore any error
+            printf("The address is %s", getdns_display_ip_address(this_address_data));
+        }
+    }
+    else if (this_callback_type == GETDNS_CALLBACK_CANCEL)
+        fprintf(stderr, "The callback with ID %"PRIu64" was cancelled. Exiting.", this_transaction_id);
+    else
+        fprintf(stderr, "The callback got a callback_type of %d. Exiting.", this_callback_type);
+}
+
+int main()
+{
+    /* Create the DNS context for this call */
+    struct getdns_context_t *this_context = NULL;
+    getdns_return_t context_create_return = getdns_context_create(&this_context, true);
+    if (context_create_return != GETDNS_RETURN_GOOD)
+    {
+        fprintf(stderr, "Trying to create the context failed: %d", context_create_return);
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    /* Create an event base and put it in the context using the unknown function name */
+    struct event_base *this_event_base;
+    this_event_base = event_base_new();
+    if (this_event_base == NULL)
+    {
+        fprintf(stderr, "Trying to create the event base failed.");
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    (void)getdns_extension_set_libevent_base(this_context, this_event_base);
+    /* Set up the getdns call */
+    const char * this_name  = "www.example.com";
+    char* this_userarg = "somestring"; // Could add things here to help identify this call
+    getdns_transaction_t this_transaction_id = 0;
+
+    /* Make the call */
+    getdns_return_t dns_request_return = getdns_address(this_context, this_name,
+        NULL, this_userarg, &this_transaction_id, this_callbackfn);
+    if (dns_request_return == GETDNS_RETURN_BAD_DOMAIN_NAME)
+    {
+        fprintf(stderr, "A bad domain name was used: %s. Exiting.", this_name);
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    else
+    {
+        /* Call the event loop */
+        int dispatch_return = event_base_dispatch(this_event_base);
+        UNUSED_PARAM(dispatch_return);
+        // TODO: check the return value above
+    }
+    /* Clean up */
+    getdns_context_destroy(this_context);
+    /* Assuming we get here, leave gracefully */
+    exit(EXIT_SUCCESS);
+}
+
+ + + +

6.2 Get IPv4 and IPv6 Addresses for a Domain Name

+ +

This example is similar to the previous one, except that it retrieves more information than just +the addresses, so it traverses the replies_tree. In this case, it gets both the addresses and +their TTLs.

+ +
#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getdns_libevent.h>
+
+#define UNUSED_PARAM(x) ((void)(x))
+
+/* Set up the callback function, which will also do the processing of the results */
+void this_callbackfn(struct getdns_context_t *this_context,
+                     getdns_return_t this_callback_type,
+                     struct getdns_dict *this_response, 
+                     void *this_userarg,
+                     getdns_transaction_t this_transaction_id)
+{
+    UNUSED_PARAM(this_userarg);  /* Not looking at the userarg for this example */
+    UNUSED_PARAM(this_context);  /* Not looking at the context for this example */
+    getdns_return_t this_ret;  /* Holder for all function returns */
+    if (this_callback_type == GETDNS_CALLBACK_COMPLETE)  /* This is a callback with data */
+    {
+        /* Be sure the search returned something */
+        uint32_t * this_error = NULL;
+        this_ret = getdns_dict_get_int(this_response, "status", this_error);  // Ignore any error
+        if (*this_error != GETDNS_RESPSTATUS_GOOD)  // If the search didn't return "good"
+        {
+            fprintf(stderr, "The search had no results, and a return value of %d. Exiting.", *this_error);
+            return;
+        }
+        /* Find all the answers returned */
+        struct getdns_list * these_answers;
+        this_ret = getdns_dict_get_list(this_response, "replies-tree", &these_answers);
+        if (this_ret == GETDNS_RETURN_NO_SUCH_DICT_NAME)
+        {
+            fprintf(stderr, "Weird: the response had no error, but also no replies-tree. Exiting.");
+            return;
+        }
+        size_t * num_answers_ptr = NULL;
+        this_ret = getdns_list_get_length(these_answers, num_answers_ptr);
+        /* Go through each answer */
+        for ( size_t rec_count = 0; rec_count <= *num_answers_ptr; ++rec_count )
+        {
+            struct getdns_dict * this_record;
+            this_ret = getdns_list_get_dict(these_answers, rec_count, &this_record);  // Ignore any error
+            /* Get the answer section */
+            struct getdns_list * this_answer;
+            this_ret = getdns_dict_get_list(this_record, "answer", &this_answer);  // Ignore any error
+            /* Get each RR in the answer section */
+            size_t * num_rrs_ptr = NULL;
+            this_ret = getdns_list_get_length(this_answer, num_rrs_ptr);
+            for ( size_t rr_count = 0; rr_count <= *num_rrs_ptr; ++rr_count )
+            {
+                struct getdns_dict * this_rr = NULL;
+                this_ret = getdns_list_get_dict(this_answer, rr_count, &this_rr);  // Ignore any error
+                /* Get the RDATA */
+                struct getdns_dict * this_rdata = NULL;
+                this_ret = getdns_dict_get_dict(this_rr, "rdata", &this_rdata);  // Ignore any error
+                /* Get the RDATA type */
+                uint32_t * this_type = NULL;
+                this_ret = getdns_dict_get_int(this_rdata, "type", this_type);  // Ignore any error
+                /* If it is type A or AAAA, print the value */
+                if (*this_type == GETDNS_RRTYPE_A)
+                {
+                    struct getdns_bindata * this_a_record = NULL;
+                    this_ret = getdns_dict_get_bindata(this_rdata, "ipv4_address", &this_a_record);
+                    if (this_ret == GETDNS_RETURN_NO_SUCH_DICT_NAME)
+                    {
+                        fprintf(stderr, "Weird: the A record at %d in record at %d had no address. Exiting.",
+                            (int) rr_count, (int) rec_count);
+                        return;
+                    }
+                    printf("The IPv4 address is %s", getdns_display_ip_address(this_a_record));
+                }
+                else if (*this_type == GETDNS_RRTYPE_AAAA)
+                {
+                    struct getdns_bindata * this_aaaa_record = NULL;
+                    this_ret = getdns_dict_get_bindata(this_rdata, "ipv6_address", &this_aaaa_record);
+                    if (this_ret == GETDNS_RETURN_NO_SUCH_DICT_NAME)
+                    {
+                        fprintf(stderr, "Weird: the AAAA record at %d in record at %d had no address. Exiting.",
+                            (int) rr_count, (int) rec_count);
+                        return;
+                    }
+                    printf("The IPv6 address is %s", getdns_display_ip_address(this_aaaa_record));
+                }
+            }
+        }
+    }
+    else if (this_callback_type == GETDNS_CALLBACK_CANCEL)
+        fprintf(stderr, "The callback with ID %"PRIu64" was cancelled. Exiting.", this_transaction_id);
+    else
+        fprintf(stderr, "The callback got a callback_type of %d. Exiting.", this_callback_type);
+}
+
+int main()
+{
+    /* Create the DNS context for this call */
+    struct getdns_context_t *this_context = NULL;
+    getdns_return_t context_create_return = getdns_context_create(&this_context, true);
+    if (context_create_return != GETDNS_RETURN_GOOD)
+    {
+        fprintf(stderr, "Trying to create the context failed: %d", context_create_return);
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    /* Create an event base and put it in the context using the unknown function name */
+    struct event_base *this_event_base;
+    this_event_base = event_base_new();
+    if (this_event_base == NULL)
+    {
+        fprintf(stderr, "Trying to create the event base failed.");
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    (void)getdns_extension_set_libevent_base(this_context, this_event_base);
+    /* Set up the getdns call */
+    const char * this_name  = "www.example.com";
+    char* this_userarg = "somestring"; // Could add things here to help identify this call
+    getdns_transaction_t this_transaction_id = 0;
+
+    /* Make the call */
+    getdns_return_t dns_request_return = getdns_address(this_context, this_name,
+        NULL, this_userarg, &this_transaction_id, this_callbackfn);
+    if (dns_request_return == GETDNS_RETURN_BAD_DOMAIN_NAME)
+    {
+        fprintf(stderr, "A bad domain name was used: %s. Exiting.", this_name);
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    else
+    {
+        /* Call the event loop */
+        int dispatch_return = event_base_dispatch(this_event_base);
+        UNUSED_PARAM(dispatch_return);
+        // TODO: check the return value above
+    }
+    /* Clean up */
+    getdns_context_destroy(this_context);
+    /* Assuming we get here, leave gracefully */
+    exit(EXIT_SUCCESS);
+}
+
+ + + +

6.3 Get Addresses for a Domain Name And Their Associated DNSSEC Validation Status

+ +

This example shows how to check for secure DNSSEC results using the +dnssec_return_status extension. In the innermost loop of the +callback function, add a check for the DNSSEC status. It shows how to add two +extensions to the extensions argument of the call.

+ +
+struct getdns_dict * this_extensions = getdns_dict_create();
+this_ret = getdns_dict_set_int(this_extensions, "return_both_v4_and_v6", GETDNS_EXTENSION_TRUE);
+this_ret = getdns_dict_set_int(this_extensions, "dnssec_return_status", GETDNS_EXTENSION_TRUE);
+. . .
+if (*this_type == GETDNS_RRTYPE_A)
+{
+    uint32_t * this_dnssec_status;
+    this_ret = getdns_dict_get_int(this_rdata, "dnssec_status", this_dnssec_status);
+    if (&this_dnssec_status != GETDNS_DNSSEC_SECURE)
+    {
+        // Log the DNSSEC status somewhere
+    }
+    else
+    {
+        // Deal with the record however you were going to
+    }
+}
+. . .
+
+ +

You can put the DNSSEC status check outside the check for the particular type of record you care about, but +you will then get log messages for bad status on records you might not care about as well.

+ +

6.4 Using the API Synchronously with getdns_sync_request()

+ +

This example is the same as the earlier examples, but uses getdns_general_sync() +and thus does not use the async code. Note that the processing of the answers is essentially the same +as it is for the synchronous example, it is just done in main().

+ +
#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getdns_core_only.h>
+
+int main()
+{
+    getdns_return_t this_ret;  /* Holder for all function returns */
+    /* Create the DNS context for this call */
+    struct getdns_context_t *this_context = NULL;
+    getdns_return_t context_create_return = getdns_context_create(&this_context, true);
+    if (context_create_return != GETDNS_RETURN_GOOD)
+    {
+        fprintf(stderr, "Trying to create the context failed: %d", context_create_return);
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    /* Set up the getdns_sync_request call */
+    const char * this_name  = "www.example.com";
+    uint8_t this_request_type = GETDNS_RRTYPE_A;
+    /* Get the A and AAAA records */
+    struct getdns_dict * this_extensions = getdns_dict_create();
+    this_ret = getdns_dict_set_int(this_extensions, "return_both_v4_and_v6", GETDNS_EXTENSION_TRUE);
+    if (this_ret != GETDNS_RETURN_GOOD)
+    {
+        fprintf(stderr, "Trying to set an extension do both IPv4 and IPv6 failed: %d", this_ret);
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    uint32_t this_response_length;
+    struct getdns_dict * this_response = NULL;
+
+    /* Make the call */
+    getdns_return_t dns_request_return = getdns_general_sync(this_context, this_name, this_request_type,
+        this_extensions, &this_response_length, this_response);
+    if (dns_request_return == GETDNS_RETURN_BAD_DOMAIN_NAME)
+    {
+        fprintf(stderr, "A bad domain name was used: %s. Exiting.", this_name);
+        return(GETDNS_RETURN_GENERIC_ERROR);
+    }
+    else
+    {
+        /* Be sure the search returned something */
+        uint32_t * this_error = NULL;
+        this_ret = getdns_dict_get_int(this_response, "status", this_error);  // Ignore any error
+        if (*this_error != GETDNS_RESPSTATUS_GOOD)  // If the search didn't return "good"
+        {
+            fprintf(stderr, "The search had no results, and a return value of %d. Exiting.", *this_error);
+            return(GETDNS_RETURN_GENERIC_ERROR);
+        }
+        struct getdns_list * just_the_addresses_ptr;
+        this_ret = getdns_dict_get_list(this_response, "just_address_answers", &just_the_addresses_ptr);  // Ignore any error
+        size_t * num_addresses_ptr = NULL;
+        this_ret = getdns_list_get_length(just_the_addresses_ptr, num_addresses_ptr);  // Ignore any error
+        /* Go through each record */
+        for ( size_t rec_count = 0; rec_count <= *num_addresses_ptr; ++rec_count )
+        {
+            struct getdns_dict * this_address;
+            this_ret = getdns_list_get_dict(just_the_addresses_ptr, rec_count, &this_address);  // Ignore any error
+            /* Just print the address */
+            struct getdns_bindata * this_address_data;
+            this_ret = getdns_dict_get_bindata(this_address, "address_data", &this_address_data); // Ignore any error
+            printf("The address is %s", getdns_display_ip_address(this_address_data));
+        }
+    }
+    /* Clean up */
+    getdns_context_destroy(this_context);
+    getdns_free_sync_request_memory(this_response); 
+    /* Assuming we get here, leave gracefully */
+    exit(EXIT_SUCCESS);
+}
+
+ + + +

7. More Helper Functions

+ +

The following two functions convert individual labels of IDNs between their Unicode +encoding and their ASCII encoding. They follow the rules for IDNA 2008 described in +RFC 5890-5892.

+
char * +getdns_convert_ulabel_to_alabel( + char *ulabel +); +
+
char * +getdns_convert_alabel_to_ulabel( + char *alabel +); +
+ +

If an application wants the API do perform DNSSEC validation without using the extensions, it +can use the getdns_validate_dnssec() helper function.

+
getdns_return_t +getdns_validate_dnssec( + struct getdns_bindata *record_to_validate, + struct getdns_list *bundle_of_support_records, + struct getdns_list *trust_anchor_rdatas +); +
+

The record_to_validate is the resource record being validated. The API +will use the resource records in bundle_of_support_records and the RDATAs in the +trust_ancor_rdatas as trust anchors. The function returns one of +GETDNS_DNSSEC_SECURE, GETDNS_DNSSEC_BOGUS, +GETDNS_DNSSEC_INDETERMINATE, or GETDNS_DNSSEC_INSECURE.

+ +

There are two functions that help process data:

+ +
+char * +getdns_pretty_print_dict( + struct getdns_dict *some_dict +); +
+

This returns a string that is the nicely-formatted version +of the dict and all of the named elements in it.

+ +
+char * +getdns_display_ip_address( + struct getdns_bindata *bindata_of_ipv4_or_ipv6_address +); +
+

This returns a string that is the nicely-formatted version +of the IPv4 or IPv6 address in it. The API determines they type of address +by the length given in the bindata.

+ +

8. DNS Contexts

+ +

Many calls in the DNS API require a DNS context. A DNS +context contains the information that the API needs in order to process DNS calls, such as the +locations of upstream DNS servers, DNSSEC trust anchors, and so on. The internal structure of the +DNS context is opaque, and might be different on each OS. When a context is passed to any function, +it must be an allocated context; the context must not be NULL.

+ +

A typical application using this API doesn't need to know anything about contexts. Basically, +the application creates a default context, uses it in the functions that require a context, and +then deallocates it when done. Context manipulation is available for more DNS-aware programs, +but is unlikely to be of interest to applications that just want the results of lookups for +A, AAAA, SRV, and PTR records.

+ +

It is expected that contexts in implementations of the API will not necessarily be thread-safe, +but they will not be thread-hostile. A context should not be used by multiple threads: create a new +context for use on a different thread. It is just fine for an application to have many contexts, +and some DNS-heavy applications will certainly want to have many even if the application uses +a single thread.

+ +

See above for the method for creating and destroying +contexts. When the context is used in the API for the first time and set_from_os is +true, the API starts replacing some of the values with values from the OS, such as +those that would be found in res_query(3), /etc/resolv.conf, and so on, then proceeds with the new +function. Some advanced users will not want the API to change the values to the OS's defaults; if +set_from_os is false, the API will not do any updates to the initial +values based on changes in the OS. For example, this might be useful if the API is acting +as a stub resolver that is using a specific upstream recursive resolver chosen by the +application, not the one that might come back from DHCP.

+ +

8.1 Updating the Context Automatically

+ +

The context returned by getdns_context_create() is updated by the API by default, +such as when changes are made to /etc/resolv.conf. When there is a change, the callback function +that is set in getdns_context_set_context_update_callback() (described below) is +called.

+ +

Many of the defaults for a context come from the operating system under which the API is running. +In specific, it is important that the implementation should try to replicate as best as possible the +logic of a local getaddrinfo() when creating a new context. This includes making +lookups in WINS for NetBIOS, mDNS lookups, nis names, and any other name lookup that +getaddrinfo() normally does automatically. The API should look at nsswitch, the Windows +resolver, and so on.

+ +

In the function definitions below, the choice listed in bold is the one used +for the API default context.

+ +

8.2 Updating the Context Manually

+ +

Setting specific values in a context are done with value-specific +functions shown here. The setting functions all return either GETDNS_RETURN_GOOD for +success, GETDNS_RETURN_BAD_CONTEXT for trying to set a type with a value that +is not allowed, or GETDNS_RETURN_CONTEXT_UPDATE_FAIL for a failure to update the context.

+ +

An application can be notified when the context is changed.

+ +
+getdns_return_t +getdns_context_set_context_update_callback( + getdns_context_t context, + void (*value)(getdns_context_t context, uint16_t changed_item) +);
+

The value is a pointer to the callback function that will be +called when any context is changed. Such changes might be from automatic +changes from the API (such as changes to /etc/resolv.conf), or might be from any of the +API functions in this section being called. The second argument to the callback function +specifies which of the context changed; the context codes are listed +later in this document.

+ +

8.3 Contexts for Basic Resolution

+ +
+getdns_return_t +getdns_context_set_resolution_type( + getdns_context_t context, + uint16_t value +);
+

Specifies whether DNS queries are performed with nonrecurive lookups or +as a stub resolver. The value is GETDNS_CONTEXT_RECURSING or +GETDNS_CONTEXT_STUB.

+ +

All implementations of this API can act as recursive resolvers, and that must be the +default mode of the default context. +Some implementations of this API are expected to also be able to act as stub resolvers. +If an +implementation of this API is only able to act as a recursive resolver, a call to +getdns_context_set_resolution_type(somecontext, GETDNS_CONTEXT_STUB) will +return GETDNS_RETURN_CONTEXT_UPDATE_FAIL.

+ +
+getdns_return_t +getdns_context_set_namespaces( + getdns_context_t context, + size_t namespace_count, + uint16_t *namespaces +);
+

The namespaces array contains an ordered list +of namespaces that will be queried. +Important: this context setting is ignored for the getdns_general and +getdns_general_sync functions; it is used for the other funtions. +The values +are GETDNS_CONTEXT_NAMESPACE_DNS, +GETDNS_CONTEXT_NAMESPACE_LOCALNAMES, +GETDNS_CONTEXT_NAMESPACE_NETBIOS, +GETDNS_CONTEXT_NAMESPACE_MDNS, and +GETDNS_CONTEXT_NAMESPACE_NIS. When a normal lookup is done, +the API does the lookups in the order given and stops when it gets the +first result; a different method with the same result would be to run +the queries in parallel and return when it gets the first result. +Because lookups might be done over different mechanisms because of the +different namespaces, there can be information leakage that is similar +to that seen with getaddrinfo(). The +default is determined by the OS.

+ +
+getdns_return_t +getdns_context_set_dns_transport( + getdns_context_t context, + uint16_t value +);
+

Specifies what transport is used for DNS lookups. +The value is +GETDNS_CONTEXT_UDP_FIRST_AND_FALL_BACK_TO_TCP, +GETDNS_CONTEXT_UDP_ONLY, +GETDNS_CONTEXT_TCP_ONLY, or +GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN.

+ +
+getdns_return_t +getdns_context_set_limit_outstanding_queries( + getdns_context_t context, + uint16_t limit +);
+

Specifies limit the number of outstanding DNS queries. +The API will block itself from sending more queries if it is about to exceed +this value, and instead keep those queries in an internal queue. +The a value of 0 indicates that +the number of outstanding DNS queries is unlimited.

+ +
+getdns_return_t +getdns_context_set_timeout( + getdns_context_t context, + uint16_t timeout +);
+

Specifies number of seconds the API will wait for request to return. +The default is not specified.

+ +

8.4 Context for Recursive Resolvers

+ +
+getdns_return_t +getdns_context_set_follow_redirects( + getdns_context_t context, + uint16_t value +);
+

Specifies whether or not DNS queries follow redirects. +The value is GETDNS_CONTEXT_FOLLOW_REDIRECTS for normal +following of redirects though CNAME and DNAME; or +GETDNS_CONTEXT_DO_NOT_FOLLOW_REDIRECTS to cause any lookups that would have gone +through CNAME and DNAME to return the CNAME or DNAME, not the eventual target.

+ +
+getdns_return_t +getdns_context_set_dns_root_servers( + getdns_context_t context, + struct getdns_list *addresses +);
+

The list contains dicts that are addresses to be used for looking up top-level +domains; the default is the list of "normal" IANA root servers. Each dict in the list +contains at least two names: address_type (whose value is a bindata; it is currently +either "IPv4" or "IPv6") and address_data (whose value is a bindata).

+ +

8.5 Context for Local Naming

+ +
+getdns_return_t +getdns_context_set_append_name( + getdns_context_t context, + uint16_t value +);
+

Specifies whether to append a suffix to the query string +before the API starts resolving a name. +The value is +GETDNS_CONTEXT_APPEND_NAME_ALWAYS, +GETDNS_CONTEXT_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE, +GETDNS_CONTEXT_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE, +or GETDNS_CONTEXT_DO_NOT_APPEND_NAMES. This controls +whether or not to append the suffix given by getdns_context_set_suffix

+ +
+getdns_return_t +getdns_context_set_suffix( + getdns_context_t context, + struct getdns_list *value +);
+

The value is a list of bindatas that are strings that are +to be appended based on getdns_context_set_append_name; the default is an empty list. The values here follow the rules in section 2.1 of RFC 4343 +to allow non-ASCII octets and special characters in labels.

+ +

8.6 Context for DNSSEC

+ +

These context settings affect queries that have extensions that specify the use of DNSSEC.

+ +

Applications that need to specify the DNSSEC trust anchors can use:

+
+getdns_return_t +getdns_context_set_dnssec_trust_anchors( + getdns_context_t context, + struct getdns_list *value +);
+

The value is a list of bindatas that are the DNSSEC trust anchors. The default +is the trust anchors from the IANA root. The trust anchors +are expressed as RDATAs from DNSKEY resource records.

+ +

In the rare case that an application needs to set the DNSSEC skew, it can:

+
+getdns_return_t +getdns_context_set_dnssec_allowed_skew( + getdns_context_t context, + uint16_t value +);
+

The value is the number of seconds of skew that is allowed in either direction when +checking an RRSIG's Expiration and Inception fields. The default +is 0.

+ +

8.7 Context Specific to Stub Resolvers

+ +

An application can change the quering mechanism of a context to be to act as a stub +resolver. Such an application might first get the default information to make this change +from the operating system, probably through DHCP.

+ +

Note that if a context is changed to being a stub resolver, this automatically prevents the application +from using the extenstions for DNSSEC. An application that wants to both do DNSSEC and stub resolution +must do its own DNSSEC processing, possibly with the getdns_validate_dnssec() function.

+ +
+getdns_return_t +getdns_context_set_stub_resolution( + getdns_context_t context, + struct getdns_list *upstream_list +);
+

The list of dicts define where a stub resolver will send queries. Each dict contains +at least two names: address_type (whose value is a bindata; it is currently either +"IPv4" or "IPv6") and address_data (whose value is a bindata). It might also contain +port to specify which port to use to contact these DNS servers; the default is 53. If +the stub and a recursive resolver both support TSIG (RFC 2845), the upstream_list entry +can also contain tsig_algorithm (a bindata) that is the name of the TSIG hash +algorithm, and tsig_secret (a bindata) that is the TSIG key.

+ +

8.8 Context for EDNS

+ +

These context settings affect queries that have extensions that specify the use of OPT resource records. +These come from RFC 2671.

+ +
+getdns_return_t +getdns_context_set_edns_maximum_udp_payload_size( + getdns_context_t context, + uint16_t value +);
+

The value is between 512 and 65535; the default +is 512.

+ +
+getdns_return_t +getdns_context_set_edns_extended_rcode( + getdns_context_t context, + uint8_t value +);
+

The value is between 0 and 256; the default +is 0.

+ +
+getdns_return_t +getdns_context_set_edns_version( + getdns_context_t context, + uint8_t value +);
+

The value is between 0 and 256; the default +is 0.

+ +
+getdns_return_t +getdns_context_set_edns_do_bit( + getdns_context_t context, + uint8_t value +);
+

The value is between 0 and 1; the default +is 0.

+ +

8.9 Context Use of C Functions

+ +
+getdns_return_t +getdns_context_set_memory_allocator( + getdns_context_t context, + void (*value)(size_t somesize) +);
+

The value is a function pointer to the memory allocator; the +default is the malloc function.

+ +
+getdns_return_t +getdns_context_set_memory_deallocator( + getdns_context_t context, + void (*value)(void*) +);
+

The value is a function pointer to the memory deallocator; the +default is the free function.

+ +
+getdns_return_t +getdns_context_set_memory_reallocator( + getdns_context_t context, + void (*value)(void*) +);
+

The value is a function pointer to the memory reallocator; the +default is the realloc function.

+ +

8.10 Context Codes

+ +

The context codes for getdns_context_set_context_update_callback() are:

+ +

GETDNS_CONTEXT_CODE_NAMESPACES

+

Change related to getdns_context_set_namespaces

+

GETDNS_CONTEXT_CODE_RESOLUTION_TYPE

+

Change related to getdns_context_set_resolution_type

+

GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS

+

Change related to getdns_context_set_follow_redirects

+

GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS

+

Change related to getdns_context_set_upstream_recursive_servers

+

GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS

+

Change related to getdns_context_set_dns_root_servers

+

GETDNS_CONTEXT_CODE_USE_UDP_TCP

+

Change related to getdns_context_set_use_udp_tcp

+

GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES

+

Change related to getdns_context_set_limit_outstanding_queries

+

GETDNS_CONTEXT_CODE_APPEND_NAME

+

Change related to getdns_context_set_append_name

+

GETDNS_CONTEXT_CODE_SUFFIX

+

Change related to getdns_context_set_suffix

+

GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS

+

Change related to getdns_context_set_dnssec_trust_anchors

+

GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE

+

Change related to getdns_context_set_edns_maximum_udp_payload_size

+

GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE

+

Change related to getdns_context_set_edns_extended_rcode

+

GETDNS_CONTEXT_CODE_EDNS_VERSION

+

Change related to getdns_context_set_edns_version

+

GETDNS_CONTEXT_CODE_EDNS_DO_BIT

+

Change related to getdns_context_set_edns_do_bit

+

GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW

+

Change related to getdns_context_set_dnssec_allowed_skew

+

GETDNS_CONTEXT_CODE_MEMORY_ALLOCATOR

+

Change related to getdns_context_set_memory_allocator

+

GETDNS_CONTEXT_CODE_MEMORY_DEALLOCATOR

+

Change related to getdns_context_set_memory_deallocator

+

GETDNS_CONTEXT_CODE_MEMORY_REALLOCATOR

+

Change related to getdns_context_set_memory_reallocator

+ + +

9. The Generated Files

+ +

There is a tarball that includes the .h files, +the examples, and so on. The examples all make, even though there is no API implementation, based +on a pseudo-implementation in the tarball; see make-examples-PLATFORM.sh. Note that this currently builds fine +on the Macintosh and Ubuntu; help is definitely appreciated on making the build process +work on more platforms if it fails there.

+ +

10. Commentary

+ +

The following description of the API may be of value to those who might implement the design, and +those who are using an implementation of the design.

+ +

10.1 API Design Considerations

+ +

The genesis of this DNS API design was seeing other DNS API designs flounder. There are other +DNS APIs already available (such as draft-hayatnagarkar-dnsext-validator-api, as well +as DNSSEC APIs in BIND and Unbound), but there has been very little uptake of them. In talking to +application developers, there was a consistent story: that they felt that the APIs were developed by and +for DNS people, not applications developers.

+ +

This API design comes from talking to a small handful of applications developers about what they +would want to see in a modern DNS API. Now that the API is public, it would be great to hear from many +more application developers about whether it would meet their needs if it was implemented. My goal +is to create a design that is a natural follow-on to getaddrinfo() that has all the +capabilities that most application developers might want now or in the next few years: access to all +types of DNS records (including those which are yet to be defined), full DNSSEC awareness, IDN +handling, and parity for IPv4 and IPv6 addresses.

+ +

Note that this is just a design for a new API: there is no implementation of the design yet, but +at least one is being worked on. The process of designing the API without implementing it at the +same time has the huge advantage that major design changes could be made without any worry about +"but we already coded it the other way". In the early revisions of this document, many fundamental +design choices changed over and over, and even bike-shedding-like changes were allowed because they +didn't involve any programming effort.

+ +

This work was done independently, not through the IETF because the IETF generally doesn't take on +API work, and has explicitly avoided DNS API work in the past.

+ +

This API design has a Creative Commons license so that it can be +used widely by potential API implementers. This also allows other people who want to fork the design +to do so cleanly. Of course, any implementation of this API can choose whatever kind of license the +API implementer wishes, but it would be fabulous if one or more such implementations had Creative +Commons or BSD-ish licenses.

+ +

The API relies heavily on C macros and hopefully has no magic numbers.

+ +

10.2 API Implementation Considerations

+ +

All implementations of this API must act as recursive resolvers, and some might choose not to be +able to act as stub resolvers. Note that all implementations of this API must be DNSSEC validators.

+ +

Because there are many C event libraries available, and they have different calling routines, +it is the implementation of an API that determines which event library is used. This is certainly +not optimal for C programmers, but they appear to have gotten used to is so far. All implementations +of this API must support synchronous calls with getdns_sync_request().

+ +

Versions are differentiated by version strings instead of version numbers. The version string for +this API is "getdns April 2013". Each implementation is free to set the implementation string as it +feels fit.

+ +

The API's .h file contains a macro called GETDNS_COMPILATION_COMMENT. This can be useful +to an application which will use the API because it can check the string without calling any +functions. Each time the API implementation is compiled, this string should be updated with unique +information about the implementation build.

+ +

The implementation of both the async and sync getdns functions will +copy all the values of the parameters into local memory, in case the application changes or +deallocates them.

+ +
+ +

Creative
+Commons License
This work is licensed under a Creative Commons Attribution 3.0 +Unported License.

+ + diff --git a/spec/make-examples-linux.sh b/spec/make-examples-linux.sh new file mode 100755 index 00000000..ca56726d --- /dev/null +++ b/spec/make-examples-linux.sh @@ -0,0 +1,22 @@ +rm -rf *.o *.dylib +gcc -std=c89 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c getdns_core_only.c +gcc -std=c89 -shared -fPIC -levent_core -o libgetdns.so getdns_core_only.o +gcc -std=c89 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-all-functions.c +gcc -std=c89 -fPIC -L./ example-all-functions.o -levent_core -lgetdns -o example-all-functions +gcc -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-simple-answers.c +gcc -std=c99 -fPIC -L./ example-simple-answers.o -levent_core -lgetdns -o example-simple-answers +gcc -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-tree.c +gcc -std=c99 -fPIC -L./ example-tree.o -levent_core -lgetdns -o example-tree +gcc -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-synchronous.c +gcc -std=c99 -fPIC -L./ example-synchronous.o -levent_core -lgetdns -o example-synchronous +rm -rf *.o *.dylib +clang -std=c89 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c getdns_core_only.c +clang -std=c89 -shared -fPIC -levent_core -o libgetdns.so getdns_core_only.o +clang -std=c89 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-all-functions.c +clang -std=c89 -fPIC -L./ example-all-functions.o -levent_core -lgetdns -o example-all-functions +clang -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-simple-answers.c +clang -std=c99 -fPIC -L./ example-simple-answers.o -levent_core -lgetdns -o example-simple-answers +clang -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-tree.c +clang -std=c99 -fPIC -L./ example-tree.o -levent_core -lgetdns -o example-tree +clang -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-synchronous.c +clang -std=c99 -fPIC -L./ example-synchronous.o -levent_core -lgetdns -o example-synchronous diff --git a/spec/make-examples-mac.sh b/spec/make-examples-mac.sh new file mode 100755 index 00000000..02c91eb0 --- /dev/null +++ b/spec/make-examples-mac.sh @@ -0,0 +1,22 @@ +rm -rf *.o *.dylib +gcc -std=c89 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c getdns_core_only.c +gcc -std=c89 -dynamiclib -fPIC -levent_core -o libgetdns.dylib getdns_core_only.o +gcc -std=c89 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-all-functions.c +gcc -std=c89 -fPIC -L./ example-all-functions.o -levent_core -lgetdns -o example-all-functions +gcc -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-simple-answers.c +gcc -std=c99 -fPIC -L./ example-simple-answers.o -levent_core -lgetdns -o example-simple-answers +gcc -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-tree.c +gcc -std=c99 -fPIC -L./ example-tree.o -levent_core -lgetdns -o example-tree +gcc -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-synchronous.c +gcc -std=c99 -fPIC -L./ example-synchronous.o -levent_core -lgetdns -o example-synchronous +rm -rf *.o *.dylib +clang -std=c89 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c getdns_core_only.c +clang -std=c89 -dynamiclib -fPIC -levent_core -o libgetdns.dylib getdns_core_only.o +clang -std=c89 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-all-functions.c +clang -std=c89 -fPIC -L./ example-all-functions.o -levent_core -lgetdns -o example-all-functions +clang -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-simple-answers.c +clang -std=c99 -fPIC -L./ example-simple-answers.o -levent_core -lgetdns -o example-simple-answers +clang -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-tree.c +clang -std=c99 -fPIC -L./ example-tree.o -levent_core -lgetdns -o example-tree +clang -std=c99 -c -fPIC -pedantic -g -I./ -Werror -Wall -Wextra -c example-synchronous.c +clang -std=c99 -fPIC -L./ example-synchronous.o -levent_core -lgetdns -o example-synchronous diff --git a/src/dict.c b/src/dict.c index 6d7a89ea..9e51d1c4 100644 --- a/src/dict.c +++ b/src/dict.c @@ -7,26 +7,32 @@ * Interfaces originally taken from the getdns API description pseudo implementation. * */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. + +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include @@ -677,4 +683,4 @@ getdns_pretty_print_dict(struct getdns_dict *dict) return ret; } /* getdns_pretty_print_dict */ -/* getdns_dict.c */ +/* dict.c */ diff --git a/src/dict.h b/src/dict.h index d184cba2..91ca0180 100644 --- a/src/dict.h +++ b/src/dict.h @@ -1,32 +1,37 @@ /** * - * /brief getdns contect management functions + * /brief getdns dict data type management functions * - * This is the meat of the API - * Originally taken from the getdns API description pseudo implementation. * */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. + +/* + * Copyright (c) 2013, NLNet Labs, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef _GETDNS_DICT_H_ #define _GETDNS_DICT_H_ @@ -63,3 +68,4 @@ struct getdns_dict { #endif +/* dict.h */ diff --git a/src/general.c b/src/general.c index 348436e0..060974ee 100644 --- a/src/general.c +++ b/src/general.c @@ -1,31 +1,37 @@ /** * - * /brief getdns core functions - * - * This is the meat of the API - * Originally taken from the getdns API description pseudo implementation. + * /brief getdns_general and related support functions * + * The getdns_general function is called by most of the other public entry + * points to the library. Private support functions are also included in this + * file where they are directly logically related to the getdns_general implementation. */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. + +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include @@ -231,7 +237,8 @@ getdns_general_ub(struct ub_ctx* unbound, struct getdns_dict *extensions, void *userarg, getdns_transaction_t *transaction_id, - getdns_callback_t callbackfn) { + getdns_callback_t callbackfn) +{ /* timeout */ struct timeval tv; getdns_return_t gr; @@ -283,9 +290,9 @@ getdns_general_ub(struct ub_ctx* unbound, return GETDNS_RETURN_GENERIC_ERROR; } return GETDNS_RETURN_GOOD; -} +} /* getdns_general_ub */ -/* +/** * getdns_general */ getdns_return_t @@ -295,7 +302,9 @@ getdns_general_ub(struct ub_ctx* unbound, struct getdns_dict *extensions, void *userarg, getdns_transaction_t *transaction_id, - getdns_callback_t callback) { + getdns_callback_t callback) +{ + int extcheck = GETDNS_RETURN_GOOD; if (!context || !context->event_base_async || callback == NULL) { @@ -305,6 +314,10 @@ getdns_general_ub(struct ub_ctx* unbound, return GETDNS_RETURN_BAD_CONTEXT; } + extcheck = validate_extensions(extensions); + if(extcheck != GETDNS_RETURN_GOOD) + return extcheck; + return getdns_general_ub(context->unbound_async, context->event_base_async, context, @@ -317,7 +330,6 @@ getdns_general_ub(struct ub_ctx* unbound, } /* getdns_general */ - /* * getdns_address * diff --git a/src/general.h b/src/general.h index 658131eb..7b4c98e8 100644 --- a/src/general.h +++ b/src/general.h @@ -6,27 +6,33 @@ * Originally taken from the getdns API description pseudo implementation. * */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef _GETDNS_GENERAL_H_ #define _GETDNS_GENERAL_H_ diff --git a/src/getdns/README b/src/getdns/README new file mode 100644 index 00000000..064d654c --- /dev/null +++ b/src/getdns/README @@ -0,0 +1 @@ +This directory contains the getdns API description that serves as the target of this implementation. diff --git a/src/getdns/getdns.h b/src/getdns/getdns.h index 6ec786c3..727741cb 100644 --- a/src/getdns/getdns.h +++ b/src/getdns/getdns.h @@ -1,30 +1,36 @@ /** * \file - * \brief Public interfaces to getdns - include this in your application to use getdns API. + * \brief Public interfaces to getdns, include in your application to use getdns API. * * This source was taken from the original pseudo-implementation by * Paul Hoffman. */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. + +/* + * Copyright (c) 2013, NLNet Labs, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GETDNS_H @@ -64,7 +70,7 @@ struct event_base; #define GETDNS_RETURN_NO_SUCH_EXTENSION 307 #define GETDNS_RETURN_NO_SUCH_EXTENSION_TEXT A name in the extensions dict is not a valid extension. #define GETDNS_RETURN_EXTENSION_MISFORMAT 308 -#define GETDNS_RETURN_EXTENSION_MISFORMAT_TEXT One or more of the extensions is has a bad format. +#define GETDNS_RETURN_EXTENSION_MISFORMAT_TEXT One or more of the extensions has a bad format. #define GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED 309 #define GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED_TEXT A query was made with a context that is using stub resolution and a DNSSEC extension specified. @@ -278,12 +284,6 @@ struct event_base; #define GETDNS_STR_KEY_QTYPE "qtype" #define GETDNS_STR_KEY_QCLASS "qclass" #define GETDNS_STR_KEY_QNAME "qname" - - - - - - /** @} */ @@ -372,6 +372,9 @@ struct event_base; typedef struct getdns_context_t *getdns_context_t; typedef uint16_t getdns_return_t; typedef uint64_t getdns_transaction_t; +/** + * used to check data types within complex types (dict, list) + */ typedef enum getdns_data_type { t_dict, t_list, t_int, t_bindata, t_invalid } getdns_data_type; diff --git a/src/list.c b/src/list.c index d3865cd9..73036143 100644 --- a/src/list.c +++ b/src/list.c @@ -6,26 +6,32 @@ * Originally taken from the getdns API description pseudo implementation. * */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. + +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include diff --git a/src/request-internal.c b/src/request-internal.c index 88e58c3b..2893b2d5 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -6,26 +6,31 @@ * Originally taken from the getdns API description pseudo implementation. * */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "types-internal.h" @@ -108,7 +113,8 @@ void dns_req_free(getdns_dns_req* req) { } /* create a new dns req to be submitted */ -getdns_dns_req* dns_req_new(getdns_context_t context, +getdns_dns_req* +dns_req_new(getdns_context_t context, struct ub_ctx* unbound, const char* name, uint16_t request_type, diff --git a/src/sync.c b/src/sync.c index cc5b00d9..e3f75621 100644 --- a/src/sync.c +++ b/src/sync.c @@ -5,26 +5,32 @@ * Originally taken from the getdns API description pseudo implementation. * */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. + +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include @@ -59,12 +65,16 @@ getdns_general_sync( { getdns_return_t response_status; - response_status = getdns_general_ub(context->unbound_sync, context->event_base_sync, - context, name, request_type, extensions, - (void *)response, NULL, sync_callback_func); - - event_base_dispatch(context->event_base_sync); + response_status = validate_extensions(extensions); + if (response_status == GETDNS_RETURN_GOOD) { + response_status = getdns_general_ub(context->unbound_sync, + context->event_base_sync, + context, name, request_type, + extensions, (void *)response, + NULL, sync_callback_func); + event_base_dispatch(context->event_base_sync); + } return response_status; } diff --git a/src/types-internal.h b/src/types-internal.h index 929d8b77..38513bc8 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -1,31 +1,36 @@ /** * - * /brief getdns contect management functions - * - * This is the meat of the API - * Originally taken from the getdns API description pseudo implementation. + * /brief type declarations private to the getdns library * + * These type declarations are not meant to be used by applications calling + * the public library functions. */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. + +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TYPES_INTERNAL_H_ @@ -48,6 +53,14 @@ typedef enum network_req_state_enum { NET_REQ_CANCELED } network_req_state; +/** + * structure used by validate_extensions() to check extension formats + */ +typedef struct getdns_extension_format { + char *extstring; + getdns_data_type exttype; +} getdns_extension_format; + /** * Request data for unbound **/ @@ -72,7 +85,8 @@ typedef struct getdns_network_req { struct getdns_network_req* next; } getdns_network_req; -/* dns request - manages a number of network requests and +/** + * dns request - manages a number of network requests and * the initial data passed to getdns_general */ typedef struct getdns_dns_req { @@ -138,3 +152,5 @@ getdns_dns_req* dns_req_new(getdns_context_t context, void dns_req_free(getdns_dns_req* req); #endif + +/* types-internal.h */ diff --git a/src/util-internal.c b/src/util-internal.c index 08e862c8..d264c99a 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -1,36 +1,64 @@ /** * - * /brief getdns contect management functions + * /file + * /brief private library routines * - * This is the meat of the API - * Originally taken from the getdns API description pseudo implementation. + * These routines are not intended to be used by applications calling into + * the library. * */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "getdns/getdns.h" +#include +#include "dict.h" #include "util-internal.h" #include "types-internal.h" +/** + * this is a comprehensive list of extensions and their data types + * used by validate_extensions() + * The list has to be in sorted order for bsearch lookup in function + * validate_extensions. + */ +getdns_extension_format extformats[] = { + {"add_opt_parameters", t_dict}, + {"add_warning_for_bad_dns", t_int}, + {"dnssec_return_only_secure", t_int}, + {"dnssec_return_status", t_int}, + {"dnssec_return_supporting_responses", t_int}, + {"return_api_information", t_int}, + {"return_both_v4_and_v6", t_int}, + {"return_call_debugging", t_int}, + {"specify_class", t_int}, +}; + getdns_return_t getdns_dict_util_set_string(getdns_dict* dict, char* name, const char* value) { /* account for the null term */ @@ -464,11 +492,12 @@ getdns_dict *create_getdns_response(struct getdns_dns_req* completed_request) { return result; } -/* - * reverse an IP address for PTR lookup +/** + * reverse an IP address for PTR lookup + * @param addr_str dotted notation of IP address to reverse + * @return NULL on allocation failure + * @return reversed string on success, caller must free storage via call to free() */ - - char * reverse_address(char *addr_str) { @@ -492,3 +521,35 @@ reverse_address(char *addr_str) ldns_rdf_deep_free(rev_rdf); return rev_str; } + +static int extformatcmp(const void *a, const void *b) +{ + return strcmp(((getdns_extension_format *)a)->extstring, + ((getdns_extension_format *)b)->extstring); +} + +/*---------------------------------------- validate_extensions */ +getdns_return_t +validate_extensions(getdns_dict *extensions) +{ + struct getdns_dict_item *item; + getdns_extension_format *extformat; + + if(extensions) + LDNS_RBTREE_FOR(item, struct getdns_dict_item *, &(extensions->root)) { + getdns_extension_format key; + key.extstring = (char *)item->node.key; + extformat = bsearch(&key, extformats, + sizeof(extformats) / + sizeof(getdns_extension_format), + sizeof(getdns_extension_format), extformatcmp); + if (! extformat) + return GETDNS_RETURN_NO_SUCH_EXTENSION; + + if (item->dtype != extformat->exttype) + return GETDNS_RETURN_EXTENSION_MISFORMAT; + } + return GETDNS_RETURN_GOOD; +} /* validate_extensions */ + +/* util-internal.c */ diff --git a/src/util-internal.h b/src/util-internal.h index 94b95bc3..ef0f89f9 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -6,26 +6,32 @@ * Originally taken from the getdns API description pseudo implementation. * */ -/* The MIT License (MIT) - * Copyright (c) 2013 Verisign, Inc. + +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* @@ -52,3 +58,15 @@ getdns_return_t getdns_dict_util_set_string(getdns_dict* dict, char* name, getdns_return_t getdns_dict_util_get_string(getdns_dict* dict, char* name, char** result); char *reverse_address(char *addr_str); + +/** + * detect unrecognized extension strings or invalid extension formats + * TODO: this could be optimized by searching a sorted list + * @param extensions dictionary of valid extension strings and values + * @return GETDNS_RETURN_GOOD if each extension string is valid and the format matches the API specification + * @return GETDNS_RETURN_NO_SUCH_EXTENSION A name in the extensions dict is not a valid extension. + * @return GETDNS_RETURN_EXTENSION_MISFORMAT One or more of the extensions has a bad format. + */ +getdns_return_t validate_extensions(getdns_dict *extensions); + +/* util-internal.h */