ldns-1.8.4/0000775000175000017500000000000014646643056012050 5ustar willemwillemldns-1.8.4/str2host.c0000664000175000017500000016373414646643036014020 0ustar willemwillem/* * str2host.c * * conversion routines from the presentation format * to the host format * * a Net::DNS like library for C * * (c) NLnet Labs, 2004-2006 * * See the file LICENSE for the license */ #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #include #include #ifdef HAVE_NETDB_H #include #endif #include #ifdef HAVE_SYS_PARAM_H #include #endif ldns_status ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr) { char *end = NULL; uint16_t *r; r = LDNS_MALLOC(uint16_t); if(!r) return LDNS_STATUS_MEM_ERR; *r = htons((uint16_t)strtol((char *)shortstr, &end, 10)); if(*end != 0) { LDNS_FREE(r); return LDNS_STATUS_INVALID_INT; } else { *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r); LDNS_FREE(r); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } } ldns_status ldns_str2rdf_time(ldns_rdf **rd, const char *time) { /* convert a time YYYYDDMMHHMMSS to wireformat */ uint32_t *r = NULL; struct tm tm; uint32_t l; char *end; /* Try to scan the time... */ r = (uint32_t *)LDNS_MALLOC(uint32_t); if(!r) return LDNS_STATUS_MEM_ERR; memset(&tm, 0, sizeof(tm)); if (strlen(time) == 14 && sscanf(time, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6 ) { tm.tm_year -= 1900; tm.tm_mon--; /* Check values */ if (tm.tm_year < 70) { goto bad_format; } if (tm.tm_mon < 0 || tm.tm_mon > 11) { goto bad_format; } if (tm.tm_mday < 1 || tm.tm_mday > 31) { goto bad_format; } if (tm.tm_hour < 0 || tm.tm_hour > 23) { goto bad_format; } if (tm.tm_min < 0 || tm.tm_min > 59) { goto bad_format; } if (tm.tm_sec < 0 || tm.tm_sec > 59) { goto bad_format; } l = htonl(ldns_mktime_from_utc(&tm)); memcpy(r, &l, sizeof(uint32_t)); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); LDNS_FREE(r); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } else { /* handle it as 32 bits timestamp */ l = htonl((uint32_t)strtol((char*)time, &end, 10)); if(*end != 0) { LDNS_FREE(r); return LDNS_STATUS_ERR; } else { memcpy(r, &l, sizeof(uint32_t)); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); LDNS_FREE(r); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } } bad_format: LDNS_FREE(r); return LDNS_STATUS_INVALID_TIME; } ldns_status ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) { uint8_t salt_length; int c; int salt_length_str; uint8_t *salt; uint8_t *data; if(rd == NULL) { return LDNS_STATUS_NULL; } salt_length_str = (int)strlen(salt_str); if (salt_length_str == 1 && salt_str[0] == '-') { salt_length_str = 0; } else if (salt_length_str % 2 != 0) { return LDNS_STATUS_INVALID_HEX; } if (salt_length_str > 512) { return LDNS_STATUS_INVALID_HEX; } salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2); if(!salt) { return LDNS_STATUS_MEM_ERR; } for (c = 0; c < salt_length_str; c += 2) { if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) { salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 + ldns_hexdigit_to_int(salt_str[c+1]); } else { LDNS_FREE(salt); return LDNS_STATUS_INVALID_HEX; } } salt_length = (uint8_t) (salt_length_str / 2); data = LDNS_XMALLOC(uint8_t, 1 + salt_length); if(!data) { LDNS_FREE(salt); return LDNS_STATUS_MEM_ERR; } data[0] = salt_length; memcpy(&data[1], salt, salt_length); *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data); LDNS_FREE(data); LDNS_FREE(salt); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_period(ldns_rdf **rd,const char *period) { uint32_t p; const char *end; /* Allocate required space... */ p = ldns_str2period(period, &end); if (*end != 0) { return LDNS_STATUS_ERR; } else { p = (uint32_t) htonl(p); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p); } return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) { char *end; uint32_t *r = NULL; uint32_t l; r = (uint32_t*)LDNS_MALLOC(uint32_t); if(!r) return LDNS_STATUS_MEM_ERR; errno = 0; /* must set to zero before call, note race condition on errno */ if(*longstr == '-') l = htonl((uint32_t)strtol((char*)longstr, &end, 10)); else l = htonl((uint32_t)strtoul((char*)longstr, &end, 10)); if(*end != 0) { LDNS_FREE(r); return LDNS_STATUS_ERR; } else { if (errno == ERANGE) { LDNS_FREE(r); return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; } memcpy(r, &l, sizeof(uint32_t)); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); LDNS_FREE(r); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } } ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) { char *end; uint8_t *r = NULL; r = LDNS_MALLOC(uint8_t); if(!r) return LDNS_STATUS_MEM_ERR; *r = (uint8_t)strtol((char*)bytestr, &end, 10); if(*end != 0) { LDNS_FREE(r); return LDNS_STATUS_ERR; } else { *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r); LDNS_FREE(r); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } } /* * Checks whether the escaped value at **s is an decimal value or * a 'normally' escaped character (and not eos) * * The string pointer at *s is increased by either 0 (on error), 1 (on * normal escapes), or 3 (on decimals) * * Returns the number of bytes read from the escaped string, or * 0 on error */ INLINE bool parse_escape(uint8_t *ch_p, const char** str_p) { uint16_t val; if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) && (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) && (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) { val = (uint16_t)(((*str_p)[0] - '0') * 100 + ((*str_p)[1] - '0') * 10 + ((*str_p)[2] - '0')); if (val > 255) { goto error; } *ch_p = (uint8_t)val; *str_p += 3; return true; } else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) { *ch_p = (uint8_t)*(*str_p)++; return true; } error: *str_p = NULL; return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */ } INLINE bool parse_char(uint8_t *ch_p, const char** str_p) { switch (**str_p) { case '\0': return false; case '\\': *str_p += 1; return parse_escape(ch_p, str_p); default: *ch_p = (uint8_t)*(*str_p)++; return true; } } /* * No special care is taken, all dots are translated into * label separators. * Could be made more efficient....we do 3 memcpy's in total... */ ldns_status ldns_str2rdf_dname(ldns_rdf **d, const char *str) { size_t len; const char *s; uint8_t *q, *pq, label_len; uint8_t buf[LDNS_MAX_DOMAINLEN + 1]; *d = NULL; len = strlen((char*)str); /* octet representation can make strings a lot longer than actual length */ if (len > LDNS_MAX_DOMAINLEN * 4) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } if (0 == len) { return LDNS_STATUS_DOMAINNAME_UNDERFLOW; } /* root label */ if (1 == len && *str == '.') { *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0"); return LDNS_STATUS_OK; } /* get on with the rest */ /* s is on the current character in the string * pq points to where the labellength is going to go * label_len keeps track of the current label's length * q builds the dname inside the buf array */ len = 0; q = buf+1; pq = buf; label_len = 0; for (s = str; *s; s++, q++) { if (q >= buf + LDNS_MAX_DOMAINLEN) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } *q = 0; switch (*s) { case '.': if (label_len > LDNS_MAX_LABELLEN) { return LDNS_STATUS_LABEL_OVERFLOW; } if (label_len == 0) { return LDNS_STATUS_EMPTY_LABEL; } len += label_len + 1; *pq = label_len; label_len = 0; pq = q; break; case '\\': /* octet value or literal char */ s += 1; if (! parse_escape(q, &s)) { return LDNS_STATUS_SYNTAX_BAD_ESCAPE; } s -= 1; label_len++; break; default: *q = (uint8_t)*s; label_len++; } } /* add root label if last char was not '.' */ if (!ldns_dname_str_absolute(str)) { if (q >= buf + LDNS_MAX_DOMAINLEN) { return LDNS_STATUS_DOMAINNAME_OVERFLOW; } if (label_len > LDNS_MAX_LABELLEN) { return LDNS_STATUS_LABEL_OVERFLOW; } if (label_len == 0) { /* label_len 0 but not . at end? */ return LDNS_STATUS_EMPTY_LABEL; } len += label_len + 1; *pq = label_len; *q = 0; } len++; *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf); return LDNS_STATUS_OK; } ldns_status ldns_str2rdf_a(ldns_rdf **rd, const char *str) { in_addr_t address; if (inet_pton(AF_INET, (char*)str, &address) != 1) { return LDNS_STATUS_INVALID_IP4; } else { *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A, sizeof(address), &address); } return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str) { uint8_t address[LDNS_IP6ADDRLEN + 1]; if (inet_pton(AF_INET6, (char*)str, address) != 1) { return LDNS_STATUS_INVALID_IP6; } else { *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address); } return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str) { uint8_t *data, *dp, ch = 0; size_t length; /* Worst case space requirement. We'll realloc to actual size later. */ dp = data = LDNS_XMALLOC(uint8_t, strlen(str) > 255 ? 256 : (strlen(str) + 1)); if (! data) { return LDNS_STATUS_MEM_ERR; } /* Fill data (up to 255 characters) */ while (parse_char(&ch, &str)) { if (dp - data >= 255) { LDNS_FREE(data); return LDNS_STATUS_INVALID_STR; } *++dp = ch; } if (! str) { LDNS_FREE(data); return LDNS_STATUS_SYNTAX_BAD_ESCAPE; } length = (size_t)(dp - data); /* Fix last length byte */ data[0] = (uint8_t)length; /* Lose the overmeasure */ data = LDNS_XREALLOC(dp = data, uint8_t, length + 1); if (! data) { LDNS_FREE(dp); return LDNS_STATUS_MEM_ERR; } /* Create rdf */ *rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data); if (! *rd) { LDNS_FREE(data); return LDNS_STATUS_MEM_ERR; } return LDNS_STATUS_OK; } ldns_status ldns_str2rdf_apl(ldns_rdf **rd, const char *str) { const char *my_str = str; char *my_ip_str; size_t ip_str_len; uint16_t family; bool negation; uint8_t afdlength = 0; uint8_t *afdpart; uint8_t prefix; uint8_t *data; size_t i = 0; /* [!]afi:address/prefix */ if (strlen(my_str) < 2 || strchr(my_str, ':') == NULL || strchr(my_str, '/') == NULL || strchr(my_str, ':') > strchr(my_str, '/')) { return LDNS_STATUS_INVALID_STR; } if (my_str[0] == '!') { negation = true; my_str += 1; } else { negation = false; } family = (uint16_t) atoi(my_str); my_str = strchr(my_str, ':') + 1; /* need ip addr and only ip addr for inet_pton */ ip_str_len = (size_t) (strchr(my_str, '/') - my_str); my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1); if(!my_ip_str) return LDNS_STATUS_MEM_ERR; strncpy(my_ip_str, my_str, ip_str_len + 1); my_ip_str[ip_str_len] = '\0'; if (family == 1) { /* ipv4 */ afdpart = LDNS_XMALLOC(uint8_t, 4); if(!afdpart) { LDNS_FREE(my_ip_str); return LDNS_STATUS_MEM_ERR; } if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) { LDNS_FREE(my_ip_str); LDNS_FREE(afdpart); return LDNS_STATUS_INVALID_STR; } for (i = 0; i < 4; i++) { if (afdpart[i] != 0) { afdlength = i + 1; } } } else if (family == 2) { /* ipv6 */ afdpart = LDNS_XMALLOC(uint8_t, 16); if(!afdpart) { LDNS_FREE(my_ip_str); return LDNS_STATUS_MEM_ERR; } if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) { LDNS_FREE(my_ip_str); LDNS_FREE(afdpart); return LDNS_STATUS_INVALID_STR; } for (i = 0; i < 16; i++) { if (afdpart[i] != 0) { afdlength = i + 1; } } } else { /* unknown family */ LDNS_FREE(my_ip_str); return LDNS_STATUS_INVALID_STR; } my_str = strchr(my_str, '/') + 1; prefix = (uint8_t) atoi(my_str); data = LDNS_XMALLOC(uint8_t, 4 + afdlength); if(!data) { LDNS_FREE(afdpart); LDNS_FREE(my_ip_str); return LDNS_STATUS_INVALID_STR; } ldns_write_uint16(data, family); data[2] = prefix; data[3] = afdlength; if (negation) { /* set bit 1 of byte 3 */ data[3] = data[3] | 0x80; } memcpy(data + 4, afdpart, afdlength); *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data); LDNS_FREE(afdpart); LDNS_FREE(data); LDNS_FREE(my_ip_str); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_b64(ldns_rdf **rd, const char *str) { uint8_t *buffer; int16_t i; if ((*str == '-' || *str == '0') && str[1] == '\0') { *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, 0, NULL); return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; } buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); if(!buffer) { return LDNS_STATUS_MEM_ERR; } i = (uint16_t)ldns_b64_pton((const char*)str, buffer, ldns_b64_ntop_calculate_size(strlen(str))); if (-1 == i) { LDNS_FREE(buffer); return LDNS_STATUS_INVALID_B64; } else { *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_B64, (uint16_t) i, buffer); } LDNS_FREE(buffer); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) { uint8_t *buffer; int i; /* first byte contains length of actual b32 data */ size_t slen = strlen(str); size_t len = ldns_b32_pton_calculate_size(slen); if (len > 255) { return LDNS_STATUS_INVALID_B32_EXT; } buffer = LDNS_XMALLOC(uint8_t, len + 1); if(!buffer) { return LDNS_STATUS_MEM_ERR; } buffer[0] = len; i = ldns_b32_pton_extended_hex((const char*)str, slen, buffer + 1, ldns_b32_ntop_calculate_size(slen)); if (i < 0) { LDNS_FREE(buffer); return LDNS_STATUS_INVALID_B32_EXT; } else { *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer); } LDNS_FREE(buffer); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_hex(ldns_rdf **rd, const char *str) { uint8_t *t, *t_orig; int i; size_t len; len = strlen(str); if (len > LDNS_MAX_RDFLEN * 2) { return LDNS_STATUS_LABEL_OVERFLOW; } else { t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); if(!t) { return LDNS_STATUS_MEM_ERR; } t_orig = t; /* Now process octet by octet... */ while (*str) { *t = 0; if (isspace((int) *str)) { str++; } else { for (i = 16; i >= 1; i -= 15) { while (*str && isspace((int) *str)) { str++; } if (*str) { if (isxdigit((int) *str)) { *t += ldns_hexdigit_to_int(*str) * i; } else { LDNS_FREE(t_orig); return LDNS_STATUS_ERR; } ++str; } } ++t; } } *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, (size_t) (t - t_orig), t_orig); LDNS_FREE(t_orig); } return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) { const char *delimiters = "\n\t "; char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); ldns_buffer *str_buf; ssize_t c; uint16_t cur_type; size_t type_count = 0; ldns_rr_type type_list[65536]; if(!token) return LDNS_STATUS_MEM_ERR; if(rd == NULL) { LDNS_FREE(token); return LDNS_STATUS_NULL; } str_buf = LDNS_MALLOC(ldns_buffer); if(!str_buf) { LDNS_FREE(token); return LDNS_STATUS_MEM_ERR; } ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { LDNS_FREE(str_buf); LDNS_FREE(token); return LDNS_STATUS_MEM_ERR; } while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { if(type_count >= sizeof(type_list)) { LDNS_FREE(str_buf); LDNS_FREE(token); return LDNS_STATUS_ERR; } cur_type = ldns_get_rr_type_by_name(token); type_list[type_count] = cur_type; type_count++; } *rd = ldns_dnssec_create_nsec_bitmap(type_list, type_count, LDNS_RR_TYPE_NSEC); LDNS_FREE(token); ldns_buffer_free(str_buf); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_type(ldns_rdf **rd, const char *str) { uint16_t type; type = htons(ldns_get_rr_type_by_name(str)); /* ldns_rr_type is a 16 bit value */ *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_class(ldns_rdf **rd, const char *str) { uint16_t klass; klass = htons(ldns_get_rr_class_by_name(str)); /* class is 16 bit */ *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } /* An certificate alg field can either be specified as a 8 bits number * or by its symbolic name. Handle both */ ldns_status ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str) { ldns_lookup_table *lt; ldns_status st; uint8_t idd[2]; lt = ldns_lookup_by_name(ldns_cert_algorithms, str); st = LDNS_STATUS_OK; if (lt) { ldns_write_uint16(idd, (uint16_t) lt->id); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd); if (!*rd) { st = LDNS_STATUS_ERR; } } else { /* try as-is (a number) */ st = ldns_str2rdf_int16(rd, str); if (st == LDNS_STATUS_OK && ldns_rdf2native_int16(*rd) == 0) { st = LDNS_STATUS_CERT_BAD_ALGORITHM; } } return st; } static ldns_lookup_table ldns_tlsa_certificate_usages[] = { { LDNS_TLSA_USAGE_PKIX_TA , "PKIX-TA" }, { LDNS_TLSA_USAGE_PKIX_EE , "PKIX-EE" }, { LDNS_TLSA_USAGE_DANE_TA , "DANE-TA" }, { LDNS_TLSA_USAGE_DANE_EE , "DANE-EE" }, { LDNS_TLSA_USAGE_PRIVCERT , "PrivCert" }, { 0, NULL } }; static ldns_lookup_table ldns_tlsa_selectors[] = { { LDNS_TLSA_SELECTOR_CERT , "Cert" }, { LDNS_TLSA_SELECTOR_SPKI , "SPKI" }, { LDNS_TLSA_SELECTOR_PRIVSEL , "PrivSel" }, { 0, NULL } }; static ldns_lookup_table ldns_tlsa_matching_types[] = { { LDNS_TLSA_MATCHING_TYPE_FULL , "Full" }, { LDNS_TLSA_MATCHING_TYPE_SHA2_256 , "SHA2-256" }, { LDNS_TLSA_MATCHING_TYPE_SHA2_512 , "SHA2-512" }, { LDNS_TLSA_MATCHING_TYPE_PRIVMATCH , "PrivMatch" }, { 0, NULL } }; static ldns_status ldns_str2rdf_mnemonic4int8(ldns_lookup_table *lt, ldns_rdf **rd, const char *str) { if ((lt = ldns_lookup_by_name(lt, str))) { /* it was given as a integer */ *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id); if (!*rd) return LDNS_STATUS_ERR; else return LDNS_STATUS_OK; } return ldns_str2rdf_int8(rd, str); } /* An alg field can either be specified as a 8 bits number * or by its symbolic name. Handle both */ ldns_status ldns_str2rdf_alg(ldns_rdf **rd, const char *str) { return ldns_str2rdf_mnemonic4int8(ldns_algorithms, rd, str); } ldns_status ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str) { return ldns_str2rdf_mnemonic4int8( ldns_tlsa_certificate_usages, rd, str); } ldns_status ldns_str2rdf_selector(ldns_rdf **rd, const char *str) { return ldns_str2rdf_mnemonic4int8(ldns_tlsa_selectors, rd, str); } ldns_status ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str) { return ldns_str2rdf_mnemonic4int8(ldns_tlsa_matching_types, rd, str); } ldns_status ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd) , ATTR_UNUSED(const char *str) ) { /* this should be caught in an earlier time (general str2host for rr's */ return LDNS_STATUS_NOT_IMPL; } ldns_status ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd) , ATTR_UNUSED(const char *str) ) { /* is this used? is this actually WKS? or SRV? */ return LDNS_STATUS_NOT_IMPL; } static int loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) { /* read [.][mM] */ /* into mantissa exponent format for LOC type */ uint32_t meters = 0, cm = 0, val; char* cm_endstr; while (isblank((unsigned char)*my_str)) { my_str++; } meters = (uint32_t)strtol(my_str, &my_str, 10); if (*my_str == '.') { my_str++; cm = (uint32_t)strtol(my_str, &cm_endstr, 10); if (cm_endstr - my_str == 1) cm *= 10; my_str = cm_endstr; } if (meters >= 1) { *e = 2; val = meters; } else { *e = 0; val = cm; } while(val >= 10) { (*e)++; val /= 10; } *m = (uint8_t)val; if (*e > 9) return 0; if (*my_str == 'm' || *my_str == 'M') { my_str++; } *endstr = my_str; return 1; } ldns_status ldns_str2rdf_loc(ldns_rdf **rd, const char *str) { uint32_t latitude = 0; uint32_t longitude = 0; uint32_t altitude = 0; uint8_t *data; uint32_t equator = (uint32_t) ldns_power(2, 31); uint32_t h = 0; uint32_t m = 0; uint8_t size_b = 1, size_e = 2; uint8_t horiz_pre_b = 1, horiz_pre_e = 6; uint8_t vert_pre_b = 1, vert_pre_e = 3; double s = 0.0; bool northern_hemisphere; bool eastern_hemisphere; char *my_str = (char *) str; /* only support version 0 */ if (isdigit((int) *my_str)) { h = (uint32_t) strtol(my_str, &my_str, 10); } else { return LDNS_STATUS_INVALID_STR; } while (isblank((int) *my_str)) { my_str++; } if (isdigit((int) *my_str)) { m = (uint32_t) strtol(my_str, &my_str, 10); } else if (*my_str == 'N' || *my_str == 'S') { goto north; } else { return LDNS_STATUS_INVALID_STR; } while (isblank((int) *my_str)) { my_str++; } if (isdigit((int) *my_str)) { s = strtod(my_str, &my_str); } north: while (isblank((int) *my_str)) { my_str++; } if (*my_str == 'N') { northern_hemisphere = true; } else if (*my_str == 'S') { northern_hemisphere = false; } else { return LDNS_STATUS_INVALID_STR; } my_str++; /* store number */ s = 1000.0 * s; /* add a little to make floor in conversion a round */ s += 0.0005; latitude = (uint32_t) s; latitude += 1000 * 60 * m; latitude += 1000 * 60 * 60 * h; if (northern_hemisphere) { latitude = equator + latitude; } else { latitude = equator - latitude; } while (isblank((unsigned char)*my_str)) { my_str++; } if (isdigit((int) *my_str)) { h = (uint32_t) strtol(my_str, &my_str, 10); } else { return LDNS_STATUS_INVALID_STR; } while (isblank((int) *my_str)) { my_str++; } if (isdigit((int) *my_str)) { m = (uint32_t) strtol(my_str, &my_str, 10); } else if (*my_str == 'E' || *my_str == 'W') { goto east; } else { return LDNS_STATUS_INVALID_STR; } while (isblank((unsigned char)*my_str)) { my_str++; } if (isdigit((int) *my_str)) { s = strtod(my_str, &my_str); } east: while (isblank((unsigned char)*my_str)) { my_str++; } if (*my_str == 'E') { eastern_hemisphere = true; } else if (*my_str == 'W') { eastern_hemisphere = false; } else { return LDNS_STATUS_INVALID_STR; } my_str++; /* store number */ s *= 1000.0; /* add a little to make floor in conversion a round */ s += 0.0005; longitude = (uint32_t) s; longitude += 1000 * 60 * m; longitude += 1000 * 60 * 60 * h; if (eastern_hemisphere) { longitude += equator; } else { longitude = equator - longitude; } altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 10000000.0 + 0.5); if (*my_str == 'm' || *my_str == 'M') { my_str++; } if (strlen(my_str) > 0) { if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) return LDNS_STATUS_INVALID_STR; } if (strlen(my_str) > 0) { if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) return LDNS_STATUS_INVALID_STR; } if (strlen(my_str) > 0) { if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) return LDNS_STATUS_INVALID_STR; } data = LDNS_XMALLOC(uint8_t, 16); if(!data) { return LDNS_STATUS_MEM_ERR; } data[0] = 0; data[1] = 0; data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); ldns_write_uint32(data + 4, latitude); ldns_write_uint32(data + 8, longitude); ldns_write_uint32(data + 12, altitude); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_LOC, 16, data); LDNS_FREE(data); return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_wks(ldns_rdf **rd, const char *str) { uint8_t *bitmap = NULL; uint8_t *data; int bm_len = 0; struct protoent *proto = NULL; struct servent *serv = NULL; int serv_port; ldns_buffer *str_buf; char *proto_str = NULL; char *lc_proto_str = NULL; char *token; char *lc_token; char *c; if(strlen(str) == 0) token = LDNS_XMALLOC(char, 50); else token = LDNS_XMALLOC(char, strlen(str)+2); if(!token) return LDNS_STATUS_MEM_ERR; str_buf = LDNS_MALLOC(ldns_buffer); if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { LDNS_FREE(str_buf); LDNS_FREE(token); return LDNS_STATUS_MEM_ERR; } while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { if (!proto_str) { proto_str = strdup(token); lc_proto_str = strdup(token); for (c = lc_proto_str; *c; c++) { *c = tolower((unsigned char)*c); } if (!proto_str || !lc_proto_str) { free(proto_str); free(lc_proto_str); LDNS_FREE(bitmap); LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } } else { serv = getservbyname(token, proto_str); if (!serv) { serv = getservbyname(token, lc_proto_str); } if (!serv && (lc_token = strdup(token))) { for (c = lc_token; *c; c++) { *c = tolower((unsigned char)*c); } serv = getservbyname(lc_token, proto_str); if (!serv) { serv = getservbyname(lc_token, lc_proto_str); } free(lc_token); } if (serv) { serv_port = (int) ntohs((uint16_t) serv->s_port); } else { serv_port = atoi(token); } if (serv_port < 0 || serv_port > 65535) { LDNS_FREE(bitmap); LDNS_FREE(token); ldns_buffer_free(str_buf); free(proto_str); free(lc_proto_str); return LDNS_STATUS_INVALID_STR; } if (serv_port / 8 >= bm_len) { uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); if(!b2) { LDNS_FREE(bitmap); LDNS_FREE(token); ldns_buffer_free(str_buf); free(proto_str); free(lc_proto_str); return LDNS_STATUS_INVALID_STR; } bitmap = b2; /* set to zero to be sure */ for (; bm_len <= serv_port / 8; bm_len++) { bitmap[bm_len] = 0; } } ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true); } } if (!proto_str || !bitmap) { LDNS_FREE(bitmap); LDNS_FREE(token); ldns_buffer_free(str_buf); free(proto_str); free(lc_proto_str); return LDNS_STATUS_INVALID_STR; } data = LDNS_XMALLOC(uint8_t, bm_len + 1); if(!data) { LDNS_FREE(token); ldns_buffer_free(str_buf); LDNS_FREE(bitmap); free(proto_str); free(lc_proto_str); return LDNS_STATUS_INVALID_STR; } if (proto_str) proto = getprotobyname(proto_str); if (!proto) { proto = getprotobyname(lc_proto_str); } if (proto) { data[0] = (uint8_t) proto->p_proto; } else if (proto_str) { data[0] = (uint8_t) atoi(proto_str); } memcpy(data + 1, bitmap, (size_t) bm_len); *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data); LDNS_FREE(data); LDNS_FREE(token); ldns_buffer_free(str_buf); LDNS_FREE(bitmap); free(proto_str); free(lc_proto_str); #ifdef HAVE_ENDSERVENT endservent(); #endif #ifdef HAVE_ENDPROTOENT endprotoent(); #endif if(!*rd) return LDNS_STATUS_MEM_ERR; return LDNS_STATUS_OK; } ldns_status ldns_str2rdf_nsap(ldns_rdf **rd, const char *str) { size_t len, i; char* nsap_str = (char*) str; /* just a hex string with optional dots? */ if (str[0] != '0' || str[1] != 'x') { return LDNS_STATUS_INVALID_STR; } else { len = strlen(str); for (i=0; i < len; i++) { if (nsap_str[i] == '.') nsap_str[i] = ' '; } return ldns_str2rdf_hex(rd, str+2); } } ldns_status ldns_str2rdf_atma(ldns_rdf **rd, const char *str) { size_t len, i; char* atma_str = (char*) str; ldns_status status; /* just a hex string with optional dots? */ len = strlen(str); for (i=0; i < len; i++) { if (atma_str[i] == '.') atma_str[i] = ' '; } status = ldns_str2rdf_hex(rd, str); if (status != LDNS_STATUS_OK) { ; /* probably in e.164 format than */ } return status; } ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) { uint8_t precedence = 0; uint8_t gateway_type = 0; uint8_t algorithm = 0; char* gateway = NULL; char* publickey = NULL; uint8_t *data; ldns_buffer *str_buf; char *token; int token_count = 0; int ipseckey_len = 0; ldns_rdf* gateway_rdf = NULL; ldns_rdf* publickey_rdf = NULL; ldns_status status = LDNS_STATUS_OK; if(strlen(str) == 0) token = LDNS_XMALLOC(char, 256); else token = LDNS_XMALLOC(char, strlen(str)+2); if(!token) return LDNS_STATUS_MEM_ERR; str_buf = LDNS_MALLOC(ldns_buffer); if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { LDNS_FREE(str_buf); LDNS_FREE(token); return LDNS_STATUS_MEM_ERR; } while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { switch (token_count) { case 0: precedence = (uint8_t)atoi(token); break; case 1: gateway_type = (uint8_t)atoi(token); break; case 2: algorithm = (uint8_t)atoi(token); break; case 3: gateway = strdup(token); if (!gateway || (gateway_type == 0 && (token[0] != '.' || token[1] != '\0'))) { LDNS_FREE(gateway); LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } break; case 4: publickey = strdup(token); break; default: LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; break; } token_count++; } if (!gateway || !publickey) { if (gateway) LDNS_FREE(gateway); if (publickey) LDNS_FREE(publickey); LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } if (gateway_type == 1) { status = ldns_str2rdf_a(&gateway_rdf, gateway); } else if (gateway_type == 2) { status = ldns_str2rdf_aaaa(&gateway_rdf, gateway); } else if (gateway_type == 3) { status = ldns_str2rdf_dname(&gateway_rdf, gateway); } else if (gateway_type > 3) { status = LDNS_STATUS_INVALID_STR; } if (status != LDNS_STATUS_OK) { if (gateway) LDNS_FREE(gateway); if (publickey) LDNS_FREE(publickey); LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } status = ldns_str2rdf_b64(&publickey_rdf, publickey); if (status != LDNS_STATUS_OK) { if (gateway) LDNS_FREE(gateway); if (publickey) LDNS_FREE(publickey); LDNS_FREE(token); ldns_buffer_free(str_buf); if (gateway_rdf) ldns_rdf_free(gateway_rdf); return LDNS_STATUS_INVALID_STR; } /* now copy all into one ipseckey rdf */ if (gateway_type) ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf); else ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf); data = LDNS_XMALLOC(uint8_t, ipseckey_len); if(!data) { if (gateway) LDNS_FREE(gateway); if (publickey) LDNS_FREE(publickey); LDNS_FREE(token); ldns_buffer_free(str_buf); if (gateway_rdf) ldns_rdf_free(gateway_rdf); if (publickey_rdf) ldns_rdf_free(publickey_rdf); return LDNS_STATUS_MEM_ERR; } data[0] = precedence; data[1] = gateway_type; data[2] = algorithm; if (gateway_type) { memcpy(data + 3, ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf)); memcpy(data + 3 + ldns_rdf_size(gateway_rdf), ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); } else { memcpy(data + 3, ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); } *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data); if (gateway) LDNS_FREE(gateway); if (publickey) LDNS_FREE(publickey); LDNS_FREE(token); ldns_buffer_free(str_buf); ldns_rdf_deep_free(gateway_rdf); ldns_rdf_deep_free(publickey_rdf); LDNS_FREE(data); if(!*rd) return LDNS_STATUS_MEM_ERR; return LDNS_STATUS_OK; } ldns_status ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str) { unsigned int a, b, c, d; uint16_t shorts[4]; int l; if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || l != (int)strlen(str) || /* more data to read */ strpbrk(str, "+-") /* signed hexes */ ) { return LDNS_STATUS_INVALID_ILNP64; } else { shorts[0] = htons(a); shorts[1] = htons(b); shorts[2] = htons(c); shorts[3] = htons(d); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts); } return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_eui48(ldns_rdf **rd, const char *str) { unsigned int a, b, c, d, e, f; uint8_t bytes[6]; int l; if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", &a, &b, &c, &d, &e, &f, &l) != 6 || l != (int)strlen(str)) { return LDNS_STATUS_INVALID_EUI48; } else { bytes[0] = a; bytes[1] = b; bytes[2] = c; bytes[3] = d; bytes[4] = e; bytes[5] = f; *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48, 6, &bytes); } return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_eui64(ldns_rdf **rd, const char *str) { unsigned int a, b, c, d, e, f, g, h; uint8_t bytes[8]; int l; if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || l != (int)strlen(str)) { return LDNS_STATUS_INVALID_EUI64; } else { bytes[0] = a; bytes[1] = b; bytes[2] = c; bytes[3] = d; bytes[4] = e; bytes[5] = f; bytes[6] = g; bytes[7] = h; *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64, 8, &bytes); } return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; } ldns_status ldns_str2rdf_tag(ldns_rdf **rd, const char *str) { uint8_t *data; const char* ptr; if (strlen(str) > 255) { return LDNS_STATUS_INVALID_TAG; } for (ptr = str; *ptr; ptr++) { if (! isalnum((unsigned char)*ptr)) { return LDNS_STATUS_INVALID_TAG; } } data = LDNS_XMALLOC(uint8_t, strlen(str) + 1); if (!data) { return LDNS_STATUS_MEM_ERR; } data[0] = strlen(str); memcpy(data + 1, str, strlen(str)); *rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data); if (!*rd) { LDNS_FREE(data); return LDNS_STATUS_MEM_ERR; } return LDNS_STATUS_OK; } ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str) { uint8_t *data, *dp, ch = 0; size_t length; /* Worst case space requirement. We'll realloc to actual size later. */ dp = data = LDNS_XMALLOC(uint8_t, strlen(str)); if (! data) { return LDNS_STATUS_MEM_ERR; } /* Fill data with parsed bytes */ while (parse_char(&ch, &str)) { *dp++ = ch; if (dp - data > LDNS_MAX_RDFLEN) { LDNS_FREE(data); return LDNS_STATUS_INVALID_STR; } } if (! str) { LDNS_FREE(data); return LDNS_STATUS_SYNTAX_BAD_ESCAPE; } if (!(length = (size_t)(dp - data))) { /* An empty string is a data buffer of 0 bytes. The rdf for * this long string has to have length 0 and point to NULL. */ LDNS_FREE(data); data = NULL; } else { /* Lose the overmeasure */ data = LDNS_XREALLOC(dp = data, uint8_t, length); if (! data) { LDNS_FREE(dp); return LDNS_STATUS_MEM_ERR; } } /* Create rdf */ *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data); if (! *rd) { LDNS_FREE(data); return LDNS_STATUS_MEM_ERR; } return LDNS_STATUS_OK; } ldns_status ldns_str2rdf_hip(ldns_rdf **rd, const char *str) { const char *hit = str == NULL ? NULL : strchr(str, ' '); const char *pk = hit == NULL ? NULL : strchr(hit + 1, ' '); size_t hit_size = hit == NULL ? 0 : pk == NULL ? strlen(hit + 1) : (size_t) (pk - hit) - 1; size_t pk_size = pk == NULL ? 0 : strlen(pk + 1); size_t hit_wire_size = (hit_size + 1) / 2; size_t pk_wire_size = ldns_b64_pton_calculate_size(pk_size); size_t rdf_size = 4 + hit_wire_size + pk_wire_size; char *endptr; /* utility var for strtol usage */ int algorithm = str == NULL ? 0 : strtol(str, &endptr, 10); uint8_t *data, *dp; int hi, lo, written; if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255 || rdf_size > LDNS_MAX_RDFLEN || algorithm < 0 || algorithm > 255 || (errno != 0 && algorithm == 0) /* out of range */ || endptr == str /* no digits */) { return LDNS_STATUS_SYNTAX_ERR; } hit += 1; pk += 1; if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) { return LDNS_STATUS_MEM_ERR; } /* From RFC 5205 section 5. HIP RR Storage Format: ************************************************* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | HIT length | PK algorithm | PK length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | ~ HIT ~ | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | +-+-+-+-+-+-+-+-+-+-+-+ + | Public Key | ~ ~ | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | ~ Rendezvous Servers ~ | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | +-+-+-+-+-+-+-+ */ data[0] = (uint8_t) hit_wire_size; data[1] = (uint8_t) algorithm; for (dp = data + 4; *hit && *hit != ' '; dp++) { if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 || (lo = ldns_hexdigit_to_int(*hit++)) == -1) { LDNS_FREE(data); return LDNS_STATUS_INVALID_HEX; } *dp = (uint8_t) hi << 4 | lo; } if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) { LDNS_FREE(data); return LDNS_STATUS_INVALID_B64; } /* Because ldns_b64_pton_calculate_size isn't always correct: * (we have to fix it at some point) */ pk_wire_size = (uint16_t) written; ldns_write_uint16(data + 2, pk_wire_size); rdf_size = 4 + hit_wire_size + pk_wire_size; /* Create rdf */ if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) { LDNS_FREE(data); return LDNS_STATUS_MEM_ERR; } return LDNS_STATUS_OK; } /* Implementation mimics ldns_str2rdf_ipseckey */ ldns_status ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str) { /* From draft-ietf-mboned-driad-amt-discovery * Section 4.2. AMTRELAY RData Format ************************************************* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | precedence |D| type | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ~ relay ~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ uint8_t precedence = 0; uint8_t relay_type = 0; uint8_t discovery_optional = 0; char* relay = NULL; uint8_t *data; ldns_buffer *str_buf; char *token; int token_count = 0; int amtrelay_len = 0; ldns_rdf* relay_rdf = NULL; ldns_status status = LDNS_STATUS_OK; if(strlen(str) == 0) token = LDNS_XMALLOC(char, 256); else token = LDNS_XMALLOC(char, strlen(str)+2); if(!token) return LDNS_STATUS_MEM_ERR; str_buf = LDNS_MALLOC(ldns_buffer); if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { LDNS_FREE(str_buf); LDNS_FREE(token); return LDNS_STATUS_MEM_ERR; } while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { switch (token_count) { case 0: precedence = (uint8_t)atoi(token); break; case 1: discovery_optional = (uint8_t)atoi(token); if (discovery_optional != 0 && discovery_optional != 1) { LDNS_FREE(relay); LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } break; case 2: relay_type = (uint8_t)atoi(token); break; case 3: relay = strdup(token); if (!relay || (relay_type == 0 && (token[0] != '.' || token[1] != '\0'))) { LDNS_FREE(relay); LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } break; default: LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; break; } token_count++; } if (!relay && relay_type > 0) { if (relay) LDNS_FREE(relay); LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } if (relay_type == 1) { status = ldns_str2rdf_a(&relay_rdf, relay); } else if (relay_type == 2) { status = ldns_str2rdf_aaaa(&relay_rdf, relay); } else if (relay_type == 3) { status = ldns_str2rdf_dname(&relay_rdf, relay); } else if (relay_type > 3) { status = LDNS_STATUS_INVALID_STR; } if (status != LDNS_STATUS_OK) { if (relay) LDNS_FREE(relay); LDNS_FREE(token); ldns_buffer_free(str_buf); return LDNS_STATUS_INVALID_STR; } /* now copy all into one amtrelay rdf */ if (relay_type) amtrelay_len = 2 + (int)ldns_rdf_size(relay_rdf); else amtrelay_len = 2; data = LDNS_XMALLOC(uint8_t, amtrelay_len); if(!data) { if (relay) LDNS_FREE(relay); LDNS_FREE(token); ldns_buffer_free(str_buf); if (relay_rdf) ldns_rdf_free(relay_rdf); return LDNS_STATUS_MEM_ERR; } data[0] = precedence; data[1] = relay_type; data[1] |= (discovery_optional << 7); if (relay_type) { memcpy(data + 2, ldns_rdf_data(relay_rdf), ldns_rdf_size(relay_rdf)); } *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_AMTRELAY , (uint16_t) amtrelay_len, data); if (relay) LDNS_FREE(relay); LDNS_FREE(token); ldns_buffer_free(str_buf); ldns_rdf_free(relay_rdf); LDNS_FREE(data); if(!*rd) return LDNS_STATUS_MEM_ERR; return LDNS_STATUS_OK; } #ifdef RRTYPE_SVCB_HTTPS static int network_uint16_cmp(const void *a, const void *b) { return ((int)ldns_read_uint16(a)) - ((int)ldns_read_uint16(b)); } static ldns_status parse_svcparam_key(const char **s, ldns_svcparam_key *key); static ldns_status parse_svcparam_mandatory(const char **s, uint8_t **dp, uint8_t *eod) { bool quoted = false; uint8_t *keys = *dp; int prev_key; if (**s == '"') { *s += 1; quoted = true; } for (;;) { ldns_status st; ldns_svcparam_key key; if ((st = parse_svcparam_key(s, &key))) return st; if (*dp + 2 > eod) return LDNS_STATUS_RDATA_OVERFLOW; ldns_write_uint16(*dp, key); *dp += 2; if (**s == ',') *s += 1; else break; } if (quoted) { if (**s != '"') return LDNS_STATUS_INVALID_STR; *s += 1; } if (*dp - keys == 0) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; if (**s && !isspace((unsigned char)**s)) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; /* In draft-ietf-dnsop-svcb-https-02 Section 7: * * In wire format, the keys are represented by their numeric * values in network byte order, concatenated in ascending order. */ qsort(keys, (*dp - keys) / 2, 2, network_uint16_cmp); /* In draft-ietf-dnsop-svcb-https-02 Section 7: * * Keys ...... MUST NOT appear more than once. */ prev_key = -1; while (keys < *dp) { uint16_t key = ldns_read_uint16(keys); if (key == prev_key) { /* "Be conservative in what you send, * be liberal in what you accept" * * Instead of * `return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE;`, * * we eliminate the double occurrence. */ memmove(keys - 2, keys, *dp - keys); *dp -= 2; } else { prev_key = key; keys += 2; } } return LDNS_STATUS_OK; } INLINE bool parse_escape2(uint8_t *ch_p, const char** str_p) { *str_p += 1; return parse_escape(ch_p, str_p); } static ldns_status parse_svcparam_alpn(const char **s, uint8_t **dp, uint8_t *eod) { uint8_t *val; size_t len; if (*dp + 1 > eod) return LDNS_STATUS_RDATA_OVERFLOW; *dp += 1; val = *dp; if (**s == '"') { *s += 1; while (**s != '"') { if (**s == 0) return LDNS_STATUS_INVALID_STR; else if (**s == ',') { len = *dp - val; if (len == 0 || len > 255) return LDNS_STATUS_INVALID_STR; val[-1] = len; if (*dp + 1 > eod) return LDNS_STATUS_RDATA_OVERFLOW; *dp += 1; val = *dp; *s += 1; } else if (*dp + 1 > eod) return LDNS_STATUS_RDATA_OVERFLOW; else if (**s != '\\') *(*dp)++ = (uint8_t)*(*s)++; else if (!parse_escape2(*dp, s)) return LDNS_STATUS_SYNTAX_BAD_ESCAPE; else *dp += 1; } *s += 1; } else while (**s && !isspace((unsigned char)**s)) { if (**s == ',') { len = *dp - val; if (len == 0 || len > 255) return LDNS_STATUS_INVALID_STR; val[-1] = len; if (*dp + 1 > eod) return LDNS_STATUS_RDATA_OVERFLOW; *dp += 1; val = *dp; *s += 1; } else if (*dp + 1 > eod) return LDNS_STATUS_RDATA_OVERFLOW; else if (**s != '\\') *(*dp)++ = (uint8_t)*(*s)++; else if (!parse_escape2(*dp, s)) return LDNS_STATUS_SYNTAX_BAD_ESCAPE; else *dp += 1; } len = *dp - val; if (len == 0 || len > 255) return LDNS_STATUS_INVALID_STR; val[-1] = len; return **s && !isspace((unsigned char)**s) ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR : LDNS_STATUS_OK; } static ldns_status parse_svcparam_value(const char **s, uint8_t **dp, uint8_t *eod) { if (**s == '"') { *s += 1; while (**s != '"') { if (**s == 0) return LDNS_STATUS_INVALID_STR; else if (*dp + 1 > eod) return LDNS_STATUS_RDATA_OVERFLOW; else if (**s != '\\') *(*dp)++ = (uint8_t)*(*s)++; else if (!parse_escape2(*dp, s)) return LDNS_STATUS_SYNTAX_BAD_ESCAPE; else *dp += 1; } *s += 1; } else while (**s && !isspace((unsigned char)**s)) { if (*dp + 1 > eod) return LDNS_STATUS_RDATA_OVERFLOW; else if (**s != '\\') *(*dp)++ = (uint8_t)*(*s)++; else if (!parse_escape2(*dp, s)) return LDNS_STATUS_SYNTAX_BAD_ESCAPE; else *dp += 1; } return **s && !isspace((unsigned char)**s) ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR : LDNS_STATUS_OK; } static ldns_status parse_svcparam_port(const char **s, uint8_t **dp, uint8_t *eod) { uint8_t *val = *dp; ldns_status st; size_t len; char num_str[6]; char *endptr; unsigned long int num; if ((st = parse_svcparam_value(s, dp, eod))) return st; len = *dp - val; if (len == 0 || len > 5) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; memcpy(num_str, val, len); num_str[len] = 0; num = strtoul(num_str, &endptr, 10); if (*endptr) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; ldns_write_uint16(val, num); *dp = val + 2; return LDNS_STATUS_OK; } static ldns_status parse_svcparam_ipv4hint(const char **s, uint8_t **dp, uint8_t *eod) { bool quoted = false; if (**s == '"') { *s += 1; quoted = true; } for (;;) { const char *ipv4_start = *s; char ipv4_str[16]; size_t len; while (isdigit((unsigned char)**s) || **s == '.') *s += 1; len = *s - ipv4_start; if (len == 0 || len > 15) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; if (*dp + 4 > eod) return LDNS_STATUS_RDATA_OVERFLOW; memcpy(ipv4_str, ipv4_start, len); ipv4_str[len] = 0; if (inet_pton(AF_INET, ipv4_str, *dp) != 1) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; *dp += 4; if (**s == ',') *s += 1; else break; } if (quoted) { if (**s != '"') return LDNS_STATUS_INVALID_STR; *s += 1; } return **s && !isspace((unsigned char)**s) ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR : LDNS_STATUS_OK; } static ldns_status parse_svcparam_ech(const char **s, uint8_t **dp, uint8_t *eod) { bool quoted = false; const char *b64_str; size_t len, pad, out_len; char in_buf[4096]; char *in = in_buf; int out; if (**s == '"') { *s += 1; quoted = true; } b64_str = *s; while (isalnum((unsigned char)**s) || **s == '+' || **s == '/' || **s == '=') *s += 1; len = *s - b64_str; pad = len % 4; pad = pad ? 4 - pad : 0; if (len == 0 || pad == 3) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; if (quoted) { if (**s != '"') return LDNS_STATUS_INVALID_STR; *s += 1; } if (**s && !isspace((unsigned char)**s)) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; out_len = ldns_b64_pton_calculate_size(len); if (*dp + out_len > eod) return LDNS_STATUS_RDATA_OVERFLOW; if (len + pad > sizeof(in_buf) - 1 && !(in = LDNS_XMALLOC(char, len + pad + 1))) return LDNS_STATUS_MEM_ERR; memcpy(in, b64_str, len); while (pad--) in[len++] = '='; in[len] = 0; out = ldns_b64_pton(in, *dp, out_len); if (in != in_buf) LDNS_FREE(in); if (out <= 0) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; *dp += out; return LDNS_STATUS_OK; } static ldns_status parse_svcparam_ipv6hint(const char **s, uint8_t **dp, uint8_t *eod) { bool quoted = false; if (**s == '"') { *s += 1; quoted = true; } for (;;) { const char *ipv6_start = *s; char ipv6_str[INET6_ADDRSTRLEN]; size_t len; while (isxdigit((unsigned char)**s) || **s == ':' || **s == '.') *s += 1; len = *s - ipv6_start; if (len == 0 || len > INET6_ADDRSTRLEN) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; if (*dp + 16 > eod) return LDNS_STATUS_RDATA_OVERFLOW; memcpy(ipv6_str, ipv6_start, len); ipv6_str[len] = 0; if (inet_pton(AF_INET6, ipv6_str, *dp) != 1) return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; *dp += 16; if (**s == ',') *s += 1; else break; } if (quoted) { if (**s != '"') return LDNS_STATUS_INVALID_STR; *s += 1; } return **s && !isspace((unsigned char)**s) ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR : LDNS_STATUS_OK; } struct struct_svcparam_key_def { const char *str; size_t len; }; typedef struct struct_svcparam_key_def svcparam_key_def; static svcparam_key_def svcparam_key_defs[] = { { "mandatory" , 9 } , { "alpn" , 4 } , { "no-default-alpn", 15 } , { "port" , 4 } , { "ipv4hint" , 8 } , { "ech" , 3 } , { "ipv6hint" , 8 } , { "dohpath" , 7 } }; static const size_t svcparam_key_defs_len = sizeof(svcparam_key_defs) / sizeof(svcparam_key_def); /* svcparam_key2buffer_str() should actually be in host2str.c, but we need the * svcparam_key_defs for it and it is not an exposed symbol anyway. */ ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key) { if (key <= LDNS_SVCPARAM_KEY_LAST_KEY) ldns_buffer_write_string(output, svcparam_key_defs[key].str); else ldns_buffer_printf(output, "key%d", (int)key); return ldns_buffer_status(output); } static ldns_status parse_svcparam_key(const char **s, ldns_svcparam_key *key) { size_t i, len; const char *key_str = *s; char num_str[6]; char *endptr; unsigned long int num; /* parse key */ while (islower((unsigned char)**s) || isdigit((unsigned char)**s) || **s == '-') *s += 1; len = *s - key_str; for (i = 0; i < svcparam_key_defs_len; i++) { if (len == svcparam_key_defs[i].len && !strncmp(key_str, svcparam_key_defs[i].str, len)) { *key = i; return LDNS_STATUS_OK; } } /* Also allow "echconfig" from earlier draft versions. */ if (len == 9 && !strncmp(key_str, "echconfig", 9)) { *key = LDNS_SVCPARAM_KEY_ECH; return LDNS_STATUS_OK; } if (len < 4 || len > 8 || strncmp(key_str, "key", 3)) return LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR; memcpy(num_str, key_str + 3, len - 3); num_str[len - 3] = 0; num = strtoul(num_str, &endptr, 10); if (*endptr || num > 65535) return LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR; /* key65535 is Reserved to be an ("Invalid key"), though there is no * physiological reason to deny usage. We restrict ourselves to the * anatomical limitations only to maximize serviceability. * ``` * if (num == 65535) * return LDNS_STATUS_RESERVED_SVCPARAM_KEY; * ``` */ *key = num; return LDNS_STATUS_OK; } static ldns_status parse_svcparam(const char **s, uint8_t **dp, uint8_t *eod) { ldns_svcparam_key key; ldns_status st; uint8_t *val; if (*dp + 4 > eod) return LDNS_STATUS_RDATA_OVERFLOW; if ((st = parse_svcparam_key(s, &key))) return st; ldns_write_uint16(*dp, key); ldns_write_uint16(*dp + 2, 0); *dp += 4; if (isspace((unsigned char)**s) || !**s) return LDNS_STATUS_OK; else if (**s != '=') return LDNS_STATUS_SYNTAX_ERR; *s += 1; val = *dp; switch(key) { case LDNS_SVCPARAM_KEY_MANDATORY: st = parse_svcparam_mandatory(s, dp, eod); break; case LDNS_SVCPARAM_KEY_ALPN: st = parse_svcparam_alpn(s, dp, eod); break; case LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN: return LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED; case LDNS_SVCPARAM_KEY_PORT: st = parse_svcparam_port(s, dp, eod); break; case LDNS_SVCPARAM_KEY_IPV4HINT: st = parse_svcparam_ipv4hint(s, dp, eod); break; case LDNS_SVCPARAM_KEY_ECH: st = parse_svcparam_ech(s, dp, eod); break; case LDNS_SVCPARAM_KEY_IPV6HINT: st = parse_svcparam_ipv6hint(s, dp, eod); break; default: st = parse_svcparam_value(s, dp, eod); break; } if (st) return st; ldns_write_uint16(val - 2, *dp - val); return LDNS_STATUS_OK; } static int svcparam_ptr_cmp(const void *a, const void *b) { uint8_t *x = *(uint8_t **)a , *y = *(uint8_t **)b; uint16_t x_type = ldns_read_uint16(x), y_type = ldns_read_uint16(y); uint16_t x_len , y_len; if (x_type != y_type) return x_type > y_type ? 1 : -1; x_len = ldns_read_uint16(x + 2); y_len = ldns_read_uint16(y + 2); return x_len != y_len ? (x_len > y_len ? 1 : -1) : (x_len == 0 ? 0 : memcmp(x + 4, y + 4, x_len)); } ldns_status ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str) { uint8_t *data, *dp, *eod, *p, *new_data; ldns_status st = LDNS_STATUS_OK; size_t length, i; size_t nparams = 0; uint8_t **svcparams; int prev_key; if (!rd || !str) return LDNS_STATUS_NULL; length = strlen(str); /* Worst case space requirement. We'll realloc to actual size later. */ if (!(dp = data = LDNS_XMALLOC(uint8_t, length * 4))) return LDNS_STATUS_MEM_ERR; eod = data + length * 4; /* Fill data with parsed bytes */ for (;;) { while (isspace((unsigned char)*str)) str += 1; if(!*str) break; if ((st = parse_svcparam(&str, &dp, eod))) { LDNS_FREE(data); return st; } nparams += 1; } /* draft-ietf-dnsop-svcb-https-02 in Section 2.2: * * SvcParamKeys SHALL appear in increasing numeric order * * A svcparams array (with pointers to the individual key, value pairs) * is created to qsort the pairs in increasing numeric order. */ if (!(svcparams = LDNS_XMALLOC(uint8_t *, nparams))) { LDNS_FREE(data); return LDNS_STATUS_MEM_ERR; } for ( p = data, i = 0 ; p < dp && i < nparams ; p += 4 + ldns_read_uint16(p + 2)) svcparams[i++] = p; qsort(svcparams, i, sizeof(uint8_t *), svcparam_ptr_cmp); /* Write out the (key, value) pairs to a newly allocated data in * sorted order. */ length = dp - data; if (!(new_data = LDNS_XMALLOC(uint8_t, length))) { LDNS_FREE(data); LDNS_FREE(svcparams); return LDNS_STATUS_MEM_ERR; } prev_key = -1; for ( p = new_data, i = 0 ; p < new_data + length && i < nparams ; p += 4 + ldns_read_uint16(p + 2), i += 1) { uint16_t key = ldns_read_uint16(svcparams[i]); /* In draft-ietf-dnsop-svcb-https-02 Section 2.1: * * SvcParams ...... keys MUST NOT be repeated. * * ldns will not impose this limitation on the library user, * but we can merge completely equal repetitions into one. * So, not doing * ``` * if (key == prev_key) * return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE; * ``` * but instead: */ if (key == prev_key && ldns_read_uint16(svcparams[i] + 2) == ldns_read_uint16(svcparams[i - 1] + 2) && 0 == memcmp( svcparams[i ] + 4 , svcparams[i - 1] + 4 , ldns_read_uint16(svcparams[i] + 2))) { p -= 4 + ldns_read_uint16(svcparams[i] + 2); continue; } memcpy(p, svcparams[i], 4 + ldns_read_uint16(svcparams[i] + 2)); prev_key = key; } LDNS_FREE(data); LDNS_FREE(svcparams); /* Create rdf */ *rd = ldns_rdf_new(LDNS_RDF_TYPE_SVCPARAMS, p - new_data, new_data); if (! *rd) { LDNS_FREE(new_data); return LDNS_STATUS_MEM_ERR; } return LDNS_STATUS_OK; } #else /* #ifdef RRTYPE_SVCB_HTTPS */ ldns_status ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str) { (void)rd; (void)str; return LDNS_STATUS_NOT_IMPL; } #endif /* #ifdef RRTYPE_SVCB_HTTPS */ ldns-1.8.4/keys.c0000664000175000017500000014740614646643036013201 0ustar willemwillem/* * keys.c handle private keys for use in DNSSEC * * This module should hide some of the openSSL complexities * and give a general interface for private keys and hmac * handling * * (c) NLnet Labs, 2004-2006 * * See the file LICENSE for the license */ #include #include #ifdef HAVE_SSL #include #include #include #include #include #ifdef USE_DSA #include #endif #if defined(HAVE_OPENSSL_ENGINE_H) && !defined(OPENSSL_NO_ENGINE) #include #else # ifndef OPENSSL_NO_ENGINE # define OPENSSL_NO_ENGINE # endif #endif #endif /* HAVE_SSL */ ldns_lookup_table ldns_signing_algorithms[] = { { LDNS_SIGN_RSAMD5, "RSAMD5" }, { LDNS_SIGN_RSASHA1, "RSASHA1" }, { LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, #ifdef USE_SHA2 { LDNS_SIGN_RSASHA256, "RSASHA256" }, { LDNS_SIGN_RSASHA512, "RSASHA512" }, #endif #ifdef USE_GOST { LDNS_SIGN_ECC_GOST, "ECC-GOST" }, #endif #ifdef USE_ECDSA { LDNS_SIGN_ECDSAP256SHA256, "ECDSAP256SHA256" }, { LDNS_SIGN_ECDSAP384SHA384, "ECDSAP384SHA384" }, #endif #ifdef USE_ED25519 { LDNS_SIGN_ED25519, "ED25519" }, #endif #ifdef USE_ED448 { LDNS_SIGN_ED448, "ED448" }, #endif #ifdef USE_DSA { LDNS_SIGN_DSA, "DSA" }, { LDNS_SIGN_DSA_NSEC3, "DSA-NSEC3-SHA1" }, #endif { LDNS_SIGN_HMACMD5, "hmac-md5.sig-alg.reg.int" }, { LDNS_SIGN_HMACSHA1, "hmac-sha1" }, { LDNS_SIGN_HMACSHA256, "hmac-sha256" }, { LDNS_SIGN_HMACSHA224, "hmac-sha224" }, { LDNS_SIGN_HMACSHA384, "hmac-sha384" }, { LDNS_SIGN_HMACSHA512, "hmac-sha512" }, { 0, NULL } }; ldns_key_list * ldns_key_list_new(void) { ldns_key_list *key_list = LDNS_MALLOC(ldns_key_list); if (!key_list) { return NULL; } else { key_list->_key_count = 0; key_list->_keys = NULL; return key_list; } } ldns_key * ldns_key_new(void) { ldns_key *newkey; newkey = LDNS_MALLOC(ldns_key); if (!newkey) { return NULL; } else { /* some defaults - not sure whether to do this */ ldns_key_set_use(newkey, true); ldns_key_set_flags(newkey, LDNS_KEY_ZONE_KEY); ldns_key_set_origttl(newkey, 0); ldns_key_set_keytag(newkey, 0); ldns_key_set_inception(newkey, 0); ldns_key_set_expiration(newkey, 0); ldns_key_set_pubkey_owner(newkey, NULL); #ifdef HAVE_SSL ldns_key_set_evp_key(newkey, NULL); #endif /* HAVE_SSL */ ldns_key_set_hmac_key(newkey, NULL); ldns_key_set_external_key(newkey, NULL); return newkey; } } ldns_status ldns_key_new_frm_fp(ldns_key **k, FILE *fp) { return ldns_key_new_frm_fp_l(k, fp, NULL); } #if defined(HAVE_SSL) && !defined(OPENSSL_NO_ENGINE) ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm alg) { ldns_key *k; k = ldns_key_new(); if(!k) return LDNS_STATUS_MEM_ERR; #ifndef S_SPLINT_S ldns_key_set_algorithm(k, (ldns_signing_algorithm) alg); k->_key.key = ENGINE_load_private_key(e, key_id, UI_OpenSSL(), NULL); if (!k->_key.key) { ldns_key_free(k); return LDNS_STATUS_ENGINE_KEY_NOT_LOADED; } #endif /* splint */ *key = k; return LDNS_STATUS_OK; } #endif #if defined(USE_GOST) && !defined(OPENSSL_NO_ENGINE) /** store GOST engine reference loaded into OpenSSL library */ ENGINE* ldns_gost_engine = NULL; int ldns_key_EVP_load_gost_id(void) { static int gost_id = 0; const EVP_PKEY_ASN1_METHOD* meth; ENGINE* e; if(gost_id) return gost_id; /* see if configuration loaded gost implementation from other engine*/ meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); if(meth) { EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); return gost_id; } /* see if engine can be loaded already */ e = ENGINE_by_id("gost"); if(!e) { /* load it ourself, in case statically linked */ ENGINE_load_builtin_engines(); ENGINE_load_dynamic(); e = ENGINE_by_id("gost"); } if(!e) { /* no gost engine in openssl */ return 0; } if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { ENGINE_finish(e); ENGINE_free(e); return 0; } meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); if(!meth) { /* algo not found */ ENGINE_finish(e); ENGINE_free(e); return 0; } /* Note: do not ENGINE_finish and ENGINE_free the acquired engine * on some platforms this frees up the meth and unloads gost stuff */ ldns_gost_engine = e; EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); return gost_id; } void ldns_key_EVP_unload_gost(void) { if(ldns_gost_engine) { ENGINE_finish(ldns_gost_engine); ENGINE_free(ldns_gost_engine); ldns_gost_engine = NULL; } } /** read GOST private key */ static EVP_PKEY* ldns_key_new_frm_fp_gost_l(FILE* fp, int* line_nr) { char token[16384]; const unsigned char* pp; int gost_id; EVP_PKEY* pkey; ldns_rdf* b64rdf = NULL; gost_id = ldns_key_EVP_load_gost_id(); if(!gost_id) return NULL; if (ldns_fget_keyword_data_l(fp, "GostAsn1", ": ", token, "\n", sizeof(token), line_nr) == -1) return NULL; while(strlen(token) < 96) { /* read more b64 from the file, b64 split on multiple lines */ if(ldns_fget_token_l(fp, token+strlen(token), "\n", sizeof(token)-strlen(token), line_nr) == -1) return NULL; } if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK) return NULL; pp = (unsigned char*)ldns_rdf_data(b64rdf); pkey = d2i_PrivateKey(gost_id, NULL, &pp, (int)ldns_rdf_size(b64rdf)); ldns_rdf_deep_free(b64rdf); return pkey; } #endif #ifdef USE_ECDSA /** calculate public key from private key */ static int ldns_EC_KEY_calc_public(EC_KEY* ec) { EC_POINT* pub_key; const EC_GROUP* group; group = EC_KEY_get0_group(ec); pub_key = EC_POINT_new(group); if(!pub_key) return 0; if(!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { EC_POINT_free(pub_key); return 0; } if(!EC_POINT_mul(group, pub_key, EC_KEY_get0_private_key(ec), NULL, NULL, NULL)) { EC_POINT_free(pub_key); return 0; } if(EC_KEY_set_public_key(ec, pub_key) == 0) { EC_POINT_free(pub_key); return 0; } EC_POINT_free(pub_key); return 1; } /** read ECDSA private key */ static EVP_PKEY* ldns_key_new_frm_fp_ecdsa_l(FILE* fp, ldns_algorithm alg, int* line_nr) { char token[16384]; ldns_rdf* b64rdf = NULL; unsigned char* pp; BIGNUM* bn; EVP_PKEY* evp_key; EC_KEY* ec; if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n", sizeof(token), line_nr) == -1) return NULL; if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK) return NULL; pp = (unsigned char*)ldns_rdf_data(b64rdf); if(alg == LDNS_ECDSAP256SHA256) ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); else if(alg == LDNS_ECDSAP384SHA384) ec = EC_KEY_new_by_curve_name(NID_secp384r1); else ec = NULL; if(!ec) { ldns_rdf_deep_free(b64rdf); return NULL; } bn = BN_bin2bn(pp, (int)ldns_rdf_size(b64rdf), NULL); ldns_rdf_deep_free(b64rdf); if(!bn) { EC_KEY_free(ec); return NULL; } EC_KEY_set_private_key(ec, bn); BN_free(bn); if(!ldns_EC_KEY_calc_public(ec)) { EC_KEY_free(ec); return NULL; } evp_key = EVP_PKEY_new(); if(!evp_key) { EC_KEY_free(ec); return NULL; } if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { EVP_PKEY_free(evp_key); EC_KEY_free(ec); return NULL; } return evp_key; } #endif #ifdef USE_ED25519 /** turn private key buffer into EC_KEY structure */ static EVP_PKEY* ldns_ed25519_priv_raw(uint8_t* pkey, int plen) { const unsigned char* pp; uint8_t buf[256]; int buflen = 0; uint8_t pre[] = {0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04, 0x20}; int pre_len = 16; /* ASN looks like this for ED25519 public key * 302a300506032b6570032100 <32byteskey> * for ED25519 private key * 302e020100300506032b657004220420 <32bytes> * * for X25519 this was * 30320201010420 <32byteskey> * andparameters a00b06092b06010401da470f01 * (noparameters, preamble is 30250201010420). * the key is reversed (little endian). */ buflen = pre_len + plen; if((size_t)buflen > sizeof(buf)) return NULL; memmove(buf, pre, pre_len); memmove(buf+pre_len, pkey, plen); /* reverse the pkey into the buf - key is not reversed it seems */ /* for(i=0; i * the key is reversed (little endian). */ buflen = pre_len + plen; if((size_t)buflen > sizeof(buf)) return NULL; memmove(buf, pre, pre_len); memmove(buf+pre_len, pkey, plen); /* reverse the pkey into the buf - key is not reversed it seems */ /* for(i=0; i_key.key) { ldns_key_free(k); return LDNS_STATUS_ERR; } #endif /* splint */ #endif break; #ifdef USE_ECDSA case LDNS_SIGN_ECDSAP256SHA256: case LDNS_SIGN_ECDSAP384SHA384: ldns_key_set_algorithm(k, alg); ldns_key_set_evp_key(k, ldns_key_new_frm_fp_ecdsa_l(fp, (ldns_algorithm)alg, line_nr)); #ifndef S_SPLINT_S if(!k->_key.key) { ldns_key_free(k); return LDNS_STATUS_ERR; } #endif /* splint */ break; #endif #ifdef USE_ED25519 case LDNS_SIGN_ED25519: ldns_key_set_algorithm(k, alg); ldns_key_set_evp_key(k, ldns_key_new_frm_fp_ed25519_l(fp, line_nr)); #ifndef S_SPLINT_S if(!k->_key.key) { ldns_key_free(k); return LDNS_STATUS_ERR; } #endif /* splint */ break; #endif #ifdef USE_ED448 case LDNS_SIGN_ED448: ldns_key_set_algorithm(k, alg); ldns_key_set_evp_key(k, ldns_key_new_frm_fp_ed448_l(fp, line_nr)); #ifndef S_SPLINT_S if(!k->_key.key) { ldns_key_free(k); return LDNS_STATUS_ERR; } #endif /* splint */ break; #endif default: ldns_key_free(k); return LDNS_STATUS_SYNTAX_ALG_ERR; } key_rr = ldns_key2rr(k); ldns_key_set_keytag(k, ldns_calc_keytag(key_rr)); ldns_rr_free(key_rr); if (key) { *key = k; return LDNS_STATUS_OK; } ldns_key_free(k); return LDNS_STATUS_ERR; } #ifdef HAVE_SSL RSA * ldns_key_new_frm_fp_rsa(FILE *f) { return ldns_key_new_frm_fp_rsa_l(f, NULL); } RSA * ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr) { /* we parse * Modulus: * PublicExponent: * PrivateExponent: * Prime1: * Prime2: * Exponent1: * Exponent2: * Coefficient: * * man 3 RSA: * * struct * { * BIGNUM *n; // public modulus * BIGNUM *e; // public exponent * BIGNUM *d; // private exponent * BIGNUM *p; // secret prime factor * BIGNUM *q; // secret prime factor * BIGNUM *dmp1; // d mod (p-1) * BIGNUM *dmq1; // d mod (q-1) * BIGNUM *iqmp; // q^-1 mod p * // ... * */ char *b; RSA *rsa; uint8_t *buf; int i; BIGNUM *n=NULL, *e=NULL, *d=NULL, *p=NULL, *q=NULL, *dmp1=NULL, *dmq1=NULL, *iqmp=NULL; b = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN); rsa = RSA_new(); if (!b || !rsa || !buf) { goto error; } /* I could use functions again, but that seems an overkill, * although this also looks tedious */ /* Modules, rsa->n */ if (ldns_fget_keyword_data_l(f, "Modulus", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b))); #ifndef S_SPLINT_S n = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!n) { goto error; } /* PublicExponent, rsa->e */ if (ldns_fget_keyword_data_l(f, "PublicExponent", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b))); e = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!e) { goto error; } /* PrivateExponent, rsa->d */ if (ldns_fget_keyword_data_l(f, "PrivateExponent", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b))); d = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!d) { goto error; } /* Prime1, rsa->p */ if (ldns_fget_keyword_data_l(f, "Prime1", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b))); p = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!p) { goto error; } /* Prime2, rsa->q */ if (ldns_fget_keyword_data_l(f, "Prime2", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b))); q = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!q) { goto error; } /* Exponent1, rsa->dmp1 */ if (ldns_fget_keyword_data_l(f, "Exponent1", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b))); dmp1 = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!dmp1) { goto error; } /* Exponent2, rsa->dmq1 */ if (ldns_fget_keyword_data_l(f, "Exponent2", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b))); dmq1 = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!dmq1) { goto error; } /* Coefficient, rsa->iqmp */ if (ldns_fget_keyword_data_l(f, "Coefficient", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b))); iqmp = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!iqmp) { goto error; } #endif /* splint */ #if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) # ifndef S_SPLINT_S rsa->n = n; rsa->e = e; rsa->d = d; rsa->p = p; rsa->q = q; rsa->dmp1 = dmp1; rsa->dmq1 = dmq1; rsa->iqmp = iqmp; # endif #else if(!RSA_set0_key(rsa, n, e, d)) goto error; n = NULL; e = NULL; d = NULL; if(!RSA_set0_factors(rsa, p, q)) goto error; p = NULL; q = NULL; if(!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) goto error; #endif LDNS_FREE(buf); LDNS_FREE(b); return rsa; error: RSA_free(rsa); LDNS_FREE(b); LDNS_FREE(buf); BN_free(n); BN_free(e); BN_free(d); BN_free(p); BN_free(q); BN_free(dmp1); BN_free(dmq1); BN_free(iqmp); return NULL; } #ifdef USE_DSA DSA * ldns_key_new_frm_fp_dsa(FILE *f) { return ldns_key_new_frm_fp_dsa_l(f, NULL); } DSA * ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr)) { int i; char *d; DSA *dsa; uint8_t *buf; BIGNUM *p=NULL, *q=NULL, *g=NULL, *priv_key=NULL, *pub_key=NULL; d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN); dsa = DSA_new(); if (!d || !dsa || !buf) { goto error; } /* the line parser removes the () from the input... */ /* Prime, dsa->p */ if (ldns_fget_keyword_data_l(f, "Primep", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); #ifndef S_SPLINT_S p = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!p) { goto error; } /* Subprime, dsa->q */ if (ldns_fget_keyword_data_l(f, "Subprimeq", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); q = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!q) { goto error; } /* Base, dsa->g */ if (ldns_fget_keyword_data_l(f, "Baseg", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); g = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!g) { goto error; } /* Private key, dsa->priv_key */ if (ldns_fget_keyword_data_l(f, "Private_valuex", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); priv_key = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!priv_key) { goto error; } /* Public key, dsa->priv_key */ if (ldns_fget_keyword_data_l(f, "Public_valuey", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); pub_key = BN_bin2bn((const char unsigned*)buf, i, NULL); if (!pub_key) { goto error; } #endif /* splint */ #if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) # ifndef S_SPLINT_S dsa->p = p; dsa->q = q; dsa->g = g; dsa->priv_key = priv_key; dsa->pub_key = pub_key; # endif #else if(!DSA_set0_pqg(dsa, p, q, g)) goto error; p = NULL; q = NULL; g = NULL; if(!DSA_set0_key(dsa, pub_key, priv_key)) goto error; #endif LDNS_FREE(buf); LDNS_FREE(d); return dsa; error: LDNS_FREE(d); LDNS_FREE(buf); DSA_free(dsa); BN_free(p); BN_free(q); BN_free(g); BN_free(priv_key); BN_free(pub_key); return NULL; } #endif /* USE_DSA */ unsigned char * ldns_key_new_frm_fp_hmac(FILE *f, size_t *hmac_size) { return ldns_key_new_frm_fp_hmac_l(f, NULL, hmac_size); } unsigned char * ldns_key_new_frm_fp_hmac_l( FILE *f , ATTR_UNUSED(int *line_nr) , size_t *hmac_size ) { size_t bufsz; char d[LDNS_MAX_LINELEN]; unsigned char *buf = NULL; *hmac_size = ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1 ? 0 : (buf = LDNS_XMALLOC( unsigned char, (bufsz = ldns_b64_ntop_calculate_size(strlen(d))))) == NULL ? 0 : (size_t) ldns_b64_pton((const char*)d, buf, bufsz); return buf; } #endif /* HAVE_SSL */ #ifdef USE_GOST static EVP_PKEY* ldns_gen_gost_key(void) { EVP_PKEY_CTX* ctx; EVP_PKEY* p = NULL; int gost_id = ldns_key_EVP_load_gost_id(); if(!gost_id) return NULL; ctx = EVP_PKEY_CTX_new_id(gost_id, NULL); if(!ctx) { /* the id should be available now */ return NULL; } if(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) { /* cannot set paramset */ EVP_PKEY_CTX_free(ctx); return NULL; } if(EVP_PKEY_keygen_init(ctx) <= 0) { EVP_PKEY_CTX_free(ctx); return NULL; } if(EVP_PKEY_keygen(ctx, &p) <= 0) { EVP_PKEY_free(p); EVP_PKEY_CTX_free(ctx); return NULL; } EVP_PKEY_CTX_free(ctx); return p; } #endif ldns_key * ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) { ldns_key *k; #ifdef HAVE_SSL #ifdef USE_DSA DSA *d; #endif /* USE_DSA */ # ifdef USE_ECDSA EC_KEY *ec = NULL; # endif # ifdef HAVE_EVP_PKEY_KEYGEN EVP_PKEY_CTX *ctx; # else RSA *r; # endif #else int i; uint16_t offset = 0; #endif unsigned char *hmac; k = ldns_key_new(); if (!k) { return NULL; } switch(alg) { case LDNS_SIGN_RSAMD5: case LDNS_SIGN_RSASHA1: case LDNS_SIGN_RSASHA1_NSEC3: case LDNS_SIGN_RSASHA256: case LDNS_SIGN_RSASHA512: #ifdef HAVE_SSL #ifdef HAVE_EVP_PKEY_KEYGEN ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if(!ctx) { ldns_key_free(k); return NULL; } if(EVP_PKEY_keygen_init(ctx) <= 0) { ldns_key_free(k); EVP_PKEY_CTX_free(ctx); return NULL; } if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, size) <= 0) { ldns_key_free(k); EVP_PKEY_CTX_free(ctx); return NULL; } #ifndef S_SPLINT_S if (EVP_PKEY_keygen(ctx, &k->_key.key) <= 0) { ldns_key_free(k); EVP_PKEY_CTX_free(ctx); return NULL; } #endif EVP_PKEY_CTX_free(ctx); #else /* HAVE_EVP_PKEY_KEYGEN */ r = RSA_generate_key((int)size, RSA_F4, NULL, NULL); if(!r) { ldns_key_free(k); return NULL; } if (RSA_check_key(r) != 1) { ldns_key_free(k); return NULL; } ldns_key_set_rsa_key(k, r); RSA_free(r); #endif /* HAVE_EVP_PKEY_KEYGEN */ #endif /* HAVE_SSL */ break; #ifdef USE_DSA case LDNS_SIGN_DSA: case LDNS_SIGN_DSA_NSEC3: #ifdef HAVE_SSL # if OPENSSL_VERSION_NUMBER < 0x00908000L d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL); if (!d) { ldns_key_free(k); return NULL; } # else if (! (d = DSA_new())) { ldns_key_free(k); return NULL; } if (! DSA_generate_parameters_ex(d, (int)size, NULL, 0, NULL, NULL, NULL)) { DSA_free(d); ldns_key_free(k); return NULL; } # endif if (DSA_generate_key(d) != 1) { ldns_key_free(k); return NULL; } ldns_key_set_dsa_key(k, d); DSA_free(d); #endif /* HAVE_SSL */ #endif /* USE_DSA */ break; case LDNS_SIGN_HMACMD5: case LDNS_SIGN_HMACSHA1: case LDNS_SIGN_HMACSHA224: case LDNS_SIGN_HMACSHA256: case LDNS_SIGN_HMACSHA384: case LDNS_SIGN_HMACSHA512: #ifdef HAVE_SSL #ifndef S_SPLINT_S k->_key.key = NULL; #endif /* splint */ #endif /* HAVE_SSL */ size = size / 8; ldns_key_set_hmac_size(k, size); hmac = LDNS_XMALLOC(unsigned char, size); if(!hmac) { ldns_key_free(k); return NULL; } #ifdef HAVE_SSL if (RAND_bytes(hmac, (int) size) != 1) { LDNS_FREE(hmac); ldns_key_free(k); return NULL; } #else while (offset + sizeof(i) < size) { i = random(); memcpy(&hmac[offset], &i, sizeof(i)); offset += sizeof(i); } if (offset < size) { i = random(); memcpy(&hmac[offset], &i, size - offset); } #endif /* HAVE_SSL */ ldns_key_set_hmac_key(k, hmac); ldns_key_set_flags(k, 0); break; case LDNS_SIGN_ECC_GOST: #if defined(HAVE_SSL) && defined(USE_GOST) ldns_key_set_evp_key(k, ldns_gen_gost_key()); #ifndef S_SPLINT_S if(!k->_key.key) { ldns_key_free(k); return NULL; } #endif /* splint */ #else ldns_key_free(k); return NULL; #endif /* HAVE_SSL and USE_GOST */ break; case LDNS_SIGN_ECDSAP256SHA256: case LDNS_SIGN_ECDSAP384SHA384: #ifdef USE_ECDSA if(alg == LDNS_SIGN_ECDSAP256SHA256) ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); else if(alg == LDNS_SIGN_ECDSAP384SHA384) ec = EC_KEY_new_by_curve_name(NID_secp384r1); if(!ec) { ldns_key_free(k); return NULL; } if(!EC_KEY_generate_key(ec)) { ldns_key_free(k); EC_KEY_free(ec); return NULL; } #ifndef S_SPLINT_S k->_key.key = EVP_PKEY_new(); if(!k->_key.key) { ldns_key_free(k); EC_KEY_free(ec); return NULL; } if (!EVP_PKEY_assign_EC_KEY(k->_key.key, ec)) { ldns_key_free(k); EC_KEY_free(ec); return NULL; } #endif /* splint */ #else ldns_key_free(k); return NULL; #endif /* ECDSA */ break; #ifdef USE_ED25519 case LDNS_SIGN_ED25519: #ifdef HAVE_EVP_PKEY_KEYGEN ctx = EVP_PKEY_CTX_new_id(NID_ED25519, NULL); if(!ctx) { ldns_key_free(k); return NULL; } if(EVP_PKEY_keygen_init(ctx) <= 0) { ldns_key_free(k); EVP_PKEY_CTX_free(ctx); return NULL; } if (EVP_PKEY_keygen(ctx, &k->_key.key) <= 0) { ldns_key_free(k); EVP_PKEY_CTX_free(ctx); return NULL; } EVP_PKEY_CTX_free(ctx); #endif break; #endif /* ED25519 */ #ifdef USE_ED448 case LDNS_SIGN_ED448: #ifdef HAVE_EVP_PKEY_KEYGEN ctx = EVP_PKEY_CTX_new_id(NID_ED448, NULL); if(!ctx) { ldns_key_free(k); return NULL; } if(EVP_PKEY_keygen_init(ctx) <= 0) { ldns_key_free(k); EVP_PKEY_CTX_free(ctx); return NULL; } if (EVP_PKEY_keygen(ctx, &k->_key.key) <= 0) { ldns_key_free(k); EVP_PKEY_CTX_free(ctx); return NULL; } EVP_PKEY_CTX_free(ctx); #endif break; #endif /* ED448 */ } ldns_key_set_algorithm(k, alg); return k; } void ldns_key_print(FILE *output, const ldns_key *k) { char *str = ldns_key2str(k); if (str) { fprintf(output, "%s", str); } else { fprintf(output, "Unable to convert private key to string\n"); } LDNS_FREE(str); } void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l) { k->_alg = l; } void ldns_key_set_flags(ldns_key *k, uint16_t f) { k->_extra.dnssec.flags = f; } #ifdef HAVE_SSL #ifndef S_SPLINT_S void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e) { k->_key.key = e; } void ldns_key_set_rsa_key(ldns_key *k, RSA *r) { EVP_PKEY *key = EVP_PKEY_new(); EVP_PKEY_set1_RSA(key, r); k->_key.key = key; } void ldns_key_set_dsa_key(ldns_key *k, DSA *d) { #ifdef USE_DSA EVP_PKEY *key = EVP_PKEY_new(); EVP_PKEY_set1_DSA(key, d); k->_key.key = key; #else (void)k; (void)d; #endif } void ldns_key_assign_rsa_key(ldns_key *k, RSA *r) { EVP_PKEY *key = EVP_PKEY_new(); EVP_PKEY_assign_RSA(key, r); k->_key.key = key; } void ldns_key_assign_dsa_key(ldns_key *k, DSA *d) { #ifdef USE_DSA EVP_PKEY *key = EVP_PKEY_new(); EVP_PKEY_assign_DSA(key, d); k->_key.key = key; #else (void)k; (void)d; #endif } #endif /* splint */ #endif /* HAVE_SSL */ void ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac) { k->_key.hmac.key = hmac; } void ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size) { k->_key.hmac.size = hmac_size; } void ldns_key_set_external_key(ldns_key *k, void *external_key) { k->_key.external_key = external_key; } void ldns_key_set_origttl(ldns_key *k, uint32_t t) { k->_extra.dnssec.orig_ttl = t; } void ldns_key_set_inception(ldns_key *k, uint32_t i) { k->_extra.dnssec.inception = i; } void ldns_key_set_expiration(ldns_key *k, uint32_t e) { k->_extra.dnssec.expiration = e; } void ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r) { k->_pubkey_owner = r; } void ldns_key_set_keytag(ldns_key *k, uint16_t tag) { k->_extra.dnssec.keytag = tag; } /* read */ size_t ldns_key_list_key_count(const ldns_key_list *key_list) { return key_list ? key_list->_key_count : 0; } ldns_key * ldns_key_list_key(const ldns_key_list *key, size_t nr) { if (nr < ldns_key_list_key_count(key)) { return key->_keys[nr]; } else { return NULL; } } ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k) { return k->_alg; } void ldns_key_set_use(ldns_key *k, bool v) { if (k) { k->_use = v; } } bool ldns_key_use(const ldns_key *k) { if (k) { return k->_use; } return false; } #ifdef HAVE_SSL #ifndef S_SPLINT_S EVP_PKEY * ldns_key_evp_key(const ldns_key *k) { return k->_key.key; } RSA * ldns_key_rsa_key(const ldns_key *k) { if (k->_key.key) { return EVP_PKEY_get1_RSA(k->_key.key); } else { return NULL; } } DSA * ldns_key_dsa_key(const ldns_key *k) { #ifdef USE_DSA if (k->_key.key) { return EVP_PKEY_get1_DSA(k->_key.key); } else { return NULL; } #else (void)k; return NULL; #endif } #endif /* splint */ #endif /* HAVE_SSL */ unsigned char * ldns_key_hmac_key(const ldns_key *k) { if (k->_key.hmac.key) { return k->_key.hmac.key; } else { return NULL; } } size_t ldns_key_hmac_size(const ldns_key *k) { if (k->_key.hmac.size) { return k->_key.hmac.size; } else { return 0; } } void * ldns_key_external_key(const ldns_key *k) { return k->_key.external_key; } uint32_t ldns_key_origttl(const ldns_key *k) { return k->_extra.dnssec.orig_ttl; } uint16_t ldns_key_flags(const ldns_key *k) { return k->_extra.dnssec.flags; } uint32_t ldns_key_inception(const ldns_key *k) { return k->_extra.dnssec.inception; } uint32_t ldns_key_expiration(const ldns_key *k) { return k->_extra.dnssec.expiration; } uint16_t ldns_key_keytag(const ldns_key *k) { return k->_extra.dnssec.keytag; } ldns_rdf * ldns_key_pubkey_owner(const ldns_key *k) { return k->_pubkey_owner; } /* write */ void ldns_key_list_set_use(ldns_key_list *keys, bool v) { size_t i; for (i = 0; i < ldns_key_list_key_count(keys); i++) { ldns_key_set_use(ldns_key_list_key(keys, i), v); } } void ldns_key_list_set_key_count(ldns_key_list *key, size_t count) { key->_key_count = count; } bool ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key) { size_t key_count; ldns_key **keys; key_count = ldns_key_list_key_count(key_list); /* grow the array */ keys = LDNS_XREALLOC( key_list->_keys, ldns_key *, key_count + 1); if (!keys) { return false; } /* add the new member */ key_list->_keys = keys; key_list->_keys[key_count] = key; ldns_key_list_set_key_count(key_list, key_count + 1); return true; } ldns_key * ldns_key_list_pop_key(ldns_key_list *key_list) { size_t key_count; ldns_key** a; ldns_key *pop; if (!key_list) { return NULL; } key_count = ldns_key_list_key_count(key_list); if (key_count == 0) { return NULL; } pop = ldns_key_list_key(key_list, key_count); /* shrink the array */ a = LDNS_XREALLOC(key_list->_keys, ldns_key *, key_count - 1); if(a) { key_list->_keys = a; } ldns_key_list_set_key_count(key_list, key_count - 1); return pop; } #ifdef HAVE_SSL #ifndef S_SPLINT_S /* data pointer must be large enough (LDNS_MAX_KEYLEN) */ static bool ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size) { int i,j; const BIGNUM *n=NULL, *e=NULL; if (!k) { return false; } #if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000) n = k->n; e = k->e; #else RSA_get0_key(k, &n, &e, NULL); #endif if (BN_num_bytes(e) <= 256) { /* normally only this path is executed (small factors are * more common */ data[0] = (unsigned char) BN_num_bytes(e); i = BN_bn2bin(e, data + 1); j = BN_bn2bin(n, data + i + 1); *size = (uint16_t) i + j; } else if (BN_num_bytes(e) <= 65536) { data[0] = 0; /* BN_bn2bin does bigendian, _uint16 also */ ldns_write_uint16(data + 1, (uint16_t) BN_num_bytes(e)); BN_bn2bin(e, data + 3); BN_bn2bin(n, data + 4 + BN_num_bytes(e)); *size = (uint16_t) BN_num_bytes(n) + 6; } else { return false; } return true; } #ifdef USE_DSA /* data pointer must be large enough (LDNS_MAX_KEYLEN) */ static bool ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size) { uint8_t T; const BIGNUM *p, *q, *g; const BIGNUM *pub_key, *priv_key; if (!k) { return false; } /* See RFC2536 */ # ifdef HAVE_DSA_GET0_PQG DSA_get0_pqg(k, &p, &q, &g); # else p = k->p; q = k->q; g = k->g; # endif # ifdef HAVE_DSA_GET0_KEY DSA_get0_key(k, &pub_key, &priv_key); # else pub_key = k->pub_key; priv_key = k->priv_key; # endif (void)priv_key; *size = (uint16_t)BN_num_bytes(p); T = (*size - 64) / 8; if (T > 8) { #ifdef STDERR_MSGS fprintf(stderr, "DSA key with T > 8 (ie. > 1024 bits)"); fprintf(stderr, " not implemented\n"); #endif return false; } /* size = 64 + (T * 8); */ memset(data, 0, 21 + *size * 3); data[0] = (unsigned char)T; BN_bn2bin(q, data + 1 ); /* 20 octects */ BN_bn2bin(p, data + 21 ); /* offset octects */ BN_bn2bin(g, data + 21 + *size * 2 - BN_num_bytes(g)); BN_bn2bin(pub_key,data + 21 + *size * 3 - BN_num_bytes(pub_key)); *size = 21 + *size * 3; return true; } #endif /* USE_DSA */ #ifdef USE_GOST static bool ldns_key_gost2bin(unsigned char* data, EVP_PKEY* k, uint16_t* size) { int i; unsigned char* pp = NULL; if(i2d_PUBKEY(k, &pp) != 37 + 64) { /* expect 37 byte(ASN header) and 64 byte(X and Y) */ free(pp); return false; } /* omit ASN header */ for(i=0; i<64; i++) data[i] = pp[i+37]; free(pp); *size = 64; return true; } #endif /* USE_GOST */ #ifdef USE_ED25519 static bool ldns_key_ed255192bin(unsigned char* data, EVP_PKEY* k, uint16_t* size) { int i; unsigned char* pp = NULL; if(i2d_PUBKEY(k, &pp) != 12 + 32) { /* expect 12 byte(ASN header) and 32 byte(pubkey) */ free(pp); return false; } /* omit ASN header */ for(i=0; i<32; i++) data[i] = pp[i+12]; free(pp); *size = 32; return true; } #endif /* USE_ED25519 */ #ifdef USE_ED448 static bool ldns_key_ed4482bin(unsigned char* data, EVP_PKEY* k, uint16_t* size) { int i; unsigned char* pp = NULL; if(i2d_PUBKEY(k, &pp) != 12 + 57) { /* expect 12 byte(ASN header) and 57 byte(pubkey) */ free(pp); return false; } /* omit ASN header */ for(i=0; i<57; i++) data[i] = pp[i+12]; free(pp); *size = 57; return true; } #endif /* USE_ED448 */ #endif /* splint */ #endif /* HAVE_SSL */ ldns_rr * ldns_key2rr(const ldns_key *k) { /* this function will convert a the keydata contained in * rsa/dsa pointers to a DNSKEY rr. It will fill in as * much as it can, but it does not know about key-flags * for instance */ ldns_rr *pubkey; ldns_rdf *keybin; unsigned char *bin = NULL; uint16_t size = 0; #ifdef HAVE_SSL RSA *rsa = NULL; #ifdef USE_DSA DSA *dsa = NULL; #endif /* USE_DSA */ #endif /* HAVE_SSL */ #ifdef USE_ECDSA EC_KEY* ec; #endif int internal_data = 0; if (!k) { return NULL; } pubkey = ldns_rr_new(); switch (ldns_key_algorithm(k)) { case LDNS_SIGN_HMACMD5: case LDNS_SIGN_HMACSHA1: case LDNS_SIGN_HMACSHA224: case LDNS_SIGN_HMACSHA256: case LDNS_SIGN_HMACSHA384: case LDNS_SIGN_HMACSHA512: ldns_rr_set_type(pubkey, LDNS_RR_TYPE_KEY); break; default: ldns_rr_set_type(pubkey, LDNS_RR_TYPE_DNSKEY); break; } /* zero-th rdf - flags */ ldns_rr_push_rdf(pubkey, ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_key_flags(k))); /* first - proto */ ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, LDNS_DNSSEC_KEYPROTO)); if (ldns_key_pubkey_owner(k)) { ldns_rr_set_owner(pubkey, ldns_rdf_clone(ldns_key_pubkey_owner(k))); } /* third - da algorithm */ switch(ldns_key_algorithm(k)) { case LDNS_SIGN_RSAMD5: case LDNS_SIGN_RSASHA1: case LDNS_SIGN_RSASHA1_NSEC3: case LDNS_SIGN_RSASHA256: case LDNS_SIGN_RSASHA512: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); #ifdef HAVE_SSL rsa = ldns_key_rsa_key(k); if (rsa) { bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { ldns_rr_free(pubkey); return NULL; } if (!ldns_key_rsa2bin(bin, rsa, &size)) { LDNS_FREE(bin); ldns_rr_free(pubkey); return NULL; } RSA_free(rsa); internal_data = 1; } #endif size++; break; #ifdef USE_DSA case LDNS_SIGN_DSA: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA)); #ifdef HAVE_SSL dsa = ldns_key_dsa_key(k); if (dsa) { bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { ldns_rr_free(pubkey); return NULL; } if (!ldns_key_dsa2bin(bin, dsa, &size)) { LDNS_FREE(bin); ldns_rr_free(pubkey); return NULL; } DSA_free(dsa); internal_data = 1; } #endif /* HAVE_SSL */ #endif /* USE_DSA */ break; #ifdef USE_DSA case LDNS_SIGN_DSA_NSEC3: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA_NSEC3)); #ifdef HAVE_SSL dsa = ldns_key_dsa_key(k); if (dsa) { bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { ldns_rr_free(pubkey); return NULL; } if (!ldns_key_dsa2bin(bin, dsa, &size)) { LDNS_FREE(bin); ldns_rr_free(pubkey); return NULL; } DSA_free(dsa); internal_data = 1; } #endif /* HAVE_SSL */ #endif /* USE_DSA */ break; case LDNS_SIGN_ECC_GOST: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8( LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); #if defined(HAVE_SSL) && defined(USE_GOST) bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { ldns_rr_free(pubkey); return NULL; } #ifndef S_SPLINT_S if (!ldns_key_gost2bin(bin, k->_key.key, &size)) { LDNS_FREE(bin); ldns_rr_free(pubkey); return NULL; } #endif /* splint */ internal_data = 1; #else ldns_rr_free(pubkey); return NULL; #endif /* HAVE_SSL and USE_GOST */ break; case LDNS_SIGN_ECDSAP256SHA256: case LDNS_SIGN_ECDSAP384SHA384: #ifdef USE_ECDSA ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8( LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); bin = NULL; #ifndef S_SPLINT_S ec = EVP_PKEY_get1_EC_KEY(k->_key.key); #endif EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); size = (uint16_t)i2o_ECPublicKey(ec, NULL); if(!i2o_ECPublicKey(ec, &bin)) { EC_KEY_free(ec); ldns_rr_free(pubkey); return NULL; } if(size > 1) { /* move back one byte to shave off the 0x02 * 'uncompressed' indicator that openssl made * Actually its 0x04 (from implementation). */ assert(bin[0] == POINT_CONVERSION_UNCOMPRESSED); size -= 1; memmove(bin, bin+1, size); } /* down the reference count for ec, its still assigned * to the pkey */ EC_KEY_free(ec); internal_data = 1; #else ldns_rr_free(pubkey); return NULL; #endif /* ECDSA */ break; #ifdef USE_ED25519 case LDNS_SIGN_ED25519: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8( LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { ldns_rr_free(pubkey); return NULL; } if (!ldns_key_ed255192bin(bin, k->_key.key, &size)) { LDNS_FREE(bin); ldns_rr_free(pubkey); return NULL; } internal_data = 1; break; #endif #ifdef USE_ED448 case LDNS_SIGN_ED448: ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8( LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); if (!bin) { ldns_rr_free(pubkey); return NULL; } if (!ldns_key_ed4482bin(bin, k->_key.key, &size)) { LDNS_FREE(bin); ldns_rr_free(pubkey); return NULL; } internal_data = 1; break; #endif case LDNS_SIGN_HMACMD5: case LDNS_SIGN_HMACSHA1: case LDNS_SIGN_HMACSHA224: case LDNS_SIGN_HMACSHA256: case LDNS_SIGN_HMACSHA384: case LDNS_SIGN_HMACSHA512: bin = LDNS_XMALLOC(unsigned char, ldns_key_hmac_size(k)); if (!bin) { ldns_rr_free(pubkey); return NULL; } ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); size = ldns_key_hmac_size(k); memcpy(bin, ldns_key_hmac_key(k), size); internal_data = 1; break; } /* fourth the key bin material */ if (internal_data) { keybin = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, size, bin); LDNS_FREE(bin); ldns_rr_push_rdf(pubkey, keybin); } return pubkey; } void ldns_key_free(ldns_key *key) { LDNS_FREE(key); } void ldns_key_deep_free(ldns_key *key) { unsigned char* hmac; if (ldns_key_pubkey_owner(key)) { ldns_rdf_deep_free(ldns_key_pubkey_owner(key)); } #ifdef HAVE_SSL if (ldns_key_evp_key(key)) { EVP_PKEY_free(ldns_key_evp_key(key)); } #endif /* HAVE_SSL */ if (ldns_key_hmac_key(key)) { hmac = ldns_key_hmac_key(key); LDNS_FREE(hmac); } LDNS_FREE(key); } void ldns_key_list_free(ldns_key_list *key_list) { size_t i; for (i = 0; i < ldns_key_list_key_count(key_list); i++) { ldns_key_deep_free(ldns_key_list_key(key_list, i)); } LDNS_FREE(key_list->_keys); LDNS_FREE(key_list); } ldns_rr * ldns_read_anchor_file(const char *filename) { FILE *fp; /*char line[LDNS_MAX_PACKETLEN];*/ char *line = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN); int c; size_t i = 0; ldns_rr *r; ldns_status status; if(!line) { return NULL; } fp = fopen(filename, "r"); if (!fp) { #ifdef STDERR_MSGS fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); #endif LDNS_FREE(line); return NULL; } while ((c = fgetc(fp)) && i+1 < LDNS_MAX_PACKETLEN && c != EOF) { line[i] = c; i++; } line[i] = '\0'; fclose(fp); if (i <= 0) { #ifdef STDERR_MSGS fprintf(stderr, "nothing read from %s", filename); #endif LDNS_FREE(line); return NULL; } else { status = ldns_rr_new_frm_str(&r, line, 0, NULL, NULL); if (status == LDNS_STATUS_OK && (ldns_rr_get_type(r) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(r) == LDNS_RR_TYPE_DS)) { LDNS_FREE(line); return r; } else { #ifdef STDERR_MSGS fprintf(stderr, "Error creating DNSKEY or DS rr from %s: %s\n", filename, ldns_get_errorstr_by_id(status)); #endif LDNS_FREE(line); return NULL; } } } char * ldns_key_get_file_base_name(const ldns_key *key) { ldns_buffer *buffer; char *file_base_name; buffer = ldns_buffer_new(255); ldns_buffer_printf(buffer, "K"); (void)ldns_rdf2buffer_str_dname(buffer, ldns_key_pubkey_owner(key)); ldns_buffer_printf(buffer, "+%03u+%05u", ldns_key_algorithm(key), ldns_key_keytag(key)); file_base_name = ldns_buffer_export(buffer); ldns_buffer_free(buffer); return file_base_name; } int ldns_key_algo_supported(int algo) { ldns_lookup_table *lt = ldns_signing_algorithms; while(lt->name) { if(lt->id == algo) return 1; lt++; } return 0; } ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name) { /* list of (signing algorithm id, alias_name) */ ldns_lookup_table aliases[] = { /* from bind dnssec-keygen */ {LDNS_SIGN_HMACMD5, "HMAC-MD5"}, #ifdef USE_DSA {LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"}, #endif /* USE_DSA */ {LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"}, /* old ldns usage, now RFC names */ #ifdef USE_DSA {LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" }, #endif {LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" }, #ifdef USE_GOST {LDNS_SIGN_ECC_GOST, "GOST"}, #endif /* compat with possible output */ {LDNS_DH, "DH"}, {LDNS_ECC, "ECC"}, {LDNS_INDIRECT, "INDIRECT"}, {LDNS_PRIVATEDNS, "PRIVATEDNS"}, {LDNS_PRIVATEOID, "PRIVATEOID"}, {0, NULL}}; ldns_lookup_table* lt = ldns_signing_algorithms; ldns_signing_algorithm a; char *endptr; while(lt->name) { if(strcasecmp(lt->name, name) == 0) return lt->id; lt++; } lt = aliases; while(lt->name) { if(strcasecmp(lt->name, name) == 0) return lt->id; lt++; } a = strtol(name, &endptr, 10); if (*name && !*endptr) return a; return 0; } ldns-1.8.4/libdns.vim0000664000175000017500000004621514646643036014046 0ustar willemwillem" Vim syntax file " Language: C libdns " Maintainer: miekg " Last change: 2011-09-15 " ldns/util.h syn keyword ldnsMacro LDNS_MALLOC syn keyword ldnsMacro LDNS_XMALLOC syn keyword ldnsMacro LDNS_CALLOC syn keyword ldnsMacro LDNS_REALLOC syn keyword ldnsMacro LDNS_XREALLOC syn keyword ldnsMacro LDNS_FREE syn keyword ldnsMacro LDNS_DEP syn keyword ldnsMacro LDNS_VERSION syn keyword ldnsMacro LDNS_REVISION " ldns/dname.h syn keyword ldnsMacro LDNS_DNAME_NORMALIZE " ldns/tsig.h syn keyword ldnsType ldns_tsig_credentials " ldns/update.h " -- " ldns/rdata.h syn keyword ldnsType ldns_rdf syn keyword ldnsType ldns_rdf_type syn keyword ldnsType ldns_cert_algorithm syn keyword ldnsConstant LDNS_RDF_TYPE_NONE syn keyword ldnsConstant LDNS_RDF_TYPE_DNAME syn keyword ldnsConstant LDNS_RDF_TYPE_INT8 syn keyword ldnsConstant LDNS_RDF_TYPE_INT16 syn keyword ldnsConstant LDNS_RDF_TYPE_INT16_DATA syn keyword ldnsConstant LDNS_RDF_TYPE_INT32 syn keyword ldnsConstant LDNS_RDF_TYPE_A syn keyword ldnsConstant LDNS_RDF_TYPE_AAAA syn keyword ldnsConstant LDNS_RDF_TYPE_STR syn keyword ldnsConstant LDNS_RDF_TYPE_APL syn keyword ldnsConstant LDNS_RDF_TYPE_B32_EXT syn keyword ldnsConstant LDNS_RDF_TYPE_B64 syn keyword ldnsConstant LDNS_RDF_TYPE_HEX syn keyword ldnsConstant LDNS_RDF_TYPE_NSEC syn keyword ldnsConstant LDNS_RDF_TYPE_TYPE syn keyword ldnsConstant LDNS_RDF_TYPE_CLASS syn keyword ldnsConstant LDNS_RDF_TYPE_CERT syn keyword ldnsConstant LDNS_RDF_TYPE_CERT_ALG syn keyword ldnsConstant LDNS_RDF_TYPE_ALG syn keyword ldnsConstant LDNS_RDF_TYPE_UNKNOWN syn keyword ldnsConstant LDNS_RDF_TYPE_TIME syn keyword ldnsConstant LDNS_RDF_TYPE_PERIOD syn keyword ldnsConstant LDNS_RDF_TYPE_TSIGTIME syn keyword ldnsConstant LDNS_RDF_TYPE_SERVICE syn keyword ldnsConstant LDNS_RDF_TYPE_LOC syn keyword ldnsConstant LDNS_RDF_TYPE_WKS syn keyword ldnsConstant LDNS_RDF_TYPE_NSAP syn keyword ldnsConstant LDNS_RDF_TYPE_ATMA syn keyword ldnsConstant LDNS_RDF_TYPE_NSEC3_SALT syn keyword ldnsConstant LDNS_RDF_TYPE_NSEC3_NEXT_OWNER syn keyword ldnsConstant LDNS_RDF_TYPE_IPSECKEY syn keyword ldnsConstant LDNS_RDF_TYPE_TSIG syn keyword ldnsConstant LDNS_MAX_RDFLEN syn keyword ldnsConstant LDNS_RDF_SIZE_BYTE syn keyword ldnsConstant LDNS_RDF_SIZE_WORD syn keyword ldnsConstant LDNS_RDF_SIZE_DOUBLEWORD syn keyword ldnsConstant LDNS_RDF_SIZE_6BYTES syn keyword ldnsConstant LDNS_RDF_SIZE_16BYTES syn keyword ldnsConstant LDNS_NSEC3_VARS_OPTOUT_MASK syn keyword ldnsConstant LDNS_CERT_PKIX syn keyword ldnsConstant LDNS_CERT_SPKI syn keyword ldnsConstant LDNS_CERT_PGP syn keyword ldnsConstant LDNS_CERT_IPKIX syn keyword ldnsConstant LDNS_CERT_ISPKI syn keyword ldnsConstant LDNS_CERT_IPGP syn keyword ldnsConstant LDNS_CERT_ACPKIX syn keyword ldnsConstant LDNS_CERT_IACPKIX syn keyword ldnsConstant LDNS_CERT_URI syn keyword ldnsConstant LDNS_CERT_OID " ldns/ldns.h syn keyword ldnsConstant LDNS_PORT syn keyword ldnsConstant LDNS_IP4ADDRLEN syn keyword ldnsConstant LDNS_IP6ADDRLEN syn keyword ldnsConstant LDNS_ROOT_LABEL_STR syn keyword ldnsConstant LDNS_DEFAULT_TTL " ldns/packet.h syn keyword ldnsType ldns_pkt syn keyword ldnsType ldns_pkt_section syn keyword ldnsType ldns_pkt_type syn keyword ldnsType ldns_pkt_opcode syn keyword ldnsType ldns_pkt_rcode syn keyword ldnsType ldns_hdr syn keyword ldnsConstant LDNS_QR syn keyword ldnsConstant LDNS_AA syn keyword ldnsConstant LDNS_TC syn keyword ldnsConstant LDNS_RD syn keyword ldnsConstant LDNS_CD syn keyword ldnsConstant LDNS_RA syn keyword ldnsConstant LDNS_AD syn keyword ldnsConstant LDNS_MAX_PACKETLEN syn keyword ldnsConstant LDNS_PACKET_QUESTION syn keyword ldnsConstant LDNS_PACKET_REFERRAL syn keyword ldnsConstant LDNS_PACKET_ANSWER syn keyword ldnsConstant LDNS_PACKET_NXDOMAIN syn keyword ldnsConstant LDNS_PACKET_NODATA syn keyword ldnsConstant LDNS_PACKET_UNKNOWN syn keyword ldnsConstant LDNS_SECTION_QUESTION syn keyword ldnsConstant LDNS_SECTION_ANSWER syn keyword ldnsConstant LDNS_SECTION_AUTHORITY syn keyword ldnsConstant LDNS_SECTION_ADDITIONAL syn keyword ldnsConstant LDNS_SECTION_ANY syn keyword ldnsConstant LDNS_SECTION_ANY_NOQUESTION syn keyword ldnsConstant LDNS_PACKET_QUERY syn keyword ldnsConstant LDNS_PACKET_IQUERY syn keyword ldnsConstant LDNS_PACKET_STATUS syn keyword ldnsConstant LDNS_PACKET_NOTIFY syn keyword ldnsConstant LDNS_PACKET_UPDATE syn keyword ldnsConstant LDNS_RCODE_NOERROR syn keyword ldnsConstant LDNS_RCODE_FORMERR syn keyword ldnsConstant LDNS_RCODE_SERVFAIL syn keyword ldnsConstant LDNS_RCODE_NXDOMAIN syn keyword ldnsConstant LDNS_RCODE_NOTIMPL syn keyword ldnsConstant LDNS_RCODE_REFUSED syn keyword ldnsConstant LDNS_RCODE_YXDOMAIN syn keyword ldnsConstant LDNS_RCODE_YXRRSET syn keyword ldnsConstant LDNS_RCODE_NXRRSET syn keyword ldnsConstant LDNS_RCODE_NOTAUTH syn keyword ldnsConstant LDNS_RCODE_NOTZONE " dns/error.h syn keyword ldnsConstant LDNS_STATUS_OK syn keyword ldnsConstant LDNS_STATUS_EMPTY_LABEL syn keyword ldnsConstant LDNS_STATUS_LABEL_OVERFLOW syn keyword ldnsConstant LDNS_STATUS_DOMAINNAME_OVERFLOW syn keyword ldnsConstant LDNS_STATUS_DOMAINNAME_UNDERFLOW syn keyword ldnsConstant LDNS_STATUS_DDD_OVERFLOW syn keyword ldnsConstant LDNS_STATUS_PACKET_OVERFLOW syn keyword ldnsConstant LDNS_STATUS_INVALID_POINTER syn keyword ldnsConstant LDNS_STATUS_MEM_ERR syn keyword ldnsConstant LDNS_STATUS_INTERNAL_ERR syn keyword ldnsConstant LDNS_STATUS_SSL_ERR syn keyword ldnsConstant LDNS_STATUS_ERR syn keyword ldnsConstant LDNS_STATUS_INVALID_INT syn keyword ldnsConstant LDNS_STATUS_INVALID_IP4 syn keyword ldnsConstant LDNS_STATUS_INVALID_IP6 syn keyword ldnsConstant LDNS_STATUS_INVALID_STR syn keyword ldnsConstant LDNS_STATUS_INVALID_B32_EXT syn keyword ldnsConstant LDNS_STATUS_INVALID_B64 syn keyword ldnsConstant LDNS_STATUS_INVALID_HEX syn keyword ldnsConstant LDNS_STATUS_INVALID_TIME syn keyword ldnsConstant LDNS_STATUS_NETWORK_ERR syn keyword ldnsConstant LDNS_STATUS_ADDRESS_ERR syn keyword ldnsConstant LDNS_STATUS_FILE_ERR syn keyword ldnsConstant LDNS_STATUS_UNKNOWN_INET syn keyword ldnsConstant LDNS_STATUS_NOT_IMPL syn keyword ldnsConstant LDNS_STATUS_NULL syn keyword ldnsConstant LDNS_STATUS_CRYPTO_UNKNOWN_ALGO syn keyword ldnsConstant LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_RRSIG syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_DNSKEY syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_DS syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_TRUSTED_DS syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY syn keyword ldnsConstant LDNS_STATUS_CRYPTO_VALIDATED syn keyword ldnsConstant LDNS_STATUS_CRYPTO_BOGUS syn keyword ldnsConstant LDNS_STATUS_CRYPTO_SIG_EXPIRED syn keyword ldnsConstant LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED syn keyword ldnsConstant LDNS_STATUS_CRYPTO_TSIG_BOGUS syn keyword ldnsConstant LDNS_STATUS_CRYPTO_TSIG_ERR syn keyword ldnsConstant LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION syn keyword ldnsConstant LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR syn keyword ldnsConstant LDNS_STATUS_ENGINE_KEY_NOT_LOADED syn keyword ldnsConstant LDNS_STATUS_NSEC3_ERR syn keyword ldnsConstant LDNS_STATUS_RES_NO_NS syn keyword ldnsConstant LDNS_STATUS_RES_QUERY syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_HEADER syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_QUESTION syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_ANSWER syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL syn keyword ldnsConstant LDNS_STATUS_NO_DATA syn keyword ldnsConstant LDNS_STATUS_CERT_BAD_ALGORITHM syn keyword ldnsConstant LDNS_STATUS_SYNTAX_TYPE_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_CLASS_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_TTL_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL syn keyword ldnsConstant LDNS_STATUS_SYNTAX_RDATA_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_DNAME_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_VERSION_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_ALG_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_KEYWORD_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_TTL syn keyword ldnsConstant LDNS_STATUS_SYNTAX_ORIGIN syn keyword ldnsConstant LDNS_STATUS_SYNTAX_INCLUDE syn keyword ldnsConstant LDNS_STATUS_SYNTAX_EMPTY syn keyword ldnsConstant LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW syn keyword ldnsConstant LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW syn keyword ldnsConstant LDNS_STATUS_SYNTAX_BAD_ESCAPE syn keyword ldnsConstant LDNS_STATUS_SOCKET_ERROR syn keyword ldnsConstant LDNS_STATUS_SYNTAX_ERR syn keyword ldnsConstant LDNS_STATUS_DNSSEC_EXISTENCE_DENIED syn keyword ldnsConstant LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED syn keyword ldnsConstant LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED syn keyword ldnsConstant LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND syn keyword ldnsConstant LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG syn keyword ldnsConstant LDNS_STATUS_MISSING_RDATA_FIELDS_KEY " ldns/resolver.h syn keyword ldnsType ldns_resolver syn keyword ldnsConstant LDNS_RESOLV_CONF syn keyword ldnsConstant LDNS_RESOLV_HOSTS syn keyword ldnsConstant LDNS_RESOLV_KEYWORD syn keyword ldnsConstant LDNS_RESOLV_DEFDOMAIN syn keyword ldnsConstant LDNS_RESOLV_NAMESERVER syn keyword ldnsConstant LDNS_RESOLV_SEARCH syn keyword ldnsConstant LDNS_RESOLV_SORTLIST syn keyword ldnsConstant LDNS_RESOLV_OPTIONS syn keyword ldnsConstant LDNS_RESOLV_ANCHOR syn keyword ldnsConstant LDNS_RESOLV_KEYWORDS syn keyword ldnsConstant LDNS_RESOLV_INETANY syn keyword ldnsConstant LDNS_RESOLV_INET syn keyword ldnsConstant LDNS_RESOLV_INET6 syn keyword ldnsConstant LDNS_RESOLV_RTT_INF syn keyword ldnsConstant LDNS_RESOLV_RTT_MIN " ldns/zone.h syn keyword ldnsType ldns_zone " ldns/dnssec.h syn keyword ldnsConstant LDNS_NSEC3_MAX_ITERATIONS syn keyword ldnsConstant LDNS_DEFAULT_EXP_TIME syn keyword ldnsConstant LDNS_DNSSEC_KEYPROTO syn keyword ldnsConstant LDNS_MAX_KEYLEN " ldns/dnssec_sign.h " -- " ldns/dnssec_zone.h syn keyword ldnsType ldns_dnssec_rrs syn keyword ldnsType ldns_dnssec_rrsets syn keyword ldnsType ldns_dnssec_name syn keyword ldnsType ldns_dnssec_zone " ldns/dnssec_verify.h syn keyword ldnsType ldns_dnssec_data_chain syn keyword ldnsType ldns_dnssec_trust_tree " ldns/rr.h syn keyword ldnsType ldns_rr_list syn keyword ldnsType ldns_rr_descriptor syn keyword ldnsType ldns_rr syn keyword ldnsType ldns_rr_type syn keyword ldnsType ldns_rr_class syn keyword ldnsType ldns_rr_compress syn keyword ldnsConstant LDNS_MAX_LABELLEN syn keyword ldnsConstant LDNS_MAX_DOMAINLEN syn keyword ldnsConstant LDNS_RR_COMPRESS syn keyword ldnsConstant LDNS_RR_NO_COMPRESS syn keyword ldnsConstant LDNS_RR_CLASS_IN syn keyword ldnsConstant LDNS_RR_CLASS_CH syn keyword ldnsConstant LDNS_RR_CLASS_HS syn keyword ldnsConstant LDNS_RR_CLASS_NONE syn keyword ldnsConstant LDNS_RR_CLASS_ANY syn keyword ldnsConstant LDNS_RR_TYPE_A syn keyword ldnsConstant LDNS_RR_TYPE_A6 syn keyword ldnsConstant LDNS_RR_TYPE_AAAA syn keyword ldnsConstant LDNS_RR_TYPE_AFSDB syn keyword ldnsConstant LDNS_RR_TYPE_ANY syn keyword ldnsConstant LDNS_RR_TYPE_APL syn keyword ldnsConstant LDNS_RR_TYPE_ATMA syn keyword ldnsConstant LDNS_RR_TYPE_AXFR syn keyword ldnsConstant LDNS_RR_TYPE_CERT syn keyword ldnsConstant LDNS_RR_TYPE_CNAME syn keyword ldnsConstant LDNS_RR_TYPE_COUNT syn keyword ldnsConstant LDNS_RR_TYPE_DHCID syn keyword ldnsConstant LDNS_RR_TYPE_DLV syn keyword ldnsConstant LDNS_RR_TYPE_DNAME syn keyword ldnsConstant LDNS_RR_TYPE_DNSKEY syn keyword ldnsConstant LDNS_RR_TYPE_DS syn keyword ldnsConstant LDNS_RR_TYPE_EID syn keyword ldnsConstant LDNS_RR_TYPE_FIRST syn keyword ldnsConstant LDNS_RR_TYPE_GID syn keyword ldnsConstant LDNS_RR_TYPE_GPOS syn keyword ldnsConstant LDNS_RR_TYPE_HINFO syn keyword ldnsConstant LDNS_RR_TYPE_IPSECKEY syn keyword ldnsConstant LDNS_RR_TYPE_ISDN syn keyword ldnsConstant LDNS_RR_TYPE_IXFR syn keyword ldnsConstant LDNS_RR_TYPE_KEY syn keyword ldnsConstant LDNS_RR_TYPE_KX syn keyword ldnsConstant LDNS_RR_TYPE_LAST syn keyword ldnsConstant LDNS_RR_TYPE_LOC syn keyword ldnsConstant LDNS_RR_TYPE_MAILA syn keyword ldnsConstant LDNS_RR_TYPE_MAILB syn keyword ldnsConstant LDNS_RR_TYPE_MB syn keyword ldnsConstant LDNS_RR_TYPE_MD syn keyword ldnsConstant LDNS_RR_TYPE_MF syn keyword ldnsConstant LDNS_RR_TYPE_MG syn keyword ldnsConstant LDNS_RR_TYPE_MINFO syn keyword ldnsConstant LDNS_RR_TYPE_MR syn keyword ldnsConstant LDNS_RR_TYPE_MX syn keyword ldnsConstant LDNS_RR_TYPE_NAPTR syn keyword ldnsConstant LDNS_RR_TYPE_NIMLOC syn keyword ldnsConstant LDNS_RR_TYPE_NS syn keyword ldnsConstant LDNS_RR_TYPE_NSAP syn keyword ldnsConstant LDNS_RR_TYPE_NSAP_PTR syn keyword ldnsConstant LDNS_RR_TYPE_NSEC syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3 syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3 syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3PARAM syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3PARAMS syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3PARAMS syn keyword ldnsConstant LDNS_RR_TYPE_NULL syn keyword ldnsConstant LDNS_RR_TYPE_NXT syn keyword ldnsConstant LDNS_RR_TYPE_OPT syn keyword ldnsConstant LDNS_RR_TYPE_PTR syn keyword ldnsConstant LDNS_RR_TYPE_PX syn keyword ldnsConstant LDNS_RR_TYPE_RP syn keyword ldnsConstant LDNS_RR_TYPE_RRSIG syn keyword ldnsConstant LDNS_RR_TYPE_RT syn keyword ldnsConstant LDNS_RR_TYPE_SIG syn keyword ldnsConstant LDNS_RR_TYPE_SINK syn keyword ldnsConstant LDNS_RR_TYPE_SOA syn keyword ldnsConstant LDNS_RR_TYPE_SPF syn keyword ldnsConstant LDNS_RR_TYPE_SRV syn keyword ldnsConstant LDNS_RR_TYPE_SSHFP syn keyword ldnsConstant LDNS_RR_TYPE_TALINK syn keyword ldnsConstant LDNS_RR_TYPE_TSIG syn keyword ldnsConstant LDNS_RR_TYPE_TXT syn keyword ldnsConstant LDNS_RR_TYPE_UID syn keyword ldnsConstant LDNS_RR_TYPE_UINFO syn keyword ldnsConstant LDNS_RR_TYPE_UNSPEC syn keyword ldnsConstant LDNS_RR_TYPE_WKS syn keyword ldnsConstant LDNS_RR_TYPE_X25 " ldns/buffer.h syn keyword ldnsType ldns_buffer syn keyword ldnsConstant LDNS_MIN_BUFLEN " ldns/host2str.h syn keyword ldnsConstant LDNS_APL_IP4 syn keyword ldnsConstant LDNS_APL_IP6 syn keyword ldnsConstant LDNS_APL_MASK syn keyword ldnsConstant LDNS_APL_NEGATION " ldns/keys.h syn keyword ldnsType ldns_key syn keyword ldnsType ldns_key_list syn keyword ldnsType ldns_signing_algorithm syn keyword ldnsType ldns_hash syn keyword ldnsType ldns_algorithm syn keyword ldnsConstant LDNS_KEY_ZONE_KEY syn keyword ldnsConstant LDNS_KEY_SEP_KEY syn keyword ldnsConstant LDNS_KEY_REVOKE_KEY syn keyword ldnsConstant LDNS_SHA1 syn keyword ldnsConstant LDNS_SHA256 syn keyword ldnsConstant LDNS_HASH_GOST syn keyword ldnsConstant LDNS_SHA384 syn keyword ldnsConstant LDNS_SIGN_RSAMD5 syn keyword ldnsConstant LDNS_SIGN_RSASHA1 syn keyword ldnsConstant LDNS_SIGN_DSA syn keyword ldnsConstant LDNS_SIGN_RSASHA1_NSEC3 syn keyword ldnsConstant LDNS_SIGN_RSASHA256 syn keyword ldnsConstant LDNS_SIGN_RSASHA512 syn keyword ldnsConstant LDNS_SIGN_DSA_NSEC3 syn keyword ldnsConstant LDNS_SIGN_ECC_GOST syn keyword ldnsConstant LDNS_SIGN_ECDSAP256SHA256 syn keyword ldnsConstant LDNS_SIGN_ECDSAP384SHA384 syn keyword ldnsConstant LDNS_SIGN_HMACMD5 syn keyword ldnsConstant LDNS_SIGN_HMACSHA1 syn keyword ldnsConstant LDNS_SIGN_HMACSHA256 " ldns/wire2host.h syn keyword ldnsMacro LDNS_WIRE2HOST_H syn keyword ldnsMacro LDNS_HEADER_SIZE syn keyword ldnsMacro LDNS_RD_MASK syn keyword ldnsMacro LDNS_RD_SHIFT syn keyword ldnsMacro LDNS_RD_WIRE syn keyword ldnsMacro LDNS_RD_SET syn keyword ldnsMacro LDNS_RD_CLR syn keyword ldnsMacro LDNS_TC_MASK syn keyword ldnsMacro LDNS_TC_SHIFT syn keyword ldnsMacro LDNS_TC_WIRE syn keyword ldnsMacro LDNS_TC_SET syn keyword ldnsMacro LDNS_TC_CLR syn keyword ldnsMacro LDNS_AA_MASK syn keyword ldnsMacro LDNS_AA_SHIFT syn keyword ldnsMacro LDNS_AA_WIRE syn keyword ldnsMacro LDNS_AA_SET syn keyword ldnsMacro LDNS_AA_CLR syn keyword ldnsMacro LDNS_OPCODE_MASK syn keyword ldnsMacro LDNS_OPCODE_SHIFT syn keyword ldnsMacro LDNS_OPCODE_WIRE syn keyword ldnsMacro LDNS_OPCODE_SET syn keyword ldnsMacro LDNS_QR_MASK syn keyword ldnsMacro LDNS_QR_SHIFT syn keyword ldnsMacro LDNS_QR_WIRE syn keyword ldnsMacro LDNS_QR_SET syn keyword ldnsMacro LDNS_QR_CLR syn keyword ldnsMacro LDNS_RCODE_MASK syn keyword ldnsMacro LDNS_RCODE_SHIFT syn keyword ldnsMacro LDNS_RCODE_WIRE syn keyword ldnsMacro LDNS_RCODE_SET syn keyword ldnsMacro LDNS_CD_MASK syn keyword ldnsMacro LDNS_CD_SHIFT syn keyword ldnsMacro LDNS_CD_WIRE syn keyword ldnsMacro LDNS_CD_SET syn keyword ldnsMacro LDNS_CD_CLR syn keyword ldnsMacro LDNS_AD_MASK syn keyword ldnsMacro LDNS_AD_SHIFT syn keyword ldnsMacro LDNS_AD_WIRE syn keyword ldnsMacro LDNS_AD_SET syn keyword ldnsMacro LDNS_AD_CLR syn keyword ldnsMacro LDNS_Z_MASK syn keyword ldnsMacro LDNS_Z_SHIFT syn keyword ldnsMacro LDNS_Z_WIRE syn keyword ldnsMacro LDNS_Z_SET syn keyword ldnsMacro LDNS_Z_CLR syn keyword ldnsMacro LDNS_RA_MASK syn keyword ldnsMacro LDNS_RA_SHIFT syn keyword ldnsMacro LDNS_RA_WIRE syn keyword ldnsMacro LDNS_RA_SET syn keyword ldnsMacro LDNS_RA_CLR syn keyword ldnsMacro LDNS_ID_WIRE syn keyword ldnsMacro LDNS_ID_SET syn keyword ldnsMacro LDNS_QDCOUNT_OFF syn keyword ldnsMacro QDCOUNT syn keyword ldnsMacro LDNS_QDCOUNT syn keyword ldnsMacro LDNS_ANCOUNT_OFF syn keyword ldnsMacro LDNS_ANCOUNT syn keyword ldnsMacro LDNS_NSCOUNT_OFF syn keyword ldnsMacro LDNS_NSCOUNT syn keyword ldnsMacro LDNS_ARCOUNT_OFF syn keyword ldnsMacro LDNS_ARCOUNT " ldns/host2wire.h " -- " ldns/* -- All functions " Created with: " Get all the functions that start with 'ldns_' " egrep '^[a-z_]+ [*a-z_0-9]+\(' *.h | sed -e 's/(.*$//' | awk '{print $2}' | \ " sed 's/^\*//' | grep '^ldns' | sort " Not included, but could be added...? " Default highlighting command -nargs=+ HiLink hi def link HiLink ldnsType Type " Currently no functions are defined HiLink ldnsFunction Function HiLink ldnsMacro Macro HiLink ldnsConstant Constant delcommand HiLink ldns-1.8.4/libdns.doxygen.in0000664000175000017500000034037714646643036015343 0ustar willemwillem# Doxyfile 1.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the configuration # file that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = @PACKAGE_NAME@ # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = @PACKAGE_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = @srcdir@/doc/images/LogoInGradientBar2-y100.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = doc/ # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all generated output in the proper direction. # Possible values are: None, LTR, RTL and Context. # The default value is: None. OUTPUT_TEXT_DIRECTION = None # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line # such as # /*************** # as being the beginning of a Javadoc-style comment "banner". If set to NO, the # Javadoc-style will behave just like regular comments and it will not be # interpreted by doxygen. # The default value is: NO. JAVADOC_BANNER = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # By default Python docstrings are displayed as preformatted text and doxygen's # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the # doxygen's special commands can be used and the contents of the docstring # documentation blocks is shown as doxygen documentation. # The default value is: YES. PYTHON_DOCSTRING = YES # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines (in the resulting output). You can put ^^ in the value part of an # alias to insert a newline as if a physical newline was in the original file. # When you need a literal { or } or , in the value part of an alias you have to # escape them by means of a backslash (\), this can lead to conflicts with the # commands \{ and \} for these it is advised to use the version @{ and @} or use # a double escape (\\{ and \\}) ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice # sources only. Doxygen will then generate output that is more tailored for that # language. For instance, namespaces will be presented as modules, types will be # separated into more groups, etc. # The default value is: NO. OPTIMIZE_OUTPUT_SLICE = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, # Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, # Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the # default for Fortran type files). For instance to make doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 5 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 # The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use # during processing. When set to 0 doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, # which efficively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. NUM_PROC_THREADS = 1 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual # methods of a class will be included in the documentation. # The default value is: NO. EXTRACT_PRIV_VIRTUAL = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If this flag is set to YES, the name of an unnamed parameter in a declaration # will be determined by the corresponding definition. By default unnamed # parameters remain unnamed in the output. # The default value is: YES. RESOLVE_UNNAMED_PARAMS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # With the correct setting of option CASE_SENSE_NAMES doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that # are not case sensitive the option should be be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On # Windows (including Cygwin) and MacOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = NO # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. If # EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # at the end of the doxygen process doxygen will return with a non-zero status. # Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "doxygen: $file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = ldns/ \ @srcdir@/doc/ \ @srcdir@/examples/ldns-mx.c \ @srcdir@/examples/ldns-read-zone.c \ @srcdir@/examples/ldns-signzone.c \ @srcdir@ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), # *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, # *.ucf, *.qsf and *.ice. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = @srcdir@/examples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = @srcdir@/doc/images # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: # http://clang.llvm.org/) for more accurate parsing at the cost of reduced # performance. This can be particularly helpful with template rich C++ code for # which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to # YES then doxygen will add the directory of each input to the include path. # The default value is: YES. CLANG_ADD_INC_PATHS = YES # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = # If clang assisted parsing is enabled you can provide the clang parser with the # path to the directory containing a file called compile_commands.json. This # file is the compilation database (see: # http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the # options used when the source files were built. This is equivalent to # specifying the -p option to a clang tool, such as clang-check. These options # will then be passed to the parser. Any options specified with CLANG_OPTIONS # will be added as well. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. CLANG_DATABASE_PATH = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = ldns_ #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = doc/header.html # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML # page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To # create a documentation set, doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: # https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. # Possible values are: png (the default) and svg (looks nicer but requires the # pdf2svg or inkscape tool). # The default value is: png. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. # The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /